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
|
@ -31,7 +31,9 @@ use tracing::{debug, instrument};
|
|||
use crate::abi::FnAbiLlvmExt;
|
||||
use crate::common::Funclet;
|
||||
use crate::context::{CodegenCx, SimpleCx};
|
||||
use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, Metadata, True};
|
||||
use crate::llvm::{
|
||||
self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True,
|
||||
};
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
|
@ -910,13 +912,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
|
||||
fn gep(&mut self, ty: &'ll Type, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
|
||||
unsafe {
|
||||
llvm::LLVMBuildGEP2(
|
||||
llvm::LLVMBuildGEPWithNoWrapFlags(
|
||||
self.llbuilder,
|
||||
ty,
|
||||
ptr,
|
||||
indices.as_ptr(),
|
||||
indices.len() as c_uint,
|
||||
UNNAMED,
|
||||
GEPNoWrapFlags::default(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -928,13 +931,33 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
indices: &[&'ll Value],
|
||||
) -> &'ll Value {
|
||||
unsafe {
|
||||
llvm::LLVMBuildInBoundsGEP2(
|
||||
llvm::LLVMBuildGEPWithNoWrapFlags(
|
||||
self.llbuilder,
|
||||
ty,
|
||||
ptr,
|
||||
indices.as_ptr(),
|
||||
indices.len() as c_uint,
|
||||
UNNAMED,
|
||||
GEPNoWrapFlags::InBounds,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn inbounds_nuw_gep(
|
||||
&mut self,
|
||||
ty: &'ll Type,
|
||||
ptr: &'ll Value,
|
||||
indices: &[&'ll Value],
|
||||
) -> &'ll Value {
|
||||
unsafe {
|
||||
llvm::LLVMBuildGEPWithNoWrapFlags(
|
||||
self.llbuilder,
|
||||
ty,
|
||||
ptr,
|
||||
indices.as_ptr(),
|
||||
indices.len() as c_uint,
|
||||
UNNAMED,
|
||||
GEPNoWrapFlags::InBounds | GEPNoWrapFlags::NUW,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -954,6 +954,17 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
// These values **must** match with LLVMGEPNoWrapFlags
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
#[derive(Default)]
|
||||
pub struct GEPNoWrapFlags : c_uint {
|
||||
const InBounds = 1 << 0;
|
||||
const NUSW = 1 << 1;
|
||||
const NUW = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
pub type ModuleBuffer;
|
||||
}
|
||||
|
@ -1454,21 +1465,14 @@ unsafe extern "C" {
|
|||
|
||||
pub(crate) fn LLVMBuildStore<'a>(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
|
||||
|
||||
pub(crate) fn LLVMBuildGEP2<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Pointer: &'a Value,
|
||||
Indices: *const &'a Value,
|
||||
NumIndices: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
pub(crate) fn LLVMBuildInBoundsGEP2<'a>(
|
||||
pub(crate) fn LLVMBuildGEPWithNoWrapFlags<'a>(
|
||||
B: &Builder<'a>,
|
||||
Ty: &'a Type,
|
||||
Pointer: &'a Value,
|
||||
Indices: *const &'a Value,
|
||||
NumIndices: c_uint,
|
||||
Name: *const c_char,
|
||||
Flags: GEPNoWrapFlags,
|
||||
) -> &'a Value;
|
||||
|
||||
// Casts
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue