Fix #666: Change the way we consider a block has been visited in relaxation;
This was previously using the following condition to decide that a block hadn't been visited yet: either dest_offset is non-0 or the block isn't the entry block. Unfortunately, this didn't work when the first block would be non-empty but wouldn't generate code at all. Since the original code would do at least one pass over the entire code, the first pass that determines initial EBB offsets is done separately, without considering branch relaxation. This ensures that all EBBs have been visited and have correct initial offsets, and doesn't require a special check to know whether an EBB has been visited or not.
This commit is contained in:
@@ -55,13 +55,26 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<Cod
|
||||
let mut offset = 0;
|
||||
let mut divert = RegDiversions::new();
|
||||
|
||||
// The relaxation algorithm iterates to convergence.
|
||||
// First, compute initial offsets for every EBB.
|
||||
{
|
||||
let mut cur = FuncCursor::new(func);
|
||||
while let Some(ebb) = cur.next_ebb() {
|
||||
divert.clear();
|
||||
cur.func.offsets[ebb] = offset;
|
||||
while let Some(inst) = cur.next_inst() {
|
||||
let enc = cur.func.encodings[inst];
|
||||
offset += encinfo.byte_size(enc, inst, &divert, &cur.func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then, run the relaxation algorithm until it converges.
|
||||
let mut go_again = true;
|
||||
while go_again {
|
||||
go_again = false;
|
||||
offset = 0;
|
||||
|
||||
// Visit all instructions in layout order
|
||||
// Visit all instructions in layout order.
|
||||
let mut cur = FuncCursor::new(func);
|
||||
while let Some(ebb) = cur.next_ebb() {
|
||||
divert.clear();
|
||||
@@ -81,15 +94,12 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> CodegenResult<Cod
|
||||
|
||||
let enc = cur.func.encodings[inst];
|
||||
|
||||
// See if this might be a branch that is out of range.
|
||||
// See if this is a branch has a range and a destination, and if the target is in
|
||||
// range.
|
||||
if let Some(range) = encinfo.branch_range(enc) {
|
||||
if let Some(dest) = cur.func.dfg[inst].branch_destination() {
|
||||
let dest_offset = cur.func.offsets[dest];
|
||||
// This could be an out-of-range branch.
|
||||
// Relax it unless the destination offset has not been computed yet.
|
||||
if !range.contains(offset, dest_offset)
|
||||
&& (dest_offset != 0 || Some(dest) == cur.func.layout.entry_block())
|
||||
{
|
||||
if !range.contains(offset, dest_offset) {
|
||||
offset +=
|
||||
relax_branch(&mut cur, &divert, offset, dest_offset, &encinfo, isa);
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user