code wiki / (root) / nx_x86_regalloc.nx

nx_x86_regalloc.nx

buildroot/runtime/nx_x86_regalloc.nx

103312 B2218 linesdepth 2pulls 3 transitivereach 5 importersview sourcekind librarytopic x86
docsdependenciesstructsconstsfunctions

about

nx_x86_regalloc.nx -- genuine x86_64 register allocation (G1 keystone). FRESH, x86_-prefixed, self-host-isolated: re-implements the proven IDEAS of nx_regalloc.nx (Interval shape, def-to-last-use scan, mark_crosses_call, ValueLoc lowering) with ZERO shared symbols and NO `import "nx_regalloc.nx"`, because regalloc_function is on the live RISC-V self-host bootstrap host (nx_nxc.nx:139, nx_main.nx:64) that compiles the x86 compiler -- re-binding a shared name there would corrupt the host. See docs/NX_G1_X86_REGALLOC_PLAN. ALLOCATE-not-COPY: a homed value LIVES in a callee-saved GPR for its whole live range (producing op computes straight into it -- zero copy), unlike the reverted K=1 cache (movq %reg,%rbx per result, +2018 insns -> net-negative). Home pool = the 5 SysV callee-saved GPRs {r12,r13,r14,r15,rbx} (home idx 0..4) -- none used as scratch/operand/arg/clobber by the x86 backend, so they survive every CALL/SYSCALL/TAIL_CALL/clone with no save-around-call logic. FIX-12 INVARIANT: never add rcx/rdx/rbp/r10/r11 to this pool. THIS IS STEP 1b: full interval analysis (build_intervals + mark_crosses_call + single_block) RUNS over every function -- crash-tested by the self-host fixpoint over the whole corpus -- but its result is DISCARDED: every value lowers to {VL_SPILLED,-1}, mask 0, so emitted code is byte-identical to the pre-regalloc backend. Home selection + emit-path retarget land in STEP 2.

dependencies 2 imports · 3 importers

nx_syscalls.nx nx_types.nx nx_x86_regalloc.nx nx_compile_field_candidate_t280.nx nx_compile_x86.nx nx_x86_64_ctx.nx

imports: nx_syscalls.nxnx_types.nx

imported by: nx_compile_field_candidate_t280.nxnx_compile_x86.nxnx_x86_64_ctx.nx

structs

128struct X86Interval

consts

29const X86_HOME_CAP: i64 = 5 // {r12,r13,r14,r15,rbx}
33const X86_HOME_LOADS: i64 = 1
50const X86_CALLER_POOL_ENABLE: i64 = 1
51const X86_ALLOW_CROSSBLOCK: i64 = 1
57const X86_CALLER_MIN_WCOST: i64 = 256
61const X86_NEGCTL_CALLER_IGNORE_CALL: i64 = 0
62const X86_CALLER_BASE: i64 = 5
63const X86_CALLER_CAP: i64 = 4 // idx 5,6,7,8
67const X86_CALLER_MIN_USES: i64 = 1
433const X86_NEGCTL_NO_BACKEDGE_EXT: i64 = 0
612const X86_HOME_CAP_ENABLE: i64 = 1 // ON: composes with opt_run for the measured crypto win
613const X86_HOME_MIN_USES: i64 = 3 // require >= this many uses to beat save/restore
1166const X86_NEGCTL_NONNEG_ALWAYS: i64 = 0
1246const X86_FWD_ENABLE: i64 = 1
1250const X86_NEGCTL_FWD_IGNORE_STORE: i64 = 0
1255const X86_NEGCTL_FWD_WRONG_HOME: i64 = 0
1272const X86_CHAIN_ENABLE: i64 = 1
1276const X86_NEGCTL_CHAIN_IGNORE_READ: i64 = 0
1281const X86_NEGCTL_CHAIN_SELFREF_OFF: i64 = 0
1559const X86_LN7_BLOCK_FWD_ENABLE: i64 = 1

functions

77func x86_home_reg_name(idx: i64) -> *u8
98func x86_reg_eq(a: *u8, b: *u8) -> i64
111func x86_home_save_off(slot_index: i64) -> i64
115func x86_popcount(mask: i64) -> i64
139func x86_intv_at(buf: *X86Interval, id: i64) -> *X86Interval
145func x86_val_at(f: *Function, id: i64) -> *Value
149func x86_block_at(f: *Function, id: i64) -> *BasicBlock
155func x86_operand_k(inst: *Instr, k: i64) -> i64
186func x86_n_value_operands(inst: *Instr) -> i64
197func x86_is_call_class(op: i64) -> i64
206func x86_touch_bb(first_bb: *i64, last_bb: *i64, v: i64, bi: i64) -> i64
222func x86_compute_loop_depth(f: *Function, depth: *i64) -> i64
252func x86_weight_for_depth(d: i64) -> i64
260func x86_compute_wcost(f: *Function, depth: *i64, wcost: *i64) -> i64
287func x86_build_intervals(f: *Function, intv: *X86Interval,
435func x86_extend_backedge_intervals(f: *Function, intv: *X86Interval,
475func x86_mark_crosses_call(intv: *X86Interval, n_values: i64,
496func x86_is_pure_rax_binop(op: i64) -> i64
509func x86_is_homeable(f: *Function, intv: *X86Interval, alloca_off: *i64,
564func x86_op_clobbers_caller_saved(op: i64) -> i64
586func x86_fn_has_clobber_intrinsic(f: *Function) -> i64
620func x86_select_homes(f: *Function, intv: *X86Interval, alloca_off: *i64,
730func x86_ah_value_consume_ok(op: i64) -> i64
763func x86_ah_base_ok(f: *Function, v: i64) -> i64
778func x86_ah_ldst_sz8(inst: *Instr) -> i64
788func x86_ah_scan(f: *Function, alloca_off: *i64, elig: *i64, cnt: *i64) -> i64
831func x86_ah_select(f: *Function, elig: *i64, cnt: *i64,
887func x86_g4_is_binop(op: i64) -> i64
903func x86_g4_is_cmp(op: i64) -> i64
915func x86_chain_op_commutative(op: i64) -> i64
929func x86_g4_producer_ok(op: i64) -> i64
954func x86_g4_pos_ok(jop: i64, k: i64, jres_homed: i64) -> i64
981func x86_g4_elide_scan(f: *Function, locs: *ValueLoc, alloca_off: *i64,
1064func x86_g5_imm32_ok(v: i64) -> i64
1070func x86_g5_select_const_homes(f: *Function, intv: *X86Interval,
1168func x86_const_ge(f: *Function, v: i64, lo: i64) -> i64
1177func x86_val_nonneg(f: *Function, v: i64, depth: i64) -> i64
1285func x86_chain_op_ok(op: i64) -> i64
1303func x86_chain_scan(f: *Function, alloca_off: *i64, alloca_home: *i64,
1462func x86_fwd_const_in(f: *Function, u: i64, a: i64, b: i64, c2: i64, d: i64) -> i64
1479func x86_fwd_is_sibish(f: *Function, u: i64) -> i64
1505func x86_fwd_consumer_ok(f: *Function, J: *Instr, k: i64) -> i64
1565func x86_fwd_pos_audited(op: i64, k: i64) -> i64
1604func x86_fwd_step(f: *Function, K: *Instr, a: i64, r: i64) -> i64
1624func x86_fwd_push_succs2(f: *Function, B: *BasicBlock, scratch: *i64, sp_in: i64, nb: i64) -> i64
1679func x86_fwd_probe(f: *Function, inst: *Instr, alloca_off: *i64, intv: *X86Interval,
1837func x86_fwd_cand_scan(f: *Function, alloca_off: *i64, intv: *X86Interval, fwd_cand: *i64,
1870func x86_fwd_scan(f: *Function, alloca_off: *i64, alloca_home: *i64,
1905func x86_recompute_cs_mask(f: *Function, intv: *X86Interval, alloca_off: *i64,
1940func x86_ln7_rax_served(f: *Function, intv: *X86Interval, alloca_off: *i64, v: i64) -> i64
1971func x86_select_all(f: *Function, intv: *X86Interval, alloca_off: *i64,
2108func x86_regalloc_function(f: *Function, alloca_off: *i64,