qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

pmov.c (4977B)


      1 /*% rm -f rega.o main.o && cc -g -std=c99 -Wall -DTEST_PMOV -o pmov % *.o
      2  *
      3  * This is a test framwork for the dopm() function
      4  * in rega.c, use it when you want to modify it or
      5  * all the parallel move functions.
      6  *
      7  * You might need to decrease NIReg to see it
      8  * terminate, I used NIReg == 7 at most.
      9  */
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 
     14 static void assert_test(char *, int), fail(void), iexec(int *);
     15 
     16 #include "../../rega.c"
     17 
     18 static void bsinit_(BSet *, uint);
     19 
     20 static RMap mbeg;
     21 static Ins ins[NIReg], *ip;
     22 static Blk dummyb = { .ins = ins };
     23 
     24 int
     25 main()
     26 {
     27 	Ins *i1;
     28 	unsigned long long tm, rm, cnt;
     29 	RMap mend;
     30 	int reg[NIReg], val[NIReg+1];
     31 	int t, i, r, nr;
     32 
     33 	tmp = (Tmp[Tmp0+NIReg]){{{0}}};
     34 	for (t=0; t<Tmp0+NIReg; t++)
     35 		if (t >= Tmp0) {
     36 			tmp[t].cls = Kw;
     37 			tmp[t].hint.r = -1;
     38 			tmp[t].hint.m = 0;
     39 			tmp[t].slot = -1;
     40 			sprintf(tmp[t].name, "tmp%d", t-Tmp0+1);
     41 		}
     42 
     43 	bsinit_(mbeg.b, Tmp0+NIReg);
     44 	bsinit_(mend.b, Tmp0+NIReg);
     45 	cnt = 0;
     46 	for (tm = 0; tm < 1ull << (2*NIReg); tm++) {
     47 		mbeg.n = 0;
     48 		bszero(mbeg.b);
     49 		ip = ins;
     50 
     51 		/* find what temporaries are in copy and
     52 		 * wether or not they are in register
     53 		 */
     54 		for (t=0; t<NIReg; t++)
     55 			switch ((tm >> (2*t)) & 3) {
     56 			case 0:
     57 				/* not in copy, not in reg */
     58 				break;
     59 			case 1:
     60 				/* not in copy, in reg */
     61 				radd(&mbeg, Tmp0+t, t+1);
     62 				break;
     63 			case 2:
     64 				/* in copy, not in reg */
     65 				*ip++ = (Ins){OCopy, Kw, TMP(Tmp0+t), {R, R}};
     66 				break;
     67 			case 3:
     68 				/* in copy, in reg */
     69 				*ip++ = (Ins){OCopy, Kw, TMP(Tmp0+t), {R, R}};
     70 				radd(&mbeg, Tmp0+t, t+1);
     71 				break;
     72 			}
     73 
     74 		if (ip == ins)
     75 			/* cancel if the parallel move
     76 			 * is empty
     77 			 */
     78 			goto Nxt;
     79 
     80 		/* find registers for temporaries
     81 		 * in mbeg
     82 		 */
     83 		nr = ip - ins;
     84 		rm = (1ull << (nr+1)) - 1;
     85 		for (i=0; i<nr; i++)
     86 			reg[i] = i+1;
     87 
     88 		for (;;) {
     89 			/* set registers on copies
     90 			 */
     91 			for (i=0, i1=ins; i1<ip; i1++, i++)
     92 				i1->arg[0] = TMP(reg[i]);
     93 
     94 			/* compile the parallel move
     95 			 */
     96 			rcopy(&mend, &mbeg);
     97 			dopm(&dummyb, ip-1, &mend);
     98 			cnt++;
     99 
    100 			/* check that mend contain mappings for
    101 			 * source registers and does not map any
    102 			 * assigned temporary, then check that
    103 			 * all temporaries in mend are mapped in
    104 			 * mbeg and not used in the copy
    105 			 */
    106 			for (i1=ins; i1<ip; i1++) {
    107 				r = i1->arg[0].val;
    108 				assert(rfree(&mend, r) == r);
    109 				t = i1->to.val;
    110 				assert(!bshas(mend.b, t));
    111 			}
    112 			for (i=0; i<mend.n; i++) {
    113 				t = mend.t[i];
    114 				assert(bshas(mbeg.b, t));
    115 				t -= Tmp0;
    116 				assert(((tm >> (2*t)) & 3) == 1);
    117 			}
    118 
    119 			/* execute the code generated and check
    120 			 * that all assigned temporaries got their
    121 			 * value, and that all live variables's
    122 			 * content got preserved
    123 			 */
    124 			 for (i=1; i<=NIReg; i++)
    125 			 	val[i] = i;
    126 			 iexec(val);
    127 			 for (i1=ins; i1<ip; i1++) {
    128 			 	t = i1->to.val;
    129 			 	r = rfind(&mbeg, t);
    130 			 	if (r != -1)
    131 			 		assert(val[r] == i1->arg[0].val);
    132 			 }
    133 			 for (i=0; i<mend.n; i++) {
    134 			 	t = mend.t[i];
    135 			 	r = mend.r[i];
    136 			 	assert(val[t-Tmp0+1] == r);
    137 			 }
    138 
    139 			/* find the next register assignment */
    140 			i = nr - 1;
    141 			for (;;) {
    142 				r = reg[i];
    143 				rm &= ~(1ull<<r);
    144 				do
    145 					r++;
    146 				while (r <= NIReg && (rm & (1ull<<r)));
    147 				if (r == NIReg+1) {
    148 					if (i == 0)
    149 						goto Nxt;
    150 					i--;
    151 				} else {
    152 					rm |= (1ull<<r);
    153 					reg[i++] = r;
    154 					break;
    155 				}
    156 			}
    157 			for (; i<nr; i++)
    158 				for (r=1; r<=NIReg; r++)
    159 					if (!(rm & (1ull<<r))) {
    160 						rm |= (1ull<<r);
    161 						reg[i] = r;
    162 						break;
    163 					}
    164 		}
    165 	Nxt:	freeall();
    166 	}
    167 	printf("%llu tests successful!\n", cnt);
    168 	exit(0);
    169 }
    170 
    171 
    172 /* execute what pmgen() wrote (swap, copy) */
    173 
    174 #define validr(r)           \
    175 	rtype(r) == RTmp && \
    176 	r.val > 0 &&        \
    177 	r.val <= NIReg
    178 
    179 static void
    180 iexec(int val[])
    181 {
    182 	Ins *i;
    183 	int t;
    184 
    185 	for (i=insb; i<curi; i++)
    186 		switch (i->op) {
    187 		default:
    188 			assert(!"iexec: missing case\n");
    189 			exit(1);
    190 		case OSwap:
    191 			assert(validr(i->arg[0]));
    192 			assert(validr(i->arg[1]));
    193 			t = val[i->arg[0].val];
    194 			val[i->arg[0].val] = val[i->arg[1].val];
    195 			val[i->arg[1].val] = t;
    196 			break;
    197 		case OCopy:
    198 			assert(validr(i->to));
    199 			assert(validr(i->arg[0]));
    200 			val[i->to.val] = val[i->arg[0].val];
    201 			break;
    202 		}
    203 }
    204 
    205 
    206 /* failure diagnostics */
    207 
    208 static int re;
    209 
    210 static void
    211 replay()
    212 {
    213 	RMap mend;
    214 
    215 	re = 1;
    216 	bsinit_(mend.b, Tmp0+NIReg);
    217 	rcopy(&mend, &mbeg);
    218 	dopm(&dummyb, ip-1, &mend);
    219 }
    220 
    221 static void
    222 fail()
    223 {
    224 	Ins *i1;
    225 	int i;
    226 
    227 	printf("\nIn registers: ");
    228 	for (i=0; i<mbeg.n; i++)
    229 		printf("%s(r%d) ",
    230 			tmp[mbeg.t[i]].name,
    231 			mbeg.r[i]);
    232 	printf("\n");
    233 	printf("Parallel move:\n");
    234 	for (i1=ins; i1<ip; i1++)
    235 		printf("\t %s <- r%d\n",
    236 			tmp[i1->to.val].name,
    237 			i1->arg[0].val);
    238 	replay();
    239 	abort();
    240 }
    241 
    242 static void
    243 assert_test(char *s, int x)
    244 {
    245 	if (x)
    246 		return;
    247 	if (re)
    248 		abort();
    249 	printf("!assertion failure: %s\n", s);
    250 	fail();
    251 }
    252 
    253 static void
    254 bsinit_(BSet *bs, uint n)
    255 {
    256 	n = (n + NBit-1) / NBit;
    257 	bs->nt = n;
    258 	bs->t = emalloc(n * sizeof bs->t[0]);
    259 }
    260 
    261 /* symbols required by the linker */
    262 char debug['Z'+1];