qbe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }