diff options
| author | Ralf Jung <post@ralfj.de> | 2025-01-08 09:23:40 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2025-01-08 09:23:40 +0100 |
| commit | 2d180714e14b34e36bf883bdf706ebaf5fa96754 (patch) | |
| tree | 36b4829675d832d323283fc37457f6509f8a519c /tests/codegen | |
| parent | fc4a52f598f6259a98964aa3290e9e74e396c1e3 (diff) | |
| parent | 67f49010adf4ec3238564ec072b3652179813dd1 (diff) | |
| download | rust-2d180714e14b34e36bf883bdf706ebaf5fa96754.tar.gz rust-2d180714e14b34e36bf883bdf706ebaf5fa96754.zip | |
Merge from rustc
Diffstat (limited to 'tests/codegen')
| -rw-r--r-- | tests/codegen/bool-select-unpredictable.rs | 35 | ||||
| -rw-r--r-- | tests/codegen/emscripten-catch-unwind-js-eh.rs (renamed from tests/codegen/emcripten-catch-unwind.rs) | 0 | ||||
| -rw-r--r-- | tests/codegen/emscripten-catch-unwind-wasm-eh.rs | 65 | ||||
| -rw-r--r-- | tests/codegen/intrinsics/select_unpredictable.rs | 39 | ||||
| -rw-r--r-- | tests/codegen/min-function-alignment.rs | 43 | ||||
| -rw-r--r-- | tests/codegen/naked-fn/min-function-alignment.rs | 44 | ||||
| -rw-r--r-- | tests/codegen/slice-init.rs | 26 | ||||
| -rw-r--r-- | tests/codegen/target-feature-overrides.rs | 8 | ||||
| -rw-r--r-- | tests/codegen/tied-features-strength.rs | 5 | ||||
| -rw-r--r-- | tests/codegen/vec-in-place.rs | 54 | ||||
| -rw-r--r-- | tests/codegen/vec_pop_push_noop.rs | 3 |
11 files changed, 265 insertions, 57 deletions
diff --git a/tests/codegen/bool-select-unpredictable.rs b/tests/codegen/bool-select-unpredictable.rs deleted file mode 100644 index 1562b177542..00000000000 --- a/tests/codegen/bool-select-unpredictable.rs +++ /dev/null @@ -1,35 +0,0 @@ -//@ compile-flags: -O - -#![feature(select_unpredictable)] -#![crate_type = "lib"] - -#[no_mangle] -pub fn test_int(p: bool, a: u64, b: u64) -> u64 { - // CHECK-LABEL: define{{.*}} @test_int - // CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable - p.select_unpredictable(a, b) -} - -#[no_mangle] -pub fn test_pair(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) { - // CHECK-LABEL: define{{.*}} @test_pair - // CHECK: select i1 %p, {{.*}}, !unpredictable - p.select_unpredictable(a, b) -} - -struct Large { - e: [u64; 100], -} - -#[no_mangle] -pub fn test_struct(p: bool, a: Large, b: Large) -> Large { - // CHECK-LABEL: define{{.*}} @test_struct - // CHECK: select i1 %p, {{.*}}, !unpredictable - p.select_unpredictable(a, b) -} - -#[no_mangle] -pub fn test_zst(p: bool, a: (), b: ()) -> () { - // CHECK-LABEL: define{{.*}} @test_zst - p.select_unpredictable(a, b) -} diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emscripten-catch-unwind-js-eh.rs index b15fb40b68f..b15fb40b68f 100644 --- a/tests/codegen/emcripten-catch-unwind.rs +++ b/tests/codegen/emscripten-catch-unwind-js-eh.rs diff --git a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs new file mode 100644 index 00000000000..72395f432d5 --- /dev/null +++ b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs @@ -0,0 +1,65 @@ +//@ compile-flags: -O --target wasm32-unknown-emscripten -Z emscripten-wasm-eh +//@ needs-llvm-components: webassembly + +// Emscripten catch_unwind using wasm exceptions + +#![feature(no_core, lang_items, intrinsics, rustc_attrs)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +impl<T> Copy for *mut T {} + +#[rustc_intrinsic] +fn size_of<T>() -> usize { + loop {} +} + +extern "rust-intrinsic" { + fn catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), + ) -> i32; +} + +// CHECK-LABEL: @ptr_size +#[no_mangle] +pub fn ptr_size() -> usize { + // CHECK: ret [[PTR_SIZE:.*]] + size_of::<*mut u8>() +} + +// CHECK-LABEL: @test_catch_unwind +#[no_mangle] +pub unsafe fn test_catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), +) -> i32 { + // CHECK: start: + // CHECK: invoke void %try_fn(ptr %data) + // CHECK: to label %__rust_try.exit unwind label %catchswitch.i + // CHECK: catchswitch.i: ; preds = %start + // CHECK: %catchswitch1.i = catchswitch within none [label %catchpad.i] unwind to caller + + // CHECK: catchpad.i: ; preds = %catchswitch.i + // CHECK: %catchpad2.i = catchpad within %catchswitch1.i [ptr null] + // CHECK: %0 = tail call ptr @llvm.wasm.get.exception(token %catchpad2.i) + // CHECK: %1 = tail call i32 @llvm.wasm.get.ehselector(token %catchpad2.i) + // CHECK: call void %catch_fn(ptr %data, ptr %0) [ "funclet"(token %catchpad2.i) ] + // CHECK: catchret from %catchpad2.i to label %__rust_try.exit + + // CHECK: __rust_try.exit: ; preds = %start, %catchpad.i + // CHECK: %common.ret.op.i = phi i32 [ 0, %start ], [ 1, %catchpad.i ] + // CHECK: ret i32 %common.ret.op.i + + catch_unwind(try_fn, data, catch_fn) +} diff --git a/tests/codegen/intrinsics/select_unpredictable.rs b/tests/codegen/intrinsics/select_unpredictable.rs index 2054838dd79..ea6127a48bf 100644 --- a/tests/codegen/intrinsics/select_unpredictable.rs +++ b/tests/codegen/intrinsics/select_unpredictable.rs @@ -1,8 +1,11 @@ -//@ compile-flags: -O +//@ compile-flags: -O -Zmerge-functions=disabled #![feature(core_intrinsics)] +#![feature(select_unpredictable)] #![crate_type = "lib"] +/* Test the intrinsic */ + #[no_mangle] pub fn test_int(p: bool, a: u64, b: u64) -> u64 { // CHECK-LABEL: define{{.*}} @test_int @@ -28,8 +31,42 @@ pub fn test_struct(p: bool, a: Large, b: Large) -> Large { core::intrinsics::select_unpredictable(p, a, b) } +// ZSTs should not need a `select` expression. #[no_mangle] pub fn test_zst(p: bool, a: (), b: ()) -> () { // CHECK-LABEL: define{{.*}} @test_zst + // CHECK-NEXT: start: + // CHECK-NEXT: ret void core::intrinsics::select_unpredictable(p, a, b) } + +/* Test the user-facing version */ + +#[no_mangle] +pub fn test_int2(p: bool, a: u64, b: u64) -> u64 { + // CHECK-LABEL: define{{.*}} @test_int2 + // CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable + p.select_unpredictable(a, b) +} + +#[no_mangle] +pub fn test_pair2(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) { + // CHECK-LABEL: define{{.*}} @test_pair2 + // CHECK: select i1 %p, {{.*}}, !unpredictable + p.select_unpredictable(a, b) +} + +#[no_mangle] +pub fn test_struct2(p: bool, a: Large, b: Large) -> Large { + // CHECK-LABEL: define{{.*}} @test_struct2 + // CHECK: select i1 %p, {{.*}}, !unpredictable + p.select_unpredictable(a, b) +} + +#[no_mangle] +pub fn test_zst2(p: bool, a: (), b: ()) -> () { + // CHECK-LABEL: define{{.*}} @test_zst2 + // CHECK-NEXT: start: + // CHECK-NEXT: ret void + p.select_unpredictable(a, b) +} diff --git a/tests/codegen/min-function-alignment.rs b/tests/codegen/min-function-alignment.rs new file mode 100644 index 00000000000..7c0ad12402a --- /dev/null +++ b/tests/codegen/min-function-alignment.rs @@ -0,0 +1,43 @@ +//@ revisions: align16 align1024 +//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 +//@ [align16] compile-flags: -Zmin-function-alignment=16 +//@ [align1024] compile-flags: -Zmin-function-alignment=1024 + +#![crate_type = "lib"] +#![feature(fn_align)] + +// functions without explicit alignment use the global minimum +// +// CHECK-LABEL: @no_explicit_align +// align16: align 16 +// align1024: align 1024 +#[no_mangle] +pub fn no_explicit_align() {} + +// CHECK-LABEL: @lower_align +// align16: align 16 +// align1024: align 1024 +#[no_mangle] +#[repr(align(8))] +pub fn lower_align() {} + +// the higher value of min-function-alignment and repr(align) wins out +// +// CHECK-LABEL: @higher_align +// align16: align 32 +// align1024: align 1024 +#[no_mangle] +#[repr(align(32))] +pub fn higher_align() {} + +// cold functions follow the same rules as other functions +// +// in GCC, the `-falign-functions` does not apply to cold functions, but +// `-Zmin-function-alignment` applies to all functions. +// +// CHECK-LABEL: @no_explicit_align_cold +// align16: align 16 +// align1024: align 1024 +#[no_mangle] +#[cold] +pub fn no_explicit_align_cold() {} diff --git a/tests/codegen/naked-fn/min-function-alignment.rs b/tests/codegen/naked-fn/min-function-alignment.rs new file mode 100644 index 00000000000..1330d796d39 --- /dev/null +++ b/tests/codegen/naked-fn/min-function-alignment.rs @@ -0,0 +1,44 @@ +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 -Zmin-function-alignment=16 +//@ needs-asm-support +//@ ignore-arm no "ret" mnemonic + +#![feature(naked_functions, fn_align)] +#![crate_type = "lib"] + +// functions without explicit alignment use the global minimum +// +// CHECK: .balign 16 +#[no_mangle] +#[naked] +pub unsafe extern "C" fn naked_no_explicit_align() { + core::arch::naked_asm!("ret") +} + +// CHECK: .balign 16 +#[no_mangle] +#[repr(align(8))] +#[naked] +pub unsafe extern "C" fn naked_lower_align() { + core::arch::naked_asm!("ret") +} + +// CHECK: .balign 32 +#[no_mangle] +#[repr(align(32))] +#[naked] +pub unsafe extern "C" fn naked_higher_align() { + core::arch::naked_asm!("ret") +} + +// cold functions follow the same rules as other functions +// +// in GCC, the `-falign-functions` does not apply to cold functions, but +// `-Zmin-function-alignment` applies to all functions. +// +// CHECK: .balign 16 +#[no_mangle] +#[cold] +#[naked] +pub unsafe extern "C" fn no_explicit_align_cold() { + core::arch::naked_asm!("ret") +} diff --git a/tests/codegen/slice-init.rs b/tests/codegen/slice-init.rs index 8126bf84618..1c2dd3e8875 100644 --- a/tests/codegen/slice-init.rs +++ b/tests/codegen/slice-init.rs @@ -63,6 +63,32 @@ pub fn nonzero_integer_array() { opaque(&x); } +const N: usize = 100; + +// CHECK-LABEL: @u16_init_one_bytes +#[no_mangle] +pub fn u16_init_one_bytes() -> [u16; N] { + // CHECK-NOT: select + // CHECK-NOT: br + // CHECK-NOT: switch + // CHECK-NOT: icmp + // CHECK: call void @llvm.memset.p0 + [const { u16::from_be_bytes([1, 1]) }; N] +} + +// FIXME: undef bytes can just be initialized with the same value as the +// defined bytes, if the defines bytes are all the same. +// CHECK-LABEL: @option_none_init +#[no_mangle] +pub fn option_none_init() -> [Option<u8>; N] { + // CHECK-NOT: select + // CHECK: br label %repeat_loop_header{{.*}} + // CHECK-NOT: switch + // CHECK: icmp + // CHECK-NOT: call void @llvm.memset.p0 + [None; N] +} + // Use an opaque function to prevent rustc from removing useless drops. #[inline(never)] pub fn opaque(_: impl Sized) {} diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs index f38a1ae72de..e7f70a1e24a 100644 --- a/tests/codegen/target-feature-overrides.rs +++ b/tests/codegen/target-feature-overrides.rs @@ -39,8 +39,8 @@ pub unsafe fn banana() -> u32 { } // CHECK: attributes [[APPLEATTRS]] -// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx,{{.*}}" +// COMPAT-SAME: "target-features"="+x87,+sse2,+avx,+avx2,{{.*}}" +// INCOMPAT-SAME: "target-features"="+x87,+sse2,-avx2,-avx,+avx,{{.*}}" // CHECK: attributes [[BANANAATTRS]] -// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx" +// COMPAT-SAME: "target-features"="+x87,+sse2,+avx,+avx2,{{.*}}" +// INCOMPAT-SAME: "target-features"="+x87,+sse2,-avx2,-avx" diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 1b2b63c3d1a..6daa5cd7d5e 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -11,10 +11,11 @@ // ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+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,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +// `neon` and `fp-armv8` get enabled as target base features, but then disabled again at the end of the list. +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fp-armv8,?)|(\+neon,?))*}},-neon,-fp-armv8{{(,\+fpmr)?}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs index 33de0913f77..e835a7ef69b 100644 --- a/tests/codegen/vec-in-place.rs +++ b/tests/codegen/vec-in-place.rs @@ -37,8 +37,11 @@ pub struct Baz { #[no_mangle] pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| e as u8).collect() @@ -48,8 +51,11 @@ pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> { #[no_mangle] pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| Wrapper(e)).collect() @@ -76,8 +82,11 @@ pub fn vec_iterator_cast_signed_nested(vec: Vec<Vec<i32>>) -> Vec<Vec<u32>> { #[no_mangle] pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| e.0).collect() @@ -87,8 +96,11 @@ pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> { #[no_mangle] pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() @@ -98,8 +110,11 @@ pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> { #[no_mangle] pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call @@ -114,8 +129,11 @@ pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> { #[no_mangle] pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> { // CHECK-NOT: loop - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: loop + // CHECK-NOT: call + // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call @@ -138,6 +156,12 @@ pub fn vec_iterator_cast_unwrap_drop(vec: Vec<Wrapper<String>>) -> Vec<String> { // CHECK-NOT: call // CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = udiv + // CHECK: call + // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} + // CHECK-NOT: call + // CHECK-NOT: %{{.*}} = mul + // CHECK-NOT: %{{.*}} = udiv vec.into_iter().map(|Wrapper(e)| e).collect() } @@ -154,6 +178,12 @@ pub fn vec_iterator_cast_wrap_drop(vec: Vec<String>) -> Vec<Wrapper<String>> { // CHECK-NOT: call // CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = udiv + // CHECK: call + // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) + // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} + // CHECK-NOT: call + // CHECK-NOT: %{{.*}} = mul + // CHECK-NOT: %{{.*}} = udiv // CHECK: ret void vec.into_iter().map(Wrapper).collect() diff --git a/tests/codegen/vec_pop_push_noop.rs b/tests/codegen/vec_pop_push_noop.rs index a8ad5b6f1a3..4821e840884 100644 --- a/tests/codegen/vec_pop_push_noop.rs +++ b/tests/codegen/vec_pop_push_noop.rs @@ -12,9 +12,6 @@ pub fn noop(v: &mut Vec<u8>) { // CHECK-NOT: call // CHECK: tail call void @llvm.assume // CHECK-NOT: grow_one - // llvm-pre-19: call - // llvm-pre-19-same: void @llvm.assume - // llvm-pre-19-NOT: grow_one // CHECK-NOT: call // CHECK: {{ret|[}]}} if let Some(x) = v.pop() { |
