Lower intrinsics::offset
to mir::BinOp::Offset
They're semantically the same, so this means the backends don't need to handle the intrinsic and means fewer MIR basic blocks in pointer arithmetic code.
This commit is contained in:
parent
a7aa20517c
commit
05a665f21a
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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])?;
|
||||
|
@ -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, .. }) =
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user