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