Commit a0721838 authored by Russ Cox's avatar Russ Cox

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
parent 5636b60b
......@@ -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))
......
// 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;
}
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment