noop.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. #include "l.h"
  2. void
  3. noops(void)
  4. {
  5. Prog *p, *p1, *q, *q1;
  6. int o, 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. case ATEXT:
  30. if(curtext && curtext->from.sym) {
  31. curtext->from.sym->frame = curframe;
  32. curtext->from.sym->become = curbecome;
  33. if(curbecome > maxbecome)
  34. maxbecome = curbecome;
  35. }
  36. curframe = 0;
  37. curbecome = 0;
  38. p->mark |= LABEL|LEAF|SYNC;
  39. if(p->link)
  40. p->link->mark |= LABEL;
  41. curtext = p;
  42. break;
  43. /* too hard, just leave alone */
  44. case AMOVW:
  45. if(p->to.type == D_FCREG ||
  46. p->to.type == D_MREG) {
  47. p->mark |= LABEL|SYNC;
  48. break;
  49. }
  50. if(p->from.type == D_FCREG ||
  51. p->from.type == D_MREG) {
  52. p->mark |= LABEL|SYNC;
  53. addnop(p);
  54. addnop(p);
  55. nop.mfrom.count += 2;
  56. nop.mfrom.outof += 2;
  57. break;
  58. }
  59. break;
  60. /* too hard, just leave alone */
  61. case ACASE:
  62. case ASYSCALL:
  63. case AWORD:
  64. case ATLBWR:
  65. case ATLBWI:
  66. case ATLBP:
  67. case ATLBR:
  68. p->mark |= LABEL|SYNC;
  69. break;
  70. case ANOR:
  71. if(p->to.type == D_REG && p->to.reg == REGZERO)
  72. p->mark |= LABEL|SYNC;
  73. break;
  74. case ARET:
  75. /* special form of RET is BECOME */
  76. if(p->from.type == D_CONST)
  77. if(p->from.offset > curbecome)
  78. curbecome = p->from.offset;
  79. if(p->link != P)
  80. p->link->mark |= LABEL;
  81. break;
  82. case ANOP:
  83. q1 = p->link;
  84. q->link = q1; /* q is non-nop */
  85. q1->mark |= p->mark;
  86. continue;
  87. case ABCASE:
  88. p->mark |= LABEL|SYNC;
  89. goto dstlab;
  90. case ABGEZAL:
  91. case ABLTZAL:
  92. case AJAL:
  93. if(curtext != P)
  94. curtext->mark &= ~LEAF;
  95. case AJMP:
  96. case ABEQ:
  97. case ABGEZ:
  98. case ABGTZ:
  99. case ABLEZ:
  100. case ABLTZ:
  101. case ABNE:
  102. case ABFPT:
  103. case ABFPF:
  104. p->mark |= BRANCH;
  105. dstlab:
  106. q1 = p->cond;
  107. if(q1 != P) {
  108. while(q1->as == ANOP) {
  109. q1 = q1->link;
  110. p->cond = q1;
  111. }
  112. if(!(q1->mark & LEAF))
  113. q1->mark |= LABEL;
  114. } else
  115. p->mark |= LABEL;
  116. q1 = p->link;
  117. if(q1 != P)
  118. q1->mark |= LABEL;
  119. break;
  120. }
  121. q = p;
  122. }
  123. if(curtext && curtext->from.sym) {
  124. curtext->from.sym->frame = curframe;
  125. curtext->from.sym->become = curbecome;
  126. if(curbecome > maxbecome)
  127. maxbecome = curbecome;
  128. }
  129. if(debug['b'])
  130. print("max become = %d\n", maxbecome);
  131. xdefine("ALEFbecome", STEXT, maxbecome);
  132. curtext = 0;
  133. for(p = firstp; p != P; p = p->link) {
  134. switch(p->as) {
  135. case ATEXT:
  136. curtext = p;
  137. break;
  138. case AJAL:
  139. if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
  140. o = maxbecome - curtext->from.sym->frame;
  141. if(o <= 0)
  142. break;
  143. /* calling a become or calling a variable */
  144. if(p->to.sym == S || p->to.sym->become) {
  145. curtext->to.offset += o;
  146. if(debug['b']) {
  147. curp = p;
  148. print("%D calling %D increase %d\n",
  149. &curtext->from, &p->to, o);
  150. }
  151. }
  152. }
  153. break;
  154. }
  155. }
  156. for(p = firstp; p != P; p = p->link) {
  157. o = p->as;
  158. switch(o) {
  159. case ATEXT:
  160. curtext = p;
  161. autosize = p->to.offset + 4;
  162. if(autosize <= 4)
  163. if(curtext->mark & LEAF) {
  164. p->to.offset = -4;
  165. autosize = 0;
  166. }
  167. q = p;
  168. if(autosize) {
  169. q = prg();
  170. q->as = AADD;
  171. q->line = p->line;
  172. q->from.type = D_CONST;
  173. q->from.offset = -autosize;
  174. q->to.type = D_REG;
  175. q->to.reg = REGSP;
  176. q->link = p->link;
  177. p->link = q;
  178. } else
  179. if(!(curtext->mark & LEAF)) {
  180. if(debug['v'])
  181. Bprint(&bso, "save suppressed in: %s\n",
  182. curtext->from.sym->name);
  183. Bflush(&bso);
  184. curtext->mark |= LEAF;
  185. }
  186. if(curtext->mark & LEAF) {
  187. if(curtext->from.sym)
  188. curtext->from.sym->type = SLEAF;
  189. break;
  190. }
  191. q1 = prg();
  192. q1->as = AMOVW;
  193. q1->line = p->line;
  194. q1->from.type = D_REG;
  195. q1->from.reg = REGLINK;
  196. q1->to.type = D_OREG;
  197. q1->from.offset = 0;
  198. q1->to.reg = REGSP;
  199. q1->link = q->link;
  200. q->link = q1;
  201. break;
  202. case ARET:
  203. nocache(p);
  204. if(p->from.type == D_CONST)
  205. goto become;
  206. if(curtext->mark & LEAF) {
  207. if(!autosize) {
  208. p->as = AJMP;
  209. p->from = zprg.from;
  210. p->to.type = D_OREG;
  211. p->to.offset = 0;
  212. p->to.reg = REGLINK;
  213. p->mark |= BRANCH;
  214. break;
  215. }
  216. p->as = AADD;
  217. p->from.type = D_CONST;
  218. p->from.offset = autosize;
  219. p->to.type = D_REG;
  220. p->to.reg = REGSP;
  221. q = prg();
  222. q->as = AJMP;
  223. q->line = p->line;
  224. q->to.type = D_OREG;
  225. q->to.offset = 0;
  226. q->to.reg = REGLINK;
  227. q->mark |= BRANCH;
  228. q->link = p->link;
  229. p->link = q;
  230. break;
  231. }
  232. p->as = AMOVW;
  233. p->from.type = D_OREG;
  234. p->from.offset = 0;
  235. p->from.reg = REGSP;
  236. p->to.type = D_REG;
  237. p->to.reg = 2;
  238. q = p;
  239. if(autosize) {
  240. q = prg();
  241. q->as = AADD;
  242. q->line = p->line;
  243. q->from.type = D_CONST;
  244. q->from.offset = autosize;
  245. q->to.type = D_REG;
  246. q->to.reg = REGSP;
  247. q->link = p->link;
  248. p->link = q;
  249. }
  250. q1 = prg();
  251. q1->as = AJMP;
  252. q1->line = p->line;
  253. q1->to.type = D_OREG;
  254. q1->to.offset = 0;
  255. q1->to.reg = 2;
  256. q1->mark |= BRANCH;
  257. q1->link = q->link;
  258. q->link = q1;
  259. break;
  260. become:
  261. if(curtext->mark & LEAF) {
  262. q = prg();
  263. q->line = p->line;
  264. q->as = AJMP;
  265. q->from = zprg.from;
  266. q->to = p->to;
  267. q->cond = p->cond;
  268. q->link = p->link;
  269. q->mark |= BRANCH;
  270. p->link = q;
  271. p->as = AADD;
  272. p->from = zprg.from;
  273. p->from.type = D_CONST;
  274. p->from.offset = autosize;
  275. p->to = zprg.to;
  276. p->to.type = D_REG;
  277. p->to.reg = REGSP;
  278. break;
  279. }
  280. q = prg();
  281. q->line = p->line;
  282. q->as = AJMP;
  283. q->from = zprg.from;
  284. q->to = p->to;
  285. q->cond = p->cond;
  286. q->link = p->link;
  287. q->mark |= BRANCH;
  288. p->link = q;
  289. q = prg();
  290. q->line = p->line;
  291. q->as = AADD;
  292. q->from.type = D_CONST;
  293. q->from.offset = autosize;
  294. q->to.type = D_REG;
  295. q->to.reg = REGSP;
  296. q->link = p->link;
  297. p->link = q;
  298. p->as = AMOVW;
  299. p->from = zprg.from;
  300. p->from.type = D_OREG;
  301. p->from.offset = 0;
  302. p->from.reg = REGSP;
  303. p->to = zprg.to;
  304. p->to.type = D_REG;
  305. p->to.reg = REGLINK;
  306. break;
  307. }
  308. }
  309. curtext = P;
  310. q = P; /* p - 1 */
  311. q1 = firstp; /* top of block */
  312. o = 0; /* count of instructions */
  313. for(p = firstp; p != P; p = p1) {
  314. p1 = p->link;
  315. o++;
  316. if(p->mark & NOSCHED){
  317. if(q1 != p){
  318. sched(q1, q);
  319. }
  320. for(; p != P; p = p->link){
  321. if(!(p->mark & NOSCHED))
  322. break;
  323. q = p;
  324. }
  325. p1 = p;
  326. q1 = p;
  327. o = 0;
  328. continue;
  329. }
  330. if(p->mark & (LABEL|SYNC)) {
  331. if(q1 != p)
  332. sched(q1, q);
  333. q1 = p;
  334. o = 1;
  335. }
  336. if(p->mark & (BRANCH|SYNC)) {
  337. sched(q1, p);
  338. q1 = p1;
  339. o = 0;
  340. }
  341. if(o >= NSCHED) {
  342. sched(q1, p);
  343. q1 = p1;
  344. o = 0;
  345. }
  346. q = p;
  347. }
  348. }
  349. void
  350. addnop(Prog *p)
  351. {
  352. Prog *q;
  353. q = prg();
  354. q->as = ANOR;
  355. q->line = p->line;
  356. q->from.type = D_REG;
  357. q->from.reg = REGZERO;
  358. q->to.type = D_REG;
  359. q->to.reg = REGZERO;
  360. q->link = p->link;
  361. p->link = q;
  362. }
  363. void
  364. nocache(Prog *p)
  365. {
  366. p->optab = 0;
  367. p->from.class = 0;
  368. p->to.class = 0;
  369. }