1
0
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:
Russ Cox 2015-02-03 19:23:18 -05:00
parent b8a3e88ea7
commit ad88fd1d4a
32 changed files with 1433 additions and 5379 deletions

View File

@ -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);
}

View File

@ -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*);

View File

@ -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);

View File

@ -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*);

View File

@ -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);
}

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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*);

View File

@ -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);

View File

@ -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;

View File

@ -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))

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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*);

View File

@ -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);

View File

@ -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;

View File

@ -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*);

View File

@ -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;

View File

@ -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))

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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*);

View File

@ -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);

View File

@ -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.

View File

@ -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)

View File

@ -5,6 +5,7 @@
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "../gc/popt.h"
#include "opt.h"
enum {

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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);

View File

@ -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

File diff suppressed because it is too large Load Diff