use crate::ir::Opcode;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct Cost(u32);
impl Cost {
pub(crate) fn at_level(&self, loop_level: usize) -> Cost {
let loop_level = std::cmp::min(2, loop_level);
let multiplier = 1u32 << ((10 * loop_level) as u32);
Cost(self.0.saturating_mul(multiplier)).finite()
}
pub(crate) fn infinity() -> Cost {
Cost(u32::MAX)
}
pub(crate) fn zero() -> Cost {
Cost(0)
}
fn finite(self) -> Cost {
Cost(std::cmp::min(u32::MAX - 1, self.0))
}
}
impl std::default::Default for Cost {
fn default() -> Cost {
Cost::zero()
}
}
impl std::ops::Add<Cost> for Cost {
type Output = Cost;
fn add(self, other: Cost) -> Cost {
Cost(self.0.saturating_add(other.0)).finite()
}
}
pub(crate) fn pure_op_cost(op: Opcode) -> Cost {
match op {
Opcode::Iconst | Opcode::F32const | Opcode::F64const => Cost(0),
Opcode::Uextend | Opcode::Sextend | Opcode::Ireduce | Opcode::Iconcat | Opcode::Isplit => {
Cost(1)
}
Opcode::Iadd
| Opcode::Isub
| Opcode::Band
| Opcode::Bor
| Opcode::Bxor
| Opcode::Bnot
| Opcode::Ishl
| Opcode::Ushr
| Opcode::Sshr => Cost(2),
_ => Cost(3),
}
}