mirror of
https://github.com/golang/go
synced 2024-11-23 18:30:06 -07:00
cmd/gc: move reg.c into portable code
Now there is only one registerizer shared among all the systems. There are some unfortunate special cases based on arch.thechar in reg.c, to preserve bit-for-bit compatibility during the refactoring. Most are probably bugs one way or another and should be revisited. Change-Id: I153b435c0eaa05bbbeaf8876822eeb6dedaae3cf Reviewed-on: https://go-review.googlesource.com/3883 Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
b8a3e88ea7
commit
ad88fd1d4a
@ -66,14 +66,22 @@ main(int argc, char **argv)
|
||||
arch.ginscall = ginscall;
|
||||
arch.igen = igen;
|
||||
arch.linkarchinit = linkarchinit;
|
||||
arch.peep = peep;
|
||||
arch.proginfo = proginfo;
|
||||
arch.regalloc = regalloc;
|
||||
arch.regfree = regfree;
|
||||
arch.regopt = regopt;
|
||||
arch.regtyp = regtyp;
|
||||
arch.sameaddr = sameaddr;
|
||||
arch.smallindir = smallindir;
|
||||
arch.stackaddr = stackaddr;
|
||||
arch.excludedregs = excludedregs;
|
||||
arch.RtoB = RtoB;
|
||||
arch.FtoB = RtoB;
|
||||
arch.BtoR = BtoR;
|
||||
arch.BtoF = BtoF;
|
||||
arch.optoas = optoas;
|
||||
arch.doregbits = doregbits;
|
||||
arch.regnames = regnames;
|
||||
|
||||
gcmain(argc, argv);
|
||||
}
|
||||
|
@ -159,3 +159,19 @@ int sameaddr(Addr*, Addr*);
|
||||
int smallindir(Addr*, Addr*);
|
||||
int stackaddr(Addr*);
|
||||
Prog* unpatch(Prog*);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
uint64 excludedregs(void);
|
||||
uint64 RtoB(int);
|
||||
uint64 FtoB(int);
|
||||
int BtoR(uint64);
|
||||
int BtoF(uint64);
|
||||
uint64 doregbits(int);
|
||||
char** regnames(int*);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
static Prog* appendpp(Prog*, int, int, int, int32, int, int, int32);
|
||||
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0);
|
||||
|
179
src/cmd/5g/opt.h
179
src/cmd/5g/opt.h
@ -1,179 +0,0 @@
|
||||
// Inferno utils/5c/gc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/5c/gc.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
#define Z N
|
||||
#define Adr Addr
|
||||
|
||||
#define D_HI TYPE_NONE
|
||||
#define D_LO TYPE_NONE
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
|
||||
/*c2go
|
||||
extern Node *Z;
|
||||
enum
|
||||
{
|
||||
D_HI = TYPE_NONE,
|
||||
D_LO = TYPE_NONE,
|
||||
CLOAD = 5,
|
||||
CREF = 5,
|
||||
CINF = 1000,
|
||||
LOOP = 3,
|
||||
};
|
||||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
// register optimization information while the optimizer runs.
|
||||
// r->prog is the instruction.
|
||||
// r->prog->opt points back to r.
|
||||
struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu; // register used bitmap
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
/*c2go extern Reg *R; */
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
EXTERN int32 regbits;
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
EXTERN Bits ivar;
|
||||
EXTERN Bits ovar;
|
||||
EXTERN int change;
|
||||
EXTERN int32 maxnr;
|
||||
EXTERN int32* idom;
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
int32 ncvtreg;
|
||||
int32 nspill;
|
||||
int32 nreload;
|
||||
int32 ndelmov;
|
||||
int32 nvar;
|
||||
int32 naddr;
|
||||
} ostats;
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg *r, Adr *a);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpit(char *str, Flow *r0, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
*/
|
||||
void proginfo(ProgInfo*, Prog*);
|
@ -32,7 +32,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
static int xtramodes(Graph*, Flow*, Adr*);
|
||||
static int shortprop(Flow *r);
|
||||
@ -47,6 +47,7 @@ static Flow* findpre(Flow *r, Adr *v);
|
||||
static int copyau1(Prog *p, Adr *v);
|
||||
static int isdconst(Addr *a);
|
||||
static int isfloatreg(Addr*);
|
||||
static int copyu(Prog *p, Adr *v, Adr *s);
|
||||
|
||||
static uint32 gactive;
|
||||
|
||||
@ -941,7 +942,7 @@ xtramodes(Graph *g, Flow *r, Adr *a)
|
||||
* 4 if set and used
|
||||
* 0 otherwise (not touched)
|
||||
*/
|
||||
int
|
||||
static int
|
||||
copyu(Prog *p, Adr *v, Adr *s)
|
||||
{
|
||||
switch(p->as) {
|
||||
@ -1572,3 +1573,12 @@ smallindir(Addr *a, Addr *reg)
|
||||
a->reg == reg->reg &&
|
||||
0 <= a->offset && a->offset < 4096;
|
||||
}
|
||||
|
||||
void
|
||||
excise(Flow *r)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = r->prog;
|
||||
nopout(p);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@ -148,4 +148,13 @@ proginfo(ProgInfo *info, Prog *p)
|
||||
|
||||
if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite))
|
||||
info->flags |= RightRead;
|
||||
|
||||
switch(p->as) {
|
||||
case ADIV:
|
||||
case ADIVU:
|
||||
case AMOD:
|
||||
case AMODU:
|
||||
info->regset |= RtoB(REG_R12);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
1329
src/cmd/5g/reg.c
1329
src/cmd/5g/reg.c
File diff suppressed because it is too large
Load Diff
@ -89,14 +89,22 @@ main(int argc, char **argv)
|
||||
arch.ginscall = ginscall;
|
||||
arch.igen = igen;
|
||||
arch.linkarchinit = linkarchinit;
|
||||
arch.peep = peep;
|
||||
arch.proginfo = proginfo;
|
||||
arch.regalloc = regalloc;
|
||||
arch.regfree = regfree;
|
||||
arch.regopt = regopt;
|
||||
arch.regtyp = regtyp;
|
||||
arch.sameaddr = sameaddr;
|
||||
arch.smallindir = smallindir;
|
||||
arch.stackaddr = stackaddr;
|
||||
arch.excludedregs = excludedregs;
|
||||
arch.RtoB = RtoB;
|
||||
arch.FtoB = FtoB;
|
||||
arch.BtoR = BtoR;
|
||||
arch.BtoF = BtoF;
|
||||
arch.optoas = optoas;
|
||||
arch.doregbits = doregbits;
|
||||
arch.regnames = regnames;
|
||||
|
||||
gcmain(argc, argv);
|
||||
}
|
||||
|
@ -159,3 +159,18 @@ int smallindir(Addr*, Addr*);
|
||||
int stackaddr(Addr*);
|
||||
Prog* unpatch(Prog*);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
uint64 excludedregs(void);
|
||||
uint64 RtoB(int);
|
||||
uint64 FtoB(int);
|
||||
int BtoR(uint64);
|
||||
int BtoF(uint64);
|
||||
uint64 doregbits(int);
|
||||
char** regnames(int*);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
|
||||
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
static void conprop(Flow *r);
|
||||
static void elimshortmov(Graph *g);
|
||||
@ -44,9 +44,15 @@ static int copy1(Adr*, Adr*, Flow*, int);
|
||||
static int copyas(Adr*, Adr*);
|
||||
static int copyau(Adr*, Adr*);
|
||||
static int copysub(Adr*, Adr*, Adr*, int);
|
||||
static int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
static uint32 gactive;
|
||||
|
||||
enum
|
||||
{
|
||||
exregoffset = REG_R15,
|
||||
};
|
||||
|
||||
// do we need the carry bit
|
||||
static int
|
||||
needc(Prog *p)
|
||||
@ -737,7 +743,7 @@ copy1(Adr *v1, Adr *v2, Flow *r, int f)
|
||||
* 4 if set and used
|
||||
* 0 otherwise (not touched)
|
||||
*/
|
||||
int
|
||||
static int
|
||||
copyu(Prog *p, Adr *v, Adr *s)
|
||||
{
|
||||
ProgInfo info;
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
// Matches real RtoB but can be used in global initializer.
|
||||
#define RtoB(r) (1<<((r)-REG_AX))
|
||||
|
1176
src/cmd/6g/reg.c
1176
src/cmd/6g/reg.c
File diff suppressed because it is too large
Load Diff
@ -66,14 +66,22 @@ main(int argc, char **argv)
|
||||
arch.ginscall = ginscall;
|
||||
arch.igen = igen;
|
||||
arch.linkarchinit = linkarchinit;
|
||||
arch.peep = peep;
|
||||
arch.proginfo = proginfo;
|
||||
arch.regalloc = regalloc;
|
||||
arch.regfree = regfree;
|
||||
arch.regopt = regopt;
|
||||
arch.regtyp = regtyp;
|
||||
arch.sameaddr = sameaddr;
|
||||
arch.smallindir = smallindir;
|
||||
arch.stackaddr = stackaddr;
|
||||
arch.excludedregs = excludedregs;
|
||||
arch.RtoB = RtoB;
|
||||
arch.FtoB = FtoB;
|
||||
arch.BtoR = BtoR;
|
||||
arch.BtoF = BtoF;
|
||||
arch.optoas = optoas;
|
||||
arch.doregbits = doregbits;
|
||||
arch.regnames = regnames;
|
||||
|
||||
gcmain(argc, argv);
|
||||
}
|
||||
|
@ -171,3 +171,19 @@ int sameaddr(Addr*, Addr*);
|
||||
int smallindir(Addr*, Addr*);
|
||||
int stackaddr(Addr*);
|
||||
Prog* unpatch(Prog*);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
uint64 excludedregs(void);
|
||||
uint64 RtoB(int);
|
||||
uint64 FtoB(int);
|
||||
int BtoR(uint64);
|
||||
int BtoF(uint64);
|
||||
uint64 doregbits(int);
|
||||
char** regnames(int*);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
|
||||
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
|
||||
|
@ -188,6 +188,14 @@ optoas(int op, Type *t)
|
||||
a = AMOVL;
|
||||
break;
|
||||
|
||||
case CASE(OAS, TFLOAT32):
|
||||
a = AMOVSS;
|
||||
break;
|
||||
|
||||
case CASE(OAS, TFLOAT64):
|
||||
a = AMOVSD;
|
||||
break;
|
||||
|
||||
case CASE(OADD, TINT8):
|
||||
case CASE(OADD, TUINT8):
|
||||
a = AADDB;
|
||||
|
192
src/cmd/8g/opt.h
192
src/cmd/8g/opt.h
@ -1,192 +0,0 @@
|
||||
// Derived from Inferno utils/6c/gc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
#define Z N
|
||||
#define Adr Addr
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
|
||||
/*c2go
|
||||
extern Node *Z;
|
||||
enum
|
||||
{
|
||||
CLOAD = 5,
|
||||
CREF = 5,
|
||||
CINF = 1000,
|
||||
LOOP = 3,
|
||||
};
|
||||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
// register optimization information while the optimizer runs.
|
||||
// r->prog is the instruction.
|
||||
// r->prog->opt points back to r.
|
||||
struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu; // register used bitmap
|
||||
int32 rpo; // reverse post ordering
|
||||
int32 active;
|
||||
|
||||
uint16 loop; // x5 for every loop
|
||||
uchar refset; // diagnostic generated
|
||||
|
||||
Reg* p1; // predecessors of this instruction: p1,
|
||||
Reg* p2; // and then p2 linked though p2link.
|
||||
Reg* p2link;
|
||||
Reg* s1; // successors of this instruction (at most two: s1 and s2).
|
||||
Reg* s2;
|
||||
Reg* link; // next instruction in function code
|
||||
Prog* prog; // actual instruction
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
/*c2go extern Reg *R; */
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN int32 exregoffset; // not set
|
||||
EXTERN int32 exfregoffset; // not set
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits;
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
EXTERN Bits ivar;
|
||||
EXTERN Bits ovar;
|
||||
EXTERN int change;
|
||||
EXTERN int32 maxnr;
|
||||
EXTERN int32* idom;
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
int32 ncvtreg;
|
||||
int32 nspill;
|
||||
int32 nreload;
|
||||
int32 ndelmov;
|
||||
int32 nvar;
|
||||
int32 naddr;
|
||||
} ostats;
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Adr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, int32);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
*/
|
||||
void proginfo(ProgInfo*, Prog*);
|
@ -31,10 +31,11 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
enum {
|
||||
REGEXT = 0,
|
||||
exregoffset = REG_DI,
|
||||
};
|
||||
|
||||
static void conprop(Flow *r);
|
||||
@ -45,6 +46,7 @@ static int copy1(Adr*, Adr*, Flow*, int);
|
||||
static int copyas(Adr*, Adr*);
|
||||
static int copyau(Adr*, Adr*);
|
||||
static int copysub(Adr*, Adr*, Adr*, int);
|
||||
static int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
static uint32 gactive;
|
||||
|
||||
@ -535,7 +537,7 @@ copy1(Adr *v1, Adr *v2, Flow *r, int f)
|
||||
* 4 if set and used
|
||||
* 0 otherwise (not touched)
|
||||
*/
|
||||
int
|
||||
static int
|
||||
copyu(Prog *p, Adr *v, Adr *s)
|
||||
{
|
||||
ProgInfo info;
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
// Matches real RtoB but can be used in global initializer.
|
||||
#define RtoB(r) (1<<((r)-REG_AX))
|
||||
|
1187
src/cmd/8g/reg.c
1187
src/cmd/8g/reg.c
File diff suppressed because it is too large
Load Diff
@ -73,14 +73,22 @@ main(int argc, char **argv)
|
||||
arch.ginscall = ginscall;
|
||||
arch.igen = igen;
|
||||
arch.linkarchinit = linkarchinit;
|
||||
arch.peep = peep;
|
||||
arch.proginfo = proginfo;
|
||||
arch.regalloc = regalloc;
|
||||
arch.regfree = regfree;
|
||||
arch.regopt = regopt;
|
||||
arch.regtyp = regtyp;
|
||||
arch.sameaddr = sameaddr;
|
||||
arch.smallindir = smallindir;
|
||||
arch.stackaddr = stackaddr;
|
||||
arch.excludedregs = excludedregs;
|
||||
arch.RtoB = RtoB;
|
||||
arch.FtoB = RtoB;
|
||||
arch.BtoR = BtoR;
|
||||
arch.BtoF = BtoF;
|
||||
arch.optoas = optoas;
|
||||
arch.doregbits = doregbits;
|
||||
arch.regnames = regnames;
|
||||
|
||||
gcmain(argc, argv);
|
||||
}
|
||||
|
@ -154,3 +154,19 @@ int smallindir(Addr*, Addr*);
|
||||
int stackaddr(Addr*);
|
||||
Prog* unpatch(Prog*);
|
||||
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
uint64 excludedregs(void);
|
||||
uint64 RtoB(int);
|
||||
uint64 FtoB(int);
|
||||
int BtoR(uint64);
|
||||
int BtoF(uint64);
|
||||
uint64 doregbits(int);
|
||||
char** regnames(int*);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "opt.h"
|
||||
#include "../gc/popt.h"
|
||||
|
||||
static Prog *appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset);
|
||||
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi);
|
||||
|
175
src/cmd/9g/opt.h
175
src/cmd/9g/opt.h
@ -1,175 +1,6 @@
|
||||
// Derived from Inferno utils/6c/gc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
#define Z N
|
||||
#define Adr Addr
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
|
||||
/*c2go
|
||||
extern Node *Z;
|
||||
enum
|
||||
{
|
||||
CLOAD = 5,
|
||||
CREF = 5,
|
||||
CINF = 1000,
|
||||
LOOP = 3,
|
||||
};
|
||||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint32 LOAD(Reg*);
|
||||
uint32 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
// register optimization information while the optimizer runs.
|
||||
// r->prog is the instruction.
|
||||
// r->prog->opt points back to r.
|
||||
struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
uint64 regu; // register used bitmap
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
/*c2go extern Reg *R; */
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN int32 exregoffset; // not set
|
||||
EXTERN int32 exfregoffset; // not set
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits; // TODO(austin) not used; remove
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
EXTERN Bits ivar;
|
||||
EXTERN Bits ovar;
|
||||
EXTERN int change;
|
||||
EXTERN int32 maxnr;
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
int32 ncvtreg;
|
||||
int32 nspill;
|
||||
int32 ndelmov;
|
||||
int32 nvar;
|
||||
} ostats;
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Adr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void synch(Reg*, Bits);
|
||||
uint64 allreg(uint64, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint64 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint64, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
uint64 RtoB(int);
|
||||
uint64 FtoB(int);
|
||||
int BtoR(uint64);
|
||||
int BtoF(uint64);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
*/
|
||||
void proginfo(ProgInfo*, Prog*);
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Many Power ISA arithmetic and logical instructions come in four
|
||||
// standard variants. These bits let us map between variants.
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "../gc/popt.h"
|
||||
#include "opt.h"
|
||||
|
||||
static int regzer(Addr *a);
|
||||
@ -42,6 +43,7 @@ static int copyau(Addr*, Addr*);
|
||||
static int copysub(Addr*, Addr*, Addr*, int);
|
||||
static int copysub1(Prog*, Addr*, Addr*, int);
|
||||
static int copyau1(Prog *p, Addr *v);
|
||||
static int copyu(Prog *p, Addr *v, Addr *s);
|
||||
|
||||
static uint32 gactive;
|
||||
|
||||
@ -568,7 +570,7 @@ copy1(Addr *v1, Addr *v2, Flow *r, int f)
|
||||
// 4 if v is set in one address and used in another (so addresses
|
||||
// can be rewritten independently)
|
||||
// 0 otherwise (not touched)
|
||||
int
|
||||
static int
|
||||
copyu(Prog *p, Addr *v, Addr *s)
|
||||
{
|
||||
if(p->from3.type != TYPE_NONE)
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "gg.h"
|
||||
#include "../gc/popt.h"
|
||||
#include "opt.h"
|
||||
|
||||
enum {
|
||||
|
1176
src/cmd/9g/reg.c
1176
src/cmd/9g/reg.c
File diff suppressed because it is too large
Load Diff
@ -1679,14 +1679,22 @@ struct Arch
|
||||
void (*ginscall)(Node*, int);
|
||||
void (*igen)(Node*, Node*, Node*);
|
||||
void (*linkarchinit)(void);
|
||||
void (*peep)(Prog*);
|
||||
void (*proginfo)(ProgInfo*, Prog*);
|
||||
void (*regalloc)(Node*, Type*, Node*);
|
||||
void (*regfree)(Node*);
|
||||
void (*regopt)(Prog*);
|
||||
int (*regtyp)(Addr*);
|
||||
int (*sameaddr)(Addr*, Addr*);
|
||||
int (*smallindir)(Addr*, Addr*);
|
||||
int (*stackaddr)(Addr*);
|
||||
uint64 (*excludedregs)(void);
|
||||
uint64 (*RtoB)(int);
|
||||
uint64 (*FtoB)(int);
|
||||
int (*BtoR)(uint64);
|
||||
int (*BtoF)(uint64);
|
||||
int (*optoas)(int, Type*);
|
||||
uint64 (*doregbits)(int);
|
||||
char **(*regnames)(int*);
|
||||
};
|
||||
|
||||
void afunclit(Addr*, Node*);
|
||||
@ -1716,6 +1724,7 @@ Prog* unpatch(Prog*);
|
||||
void datagostring(Strlit *sval, Addr *a);
|
||||
int ismem(Node*);
|
||||
int samereg(Node*, Node*);
|
||||
void regopt(Prog*);
|
||||
|
||||
EXTERN int32 pcloc;
|
||||
|
||||
|
@ -302,7 +302,7 @@ compile(Node *fn)
|
||||
|
||||
fixjmp(ptxt);
|
||||
if(!debug['N'] || debug['R'] || debug['P']) {
|
||||
arch.regopt(ptxt);
|
||||
regopt(ptxt);
|
||||
nilopt(ptxt);
|
||||
}
|
||||
arch.expandchecks(ptxt);
|
||||
|
@ -28,7 +28,6 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
#define Z N
|
||||
#define Adr Addr
|
||||
|
||||
@ -91,7 +90,7 @@ struct Reg
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu; // register used bitmap
|
||||
uint64 regu; // register used bitmap
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
/*c2go extern Reg *R; */
|
||||
@ -116,15 +115,12 @@ struct Rgn
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN int32 exregoffset; // not set
|
||||
EXTERN int32 exfregoffset; // not set
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits;
|
||||
EXTERN uint64 regbits;
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
@ -153,28 +149,23 @@ void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Adr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
uint64 allreg(uint64, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
uint64 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint64, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(Prog*);
|
||||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
*/
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
*/
|
||||
|
||||
void proginfo(ProgInfo*, Prog*);
|
||||
*/
|
1193
src/cmd/gc/reg.c
Normal file
1193
src/cmd/gc/reg.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user