peepmatic: Do not transplant instructions whose results are potentially used elsewhere
This commit is contained in:
@@ -208,26 +208,6 @@ fn const_to_value<'a>(builder: impl InstBuilder<'a>, c: Constant, root: Inst) ->
|
||||
}
|
||||
}
|
||||
|
||||
fn part_to_inst(pos: &mut FuncCursor, root: Inst, part: Part<ValueOrInst>) -> Option<Inst> {
|
||||
match part {
|
||||
Part::Instruction(ValueOrInst::Inst(inst)) => Some(inst),
|
||||
Part::Instruction(ValueOrInst::Value(v)) => {
|
||||
let inst = pos.func.dfg.value_def(v).inst()?;
|
||||
if pos.func.dfg.inst_results(inst).len() == 1 {
|
||||
Some(inst)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Part::Constant(c) => {
|
||||
let v = const_to_value(pos.ins(), c, root);
|
||||
let inst = pos.func.dfg.value_def(v).unwrap_inst();
|
||||
Some(inst)
|
||||
}
|
||||
Part::ConditionCode(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn part_to_value(pos: &mut FuncCursor, root: Inst, part: Part<ValueOrInst>) -> Option<Value> {
|
||||
match part {
|
||||
Part::Instruction(ValueOrInst::Inst(inst)) => {
|
||||
@@ -454,14 +434,30 @@ impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
new: Part<ValueOrInst>,
|
||||
) -> ValueOrInst {
|
||||
log::trace!("replace {:?} with {:?}", old, new);
|
||||
let old_inst = old.unwrap_inst();
|
||||
let old_inst = old.resolve_inst(&pos.func.dfg).unwrap();
|
||||
|
||||
// Try to convert `new` to an instruction, because we prefer replacing
|
||||
// an old instruction with a new one wholesale. However, if the
|
||||
// replacement cannot be converted to an instruction (e.g. the
|
||||
// right-hand side is a block/function parameter value) then we change
|
||||
// the old instruction's result to an alias of the new value.
|
||||
match part_to_inst(pos, old_inst, new) {
|
||||
let new_inst = match new {
|
||||
Part::Instruction(ValueOrInst::Inst(inst)) => Some(inst),
|
||||
Part::Instruction(ValueOrInst::Value(_)) => {
|
||||
// Do not try and follow the value definition. If we transplant
|
||||
// this value's instruction, and there are other uses of this
|
||||
// value, then we could mess up ordering between instructions.
|
||||
None
|
||||
}
|
||||
Part::Constant(c) => {
|
||||
let v = const_to_value(pos.ins(), c, old_inst);
|
||||
let inst = pos.func.dfg.value_def(v).unwrap_inst();
|
||||
Some(inst)
|
||||
}
|
||||
Part::ConditionCode(_) => None,
|
||||
};
|
||||
|
||||
match new_inst {
|
||||
Some(new_inst) => {
|
||||
pos.func.transplant_inst(old_inst, new_inst);
|
||||
debug_assert_eq!(pos.current_inst(), Some(old_inst));
|
||||
@@ -528,7 +524,7 @@ impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
) -> ValueOrInst {
|
||||
log::trace!("make_inst_1: {:?}({:?})", operator, a);
|
||||
|
||||
let root = root.unwrap_inst();
|
||||
let root = root.resolve_inst(&pos.func.dfg).unwrap();
|
||||
match operator {
|
||||
Operator::AdjustSpDown => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
@@ -541,12 +537,14 @@ impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
}
|
||||
Operator::Bconst => {
|
||||
let c = a.unwrap_constant();
|
||||
const_to_value(pos.ins(), c, root).into()
|
||||
let val = const_to_value(pos.ins(), c, root);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Bint => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let ty = peepmatic_ty_to_ir_ty(r#type, &pos.func.dfg, root);
|
||||
pos.ins().bint(ty, a).into()
|
||||
let val = pos.ins().bint(ty, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Brnz => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
@@ -571,17 +569,20 @@ impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
}
|
||||
Operator::Iconst => {
|
||||
let a = a.unwrap_constant();
|
||||
const_to_value(pos.ins(), a, root).into()
|
||||
let val = const_to_value(pos.ins(), a, root);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Ireduce => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let ty = peepmatic_ty_to_ir_ty(r#type, &pos.func.dfg, root);
|
||||
pos.ins().ireduce(ty, a).into()
|
||||
let val = pos.ins().ireduce(ty, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Sextend => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let ty = peepmatic_ty_to_ir_ty(r#type, &pos.func.dfg, root);
|
||||
pos.ins().sextend(ty, a).into()
|
||||
let val = pos.ins().sextend(ty, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Trapnz => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
@@ -604,7 +605,8 @@ impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
Operator::Uextend => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let ty = peepmatic_ty_to_ir_ty(r#type, &pos.func.dfg, root);
|
||||
pos.ins().uextend(ty, a).into()
|
||||
let val = pos.ins().uextend(ty, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -621,167 +623,199 @@ impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
) -> ValueOrInst {
|
||||
log::trace!("make_inst_2: {:?}({:?}, {:?})", operator, a, b);
|
||||
|
||||
let root = root.unwrap_inst();
|
||||
let root = root.resolve_inst(&pos.func.dfg).unwrap();
|
||||
match operator {
|
||||
Operator::Band => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().band(a, b).into()
|
||||
let val = pos.ins().band(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::BandImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().band_imm(b, a).into()
|
||||
let val = pos.ins().band_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Bor => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().bor(a, b).into()
|
||||
let val = pos.ins().bor(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::BorImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().bor_imm(b, a).into()
|
||||
let val = pos.ins().bor_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Bxor => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().bxor(a, b).into()
|
||||
let val = pos.ins().bxor(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::BxorImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().bxor_imm(b, a).into()
|
||||
let val = pos.ins().bxor_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Iadd => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().iadd(a, b).into()
|
||||
let val = pos.ins().iadd(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::IaddImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().iadd_imm(b, a).into()
|
||||
let val = pos.ins().iadd_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Ifcmp => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().ifcmp(a, b).into()
|
||||
let val = pos.ins().ifcmp(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::IfcmpImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().ifcmp_imm(b, a).into()
|
||||
let val = pos.ins().ifcmp_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Imul => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().imul(a, b).into()
|
||||
let val = pos.ins().imul(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::ImulImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().imul_imm(b, a).into()
|
||||
let val = pos.ins().imul_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::IrsubImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().irsub_imm(b, a).into()
|
||||
let val = pos.ins().irsub_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Ishl => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().ishl(a, b).into()
|
||||
let val = pos.ins().ishl(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::IshlImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().ishl_imm(b, a).into()
|
||||
let val = pos.ins().ishl_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Isub => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().isub(a, b).into()
|
||||
let val = pos.ins().isub(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Rotl => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().rotl(a, b).into()
|
||||
let val = pos.ins().rotl(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::RotlImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().rotl_imm(b, a).into()
|
||||
let val = pos.ins().rotl_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Rotr => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().rotr(a, b).into()
|
||||
let val = pos.ins().rotr(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::RotrImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().rotr_imm(b, a).into()
|
||||
let val = pos.ins().rotr_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Sdiv => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().sdiv(a, b).into()
|
||||
let val = pos.ins().sdiv(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::SdivImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().sdiv_imm(b, a).into()
|
||||
let val = pos.ins().sdiv_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Srem => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().srem(a, b).into()
|
||||
let val = pos.ins().srem(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::SremImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().srem_imm(b, a).into()
|
||||
let val = pos.ins().srem_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Sshr => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().sshr(a, b).into()
|
||||
let val = pos.ins().sshr(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::SshrImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().sshr_imm(b, a).into()
|
||||
let val = pos.ins().sshr_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Udiv => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().udiv(a, b).into()
|
||||
let val = pos.ins().udiv(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::UdivImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().udiv_imm(b, a).into()
|
||||
let val = pos.ins().udiv_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Urem => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().urem(a, b).into()
|
||||
let val = pos.ins().urem(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::UremImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().urem_imm(b, a).into()
|
||||
let val = pos.ins().urem_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Ushr => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().ushr(a, b).into()
|
||||
let val = pos.ins().ushr(a, b);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::UshrImm => {
|
||||
let a = part_to_imm64(pos, a);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
pos.ins().ushr_imm(b, a).into()
|
||||
let val = pos.ins().ushr_imm(b, a);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -799,27 +833,30 @@ impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
) -> ValueOrInst {
|
||||
log::trace!("make_inst_3: {:?}({:?}, {:?}, {:?})", operator, a, b, c);
|
||||
|
||||
let root = root.unwrap_inst();
|
||||
let root = root.resolve_inst(&pos.func.dfg).unwrap();
|
||||
match operator {
|
||||
Operator::Icmp => {
|
||||
let cond = a.unwrap_condition_code();
|
||||
let cond = peepmatic_to_intcc(cond);
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
let c = part_to_value(pos, root, c).unwrap();
|
||||
pos.ins().icmp(cond, b, c).into()
|
||||
let val = pos.ins().icmp(cond, b, c);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::IcmpImm => {
|
||||
let cond = a.unwrap_condition_code();
|
||||
let cond = peepmatic_to_intcc(cond);
|
||||
let imm = part_to_imm64(pos, b);
|
||||
let c = part_to_value(pos, root, c).unwrap();
|
||||
pos.ins().icmp_imm(cond, c, imm).into()
|
||||
let val = pos.ins().icmp_imm(cond, c, imm);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
Operator::Select => {
|
||||
let a = part_to_value(pos, root, a).unwrap();
|
||||
let b = part_to_value(pos, root, b).unwrap();
|
||||
let c = part_to_value(pos, root, c).unwrap();
|
||||
pos.ins().select(a, b, c).into()
|
||||
let val = pos.ins().select(a, b, c);
|
||||
pos.func.dfg.value_def(val).unwrap_inst().into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user