Unify validity checks into a single query
Previously, there were two queries to check whether a type allows the 0x01 or zeroed bitpattern. I am planning on adding a further initness to check, truly uninit for MaybeUninit, which would make this three queries. This seems overkill for such a small feature, so this PR unifies them into one.
This commit is contained in:
parent
b869e84e58
commit
025d2a147f
11 changed files with 89 additions and 67 deletions
|
@ -6,8 +6,8 @@ use rustc_middle::mir::{
|
|||
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
|
||||
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
|
||||
};
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
use rustc_middle::ty::{self, ParamEnv, ParamEnvAnd, SubstsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::layout::InitKind;
|
||||
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
pub struct InstCombine;
|
||||
|
@ -234,16 +234,15 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
|
|||
}
|
||||
let ty = substs.type_at(0);
|
||||
|
||||
// Check this is a foldable intrinsic before we query the layout of our generic parameter
|
||||
let Some(assert_panics) = intrinsic_assert_panics(intrinsic_name) else { return; };
|
||||
match assert_panics(self.tcx, self.param_env.and(ty)) {
|
||||
// We don't know the layout, don't touch the assertion
|
||||
Err(_) => {}
|
||||
Ok(true) => {
|
||||
let known_is_valid = intrinsic_assert_panics(self.tcx, self.param_env, ty, intrinsic_name);
|
||||
match known_is_valid {
|
||||
// We don't know the layout or it's not validity assertion at all, don't touch it
|
||||
None => {}
|
||||
Some(true) => {
|
||||
// If we know the assert panics, indicate to later opts that the call diverges
|
||||
*target = None;
|
||||
}
|
||||
Ok(false) => {
|
||||
Some(false) => {
|
||||
// If we know the assert does not panic, turn the call into a Goto
|
||||
terminator.kind = TerminatorKind::Goto { target: *target_block };
|
||||
}
|
||||
|
@ -252,33 +251,21 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
|
|||
}
|
||||
|
||||
fn intrinsic_assert_panics<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
intrinsic_name: Symbol,
|
||||
) -> Option<fn(TyCtxt<'tcx>, ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, LayoutError<'tcx>>> {
|
||||
fn inhabited_predicate<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
) -> Result<bool, LayoutError<'tcx>> {
|
||||
Ok(tcx.layout_of(param_env_and_ty)?.abi.is_uninhabited())
|
||||
}
|
||||
fn zero_valid_predicate<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
) -> Result<bool, LayoutError<'tcx>> {
|
||||
Ok(!tcx.permits_zero_init(param_env_and_ty)?)
|
||||
}
|
||||
fn mem_uninitialized_valid_predicate<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
) -> Result<bool, LayoutError<'tcx>> {
|
||||
Ok(!tcx.permits_uninit_init(param_env_and_ty)?)
|
||||
}
|
||||
|
||||
match intrinsic_name {
|
||||
sym::assert_inhabited => Some(inhabited_predicate),
|
||||
sym::assert_zero_valid => Some(zero_valid_predicate),
|
||||
sym::assert_mem_uninitialized_valid => Some(mem_uninitialized_valid_predicate),
|
||||
_ => None,
|
||||
}
|
||||
) -> Option<bool> {
|
||||
Some(match intrinsic_name {
|
||||
sym::assert_inhabited => tcx.layout_of(param_env.and(ty)).ok()?.abi.is_uninhabited(),
|
||||
sym::assert_zero_valid => {
|
||||
!tcx.check_validity_of_init((InitKind::Zero, param_env.and(ty))).ok()?
|
||||
}
|
||||
sym::assert_mem_uninitialized_valid => !tcx
|
||||
.check_validity_of_init((InitKind::UninitMitigated0x01Fill, param_env.and(ty)))
|
||||
.ok()?,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn resolve_rust_intrinsic<'tcx>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue