noop.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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. /* 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 AORN:
  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 AUNIMP:
  52. case ATAS:
  53. case ASWAP:
  54. case ATA:
  55. case ATCC:
  56. case ATCS:
  57. case ATE:
  58. case ATG:
  59. case ATGE:
  60. case ATGU:
  61. case ATL:
  62. case ATLE:
  63. case ATLEU:
  64. case ATN:
  65. case ATNE:
  66. case ATNEG:
  67. case ATPOS:
  68. case ATVC:
  69. case ATVS:
  70. case AWORD:
  71. q = p;
  72. p->mark |= LABEL|SYNC;
  73. continue;
  74. case AFABSD:
  75. case AFABSF:
  76. case AFABSX:
  77. case AFADDD:
  78. case AFADDF:
  79. case AFADDX:
  80. case AFDIVD:
  81. case AFDIVF:
  82. case AFDIVX:
  83. case AFMOVD:
  84. case AFMOVDF:
  85. case AFMOVDW:
  86. case AFMOVDX:
  87. case AFMOVF:
  88. case AFMOVFD:
  89. case AFMOVFW:
  90. case AFMOVFX:
  91. case AFMOVWD:
  92. case AFMOVWF:
  93. case AFMOVWX:
  94. case AFMOVX:
  95. case AFMOVXD:
  96. case AFMOVXF:
  97. case AFMOVXW:
  98. case AFMULD:
  99. case AFMULF:
  100. case AFMULX:
  101. case AFNEGD:
  102. case AFNEGF:
  103. case AFNEGX:
  104. case AFSQRTD:
  105. case AFSQRTF:
  106. case AFSQRTX:
  107. case AFSUBD:
  108. case AFSUBF:
  109. case AFSUBX:
  110. q = p;
  111. p->mark |= FLOAT;
  112. continue;
  113. case AMUL:
  114. case ADIV:
  115. case ADIVL:
  116. case AMOD:
  117. case AMODL:
  118. q = p;
  119. if(!debug['M']) {
  120. if(prog_mul == P)
  121. initmuldiv();
  122. if(curtext != P)
  123. curtext->mark &= ~LEAF;
  124. }
  125. continue;
  126. case AJMPL:
  127. if(curtext != P)
  128. curtext->mark &= ~LEAF;
  129. case AJMP:
  130. case ABA:
  131. case ABN:
  132. case ABE:
  133. case ABNE:
  134. case ABLE:
  135. case ABG:
  136. case ABL:
  137. case ABGE:
  138. case ABLEU:
  139. case ABGU:
  140. case ABCS:
  141. case ABCC:
  142. case ABNEG:
  143. case ABPOS:
  144. case ABVC:
  145. case ABVS:
  146. case AFBN:
  147. case AFBO:
  148. case AFBE:
  149. case AFBLG:
  150. case AFBG:
  151. case AFBLE:
  152. case AFBGE:
  153. case AFBL:
  154. case AFBNE:
  155. case AFBUE:
  156. case AFBA:
  157. case AFBU:
  158. case AFBUG:
  159. case AFBULE:
  160. case AFBUGE:
  161. case AFBUL:
  162. p->mark |= BRANCH;
  163. q = p;
  164. q1 = p->cond;
  165. if(q1 != P) {
  166. while(q1->as == ANOP) {
  167. q1 = q1->link;
  168. p->cond = q1;
  169. }
  170. if(!(q1->mark & LEAF))
  171. q1->mark |= LABEL;
  172. } else
  173. p->mark |= LABEL;
  174. q1 = p->link;
  175. if(q1 != P)
  176. q1->mark |= LABEL;
  177. continue;
  178. case AFCMPD:
  179. case AFCMPED:
  180. case AFCMPEF:
  181. case AFCMPEX:
  182. case AFCMPF:
  183. case AFCMPX:
  184. q = p;
  185. p->mark |= FCMP|FLOAT;
  186. continue;
  187. case ARETURN:
  188. /* special form of RETURN is BECOME */
  189. if(p->from.type == D_CONST)
  190. if(p->from.offset > curbecome)
  191. curbecome = p->from.offset;
  192. q = p;
  193. if(p->link != P)
  194. p->link->mark |= LABEL;
  195. continue;
  196. case ANOP:
  197. q1 = p->link;
  198. q->link = q1; /* q is non-nop */
  199. q1->mark |= p->mark;
  200. continue;
  201. default:
  202. q = p;
  203. continue;
  204. }
  205. }
  206. if(curtext && curtext->from.sym) {
  207. curtext->from.sym->frame = curframe;
  208. curtext->from.sym->become = curbecome;
  209. if(curbecome > maxbecome)
  210. maxbecome = curbecome;
  211. }
  212. if(debug['b'])
  213. print("max become = %d\n", maxbecome);
  214. xdefine("ALEFbecome", STEXT, maxbecome);
  215. curtext = 0;
  216. for(p = firstp; p != P; p = p->link) {
  217. switch(p->as) {
  218. case ATEXT:
  219. curtext = p;
  220. break;
  221. case AJMPL:
  222. if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
  223. o = maxbecome - curtext->from.sym->frame;
  224. if(o <= 0)
  225. break;
  226. /* calling a become or calling a variable */
  227. if(p->to.sym == S || p->to.sym->become) {
  228. curtext->to.offset += o;
  229. if(debug['b']) {
  230. curp = p;
  231. print("%D calling %D increase %d\n",
  232. &curtext->from, &p->to, o);
  233. }
  234. }
  235. }
  236. break;
  237. }
  238. }
  239. curtext = P;
  240. for(p = firstp; p != P; p = p->link) {
  241. o = p->as;
  242. switch(o) {
  243. case ATEXT:
  244. curtext = p;
  245. autosize = p->to.offset + 4;
  246. if((p->mark & LEAF) && autosize <= 4)
  247. autosize = 0;
  248. else
  249. if(autosize & 4)
  250. autosize += 4;
  251. p->to.offset = autosize - 4;
  252. q = p;
  253. if(autosize) {
  254. q = prg();
  255. q->as = ASUB;
  256. q->line = p->line;
  257. q->from.type = D_CONST;
  258. q->from.offset = autosize;
  259. q->to.type = D_REG;
  260. q->to.reg = REGSP;
  261. q->link = p->link;
  262. p->link = q;
  263. } else
  264. if(!(curtext->mark & LEAF)) {
  265. if(debug['v'])
  266. Bprint(&bso, "save suppressed in: %s\n",
  267. curtext->from.sym->name);
  268. curtext->mark |= LEAF;
  269. }
  270. if(curtext->mark & LEAF) {
  271. if(curtext->from.sym)
  272. curtext->from.sym->type = SLEAF;
  273. break;
  274. }
  275. q1 = prg();
  276. q1->as = AMOVW;
  277. q1->line = p->line;
  278. q1->from.type = D_REG;
  279. q1->from.reg = REGLINK;
  280. q1->to.type = D_OREG;
  281. q1->from.offset = 0;
  282. q1->to.reg = REGSP;
  283. q1->link = q->link;
  284. q->link = q1;
  285. break;
  286. case AMUL:
  287. case ADIV:
  288. case ADIVL:
  289. case AMOD:
  290. case AMODL:
  291. if(debug['M'])
  292. break;
  293. if(p->from.type != D_REG)
  294. break;
  295. if(p->to.type != D_REG)
  296. break;
  297. q1 = p;
  298. /* MOV a,4(SP) */
  299. q = prg();
  300. q->link = p->link;
  301. p->link = q;
  302. p = q;
  303. p->as = AMOVW;
  304. p->line = q1->line;
  305. p->from.type = D_REG;
  306. p->from.reg = q1->from.reg;
  307. p->to.type = D_OREG;
  308. p->to.reg = REGSP;
  309. p->to.offset = 4;
  310. /* MOV b,REGTMP */
  311. q = prg();
  312. q->link = p->link;
  313. p->link = q;
  314. p = q;
  315. p->as = AMOVW;
  316. p->line = q1->line;
  317. p->from.type = D_REG;
  318. p->from.reg = q1->reg;
  319. if(q1->reg == NREG)
  320. p->from.reg = q1->to.reg;
  321. p->to.type = D_REG;
  322. p->to.reg = REGTMP;
  323. p->to.offset = 0;
  324. /* CALL appropriate */
  325. q = prg();
  326. q->link = p->link;
  327. p->link = q;
  328. p = q;
  329. p->as = AJMPL;
  330. p->line = q1->line;
  331. p->to.type = D_BRANCH;
  332. p->cond = p;
  333. p->mark |= BRANCH;
  334. switch(o) {
  335. case AMUL:
  336. p->cond = prog_mul;
  337. break;
  338. case ADIV:
  339. p->cond = prog_div;
  340. break;
  341. case ADIVL:
  342. p->cond = prog_divl;
  343. break;
  344. case AMOD:
  345. p->cond = prog_mod;
  346. break;
  347. case AMODL:
  348. p->cond = prog_modl;
  349. break;
  350. }
  351. /* MOV REGTMP, b */
  352. q = prg();
  353. q->link = p->link;
  354. p->link = q;
  355. p = q;
  356. p->as = AMOVW;
  357. p->line = q1->line;
  358. p->from.type = D_REG;
  359. p->from.reg = REGTMP;
  360. p->from.offset = 0;
  361. p->to.type = D_REG;
  362. p->to.reg = q1->to.reg;
  363. /* ADD $8,SP */
  364. q = prg();
  365. q->link = p->link;
  366. p->link = q;
  367. p = q;
  368. p->as = AADD;
  369. p->from.type = D_CONST;
  370. p->from.reg = NREG;
  371. p->from.offset = 8;
  372. p->reg = NREG;
  373. p->to.type = D_REG;
  374. p->to.reg = REGSP;
  375. /* SUB $8,SP */
  376. q1->as = ASUB;
  377. q1->from.type = D_CONST;
  378. q1->from.offset = 8;
  379. q1->from.reg = NREG;
  380. q1->reg = NREG;
  381. q1->to.type = D_REG;
  382. q1->to.reg = REGSP;
  383. break;
  384. case ARETURN:
  385. if(p->from.type == D_CONST)
  386. goto become;
  387. if(curtext->mark & LEAF) {
  388. if(!autosize) {
  389. p->as = AJMP;
  390. p->from = zprg.from;
  391. p->to.type = D_OREG;
  392. p->to.offset = 8;
  393. p->to.reg = REGLINK;
  394. p->mark |= BRANCH;
  395. break;
  396. }
  397. p->as = AADD;
  398. p->from.type = D_CONST;
  399. p->from.offset = autosize;
  400. p->to.type = D_REG;
  401. p->to.reg = REGSP;
  402. q = prg();
  403. q->as = AJMP;
  404. q->line = p->line;
  405. q->to.type = D_OREG;
  406. q->to.offset = 8;
  407. q->to.reg = REGLINK;
  408. q->mark |= BRANCH;
  409. q->link = p->link;
  410. p->link = q;
  411. break;
  412. }
  413. p->as = AMOVW;
  414. p->from.type = D_OREG;
  415. p->from.offset = 0;
  416. p->from.reg = REGSP;
  417. p->to.type = D_REG;
  418. p->to.reg = REGRET+1;
  419. q = p;
  420. if(autosize) {
  421. q = prg();
  422. q->as = AADD;
  423. q->line = p->line;
  424. q->from.type = D_CONST;
  425. q->from.offset = autosize;
  426. q->to.type = D_REG;
  427. q->to.reg = REGSP;
  428. q->link = p->link;
  429. p->link = q;
  430. }
  431. q1 = prg();
  432. q1->as = AJMP;
  433. q1->line = p->line;
  434. q1->to.type = D_OREG;
  435. q1->to.offset = 8;
  436. q1->to.reg = REGRET+1;
  437. q1->mark |= BRANCH;
  438. q1->link = q->link;
  439. q->link = q1;
  440. break;
  441. become:
  442. if(curtext->mark & LEAF) {
  443. q = prg();
  444. q->line = p->line;
  445. q->as = AJMP;
  446. q->from = zprg.from;
  447. q->to = p->to;
  448. q->cond = p->cond;
  449. q->link = p->link;
  450. q->mark |= BRANCH;
  451. p->link = q;
  452. p->as = AADD;
  453. p->from = zprg.from;
  454. p->from.type = D_CONST;
  455. p->from.offset = autosize;
  456. p->to = zprg.to;
  457. p->to.type = D_REG;
  458. p->to.reg = REGSP;
  459. break;
  460. }
  461. q = prg();
  462. q->line = p->line;
  463. q->as = AJMP;
  464. q->from = zprg.from;
  465. q->to = p->to;
  466. q->cond = p->cond;
  467. q->mark |= BRANCH;
  468. q->link = p->link;
  469. p->link = q;
  470. q = prg();
  471. q->line = p->line;
  472. q->as = AADD;
  473. q->from.type = D_CONST;
  474. q->from.offset = autosize;
  475. q->to.type = D_REG;
  476. q->to.reg = REGSP;
  477. q->link = p->link;
  478. p->link = q;
  479. p->as = AMOVW;
  480. p->from = zprg.from;
  481. p->from.type = D_OREG;
  482. p->from.offset = 0;
  483. p->from.reg = REGSP;
  484. p->to = zprg.to;
  485. p->to.type = D_REG;
  486. p->to.reg = REGLINK;
  487. break;
  488. }
  489. }
  490. curtext = P;
  491. q = P; /* p - 1 */
  492. q1 = firstp; /* top of block */
  493. o = 0; /* count of instructions */
  494. for(p = firstp; p != P; p = p1) {
  495. p1 = p->link;
  496. o++;
  497. if(p->mark & NOSCHED){
  498. if(q1 != p){
  499. sched(q1, q);
  500. }
  501. for(; p != P; p = p->link){
  502. if(!(p->mark & NOSCHED))
  503. break;
  504. q = p;
  505. }
  506. p1 = p;
  507. q1 = p;
  508. o = 0;
  509. continue;
  510. }
  511. if(p->mark & (LABEL|SYNC)) {
  512. if(q1 != p)
  513. sched(q1, q);
  514. q1 = p;
  515. o = 1;
  516. }
  517. if(p->mark & (BRANCH|SYNC)) {
  518. sched(q1, p);
  519. q1 = p1;
  520. o = 0;
  521. }
  522. if(o >= NSCHED) {
  523. sched(q1, p);
  524. q1 = p1;
  525. o = 0;
  526. }
  527. q = p;
  528. }
  529. }
  530. void
  531. addnop(Prog *p)
  532. {
  533. Prog *q;
  534. q = prg();
  535. q->as = AORN;
  536. q->line = p->line;
  537. q->from.type = D_REG;
  538. q->from.reg = REGZERO;
  539. q->to.type = D_REG;
  540. q->to.reg = REGZERO;
  541. q->link = p->link;
  542. p->link = q;
  543. }
  544. void
  545. initmuldiv(void)
  546. {
  547. Sym *s1, *s2, *s3, *s4, *s5;
  548. Prog *p;
  549. s1 = lookup("_mul", 0);
  550. s2 = lookup("_div", 0);
  551. s3 = lookup("_divl", 0);
  552. s4 = lookup("_mod", 0);
  553. s5 = lookup("_modl", 0);
  554. for(p = firstp; p != P; p = p->link)
  555. if(p->as == ATEXT) {
  556. if(p->from.sym == s1)
  557. prog_mul = p;
  558. if(p->from.sym == s2)
  559. prog_div = p;
  560. if(p->from.sym == s3)
  561. prog_divl = p;
  562. if(p->from.sym == s4)
  563. prog_mod = p;
  564. if(p->from.sym == s5)
  565. prog_modl = p;
  566. }
  567. if(prog_mul == P) {
  568. diag("undefined: %s", s1->name);
  569. prog_mul = curtext;
  570. }
  571. if(prog_div == P) {
  572. diag("undefined: %s", s2->name);
  573. prog_div = curtext;
  574. }
  575. if(prog_divl == P) {
  576. diag("undefined: %s", s3->name);
  577. prog_divl = curtext;
  578. }
  579. if(prog_mod == P) {
  580. diag("undefined: %s", s4->name);
  581. prog_mod = curtext;
  582. }
  583. if(prog_modl == P) {
  584. diag("undefined: %s", s5->name);
  585. prog_modl = curtext;
  586. }
  587. }