opt.h (6662B)
1 #ifndef KIT_OPT_H 2 #define KIT_OPT_H 3 4 #include "arch/mc.h" 5 #include "arch/native_target.h" 6 #include "cg/cgtarget.h" /* CgFinishPolicy + the CgTarget the optimizer lowers to */ 7 #include "cg/ir.h" 8 #include "opt/ir.h" 9 10 /* O1 input boundary: semantic cg/ir.h is recorded once, then lowered into the 11 * optimizer-private Func/PReg view. During the O2 cutover window every 12 * opt_level >= 1 is normalized internally to this O1 path. */ 13 CgTarget* opt_cgtarget_new(Compiler*, CgTarget* target, int level); 14 Func* opt_func_from_cg_ir(Compiler*, const CgIrFunc*); 15 void opt_set_finish_policy(CgTarget*, const CgFinishPolicy*); 16 17 /* Interpreter tap: run the maximal target-independent subset of the O1 pipeline 18 * (everything in opt_run_o1_native up to, but excluding, opt_machinize_native / 19 * regalloc / MIR / native emit) and return the resulting Func for the threaded 20 * bytecode interpreter to consume. At this point opt_reg_ssa==0, OPK_REG 21 * operands carry virtual PReg ids, and there are no IR_PHI nodes. */ 22 Func* opt_run_o1_interp(Compiler*, const CgIrFunc*); 23 24 /* ----- intra-procedural passes (run per retained Func at finalize on -O2) 25 * ----- */ 26 void opt_build_cfg(Func*); 27 typedef enum OptJumpCleanupStage { 28 OPT_JUMP_CLEANUP_CFG, 29 OPT_JUMP_CLEANUP_LAYOUT, 30 } OptJumpCleanupStage; 31 void opt_jump_cleanup(Func*, OptJumpCleanupStage); 32 /* O1.md W9+W10: linear one-pass branch cleanup subset + constant cmp_branch 33 * folding for the no-SSA O1 prepare path (rebuilds the CFG only if it changed 34 * anything). */ 35 void opt_jump_cleanup_o1(Func*); 36 void opt_block_cloning(Func*); 37 void opt_build_reg_ssa(Func*); 38 void opt_build_ssa(Func*); 39 void opt_addr_xform(Func*); 40 void opt_addr_xform_pregs(Func*); /* O1: PReg-namespace addr-of-local folding */ 41 void opt_promote_scalar_locals(Func*); /* O1: promote non-escaped scalar 42 frame slots to mutable PRegs. */ 43 void opt_addr_of_global_cse(Func*); /* O1: hoist duplicate ADDR_OF(global) 44 defs to a single entry-block compute. */ 45 void opt_hoist_loop_consts(Func*); /* O1: hoist loop-invariant LOAD_IMM 46 materialization to the entry block. */ 47 void opt_lower_loop_imm_operands( 48 Func*, NativeTarget*); /* O1: convert non-foldable inline imm operands in 49 loop bodies into IR_LOAD_IMM + reg uses so the 50 hoister can lift them. */ 51 void opt_simplify_local(Func*); 52 void opt_simplify(Func*); 53 void opt_gvn(Func*); /* incl. constprop, redundant-load elim */ 54 void opt_copy_cleanup(Func*); 55 void opt_copy_prop(Func*); /* incl. redundant-extension elim */ 56 void opt_dse(Func*); /* dead store elimination */ 57 void opt_ssa_dce(Func*); 58 void opt_licm(Func*); /* requires loop tree built */ 59 void opt_pressure_relief(Func*); 60 void opt_make_conventional_ssa(Func*); 61 void opt_ssa_combine(Func*); 62 void opt_undo_ssa(Func*); 63 void opt_jump_opt(Func*); 64 65 /* ----- lowering / backend prep (per Func, run before NativeTarget emission) 66 * ----- */ 67 void opt_machinize_native(Func*, NativeTarget* target); 68 /* Rebuild target-derived per-instruction fixed-register effects after an HIR 69 * shape-changing pass. The O1 pipeline calls this at its final HIR boundary, 70 * before liveness and allocation consume those effects. */ 71 void opt_refresh_machine_clobbers(Func*, NativeTarget* target); 72 void opt_build_loop_tree(Func*); 73 74 typedef struct OptBitset { 75 Arena* arena; 76 u64* words; 77 u32 nwords; 78 u32 active_words; 79 } OptBitset; 80 81 typedef struct OptBlockLive { 82 OptBitset live_in; 83 OptBitset live_out; 84 OptBitset live_use; 85 OptBitset live_def; 86 } OptBlockLive; 87 88 typedef struct OptLiveInfo { 89 Arena* arena; 90 Func* f; 91 u32 words; 92 u64 active_words; 93 u64 block_bytes; 94 u64 set_bit_scans; 95 u64 bitset_words_touched; 96 u64 dataflow_iterations; 97 u64 dataflow_block_visits; 98 OptBlockLive* blocks; 99 } OptLiveInfo; 100 101 #define OPT_RANGE_NONE ((u32)~0u) 102 103 typedef struct OptLiveRange { 104 PReg preg; 105 u32 start; 106 u32 end; 107 u32 raw_start; 108 u32 raw_end; 109 u32 next; 110 u32 block; 111 u8 whole_block; 112 u8 pad[3]; 113 } OptLiveRange; 114 115 typedef struct OptLiveRangeSet { 116 Arena* arena; 117 Func* f; 118 OptLiveRange* ranges; 119 u32 nranges; 120 u32 cap; 121 u32* first_range_by_preg; 122 u32* live_length_by_preg; 123 u32* use_freq_by_preg; 124 u32* def_freq_by_preg; 125 u32* live_block_freq_by_preg; 126 u32* live_across_call_freq_by_preg; 127 u32* spill_cost_by_preg; 128 u32 point_count; 129 u32 raw_point_count; 130 u32 max_ranges_per_preg; 131 u32 max_live_length; 132 u32 whole_block_spans; 133 u64 range_point_visits; 134 u64 preg_scans; 135 u64 live_words_touched; 136 } OptLiveRangeSet; 137 138 typedef void (*OptBitsetIterFn)(PReg, void*); 139 140 void opt_bitset_clear(OptBitset*); 141 void opt_bitset_set(OptBitset*, PReg); 142 void opt_bitset_clear_bit(OptBitset*, PReg); 143 int opt_bitset_has(const OptBitset*, PReg); 144 int opt_bitset_copy(OptBitset*, const OptBitset*); 145 int opt_bitset_union(OptBitset*, const OptBitset*); 146 int opt_bitset_union_and_not(OptBitset*, const OptBitset*, const OptBitset*); 147 void opt_bitset_iter_set(const OptBitset*, OptBitsetIterFn, void* arg); 148 149 void opt_live_blocks(Func*, OptLiveInfo*); 150 void opt_live_dump_blocks(Func*, const OptLiveInfo*, Writer*); 151 void opt_live_ranges_build(Func*, const OptLiveInfo*, OptLiveRangeSet*); 152 void opt_live_dump_ranges(Func*, const OptLiveRangeSet*, Writer*); 153 void opt_ir_dump(Func*, Writer*); 154 void opt_ssa_dump(Func*, Writer*); 155 void opt_rewrite_dump(Func*, Writer*); 156 void opt_coalesce(Func*); 157 void opt_regalloc_locations(Func*, OptLiveInfo* live_out); 158 void opt_lower_to_mir(Func*, const OptLiveInfo*); 159 void opt_mir_combine(Func*, NativeTarget* target); 160 void opt_mir_dce(Func*); 161 void opt_mir_jump_cleanup(Func*, OptJumpCleanupStage); 162 void opt_mir_build_cfg(Func*); 163 void opt_mir_verify(Func*, const char* stage); 164 /* code selection: merge dependent insns. `target` (may be NULL) supplies the 165 * immediate-legality oracle for the W6 cmp-imm / address-offset folds. */ 166 void opt_combine(Func*, NativeTarget* target); 167 void opt_dce(Func*); /* post-RA DCE */ 168 void opt_dead_def_elim(Func*); /* pre-RA dead-definition elimination */ 169 void opt_dead_def_elim_with_live(Func*, const OptLiveInfo*); 170 171 /* Walks the lowered MIR and drives the physical native backend. */ 172 void opt_emit_native(Compiler*, Func*, NativeTarget* target); 173 174 /* When set, the wrapper writes a textual dump of each function's recorded 175 * tape to `w` on func_end, immediately before replay. Pass `w == NULL` to 176 * disable. The format is line-oriented and stable enough for golden-file 177 * diffs but otherwise unspecified. No-op if `t` is not an opt_cgtarget. */ 178 void opt_set_dump_writer(CgTarget* t, Writer* w); 179 180 #endif