Auto merge of #137271 - nikic:gep-nuw-2, r=scottmcm
Emit getelementptr inbounds nuw for pointer::add() Lower pointer::add (via intrinsic::offset with unsigned offset) to getelementptr inbounds nuw on LLVM versions that support it. This lets LLVM make use of the pre-condition that the offset addition does not wrap in an unsigned sense. Together with inbounds, this also implies that the offset is non-negative. Fixes https://github.com/rust-lang/rust/issues/137217.
This commit is contained in:
commit
e0be1a0262
10 changed files with 93 additions and 29 deletions
|
@ -423,7 +423,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
layout.size
|
||||
};
|
||||
|
||||
let llval = bx.inbounds_gep(bx.cx().backend_type(layout), self.val.llval, &[llindex]);
|
||||
let llval = bx.inbounds_nuw_gep(bx.cx().backend_type(layout), self.val.llval, &[llindex]);
|
||||
let align = self.val.align.restrict_for_offset(offset);
|
||||
PlaceValue::new_sized(llval, align).with_type(layout)
|
||||
}
|
||||
|
|
|
@ -666,9 +666,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
lhs.layout.ty,
|
||||
),
|
||||
|
||||
(OperandValue::Immediate(lhs_val), OperandValue::Immediate(rhs_val)) => {
|
||||
self.codegen_scalar_binop(bx, op, lhs_val, rhs_val, lhs.layout.ty)
|
||||
}
|
||||
(OperandValue::Immediate(lhs_val), OperandValue::Immediate(rhs_val)) => self
|
||||
.codegen_scalar_binop(
|
||||
bx,
|
||||
op,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
lhs.layout.ty,
|
||||
rhs.layout.ty,
|
||||
),
|
||||
|
||||
_ => bug!(),
|
||||
};
|
||||
|
@ -889,10 +895,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
op: mir::BinOp,
|
||||
lhs: Bx::Value,
|
||||
rhs: Bx::Value,
|
||||
input_ty: Ty<'tcx>,
|
||||
lhs_ty: Ty<'tcx>,
|
||||
rhs_ty: Ty<'tcx>,
|
||||
) -> Bx::Value {
|
||||
let is_float = input_ty.is_floating_point();
|
||||
let is_signed = input_ty.is_signed();
|
||||
let is_float = lhs_ty.is_floating_point();
|
||||
let is_signed = lhs_ty.is_signed();
|
||||
match op {
|
||||
mir::BinOp::Add => {
|
||||
if is_float {
|
||||
|
@ -958,9 +965,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::BinOp::BitAnd => bx.and(lhs, rhs),
|
||||
mir::BinOp::BitXor => bx.xor(lhs, rhs),
|
||||
mir::BinOp::Offset => {
|
||||
let pointee_type = input_ty
|
||||
let pointee_type = lhs_ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty));
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", lhs_ty));
|
||||
let pointee_layout = bx.cx().layout_of(pointee_type);
|
||||
if pointee_layout.is_zst() {
|
||||
// `Offset` works in terms of the size of pointee,
|
||||
|
@ -968,7 +975,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
lhs
|
||||
} else {
|
||||
let llty = bx.cx().backend_type(pointee_layout);
|
||||
bx.inbounds_gep(llty, lhs, &[rhs])
|
||||
if !rhs_ty.is_signed() {
|
||||
bx.inbounds_nuw_gep(llty, lhs, &[rhs])
|
||||
} else {
|
||||
bx.inbounds_gep(llty, lhs, &[rhs])
|
||||
}
|
||||
}
|
||||
}
|
||||
mir::BinOp::Shl | mir::BinOp::ShlUnchecked => {
|
||||
|
|
|
@ -325,6 +325,14 @@ pub trait BuilderMethods<'a, 'tcx>:
|
|||
ptr: Self::Value,
|
||||
indices: &[Self::Value],
|
||||
) -> Self::Value;
|
||||
fn inbounds_nuw_gep(
|
||||
&mut self,
|
||||
ty: Self::Type,
|
||||
ptr: Self::Value,
|
||||
indices: &[Self::Value],
|
||||
) -> Self::Value {
|
||||
self.inbounds_gep(ty, ptr, indices)
|
||||
}
|
||||
fn ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
|
||||
self.gep(self.cx().type_i8(), ptr, &[offset])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue