Skip to content

Commit

Permalink
Merge pull request #6176 from WalterBright/structslice1
Browse files Browse the repository at this point in the history
add backend/gslice.d:  struct slice optimization
  • Loading branch information
WalterBright committed Oct 7, 2016
2 parents 77d690f + 4b842de commit 68c35a6
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 6 deletions.
5 changes: 3 additions & 2 deletions src/backend/cgxmm.c
Expand Up @@ -187,7 +187,8 @@ code *xmmeq(elem *e, unsigned op, elem *e1, elem *e2,regm_t *pretregs)
// Be careful of cases like (x = x+x+x). We cannot evaluate in
// x if x is in a register.
if (isregvar(e1,&varregm,&varreg) && // if lvalue is register variable
doinreg(e1->EV.sp.Vsym,e2) // and we can compute directly into it
doinreg(e1->EV.sp.Vsym,e2) && // and we can compute directly into it
varregm & XMMREGS
)
{ regvar = TRUE;
retregs = varregm;
Expand Down Expand Up @@ -219,7 +220,7 @@ code *xmmeq(elem *e, unsigned op, elem *e1, elem *e2,regm_t *pretregs)
cl = getlvalue(&cs,e1,RMstore | retregs); // get lvalue (cl == CNIL if regvar)
}

c = getregs_imm(varregm);
c = getregs_imm(regvar ? varregm : 0);

reg = findreg(retregs & XMMREGS);
cs.Irm |= modregrm(0,(reg - XMM0) & 7,0);
Expand Down
1 change: 1 addition & 0 deletions src/backend/go.c
Expand Up @@ -275,6 +275,7 @@ void optfunc()
blockopt(0); // do block optimization
out_regcand(&globsym); // recompute register candidates
go.changes = 0; // no changes yet
sliceStructs();
if (go.mfoptim & MFcnp)
constprop(); /* make relationals unsigned */
if (go.mfoptim & (MFli | MFliv))
Expand Down
3 changes: 3 additions & 0 deletions src/backend/go.h
Expand Up @@ -105,4 +105,7 @@ void deadvar();
void verybusyexp();
list_t listrds(vec_t, elem *, vec_t);

/* gslice.c */
void sliceStructs();

#endif /* GO_H */
263 changes: 263 additions & 0 deletions src/backend/gslice.c
@@ -0,0 +1,263 @@

/*
* Copyright (c) 2016 by Digital Mars
* All Rights Reserved
* written by Walter Bright
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* http://www.boost.org/LICENSE_1_0.txt
* https://github.com/dlang/dmd/blob/master/src/backend/gslice.c
*/

#if (SCPP || MARS) && !HTOD

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#include "cc.h"
#include "el.h"
#include "go.h"
#include "oper.h"
#include "global.h"
#include "type.h"
#include "code.h"

static char __file__[] = __FILE__; /* for tassert.h */
#include "tassert.h"

/* This 'slices' a two register wide aggregate into two separate register-sized variables,
* enabling much better enregistering.
*/

struct SymInfo
{
bool canSlice;
SYMIDX si0;
};

static void sliceStructs_Gather(SymInfo *sia, elem *e)
{
while (1)
{
switch (e->Eoper)
{
case OPvar:
{
SYMIDX si = e->EV.sp.Vsym->Ssymnum;
if (si >= 0 && sia[si].canSlice)
{
assert(si < globsym.top);
if (tysize(e->Ety) != REGSIZE ||
(e->Eoffset != 0 && e->Eoffset != REGSIZE))
{
sia[si].canSlice = false;
}
}
return;
}
default:
if (OTunary(e->Eoper))
{
e = e->E1;
break;
}
if (OTbinary(e->Eoper))
{
sliceStructs_Gather(sia, e->E2);
e = e->E1;
break;
}
return;
}
}
}

static void sliceStructs_Replace(SymInfo *sia, elem *e)
{
while (1)
{
switch (e->Eoper)
{
case OPvar:
{
Symbol *s = e->EV.sp.Vsym;
SYMIDX si = s->Ssymnum;
//printf("e: %d %d\n", si, sia[si].canSlice);
//elem_print(e);
if (si >= 0 && sia[si].canSlice)
{
if (e->Eoffset == 0) // the first slice of the symbol is the same as the original
{
type_free(s->Stype);
s->Stype = type_fake(e->Ety);
}
else
{
Symbol *s1 = globsym.tab[sia[si].si0 + 1]; // +1 for second slice
type_free(s1->Stype);
s1->Stype = type_fake(e->Ety);
e->EV.sp.Vsym = s1;
e->Eoffset = 0;
//printf("replaced with:\n");
//elem_print(e);
}
}
return;
}

default:
if (OTunary(e->Eoper))
{
e = e->E1;
break;
}
if (OTbinary(e->Eoper))
{
sliceStructs_Replace(sia, e->E2);
e = e->E1;
break;
}
return;
}
}
}

void sliceStructs()
{
if (debugc) printf("sliceStructs()\n");
size_t sia_length = globsym.top;
/* 3 is because it is used for two arrays, sia[] and sia2[].
* sia2[] can grow to twice the size of sia[], as symbols can get split into two.
*/
SymInfo *sia = (SymInfo *)malloc(3 * sia_length * sizeof(SymInfo));
assert(sia);
SymInfo *sia2 = sia + sia_length;

bool anySlice = false;
for (int si = 0; si < globsym.top; si++)
{
Symbol *s = globsym.tab[si];
//printf("slice1: %s\n", s->Sident);

if ((s->Sflags & (GTregcand | SFLunambig)) != (GTregcand | SFLunambig))
{
sia[si].canSlice = false;
continue;
}

targ_size_t sz = type_size(s->Stype);
if (sz != 2 * REGSIZE ||
tyfv(s->Stype->Tty) || tybasic(s->Stype->Tty) == TYhptr) // because there is no TYseg
{
sia[si].canSlice = false;
continue;
}

switch (s->Sclass)
{
case SCfastpar:
case SCregister:
case SCauto:
case SCshadowreg:
case SCparameter:
anySlice = true;
sia[si].canSlice = true;
break;

case SCstack:
case SCpseudo:
case SCstatic:
case SCbprel:
sia[si].canSlice = false;
break;

default:
symbol_print(s);
assert(0);
}
}

if (!anySlice)
goto Ldone;

for (block *b = startblock; b; b = b->Bnext)
{
if (b->BC == BCasm)
goto Ldone;
if (b->Belem)
sliceStructs_Gather(sia, b->Belem);
}

{ // scope needed because of goto skipping declarations
bool any = false;
int n = 0; // the number of symbols added
for (int si = 0; si < sia_length; si++)
{
sia2[si + n].canSlice = false;
if (sia[si].canSlice)
{
/* Split slice-able symbol sold into two symbols,
* (sold,snew) in adjacent slots in the symbol table.
*/
Symbol *sold = globsym.tab[si + n];

size_t idlen = 2 + strlen(sold->Sident) + 2;
char *id = (char *)malloc(idlen + 1);
assert(id);
sprintf(id, "__%s_%d", sold->Sident, REGSIZE);
if (debugc) printf("creating slice symbol %s\n", id);
Symbol *snew = symbol_calloc(id, idlen);
free(id);
snew->Sclass = sold->Sclass;
snew->Sfl = sold->Sfl;
snew->Sflags = sold->Sflags;
if (snew->Sclass == SCfastpar || snew->Sclass == SCshadowreg)
{
snew->Spreg = sold->Spreg2;
snew->Spreg2 = NOREG;
sold->Spreg2 = NOREG;
}
type_free(sold->Stype);
sold->Stype = type_fake(TYnptr);
sold->Stype->Tcount++;
snew->Stype = type_fake(TYnptr);
snew->Stype->Tcount++;

SYMIDX sinew = symbol_add(snew);
for (int i = sinew; i > si + n + 1; --i)
{
globsym.tab[i] = globsym.tab[i - 1];
globsym.tab[i]->Ssymnum += 1;
}
globsym.tab[si + n + 1] = snew;
snew->Ssymnum = si + n + 1;

sia2[si + n].canSlice = true;
sia2[si + n].si0 = si + n;
++n;
any = true;
}
}
if (!any)
goto Ldone;
}

for (int si = 0; si < globsym.top; si++)
{
Symbol *s = globsym.tab[si];
assert(s->Ssymnum == si);
}

for (block *b = startblock; b; b = b->Bnext)
{
if (b->Belem)
sliceStructs_Replace(sia2, b->Belem);
}

Ldone:
free(sia);
}

#endif
4 changes: 2 additions & 2 deletions src/posix.mak
Expand Up @@ -241,7 +241,7 @@ GLUE_SRCS=$(addsuffix .d, irstate toelfdebug toctype glue gluelayer todt tocsym

DMD_SRCS=$(FRONT_SRCS) $(GLUE_SRCS) $(BACK_HDRS) $(TK_HDRS)

BACK_OBJS = go.o gdag.o gother.o gflow.o gloop.o var.o el.o \
BACK_OBJS = go.o gdag.o gother.o gflow.o gloop.o gslice.o var.o el.o \
glocal.o os.o nteh.o evalu8.o cgcs.o \
rtlsym.o cgelem.o cgen.o cgreg.o out.o \
blockopt.o cg.o type.o dt.o \
Expand Down Expand Up @@ -294,7 +294,7 @@ BACK_SRC = \
$C/cgsched.c $C/cod1.c $C/cod2.c $C/cod3.c $C/cod4.c $C/cod5.c \
$C/code.c $C/symbol.c $C/debug.c $C/dt.c $C/ee.c $C/el.c \
$C/evalu8.c $C/go.c $C/gflow.c $C/gdag.c \
$C/gother.c $C/glocal.c $C/gloop.c $C/newman.c \
$C/gother.c $C/glocal.c $C/gloop.c $C/gslice.c $C/newman.c \
$C/nteh.c $C/os.c $C/out.c $C/outbuf.c $C/ptrntab.c $C/rtlsym.c \
$C/type.c $C/melf.h $C/mach.h $C/mscoff.h $C/bcomplex.h \
$C/outbuf.h $C/token.h $C/tassert.h \
Expand Down
7 changes: 5 additions & 2 deletions src/win32.mak
Expand Up @@ -180,7 +180,7 @@ BACKOBJ= go.obj gdag.obj gother.obj gflow.obj gloop.obj var.obj el.obj \
bcomplex.obj ptrntab.obj aa.obj ti_achar.obj md5.obj \
ti_pvoid.obj mscoffobj.obj pdata.obj cv8.obj backconfig.obj \
divcoeff.obj dwarf.obj compress.obj varstats.obj \
ph2.obj util2.obj eh.obj tk.obj \
ph2.obj util2.obj eh.obj tk.obj gslice.obj \

# Root package
ROOT_SRCS=$(ROOT)/aav.d $(ROOT)/array.d $(ROOT)/ctfloat.d $(ROOT)/file.d \
Expand Down Expand Up @@ -216,7 +216,7 @@ BACKSRC= $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c \
$C\cgsched.c $C\cod1.c $C\cod2.c $C\cod3.c $C\cod4.c $C\cod5.c \
$C\code.c $C\symbol.c $C\debug.c $C\dt.c $C\ee.c $C\el.c \
$C\evalu8.c $C\go.c $C\gflow.c $C\gdag.c \
$C\gother.c $C\glocal.c $C\gloop.c $C\newman.c \
$C\gother.c $C\glocal.c $C\gloop.c $C\gslice.c $C\newman.c \
$C\nteh.c $C\os.c $C\out.c $C\outbuf.c $C\ptrntab.c $C\rtlsym.c \
$C\type.c $C\melf.h $C\mach.h $C\mscoff.h $C\bcomplex.h \
$C\outbuf.h $C\token.h $C\tassert.h \
Expand Down Expand Up @@ -516,6 +516,9 @@ gloop.obj : $C\gloop.c
glue.obj : $(CH) $C\rtlsym.h mars.h module.h glue.c
$(CC) -c $(MFLAGS) -I$(ROOT) glue

gslice.obj : $C\gslice.c
$(CC) -c $(MFLAGS) $C\gslice

md5.obj : $C\md5.h $C\md5.c
$(CC) -c $(MFLAGS) $C\md5

Expand Down

0 comments on commit 68c35a6

Please sign in to comment.