Skip to content

Commit 2aca987

Browse files
author
metrics
committed
feat: move is_commutative function to utils and update local CSE implementation
1 parent 67eaeeb commit 2aca987

3 files changed

Lines changed: 41 additions & 36 deletions

File tree

crates/herkos-core/src/optimizer/local_cse.rs

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use crate::ir::{BinOp, IrFunction, IrInstr, IrValue, UnOp, VarId};
99
use std::collections::HashMap;
1010

11-
use super::utils::prune_dead_locals;
11+
use super::utils::{is_commutative, prune_dead_locals};
1212

1313
// ── Value key ────────────────────────────────────────────────────────────────
1414

@@ -45,37 +45,6 @@ impl From<IrValue> for ConstKey {
4545
}
4646
}
4747

48-
// ── Commutative op detection ─────────────────────────────────────────────────
49-
50-
/// Returns true for operations where `op(a, b) == op(b, a)`.
51-
fn is_commutative(op: &BinOp) -> bool {
52-
matches!(
53-
op,
54-
BinOp::I32Add
55-
| BinOp::I32Mul
56-
| BinOp::I32And
57-
| BinOp::I32Or
58-
| BinOp::I32Xor
59-
| BinOp::I32Eq
60-
| BinOp::I32Ne
61-
| BinOp::I64Add
62-
| BinOp::I64Mul
63-
| BinOp::I64And
64-
| BinOp::I64Or
65-
| BinOp::I64Xor
66-
| BinOp::I64Eq
67-
| BinOp::I64Ne
68-
| BinOp::F32Add
69-
| BinOp::F32Mul
70-
| BinOp::F32Eq
71-
| BinOp::F32Ne
72-
| BinOp::F64Add
73-
| BinOp::F64Mul
74-
| BinOp::F64Eq
75-
| BinOp::F64Ne
76-
)
77-
}
78-
7948
/// Build a `ValueKey` for a `BinOp`, normalizing operand order for commutative ops.
8049
fn binop_key(op: BinOp, lhs: VarId, rhs: VarId) -> ValueKey {
8150
let (lhs, rhs) = if is_commutative(&op) && lhs.0 > rhs.0 {
@@ -97,8 +66,11 @@ pub fn eliminate(func: &mut IrFunction) {
9766
let mut value_map: HashMap<ValueKey, VarId> = HashMap::new();
9867

9968
for instr in &mut block.instructions {
100-
// In strict SSA form each variable is defined exactly once, so there
101-
// is no need to invalidate cached CSE entries on redefinition.
69+
// This pass runs on lowered (post-phi) IR. While the function is no
70+
// longer globally in SSA form, within any single block each BinOp,
71+
// UnOp, and Const dest is still defined at most once: phi lowering
72+
// only inserts Assigns into predecessor blocks, never into the block
73+
// being processed. So value_map entries are never stale.
10274
match instr {
10375
IrInstr::Const { dest, value } => {
10476
let key = ValueKey::Const(ConstKey::from(*value));

crates/herkos-core/src/optimizer/utils.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,37 @@ pub fn is_side_effect_free(instr: &IrInstr) -> bool {
466466
}
467467
}
468468

469+
// ── Commutative op detection ─────────────────────────────────────────────────
470+
471+
/// Returns true for operations where `op(a, b) == op(b, a)`.
472+
pub fn is_commutative(op: &BinOp) -> bool {
473+
matches!(
474+
op,
475+
BinOp::I32Add
476+
| BinOp::I32Mul
477+
| BinOp::I32And
478+
| BinOp::I32Or
479+
| BinOp::I32Xor
480+
| BinOp::I32Eq
481+
| BinOp::I32Ne
482+
| BinOp::I64Add
483+
| BinOp::I64Mul
484+
| BinOp::I64And
485+
| BinOp::I64Or
486+
| BinOp::I64Xor
487+
| BinOp::I64Eq
488+
| BinOp::I64Ne
489+
| BinOp::F32Add
490+
| BinOp::F32Mul
491+
| BinOp::F32Eq
492+
| BinOp::F32Ne
493+
| BinOp::F64Add
494+
| BinOp::F64Mul
495+
| BinOp::F64Eq
496+
| BinOp::F64Ne
497+
)
498+
}
499+
469500
// ── Rewrite terminator block targets ─────────────────────────────────────────
470501

471502
/// Rewrite all block-ID references in a terminator from `old` to `new`.

scripts/compare_metrics.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,16 @@ def display_html(groups: Dict[str, List[Dict]], output_path: str = "metrics_repo
238238

239239
timestamps = [parse_timestamp(e["timestamp"]).isoformat() for e in entries]
240240
values = [e["value"] for e in entries]
241+
indices = list(range(len(entries)))
241242

242243
fig.add_trace(
243244
go.Scatter(
244-
x=timestamps,
245+
x=indices,
245246
y=values,
246247
mode="lines+markers",
247248
name=name,
248-
hovertemplate=f"<b>{name}</b><br>Timestamp: %{{x}}<br>Value: %{{y:.2f}}<extra></extra>",
249+
customdata=timestamps,
250+
hovertemplate=f"<b>{name}</b><br>Timestamp: %{{customdata}}<br>Value: %{{y:.2f}}<extra></extra>",
249251
),
250252
row=row,
251253
col=col,

0 commit comments

Comments
 (0)