Struct midenc_hir_transform::RewriteSpills
source · pub struct RewriteSpills;Expand description
This pass rewrites a function annotated by the InsertSpills pass, by means of the spill and reload pseudo-instructions, such that the resulting function is semantically equivalent to the original function, but with the additional property that the function will keep the operand stack depth <= 16 at all times.
This rewrite consists of the following main objectives:
- Match all uses of spilled values with the nearest dominating definition, modifying the IR as required to ensure that all uses are strictly dominated by their definitions.
- Allocate sufficient procedure locals to store concurrently-active spills
- Rewrite all
spillinstructions to primitivelocal.storeinstructions - Rewrite used
reloadinstructions to primitivelocal.loadinstructions - Remove unused
reloadinstructions as dead code
NOTE: This pass is intended to be combined with the InsertSpills pass. If run on its own, it is effectively a no-op, so it is safe to do, but nonsensical. In a normal compilation pipeline, this pass is run immediately after InsertSpills. It is not safe to run other passes between InsertSpills and RewriteSpills, unless that pass specifically is designed to preserve the results of the SpillAnalysis computed and used by InsertSpills to place spills and reloads. Conversely, you can’t just run InsertSpills without this pass, or the resulting IR will fail to codegen.
§Design
See SpillAnalysis and InsertSpills for more context and details.
The primary purpose of this pass is twofold: reconstruct SSA form after insertion of spills and reloads by InsertSpills, and lowering of the spill and reload pseudo-instructions to primitive stores and loads from procedure-local variables. It is the final, and most important phase of the spills transformation.
Unlike InsertSpills, which mainly just materializes the results of the SpillAnalysis, this pass must do a tricky combo of dataflow analysis and rewrite in a single postorder traversal of the CFG (i.e. bottom-up):
- We need to find uses of spilled values as we encounter them, and keep track of them until we find an appropriate definition for each use.
- We need to propagate uses up the dominance tree until all uses are matched with definitions
- We need to rewrite uses when we find a definition
- We need to identify whether a block we are about to leave (on our way up the CFG), is in the iterated dominance frontier for the set of spilled values we’ve found uses for. If it is, we must append a new block parameter, rewrite the terminator of any predecessor blocks, and rewrite all uses found so far by using the new block parameter as the dominating definition.
Technically, this pass could be generalized a step further, such that it fixes up invalid def-use relationships in general, rather than just the narrow case of spills/reloads - but it is more efficient to keep it specialized for now, we can always generalize later.
This pass guarantees that:
- No
spillorreloadinstructions remain in the IR - The semantics of the original IR on which InsertSpills was run, will be preserved, if:
- The original IR was valid
- No modification to the IR was made between InsertSpills and RewriteSpills
- The resulting function, once compiled to Miden Assembly, will keep the operand stack depth <= 16 elements, so long as the schedule produced by the backend preserves the scheduling semantics. For example, spills/reloads are computed based on an implied scheduling of operations, given by following the control flow graph, and visiting instructions in a block top-down. If the backend reschedules operations for more optimal placement of operands on the operand stack, it is possible that this rescheduling could result in the operand stack depth exceeding 16 elements. However, at this point, it is not expected that this will be a practical issue, even if it does occur, since the introduction of spills and reloads, not only place greater constraints on backend scheduling, but also ensure that more live ranges are split, and thus operands will spend less time on the operand stack overall. Time will tell whether this holds true or not.
Trait Implementations§
source§impl Default for RewriteSpills
impl Default for RewriteSpills
source§fn default() -> RewriteSpills
fn default() -> RewriteSpills
source§impl RewritePass for RewriteSpills
impl RewritePass for RewriteSpills
source§fn apply(
&mut self,
function: &mut Self::Entity,
analyses: &mut AnalysisManager,
session: &Session,
) -> RewriteResult
fn apply( &mut self, function: &mut Self::Entity, analyses: &mut AnalysisManager, session: &Session, ) -> RewriteResult
entitysource§fn should_apply(&self, _entity: &Self::Entity, _session: &Session) -> bool
fn should_apply(&self, _entity: &Self::Entity, _session: &Session) -> bool
entitysource§fn chain<R>(self, next: R) -> RewriteSet<Self::Entity>
fn chain<R>(self, next: R) -> RewriteSet<Self::Entity>
next as a pipeline of rewritesAuto Trait Implementations§
impl Freeze for RewriteSpills
impl RefUnwindSafe for RewriteSpills
impl Send for RewriteSpills
impl Sync for RewriteSpills
impl Unpin for RewriteSpills
impl UnwindSafe for RewriteSpills
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moresource§impl<D> OwoColorize for D
impl<D> OwoColorize for D
source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moresource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read more