Add reglap to ncg. Add 4-byte reg_float to PowerPC ncg.
authorGeorge Koehler <xkernigh@netscape.net>
Sat, 14 Oct 2017 16:40:04 +0000 (12:40 -0400)
committerGeorge Koehler <xkernigh@netscape.net>
Sat, 14 Oct 2017 16:40:04 +0000 (12:40 -0400)
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.

mach/powerpc/ncg/mach.c
mach/powerpc/ncg/table
mach/proto/ncg/regvar.c
util/ncgg/expr.c
util/ncgg/output.c
util/ncgg/regvar.h
util/ncgg/subr.c
util/ncgg/var.c

index 31ca2d3..32e05da 100644 (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--)
index 7c6ffbd..23b9042 100644 (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
index 4c11da2..934b775 100644 (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);
                }
index 77afe57..0a63515 100644 (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[];
@@ -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);
 }
                
index 77e3eb4..9d2f2b8 100644 (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++) {
index 7961d1e..9a772c0 100644 (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];
index 08c7c65..89b2b09 100644 (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++;
 }
index 72a3f82..19a4da4 100644 (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];