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
use crate::mir::ops;
pub type OpCost = u32;
pub type OpCostFactor = f32;
pub fn cost_for_op_category(category: ops::OpCategory) -> OpCost {
use crate::mir::ops::OpCategory;
match category {
OpCategory::Unreachable => 0,
OpCategory::ConstCastBoxed | OpCategory::CastBoxed => 0,
OpCategory::ConstReg => 1,
OpCategory::RegOp => 2,
OpCategory::ConstBox => 4,
OpCategory::Cond => 5,
OpCategory::MakeCallback => 5,
OpCategory::MemLoad => 5,
OpCategory::Ret => 5,
OpCategory::Call => 9,
OpCategory::AllocBoxed => 15,
}
}
fn cost_for_op(op: &ops::Op) -> OpCost {
let category_cost = cost_for_op_category(op.kind().category());
let op_adjustment = match op.kind() {
ops::OpKind::Cond(cond_op) => {
std::cmp::max(
cost_for_ops(cond_op.true_ops.iter()),
cost_for_ops(cond_op.false_ops.iter()),
)
}
ops::OpKind::Call(_, call_op) => {
let impure_penalty = if call_op.impure { 2 } else { 0 };
let callee_penalty = match call_op.callee {
ops::Callee::BoxedFunThunk(_) | ops::Callee::StaticSymbol(_) => 2,
_ => 0,
};
impure_penalty + callee_penalty
}
_ => 0,
};
category_cost + op_adjustment
}
pub fn cost_for_ops<'o>(ops: impl Iterator<Item = &'o ops::Op>) -> OpCost {
ops.map(cost_for_op).sum()
}