From a07218385ce652f55547dc06e664eaab6a47be43 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 12 Aug 2013 13:42:23 -0400 Subject: [PATCH] cmd/5g: factor out prog information Like CL 12637051, but for 5g instead of 6g. R=ken2 CC=golang-dev https://golang.org/cl/12779043 --- src/cmd/5g/opt.h | 52 +++++++++++++++ src/cmd/5g/peep.c | 84 +++++++----------------- src/cmd/5g/prog.c | 135 ++++++++++++++++++++++++++++++++++++++ src/cmd/5g/reg.c | 160 +++++++--------------------------------------- 4 files changed, 231 insertions(+), 200 deletions(-) create mode 100644 src/cmd/5g/prog.c diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h index af7d654dee..84c81c849b 100644 --- a/src/cmd/5g/opt.h +++ b/src/cmd/5g/opt.h @@ -165,3 +165,55 @@ int32 RtoB(int); int32 FtoB(int); int BtoR(int32); int BtoF(int32); + +/* + * prog.c + */ +typedef struct ProgInfo ProgInfo; +struct ProgInfo +{ + uint32 flags; // the bits below +}; + +enum +{ + // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA. + Pseudo = 1<<1, + + // There's nothing to say about the instruction, + // but it's still okay to see. + OK = 1<<2, + + // Size of right-side write, or right-side read if no write. + SizeB = 1<<3, + SizeW = 1<<4, + SizeL = 1<<5, + SizeQ = 1<<6, + SizeF = 1<<7, // float aka float32 + SizeD = 1<<8, // double aka float64 + + // Left side: address taken, read, write. + LeftAddr = 1<<9, + LeftRead = 1<<10, + LeftWrite = 1<<11, + + // Register in middle; never written. + RegRead = 1<<12, + CanRegRead = 1<<13, + + // Right side: address taken, read, write. + RightAddr = 1<<14, + RightRead = 1<<15, + RightWrite = 1<<16, + + // Instruction kinds + Move = 1<<17, // straight move + Conv = 1<<18, // size conversion + Cjmp = 1<<19, // conditional jump + Break = 1<<20, // breaks control flow (no fallthrough) + Call = 1<<21, // function call + Jump = 1<<22, // jump + Skip = 1<<23, // data instruction +}; + +void proginfo(ProgInfo*, Prog*); diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c index b1db361164..71c81ecc40 100644 --- a/src/cmd/5g/peep.c +++ b/src/cmd/5g/peep.c @@ -50,6 +50,7 @@ peep(void) Reg *r, *r1, *r2; Prog *p; int t; + ProgInfo info; /* * complete R structure @@ -58,28 +59,24 @@ peep(void) r1 = r->link; if(r1 == R) break; - p = r->prog->link; - while(p != r1->prog) - switch(p->as) { - default: + for(p = r->prog->link; p != r1->prog; p = p->link) { + proginfo(&info, p); + if(info.flags & Skip) + continue; + r2 = rega(); r->link = r2; r2->link = r1; r2->prog = p; + p->regp = r2; + r2->p1 = r; r->s1 = r2; r2->s1 = r1; r1->p1 = r2; r = r2; - - case ADATA: - case AGLOBL: - case ANAME: - case ASIGNAME: - case ATYPE: - p = p->link; } } //dumpit("begin", firstr); @@ -324,6 +321,7 @@ subprop(Reg *r0) Adr *v1, *v2; Reg *r; int t; + ProgInfo info; p = r0->prog; v1 = &p->from; @@ -336,68 +334,30 @@ subprop(Reg *r0) if(uniqs(r) == R) break; p = r->prog; - switch(p->as) { - case ABL: + proginfo(&info, p); + if(info.flags & Call) return 0; + if((info.flags & CanRegRead) && p->to.type == D_REG) { + info.flags |= RegRead; + info.flags &= ~(CanRegRead | RightRead); + p->reg = p->to.reg; + } + + switch(p->as) { case AMULLU: case AMULA: case AMVN: return 0; - - case ACMN: - case AADD: - case ASUB: - case ASBC: - case ARSB: - case ASLL: - case ASRL: - case ASRA: - case AORR: - case AAND: - case AEOR: - case AMUL: - case AMULU: - case ADIV: - case ADIVU: - case AMOD: - case AMODU: - - case AADDD: - case AADDF: - case ASUBD: - case ASUBF: - case AMULD: - case AMULF: - case ADIVD: - case ADIVF: - if(p->to.type == v1->type) - if(p->to.reg == v1->reg) - if(p->scond == C_SCOND_NONE) { - if(p->reg == NREG) - p->reg = p->to.reg; - goto gotit; - } - break; - - case AMOVF: - case AMOVD: - case AMOVB: - case AMOVH: - case AMOVW: + } + + if((info.flags & (RightRead|RightWrite)) == RightWrite) { if(p->to.type == v1->type) if(p->to.reg == v1->reg) if(p->scond == C_SCOND_NONE) goto gotit; - break; - - case AMOVM: - t = 1<reg; - if((p->from.type == D_CONST && (p->from.offset&t)) || - (p->to.type == D_CONST && (p->to.offset&t))) - return 0; - break; } + if(copyau(&p->from, v2) || copyau1(p, v2) || copyau(&p->to, v2)) diff --git a/src/cmd/5g/prog.c b/src/cmd/5g/prog.c new file mode 100644 index 0000000000..63709fbee4 --- /dev/null +++ b/src/cmd/5g/prog.c @@ -0,0 +1,135 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include +#include +#include "gg.h" +#include "opt.h" + +enum +{ + RightRdwr = RightRead | RightWrite, +}; + +// This table gives the basic information about instruction +// generated by the compiler and processed in the optimizer. +// See opt.h for bit definitions. +// +// Instructions not generated need not be listed. +// As an exception to that rule, we typically write down all the +// size variants of an operation even if we just use a subset. +// +// The table is formatted for 8-space tabs. +static ProgInfo progtable[ALAST] = { + [ATYPE]= {Pseudo | Skip}, + [ATEXT]= {Pseudo}, + [AFUNCDATA]= {Pseudo}, + [APCDATA]= {Pseudo}, + + // NOP is an internal no-op that also stands + // for USED and SET annotations, not the Intel opcode. + [ANOP]= {LeftRead | RightWrite}, + + // Integer. + [AADC]= {SizeL | LeftRead | RegRead | RightWrite}, + [AADD]= {SizeL | LeftRead | RegRead | RightWrite}, + [AAND]= {SizeL | LeftRead | RegRead | RightWrite}, + [ABIC]= {SizeL | LeftRead | RegRead | RightWrite}, + [ACMN]= {SizeL | LeftRead | RightRead}, + [ACMP]= {SizeL | LeftRead | RightRead}, + [ADIVU]= {SizeL | LeftRead | RegRead | RightWrite}, + [ADIV]= {SizeL | LeftRead | RegRead | RightWrite}, + [AEOR]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMODU]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMOD]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMULALU]= {SizeL | LeftRead | RegRead | RightRdwr}, + [AMULAL]= {SizeL | LeftRead | RegRead | RightRdwr}, + [AMULA]= {SizeL | LeftRead | RegRead | RightRdwr}, + [AMULU]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMUL]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMULL]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMULLU]= {SizeL | LeftRead | RegRead | RightWrite}, + [AMVN]= {SizeL | LeftRead | RightWrite}, + [AORR]= {SizeL | LeftRead | RegRead | RightWrite}, + [ARSB]= {SizeL | LeftRead | RegRead | RightWrite}, + [ARSC]= {SizeL | LeftRead | RegRead | RightWrite}, + [ASBC]= {SizeL | LeftRead | RegRead | RightWrite}, + [ASLL]= {SizeL | LeftRead | RegRead | RightWrite}, + [ASRA]= {SizeL | LeftRead | RegRead | RightWrite}, + [ASRL]= {SizeL | LeftRead | RegRead | RightWrite}, + [ASUB]= {SizeL | LeftRead | RegRead | RightWrite}, + [ATEQ]= {SizeL | LeftRead | RightRead}, + [ATST]= {SizeL | LeftRead | RightRead}, + + // Floating point. + [AADDD]= {SizeD | LeftRead | RightRdwr}, + [AADDF]= {SizeF | LeftRead | RightRdwr}, + [ACMPD]= {SizeD | LeftRead | RightRead}, + [ACMPF]= {SizeF | LeftRead | RightRead}, + [ADIVD]= {SizeD | LeftRead | RightRdwr}, + [ADIVF]= {SizeF | LeftRead | RightRdwr}, + [AMULD]= {SizeD | LeftRead | RightRdwr}, + [AMULF]= {SizeF | LeftRead | RightRdwr}, + [ASUBD]= {SizeD | LeftRead | RightRdwr}, + [ASUBF]= {SizeF | LeftRead | RightRdwr}, + + // Conversions. + [AMOVWD]= {SizeD | LeftRead | RightWrite | Conv}, + [AMOVWF]= {SizeF | LeftRead | RightWrite | Conv}, + [AMOVDF]= {SizeF | LeftRead | RightWrite | Conv}, + [AMOVDW]= {SizeL | LeftRead | RightWrite | Conv}, + [AMOVFD]= {SizeD | LeftRead | RightWrite | Conv}, + [AMOVFW]= {SizeL | LeftRead | RightWrite | Conv}, + + // Moves. + [AMOVB]= {SizeB | LeftRead | RightWrite | Move}, + [AMOVD]= {SizeD | LeftRead | RightWrite | Move}, + [AMOVF]= {SizeF | LeftRead | RightWrite | Move}, + [AMOVH]= {SizeW | LeftRead | RightWrite | Move}, + [AMOVW]= {SizeL | LeftRead | RightWrite | Move}, + + // These should be split into the two different conversions instead + // of overloading the one. + [AMOVBS]= {SizeB | LeftRead | RightWrite | Conv}, + [AMOVBU]= {SizeB | LeftRead | RightWrite | Conv}, + [AMOVHS]= {SizeW | LeftRead | RightWrite | Conv}, + [AMOVHU]= {SizeW | LeftRead | RightWrite | Conv}, + + // Jumps. + [AB]= {Jump}, + [ABL]= {Call}, + [ABEQ]= {Cjmp}, + [ABNE]= {Cjmp}, + [ABCS]= {Cjmp}, + [ABHS]= {Cjmp}, + [ABCC]= {Cjmp}, + [ABLO]= {Cjmp}, + [ABMI]= {Cjmp}, + [ABPL]= {Cjmp}, + [ABVS]= {Cjmp}, + [ABVC]= {Cjmp}, + [ABHI]= {Cjmp}, + [ABLS]= {Cjmp}, + [ABGE]= {Cjmp}, + [ABLT]= {Cjmp}, + [ABGT]= {Cjmp}, + [ABLE]= {Cjmp}, + [ARET]= {Break}, +}; + +void +proginfo(ProgInfo *info, Prog *p) +{ + *info = progtable[p->as]; + if(info->flags == 0) + fatal("unknown instruction %P", p); + + if((info->flags & RegRead) && p->reg == NREG) { + info->flags &= ~RegRead; + info->flags |= CanRegRead | RightRead; + } + + if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite)) + info->flags |= RightRead; +} diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 0fa6c54b17..368da58fe0 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -180,7 +180,8 @@ regopt(Prog *firstp) int i, z, nr; uint32 vreg; Bits bit; - + ProgInfo info, info2; + if(first == 0) { fmtinstall('Q', Qconv); } @@ -243,14 +244,10 @@ regopt(Prog *firstp) */ nr = 0; for(p=firstp; p != P; p = p->link) { - switch(p->as) { - case ADATA: - case AGLOBL: - case ANAME: - case ASIGNAME: - case ATYPE: + proginfo(&info, p); + if(info.flags & Skip) continue; - } + r = rega(); nr++; if(firstr == R) { @@ -267,10 +264,8 @@ regopt(Prog *firstp) r1 = r->p1; if(r1 != R) { - switch(r1->prog->as) { - case ARET: - case AB: - case ARFE: + proginfo(&info2, r1->prog); + if(info2.flags & Break) { r->p1 = R; r1->s1 = R; } @@ -280,140 +275,29 @@ regopt(Prog *firstp) if(p->as == ABL && p->to.type == D_EXTERN) continue; - /* - * left side always read - */ - bit = mkvar(r, &p->from); - for(z=0; zuse1.b[z] |= bit.b[z]; - - /* - * middle always read when present - */ - if(p->reg != NREG) { + if(info.flags & LeftRead) { + bit = mkvar(r, &p->from); + for(z=0; zuse1.b[z] |= bit.b[z]; + } + + if(info.flags & RegRead) { 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 - */ - bit = mkvar(r, &p->to); - if(bany(&bit)) - switch(p->as) { - 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 AMULA: - case AMULAL: - case AMULALU: - for(z=0; zuse2.b[z] |= bit.b[z]; - r->set.b[z] |= bit.b[z]; - } - break; - - /* - * right side write - */ - case ANOP: - case AMOVB: - case AMOVBS: - case AMOVBU: - case AMOVD: - case AMOVDF: - case AMOVDW: - case AMOVF: - case AMOVFW: - case AMOVH: - case AMOVHS: - case AMOVHU: - case AMOVW: - case AMOVWD: - case AMOVWF: - case AMVN: - case AMULL: - case AMULLU: - if((p->scond & C_SCOND) != C_SCOND_NONE) + if(info.flags & (RightAddr | RightRead | RightWrite)) { + bit = mkvar(r, &p->to); + if(info.flags & RightAddr) + setaddrs(bit); + if(info.flags & RightRead) for(z=0; zuse2.b[z] |= bit.b[z]; - for(z=0; zset.b[z] |= bit.b[z]; - break; - - /* - * funny - */ - case ABL: - setaddrs(bit); - break; - } - - if(p->as == AMOVM) { - z = p->to.offset; - if(p->from.type == D_CONST) - z = p->from.offset; - for(i=0; z; i++) { - if(z&1) - regbits |= RtoB(i); - z >>= 1; - } + if(info.flags & RightWrite) + for(z=0; zset.b[z] |= bit.b[z]; } } if(firstr == R) -- 2.48.1