Commit ad88fd1d authored by Russ Cox's avatar Russ Cox

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/3883Reviewed-by: 's avatarAustin Clements <austin@google.com>
parent b8a3e88e
...@@ -66,14 +66,22 @@ main(int argc, char **argv) ...@@ -66,14 +66,22 @@ main(int argc, char **argv)
arch.ginscall = ginscall; arch.ginscall = ginscall;
arch.igen = igen; arch.igen = igen;
arch.linkarchinit = linkarchinit; arch.linkarchinit = linkarchinit;
arch.peep = peep;
arch.proginfo = proginfo; arch.proginfo = proginfo;
arch.regalloc = regalloc; arch.regalloc = regalloc;
arch.regfree = regfree; arch.regfree = regfree;
arch.regopt = regopt;
arch.regtyp = regtyp; arch.regtyp = regtyp;
arch.sameaddr = sameaddr; arch.sameaddr = sameaddr;
arch.smallindir = smallindir; arch.smallindir = smallindir;
arch.stackaddr = stackaddr; 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); gcmain(argc, argv);
} }
...@@ -159,3 +159,19 @@ int sameaddr(Addr*, Addr*); ...@@ -159,3 +159,19 @@ int sameaddr(Addr*, Addr*);
int smallindir(Addr*, Addr*); int smallindir(Addr*, Addr*);
int stackaddr(Addr*); int stackaddr(Addr*);
Prog* unpatch(Prog*); 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 @@ ...@@ -7,7 +7,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
static Prog* appendpp(Prog*, int, int, int, int32, int, int, int32); static Prog* appendpp(Prog*, int, int, int, int32, int, int, int32);
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0); static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0);
......
// 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 @@ ...@@ -32,7 +32,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
static int xtramodes(Graph*, Flow*, Adr*); static int xtramodes(Graph*, Flow*, Adr*);
static int shortprop(Flow *r); static int shortprop(Flow *r);
...@@ -47,6 +47,7 @@ static Flow* findpre(Flow *r, Adr *v); ...@@ -47,6 +47,7 @@ static Flow* findpre(Flow *r, Adr *v);
static int copyau1(Prog *p, Adr *v); static int copyau1(Prog *p, Adr *v);
static int isdconst(Addr *a); static int isdconst(Addr *a);
static int isfloatreg(Addr*); static int isfloatreg(Addr*);
static int copyu(Prog *p, Adr *v, Adr *s);
static uint32 gactive; static uint32 gactive;
...@@ -941,7 +942,7 @@ xtramodes(Graph *g, Flow *r, Adr *a) ...@@ -941,7 +942,7 @@ xtramodes(Graph *g, Flow *r, Adr *a)
* 4 if set and used * 4 if set and used
* 0 otherwise (not touched) * 0 otherwise (not touched)
*/ */
int static int
copyu(Prog *p, Adr *v, Adr *s) copyu(Prog *p, Adr *v, Adr *s)
{ {
switch(p->as) { switch(p->as) {
...@@ -1572,3 +1573,12 @@ smallindir(Addr *a, Addr *reg) ...@@ -1572,3 +1573,12 @@ smallindir(Addr *a, Addr *reg)
a->reg == reg->reg && a->reg == reg->reg &&
0 <= a->offset && a->offset < 4096; 0 <= a->offset && a->offset < 4096;
} }
void
excise(Flow *r)
{
Prog *p;
p = r->prog;
nopout(p);
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
enum enum
{ {
...@@ -148,4 +148,13 @@ proginfo(ProgInfo *info, Prog *p) ...@@ -148,4 +148,13 @@ proginfo(ProgInfo *info, Prog *p)
if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite)) if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite))
info->flags |= RightRead; info->flags |= RightRead;
switch(p->as) {
case ADIV:
case ADIVU:
case AMOD:
case AMODU:
info->regset |= RtoB(REG_R12);
break;
}
} }
This diff is collapsed.
...@@ -89,14 +89,22 @@ main(int argc, char **argv) ...@@ -89,14 +89,22 @@ main(int argc, char **argv)
arch.ginscall = ginscall; arch.ginscall = ginscall;
arch.igen = igen; arch.igen = igen;
arch.linkarchinit = linkarchinit; arch.linkarchinit = linkarchinit;
arch.peep = peep;
arch.proginfo = proginfo; arch.proginfo = proginfo;
arch.regalloc = regalloc; arch.regalloc = regalloc;
arch.regfree = regfree; arch.regfree = regfree;
arch.regopt = regopt;
arch.regtyp = regtyp; arch.regtyp = regtyp;
arch.sameaddr = sameaddr; arch.sameaddr = sameaddr;
arch.smallindir = smallindir; arch.smallindir = smallindir;
arch.stackaddr = stackaddr; 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); gcmain(argc, argv);
} }
...@@ -159,3 +159,18 @@ int smallindir(Addr*, Addr*); ...@@ -159,3 +159,18 @@ int smallindir(Addr*, Addr*);
int stackaddr(Addr*); int stackaddr(Addr*);
Prog* unpatch(Prog*); 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 @@ ...@@ -7,7 +7,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong); static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax); static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
static void conprop(Flow *r); static void conprop(Flow *r);
static void elimshortmov(Graph *g); static void elimshortmov(Graph *g);
...@@ -44,9 +44,15 @@ static int copy1(Adr*, Adr*, Flow*, int); ...@@ -44,9 +44,15 @@ static int copy1(Adr*, Adr*, Flow*, int);
static int copyas(Adr*, Adr*); static int copyas(Adr*, Adr*);
static int copyau(Adr*, Adr*); static int copyau(Adr*, Adr*);
static int copysub(Adr*, Adr*, Adr*, int); static int copysub(Adr*, Adr*, Adr*, int);
static int copyu(Prog*, Adr*, Adr*);
static uint32 gactive; static uint32 gactive;
enum
{
exregoffset = REG_R15,
};
// do we need the carry bit // do we need the carry bit
static int static int
needc(Prog *p) needc(Prog *p)
...@@ -737,7 +743,7 @@ copy1(Adr *v1, Adr *v2, Flow *r, int f) ...@@ -737,7 +743,7 @@ copy1(Adr *v1, Adr *v2, Flow *r, int f)
* 4 if set and used * 4 if set and used
* 0 otherwise (not touched) * 0 otherwise (not touched)
*/ */
int static int
copyu(Prog *p, Adr *v, Adr *s) copyu(Prog *p, Adr *v, Adr *s)
{ {
ProgInfo info; ProgInfo info;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
// Matches real RtoB but can be used in global initializer. // Matches real RtoB but can be used in global initializer.
#define RtoB(r) (1<<((r)-REG_AX)) #define RtoB(r) (1<<((r)-REG_AX))
......
This diff is collapsed.
...@@ -66,14 +66,22 @@ main(int argc, char **argv) ...@@ -66,14 +66,22 @@ main(int argc, char **argv)
arch.ginscall = ginscall; arch.ginscall = ginscall;
arch.igen = igen; arch.igen = igen;
arch.linkarchinit = linkarchinit; arch.linkarchinit = linkarchinit;
arch.peep = peep;
arch.proginfo = proginfo; arch.proginfo = proginfo;
arch.regalloc = regalloc; arch.regalloc = regalloc;
arch.regfree = regfree; arch.regfree = regfree;
arch.regopt = regopt;
arch.regtyp = regtyp; arch.regtyp = regtyp;
arch.sameaddr = sameaddr; arch.sameaddr = sameaddr;
arch.smallindir = smallindir; arch.smallindir = smallindir;
arch.stackaddr = stackaddr; 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); gcmain(argc, argv);
} }
...@@ -171,3 +171,19 @@ int sameaddr(Addr*, Addr*); ...@@ -171,3 +171,19 @@ int sameaddr(Addr*, Addr*);
int smallindir(Addr*, Addr*); int smallindir(Addr*, Addr*);
int stackaddr(Addr*); int stackaddr(Addr*);
Prog* unpatch(Prog*); 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 @@ ...@@ -7,7 +7,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong); static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax); static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
......
...@@ -188,6 +188,14 @@ optoas(int op, Type *t) ...@@ -188,6 +188,14 @@ optoas(int op, Type *t)
a = AMOVL; a = AMOVL;
break; break;
case CASE(OAS, TFLOAT32):
a = AMOVSS;
break;
case CASE(OAS, TFLOAT64):
a = AMOVSD;
break;
case CASE(OADD, TINT8): case CASE(OADD, TINT8):
case CASE(OADD, TUINT8): case CASE(OADD, TUINT8):
a = AADDB; a = AADDB;
......
// 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 @@ ...@@ -31,10 +31,11 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
enum { enum {
REGEXT = 0, REGEXT = 0,
exregoffset = REG_DI,
}; };
static void conprop(Flow *r); static void conprop(Flow *r);
...@@ -45,6 +46,7 @@ static int copy1(Adr*, Adr*, Flow*, int); ...@@ -45,6 +46,7 @@ static int copy1(Adr*, Adr*, Flow*, int);
static int copyas(Adr*, Adr*); static int copyas(Adr*, Adr*);
static int copyau(Adr*, Adr*); static int copyau(Adr*, Adr*);
static int copysub(Adr*, Adr*, Adr*, int); static int copysub(Adr*, Adr*, Adr*, int);
static int copyu(Prog*, Adr*, Adr*);
static uint32 gactive; static uint32 gactive;
...@@ -535,7 +537,7 @@ copy1(Adr *v1, Adr *v2, Flow *r, int f) ...@@ -535,7 +537,7 @@ copy1(Adr *v1, Adr *v2, Flow *r, int f)
* 4 if set and used * 4 if set and used
* 0 otherwise (not touched) * 0 otherwise (not touched)
*/ */
int static int
copyu(Prog *p, Adr *v, Adr *s) copyu(Prog *p, Adr *v, Adr *s)
{ {
ProgInfo info; ProgInfo info;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "opt.h" #include "../gc/popt.h"
// Matches real RtoB but can be used in global initializer. // Matches real RtoB but can be used in global initializer.
#define RtoB(r) (1<<((r)-REG_AX)) #define RtoB(r) (1<<((r)-REG_AX))
......
This diff is collapsed.
...@@ -73,14 +73,22 @@ main(int argc, char **argv) ...@@ -73,14 +73,22 @@ main(int argc, char **argv)
arch.ginscall = ginscall; arch.ginscall = ginscall;
arch.igen = igen; arch.igen = igen;
arch.linkarchinit = linkarchinit; arch.linkarchinit = linkarchinit;
arch.peep = peep;
arch.proginfo = proginfo; arch.proginfo = proginfo;
arch.regalloc = regalloc; arch.regalloc = regalloc;
arch.regfree = regfree; arch.regfree = regfree;
arch.regopt = regopt;
arch.regtyp = regtyp; arch.regtyp = regtyp;
arch.sameaddr = sameaddr; arch.sameaddr = sameaddr;
arch.smallindir = smallindir; arch.smallindir = smallindir;
arch.stackaddr = stackaddr; 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); gcmain(argc, argv);
} }
...@@ -154,3 +154,19 @@ int smallindir(Addr*, Addr*); ...@@ -154,3 +154,19 @@ int smallindir(Addr*, Addr*);
int stackaddr(Addr*); int stackaddr(Addr*);
Prog* unpatch(Prog*); 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 @@ ...@@ -7,7 +7,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.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 *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); static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi);
......
// Derived from Inferno utils/6c/gc.h // Copyright 2014 The Go Authors. All rights reserved.
// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h // Use of this source code is governed by a BSD-style
// // license that can be found in the LICENSE file.
// 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*);
// Many Power ISA arithmetic and logical instructions come in four // Many Power ISA arithmetic and logical instructions come in four
// standard variants. These bits let us map between variants. // standard variants. These bits let us map between variants.
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "../gc/popt.h"
#include "opt.h" #include "opt.h"
static int regzer(Addr *a); static int regzer(Addr *a);
...@@ -42,6 +43,7 @@ static int copyau(Addr*, Addr*); ...@@ -42,6 +43,7 @@ static int copyau(Addr*, Addr*);
static int copysub(Addr*, Addr*, Addr*, int); static int copysub(Addr*, Addr*, Addr*, int);
static int copysub1(Prog*, Addr*, Addr*, int); static int copysub1(Prog*, Addr*, Addr*, int);
static int copyau1(Prog *p, Addr *v); static int copyau1(Prog *p, Addr *v);
static int copyu(Prog *p, Addr *v, Addr *s);
static uint32 gactive; static uint32 gactive;
...@@ -568,7 +570,7 @@ copy1(Addr *v1, Addr *v2, Flow *r, int f) ...@@ -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 // 4 if v is set in one address and used in another (so addresses
// can be rewritten independently) // can be rewritten independently)
// 0 otherwise (not touched) // 0 otherwise (not touched)
int static int
copyu(Prog *p, Addr *v, Addr *s) copyu(Prog *p, Addr *v, Addr *s)
{ {
if(p->from3.type != TYPE_NONE) if(p->from3.type != TYPE_NONE)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include "gg.h" #include "gg.h"
#include "../gc/popt.h"
#include "opt.h" #include "opt.h"
enum { enum {
......
This diff is collapsed.
...@@ -1679,14 +1679,22 @@ struct Arch ...@@ -1679,14 +1679,22 @@ struct Arch
void (*ginscall)(Node*, int); void (*ginscall)(Node*, int);
void (*igen)(Node*, Node*, Node*); void (*igen)(Node*, Node*, Node*);
void (*linkarchinit)(void); void (*linkarchinit)(void);
void (*peep)(Prog*);
void (*proginfo)(ProgInfo*, Prog*); void (*proginfo)(ProgInfo*, Prog*);
void (*regalloc)(Node*, Type*, Node*); void (*regalloc)(Node*, Type*, Node*);
void (*regfree)(Node*); void (*regfree)(Node*);
void (*regopt)(Prog*);
int (*regtyp)(Addr*); int (*regtyp)(Addr*);
int (*sameaddr)(Addr*, Addr*); int (*sameaddr)(Addr*, Addr*);
int (*smallindir)(Addr*, Addr*); int (*smallindir)(Addr*, Addr*);
int (*stackaddr)(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*); void afunclit(Addr*, Node*);
...@@ -1716,6 +1724,7 @@ Prog* unpatch(Prog*); ...@@ -1716,6 +1724,7 @@ Prog* unpatch(Prog*);
void datagostring(Strlit *sval, Addr *a); void datagostring(Strlit *sval, Addr *a);
int ismem(Node*); int ismem(Node*);
int samereg(Node*, Node*); int samereg(Node*, Node*);
void regopt(Prog*);
EXTERN int32 pcloc; EXTERN int32 pcloc;
......
...@@ -302,7 +302,7 @@ compile(Node *fn) ...@@ -302,7 +302,7 @@ compile(Node *fn)
fixjmp(ptxt); fixjmp(ptxt);
if(!debug['N'] || debug['R'] || debug['P']) { if(!debug['N'] || debug['R'] || debug['P']) {
arch.regopt(ptxt); regopt(ptxt);
nilopt(ptxt); nilopt(ptxt);
} }
arch.expandchecks(ptxt); arch.expandchecks(ptxt);
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#define Z N #define Z N
#define Adr Addr #define Adr Addr
...@@ -91,7 +90,7 @@ struct Reg ...@@ -91,7 +90,7 @@ struct Reg
Bits regdiff; Bits regdiff;
Bits act; Bits act;
int32 regu; // register used bitmap uint64 regu; // register used bitmap
}; };
#define R ((Reg*)0) #define R ((Reg*)0)
/*c2go extern Reg *R; */ /*c2go extern Reg *R; */
...@@ -116,15 +115,12 @@ struct Rgn ...@@ -116,15 +115,12 @@ struct Rgn
short regno; short regno;
}; };
EXTERN int32 exregoffset; // not set
EXTERN int32 exfregoffset; // not set
EXTERN Reg zreg; EXTERN Reg zreg;
EXTERN Rgn region[NRGN]; EXTERN Rgn region[NRGN];
EXTERN Rgn* rgp; EXTERN Rgn* rgp;
EXTERN int nregion; EXTERN int nregion;
EXTERN int nvar; EXTERN int nvar;
EXTERN int32 regbits; EXTERN uint64 regbits;
EXTERN int32 exregbits;
EXTERN Bits externs; EXTERN Bits externs;
EXTERN Bits params; EXTERN Bits params;
EXTERN Bits consts; EXTERN Bits consts;
...@@ -153,28 +149,23 @@ void addmove(Reg*, int, int, int); ...@@ -153,28 +149,23 @@ void addmove(Reg*, int, int, int);
Bits mkvar(Reg*, Adr*); Bits mkvar(Reg*, Adr*);
void prop(Reg*, Bits, Bits); void prop(Reg*, Bits, Bits);
void synch(Reg*, Bits); void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*); uint64 allreg(uint64, Rgn*);
void paint1(Reg*, int); void paint1(Reg*, int);
uint32 paint2(Reg*, int, int); uint64 paint2(Reg*, int, int);
void paint3(Reg*, int, uint32, int); void paint3(Reg*, int, uint64, int);
void addreg(Adr*, int); void addreg(Adr*, int);
void dumpone(Flow*, int); void dumpone(Flow*, int);
void dumpit(char*, Flow*, int); void dumpit(char*, Flow*, int);
/* /*
* peep.c * peep.c
*/
void peep(Prog*); void peep(Prog*);
void excise(Flow*); void excise(Flow*);
int copyu(Prog*, Adr*, Adr*); int copyu(Prog*, Adr*, Adr*);
*/
uint32 RtoB(int);
uint32 FtoB(int);
int BtoR(uint32);
int BtoF(uint32);
/* /*
* prog.c * prog.c
*/
void proginfo(ProgInfo*, Prog*); void proginfo(ProgInfo*, Prog*);
*/
This diff is collapsed.
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