ref: c3ba64f6935322f09b6de5c2285544fd471c605d
dir: /sys/src/cmd/qc/sgen.c/
#include "gc.h" void noretval(int n) { if(n & 1) { gins(ANOP, Z, Z); p->to.type = D_REG; p->to.reg = REGRET; } if(n & 2) { gins(ANOP, Z, Z); p->to.type = D_FREG; p->to.reg = FREGRET; } } /* * calculate addressability as follows * CONST ==> 20 $value * NAME ==> 10 name * REGISTER ==> 11 register * INDREG ==> 12 *[(reg)+offset] * &10 ==> 2 $name * ADD(2, 20) ==> 2 $name+offset * ADD(3, 20) ==> 3 $(reg)+offset * &12 ==> 3 $(reg)+offset * *11 ==> 11 ?? * *2 ==> 10 name * *3 ==> 12 *(reg)+offset * calculate complexity (number of registers) */ void xcom(Node *n) { Node *l, *r; int v, nr; if(n == Z) return; l = n->left; r = n->right; n->addable = 0; n->complex = 0; switch(n->op) { case OCONST: n->addable = 20; return; case OREGISTER: n->addable = 11; return; case OINDREG: n->addable = 12; return; case ONAME: n->addable = 10; return; case OADDR: xcom(l); if(l->addable == 10) n->addable = 2; if(l->addable == 12) n->addable = 3; break; case OIND: xcom(l); if(l->addable == 11) n->addable = 12; if(l->addable == 3) n->addable = 12; if(l->addable == 2) n->addable = 10; break; case OADD: xcom(l); xcom(r); if(l->addable == 20) { if(r->addable == 2) n->addable = 2; if(r->addable == 3) n->addable = 3; } if(r->addable == 20) { if(l->addable == 2) n->addable = 2; if(l->addable == 3) n->addable = 3; } break; case OASMUL: case OASLMUL: xcom(l); xcom(r); v = vlog(r); if(v >= 0) { n->op = OASASHL; r->vconst = v; r->type = types[TINT]; } break; case OMUL: case OLMUL: xcom(l); xcom(r); v = vlog(r); if(v >= 0) { n->op = OASHL; r->vconst = v; r->type = types[TINT]; } v = vlog(l); if(v >= 0) { n->op = OASHL; n->left = r; n->right = l; r = l; l = n->left; r->vconst = v; r->type = types[TINT]; simplifyshift(n); } break; case OASLDIV: xcom(l); xcom(r); v = vlog(r); if(v >= 0) { n->op = OASLSHR; r->vconst = v; r->type = types[TINT]; } break; case OLDIV: xcom(l); xcom(r); v = vlog(r); if(v >= 0) { n->op = OLSHR; r->vconst = v; r->type = types[TINT]; simplifyshift(n); } break; case OASLMOD: xcom(l); xcom(r); v = vlog(r); if(v >= 0) { n->op = OASAND; r->vconst--; } break; case OLMOD: xcom(l); xcom(r); v = vlog(r); if(v >= 0) { n->op = OAND; r->vconst--; } break; case OLSHR: case OASHL: case OASHR: xcom(l); xcom(r); simplifyshift(n); break; default: if(l != Z) xcom(l); if(r != Z) xcom(r); break; } if(n->addable >= 10) return; if(l != Z) n->complex = l->complex; if(r != Z) { nr = 1; if(r->type != T && typev[r->type->etype] || n->type != T && typev[n->type->etype]) { nr = 2; if(n->op == OMUL || n->op == OLMUL) nr += 3; } if(r->complex == n->complex) n->complex = r->complex+nr; else if(r->complex > n->complex) n->complex = r->complex; } if(n->complex == 0){ n->complex++; if(n->type != T && typev[n->type->etype]) n->complex++; } if(com64(n)) return; switch(n->op) { case OFUNC: n->complex = FNX; break; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OHI: case OHS: case OLO: case OLS: /* * immediate operators, make const on right */ if(l->op == OCONST) { n->left = r; n->right = l; n->op = invrel[relindex(n->op)]; } break; case OADD: case OXOR: case OAND: case OOR: /* * immediate operators, make const on right */ if(l->op == OCONST) { n->left = r; n->right = l; } break; } }