code wiki / (root) / nx_x86_regalloc.nx

nx_x86_regalloc.nx

buildroot/runtime/nx_x86_regalloc.nx

84573 B1833 linesdepth 2pulls 3 transitivereach 4 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 · 2 importers

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

imports: nx_syscalls.nxnx_types.nx

imported by: nx_compile_x86.nxnx_x86_64_ctx.nx

structs

124struct X86Interval

consts

29const X86_HOME_CAP: i64 = 5 // {r12,r13,r14,r15,rbx}
46const X86_CALLER_POOL_ENABLE: i64 = 1
47const X86_ALLOW_CROSSBLOCK: i64 = 1
53const X86_CALLER_MIN_WCOST: i64 = 256
57const X86_NEGCTL_CALLER_IGNORE_CALL: i64 = 0
58const X86_CALLER_BASE: i64 = 5
59const X86_CALLER_CAP: i64 = 4 // idx 5,6,7,8
63const X86_CALLER_MIN_USES: i64 = 1
429const X86_NEGCTL_NO_BACKEDGE_EXT: i64 = 0
587const X86_HOME_CAP_ENABLE: i64 = 1 // ON: composes with opt_run for the measured crypto win
588const X86_HOME_MIN_USES: i64 = 3 // require >= this many uses to beat save/restore
1141const X86_NEGCTL_NONNEG_ALWAYS: i64 = 0
1221const X86_FWD_ENABLE: i64 = 1
1225const X86_NEGCTL_FWD_IGNORE_STORE: i64 = 0
1230const X86_NEGCTL_FWD_WRONG_HOME: i64 = 0
1247const X86_CHAIN_ENABLE: i64 = 1
1251const X86_NEGCTL_CHAIN_IGNORE_READ: i64 = 0
1256const X86_NEGCTL_CHAIN_SELFREF_OFF: i64 = 0

functions

73func x86_home_reg_name(idx: i64) -> *u8
94func x86_reg_eq(a: *u8, b: *u8) -> i64
107func x86_home_save_off(slot_index: i64) -> i64
111func x86_popcount(mask: i64) -> i64
called by 1: x86ctx_init
135func x86_intv_at(buf: *X86Interval, id: i64) -> *X86Interval
141func x86_val_at(f: *Function, id: i64) -> *Value
145func x86_block_at(f: *Function, id: i64) -> *BasicBlock
151func x86_operand_k(inst: *Instr, k: i64) -> i64
182func x86_n_value_operands(inst: *Instr) -> i64
193func x86_is_call_class(op: i64) -> i64
202func x86_touch_bb(first_bb: *i64, last_bb: *i64, v: i64, bi: i64) -> i64
called by 1: x86_build_intervals
218func x86_compute_loop_depth(f: *Function, depth: *i64) -> i64
called by 1: x86_regalloc_function calls 1: x86_block_at
248func x86_weight_for_depth(d: i64) -> i64
called by 1: x86_compute_wcost
256func x86_compute_wcost(f: *Function, depth: *i64, wcost: *i64) -> i64
283func x86_build_intervals(f: *Function, intv: *X86Interval,
431func x86_extend_backedge_intervals(f: *Function, intv: *X86Interval,
471func x86_mark_crosses_call(intv: *X86Interval, n_values: i64,
called by 1: x86_regalloc_function calls 1: x86_intv_at
492func x86_is_pure_rax_binop(op: i64) -> i64
505func x86_is_homeable(f: *Function, intv: *X86Interval, alloca_off: *i64,
540func x86_op_clobbers_caller_saved(op: i64) -> i64
561func x86_fn_has_clobber_intrinsic(f: *Function) -> i64
595func x86_select_homes(f: *Function, intv: *X86Interval, alloca_off: *i64,
705func x86_ah_value_consume_ok(op: i64) -> i64
called by 1: x86_ah_scan
738func x86_ah_base_ok(f: *Function, v: i64) -> i64
called by 1: x86_ah_scan calls 1: x86_val_at
753func x86_ah_ldst_sz8(inst: *Instr) -> i64
called by 1: x86_ah_scan
763func x86_ah_scan(f: *Function, alloca_off: *i64, elig: *i64, cnt: *i64) -> i64
806func x86_ah_select(f: *Function, elig: *i64, cnt: *i64,
862func x86_g4_is_binop(op: i64) -> i64
called by 1: x86_g4_pos_ok
878func x86_g4_is_cmp(op: i64) -> i64
called by 1: x86_g4_pos_ok
890func x86_chain_op_commutative(op: i64) -> i64
904func x86_g4_producer_ok(op: i64) -> i64
called by 1: x86_g4_elide_scan
929func x86_g4_pos_ok(jop: i64, k: i64, jres_homed: i64) -> i64
956func x86_g4_elide_scan(f: *Function, locs: *ValueLoc, alloca_off: *i64,
1039func x86_g5_imm32_ok(v: i64) -> i64
1045func x86_g5_select_const_homes(f: *Function, intv: *X86Interval,
1143func x86_const_ge(f: *Function, v: i64, lo: i64) -> i64
called by 1: x86_val_nonneg calls 1: x86_val_at
1152func x86_val_nonneg(f: *Function, v: i64, depth: i64) -> i64
1260func x86_chain_op_ok(op: i64) -> i64
called by 1: x86_chain_scan
1278func x86_chain_scan(f: *Function, alloca_off: *i64, alloca_home: *i64,
1430func x86_fwd_const_in(f: *Function, u: i64, a: i64, b: i64, c2: i64, d: i64) -> i64
1447func x86_fwd_is_sibish(f: *Function, u: i64) -> i64
1473func x86_fwd_consumer_ok(f: *Function, J: *Instr, k: i64) -> i64
1525func x86_fwd_scan(f: *Function, alloca_off: *i64, alloca_home: *i64,
1608func x86_select_all(f: *Function, intv: *X86Interval, alloca_off: *i64,
1733func x86_regalloc_function(f: *Function, alloca_off: *i64,