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:
George Koehler 2017-10-14 12:40:04 -04:00
parent 2c266c631a
commit 7e9348169c
8 changed files with 163 additions and 26 deletions

View file

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

View file

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

View file

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

View file

@ -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[];
@ -282,6 +283,15 @@ expr_t regvar_expr(e,regtyp) expr_t e; {
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);
}

View file

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

View file

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

View file

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

View file

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