cfg.c 5.0 KB

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