copy.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include "all.h"
  2. static int
  3. iscon(Ref r, int64_t bits, Fn *fn)
  4. {
  5. return rtype(r) == RCon
  6. && fn->con[r.val].type == CBits
  7. && fn->con[r.val].bits.i == bits;
  8. }
  9. static int
  10. iscopy(Ins *i, Ref r, Fn *fn)
  11. {
  12. static bits extcpy[] = {
  13. [WFull] = 0,
  14. [Wsb] = BIT(Wsb) | BIT(Wsh) | BIT(Wsw),
  15. [Wub] = BIT(Wub) | BIT(Wuh) | BIT(Wuw),
  16. [Wsh] = BIT(Wsh) | BIT(Wsw),
  17. [Wuh] = BIT(Wuh) | BIT(Wuw),
  18. [Wsw] = BIT(Wsw),
  19. [Wuw] = BIT(Wuw),
  20. };
  21. Op *op;
  22. bits b;
  23. Tmp *t;
  24. if (i->op == Ocopy)
  25. return 1;
  26. op = &optab[i->op];
  27. if (op->hasid && KBASE(i->cls) == 0)
  28. return iscon(i->arg[1], op->idval, fn);
  29. if (!isext(i->op) || rtype(r) != RTmp)
  30. return 0;
  31. if (i->op == Oextsw || i->op == Oextuw)
  32. if (i->cls == Kw)
  33. return 1;
  34. t = &fn->tmp[r.val];
  35. assert(KBASE(t->cls) == 0);
  36. if (i->cls == Kl && t->cls == Kw)
  37. return 0;
  38. b = extcpy[t->width];
  39. return (BIT(Wsb + (i->op-Oextsb)) & b) != 0;
  40. }
  41. static Ref
  42. copyof(Ref r, Ref *cpy)
  43. {
  44. if (rtype(r) == RTmp && !req(cpy[r.val], R))
  45. return cpy[r.val];
  46. return r;
  47. }
  48. /* detects a cluster of phis/copies redundant with 'r';
  49. * the algorithm is inspired by Section 3.2 of "Simple
  50. * and Efficient SSA Construction" by Braun M. et al.
  51. */
  52. static void
  53. phisimpl(Phi *p, Ref r, Ref *cpy, Use ***pstk, BSet *ts, BSet *as, Fn *fn)
  54. {
  55. Use **stk, *u, *u1;
  56. uint nstk, a;
  57. int t;
  58. Ref r1;
  59. Phi *p0;
  60. bszero(ts);
  61. bszero(as);
  62. p0 = &(Phi){.narg = 0};
  63. stk = *pstk;
  64. nstk = 1;
  65. stk[0] = &(Use){.type = UPhi, .u.phi = p};
  66. while (nstk) {
  67. u = stk[--nstk];
  68. if (u->type == UIns && iscopy(u->u.ins, r, fn)) {
  69. p = p0;
  70. t = u->u.ins->to.val;
  71. }
  72. else if (u->type == UPhi) {
  73. p = u->u.phi;
  74. t = p->to.val;
  75. }
  76. else
  77. continue;
  78. if (bshas(ts, t))
  79. continue;
  80. bsset(ts, t);
  81. for (a=0; a<p->narg; a++) {
  82. r1 = copyof(p->arg[a], cpy);
  83. if (req(r1, r))
  84. continue;
  85. if (rtype(r1) != RTmp)
  86. return;
  87. bsset(as, r1.val);
  88. }
  89. u = fn->tmp[t].use;
  90. u1 = &u[fn->tmp[t].nuse];
  91. vgrow(pstk, nstk+(u1-u));
  92. stk = *pstk;
  93. for (; u<u1; u++)
  94. stk[nstk++] = u;
  95. }
  96. bsdiff(as, ts);
  97. if (!bscount(as))
  98. for (t=0; bsiter(ts, &t); t++)
  99. cpy[t] = r;
  100. }
  101. static void
  102. subst(Ref *pr, Ref *cpy)
  103. {
  104. assert(rtype(*pr) != RTmp || !req(cpy[pr->val], R));
  105. *pr = copyof(*pr, cpy);
  106. }
  107. /* requires use and dom, breaks use */
  108. void
  109. copy(Fn *fn)
  110. {
  111. BSet ts[1], as[1];
  112. Use **stk;
  113. Phi *p, **pp;
  114. Ins *i;
  115. Blk *b;
  116. uint n, a, eq;
  117. Ref *cpy, r, r1;
  118. int t;
  119. bsinit(ts, fn->ntmp);
  120. bsinit(as, fn->ntmp);
  121. cpy = emalloc(fn->ntmp * sizeof cpy[0]);
  122. stk = vnew(10, sizeof stk[0], PHeap);
  123. /* 1. build the copy-of map */
  124. for (n=0; n<fn->nblk; n++) {
  125. b = fn->rpo[n];
  126. for (p=b->phi; p; p=p->link) {
  127. assert(rtype(p->to) == RTmp);
  128. if (!req(cpy[p->to.val], R))
  129. continue;
  130. eq = 0;
  131. r = R;
  132. for (a=0; a<p->narg; a++)
  133. if (p->blk[a]->id < n) {
  134. r1 = copyof(p->arg[a], cpy);
  135. if (req(r, R) || req(r, UNDEF))
  136. r = r1;
  137. if (req(r1, r) || req(r1, UNDEF))
  138. eq++;
  139. }
  140. assert(!req(r, R));
  141. if (rtype(r) == RTmp
  142. && !dom(fn->rpo[fn->tmp[r.val].bid], b))
  143. cpy[p->to.val] = p->to;
  144. else if (eq == p->narg)
  145. cpy[p->to.val] = r;
  146. else {
  147. cpy[p->to.val] = p->to;
  148. phisimpl(p, r, cpy, &stk, ts, as, fn);
  149. }
  150. }
  151. for (i=b->ins; i<&b->ins[b->nins]; i++) {
  152. assert(rtype(i->to) <= RTmp);
  153. if (!req(cpy[i->to.val], R))
  154. continue;
  155. r = copyof(i->arg[0], cpy);
  156. if (iscopy(i, r, fn))
  157. cpy[i->to.val] = r;
  158. else
  159. cpy[i->to.val] = i->to;
  160. }
  161. }
  162. /* 2. remove redundant phis/copies
  163. * and rewrite their uses */
  164. for (b=fn->start; b; b=b->link) {
  165. for (pp=&b->phi; (p=*pp);) {
  166. r = cpy[p->to.val];
  167. if (!req(r, p->to)) {
  168. *pp = p->link;
  169. continue;
  170. }
  171. for (a=0; a<p->narg; a++)
  172. subst(&p->arg[a], cpy);
  173. pp=&p->link;
  174. }
  175. for (i=b->ins; i<&b->ins[b->nins]; i++) {
  176. r = cpy[i->to.val];
  177. if (!req(r, i->to)) {
  178. *i = (Ins){.op = Onop};
  179. continue;
  180. }
  181. subst(&i->arg[0], cpy);
  182. subst(&i->arg[1], cpy);
  183. }
  184. subst(&b->jmp.arg, cpy);
  185. }
  186. if (debug['C']) {
  187. fprintf(stderr, "\n> Copy information:");
  188. for (t=Tmp0; t<fn->ntmp; t++) {
  189. if (req(cpy[t], R)) {
  190. fprintf(stderr, "\n%10s not seen!",
  191. fn->tmp[t].name);
  192. }
  193. else if (!req(cpy[t], TMP(t))) {
  194. fprintf(stderr, "\n%10s copy of ",
  195. fn->tmp[t].name);
  196. printref(cpy[t], fn, stderr);
  197. }
  198. }
  199. fprintf(stderr, "\n\n> After copy elimination:\n");
  200. printfn(fn, stderr);
  201. }
  202. vfree(stk);
  203. free(cpy);
  204. }