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];