Add a fallthrough instruction.

Change jumps to fallthroughs in the branch relaxation pass before
computing the EBB offsets.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-06 14:22:32 -07:00
parent 5025bb67f4
commit fa4f151b9b
4 changed files with 51 additions and 2 deletions

View File

@@ -29,8 +29,9 @@
use binemit::CodeOffset;
use entity_map::EntityMap;
use ir::{Function, DataFlowGraph, Cursor, Inst};
use ir::{Function, DataFlowGraph, Cursor, Inst, InstructionData, Opcode};
use isa::{TargetIsa, EncInfo, Encoding};
use iterators::IteratorExtras;
/// Relax branches and compute the final layout of EBB headers in `func`.
///
@@ -42,6 +43,9 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) {
func.offsets.clear();
func.offsets.resize(func.dfg.num_ebbs());
// Start by inserting fall through instructions.
fallthroughs(func);
// The relaxation algorithm iterates to convergence.
let mut go_again = true;
while go_again {
@@ -89,6 +93,37 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) {
}
}
/// Convert `jump` instructions to `fallthrough` instructions where possible and verify that any
/// existing `fallthrough` instructions are correct.
fn fallthroughs(func: &mut Function) {
for (ebb, succ) in func.layout.ebbs().adjacent_pairs() {
let term = func.layout
.last_inst(ebb)
.expect("EBB has no terminator.");
if let InstructionData::Jump {
ref mut opcode,
destination,
..
} = func.dfg[term] {
match *opcode {
Opcode::Fallthrough => {
// Somebody used a fall-through instruction before the branch relaxation pass.
// Make sure it is correct, i.e. the destination is the layout successor.
assert_eq!(destination, succ, "Illegal fall-through in {}", ebb)
}
Opcode::Jump => {
// If this is a jump to the successor EBB, change it to a fall-through.
if destination == succ {
*opcode = Opcode::Fallthrough;
func.encodings[term] = Default::default();
}
}
_ => {}
}
}
}
}
/// Relax the branch instruction at `pos` so it can cover the range `offset - dest_offset`.
///
/// Return the size of the replacement instructions up to and including the location where `pos` is