cfg.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. #include "all.h"
  2. Blk *
  3. newblk()
  4. {
  5. static Blk z;
  6. Blk *b;
  7. b = alloc(sizeof *b);
  8. *b = z;
  9. b->ins = vnew(0, sizeof b->ins[0], PFn);
  10. b->pred = vnew(0, sizeof b->pred[0], PFn);
  11. return b;
  12. }
  13. static void
  14. fixphis(Fn *f)
  15. {
  16. Blk *b, *bp;
  17. Phi *p;
  18. uint n, n0;
  19. for (b=f->start; b; b=b->link) {
  20. assert(b->id < f->nblk);
  21. for (p=b->phi; p; p=p->link) {
  22. for (n=n0=0; n<p->narg; n++) {
  23. bp = p->blk[n];
  24. if (bp->id != -1u)
  25. if (bp->s1 == b || bp->s2 == b) {
  26. p->blk[n0] = bp;
  27. p->arg[n0] = p->arg[n];
  28. n0++;
  29. }
  30. }
  31. assert(n0 > 0);
  32. p->narg = n0;
  33. }
  34. }
  35. }
  36. static void
  37. addpred(Blk *bp, Blk *b)
  38. {
  39. vgrow(&b->pred, ++b->npred);
  40. b->pred[b->npred-1] = bp;
  41. }
  42. void
  43. fillpreds(Fn *f)
  44. {
  45. Blk *b;
  46. for (b=f->start; b; b=b->link)
  47. b->npred = 0;
  48. for (b=f->start; b; b=b->link) {
  49. if (b->s1)
  50. addpred(b, b->s1);
  51. if (b->s2 && b->s2 != b->s1)
  52. addpred(b, b->s2);
  53. }
  54. }
  55. static void
  56. porec(Blk *b, uint *npo)
  57. {
  58. Blk *s1, *s2;
  59. if (!b || b->id != -1u)
  60. return;
  61. b->id = 0; /* marker */
  62. s1 = b->s1;
  63. s2 = b->s2;
  64. if (s1 && s2 && s1->loop > s2->loop) {
  65. s1 = b->s2;
  66. s2 = b->s1;
  67. }
  68. porec(s1, npo);
  69. porec(s2, npo);
  70. b->id = (*npo)++;
  71. }
  72. static void
  73. fillrpo(Fn *f)
  74. {
  75. Blk *b, **p;
  76. for (b=f->start; b; b=b->link)
  77. b->id = -1u;
  78. f->nblk = 0;
  79. porec(f->start, &f->nblk);
  80. vgrow(&f->rpo, f->nblk);
  81. for (p=&f->start; (b=*p);) {
  82. if (b->id == -1u) {
  83. *p = b->link;
  84. } else {
  85. b->id = f->nblk-b->id-1;
  86. f->rpo[b->id] = b;
  87. p = &b->link;
  88. }
  89. }
  90. }
  91. /* fill rpo, preds; prune dead blks */
  92. void
  93. fillcfg(Fn *f)
  94. {
  95. fillrpo(f);
  96. fillpreds(f);
  97. fixphis(f);
  98. }
  99. /* for dominators computation, read
  100. * "A Simple, Fast Dominance Algorithm"
  101. * by K. Cooper, T. Harvey, and K. Kennedy.
  102. */
  103. static Blk *
  104. inter(Blk *b1, Blk *b2)
  105. {
  106. Blk *bt;
  107. if (b1 == 0)
  108. return b2;
  109. while (b1 != b2) {
  110. if (b1->id < b2->id) {
  111. bt = b1;
  112. b1 = b2;
  113. b2 = bt;
  114. }
  115. while (b1->id > b2->id) {
  116. b1 = b1->idom;
  117. assert(b1);
  118. }
  119. }
  120. return b1;
  121. }
  122. void
  123. filldom(Fn *fn)
  124. {
  125. Blk *b, *d;
  126. int ch;
  127. uint n, p;
  128. for (b=fn->start; b; b=b->link) {
  129. b->idom = 0;
  130. b->dom = 0;
  131. b->dlink = 0;
  132. }
  133. do {
  134. ch = 0;
  135. for (n=1; n<fn->nblk; n++) {
  136. b = fn->rpo[n];
  137. d = 0;
  138. for (p=0; p<b->npred; p++)
  139. if (b->pred[p]->idom
  140. || b->pred[p] == fn->start)
  141. d = inter(d, b->pred[p]);
  142. if (d != b->idom) {
  143. ch++;
  144. b->idom = d;
  145. }
  146. }
  147. } while (ch);
  148. for (b=fn->start; b; b=b->link)
  149. if ((d=b->idom)) {
  150. assert(d != b);
  151. b->dlink = d->dom;
  152. d->dom = b;
  153. }
  154. }
  155. int
  156. sdom(Blk *b1, Blk *b2)
  157. {
  158. assert(b1 && b2);
  159. if (b1 == b2)
  160. return 0;
  161. while (b2->id > b1->id)
  162. b2 = b2->idom;
  163. return b1 == b2;
  164. }
  165. int
  166. dom(Blk *b1, Blk *b2)
  167. {
  168. return b1 == b2 || sdom(b1, b2);
  169. }
  170. static void
  171. addfron(Blk *a, Blk *b)
  172. {
  173. uint n;
  174. for (n=0; n<a->nfron; n++)
  175. if (a->fron[n] == b)
  176. return;
  177. if (!a->nfron)
  178. a->fron = vnew(++a->nfron, sizeof a->fron[0], PFn);
  179. else
  180. vgrow(&a->fron, ++a->nfron);
  181. a->fron[a->nfron-1] = b;
  182. }
  183. /* fill the dominance frontier */
  184. void
  185. fillfron(Fn *fn)
  186. {
  187. Blk *a, *b;
  188. for (b=fn->start; b; b=b->link)
  189. b->nfron = 0;
  190. for (b=fn->start; b; b=b->link) {
  191. if (b->s1)
  192. for (a=b; !sdom(a, b->s1); a=a->idom)
  193. addfron(a, b->s1);
  194. if (b->s2)
  195. for (a=b; !sdom(a, b->s2); a=a->idom)
  196. addfron(a, b->s2);
  197. }
  198. }
  199. static void
  200. loopmark(Blk *hd, Blk *b, void f(Blk *, Blk *))
  201. {
  202. uint p;
  203. if (b->id < hd->id || b->visit == hd->id)
  204. return;
  205. b->visit = hd->id;
  206. f(hd, b);
  207. for (p=0; p<b->npred; ++p)
  208. loopmark(hd, b->pred[p], f);
  209. }
  210. void
  211. loopiter(Fn *fn, void f(Blk *, Blk *))
  212. {
  213. uint n, p;
  214. Blk *b;
  215. for (b=fn->start; b; b=b->link)
  216. b->visit = -1u;
  217. for (n=0; n<fn->nblk; ++n) {
  218. b = fn->rpo[n];
  219. for (p=0; p<b->npred; ++p)
  220. if (b->pred[p]->id >= n)
  221. loopmark(b, b->pred[p], f);
  222. }
  223. }
  224. /* dominator tree depth */
  225. void
  226. filldepth(Fn *fn)
  227. {
  228. Blk *b, *d;
  229. int depth;
  230. for (b=fn->start; b; b=b->link)
  231. b->depth = -1;
  232. fn->start->depth = 0;
  233. for (b=fn->start; b; b=b->link) {
  234. if (b->depth != -1)
  235. continue;
  236. depth = 1;
  237. for (d=b->idom; d->depth==-1; d=d->idom)
  238. depth++;
  239. depth += d->depth;
  240. b->depth = depth;
  241. for (d=b->idom; d->depth==-1; d=d->idom)
  242. d->depth = --depth;
  243. }
  244. }
  245. /* least common ancestor in dom tree */
  246. Blk *
  247. lca(Blk *b1, Blk *b2)
  248. {
  249. if (!b1)
  250. return b2;
  251. if (!b2)
  252. return b1;
  253. while (b1->depth > b2->depth)
  254. b1 = b1->idom;
  255. while (b2->depth > b1->depth)
  256. b2 = b2->idom;
  257. while (b1 != b2) {
  258. b1 = b1->idom;
  259. b2 = b2->idom;
  260. }
  261. return b1;
  262. }
  263. void
  264. multloop(Blk *hd, Blk *b)
  265. {
  266. (void)hd;
  267. b->loop *= 10;
  268. }
  269. void
  270. fillloop(Fn *fn)
  271. {
  272. Blk *b;
  273. for (b=fn->start; b; b=b->link)
  274. b->loop = 1;
  275. loopiter(fn, multloop);
  276. }
  277. static void
  278. uffind(Blk **pb, Blk **uf)
  279. {
  280. Blk **pb1;
  281. pb1 = &uf[(*pb)->id];
  282. if (*pb1) {
  283. uffind(pb1, uf);
  284. *pb = *pb1;
  285. }
  286. }
  287. /* requires rpo and no phis, breaks cfg */
  288. void
  289. simpljmp(Fn *fn)
  290. {
  291. Blk **uf; /* union-find */
  292. Blk **p, *b, *ret;
  293. ret = newblk();
  294. ret->id = fn->nblk++;
  295. ret->jmp.type = Jret0;
  296. uf = emalloc(fn->nblk * sizeof uf[0]);
  297. for (b=fn->start; b; b=b->link) {
  298. assert(!b->phi);
  299. if (b->jmp.type == Jret0) {
  300. b->jmp.type = Jjmp;
  301. b->s1 = ret;
  302. }
  303. if (b->nins == 0)
  304. if (b->jmp.type == Jjmp) {
  305. uffind(&b->s1, uf);
  306. if (b->s1 != b)
  307. uf[b->id] = b->s1;
  308. }
  309. }
  310. for (p=&fn->start; (b=*p); p=&b->link) {
  311. if (b->s1)
  312. uffind(&b->s1, uf);
  313. if (b->s2)
  314. uffind(&b->s2, uf);
  315. if (b->s1 && b->s1 == b->s2) {
  316. b->jmp.type = Jjmp;
  317. b->s2 = 0;
  318. }
  319. }
  320. *p = ret;
  321. free(uf);
  322. }
  323. static int
  324. reachrec(Blk *b, Blk *to)
  325. {
  326. if (b == to)
  327. return 1;
  328. if (!b || b->visit)
  329. return 0;
  330. b->visit = 1;
  331. if (reachrec(b->s1, to))
  332. return 1;
  333. if (reachrec(b->s2, to))
  334. return 1;
  335. return 0;
  336. }
  337. /* Blk.visit needs to be clear at entry */
  338. int
  339. reaches(Fn *fn, Blk *b, Blk *to)
  340. {
  341. int r;
  342. assert(to);
  343. r = reachrec(b, to);
  344. for (b=fn->start; b; b=b->link)
  345. b->visit = 0;
  346. return r;
  347. }
  348. /* can b reach 'to' not through excl
  349. * Blk.visit needs to be clear at entry */
  350. int
  351. reachesnotvia(Fn *fn, Blk *b, Blk *to, Blk *excl)
  352. {
  353. excl->visit = 1;
  354. return reaches(fn, b, to);
  355. }
  356. int
  357. ifgraph(Blk *ifb, Blk **pthenb, Blk **pelseb, Blk **pjoinb)
  358. {
  359. Blk *s1, *s2, **t;
  360. if (ifb->jmp.type != Jjnz)
  361. return 0;
  362. s1 = ifb->s1;
  363. s2 = ifb->s2;
  364. if (s1->id > s2->id) {
  365. s1 = ifb->s2;
  366. s2 = ifb->s1;
  367. t = pthenb;
  368. pthenb = pelseb;
  369. pelseb = t;
  370. }
  371. if (s1 == s2)
  372. return 0;
  373. if (s1->jmp.type != Jjmp || s1->npred != 1)
  374. return 0;
  375. if (s1->s1 == s2) {
  376. /* if-then / if-else */
  377. if (s2->npred != 2)
  378. return 0;
  379. *pthenb = s1;
  380. *pelseb = ifb;
  381. *pjoinb = s2;
  382. return 1;
  383. }
  384. if (s2->jmp.type != Jjmp || s2->npred != 1)
  385. return 0;
  386. if (s1->s1 != s2->s1 || s1->s1->npred != 2)
  387. return 0;
  388. assert(s1->s1 != ifb);
  389. *pthenb = s1;
  390. *pelseb = s2;
  391. *pjoinb = s1->s1;
  392. return 1;
  393. }
  394. typedef struct Jmp Jmp;
  395. struct Jmp {
  396. int type;
  397. Ref arg;
  398. Blk *s1, *s2;
  399. };
  400. static int
  401. jmpeq(Jmp *a, Jmp *b)
  402. {
  403. return a->type == b->type && req(a->arg, b->arg)
  404. && a->s1 == b->s1 && a->s2 == b->s2;
  405. }
  406. static int
  407. jmpnophi(Jmp *j)
  408. {
  409. if (j->s1 && j->s1->phi)
  410. return 0;
  411. if (j->s2 && j->s2->phi)
  412. return 0;
  413. return 1;
  414. }
  415. /* require cfg rpo, breaks use */
  416. void
  417. simplcfg(Fn *fn)
  418. {
  419. Ins cpy, *i;
  420. Blk *b, *bb, **pb;
  421. Jmp *jmp, *j, *jj;
  422. Phi *p;
  423. int *empty, done;
  424. uint n;
  425. if (debug['C']) {
  426. fprintf(stderr, "\n> Before CFG simplification:\n");
  427. printfn(fn, stderr);
  428. }
  429. cpy = (Ins){.op = Ocopy};
  430. for (b=fn->start; b; b=b->link)
  431. if (b->npred == 1) {
  432. bb = b->pred[0];
  433. for (p=b->phi; p; p=p->link) {
  434. cpy.cls = p->cls;
  435. cpy.to = p->to;
  436. cpy.arg[0] = phiarg(p, bb);
  437. addins(&bb->ins, &bb->nins, &cpy);
  438. }
  439. b->phi = 0;
  440. }
  441. jmp = emalloc(fn->nblk * sizeof jmp[0]);
  442. empty = emalloc(fn->nblk * sizeof empty[0]);
  443. for (b=fn->start; b; b=b->link) {
  444. jmp[b->id].type = b->jmp.type;
  445. jmp[b->id].arg = b->jmp.arg;
  446. jmp[b->id].s1 = b->s1;
  447. jmp[b->id].s2 = b->s2;
  448. empty[b->id] = !b->phi;
  449. for (i=b->ins; i<&b->ins[b->nins]; i++)
  450. if (i->op != Onop && i->op != Odbgloc) {
  451. empty[b->id] = 0;
  452. break;
  453. }
  454. }
  455. do {
  456. done = 1;
  457. for (b=fn->start; b; b=b->link) {
  458. if (b->id == -1u)
  459. continue;
  460. j = &jmp[b->id];
  461. if (j->type == Jjmp && j->s1->npred == 1) {
  462. assert(!j->s1->phi);
  463. addbins(&b->ins, &b->nins, j->s1);
  464. empty[b->id] &= empty[j->s1->id];
  465. jj = &jmp[j->s1->id];
  466. pb = (Blk*[]){jj->s1, jj->s2, 0};
  467. for (; (bb=*pb); pb++)
  468. for (p=bb->phi; p; p=p->link) {
  469. n = phiargn(p, j->s1);
  470. p->blk[n] = b;
  471. }
  472. j->s1->id = -1u;
  473. *j = *jj;
  474. done = 0;
  475. }
  476. else if (j->type == Jjnz
  477. && empty[j->s1->id] && empty[j->s2->id]
  478. && jmpeq(&jmp[j->s1->id], &jmp[j->s2->id])
  479. && jmpnophi(&jmp[j->s1->id])) {
  480. *j = jmp[j->s1->id];
  481. done = 0;
  482. }
  483. }
  484. } while (!done);
  485. for (b=fn->start; b; b=b->link)
  486. if (b->id != -1u) {
  487. j = &jmp[b->id];
  488. b->jmp.type = j->type;
  489. b->jmp.arg = j->arg;
  490. b->s1 = j->s1;
  491. b->s2 = j->s2;
  492. assert(!j->s1 || j->s1->id != -1u);
  493. assert(!j->s2 || j->s2->id != -1u);
  494. }
  495. fillcfg(fn);
  496. free(empty);
  497. free(jmp);
  498. if (debug['C']) {
  499. fprintf(stderr, "\n> After CFG simplification:\n");
  500. printfn(fn, stderr);
  501. }
  502. }