Simple preopt: fold instructions using simple algebraic identities;
This commit is contained in:
@@ -577,52 +577,95 @@ fn simplify(pos: &mut FuncCursor, inst: Inst) {
|
|||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
||||||
InstructionData::BinaryImm { opcode, arg, imm } => match opcode {
|
InstructionData::BinaryImm { opcode, arg, imm } => {
|
||||||
Opcode::IaddImm
|
let ty = pos.func.dfg.ctrl_typevar(inst);
|
||||||
| Opcode::ImulImm
|
|
||||||
| Opcode::BorImm
|
let mut imm = imm;
|
||||||
| Opcode::BandImm
|
match opcode {
|
||||||
| Opcode::BxorImm => {
|
Opcode::IaddImm
|
||||||
// Fold binary_op(C2, binary_op(C1, x)) into binary_op(binary_op(C1 | C2), x)
|
| Opcode::ImulImm
|
||||||
if let ValueDef::Result(arg_inst, _) = pos.func.dfg.value_def(arg) {
|
| Opcode::BorImm
|
||||||
if let InstructionData::BinaryImm {
|
| Opcode::BandImm
|
||||||
opcode: prev_opcode,
|
| Opcode::BxorImm => {
|
||||||
arg: prev_arg,
|
// Fold binary_op(C2, binary_op(C1, x)) into binary_op(binary_op(C1, C2), x)
|
||||||
imm: prev_imm,
|
if let ValueDef::Result(arg_inst, _) = pos.func.dfg.value_def(arg) {
|
||||||
} = &pos.func.dfg[arg_inst]
|
if let InstructionData::BinaryImm {
|
||||||
{
|
opcode: prev_opcode,
|
||||||
if opcode == *prev_opcode {
|
arg: prev_arg,
|
||||||
let ty = pos.func.dfg.ctrl_typevar(inst);
|
imm: prev_imm,
|
||||||
if ty == pos.func.dfg.ctrl_typevar(arg_inst) {
|
} = &pos.func.dfg[arg_inst]
|
||||||
let lhs: i64 = imm.into();
|
{
|
||||||
let rhs: i64 = (*prev_imm).into();
|
if opcode == *prev_opcode {
|
||||||
let new_imm = match opcode {
|
if ty == pos.func.dfg.ctrl_typevar(arg_inst) {
|
||||||
Opcode::BorImm => lhs | rhs,
|
let lhs: i64 = imm.into();
|
||||||
Opcode::BandImm => lhs & rhs,
|
let rhs: i64 = (*prev_imm).into();
|
||||||
Opcode::BxorImm => lhs ^ rhs,
|
let new_imm = match opcode {
|
||||||
Opcode::IaddImm => lhs.wrapping_add(rhs),
|
Opcode::BorImm => lhs | rhs,
|
||||||
Opcode::ImulImm => lhs.wrapping_mul(rhs),
|
Opcode::BandImm => lhs & rhs,
|
||||||
_ => panic!("can't happen"),
|
Opcode::BxorImm => lhs ^ rhs,
|
||||||
};
|
Opcode::IaddImm => lhs.wrapping_add(rhs),
|
||||||
let new_imm = immediates::Imm64::from(new_imm);
|
Opcode::ImulImm => lhs.wrapping_mul(rhs),
|
||||||
let arg = *prev_arg;
|
_ => panic!("can't happen"),
|
||||||
pos.func
|
};
|
||||||
.dfg
|
let new_imm = immediates::Imm64::from(new_imm);
|
||||||
.replace(inst)
|
let arg = *prev_arg;
|
||||||
.BinaryImm(opcode, ty, new_imm, arg);
|
pos.func
|
||||||
|
.dfg
|
||||||
|
.replace(inst)
|
||||||
|
.BinaryImm(opcode, ty, new_imm, arg);
|
||||||
|
imm = new_imm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Opcode::UshrImm | Opcode::SshrImm => {
|
Opcode::UshrImm | Opcode::SshrImm => {
|
||||||
if try_fold_extended_move(pos, inst, opcode, arg, imm) {
|
if try_fold_extended_move(pos, inst, opcode, arg, imm) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Replace operations that are no-ops.
|
||||||
|
match (opcode, imm.into()) {
|
||||||
|
(Opcode::IaddImm, 0)
|
||||||
|
| (Opcode::ImulImm, 1)
|
||||||
|
| (Opcode::SdivImm, 1)
|
||||||
|
| (Opcode::UdivImm, 1)
|
||||||
|
| (Opcode::BorImm, 0)
|
||||||
|
| (Opcode::BandImm, -1)
|
||||||
|
| (Opcode::BxorImm, 0)
|
||||||
|
| (Opcode::RotlImm, 0)
|
||||||
|
| (Opcode::RotrImm, 0)
|
||||||
|
| (Opcode::IshlImm, 0)
|
||||||
|
| (Opcode::UshrImm, 0)
|
||||||
|
| (Opcode::SshrImm, 0) => {
|
||||||
|
// Alias the result value with the original argument.
|
||||||
|
let results = pos.func.dfg.detach_results(inst);
|
||||||
|
debug_assert!(results.len(&pos.func.dfg.value_lists) == 1);
|
||||||
|
let first_result = results.get(0, &pos.func.dfg.value_lists).unwrap();
|
||||||
|
pos.func.dfg.change_to_alias(first_result, arg);
|
||||||
|
|
||||||
|
// Replace instruction by a nop.
|
||||||
|
pos.func.dfg.replace(inst).nop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
(Opcode::ImulImm, 0) | (Opcode::BandImm, 0) => {
|
||||||
|
// Replace by zero.
|
||||||
|
pos.func.dfg.replace(inst).iconst(ty, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(Opcode::BorImm, -1) => {
|
||||||
|
// Replace by minus one.
|
||||||
|
pos.func.dfg.replace(inst).iconst(ty, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
_ => {}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
InstructionData::IntCompare { opcode, cond, args } => {
|
InstructionData::IntCompare { opcode, cond, args } => {
|
||||||
debug_assert_eq!(opcode, Opcode::Icmp);
|
debug_assert_eq!(opcode, Opcode::Icmp);
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ ebb0(v0: i32):
|
|||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
; converted to a copy
|
; converted to a nop
|
||||||
function %t_udiv32_p1(i32) -> i32 {
|
function %t_udiv32_p1(i32) -> i32 {
|
||||||
ebb0(v0: i32):
|
ebb0(v0: i32):
|
||||||
v1 = udiv_imm v0, 1
|
v1 = udiv_imm v0, 1
|
||||||
; check: copy v0
|
; check: nop
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,11 +46,11 @@ ebb0(v0: i64):
|
|||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
; converted to a copy
|
; converted to a nop
|
||||||
function %t_udiv64_p1(i64) -> i64 {
|
function %t_udiv64_p1(i64) -> i64 {
|
||||||
ebb0(v0: i64):
|
ebb0(v0: i64):
|
||||||
v1 = udiv_imm v0, 1
|
v1 = udiv_imm v0, 1
|
||||||
; check: copy v0
|
; check: nop
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,11 +81,11 @@ ebb0(v0: i32):
|
|||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
; converted to a copy
|
; converted to a nop
|
||||||
function %t_sdiv32_p1(i32) -> i32 {
|
function %t_sdiv32_p1(i32) -> i32 {
|
||||||
ebb0(v0: i32):
|
ebb0(v0: i32):
|
||||||
v1 = sdiv_imm v0, 1
|
v1 = sdiv_imm v0, 1
|
||||||
; check: copy v0
|
; check: nop
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,11 +192,11 @@ ebb0(v0: i64):
|
|||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
; converted to a copy
|
; converted to a nop
|
||||||
function %t_sdiv64_p1(i64) -> i64 {
|
function %t_sdiv64_p1(i64) -> i64 {
|
||||||
ebb0(v0: i64):
|
ebb0(v0: i64):
|
||||||
v1 = sdiv_imm v0, 1
|
v1 = sdiv_imm v0, 1
|
||||||
; check: copy v0
|
; check: nop
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user