Files
stationeers_lang/rust_compiler/libs/optimizer/src/strength_reduction.rs

64 lines
1.8 KiB
Rust

use il::{Instruction, InstructionNode, Operand};
use rust_decimal::Decimal;
/// Pass: Strength Reduction
/// Replaces expensive operations with cheaper equivalents.
/// Example: x * 2 -> add x x x (addition is typically faster than multiplication)
pub fn strength_reduction<'a>(
input: Vec<InstructionNode<'a>>,
) -> (Vec<InstructionNode<'a>>, bool) {
let mut output = Vec::with_capacity(input.len());
let mut changed = false;
for mut node in input {
let reduced = match &node.instruction {
// x * 2 = x + x
Instruction::Mul(dst, a, Operand::Number(n)) if *n == Decimal::from(2) => {
Some(Instruction::Add(dst.clone(), a.clone(), a.clone()))
}
Instruction::Mul(dst, Operand::Number(n), b) if *n == Decimal::from(2) => {
Some(Instruction::Add(dst.clone(), b.clone(), b.clone()))
}
// Future: Could add power-of-2 optimizations using bit shifts if IC10 supports them
// x * 4 = (x + x) + (x + x) or x << 2
// x / 2 = x >> 1
_ => None,
};
if let Some(new) = reduced {
node.instruction = new;
changed = true;
}
output.push(node);
}
(output, changed)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mul_two_to_add() {
let input = vec![InstructionNode::new(
Instruction::Mul(
Operand::Register(1),
Operand::Register(2),
Operand::Number(Decimal::from(2)),
),
None,
)];
let (output, changed) = strength_reduction(input);
assert!(changed);
assert!(matches!(
output[0].instruction,
Instruction::Add(Operand::Register(1), Operand::Register(2), Operand::Register(2))
));
}
}