constant_propagation_pass: Fold division operations where applicable
We can fold division operations if: 1. The divisor is zero, then we can replace the result with zero (as this is how ARM platforms expect it). 2. Both values are known, in which case we can just do the operation and store the result 3. The divisor is 1, in which case just return the other operand.
This commit is contained in:
parent
d83eae2004
commit
8248999c5d
1 changed files with 36 additions and 0 deletions
|
@ -50,6 +50,34 @@ void FoldAND(IR::Inst& inst, bool is_32_bit) {
|
|||
}
|
||||
}
|
||||
|
||||
// Folds division operations based on the following:
|
||||
//
|
||||
// 1. x / 0 -> 0 (NOTE: This is an ARM-specific behavior defined in the architecture reference manual)
|
||||
// 2. imm_x / imm_y -> result
|
||||
// 3. x / 1 -> x
|
||||
//
|
||||
void FoldDivide(IR::Inst& inst, bool is_32_bit, bool is_signed) {
|
||||
const auto rhs = inst.GetArg(1);
|
||||
|
||||
if (rhs.IsZero()) {
|
||||
ReplaceUsesWith(inst, is_32_bit, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto lhs = inst.GetArg(0);
|
||||
if (lhs.IsImmediate() && rhs.IsImmediate()) {
|
||||
if (is_signed) {
|
||||
const s64 result = lhs.GetImmediateAsS64() / rhs.GetImmediateAsS64();
|
||||
ReplaceUsesWith(inst, is_32_bit, static_cast<u64>(result));
|
||||
} else {
|
||||
const u64 result = lhs.GetImmediateAsU64() / rhs.GetImmediateAsU64();
|
||||
ReplaceUsesWith(inst, is_32_bit, result);
|
||||
}
|
||||
} else if (rhs.IsUnsignedImmediate(1)) {
|
||||
inst.ReplaceUsesWith(IR::Value{lhs});
|
||||
}
|
||||
}
|
||||
|
||||
// Folds EOR operations based on the following:
|
||||
//
|
||||
// 1. imm_x ^ imm_y -> result
|
||||
|
@ -190,6 +218,14 @@ void ConstantPropagation(IR::Block& block) {
|
|||
case IR::Opcode::Mul64:
|
||||
FoldMultiply(inst, opcode == IR::Opcode::Mul32);
|
||||
break;
|
||||
case IR::Opcode::SignedDiv32:
|
||||
case IR::Opcode::SignedDiv64:
|
||||
FoldDivide(inst, opcode == IR::Opcode::SignedDiv32, true);
|
||||
break;
|
||||
case IR::Opcode::UnsignedDiv32:
|
||||
case IR::Opcode::UnsignedDiv64:
|
||||
FoldDivide(inst, opcode == IR::Opcode::UnsignedDiv32, false);
|
||||
break;
|
||||
case IR::Opcode::And32:
|
||||
case IR::Opcode::And64:
|
||||
FoldAND(inst, opcode == IR::Opcode::And32);
|
||||
|
|
Loading…
Reference in a new issue