Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ impl<'tcx> Body<'tcx> {

/// Returns an iterator over all function arguments.
#[inline]
pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator + use<> {
(1..self.arg_count + 1).map(Local::new)
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty};
rustc_index::newtype_index! {
#[derive(HashStable)]
#[encodable]
#[debug_format = "_{}"]
#[debug_format = "_s{}"]
pub struct CoroutineSavedLocal {}
}

Expand Down
286 changes: 163 additions & 123 deletions compiler/rustc_mir_transform/src/coroutine.rs

Large diffs are not rendered by default.

16 changes: 13 additions & 3 deletions compiler/rustc_mir_transform/src/coroutine/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ fn build_pin_fut<'tcx>(
// Ready() => ready_block
// Pending => yield_block
//}
#[tracing::instrument(level = "trace", skip(tcx, body), ret)]
fn build_poll_switch<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
Expand Down Expand Up @@ -179,6 +180,7 @@ fn build_poll_switch<'tcx>(
}

// Gather blocks, reachable through 'drop' targets of Yield and Drop terminators (chained)
#[tracing::instrument(level = "trace", skip(body), ret)]
fn gather_dropline_blocks<'tcx>(body: &mut Body<'tcx>) -> DenseBitSet<BasicBlock> {
let mut dropline: DenseBitSet<BasicBlock> = DenseBitSet::new_empty(body.basic_blocks.len());
for (bb, data) in traversal::reverse_postorder(body) {
Expand Down Expand Up @@ -249,6 +251,7 @@ pub(super) fn has_expandable_async_drops<'tcx>(
}

/// Expand Drop terminator for async drops into mainline poll-switch and dropline poll-switch
#[tracing::instrument(level = "trace", skip(tcx, body), ret)]
pub(super) fn expand_async_drops<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
Expand All @@ -259,6 +262,7 @@ pub(super) fn expand_async_drops<'tcx>(
let dropline = gather_dropline_blocks(body);
// Clean drop and async_fut fields if potentially async drop is not expanded (stays sync)
let remove_asyncness = |block: &mut BasicBlockData<'tcx>| {
tracing::trace!("remove_asyncness");
if let TerminatorKind::Drop {
place: _,
target: _,
Expand All @@ -273,6 +277,7 @@ pub(super) fn expand_async_drops<'tcx>(
}
};
for bb in START_BLOCK..body.basic_blocks.next_index() {
tracing::trace!(?bb);
// Drops in unwind path (cleanup blocks) are not expanded to async drops, only sync drops in unwind path
if body[bb].is_cleanup {
remove_asyncness(&mut body[bb]);
Expand Down Expand Up @@ -461,6 +466,7 @@ pub(super) fn expand_async_drops<'tcx>(
}
}

#[tracing::instrument(level = "trace", skip(tcx, body))]
pub(super) fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
use crate::elaborate_drop::{Unwind, elaborate_drop};
use crate::patch::MirPatch;
Expand Down Expand Up @@ -519,6 +525,7 @@ pub(super) fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
elaborator.patch.apply(body);
}

#[tracing::instrument(level = "trace", skip(tcx, body), ret)]
pub(super) fn insert_clean_drop<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
Expand Down Expand Up @@ -550,6 +557,7 @@ pub(super) fn insert_clean_drop<'tcx>(
.push(BasicBlockData::new(Some(Terminator { source_info, kind: term }), false))
}

#[tracing::instrument(level = "trace", skip(tcx, transform, body))]
pub(super) fn create_coroutine_drop_shim<'tcx>(
tcx: TyCtxt<'tcx>,
transform: &TransformVisitor<'tcx>,
Expand Down Expand Up @@ -621,6 +629,7 @@ pub(super) fn create_coroutine_drop_shim<'tcx>(
}

// Create async drop shim function to drop coroutine itself
#[tracing::instrument(level = "trace", skip(tcx, transform, body))]
pub(super) fn create_coroutine_drop_shim_async<'tcx>(
tcx: TyCtxt<'tcx>,
transform: &TransformVisitor<'tcx>,
Expand Down Expand Up @@ -676,12 +685,13 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>(
let poll_enum = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()]));
body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(poll_enum, source_info);

make_coroutine_state_argument_indirect(tcx, &mut body);

match transform.coroutine_kind {
// Iterator::next doesn't accept a pinned argument,
// unlike for all other coroutine kinds.
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {}
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
make_coroutine_state_argument_indirect(tcx, &mut body);
}

_ => {
make_coroutine_state_argument_pinned(tcx, &mut body);
}
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_mir_transform/src/dataflow_const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
return;
}

// Avoid computing layout inside coroutines, since their `optimized_mir` is used for layout
// computation, which can create a cycle.
if body.coroutine.is_some() {
return;
}

// We want to have a somewhat linear runtime w.r.t. the number of statements/terminators.
// Let's call this number `n`. Dataflow analysis has `O(h*n)` transfer function
// applications, where `h` is the height of the lattice. Because the height of our lattice
Expand Down Expand Up @@ -241,9 +247,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
TerminatorKind::Drop { place, .. } => {
state.flood_with(place.as_ref(), &self.map, FlatSet::<Scalar>::BOTTOM);
}
TerminatorKind::Yield { .. } => {
// They would have an effect, but are not allowed in this phase.
bug!("encountered disallowed terminator");
TerminatorKind::Yield { resume_arg, .. } => {
state.flood_with(resume_arg.as_ref(), &self.map, FlatSet::<Scalar>::BOTTOM);
}
TerminatorKind::SwitchInt { discr, targets } => {
return self.handle_switch_int(discr, targets, state);
Expand Down
20 changes: 12 additions & 8 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1730,14 +1730,18 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
}

fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator {
if let Some(local) = destination.as_local()
&& self.ssa.is_ssa(local)
{
let ty = self.local_decls[local].ty;
let opaque = self.new_opaque(ty);
self.assign(local, opaque);
}
let destination = match terminator.kind {
TerminatorKind::Call { destination, .. } => Some(destination),
TerminatorKind::Yield { resume_arg, .. } => Some(resume_arg),
_ => None,
};
if let Some(destination) = destination
&& let Some(local) = destination.as_local()
&& self.ssa.is_ssa(local)
{
let ty = self.local_decls[local].ty;
let opaque = self.new_opaque(ty);
self.assign(local, opaque);
}
// Function calls and ASM may invalidate (nested) derefs. We must handle them carefully.
// Currently, only preserving derefs for trivial terminators like SwitchInt and Goto.
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_mir_transform/src/jump_threading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
| TerminatorKind::Unreachable
| TerminatorKind::CoroutineDrop => bug!("{term:?} has no terminators"),
// Disallowed during optimizations.
TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Yield { .. } => bug!("{term:?} invalid"),
TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => {
bug!("{term:?} invalid")
}
// Cannot reason about inline asm.
TerminatorKind::InlineAsm { .. } => return,
// `SwitchInt` is handled specially.
Expand All @@ -623,6 +623,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
TerminatorKind::Goto { .. } => None,
// Flood the overwritten place, and progress through.
TerminatorKind::Drop { place: destination, .. }
| TerminatorKind::Yield { resume_arg: destination, .. }
| TerminatorKind::Call { destination, .. } => Some(destination),
// Ignore, as this can be a no-op at codegen time.
TerminatorKind::Assert { .. } => None,
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ mod ssa;
macro_rules! declare_passes {
(
$(
$vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* } )?),+ $(,)?;
$vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* $(,)? } )?),+ $(,)?;
)*
) => {
$(
Expand Down Expand Up @@ -180,12 +180,14 @@ declare_passes! {
PreOptimizations,
Final,
MakeShim,
AfterUnreachableEnumBranching
AfterUnreachableEnumBranching,
PostStateTransform,
},
SimplifyLocals {
BeforeConstProp,
AfterGVN,
Final
Final,
PostStateTransform,
};
mod simplify_branches : SimplifyConstCondition {
AfterConstProp,
Expand Down Expand Up @@ -621,7 +623,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Otherwise it should run fairly late, but before optimizations begin.
&add_retag::AddRetag,
&elaborate_box_derefs::ElaborateBoxDerefs,
&coroutine::StateTransform,
&Lint(known_panics_lint::KnownPanicsLint),
];
pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
Expand Down Expand Up @@ -727,6 +728,7 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
&simplify::SimplifyLocals::Final,
&multiple_return_terminators::MultipleReturnTerminators,
&large_enums::EnumSizeOpt { discrepancy: 128 },
&coroutine::StateTransform,
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
&add_call_guards::CriticalCallEdges,
// Cleanup for human readability, off by default.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
tcx,
&mut body,
&[
&mentioned_items::MentionedItems,
&abort_unwinding_calls::AbortUnwindingCalls,
&add_call_guards::CriticalCallEdges,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ fn build_adrop_for_coroutine_shim<'tcx>(
body.source.instance = instance;
body.phase = MirPhase::Runtime(RuntimePhase::Initial);
body.var_debug_info.clear();
body.mentioned_items = None;
let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span));
let args = tcx.mk_args(&[proxy_ref.into()]);
let pin_proxy_ref = Ty::new_adt(tcx, pin_adt_ref, args);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_mir_transform/src/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub(super) enum SimplifyCfg {
Final,
MakeShim,
AfterUnreachableEnumBranching,
/// Extra run introduced by `StateTransform`.
PostStateTransform,
}

impl SimplifyCfg {
Expand All @@ -70,6 +72,7 @@ impl SimplifyCfg {
SimplifyCfg::AfterUnreachableEnumBranching => {
"SimplifyCfg-after-unreachable-enum-branching"
}
SimplifyCfg::PostStateTransform => "SimplifyCfg-post-StateTransform",
}
}
}
Expand Down Expand Up @@ -390,6 +393,8 @@ pub(super) enum SimplifyLocals {
BeforeConstProp,
AfterGVN,
Final,
/// Extra run introduced by `StateTransform`.
PostStateTransform,
}

impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
Expand All @@ -398,6 +403,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop",
SimplifyLocals::AfterGVN => "SimplifyLocals-after-value-numbering",
SimplifyLocals::Final => "SimplifyLocals-final",
SimplifyLocals::PostStateTransform => "SimplifyLocals-post-StateTransform",
}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
if self.body.coroutine.is_none() {
self.fail(location, "`Yield` cannot appear outside coroutine bodies");
}
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) {
self.fail(location, "`Yield` should have been replaced by coroutine lowering");
}
self.check_edge(location, *resume, EdgeKind::Normal);
Expand Down Expand Up @@ -488,7 +488,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
if self.body.coroutine.is_none() {
self.fail(location, "`CoroutineDrop` cannot appear outside coroutine bodies");
}
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) {
self.fail(
location,
"`CoroutineDrop` should have been replaced by coroutine lowering",
Expand Down
Loading
Loading