cfg.c 5.8 KB

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