isel.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. #include "all.h"
  2. enum Imm {
  3. Iother,
  4. Iplo12,
  5. Iphi12,
  6. Iplo24,
  7. Inlo12,
  8. Inhi12,
  9. Inlo24
  10. };
  11. static enum Imm
  12. imm(Con *c, int k, int64_t *pn)
  13. {
  14. int64_t n;
  15. int i;
  16. if (c->type != CBits)
  17. return Iother;
  18. n = c->bits.i;
  19. if (k == Kw)
  20. n = (int32_t)n;
  21. i = Iplo12;
  22. if (n < 0) {
  23. i = Inlo12;
  24. n = -n;
  25. }
  26. *pn = n;
  27. if ((n & 0x000fff) == n)
  28. return i;
  29. if ((n & 0xfff000) == n)
  30. return i + 1;
  31. if ((n & 0xffffff) == n)
  32. return i + 2;
  33. return Iother;
  34. }
  35. int
  36. arm64_logimm(uint64_t x, int k)
  37. {
  38. uint64_t n;
  39. if (k == Kw)
  40. x = (x & 0xffffffff) | x << 32;
  41. if (x & 1)
  42. x = ~x;
  43. if (x == 0)
  44. return 0;
  45. if (x == 0xaaaaaaaaaaaaaaaa)
  46. return 1;
  47. n = x & 0xf;
  48. if (0x1111111111111111 * n == x)
  49. goto Check;
  50. n = x & 0xff;
  51. if (0x0101010101010101 * n == x)
  52. goto Check;
  53. n = x & 0xffff;
  54. if (0x0001000100010001 * n == x)
  55. goto Check;
  56. n = x & 0xffffffff;
  57. if (0x0000000100000001 * n == x)
  58. goto Check;
  59. n = x;
  60. Check:
  61. return (n & (n + (n & -n))) == 0;
  62. }
  63. static void
  64. fixarg(Ref *pr, int k, int phi, Fn *fn)
  65. {
  66. char buf[32];
  67. Con *c, cc;
  68. Ref r0, r1, r2, r3;
  69. int s, n;
  70. r0 = *pr;
  71. switch (rtype(r0)) {
  72. case RCon:
  73. c = &fn->con[r0.val];
  74. if (T.apple
  75. && c->type == CAddr
  76. && c->sym.type == SThr) {
  77. r1 = newtmp("isel", Kl, fn);
  78. *pr = r1;
  79. if (c->bits.i) {
  80. r2 = newtmp("isel", Kl, fn);
  81. cc = (Con){.type = CBits};
  82. cc.bits.i = c->bits.i;
  83. r3 = newcon(&cc, fn);
  84. emit(Oadd, Kl, r1, r2, r3);
  85. r1 = r2;
  86. }
  87. emit(Ocopy, Kl, r1, TMP(R0), R);
  88. r1 = newtmp("isel", Kl, fn);
  89. r2 = newtmp("isel", Kl, fn);
  90. emit(Ocall, 0, R, r1, CALL(33));
  91. emit(Ocopy, Kl, TMP(R0), r2, R);
  92. emit(Oload, Kl, r1, r2, R);
  93. cc = *c;
  94. cc.bits.i = 0;
  95. r3 = newcon(&cc, fn);
  96. emit(Ocopy, Kl, r2, r3, R);
  97. break;
  98. }
  99. if (KBASE(k) == 0 && phi)
  100. return;
  101. r1 = newtmp("isel", k, fn);
  102. if (KBASE(k) == 0) {
  103. emit(Ocopy, k, r1, r0, R);
  104. } else {
  105. n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);
  106. vgrow(&fn->con, ++fn->ncon);
  107. c = &fn->con[fn->ncon-1];
  108. sprintf(buf, "\"%sfp%d\"", T.asloc, n);
  109. *c = (Con){.type = CAddr};
  110. c->sym.id = intern(buf);
  111. r2 = newtmp("isel", Kl, fn);
  112. emit(Oload, k, r1, r2, R);
  113. emit(Ocopy, Kl, r2, CON(c-fn->con), R);
  114. }
  115. *pr = r1;
  116. break;
  117. case RTmp:
  118. s = fn->tmp[r0.val].slot;
  119. if (s == -1)
  120. break;
  121. r1 = newtmp("isel", Kl, fn);
  122. emit(Oaddr, Kl, r1, SLOT(s), R);
  123. *pr = r1;
  124. break;
  125. }
  126. }
  127. static int
  128. selcmp(Ref arg[2], int k, Fn *fn)
  129. {
  130. Ref r, *iarg;
  131. Con *c;
  132. int swap, cmp, fix;
  133. int64_t n;
  134. if (KBASE(k) == 1) {
  135. emit(Oafcmp, k, R, arg[0], arg[1]);
  136. iarg = curi->arg;
  137. fixarg(&iarg[0], k, 0, fn);
  138. fixarg(&iarg[1], k, 0, fn);
  139. return 0;
  140. }
  141. swap = rtype(arg[0]) == RCon;
  142. if (swap) {
  143. r = arg[1];
  144. arg[1] = arg[0];
  145. arg[0] = r;
  146. }
  147. fix = 1;
  148. cmp = Oacmp;
  149. r = arg[1];
  150. if (rtype(r) == RCon) {
  151. c = &fn->con[r.val];
  152. switch (imm(c, k, &n)) {
  153. default:
  154. break;
  155. case Iplo12:
  156. case Iphi12:
  157. fix = 0;
  158. break;
  159. case Inlo12:
  160. case Inhi12:
  161. cmp = Oacmn;
  162. r = getcon(n, fn);
  163. fix = 0;
  164. break;
  165. }
  166. }
  167. emit(cmp, k, R, arg[0], r);
  168. iarg = curi->arg;
  169. fixarg(&iarg[0], k, 0, fn);
  170. if (fix)
  171. fixarg(&iarg[1], k, 0, fn);
  172. return swap;
  173. }
  174. static int
  175. callable(Ref r, Fn *fn)
  176. {
  177. Con *c;
  178. if (rtype(r) == RTmp)
  179. return 1;
  180. if (rtype(r) == RCon) {
  181. c = &fn->con[r.val];
  182. if (c->type == CAddr)
  183. if (c->bits.i == 0)
  184. return 1;
  185. }
  186. return 0;
  187. }
  188. static void
  189. sel(Ins i, Fn *fn)
  190. {
  191. Ref *iarg;
  192. Ins *i0;
  193. int ck, cc;
  194. if (INRANGE(i.op, Oalloc, Oalloc1)) {
  195. i0 = curi - 1;
  196. salloc(i.to, i.arg[0], fn);
  197. fixarg(&i0->arg[0], Kl, 0, fn);
  198. return;
  199. }
  200. if (iscmp(i.op, &ck, &cc)) {
  201. emit(Oflag, i.cls, i.to, R, R);
  202. i0 = curi;
  203. if (selcmp(i.arg, ck, fn))
  204. i0->op += cmpop(cc);
  205. else
  206. i0->op += cc;
  207. return;
  208. }
  209. if (i.op == Ocall)
  210. if (callable(i.arg[0], fn)) {
  211. emiti(i);
  212. return;
  213. }
  214. if (i.op != Onop) {
  215. emiti(i);
  216. iarg = curi->arg; /* fixarg() can change curi */
  217. fixarg(&iarg[0], argcls(&i, 0), 0, fn);
  218. fixarg(&iarg[1], argcls(&i, 1), 0, fn);
  219. }
  220. }
  221. static void
  222. seljmp(Blk *b, Fn *fn)
  223. {
  224. Ref r;
  225. Ins *i, *ir;
  226. int ck, cc, use;
  227. if (b->jmp.type == Jret0
  228. || b->jmp.type == Jjmp
  229. || b->jmp.type == Jhlt)
  230. return;
  231. assert(b->jmp.type == Jjnz);
  232. r = b->jmp.arg;
  233. use = -1;
  234. b->jmp.arg = R;
  235. ir = 0;
  236. i = &b->ins[b->nins];
  237. while (i > b->ins)
  238. if (req((--i)->to, r)) {
  239. use = fn->tmp[r.val].nuse;
  240. ir = i;
  241. break;
  242. }
  243. if (ir && use == 1
  244. && iscmp(ir->op, &ck, &cc)) {
  245. if (selcmp(ir->arg, ck, fn))
  246. cc = cmpop(cc);
  247. b->jmp.type = Jjf + cc;
  248. *ir = (Ins){.op = Onop};
  249. }
  250. else {
  251. selcmp((Ref[]){r, CON_Z}, Kw, fn);
  252. b->jmp.type = Jjfine;
  253. }
  254. }
  255. void
  256. arm64_isel(Fn *fn)
  257. {
  258. Blk *b, **sb;
  259. Ins *i;
  260. Phi *p;
  261. uint n, al;
  262. int64_t sz;
  263. /* assign slots to fast allocs */
  264. b = fn->start;
  265. /* specific to NAlign == 3 */ /* or change n=4 and sz /= 4 below */
  266. for (al=Oalloc, n=4; al<=Oalloc1; al++, n*=2)
  267. for (i=b->ins; i<&b->ins[b->nins]; i++)
  268. if (i->op == al) {
  269. if (rtype(i->arg[0]) != RCon)
  270. break;
  271. sz = fn->con[i->arg[0].val].bits.i;
  272. if (sz < 0 || sz >= INT_MAX-15)
  273. err("invalid alloc size %"PRId64, sz);
  274. sz = (sz + n-1) & -n;
  275. sz /= 4;
  276. fn->tmp[i->to.val].slot = fn->slot;
  277. fn->slot += sz;
  278. *i = (Ins){.op = Onop};
  279. }
  280. for (b=fn->start; b; b=b->link) {
  281. curi = &insb[NIns];
  282. for (sb=(Blk*[3]){b->s1, b->s2, 0}; *sb; sb++)
  283. for (p=(*sb)->phi; p; p=p->link) {
  284. for (n=0; p->blk[n] != b; n++)
  285. assert(n+1 < p->narg);
  286. fixarg(&p->arg[n], p->cls, 1, fn);
  287. }
  288. seljmp(b, fn);
  289. for (i=&b->ins[b->nins]; i!=b->ins;)
  290. sel(*--i, fn);
  291. b->nins = &insb[NIns] - curi;
  292. idup(&b->ins, curi, b->nins);
  293. }
  294. if (debug['I']) {
  295. fprintf(stderr, "\n> After instruction selection:\n");
  296. printfn(fn, stderr);
  297. }
  298. }