about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-26 15:52:33 +0000
committerbors <bors@rust-lang.org>2023-04-26 15:52:33 +0000
commit9c044d77a334609513f3b615e0763a40cc02424d (patch)
treeae444821302a827fe1af2cc2a2da4396e099c6c3
parent8763965a2c7b68a33af5fc55999f9eff26749fd6 (diff)
parent05a665f21a6f9763d136a9d2d7c0255de6d333fb (diff)
downloadrust-9c044d77a334609513f3b615e0763a40cc02424d.tar.gz
rust-9c044d77a334609513f3b615e0763a40cc02424d.zip
Auto merge of #110822 - scottmcm:lower-offset-to-mir, r=compiler-errors
Lower `intrinsics::offset` to `mir::BinOp::Offset`

They're [semantically the same](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.Rvalue.html#variant.BinaryOp), so this means the backends don't need to handle the intrinsic and means fewer MIR basic blocks in pointer arithmetic code.
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs7
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs8
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs17
-rw-r--r--tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.diff30
-rw-r--r--tests/mir-opt/lower_intrinsics.rs5
7 files changed, 66 insertions, 20 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 03f2a65fcca..90b36c61114 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -534,7 +534,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
         // The only difference between offset and arith_offset is regarding UB. Because Cranelift
         // doesn't have UB both are codegen'ed the same way
-        sym::offset | sym::arith_offset => {
+        sym::arith_offset => {
             intrinsic_args!(fx, args => (base, offset); intrinsic);
             let offset = offset.load_scalar(fx);
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 7af7fc92dbc..1479242f23a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -135,13 +135,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     .unwrap();
                 OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
             }
-            sym::offset => {
-                let ty = substs.type_at(0);
-                let layout = bx.layout_of(ty);
-                let ptr = args[0].immediate();
-                let offset = args[1].immediate();
-                bx.inbounds_gep(bx.backend_type(layout), ptr, &[offset])
-            }
             sym::arith_offset => {
                 let ty = substs.type_at(0);
                 let layout = bx.layout_of(ty);
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 814b67b46ec..bfca58a15b3 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -559,11 +559,20 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     }
 
     fn binary_ptr_op(
-        _ecx: &InterpCx<'mir, 'tcx, Self>,
-        _bin_op: mir::BinOp,
-        _left: &ImmTy<'tcx>,
-        _right: &ImmTy<'tcx>,
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        bin_op: mir::BinOp,
+        left: &ImmTy<'tcx>,
+        right: &ImmTy<'tcx>,
     ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
+        if bin_op == mir::BinOp::Offset {
+            let ptr = left.to_scalar().to_pointer(ecx)?;
+            let offset_count = right.to_scalar().to_target_isize(ecx)?;
+            let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
+
+            let offset_ptr = ecx.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
+            return Ok((Scalar::from_maybe_pointer(offset_ptr, ecx), false, left.layout.ty));
+        }
+
         throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index eada75ae391..a77c699c22f 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -286,14 +286,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::write_bytes => {
                 self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?;
             }
-            sym::offset => {
-                let ptr = self.read_pointer(&args[0])?;
-                let offset_count = self.read_target_isize(&args[1])?;
-                let pointee_ty = substs.type_at(0);
-
-                let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
-                self.write_pointer(offset_ptr, dest)?;
-            }
             sym::arith_offset => {
                 let ptr = self.read_pointer(&args[0])?;
                 let offset_count = self.read_target_isize(&args[1])?;
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index c7d3f6c9f04..62b727674c5 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -192,6 +192,23 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             terminator.kind = TerminatorKind::Goto { target };
                         }
                     }
+                    sym::offset => {
+                        let target = target.unwrap();
+                        let Ok([ptr, delta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
+                            span_bug!(
+                                terminator.source_info.span,
+                                "Wrong number of arguments for offset intrinsic",
+                            );
+                        };
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, delta))),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::option_payload_ptr => {
                         if let (Some(target), Some(arg)) = (*target, args[0].place()) {
                             let ty::RawPtr(ty::TypeAndMut { ty: dest_ty, .. }) =
diff --git a/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.diff
new file mode 100644
index 00000000000..f342bf30d02
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.diff
@@ -0,0 +1,30 @@
+- // MIR for `ptr_offset` before LowerIntrinsics
++ // MIR for `ptr_offset` after LowerIntrinsics
+  
+  fn ptr_offset(_1: *const i32, _2: isize) -> *const i32 {
+      debug p => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:26: +0:27
+      debug d => _2;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:41: +0:42
+      let mut _0: *const i32;              // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:54: +0:64
+      let mut _3: *const i32;              // in scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
+      let mut _4: isize;                   // in scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
+          _3 = _1;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
+          StorageLive(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34
+          _4 = _2;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34
+-         _0 = offset::<i32>(move _3, move _4) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:140:5: 140:29
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, isize) -> *const i32 {offset::<i32>}, val: Value(<ZST>) }
++         _0 = Offset(move _3, move _4);   // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35
+      }
+  
+      bb1: {
+          StorageDead(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+          StorageDead(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs
index 33fef930ad3..ad690f803c4 100644
--- a/tests/mir-opt/lower_intrinsics.rs
+++ b/tests/mir-opt/lower_intrinsics.rs
@@ -134,3 +134,8 @@ pub fn option_payload(o: &Option<usize>, p: &Option<String>) {
         let _y = core::intrinsics::option_payload_ptr(p);
     }
 }
+
+// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff
+pub unsafe fn ptr_offset(p: *const i32, d: isize) -> *const i32 {
+    core::intrinsics::offset(p, d)
+}