Permalink
Browse files

add BT pattern to optimizer

  • Loading branch information...
1 parent 3904f7e commit 4b139c0a217ccbf3c71a0d993eb6e3556254de60 @WalterBright WalterBright committed Jan 14, 2013
Showing with 196 additions and 10 deletions.
  1. +53 −3 src/backend/cgelem.c
  2. +116 −0 src/backend/cod4.c
  3. +1 −0 src/backend/code.h
  4. +6 −0 src/backend/evalu8.c
  5. +1 −0 src/backend/gloop.c
  6. +1 −0 src/backend/oper.h
  7. +6 −5 src/backend/optabgen.c
  8. +4 −0 src/declaration.c
  9. +2 −0 src/func.c
  10. +6 −2 src/mtype.c
View
56 src/backend/cgelem.c
@@ -1345,6 +1345,19 @@ STATIC elem * elbitwise(elem *e)
e1->E1 = el_selecte1(e1->E1);
goto Lopt;
}
+
+ // Replace ((a >> b) & 1) with (a bt b)
+ if ((I32 || I64) &&
+ e->Eoper == OPand &&
+ ul == 1 &&
+ (e->E1->Eoper == OPshr || e->E1->Eoper == OPashr) &&
+ sz <= REGSIZE
+ )
+ {
+ e->E1->Eoper = OPbtst;
+ e = el_selecte1(e);
+ goto Lopt;
+ }
}
}
return e;
@@ -3578,16 +3591,17 @@ STATIC elem * elcmp(elem *e)
/*****************************
* Boolean operator.
- * bool c => (bool c)
- * bool logical_operator e => logical_operator e
+ * OPbool
*/
STATIC elem * elbool(elem *e)
{
if (OTlogical(e->E1->Eoper) ||
+ // bool bool => bool
(tybasic(e->E1->Ety) == TYbool && tysize(e->Ety) == 1)
)
return el_selecte1(e);
+
if (OPTIMIZER)
{
// Replace bool(x,1) with (x,1),1
@@ -3659,6 +3673,26 @@ STATIC elem * elbool(elem *e)
}
e = optelem(e,TRUE);
}
+
+ // replace bool((1<<c)&b) with -(b btst c)
+ else if ((I32 || I64) &&
+ e->E1->Eoper == OPand &&
+ e->E1->E1->Eoper == OPshl &&
+ e->E1->E1->E1->Eoper == OPconst && el_tolong(e->E1->E1->E1) == 1 &&
+ tysize(e->E1->Ety) <= REGSIZE
+ )
+ {
+ tym_t ty = e->Ety;
+ elem *ex = e->E1->E1;
+ ex->Eoper = OPbtst;
+ e->E1->E1 = NULL;
+ ex->E1 = e->E1->E2;
+ e->E1->E2 = NULL;
+ ex->Ety = e->Ety;
+ el_free(e);
+ e = ex;
+ return optelem(e,TRUE);
+ }
}
return e;
}
@@ -3947,12 +3981,28 @@ STATIC elem *elc_i(elem *e)
STATIC elem * elbyteint(elem *e)
{
- if (OTlogical(e->E1->Eoper))
+ if (OTlogical(e->E1->Eoper) || e->E1->Eoper == OPbtst)
{
e->E1->Ety = e->Ety;
e = el_selecte1(e);
+ return e;
}
+ return evalu8(e);
+}
+
+/******************************
+ * OPs32_64
+ * OPu32_64
+ */
+STATIC elem * el32_64(elem *e)
+{
+ if (REGSIZE == 8 && e->E1->Eoper == OPbtst)
+ {
+ e->E1->Ety = e->Ety;
+ e = el_selecte1(e);
return e;
+ }
+ return evalu8(e);
}
/****************************
View
116 src/backend/cod4.c
@@ -3255,6 +3255,122 @@ code *cdfar16( elem *e, regm_t *pretregs)
#endif
/*************************
+ * Generate code for OPbtst
+ */
+
+code *cdbtst(elem *e, regm_t *pretregs)
+{
+ elem *e1;
+ elem *e2;
+ code *c;
+ code *c2;
+ code cs;
+ regm_t idxregs;
+ regm_t retregs;
+ unsigned reg;
+ unsigned char word;
+ tym_t ty1;
+ int op;
+ int mode;
+
+ op = 0xA3; // BT EA,value
+ mode = 4;
+
+ e1 = e->E1;
+ e2 = e->E2;
+ cs.Iflags = 0;
+
+ if (*pretregs == 0) // if don't want result
+ { c = codelem(e1,pretregs,FALSE); // eval left leaf
+ *pretregs = 0; // in case they got set
+ return cat(c,codelem(e2,pretregs,FALSE));
+ }
+
+ if ((e1->Eoper == OPind && !e1->Ecount) || e1->Eoper == OPvar)
+ {
+ c = getlvalue(&cs, e1, RMload); // get addressing mode
+ idxregs = idxregm(&cs); // mask if index regs used
+ }
+ else
+ {
+ retregs = allregs;
+ c = codelem(e1, &retregs, FALSE);
+ reg = findreg(retregs);
+ cs.Irm = modregrm(3,0,reg & 7);
+ cs.Iflags = 0;
+ cs.Irex = 0;
+ if (reg & 8)
+ cs.Irex |= REX_B;
+ idxregs = retregs;
+ }
+
+ ty1 = tybasic(e1->Ety);
+ word = (!I16 && tysize[ty1] == SHORTSIZE) ? CFopsize : 0;
+
+// if (e2->Eoper == OPconst && e2->EV.Vuns < 0x100) // should do this instead?
+ if (e2->Eoper == OPconst)
+ {
+ cs.Iop = 0x0FBA; // BT rm,imm8
+ cs.Irm |= modregrm(0,mode,0);
+ cs.Iflags |= CFpsw | word;
+ cs.IFL2 = FLconst;
+ if (tysize[ty1] == SHORTSIZE)
+ {
+ cs.IEV2.Vint = e2->EV.Vint & 15;
+ }
+ else if (tysize[ty1] == 4)
+ {
+ cs.IEV2.Vint = e2->EV.Vint & 31;
+ }
+ else
+ {
+ cs.IEV2.Vint = e2->EV.Vint & 63;
+ if (I64)
+ cs.Irex |= REX_W;
+ }
+ c2 = gen(CNIL,&cs);
+ }
+ else
+ {
+ retregs = ALLREGS & ~idxregs;
+ c2 = scodelem(e2,&retregs,idxregs,TRUE);
+ reg = findreg(retregs);
+
+ cs.Iop = 0x0F00 | op; // BT rm,reg
+ code_newreg(&cs,reg);
+ cs.Iflags |= CFpsw | word;
+ c2 = gen(c2,&cs);
+ }
+
+ if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register
+ {
+ code *nop = CNIL;
+ regm_t save = regcon.immed.mval;
+ code *cg = allocreg(&retregs,&reg,TYint);
+ regcon.immed.mval = save;
+ if ((*pretregs & mPSW) == 0)
+ {
+ cg = cat(cg,getregs(retregs));
+ cg = genregs(cg,0x19,reg,reg); // SBB reg,reg
+ cg = gen2(cg,0xF7,modregrmx(3,3,reg)); // NEG reg
+ }
+ else
+ {
+ cg = movregconst(cg,reg,1,8); // MOV reg,1
+ nop = gennop(nop);
+ cg = genjmp(cg,JC,FLcode,(block *) nop); // Jtrue nop
+ // MOV reg,0
+ movregconst(cg,reg,0,8);
+ regcon.immed.mval &= ~mask[reg];
+ }
+ *pretregs = retregs;
+ c2 = cat3(c2,cg,nop);
+ }
+
+ return cat(c,c2);
+}
+
+/*************************
* Generate code for OPbt, OPbtc, OPbtr, OPbts
*/
View
1 src/backend/code.h
@@ -421,6 +421,7 @@ cd_t cdsetjmp;
cd_t cdvoid;
cd_t cdhalt;
cd_t cdfar16;
+cd_t cdbtst;
cd_t cdbt;
cd_t cdbscan;
cd_t cdpair;
View
6 src/backend/evalu8.c
@@ -1564,6 +1564,12 @@ elem * evalu8(elem *e)
#endif
break;
+ case OPbtst:
+ if ((targ_ullong) i2 > sizeof(targ_ullong) * 8)
+ i2 = sizeof(targ_ullong) * 8;
+ e->EV.Vullong = (((targ_ullong) l1) >> i2) & 1;
+ break;
+
#if MARS
case OPashr:
if ((targ_ullong) i2 > sizeof(targ_ullong) * 8)
View
1 src/backend/gloop.c
@@ -1107,6 +1107,7 @@ STATIC void markinvar(elem *n,vec_t rd)
case OPlt: case OPle: case OPgt: case OPge:
case OPashr:
case OPror: case OProl:
+ case OPbtst:
case OPunord: case OPlg: case OPleg: case OPule:
case OPul: case OPuge: case OPug: case OPue:
View
1 src/backend/oper.h
@@ -76,6 +76,7 @@ enum OPER
OPbswap, // swap bytes
OProl, // rotate left
OPror, // rotate right
+ OPbtst, // bit test
OPstreq, /* structure assignment */
View
11 src/backend/optabgen.c
@@ -40,7 +40,7 @@ int _binary[] =
OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
OPinfo,OParray,OPfield,OPnewarray,OPmultinewarray,OPinstanceof,OPfinalinstanceof,
OPcheckcast,OPpair,OPrpair,
- OPbt,OPbtc,OPbtr,OPbts,OPror,OProl,
+ OPbt,OPbtc,OPbtr,OPbts,OPror,OProl,OPbtst,
OPremquo,
#if TX86
OPoutp,OPscale,OPyl2x,OPyl2xp1,
@@ -145,7 +145,7 @@ int _ae[] = {OPvar,OPconst,OPrelconst,OPneg,
OP128_64,OPs64_128,OPu64_128,
OPsizeof,OParray,OPfield,OPinstanceof,OPfinalinstanceof,OPcheckcast,OParraylength,
OPcallns,OPucallns,OPnullcheck,OPpair,OPrpair,
- OPbsf,OPbsr,OPbt,OPbswap,OPb_8,
+ OPbsf,OPbsr,OPbt,OPbswap,OPb_8,OPbtst,
OPgot,OPremquo,
OPnullptr,
OProl,OPror,
@@ -175,7 +175,7 @@ int _exp[] = {OPvar,OPconst,OPrelconst,OPneg,OPabs,OPrndtol,OPrint,
OPcall,OPcallns,OPeq,OPstreq,OPpostinc,OPpostdec,
OPaddass,OPminass,OPmulass,OPdivass,OPmodass,OPandass,
OPorass,OPxorass,OPshlass,OPshrass,OPashrass,OPoror,OPandand,OPcond,
- OPbsf,OPbsr,OPbt,OPbtc,OPbtr,OPbts,OPbswap,
+ OPbsf,OPbsr,OPbt,OPbtc,OPbtr,OPbts,OPbswap,OPbtst,
OProl,OPror,OPvector,
OPpair,OPrpair,OPframeptr,OPgot,OPremquo,
OPcolon,OPcolon2,OPasm,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,OPnegass,
@@ -596,8 +596,8 @@ void dotab()
case OPu8_16: X("u8_16", elbyteint, cdbyteint);
case OPs8_16: X("s8_16", elbyteint, cdbyteint);
case OP16_8: X("16_8", ellngsht,cdlngsht);
- case OPu32_64: X("u32_64", evalu8, cdshtlng);
- case OPs32_64: X("s32_64", evalu8, cdshtlng);
+ case OPu32_64: X("u32_64", el32_64, cdshtlng);
+ case OPs32_64: X("s32_64", el32_64, cdshtlng);
case OP64_32: X("64_32", el64_32, cdlngsht);
case OPu64_128: X("u64_128", evalu8, cdshtlng);
case OPs64_128: X("s64_128", evalu8, cdshtlng);
@@ -636,6 +636,7 @@ void dotab()
case OPbsf: X("bsf", elzot, cdbscan);
case OPbsr: X("bsr", elzot, cdbscan);
+ case OPbtst: X("btst", elzot, cdbtst);
case OPbt: X("bt", elzot, cdbt);
case OPbtc: X("btc", elzot, cdbt);
case OPbtr: X("btr", elzot, cdbt);
View
4 src/declaration.c
@@ -2013,6 +2013,10 @@ Expression *VarDeclaration::getConstInitializer()
ExpInitializer *ei = getExpInitializer();
if (ei)
return ei->exp;
+ else if (init)
+ {
+ return init->toExpression();
+ }
}
return NULL;
View
2 src/func.c
@@ -2985,6 +2985,8 @@ enum PURE FuncDeclaration::isPure()
if (tf->purity == PUREfwdref)
tf->purityLevel();
enum PURE purity = tf->purity;
+ if (purity > PUREweak && isNested())
+ purity = PUREweak;
if (purity > PUREweak && needThis())
{ // The attribute of the 'this' reference affects purity strength
if (type->mod & (MODimmutable | MODwild))
View
8 src/mtype.c
@@ -8154,6 +8154,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
for (size_t j = 0; j < structelems->dim; j++)
{
VarDeclaration *vd = sym->fields[j];
+ Type *telem = vd->type->addMod(this->mod);
Expression *e;
if (vd->init)
{ if (vd->init->isVoidInitializer())
@@ -8164,7 +8165,10 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
else
e = vd->type->defaultInitLiteral(loc);
if (e && vd->scope)
- e = e->semantic(vd->scope);
+ {
+ e = e->semantic(vd->scope);
+ e = e->implicitCastTo(vd->scope, telem);
+ }
(*structelems)[j] = e;
}
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
@@ -8802,7 +8806,7 @@ int TypeClass::isscope()
int TypeClass::isBaseOf(Type *t, int *poffset)
{
- if (t->ty == Tclass)
+ if (t && t->ty == Tclass)
{ ClassDeclaration *cd;
cd = ((TypeClass *)t)->sym;

0 comments on commit 4b139c0

Please sign in to comment.