Skip to content

Commit 9c044d7

Browse files
committed
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.
2 parents 8763965 + 05a665f commit 9c044d7

File tree

7 files changed

+66
-20
lines changed

7 files changed

+66
-20
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
534534

535535
// The only difference between offset and arith_offset is regarding UB. Because Cranelift
536536
// doesn't have UB both are codegen'ed the same way
537-
sym::offset | sym::arith_offset => {
537+
sym::arith_offset => {
538538
intrinsic_args!(fx, args => (base, offset); intrinsic);
539539
let offset = offset.load_scalar(fx);
540540

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

-7
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
135135
.unwrap();
136136
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
137137
}
138-
sym::offset => {
139-
let ty = substs.type_at(0);
140-
let layout = bx.layout_of(ty);
141-
let ptr = args[0].immediate();
142-
let offset = args[1].immediate();
143-
bx.inbounds_gep(bx.backend_type(layout), ptr, &[offset])
144-
}
145138
sym::arith_offset => {
146139
let ty = substs.type_at(0);
147140
let layout = bx.layout_of(ty);

compiler/rustc_const_eval/src/const_eval/machine.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,20 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
559559
}
560560

561561
fn binary_ptr_op(
562-
_ecx: &InterpCx<'mir, 'tcx, Self>,
563-
_bin_op: mir::BinOp,
564-
_left: &ImmTy<'tcx>,
565-
_right: &ImmTy<'tcx>,
562+
ecx: &InterpCx<'mir, 'tcx, Self>,
563+
bin_op: mir::BinOp,
564+
left: &ImmTy<'tcx>,
565+
right: &ImmTy<'tcx>,
566566
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
567+
if bin_op == mir::BinOp::Offset {
568+
let ptr = left.to_scalar().to_pointer(ecx)?;
569+
let offset_count = right.to_scalar().to_target_isize(ecx)?;
570+
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
571+
572+
let offset_ptr = ecx.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
573+
return Ok((Scalar::from_maybe_pointer(offset_ptr, ecx), false, left.layout.ty));
574+
}
575+
567576
throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
568577
}
569578

compiler/rustc_const_eval/src/interpret/intrinsics.rs

-8
Original file line numberDiff line numberDiff line change
@@ -286,14 +286,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
286286
sym::write_bytes => {
287287
self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?;
288288
}
289-
sym::offset => {
290-
let ptr = self.read_pointer(&args[0])?;
291-
let offset_count = self.read_target_isize(&args[1])?;
292-
let pointee_ty = substs.type_at(0);
293-
294-
let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
295-
self.write_pointer(offset_ptr, dest)?;
296-
}
297289
sym::arith_offset => {
298290
let ptr = self.read_pointer(&args[0])?;
299291
let offset_count = self.read_target_isize(&args[1])?;

compiler/rustc_mir_transform/src/lower_intrinsics.rs

+17
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,23 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
192192
terminator.kind = TerminatorKind::Goto { target };
193193
}
194194
}
195+
sym::offset => {
196+
let target = target.unwrap();
197+
let Ok([ptr, delta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
198+
span_bug!(
199+
terminator.source_info.span,
200+
"Wrong number of arguments for offset intrinsic",
201+
);
202+
};
203+
block.statements.push(Statement {
204+
source_info: terminator.source_info,
205+
kind: StatementKind::Assign(Box::new((
206+
*destination,
207+
Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, delta))),
208+
))),
209+
});
210+
terminator.kind = TerminatorKind::Goto { target };
211+
}
195212
sym::option_payload_ptr => {
196213
if let (Some(target), Some(arg)) = (*target, args[0].place()) {
197214
let ty::RawPtr(ty::TypeAndMut { ty: dest_ty, .. }) =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
- // MIR for `ptr_offset` before LowerIntrinsics
2+
+ // MIR for `ptr_offset` after LowerIntrinsics
3+
4+
fn ptr_offset(_1: *const i32, _2: isize) -> *const i32 {
5+
debug p => _1; // in scope 0 at $DIR/lower_intrinsics.rs:+0:26: +0:27
6+
debug d => _2; // in scope 0 at $DIR/lower_intrinsics.rs:+0:41: +0:42
7+
let mut _0: *const i32; // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:54: +0:64
8+
let mut _3: *const i32; // in scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
9+
let mut _4: isize; // in scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34
10+
11+
bb0: {
12+
StorageLive(_3); // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
13+
_3 = _1; // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
14+
StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34
15+
_4 = _2; // scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34
16+
- _0 = offset::<i32>(move _3, move _4) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35
17+
- // mir::Constant
18+
- // + span: $DIR/lower_intrinsics.rs:140:5: 140:29
19+
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, isize) -> *const i32 {offset::<i32>}, val: Value(<ZST>) }
20+
+ _0 = Offset(move _3, move _4); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35
21+
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35
22+
}
23+
24+
bb1: {
25+
StorageDead(_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35
26+
StorageDead(_3); // scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35
27+
return; // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
28+
}
29+
}
30+

tests/mir-opt/lower_intrinsics.rs

+5
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,8 @@ pub fn option_payload(o: &Option<usize>, p: &Option<String>) {
134134
let _y = core::intrinsics::option_payload_ptr(p);
135135
}
136136
}
137+
138+
// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff
139+
pub unsafe fn ptr_offset(p: *const i32, d: isize) -> *const i32 {
140+
core::intrinsics::offset(p, d)
141+
}

0 commit comments

Comments
 (0)