simpl.c (2283B)
1 #include "all.h" 2 3 static void 4 blit(Ref sd[2], int sz, Fn *fn) 5 { 6 struct { int st, ld, cls, size; } *p, tbl[] = { 7 { Ostorel, Oload, Kl, 8 }, 8 { Ostorew, Oload, Kw, 4 }, 9 { Ostoreh, Oloaduh, Kw, 2 }, 10 { Ostoreb, Oloadub, Kw, 1 } 11 }; 12 Ref r, r1, ro; 13 int off, fwd, n; 14 15 fwd = sz >= 0; 16 sz = abs(sz); 17 off = fwd ? sz : 0; 18 for (p=tbl; sz; p++) 19 for (n=p->size; sz>=n; sz-=n) { 20 off -= fwd ? n : 0; 21 r = newtmp("blt", Kl, fn); 22 r1 = newtmp("blt", Kl, fn); 23 ro = getcon(off, fn); 24 emit(p->st, 0, R, r, r1); 25 emit(Oadd, Kl, r1, sd[1], ro); 26 r1 = newtmp("blt", Kl, fn); 27 emit(p->ld, p->cls, r, r1, R); 28 emit(Oadd, Kl, r1, sd[0], ro); 29 off += fwd ? 0 : n; 30 } 31 } 32 33 static int 34 ulog2_tab64[64] = { 35 63, 0, 1, 41, 37, 2, 16, 42, 36 38, 29, 32, 3, 12, 17, 43, 55, 37 39, 35, 30, 53, 33, 21, 4, 23, 38 13, 9, 18, 6, 25, 44, 48, 56, 39 62, 40, 36, 15, 28, 31, 11, 54, 40 34, 52, 20, 22, 8, 5, 24, 47, 41 61, 14, 27, 10, 51, 19, 7, 46, 42 60, 26, 50, 45, 59, 49, 58, 57, 43 }; 44 45 static int 46 ulog2(uint64_t pow2) 47 { 48 return ulog2_tab64[(pow2 * 0x5b31ab928877a7e) >> 58]; 49 } 50 51 static int 52 ispow2(uint64_t v) 53 { 54 return v && (v & (v - 1)) == 0; 55 } 56 57 static void 58 ins(Ins **pi, int *new, Blk *b, Fn *fn) 59 { 60 ulong ni; 61 Con *c; 62 Ins *i; 63 Ref r; 64 int n; 65 66 i = *pi; 67 /* simplify more instructions here; 68 * copy 0 into xor, bit rotations, 69 * etc. */ 70 switch (i->op) { 71 case Oblit1: 72 assert(i > b->ins); 73 assert((i-1)->op == Oblit0); 74 if (!*new) { 75 curi = &insb[NIns]; 76 ni = &b->ins[b->nins] - (i+1); 77 curi -= ni; 78 icpy(curi, i+1, ni); 79 *new = 1; 80 } 81 blit((i-1)->arg, rsval(i->arg[0]), fn); 82 *pi = i-1; 83 return; 84 case Oudiv: 85 case Ourem: 86 r = i->arg[1]; 87 if (KBASE(i->cls) == 0) 88 if (rtype(r) == RCon) { 89 c = &fn->con[r.val]; 90 if (c->type == CBits) 91 if (ispow2(c->bits.i)) { 92 n = ulog2(c->bits.i); 93 if (i->op == Ourem) { 94 i->op = Oand; 95 i->arg[1] = getcon((1ull<<n) - 1, fn); 96 } else { 97 i->op = Oshr; 98 i->arg[1] = getcon(n, fn); 99 } 100 } 101 } 102 break; 103 } 104 if (*new) 105 emiti(*i); 106 } 107 108 void 109 simpl(Fn *fn) 110 { 111 Blk *b; 112 Ins *i; 113 int new; 114 115 for (b=fn->start; b; b=b->link) { 116 new = 0; 117 for (i=&b->ins[b->nins]; i!=b->ins;) { 118 --i; 119 ins(&i, &new, b, fn); 120 } 121 if (new) { 122 b->nins = &insb[NIns] - curi; 123 idup(&b->ins, curi, b->nins); 124 } 125 } 126 }