Auto merge of #136735 - scottmcm:transmute-nonnull, r=oli-obk
`transmute` should also assume non-null pointers Previously it only did integer-ABI things, but this way it does data pointers too. That gives more information in general to the backend, and allows slightly simplifying one of the helpers in slice iterators.
This commit is contained in:
commit
d88ffcdb8b
8 changed files with 148 additions and 78 deletions
|
@ -435,18 +435,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
scalar: abi::Scalar,
|
||||
backend_ty: Bx::Type,
|
||||
) {
|
||||
if matches!(self.cx.sess().opts.optimize, OptLevel::No)
|
||||
// For now, the critical niches are all over `Int`eger values.
|
||||
// Should floating-point values or pointers ever get more complex
|
||||
// niches, then this code will probably want to handle them too.
|
||||
|| !matches!(scalar.primitive(), abi::Primitive::Int(..))
|
||||
|| scalar.is_always_valid(self.cx)
|
||||
{
|
||||
if matches!(self.cx.sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(self.cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
let range = scalar.valid_range(self.cx);
|
||||
bx.assume_integer_range(imm, backend_ty, range);
|
||||
match scalar.primitive() {
|
||||
abi::Primitive::Int(..) => {
|
||||
let range = scalar.valid_range(self.cx);
|
||||
bx.assume_integer_range(imm, backend_ty, range);
|
||||
}
|
||||
abi::Primitive::Pointer(abi::AddressSpace::DATA)
|
||||
if !scalar.valid_range(self.cx).contains(0) =>
|
||||
{
|
||||
bx.assume_nonnull(imm);
|
||||
}
|
||||
abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_rvalue_unsized(
|
||||
|
|
|
@ -243,6 +243,19 @@ pub trait BuilderMethods<'a, 'tcx>:
|
|||
self.assume(cmp);
|
||||
}
|
||||
|
||||
/// Emits an `assume` that the `val` of pointer type is non-null.
|
||||
///
|
||||
/// You may want to check the optimization level before bothering calling this.
|
||||
fn assume_nonnull(&mut self, val: Self::Value) {
|
||||
// Arguably in LLVM it'd be better to emit an assume operand bundle instead
|
||||
// <https://llvm.org/docs/LangRef.html#assume-operand-bundles>
|
||||
// but this works fine for all backends.
|
||||
|
||||
let null = self.const_null(self.type_ptr());
|
||||
let is_null = self.icmp(IntPredicate::IntNE, val, null);
|
||||
self.assume(is_null);
|
||||
}
|
||||
|
||||
fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
|
||||
fn nonnull_metadata(&mut self, load: Self::Value);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue