copy.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #include "all.h"
  2. typedef struct Ext Ext;
  3. struct Ext {
  4. char zext;
  5. char nopw; /* is a no-op if arg width is <= nopw */
  6. char usew; /* uses only the low usew bits of arg */
  7. };
  8. static int
  9. ext(Ins *i, Ext *e)
  10. {
  11. static Ext tbl[] = {
  12. /*extsb*/ {0, 7, 8},
  13. /*extub*/ {1, 8, 8},
  14. /*extsh*/ {0, 15, 16},
  15. /*extuh*/ {1, 16, 16},
  16. /*extsw*/ {0, 31, 32},
  17. /*extuw*/ {1, 32, 32},
  18. };
  19. if (!isext(i->op))
  20. return 0;
  21. *e = tbl[i->op - Oextsb];
  22. return 1;
  23. }
  24. static int
  25. bitwidth(uint64_t v)
  26. {
  27. int n;
  28. n = 0;
  29. if (v >> 32) { n += 32; v >>= 32; }
  30. if (v >> 16) { n += 16; v >>= 16; }
  31. if (v >> 8) { n += 8; v >>= 8; }
  32. if (v >> 4) { n += 4; v >>= 4; }
  33. if (v >> 2) { n += 2; v >>= 2; }
  34. if (v >> 1) { n += 1; v >>= 1; }
  35. return n+v;
  36. }
  37. /* no more than w bits are used */
  38. static int
  39. usewidthle(Fn *fn, Ref r, int w)
  40. {
  41. Ext e;
  42. Tmp *t;
  43. Use *u;
  44. Phi *p;
  45. Ins *i;
  46. Ref rc;
  47. int64_t v;
  48. int b;
  49. assert(rtype(r) == RTmp);
  50. t = &fn->tmp[r.val];
  51. for (u=t->use; u<&t->use[t->nuse]; u++) {
  52. switch (u->type) {
  53. case UPhi:
  54. p = u->u.phi;
  55. if (p->visit)
  56. continue;
  57. p->visit = 1;
  58. b = usewidthle(fn, p->to, w);
  59. p->visit = 0;
  60. if (b)
  61. continue;
  62. break;
  63. case UIns:
  64. i = u->u.ins;
  65. assert(i != 0);
  66. if (i->op == Ocopy)
  67. if (usewidthle(fn, i->to, w))
  68. continue;
  69. if (ext(i, &e)) {
  70. if (e.usew <= w)
  71. continue;
  72. if (usewidthle(fn, i->to, w))
  73. continue;
  74. }
  75. if (i->op == Oand) {
  76. if (req(r, i->arg[0]))
  77. rc = i->arg[1];
  78. else {
  79. assert(req(r, i->arg[1]));
  80. rc = i->arg[0];
  81. }
  82. if (isconbits(fn, rc, &v)
  83. && bitwidth(v) <= w)
  84. continue;
  85. break;
  86. }
  87. break;
  88. default:
  89. break;
  90. }
  91. return 0;
  92. }
  93. return 1;
  94. }
  95. static int
  96. min(int v1, int v2)
  97. {
  98. return v1 < v2 ? v1 : v2;
  99. }
  100. /* is the ref narrower than w bits */
  101. static int
  102. defwidthle(Fn *fn, Ref r, int w)
  103. {
  104. Ext e;
  105. Tmp *t;
  106. Phi *p;
  107. Ins *i;
  108. uint n;
  109. int64_t v;
  110. int x;
  111. if (isconbits(fn, r, &v)
  112. && bitwidth(v) <= w)
  113. return 1;
  114. if (rtype(r) != RTmp)
  115. return 0;
  116. t = &fn->tmp[r.val];
  117. if (t->cls != Kw)
  118. return 0;
  119. if (!t->def) {
  120. /* phi def */
  121. for (p=fn->rpo[t->bid]->phi; p; p=p->link)
  122. if (req(p->to, r))
  123. break;
  124. assert(p);
  125. if (p->visit)
  126. return 1;
  127. p->visit = 1;
  128. for (n=0; n<p->narg; n++)
  129. if (!defwidthle(fn, p->arg[n], w)) {
  130. p->visit = 0;
  131. return 0;
  132. }
  133. p->visit = 0;
  134. return 1;
  135. }
  136. i = t->def;
  137. if (i->op == Ocopy)
  138. return defwidthle(fn, i->arg[0], w);
  139. if (i->op == Oshr || i->op == Osar) {
  140. if (isconbits(fn, i->arg[1], &v))
  141. if (0 < v && v <= 32) {
  142. if (i->op == Oshr && w+v >= 32)
  143. return 1;
  144. if (w < 32) {
  145. if (i->op == Osar)
  146. w = min(31, w+v);
  147. else
  148. w = min(32, w+v);
  149. }
  150. }
  151. return defwidthle(fn, i->arg[0], w);
  152. }
  153. if (iscmp(i->op, &x, &x))
  154. return w >= 1;
  155. if (i->op == Oand) {
  156. if (defwidthle(fn, i->arg[0], w)
  157. || defwidthle(fn, i->arg[1], w))
  158. return 1;
  159. return 0;
  160. }
  161. if (i->op == Oor || i->op == Oxor) {
  162. if (defwidthle(fn, i->arg[0], w)
  163. && defwidthle(fn, i->arg[1], w))
  164. return 1;
  165. return 0;
  166. }
  167. if (ext(i, &e)) {
  168. if (e.zext && e.usew <= w)
  169. return 1;
  170. w = min(w, e.nopw);
  171. return defwidthle(fn, i->arg[0], w);
  172. }
  173. return 0;
  174. }
  175. static int
  176. isw1(Fn *fn, Ref r)
  177. {
  178. return defwidthle(fn, r, 1);
  179. }
  180. /* insert early extub/extuh instructions
  181. * for pars used only narrowly; this
  182. * helps factoring extensions out of
  183. * loops
  184. *
  185. * needs use; breaks use
  186. */
  187. void
  188. narrowpars(Fn *fn)
  189. {
  190. Blk *b;
  191. int loop;
  192. Ins ext, *i, *ins;
  193. uint npar, nins;
  194. Ref r;
  195. /* only useful for functions with loops */
  196. loop = 0;
  197. for (b=fn->start; b; b=b->link)
  198. if (b->loop > 1) {
  199. loop = 1;
  200. break;
  201. }
  202. if (!loop)
  203. return;
  204. b = fn->start;
  205. npar = 0;
  206. for (i=b->ins; i<&b->ins[b->nins]; i++) {
  207. if (!ispar(i->op))
  208. break;
  209. npar++;
  210. }
  211. if (npar == 0)
  212. return;
  213. nins = b->nins + npar;
  214. ins = vnew(nins, sizeof ins[0], PFn);
  215. icpy(ins, b->ins, npar);
  216. icpy(ins + 2*npar, b->ins+npar, b->nins-npar);
  217. b->ins = ins;
  218. b->nins = nins;
  219. for (i=b->ins; i<&b->ins[b->nins]; i++) {
  220. if (!ispar(i->op))
  221. break;
  222. ext = (Ins){.op = Onop};
  223. if (i->cls == Kw)
  224. if (usewidthle(fn, i->to, 16)) {
  225. ext.op = Oextuh;
  226. if (usewidthle(fn, i->to, 8))
  227. ext.op = Oextub;
  228. r = newtmp("vw", i->cls, fn);
  229. ext.cls = i->cls;
  230. ext.to = i->to;
  231. ext.arg[0] = r;
  232. i->to = r;
  233. }
  234. *(i+npar) = ext;
  235. }
  236. }
  237. Ref
  238. copyref(Fn *fn, Blk *b, Ins *i)
  239. {
  240. /* which extensions are copies for a given
  241. * argument width */
  242. static bits extcpy[] = {
  243. [WFull] = 0,
  244. [Wsb] = BIT(Wsb) | BIT(Wsh) | BIT(Wsw),
  245. [Wub] = BIT(Wub) | BIT(Wuh) | BIT(Wuw),
  246. [Wsh] = BIT(Wsh) | BIT(Wsw),
  247. [Wuh] = BIT(Wuh) | BIT(Wuw),
  248. [Wsw] = BIT(Wsw),
  249. [Wuw] = BIT(Wuw),
  250. };
  251. Ext e;
  252. Tmp *t;
  253. int64_t v;
  254. int w, z;
  255. if (i->op == Ocopy)
  256. return i->arg[0];
  257. /* op identity value */
  258. if (optab[i->op].hasid
  259. && KBASE(i->cls) == 0 /* integer only - fp NaN! */
  260. && req(i->arg[1], con01[optab[i->op].idval])
  261. && (!optab[i->op].cmpeqwl || isw1(fn, i->arg[0])))
  262. return i->arg[0];
  263. /* idempotent op with identical args */
  264. if (optab[i->op].idemp
  265. && req(i->arg[0], i->arg[1]))
  266. return i->arg[0];
  267. /* integer cmp with identical args */
  268. if ((optab[i->op].cmpeqwl || optab[i->op].cmplgtewl)
  269. && req(i->arg[0], i->arg[1]))
  270. return con01[optab[i->op].eqval];
  271. /* cmpeq/ne 0 with 0/non-0 inference */
  272. if (optab[i->op].cmpeqwl
  273. && req(i->arg[1], CON_Z)
  274. && zeroval(fn, b, i->arg[0], argcls(i, 0), &z))
  275. return con01[optab[i->op].eqval^z^1];
  276. /* redundant and mask */
  277. if (i->op == Oand
  278. && isconbits(fn, i->arg[1], &v)
  279. && (v > 0 && ((v+1) & v) == 0)
  280. && defwidthle(fn, i->arg[0], bitwidth(v)))
  281. return i->arg[0];
  282. if (i->cls == Kw
  283. && (i->op == Oextsw || i->op == Oextuw))
  284. return i->arg[0];
  285. if (ext(i, &e) && rtype(i->arg[0]) == RTmp) {
  286. t = &fn->tmp[i->arg[0].val];
  287. assert(KBASE(t->cls) == 0);
  288. /* do not break typing by returning
  289. * a narrower temp */
  290. if (KWIDE(i->cls) > KWIDE(t->cls))
  291. return R;
  292. w = Wsb + (i->op - Oextsb);
  293. if (BIT(w) & extcpy[t->width])
  294. return i->arg[0];
  295. /* avoid eliding extensions of params
  296. * inserted in the start block; their
  297. * point is to make further extensions
  298. * redundant */
  299. if ((!t->def || !ispar(t->def->op))
  300. && usewidthle(fn, i->to, e.usew))
  301. return i->arg[0];
  302. if (defwidthle(fn, i->arg[0], e.nopw))
  303. return i->arg[0];
  304. }
  305. return R;
  306. }
  307. static int
  308. phieq(Phi *pa, Phi *pb)
  309. {
  310. Ref r;
  311. uint n;
  312. assert(pa->narg == pb->narg);
  313. for (n=0; n<pa->narg; n++) {
  314. r = phiarg(pb, pa->blk[n]);
  315. if (!req(pa->arg[n], r))
  316. return 0;
  317. }
  318. return 1;
  319. }
  320. Ref
  321. phicopyref(Fn *fn, Blk *b, Phi *p)
  322. {
  323. Blk *d, **s;
  324. Phi *p1;
  325. uint n, c;
  326. /* identical args */
  327. for (n=0; n<p->narg-1; n++)
  328. if (!req(p->arg[n], p->arg[n+1]))
  329. break;
  330. if (n == p->narg-1)
  331. return p->arg[n];
  332. /* same as a previous phi */
  333. for (p1=b->phi; p1!=p; p1=p1->link) {
  334. assert(p1);
  335. if (phieq(p1, p))
  336. return p1->to;
  337. }
  338. /* can be replaced by a
  339. * dominating jnz arg */
  340. d = b->idom;
  341. if (p->narg != 2
  342. || d->jmp.type != Jjnz
  343. || !isw1(fn, d->jmp.arg))
  344. return R;
  345. s = (Blk*[]){0, 0};
  346. for (n=0; n<2; n++)
  347. for (c=0; c<2; c++)
  348. if (req(p->arg[n], con01[c]))
  349. s[c] = p->blk[n];
  350. /* if s1 ends with a jnz on either b
  351. * or s2; the inference below is wrong
  352. * without the jump type checks */
  353. if (d->s1 == s[1] && d->s2 == s[0]
  354. && d->s1->jmp.type == Jjmp
  355. && d->s2->jmp.type == Jjmp)
  356. return d->jmp.arg;
  357. return R;
  358. }