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 }