Mass rename Ebb and relatives to Block (#1365)
* Manually rename BasicBlock to BlockPredecessor BasicBlock is a pair of (Ebb, Inst) that is used to represent the basic block subcomponent of an Ebb that is a predecessor to an Ebb. Eventually we will be able to remove this struct, but for now it makes sense to give it a non-conflicting name so that we can start to transition Ebb to represent a basic block. I have not updated any comments that refer to BasicBlock, as eventually we will remove BlockPredecessor and replace with Block, which is a basic block, so the comments will become correct. * Manually rename SSABuilder block types to avoid conflict SSABuilder has its own Block and BlockData types. These along with associated identifier will cause conflicts in a later commit, so they are renamed to be more verbose here. * Automatically rename 'Ebb' to 'Block' in *.rs * Automatically rename 'EBB' to 'block' in *.rs * Automatically rename 'ebb' to 'block' in *.rs * Automatically rename 'extended basic block' to 'basic block' in *.rs * Automatically rename 'an basic block' to 'a basic block' in *.rs * Manually update comment for `Block` `Block`'s wikipedia article required an update. * Automatically rename 'an `Block`' to 'a `Block`' in *.rs * Automatically rename 'extended_basic_block' to 'basic_block' in *.rs * Automatically rename 'ebb' to 'block' in *.clif * Manually rename clif constant that contains 'ebb' as substring to avoid conflict * Automatically rename filecheck uses of 'EBB' to 'BB' 'regex: EBB' -> 'regex: BB' '$EBB' -> '$BB' * Automatically rename 'EBB' 'Ebb' to 'block' in *.clif * Automatically rename 'an block' to 'a block' in *.clif * Fix broken testcase when function name length increases Test function names are limited to 16 characters. This causes the new longer name to be truncated and fail a filecheck test. An outdated comment was also fixed.
This commit is contained in:
@@ -22,7 +22,7 @@ use crate::cursor::{Cursor, FuncCursor};
|
||||
use crate::flowgraph::ControlFlowGraph;
|
||||
use crate::ir::instructions::CallInfo;
|
||||
use crate::ir::{
|
||||
AbiParam, ArgumentLoc, ArgumentPurpose, DataFlowGraph, Ebb, Function, Inst, InstBuilder,
|
||||
AbiParam, ArgumentLoc, ArgumentPurpose, Block, DataFlowGraph, Function, Inst, InstBuilder,
|
||||
MemFlags, SigRef, Signature, StackSlotData, StackSlotKind, Type, Value, ValueLoc,
|
||||
};
|
||||
use crate::isa::TargetIsa;
|
||||
@@ -84,12 +84,12 @@ fn legalize_signature(
|
||||
/// Legalize the entry block parameters after `func`'s signature has been legalized.
|
||||
///
|
||||
/// The legalized signature may contain more parameters than the original signature, and the
|
||||
/// parameter types have been changed. This function goes through the parameters of the entry EBB
|
||||
/// parameter types have been changed. This function goes through the parameters of the entry block
|
||||
/// and replaces them with parameters of the right type for the ABI.
|
||||
///
|
||||
/// The original entry EBB parameters are computed from the new ABI parameters by code inserted at
|
||||
/// The original entry block parameters are computed from the new ABI parameters by code inserted at
|
||||
/// the top of the entry block.
|
||||
fn legalize_entry_params(func: &mut Function, entry: Ebb) {
|
||||
fn legalize_entry_params(func: &mut Function, entry: Block) {
|
||||
let mut has_sret = false;
|
||||
let mut has_link = false;
|
||||
let mut has_vmctx = false;
|
||||
@@ -104,19 +104,19 @@ fn legalize_entry_params(func: &mut Function, entry: Ebb) {
|
||||
// Keep track of the argument types in the ABI-legalized signature.
|
||||
let mut abi_arg = 0;
|
||||
|
||||
// Process the EBB parameters one at a time, possibly replacing one argument with multiple new
|
||||
// ones. We do this by detaching the entry EBB parameters first.
|
||||
let ebb_params = pos.func.dfg.detach_ebb_params(entry);
|
||||
// Process the block parameters one at a time, possibly replacing one argument with multiple new
|
||||
// ones. We do this by detaching the entry block parameters first.
|
||||
let block_params = pos.func.dfg.detach_block_params(entry);
|
||||
let mut old_arg = 0;
|
||||
while let Some(arg) = ebb_params.get(old_arg, &pos.func.dfg.value_lists) {
|
||||
while let Some(arg) = block_params.get(old_arg, &pos.func.dfg.value_lists) {
|
||||
old_arg += 1;
|
||||
|
||||
let abi_type = pos.func.signature.params[abi_arg];
|
||||
let arg_type = pos.func.dfg.value_type(arg);
|
||||
if arg_type == abi_type.value_type {
|
||||
// No value translation is necessary, this argument matches the ABI type.
|
||||
// Just use the original EBB argument value. This is the most common case.
|
||||
pos.func.dfg.attach_ebb_param(entry, arg);
|
||||
// Just use the original block argument value. This is the most common case.
|
||||
pos.func.dfg.attach_block_param(entry, arg);
|
||||
match abi_type.purpose {
|
||||
ArgumentPurpose::Normal => {}
|
||||
ArgumentPurpose::FramePointer => {}
|
||||
@@ -151,13 +151,13 @@ fn legalize_entry_params(func: &mut Function, entry: Ebb) {
|
||||
);
|
||||
if ty == abi_type.value_type {
|
||||
abi_arg += 1;
|
||||
Ok(func.dfg.append_ebb_param(entry, ty))
|
||||
Ok(func.dfg.append_block_param(entry, ty))
|
||||
} else {
|
||||
Err(abi_type)
|
||||
}
|
||||
};
|
||||
let converted = convert_from_abi(&mut pos, arg_type, Some(arg), &mut get_arg);
|
||||
// The old `arg` is no longer an attached EBB argument, but there are probably still
|
||||
// The old `arg` is no longer an attached block argument, but there are probably still
|
||||
// uses of the value.
|
||||
debug_assert_eq!(pos.func.dfg.resolve_aliases(arg), converted);
|
||||
}
|
||||
@@ -201,7 +201,7 @@ fn legalize_entry_params(func: &mut Function, entry: Ebb) {
|
||||
|
||||
// Just create entry block values to match here. We will use them in `handle_return_abi()`
|
||||
// below.
|
||||
pos.func.dfg.append_ebb_param(entry, arg.value_type);
|
||||
pos.func.dfg.append_block_param(entry, arg.value_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,7 +851,7 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
|
||||
let val = pos
|
||||
.func
|
||||
.dfg
|
||||
.ebb_params(pos.func.layout.entry_block().unwrap())[idx];
|
||||
.block_params(pos.func.layout.entry_block().unwrap())[idx];
|
||||
debug_assert_eq!(pos.func.dfg.value_type(val), arg.value_type);
|
||||
vlist.push(val, &mut pos.func.dfg.value_lists);
|
||||
|
||||
@@ -958,8 +958,13 @@ fn round_up_to_multiple_of_pow2(n: u32, to: u32) -> u32 {
|
||||
///
|
||||
/// Values that are passed into the function on the stack must be assigned to an `IncomingArg`
|
||||
/// stack slot already during legalization.
|
||||
fn spill_entry_params(func: &mut Function, entry: Ebb) {
|
||||
for (abi, &arg) in func.signature.params.iter().zip(func.dfg.ebb_params(entry)) {
|
||||
fn spill_entry_params(func: &mut Function, entry: Block) {
|
||||
for (abi, &arg) in func
|
||||
.signature
|
||||
.params
|
||||
.iter()
|
||||
.zip(func.dfg.block_params(entry))
|
||||
{
|
||||
if let ArgumentLoc::Stack(offset) = abi.location {
|
||||
let ss = func.stack_slots.make_incoming_arg(abi.value_type, offset);
|
||||
func.locations[arg] = ValueLoc::Stack(ss);
|
||||
|
||||
@@ -120,12 +120,12 @@ fn static_addr(
|
||||
pos.ins().trap(ir::TrapCode::HeapOutOfBounds);
|
||||
pos.func.dfg.replace(inst).iconst(addr_ty, 0);
|
||||
|
||||
// Split Ebb, as the trap is a terminator instruction.
|
||||
let curr_ebb = pos.current_ebb().expect("Cursor is not in an ebb");
|
||||
let new_ebb = pos.func.dfg.make_ebb();
|
||||
pos.insert_ebb(new_ebb);
|
||||
cfg.recompute_ebb(pos.func, curr_ebb);
|
||||
cfg.recompute_ebb(pos.func, new_ebb);
|
||||
// Split Block, as the trap is a terminator instruction.
|
||||
let curr_block = pos.current_block().expect("Cursor is not in an block");
|
||||
let new_block = pos.func.dfg.make_block();
|
||||
pos.insert_block(new_block);
|
||||
cfg.recompute_block(pos.func, curr_block);
|
||||
cfg.recompute_block(pos.func, new_block);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ fn legalize_inst(
|
||||
return LegalizeInstResult::SplitLegalizePending;
|
||||
}
|
||||
}
|
||||
ir::ValueDef::Param(_ebb, _num) => {}
|
||||
ir::ValueDef::Param(_block, _num) => {}
|
||||
}
|
||||
|
||||
let res = pos.func.dfg.inst_results(inst).to_vec();
|
||||
@@ -148,10 +148,10 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
||||
let mut pos = FuncCursor::new(func);
|
||||
let func_begin = pos.position();
|
||||
|
||||
// Split ebb params before trying to legalize instructions, so that the newly introduced
|
||||
// Split block params before trying to legalize instructions, so that the newly introduced
|
||||
// isplit instructions get legalized.
|
||||
while let Some(ebb) = pos.next_ebb() {
|
||||
split::split_ebb_params(pos.func, cfg, ebb);
|
||||
while let Some(block) = pos.next_block() {
|
||||
split::split_block_params(pos.func, cfg, block);
|
||||
}
|
||||
|
||||
pos.set_position(func_begin);
|
||||
@@ -159,9 +159,9 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
||||
// This must be a set to prevent trying to legalize `isplit` and `vsplit` twice in certain cases.
|
||||
let mut pending_splits = BTreeSet::new();
|
||||
|
||||
// Process EBBs in layout order. Some legalization actions may split the current EBB or append
|
||||
// new ones to the end. We need to make sure we visit those new EBBs too.
|
||||
while let Some(_ebb) = pos.next_ebb() {
|
||||
// Process blocks in layout order. Some legalization actions may split the current block or append
|
||||
// new ones to the end. We need to make sure we visit those new blocks too.
|
||||
while let Some(_block) = pos.next_block() {
|
||||
// Keep track of the cursor position before the instruction being processed, so we can
|
||||
// double back when replacing instructions.
|
||||
let mut prev_pos = pos.position();
|
||||
@@ -225,48 +225,48 @@ fn expand_cond_trap(
|
||||
_ => panic!("Expected cond trap: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
// Split the EBB after `inst`:
|
||||
// Split the block after `inst`:
|
||||
//
|
||||
// trapnz arg
|
||||
// ..
|
||||
//
|
||||
// Becomes:
|
||||
//
|
||||
// brz arg, new_ebb_resume
|
||||
// jump new_ebb_trap
|
||||
// brz arg, new_block_resume
|
||||
// jump new_block_trap
|
||||
//
|
||||
// new_ebb_trap:
|
||||
// new_block_trap:
|
||||
// trap
|
||||
//
|
||||
// new_ebb_resume:
|
||||
// new_block_resume:
|
||||
// ..
|
||||
let old_ebb = func.layout.pp_ebb(inst);
|
||||
let new_ebb_trap = func.dfg.make_ebb();
|
||||
let new_ebb_resume = func.dfg.make_ebb();
|
||||
let old_block = func.layout.pp_block(inst);
|
||||
let new_block_trap = func.dfg.make_block();
|
||||
let new_block_resume = func.dfg.make_block();
|
||||
|
||||
// Replace trap instruction by the inverted condition.
|
||||
if trapz {
|
||||
func.dfg.replace(inst).brnz(arg, new_ebb_resume, &[]);
|
||||
func.dfg.replace(inst).brnz(arg, new_block_resume, &[]);
|
||||
} else {
|
||||
func.dfg.replace(inst).brz(arg, new_ebb_resume, &[]);
|
||||
func.dfg.replace(inst).brz(arg, new_block_resume, &[]);
|
||||
}
|
||||
|
||||
// Add jump instruction after the inverted branch.
|
||||
let mut pos = FuncCursor::new(func).after_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
pos.ins().jump(new_ebb_trap, &[]);
|
||||
pos.ins().jump(new_block_trap, &[]);
|
||||
|
||||
// Insert the new label and the unconditional trap terminator.
|
||||
pos.insert_ebb(new_ebb_trap);
|
||||
pos.insert_block(new_block_trap);
|
||||
pos.ins().trap(code);
|
||||
|
||||
// Insert the new label and resume the execution when the trap fails.
|
||||
pos.insert_ebb(new_ebb_resume);
|
||||
pos.insert_block(new_block_resume);
|
||||
|
||||
// Finally update the CFG.
|
||||
cfg.recompute_ebb(pos.func, old_ebb);
|
||||
cfg.recompute_ebb(pos.func, new_ebb_resume);
|
||||
cfg.recompute_ebb(pos.func, new_ebb_trap);
|
||||
cfg.recompute_block(pos.func, old_block);
|
||||
cfg.recompute_block(pos.func, new_block_resume);
|
||||
cfg.recompute_block(pos.func, new_block_trap);
|
||||
}
|
||||
|
||||
/// Jump tables.
|
||||
@@ -292,7 +292,7 @@ fn expand_br_table_jt(
|
||||
) {
|
||||
use crate::ir::condcodes::IntCC;
|
||||
|
||||
let (arg, default_ebb, table) = match func.dfg[inst] {
|
||||
let (arg, default_block, table) = match func.dfg[inst] {
|
||||
ir::InstructionData::BranchTable {
|
||||
opcode: ir::Opcode::BrTable,
|
||||
arg,
|
||||
@@ -304,22 +304,22 @@ fn expand_br_table_jt(
|
||||
|
||||
// Rewrite:
|
||||
//
|
||||
// br_table $idx, default_ebb, $jt
|
||||
// br_table $idx, default_block, $jt
|
||||
//
|
||||
// To:
|
||||
//
|
||||
// $oob = ifcmp_imm $idx, len($jt)
|
||||
// brif uge $oob, default_ebb
|
||||
// jump fallthrough_ebb
|
||||
// brif uge $oob, default_block
|
||||
// jump fallthrough_block
|
||||
//
|
||||
// fallthrough_ebb:
|
||||
// fallthrough_block:
|
||||
// $base = jump_table_base.i64 $jt
|
||||
// $rel_addr = jump_table_entry.i64 $idx, $base, 4, $jt
|
||||
// $addr = iadd $base, $rel_addr
|
||||
// indirect_jump_table_br $addr, $jt
|
||||
|
||||
let ebb = func.layout.pp_ebb(inst);
|
||||
let jump_table_ebb = func.dfg.make_ebb();
|
||||
let block = func.layout.pp_block(inst);
|
||||
let jump_table_block = func.dfg.make_block();
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
@@ -330,9 +330,9 @@ fn expand_br_table_jt(
|
||||
.ins()
|
||||
.icmp_imm(IntCC::UnsignedGreaterThanOrEqual, arg, table_size);
|
||||
|
||||
pos.ins().brnz(oob, default_ebb, &[]);
|
||||
pos.ins().jump(jump_table_ebb, &[]);
|
||||
pos.insert_ebb(jump_table_ebb);
|
||||
pos.ins().brnz(oob, default_block, &[]);
|
||||
pos.ins().jump(jump_table_block, &[]);
|
||||
pos.insert_block(jump_table_block);
|
||||
|
||||
let addr_ty = isa.pointer_type();
|
||||
|
||||
@@ -351,8 +351,8 @@ fn expand_br_table_jt(
|
||||
pos.ins().indirect_jump_table_br(addr, table);
|
||||
|
||||
pos.remove_inst();
|
||||
cfg.recompute_ebb(pos.func, ebb);
|
||||
cfg.recompute_ebb(pos.func, jump_table_ebb);
|
||||
cfg.recompute_block(pos.func, block);
|
||||
cfg.recompute_block(pos.func, jump_table_block);
|
||||
}
|
||||
|
||||
/// Expand br_table to series of conditionals.
|
||||
@@ -364,7 +364,7 @@ fn expand_br_table_conds(
|
||||
) {
|
||||
use crate::ir::condcodes::IntCC;
|
||||
|
||||
let (arg, default_ebb, table) = match func.dfg[inst] {
|
||||
let (arg, default_block, table) = match func.dfg[inst] {
|
||||
ir::InstructionData::BranchTable {
|
||||
opcode: ir::Opcode::BrTable,
|
||||
arg,
|
||||
@@ -374,15 +374,15 @@ fn expand_br_table_conds(
|
||||
_ => panic!("Expected br_table: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
let ebb = func.layout.pp_ebb(inst);
|
||||
let block = func.layout.pp_block(inst);
|
||||
|
||||
// This is a poor man's jump table using just a sequence of conditional branches.
|
||||
let table_size = func.jump_tables[table].len();
|
||||
let mut cond_failed_ebb = vec![];
|
||||
let mut cond_failed_block = vec![];
|
||||
if table_size >= 1 {
|
||||
cond_failed_ebb = alloc::vec::Vec::with_capacity(table_size - 1);
|
||||
cond_failed_block = alloc::vec::Vec::with_capacity(table_size - 1);
|
||||
for _ in 0..table_size - 1 {
|
||||
cond_failed_ebb.push(func.dfg.make_ebb());
|
||||
cond_failed_block.push(func.dfg.make_block());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,19 +397,19 @@ fn expand_br_table_conds(
|
||||
pos.ins().brnz(t, dest, &[]);
|
||||
// Jump to the next case.
|
||||
if i < table_size - 1 {
|
||||
let ebb = cond_failed_ebb[i];
|
||||
pos.ins().jump(ebb, &[]);
|
||||
pos.insert_ebb(ebb);
|
||||
let block = cond_failed_block[i];
|
||||
pos.ins().jump(block, &[]);
|
||||
pos.insert_block(block);
|
||||
}
|
||||
}
|
||||
|
||||
// `br_table` jumps to the default destination if nothing matches
|
||||
pos.ins().jump(default_ebb, &[]);
|
||||
pos.ins().jump(default_block, &[]);
|
||||
|
||||
pos.remove_inst();
|
||||
cfg.recompute_ebb(pos.func, ebb);
|
||||
for failed_ebb in cond_failed_ebb.into_iter() {
|
||||
cfg.recompute_ebb(pos.func, failed_ebb);
|
||||
cfg.recompute_block(pos.func, block);
|
||||
for failed_block in cond_failed_block.into_iter() {
|
||||
cfg.recompute_block(pos.func, failed_block);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,23 +433,23 @@ fn expand_select(
|
||||
|
||||
// Replace `result = select ctrl, tval, fval` with:
|
||||
//
|
||||
// brnz ctrl, new_ebb(tval)
|
||||
// jump new_ebb(fval)
|
||||
// new_ebb(result):
|
||||
let old_ebb = func.layout.pp_ebb(inst);
|
||||
// brnz ctrl, new_block(tval)
|
||||
// jump new_block(fval)
|
||||
// new_block(result):
|
||||
let old_block = func.layout.pp_block(inst);
|
||||
let result = func.dfg.first_result(inst);
|
||||
func.dfg.clear_results(inst);
|
||||
let new_ebb = func.dfg.make_ebb();
|
||||
func.dfg.attach_ebb_param(new_ebb, result);
|
||||
let new_block = func.dfg.make_block();
|
||||
func.dfg.attach_block_param(new_block, result);
|
||||
|
||||
func.dfg.replace(inst).brnz(ctrl, new_ebb, &[tval]);
|
||||
func.dfg.replace(inst).brnz(ctrl, new_block, &[tval]);
|
||||
let mut pos = FuncCursor::new(func).after_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
pos.ins().jump(new_ebb, &[fval]);
|
||||
pos.insert_ebb(new_ebb);
|
||||
pos.ins().jump(new_block, &[fval]);
|
||||
pos.insert_block(new_block);
|
||||
|
||||
cfg.recompute_ebb(pos.func, new_ebb);
|
||||
cfg.recompute_ebb(pos.func, old_ebb);
|
||||
cfg.recompute_block(pos.func, new_block);
|
||||
cfg.recompute_block(pos.func, old_block);
|
||||
}
|
||||
|
||||
fn expand_br_icmp(
|
||||
@@ -458,7 +458,7 @@ fn expand_br_icmp(
|
||||
cfg: &mut ControlFlowGraph,
|
||||
_isa: &dyn TargetIsa,
|
||||
) {
|
||||
let (cond, a, b, destination, ebb_args) = match func.dfg[inst] {
|
||||
let (cond, a, b, destination, block_args) = match func.dfg[inst] {
|
||||
ir::InstructionData::BranchIcmp {
|
||||
cond,
|
||||
destination,
|
||||
@@ -474,16 +474,16 @@ fn expand_br_icmp(
|
||||
_ => panic!("Expected br_icmp {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
let old_ebb = func.layout.pp_ebb(inst);
|
||||
let old_block = func.layout.pp_block(inst);
|
||||
func.dfg.clear_results(inst);
|
||||
|
||||
let icmp_res = func.dfg.replace(inst).icmp(cond, a, b);
|
||||
let mut pos = FuncCursor::new(func).after_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
pos.ins().brnz(icmp_res, destination, &ebb_args);
|
||||
pos.ins().brnz(icmp_res, destination, &block_args);
|
||||
|
||||
cfg.recompute_ebb(pos.func, destination);
|
||||
cfg.recompute_ebb(pos.func, old_ebb);
|
||||
cfg.recompute_block(pos.func, destination);
|
||||
cfg.recompute_block(pos.func, old_block);
|
||||
}
|
||||
|
||||
/// Expand illegal `f32const` and `f64const` instructions.
|
||||
|
||||
@@ -54,19 +54,19 @@
|
||||
//! This means that the `iconcat` instructions defining `v1` and `v4` end up with no uses, so they
|
||||
//! can be trivially deleted by a dead code elimination pass.
|
||||
//!
|
||||
//! # EBB arguments
|
||||
//! # block arguments
|
||||
//!
|
||||
//! If all instructions that produce an `i64` value are legalized as above, we will eventually end
|
||||
//! up with no `i64` values anywhere, except for EBB arguments. We can work around this by
|
||||
//! iteratively splitting EBB arguments too. That should leave us with no illegal value types
|
||||
//! up with no `i64` values anywhere, except for block arguments. We can work around this by
|
||||
//! iteratively splitting block arguments too. That should leave us with no illegal value types
|
||||
//! anywhere.
|
||||
//!
|
||||
//! It is possible to have circular dependencies of EBB arguments that are never used by any real
|
||||
//! It is possible to have circular dependencies of block arguments that are never used by any real
|
||||
//! instructions. These loops will remain in the program.
|
||||
|
||||
use crate::cursor::{Cursor, CursorPosition, FuncCursor};
|
||||
use crate::flowgraph::{BasicBlock, ControlFlowGraph};
|
||||
use crate::ir::{self, Ebb, Inst, InstBuilder, InstructionData, Opcode, Type, Value, ValueDef};
|
||||
use crate::flowgraph::{BlockPredecessor, ControlFlowGraph};
|
||||
use crate::ir::{self, Block, Inst, InstBuilder, InstructionData, Opcode, Type, Value, ValueDef};
|
||||
use alloc::vec::Vec;
|
||||
use core::iter;
|
||||
use smallvec::SmallVec;
|
||||
@@ -95,7 +95,7 @@ pub fn vsplit(
|
||||
split_any(func, cfg, pos, srcloc, value, Opcode::Vconcat)
|
||||
}
|
||||
|
||||
/// After splitting an EBB argument, we need to go back and fix up all of the predecessor
|
||||
/// After splitting an block argument, we need to go back and fix up all of the predecessor
|
||||
/// instructions. This is potentially a recursive operation, but we don't implement it recursively
|
||||
/// since that could use up too muck stack.
|
||||
///
|
||||
@@ -104,11 +104,11 @@ struct Repair {
|
||||
concat: Opcode,
|
||||
// The argument type after splitting.
|
||||
split_type: Type,
|
||||
// The destination EBB whose arguments have been split.
|
||||
ebb: Ebb,
|
||||
// Number of the original EBB argument which has been replaced by the low part.
|
||||
// The destination block whose arguments have been split.
|
||||
block: Block,
|
||||
// Number of the original block argument which has been replaced by the low part.
|
||||
num: usize,
|
||||
// Number of the new EBB argument which represents the high part after the split.
|
||||
// Number of the new block argument which represents the high part after the split.
|
||||
hi_num: usize,
|
||||
}
|
||||
|
||||
@@ -130,9 +130,9 @@ fn split_any(
|
||||
result
|
||||
}
|
||||
|
||||
pub fn split_ebb_params(func: &mut ir::Function, cfg: &ControlFlowGraph, ebb: Ebb) {
|
||||
let pos = &mut FuncCursor::new(func).at_top(ebb);
|
||||
let ebb_params = pos.func.dfg.ebb_params(ebb);
|
||||
pub fn split_block_params(func: &mut ir::Function, cfg: &ControlFlowGraph, block: Block) {
|
||||
let pos = &mut FuncCursor::new(func).at_top(block);
|
||||
let block_params = pos.func.dfg.block_params(block);
|
||||
|
||||
// Add further splittable types here.
|
||||
fn type_requires_splitting(ty: Type) -> bool {
|
||||
@@ -140,31 +140,31 @@ pub fn split_ebb_params(func: &mut ir::Function, cfg: &ControlFlowGraph, ebb: Eb
|
||||
}
|
||||
|
||||
// A shortcut. If none of the param types require splitting, exit now. This helps because
|
||||
// the loop below necessarily has to copy the ebb params into a new vector, so it's better to
|
||||
// the loop below necessarily has to copy the block params into a new vector, so it's better to
|
||||
// avoid doing so when possible.
|
||||
if !ebb_params
|
||||
if !block_params
|
||||
.iter()
|
||||
.any(|ebb_param| type_requires_splitting(pos.func.dfg.value_type(*ebb_param)))
|
||||
.any(|block_param| type_requires_splitting(pos.func.dfg.value_type(*block_param)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let mut repairs = Vec::new();
|
||||
for (num, ebb_param) in ebb_params.to_vec().into_iter().enumerate() {
|
||||
if !type_requires_splitting(pos.func.dfg.value_type(ebb_param)) {
|
||||
for (num, block_param) in block_params.to_vec().into_iter().enumerate() {
|
||||
if !type_requires_splitting(pos.func.dfg.value_type(block_param)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
split_ebb_param(pos, ebb, num, ebb_param, Opcode::Iconcat, &mut repairs);
|
||||
split_block_param(pos, block, num, block_param, Opcode::Iconcat, &mut repairs);
|
||||
}
|
||||
|
||||
perform_repairs(pos, cfg, repairs);
|
||||
}
|
||||
|
||||
fn perform_repairs(pos: &mut FuncCursor, cfg: &ControlFlowGraph, mut repairs: Vec<Repair>) {
|
||||
// We have split the value requested, and now we may need to fix some EBB predecessors.
|
||||
// We have split the value requested, and now we may need to fix some block predecessors.
|
||||
while let Some(repair) = repairs.pop() {
|
||||
for BasicBlock { inst, .. } in cfg.pred_iter(repair.ebb) {
|
||||
for BlockPredecessor { inst, .. } in cfg.pred_iter(repair.block) {
|
||||
let branch_opc = pos.func.dfg[inst].opcode();
|
||||
debug_assert!(
|
||||
branch_opc.is_branch(),
|
||||
@@ -176,7 +176,7 @@ fn perform_repairs(pos: &mut FuncCursor, cfg: &ControlFlowGraph, mut repairs: Ve
|
||||
.take_value_list()
|
||||
.expect("Branches must have value lists.");
|
||||
let num_args = args.len(&pos.func.dfg.value_lists);
|
||||
// Get the old value passed to the EBB argument we're repairing.
|
||||
// Get the old value passed to the block argument we're repairing.
|
||||
let old_arg = args
|
||||
.get(num_fixed_args + repair.num, &pos.func.dfg.value_lists)
|
||||
.expect("Too few branch arguments");
|
||||
@@ -190,13 +190,13 @@ fn perform_repairs(pos: &mut FuncCursor, cfg: &ControlFlowGraph, mut repairs: Ve
|
||||
// Split the old argument, possibly causing more repairs to be scheduled.
|
||||
pos.goto_inst(inst);
|
||||
|
||||
let inst_ebb = pos.func.layout.inst_ebb(inst).expect("inst in ebb");
|
||||
let inst_block = pos.func.layout.inst_block(inst).expect("inst in block");
|
||||
|
||||
// Insert split values prior to the terminal branch group.
|
||||
let canonical = pos
|
||||
.func
|
||||
.layout
|
||||
.canonical_branch_inst(&pos.func.dfg, inst_ebb);
|
||||
.canonical_branch_inst(&pos.func.dfg, inst_block);
|
||||
if let Some(first_branch) = canonical {
|
||||
pos.goto_inst(first_branch);
|
||||
}
|
||||
@@ -209,7 +209,7 @@ fn perform_repairs(pos: &mut FuncCursor, cfg: &ControlFlowGraph, mut repairs: Ve
|
||||
.unwrap() = lo;
|
||||
|
||||
// The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
|
||||
// same EBB, there could be multiple arguments missing.
|
||||
// same block, there could be multiple arguments missing.
|
||||
if num_args > num_fixed_args + repair.hi_num {
|
||||
*args
|
||||
.get_mut(
|
||||
@@ -259,11 +259,11 @@ fn split_value(
|
||||
}
|
||||
}
|
||||
}
|
||||
ValueDef::Param(ebb, num) => {
|
||||
// This is an EBB parameter.
|
||||
ValueDef::Param(block, num) => {
|
||||
// This is an block parameter.
|
||||
// We can split the parameter value unless this is the entry block.
|
||||
if pos.func.layout.entry_block() != Some(ebb) {
|
||||
reuse = Some(split_ebb_param(pos, ebb, num, value, concat, repairs));
|
||||
if pos.func.layout.entry_block() != Some(block) {
|
||||
reuse = Some(split_block_param(pos, block, num, value, concat, repairs));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,7 +273,7 @@ fn split_value(
|
||||
pair
|
||||
} else {
|
||||
// No, we'll just have to insert the requested split instruction at `pos`. Note that `pos`
|
||||
// has not been moved by the EBB argument code above when `reuse` is `None`.
|
||||
// has not been moved by the block argument code above when `reuse` is `None`.
|
||||
match concat {
|
||||
Opcode::Iconcat => pos.ins().isplit(value),
|
||||
Opcode::Vconcat => pos.ins().vsplit(value),
|
||||
@@ -282,9 +282,9 @@ fn split_value(
|
||||
}
|
||||
}
|
||||
|
||||
fn split_ebb_param(
|
||||
fn split_block_param(
|
||||
pos: &mut FuncCursor,
|
||||
ebb: Ebb,
|
||||
block: Block,
|
||||
param_num: usize,
|
||||
value: Value,
|
||||
concat: Opcode,
|
||||
@@ -300,14 +300,14 @@ fn split_ebb_param(
|
||||
};
|
||||
|
||||
// Since the `repairs` stack potentially contains other parameter numbers for
|
||||
// `ebb`, avoid shifting and renumbering EBB parameters. It could invalidate other
|
||||
// `block`, avoid shifting and renumbering block parameters. It could invalidate other
|
||||
// `repairs` entries.
|
||||
//
|
||||
// Replace the original `value` with the low part, and append the high part at the
|
||||
// end of the argument list.
|
||||
let lo = pos.func.dfg.replace_ebb_param(value, split_type);
|
||||
let hi_num = pos.func.dfg.num_ebb_params(ebb);
|
||||
let hi = pos.func.dfg.append_ebb_param(ebb, split_type);
|
||||
let lo = pos.func.dfg.replace_block_param(value, split_type);
|
||||
let hi_num = pos.func.dfg.num_block_params(block);
|
||||
let hi = pos.func.dfg.append_block_param(block, split_type);
|
||||
|
||||
// Now the original value is dangling. Insert a concatenation instruction that can
|
||||
// compute it from the two new parameters. This also serves as a record of what we
|
||||
@@ -315,14 +315,14 @@ fn split_ebb_param(
|
||||
//
|
||||
// Note that it is safe to move `pos` here since `reuse` was set above, so we don't
|
||||
// need to insert a split instruction before returning.
|
||||
pos.goto_first_inst(ebb);
|
||||
pos.goto_first_inst(block);
|
||||
pos.ins()
|
||||
.with_result(value)
|
||||
.Binary(concat, split_type, lo, hi);
|
||||
|
||||
// Finally, splitting the EBB parameter is not enough. We also have to repair all
|
||||
// Finally, splitting the block parameter is not enough. We also have to repair all
|
||||
// of the predecessor instructions that branch here.
|
||||
add_repair(concat, split_type, ebb, param_num, hi_num, repairs);
|
||||
add_repair(concat, split_type, block, param_num, hi_num, repairs);
|
||||
|
||||
(lo, hi)
|
||||
}
|
||||
@@ -331,7 +331,7 @@ fn split_ebb_param(
|
||||
fn add_repair(
|
||||
concat: Opcode,
|
||||
split_type: Type,
|
||||
ebb: Ebb,
|
||||
block: Block,
|
||||
num: usize,
|
||||
hi_num: usize,
|
||||
repairs: &mut Vec<Repair>,
|
||||
@@ -339,7 +339,7 @@ fn add_repair(
|
||||
repairs.push(Repair {
|
||||
concat,
|
||||
split_type,
|
||||
ebb,
|
||||
block,
|
||||
num,
|
||||
hi_num,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user