1
Fork 0

Rollup merge of #97077 - ouz-a:Optimize-backend, r=oli-obk

Simplify some code that depend on Deref

Now that we can assume #97025 works, it's safe to expect Deref is always in the first place of projections. With this, I was able to simplify some code that depended on Deref's place in projections. When we are able to move Derefer before `ElaborateDrops` successfully we will be able to optimize more places.

r? `@oli-obk`
This commit is contained in:
Yuki Okushi 2022-07-26 07:14:44 +09:00 committed by GitHub
commit 29892759f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 30 deletions

View file

@ -435,18 +435,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
LocalRef::Place(place) => place, LocalRef::Place(place) => place,
LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx), LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
LocalRef::Operand(..) => { LocalRef::Operand(..) => {
if let Some(elem) = place_ref if place_ref.has_deref() {
.projection base = 1;
.iter()
.enumerate()
.find(|elem| matches!(elem.1, mir::ProjectionElem::Deref))
{
base = elem.0 + 1;
let cg_base = self.codegen_consume( let cg_base = self.codegen_consume(
bx, bx,
mir::PlaceRef { projection: &place_ref.projection[..elem.0], ..place_ref }, mir::PlaceRef { projection: &place_ref.projection[..0], ..place_ref },
); );
cg_base.deref(bx.cx()) cg_base.deref(bx.cx())
} else { } else {
bug!("using operand local {:?} as place", place_ref); bug!("using operand local {:?} as place", place_ref);

View file

@ -1461,6 +1461,14 @@ impl<'tcx> Place<'tcx> {
self.projection.iter().any(|elem| elem.is_indirect()) self.projection.iter().any(|elem| elem.is_indirect())
} }
/// If MirPhase >= Derefered and if projection contains Deref,
/// It's guaranteed to be in the first place
pub fn has_deref(&self) -> bool {
// To make sure this is not accidently used in wrong mir phase
debug_assert!(!self.projection[1..].contains(&PlaceElem::Deref));
self.projection.first() == Some(&PlaceElem::Deref)
}
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
/// a single deref of a local. /// a single deref of a local.
#[inline(always)] #[inline(always)]
@ -1533,6 +1541,12 @@ impl<'tcx> PlaceRef<'tcx> {
} }
} }
/// If MirPhase >= Derefered and if projection contains Deref,
/// It's guaranteed to be in the first place
pub fn has_deref(&self) -> bool {
self.projection.first() == Some(&PlaceElem::Deref)
}
/// If this place represents a local variable like `_X` with no /// If this place represents a local variable like `_X` with no
/// projections, return `Some(_X)`. /// projections, return `Some(_X)`.
#[inline] #[inline]

View file

@ -15,22 +15,9 @@ pub struct AddRetag;
/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic /// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
/// copies. Data races are UB.) /// copies. Data races are UB.)
fn is_stable(place: PlaceRef<'_>) -> bool { fn is_stable(place: PlaceRef<'_>) -> bool {
place.projection.iter().all(|elem| {
match elem {
// Which place this evaluates to can change with any memory write, // Which place this evaluates to can change with any memory write,
// so cannot assume this to be stable. // so cannot assume deref to be stable.
ProjectionElem::Deref => false, !place.has_deref()
// Array indices are interesting, but MIR building generates a *fresh*
// temporary for every array access, so the index cannot be changed as
// a side-effect.
ProjectionElem::Index { .. } |
// The rest is completely boring, they just offset by a constant.
ProjectionElem::Field { .. } |
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Subslice { .. } |
ProjectionElem::Downcast { .. } => true,
}
})
} }
/// Determine whether this type may contain a reference (or box), and thus needs retagging. /// Determine whether this type may contain a reference (or box), and thus needs retagging.
@ -91,11 +78,8 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
}; };
let place_base_raw = |place: &Place<'tcx>| { let place_base_raw = |place: &Place<'tcx>| {
// If this is a `Deref`, get the type of what we are deref'ing. // If this is a `Deref`, get the type of what we are deref'ing.
let deref_base = if place.has_deref() {
place.projection.iter().rposition(|p| matches!(p, ProjectionElem::Deref)); let ty = &local_decls[place.local].ty;
if let Some(deref_base) = deref_base {
let base_proj = &place.projection[..deref_base];
let ty = Place::ty_from(place.local, base_proj, &*local_decls, tcx).ty;
ty.is_unsafe_ptr() ty.is_unsafe_ptr()
} else { } else {
// Not a deref, and thus not raw. // Not a deref, and thus not raw.