Skip to content

Commit 9ef5d52

Browse files
committed
Auto merge of rust-lang#111061 - cjgillot:reorder-passes, r=<try>
[perf] Enable some more MIR optimizations r? `@ghost`
2 parents 88189a7 + 0c2525b commit 9ef5d52

File tree

242 files changed

+11161
-5483
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

242 files changed

+11161
-5483
lines changed

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+85-54
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ use super::operand::{OperandRef, OperandValue};
1717
use super::place::PlaceRef;
1818
use super::{FunctionCx, LocalRef};
1919

20-
use std::ops::Range;
21-
2220
pub struct FunctionDebugContext<'tcx, S, L> {
2321
/// Maps from source code to the corresponding debug info scope.
2422
pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
@@ -36,17 +34,17 @@ pub enum VariableKind {
3634
#[derive(Clone)]
3735
pub struct PerLocalVarDebugInfo<'tcx, D> {
3836
pub name: Symbol,
37+
pub ty: Ty<'tcx>,
3938
pub source_info: mir::SourceInfo,
4039

4140
/// `DIVariable` returned by `create_dbg_var`.
4241
pub dbg_var: Option<D>,
4342

44-
/// Byte range in the `dbg_var` covered by this fragment,
45-
/// if this is a fragment of a composite `VarDebugInfo`.
46-
pub fragment: Option<Range<Size>>,
47-
4843
/// `.place.projection` from `mir::VarDebugInfo`.
49-
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
44+
pub projection: &'tcx [mir::PlaceElem<'tcx>],
45+
46+
/// Projection from fragment debuginfo.
47+
pub fragment: &'tcx [mir::PlaceElem<'tcx>],
5048
}
5149

5250
#[derive(Clone, Copy, Debug)]
@@ -149,6 +147,8 @@ struct DebugInfoOffset<T> {
149147
indirect_offsets: Vec<Size>,
150148
/// The final location debuginfo should point to.
151149
result: T,
150+
/// Whether the final location is a fragment of a larger contiguous projection.
151+
fragment: bool,
152152
}
153153

154154
fn calculate_debuginfo_offset<
@@ -165,17 +165,21 @@ fn calculate_debuginfo_offset<
165165
// FIXME(eddyb) use smallvec here.
166166
let mut indirect_offsets = vec![];
167167
let mut place = base;
168+
let mut fragment = false;
168169

169170
for elem in projection {
171+
let layout = place.layout();
170172
match *elem {
171173
mir::ProjectionElem::Deref => {
172174
indirect_offsets.push(Size::ZERO);
173175
place = place.deref(bx);
176+
fragment = false;
174177
}
175178
mir::ProjectionElem::Field(field, _) => {
176179
let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
177180
*offset += place.layout().fields.offset(field.index());
178181
place = place.project_field(bx, field);
182+
fragment |= place.layout().size != layout.size;
179183
}
180184
mir::ProjectionElem::Downcast(_, variant) => {
181185
place = place.downcast(bx, variant);
@@ -191,16 +195,17 @@ fn calculate_debuginfo_offset<
191195
};
192196
*offset += stride * index;
193197
place = place.project_constant_index(bx, index);
198+
fragment |= place.layout().size != layout.size;
194199
}
195200
_ => {
196201
// Sanity check for `can_use_in_debuginfo`.
197202
debug_assert!(!elem.can_use_in_debuginfo());
198-
bug!("unsupported var debuginfo projection `{:?}`", projection)
203+
bug!("unsupported var debuginfo place `{:?}`", projection)
199204
}
200205
}
201206
}
202207

203-
DebugInfoOffset { direct_offset, indirect_offsets, result: place }
208+
DebugInfoOffset { direct_offset, indirect_offsets, result: place, fragment }
204209
}
205210

206211
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -290,14 +295,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
290295
} else {
291296
let name = kw::Empty;
292297
let decl = &self.mir.local_decls[local];
298+
let arg_ty = self.monomorphize(decl.ty);
299+
293300
let dbg_var = if full_debug_info {
294301
self.adjusted_span_and_dbg_scope(decl.source_info).map(
295302
|(dbg_scope, _, span)| {
296303
// FIXME(eddyb) is this `+ 1` needed at all?
297304
let kind = VariableKind::ArgumentVariable(arg_index + 1);
298305

299-
let arg_ty = self.monomorphize(decl.ty);
300-
301306
self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
302307
},
303308
)
@@ -307,10 +312,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
307312

308313
Some(PerLocalVarDebugInfo {
309314
name,
315+
ty: arg_ty,
310316
source_info: decl.source_info,
311317
dbg_var,
312-
fragment: None,
313-
projection: ty::List::empty(),
318+
fragment: &[],
319+
projection: &[],
314320
})
315321
}
316322
} else {
@@ -392,8 +398,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
392398
let Some(dbg_var) = var.dbg_var else { return };
393399
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
394400

395-
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
401+
let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _, fragment: _ } =
396402
calculate_debuginfo_offset(bx, var.projection, base.layout);
403+
let mut indirect_offsets = &indirect_offsets[..];
397404

398405
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
399406
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -410,8 +417,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
410417
&& (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
411418

412419
if should_create_individual_allocas {
413-
let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
414-
calculate_debuginfo_offset(bx, var.projection, base);
420+
let DebugInfoOffset {
421+
direct_offset: _,
422+
indirect_offsets: _,
423+
fragment: _,
424+
result: place,
425+
} = calculate_debuginfo_offset(bx, var.projection, base);
415426

416427
// Create a variable which will be a pointer to the actual value
417428
let ptr_ty = Ty::new_ptr(
@@ -426,24 +437,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
426437
bx.store(place.llval, alloca.llval, alloca.align);
427438

428439
// Point the debug info to `*alloca` for the current variable
429-
bx.dbg_var_addr(
430-
dbg_var,
431-
dbg_loc,
432-
alloca.llval,
433-
Size::ZERO,
434-
&[Size::ZERO],
435-
var.fragment,
436-
);
440+
direct_offset = Size::ZERO;
441+
indirect_offsets = &[Size::ZERO];
442+
}
443+
444+
self.debug_introduce_place(
445+
bx,
446+
dbg_var,
447+
dbg_loc,
448+
base.llval,
449+
direct_offset,
450+
indirect_offsets,
451+
var.ty,
452+
var.fragment,
453+
);
454+
}
455+
456+
fn debug_introduce_place(
457+
&self,
458+
bx: &mut Bx,
459+
dbg_var: Bx::DIVariable,
460+
dbg_loc: Bx::DILocation,
461+
base: Bx::Value,
462+
direct_offset: Size,
463+
indirect_offsets: &[Size],
464+
ty: Ty<'tcx>,
465+
fragment: &[mir::PlaceElem<'tcx>],
466+
) {
467+
let DebugInfoOffset {
468+
direct_offset: fragment_offset,
469+
indirect_offsets: fragment_indirect,
470+
result: fragment_layout,
471+
fragment,
472+
} = calculate_debuginfo_offset(bx, fragment, bx.layout_of(ty));
473+
474+
let fragment = if fragment_layout.size == Size::ZERO {
475+
return;
476+
} else if fragment {
477+
Some(fragment_offset..fragment_offset + fragment_layout.size)
437478
} else {
438-
bx.dbg_var_addr(
439-
dbg_var,
440-
dbg_loc,
441-
base.llval,
442-
direct_offset,
443-
&indirect_offsets,
444-
var.fragment,
445-
);
479+
None
480+
};
481+
482+
if !fragment_indirect.is_empty() {
483+
return;
446484
}
485+
486+
bx.dbg_var_addr(dbg_var, dbg_loc, base, direct_offset, indirect_offsets, fragment);
447487
}
448488

449489
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
@@ -515,32 +555,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
515555
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
516556
});
517557

518-
let fragment = if let Some(ref fragment) = var.composite {
519-
let var_layout = self.cx.layout_of(var_ty);
520-
521-
let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } =
522-
calculate_debuginfo_offset(bx, &fragment.projection, var_layout);
523-
debug_assert!(indirect_offsets.is_empty());
524-
525-
if fragment_layout.size == Size::ZERO {
526-
// Fragment is a ZST, so does not represent anything. Avoid generating anything
527-
// as this may conflict with a fragment that covers the entire variable.
528-
continue;
529-
} else if fragment_layout.size == var_layout.size {
530-
// Fragment covers entire variable, so as far as
531-
// DWARF is concerned, it's not really a fragment.
532-
None
533-
} else {
534-
Some(direct_offset..direct_offset + fragment_layout.size)
535-
}
536-
} else {
537-
None
538-
};
558+
let fragment =
559+
if let Some(ref fragment) = var.composite { &fragment.projection[..] } else { &[] };
539560

540561
match var.value {
541562
mir::VarDebugInfoContents::Place(place) => {
542563
per_local[place.local].push(PerLocalVarDebugInfo {
543564
name: var.name,
565+
ty: var_ty,
544566
source_info: var.source_info,
545567
dbg_var,
546568
fragment,
@@ -556,7 +578,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
556578
let base =
557579
Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx);
558580

559-
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[], fragment);
581+
self.debug_introduce_place(
582+
bx,
583+
dbg_var,
584+
dbg_loc,
585+
base.llval,
586+
Size::ZERO,
587+
&[],
588+
var_ty,
589+
fragment,
590+
);
560591
}
561592
}
562593
}

compiler/rustc_const_eval/src/interpret/cast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
416416
}
417417
}
418418

419-
fn unsize_into(
419+
pub fn unsize_into(
420420
&mut self,
421421
src: &OpTy<'tcx, M::Provenance>,
422422
cast_ty: TyAndLayout<'tcx>,

compiler/rustc_const_eval/src/transform/validate.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
748748
format!("invalid empty projection in debuginfo for {:?}", debuginfo.name),
749749
);
750750
}
751-
if projection.iter().any(|p| !matches!(p, PlaceElem::Field(..))) {
751+
if !projection.iter().all(|p| {
752+
matches!(
753+
p,
754+
PlaceElem::Field(..) | PlaceElem::Deref | PlaceElem::ConstantIndex { .. }
755+
)
756+
}) {
752757
self.fail(
753758
START_BLOCK.start_location(),
754759
format!(

compiler/rustc_middle/src/mir/visit.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -846,8 +846,13 @@ macro_rules! make_mir_visitor {
846846
if let Some(box VarDebugInfoFragment { ref $($mutability)? ty, ref $($mutability)? projection }) = composite {
847847
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
848848
for elem in projection {
849-
let ProjectionElem::Field(_, ty) = elem else { bug!() };
850-
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
849+
match elem {
850+
ProjectionElem::Deref | ProjectionElem::ConstantIndex { .. } => {}
851+
ProjectionElem::Field(_, ty) => {
852+
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location))
853+
}
854+
_ => bug!("unexpected projection in debuginfo: {elem:?}"),
855+
}
851856
}
852857
}
853858
match value {

compiler/rustc_mir_dataflow/src/value_analysis.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ impl Map {
720720
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
721721
/// chosen is an implementation detail and may not be relied upon (other than that their type
722722
/// are scalars).
723-
pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) -> Self {
723+
pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, place_limit: Option<usize>) -> Self {
724724
let mut map = Self {
725725
locals: IndexVec::new(),
726726
projections: FxHashMap::default(),
@@ -730,7 +730,7 @@ impl Map {
730730
inner_values_buffer: Vec::new(),
731731
};
732732
let exclude = excluded_locals(body);
733-
map.register(tcx, body, exclude, value_limit);
733+
map.register(tcx, body, exclude, place_limit);
734734
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
735735
map
736736
}
@@ -741,9 +741,9 @@ impl Map {
741741
tcx: TyCtxt<'tcx>,
742742
body: &Body<'tcx>,
743743
exclude: BitSet<Local>,
744-
value_limit: Option<usize>,
744+
place_limit: Option<usize>,
745745
) {
746-
let mut worklist = VecDeque::with_capacity(value_limit.unwrap_or(body.local_decls.len()));
746+
let mut worklist = VecDeque::with_capacity(place_limit.unwrap_or(body.local_decls.len()));
747747
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
748748

749749
// Start by constructing the places for each bare local.
@@ -766,8 +766,8 @@ impl Map {
766766
// `elem1` is either `Some(Variant(i))` or `None`.
767767
while let Some((mut place, elem1, elem2, ty)) = worklist.pop_front() {
768768
// The user requires a bound on the number of created values.
769-
if let Some(value_limit) = value_limit
770-
&& self.value_count >= value_limit
769+
if let Some(place_limit) = place_limit
770+
&& self.places.len() >= place_limit
771771
{
772772
break;
773773
}

0 commit comments

Comments
 (0)