peep.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "gc.h"
  10. int xtramodes(Reg*, Adr*);
  11. void
  12. peep(void)
  13. {
  14. Reg *r, *r1, *r2;
  15. Prog *p, *p1;
  16. int t;
  17. /*
  18. * complete R structure
  19. */
  20. t = 0;
  21. for(r=firstr; r!=R; r=r1) {
  22. r1 = r->link;
  23. if(r1 == R)
  24. break;
  25. p = r->prog->link;
  26. while(p != r1->prog)
  27. switch(p->as) {
  28. default:
  29. r2 = rega();
  30. r->link = r2;
  31. r2->link = r1;
  32. r2->prog = p;
  33. r2->p1 = r;
  34. r->s1 = r2;
  35. r2->s1 = r1;
  36. r1->p1 = r2;
  37. r = r2;
  38. t++;
  39. case ADATA:
  40. case AGLOBL:
  41. case ANAME:
  42. case ASIGNAME:
  43. p = p->link;
  44. }
  45. }
  46. loop1:
  47. t = 0;
  48. for(r=firstr; r!=R; r=r->link) {
  49. p = r->prog;
  50. if(p->as == ASLL || p->as == ASRL || p->as == ASRA) {
  51. /*
  52. * elide shift into D_SHIFT operand of subsequent instruction
  53. */
  54. if(shiftprop(r)) {
  55. excise(r);
  56. t++;
  57. }
  58. }
  59. if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
  60. if(regtyp(&p->to)) {
  61. if(p->from.type == D_CONST)
  62. constprop(&p->from, &p->to, r->s1);
  63. else if(regtyp(&p->from))
  64. if(p->from.type == p->to.type) {
  65. if(copyprop(r)) {
  66. excise(r);
  67. t++;
  68. } else
  69. if(subprop(r) && copyprop(r)) {
  70. excise(r);
  71. t++;
  72. }
  73. }
  74. }
  75. }
  76. if(t)
  77. goto loop1;
  78. /*
  79. * look for MOVB x,R; MOVB R,R
  80. */
  81. for(r=firstr; r!=R; r=r->link) {
  82. p = r->prog;
  83. switch(p->as) {
  84. default:
  85. continue;
  86. case AEOR:
  87. /*
  88. * EOR -1,x,y => MVN x,y
  89. */
  90. if(p->from.type == D_CONST && p->from.offset == -1) {
  91. p->as = AMVN;
  92. p->from.type = D_REG;
  93. if(p->reg != NREG)
  94. p->from.reg = p->reg;
  95. else
  96. p->from.reg = p->to.reg;
  97. p->reg = NREG;
  98. }
  99. continue;
  100. case AMOVH:
  101. case AMOVHU:
  102. case AMOVB:
  103. case AMOVBU:
  104. if(p->to.type != D_REG)
  105. continue;
  106. break;
  107. }
  108. r1 = r->link;
  109. if(r1 == R)
  110. continue;
  111. p1 = r1->prog;
  112. if(p1->as != p->as)
  113. continue;
  114. if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
  115. continue;
  116. if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
  117. continue;
  118. excise(r1);
  119. }
  120. for(r=firstr; r!=R; r=r->link) {
  121. p = r->prog;
  122. switch(p->as) {
  123. case AMOVW:
  124. case AMOVB:
  125. case AMOVBU:
  126. if(p->from.type == D_OREG && p->from.offset == 0)
  127. xtramodes(r, &p->from);
  128. else if(p->to.type == D_OREG && p->to.offset == 0)
  129. xtramodes(r, &p->to);
  130. else
  131. continue;
  132. break;
  133. case ACMP:
  134. /*
  135. * elide CMP $0,x if calculation of x can set condition codes
  136. */
  137. if(p->from.type != D_CONST || p->from.offset != 0)
  138. continue;
  139. r2 = r->s1;
  140. if(r2 == R)
  141. continue;
  142. t = r2->prog->as;
  143. switch(t) {
  144. default:
  145. continue;
  146. case ABEQ:
  147. case ABNE:
  148. case ABMI:
  149. case ABPL:
  150. break;
  151. case ABGE:
  152. t = ABPL;
  153. break;
  154. case ABLT:
  155. t = ABMI;
  156. break;
  157. case ABHI:
  158. t = ABNE;
  159. break;
  160. case ABLS:
  161. t = ABEQ;
  162. break;
  163. }
  164. r1 = r;
  165. do
  166. r1 = uniqp(r1);
  167. while (r1 != R && r1->prog->as == ANOP);
  168. if(r1 == R)
  169. continue;
  170. p1 = r1->prog;
  171. if(p1->to.type != D_REG)
  172. continue;
  173. if(p1->to.reg != p->reg)
  174. if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
  175. continue;
  176. switch(p1->as) {
  177. default:
  178. continue;
  179. case AMOVW:
  180. if(p1->from.type != D_REG)
  181. continue;
  182. case AAND:
  183. case AEOR:
  184. case AORR:
  185. case ABIC:
  186. case AMVN:
  187. case ASUB:
  188. case ARSB:
  189. case AADD:
  190. case AADC:
  191. case ASBC:
  192. case ARSC:
  193. break;
  194. }
  195. p1->scond |= C_SBIT;
  196. r2->prog->as = t;
  197. excise(r);
  198. continue;
  199. }
  200. }
  201. predicate();
  202. }
  203. void
  204. excise(Reg *r)
  205. {
  206. Prog *p;
  207. p = r->prog;
  208. p->as = ANOP;
  209. p->scond = zprog.scond;
  210. p->from = zprog.from;
  211. p->to = zprog.to;
  212. p->reg = zprog.reg; /**/
  213. }
  214. Reg*
  215. uniqp(Reg *r)
  216. {
  217. Reg *r1;
  218. r1 = r->p1;
  219. if(r1 == R) {
  220. r1 = r->p2;
  221. if(r1 == R || r1->p2link != R)
  222. return R;
  223. } else
  224. if(r->p2 != R)
  225. return R;
  226. return r1;
  227. }
  228. Reg*
  229. uniqs(Reg *r)
  230. {
  231. Reg *r1;
  232. r1 = r->s1;
  233. if(r1 == R) {
  234. r1 = r->s2;
  235. if(r1 == R)
  236. return R;
  237. } else
  238. if(r->s2 != R)
  239. return R;
  240. return r1;
  241. }
  242. int
  243. regtyp(Adr *a)
  244. {
  245. if(a->type == D_REG)
  246. return 1;
  247. if(a->type == D_FREG)
  248. return 1;
  249. return 0;
  250. }
  251. /*
  252. * the idea is to substitute
  253. * one register for another
  254. * from one MOV to another
  255. * MOV a, R0
  256. * ADD b, R0 / no use of R1
  257. * MOV R0, R1
  258. * would be converted to
  259. * MOV a, R1
  260. * ADD b, R1
  261. * MOV R1, R0
  262. * hopefully, then the former or latter MOV
  263. * will be eliminated by copy propagation.
  264. */
  265. int
  266. subprop(Reg *r0)
  267. {
  268. Prog *p;
  269. Adr *v1, *v2;
  270. Reg *r;
  271. int t;
  272. p = r0->prog;
  273. v1 = &p->from;
  274. if(!regtyp(v1))
  275. return 0;
  276. v2 = &p->to;
  277. if(!regtyp(v2))
  278. return 0;
  279. for(r=uniqp(r0); r!=R; r=uniqp(r)) {
  280. if(uniqs(r) == R)
  281. break;
  282. p = r->prog;
  283. switch(p->as) {
  284. case ABL:
  285. return 0;
  286. case ACMP:
  287. case ACMN:
  288. case AADD:
  289. case ASUB:
  290. case ARSB:
  291. case ASLL:
  292. case ASRL:
  293. case ASRA:
  294. case AORR:
  295. case AAND:
  296. case AEOR:
  297. case AMUL:
  298. case ADIV:
  299. case ADIVU:
  300. case ACMPF:
  301. case ACMPD:
  302. case AADDD:
  303. case AADDF:
  304. case ASUBD:
  305. case ASUBF:
  306. case AMULD:
  307. case AMULF:
  308. case ADIVD:
  309. case ADIVF:
  310. if(p->to.type == v1->type)
  311. if(p->to.reg == v1->reg) {
  312. if(p->reg == NREG)
  313. p->reg = p->to.reg;
  314. goto gotit;
  315. }
  316. break;
  317. case AMOVF:
  318. case AMOVD:
  319. case AMOVW:
  320. if(p->to.type == v1->type)
  321. if(p->to.reg == v1->reg)
  322. goto gotit;
  323. break;
  324. case AMOVM:
  325. t = 1<<v2->reg;
  326. if((p->from.type == D_CONST && (p->from.offset&t)) ||
  327. (p->to.type == D_CONST && (p->to.offset&t)))
  328. return 0;
  329. break;
  330. }
  331. if(copyau(&p->from, v2) ||
  332. copyau1(p, v2) ||
  333. copyau(&p->to, v2))
  334. break;
  335. if(copysub(&p->from, v1, v2, 0) ||
  336. copysub1(p, v1, v2, 0) ||
  337. copysub(&p->to, v1, v2, 0))
  338. break;
  339. }
  340. return 0;
  341. gotit:
  342. copysub(&p->to, v1, v2, 1);
  343. if(debug['P']) {
  344. print("gotit: %D->%D\n%P", v1, v2, r->prog);
  345. if(p->from.type == v2->type)
  346. print(" excise");
  347. print("\n");
  348. }
  349. for(r=uniqs(r); r!=r0; r=uniqs(r)) {
  350. p = r->prog;
  351. copysub(&p->from, v1, v2, 1);
  352. copysub1(p, v1, v2, 1);
  353. copysub(&p->to, v1, v2, 1);
  354. if(debug['P'])
  355. print("%P\n", r->prog);
  356. }
  357. t = v1->reg;
  358. v1->reg = v2->reg;
  359. v2->reg = t;
  360. if(debug['P'])
  361. print("%P last\n", r->prog);
  362. return 1;
  363. }
  364. /*
  365. * The idea is to remove redundant copies.
  366. * v1->v2 F=0
  367. * (use v2 s/v2/v1/)*
  368. * set v1 F=1
  369. * use v2 return fail
  370. * -----------------
  371. * v1->v2 F=0
  372. * (use v2 s/v2/v1/)*
  373. * set v1 F=1
  374. * set v2 return success
  375. */
  376. int
  377. copyprop(Reg *r0)
  378. {
  379. Prog *p;
  380. Adr *v1, *v2;
  381. Reg *r;
  382. p = r0->prog;
  383. v1 = &p->from;
  384. v2 = &p->to;
  385. if(copyas(v1, v2))
  386. return 1;
  387. for(r=firstr; r!=R; r=r->link)
  388. r->active = 0;
  389. return copy1(v1, v2, r0->s1, 0);
  390. }
  391. int
  392. copy1(Adr *v1, Adr *v2, Reg *r, int f)
  393. {
  394. int t;
  395. Prog *p;
  396. if(r->active) {
  397. if(debug['P'])
  398. print("act set; return 1\n");
  399. return 1;
  400. }
  401. r->active = 1;
  402. if(debug['P'])
  403. print("copy %D->%D f=%d\n", v1, v2, f);
  404. for(; r != R; r = r->s1) {
  405. p = r->prog;
  406. if(debug['P'])
  407. print("%P", p);
  408. if(!f && uniqp(r) == R) {
  409. f = 1;
  410. if(debug['P'])
  411. print("; merge; f=%d", f);
  412. }
  413. t = copyu(p, v2, A);
  414. switch(t) {
  415. case 2: /* rar, cant split */
  416. if(debug['P'])
  417. print("; %Drar; return 0\n", v2);
  418. return 0;
  419. case 3: /* set */
  420. if(debug['P'])
  421. print("; %Dset; return 1\n", v2);
  422. return 1;
  423. case 1: /* used, substitute */
  424. case 4: /* use and set */
  425. if(f) {
  426. if(!debug['P'])
  427. return 0;
  428. if(t == 4)
  429. print("; %Dused+set and f=%d; return 0\n", v2, f);
  430. else
  431. print("; %Dused and f=%d; return 0\n", v2, f);
  432. return 0;
  433. }
  434. if(copyu(p, v2, v1)) {
  435. if(debug['P'])
  436. print("; sub fail; return 0\n");
  437. return 0;
  438. }
  439. if(debug['P'])
  440. print("; sub%D/%D", v2, v1);
  441. if(t == 4) {
  442. if(debug['P'])
  443. print("; %Dused+set; return 1\n", v2);
  444. return 1;
  445. }
  446. break;
  447. }
  448. if(!f) {
  449. t = copyu(p, v1, A);
  450. if(!f && (t == 2 || t == 3 || t == 4)) {
  451. f = 1;
  452. if(debug['P'])
  453. print("; %Dset and !f; f=%d", v1, f);
  454. }
  455. }
  456. if(debug['P'])
  457. print("\n");
  458. if(r->s2)
  459. if(!copy1(v1, v2, r->s2, f))
  460. return 0;
  461. }
  462. return 1;
  463. }
  464. /*
  465. * The idea is to remove redundant constants.
  466. * $c1->v1
  467. * ($c1->v2 s/$c1/v1)*
  468. * set v1 return
  469. * The v1->v2 should be eliminated by copy propagation.
  470. */
  471. void
  472. constprop(Adr *c1, Adr *v1, Reg *r)
  473. {
  474. Prog *p;
  475. if(debug['C'])
  476. print("constprop %D->%D\n", c1, v1);
  477. for(; r != R; r = r->s1) {
  478. p = r->prog;
  479. if(debug['C'])
  480. print("%P", p);
  481. if(uniqp(r) == R) {
  482. if(debug['C'])
  483. print("; merge; return\n");
  484. return;
  485. }
  486. if(p->as == AMOVW && copyas(&p->from, c1)) {
  487. if(debug['C'])
  488. print("; sub%D/%D", &p->from, v1);
  489. p->from = *v1;
  490. } else if(copyu(p, v1, A) > 1) {
  491. if(debug['C'])
  492. print("; %Dset; return\n", v1);
  493. return;
  494. }
  495. if(debug['C'])
  496. print("\n");
  497. if(r->s2)
  498. constprop(c1, v1, r->s2);
  499. }
  500. }
  501. /*
  502. * ASLL x,y,w
  503. * .. (not use w, not set x y w)
  504. * AXXX w,a,b (a != w)
  505. * .. (not use w)
  506. * (set w)
  507. * ----------- changed to
  508. * ..
  509. * AXXX (x<<y),a,b
  510. * ..
  511. */
  512. #define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
  513. int
  514. shiftprop(Reg *r)
  515. {
  516. Reg *r1;
  517. Prog *p, *p1, *p2;
  518. int n, o;
  519. Adr a;
  520. p = r->prog;
  521. if(p->to.type != D_REG)
  522. FAIL("BOTCH: result not reg");
  523. n = p->to.reg;
  524. a = zprog.from;
  525. if(p->reg != NREG && p->reg != p->to.reg) {
  526. a.type = D_REG;
  527. a.reg = p->reg;
  528. }
  529. if(debug['H'])
  530. print("shiftprop\n%P", p);
  531. r1 = r;
  532. for(;;) {
  533. /* find first use of shift result; abort if shift operands or result are changed */
  534. r1 = uniqs(r1);
  535. if(r1 == R)
  536. FAIL("branch");
  537. if(uniqp(r1) == R)
  538. FAIL("merge");
  539. p1 = r1->prog;
  540. if(debug['H'])
  541. print("\n%P", p1);
  542. switch(copyu(p1, &p->to, A)) {
  543. case 0: /* not used or set */
  544. if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
  545. (a.type == D_REG && copyu(p1, &a, A) > 1))
  546. FAIL("args modified");
  547. continue;
  548. case 3: /* set, not used */
  549. FAIL("BOTCH: noref");
  550. }
  551. break;
  552. }
  553. /* check whether substitution can be done */
  554. switch(p1->as) {
  555. default:
  556. FAIL("non-dpi");
  557. case AAND:
  558. case AEOR:
  559. case AADD:
  560. case AADC:
  561. case AORR:
  562. case ASUB:
  563. case ARSB:
  564. case ASBC:
  565. case ARSC:
  566. if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
  567. if(p1->from.type != D_REG)
  568. FAIL("can't swap");
  569. p1->reg = p1->from.reg;
  570. p1->from.reg = n;
  571. switch(p1->as) {
  572. case ASUB:
  573. p1->as = ARSB;
  574. break;
  575. case ARSB:
  576. p1->as = ASUB;
  577. break;
  578. case ASBC:
  579. p1->as = ARSC;
  580. break;
  581. case ARSC:
  582. p1->as = ASBC;
  583. break;
  584. }
  585. if(debug['H'])
  586. print("\t=>%P", p1);
  587. }
  588. case ABIC:
  589. case ACMP:
  590. case ACMN:
  591. if(p1->reg == n)
  592. FAIL("can't swap");
  593. if(p1->reg == NREG && p1->to.reg == n)
  594. FAIL("shift result used twice");
  595. case AMVN:
  596. if(p1->from.type == D_SHIFT)
  597. FAIL("shift result used in shift");
  598. if(p1->from.type != D_REG || p1->from.reg != n)
  599. FAIL("BOTCH: where is it used?");
  600. break;
  601. }
  602. /* check whether shift result is used subsequently */
  603. p2 = p1;
  604. if(p1->to.reg != n)
  605. for (;;) {
  606. r1 = uniqs(r1);
  607. if(r1 == R)
  608. FAIL("inconclusive");
  609. p1 = r1->prog;
  610. if(debug['H'])
  611. print("\n%P", p1);
  612. switch(copyu(p1, &p->to, A)) {
  613. case 0: /* not used or set */
  614. continue;
  615. case 3: /* set, not used */
  616. break;
  617. default:/* used */
  618. FAIL("reused");
  619. }
  620. break;
  621. }
  622. /* make the substitution */
  623. p2->from.type = D_SHIFT;
  624. p2->from.reg = NREG;
  625. o = p->reg;
  626. if(o == NREG)
  627. o = p->to.reg;
  628. switch(p->from.type){
  629. case D_CONST:
  630. o |= (p->from.offset&0x1f)<<7;
  631. break;
  632. case D_REG:
  633. o |= (1<<4) | (p->from.reg<<8);
  634. break;
  635. }
  636. switch(p->as){
  637. case ASLL:
  638. o |= 0<<5;
  639. break;
  640. case ASRL:
  641. o |= 1<<5;
  642. break;
  643. case ASRA:
  644. o |= 2<<5;
  645. break;
  646. }
  647. p2->from.offset = o;
  648. if(debug['H'])
  649. print("\t=>%P\tSUCCEED\n", p2);
  650. return 1;
  651. }
  652. Reg*
  653. findpre(Reg *r, Adr *v)
  654. {
  655. Reg *r1;
  656. for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
  657. if(uniqs(r1) != r)
  658. return R;
  659. switch(copyu(r1->prog, v, A)) {
  660. case 1: /* used */
  661. case 2: /* read-alter-rewrite */
  662. return R;
  663. case 3: /* set */
  664. case 4: /* set and used */
  665. return r1;
  666. }
  667. }
  668. return R;
  669. }
  670. Reg*
  671. findinc(Reg *r, Reg *r2, Adr *v)
  672. {
  673. Reg *r1;
  674. Prog *p;
  675. for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
  676. if(uniqp(r1) != r)
  677. return R;
  678. switch(copyu(r1->prog, v, A)) {
  679. case 0: /* not touched */
  680. continue;
  681. case 4: /* set and used */
  682. p = r1->prog;
  683. if(p->as == AADD)
  684. if(p->from.type == D_CONST)
  685. if(p->from.offset > -4096 && p->from.offset < 4096)
  686. return r1;
  687. default:
  688. return R;
  689. }
  690. }
  691. return R;
  692. }
  693. int
  694. nochange(Reg *r, Reg *r2, Prog *p)
  695. {
  696. Adr a[3];
  697. int i, n;
  698. if(r == r2)
  699. return 1;
  700. n = 0;
  701. if(p->reg != NREG && p->reg != p->to.reg) {
  702. a[n].type = D_REG;
  703. a[n++].reg = p->reg;
  704. }
  705. switch(p->from.type) {
  706. case D_SHIFT:
  707. a[n].type = D_REG;
  708. a[n++].reg = p->from.offset&0xf;
  709. case D_REG:
  710. a[n].type = D_REG;
  711. a[n++].reg = p->from.reg;
  712. }
  713. if(n == 0)
  714. return 1;
  715. for(; r!=R && r!=r2; r=uniqs(r)) {
  716. p = r->prog;
  717. for(i=0; i<n; i++)
  718. if(copyu(p, &a[i], A) > 1)
  719. return 0;
  720. }
  721. return 1;
  722. }
  723. int
  724. findu1(Reg *r, Adr *v)
  725. {
  726. for(; r != R; r = r->s1) {
  727. if(r->active)
  728. return 0;
  729. r->active = 1;
  730. switch(copyu(r->prog, v, A)) {
  731. case 1: /* used */
  732. case 2: /* read-alter-rewrite */
  733. case 4: /* set and used */
  734. return 1;
  735. case 3: /* set */
  736. return 0;
  737. }
  738. if(r->s2)
  739. if (findu1(r->s2, v))
  740. return 1;
  741. }
  742. return 0;
  743. }
  744. int
  745. finduse(Reg *r, Adr *v)
  746. {
  747. Reg *r1;
  748. for(r1=firstr; r1!=R; r1=r1->link)
  749. r1->active = 0;
  750. return findu1(r, v);
  751. }
  752. int
  753. xtramodes(Reg *r, Adr *a)
  754. {
  755. Reg *r1, *r2, *r3;
  756. Prog *p, *p1;
  757. Adr v;
  758. p = r->prog;
  759. if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG) /* byte load */
  760. return 0;
  761. v = *a;
  762. v.type = D_REG;
  763. r1 = findpre(r, &v);
  764. if(r1 != R) {
  765. p1 = r1->prog;
  766. if(p1->to.type == D_REG && p1->to.reg == v.reg)
  767. switch(p1->as) {
  768. case AADD:
  769. if(p1->from.type == D_REG ||
  770. (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
  771. (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
  772. (p1->from.type == D_CONST &&
  773. p1->from.offset > -4096 && p1->from.offset < 4096))
  774. if(nochange(uniqs(r1), r, p1)) {
  775. if(a != &p->from || v.reg != p->to.reg)
  776. if (finduse(r->s1, &v)) {
  777. if(p1->reg == NREG || p1->reg == v.reg)
  778. /* pre-indexing */
  779. p->scond |= C_WBIT;
  780. else return 0;
  781. }
  782. switch (p1->from.type) {
  783. case D_REG:
  784. /* register offset */
  785. a->type = D_SHIFT;
  786. a->offset = p1->from.reg;
  787. break;
  788. case D_SHIFT:
  789. /* scaled register offset */
  790. a->type = D_SHIFT;
  791. case D_CONST:
  792. /* immediate offset */
  793. a->offset = p1->from.offset;
  794. break;
  795. }
  796. if(p1->reg != NREG)
  797. a->reg = p1->reg;
  798. excise(r1);
  799. return 1;
  800. }
  801. break;
  802. case AMOVW:
  803. if(p1->from.type == D_REG)
  804. if((r2 = findinc(r1, r, &p1->from)) != R) {
  805. for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
  806. ;
  807. if(r3 == r) {
  808. /* post-indexing */
  809. p1 = r2->prog;
  810. a->reg = p1->to.reg;
  811. a->offset = p1->from.offset;
  812. p->scond |= C_PBIT;
  813. if(!finduse(r, &r1->prog->to))
  814. excise(r1);
  815. excise(r2);
  816. return 1;
  817. }
  818. }
  819. break;
  820. }
  821. }
  822. if(a != &p->from || a->reg != p->to.reg)
  823. if((r1 = findinc(r, R, &v)) != R) {
  824. /* post-indexing */
  825. p1 = r1->prog;
  826. a->offset = p1->from.offset;
  827. p->scond |= C_PBIT;
  828. excise(r1);
  829. return 1;
  830. }
  831. return 0;
  832. }
  833. /*
  834. * return
  835. * 1 if v only used (and substitute),
  836. * 2 if read-alter-rewrite
  837. * 3 if set
  838. * 4 if set and used
  839. * 0 otherwise (not touched)
  840. */
  841. int
  842. copyu(Prog *p, Adr *v, Adr *s)
  843. {
  844. switch(p->as) {
  845. default:
  846. if(debug['P'])
  847. print(" (???)");
  848. return 2;
  849. case AMOVM:
  850. if(v->type != D_REG)
  851. return 0;
  852. if(p->from.type == D_CONST) { /* read reglist, read/rar */
  853. if(s != A) {
  854. if(p->from.offset&(1<<v->reg))
  855. return 1;
  856. if(copysub(&p->to, v, s, 1))
  857. return 1;
  858. return 0;
  859. }
  860. if(copyau(&p->to, v)) {
  861. if(p->scond&C_WBIT)
  862. return 2;
  863. return 1;
  864. }
  865. if(p->from.offset&(1<<v->reg))
  866. return 1;
  867. } else { /* read/rar, write reglist */
  868. if(s != A) {
  869. if(p->to.offset&(1<<v->reg))
  870. return 1;
  871. if(copysub(&p->from, v, s, 1))
  872. return 1;
  873. return 0;
  874. }
  875. if(copyau(&p->from, v)) {
  876. if(p->scond&C_WBIT)
  877. return 2;
  878. if(p->to.offset&(1<<v->reg))
  879. return 4;
  880. return 1;
  881. }
  882. if(p->to.offset&(1<<v->reg))
  883. return 3;
  884. }
  885. return 0;
  886. case ANOP: /* read, write */
  887. case AMOVW:
  888. case AMOVF:
  889. case AMOVD:
  890. case AMOVH:
  891. case AMOVHU:
  892. case AMOVB:
  893. case AMOVBU:
  894. case AMOVDW:
  895. case AMOVWD:
  896. case AMOVFD:
  897. case AMOVDF:
  898. if(p->scond&(C_WBIT|C_PBIT))
  899. if(v->type == D_REG) {
  900. if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
  901. if(p->from.reg == v->reg)
  902. return 2;
  903. } else {
  904. if(p->to.reg == v->reg)
  905. return 2;
  906. }
  907. }
  908. if(s != A) {
  909. if(copysub(&p->from, v, s, 1))
  910. return 1;
  911. if(!copyas(&p->to, v))
  912. if(copysub(&p->to, v, s, 1))
  913. return 1;
  914. return 0;
  915. }
  916. if(copyas(&p->to, v)) {
  917. if(copyau(&p->from, v))
  918. return 4;
  919. return 3;
  920. }
  921. if(copyau(&p->from, v))
  922. return 1;
  923. if(copyau(&p->to, v))
  924. return 1;
  925. return 0;
  926. case AADD: /* read, read, write */
  927. case ASUB:
  928. case ARSB:
  929. case ASLL:
  930. case ASRL:
  931. case ASRA:
  932. case AORR:
  933. case AAND:
  934. case AEOR:
  935. case AMUL:
  936. case ADIV:
  937. case ADIVU:
  938. case AADDF:
  939. case AADDD:
  940. case ASUBF:
  941. case ASUBD:
  942. case AMULF:
  943. case AMULD:
  944. case ADIVF:
  945. case ADIVD:
  946. case ACMPF:
  947. case ACMPD:
  948. case ACMP:
  949. case ACMN:
  950. case ACASE:
  951. if(s != A) {
  952. if(copysub(&p->from, v, s, 1))
  953. return 1;
  954. if(copysub1(p, v, s, 1))
  955. return 1;
  956. if(!copyas(&p->to, v))
  957. if(copysub(&p->to, v, s, 1))
  958. return 1;
  959. return 0;
  960. }
  961. if(copyas(&p->to, v)) {
  962. if(p->reg == NREG)
  963. p->reg = p->to.reg;
  964. if(copyau(&p->from, v))
  965. return 4;
  966. if(copyau1(p, v))
  967. return 4;
  968. return 3;
  969. }
  970. if(copyau(&p->from, v))
  971. return 1;
  972. if(copyau1(p, v))
  973. return 1;
  974. if(copyau(&p->to, v))
  975. return 1;
  976. return 0;
  977. case ABEQ: /* read, read */
  978. case ABNE:
  979. case ABCS:
  980. case ABHS:
  981. case ABCC:
  982. case ABLO:
  983. case ABMI:
  984. case ABPL:
  985. case ABVS:
  986. case ABVC:
  987. case ABHI:
  988. case ABLS:
  989. case ABGE:
  990. case ABLT:
  991. case ABGT:
  992. case ABLE:
  993. if(s != A) {
  994. if(copysub(&p->from, v, s, 1))
  995. return 1;
  996. return copysub1(p, v, s, 1);
  997. }
  998. if(copyau(&p->from, v))
  999. return 1;
  1000. if(copyau1(p, v))
  1001. return 1;
  1002. return 0;
  1003. case AB: /* funny */
  1004. if(s != A) {
  1005. if(copysub(&p->to, v, s, 1))
  1006. return 1;
  1007. return 0;
  1008. }
  1009. if(copyau(&p->to, v))
  1010. return 1;
  1011. return 0;
  1012. case ARET: /* funny */
  1013. if(v->type == D_REG)
  1014. if(v->reg == REGRET)
  1015. return 2;
  1016. if(v->type == D_FREG)
  1017. if(v->reg == FREGRET)
  1018. return 2;
  1019. case ABL: /* funny */
  1020. if(v->type == D_REG) {
  1021. if(v->reg <= REGEXT && v->reg > exregoffset)
  1022. return 2;
  1023. if(v->reg == (uint8_t)REGARG)
  1024. return 2;
  1025. }
  1026. if(v->type == D_FREG)
  1027. if(v->reg <= FREGEXT && v->reg > exfregoffset)
  1028. return 2;
  1029. if(s != A) {
  1030. if(copysub(&p->to, v, s, 1))
  1031. return 1;
  1032. return 0;
  1033. }
  1034. if(copyau(&p->to, v))
  1035. return 4;
  1036. return 3;
  1037. case ATEXT: /* funny */
  1038. if(v->type == D_REG)
  1039. if(v->reg == (uint8_t)REGARG)
  1040. return 3;
  1041. return 0;
  1042. }
  1043. }
  1044. int
  1045. a2type(Prog *p)
  1046. {
  1047. switch(p->as) {
  1048. case ACMP:
  1049. case ACMN:
  1050. case AADD:
  1051. case ASUB:
  1052. case ARSB:
  1053. case ASLL:
  1054. case ASRL:
  1055. case ASRA:
  1056. case AORR:
  1057. case AAND:
  1058. case AEOR:
  1059. case AMUL:
  1060. case ADIV:
  1061. case ADIVU:
  1062. return D_REG;
  1063. case ACMPF:
  1064. case ACMPD:
  1065. case AADDF:
  1066. case AADDD:
  1067. case ASUBF:
  1068. case ASUBD:
  1069. case AMULF:
  1070. case AMULD:
  1071. case ADIVF:
  1072. case ADIVD:
  1073. return D_FREG;
  1074. }
  1075. return D_NONE;
  1076. }
  1077. /*
  1078. * direct reference,
  1079. * could be set/use depending on
  1080. * semantics
  1081. */
  1082. int
  1083. copyas(Adr *a, Adr *v)
  1084. {
  1085. if(regtyp(v)) {
  1086. if(a->type == v->type)
  1087. if(a->reg == v->reg)
  1088. return 1;
  1089. } else if(v->type == D_CONST) { /* for constprop */
  1090. if(a->type == v->type)
  1091. if(a->name == v->name)
  1092. if(a->sym == v->sym)
  1093. if(a->reg == v->reg)
  1094. if(a->offset == v->offset)
  1095. return 1;
  1096. }
  1097. return 0;
  1098. }
  1099. /*
  1100. * either direct or indirect
  1101. */
  1102. int
  1103. copyau(Adr *a, Adr *v)
  1104. {
  1105. if(copyas(a, v))
  1106. return 1;
  1107. if(v->type == D_REG) {
  1108. if(a->type == D_OREG) {
  1109. if(v->reg == a->reg)
  1110. return 1;
  1111. } else if(a->type == D_SHIFT) {
  1112. if((a->offset&0xf) == v->reg)
  1113. return 1;
  1114. if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
  1115. return 1;
  1116. }
  1117. }
  1118. return 0;
  1119. }
  1120. int
  1121. copyau1(Prog *p, Adr *v)
  1122. {
  1123. if(regtyp(v)) {
  1124. if(a2type(p) == v->type)
  1125. if(p->reg == v->reg) {
  1126. if(a2type(p) != v->type)
  1127. print("botch a2type %P\n", p);
  1128. return 1;
  1129. }
  1130. }
  1131. return 0;
  1132. }
  1133. /*
  1134. * substitute s for v in a
  1135. * return failure to substitute
  1136. */
  1137. int
  1138. copysub(Adr *a, Adr *v, Adr *s, int f)
  1139. {
  1140. if(f)
  1141. if(copyau(a, v)) {
  1142. if(a->type == D_SHIFT) {
  1143. if((a->offset&0xf) == v->reg)
  1144. a->offset = (a->offset&~0xf)|s->reg;
  1145. if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
  1146. a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
  1147. } else
  1148. a->reg = s->reg;
  1149. }
  1150. return 0;
  1151. }
  1152. int
  1153. copysub1(Prog *p1, Adr *v, Adr *s, int f)
  1154. {
  1155. if(f)
  1156. if(copyau1(p1, v))
  1157. p1->reg = s->reg;
  1158. return 0;
  1159. }
  1160. struct {
  1161. int opcode;
  1162. int notopcode;
  1163. int scond;
  1164. int notscond;
  1165. } predinfo[] = {
  1166. { ABEQ, ABNE, 0x0, 0x1, },
  1167. { ABNE, ABEQ, 0x1, 0x0, },
  1168. { ABCS, ABCC, 0x2, 0x3, },
  1169. { ABHS, ABLO, 0x2, 0x3, },
  1170. { ABCC, ABCS, 0x3, 0x2, },
  1171. { ABLO, ABHS, 0x3, 0x2, },
  1172. { ABMI, ABPL, 0x4, 0x5, },
  1173. { ABPL, ABMI, 0x5, 0x4, },
  1174. { ABVS, ABVC, 0x6, 0x7, },
  1175. { ABVC, ABVS, 0x7, 0x6, },
  1176. { ABHI, ABLS, 0x8, 0x9, },
  1177. { ABLS, ABHI, 0x9, 0x8, },
  1178. { ABGE, ABLT, 0xA, 0xB, },
  1179. { ABLT, ABGE, 0xB, 0xA, },
  1180. { ABGT, ABLE, 0xC, 0xD, },
  1181. { ABLE, ABGT, 0xD, 0xC, },
  1182. };
  1183. typedef struct {
  1184. Reg *start;
  1185. Reg *last;
  1186. Reg *end;
  1187. int len;
  1188. } Joininfo;
  1189. enum {
  1190. Join,
  1191. Split,
  1192. End,
  1193. Branch,
  1194. Setcond,
  1195. Toolong
  1196. };
  1197. enum {
  1198. Falsecond,
  1199. Truecond,
  1200. Delbranch,
  1201. Keepbranch
  1202. };
  1203. int
  1204. isbranch(Prog *p)
  1205. {
  1206. return (ABEQ <= p->as) && (p->as <= ABLE);
  1207. }
  1208. int
  1209. predicable(Prog *p)
  1210. {
  1211. if (isbranch(p)
  1212. || p->as == ANOP
  1213. || p->as == AXXX
  1214. || p->as == ADATA
  1215. || p->as == AGLOBL
  1216. || p->as == AGOK
  1217. || p->as == AHISTORY
  1218. || p->as == ANAME
  1219. || p->as == ASIGNAME
  1220. || p->as == ATEXT
  1221. || p->as == AWORD
  1222. || p->as == ADYNT
  1223. || p->as == AINIT
  1224. || p->as == ABCASE
  1225. || p->as == ACASE)
  1226. return 0;
  1227. return 1;
  1228. }
  1229. /*
  1230. * Depends on an analysis of the encodings performed by 5l.
  1231. * These seem to be all of the opcodes that lead to the "S" bit
  1232. * being set in the instruction encodings.
  1233. *
  1234. * C_SBIT may also have been set explicitly in p->scond.
  1235. */
  1236. int
  1237. modifiescpsr(Prog *p)
  1238. {
  1239. return (p->scond&C_SBIT)
  1240. || p->as == ATST
  1241. || p->as == ATEQ
  1242. || p->as == ACMN
  1243. || p->as == ACMP
  1244. || p->as == AMULU
  1245. || p->as == ADIVU
  1246. || p->as == AMUL
  1247. || p->as == ADIV
  1248. || p->as == AMOD
  1249. || p->as == AMODU
  1250. || p->as == ABL;
  1251. }
  1252. /*
  1253. * Find the maximal chain of instructions starting with r which could
  1254. * be executed conditionally
  1255. */
  1256. int
  1257. joinsplit(Reg *r, Joininfo *j)
  1258. {
  1259. j->start = r;
  1260. j->last = r;
  1261. j->len = 0;
  1262. do {
  1263. if (r->p2 && (r->p1 || r->p2->p2link)) {
  1264. j->end = r;
  1265. return Join;
  1266. }
  1267. if (r->s1 && r->s2) {
  1268. j->end = r;
  1269. return Split;
  1270. }
  1271. j->last = r;
  1272. if (r->prog->as != ANOP)
  1273. j->len++;
  1274. if (!r->s1 && !r->s2) {
  1275. j->end = r->link;
  1276. return End;
  1277. }
  1278. if (r->s2) {
  1279. j->end = r->s2;
  1280. return Branch;
  1281. }
  1282. if (modifiescpsr(r->prog)) {
  1283. j->end = r->s1;
  1284. return Setcond;
  1285. }
  1286. r = r->s1;
  1287. } while (j->len < 4);
  1288. j->end = r;
  1289. return Toolong;
  1290. }
  1291. Reg *
  1292. successor(Reg *r)
  1293. {
  1294. if (r->s1)
  1295. return r->s1;
  1296. else
  1297. return r->s2;
  1298. }
  1299. void
  1300. applypred(Reg *rstart, Joininfo *j, int cond, int branch)
  1301. {
  1302. int pred;
  1303. Reg *r;
  1304. if(j->len == 0)
  1305. return;
  1306. if (cond == Truecond)
  1307. pred = predinfo[rstart->prog->as - ABEQ].scond;
  1308. else
  1309. pred = predinfo[rstart->prog->as - ABEQ].notscond;
  1310. for (r = j->start; ; r = successor(r)) {
  1311. if (r->prog->as == AB) {
  1312. if (r != j->last || branch == Delbranch)
  1313. excise(r);
  1314. else {
  1315. if (cond == Truecond)
  1316. r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
  1317. else
  1318. r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
  1319. }
  1320. }
  1321. else if (predicable(r->prog))
  1322. r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
  1323. if (r->s1 != r->link) {
  1324. r->s1 = r->link;
  1325. r->link->p1 = r;
  1326. }
  1327. if (r == j->last)
  1328. break;
  1329. }
  1330. }
  1331. void
  1332. predicate(void)
  1333. {
  1334. Reg *r;
  1335. int t1, t2;
  1336. Joininfo j1, j2;
  1337. for(r=firstr; r!=R; r=r->link) {
  1338. if (isbranch(r->prog)) {
  1339. t1 = joinsplit(r->s1, &j1);
  1340. t2 = joinsplit(r->s2, &j2);
  1341. if(j1.last->link != j2.start)
  1342. continue;
  1343. if(j1.end == j2.end)
  1344. if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
  1345. (t2 == Join && (t1 == Join || t1 == Setcond))) {
  1346. applypred(r, &j1, Falsecond, Delbranch);
  1347. applypred(r, &j2, Truecond, Delbranch);
  1348. excise(r);
  1349. continue;
  1350. }
  1351. if(t1 == End || t1 == Branch) {
  1352. applypred(r, &j1, Falsecond, Keepbranch);
  1353. excise(r);
  1354. continue;
  1355. }
  1356. }
  1357. }
  1358. }