diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 1cbeb3e3de..68d40f00c3 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -32,6 +32,8 @@ #include "gg.h" #include "opt.h" +#define NREGVAR 24 +#define REGBITS ((uint32)0xffffff) #define P2R(p) (Reg*)(p->reg) void addsplits(void); @@ -128,6 +130,33 @@ setaddrs(Bits bit) } } +static char* regname[] = { + ".R0", + ".R1", + ".R2", + ".R3", + ".R4", + ".R5", + ".R6", + ".R7", + ".R8", + ".R9", + ".R10", + ".R11", + ".R12", + ".R13", + ".R14", + ".R15", + ".F0", + ".F1", + ".F2", + ".F3", + ".F4", + ".F5", + ".F6", + ".F7", +}; + void regopt(Prog *firstp) { @@ -136,7 +165,7 @@ regopt(Prog *firstp) int i, z, nr; uint32 vreg; Bits bit; - + if(first == 0) { fmtinstall('Q', Qconv); } @@ -164,7 +193,17 @@ regopt(Prog *firstp) r1 = R; firstr = R; lastr = R; - nvar = 0; + + /* + * control flow is more complicated in generated go code + * than in generated c code. define pseudo-variables for + * registers, so we have complete register usage information. + */ + nvar = NREGVAR; + memset(var, 0, NREGVAR*sizeof var[0]); + for(i=0; ifrom); for(z=0; zuse1.b[z] |= bit.b[z]; + + /* + * middle always read when present + */ + if(p->reg != NREG) { + if(p->from.type != D_FREG) + r->use1.b[0] |= RtoB(p->reg); + else + r->use1.b[0] |= FtoB(p->reg); + } /* * right side depends on opcode @@ -233,6 +282,67 @@ regopt(Prog *firstp) default: yyerror("reg: unknown op: %A", p->as); break; + + /* + * right side read + */ + case ATST: + case ATEQ: + case ACMP: + case ACMN: + case ACMPD: + case ACMPF: + rightread: + for(z=0; zuse2.b[z] |= bit.b[z]; + break; + + /* + * right side read or read+write, depending on middle + * ADD x, z => z += x + * ADD x, y, z => z = x + y + */ + case AADD: + case AAND: + case AEOR: + case ASUB: + case ARSB: + case AADC: + case ASBC: + case ARSC: + case AORR: + case ABIC: + case ASLL: + case ASRL: + case ASRA: + case AMUL: + case AMULU: + case ADIV: + case AMOD: + case AMODU: + case ADIVU: + if(p->reg != NREG) + goto rightread; + // fall through + + /* + * right side read+write + */ + case AADDF: + case AADDD: + case ASUBF: + case ASUBD: + case AMULF: + case AMULD: + case ADIVF: + case ADIVD: + case AMULAL: + case AMULALU: + for(z=0; zuse2.b[z] |= bit.b[z]; + r->set.b[z] |= bit.b[z]; + } + break; /* * right side write @@ -240,11 +350,22 @@ regopt(Prog *firstp) case ANOP: case AMOVB: case AMOVBU: + case AMOVD: + case AMOVDF: + case AMOVDW: + case AMOVF: + case AMOVFW: case AMOVH: case AMOVHU: case AMOVW: - case AMOVF: - case AMOVD: + case AMOVWD: + case AMOVWF: + case AMVN: + case AMULL: + case AMULLU: + if((p->scond & C_SCOND) != C_SCOND_NONE) + for(z=0; zuse2.b[z] |= bit.b[z]; for(z=0; zset.b[z] |= bit.b[z]; break; @@ -396,6 +517,24 @@ loop2: } } + /* + * pass 4.5 + * move register pseudo-variables into regu. + */ + for(r = firstr; r != R; r = r->link) { + r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS; + + r->set.b[0] &= ~REGBITS; + r->use1.b[0] &= ~REGBITS; + r->use2.b[0] &= ~REGBITS; + r->refbehind.b[0] &= ~REGBITS; + r->refahead.b[0] &= ~REGBITS; + r->calbehind.b[0] &= ~REGBITS; + r->calahead.b[0] &= ~REGBITS; + r->regdiff.b[0] &= ~REGBITS; + r->act.b[0] &= ~REGBITS; + } + /* * pass 5 * isolate regions @@ -715,21 +854,40 @@ mkvar(Reg *r, Adr *a) goto onereg; case D_REGREG: + bit = zbits; if(a->offset != NREG) - r->regu |= RtoB(a->offset); - goto onereg; + bit.b[0] |= RtoB(a->offset); + if(a->reg != NREG) + bit.b[0] |= RtoB(a->reg); + return bit; case D_REG: case D_SHIFT: - case D_OREG: onereg: - if(a->reg != NREG) - r->regu |= RtoB(a->reg); + if(a->reg != NREG) { + bit = zbits; + bit.b[0] = RtoB(a->reg); + return bit; + } + break; + + case D_OREG: + if(a->reg != NREG) { + if(a == &r->prog->from) + r->use1.b[0] |= RtoB(a->reg); + else + r->use2.b[0] |= RtoB(a->reg); + if(r->prog->scond & (C_PBIT|C_WBIT)) + r->set.b[0] |= RtoB(a->reg); + } break; case D_FREG: - if(a->reg != NREG) - r->regu |= FtoB(a->reg); + if(a->reg != NREG) { + bit = zbits; + bit.b[0] = FtoB(a->reg); + return bit; + } break; } diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index b4b5b7d6be..a3a33b43f1 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -33,6 +33,8 @@ #define EXTERN #include "opt.h" +#define NREGVAR 32 /* 16 general + 16 floating */ +#define REGBITS ((uint32)0xffffffff) #define P2R(p) (Reg*)(p->reg) static int first = 1; @@ -114,6 +116,41 @@ setaddrs(Bits bit) } } +static char* regname[] = { + ".AX", + ".CX", + ".DX", + ".BX", + ".SP", + ".BP", + ".SI", + ".DI", + ".R8", + ".R9", + ".R10", + ".R11", + ".R12", + ".R13", + ".R14", + ".R15", + ".X0", + ".X1", + ".X2", + ".X3", + ".X4", + ".X5", + ".X6", + ".X7", + ".X8", + ".X9", + ".X10", + ".X11", + ".X12", + ".X13", + ".X14", + ".X15", +}; + void regopt(Prog *firstp) { @@ -143,6 +180,17 @@ regopt(Prog *firstp) firstr = R; lastr = R; nvar = 0; + + /* + * control flow is more complicated in generated go code + * than in generated c code. define pseudo-variables for + * registers, so we have complete register usage information. + */ + nvar = NREGVAR; + memset(var, 0, NREGVAR*sizeof var[0]); + for(i=0; iuse2.b[z] |= bit.b[z]; break; @@ -254,6 +305,7 @@ regopt(Prog *firstp) /* * right side write */ + case ALEAQ: case ANOP: case AMOVL: case AMOVQ: @@ -261,6 +313,8 @@ regopt(Prog *firstp) case AMOVW: case AMOVBLSX: case AMOVBLZX: + case AMOVBWSX: + case AMOVBWZX: case AMOVBQSX: case AMOVBQZX: case AMOVLQSX: @@ -269,6 +323,7 @@ regopt(Prog *firstp) case AMOVWLZX: case AMOVWQSX: case AMOVWQZX: + case APOPQ: case AMOVSS: case AMOVSD: @@ -357,6 +412,8 @@ regopt(Prog *firstp) case AIMULL: case AIMULQ: case AIMULW: + case ANEGB: + case ANEGW: case ANEGL: case ANEGQ: case ANOTL: @@ -366,6 +423,23 @@ regopt(Prog *firstp) case ASBBL: case ASBBQ: + case ASETCC: + case ASETCS: + case ASETEQ: + case ASETGE: + case ASETGT: + case ASETHI: + case ASETLE: + case ASETLS: + case ASETLT: + case ASETMI: + case ASETNE: + case ASETOC: + case ASETOS: + case ASETPC: + case ASETPL: + case ASETPS: + case AXCHGB: case AXCHGW: case AXCHGL: @@ -411,32 +485,44 @@ regopt(Prog *firstp) if(p->to.type != D_NONE) break; - case AIDIVB: case AIDIVL: - case AIDIVQ: case AIDIVW: + case AIDIVQ: + case ADIVL: + case ADIVW: + case ADIVQ: + case AMULL: + case AMULW: + case AMULQ: + r->set.b[0] |= RtoB(D_AX) | RtoB(D_DX); + r->use1.b[0] |= RtoB(D_AX) | RtoB(D_DX); + break; + + case AIDIVB: case AIMULB: case ADIVB: - case ADIVL: - case ADIVQ: - case ADIVW: - case AMULB: - case AMULL: - case AMULQ: - case AMULW: + case AMULB: + r->set.b[0] |= RtoB(D_AX); + r->use1.b[0] |= RtoB(D_AX); + break; case ACWD: - case ACDQ: - case ACQO: - r->regu |= RtoB(D_AX) | RtoB(D_DX); + r->set.b[0] |= RtoB(D_AX) | RtoB(D_DX); + r->use1.b[0] |= RtoB(D_AX); break; + case ACDQ: + r->set.b[0] |= RtoB(D_DX); + r->use1.b[0] |= RtoB(D_AX); + break; + case AREP: case AREPN: case ALOOP: case ALOOPEQ: case ALOOPNE: - r->regu |= RtoB(D_CX); + r->set.b[0] |= RtoB(D_CX); + r->use1.b[0] |= RtoB(D_CX); break; case AMOVSB: @@ -447,7 +533,8 @@ regopt(Prog *firstp) case ACMPSL: case ACMPSQ: case ACMPSW: - r->regu |= RtoB(D_SI) | RtoB(D_DI); + r->set.b[0] |= RtoB(D_SI) | RtoB(D_DI); + r->use1.b[0] |= RtoB(D_SI) | RtoB(D_DI); break; case ASTOSB: @@ -458,16 +545,22 @@ regopt(Prog *firstp) case ASCASL: case ASCASQ: case ASCASW: - r->regu |= RtoB(D_AX) | RtoB(D_DI); + r->set.b[0] |= RtoB(D_DI); + r->use1.b[0] |= RtoB(D_AX) | RtoB(D_DI); break; case AINSB: case AINSL: case AINSW: + r->set.b[0] |= RtoB(D_DX) | RtoB(D_DI); + r->use1.b[0] |= RtoB(D_DI); + break; + case AOUTSB: case AOUTSL: case AOUTSW: - r->regu |= RtoB(D_DI) | RtoB(D_DX); + r->set.b[0] |= RtoB(D_DI); + r->use1.b[0] |= RtoB(D_DX) | RtoB(D_DI); break; } } @@ -573,6 +666,24 @@ loop2: if(debug['R'] && debug['v']) dumpit("pass4", firstr); + /* + * pass 4.5 + * move register pseudo-variables into regu. + */ + for(r = firstr; r != R; r = r->link) { + r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS; + + r->set.b[0] &= ~REGBITS; + r->use1.b[0] &= ~REGBITS; + r->use2.b[0] &= ~REGBITS; + r->refbehind.b[0] &= ~REGBITS; + r->refahead.b[0] &= ~REGBITS; + r->calbehind.b[0] &= ~REGBITS; + r->calahead.b[0] &= ~REGBITS; + r->regdiff.b[0] &= ~REGBITS; + r->act.b[0] &= ~REGBITS; + } + /* * pass 5 * isolate regions @@ -818,6 +929,7 @@ mkvar(Reg *r, Adr *a) { Var *v; int i, t, n, et, z, w, flag; + uint32 regu; int32 o; Bits bit; Sym *s; @@ -829,14 +941,17 @@ mkvar(Reg *r, Adr *a) if(t == D_NONE) goto none; - if(r != R) { - r->regu |= doregbits(t); - r->regu |= doregbits(a->index); - } + if(r != R) + r->use1.b[0] |= doregbits(a->index); switch(t) { default: - goto none; + regu = doregbits(t); + if(regu == 0) + goto none; + bit = zbits; + bit.b[0] = regu; + return bit; case D_ADDR: a->type = a->index; diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index 1465d372ce..062ce58bbd 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -33,6 +33,8 @@ #define EXTERN #include "opt.h" +#define NREGVAR 8 +#define REGBITS ((uint32)0xff) #define P2R(p) (Reg*)(p->reg) static int first = 1; @@ -114,6 +116,8 @@ setaddrs(Bits bit) } } +static char* regname[] = { ".ax", ".cx", ".dx", ".bx", ".sp", ".bp", ".si", ".di" }; + void regopt(Prog *firstp) { @@ -142,7 +146,17 @@ regopt(Prog *firstp) r1 = R; firstr = R; lastr = R; - nvar = 0; + + /* + * control flow is more complicated in generated go code + * than in generated c code. define pseudo-variables for + * registers, so we have complete register usage information. + */ + nvar = NREGVAR; + memset(var, 0, NREGVAR*sizeof var[0]); + for(i=0; iset.b[z] |= bit.b[z]; break; @@ -321,6 +340,23 @@ regopt(Prog *firstp) case AADCL: case ASBBL: + case ASETCC: + case ASETCS: + case ASETEQ: + case ASETGE: + case ASETGT: + case ASETHI: + case ASETLE: + case ASETLS: + case ASETLT: + case ASETMI: + case ASETNE: + case ASETOC: + case ASETOS: + case ASETPC: + case ASETPL: + case ASETPS: + case AXCHGB: case AXCHGW: case AXCHGL: @@ -349,20 +385,32 @@ regopt(Prog *firstp) if(p->to.type != D_NONE) break; - case AIDIVB: case AIDIVL: case AIDIVW: - case AIMULB: - case ADIVB: case ADIVL: case ADIVW: - case AMULB: case AMULL: case AMULW: + r->set.b[0] |= RtoB(D_AX) | RtoB(D_DX); + r->use1.b[0] |= RtoB(D_AX) | RtoB(D_DX); + break; + + case AIDIVB: + case AIMULB: + case ADIVB: + case AMULB: + r->set.b[0] |= RtoB(D_AX); + r->use1.b[0] |= RtoB(D_AX); + break; case ACWD: + r->set.b[0] |= RtoB(D_AX) | RtoB(D_DX); + r->use1.b[0] |= RtoB(D_AX); + break; + case ACDQ: - r->regu |= RtoB(D_AX) | RtoB(D_DX); + r->set.b[0] |= RtoB(D_DX); + r->use1.b[0] |= RtoB(D_AX); break; case AREP: @@ -370,7 +418,8 @@ regopt(Prog *firstp) case ALOOP: case ALOOPEQ: case ALOOPNE: - r->regu |= RtoB(D_CX); + r->set.b[0] |= RtoB(D_CX); + r->use1.b[0] |= RtoB(D_CX); break; case AMOVSB: @@ -379,7 +428,8 @@ regopt(Prog *firstp) case ACMPSB: case ACMPSL: case ACMPSW: - r->regu |= RtoB(D_SI) | RtoB(D_DI); + r->set.b[0] |= RtoB(D_SI) | RtoB(D_DI); + r->use1.b[0] |= RtoB(D_SI) | RtoB(D_DI); break; case ASTOSB: @@ -388,16 +438,22 @@ regopt(Prog *firstp) case ASCASB: case ASCASL: case ASCASW: - r->regu |= RtoB(D_AX) | RtoB(D_DI); + r->set.b[0] |= RtoB(D_DI); + r->use1.b[0] |= RtoB(D_AX) | RtoB(D_DI); break; case AINSB: case AINSL: case AINSW: + r->set.b[0] |= RtoB(D_DX) | RtoB(D_DI); + r->use1.b[0] |= RtoB(D_DI); + break; + case AOUTSB: case AOUTSL: case AOUTSW: - r->regu |= RtoB(D_DI) | RtoB(D_DX); + r->set.b[0] |= RtoB(D_DI); + r->use1.b[0] |= RtoB(D_DX) | RtoB(D_DI); break; } } @@ -503,6 +559,24 @@ loop2: if(debug['R'] && debug['v']) dumpit("pass4", firstr); + /* + * pass 4.5 + * move register pseudo-variables into regu. + */ + for(r = firstr; r != R; r = r->link) { + r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS; + + r->set.b[0] &= ~REGBITS; + r->use1.b[0] &= ~REGBITS; + r->use2.b[0] &= ~REGBITS; + r->refbehind.b[0] &= ~REGBITS; + r->refahead.b[0] &= ~REGBITS; + r->calbehind.b[0] &= ~REGBITS; + r->calahead.b[0] &= ~REGBITS; + r->regdiff.b[0] &= ~REGBITS; + r->act.b[0] &= ~REGBITS; + } + /* * pass 5 * isolate regions @@ -732,7 +806,7 @@ Bits mkvar(Reg *r, Adr *a) { Var *v; - int i, t, n, et, z, w, flag; + int i, t, n, et, z, w, flag, regu; int32 o; Bits bit; Sym *s; @@ -744,14 +818,17 @@ mkvar(Reg *r, Adr *a) if(t == D_NONE) goto none; - if(r != R) { - r->regu |= doregbits(t); - r->regu |= doregbits(a->index); - } + if(r != R) + r->use1.b[0] |= doregbits(a->index); switch(t) { default: - goto none; + regu = doregbits(t); + if(regu == 0) + goto none; + bit = zbits; + bit.b[0] = regu; + return bit; case D_ADDR: a->type = a->index; diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index 0b6f5bbd83..a4b96abc52 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -703,5 +703,4 @@ tempname(Node *n, Type *t) if(thechar == '5') stksize = rnd(stksize, widthptr); n->xoffset = -stksize; - n->pun = anyregalloc(); }