Move default blocks into jump tables (#5756)

Move the default block off of the br_table instrution, and into the JumpTable that it references.
This commit is contained in:
Trevor Elliott
2023-02-10 08:53:30 -08:00
committed by GitHub
parent 49613be393
commit d99783fc91
21 changed files with 118 additions and 175 deletions

View File

@@ -129,9 +129,7 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
}
}
ir::InstructionData::BranchTable {
table, destination, ..
} => {
ir::InstructionData::BranchTable { table, .. } => {
// Unlike all other jumps/branches, jump tables are
// capable of having the same successor appear
// multiple times, so we must deduplicate.
@@ -144,9 +142,12 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
.jump_tables
.get(*table)
.expect("you are referencing an undeclared jump table")
.iter()
.filter(|&dest_block| unique.insert(*dest_block))
.all_branches()
{
if !unique.insert(*dest_block) {
continue;
}
// Call `declare_block_predecessor` instead of `declare_successor` for
// avoiding the borrow checker.
self.builder
@@ -154,7 +155,6 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
.ssa
.declare_block_predecessor(*dest_block, inst);
}
self.builder.declare_successor(*destination, inst);
}
inst => debug_assert!(!inst.opcode().is_branch()),

View File

@@ -591,27 +591,18 @@ impl SSABuilder {
}
None
}
InstructionData::BranchTable {
table: jt,
destination,
..
} => {
InstructionData::BranchTable { table: jt, .. } => {
// In the case of a jump table, the situation is tricky because br_table doesn't
// support arguments. We have to split the critical edge.
let middle_block = dfg.blocks.add();
func.stencil.layout.append_block(middle_block);
let table = &mut dfg.jump_tables[*jt];
for block in table.iter_mut() {
for block in dfg.jump_tables[*jt].all_branches_mut() {
if *block == dest_block {
*block = middle_block;
}
}
if *destination == dest_block {
*destination = middle_block;
}
let mut cur = FuncCursor::new(func).at_bottom(middle_block);
let middle_jump_inst = cur.ins().jump(dest_block, &[val]);
Some((middle_block, middle_jump_inst))
@@ -1001,9 +992,6 @@ mod tests {
let block0 = func.dfg.make_block();
let block1 = func.dfg.make_block();
let block2 = func.dfg.make_block();
let mut jump_table = JumpTableData::new();
jump_table.push_entry(block2);
jump_table.push_entry(block1);
{
let mut cur = FuncCursor::new(&mut func);
cur.insert_block(block0);
@@ -1022,9 +1010,10 @@ mod tests {
ssa.def_var(x_var, x1, block0);
ssa.use_var(&mut func, x_var, I32, block0).0;
let br_table = {
let jump_table = JumpTableData::new(block2, vec![block2, block1]);
let jt = func.create_jump_table(jump_table);
let mut cur = FuncCursor::new(&mut func).at_bottom(block0);
cur.ins().br_table(x1, block2, jt)
cur.ins().br_table(x1, jt)
};
// block1

View File

@@ -220,7 +220,7 @@ impl Switch {
"Jump tables bigger than 2^32-1 are not yet supported"
);
let jt_data = JumpTableData::with_blocks(Vec::from(blocks));
let jt_data = JumpTableData::new(otherwise, Vec::from(blocks));
let jump_table = bx.create_jump_table(jt_data);
let discr = if first_index == 0 {
@@ -256,7 +256,7 @@ impl Switch {
_ => discr,
};
bx.ins().br_table(discr, otherwise, jump_table);
bx.ins().br_table(discr, jump_table);
}
/// Build the switch