about summary refs log tree commit diff
path: root/src/test/codegen
diff options
context:
space:
mode:
authorCassandra Fridkin <cass@swag.lgbt>2020-10-05 18:49:51 -0400
committerCassandra Fridkin <cass@swag.lgbt>2020-10-05 18:49:51 -0400
commit44af74f6ddf9102b358f271b371697c4b4e6dd2f (patch)
treefd20034f9565a59750cdd1781a6a6e5f20d15a94 /src/test/codegen
parenta009e2838b25df2761093d727d322a59f69d8f68 (diff)
parenta1dfd2490a6cb456b92e469fa550dc217e20ad6d (diff)
downloadrust-44af74f6ddf9102b358f271b371697c4b4e6dd2f.tar.gz
rust-44af74f6ddf9102b358f271b371697c4b4e6dd2f.zip
Merge branch 'master' into hooks
Diffstat (limited to 'src/test/codegen')
-rw-r--r--src/test/codegen/consts.rs6
-rw-r--r--src/test/codegen/drop.rs6
-rw-r--r--src/test/codegen/issue-34634.rs16
-rw-r--r--src/test/codegen/issue-73396-bounds-check-after-position.rs78
-rw-r--r--src/test/codegen/issue-75659.rs63
-rw-r--r--src/test/codegen/len-is-bounded.rs24
-rw-r--r--src/test/codegen/return-value-in-reg.rs32
-rw-r--r--src/test/codegen/try_identity.rs2
-rw-r--r--src/test/codegen/tuple-layout-opt.rs36
-rw-r--r--src/test/codegen/x86_mmx.rs27
-rw-r--r--src/test/codegen/zst-offset.rs43
11 files changed, 299 insertions, 34 deletions
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index 318f9b0eec3..fcb9002986a 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -14,7 +14,7 @@
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @alloc20, i32 0, i32 0, i32 0), {{.*}}
+// CHECK: [[LOW_HIGH:@alloc[0-9]+]] = {{.*}}, align 4
 
 #[derive(Copy, Clone)]
 // repr(i16) is required for the {low,high}_align_const test
@@ -43,7 +43,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
 #[no_mangle]
 pub fn low_align_const() -> E<i16, [i16; 3]> {
     // Check that low_align_const and high_align_const use the same constant
-    // CHECK: load %"E<i16, [i16; 3]>"*, %"E<i16, [i16; 3]>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, [i16; 3]>"**),
+    // CHECK: memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 2 %1, i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0), i{{(32|64)}} 8, i1 false)
     *&E::A(0)
 }
 
@@ -51,6 +51,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
 #[no_mangle]
 pub fn high_align_const() -> E<i16, i32> {
     // Check that low_align_const and high_align_const use the same constant
-    // CHECK: load %"E<i16, i32>"*, %"E<i16, i32>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, i32>"**),
+    // CHECK: memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 4 %1, i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0), i{{(32|64)}} 8, i1 false)
     *&E::A(0)
 }
diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs
index 0c7f3bb2020..99a791464ab 100644
--- a/src/test/codegen/drop.rs
+++ b/src/test/codegen/drop.rs
@@ -23,13 +23,13 @@ pub fn droppy() {
 // FIXME(eddyb) the `void @` forces a match on the instruction, instead of the
 // comment, that's `; call core::intrinsics::drop_in_place::<drop::SomeUniqueName>`
 // for the `v0` mangling, should switch to matching on that once `legacy` is gone.
+// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
+// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
+// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
-// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
-// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
-// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName
 // The next line checks for the } that ends the function definition
diff --git a/src/test/codegen/issue-34634.rs b/src/test/codegen/issue-34634.rs
new file mode 100644
index 00000000000..6c18adbcb3c
--- /dev/null
+++ b/src/test/codegen/issue-34634.rs
@@ -0,0 +1,16 @@
+// Test that `wrapping_div` only checks divisor once.
+// This test checks that there is only a single compare agains -1 and -1 is not present as a
+// switch case (the second check present until rustc 1.12).
+// This test also verifies that a single panic call is generated (for the division by zero case).
+
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @f
+#[no_mangle]
+pub fn f(x: i32, y: i32) -> i32 {
+    // CHECK-COUNT-1: icmp eq i32 %y, -1
+    // CHECK-COUNT-1: panic
+    // CHECK-NOT: i32 -1, label
+    x.wrapping_div(y)
+}
diff --git a/src/test/codegen/issue-73396-bounds-check-after-position.rs b/src/test/codegen/issue-73396-bounds-check-after-position.rs
new file mode 100644
index 00000000000..e5f3ae45c07
--- /dev/null
+++ b/src/test/codegen/issue-73396-bounds-check-after-position.rs
@@ -0,0 +1,78 @@
+// min-llvm-version: 11.0.0
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted when slicing or indexing
+// with an index from `position()` or `rposition()`.
+
+// CHECK-LABEL: @position_slice_to_no_bounds_check
+#[no_mangle]
+pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+        &s[..idx]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @position_slice_from_no_bounds_check
+#[no_mangle]
+pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+        &s[idx..]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @position_index_no_bounds_check
+#[no_mangle]
+pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+        s[idx]
+    } else {
+        42
+    }
+}
+// CHECK-LABEL: @rposition_slice_to_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+        &s[..idx]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @rposition_slice_from_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+        &s[idx..]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @rposition_index_no_bounds_check
+#[no_mangle]
+pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+        s[idx]
+    } else {
+        42
+    }
+}
diff --git a/src/test/codegen/issue-75659.rs b/src/test/codegen/issue-75659.rs
new file mode 100644
index 00000000000..d093c841d68
--- /dev/null
+++ b/src/test/codegen/issue-75659.rs
@@ -0,0 +1,63 @@
+// This test checks that the call to memchr/slice_contains is optimized away
+// when searching in small slices.
+
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @foo1
+#[no_mangle]
+pub fn foo1(x: u8, data: &[u8; 1]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo2
+#[no_mangle]
+pub fn foo2(x: u8, data: &[u8; 2]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo3
+#[no_mangle]
+pub fn foo3(x: u8, data: &[u8; 3]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo4
+#[no_mangle]
+pub fn foo4(x: u8, data: &[u8; 4]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8
+#[no_mangle]
+pub fn foo8(x: u8, data: &[u8; 8]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8_i8
+#[no_mangle]
+pub fn foo8_i8(x: i8, data: &[i8; 8]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    !data.contains(&x)
+}
+
+// Check that the general case isn't inlined
+// CHECK-LABEL: @foo80
+#[no_mangle]
+pub fn foo80(x: u8, data: &[u8; 80]) -> bool {
+    // CHECK: call core::slice::memchr
+    data.contains(&x)
+}
diff --git a/src/test/codegen/len-is-bounded.rs b/src/test/codegen/len-is-bounded.rs
new file mode 100644
index 00000000000..bb74fc3b275
--- /dev/null
+++ b/src/test/codegen/len-is-bounded.rs
@@ -0,0 +1,24 @@
+// min-llvm-version: 11.0
+// compile-flags: -O -C panic=abort
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn len_range(a: &[u8], b: &[u8]) -> usize {
+    // CHECK-NOT: panic
+    a.len().checked_add(b.len()).unwrap()
+}
+
+#[no_mangle]
+pub fn len_range_on_non_byte(a: &[u16], b: &[u16]) -> usize {
+    // CHECK-NOT: panic
+    a.len().checked_add(b.len()).unwrap()
+}
+
+pub struct Zst;
+
+#[no_mangle]
+pub fn zst_range(a: &[Zst], b: &[Zst]) -> usize {
+    // Zsts may be arbitrarily large.
+    // CHECK: panic
+    a.len().checked_add(b.len()).unwrap()
+}
diff --git a/src/test/codegen/return-value-in-reg.rs b/src/test/codegen/return-value-in-reg.rs
new file mode 100644
index 00000000000..4bc0136c5e3
--- /dev/null
+++ b/src/test/codegen/return-value-in-reg.rs
@@ -0,0 +1,32 @@
+//! This test checks that types of up to 128 bits are returned by-value instead of via out-pointer.
+
+// compile-flags: -C no-prepopulate-passes -O
+// only-x86_64
+
+#![crate_type = "lib"]
+
+pub struct S {
+    a: u64,
+    b: u32,
+    c: u32,
+}
+
+// CHECK: define i128 @modify(%S* noalias nocapture dereferenceable(16) %s)
+#[no_mangle]
+pub fn modify(s: S) -> S {
+    S { a: s.a + s.a, b: s.b + s.b, c: s.c + s.c }
+}
+
+#[repr(packed)]
+pub struct TooBig {
+    a: u64,
+    b: u32,
+    c: u32,
+    d: u8,
+}
+
+// CHECK: define void @m_big(%TooBig* [[ATTRS:.*sret.*]], %TooBig* [[ATTRS2:.*]] %s)
+#[no_mangle]
+pub fn m_big(s: TooBig) -> TooBig {
+    TooBig { a: s.a + s.a, b: s.b + s.b, c: s.c + s.c, d: s.d + s.d }
+}
diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs
index 30e7adfddf7..d30b706eafc 100644
--- a/src/test/codegen/try_identity.rs
+++ b/src/test/codegen/try_identity.rs
@@ -1,4 +1,4 @@
-// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=2
+// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=2 -Zunsound-mir-opts
 
 // Ensure that `x?` has no overhead on `Result<T, E>` due to identity `match`es in lowering.
 // This requires inlining to trigger the MIR optimizations in `SimplifyArmIdentity`.
diff --git a/src/test/codegen/tuple-layout-opt.rs b/src/test/codegen/tuple-layout-opt.rs
new file mode 100644
index 00000000000..e86c75f3f48
--- /dev/null
+++ b/src/test/codegen/tuple-layout-opt.rs
@@ -0,0 +1,36 @@
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes
+
+// Test that tuples get optimized layout, in particular with a ZST in the last field (#63244)
+
+#![crate_type="lib"]
+
+type ScalarZstLast = (u128, ());
+// CHECK: define i128 @test_ScalarZstLast(i128 %_1)
+#[no_mangle]
+pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast { loop {} }
+
+type ScalarZstFirst = ((), u128);
+// CHECK: define i128 @test_ScalarZstFirst(i128 %_1)
+#[no_mangle]
+pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { loop {} }
+
+type ScalarPairZstLast = (u8, u128, ());
+// CHECK: define { i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
+#[no_mangle]
+pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast { loop {} }
+
+type ScalarPairZstFirst = ((), u8, u128);
+// CHECK: define { i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
+#[no_mangle]
+pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst { loop {} }
+
+type ScalarPairLotsOfZsts = ((), u8, (), u128, ());
+// CHECK: define { i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
+#[no_mangle]
+pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts { loop {} }
+
+type ScalarPairLottaNesting = (((), ((), u8, (), u128, ())), ());
+// CHECK: define { i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
+#[no_mangle]
+pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting { loop {} }
diff --git a/src/test/codegen/x86_mmx.rs b/src/test/codegen/x86_mmx.rs
deleted file mode 100644
index 9a58ef1c37a..00000000000
--- a/src/test/codegen/x86_mmx.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// ignore-arm
-// ignore-aarch64
-// ignore-emscripten
-// ignore-mips
-// ignore-mips64
-// ignore-powerpc
-// ignore-powerpc64
-// ignore-powerpc64le
-// ignore-riscv64
-// ignore-sparc
-// ignore-sparc64
-// ignore-s390x
-// compile-flags: -O
-
-#![feature(repr_simd)]
-#![crate_type="lib"]
-
-#[repr(simd)]
-#[derive(Clone, Copy)]
-pub struct i8x8(u64);
-
-#[no_mangle]
-pub fn a(a: &mut i8x8, b: i8x8) -> i8x8 {
-    // CHECK-LABEL: define void @a(x86_mmx*{{.*}}, x86_mmx*{{.*}}, x86_mmx*{{.*}})
-    *a = b;
-    return b
-}
diff --git a/src/test/codegen/zst-offset.rs b/src/test/codegen/zst-offset.rs
new file mode 100644
index 00000000000..0c015fca325
--- /dev/null
+++ b/src/test/codegen/zst-offset.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(repr_simd)]
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
+#[no_mangle]
+pub fn helper(_: usize) {
+}
+
+// Check that we correctly generate a GEP for a ZST that is not included in Scalar layout
+// CHECK-LABEL: @scalar_layout
+#[no_mangle]
+pub fn scalar_layout(s: &(u64, ())) {
+// CHECK: [[X0:%[0-9]+]] = bitcast i64* %s to i8*
+// CHECK-NEXT: [[X1:%[0-9]+]] = getelementptr i8, i8* [[X0]], [[USIZE]] 8
+    let x = &s.1;
+    &x; // keep variable in an alloca
+}
+
+// Check that we correctly generate a GEP for a ZST that is not included in ScalarPair layout
+// CHECK-LABEL: @scalarpair_layout
+#[no_mangle]
+pub fn scalarpair_layout(s: &(u64, u32, ())) {
+// CHECK: [[X0:%[0-9]+]] = bitcast { i64, i32 }* %s to i8*
+// CHECK-NEXT: [[X1:%[0-9]+]] = getelementptr i8, i8* [[X0]], [[USIZE]] 12
+    let x = &s.2;
+    &x; // keep variable in an alloca
+}
+
+#[repr(simd)]
+pub struct U64x4(u64, u64, u64, u64);
+
+// Check that we correctly generate a GEP for a ZST that is not included in Vector layout
+// CHECK-LABEL: @vector_layout
+#[no_mangle]
+pub fn vector_layout(s: &(U64x4, ())) {
+// CHECK: [[X0:%[0-9]+]] = bitcast <4 x i64>* %s to i8*
+// CHECK-NEXT: [[X1:%[0-9]+]] = getelementptr i8, i8* [[X0]], [[USIZE]] 32
+    let x = &s.1;
+    &x; // keep variable in an alloca
+}