noop.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. #include "l.h"
  2. void
  3. noops(void)
  4. {
  5. Prog *p, *p1, *q, *q1;
  6. int o, mov, aoffset, curframe, curbecome, maxbecome;
  7. /*
  8. * find leaf subroutines
  9. * become sizes
  10. * frame sizes
  11. * strip NOPs
  12. * expand RET
  13. * expand BECOME pseudo
  14. */
  15. if(debug['v'])
  16. Bprint(&bso, "%5.2f noops\n", cputime());
  17. Bflush(&bso);
  18. curframe = 0;
  19. curbecome = 0;
  20. maxbecome = 0;
  21. curtext = 0;
  22. q = P;
  23. for(p = firstp; p != P; p = p->link) {
  24. /* find out how much arg space is used in this TEXT */
  25. if(p->to.type == D_OREG && p->to.reg == REGSP)
  26. if(p->to.offset > curframe)
  27. curframe = p->to.offset;
  28. switch(p->as) {
  29. /* too hard, just leave alone */
  30. case ATEXT:
  31. if(curtext && curtext->from.sym) {
  32. curtext->from.sym->frame = curframe;
  33. curtext->from.sym->become = curbecome;
  34. if(curbecome > maxbecome)
  35. maxbecome = curbecome;
  36. }
  37. curframe = 0;
  38. curbecome = 0;
  39. q = p;
  40. p->mark |= LABEL|LEAF|SYNC;
  41. if(p->link)
  42. p->link->mark |= LABEL;
  43. curtext = p;
  44. break;
  45. case ANOR:
  46. q = p;
  47. if(p->to.type == D_REG)
  48. if(p->to.reg == REGZERO)
  49. p->mark |= LABEL|SYNC;
  50. break;
  51. case ALWAR:
  52. case ASTWCCC:
  53. case AECIWX:
  54. case AECOWX:
  55. case AEIEIO:
  56. case AICBI:
  57. case AISYNC:
  58. case ATLBIE:
  59. case ATLBIEL:
  60. case ASLBIA:
  61. case ASLBIE:
  62. case ASLBMFEE:
  63. case ASLBMFEV:
  64. case ASLBMTE:
  65. case ADCBF:
  66. case ADCBI:
  67. case ADCBST:
  68. case ADCBT:
  69. case ADCBTST:
  70. case ADCBZ:
  71. case ASYNC:
  72. case ATLBSYNC:
  73. case APTESYNC:
  74. case ATW:
  75. case AWORD:
  76. case ARFI:
  77. case ARFCI:
  78. case ARFID:
  79. case AHRFID:
  80. q = p;
  81. p->mark |= LABEL|SYNC;
  82. continue;
  83. case AMOVW:
  84. case AMOVWZ:
  85. case AMOVD:
  86. q = p;
  87. switch(p->from.type) {
  88. case D_MSR:
  89. case D_SPR:
  90. case D_FPSCR:
  91. case D_CREG:
  92. case D_DCR:
  93. p->mark |= LABEL|SYNC;
  94. }
  95. switch(p->to.type) {
  96. case D_MSR:
  97. case D_SPR:
  98. case D_FPSCR:
  99. case D_CREG:
  100. case D_DCR:
  101. p->mark |= LABEL|SYNC;
  102. }
  103. continue;
  104. case AFABS:
  105. case AFABSCC:
  106. case AFADD:
  107. case AFADDCC:
  108. case AFCTIW:
  109. case AFCTIWCC:
  110. case AFCTIWZ:
  111. case AFCTIWZCC:
  112. case AFDIV:
  113. case AFDIVCC:
  114. case AFMADD:
  115. case AFMADDCC:
  116. case AFMOVD:
  117. case AFMOVDU:
  118. /* case AFMOVDS: */
  119. case AFMOVS:
  120. case AFMOVSU:
  121. /* case AFMOVSD: */
  122. case AFMSUB:
  123. case AFMSUBCC:
  124. case AFMUL:
  125. case AFMULCC:
  126. case AFNABS:
  127. case AFNABSCC:
  128. case AFNEG:
  129. case AFNEGCC:
  130. case AFNMADD:
  131. case AFNMADDCC:
  132. case AFNMSUB:
  133. case AFNMSUBCC:
  134. case AFRSP:
  135. case AFRSPCC:
  136. case AFSUB:
  137. case AFSUBCC:
  138. q = p;
  139. p->mark |= FLOAT;
  140. continue;
  141. case ABL:
  142. case ABCL:
  143. if(curtext != P)
  144. curtext->mark &= ~LEAF;
  145. case ABC:
  146. case ABEQ:
  147. case ABGE:
  148. case ABGT:
  149. case ABLE:
  150. case ABLT:
  151. case ABNE:
  152. case ABR:
  153. case ABVC:
  154. case ABVS:
  155. p->mark |= BRANCH;
  156. q = p;
  157. q1 = p->cond;
  158. if(q1 != P) {
  159. while(q1->as == ANOP) {
  160. q1 = q1->link;
  161. p->cond = q1;
  162. }
  163. if(!(q1->mark & LEAF))
  164. q1->mark |= LABEL;
  165. } else
  166. p->mark |= LABEL;
  167. q1 = p->link;
  168. if(q1 != P)
  169. q1->mark |= LABEL;
  170. continue;
  171. case AFCMPO:
  172. case AFCMPU:
  173. q = p;
  174. p->mark |= FCMP|FLOAT;
  175. continue;
  176. case ARETURN:
  177. /* special form of RETURN is BECOME */
  178. if(p->from.type == D_CONST)
  179. if(p->from.offset > curbecome)
  180. curbecome = p->from.offset;
  181. q = p;
  182. if(p->link != P)
  183. p->link->mark |= LABEL;
  184. continue;
  185. case ANOP:
  186. q1 = p->link;
  187. q->link = q1; /* q is non-nop */
  188. q1->mark |= p->mark;
  189. continue;
  190. default:
  191. q = p;
  192. continue;
  193. }
  194. }
  195. if(curtext && curtext->from.sym) {
  196. curtext->from.sym->frame = curframe;
  197. curtext->from.sym->become = curbecome;
  198. if(curbecome > maxbecome)
  199. maxbecome = curbecome;
  200. }
  201. if(debug['b'])
  202. print("max become = %d\n", maxbecome);
  203. xdefine("ALEFbecome", STEXT, maxbecome);
  204. curtext = 0;
  205. for(p = firstp; p != P; p = p->link) {
  206. switch(p->as) {
  207. case ATEXT:
  208. curtext = p;
  209. break;
  210. case ABL: /* ABCL? */
  211. if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
  212. o = maxbecome - curtext->from.sym->frame;
  213. if(o <= 0)
  214. break;
  215. /* calling a become or calling a variable */
  216. if(p->to.sym == S || p->to.sym->become) {
  217. curtext->to.offset += o;
  218. if(debug['b']) {
  219. curp = p;
  220. print("%D calling %D increase %d\n",
  221. &curtext->from, &p->to, o);
  222. }
  223. }
  224. }
  225. break;
  226. }
  227. }
  228. curtext = P;
  229. for(p = firstp; p != P; p = p->link) {
  230. o = p->as;
  231. switch(o) {
  232. case ATEXT:
  233. mov = AMOVD;
  234. aoffset = 0;
  235. curtext = p;
  236. autosize = p->to.offset + 8;
  237. if((p->mark & LEAF) && autosize <= 8)
  238. autosize = 0;
  239. else
  240. if(autosize & 4)
  241. autosize += 4;
  242. p->to.offset = autosize - 8;
  243. q = p;
  244. if(autosize) {
  245. /* use MOVDU to adjust R1 when saving R31, if autosize is small */
  246. if(!(curtext->mark & LEAF) && autosize >= -BIG && autosize <= BIG) {
  247. mov = AMOVDU;
  248. aoffset = -autosize;
  249. } else {
  250. q = prg();
  251. q->as = AADD;
  252. q->line = p->line;
  253. q->from.type = D_CONST;
  254. q->from.offset = -autosize;
  255. q->to.type = D_REG;
  256. q->to.reg = REGSP;
  257. q->link = p->link;
  258. p->link = q;
  259. }
  260. } else
  261. if(!(curtext->mark & LEAF)) {
  262. if(debug['v'])
  263. Bprint(&bso, "save suppressed in: %s\n",
  264. curtext->from.sym->name);
  265. curtext->mark |= LEAF;
  266. }
  267. if(curtext->mark & LEAF) {
  268. if(curtext->from.sym)
  269. curtext->from.sym->type = SLEAF;
  270. break;
  271. }
  272. q1 = prg();
  273. q1->as = mov;
  274. q1->line = p->line;
  275. q1->from.type = D_REG;
  276. q1->from.reg = REGTMP;
  277. q1->to.type = D_OREG;
  278. q1->to.offset = aoffset;
  279. q1->to.reg = REGSP;
  280. q1->link = q->link;
  281. q->link = q1;
  282. q1 = prg();
  283. q1->as = AMOVD;
  284. q1->line = p->line;
  285. q1->from.type = D_SPR;
  286. q1->from.offset = D_LR;
  287. q1->to.type = D_REG;
  288. q1->to.reg = REGTMP;
  289. q1->link = q->link;
  290. q->link = q1;
  291. break;
  292. case ARETURN:
  293. if(p->from.type == D_CONST)
  294. goto become;
  295. if(curtext->mark & LEAF) {
  296. if(!autosize) {
  297. p->as = ABR;
  298. p->from = zprg.from;
  299. p->to.type = D_SPR;
  300. p->to.offset = D_LR;
  301. p->mark |= BRANCH;
  302. break;
  303. }
  304. p->as = AADD;
  305. p->from.type = D_CONST;
  306. p->from.offset = autosize;
  307. p->to.type = D_REG;
  308. p->to.reg = REGSP;
  309. q = prg();
  310. q->as = ABR;
  311. q->line = p->line;
  312. q->to.type = D_SPR;
  313. q->to.offset = D_LR;
  314. q->mark |= BRANCH;
  315. q->link = p->link;
  316. p->link = q;
  317. break;
  318. }
  319. p->as = AMOVD;
  320. p->from.type = D_OREG;
  321. p->from.offset = 0;
  322. p->from.reg = REGSP;
  323. p->to.type = D_REG;
  324. p->to.reg = REGTMP;
  325. q = prg();
  326. q->as = AMOVD;
  327. q->line = p->line;
  328. q->from.type = D_REG;
  329. q->from.reg = REGTMP;
  330. q->to.type = D_SPR;
  331. q->to.offset = D_LR;
  332. q->link = p->link;
  333. p->link = q;
  334. p = q;
  335. if(autosize) {
  336. q = prg();
  337. q->as = AADD;
  338. q->line = p->line;
  339. q->from.type = D_CONST;
  340. q->from.offset = autosize;
  341. q->to.type = D_REG;
  342. q->to.reg = REGSP;
  343. q->link = p->link;
  344. p->link = q;
  345. }
  346. q1 = prg();
  347. q1->as = ABR;
  348. q1->line = p->line;
  349. q1->to.type = D_SPR;
  350. q1->to.offset = D_LR;
  351. q1->mark |= BRANCH;
  352. q1->link = q->link;
  353. q->link = q1;
  354. break;
  355. become:
  356. if(curtext->mark & LEAF) {
  357. q = prg();
  358. q->line = p->line;
  359. q->as = ABR;
  360. q->from = zprg.from;
  361. q->to = p->to;
  362. q->cond = p->cond;
  363. q->link = p->link;
  364. q->mark |= BRANCH;
  365. p->link = q;
  366. p->as = AADD;
  367. p->from = zprg.from;
  368. p->from.type = D_CONST;
  369. p->from.offset = autosize;
  370. p->to = zprg.to;
  371. p->to.type = D_REG;
  372. p->to.reg = REGSP;
  373. break;
  374. }
  375. q = prg();
  376. q->line = p->line;
  377. q->as = ABR;
  378. q->from = zprg.from;
  379. q->to = p->to;
  380. q->cond = p->cond;
  381. q->mark |= BRANCH;
  382. q->link = p->link;
  383. p->link = q;
  384. q = prg();
  385. q->line = p->line;
  386. q->as = AADD;
  387. q->from.type = D_CONST;
  388. q->from.offset = autosize;
  389. q->to.type = D_REG;
  390. q->to.reg = REGSP;
  391. q->link = p->link;
  392. p->link = q;
  393. q = prg();
  394. q->line = p->line;
  395. q->as = AMOVD;
  396. q->line = p->line;
  397. q->from.type = D_REG;
  398. q->from.reg = REGTMP;
  399. q->to.type = D_SPR;
  400. q->to.offset = D_LR;
  401. q->link = p->link;
  402. p->link = q;
  403. p->as = AMOVD;
  404. p->from = zprg.from;
  405. p->from.type = D_OREG;
  406. p->from.offset = 0;
  407. p->from.reg = REGSP;
  408. p->to = zprg.to;
  409. p->to.type = D_REG;
  410. p->to.reg = REGTMP;
  411. break;
  412. }
  413. }
  414. if(debug['Q'] == 0)
  415. return;
  416. curtext = P;
  417. q = P; /* p - 1 */
  418. q1 = firstp; /* top of block */
  419. o = 0; /* count of instructions */
  420. for(p = firstp; p != P; p = p1) {
  421. p1 = p->link;
  422. o++;
  423. if(p->mark & NOSCHED){
  424. if(q1 != p){
  425. sched(q1, q);
  426. }
  427. for(; p != P; p = p->link){
  428. if(!(p->mark & NOSCHED))
  429. break;
  430. q = p;
  431. }
  432. p1 = p;
  433. q1 = p;
  434. o = 0;
  435. continue;
  436. }
  437. if(p->mark & (LABEL|SYNC)) {
  438. if(q1 != p)
  439. sched(q1, q);
  440. q1 = p;
  441. o = 1;
  442. }
  443. if(p->mark & (BRANCH|SYNC)) {
  444. sched(q1, p);
  445. q1 = p1;
  446. o = 0;
  447. }
  448. if(o >= NSCHED) {
  449. sched(q1, p);
  450. q1 = p1;
  451. o = 0;
  452. }
  453. q = p;
  454. }
  455. }
  456. void
  457. addnop(Prog *p)
  458. {
  459. Prog *q;
  460. q = prg();
  461. q->as = AOR;
  462. q->line = p->line;
  463. q->from.type = D_REG;
  464. q->from.reg = REGZERO;
  465. q->to.type = D_REG;
  466. q->to.reg = REGZERO;
  467. q->link = p->link;
  468. p->link = q;
  469. }