about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2024-06-16 22:25:57 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2024-06-20 22:16:59 -0700
commit55d13379ac57227a08ba537316adcf2d3c388f57 (patch)
treed51241ad161dc95a38113805b0d067c2d6f51065
parent4341cb709d4d1c1d26d9aea55b00ff16945fe644 (diff)
downloadrust-55d13379ac57227a08ba537316adcf2d3c388f57.tar.gz
rust-55d13379ac57227a08ba537316adcf2d3c388f57.zip
[GVN] Add tests for generic pointees with PtrMetadata
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/intrinsics/mir.rs7
-rw-r--r--tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff38
-rw-r--r--tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff38
-rw-r--r--tests/mir-opt/gvn.rs50
6 files changed, 138 insertions, 0 deletions
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index b1a305efa4c..7549481c1b3 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -193,6 +193,10 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 let source = self.parse_operand(args[0])?;
                 Ok(Rvalue::Cast(CastKind::Transmute, source, expr.ty))
             },
+            @call(mir_cast_ptr_to_ptr, args) => {
+                let source = self.parse_operand(args[0])?;
+                Ok(Rvalue::Cast(CastKind::PtrToPtr, source, expr.ty))
+            },
             @call(mir_checked, args) => {
                 parse_by_kind!(self, args[0], _, "binary op",
                     ExprKind::Binary { op, lhs, rhs } => {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 55eba257ca2..a508c279439 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1175,6 +1175,7 @@ symbols! {
         mir_assume,
         mir_basic_block,
         mir_call,
+        mir_cast_ptr_to_ptr,
         mir_cast_transmute,
         mir_checked,
         mir_copy_for_deref,
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index ec8488009b9..1daf1d723fb 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -445,6 +445,13 @@ define!(
     fn CastTransmute<T, U>(operand: T) -> U
 );
 define!(
+    "mir_cast_ptr_to_ptr",
+    /// Emits a `CastKind::PtrToPtr` cast.
+    ///
+    /// This allows bypassing normal validation to generate strange casts.
+    fn CastPtrToPtr<T, U>(operand: T) -> U
+);
+define!(
     "mir_make_place",
     #[doc(hidden)]
     fn __internal_make_place<T>(place: T) -> *mut T
diff --git a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff
new file mode 100644
index 00000000000..1d462a8a23c
--- /dev/null
+++ b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-abort.diff
@@ -0,0 +1,38 @@
+- // MIR for `generic_cast_metadata` before GVN
++ // MIR for `generic_cast_metadata` after GVN
+  
+  fn generic_cast_metadata(_1: *const [T], _2: *const A, _3: *const B) -> () {
+      let mut _0: ();
+      let mut _4: *const T;
+      let mut _5: ();
+      let mut _6: *const (&A, [T]);
+      let mut _7: usize;
+      let mut _8: *const (T, B);
+      let mut _9: <B as std::ptr::Pointee>::Metadata;
+      let mut _10: *const (T, A);
+      let mut _11: <A as std::ptr::Pointee>::Metadata;
+      let mut _12: *mut A;
+      let mut _13: <A as std::ptr::Pointee>::Metadata;
+      let mut _14: *mut B;
+      let mut _15: <B as std::ptr::Pointee>::Metadata;
+  
+      bb0: {
+          _4 = _1 as *const T (PtrToPtr);
+          _5 = PtrMetadata(_4);
+          _6 = _1 as *const (&A, [T]) (PtrToPtr);
+-         _7 = PtrMetadata(_6);
++         _7 = PtrMetadata(_1);
+          _8 = _2 as *const (T, B) (PtrToPtr);
+          _9 = PtrMetadata(_8);
+          _10 = _2 as *const (T, A) (PtrToPtr);
+-         _11 = PtrMetadata(_10);
++         _11 = PtrMetadata(_2);
+          _12 = _3 as *mut A (PtrToPtr);
+          _13 = PtrMetadata(_12);
+          _14 = _3 as *mut B (PtrToPtr);
+-         _15 = PtrMetadata(_14);
++         _15 = PtrMetadata(_3);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..1d462a8a23c
--- /dev/null
+++ b/tests/mir-opt/gvn.generic_cast_metadata.GVN.panic-unwind.diff
@@ -0,0 +1,38 @@
+- // MIR for `generic_cast_metadata` before GVN
++ // MIR for `generic_cast_metadata` after GVN
+  
+  fn generic_cast_metadata(_1: *const [T], _2: *const A, _3: *const B) -> () {
+      let mut _0: ();
+      let mut _4: *const T;
+      let mut _5: ();
+      let mut _6: *const (&A, [T]);
+      let mut _7: usize;
+      let mut _8: *const (T, B);
+      let mut _9: <B as std::ptr::Pointee>::Metadata;
+      let mut _10: *const (T, A);
+      let mut _11: <A as std::ptr::Pointee>::Metadata;
+      let mut _12: *mut A;
+      let mut _13: <A as std::ptr::Pointee>::Metadata;
+      let mut _14: *mut B;
+      let mut _15: <B as std::ptr::Pointee>::Metadata;
+  
+      bb0: {
+          _4 = _1 as *const T (PtrToPtr);
+          _5 = PtrMetadata(_4);
+          _6 = _1 as *const (&A, [T]) (PtrToPtr);
+-         _7 = PtrMetadata(_6);
++         _7 = PtrMetadata(_1);
+          _8 = _2 as *const (T, B) (PtrToPtr);
+          _9 = PtrMetadata(_8);
+          _10 = _2 as *const (T, A) (PtrToPtr);
+-         _11 = PtrMetadata(_10);
++         _11 = PtrMetadata(_2);
+          _12 = _3 as *mut A (PtrToPtr);
+          _13 = PtrMetadata(_12);
+          _14 = _3 as *mut B (PtrToPtr);
+-         _15 = PtrMetadata(_14);
++         _15 = PtrMetadata(_3);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs
index 74f1849c42a..8bc2550b8f5 100644
--- a/tests/mir-opt/gvn.rs
+++ b/tests/mir-opt/gvn.rs
@@ -834,6 +834,55 @@ fn array_len(x: &mut [i32; 42]) -> usize {
     std::intrinsics::ptr_metadata(x)
 }
 
+#[custom_mir(dialect = "runtime")]
+fn generic_cast_metadata<T, A: ?Sized, B: ?Sized>(ps: *const [T], pa: *const A, pb: *const B) {
+    // CHECK-LABEL: fn generic_cast_metadata
+    mir! {
+        {
+            // These tests check that we correctly do or don't elide casts
+            // when the pointee metadata do or don't match, respectively.
+
+            // Metadata usize -> (), do not optimize.
+            // CHECK: [[T:_.+]] = _1 as
+            // CHECK-NEXT: PtrMetadata([[T]])
+            let t1 = CastPtrToPtr::<_, *const T>(ps);
+            let m1 = PtrMetadata(t1);
+
+            // `(&A, [T])` has `usize` metadata, same as `[T]`, yes optimize.
+            // CHECK: [[T:_.+]] = _1 as
+            // CHECK-NEXT: PtrMetadata(_1)
+            let t2 = CastPtrToPtr::<_, *const (&A, [T])>(ps);
+            let m2 = PtrMetadata(t2);
+
+            // Tail `A` and tail `B`, do not optimize.
+            // CHECK: [[T:_.+]] = _2 as
+            // CHECK-NEXT: PtrMetadata([[T]])
+            let t3 = CastPtrToPtr::<_, *const (T, B)>(pa);
+            let m3 = PtrMetadata(t3);
+
+            // Both have tail `A`, yes optimize.
+            // CHECK: [[T:_.+]] = _2 as
+            // CHECK-NEXT: PtrMetadata(_2)
+            let t4 = CastPtrToPtr::<_, *const (T, A)>(pa);
+            let m4 = PtrMetadata(t4);
+
+            // Tail `B` and tail `A`, do not optimize.
+            // CHECK: [[T:_.+]] = _3 as
+            // CHECK-NEXT: PtrMetadata([[T]])
+            let t5 = CastPtrToPtr::<_, *mut A>(pb);
+            let m5 = PtrMetadata(t5);
+
+            // Both have tail `B`, yes optimize.
+            // CHECK: [[T:_.+]] = _3 as
+            // CHECK-NEXT: PtrMetadata(_3)
+            let t6 = CastPtrToPtr::<_, *mut B>(pb);
+            let m6 = PtrMetadata(t6);
+
+            Return()
+        }
+    }
+}
+
 fn main() {
     subexpression_elimination(2, 4, 5);
     wrap_unwrap(5);
@@ -900,3 +949,4 @@ fn identity<T>(x: T) -> T {
 // EMIT_MIR gvn.casts_before_aggregate_raw_ptr.GVN.diff
 // EMIT_MIR gvn.manual_slice_mut_len.GVN.diff
 // EMIT_MIR gvn.array_len.GVN.diff
+// EMIT_MIR gvn.generic_cast_metadata.GVN.diff