Add reglap to ncg. Add 4-byte reg_float to PowerPC ncg.
The new feature "reglap" allows two sizes of floating-point register
variables (reg_float), if each register overlaps a single register of
the other size. PowerPC ncg uses reglap to define 4-byte instances
of f14 to f31 that overlap the 8-byte instances.
When ncgg sees the definition of fs14("f14")=f14, it removes the
8-byte f14 from its rvnumbers array, and adds the 4-byte fs14 in its
place. Later, when ncg puts a variable in fs14, if it is an 8-byte
variable, then ncg switches to the 8-byte f14. The code has
/* reglap */ comments in util/ncgg or #ifdef REGLAP in mach/proto/ncg
reglap became necessary because my commit a20b87c
caused PowerPC ego
to allocate reg_float in both 4-byte and 8-byte sizes.
This commit is contained in:
parent
2c266c631a
commit
7e9348169c
|
@ -106,6 +106,7 @@ char *segname[] = {
|
|||
static long savedf[32];
|
||||
static long savedi[32];
|
||||
static int savedtop;
|
||||
static unsigned long lfs_set;
|
||||
|
||||
/* Calculate the register score of a local variable. */
|
||||
int
|
||||
|
@ -118,7 +119,7 @@ regscore(long offset, int size, int type, int frequency, int totype)
|
|||
/* Don't put reg_float in reg_any. */
|
||||
if (totype != reg_float)
|
||||
return -1;
|
||||
assert(size == 8);
|
||||
assert(size == 4 || size == 8);
|
||||
break;
|
||||
default:
|
||||
assert(size == 4);
|
||||
|
@ -155,6 +156,8 @@ i_regsave(void)
|
|||
|
||||
/* Set top of register save area, relative to fp. */
|
||||
savedtop = -framesize;
|
||||
|
||||
lfs_set = 0; /* empty set */
|
||||
}
|
||||
|
||||
/* Mark a register as being saved. */
|
||||
|
@ -168,6 +171,8 @@ regsave(const char* regname, long offset, int size)
|
|||
case 'f':
|
||||
savedf[regnum] = offset;
|
||||
framesize += 8;
|
||||
if (size == 4)
|
||||
lfs_set |= (1U << regnum);
|
||||
break;
|
||||
case 'r':
|
||||
savedi[regnum] = offset;
|
||||
|
@ -224,9 +229,14 @@ f_regsave(void)
|
|||
emit_prolog();
|
||||
saveloadregs("stw", "stmw", "stfd");
|
||||
|
||||
/*
|
||||
* Register variables with offset >= 0 must load an argument
|
||||
* from that offset.
|
||||
*/
|
||||
for (reg = 31; reg >= 0; reg--)
|
||||
if (savedf[reg] >= 0)
|
||||
fprintf(codefile, "lfd f%d, %ld(fp)\n",
|
||||
fprintf(codefile, "%s f%d, %ld(fp)\n",
|
||||
(lfs_set & (1U << reg)) ? "lfs" : "lfd",
|
||||
reg, savedf[reg]);
|
||||
|
||||
for (reg = 31; reg >= 0; reg--)
|
||||
|
|
|
@ -77,6 +77,14 @@ REGISTERS
|
|||
fs13("f13")=f13
|
||||
: FSREG.
|
||||
|
||||
/* reglap: reg_float may have subregister of different size */
|
||||
fs14("f14")=f14, fs15("f15")=f15, fs16("f16")=f16, fs17("f17")=f17,
|
||||
fs18("f18")=f18, fs19("f19")=f19, fs20("f20")=f20, fs21("f21")=f21,
|
||||
fs22("f22")=f22, fs23("f23")=f23, fs24("f24")=f24, fs25("f25")=f25,
|
||||
fs26("f26")=f26, fs27("f27")=f27, fs28("f28")=f28, fs29("f29")=f29,
|
||||
fs30("f30")=f30, fs31("f31")=f31
|
||||
: FSREG regvar(reg_float).
|
||||
|
||||
lr, ctr : SPR.
|
||||
cr0 : CR.
|
||||
|
||||
|
@ -257,7 +265,7 @@ INSTRUCTIONS
|
|||
fdiv FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 35).
|
||||
fdivs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 21).
|
||||
fmr FPR+DLOCAL:wo, FPR:ro cost(4, 5).
|
||||
fmr FSREG:wo, FSREG:ro cost(4, 5).
|
||||
fmr FSREG+LOCAL:wo, FSREG:ro cost(4, 5).
|
||||
fmul FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 5).
|
||||
fmuls FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5).
|
||||
fneg FREG+DLOCAL:wo, FREG:ro cost(4, 5).
|
||||
|
@ -270,9 +278,9 @@ INSTRUCTIONS
|
|||
lfd FPR+DLOCAL:wo, IND_RC_D+IND_RL_D:ro cost(4, 5).
|
||||
lfdu FPR:wo, IND_RC_D:ro cost(4, 5).
|
||||
lfdx FPR+DLOCAL:wo, GPR:ro, GPR:ro cost(4, 5).
|
||||
lfs FSREG:wo, IND_RC_W+IND_RL_W:ro cost(4, 4).
|
||||
lfs FSREG+LOCAL:wo, IND_RC_W+IND_RL_W:ro cost(4, 4).
|
||||
lfsu FSREG:wo, IND_RC_W:rw cost(4, 4).
|
||||
lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4).
|
||||
lfsx FSREG+LOCAL:wo, GPR:ro, GPR:ro cost(4, 4).
|
||||
lha GPR:wo, IND_RC_H_S+IND_RL_H_S:ro cost(4, 3).
|
||||
lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
||||
lhz GPR:wo, IND_RC_H+IND_RL_H:ro cost(4, 3).
|
||||
|
@ -309,7 +317,7 @@ INSTRUCTIONS
|
|||
stfdu FPR+DLOCAL:ro, IND_RC_D:rw cost(4, 4).
|
||||
stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4).
|
||||
stfs FSREG:ro, IND_RC_W+IND_RL_W:rw cost(4, 3).
|
||||
stfsu FSREG:ro, IND_RC_W:rw cost(4, 3).
|
||||
stfsu FSREG+LOCAL:ro, IND_RC_W:rw cost(4, 3).
|
||||
stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3).
|
||||
sth GPR:ro, IND_RC_H+IND_RL_H:rw cost(4, 3).
|
||||
sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
|
||||
|
@ -328,6 +336,9 @@ MOVES
|
|||
from GPR to GPR
|
||||
gen mr %2, %1
|
||||
|
||||
from FSREG to FSREG
|
||||
gen fmr %2, %1
|
||||
|
||||
from FPR to FPR+DLOCAL
|
||||
gen fmr %2, %1
|
||||
|
||||
|
@ -577,6 +588,11 @@ TESTS
|
|||
|
||||
STACKINGRULES
|
||||
|
||||
from LOCAL inreg(%off)==reg_float to STACK
|
||||
gen
|
||||
COMMENT("stack LOCAL")
|
||||
stfsu %1, {IND_RC_W, sp, 0-4}
|
||||
|
||||
from LOCAL to STACK
|
||||
gen
|
||||
COMMENT("stack LOCAL")
|
||||
|
@ -775,7 +791,7 @@ PATTERNS
|
|||
yields {SUM_RC, %a, los($1)}
|
||||
|
||||
/* Load word from local */
|
||||
pat lol inreg($1)==reg_any
|
||||
pat lol inreg($1)==reg_any || inreg($1)==reg_float
|
||||
yields {LOCAL, $1}
|
||||
pat lol
|
||||
leaving
|
||||
|
@ -795,6 +811,13 @@ PATTERNS
|
|||
with ANY_BHW
|
||||
kills regvar($1), LOCAL %off==$1
|
||||
gen move %1, {GPRE, regvar($1)}
|
||||
pat stl inreg($1)==reg_float
|
||||
with exact FSREG
|
||||
gen fmr {LOCAL, $1}, %1
|
||||
with STACK
|
||||
gen
|
||||
lfs {LOCAL, $1}, {IND_RC_W, sp, 0}
|
||||
addi sp, sp, {CONST, 4}
|
||||
pat stl
|
||||
leaving
|
||||
lal $1
|
||||
|
|
|
@ -50,7 +50,19 @@ tryreg(rvlp,typ) register struct regvar *rvlp; {
|
|||
struct regvar *save;
|
||||
|
||||
if (typ != reg_any && nregvar[typ]!=0) {
|
||||
if (machregs[rvnumbers[typ][0]].r_size!=rvlp->rv_size)
|
||||
struct reginfo *ri = &machregs[rvnumbers[typ][0]];
|
||||
int size, wrong;
|
||||
|
||||
size = ri->r_size;
|
||||
wrong = (size!=rvlp->rv_size);
|
||||
#ifdef REGLAP
|
||||
/* reg_float may have one subregister */
|
||||
if (wrong && ri->r_members[0]!=0) {
|
||||
size = machregs[ri->r_members[0]].r_size;
|
||||
wrong = (size!=rvlp->rv_size);
|
||||
}
|
||||
#endif /* REGLAP */
|
||||
if (wrong)
|
||||
score = -1;
|
||||
else
|
||||
score = regscore(rvlp->rv_off,
|
||||
|
@ -99,11 +111,29 @@ fixregvars(saveall) {
|
|||
if (saveall) {
|
||||
struct reginfo *rp;
|
||||
rp= &machregs[rvnumbers[rvtyp][i]];
|
||||
regsave(codestrings[rp->r_repr],(long)-TEM_WSIZE,rp->r_size);
|
||||
regsave(codestrings[rp->r_repr],
|
||||
(long)-TEM_WSIZE,rp->r_size);
|
||||
#ifdef REGLAP
|
||||
/* reg_float may have one subregister */
|
||||
if (rp->r_members[0]!=0) {
|
||||
rp= &machregs[rp->r_members[0]];
|
||||
regsave(codestrings[rp->r_repr],
|
||||
(long)-TEM_WSIZE,rp->r_size);
|
||||
}
|
||||
#endif
|
||||
} else if(regassigned[rvtyp][i].ra_score>0) {
|
||||
rv=regassigned[rvtyp][i].ra_rv;
|
||||
rv->rv_reg=rvnumbers[rvtyp][i];
|
||||
rv->rv_type = rvtyp;
|
||||
#ifdef REGLAP
|
||||
/* reg_float may have alternate size */
|
||||
if (machregs[rv->rv_reg].r_size != rv->rv_size) {
|
||||
rv->rv_reg = machregs[rv->rv_reg].r_members[0];
|
||||
assert(rv->rv_reg != 0);
|
||||
assert(machregs[rv->rv_reg].r_size ==
|
||||
rv->rv_size);
|
||||
}
|
||||
#endif
|
||||
regsave(codestrings[machregs[rv->rv_reg].r_repr],
|
||||
rv->rv_off,rv->rv_size);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ static char rcsid[]= "$Id$";
|
|||
#include "expr.h"
|
||||
#include "regvar.h"
|
||||
#include <cgg_cg.h>
|
||||
#include <em_reg.h>
|
||||
#include "extern.h"
|
||||
|
||||
extern set_t l_sets[];
|
||||
|
@ -276,12 +277,21 @@ expr_t iextoaddr(e) expr_t e; {
|
|||
expr_t regvar_expr(e,regtyp) expr_t e; {
|
||||
expr_t result;
|
||||
register i;
|
||||
|
||||
|
||||
result = make_expr(TYPREG,EX_REGVAR,i_expr(e),0);
|
||||
for(i=0;i<SZOFSET(MAXREGS);i++)
|
||||
result.ex_regset[i]=0;
|
||||
for(i=0;i<nregvar[regtyp];i++)
|
||||
BIS(result.ex_regset,rvnumbers[regtyp][i]);
|
||||
/* reglap: float may overlap with one subregister */
|
||||
if (reglap!=0 && regtyp==reg_float) {
|
||||
for(i=0;i<nregvar[regtyp];i++) {
|
||||
/* reg = first subregister */
|
||||
int reg = l_regs[rvnumbers[regtyp][i]].ri_memb[0];
|
||||
if (reg!=0)
|
||||
BIS(result.ex_regset,reg);
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -317,7 +317,15 @@ outregs() {
|
|||
}
|
||||
clashlist[iclashlist++] = 0;
|
||||
}
|
||||
fprintf(ctable,",%d",l_regs[i].ri_rregvar>=0);
|
||||
/*
|
||||
* Write .r_refcount = 1 for register variables or 0
|
||||
* for other registers.
|
||||
*
|
||||
* reglap: Write .r_refcount = 0 if the register
|
||||
* variable has a subregister.
|
||||
*/
|
||||
fprintf(ctable,",%d",
|
||||
l_regs[i].ri_rregvar>=0 && l_regs[i].ri_memb[0]==0);
|
||||
fprintf(ctable,"},\n");
|
||||
}
|
||||
fprintf(ctable,"};\n\n short clashlist[] = {\n\t");
|
||||
|
@ -332,6 +340,8 @@ outregvars() {
|
|||
register i,j;
|
||||
|
||||
fprintf(htable,"#define REGVARS\n");
|
||||
if (reglap!=0)
|
||||
fprintf(htable,"#define REGLAP\n");
|
||||
fprintf(ctable,"#include \"regvar.h\"\n");
|
||||
fprintf(ctable,"int nregvar[4] = { ");
|
||||
for (i=0;i<4;i++) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#define DL_REGVAR 0x4
|
||||
|
||||
extern int rvused;
|
||||
extern int reglap;
|
||||
extern int nregvar[4];
|
||||
extern int rvsize[4];
|
||||
extern int rvnumbers[4][MAXREGVAR];
|
||||
|
|
|
@ -19,6 +19,7 @@ static char rcsid[]= "$Id$";
|
|||
#include "token.h"
|
||||
#include "regvar.h"
|
||||
#include <cgg_cg.h>
|
||||
#include <em_reg.h>
|
||||
#include "extern.h"
|
||||
|
||||
n_proc(name) char *name; {
|
||||
|
@ -228,6 +229,70 @@ n_sconst(ident,val) char *ident,*val; {
|
|||
sy_p->sy_value.syv_stringno = strlookup(val);
|
||||
}
|
||||
|
||||
static void
|
||||
add_regvar(int rvnum, reginfo *regp, int rv)
|
||||
{
|
||||
int overlap, wrong;
|
||||
|
||||
overlap = wrong = 0;
|
||||
if (regp->ri_memb[0]!=0) {
|
||||
/* reglap: float may overlap with one subregister */
|
||||
if (rv==reg_float && regp->ri_memb[1]==0)
|
||||
overlap = 1;
|
||||
else
|
||||
wrong = 1;
|
||||
}
|
||||
if (wrong)
|
||||
error("Register variables may not have subregisters");
|
||||
|
||||
rvused |= ANY_REGVAR;
|
||||
if (regp->ri_size == wordsize)
|
||||
rvused |= SL_REGVAR;
|
||||
else if (regp->ri_size == 2*wordsize)
|
||||
rvused |= DL_REGVAR;
|
||||
|
||||
wrong = 0;
|
||||
if (overlap) {
|
||||
/* reglap = size of overlap float */
|
||||
if (reglap==0)
|
||||
reglap = regp->ri_size;
|
||||
else if (reglap!=regp->ri_size)
|
||||
wrong = 1;
|
||||
} else {
|
||||
if (nregvar[rv]==0)
|
||||
rvsize[rv] = regp->ri_size;
|
||||
else if (rvsize[rv]!=regp->ri_size)
|
||||
wrong = 1;
|
||||
}
|
||||
if (wrong)
|
||||
error("All register variables of one type must have the same size");
|
||||
|
||||
if (overlap) {
|
||||
reginfo *member_p = &l_regs[regp->ri_memb[0]];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* reglap: Remove member_p from rvnumbers.
|
||||
* Add reg_p in its place.
|
||||
*/
|
||||
wrong = 1;
|
||||
for (i = 0; i < nregvar[rv]; i++) {
|
||||
if (rvnumbers[rv][i] == regp->ri_memb[0]) {
|
||||
rvnumbers[rv][i] = rvnum;
|
||||
wrong = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wrong)
|
||||
error("Register variable %s can't overlap %s",
|
||||
regp->ri_name, member_p->ri_name);
|
||||
} else {
|
||||
NEXT(nregvar[rv],MAXREGVAR,"Register variable");
|
||||
rvnumbers[rv][nregvar[rv]-1] = rvnum;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
regline(rl,pl,rv) varinfo *rl,*pl; {
|
||||
register varinfo *rrl,*rpl;
|
||||
register short *sp;
|
||||
|
@ -251,21 +316,8 @@ regline(rl,pl,rv) varinfo *rl,*pl; {
|
|||
regp->ri_size = thissize;
|
||||
regp->ri_class = regclass;
|
||||
regp->ri_rregvar = rv;
|
||||
if (rv>=0) {
|
||||
if (regp->ri_memb[0]!=0)
|
||||
error("Register variables may not have subregisters");
|
||||
rvused |= ANY_REGVAR;
|
||||
if (regp->ri_size == wordsize)
|
||||
rvused |= SL_REGVAR;
|
||||
else if (regp->ri_size == 2*wordsize)
|
||||
rvused |= DL_REGVAR;
|
||||
if (nregvar[rv]==0)
|
||||
rvsize[rv] = regp->ri_size;
|
||||
else if (rvsize[rv]!=regp->ri_size)
|
||||
error("All register variables of one type must have the same size");
|
||||
NEXT(nregvar[rv],MAXREGVAR,"Register variable");
|
||||
rvnumbers[rv][nregvar[rv]-1] = rrl->vi_int[0];
|
||||
}
|
||||
if (rv>=0)
|
||||
add_regvar(rrl->vi_int[0], regp, rv);
|
||||
}
|
||||
regclass++;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ int maxmembers=0;
|
|||
int regclass=1;
|
||||
int maxtokensize=0;
|
||||
int rvused=0;
|
||||
int reglap=0;
|
||||
int nregvar[4];
|
||||
int rvsize[4];
|
||||
int rvnumbers[4][MAXREGVAR];
|
||||
|
|
Loading…
Reference in a new issue