1 #include "gc.h" 2 3 void 4 noretval(int n) 5 { 6 7 if(n & 1) { 8 gins(ANOP, Z, Z); 9 p->to.type = REGRET; 10 } 11 if(n & 2) { 12 gins(ANOP, Z, Z); 13 p->to.type = FREGRET; 14 } 15 if((n&3) == 3) 16 if(thisfn && thisfn->link && typefd[thisfn->link->etype]) 17 gins(AFLDZ, Z, Z); 18 } 19 20 /* welcome to commute */ 21 static void 22 commute(Node *n) 23 { 24 Node *l, *r; 25 26 l = n->left; 27 r = n->right; 28 if(r->complex > l->complex) { 29 n->left = r; 30 n->right = l; 31 } 32 } 33 34 void 35 indexshift(Node *n) 36 { 37 int g; 38 39 if(!typechlp[n->type->etype]) 40 return; 41 simplifyshift(n); 42 if(n->op == OASHL && n->right->op == OCONST){ 43 g = vconst(n->right); 44 if(g >= 0 && g < 4) 45 n->addable = 7; 46 } 47 } 48 49 /* 50 * calculate addressability as follows 51 * NAME ==> 10/11 name+value(SB/SP) 52 * REGISTER ==> 12 register 53 * CONST ==> 20 $value 54 * *(20) ==> 21 value 55 * &(10) ==> 13 $name+value(SB) 56 * &(11) ==> 1 $name+value(SP) 57 * (13) + (20) ==> 13 fold constants 58 * (1) + (20) ==> 1 fold constants 59 * *(13) ==> 10 back to name 60 * *(1) ==> 11 back to name 61 * 62 * (20) * (X) ==> 7 multiplier in indexing 63 * (X,7) + (13,1) ==> 8 adder in indexing (addresses) 64 * (8) ==> &9(OINDEX) index, almost addressable 65 * 66 * calculate complexity (number of registers) 67 */ 68 void 69 xcom(Node *n) 70 { 71 Node *l, *r; 72 int g; 73 74 if(n == Z) 75 return; 76 l = n->left; 77 r = n->right; 78 n->complex = 0; 79 n->addable = 0; 80 switch(n->op) { 81 case OCONST: 82 n->addable = 20; 83 break; 84 85 case ONAME: 86 n->addable = 10; 87 if(n->class == CPARAM || n->class == CAUTO) 88 n->addable = 11; 89 break; 90 91 case OEXREG: 92 n->addable = 12; 93 break; 94 95 case OREGISTER: 96 n->addable = 12; 97 break; 98 99 case OINDREG: 100 n->addable = 12; 101 break; 102 103 case OADDR: 104 xcom(l); 105 if(l->addable == 10) 106 n->addable = 13; 107 else 108 if(l->addable == 11) 109 n->addable = 1; 110 break; 111 112 case OADD: 113 xcom(l); 114 xcom(r); 115 if(n->type->etype != TIND) 116 break; 117 118 switch(r->addable) { 119 case 20: 120 switch(l->addable) { 121 case 1: 122 case 13: 123 commadd: 124 l->type = n->type; 125 *n = *l; 126 l = new(0, Z, Z); 127 *l = *(n->left); 128 l->xoffset += r->vconst; 129 n->left = l; 130 r = n->right; 131 goto brk; 132 } 133 break; 134 135 case 1: 136 case 13: 137 case 10: 138 case 11: 139 /* l is the base, r is the index */ 140 if(l->addable != 20) 141 n->addable = 8; 142 break; 143 } 144 switch(l->addable) { 145 case 20: 146 switch(r->addable) { 147 case 13: 148 case 1: 149 r = n->left; 150 l = n->right; 151 n->left = l; 152 n->right = r; 153 goto commadd; 154 } 155 break; 156 157 case 13: 158 case 1: 159 case 10: 160 case 11: 161 /* r is the base, l is the index */ 162 if(r->addable != 20) 163 n->addable = 8; 164 break; 165 } 166 if(n->addable == 8 && !side(n)) { 167 indx(n); 168 l = new1(OINDEX, idx.basetree, idx.regtree); 169 l->scale = idx.scale; 170 l->addable = 9; 171 l->complex = l->right->complex; 172 l->type = l->left->type; 173 n->op = OADDR; 174 n->left = l; 175 n->right = Z; 176 n->addable = 8; 177 break; 178 } 179 break; 180 181 case OINDEX: 182 xcom(l); 183 xcom(r); 184 n->addable = 9; 185 break; 186 187 case OIND: 188 xcom(l); 189 if(l->op == OADDR) { 190 l = l->left; 191 l->type = n->type; 192 *n = *l; 193 return; 194 } 195 switch(l->addable) { 196 case 20: 197 n->addable = 21; 198 break; 199 case 1: 200 n->addable = 11; 201 break; 202 case 13: 203 n->addable = 10; 204 break; 205 } 206 break; 207 208 case OASHL: 209 xcom(l); 210 xcom(r); 211 indexshift(n); 212 break; 213 214 case OMUL: 215 case OLMUL: 216 xcom(l); 217 xcom(r); 218 g = vlog(l); 219 if(g >= 0) { 220 n->left = r; 221 n->right = l; 222 l = r; 223 r = n->right; 224 } 225 g = vlog(r); 226 if(g >= 0) { 227 n->op = OASHL; 228 r->vconst = g; 229 r->type = types[TINT]; 230 indexshift(n); 231 break; 232 } 233 commute(n); 234 break; 235 236 case OASLDIV: 237 xcom(l); 238 xcom(r); 239 g = vlog(r); 240 if(g >= 0) { 241 n->op = OASLSHR; 242 r->vconst = g; 243 r->type = types[TINT]; 244 } 245 break; 246 247 case OLDIV: 248 xcom(l); 249 xcom(r); 250 g = vlog(r); 251 if(g >= 0) { 252 n->op = OLSHR; 253 r->vconst = g; 254 r->type = types[TINT]; 255 indexshift(n); 256 break; 257 } 258 break; 259 260 case OASLMOD: 261 xcom(l); 262 xcom(r); 263 g = vlog(r); 264 if(g >= 0) { 265 n->op = OASAND; 266 r->vconst--; 267 } 268 break; 269 270 case OLMOD: 271 xcom(l); 272 xcom(r); 273 g = vlog(r); 274 if(g >= 0) { 275 n->op = OAND; 276 r->vconst--; 277 } 278 break; 279 280 case OASMUL: 281 case OASLMUL: 282 xcom(l); 283 xcom(r); 284 g = vlog(r); 285 if(g >= 0) { 286 n->op = OASASHL; 287 r->vconst = g; 288 } 289 break; 290 291 case OLSHR: 292 case OASHR: 293 xcom(l); 294 xcom(r); 295 indexshift(n); 296 break; 297 298 default: 299 if(l != Z) 300 xcom(l); 301 if(r != Z) 302 xcom(r); 303 break; 304 } 305 brk: 306 if(n->addable >= 10) 307 return; 308 if(l != Z) 309 n->complex = l->complex; 310 if(r != Z) { 311 if(r->complex == n->complex) 312 n->complex = r->complex+1; 313 else 314 if(r->complex > n->complex) 315 n->complex = r->complex; 316 } 317 if(n->complex == 0) 318 n->complex++; 319 320 if(com64(n)) 321 return; 322 323 switch(n->op) { 324 325 case OFUNC: 326 n->complex = FNX; 327 break; 328 329 case OLMOD: 330 case OMOD: 331 case OLMUL: 332 case OLDIV: 333 case OMUL: 334 case ODIV: 335 case OASLMUL: 336 case OASLDIV: 337 case OASLMOD: 338 case OASMUL: 339 case OASDIV: 340 case OASMOD: 341 if(r->complex >= l->complex) { 342 n->complex = l->complex + 3; 343 if(r->complex > n->complex) 344 n->complex = r->complex; 345 } else { 346 n->complex = r->complex + 3; 347 if(l->complex > n->complex) 348 n->complex = l->complex; 349 } 350 break; 351 352 case OLSHR: 353 case OASHL: 354 case OASHR: 355 case OASLSHR: 356 case OASASHL: 357 case OASASHR: 358 if(r->complex >= l->complex) { 359 n->complex = l->complex + 2; 360 if(r->complex > n->complex) 361 n->complex = r->complex; 362 } else { 363 n->complex = r->complex + 2; 364 if(l->complex > n->complex) 365 n->complex = l->complex; 366 } 367 break; 368 369 case OADD: 370 case OXOR: 371 case OAND: 372 case OOR: 373 /* 374 * immediate operators, make const on right 375 */ 376 if(l->op == OCONST) { 377 n->left = r; 378 n->right = l; 379 } 380 break; 381 382 case OEQ: 383 case ONE: 384 case OLE: 385 case OLT: 386 case OGE: 387 case OGT: 388 case OHI: 389 case OHS: 390 case OLO: 391 case OLS: 392 /* 393 * compare operators, make const on left 394 */ 395 if(r->op == OCONST) { 396 n->left = r; 397 n->right = l; 398 n->op = invrel[relindex(n->op)]; 399 } 400 break; 401 } 402 } 403 404 void 405 indx(Node *n) 406 { 407 Node *l, *r; 408 409 if(debug['x']) 410 prtree(n, "indx"); 411 412 l = n->left; 413 r = n->right; 414 if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) { 415 n->right = l; 416 n->left = r; 417 l = r; 418 r = n->right; 419 } 420 if(l->addable != 7) { 421 idx.regtree = l; 422 idx.scale = 1; 423 } else 424 if(l->right->addable == 20) { 425 idx.regtree = l->left; 426 idx.scale = 1 << l->right->vconst; 427 } else 428 if(l->left->addable == 20) { 429 idx.regtree = l->right; 430 idx.scale = 1 << l->left->vconst; 431 } else 432 diag(n, "bad index"); 433 434 idx.basetree = r; 435 if(debug['x']) { 436 print("scale = %d\n", idx.scale); 437 prtree(idx.regtree, "index"); 438 prtree(idx.basetree, "base"); 439 } 440 } 441