rega.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. #include "all.h"
  2. #ifdef TEST_PMOV
  3. #undef assert
  4. #define assert(x) assert_test(#x, x)
  5. #endif
  6. typedef struct RMap RMap;
  7. struct RMap {
  8. int t[Tmp0];
  9. int r[Tmp0];
  10. int w[Tmp0]; /* wait list, for unmatched hints */
  11. BSet b[1];
  12. int n;
  13. };
  14. static bits regu; /* registers used */
  15. static Tmp *tmp; /* function temporaries */
  16. static Mem *mem; /* function mem references */
  17. static struct {
  18. Ref src, dst;
  19. int cls;
  20. } pm[Tmp0]; /* parallel move constructed */
  21. static int npm; /* size of pm */
  22. static int loop; /* current loop level */
  23. static uint stmov; /* stats: added moves */
  24. static uint stblk; /* stats: added blocks */
  25. static int *
  26. hint(int t)
  27. {
  28. return &tmp[phicls(t, tmp)].hint.r;
  29. }
  30. static void
  31. sethint(int t, int r)
  32. {
  33. Tmp *p;
  34. p = &tmp[phicls(t, tmp)];
  35. if (p->hint.r == -1 || p->hint.w > loop) {
  36. p->hint.r = r;
  37. p->hint.w = loop;
  38. tmp[t].visit = -1;
  39. }
  40. }
  41. static void
  42. rcopy(RMap *ma, RMap *mb)
  43. {
  44. memcpy(ma->t, mb->t, sizeof ma->t);
  45. memcpy(ma->r, mb->r, sizeof ma->r);
  46. memcpy(ma->w, mb->w, sizeof ma->w);
  47. bscopy(ma->b, mb->b);
  48. ma->n = mb->n;
  49. }
  50. static int
  51. rfind(RMap *m, int t)
  52. {
  53. int i;
  54. for (i=0; i<m->n; i++)
  55. if (m->t[i] == t)
  56. return m->r[i];
  57. return -1;
  58. }
  59. static Ref
  60. rref(RMap *m, int t)
  61. {
  62. int r, s;
  63. r = rfind(m, t);
  64. if (r == -1) {
  65. s = tmp[t].slot;
  66. assert(s != -1 && "should have spilled");
  67. return SLOT(s);
  68. } else
  69. return TMP(r);
  70. }
  71. static void
  72. radd(RMap *m, int t, int r)
  73. {
  74. assert((t >= Tmp0 || t == r) && "invalid temporary");
  75. assert(((T.gpr0 <= r && r < T.gpr0 + T.ngpr)
  76. || (T.fpr0 <= r && r < T.fpr0 + T.nfpr))
  77. && "invalid register");
  78. assert(!bshas(m->b, t) && "temporary has mapping");
  79. assert(!bshas(m->b, r) && "register already allocated");
  80. assert(m->n <= T.ngpr+T.nfpr && "too many mappings");
  81. bsset(m->b, t);
  82. bsset(m->b, r);
  83. m->t[m->n] = t;
  84. m->r[m->n] = r;
  85. m->n++;
  86. regu |= BIT(r);
  87. }
  88. static Ref
  89. ralloctry(RMap *m, int t, int try)
  90. {
  91. bits regs;
  92. int h, r, r0, r1;
  93. if (t < Tmp0) {
  94. assert(bshas(m->b, t));
  95. return TMP(t);
  96. }
  97. if (bshas(m->b, t)) {
  98. r = rfind(m, t);
  99. assert(r != -1);
  100. return TMP(r);
  101. }
  102. r = tmp[t].visit;
  103. if (r == -1 || bshas(m->b, r))
  104. r = *hint(t);
  105. if (r == -1 || bshas(m->b, r)) {
  106. if (try)
  107. return R;
  108. regs = tmp[phicls(t, tmp)].hint.m;
  109. regs |= m->b->t[0];
  110. if (KBASE(tmp[t].cls) == 0) {
  111. r0 = T.gpr0;
  112. r1 = r0 + T.ngpr;
  113. } else {
  114. r0 = T.fpr0;
  115. r1 = r0 + T.nfpr;
  116. }
  117. for (r=r0; r<r1; r++)
  118. if (!(regs & BIT(r)))
  119. goto Found;
  120. for (r=r0; r<r1; r++)
  121. if (!bshas(m->b, r))
  122. goto Found;
  123. die("no more regs");
  124. }
  125. Found:
  126. radd(m, t, r);
  127. sethint(t, r);
  128. tmp[t].visit = r;
  129. h = *hint(t);
  130. if (h != -1 && h != r)
  131. m->w[h] = t;
  132. return TMP(r);
  133. }
  134. static inline Ref
  135. ralloc(RMap *m, int t)
  136. {
  137. return ralloctry(m, t, 0);
  138. }
  139. static int
  140. rfree(RMap *m, int t)
  141. {
  142. int i, r;
  143. assert(t >= Tmp0 || !(BIT(t) & T.rglob));
  144. if (!bshas(m->b, t))
  145. return -1;
  146. for (i=0; m->t[i] != t; i++)
  147. assert(i+1 < m->n);
  148. r = m->r[i];
  149. bsclr(m->b, t);
  150. bsclr(m->b, r);
  151. m->n--;
  152. memmove(&m->t[i], &m->t[i+1], (m->n-i) * sizeof m->t[0]);
  153. memmove(&m->r[i], &m->r[i+1], (m->n-i) * sizeof m->r[0]);
  154. assert(t >= Tmp0 || t == r);
  155. return r;
  156. }
  157. static void
  158. mdump(RMap *m)
  159. {
  160. int i;
  161. for (i=0; i<m->n; i++)
  162. if (m->t[i] >= Tmp0)
  163. fprintf(stderr, " (%s, R%d)",
  164. tmp[m->t[i]].name,
  165. m->r[i]);
  166. fprintf(stderr, "\n");
  167. }
  168. static void
  169. pmadd(Ref src, Ref dst, int k)
  170. {
  171. if (npm == Tmp0)
  172. die("cannot have more moves than registers");
  173. pm[npm].src = src;
  174. pm[npm].dst = dst;
  175. pm[npm].cls = k;
  176. npm++;
  177. }
  178. enum PMStat { ToMove, Moving, Moved };
  179. static int
  180. pmrec(enum PMStat *status, int i, int *k)
  181. {
  182. int j, c;
  183. /* note, this routine might emit
  184. * too many large instructions
  185. */
  186. if (req(pm[i].src, pm[i].dst)) {
  187. status[i] = Moved;
  188. return -1;
  189. }
  190. assert(KBASE(pm[i].cls) == KBASE(*k));
  191. assert((Kw|Kl) == Kl && (Ks|Kd) == Kd);
  192. *k |= pm[i].cls;
  193. for (j=0; j<npm; j++)
  194. if (req(pm[j].dst, pm[i].src))
  195. break;
  196. switch (j == npm ? Moved : status[j]) {
  197. case Moving:
  198. c = j; /* start of cycle */
  199. emit(Oswap, *k, R, pm[i].src, pm[i].dst);
  200. break;
  201. case ToMove:
  202. status[i] = Moving;
  203. c = pmrec(status, j, k);
  204. if (c == i) {
  205. c = -1; /* end of cycle */
  206. break;
  207. }
  208. if (c != -1) {
  209. emit(Oswap, *k, R, pm[i].src, pm[i].dst);
  210. break;
  211. }
  212. /* fall through */
  213. case Moved:
  214. c = -1;
  215. emit(Ocopy, pm[i].cls, pm[i].dst, pm[i].src, R);
  216. break;
  217. default:
  218. die("unreachable");
  219. }
  220. status[i] = Moved;
  221. return c;
  222. }
  223. static void
  224. pmgen()
  225. {
  226. int i;
  227. enum PMStat *status;
  228. status = alloc(npm * sizeof status[0]);
  229. assert(!npm || status[npm-1] == ToMove);
  230. for (i=0; i<npm; i++)
  231. if (status[i] == ToMove)
  232. pmrec(status, i, (int[]){pm[i].cls});
  233. }
  234. static void
  235. move(int r, Ref to, RMap *m)
  236. {
  237. int n, t, r1;
  238. r1 = req(to, R) ? -1 : rfree(m, to.val);
  239. if (bshas(m->b, r)) {
  240. /* r is used and not by to */
  241. assert(r1 != r);
  242. for (n=0; m->r[n] != r; n++)
  243. assert(n+1 < m->n);
  244. t = m->t[n];
  245. rfree(m, t);
  246. bsset(m->b, r);
  247. ralloc(m, t);
  248. bsclr(m->b, r);
  249. }
  250. t = req(to, R) ? r : to.val;
  251. radd(m, t, r);
  252. }
  253. static int
  254. regcpy(Ins *i)
  255. {
  256. return i->op == Ocopy && isreg(i->arg[0]);
  257. }
  258. static Ins *
  259. dopm(Blk *b, Ins *i, RMap *m)
  260. {
  261. RMap m0;
  262. int n, r, r1, t, s;
  263. Ins *i1, *ip;
  264. bits def;
  265. m0 = *m; /* okay since we don't use m0.b */
  266. m0.b->t = 0;
  267. i1 = ++i;
  268. do {
  269. i--;
  270. move(i->arg[0].val, i->to, m);
  271. } while (i != b->ins && regcpy(i-1));
  272. assert(m0.n <= m->n);
  273. if (i != b->ins && (i-1)->op == Ocall) {
  274. def = T.retregs((i-1)->arg[1], 0) | T.rglob;
  275. for (r=0; T.rsave[r]>=0; r++)
  276. if (!(BIT(T.rsave[r]) & def))
  277. move(T.rsave[r], R, m);
  278. }
  279. for (npm=0, n=0; n<m->n; n++) {
  280. t = m->t[n];
  281. s = tmp[t].slot;
  282. r1 = m->r[n];
  283. r = rfind(&m0, t);
  284. if (r != -1)
  285. pmadd(TMP(r1), TMP(r), tmp[t].cls);
  286. else if (s != -1)
  287. pmadd(TMP(r1), SLOT(s), tmp[t].cls);
  288. }
  289. for (ip=i; ip<i1; ip++) {
  290. if (!req(ip->to, R))
  291. rfree(m, ip->to.val);
  292. r = ip->arg[0].val;
  293. if (rfind(m, r) == -1)
  294. radd(m, r, r);
  295. }
  296. pmgen();
  297. return i;
  298. }
  299. static int
  300. prio1(Ref r1, Ref r2)
  301. {
  302. /* trivial heuristic to begin with,
  303. * later we can use the distance to
  304. * the definition instruction
  305. */
  306. (void) r2;
  307. return *hint(r1.val) != -1;
  308. }
  309. static void
  310. insert(Ref *r, Ref **rs, int p)
  311. {
  312. int i;
  313. rs[i = p] = r;
  314. while (i-- > 0 && prio1(*r, *rs[i])) {
  315. rs[i+1] = rs[i];
  316. rs[i] = r;
  317. }
  318. }
  319. static void
  320. doblk(Blk *b, RMap *cur)
  321. {
  322. int t, x, r, rf, rt, nr;
  323. bits rs;
  324. Ins *i, *i1;
  325. Mem *m;
  326. Ref *ra[4];
  327. if (rtype(b->jmp.arg) == RTmp)
  328. b->jmp.arg = ralloc(cur, b->jmp.arg.val);
  329. curi = &insb[NIns];
  330. for (i1=&b->ins[b->nins]; i1!=b->ins;) {
  331. emiti(*--i1);
  332. i = curi;
  333. rf = -1;
  334. switch (i->op) {
  335. case Ocall:
  336. rs = T.argregs(i->arg[1], 0) | T.rglob;
  337. for (r=0; T.rsave[r]>=0; r++)
  338. if (!(BIT(T.rsave[r]) & rs))
  339. rfree(cur, T.rsave[r]);
  340. break;
  341. case Ocopy:
  342. if (regcpy(i)) {
  343. curi++;
  344. i1 = dopm(b, i1, cur);
  345. stmov += i+1 - curi;
  346. continue;
  347. }
  348. if (isreg(i->to))
  349. if (rtype(i->arg[0]) == RTmp)
  350. sethint(i->arg[0].val, i->to.val);
  351. /* fall through */
  352. default:
  353. if (!req(i->to, R)) {
  354. assert(rtype(i->to) == RTmp);
  355. r = i->to.val;
  356. if (r < Tmp0 && (BIT(r) & T.rglob))
  357. break;
  358. rf = rfree(cur, r);
  359. if (rf == -1) {
  360. assert(!isreg(i->to));
  361. curi++;
  362. continue;
  363. }
  364. i->to = TMP(rf);
  365. }
  366. break;
  367. }
  368. for (x=0, nr=0; x<2; x++)
  369. switch (rtype(i->arg[x])) {
  370. case RMem:
  371. m = &mem[i->arg[x].val];
  372. if (rtype(m->base) == RTmp)
  373. insert(&m->base, ra, nr++);
  374. if (rtype(m->index) == RTmp)
  375. insert(&m->index, ra, nr++);
  376. break;
  377. case RTmp:
  378. insert(&i->arg[x], ra, nr++);
  379. break;
  380. }
  381. for (r=0; r<nr; r++)
  382. *ra[r] = ralloc(cur, ra[r]->val);
  383. if (i->op == Ocopy && req(i->to, i->arg[0]))
  384. curi++;
  385. /* try to change the register of a hinted
  386. * temporary if rf is available */
  387. if (rf != -1 && (t = cur->w[rf]) != 0)
  388. if (!bshas(cur->b, rf) && *hint(t) == rf
  389. && (rt = rfree(cur, t)) != -1) {
  390. tmp[t].visit = -1;
  391. ralloc(cur, t);
  392. assert(bshas(cur->b, rf));
  393. emit(Ocopy, tmp[t].cls, TMP(rt), TMP(rf), R);
  394. stmov += 1;
  395. cur->w[rf] = 0;
  396. for (r=0; r<nr; r++)
  397. if (req(*ra[r], TMP(rt)))
  398. *ra[r] = TMP(rf);
  399. /* one could iterate this logic with
  400. * the newly freed rt, but in this case
  401. * the above loop must be changed */
  402. }
  403. }
  404. b->nins = &insb[NIns] - curi;
  405. idup(&b->ins, curi, b->nins);
  406. }
  407. /* qsort() comparison function to peel
  408. * loop nests from inside out */
  409. static int
  410. carve(const void *a, const void *b)
  411. {
  412. Blk *ba, *bb;
  413. /* todo, evaluate if this order is really
  414. * better than the simple postorder */
  415. ba = *(Blk**)a;
  416. bb = *(Blk**)b;
  417. if (ba->loop == bb->loop)
  418. return ba->id > bb->id ? -1 : ba->id < bb->id;
  419. return ba->loop > bb->loop ? -1 : +1;
  420. }
  421. /* comparison function to order temporaries
  422. * for allocation at the end of blocks */
  423. static int
  424. prio2(int t1, int t2)
  425. {
  426. if ((tmp[t1].visit ^ tmp[t2].visit) < 0) /* != signs */
  427. return tmp[t1].visit != -1 ? +1 : -1;
  428. if ((*hint(t1) ^ *hint(t2)) < 0)
  429. return *hint(t1) != -1 ? +1 : -1;
  430. return tmp[t1].cost - tmp[t2].cost;
  431. }
  432. /* register allocation
  433. * depends on rpo, phi, cost, (and obviously spill)
  434. */
  435. void
  436. rega(Fn *fn)
  437. {
  438. int j, t, r, x, rl[Tmp0];
  439. Blk *b, *b1, *s, ***ps, *blist, **blk, **bp;
  440. RMap *end, *beg, cur, old, *m;
  441. Ins *i;
  442. Phi *p;
  443. uint u, n;
  444. Ref src, dst;
  445. /* 1. setup */
  446. stmov = 0;
  447. stblk = 0;
  448. regu = 0;
  449. tmp = fn->tmp;
  450. mem = fn->mem;
  451. blk = alloc(fn->nblk * sizeof blk[0]);
  452. end = alloc(fn->nblk * sizeof end[0]);
  453. beg = alloc(fn->nblk * sizeof beg[0]);
  454. for (n=0; n<fn->nblk; n++) {
  455. bsinit(end[n].b, fn->ntmp);
  456. bsinit(beg[n].b, fn->ntmp);
  457. }
  458. bsinit(cur.b, fn->ntmp);
  459. bsinit(old.b, fn->ntmp);
  460. loop = INT_MAX;
  461. for (t=0; t<fn->ntmp; t++) {
  462. tmp[t].hint.r = t < Tmp0 ? t : -1;
  463. tmp[t].hint.w = loop;
  464. tmp[t].visit = -1;
  465. }
  466. for (bp=blk, b=fn->start; b; b=b->link)
  467. *bp++ = b;
  468. qsort(blk, fn->nblk, sizeof blk[0], carve);
  469. for (b=fn->start, i=b->ins; i<&b->ins[b->nins]; i++)
  470. if (i->op != Ocopy || !isreg(i->arg[0]))
  471. break;
  472. else {
  473. assert(rtype(i->to) == RTmp);
  474. sethint(i->to.val, i->arg[0].val);
  475. }
  476. /* 2. assign registers */
  477. for (bp=blk; bp<&blk[fn->nblk]; bp++) {
  478. b = *bp;
  479. n = b->id;
  480. loop = b->loop;
  481. cur.n = 0;
  482. bszero(cur.b);
  483. memset(cur.w, 0, sizeof cur.w);
  484. for (x=0, t=Tmp0; bsiter(b->out, &t); t++) {
  485. j = x++;
  486. rl[j] = t;
  487. while (j-- > 0 && prio2(t, rl[j]) > 0) {
  488. rl[j+1] = rl[j];
  489. rl[j] = t;
  490. }
  491. }
  492. for (r=0; bsiter(b->out, &r) && r<Tmp0; r++)
  493. radd(&cur, r, r);
  494. for (j=0; j<x; j++)
  495. ralloctry(&cur, rl[j], 1);
  496. for (j=0; j<x; j++)
  497. ralloc(&cur, rl[j]);
  498. rcopy(&end[n], &cur);
  499. doblk(b, &cur);
  500. bscopy(b->in, cur.b);
  501. for (p=b->phi; p; p=p->link)
  502. if (rtype(p->to) == RTmp)
  503. bsclr(b->in, p->to.val);
  504. rcopy(&beg[n], &cur);
  505. }
  506. /* 3. emit copies shared by multiple edges
  507. * to the same block */
  508. for (s=fn->start; s; s=s->link) {
  509. if (s->npred <= 1)
  510. continue;
  511. m = &beg[s->id];
  512. /* rl maps a register that is live at the
  513. * beginning of s to the one used in all
  514. * predecessors (if any, -1 otherwise) */
  515. memset(rl, 0, sizeof rl);
  516. /* to find the register of a phi in a
  517. * predecessor, we have to find the
  518. * corresponding argument */
  519. for (p=s->phi; p; p=p->link) {
  520. if (rtype(p->to) != RTmp
  521. || (r=rfind(m, p->to.val)) == -1)
  522. continue;
  523. for (u=0; u<p->narg; u++) {
  524. b = p->blk[u];
  525. src = p->arg[u];
  526. if (rtype(src) != RTmp)
  527. continue;
  528. x = rfind(&end[b->id], src.val);
  529. if (x == -1) /* spilled */
  530. continue;
  531. rl[r] = (!rl[r] || rl[r] == x) ? x : -1;
  532. }
  533. if (rl[r] == 0)
  534. rl[r] = -1;
  535. }
  536. /* process non-phis temporaries */
  537. for (j=0; j<m->n; j++) {
  538. t = m->t[j];
  539. r = m->r[j];
  540. if (rl[r] || t < Tmp0 /* todo, remove this */)
  541. continue;
  542. for (bp=s->pred; bp<&s->pred[s->npred]; bp++) {
  543. x = rfind(&end[(*bp)->id], t);
  544. if (x == -1) /* spilled */
  545. continue;
  546. rl[r] = (!rl[r] || rl[r] == x) ? x : -1;
  547. }
  548. if (rl[r] == 0)
  549. rl[r] = -1;
  550. }
  551. npm = 0;
  552. for (j=0; j<m->n; j++) {
  553. t = m->t[j];
  554. r = m->r[j];
  555. x = rl[r];
  556. assert(x != 0 || t < Tmp0 /* todo, ditto */);
  557. if (x > 0 && !bshas(m->b, x)) {
  558. pmadd(TMP(x), TMP(r), tmp[t].cls);
  559. m->r[j] = x;
  560. bsset(m->b, x);
  561. }
  562. }
  563. curi = &insb[NIns];
  564. pmgen();
  565. j = &insb[NIns] - curi;
  566. if (j == 0)
  567. continue;
  568. stmov += j;
  569. s->nins += j;
  570. i = alloc(s->nins * sizeof(Ins));
  571. icpy(icpy(i, curi, j), s->ins, s->nins-j);
  572. s->ins = i;
  573. }
  574. if (debug['R']) {
  575. fprintf(stderr, "\n> Register mappings:\n");
  576. for (n=0; n<fn->nblk; n++) {
  577. b = fn->rpo[n];
  578. fprintf(stderr, "\t%-10s beg", b->name);
  579. mdump(&beg[n]);
  580. fprintf(stderr, "\t end");
  581. mdump(&end[n]);
  582. }
  583. fprintf(stderr, "\n");
  584. }
  585. /* 4. emit remaining copies in new blocks */
  586. blist = 0;
  587. for (b=fn->start;; b=b->link) {
  588. ps = (Blk**[3]){&b->s1, &b->s2, (Blk*[1]){0}};
  589. for (; (s=**ps); ps++) {
  590. npm = 0;
  591. for (p=s->phi; p; p=p->link) {
  592. dst = p->to;
  593. assert(rtype(dst)==RSlot || rtype(dst)==RTmp);
  594. if (rtype(dst) == RTmp) {
  595. r = rfind(&beg[s->id], dst.val);
  596. if (r == -1)
  597. continue;
  598. dst = TMP(r);
  599. }
  600. for (u=0; p->blk[u]!=b; u++)
  601. assert(u+1 < p->narg);
  602. src = p->arg[u];
  603. if (rtype(src) == RTmp)
  604. src = rref(&end[b->id], src.val);
  605. pmadd(src, dst, p->cls);
  606. }
  607. for (t=Tmp0; bsiter(s->in, &t); t++) {
  608. src = rref(&end[b->id], t);
  609. dst = rref(&beg[s->id], t);
  610. pmadd(src, dst, tmp[t].cls);
  611. }
  612. curi = &insb[NIns];
  613. pmgen();
  614. if (curi == &insb[NIns])
  615. continue;
  616. b1 = newblk();
  617. b1->loop = (b->loop+s->loop) / 2;
  618. b1->link = blist;
  619. blist = b1;
  620. fn->nblk++;
  621. strf(b1->name, "%s_%s", b->name, s->name);
  622. b1->nins = &insb[NIns] - curi;
  623. stmov += b1->nins;
  624. stblk += 1;
  625. idup(&b1->ins, curi, b1->nins);
  626. b1->jmp.type = Jjmp;
  627. b1->s1 = s;
  628. **ps = b1;
  629. }
  630. if (!b->link) {
  631. b->link = blist;
  632. break;
  633. }
  634. }
  635. for (b=fn->start; b; b=b->link)
  636. b->phi = 0;
  637. fn->reg = regu;
  638. if (debug['R']) {
  639. fprintf(stderr, "\n> Register allocation statistics:\n");
  640. fprintf(stderr, "\tnew moves: %d\n", stmov);
  641. fprintf(stderr, "\tnew blocks: %d\n", stblk);
  642. fprintf(stderr, "\n> After register allocation:\n");
  643. printfn(fn, stderr);
  644. }
  645. }