1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::ir::prelude::*;
use crate::opt::prelude::*;
pub struct InstSimplification;
impl Pass for InstSimplification {
fn run_on_inst(ctx: &PassContext, inst: Inst, unit: &mut UnitBuilder) -> bool {
unit.insert_after(inst);
match unit[inst].opcode() {
Opcode::DrvCond => {
if let Some(konst) = unit.get_const_int(unit[inst].args()[3]) {
if konst.is_one() {
let signal = unit[inst].args()[0];
let value = unit[inst].args()[1];
let delay = unit[inst].args()[2];
unit.ins().drv(signal, value, delay);
}
unit.delete_inst(inst);
}
}
_ => (),
}
let value = match unit.get_inst_result(inst) {
Some(value) => value,
None => return false,
};
match unit[inst].opcode() {
Opcode::And | Opcode::Or if unit[inst].args()[0] == unit[inst].args()[1] => {
replace(inst, value, unit[inst].args()[0], unit)
}
Opcode::Xor | Opcode::Umod | Opcode::Urem | Opcode::Smod | Opcode::Srem
if unit[inst].args()[0] == unit[inst].args()[1] =>
{
let ty = unit.value_type(value);
let zero = unit.ins().const_zero(&ty);
replace(inst, value, zero, unit)
}
Opcode::Mux => simplify_mux(ctx, inst, value, unit),
_ => false,
}
}
}
fn replace(from_inst: Inst, from_value: Value, to: Value, unit: &mut UnitBuilder) -> bool {
debug!("Replace {} with {}", from_inst.dump(&unit), to.dump(&unit));
unit.replace_use(from_value, to) > 0
}
fn simplify_mux(_ctx: &PassContext, inst: Inst, value: Value, unit: &mut UnitBuilder) -> bool {
let array = unit[inst].args()[0];
if let Some(array_inst) = unit.get_value_inst(array) {
let mut iter = unit[array_inst].args().iter().cloned();
let first = match iter.next() {
Some(first) => first,
None => return false,
};
let identical = iter.all(|a| a == first);
if identical {
return replace(inst, value, first, unit);
}
}
false
}