3 int xtramodes(Reg*, Adr*);
5 Reg* findpre(Reg *r, Adr *v);
6 Reg* findinc(Reg *r, Reg *r2, Adr *v);
15 * complete R structure
18 for(r=firstr; r!=R; r=r1) {
49 for(r=firstr; r!=R; r=r->link) {
51 if(p->as == ALSL || p->as == ALSR || p->as == AASR ||
52 p->as == ALSLW || p->as == ALSRW || p->as == AASRW) {
54 * elide shift into D_SHIFT operand of subsequent instruction
56 if(0 && shiftprop(r)) {
62 r1 = findpre(r, &p->from);
76 if(p->as == AMOV || p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
78 if(p->from.type == D_CONST)
79 constprop(&p->from, &p->to, r->s1);
80 else if(regtyp(&p->from))
81 if(p->from.type == p->to.type) {
86 if(subprop(r) && copyprop(r)) {
92 if(p->to.type == D_REG) {
94 p->from.reg = REGZERO;
99 if(subprop(r) && copyprop(r)) {
109 * look for MOVB x,R; MOVB R,R
111 for(r=firstr; r!=R; r=r->link) {
118 * EOR -1,x,y => MVN x,y
120 if(p->from.type == D_CONST && p->from.offset == -1) {
122 p->from.type = D_REG;
124 p->from.reg = p->reg;
126 p->from.reg = p->to.reg;
132 * EOR -1,x,y => MVN x,y
134 if(p->from.type == D_CONST && (p->from.offset&0xFFFFFFFF)==0xFFFFFFFF){
136 p->from.type = D_REG;
138 p->from.reg = p->reg;
140 p->from.reg = p->to.reg;
150 if(p->to.type != D_REG)
160 if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
162 if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
168 for(r=firstr; r!=R; r=r->link) {
174 if(p->from.type == D_OREG && p->from.offset == 0)
175 xtramodes(r, &p->from);
176 else if(p->to.type == D_OREG && p->to.offset == 0)
177 xtramodes(r, &p->to);
183 * elide CMP $0,x if calculation of x can set condition codes
185 if(p->from.type != D_CONST || p->from.offset != 0)
215 while (r1 != R && r1->prog->as == ANOP);
219 if(p1->to.type != D_REG)
221 if(p1->to.reg != p->reg)
222 if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
228 if(p1->from.type != D_REG)
261 p->scond = zprog.scond;
262 p->from = zprog.from;
264 p->reg = zprog.reg; /**/
275 if(r1 == R || r1->p2link != R)
300 * convert references to $0 to references to ZR (REGZERO)
308 return a->sym == S && a->offset == 0;
310 return a->reg == REGZERO;
319 if(a->type == D_REG){
320 if(a->reg == REGZERO)
324 if(a->type == D_FREG)
330 * the idea is to substitute
331 * one register for another
332 * from one MOV to another
334 * ADD b, R0 / no use of R1
336 * would be converted to
340 * hopefully, then the former or latter MOV
341 * will be eliminated by copy propagation.
358 for(r=uniqp(r0); r!=R; r=uniqp(r)) {
418 if(p->to.type == v1->type)
419 if(p->to.reg == v1->reg) {
447 if(p->to.type == v1->type)
448 if(p->to.reg == v1->reg)
453 if(copyau(&p->from, v2) ||
457 if(copysub(&p->from, v1, v2, 0) ||
458 copysub1(p, v1, v2, 0) ||
459 copysub(&p->to, v1, v2, 0))
465 copysub(&p->to, v1, v2, 1);
467 print("gotit: %D->%D\n%P", v1, v2, r->prog);
468 if(p->from.type == v2->type)
472 for(r=uniqs(r); r!=r0; r=uniqs(r)) {
474 copysub(&p->from, v1, v2, 1);
475 copysub1(p, v1, v2, 1);
476 copysub(&p->to, v1, v2, 1);
478 print("%P\n", r->prog);
484 print("%P last\n", r->prog);
489 * The idea is to remove redundant copies.
498 * set v2 return success
512 for(r=firstr; r!=R; r=r->link)
514 return copy1(v1, v2, r0->s1, 0);
518 copy1(Adr *v1, Adr *v2, Reg *r, int f)
525 print("act set; return 1\n");
530 print("copy %D->%D f=%d\n", v1, v2, f);
531 for(; r != R; r = r->s1) {
535 if(!f && uniqp(r) == R) {
538 print("; merge; f=%d", f);
542 case 2: /* rar, cant split */
544 print("; %Drar; return 0\n", v2);
549 print("; %Dset; return 1\n", v2);
552 case 1: /* used, substitute */
553 case 4: /* use and set */
558 print("; %Dused+set and f=%d; return 0\n", v2, f);
560 print("; %Dused and f=%d; return 0\n", v2, f);
563 if(copyu(p, v2, v1)) {
565 print("; sub fail; return 0\n");
569 print("; sub%D/%D", v2, v1);
572 print("; %Dused+set; return 1\n", v2);
579 if(!f && (t == 2 || t == 3 || t == 4)) {
582 print("; %Dset and !f; f=%d", v1, f);
588 if(!copy1(v1, v2, r->s2, f))
595 * The idea is to remove redundant constants.
597 * ($c1->v2 s/$c1/v1)*
599 * The v1->v2 should be eliminated by copy propagation.
602 constprop(Adr *c1, Adr *v1, Reg *r)
607 print("constprop %D->%D\n", c1, v1);
608 for(; r != R; r = r->s1) {
614 print("; merge; return\n");
617 if(p->as == AMOVW && copyas(&p->from, c1)) {
619 print("; sub%D/%D", &p->from, v1);
621 } else if(copyu(p, v1, A) > 1) {
623 print("; %Dset; return\n", v1);
629 constprop(c1, v1, r->s2);
635 * .. (not use w, not set x y w)
636 * AXXX w,a,b (a != w)
639 * ----------- changed to
644 #define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
654 if(p->to.type != D_REG)
655 FAIL("BOTCH: result not reg");
658 if(p->reg != NREG && p->reg != p->to.reg) {
663 print("shiftprop\n%P", p);
666 /* find first use of shift result; abort if shift operands or result are changed */
675 switch(copyu(p1, &p->to, A)) {
676 case 0: /* not used or set */
677 if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
678 (a.type == D_REG && copyu(p1, &a, A) > 1))
679 FAIL("args modified");
681 case 3: /* set, not used */
682 FAIL("BOTCH: noref");
686 /* check whether substitution can be done */
693 if(p1->reg == NREG && p1->to.reg == n)
694 FAIL("shift result used twice");
696 if(p1->from.type == D_SHIFT)
697 FAIL("shift result used in shift");
698 if(p1->from.type != D_REG || p1->from.reg != n)
699 FAIL("BOTCH: where is it used?");
702 /* check whether shift result is used subsequently */
708 FAIL("inconclusive");
712 switch(copyu(p1, &p->to, A)) {
713 case 0: /* not used or set */
715 case 3: /* set, not used */
722 /* make the substitution */
723 p2->from.type = D_SHIFT;
728 switch(p->from.type){
730 o |= (p->from.offset&0x3f)<<7;
733 o |= (1<<4) | (p->from.reg<<8);
749 print("\t=>%P\tSUCCEED\n", p2);
754 findpre(Reg *r, Adr *v)
758 for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
761 switch(copyu(r1->prog, v, A)) {
763 case 2: /* read-alter-rewrite */
766 case 4: /* set and used */
774 findinc(Reg *r, Reg *r2, Adr *v)
780 for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
783 switch(copyu(r1->prog, v, A)) {
784 case 0: /* not touched */
786 case 4: /* set and used */
789 if(p->from.type == D_CONST)
790 if(p->from.offset > -256 && p->from.offset < 256)
800 nochange(Reg *r, Reg *r2, Prog *p)
808 if(p->reg != NREG && p->reg != p->to.reg) {
812 switch(p->from.type) {
815 a[n++].reg = p->from.offset&0xf;
818 a[n++].reg = p->from.reg;
822 for(; r!=R && r!=r2; r=uniqs(r)) {
825 if(copyu(p, &a[i], A) > 1)
832 findu1(Reg *r, Adr *v)
834 for(; r != R; r = r->s1) {
838 switch(copyu(r->prog, v, A)) {
840 case 2: /* read-alter-rewrite */
841 case 4: /* set and used */
847 if (findu1(r->s2, v))
854 finduse(Reg *r, Adr *v)
858 for(r1=firstr; r1!=R; r1=r1->link)
865 xtramodes(Reg *r, Adr *a)
872 if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG) /* byte load */
879 if(p1->to.type == D_REG && p1->to.reg == v.reg)
882 if(p1->from.type == D_REG ||
883 (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
884 (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
885 (p1->from.type == D_CONST &&
886 p1->from.offset > -4096 && p1->from.offset < 4096))
887 if(nochange(uniqs(r1), r, p1)) {
888 if(a != &p->from || v.reg != p->to.reg)
889 if (finduse(r->s1, &v)) {
890 if(p1->reg == NREG || p1->reg == v.reg)
895 switch (p1->from.type) {
897 /* register offset */
899 a->offset = p1->from.reg;
902 /* scaled register offset */
905 /* immediate offset */
906 a->offset = p1->from.offset;
916 if(p1->from.type == D_REG)
917 if((r2 = findinc(r1, r, &p1->from)) != R) {
918 for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
924 a->offset = p1->from.offset;
926 if(!finduse(r, &r1->prog->to))
935 if(a != &p->from || a->reg != p->to.reg)
936 if((r1 = findinc(r, R, &v)) != R) {
939 a->offset = p1->from.offset;
950 * 1 if v only used (and substitute),
951 * 2 if read-alter-rewrite
954 * 0 otherwise (not touched)
957 copyu(Prog *p, Adr *v, Adr *s)
967 case ANOP: /* read, write */
1014 if(p->scond&(C_WBIT|C_PBIT))
1015 if(v->type == D_REG) {
1016 if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
1017 if(p->from.reg == v->reg)
1020 if(p->to.reg == v->reg)
1026 if(copysub(&p->from, v, s, 1))
1028 if(!copyas(&p->to, v))
1029 if(copysub(&p->to, v, s, 1))
1033 if(copyas(&p->to, v)) {
1034 if(copyau(&p->from, v))
1038 if(copyau(&p->from, v))
1040 if(copyau(&p->to, v))
1045 case AADD: /* read, read, write */
1053 if(0 && p->from.type == D_CONST){
1054 if(s != A && regzer(s))
1055 return 4; /* add/sub $c,r,r -> r31 is sp not zr, don't touch */
1090 if(copysub(&p->from, v, s, 1))
1092 if(copysub1(p, v, s, 1))
1094 if(!copyas(&p->to, v))
1095 if(copysub(&p->to, v, s, 1))
1099 if(copyas(&p->to, v)) {
1102 if(copyau(&p->from, v))
1108 if(copyau(&p->from, v))
1112 if(copyau(&p->to, v))
1116 case ABEQ: /* read, read */
1140 if(copysub(&p->from, v, s, 1))
1142 return copysub1(p, v, s, 1);
1144 if(copyau(&p->from, v))
1150 case AB: /* funny */
1152 if(copysub(&p->to, v, s, 1))
1156 if(copyau(&p->to, v))
1161 case ARETURN: /* funny */
1162 if(v->type == D_REG)
1163 if(v->reg == REGRET)
1165 if(v->type == D_FREG)
1166 if(v->reg == FREGRET)
1169 case ABL: /* funny */
1170 if(v->type == D_REG) {
1171 if(v->reg <= REGEXT && v->reg > exregoffset)
1173 if(v->reg == REGARG)
1176 if(v->type == D_FREG)
1177 if(v->reg <= FREGEXT && v->reg > exfregoffset)
1181 if(copysub(&p->to, v, s, 1))
1185 if(copyau(&p->to, v))
1189 case ATEXT: /* funny */
1190 if(v->type == D_REG)
1191 if(v->reg == REGARG)
1261 * could be set/use depending on
1265 copyas(Adr *a, Adr *v)
1269 if(a->type == v->type)
1270 if(a->reg == v->reg)
1272 } else if(v->type == D_CONST) { /* for constprop */
1273 if(a->type == v->type)
1274 if(a->name == v->name)
1275 if(a->sym == v->sym)
1276 if(a->reg == v->reg)
1277 if(a->offset == v->offset)
1284 * either direct or indirect
1287 copyau(Adr *a, Adr *v)
1292 if(v->type == D_REG) {
1293 if(a->type == D_OREG) {
1294 if(v->reg == a->reg)
1296 } else if(a->type == D_SHIFT) {
1297 if(((a->offset>>16)&0x1F) == v->reg)
1299 } else if(a->type == D_EXTREG) {
1300 if(a->reg == v->reg || ((a->offset>>16)&0x1F) == v->reg)
1308 copyau1(Prog *p, Adr *v)
1312 if(a2type(p) == v->type)
1313 if(p->reg == v->reg) {
1314 if(a2type(p) != v->type)
1315 print("botch a2type %P\n", p);
1323 * substitute s for v in a
1324 * return failure to substitute
1327 copysub(Adr *a, Adr *v, Adr *s, int f)
1332 if(a->type == D_SHIFT) {
1333 if(((a->offset>>16)&0x1F) == v->reg)
1334 a->offset = (a->offset&~(0x1F<<16))|(s->reg<<16);
1342 copysub1(Prog *p1, Adr *v, Adr *s, int f)
1357 { ABEQ, ABNE, 0x0, 0x1, },
1358 { ABNE, ABEQ, 0x1, 0x0, },
1359 { ABCS, ABCC, 0x2, 0x3, },
1360 { ABHS, ABLO, 0x2, 0x3, },
1361 { ABCC, ABCS, 0x3, 0x2, },
1362 { ABLO, ABHS, 0x3, 0x2, },
1363 { ABMI, ABPL, 0x4, 0x5, },
1364 { ABPL, ABMI, 0x5, 0x4, },
1365 { ABVS, ABVC, 0x6, 0x7, },
1366 { ABVC, ABVS, 0x7, 0x6, },
1367 { ABHI, ABLS, 0x8, 0x9, },
1368 { ABLS, ABHI, 0x9, 0x8, },
1369 { ABGE, ABLT, 0xA, 0xB, },
1370 { ABLT, ABGE, 0xB, 0xA, },
1371 { ABGT, ABLE, 0xC, 0xD, },
1372 { ABLE, ABGT, 0xD, 0xC, },
1401 return (ABEQ <= p->as) && (p->as <= ABLE);
1413 || p->as == AHISTORY
1415 || p->as == ASIGNAME
1427 * Depends on an analysis of the encodings performed by 5l.
1428 * These seem to be all of the opcodes that lead to the "S" bit
1429 * being set in the instruction encodings.
1431 * C_SBIT may also have been set explicitly in p->scond.
1434 modifiescpsr(Prog *p)
1436 // return (p->scond&C_SBIT)
1451 * Find the maximal chain of instructions starting with r which could
1452 * be executed conditionally
1455 joinsplit(Reg *r, Joininfo *j)
1461 if (r->p2 && (r->p1 || r->p2->p2link)) {
1465 if (r->s1 && r->s2) {
1470 if (r->prog->as != ANOP)
1472 if (!r->s1 && !r->s2) {
1480 if (modifiescpsr(r->prog)) {
1485 } while (j->len < 4);
1501 applypred(Reg *rstart, Joininfo *j, int cond, int branch)
1508 if (cond == Truecond)
1509 pred = predinfo[rstart->prog->as - ABEQ].scond;
1511 pred = predinfo[rstart->prog->as - ABEQ].notscond;
1513 for (r = j->start; ; r = successor(r)) {
1514 if (r->prog->as == AB) {
1515 if (r != j->last || branch == Delbranch)
1518 if (cond == Truecond)
1519 r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
1521 r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
1524 else if (predicable(r->prog))
1525 r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
1526 if (r->s1 != r->link) {
1543 for(r=firstr; r!=R; r=r->link) {
1544 if (isbranch(r->prog)) {
1545 t1 = joinsplit(r->s1, &j1);
1546 t2 = joinsplit(r->s2, &j2);
1547 if(j1.last->link != j2.start)
1549 if(j1.end == j2.end)
1550 if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
1551 (t2 == Join && (t1 == Join || t1 == Setcond))) {
1552 applypred(r, &j1, Falsecond, Delbranch);
1553 applypred(r, &j2, Truecond, Delbranch);
1557 if(t1 == End || t1 == Branch) {
1558 applypred(r, &j1, Falsecond, Keepbranch);