code wiki / (root) / nx_eqsat.nx

nx_eqsat.nx

buildroot/runtime/nx_eqsat.nx

111396 B2139 linesdepth 6pulls 8 transitivereach 17 importersview sourcekind librarytopic eqsat
docsdependenciesstructsconstsfunctions

about

nx_eqsat.nx -- equality-saturation framework (egg/SpEC family). Foundation for the superoptimization arc per ZERO_TO_ADVANCED.md M2: "the system is the FASTEST possible at every layer". Equality saturation is the 2026-research-grade approach -- developed by Willsey/Tate/Bornholt (egg, 2021) + Tate et al (Equality Saturation for Compiler Optimization, 2009), proven on Souper/Cranelift et al production compilers. Why equality saturation vs traditional peephole: Peephole: apply one rewrite, commit. If the rewrite was bad you lose; if a better cascade existed but required first un-doing a rewrite, you never find it. Phase-ordering tyranny. EqSat: keep ALL equivalent expressions in an e-graph. Apply all rewrites breadth-first to saturation. Extract the lowest-cost representative. Provably optimal under the rule set + cost model. For RV64IM: lets the compiler find non-obvious wins like (add x x) -> (shl x 1) (when shl is faster) (shl (shl x a) b) -> (shl x (add a b)) (kill dependent chain) (mul x 2^k) -> (shl x k) (strength reduction) (and x (not (and ~a y))) -> ... (DeMorgan reroute) AND once silicon-feedback (rv64im_min_hot_report.nx) identifies hot patterns, those become silicon-aware rewrites: (popcount-naive-loop) -> (intrinsic popcount) when silicon has it (gemm-inner-product) -> (vec mac fused) when SIMD lands Status: SEED. 2026-05-26. V1: e-class union-find + rule registry + bounded saturation loop + greedy extractor. ~50 baseline rewrites for RV64IM; extends per silicon-feedback findings.

dependencies 3 imports · 10 importers

nx_syscalls.nx nx_sketch_hash_map.nx nx_nxgate_sim.nx nx_eqsat.nx nx_apex_gcc_bench.nx nx_eqsat_congruence_bench.nx nx_eqsat_congruence_test.nx nx_eqsat_constfold_bench.nx nx_eqsat_dsl_bench.nx nx_eqsat_membership_proof.nx nx_eqsat_race_bench.nx nx_eqsat_test.nx nx_eqsat_vs_gcc_battery_test.nx nx_superopt.nx

imports: nx_syscalls.nxnx_sketch_hash_map.nxnx_nxgate_sim.nx

imported by: nx_apex_gcc_bench.nxnx_eqsat_congruence_bench.nxnx_eqsat_congruence_test.nxnx_eqsat_constfold_bench.nxnx_eqsat_dsl_bench.nxnx_eqsat_membership_proof.nxnx_eqsat_race_bench.nxnx_eqsat_test.nxnx_eqsat_vs_gcc_battery_test.nxnx_superopt.nx

structs

90struct NxENode
105struct NxEClass
190struct NxDslRule
215struct NxEGraph
2102struct NxEmitNode

consts

38const NX_MAGIC_1024: i64 = 1024
39const NX_MAGIC_1000000000: i64 = 1000000000
46const NX_EQ_OP_CONST: i64 = 0 // 0 children; payload = i64 value
47const NX_EQ_OP_VAR: i64 = 1 // 0 children; payload = variable id
48const NX_EQ_OP_ADD: i64 = 2 // 2 children
49const NX_EQ_OP_SUB: i64 = 3 // 2 children
50const NX_EQ_OP_MUL: i64 = 4 // 2 children
51const NX_EQ_OP_DIV: i64 = 5 // 2 children
52const NX_EQ_OP_REM: i64 = 6 // 2 children
53const NX_EQ_OP_AND: i64 = 7 // 2 children
54const NX_EQ_OP_OR: i64 = 8 // 2 children
55const NX_EQ_OP_XOR: i64 = 9 // 2 children
56const NX_EQ_OP_NOT: i64 = 10 // 1 child
57const NX_EQ_OP_SHL: i64 = 11 // 2 children
58const NX_EQ_OP_SHR: i64 = 12 // 2 children (logical)
59const NX_EQ_OP_SAR: i64 = 13 // 2 children (arithmetic)
60const NX_EQ_OP_NEG: i64 = 14 // 1 child
61const NX_EQ_OP_EQ: i64 = 15 // 2 children
62const NX_EQ_OP_LT: i64 = 16 // 2 children (signed)
63const NX_EQ_OP_LTU: i64 = 17 // 2 children (unsigned)
64const NX_EQ_OP_SELECT: i64 = 18 // 3 children (mux)
65const NX_EQ_OP_POPCNT: i64 = 19 // 1 child (Zbb-equivalent)
66const NX_EQ_OP_N: i64 = 20
133const NX_CF_NONE: i64 = 0 - 0x7FFFFFFFFFFFFFFF - 1
158const DSL_VAR:i64 = 0
159const DSL_CONST:i64 = 1
160const DSL_SAME_AS_A:i64 = 2
162const RHS_BIND_A:i64 = 0
163const RHS_BIND_B:i64 = 1
164const RHS_CONST:i64 = 2
165const RHS_SHL_A_BY_CONST:i64 = 3
166const RHS_SHL_A_BY_LOG2B:i64 = 4
172const RHS_SHL_A_BY_IADDED_J:i64 = 5
174const SC_NONE:i64 = 0
175const SC_POW2_B_KLTW:i64 = 1
182const SC_SHIFT_MERGE_IJW:i64 = 2
184const CNT_EVERY:i64 = 0 // count every match (the 6 V1 rules' behavior)
185const CNT_REAL_MERGE:i64 = 1 // count only real find!=find merges (mul_pow2)
309const NX_EQSAT_OK: i64 = 0
310const NX_EQSAT_BAD_OP: i64 = 1
311const NX_EQSAT_BAD_ARITY: i64 = 2
312const NX_EQSAT_OVERFLOW: i64 = 3
313const NX_EQSAT_SATURATED: i64 = 4
314const NX_EQSAT_STEP_BUDGET: i64 = 5
325const NX_EQSAT_RULE_NONE: i64 = 0
326const NX_EQSAT_RULE_ADD_ZERO: i64 = 1
327const NX_EQSAT_RULE_SUB_SELF: i64 = 2
328const NX_EQSAT_RULE_ADD_SELF: i64 = 3
329const NX_EQSAT_RULE_AND_SELF: i64 = 4
330const NX_EQSAT_RULE_OR_ZERO: i64 = 5
331const NX_EQSAT_RULE_MUL_ONE: i64 = 6
332const NX_EQSAT_RULE_MUL_POW2: i64 = 7
340const NX_EQSAT_RULE_CONGRUENCE: i64 = 8
347const NX_EQSAT_RULE_XOR_SELF: i64 = 9
361const NX_EQSAT_RULE_CONSTFOLD: i64 = 10
372const NX_EQSAT_RULE_SHIFT_MERGE: i64 = 11
373const NX_EQSAT_RULE_N: i64 = 12
1361const NX_EQSAT_W: i64 = 64

functions

68func nx_eqsat_op_is_valid(op: i64) -> i64
called by 1: nx_eqsat_add
74func nx_eqsat_arity_for(op: i64) -> i64
377func nx_eqsat_init(g: *NxEGraph,
437func nx_eqsat_enable_prov(g: *NxEGraph, buf: *i64, cap: i64) -> i64
451func nx_eqsat_log_rule(g: *NxEGraph, rule_id: i64) -> i64
476func nx_eqsat_enable_meet(g: *NxEGraph, hc: *HashMap,
called by 2: _one_itermain
518func nx_eqsat_enable_dsl(g: *NxEGraph, table: *NxDslRule, n: i64, cap: i64) -> i64
537func nx_eqsat_enable_constfold(g: *NxEGraph) -> i64
570func nx_cf_make_const_node(g: *NxEGraph, value: i64) -> i64
593func nx_cf_intern_const(g: *NxEGraph, value: i64) -> i64
631func nx_eqsat_builtin_dsl_table(table: *NxDslRule) -> i64
679func nx_eqsat_dsl_set_row(table: *NxDslRule, i: i64, rule_id: i64, lhs_op: i64,
698func nx_eqsat_mix(h: i64) -> i64
707func nx_eqsat_fingerprint(op: i64, payload: i64, kc0: i64, kc1: i64, kc2: i64) -> i64
721func nx_eqsat_node_matches(g: *NxEGraph, nidx: i64, op: i64, payload: i64,
737func nx_eqsat_add_parent(g: *NxEGraph, nidx: i64, child_cls: i64) -> i64
called by 1: nx_eqsat_add
751func nx_eqsat_push_dirty(g: *NxEGraph, cls: i64) -> i64
761func nx_eqsat_new_class(g: *NxEGraph, node_idx: i64, initial_cost: i64) -> i64
783func nx_eqsat_find(g: *NxEGraph, id: i64) -> i64
799func nx_eqsat_union_cited(g: *NxEGraph, a: i64, b: i64, rule_id: i64) -> i64
851func nx_eqsat_union(g: *NxEGraph, a: i64, b: i64) -> i64
867func nx_eqsat_op_cost(op: i64) -> i64
880func nx_eqsat_class_cost(g: *NxEGraph, class_id: i64) -> i64
918func nx_eqsat_op_to_gate_kind(op: i64) -> i64
938func nx_eqsat_class_const(g: *NxEGraph, cls: i64, out_v: *i64) -> i64
954func nx_eqsat_class_cf(g: *NxEGraph, cls: i64, out_v: *i64) -> i64
calls 1: nx_eqsat_find
971func nx_eqsat_try_constfold(g: *NxEGraph, new_cls: i64, op: i64,
1013func nx_eqsat_fold_value(g: *NxEGraph, op: i64, kc0: i64, kc1: i64, kc2: i64, out_v: *i64) -> i64
1031func nx_eqsat_add(g: *NxEGraph, op: i64, k0: i64, k1: i64, k2: i64, payload: i64) -> i64
1204func nx_eqsat_add_const(g: *NxEGraph, value: i64) -> i64
1207func nx_eqsat_add_var(g: *NxEGraph, var_id: i64) -> i64
1210func nx_eqsat_add_binary(g: *NxEGraph, op: i64, a: i64, b: i64) -> i64
1213func nx_eqsat_add_unary(g: *NxEGraph, op: i64, a: i64) -> i64
called by 1: main calls 1: nx_eqsat_add
1224func nx_eqsat_apply_rule_add_zero(g: *NxEGraph) -> i64
1252func nx_eqsat_apply_rule_sub_self(g: *NxEGraph) -> i64
1271func nx_eqsat_apply_rule_add_self(g: *NxEGraph) -> i64
1291func nx_eqsat_apply_rule_and_self(g: *NxEGraph) -> i64
1309func nx_eqsat_apply_rule_or_zero(g: *NxEGraph) -> i64
1337func nx_eqsat_apply_rule_mul_one(g: *NxEGraph) -> i64
1363func nx_eqsat_apply_rule_mul_pow2(g: *NxEGraph) -> i64
1420func nx_eqsat_match_node_inline(g: *NxEGraph, nidx: i64) -> i64
1554func nx_eqsat_dsl_log2_pow2(c: i64) -> i64
1570func nx_eqsat_dsl_class_is_const(g: *NxEGraph, cls: i64, want: i64) -> i64
1582func nx_eqsat_dsl_const_val(g: *NxEGraph, cls: i64, out_v: *i64) -> i64
1605func nx_eqsat_dsl_shift_merge(g: *NxEGraph, table: *NxDslRule, ri: i64,
1641func nx_eqsat_dsl_instantiate_rhs(g: *NxEGraph, table: *NxDslRule, ri: i64, bindA: i64, shamt: i64) -> i64
1662func nx_eqsat_apply_dsl_rule(g: *NxEGraph, table: *NxDslRule, ri: i64) -> i64
1748func nx_eqsat_apply_dsl_table(g: *NxEGraph) -> i64
1764func nx_eqsat_match_node_dsl(g: *NxEGraph, nidx: i64) -> i64
1833func nx_eqsat_match_node(g: *NxEGraph, nidx: i64) -> i64
1856func nx_eqsat_rebuild(g: *NxEGraph) -> i64
1923func nx_eqsat_saturate(g: *NxEGraph, max_iters: i64) -> i64
2017func nx_eqsat_extract_best_node(g: *NxEGraph, class_id: i64) -> i64
2036func nx_eqsat_recompute_best(g: *NxEGraph) -> i64
2086func nx_eqsat_best_cost(g: *NxEGraph, class_id: i64) -> i64
2110func nx_eqsat_emit(g: *NxEGraph, class_id: i64, out: *NxEmitNode, cap: i64, count: *i64) -> i64