diff options
Diffstat (limited to 'src/test/codegen')
| -rw-r--r-- | src/test/codegen/arg-return-value-in-reg.rs (renamed from src/test/codegen/return-value-in-reg.rs) | 4 | ||||
| -rw-r--r-- | src/test/codegen/dllimports/main.rs | 1 | ||||
| -rw-r--r-- | src/test/codegen/enum-discriminant-value.rs | 8 | ||||
| -rw-r--r-- | src/test/codegen/fewer-names.rs | 20 | ||||
| -rw-r--r-- | src/test/codegen/inline-hint.rs | 31 | ||||
| -rw-r--r-- | src/test/codegen/issue-56927.rs | 1 | ||||
| -rw-r--r-- | src/test/codegen/naked-functions.rs | 54 | ||||
| -rw-r--r-- | src/test/codegen/naked-noinline.rs | 30 | ||||
| -rw-r--r-- | src/test/codegen/panic-abort-windows.rs | 1 | ||||
| -rw-r--r-- | src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs | 47 | ||||
| -rw-r--r-- | src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs | 44 | ||||
| -rw-r--r-- | src/test/codegen/to_vec.rs | 10 | ||||
| -rw-r--r-- | src/test/codegen/transmute-scalar.rs | 85 | ||||
| -rw-r--r-- | src/test/codegen/union-abi.rs | 11 |
14 files changed, 286 insertions, 61 deletions
diff --git a/src/test/codegen/return-value-in-reg.rs b/src/test/codegen/arg-return-value-in-reg.rs index 4bc0136c5e3..a69291d4782 100644 --- a/src/test/codegen/return-value-in-reg.rs +++ b/src/test/codegen/arg-return-value-in-reg.rs @@ -1,4 +1,4 @@ -//! This test checks that types of up to 128 bits are returned by-value instead of via out-pointer. +//! Check that types of up to 128 bits are passed and returned by-value instead of via pointer. // compile-flags: -C no-prepopulate-passes -O // only-x86_64 @@ -11,7 +11,7 @@ pub struct S { c: u32, } -// CHECK: define i128 @modify(%S* noalias nocapture dereferenceable(16) %s) +// CHECK: define i128 @modify(i128{{( %0)?}}) #[no_mangle] pub fn modify(s: S) -> S { S { a: s.a + s.a, b: s.b + s.b, c: s.c + s.c } diff --git a/src/test/codegen/dllimports/main.rs b/src/test/codegen/dllimports/main.rs index 73631b92c1f..bb3134e81c9 100644 --- a/src/test/codegen/dllimports/main.rs +++ b/src/test/codegen/dllimports/main.rs @@ -1,6 +1,5 @@ // This test is for *-windows-msvc only. // ignore-android -// ignore-cloudabi // ignore-dragonfly // ignore-emscripten // ignore-freebsd diff --git a/src/test/codegen/enum-discriminant-value.rs b/src/test/codegen/enum-discriminant-value.rs index f9da987765f..cc14c212002 100644 --- a/src/test/codegen/enum-discriminant-value.rs +++ b/src/test/codegen/enum-discriminant-value.rs @@ -4,14 +4,14 @@ #[repr(i64)] pub enum I64 { - I64Min = std::i64::MIN, - I64Max = std::i64::MAX, + I64Min = i64::MIN, + I64Max = i64::MAX, } #[repr(u64)] pub enum U64 { - U64Min = std::u64::MIN, - U64Max = std::u64::MAX, + U64Min = u64::MIN, + U64Max = u64::MAX, } fn main() { diff --git a/src/test/codegen/fewer-names.rs b/src/test/codegen/fewer-names.rs new file mode 100644 index 00000000000..53a926d49ef --- /dev/null +++ b/src/test/codegen/fewer-names.rs @@ -0,0 +1,20 @@ +// no-system-llvm +// compile-flags: -Coverflow-checks=no -O +// revisions: YES NO +// [YES]compile-flags: -Zfewer-names=yes +// [NO] compile-flags: -Zfewer-names=no +#![crate_type = "lib"] + +#[no_mangle] +pub fn sum(x: u32, y: u32) -> u32 { +// YES-LABEL: define i32 @sum(i32 %0, i32 %1) +// YES-NEXT: %3 = add i32 %1, %0 +// YES-NEXT: ret i32 %3 + +// NO-LABEL: define i32 @sum(i32 %x, i32 %y) +// NO-NEXT: start: +// NO-NEXT: %z = add i32 %y, %x +// NO-NEXT: ret i32 %z + let z = x + y; + z +} diff --git a/src/test/codegen/inline-hint.rs b/src/test/codegen/inline-hint.rs new file mode 100644 index 00000000000..a2571c2e532 --- /dev/null +++ b/src/test/codegen/inline-hint.rs @@ -0,0 +1,31 @@ +// Checks that closures, constructors, and shims except +// for a drop glue receive inline hint by default. +// +// compile-flags: -Cno-prepopulate-passes -Zsymbol-mangling-version=v0 +#![crate_type = "lib"] + +pub fn f() { + let a = A; + let b = (0i32, 1i32, 2i32, 3i32); + let c = || {}; + + a(String::new(), String::new()); + b.clone(); + c(); +} + +struct A(String, String); + +// CHECK: ; core::ptr::drop_in_place::<inline_hint::A> +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: inlinehint +// CHECK-SAME: {{$}} + +// CHECK: ; <(i32, i32, i32, i32) as core::clone::Clone>::clone +// CHECK-NEXT: ; Function Attrs: inlinehint + +// CHECK: ; inline_hint::f::{closure#0} +// CHECK-NEXT: ; Function Attrs: inlinehint + +// CHECK: ; inline_hint::A +// CHECK-NEXT: ; Function Attrs: inlinehint diff --git a/src/test/codegen/issue-56927.rs b/src/test/codegen/issue-56927.rs index d502673e2f8..2c84015d5e2 100644 --- a/src/test/codegen/issue-56927.rs +++ b/src/test/codegen/issue-56927.rs @@ -1,7 +1,6 @@ // compile-flags: -C no-prepopulate-passes #![crate_type="rlib"] -use std::usize; #[repr(align(16))] pub struct S { diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs index 5e76f1d67e6..43a6be465bc 100644 --- a/src/test/codegen/naked-functions.rs +++ b/src/test/codegen/naked-functions.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 +// compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] #![feature(naked_functions)] @@ -15,11 +15,9 @@ pub fn naked_empty() { // CHECK: Function Attrs: naked #[no_mangle] #[naked] -// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}}) +// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %a)?}}) pub fn naked_with_args(a: isize) { // CHECK-NEXT: {{.+}}: - // CHECK-NEXT: %a = alloca i{{[0-9]+}} - &a; // keep variable in an alloca // CHECK: ret void } @@ -34,53 +32,11 @@ pub fn naked_with_return() -> isize { } // CHECK: Function Attrs: naked -// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %0)?}}) +// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}}) #[no_mangle] #[naked] pub fn naked_with_args_and_return(a: isize) -> isize { // CHECK-NEXT: {{.+}}: - // CHECK-NEXT: %a = alloca i{{[0-9]+}} - &a; // keep variable in an alloca - // CHECK: ret i{{[0-9]+}} %{{[0-9]+}} - a -} - -// CHECK: Function Attrs: naked -// CHECK-NEXT: define void @naked_recursive() -#[no_mangle] -#[naked] -pub fn naked_recursive() { - // CHECK-NEXT: {{.+}}: - // CHECK-NEXT: call void @naked_empty() - - // FIXME(#39685) Avoid one block per call. - // CHECK-NEXT: br label %bb1 - // CHECK: bb1: - - naked_empty(); - - // CHECK-NEXT: %_4 = call i{{[0-9]+}} @naked_with_return() - - // FIXME(#39685) Avoid one block per call. - // CHECK-NEXT: br label %bb2 - // CHECK: bb2: - - // CHECK-NEXT: %_3 = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %_4) - - // FIXME(#39685) Avoid one block per call. - // CHECK-NEXT: br label %bb3 - // CHECK: bb3: - - // CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %_3) - - // FIXME(#39685) Avoid one block per call. - // CHECK-NEXT: br label %bb4 - // CHECK: bb4: - - naked_with_args( - naked_with_args_and_return( - naked_with_return() - ) - ); - // CHECK-NEXT: ret void + // CHECK: ret i{{[0-9]+}} 0 + 0 } diff --git a/src/test/codegen/naked-noinline.rs b/src/test/codegen/naked-noinline.rs new file mode 100644 index 00000000000..2a2208d4fce --- /dev/null +++ b/src/test/codegen/naked-noinline.rs @@ -0,0 +1,30 @@ +// Checks that naked functions are never inlined. +// compile-flags: -O -Zmir-opt-level=2 +// ignore-wasm32 +#![crate_type = "lib"] +#![feature(asm)] +#![feature(naked_functions)] + +#[inline(always)] +#[naked] +#[no_mangle] +pub unsafe extern "C" fn f() { +// Check that f has naked and noinline attributes. +// +// CHECK: define void @f() unnamed_addr [[ATTR:#[0-9]+]] +// CHECK-NEXT: start: +// CHECK-NEXT: call void asm + asm!("", options(noreturn)); +} + +#[no_mangle] +pub unsafe fn g() { +// Check that call to f is not inlined. +// +// CHECK-LABEL: define void @g() +// CHECK-NEXT: start: +// CHECK-NEXT: call void @f() + f(); +} + +// CHECK: attributes [[ATTR]] = { naked noinline{{.*}} } diff --git a/src/test/codegen/panic-abort-windows.rs b/src/test/codegen/panic-abort-windows.rs index 8e38245267d..9ee4bfc4711 100644 --- a/src/test/codegen/panic-abort-windows.rs +++ b/src/test/codegen/panic-abort-windows.rs @@ -1,6 +1,5 @@ // This test is for *-windows-msvc only. // ignore-android -// ignore-cloudabi // ignore-dragonfly // ignore-emscripten // ignore-freebsd diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs new file mode 100644 index 00000000000..b5b0b1330a6 --- /dev/null +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs @@ -0,0 +1,47 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics, min_const_generics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct M(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct S<const N: usize>([f32; N]); + +extern "platform-intrinsic" { + fn simd_extract<T, U>(x: T, idx: u32) -> U; + fn simd_insert<T, U>(x: T, idx: u32, b: U) -> T; +} + +// CHECK-LABEL: @extract_m +#[no_mangle] +pub unsafe fn extract_m(v: M, i: u32) -> f32 { + // CHECK: extractelement <4 x float> %{{v|_3}}, i32 %i + simd_extract(v, i) +} + +// CHECK-LABEL: @extract_s +#[no_mangle] +pub unsafe fn extract_s(v: S<4>, i: u32) -> f32 { + // CHECK: extractelement <4 x float> %{{v|_3}}, i32 %i + simd_extract(v, i) +} + +// CHECK-LABEL: @insert_m +#[no_mangle] +pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M { + // CHECK: insertelement <4 x float> %{{v|_4}}, float %j, i32 %i + simd_insert(v, i, j) +} + +// CHECK-LABEL: @insert_s +#[no_mangle] +pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4> { + // CHECK: insertelement <4 x float> %{{v|_4}}, float %j, i32 %i + simd_insert(v, i, j) +} diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs new file mode 100644 index 00000000000..56466a78d5a --- /dev/null +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -0,0 +1,44 @@ +// ignore-tidy-linelength +// compile-flags: -C no-prepopulate-passes +// min-llvm-version 8.0 + +#![crate_type = "lib"] + +#![allow(non_camel_case_types)] +#![feature(repr_simd, platform_intrinsics, min_const_generics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct S<const N: usize>([f32; N]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct T([f32; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct U(f32, f32, f32, f32); + +// CHECK-LABEL: @build_array_s +#[no_mangle] +pub fn build_array_s(x: [f32; 4]) -> S<4> { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + S::<4>(x) +} + +// CHECK-LABEL: @build_array_t +#[no_mangle] +pub fn build_array_t(x: [f32; 4]) -> T { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + T(x) +} + +// CHECK-LABEL: @build_array_u +#[no_mangle] +pub fn build_array_u(x: [f32; 4]) -> U { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{[0-9]+}}(i8* {{.*}} %{{[0-9]+}}, i8* {{.*}} %{{[0-9]+}}, i{{[0-9]+}} 16, i1 false) + unsafe { std::mem::transmute(x) } +} diff --git a/src/test/codegen/to_vec.rs b/src/test/codegen/to_vec.rs new file mode 100644 index 00000000000..60dc4efcb62 --- /dev/null +++ b/src/test/codegen/to_vec.rs @@ -0,0 +1,10 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @copy_to_vec +#[no_mangle] +fn copy_to_vec(s: &[u64]) -> Vec<u64> { + s.to_vec() + // CHECK: call void @llvm.memcpy +} diff --git a/src/test/codegen/transmute-scalar.rs b/src/test/codegen/transmute-scalar.rs new file mode 100644 index 00000000000..78b4aa3fb88 --- /dev/null +++ b/src/test/codegen/transmute-scalar.rs @@ -0,0 +1,85 @@ +// compile-flags: -O -C no-prepopulate-passes + +#![crate_type = "lib"] + +// FIXME(eddyb) all of these tests show memory stores and loads, even after a +// scalar `bitcast`, more special-casing is required to remove `alloca` usage. + +// CHECK: define i32 @f32_to_bits(float %x) +// CHECK: %2 = bitcast float %x to i32 +// CHECK-NEXT: store i32 %2, i32* %0 +// CHECK-NEXT: %3 = load i32, i32* %0 +// CHECK: ret i32 %3 +#[no_mangle] +pub fn f32_to_bits(x: f32) -> u32 { + unsafe { std::mem::transmute(x) } +} + +// CHECK: define i8 @bool_to_byte(i1 zeroext %b) +// CHECK: %1 = zext i1 %b to i8 +// CHECK-NEXT: store i8 %1, i8* %0 +// CHECK-NEXT: %2 = load i8, i8* %0 +// CHECK: ret i8 %2 +#[no_mangle] +pub fn bool_to_byte(b: bool) -> u8 { + unsafe { std::mem::transmute(b) } +} + +// CHECK: define zeroext i1 @byte_to_bool(i8 %byte) +// CHECK: %1 = trunc i8 %byte to i1 +// CHECK-NEXT: %2 = zext i1 %1 to i8 +// CHECK-NEXT: store i8 %2, i8* %0 +// CHECK-NEXT: %3 = load i8, i8* %0 +// CHECK-NEXT: %4 = trunc i8 %3 to i1 +// CHECK: ret i1 %4 +#[no_mangle] +pub unsafe fn byte_to_bool(byte: u8) -> bool { + std::mem::transmute(byte) +} + +// CHECK: define i8* @ptr_to_ptr(i16* %p) +// CHECK: %2 = bitcast i16* %p to i8* +// CHECK-NEXT: store i8* %2, i8** %0 +// CHECK-NEXT: %3 = load i8*, i8** %0 +// CHECK: ret i8* %3 +#[no_mangle] +pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 { + unsafe { std::mem::transmute(p) } +} + +// HACK(eddyb) scalar `transmute`s between pointers and non-pointers are +// currently not special-cased like other scalar `transmute`s, because +// LLVM requires specifically `ptrtoint`/`inttoptr` instead of `bitcast`. +// +// Tests below show the non-special-cased behavior (with the possible +// future special-cased instructions in the "NOTE(eddyb)" comments). + +// CHECK: define [[USIZE:i[0-9]+]] @ptr_to_int(i16* %p) + +// NOTE(eddyb) see above, the following two CHECK lines should ideally be this: +// %2 = ptrtoint i16* %p to [[USIZE]] +// store [[USIZE]] %2, [[USIZE]]* %0 +// CHECK: %2 = bitcast [[USIZE]]* %0 to i16** +// CHECK-NEXT: store i16* %p, i16** %2 + +// CHECK-NEXT: %3 = load [[USIZE]], [[USIZE]]* %0 +// CHECK: ret [[USIZE]] %3 +#[no_mangle] +pub fn ptr_to_int(p: *mut u16) -> usize { + unsafe { std::mem::transmute(p) } +} + +// CHECK: define i16* @int_to_ptr([[USIZE]] %i) + +// NOTE(eddyb) see above, the following two CHECK lines should ideally be this: +// %2 = inttoptr [[USIZE]] %i to i16* +// store i16* %2, i16** %0 +// CHECK: %2 = bitcast i16** %0 to [[USIZE]]* +// CHECK-NEXT: store [[USIZE]] %i, [[USIZE]]* %2 + +// CHECK-NEXT: %3 = load i16*, i16** %0 +// CHECK: ret i16* %3 +#[no_mangle] +pub fn int_to_ptr(i: usize) -> *mut u16 { + unsafe { std::mem::transmute(i) } +} diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index afea01e9a2d..f282fd23705 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -63,11 +63,16 @@ pub union UnionU128{a:u128} #[no_mangle] pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} } +pub union UnionU128x2{a:(u128, u128)} +// CHECK: define void @test_UnionU128x2(i128 %_1.0, i128 %_1.1) +#[no_mangle] +pub fn test_UnionU128x2(_: UnionU128x2) { loop {} } + #[repr(C)] -pub union CUnionU128{a:u128} -// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %_1) +pub union CUnionU128x2{a:(u128, u128)} +// CHECK: define void @test_CUnionU128x2(%CUnionU128x2* {{.*}} %_1) #[no_mangle] -pub fn test_CUnionU128(_: CUnionU128) { loop {} } +pub fn test_CUnionU128x2(_: CUnionU128x2) { loop {} } pub union UnionBool { b:bool } // CHECK: define zeroext i1 @test_UnionBool(i8 %b) |
