gcm.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include "all.h"
  2. #define NOBID (-1u)
  3. static int
  4. isdivwl(Ins *i)
  5. {
  6. switch (i->op) {
  7. case Odiv:
  8. case Orem:
  9. case Oudiv:
  10. case Ourem:
  11. return KBASE(i->cls) == 0;
  12. default:
  13. return 0;
  14. }
  15. }
  16. int
  17. pinned(Ins *i)
  18. {
  19. return optab[i->op].pinned || isdivwl(i);
  20. }
  21. /* pinned ins that can be eliminated if unused */
  22. static int
  23. canelim(Ins *i)
  24. {
  25. return isload(i->op) || isalloc(i->op) || isdivwl(i);
  26. }
  27. static uint earlyins(Fn *, Blk *, Ins *);
  28. static uint
  29. schedearly(Fn *fn, Ref r)
  30. {
  31. Tmp *t;
  32. Blk *b;
  33. if (rtype(r) != RTmp)
  34. return 0;
  35. t = &fn->tmp[r.val];
  36. if (t->gcmbid != NOBID)
  37. return t->gcmbid;
  38. b = fn->rpo[t->bid];
  39. if (t->def) {
  40. assert(b->ins <= t->def && t->def < &b->ins[b->nins]);
  41. t->gcmbid = 0; /* mark as visiting */
  42. t->gcmbid = earlyins(fn, b, t->def);
  43. } else {
  44. /* phis do not move */
  45. t->gcmbid = t->bid;
  46. }
  47. return t->gcmbid;
  48. }
  49. static uint
  50. earlyins(Fn *fn, Blk *b, Ins *i)
  51. {
  52. uint b0, b1;
  53. b0 = schedearly(fn, i->arg[0]);
  54. assert(b0 != NOBID);
  55. b1 = schedearly(fn, i->arg[1]);
  56. assert(b1 != NOBID);
  57. if (fn->rpo[b0]->depth < fn->rpo[b1]->depth) {
  58. assert(dom(fn->rpo[b0], fn->rpo[b1]));
  59. b0 = b1;
  60. }
  61. return pinned(i) ? b->id : b0;
  62. }
  63. static void
  64. earlyblk(Fn *fn, uint bid)
  65. {
  66. Blk *b;
  67. Phi *p;
  68. Ins *i;
  69. uint n;
  70. b = fn->rpo[bid];
  71. for (p=b->phi; p; p=p->link)
  72. for (n=0; n<p->narg; n++)
  73. schedearly(fn, p->arg[n]);
  74. for (i=b->ins; i<&b->ins[b->nins]; i++)
  75. if (pinned(i)) {
  76. schedearly(fn, i->arg[0]);
  77. schedearly(fn, i->arg[1]);
  78. }
  79. schedearly(fn, b->jmp.arg);
  80. }
  81. /* least common ancestor in dom tree */
  82. static uint
  83. lcabid(Fn *fn, uint bid1, uint bid2)
  84. {
  85. Blk *b;
  86. if (bid1 == NOBID)
  87. return bid2;
  88. if (bid2 == NOBID)
  89. return bid1;
  90. b = lca(fn->rpo[bid1], fn->rpo[bid2]);
  91. assert(b);
  92. return b->id;
  93. }
  94. static uint
  95. bestbid(Fn *fn, uint earlybid, uint latebid)
  96. {
  97. Blk *curb, *earlyb, *bestb;
  98. if (latebid == NOBID)
  99. return NOBID; /* unused */
  100. assert(earlybid != NOBID);
  101. earlyb = fn->rpo[earlybid];
  102. bestb = curb = fn->rpo[latebid];
  103. assert(dom(earlyb, curb));
  104. while (curb != earlyb) {
  105. curb = curb->idom;
  106. if (curb->loop < bestb->loop)
  107. bestb = curb;
  108. }
  109. return bestb->id;
  110. }
  111. static uint lateins(Fn *, Blk *, Ins *, Ref r);
  112. static uint latephi(Fn *, Phi *, Ref r);
  113. static uint latejmp(Blk *, Ref r);
  114. /* return lca bid of ref uses */
  115. static uint
  116. schedlate(Fn *fn, Ref r)
  117. {
  118. Tmp *t;
  119. Blk *b;
  120. Use *u;
  121. uint earlybid;
  122. uint latebid;
  123. uint uselatebid;
  124. if (rtype(r) != RTmp)
  125. return NOBID;
  126. t = &fn->tmp[r.val];
  127. if (t->visit)
  128. return t->gcmbid;
  129. t->visit = 1;
  130. earlybid = t->gcmbid;
  131. if (earlybid == NOBID)
  132. return NOBID; /* not used */
  133. /* reuse gcmbid for late bid */
  134. t->gcmbid = t->bid;
  135. latebid = NOBID;
  136. for (u=t->use; u<&t->use[t->nuse]; u++) {
  137. assert(u->bid < fn->nblk);
  138. b = fn->rpo[u->bid];
  139. switch (u->type) {
  140. case UXXX:
  141. die("unreachable");
  142. break;
  143. case UPhi:
  144. uselatebid = latephi(fn, u->u.phi, r);
  145. break;
  146. case UIns:
  147. uselatebid = lateins(fn, b, u->u.ins, r);
  148. break;
  149. case UJmp:
  150. uselatebid = latejmp(b, r);
  151. break;
  152. }
  153. latebid = lcabid(fn, latebid, uselatebid);
  154. }
  155. /* latebid may be NOBID if the temp is used
  156. * in fixed instructions that may be eliminated
  157. * and are themselves unused transitively */
  158. if (t->def && !pinned(t->def))
  159. t->gcmbid = bestbid(fn, earlybid, latebid);
  160. /* else, keep the early one */
  161. /* now, gcmbid is the best bid */
  162. return t->gcmbid;
  163. }
  164. /* returns lca bid of uses or NOBID if
  165. * the definition can be eliminated */
  166. static uint
  167. lateins(Fn *fn, Blk *b, Ins *i, Ref r)
  168. {
  169. uint latebid;
  170. assert(b->ins <= i && i < &b->ins[b->nins]);
  171. assert(req(i->arg[0], r) || req(i->arg[1], r));
  172. latebid = schedlate(fn, i->to);
  173. if (pinned(i)) {
  174. if (latebid == NOBID)
  175. if (canelim(i))
  176. return NOBID;
  177. return b->id;
  178. }
  179. return latebid;
  180. }
  181. static uint
  182. latephi(Fn *fn, Phi *p, Ref r)
  183. {
  184. uint n;
  185. uint latebid;
  186. if (!p->narg)
  187. return NOBID; /* marked as unused */
  188. latebid = NOBID;
  189. for (n = 0; n < p->narg; n++)
  190. if (req(p->arg[n], r))
  191. latebid = lcabid(fn, latebid, p->blk[n]->id);
  192. assert(latebid != NOBID);
  193. return latebid;
  194. }
  195. static uint
  196. latejmp(Blk *b, Ref r)
  197. {
  198. if (req(b->jmp.arg, R))
  199. return NOBID;
  200. else {
  201. assert(req(b->jmp.arg, r));
  202. return b->id;
  203. }
  204. }
  205. static void
  206. lateblk(Fn *fn, uint bid)
  207. {
  208. Blk *b;
  209. Phi **pp;
  210. Ins *i;
  211. b = fn->rpo[bid];
  212. for (pp=&b->phi; *(pp);)
  213. if (schedlate(fn, (*pp)->to) == NOBID) {
  214. (*pp)->narg = 0; /* mark unused */
  215. *pp = (*pp)->link; /* remove phi */
  216. } else
  217. pp = &(*pp)->link;
  218. for (i=b->ins; i<&b->ins[b->nins]; i++)
  219. if (pinned(i))
  220. schedlate(fn, i->to);
  221. }
  222. static void
  223. addgcmins(Fn *fn, Ins *vins, uint nins)
  224. {
  225. Ins *i;
  226. Tmp *t;
  227. Blk *b;
  228. for (i=vins; i<&vins[nins]; i++) {
  229. assert(rtype(i->to) == RTmp);
  230. t = &fn->tmp[i->to.val];
  231. b = fn->rpo[t->gcmbid];
  232. addins(&b->ins, &b->nins, i);
  233. }
  234. }
  235. /* move live instructions to the
  236. * end of their target block; use-
  237. * before-def errors are fixed by
  238. * schedblk */
  239. static void
  240. gcmmove(Fn *fn)
  241. {
  242. Tmp *t;
  243. Ins *vins, *i;
  244. uint nins;
  245. nins = 0;
  246. vins = vnew(nins, sizeof vins[0], PFn);
  247. for (t=fn->tmp; t<&fn->tmp[fn->ntmp]; t++) {
  248. if (t->def == 0)
  249. continue;
  250. if (t->bid == t->gcmbid)
  251. continue;
  252. i = t->def;
  253. if (pinned(i) && !canelim(i))
  254. continue;
  255. assert(rtype(i->to) == RTmp);
  256. assert(t == &fn->tmp[i->to.val]);
  257. if (t->gcmbid != NOBID)
  258. addins(&vins, &nins, i);
  259. *i = (Ins){.op = Onop};
  260. }
  261. addgcmins(fn, vins, nins);
  262. }
  263. /* dfs ordering */
  264. static Ins *
  265. schedins(Fn *fn, Blk *b, Ins *i, Ins **pvins, uint *pnins)
  266. {
  267. Ins *i0, *i1;
  268. Tmp *t;
  269. uint n;
  270. igroup(b, i, &i0, &i1);
  271. for (i=i0; i<i1; i++)
  272. for (n=0; n<2; n++) {
  273. if (rtype(i->arg[n]) != RTmp)
  274. continue;
  275. t = &fn->tmp[i->arg[n].val];
  276. if (t->bid != b->id || !t->def)
  277. continue;
  278. schedins(fn, b, t->def, pvins, pnins);
  279. }
  280. for (i=i0; i<i1; i++) {
  281. addins(pvins, pnins, i);
  282. *i = (Ins){.op = Onop};
  283. }
  284. return i1;
  285. }
  286. /* order ins within a block */
  287. static void
  288. schedblk(Fn *fn)
  289. {
  290. Blk *b;
  291. Ins *i, *vins;
  292. uint nins;
  293. vins = vnew(0, sizeof vins[0], PHeap);
  294. for (b=fn->start; b; b=b->link) {
  295. nins = 0;
  296. for (i=b->ins; i<&b->ins[b->nins];)
  297. i = schedins(fn, b, i, &vins, &nins);
  298. idup(b, vins, nins);
  299. }
  300. vfree(vins);
  301. }
  302. static int
  303. cheap(Ins *i)
  304. {
  305. int x;
  306. if (KBASE(i->cls) != 0)
  307. return 0;
  308. switch (i->op) {
  309. case Oneg:
  310. case Oadd:
  311. case Osub:
  312. case Omul:
  313. case Oand:
  314. case Oor:
  315. case Oxor:
  316. case Osar:
  317. case Oshr:
  318. case Oshl:
  319. return 1;
  320. default:
  321. return iscmp(i->op, &x, &x);
  322. }
  323. }
  324. static void
  325. sinkref(Fn *fn, Blk *b, Ref *pr)
  326. {
  327. Ins i;
  328. Tmp *t;
  329. Ref r;
  330. if (rtype(*pr) != RTmp)
  331. return;
  332. t = &fn->tmp[pr->val];
  333. if (!t->def
  334. || t->bid == b->id
  335. || pinned(t->def)
  336. || !cheap(t->def))
  337. return;
  338. /* sink t->def to b */
  339. i = *t->def;
  340. r = newtmp("snk", t->cls, fn);
  341. t = 0; /* invalidated */
  342. *pr = r;
  343. i.to = r;
  344. fn->tmp[r.val].gcmbid = b->id;
  345. emiti(i);
  346. sinkref(fn, b, &i.arg[0]);
  347. sinkref(fn, b, &i.arg[1]);
  348. }
  349. /* redistribute trivial ops to point of
  350. * use to reduce register pressure
  351. * requires rpo, use; breaks use
  352. */
  353. static void
  354. sink(Fn *fn)
  355. {
  356. Blk *b;
  357. Ins *i;
  358. for (b=fn->start; b; b=b->link) {
  359. for (i=b->ins; i<&b->ins[b->nins]; i++)
  360. if (isload(i->op))
  361. sinkref(fn, b, &i->arg[0]);
  362. else if (isstore(i->op))
  363. sinkref(fn, b, &i->arg[1]);
  364. sinkref(fn, b, &b->jmp.arg);
  365. }
  366. addgcmins(fn, curi, &insb[NIns] - curi);
  367. }
  368. /* requires use dom
  369. * maintains rpo pred dom
  370. * breaks use
  371. */
  372. void
  373. gcm(Fn *fn)
  374. {
  375. Tmp *t;
  376. uint bid;
  377. filldepth(fn);
  378. fillloop(fn);
  379. for (t=fn->tmp; t<&fn->tmp[fn->ntmp]; t++) {
  380. t->visit = 0;
  381. t->gcmbid = NOBID;
  382. }
  383. for (bid=0; bid<fn->nblk; bid++)
  384. earlyblk(fn, bid);
  385. for (bid=0; bid<fn->nblk; bid++)
  386. lateblk(fn, bid);
  387. gcmmove(fn);
  388. filluse(fn);
  389. curi = &insb[NIns];
  390. sink(fn);
  391. filluse(fn);
  392. schedblk(fn);
  393. if (debug['G']) {
  394. fprintf(stderr, "\n> After GCM:\n");
  395. printfn(fn, stderr);
  396. }
  397. }