diff options
Diffstat (limited to 'tests/codegen')
41 files changed, 561 insertions, 194 deletions
diff --git a/tests/codegen/assign-desugar-debuginfo.rs b/tests/codegen/assign-desugar-debuginfo.rs new file mode 100644 index 00000000000..77ee8758b3b --- /dev/null +++ b/tests/codegen/assign-desugar-debuginfo.rs @@ -0,0 +1,18 @@ +//@ compile-flags: -g -Zmir-opt-level=0 + +#![crate_type = "lib"] + +#[inline(never)] +fn swizzle(a: u32, b: u32, c: u32) -> (u32, (u32, u32)) { + (b, (c, a)) +} + +pub fn work() { + let mut a = 1; + let mut b = 2; + let mut c = 3; + (a, (b, c)) = swizzle(a, b, c); + println!("{a} {b} {c}"); +} + +// CHECK-NOT: !DILocalVariable(name: "lhs", diff --git a/tests/codegen/autodiff.rs b/tests/codegen/autodiff.rs index cace0edb2b5..85358f5fcb6 100644 --- a/tests/codegen/autodiff.rs +++ b/tests/codegen/autodiff.rs @@ -11,7 +11,7 @@ fn square(x: &f64) -> f64 { x * x } -// CHECK:define internal fastcc double @diffesquare(double %x.0.val, ptr nocapture align 8 %"x'" +// CHECK:define internal fastcc double @diffesquare(double %x.0.val, ptr nocapture nonnull align 8 %"x'" // CHECK-NEXT:invertstart: // CHECK-NEXT: %_0 = fmul double %x.0.val, %x.0.val // CHECK-NEXT: %0 = fadd fast double %x.0.val, %x.0.val @@ -22,7 +22,7 @@ fn square(x: &f64) -> f64 { // CHECK-NEXT:} fn main() { - let x = 3.0; + let x = std::hint::black_box(3.0); let output = square(&x); assert_eq!(9.0, output); diff --git a/tests/codegen/autodiffv.rs b/tests/codegen/autodiffv.rs new file mode 100644 index 00000000000..e0047116405 --- /dev/null +++ b/tests/codegen/autodiffv.rs @@ -0,0 +1,116 @@ +//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat +//@ no-prefer-dynamic +//@ needs-enzyme +// +// In Enzyme, we test against a large range of LLVM versions (5+) and don't have overly many +// breakages. One benefit is that we match the IR generated by Enzyme only after running it +// through LLVM's O3 pipeline, which will remove most of the noise. +// However, our integration test could also be affected by changes in how rustc lowers MIR into +// LLVM-IR, which could cause additional noise and thus breakages. If that's the case, we should +// reduce this test to only match the first lines and the ret instructions. + +#![feature(autodiff)] + +use std::autodiff::autodiff; + +#[autodiff(d_square3, Forward, Dual, DualOnly)] +#[autodiff(d_square2, Forward, 4, Dual, DualOnly)] +#[autodiff(d_square1, Forward, 4, Dual, Dual)] +#[no_mangle] +fn square(x: &f32) -> f32 { + x * x +} + +// d_sqaure2 +// CHECK: define internal fastcc [4 x float] @fwddiffe4square(float %x.0.val, [4 x ptr] %"x'") +// CHECK-NEXT: start: +// CHECK-NEXT: %0 = extractvalue [4 x ptr] %"x'", 0 +// CHECK-NEXT: %"_2'ipl" = load float, ptr %0, align 4 +// CHECK-NEXT: %1 = extractvalue [4 x ptr] %"x'", 1 +// CHECK-NEXT: %"_2'ipl1" = load float, ptr %1, align 4 +// CHECK-NEXT: %2 = extractvalue [4 x ptr] %"x'", 2 +// CHECK-NEXT: %"_2'ipl2" = load float, ptr %2, align 4 +// CHECK-NEXT: %3 = extractvalue [4 x ptr] %"x'", 3 +// CHECK-NEXT: %"_2'ipl3" = load float, ptr %3, align 4 +// CHECK-NEXT: %4 = insertelement <4 x float> poison, float %"_2'ipl", i64 0 +// CHECK-NEXT: %5 = insertelement <4 x float> %4, float %"_2'ipl1", i64 1 +// CHECK-NEXT: %6 = insertelement <4 x float> %5, float %"_2'ipl2", i64 2 +// CHECK-NEXT: %7 = insertelement <4 x float> %6, float %"_2'ipl3", i64 3 +// CHECK-NEXT: %8 = fadd fast <4 x float> %7, %7 +// CHECK-NEXT: %9 = insertelement <4 x float> poison, float %x.0.val, i64 0 +// CHECK-NEXT: %10 = shufflevector <4 x float> %9, <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: %11 = fmul fast <4 x float> %8, %10 +// CHECK-NEXT: %12 = extractelement <4 x float> %11, i64 0 +// CHECK-NEXT: %13 = insertvalue [4 x float] undef, float %12, 0 +// CHECK-NEXT: %14 = extractelement <4 x float> %11, i64 1 +// CHECK-NEXT: %15 = insertvalue [4 x float] %13, float %14, 1 +// CHECK-NEXT: %16 = extractelement <4 x float> %11, i64 2 +// CHECK-NEXT: %17 = insertvalue [4 x float] %15, float %16, 2 +// CHECK-NEXT: %18 = extractelement <4 x float> %11, i64 3 +// CHECK-NEXT: %19 = insertvalue [4 x float] %17, float %18, 3 +// CHECK-NEXT: ret [4 x float] %19 +// CHECK-NEXT: } + +// d_square3, the extra float is the original return value (x * x) +// CHECK: define internal fastcc { float, [4 x float] } @fwddiffe4square.1(float %x.0.val, [4 x ptr] %"x'") +// CHECK-NEXT: start: +// CHECK-NEXT: %0 = extractvalue [4 x ptr] %"x'", 0 +// CHECK-NEXT: %"_2'ipl" = load float, ptr %0, align 4 +// CHECK-NEXT: %1 = extractvalue [4 x ptr] %"x'", 1 +// CHECK-NEXT: %"_2'ipl1" = load float, ptr %1, align 4 +// CHECK-NEXT: %2 = extractvalue [4 x ptr] %"x'", 2 +// CHECK-NEXT: %"_2'ipl2" = load float, ptr %2, align 4 +// CHECK-NEXT: %3 = extractvalue [4 x ptr] %"x'", 3 +// CHECK-NEXT: %"_2'ipl3" = load float, ptr %3, align 4 +// CHECK-NEXT: %_0 = fmul float %x.0.val, %x.0.val +// CHECK-NEXT: %4 = insertelement <4 x float> poison, float %"_2'ipl", i64 0 +// CHECK-NEXT: %5 = insertelement <4 x float> %4, float %"_2'ipl1", i64 1 +// CHECK-NEXT: %6 = insertelement <4 x float> %5, float %"_2'ipl2", i64 2 +// CHECK-NEXT: %7 = insertelement <4 x float> %6, float %"_2'ipl3", i64 3 +// CHECK-NEXT: %8 = fadd fast <4 x float> %7, %7 +// CHECK-NEXT: %9 = insertelement <4 x float> poison, float %x.0.val, i64 0 +// CHECK-NEXT: %10 = shufflevector <4 x float> %9, <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: %11 = fmul fast <4 x float> %8, %10 +// CHECK-NEXT: %12 = extractelement <4 x float> %11, i64 0 +// CHECK-NEXT: %13 = insertvalue [4 x float] undef, float %12, 0 +// CHECK-NEXT: %14 = extractelement <4 x float> %11, i64 1 +// CHECK-NEXT: %15 = insertvalue [4 x float] %13, float %14, 1 +// CHECK-NEXT: %16 = extractelement <4 x float> %11, i64 2 +// CHECK-NEXT: %17 = insertvalue [4 x float] %15, float %16, 2 +// CHECK-NEXT: %18 = extractelement <4 x float> %11, i64 3 +// CHECK-NEXT: %19 = insertvalue [4 x float] %17, float %18, 3 +// CHECK-NEXT: %20 = insertvalue { float, [4 x float] } undef, float %_0, 0 +// CHECK-NEXT: %21 = insertvalue { float, [4 x float] } %20, [4 x float] %19, 1 +// CHECK-NEXT: ret { float, [4 x float] } %21 +// CHECK-NEXT: } + +fn main() { + let x = std::hint::black_box(3.0); + let output = square(&x); + dbg!(&output); + assert_eq!(9.0, output); + dbg!(square(&x)); + + let mut df_dx1 = 1.0; + let mut df_dx2 = 2.0; + let mut df_dx3 = 3.0; + let mut df_dx4 = 0.0; + let [o1, o2, o3, o4] = d_square2(&x, &mut df_dx1, &mut df_dx2, &mut df_dx3, &mut df_dx4); + dbg!(o1, o2, o3, o4); + let [output2, o1, o2, o3, o4] = + d_square1(&x, &mut df_dx1, &mut df_dx2, &mut df_dx3, &mut df_dx4); + dbg!(o1, o2, o3, o4); + assert_eq!(output, output2); + assert!((6.0 - o1).abs() < 1e-10); + assert!((12.0 - o2).abs() < 1e-10); + assert!((18.0 - o3).abs() < 1e-10); + assert!((0.0 - o4).abs() < 1e-10); + assert_eq!(1.0, df_dx1); + assert_eq!(2.0, df_dx2); + assert_eq!(3.0, df_dx3); + assert_eq!(0.0, df_dx4); + assert_eq!(d_square3(&x, &mut df_dx1), 2.0 * o1); + assert_eq!(d_square3(&x, &mut df_dx2), 2.0 * o2); + assert_eq!(d_square3(&x, &mut df_dx3), 2.0 * o3); + assert_eq!(d_square3(&x, &mut df_dx4), 2.0 * o4); +} diff --git a/tests/codegen/branch-protection-old-llvm.rs b/tests/codegen/branch-protection-old-llvm.rs deleted file mode 100644 index 14b34ac5018..00000000000 --- a/tests/codegen/branch-protection-old-llvm.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Test that the correct module flags are emitted with different branch protection flags. - -//@ add-core-stubs -//@ revisions: BTI PACRET LEAF BKEY NONE -//@ needs-llvm-components: aarch64 -//@ [BTI] compile-flags: -Z branch-protection=bti -//@ [PACRET] compile-flags: -Z branch-protection=pac-ret -//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf -//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key -//@ compile-flags: --target aarch64-unknown-linux-gnu -//@ max-llvm-major-version: 18 - -#![crate_type = "lib"] -#![feature(no_core, lang_items)] -#![no_core] - -extern crate minicore; -use minicore::*; - -// A basic test function. -pub fn test() {} - -// BTI: !"branch-target-enforcement", i32 1 -// BTI: !"sign-return-address", i32 0 -// BTI: !"sign-return-address-all", i32 0 -// BTI: !"sign-return-address-with-bkey", i32 0 - -// PACRET: !"branch-target-enforcement", i32 0 -// PACRET: !"sign-return-address", i32 1 -// PACRET: !"sign-return-address-all", i32 0 -// PACRET: !"sign-return-address-with-bkey", i32 0 - -// LEAF: !"branch-target-enforcement", i32 0 -// LEAF: !"sign-return-address", i32 1 -// LEAF: !"sign-return-address-all", i32 1 -// LEAF: !"sign-return-address-with-bkey", i32 0 - -// BKEY: !"branch-target-enforcement", i32 0 -// BKEY: !"sign-return-address", i32 1 -// BKEY: !"sign-return-address-all", i32 0 -// BKEY: !"sign-return-address-with-bkey", i32 1 - -// NONE-NOT: branch-target-enforcement -// NONE-NOT: sign-return-address -// NONE-NOT: sign-return-address-all -// NONE-NOT: sign-return-address-with-bkey diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs index ae14eae9ae0..d67e494cc0d 100644 --- a/tests/codegen/branch-protection.rs +++ b/tests/codegen/branch-protection.rs @@ -12,7 +12,6 @@ //@ [PAUTHLR_LEAF] compile-flags: -Z branch-protection=pac-ret,pc,leaf //@ [PAUTHLR_BTI] compile-flags: -Z branch-protection=bti,pac-ret,pc //@ compile-flags: --target aarch64-unknown-linux-gnu -//@ min-llvm-version: 19 #![crate_type = "lib"] #![feature(no_core, lang_items)] diff --git a/tests/codegen/call-metadata.rs b/tests/codegen/call-metadata.rs deleted file mode 100644 index 7ad3ded2f09..00000000000 --- a/tests/codegen/call-metadata.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Checks that range metadata gets emitted on calls to functions returning a -// scalar value. - -//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ max-llvm-major-version: 18 - -#![crate_type = "lib"] - -pub fn test() { - // CHECK: call noundef i8 @some_true(){{( #[0-9]+)?}}, !range [[R0:![0-9]+]] - // CHECK: [[R0]] = !{i8 0, i8 3} - some_true(); -} - -#[no_mangle] -fn some_true() -> Option<bool> { - Some(true) -} diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index 186198bc631..cbd49e2f022 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -1,8 +1,7 @@ // ignore-tidy-linelength //@ add-core-stubs //@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64 -//@ min-llvm-version: 19 -//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error +//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu //@[aarch64] needs-llvm-components: arm diff --git a/tests/codegen/cffi/ffi-const.rs b/tests/codegen/cffi/ffi-const.rs index 564b8f7f8d8..6c90902e89f 100644 --- a/tests/codegen/cffi/ffi-const.rs +++ b/tests/codegen/cffi/ffi-const.rs @@ -9,8 +9,7 @@ pub fn bar() { extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] - // The attribute changed from `readnone` to `memory(none)` with LLVM 16.0. - // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readnone|memory\(none\)}}{{.*}} } + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(none){{.*}} } #[ffi_const] pub fn foo(); } diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index 404f6237849..859386d2df8 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -1,7 +1,6 @@ //@ add-core-stubs //@ revisions: linux apple -//@ min-llvm-version: 19 -//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error +//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 diff --git a/tests/codegen/cffi/ffi-pure.rs b/tests/codegen/cffi/ffi-pure.rs index 601509d5c90..2c5d5f5b4b1 100644 --- a/tests/codegen/cffi/ffi-pure.rs +++ b/tests/codegen/cffi/ffi-pure.rs @@ -9,8 +9,7 @@ pub fn bar() { extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] - // The attribute changed from `readonly` to `memory(read)` with LLVM 16.0. - // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readonly|memory\(read\)}}{{.*}} } + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(read){{.*}} } #[ffi_pure] pub fn foo(); } diff --git a/tests/codegen/char-escape-debug-no-bounds-check.rs b/tests/codegen/char-escape-debug-no-bounds-check.rs new file mode 100644 index 00000000000..cfde46045e5 --- /dev/null +++ b/tests/codegen/char-escape-debug-no-bounds-check.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +use std::char::EscapeDebug; + +// Make sure no bounds checks are emitted when escaping a character. + +// CHECK-LABEL: @char_escape_debug_no_bounds_check +#[no_mangle] +pub fn char_escape_debug_no_bounds_check(c: char) -> EscapeDebug { + // CHECK-NOT: panic + // CHECK-NOT: panic_bounds_check + c.escape_debug() +} diff --git a/tests/codegen/clone_as_copy.rs b/tests/codegen/clone_as_copy.rs index c39f120044c..ef834ef5912 100644 --- a/tests/codegen/clone_as_copy.rs +++ b/tests/codegen/clone_as_copy.rs @@ -1,6 +1,4 @@ //@ revisions: DEBUGINFO NODEBUGINFO -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see <https://github.com/rust-lang/rust/issues/132353> //@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes //@ [DEBUGINFO] compile-flags: -Cdebuginfo=full diff --git a/tests/codegen/comparison-operators-2-tuple.rs b/tests/codegen/comparison-operators-2-tuple.rs index 91a99f9b91f..6a7e489c82d 100644 --- a/tests/codegen/comparison-operators-2-tuple.rs +++ b/tests/codegen/comparison-operators-2-tuple.rs @@ -1,5 +1,4 @@ //@ compile-flags: -C opt-level=1 -Z merge-functions=disabled -//@ only-x86_64 //@ min-llvm-version: 20 #![crate_type = "lib"] diff --git a/tests/codegen/const-array.rs b/tests/codegen/const-array.rs index e257d8acc08..b3df76c3d8e 100644 --- a/tests/codegen/const-array.rs +++ b/tests/codegen/const-array.rs @@ -2,7 +2,7 @@ #![crate_type = "lib"] -const LUT: [u8; 2] = [1, 1]; +const LUT: [u8; 4] = [1, 1, 1, 1]; // CHECK-LABEL: @decode #[no_mangle] @@ -11,5 +11,5 @@ pub fn decode(i: u8) -> u8 { // CHECK-NEXT: icmp // CHECK-NEXT: select // CHECK-NEXT: ret - if i < 2 { LUT[i as usize] } else { 2 } + if i < 4 { LUT[i as usize] } else { 2 } } diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs index b9808e4079b..8a7b1cc3c4b 100644 --- a/tests/codegen/debug-vtable.rs +++ b/tests/codegen/debug-vtable.rs @@ -15,7 +15,7 @@ // Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled. // This helps debuggers more reliably map from dyn pointer to concrete type. -// CHECK: @vtable.2 = private constant <{ +// CHECK: @vtable.2 = private constant [ // CHECK: @vtable.3 = private constant <{ // CHECK: @vtable.4 = private constant <{ diff --git a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs index 0f6e99f9b1e..7530689d574 100644 --- a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs +++ b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs @@ -1,4 +1,3 @@ -//@ min-llvm-version: 19 //@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Zmir-enable-passes=+Inline // MSVC is different because of the individual allocas. //@ ignore-msvc diff --git a/tests/codegen/dont-shuffle-bswaps.rs b/tests/codegen/dont-shuffle-bswaps.rs index 0e712bc3a4e..e100474f606 100644 --- a/tests/codegen/dont-shuffle-bswaps.rs +++ b/tests/codegen/dont-shuffle-bswaps.rs @@ -3,7 +3,6 @@ //@[OPT3] compile-flags: -C opt-level=3 // some targets don't do the opt we are looking for //@[OPT3] only-64bit -//@ min-llvm-version: 18.1.3 #![crate_type = "lib"] #![no_std] diff --git a/tests/codegen/enum/enum-two-variants-match.rs b/tests/codegen/enum/enum-two-variants-match.rs index c1f208d7909..21ae1f96bca 100644 --- a/tests/codegen/enum/enum-two-variants-match.rs +++ b/tests/codegen/enum/enum-two-variants-match.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ min-llvm-version: 19 (for trunc nuw) //@ only-x86_64 (because these discriminants are isize) #![crate_type = "lib"] diff --git a/tests/codegen/external-no-mangle-statics.rs b/tests/codegen/external-no-mangle-statics.rs index dc4eca8c7b4..49f42ee977d 100644 --- a/tests/codegen/external-no-mangle-statics.rs +++ b/tests/codegen/external-no-mangle-statics.rs @@ -6,72 +6,72 @@ // `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their // definitions -// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant +// CHECK-DAG: @A = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static A: u8 = 0; -// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global +// CHECK-DAG: @B = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut B: u8 = 0; -// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant +// CHECK-DAG: @C = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static C: u8 = 0; -// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global +// CHECK-DAG: @D = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut D: u8 = 0; mod private { - // CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @E = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static E: u8 = 0; - // CHECK: @F = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @F = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut F: u8 = 0; - // CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @G = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static G: u8 = 0; - // CHECK: @H = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @H = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut H: u8 = 0; } const HIDDEN: () = { - // CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @I = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static I: u8 = 0; - // CHECK: @J = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @J = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut J: u8 = 0; - // CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @K = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static K: u8 = 0; - // CHECK: @L = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @L = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut L: u8 = 0; }; fn x() { - // CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @M = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static M: fn() = x; - // CHECK: @N = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @N = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut N: u8 = 0; - // CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @O = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static O: u8 = 0; - // CHECK: @P = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @P = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut P: u8 = 0; } diff --git a/tests/codegen/float/algebraic.rs b/tests/codegen/float/algebraic.rs new file mode 100644 index 00000000000..818a4bcdfe3 --- /dev/null +++ b/tests/codegen/float/algebraic.rs @@ -0,0 +1,149 @@ +// Verify that algebraic intrinsics generate the correct LLVM calls + +// Ensure operations get inlined +//@ compile-flags: -Copt-level=1 + +#![crate_type = "lib"] +#![feature(f16)] +#![feature(f128)] +#![feature(float_algebraic)] + +// CHECK-LABEL: @f16_algebraic_add +#[no_mangle] +pub fn f16_algebraic_add(a: f16, b: f16) -> f16 { + // CHECK: fadd reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f16_algebraic_sub +#[no_mangle] +pub fn f16_algebraic_sub(a: f16, b: f16) -> f16 { + // CHECK: fsub reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f16_algebraic_mul +#[no_mangle] +pub fn f16_algebraic_mul(a: f16, b: f16) -> f16 { + // CHECK: fmul reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f16_algebraic_div +#[no_mangle] +pub fn f16_algebraic_div(a: f16, b: f16) -> f16 { + // CHECK: fdiv reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f16_algebraic_rem +#[no_mangle] +pub fn f16_algebraic_rem(a: f16, b: f16) -> f16 { + // CHECK: frem reassoc nsz arcp contract half %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} + +// CHECK-LABEL: @f32_algebraic_add +#[no_mangle] +pub fn f32_algebraic_add(a: f32, b: f32) -> f32 { + // CHECK: fadd reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f32_algebraic_sub +#[no_mangle] +pub fn f32_algebraic_sub(a: f32, b: f32) -> f32 { + // CHECK: fsub reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f32_algebraic_mul +#[no_mangle] +pub fn f32_algebraic_mul(a: f32, b: f32) -> f32 { + // CHECK: fmul reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f32_algebraic_div +#[no_mangle] +pub fn f32_algebraic_div(a: f32, b: f32) -> f32 { + // CHECK: fdiv reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f32_algebraic_rem +#[no_mangle] +pub fn f32_algebraic_rem(a: f32, b: f32) -> f32 { + // CHECK: frem reassoc nsz arcp contract float %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} + +// CHECK-LABEL: @f64_algebraic_add +#[no_mangle] +pub fn f64_algebraic_add(a: f64, b: f64) -> f64 { + // CHECK: fadd reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f64_algebraic_sub +#[no_mangle] +pub fn f64_algebraic_sub(a: f64, b: f64) -> f64 { + // CHECK: fsub reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f64_algebraic_mul +#[no_mangle] +pub fn f64_algebraic_mul(a: f64, b: f64) -> f64 { + // CHECK: fmul reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f64_algebraic_div +#[no_mangle] +pub fn f64_algebraic_div(a: f64, b: f64) -> f64 { + // CHECK: fdiv reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f64_algebraic_rem +#[no_mangle] +pub fn f64_algebraic_rem(a: f64, b: f64) -> f64 { + // CHECK: frem reassoc nsz arcp contract double %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} + +// CHECK-LABEL: @f128_algebraic_add +#[no_mangle] +pub fn f128_algebraic_add(a: f128, b: f128) -> f128 { + // CHECK: fadd reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_add(b) +} + +// CHECK-LABEL: @f128_algebraic_sub +#[no_mangle] +pub fn f128_algebraic_sub(a: f128, b: f128) -> f128 { + // CHECK: fsub reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_sub(b) +} + +// CHECK-LABEL: @f128_algebraic_mul +#[no_mangle] +pub fn f128_algebraic_mul(a: f128, b: f128) -> f128 { + // CHECK: fmul reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_mul(b) +} + +// CHECK-LABEL: @f128_algebraic_div +#[no_mangle] +pub fn f128_algebraic_div(a: f128, b: f128) -> f128 { + // CHECK: fdiv reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_div(b) +} + +// CHECK-LABEL: @f128_algebraic_rem +#[no_mangle] +pub fn f128_algebraic_rem(a: f128, b: f128) -> f128 { + // CHECK: frem reassoc nsz arcp contract fp128 %{{.+}}, %{{.+}} + a.algebraic_rem(b) +} diff --git a/tests/codegen/float_math.rs b/tests/codegen/float_math.rs index 31387ec82b9..9a1e0b4d2d0 100644 --- a/tests/codegen/float_math.rs +++ b/tests/codegen/float_math.rs @@ -3,7 +3,10 @@ #![crate_type = "lib"] #![feature(core_intrinsics)] -use std::intrinsics::{fadd_fast, fdiv_fast, fmul_fast, frem_fast, fsub_fast}; +use std::intrinsics::{ + fadd_algebraic, fadd_fast, fdiv_algebraic, fdiv_fast, fmul_algebraic, fmul_fast, + frem_algebraic, frem_fast, fsub_algebraic, fsub_fast, +}; // CHECK-LABEL: @add #[no_mangle] @@ -13,30 +16,72 @@ pub fn add(x: f32, y: f32) -> f32 { x + y } -// CHECK-LABEL: @addition +// CHECK-LABEL: @test_fadd_algebraic #[no_mangle] -pub fn addition(x: f32, y: f32) -> f32 { - // CHECK: fadd fast float +pub fn test_fadd_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fadd reassoc nsz arcp contract float %x, %y + fadd_algebraic(x, y) +} + +// CHECK-LABEL: @test_fsub_algebraic +#[no_mangle] +pub fn test_fsub_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fsub reassoc nsz arcp contract float %x, %y + fsub_algebraic(x, y) +} + +// CHECK-LABEL: @test_fmul_algebraic +#[no_mangle] +pub fn test_fmul_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fmul reassoc nsz arcp contract float %x, %y + fmul_algebraic(x, y) +} + +// CHECK-LABEL: @test_fdiv_algebraic +#[no_mangle] +pub fn test_fdiv_algebraic(x: f32, y: f32) -> f32 { + // CHECK: fdiv reassoc nsz arcp contract float %x, %y + fdiv_algebraic(x, y) +} + +// CHECK-LABEL: @test_frem_algebraic +#[no_mangle] +pub fn test_frem_algebraic(x: f32, y: f32) -> f32 { + // CHECK: frem reassoc nsz arcp contract float %x, %y + frem_algebraic(x, y) +} + +// CHECK-LABEL: @test_fadd_fast +#[no_mangle] +pub fn test_fadd_fast(x: f32, y: f32) -> f32 { + // CHECK: fadd fast float %x, %y unsafe { fadd_fast(x, y) } } -// CHECK-LABEL: @subtraction +// CHECK-LABEL: @test_fsub_fast #[no_mangle] -pub fn subtraction(x: f32, y: f32) -> f32 { - // CHECK: fsub fast float +pub fn test_fsub_fast(x: f32, y: f32) -> f32 { + // CHECK: fsub fast float %x, %y unsafe { fsub_fast(x, y) } } -// CHECK-LABEL: @multiplication +// CHECK-LABEL: @test_fmul_fast #[no_mangle] -pub fn multiplication(x: f32, y: f32) -> f32 { - // CHECK: fmul fast float +pub fn test_fmul_fast(x: f32, y: f32) -> f32 { + // CHECK: fmul fast float %x, %y unsafe { fmul_fast(x, y) } } -// CHECK-LABEL: @division +// CHECK-LABEL: @test_fdiv_fast #[no_mangle] -pub fn division(x: f32, y: f32) -> f32 { - // CHECK: fdiv fast float +pub fn test_fdiv_fast(x: f32, y: f32) -> f32 { + // CHECK: fdiv fast float %x, %y unsafe { fdiv_fast(x, y) } } + +// CHECK-LABEL: @test_frem_fast +#[no_mangle] +pub fn test_frem_fast(x: f32, y: f32) -> f32 { + // CHECK: frem fast float %x, %y + unsafe { frem_fast(x, y) } +} diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs index 9bbf243946d..812fa8e4a42 100644 --- a/tests/codegen/integer-cmp.rs +++ b/tests/codegen/integer-cmp.rs @@ -4,7 +4,7 @@ //@ revisions: llvm-pre-20 llvm-20 //@ [llvm-20] min-llvm-version: 20 //@ [llvm-pre-20] max-llvm-major-version: 19 -//@ compile-flags: -C opt-level=3 +//@ compile-flags: -C opt-level=3 -Zmerge-functions=disabled #![crate_type = "lib"] @@ -13,7 +13,7 @@ use std::cmp::Ordering; // CHECK-LABEL: @cmp_signed #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { - // llvm-20: @llvm.scmp.i8.i64 + // llvm-20: call{{.*}} i8 @llvm.scmp.i8.i64 // llvm-pre-20: icmp slt // llvm-pre-20: icmp ne // llvm-pre-20: zext i1 @@ -24,10 +24,39 @@ pub fn cmp_signed(a: i64, b: i64) -> Ordering { // CHECK-LABEL: @cmp_unsigned #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { - // llvm-20: @llvm.ucmp.i8.i32 + // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32 // llvm-pre-20: icmp ult // llvm-pre-20: icmp ne // llvm-pre-20: zext i1 // llvm-pre-20: select i1 a.cmp(&b) } + +// CHECK-LABEL: @cmp_char +#[no_mangle] +pub fn cmp_char(a: char, b: char) -> Ordering { + // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32 + // llvm-pre-20: icmp ult + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 + a.cmp(&b) +} + +// CHECK-LABEL: @cmp_tuple +#[no_mangle] +pub fn cmp_tuple(a: (i16, u16), b: (i16, u16)) -> Ordering { + // llvm-20-DAG: call{{.*}} i8 @llvm.ucmp.i8.i16 + // llvm-20-DAG: call{{.*}} i8 @llvm.scmp.i8.i16 + // llvm-20: ret i8 + // llvm-pre-20: icmp slt + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 + // llvm-pre-20: icmp ult + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 + // llvm-pre-20: select i1 + a.cmp(&b) +} diff --git a/tests/codegen/intrinsics/carrying_mul_add.rs b/tests/codegen/intrinsics/carrying_mul_add.rs index b53585a8a6e..21fb49a3786 100644 --- a/tests/codegen/intrinsics/carrying_mul_add.rs +++ b/tests/codegen/intrinsics/carrying_mul_add.rs @@ -1,7 +1,6 @@ //@ revisions: RAW OPT //@ compile-flags: -C opt-level=1 //@[RAW] compile-flags: -C no-prepopulate-passes -//@[OPT] min-llvm-version: 19 #![crate_type = "lib"] #![feature(core_intrinsics)] diff --git a/tests/codegen/intrinsics/three_way_compare.rs b/tests/codegen/intrinsics/three_way_compare.rs index 9a476abe891..95fcb636f7c 100644 --- a/tests/codegen/intrinsics/three_way_compare.rs +++ b/tests/codegen/intrinsics/three_way_compare.rs @@ -2,6 +2,7 @@ //@ [DEBUG] compile-flags: -C opt-level=0 //@ [OPTIM] compile-flags: -C opt-level=3 //@ compile-flags: -C no-prepopulate-passes +//@ min-llvm-version: 20 #![crate_type = "lib"] #![feature(core_intrinsics)] @@ -12,17 +13,8 @@ use std::intrinsics::three_way_compare; // CHECK-LABEL: @signed_cmp // CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b) pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { - // DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b - // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 - // DEBUG: %[[LT:.+]] = icmp slt i16 %a, %b - // DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8 - // DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]] - - // OPTIM: %[[LT:.+]] = icmp slt i16 %a, %b - // OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b - // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 - // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] - // OPTIM: ret i8 %[[CGEL]] + // CHECK: %[[CMP:.+]] = call i8 @llvm.scmp.i8.i16(i16 %a, i16 %b) + // CHECK-NEXT: ret i8 %[[CMP]] three_way_compare(a, b) } @@ -30,16 +22,7 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // CHECK-LABEL: @unsigned_cmp // CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b) pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { - // DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b - // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 - // DEBUG: %[[LT:.+]] = icmp ult i16 %a, %b - // DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8 - // DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]] - - // OPTIM: %[[LT:.+]] = icmp ult i16 %a, %b - // OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b - // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 - // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] - // OPTIM: ret i8 %[[CGEL]] + // CHECK: %[[CMP:.+]] = call i8 @llvm.ucmp.i8.i16(i16 %a, i16 %b) + // CHECK-NEXT: ret i8 %[[CMP]] three_way_compare(a, b) } diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 4849b88c09c..560ebcccdd0 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -12,9 +12,6 @@ use std::intrinsics::{transmute, transmute_unchecked}; use std::mem::MaybeUninit; use std::num::NonZero; -// FIXME(LLVM18REMOVED): `trunc nuw` doesn't exist in LLVM 18, so once we no -// longer support it the optional flag checks can be changed to required. - pub enum ZstNever {} #[repr(align(2))] @@ -157,7 +154,7 @@ pub unsafe fn check_from_newtype(x: Scalar64) -> u64 { pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool { // CHECK: %x = alloca [1 x i8], align 1 // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1 - // CHECK: %[[BOOL:.+]] = trunc{{( nuw)?}} i8 %[[BYTE]] to i1 + // CHECK: %[[BOOL:.+]] = trunc nuw i8 %[[BYTE]] to i1 // CHECK: ret i1 %[[BOOL]] transmute(x) } @@ -175,7 +172,7 @@ pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 { #[no_mangle] pub unsafe fn check_byte_to_bool(x: u8) -> bool { // CHECK-NOT: alloca - // CHECK: %[[R:.+]] = trunc{{( nuw)?}} i8 %x to i1 + // CHECK: %[[R:.+]] = trunc nuw i8 %x to i1 // CHECK: ret i1 %[[R]] transmute(x) } @@ -288,7 +285,7 @@ pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] { #[no_mangle] pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) { // CHECK-NOT: alloca - // CHECK: trunc{{( nuw)?}} i8 %x.0 to i1 + // CHECK: trunc nuw i8 %x.0 to i1 // CHECK: zext i1 %x.1 to i8 transmute(x) } @@ -342,7 +339,7 @@ pub unsafe fn check_heterogeneous_integer_pair(x: (i32, bool)) -> (bool, u32) { // CHECK: store i8 %[[WIDER]] // CHECK: %[[BYTE:.+]] = load i8 - // CHECK: trunc{{( nuw)?}} i8 %[[BYTE:.+]] to i1 + // CHECK: trunc nuw i8 %[[BYTE:.+]] to i1 // CHECK: load i32 transmute(x) } diff --git a/tests/codegen/issues/issue-107681-unwrap_unchecked.rs b/tests/codegen/issues/issue-107681-unwrap_unchecked.rs index fd7296de4c8..69aefc6b1fb 100644 --- a/tests/codegen/issues/issue-107681-unwrap_unchecked.rs +++ b/tests/codegen/issues/issue-107681-unwrap_unchecked.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ min-llvm-version: 19 // Test for #107681. // Make sure we don't create `br` or `select` instructions. diff --git a/tests/codegen/issues/issue-118306.rs b/tests/codegen/issues/issue-118306.rs index f9f3e0c0529..f12dc7cdfe2 100644 --- a/tests/codegen/issues/issue-118306.rs +++ b/tests/codegen/issues/issue-118306.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ min-llvm-version: 19 //@ only-x86_64 // Test for #118306. diff --git a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs index fbea4ee8979..853a1ff36b1 100644 --- a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs +++ b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ min-llvm-version: 19 #![crate_type = "lib"] @@ -37,6 +36,8 @@ pub unsafe fn update(s: *mut State) { // CHECK-NOT: store // CHECK-NOT: memcpy // CHECK-NOT: 75{{3|4}} + + // CHECK: ret let State::A(v) = s.read() else { std::hint::unreachable_unchecked() }; s.write(State::B(v)); } diff --git a/tests/codegen/issues/issue-126585.rs b/tests/codegen/issues/issue-126585.rs index a468efd728d..466dab64cdc 100644 --- a/tests/codegen/issues/issue-126585.rs +++ b/tests/codegen/issues/issue-126585.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Copt-level=s -//@ min-llvm-version: 19 //@ only-x86_64 // Test for #126585. diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs index 196f5edb7d6..f62f6948079 100644 --- a/tests/codegen/link_section.rs +++ b/tests/codegen/link_section.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] -// CHECK: @VAR1 = {{(dso_local )?}}constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one" +// CHECK: @VAR1 = {{(dso_local )?}}constant [4 x i8] c"\01\00\00\00", section ".test_one" #[no_mangle] #[link_section = ".test_one"] #[cfg(target_endian = "little")] diff --git a/tests/codegen/range-attribute.rs b/tests/codegen/range-attribute.rs index e23f5e6bb74..b81ff9ab3e2 100644 --- a/tests/codegen/range-attribute.rs +++ b/tests/codegen/range-attribute.rs @@ -6,7 +6,6 @@ //@[bit32] only-32bit //@[bit64] only-64bit //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ min-llvm-version: 19 #![crate_type = "lib"] diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs index bfbccfe0df8..7d17b3b67cf 100644 --- a/tests/codegen/remap_path_prefix/main.rs +++ b/tests/codegen/remap_path_prefix/main.rs @@ -12,7 +12,7 @@ mod aux_mod; include!("aux_mod.rs"); // Here we check that the expansion of the file!() macro is mapped. -// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }> +// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant [34 x i8] c"/the/src/remap_path_prefix/main.rs" pub static FILE_PATH: &'static str = file!(); fn main() { diff --git a/tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs b/tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs new file mode 100644 index 00000000000..9a2290901d6 --- /dev/null +++ b/tests/codegen/sanitizer/kcfi/add-kcfi-arity-flag.rs @@ -0,0 +1,19 @@ +// Verifies that "kcfi-arity" module flag is added. +// +//@ add-core-stubs +//@ revisions: x86_64 +//@ [x86_64] compile-flags: --target x86_64-unknown-none +//@ [x86_64] needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-crt-static -Cpanic=abort -Zsanitizer=kcfi -Zsanitizer-kcfi-arity +//@ min-llvm-version: 21.0.0 + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-arity", i32 1} diff --git a/tests/codegen/slice-last-elements-optimization.rs b/tests/codegen/slice-last-elements-optimization.rs new file mode 100644 index 00000000000..b90f91d7b17 --- /dev/null +++ b/tests/codegen/slice-last-elements-optimization.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -Copt-level=3 +//@ only-x86_64 +//@ min-llvm-version: 20 +#![crate_type = "lib"] + +// This test verifies that LLVM 20 properly optimizes the bounds check +// when accessing the last few elements of a slice with proper conditions. +// Previously, this would generate an unreachable branch to +// slice_start_index_len_fail even when the bounds check was provably safe. + +// CHECK-LABEL: @last_four_initial( +#[no_mangle] +pub fn last_four_initial(s: &[u8]) -> &[u8] { + // Previously this would generate a branch to slice_start_index_len_fail + // that is unreachable. The LLVM 20 fix should eliminate this branch. + // CHECK-NOT: slice_start_index_len_fail + // CHECK-NOT: unreachable + let start = if s.len() <= 4 { 0 } else { s.len() - 4 }; + &s[start..] +} + +// CHECK-LABEL: @last_four_optimized( +#[no_mangle] +pub fn last_four_optimized(s: &[u8]) -> &[u8] { + // This version was already correctly optimized before the fix in LLVM 20. + // CHECK-NOT: slice_start_index_len_fail + // CHECK-NOT: unreachable + if s.len() <= 4 { &s[0..] } else { &s[s.len() - 4..] } +} + +// Just to verify we're correctly checking for the right thing +// CHECK-LABEL: @test_bounds_check_happens( +#[no_mangle] +pub fn test_bounds_check_happens(s: &[u8], i: usize) -> &[u8] { + // CHECK: slice_start_index_len_fail + &s[i..] +} diff --git a/tests/codegen/slice-split-at.rs b/tests/codegen/slice-split-at.rs new file mode 100644 index 00000000000..07018cf9c91 --- /dev/null +++ b/tests/codegen/slice-split-at.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +// Check that no panic is generated in `split_at` when calculating the index for +// the tail chunk using `checked_sub`. +// +// Tests written for refactored implementations of: +// `<[T]>::{split_last_chunk, split_last_chunk_mut, last_chunk, last_chunk_mut}` + +// CHECK-LABEL: @split_at_last_chunk +#[no_mangle] +pub fn split_at_last_chunk(s: &[u8], chunk_size: usize) -> Option<(&[u8], &[u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at(index)) +} + +// CHECK-LABEL: @split_at_mut_last_chunk +#[no_mangle] +pub fn split_at_mut_last_chunk(s: &mut [u8], chunk_size: usize) -> Option<(&mut [u8], &mut [u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at_mut(index)) +} diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 8b1f3b14fc3..6be0e21e0ef 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -4,21 +4,17 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 -// The "+fpmr" feature is matched as optional as it is only an explicit -// feature in LLVM 18. Once the min supported version is LLVM-19 the optional -// regex matching for this feature can be removed. - //@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 -// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(-sve,?)|(\+neon,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 -// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } +// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fp-armv8,?)|(\+neon,?))*}}" } #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 3a3453b22b4..9f68d742a75 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -1,10 +1,8 @@ //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled --edition=2021 //@ only-x86_64 -// FIXME: Remove the `min-llvm-version`. //@ revisions: NINETEEN TWENTY //@[NINETEEN] exact-llvm-major-version: 19 //@[TWENTY] min-llvm-version: 20 -//@ min-llvm-version: 19 #![crate_type = "lib"] #![feature(try_blocks)] @@ -16,12 +14,17 @@ use std::ptr::NonNull; #[no_mangle] pub fn option_nop_match_32(x: Option<u32>) -> Option<u32> { // CHECK: start: - // TWENTY-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1 - // TWENTY-NEXT: %[[PAYLOAD:.+]] = select i1 %[[IS_SOME]], i32 %1, i32 undef - // CHECK-NEXT: [[REG1:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 - // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1 - // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %[[PAYLOAD]], 1 - // CHECK-NEXT: ret { i32, i32 } [[REG2]] + // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1 + + // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %0, i32 0 + // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 [[SELECT]], 0 + // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 %1, 1 + + // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %1, i32 undef + // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 + // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 [[SELECT]], 1 + + // CHECK-NEXT: ret { i32, i32 } [[REG3]] match x { Some(x) => Some(x), None => None, @@ -90,12 +93,17 @@ pub fn control_flow_nop_traits_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, #[no_mangle] pub fn option_nop_match_64(x: Option<u64>) -> Option<u64> { // CHECK: start: - // TWENTY-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1 - // TWENTY-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef - // CHECK-NEXT: [[REG1:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } poison, i64 %0, 0 - // NINETEEN-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %1, 1 - // TWENTY-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %[[SEL]], 1 - // CHECK-NEXT: ret { i64, i64 } [[REG2]] + // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i64 %0 to i1 + + // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %0, i64 0 + // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 [[SELECT]], 0 + // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 %1, 1 + + // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %1, i64 undef + // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 %0, 0 + // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 [[SELECT]], 1 + + // CHECK-NEXT: ret { i64, i64 } [[REG3]] match x { Some(x) => Some(x), None => None, @@ -164,8 +172,8 @@ pub fn control_flow_nop_traits_64(x: ControlFlow<i64, u64>) -> ControlFlow<i64, #[no_mangle] pub fn result_nop_match_128(x: Result<i128, u128>) -> Result<i128, u128> { // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 // CHECK-NEXT: ret void match x { @@ -189,8 +197,8 @@ pub fn result_nop_traits_128(x: Result<i128, u128>) -> Result<i128, u128> { #[no_mangle] pub fn control_flow_nop_match_128(x: ControlFlow<i128, u128>) -> ControlFlow<i128, u128> { // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 // CHECK-NEXT: ret void match x { diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs index 9fccaf2252e..3f533718a2d 100644 --- a/tests/codegen/unchecked_shifts.rs +++ b/tests/codegen/unchecked_shifts.rs @@ -1,7 +1,4 @@ -//@ revisions: LLVM18 LLVM19PLUS //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@[LLVM18] exact-llvm-major-version: 18 -//@[LLVM19PLUS] min-llvm-version: 19 // This runs mir-opts to inline the standard library call, but doesn't run LLVM // optimizations so it doesn't need to worry about them adding more flags. @@ -24,8 +21,7 @@ pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 { #[no_mangle] pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i32 %b to i16 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 + // CHECK: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 // CHECK: shl i16 %a, %[[TRUNC]] a.unchecked_shl(b) } @@ -53,8 +49,7 @@ pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 { #[no_mangle] pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i32 %b to i16 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 + // CHECK: %[[TRUNC:.+]] = trunc nuw i32 %b to i16 // CHECK: ashr i16 %a, %[[TRUNC]] a.unchecked_shr(b) } @@ -90,8 +85,7 @@ pub unsafe fn unchecked_shl_i128_u8(a: i128, b: u8) -> i128 { #[no_mangle] pub unsafe fn unchecked_shl_u8_i128(a: u8, b: i128) -> u8 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i128 %b to i8 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 + // CHECK: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 // CHECK: shl i8 %a, %[[TRUNC]] std::intrinsics::unchecked_shl(a, b) } @@ -100,8 +94,7 @@ pub unsafe fn unchecked_shl_u8_i128(a: u8, b: i128) -> u8 { #[no_mangle] pub unsafe fn unchecked_shr_i8_u128(a: i8, b: u128) -> i8 { // CHECK-NOT: assume - // LLVM18: %[[TRUNC:.+]] = trunc i128 %b to i8 - // LLVM19PLUS: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 + // CHECK: %[[TRUNC:.+]] = trunc nuw i128 %b to i8 // CHECK: ashr i8 %a, %[[TRUNC]] std::intrinsics::unchecked_shr(a, b) } diff --git a/tests/codegen/uninit-consts.rs b/tests/codegen/uninit-consts.rs index a58008e171e..bde71a35c47 100644 --- a/tests/codegen/uninit-consts.rs +++ b/tests/codegen/uninit-consts.rs @@ -11,15 +11,15 @@ pub struct PartiallyUninit { y: MaybeUninit<[u8; 10]>, } -// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant <{ [10 x i8] }> undef +// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant [10 x i8] undef // CHECK: [[PARTIALLY_UNINIT:@.*]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4 // This shouldn't contain undef, since it contains more chunks // than the default value of uninit_const_chunk_threshold. -// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant <{ [32768 x i8] }> <{ [32768 x i8] c"{{.+}}" }>, align 4 +// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant [32768 x i8] c"{{.+}}", align 4 -// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant <{ [16384 x i8] }> undef +// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant [16384 x i8] undef // CHECK-LABEL: @fully_uninit #[no_mangle] diff --git a/tests/codegen/uninit-repeat-in-aggregate.rs b/tests/codegen/uninit-repeat-in-aggregate.rs new file mode 100644 index 00000000000..0fa2eb7d56c --- /dev/null +++ b/tests/codegen/uninit-repeat-in-aggregate.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +use std::mem::MaybeUninit; + +// We need to make sure len is at offset 0, otherwise codegen needs an extra instruction +#[repr(C)] +pub struct SmallVec<T> { + pub len: u64, + pub arr: [MaybeUninit<T>; 24], +} + +// CHECK-LABEL: @uninit_arr_via_const +#[no_mangle] +pub fn uninit_arr_via_const() -> SmallVec<String> { + // CHECK-NEXT: start: + // CHECK-NEXT: store i64 0, + // CHECK-NEXT: ret + SmallVec { len: 0, arr: [const { MaybeUninit::uninit() }; 24] } +} diff --git a/tests/codegen/vec_pop_push_noop.rs b/tests/codegen/vec_pop_push_noop.rs index 2635660596a..3e375219fe0 100644 --- a/tests/codegen/vec_pop_push_noop.rs +++ b/tests/codegen/vec_pop_push_noop.rs @@ -1,6 +1,3 @@ -//@ revisions: llvm-pre-19 llvm-19 -//@ [llvm-19] min-llvm-version: 19 -//@ [llvm-pre-19] max-llvm-major-version: 18 //@ compile-flags: -Copt-level=3 #![crate_type = "lib"] |
