Fix bug when i128 ebb param is unused
This commit is contained in:
@@ -174,6 +174,10 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while let Some(ebb) = pos.next_ebb() {
|
||||||
|
split::split_ebb_params(pos.func, cfg, ebb);
|
||||||
|
}
|
||||||
|
|
||||||
// Try legalizing `isplit` and `vsplit` instructions, which could not previously be legalized.
|
// Try legalizing `isplit` and `vsplit` instructions, which could not previously be legalized.
|
||||||
for inst in pending_splits {
|
for inst in pending_splits {
|
||||||
//pos.goto_inst(inst);
|
//pos.goto_inst(inst);
|
||||||
|
|||||||
@@ -124,6 +124,36 @@ fn split_any(
|
|||||||
let pos = &mut FuncCursor::new(func).at_position(pos).with_srcloc(srcloc);
|
let pos = &mut FuncCursor::new(func).at_position(pos).with_srcloc(srcloc);
|
||||||
let result = split_value(pos, value, concat, &mut repairs);
|
let result = split_value(pos, value, concat, &mut repairs);
|
||||||
|
|
||||||
|
perform_repairs(pos, cfg, repairs);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn split_ebb_params(
|
||||||
|
func: &mut ir::Function,
|
||||||
|
cfg: &ControlFlowGraph,
|
||||||
|
ebb: Ebb,
|
||||||
|
) {
|
||||||
|
let mut repairs = Vec::new();
|
||||||
|
let pos = &mut FuncCursor::new(func).at_top(ebb);
|
||||||
|
|
||||||
|
for (num, ebb_param) in pos.func.dfg.ebb_params(ebb).to_vec().into_iter().enumerate() {
|
||||||
|
let ty = pos.func.dfg.value_type(ebb_param);
|
||||||
|
if ty != ir::types::I128 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
split_ebb_param(pos, ebb, num, ebb_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 EBB predecessors.
|
||||||
while let Some(repair) = repairs.pop() {
|
while let Some(repair) = repairs.pop() {
|
||||||
for BasicBlock { inst, .. } in cfg.pred_iter(repair.ebb) {
|
for BasicBlock { inst, .. } in cfg.pred_iter(repair.ebb) {
|
||||||
@@ -181,8 +211,6 @@ fn split_any(
|
|||||||
pos.func.dfg[inst].put_value_list(args);
|
pos.func.dfg[inst].put_value_list(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split a single value using the integer or vector semantics given by the `concat` opcode.
|
/// Split a single value using the integer or vector semantics given by the `concat` opcode.
|
||||||
@@ -215,40 +243,7 @@ fn split_value(
|
|||||||
// This is an EBB parameter. We can split the parameter value unless this is the entry
|
// This is an EBB parameter. We can split the parameter value unless this is the entry
|
||||||
// block.
|
// block.
|
||||||
if pos.func.layout.entry_block() != Some(ebb) {
|
if pos.func.layout.entry_block() != Some(ebb) {
|
||||||
// We are going to replace the parameter at `num` with two new arguments.
|
reuse = Some(split_ebb_param(pos, ebb, num, value, concat, repairs));
|
||||||
// Determine the new value types.
|
|
||||||
let ty = pos.func.dfg.value_type(value);
|
|
||||||
let split_type = match concat {
|
|
||||||
Opcode::Iconcat => ty.half_width().expect("Invalid type for isplit"),
|
|
||||||
Opcode::Vconcat => ty.half_vector().expect("Invalid type for vsplit"),
|
|
||||||
_ => panic!("Unhandled concat opcode: {}", concat),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Since the `repairs` stack potentially contains other parameter numbers for
|
|
||||||
// `ebb`, avoid shifting and renumbering EBB 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);
|
|
||||||
reuse = Some((lo, hi));
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// did so a future call to this function doesn't have to redo the work.
|
|
||||||
//
|
|
||||||
// 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.ins()
|
|
||||||
.with_result(value)
|
|
||||||
.Binary(concat, split_type, lo, hi);
|
|
||||||
|
|
||||||
// Finally, splitting the EBB parameter is not enough. We also have to repair all
|
|
||||||
// of the predecessor instructions that branch here.
|
|
||||||
add_repair(concat, split_type, ebb, num, hi_num, repairs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,6 +262,51 @@ fn split_value(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn split_ebb_param(
|
||||||
|
pos: &mut FuncCursor,
|
||||||
|
ebb: Ebb,
|
||||||
|
param_num: usize,
|
||||||
|
value: Value,
|
||||||
|
concat: Opcode,
|
||||||
|
repairs: &mut Vec<Repair>,
|
||||||
|
) -> (Value, Value) {
|
||||||
|
// We are going to replace the parameter at `num` with two new arguments.
|
||||||
|
// Determine the new value types.
|
||||||
|
let ty = pos.func.dfg.value_type(value);
|
||||||
|
let split_type = match concat {
|
||||||
|
Opcode::Iconcat => ty.half_width().expect("Invalid type for isplit"),
|
||||||
|
Opcode::Vconcat => ty.half_vector().expect("Invalid type for vsplit"),
|
||||||
|
_ => panic!("Unhandled concat opcode: {}", concat),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Since the `repairs` stack potentially contains other parameter numbers for
|
||||||
|
// `ebb`, avoid shifting and renumbering EBB 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);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// did so a future call to this function doesn't have to redo the work.
|
||||||
|
//
|
||||||
|
// 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.ins()
|
||||||
|
.with_result(value)
|
||||||
|
.Binary(concat, split_type, lo, hi);
|
||||||
|
|
||||||
|
// Finally, splitting the EBB 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);
|
||||||
|
|
||||||
|
(lo, hi)
|
||||||
|
}
|
||||||
|
|
||||||
// Add a repair entry to the work list.
|
// Add a repair entry to the work list.
|
||||||
fn add_repair(
|
fn add_repair(
|
||||||
concat: Opcode,
|
concat: Opcode,
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
test compile
|
||||||
|
target x86_64
|
||||||
|
|
||||||
|
function u0:0(i128) system_v {
|
||||||
|
ebb0(v0: i128):
|
||||||
|
jump ebb1(v0)
|
||||||
|
|
||||||
|
ebb1(v1: i128):
|
||||||
|
return
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user