--- /sys/src/cmd/8c/gc.h +++ /sys/src/cmd/8c/gc.h @@ -122,7 +122,7 @@ struct Renv Node* scope; }; -#define NRGN 600 +#define NRGN 1000 struct Rgn { Reg* enter; --- /sys/src/cmd/8c/machcap.c +++ /sys/src/cmd/8c/machcap.c @@ -18,7 +18,7 @@ machcap(Node *n) if(typev[n->type->etype]) { // if(typev[n->type->etype] && n->right->op == OCONST) { // if(hi64v(n->right) == 0) - return 1; + return !mixedasop(n->type, n->right->type); } break; @@ -58,11 +58,14 @@ machcap(Node *n) case OASADD: case OASSUB: + return !mixedasop(n->type, n->right->type); + case OASAND: case OASOR: case OASXOR: return 1; + case OASASHL: case OASASHR: case OASLSHR: --- /sys/src/cmd/8c/sgen.c +++ /sys/src/cmd/8c/sgen.c @@ -46,6 +46,28 @@ indexshift(Node *n) } } +static int +indexing(Node *n) +{ + for(; n != nil; n = n->left) + switch(n->op){ + case OSIGN: + case OSIZE: + case OCONST: + case OSTRING: + case OLSTRING: + case ONAME: + case OREGPAIR: + case OREGISTER: + case OINDREG: + return 0; + case OINDEX: + return 1; + } + return 0; +} + + /* * calculate addressability as follows * NAME ==> 10/11 name+value(SB/SP) @@ -163,7 +185,7 @@ xcom(Node *n) n->addable = 8; break; } - if(n->addable == 8 && !side(n)) { + if(n->addable == 8 && !indexing(n) && !side(n)){ indx(n); l = new1(OINDEX, idx.basetree, idx.regtree); l->scale = idx.scale; --- /sys/src/cmd/kc/cgen.c +++ /sys/src/cmd/kc/cgen.c @@ -1,5 +1,7 @@ #include "gc.h" +static void genasop(int, Node*, Node*, Node*); + void cgen(Node *n, Node *nn) { @@ -217,6 +219,8 @@ cgen(Node *n, Node *nn) regfree(&nod2); break; } + genasop(o, l, r, nn); + break; case OASLMUL: case OASLDIV: @@ -226,29 +230,7 @@ cgen(Node *n, Node *nn) case OASMOD: if(l->op == OBIT) goto asbitop; - if(l->complex >= r->complex) { - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - regalloc(&nod, n, nn); - cgen(r, &nod); - } else { - regalloc(&nod, n, nn); - cgen(r, &nod); - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - } - regalloc(&nod1, n, Z); - gopcode(OAS, &nod2, Z, &nod1); - gopcode(o, &nod, &nod1, &nod); - gopcode(OAS, &nod, Z, &nod2); - regfree(&nod); - regfree(&nod1); - if(l->addable < INDEXED) - regfree(&nod2); + genasop(o, l, r, nn); break; asbitop: @@ -517,6 +499,43 @@ cgen(Node *n, Node *nn) cursafe = curs; } +static void +genasop(int o, Node *l, Node *r, Node *nn) +{ + Node nod, nod1, nod2; + int hardleft; + + hardleft = l->addable < INDEXED || l->complex >= FNX; + if(l->complex >= r->complex) { + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + regalloc(&nod1, r, Z); + cgen(r, &nod1); + } else { + regalloc(&nod1, r, Z); + cgen(r, &nod1); + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + } + if(nod1.type == nod2.type || !typefd[nod1.type->etype]) + regalloc(&nod, &nod2, nn); + else + regalloc(&nod, &nod1, Z); + gmove(&nod2, &nod); + gopcode(o, &nod1, Z, &nod); + gmove(&nod, &nod2); + if(nn != Z) + gmove(&nod2, nn); + regfree(&nod); + regfree(&nod1); + if(hardleft) + regfree(&nod2); +} + void reglcgen(Node *t, Node *n, Node *nn) { @@ -835,12 +854,12 @@ sugen(Node *n, Node *nn, long w) case OSTRUCT: /* - * rewrite so lhs has no fn call + * rewrite so lhs has no side effects */ - if(nn != Z && nn->complex >= FNX) { + if(nn != Z && side(nn)) { nod1 = *n; nod1.type = typ(TIND, n->type); - regret(&nod2, &nod1); + regalloc(&nod2, &nod1, Z); lcgen(nn, &nod2); regsalloc(&nod0, &nod1); gopcode(OAS, &nod2, Z, &nod0); --- /sys/src/cmd/kc/gc.h +++ /sys/src/cmd/kc/gc.h @@ -119,7 +119,7 @@ struct Reg }; #define R ((Reg*)0) -#define NRGN 600 +#define NRGN 1000 struct Rgn { Reg* enter; --- /sys/src/cmd/qc/cgen.c +++ /sys/src/cmd/qc/cgen.c @@ -4,6 +4,7 @@ static void cmpv(Node*, int, Node*); static void testv(Node*, int); static void cgen64(Node*, Node*); static int isvconstable(int, vlong); +static void genasop(int, Node*, Node*, Node*); void cgen(Node *n, Node *nn) @@ -255,6 +256,8 @@ cgen(Node *n, Node *nn) regfree(&nod2); break; } + genasop(o, l, r, nn); + break; case OASLMUL: case OASLDIV: @@ -264,31 +267,7 @@ cgen(Node *n, Node *nn) case OASMOD: if(l->op == OBIT) goto asbitop; - if(l->complex >= r->complex) { - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - regalloc(&nod, r, Z); - cgen(r, &nod); - } else { - regalloc(&nod, r, Z); - cgen(r, &nod); - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - } - regalloc(&nod1, n, nn); - gopcode(OAS, &nod2, Z, &nod1); - gopcode(o, &nod, Z, &nod1); - gopcode(OAS, &nod1, Z, &nod2); - if(nn != Z) - gopcode(OAS, &nod1, Z, nn); - regfree(&nod); - regfree(&nod1); - if(l->addable < INDEXED) - regfree(&nod2); + genasop(o, l, r, nn); break; asbitop: @@ -561,6 +540,43 @@ cgen(Node *n, Node *nn) cursafe = curs; } +static void +genasop(int o, Node *l, Node *r, Node *nn) +{ + Node nod, nod1, nod2; + int hardleft; + + hardleft = l->addable < INDEXED || l->complex >= FNX; + if(l->complex >= r->complex) { + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + regalloc(&nod1, r, Z); + cgen(r, &nod1); + } else { + regalloc(&nod1, r, Z); + cgen(r, &nod1); + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + } + if(nod1.type == nod2.type || !typefd[nod1.type->etype]) + regalloc(&nod, &nod2, nn); + else + regalloc(&nod, &nod1, Z); + gmove(&nod2, &nod); + gopcode(o, &nod1, Z, &nod); + gmove(&nod, &nod2); + if(nn != Z) + gmove(&nod2, nn); + regfree(&nod); + regfree(&nod1); + if(hardleft) + regfree(&nod2); +} + void reglcgen(Node *t, Node *n, Node *nn) { --- /sys/src/cmd/qc/gc.h +++ /sys/src/cmd/qc/gc.h @@ -124,7 +124,7 @@ struct Reg }; #define R ((Reg*)0) -#define NRGN 600 +#define NRGN 1000 struct Rgn { Reg* enter; --- /sys/src/cmd/qc/machcap.c +++ /sys/src/cmd/qc/machcap.c @@ -18,10 +18,12 @@ machcap(Node *n) case OMUL: case OLMUL: - case OASMUL: case OASLMUL: return 1; + case OASMUL: + return !mixedasop(n->type, n->right->type); + case OLSHR: case OASHR: case OASHL: @@ -58,6 +60,8 @@ machcap(Node *n) case OASADD: case OASSUB: + return !mixedasop(n->type, n->right->type); + case OASAND: case OASOR: case OASXOR: --- /sys/src/cmd/qc/txt.c +++ /sys/src/cmd/qc/txt.c @@ -622,12 +622,86 @@ fop(int as, int f1, int f2, Node *t) regfree(&nod3); } +static void +floattofix(Node *f, Node *t) +{ + Node nod, fxrat; + + regalloc(&nod, f, Z); + regsalloc(&fxrat, &fconstnode); + gins(AFCTIWZ, f, &nod); + gins(AFMOVD, &nod, &fxrat); + regfree(&nod); + fxrat.type = nodrat->type; + fxrat.etype = nodrat->etype; + fxrat.xoffset += 4; + gins(AMOVW, &fxrat, t); + gmove(t, t); +} + +static void +fixtofloat(Node *f, Node *t) +{ + int a, ft, tt; + Prog *p1; + Node nod, fxc0, fxc1, fxc2, fxrat; + + ft = f->type->etype; + tt = t->type->etype; + + /* + * rat[0] = 0x43300000; rat[1] = f^0x80000000; + * t = *(double*)rat - FREGCVI; + * is-unsigned(t) => if(t<0) t += 2^32; + * could be streamlined for int-to-float + */ + regalloc(&fxc0, f, Z); + regalloc(&fxc2, f, Z); + regsalloc(&fxrat, &fconstnode); /* should be type float */ + gins(AMOVW, nodconst(0x43300000L), &fxc0); + gins(AMOVW, f, &fxc2); + gins(AMOVW, &fxc0, &fxrat); + gins(AXOR, nodconst(0x80000000L), &fxc2); + fxc1 = fxrat; + fxc1.type = nodrat->type; + fxc1.etype = nodrat->etype; + fxc1.xoffset += SZ_LONG; + gins(AMOVW, &fxc2, &fxc1); + regfree(&fxc2); + regfree(&fxc0); + regalloc(&nod, t, t); /* should be type float */ + gins(AFMOVD, &fxrat, &nod); + nodreg(&fxc1, t, NREG+FREGCVI); + gins(AFSUB, &fxc1, &nod); + a = AFMOVD; + if(tt == TFLOAT) + a = AFRSP; + gins(a, &nod, t); + regfree(&nod); + if(ft == TULONG) { + regalloc(&nod, t, Z); + gins(AFCMPU, t, Z); + p->to.type = D_FREG; + p->to.reg = FREGZERO; + gins(ABGE, Z, Z); + p1 = p; + if(tt == TFLOAT) { + gins(AFMOVS, nodfconst(4294967296.), &nod); + gins(AFADDS, &nod, t); + } else { + gins(AFMOVD, nodfconst(4294967296.), &nod); + gins(AFADD, &nod, t); + } + patch(p1, pc); + regfree(&nod); + } +} + void gmove(Node *f, Node *t) { int ft, tt, a; - Node nod, fxc0, fxc1, fxc2, fxrat; - Prog *p1; + Node nod; double d; ft = f->type->etype; @@ -727,7 +801,7 @@ gmove(Node *f, Node *t) break; } if(typev[ft]) { - if(typev[tt]) { + if(typev[tt] || typefd[tt]) { regalloc(&nod, f, t); /* low order first, because its value will be used first */ f->xoffset += SZ_LONG; @@ -832,16 +906,11 @@ gmove(Node *f, Node *t) case TCHAR: case TUCHAR: /* BUG: not right for unsigned long */ - regalloc(&nod, f, Z); /* should be type float */ - regsalloc(&fxrat, &fconstnode); - gins(AFCTIWZ, f, &nod); - gins(AFMOVD, &nod, &fxrat); - regfree(&nod); - fxrat.type = nodrat->type; - fxrat.etype = nodrat->etype; - fxrat.xoffset += 4; - gins(AMOVW, &fxrat, t); - gmove(t, t); + floattofix(f, t); + return; + case TVLONG: + case TUVLONG: + diag(f, "unimplemented double->vlong"); return; } break; @@ -853,7 +922,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -871,7 +941,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -891,7 +962,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -911,7 +983,8 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - goto fxtofl; + fixtofloat(f, t); + return; case TINT: case TUINT: case TLONG: @@ -931,58 +1004,7 @@ gmove(Node *f, Node *t) switch(tt) { case TDOUBLE: case TFLOAT: - fxtofl: - /* - * rat[0] = 0x43300000; rat[1] = f^0x80000000; - * t = *(double*)rat - FREGCVI; - * is-unsigned(t) => if(t<0) t += 2^32; - * could be streamlined for int-to-float - */ - regalloc(&fxc0, f, Z); - regalloc(&fxc2, f, Z); - regsalloc(&fxrat, &fconstnode); /* should be type float */ - gins(AMOVW, nodconst(0x43300000L), &fxc0); - gins(AMOVW, f, &fxc2); - gins(AMOVW, &fxc0, &fxrat); - gins(AXOR, nodconst(0x80000000L), &fxc2); - fxc1 = fxrat; - fxc1.type = nodrat->type; - fxc1.etype = nodrat->etype; - fxc1.xoffset += SZ_LONG; - gins(AMOVW, &fxc2, &fxc1); - regfree(&fxc2); - regfree(&fxc0); - regalloc(&nod, t, t); /* should be type float */ - gins(AFMOVD, &fxrat, &nod); - nodreg(&fxc1, t, NREG+FREGCVI); - gins(AFSUB, &fxc1, &nod); - a = AFMOVD; - if(tt == TFLOAT) - a = AFRSP; - gins(a, &nod, t); - regfree(&nod); - if(ft == TULONG) { - regalloc(&nod, t, Z); - if(tt == TFLOAT) { - gins(AFCMPU, t, Z); - p->to.type = D_FREG; - p->to.reg = FREGZERO; - gins(ABGE, Z, Z); - p1 = p; - gins(AFMOVS, nodfconst(4294967296.), &nod); - gins(AFADDS, &nod, t); - } else { - gins(AFCMPU, t, Z); - p->to.type = D_FREG; - p->to.reg = FREGZERO; - gins(ABGE, Z, Z); - p1 = p; - gins(AFMOVD, nodfconst(4294967296.), &nod); - gins(AFADD, &nod, t); - } - patch(p1, pc); - regfree(&nod); - } + fixtofloat(f, t); return; case TINT: case TUINT: --- /sys/src/cmd/vc/cgen.c +++ /sys/src/cmd/vc/cgen.c @@ -1,5 +1,7 @@ #include "gc.h" +static void genasop(int, Node*, Node*, Node*); + void cgen(Node *n, Node *nn) { @@ -216,6 +218,8 @@ cgen(Node *n, Node *nn) regfree(&nod2); break; } + genasop(o, l, r, nn); + break; case OASLMUL: case OASLDIV: @@ -225,32 +229,7 @@ cgen(Node *n, Node *nn) case OASMOD: if(l->op == OBIT) goto asbitop; - if(l->complex >= r->complex) { - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - regalloc(&nod1, r, Z); - cgen(r, &nod1); - } else { - regalloc(&nod1, r, Z); - cgen(r, &nod1); - if(l->addable < INDEXED) - reglcgen(&nod2, l, Z); - else - nod2 = *l; - } - - regalloc(&nod, n, nn); - gmove(&nod2, &nod); - gopcode(o, &nod1, Z, &nod); - gmove(&nod, &nod2); - if(nn != Z) - gopcode(OAS, &nod, Z, nn); - regfree(&nod); - regfree(&nod1); - if(l->addable < INDEXED) - regfree(&nod2); + genasop(o, l, r, nn); break; asbitop: @@ -521,6 +500,43 @@ cgen(Node *n, Node *nn) cursafe = curs; } +static void +genasop(int o, Node *l, Node *r, Node *nn) +{ + Node nod, nod1, nod2; + int hardleft; + + hardleft = l->addable < INDEXED || l->complex >= FNX; + if(l->complex >= r->complex) { + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + regalloc(&nod1, r, Z); + cgen(r, &nod1); + } else { + regalloc(&nod1, r, Z); + cgen(r, &nod1); + if(hardleft) + reglcgen(&nod2, l, Z); + else + nod2 = *l; + } + if(nod1.type == nod2.type || !typefd[nod1.type->etype]) + regalloc(&nod, &nod2, nn); + else + regalloc(&nod, &nod1, Z); + gmove(&nod2, &nod); + gopcode(o, &nod1, Z, &nod); + gmove(&nod, &nod2); + if(nn != Z) + gmove(&nod2, nn); + regfree(&nod); + regfree(&nod1); + if(hardleft) + regfree(&nod2); +} + void reglcgen(Node *t, Node *n, Node *nn) { @@ -930,12 +946,12 @@ sugen(Node *n, Node *nn, long w) case OSTRUCT: /* - * rewrite so lhs has no fn call + * rewrite so lhs has no side effects */ - if(nn != Z && nn->complex >= FNX) { + if(nn != Z && side(nn)) { nod1 = *n; nod1.type = typ(TIND, n->type); - regret(&nod2, &nod1); + regalloc(&nod2, &nod1, Z); lcgen(nn, &nod2); regsalloc(&nod0, &nod1); gopcode(OAS, &nod2, Z, &nod0); --- /sys/src/cmd/vc/gc.h +++ /sys/src/cmd/vc/gc.h @@ -120,7 +120,7 @@ struct Reg }; #define R ((Reg*)0) -#define NRGN 1000 /* was 600; raised for paranoia.c */ +#define NRGN 1000 struct Rgn { Reg* enter;