cfg.c (5085B)
1 #include "all.h" 2 3 Blk * 4 newblk() 5 { 6 static Blk z; 7 Blk *b; 8 9 b = alloc(sizeof *b); 10 *b = z; 11 return b; 12 } 13 14 void 15 edgedel(Blk *bs, Blk **pbd) 16 { 17 Blk *bd; 18 Phi *p; 19 uint a; 20 int mult; 21 22 bd = *pbd; 23 mult = 1 + (bs->s1 == bs->s2); 24 *pbd = 0; 25 if (!bd || mult > 1) 26 return; 27 for (p=bd->phi; p; p=p->link) { 28 for (a=0; p->blk[a]!=bs; a++) 29 assert(a+1<p->narg); 30 p->narg--; 31 memmove(&p->blk[a], &p->blk[a+1], 32 sizeof p->blk[0] * (p->narg-a)); 33 memmove(&p->arg[a], &p->arg[a+1], 34 sizeof p->arg[0] * (p->narg-a)); 35 } 36 if (bd->npred != 0) { 37 for (a=0; bd->pred[a]!=bs; a++) 38 assert(a+1<bd->npred); 39 bd->npred--; 40 memmove(&bd->pred[a], &bd->pred[a+1], 41 sizeof bd->pred[0] * (bd->npred-a)); 42 } 43 } 44 45 static void 46 addpred(Blk *bp, Blk *bc) 47 { 48 if (!bc->pred) { 49 bc->pred = alloc(bc->npred * sizeof bc->pred[0]); 50 bc->visit = 0; 51 } 52 bc->pred[bc->visit++] = bp; 53 } 54 55 /* fill predecessors information in blocks */ 56 void 57 fillpreds(Fn *f) 58 { 59 Blk *b; 60 61 for (b=f->start; b; b=b->link) { 62 b->npred = 0; 63 b->pred = 0; 64 } 65 for (b=f->start; b; b=b->link) { 66 if (b->s1) 67 b->s1->npred++; 68 if (b->s2 && b->s2 != b->s1) 69 b->s2->npred++; 70 } 71 for (b=f->start; b; b=b->link) { 72 if (b->s1) 73 addpred(b, b->s1); 74 if (b->s2 && b->s2 != b->s1) 75 addpred(b, b->s2); 76 } 77 } 78 79 static int 80 rporec(Blk *b, uint x) 81 { 82 Blk *s1, *s2; 83 84 if (!b || b->id != -1u) 85 return x; 86 b->id = 1; 87 s1 = b->s1; 88 s2 = b->s2; 89 if (s1 && s2 && s1->loop > s2->loop) { 90 s1 = b->s2; 91 s2 = b->s1; 92 } 93 x = rporec(s1, x); 94 x = rporec(s2, x); 95 b->id = x; 96 assert(x != -1u); 97 return x - 1; 98 } 99 100 /* fill the rpo information */ 101 void 102 fillrpo(Fn *f) 103 { 104 uint n; 105 Blk *b, **p; 106 107 for (b=f->start; b; b=b->link) 108 b->id = -1u; 109 n = 1 + rporec(f->start, f->nblk-1); 110 f->nblk -= n; 111 f->rpo = alloc(f->nblk * sizeof f->rpo[0]); 112 for (p=&f->start; (b=*p);) { 113 if (b->id == -1u) { 114 edgedel(b, &b->s1); 115 edgedel(b, &b->s2); 116 *p = b->link; 117 } else { 118 b->id -= n; 119 f->rpo[b->id] = b; 120 p = &b->link; 121 } 122 } 123 } 124 125 /* for dominators computation, read 126 * "A Simple, Fast Dominance Algorithm" 127 * by K. Cooper, T. Harvey, and K. Kennedy. 128 */ 129 130 static Blk * 131 inter(Blk *b1, Blk *b2) 132 { 133 Blk *bt; 134 135 if (b1 == 0) 136 return b2; 137 while (b1 != b2) { 138 if (b1->id < b2->id) { 139 bt = b1; 140 b1 = b2; 141 b2 = bt; 142 } 143 while (b1->id > b2->id) { 144 b1 = b1->idom; 145 assert(b1); 146 } 147 } 148 return b1; 149 } 150 151 void 152 filldom(Fn *fn) 153 { 154 Blk *b, *d; 155 int ch; 156 uint n, p; 157 158 for (b=fn->start; b; b=b->link) { 159 b->idom = 0; 160 b->dom = 0; 161 b->dlink = 0; 162 } 163 do { 164 ch = 0; 165 for (n=1; n<fn->nblk; n++) { 166 b = fn->rpo[n]; 167 d = 0; 168 for (p=0; p<b->npred; p++) 169 if (b->pred[p]->idom 170 || b->pred[p] == fn->start) 171 d = inter(d, b->pred[p]); 172 if (d != b->idom) { 173 ch++; 174 b->idom = d; 175 } 176 } 177 } while (ch); 178 for (b=fn->start; b; b=b->link) 179 if ((d=b->idom)) { 180 assert(d != b); 181 b->dlink = d->dom; 182 d->dom = b; 183 } 184 } 185 186 int 187 sdom(Blk *b1, Blk *b2) 188 { 189 assert(b1 && b2); 190 if (b1 == b2) 191 return 0; 192 while (b2->id > b1->id) 193 b2 = b2->idom; 194 return b1 == b2; 195 } 196 197 int 198 dom(Blk *b1, Blk *b2) 199 { 200 return b1 == b2 || sdom(b1, b2); 201 } 202 203 static void 204 addfron(Blk *a, Blk *b) 205 { 206 uint n; 207 208 for (n=0; n<a->nfron; n++) 209 if (a->fron[n] == b) 210 return; 211 if (!a->nfron) 212 a->fron = vnew(++a->nfron, sizeof a->fron[0], PFn); 213 else 214 vgrow(&a->fron, ++a->nfron); 215 a->fron[a->nfron-1] = b; 216 } 217 218 /* fill the dominance frontier */ 219 void 220 fillfron(Fn *fn) 221 { 222 Blk *a, *b; 223 224 for (b=fn->start; b; b=b->link) 225 b->nfron = 0; 226 for (b=fn->start; b; b=b->link) { 227 if (b->s1) 228 for (a=b; !sdom(a, b->s1); a=a->idom) 229 addfron(a, b->s1); 230 if (b->s2) 231 for (a=b; !sdom(a, b->s2); a=a->idom) 232 addfron(a, b->s2); 233 } 234 } 235 236 static void 237 loopmark(Blk *hd, Blk *b, void f(Blk *, Blk *)) 238 { 239 uint p; 240 241 if (b->id < hd->id || b->visit == hd->id) 242 return; 243 b->visit = hd->id; 244 f(hd, b); 245 for (p=0; p<b->npred; ++p) 246 loopmark(hd, b->pred[p], f); 247 } 248 249 void 250 loopiter(Fn *fn, void f(Blk *, Blk *)) 251 { 252 uint n, p; 253 Blk *b; 254 255 for (b=fn->start; b; b=b->link) 256 b->visit = -1u; 257 for (n=0; n<fn->nblk; ++n) { 258 b = fn->rpo[n]; 259 for (p=0; p<b->npred; ++p) 260 if (b->pred[p]->id >= n) 261 loopmark(b, b->pred[p], f); 262 } 263 } 264 265 void 266 multloop(Blk *hd, Blk *b) 267 { 268 (void)hd; 269 b->loop *= 10; 270 } 271 272 void 273 fillloop(Fn *fn) 274 { 275 Blk *b; 276 277 for (b=fn->start; b; b=b->link) 278 b->loop = 1; 279 loopiter(fn, multloop); 280 } 281 282 static void 283 uffind(Blk **pb, Blk **uf) 284 { 285 Blk **pb1; 286 287 pb1 = &uf[(*pb)->id]; 288 if (*pb1) { 289 uffind(pb1, uf); 290 *pb = *pb1; 291 } 292 } 293 294 /* requires rpo and no phis, breaks cfg */ 295 void 296 simpljmp(Fn *fn) 297 { 298 299 Blk **uf; /* union-find */ 300 Blk **p, *b, *ret; 301 302 ret = newblk(); 303 ret->id = fn->nblk++; 304 ret->jmp.type = Jret0; 305 uf = emalloc(fn->nblk * sizeof uf[0]); 306 for (b=fn->start; b; b=b->link) { 307 assert(!b->phi); 308 if (b->jmp.type == Jret0) { 309 b->jmp.type = Jjmp; 310 b->s1 = ret; 311 } 312 if (b->nins == 0) 313 if (b->jmp.type == Jjmp) { 314 uffind(&b->s1, uf); 315 if (b->s1 != b) 316 uf[b->id] = b->s1; 317 } 318 } 319 for (p=&fn->start; (b=*p); p=&b->link) { 320 if (b->s1) 321 uffind(&b->s1, uf); 322 if (b->s2) 323 uffind(&b->s2, uf); 324 if (b->s1 && b->s1 == b->s2) { 325 b->jmp.type = Jjmp; 326 b->s2 = 0; 327 } 328 } 329 *p = ret; 330 free(uf); 331 }