kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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