mirror of https://github.com/golang/go.git
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
This commit is contained in:
parent
5636b60b70
commit
a07218385c
|
|
@ -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*);
|
||||
|
|
|
|||
|
|
@ -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<<v2->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))
|
||||
|
|
|
|||
|
|
@ -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 <u.h>
|
||||
#include <libc.h>
|
||||
#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;
|
||||
}
|
||||
160
src/cmd/5g/reg.c
160
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; z<BITS; z++)
|
||||
r->use1.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; z<BITS; z++)
|
||||
r->use1.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; z<BITS; z++)
|
||||
r->use2.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; z<BITS; z++) {
|
||||
r->use2.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; z<BITS; z++)
|
||||
r->use2.b[z] |= bit.b[z];
|
||||
for(z=0; z<BITS; z++)
|
||||
r->set.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; z<BITS; z++)
|
||||
r->set.b[z] |= bit.b[z];
|
||||
}
|
||||
}
|
||||
if(firstr == R)
|
||||
|
|
|
|||
Loading…
Reference in New Issue