Add an instruction shrinking pass.
When an instruction has multiple valid encodings, such as with and without a REX prefix on x86-64, Cretonne typically picks the encoding which gives the register allocator the most flexibility, which is typically the longest encoding. This patch adds a pass that runs after register allocation that picks the smallest encoding, working within the constraints of the register allocator's choices. The result is smaller and easier to read encodings. In the future, we may want to merge this pass into the relaxation pass, or possibly fold it into the final encoding step, however for now, a discrete pass will suffice.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
//! contexts concurrently. Typically, you would have one context per compilation thread and only a
|
||||
//! single ISA instance.
|
||||
|
||||
use binemit::{relax_branches, CodeOffset, MemoryCodeSink, RelocSink, TrapSink};
|
||||
use binemit::{relax_branches, shrink_instructions, CodeOffset, MemoryCodeSink, RelocSink, TrapSink};
|
||||
use dce::do_dce;
|
||||
use dominator_tree::DominatorTree;
|
||||
use flowgraph::ControlFlowGraph;
|
||||
@@ -140,6 +140,9 @@ impl Context {
|
||||
}
|
||||
self.regalloc(isa)?;
|
||||
self.prologue_epilogue(isa)?;
|
||||
if isa.flags().opt_level() == OptLevel::Best {
|
||||
self.shrink_instructions(isa)?;
|
||||
}
|
||||
self.relax_branches(isa)
|
||||
}
|
||||
|
||||
@@ -294,6 +297,14 @@ impl Context {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the instruction shrinking pass.
|
||||
pub fn shrink_instructions(&mut self, isa: &TargetIsa) -> CtonResult {
|
||||
shrink_instructions(&mut self.func, isa);
|
||||
self.verify_if(isa)?;
|
||||
self.verify_locations_if(isa)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the branch relaxation pass and return the final code size.
|
||||
pub fn relax_branches(&mut self, isa: &TargetIsa) -> Result<CodeOffset, CtonError> {
|
||||
let code_size = relax_branches(&mut self.func, isa)?;
|
||||
|
||||
Reference in New Issue
Block a user