pass_loop.c (3376B)
1 #include <string.h> 2 3 #include "core/arena.h" 4 #include "opt/opt_internal.h" 5 6 static void loop_body_mark(u32* mark, u32 gen, u32* body_list, u32* nbody, 7 u32 b) { 8 if (mark[b] == gen) return; 9 mark[b] = gen; 10 body_list[(*nbody)++] = b; 11 } 12 13 static void loop_mark_body(Func* f, const u8* visited, u32 header, u32 latch, 14 u32* mark, u32 gen, u32* body_list, u32* nbody, 15 u32* stack) { 16 u32 sp = 0; 17 loop_body_mark(mark, gen, body_list, nbody, header); 18 if (mark[latch] != gen) { 19 loop_body_mark(mark, gen, body_list, nbody, latch); 20 stack[sp++] = latch; 21 } 22 23 while (sp) { 24 u32 b = stack[--sp]; 25 if (b == header) continue; 26 Block* bl = &f->blocks[b]; 27 for (u32 p = 0; p < bl->npreds; ++p) { 28 u32 pred = bl->preds[p]; 29 if (pred >= f->nblocks || !visited[pred] || mark[pred] == gen) continue; 30 loop_body_mark(mark, gen, body_list, nbody, pred); 31 stack[sp++] = pred; 32 } 33 } 34 } 35 36 static u32 loop_frequency(u8 depth) { 37 u8 capped = depth > 10 ? 10 : depth; 38 return 1u << capped; 39 } 40 41 void opt_build_loop_tree(Func* f) { 42 if (!f) return; 43 opt_analysis_invalidate(f, OPT_ANALYSIS_LOOP); 44 for (u32 b = 0; b < f->nblocks; ++b) { 45 f->blocks[b].loop_depth = 0; 46 f->blocks[b].frequency = 1; 47 } 48 if (f->nblocks == 0 || f->entry >= f->nblocks) { 49 opt_analysis_mark_valid(f, OPT_ANALYSIS_LOOP); 50 return; 51 } 52 53 OptAnalysis a; 54 memset(&a, 0, sizeof a); 55 opt_analysis_build_dominators(f, &a); 56 if (a.npo == 0) { 57 opt_analysis_mark_valid(f, OPT_ANALYSIS_LOOP); 58 return; 59 } 60 61 u32* first_edge = arena_array(f->arena, u32, f->nblocks); 62 for (u32 b = 0; b < f->nblocks; ++b) first_edge[b] = UINT32_MAX; 63 u32 max_edges = 0; 64 for (u32 b = 0; b < f->nblocks; ++b) 65 if (a.reachable[b]) max_edges += f->blocks[b].nsucc; 66 u32* edge_latch = arena_array(f->arena, u32, max_edges ? max_edges : 1u); 67 u32* edge_next = arena_array(f->arena, u32, max_edges ? max_edges : 1u); 68 u32 nedges = 0; 69 70 for (u32 latch = 0; latch < f->nblocks; ++latch) { 71 if (!a.reachable[latch]) continue; 72 Block* lb = &f->blocks[latch]; 73 for (u32 s = 0; s < lb->nsucc; ++s) { 74 u32 header = lb->succ[s]; 75 if (header >= f->nblocks || !a.reachable[header]) continue; 76 if (!opt_analysis_dominates(&a, header, latch)) continue; 77 edge_latch[nedges] = latch; 78 edge_next[nedges] = first_edge[header]; 79 first_edge[header] = nedges++; 80 } 81 } 82 83 u32* mark = arena_zarray(f->arena, u32, f->nblocks); 84 u32* body_list = arena_array(f->arena, u32, f->nblocks); 85 u32* stack = arena_array(f->arena, u32, f->nblocks); 86 u32 gen = 1; 87 88 for (u32 header = 0; header < f->nblocks; ++header) { 89 if (first_edge[header] == UINT32_MAX) continue; 90 u32 nbody = 0; 91 for (u32 e = first_edge[header]; e != UINT32_MAX; e = edge_next[e]) 92 loop_mark_body(f, a.reachable, header, edge_latch[e], mark, gen, 93 body_list, &nbody, stack); 94 for (u32 i = 0; i < nbody; ++i) { 95 u32 b = body_list[i]; 96 if (f->blocks[b].loop_depth < 31) ++f->blocks[b].loop_depth; 97 } 98 if (++gen == 0) { 99 memset(mark, 0, f->nblocks * sizeof mark[0]); 100 gen = 1; 101 } 102 } 103 104 for (u32 b = 0; b < f->nblocks; ++b) 105 f->blocks[b].frequency = loop_frequency(f->blocks[b].loop_depth); 106 opt_analysis_mark_valid(f, OPT_ANALYSIS_LOOP); 107 }