kit

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

pass_hard_live.c (3657B)


      1 #include <string.h>
      2 
      3 #include "core/arena.h"
      4 #include "opt/opt_internal.h"
      5 
      6 int opt_hard_empty(const OptHardRegSet* s) {
      7   for (u32 c = 0; c < OPT_REG_CLASSES; ++c)
      8     if (s->cls[c]) return 0;
      9   return 1;
     10 }
     11 
     12 int opt_hard_intersects(const OptHardRegSet* a, const OptHardRegSet* b) {
     13   for (u32 c = 0; c < OPT_REG_CLASSES; ++c)
     14     if (a->cls[c] & b->cls[c]) return 1;
     15   return 0;
     16 }
     17 
     18 static int hard_eq(const OptHardRegSet* a, const OptHardRegSet* b) {
     19   for (u32 c = 0; c < OPT_REG_CLASSES; ++c)
     20     if (a->cls[c] != b->cls[c]) return 0;
     21   return 1;
     22 }
     23 
     24 static void hard_or(OptHardRegSet* dst, const OptHardRegSet* src) {
     25   for (u32 c = 0; c < OPT_REG_CLASSES; ++c) dst->cls[c] |= src->cls[c];
     26 }
     27 
     28 static void hard_live_in_from_out(OptHardRegSet* dst, const OptHardRegSet* use,
     29                                   const OptHardRegSet* out,
     30                                   const OptHardRegSet* def) {
     31   for (u32 c = 0; c < OPT_REG_CLASSES; ++c)
     32     dst->cls[c] = use->cls[c] | (out->cls[c] & ~def->cls[c]);
     33 }
     34 
     35 void opt_hard_live_step(OptHardRegSet* live, const OptHardRegSet* use,
     36                         const OptHardRegSet* def) {
     37   for (u32 c = 0; c < OPT_REG_CLASSES; ++c)
     38     live->cls[c] = (live->cls[c] & ~def->cls[c]) | use->cls[c];
     39 }
     40 
     41 static void hard_live_blocks(Func* f, OptHardBlockLive* live) {
     42   for (u32 b = 0; b < f->nblocks; ++b) {
     43     Block* bl = &f->blocks[b];
     44     OptHardRegSet seen_def;
     45     memset(&seen_def, 0, sizeof seen_def);
     46     memset(&live[b], 0, sizeof live[b]);
     47     for (u32 i = 0; i < bl->ninsts; ++i) {
     48       OptRegEffectMasks effects;
     49       OptHardRegSet kills;
     50       opt_inst_reg_effect_masks(f, &bl->insts[i], &effects);
     51       opt_reg_effect_mask_kills(&effects, &kills);
     52       for (u32 c = 0; c < OPT_REG_CLASSES; ++c)
     53         live[b].live_use.cls[c] |=
     54             effects.uses.cls[c] & ~seen_def.cls[c];
     55       hard_or(&seen_def, &kills);
     56       hard_or(&live[b].live_def, &kills);
     57     }
     58   }
     59 
     60   int changed;
     61   do {
     62     changed = 0;
     63     for (u32 bi = f->nblocks; bi > 0; --bi) {
     64       u32 b = bi - 1u;
     65       Block* bl = &f->blocks[b];
     66       OptHardRegSet new_out, new_in;
     67       memset(&new_out, 0, sizeof new_out);
     68       for (u32 s = 0; s < bl->nsucc; ++s) {
     69         u32 t = bl->succ[s];
     70         if (t < f->nblocks) hard_or(&new_out, &live[t].live_in);
     71       }
     72       hard_live_in_from_out(&new_in, &live[b].live_use, &new_out,
     73                             &live[b].live_def);
     74       if (!hard_eq(&live[b].live_out, &new_out)) {
     75         live[b].live_out = new_out;
     76         changed = 1;
     77       }
     78       if (!hard_eq(&live[b].live_in, &new_in)) {
     79         live[b].live_in = new_in;
     80         changed = 1;
     81       }
     82     }
     83   } while (changed);
     84 }
     85 
     86 static int hard_live_out_has_phys_reg(const OptHardBlockLive* live,
     87                                       const Operand* r) {
     88   if (!live || !r || r->kind != OPK_REG || r->cls >= OPT_REG_CLASSES ||
     89       r->v.reg >= 32)
     90     return 0;
     91   return (live->live_out.cls[r->cls] & (1u << r->v.reg)) != 0;
     92 }
     93 
     94 OptHardBlockLive* opt_maybe_build_hard_live(Func* f) {
     95   if (!f->opt_rewritten) return NULL;
     96   OptHardBlockLive* live =
     97       arena_zarray(f->arena, OptHardBlockLive, f->nblocks ? f->nblocks : 1u);
     98   hard_live_blocks(f, live);
     99   return live;
    100 }
    101 
    102 OptHardRegSet opt_hard_live_out_for_block(const OptHardBlockLive* live) {
    103   OptHardRegSet out;
    104   memset(&out, 0, sizeof out);
    105   if (live) out = live->live_out;
    106   return out;
    107 }
    108 
    109 int opt_block_live_out_has_phys_reg(Func* f, const OptHardBlockLive* hard_live,
    110                                     u32 block, const Operand* r) {
    111   (void)f;
    112   if (!hard_live || block >= f->nblocks) return 0;
    113   return hard_live_out_has_phys_reg(&hard_live[block], r);
    114 }