mirror of
https://github.com/dlang/dmd.git
synced 2025-04-28 14:10:11 +03:00
struct elem: add alias this to remove .EV. pt 3
This commit is contained in:
parent
baa3889636
commit
d94fa11c90
6 changed files with 734 additions and 734 deletions
|
@ -39,7 +39,7 @@ enum Aetype { cse, arraybounds }
|
||||||
private __gshared Aetype aetype;
|
private __gshared Aetype aetype;
|
||||||
|
|
||||||
@trusted
|
@trusted
|
||||||
bool Eunambig(elem* e) { return OTassign(e.Eoper) && e.EV.E1.Eoper == OPvar; }
|
bool Eunambig(elem* e) { return OTassign(e.Eoper) && e.E1.Eoper == OPvar; }
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
* Determine if floating point should be cse'd.
|
* Determine if floating point should be cse'd.
|
||||||
|
@ -215,13 +215,13 @@ private void aewalk(elem **pn,vec_t ae)
|
||||||
vec_clearbit(i,ae);
|
vec_clearbit(i,ae);
|
||||||
if (OTunary(n.Eoper))
|
if (OTunary(n.Eoper))
|
||||||
{
|
{
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTbinary(n.Eoper))
|
else if (OTbinary(n.Eoper))
|
||||||
{
|
{
|
||||||
aeclear(n.EV.E1);
|
aeclear(n.E1);
|
||||||
n = n.EV.E2;
|
n = n.E2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -245,8 +245,8 @@ private void aewalk(elem **pn,vec_t ae)
|
||||||
// ae = ae & ael & aer
|
// ae = ae & ael & aer
|
||||||
// AEs gened by ael and aer are mutually exclusive
|
// AEs gened by ael and aer are mutually exclusive
|
||||||
vec_t aer = vec_clone(ae);
|
vec_t aer = vec_clone(ae);
|
||||||
aewalk(&(n.EV.E1),ae);
|
aewalk(&(n.E1),ae);
|
||||||
aewalk(&(n.EV.E2),aer);
|
aewalk(&(n.E2),aer);
|
||||||
vec_andass(ae,aer);
|
vec_andass(ae,aer);
|
||||||
vec_free(aer);
|
vec_free(aer);
|
||||||
break;
|
break;
|
||||||
|
@ -255,20 +255,20 @@ private void aewalk(elem **pn,vec_t ae)
|
||||||
case OPandand:
|
case OPandand:
|
||||||
case OPoror:
|
case OPoror:
|
||||||
{
|
{
|
||||||
aewalk(&(n.EV.E1),ae);
|
aewalk(&(n.E1),ae);
|
||||||
/* ae &= aer */
|
/* ae &= aer */
|
||||||
vec_t aer = vec_clone(ae);
|
vec_t aer = vec_clone(ae);
|
||||||
aewalk(&(n.EV.E2),aer);
|
aewalk(&(n.E2),aer);
|
||||||
if (el_returns(n.EV.E2))
|
if (el_returns(n.E2))
|
||||||
vec_andass(ae,aer);
|
vec_andass(ae,aer);
|
||||||
vec_free(aer);
|
vec_free(aer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OPnegass:
|
case OPnegass:
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (t.Eoper == OPind)
|
if (t.Eoper == OPind)
|
||||||
aewalk(&(t.EV.E1),ae);
|
aewalk(&(t.E1),ae);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPctor:
|
case OPctor:
|
||||||
|
@ -288,30 +288,30 @@ private void aewalk(elem **pn,vec_t ae)
|
||||||
{
|
{
|
||||||
// Don't CSE constants that will turn into
|
// Don't CSE constants that will turn into
|
||||||
// an INC or DEC anyway
|
// an INC or DEC anyway
|
||||||
if (n.EV.E2.Eoper == OPconst &&
|
if (n.E2.Eoper == OPconst &&
|
||||||
n.EV.E2.EV.Vint == 1 &&
|
n.E2.Vint == 1 &&
|
||||||
(op == OPaddass || op == OPminass ||
|
(op == OPaddass || op == OPminass ||
|
||||||
op == OPpostinc || op == OPpostdec)
|
op == OPpostinc || op == OPpostdec)
|
||||||
)
|
)
|
||||||
{ }
|
{ }
|
||||||
else
|
else
|
||||||
aewalk(&(n.EV.E2),ae);
|
aewalk(&(n.E2),ae);
|
||||||
}
|
}
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{
|
{
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (t.Eoper == OPind)
|
if (t.Eoper == OPind)
|
||||||
aewalk(&(t.EV.E1),ae);
|
aewalk(&(t.E1),ae);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
aewalk(&(n.EV.E1),ae);
|
aewalk(&(n.E1),ae);
|
||||||
if (!ERTOL(n))
|
if (!ERTOL(n))
|
||||||
aewalk(&(n.EV.E2),ae);
|
aewalk(&(n.E2),ae);
|
||||||
}
|
}
|
||||||
else if (OTunary(op))
|
else if (OTunary(op))
|
||||||
{
|
{
|
||||||
assert(op != OPnegass);
|
assert(op != OPnegass);
|
||||||
aewalk(&(n.EV.E1),ae);
|
aewalk(&(n.E1),ae);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ private void aewalk(elem **pn,vec_t ae)
|
||||||
if (Eunambig(n)) // if unambiguous definition
|
if (Eunambig(n)) // if unambiguous definition
|
||||||
{
|
{
|
||||||
assert(t.Eoper == OPvar);
|
assert(t.Eoper == OPvar);
|
||||||
Symbol* s = t.EV.Vsym;
|
Symbol* s = t.Vsym;
|
||||||
if (Symbol_isAffected(*s))
|
if (Symbol_isAffected(*s))
|
||||||
vec_subass(ae,go.starkill);
|
vec_subass(ae,go.starkill);
|
||||||
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
|
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
|
||||||
|
@ -332,18 +332,18 @@ private void aewalk(elem **pn,vec_t ae)
|
||||||
if (!e) continue;
|
if (!e) continue;
|
||||||
if (OTunary(e.Eoper))
|
if (OTunary(e.Eoper))
|
||||||
{
|
{
|
||||||
if (vec_testbit(e.EV.E1.Eexp,ae))
|
if (vec_testbit(e.E1.Eexp,ae))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTbinary(e.Eoper))
|
else if (OTbinary(e.Eoper))
|
||||||
{
|
{
|
||||||
if (vec_testbit(e.EV.E1.Eexp,ae) &&
|
if (vec_testbit(e.E1.Eexp,ae) &&
|
||||||
vec_testbit(e.EV.E2.Eexp,ae))
|
vec_testbit(e.E2.Eexp,ae))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (e.Eoper == OPvar)
|
else if (e.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
if (e.EV.Vsym != s)
|
if (e.Vsym != s)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -402,33 +402,33 @@ private elem * delcse(elem **pe)
|
||||||
assert(e.Ecount != 0);
|
assert(e.Ecount != 0);
|
||||||
if (!OTleaf(e.Eoper))
|
if (!OTleaf(e.Eoper))
|
||||||
{
|
{
|
||||||
if (e.EV.E1.Ecount == 0xFF-1)
|
if (e.E1.Ecount == 0xFF-1)
|
||||||
{
|
{
|
||||||
elem *ereplace;
|
elem *ereplace;
|
||||||
ereplace = el_calloc();
|
ereplace = el_calloc();
|
||||||
el_copy(ereplace,e.EV.E1);
|
el_copy(ereplace,e.E1);
|
||||||
e.EV.E1 = ereplace;
|
e.E1 = ereplace;
|
||||||
ereplace.Ecount = 0;
|
ereplace.Ecount = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
e.EV.E1.Ecount++;
|
e.E1.Ecount++;
|
||||||
debug assert(e.EV.E1.Ecount != 0);
|
debug assert(e.E1.Ecount != 0);
|
||||||
}
|
}
|
||||||
if (OTbinary(e.Eoper))
|
if (OTbinary(e.Eoper))
|
||||||
{
|
{
|
||||||
if (e.EV.E2.Ecount == 0xFF-1)
|
if (e.E2.Ecount == 0xFF-1)
|
||||||
{
|
{
|
||||||
elem *ereplace;
|
elem *ereplace;
|
||||||
ereplace = el_calloc();
|
ereplace = el_calloc();
|
||||||
el_copy(ereplace,e.EV.E2);
|
el_copy(ereplace,e.E2);
|
||||||
e.EV.E2 = ereplace;
|
e.E2 = ereplace;
|
||||||
ereplace.Ecount = 0;
|
ereplace.Ecount = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
e.EV.E2.Ecount++;
|
e.E2.Ecount++;
|
||||||
debug assert(e.EV.E2.Ecount != 0);
|
debug assert(e.E2.Ecount != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -465,67 +465,67 @@ L1:
|
||||||
if (op == OPind)
|
if (op == OPind)
|
||||||
{
|
{
|
||||||
bool scaledIndex = I32 || I64; // if scaled index addressing mode support
|
bool scaledIndex = I32 || I64; // if scaled index addressing mode support
|
||||||
elem *e1 = e.EV.E1;
|
elem *e1 = e.E1;
|
||||||
if (e1.Eoper == OPadd &&
|
if (e1.Eoper == OPadd &&
|
||||||
e1.Ecount
|
e1.Ecount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (scaledIndex)
|
if (scaledIndex)
|
||||||
{
|
{
|
||||||
e1 = delcse(&e.EV.E1);
|
e1 = delcse(&e.E1);
|
||||||
if (e1.EV.E1.Ecount) // == 1)
|
if (e1.E1.Ecount) // == 1)
|
||||||
delcse(&e1.EV.E1);
|
delcse(&e1.E1);
|
||||||
if (e1.EV.E2.Ecount && e1.EV.E2.Eoper != OPind)
|
if (e1.E2.Ecount && e1.E2.Eoper != OPind)
|
||||||
delcse(&e1.EV.E2);
|
delcse(&e1.E2);
|
||||||
}
|
}
|
||||||
/* *(v +. c)
|
/* *(v +. c)
|
||||||
* *(*pc +. c)
|
* *(*pc +. c)
|
||||||
* The + and the const shouldn't be CSEs.
|
* The + and the const shouldn't be CSEs.
|
||||||
*/
|
*/
|
||||||
else if (e1.EV.E2.Eoper == OPconst &&
|
else if (e1.E2.Eoper == OPconst &&
|
||||||
(e1.EV.E1.Eoper == OPvar || (e1.EV.E1.Eoper == OPind && e1.EV.E1.Ety & (mTYconst | mTYimmutable)))
|
(e1.E1.Eoper == OPvar || (e1.E1.Eoper == OPind && e1.E1.Ety & (mTYconst | mTYimmutable)))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
e1 = delcse(&e.EV.E1);
|
e1 = delcse(&e.E1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *(((e <<. 3) + e) + e)
|
/* *(((e <<. 3) + e) + e)
|
||||||
*/
|
*/
|
||||||
if (scaledIndex && e1.Eoper == OPadd &&
|
if (scaledIndex && e1.Eoper == OPadd &&
|
||||||
e1.EV.E1.Eoper == OPadd &&
|
e1.E1.Eoper == OPadd &&
|
||||||
e1.EV.E1.EV.E1.Ecount &&
|
e1.E1.E1.Ecount &&
|
||||||
e1.EV.E1.EV.E1.Eoper == OPshl &&
|
e1.E1.E1.Eoper == OPshl &&
|
||||||
e1.EV.E1.EV.E1.EV.E2.Eoper == OPconst &&
|
e1.E1.E1.E2.Eoper == OPconst &&
|
||||||
e1.EV.E1.EV.E1.EV.E2.EV.Vuns <= 3
|
e1.E1.E1.E2.Vuns <= 3
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
delcse(&e1.EV.E1.EV.E1); // the <<. operator
|
delcse(&e1.E1.E1); // the <<. operator
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *(((e << 3) +. e) + e)
|
/* *(((e << 3) +. e) + e)
|
||||||
*/
|
*/
|
||||||
if (scaledIndex && e1.Eoper == OPadd &&
|
if (scaledIndex && e1.Eoper == OPadd &&
|
||||||
e1.EV.E1.Eoper == OPadd &&
|
e1.E1.Eoper == OPadd &&
|
||||||
e1.EV.E1.Ecount &&
|
e1.E1.Ecount &&
|
||||||
e1.EV.E1.EV.E1.Eoper == OPshl &&
|
e1.E1.E1.Eoper == OPshl &&
|
||||||
e1.EV.E1.EV.E1.EV.E2.Eoper == OPconst &&
|
e1.E1.E1.E2.Eoper == OPconst &&
|
||||||
e1.EV.E1.EV.E1.EV.E2.EV.Vuns <= 3
|
e1.E1.E1.E2.Vuns <= 3
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
delcse(&e1.EV.E1); // the +. operator
|
delcse(&e1.E1); // the +. operator
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *((e <<. 3) + e)
|
/* *((e <<. 3) + e)
|
||||||
*/
|
*/
|
||||||
else if (scaledIndex && e1.Eoper == OPadd &&
|
else if (scaledIndex && e1.Eoper == OPadd &&
|
||||||
e1.EV.E1.Ecount &&
|
e1.E1.Ecount &&
|
||||||
e1.EV.E1.Eoper == OPshl &&
|
e1.E1.Eoper == OPshl &&
|
||||||
e1.EV.E1.EV.E2.Eoper == OPconst &&
|
e1.E1.E2.Eoper == OPconst &&
|
||||||
e1.EV.E1.EV.E2.EV.Vuns <= 3
|
e1.E1.E2.Vuns <= 3
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
delcse(&e1.EV.E1); // the <<. operator
|
delcse(&e1.E1); // the <<. operator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove *e1 where it's a double
|
// Remove *e1 where it's a double
|
||||||
|
@ -536,24 +536,24 @@ L1:
|
||||||
else if (op == OPu16_32 && I16 && e.Ecount)
|
else if (op == OPu16_32 && I16 && e.Ecount)
|
||||||
e = delcse(pe);
|
e = delcse(pe);
|
||||||
|
|
||||||
else if (op == OPd_ld && e.EV.E1.Ecount > 0)
|
else if (op == OPd_ld && e.E1.Ecount > 0)
|
||||||
delcse(&e.EV.E1);
|
delcse(&e.E1);
|
||||||
|
|
||||||
// OPremquo is only worthwhile if its result is used more than once
|
// OPremquo is only worthwhile if its result is used more than once
|
||||||
else if (e.EV.E1.Eoper == OPremquo &&
|
else if (e.E1.Eoper == OPremquo &&
|
||||||
(op == OP64_32 || op == OP128_64 || op == OPmsw) &&
|
(op == OP64_32 || op == OP128_64 || op == OPmsw) &&
|
||||||
e.EV.E1.Ecount == 0)
|
e.E1.Ecount == 0)
|
||||||
{ // Convert back to OPdiv or OPmod
|
{ // Convert back to OPdiv or OPmod
|
||||||
elem *e1 = e.EV.E1;
|
elem *e1 = e.E1;
|
||||||
e.Eoper = (op == OPmsw) ? OPmod : OPdiv;
|
e.Eoper = (op == OPmsw) ? OPmod : OPdiv;
|
||||||
e.EV.E1 = e1.EV.E1;
|
e.E1 = e1.E1;
|
||||||
e.EV.E2 = e1.EV.E2;
|
e.E2 = e1.E2;
|
||||||
e1.EV.E1 = null;
|
e1.E1 = null;
|
||||||
e1.EV.E2 = null;
|
e1.E2 = null;
|
||||||
el_free(e1);
|
el_free(e1);
|
||||||
|
|
||||||
removecses(&(e.EV.E1));
|
removecses(&(e.E1));
|
||||||
pe = &(e.EV.E2);
|
pe = &(e.E2);
|
||||||
goto L1;
|
goto L1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,18 +563,18 @@ L1:
|
||||||
/* Don't CSE floating stuff if generating */
|
/* Don't CSE floating stuff if generating */
|
||||||
/* inline 8087 code, the code generator */
|
/* inline 8087 code, the code generator */
|
||||||
/* can't handle it yet */
|
/* can't handle it yet */
|
||||||
&& !(tyfloating(e.EV.E1.Ety) && config.inline8087)
|
&& !(tyfloating(e.E1.Ety) && config.inline8087)
|
||||||
)
|
)
|
||||||
e = delcse(pe);
|
e = delcse(pe);
|
||||||
if (ERTOL(e))
|
if (ERTOL(e))
|
||||||
{
|
{
|
||||||
removecses(&(e.EV.E2));
|
removecses(&(e.E2));
|
||||||
pe = &(e.EV.E1);
|
pe = &(e.E1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
removecses(&(e.EV.E1));
|
removecses(&(e.E1));
|
||||||
pe = &(e.EV.E2);
|
pe = &(e.E2);
|
||||||
}
|
}
|
||||||
goto L1;
|
goto L1;
|
||||||
}
|
}
|
||||||
|
@ -582,7 +582,7 @@ L1:
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pe = &(e.EV.E1);
|
pe = &(e.E1);
|
||||||
goto L1;
|
goto L1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,7 +625,7 @@ void boolopt()
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
elem_debug(e);
|
elem_debug(e);
|
||||||
if (e.Eoper == OPvar && e.EV.Vsym.Sflags & SFLtrue)
|
if (e.Eoper == OPvar && e.Vsym.Sflags & SFLtrue)
|
||||||
{
|
{
|
||||||
vec_setbit(i,aevec);
|
vec_setbit(i,aevec);
|
||||||
vec_setbit(i,aevecval);
|
vec_setbit(i,aevecval);
|
||||||
|
@ -678,34 +678,34 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
|
||||||
{
|
{
|
||||||
case OPcond:
|
case OPcond:
|
||||||
{
|
{
|
||||||
assert(n.EV.E2.Eoper == OPcolon || n.EV.E2.Eoper == OPcolon2);
|
assert(n.E2.Eoper == OPcolon || n.E2.Eoper == OPcolon2);
|
||||||
abewalk(n.EV.E1,ae,aeval);
|
abewalk(n.E1,ae,aeval);
|
||||||
abeboolres(n.EV.E1,ae,aeval);
|
abeboolres(n.E1,ae,aeval);
|
||||||
vec_t aer = vec_clone(ae);
|
vec_t aer = vec_clone(ae);
|
||||||
vec_t aerval = vec_clone(aeval);
|
vec_t aerval = vec_clone(aeval);
|
||||||
if (!el_returns(n.EV.E2.EV.E1))
|
if (!el_returns(n.E2.E1))
|
||||||
{
|
{
|
||||||
abeset(n.EV.E1,aer,aerval,true);
|
abeset(n.E1,aer,aerval,true);
|
||||||
abewalk(n.EV.E2.EV.E1,aer,aerval);
|
abewalk(n.E2.E1,aer,aerval);
|
||||||
abeset(n.EV.E1,ae,aeval,false);
|
abeset(n.E1,ae,aeval,false);
|
||||||
abewalk(n.EV.E2.EV.E2,ae,aeval);
|
abewalk(n.E2.E2,ae,aeval);
|
||||||
}
|
}
|
||||||
else if (!el_returns(n.EV.E2.EV.E2))
|
else if (!el_returns(n.E2.E2))
|
||||||
{
|
{
|
||||||
abeset(n.EV.E1,ae,aeval,true);
|
abeset(n.E1,ae,aeval,true);
|
||||||
abewalk(n.EV.E2.EV.E1,ae,aeval);
|
abewalk(n.E2.E1,ae,aeval);
|
||||||
abeset(n.EV.E1,aer,aerval,false);
|
abeset(n.E1,aer,aerval,false);
|
||||||
abewalk(n.EV.E2.EV.E2,aer,aerval);
|
abewalk(n.E2.E2,aer,aerval);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* ae = ae & ael & aer
|
/* ae = ae & ael & aer
|
||||||
* AEs gened by ael and aer are mutually exclusive
|
* AEs gened by ael and aer are mutually exclusive
|
||||||
*/
|
*/
|
||||||
abeset(n.EV.E1,aer,aerval,true);
|
abeset(n.E1,aer,aerval,true);
|
||||||
abewalk(n.EV.E2.EV.E1,aer,aerval);
|
abewalk(n.E2.E1,aer,aerval);
|
||||||
abeset(n.EV.E1,ae,aeval,false);
|
abeset(n.E1,ae,aeval,false);
|
||||||
abewalk(n.EV.E2.EV.E2,ae,aeval);
|
abewalk(n.E2.E2,ae,aeval);
|
||||||
|
|
||||||
vec_xorass(aerval,aeval);
|
vec_xorass(aerval,aeval);
|
||||||
vec_subass(aer,aerval);
|
vec_subass(aer,aerval);
|
||||||
|
@ -724,22 +724,22 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
|
||||||
case OPoror:
|
case OPoror:
|
||||||
{
|
{
|
||||||
//printf("test1 %p: ", n); WReqn(n); printf("\n");
|
//printf("test1 %p: ", n); WReqn(n); printf("\n");
|
||||||
abewalk(n.EV.E1,ae,aeval);
|
abewalk(n.E1,ae,aeval);
|
||||||
abeboolres(n.EV.E1,ae,aeval);
|
abeboolres(n.E1,ae,aeval);
|
||||||
vec_t aer = vec_clone(ae);
|
vec_t aer = vec_clone(ae);
|
||||||
vec_t aerval = vec_clone(aeval);
|
vec_t aerval = vec_clone(aeval);
|
||||||
if (!el_returns(n.EV.E2))
|
if (!el_returns(n.E2))
|
||||||
{
|
{
|
||||||
abeset(n.EV.E1,aer,aerval,(op == OPandand));
|
abeset(n.E1,aer,aerval,(op == OPandand));
|
||||||
abewalk(n.EV.E2,aer,aerval);
|
abewalk(n.E2,aer,aerval);
|
||||||
abeset(n.EV.E1,ae,aeval,(op != OPandand));
|
abeset(n.E1,ae,aeval,(op != OPandand));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* ae &= aer
|
/* ae &= aer
|
||||||
*/
|
*/
|
||||||
abeset(n.EV.E1,aer,aerval,(op == OPandand));
|
abeset(n.E1,aer,aerval,(op == OPandand));
|
||||||
abewalk(n.EV.E2,aer,aerval);
|
abewalk(n.E2,aer,aerval);
|
||||||
|
|
||||||
vec_xorass(aerval,aeval);
|
vec_xorass(aerval,aeval);
|
||||||
vec_subass(aer,aerval);
|
vec_subass(aer,aerval);
|
||||||
|
@ -753,8 +753,8 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
|
||||||
|
|
||||||
case OPbool:
|
case OPbool:
|
||||||
case OPnot:
|
case OPnot:
|
||||||
abewalk(n.EV.E1,ae,aeval);
|
abewalk(n.E1,ae,aeval);
|
||||||
abeboolres(n.EV.E1,ae,aeval);
|
abeboolres(n.E1,ae,aeval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPeqeq:
|
case OPeqeq:
|
||||||
|
@ -768,15 +768,15 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
|
||||||
case OPngt: case OPnge: case OPnlt: case OPnle:
|
case OPngt: case OPnge: case OPnlt: case OPnle:
|
||||||
case OPord: case OPnlg: case OPnleg: case OPnule:
|
case OPord: case OPnlg: case OPnleg: case OPnule:
|
||||||
case OPnul: case OPnuge: case OPnug: case OPnue:
|
case OPnul: case OPnuge: case OPnug: case OPnue:
|
||||||
abewalk(n.EV.E1,ae,aeval);
|
abewalk(n.E1,ae,aeval);
|
||||||
abewalk(n.EV.E2,ae,aeval);
|
abewalk(n.E2,ae,aeval);
|
||||||
abeboolres(n,ae,aeval);
|
abeboolres(n,ae,aeval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPnegass:
|
case OPnegass:
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (t.Eoper == OPind)
|
if (t.Eoper == OPind)
|
||||||
abewalk(t.EV.E1,ae,aeval);
|
abewalk(t.E1,ae,aeval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPasm:
|
case OPasm:
|
||||||
|
@ -786,19 +786,19 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
|
||||||
default:
|
default:
|
||||||
if (OTbinary(op))
|
if (OTbinary(op))
|
||||||
{ if (ERTOL(n))
|
{ if (ERTOL(n))
|
||||||
abewalk(n.EV.E2,ae,aeval);
|
abewalk(n.E2,ae,aeval);
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{ t = n.EV.E1;
|
{ t = n.E1;
|
||||||
if (t.Eoper == OPind)
|
if (t.Eoper == OPind)
|
||||||
abewalk(t.EV.E1,ae,aeval);
|
abewalk(t.E1,ae,aeval);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
abewalk(n.EV.E1,ae,aeval);
|
abewalk(n.E1,ae,aeval);
|
||||||
if (!ERTOL(n))
|
if (!ERTOL(n))
|
||||||
abewalk(n.EV.E2,ae,aeval);
|
abewalk(n.E2,ae,aeval);
|
||||||
}
|
}
|
||||||
else if (OTunary(op))
|
else if (OTunary(op))
|
||||||
abewalk(n.EV.E1,ae,aeval);
|
abewalk(n.E1,ae,aeval);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,7 +811,7 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
|
||||||
Symbol *s;
|
Symbol *s;
|
||||||
|
|
||||||
assert(t.Eoper == OPvar);
|
assert(t.Eoper == OPvar);
|
||||||
s = t.EV.Vsym;
|
s = t.Vsym;
|
||||||
if (Symbol_isAffected(*s))
|
if (Symbol_isAffected(*s))
|
||||||
vec_subass(ae,go.starkill);
|
vec_subass(ae,go.starkill);
|
||||||
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
|
for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem
|
||||||
|
@ -831,7 +831,7 @@ private void abewalk(elem *n,vec_t ae,vec_t aeval)
|
||||||
}
|
}
|
||||||
/* GEN the lvalue of an assignment operator */
|
/* GEN the lvalue of an assignment operator */
|
||||||
uint i1, i2;
|
uint i1, i2;
|
||||||
if (op == OPeq && (i1 = t.Eexp) != 0 && (i2 = n.EV.E2.Eexp) != 0)
|
if (op == OPeq && (i1 = t.Eexp) != 0 && (i2 = n.E2.Eexp) != 0)
|
||||||
{
|
{
|
||||||
if (vec_testbit(i2,ae))
|
if (vec_testbit(i2,ae))
|
||||||
{
|
{
|
||||||
|
@ -885,7 +885,7 @@ private void abeboolres(elem *n,vec_t ae,vec_t aeval)
|
||||||
}
|
}
|
||||||
|
|
||||||
abefree(n,ae);
|
abefree(n,ae);
|
||||||
n.EV.Vlong = vec_testbit(i,aeval) != 0;
|
n.Vlong = vec_testbit(i,aeval) != 0;
|
||||||
n.Eoper = OPconst;
|
n.Eoper = OPconst;
|
||||||
n.Ety = TYint;
|
n.Ety = TYint;
|
||||||
go.changes++;
|
go.changes++;
|
||||||
|
@ -910,13 +910,13 @@ private void abefree(elem *e,vec_t ae)
|
||||||
{
|
{
|
||||||
if (OTbinary(e.Eoper))
|
if (OTbinary(e.Eoper))
|
||||||
{
|
{
|
||||||
abefree(e.EV.E2,ae);
|
abefree(e.E2,ae);
|
||||||
el_free(e.EV.E2);
|
el_free(e.E2);
|
||||||
e.EV.E2 = null;
|
e.E2 = null;
|
||||||
}
|
}
|
||||||
abefree(e.EV.E1,ae);
|
abefree(e.E1,ae);
|
||||||
el_free(e.EV.E1);
|
el_free(e.E1);
|
||||||
e.EV.E1 = null;
|
e.E1 = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -943,12 +943,12 @@ private void abeset(elem *e,vec_t ae,vec_t aeval,int flag)
|
||||||
switch (e.Eoper)
|
switch (e.Eoper)
|
||||||
{ case OPnot:
|
{ case OPnot:
|
||||||
flag ^= 1;
|
flag ^= 1;
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case OPbool:
|
case OPbool:
|
||||||
case OPeq:
|
case OPeq:
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -36,7 +36,7 @@ nothrow:
|
||||||
void vec_setclear(size_t b, vec_t vs, vec_t vc) { vec_setbit(b, vs); vec_clearbit(b, vc); }
|
void vec_setclear(size_t b, vec_t vs, vec_t vc) { vec_setbit(b, vs); vec_clearbit(b, vc); }
|
||||||
|
|
||||||
@trusted
|
@trusted
|
||||||
bool Eunambig(elem* e) { return OTassign(e.Eoper) && e.EV.E1.Eoper == OPvar; }
|
bool Eunambig(elem* e) { return OTassign(e.Eoper) && e.E1.Eoper == OPvar; }
|
||||||
|
|
||||||
@trusted
|
@trusted
|
||||||
char symbol_isintab(const Symbol* s) { return sytab[s.Sclass] & SCSS; }
|
char symbol_isintab(const Symbol* s) { return sytab[s.Sclass] & SCSS; }
|
||||||
|
@ -230,17 +230,17 @@ private uint numdefelems(const(elem)* e, ref uint num_unambig_def)
|
||||||
if (OTdef(e.Eoper))
|
if (OTdef(e.Eoper))
|
||||||
{
|
{
|
||||||
++n;
|
++n;
|
||||||
if (OTassign(e.Eoper) && e.EV.E1.Eoper == OPvar)
|
if (OTassign(e.Eoper) && e.E1.Eoper == OPvar)
|
||||||
++num_unambig_def;
|
++num_unambig_def;
|
||||||
}
|
}
|
||||||
if (OTbinary(e.Eoper))
|
if (OTbinary(e.Eoper))
|
||||||
{
|
{
|
||||||
n += numdefelems(e.EV.E1, num_unambig_def);
|
n += numdefelems(e.E1, num_unambig_def);
|
||||||
e = e.EV.E2;
|
e = e.E2;
|
||||||
}
|
}
|
||||||
else if (OTunary(e.Eoper))
|
else if (OTunary(e.Eoper))
|
||||||
{
|
{
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -273,19 +273,19 @@ private void asgdefelems(block *b,elem *n, DefNode[] defnod, ref size_t i)
|
||||||
|
|
||||||
if (ERTOL(n))
|
if (ERTOL(n))
|
||||||
{
|
{
|
||||||
asgdefelems(b,n.EV.E1,defnod,i);
|
asgdefelems(b,n.E1,defnod,i);
|
||||||
n = n.EV.E2;
|
n = n.E2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
asgdefelems(b,n.EV.E2,defnod,i);
|
asgdefelems(b,n.E2,defnod,i);
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTunary(op))
|
else if (OTunary(op))
|
||||||
{
|
{
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -310,7 +310,7 @@ private void initDNunambigVectors(DefNode[] defnod)
|
||||||
foreach (const i; 0 .. defnod.length)
|
foreach (const i; 0 .. defnod.length)
|
||||||
{
|
{
|
||||||
elem *e = defnod[i].DNelem;
|
elem *e = defnod[i].DNelem;
|
||||||
if (OTassign(e.Eoper) && e.EV.E1.Eoper == OPvar)
|
if (OTassign(e.Eoper) && e.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
vec_t v = &go.dnunambig[j] + 2;
|
vec_t v = &go.dnunambig[j] + 2;
|
||||||
assert(vec_dim(v) == 0);
|
assert(vec_dim(v) == 0);
|
||||||
|
@ -351,11 +351,11 @@ private void initDNunambigVectors(DefNode[] defnod)
|
||||||
private void fillInDNunambig(vec_t v, elem *e, size_t start, DefNode[] defnod)
|
private void fillInDNunambig(vec_t v, elem *e, size_t start, DefNode[] defnod)
|
||||||
{
|
{
|
||||||
assert(OTassign(e.Eoper));
|
assert(OTassign(e.Eoper));
|
||||||
elem *t = e.EV.E1;
|
elem *t = e.E1;
|
||||||
assert(t.Eoper == OPvar);
|
assert(t.Eoper == OPvar);
|
||||||
Symbol *d = t.EV.Vsym;
|
Symbol *d = t.Vsym;
|
||||||
|
|
||||||
targ_size_t toff = t.EV.Voffset;
|
targ_size_t toff = t.Voffset;
|
||||||
targ_size_t tsize = (e.Eoper == OPstreq) ? type_size(e.ET) : tysize(t.Ety);
|
targ_size_t tsize = (e.Eoper == OPstreq) ? type_size(e.ET) : tysize(t.Ety);
|
||||||
targ_size_t ttop = toff + tsize;
|
targ_size_t ttop = toff + tsize;
|
||||||
|
|
||||||
|
@ -371,19 +371,19 @@ private void fillInDNunambig(vec_t v, elem *e, size_t start, DefNode[] defnod)
|
||||||
targ_size_t tn1size;
|
targ_size_t tn1size;
|
||||||
|
|
||||||
// If not same variable then no overlap
|
// If not same variable then no overlap
|
||||||
tn1 = tn.EV.E1;
|
tn1 = tn.E1;
|
||||||
if (d != tn1.EV.Vsym)
|
if (d != tn1.Vsym)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tn1size = (tn.Eoper == OPstreq)
|
tn1size = (tn.Eoper == OPstreq)
|
||||||
? type_size(tn.ET) : tysize(tn1.Ety);
|
? type_size(tn.ET) : tysize(tn1.Ety);
|
||||||
// If t completely overlaps tn1
|
// If t completely overlaps tn1
|
||||||
if (toff <= tn1.EV.Voffset && tn1.EV.Voffset + tn1size <= ttop)
|
if (toff <= tn1.Voffset && tn1.Voffset + tn1size <= ttop)
|
||||||
{
|
{
|
||||||
vec_setbit(i, v);
|
vec_setbit(i, v);
|
||||||
}
|
}
|
||||||
// if tn1 completely overlaps t
|
// if tn1 completely overlaps t
|
||||||
if (tn1.EV.Voffset <= toff && ttop <= tn1.EV.Voffset + tn1size)
|
if (tn1.Voffset <= toff && ttop <= tn1.Voffset + tn1size)
|
||||||
{
|
{
|
||||||
vec_setbit(start, v2);
|
vec_setbit(start, v2);
|
||||||
}
|
}
|
||||||
|
@ -416,16 +416,16 @@ private void accumrd(vec_t GEN,vec_t KILL,elem *n,uint deftop)
|
||||||
assert(GEN && KILL && n);
|
assert(GEN && KILL && n);
|
||||||
const op = n.Eoper;
|
const op = n.Eoper;
|
||||||
if (OTunary(op))
|
if (OTunary(op))
|
||||||
accumrd(GEN,KILL,n.EV.E1,deftop);
|
accumrd(GEN,KILL,n.E1,deftop);
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
if (op == OPcolon || op == OPcolon2)
|
if (op == OPcolon || op == OPcolon2)
|
||||||
{
|
{
|
||||||
vec_t Gl,Kl,Gr,Kr;
|
vec_t Gl,Kl,Gr,Kr;
|
||||||
rdelem(Gl, Kl, n.EV.E1, deftop);
|
rdelem(Gl, Kl, n.E1, deftop);
|
||||||
rdelem(Gr, Kr, n.EV.E2, deftop);
|
rdelem(Gr, Kr, n.E2, deftop);
|
||||||
|
|
||||||
switch (el_returns(n.EV.E1) * 2 | int(el_returns(n.EV.E2)))
|
switch (el_returns(n.E1) * 2 | int(el_returns(n.E2)))
|
||||||
{
|
{
|
||||||
case 3: // E1 and E2 return
|
case 3: // E1 and E2 return
|
||||||
/* GEN = (GEN - Kl) | Gl |
|
/* GEN = (GEN - Kl) | Gl |
|
||||||
|
@ -475,10 +475,10 @@ private void accumrd(vec_t GEN,vec_t KILL,elem *n,uint deftop)
|
||||||
}
|
}
|
||||||
else if (op == OPandand || op == OPoror)
|
else if (op == OPandand || op == OPoror)
|
||||||
{
|
{
|
||||||
accumrd(GEN,KILL,n.EV.E1,deftop);
|
accumrd(GEN,KILL,n.E1,deftop);
|
||||||
vec_t Gr,Kr;
|
vec_t Gr,Kr;
|
||||||
rdelem(Gr, Kr, n.EV.E2, deftop);
|
rdelem(Gr, Kr, n.E2, deftop);
|
||||||
if (el_returns(n.EV.E2))
|
if (el_returns(n.E2))
|
||||||
vec_orass(GEN,Gr); // GEN |= Gr
|
vec_orass(GEN,Gr); // GEN |= Gr
|
||||||
|
|
||||||
vec_free(Gr);
|
vec_free(Gr);
|
||||||
|
@ -486,13 +486,13 @@ private void accumrd(vec_t GEN,vec_t KILL,elem *n,uint deftop)
|
||||||
}
|
}
|
||||||
else if (OTrtol(op) && ERTOL(n))
|
else if (OTrtol(op) && ERTOL(n))
|
||||||
{
|
{
|
||||||
accumrd(GEN,KILL,n.EV.E2,deftop);
|
accumrd(GEN,KILL,n.E2,deftop);
|
||||||
accumrd(GEN,KILL,n.EV.E1,deftop);
|
accumrd(GEN,KILL,n.E1,deftop);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
accumrd(GEN,KILL,n.EV.E1,deftop);
|
accumrd(GEN,KILL,n.E1,deftop);
|
||||||
accumrd(GEN,KILL,n.EV.E2,deftop);
|
accumrd(GEN,KILL,n.E2,deftop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,20 +687,20 @@ private void aecpgenkill(ref GlobalOptimizer go, int flowxx)
|
||||||
if (OTunary(op))
|
if (OTunary(op))
|
||||||
{
|
{
|
||||||
n.Eexp = 0;
|
n.Eexp = 0;
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
if (ERTOL(n))
|
if (ERTOL(n))
|
||||||
{
|
{
|
||||||
asgcpelems(n.EV.E2);
|
asgcpelems(n.E2);
|
||||||
asgcpelems(n.EV.E1);
|
asgcpelems(n.E1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asgcpelems(n.EV.E1);
|
asgcpelems(n.E1);
|
||||||
asgcpelems(n.EV.E2);
|
asgcpelems(n.E2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* look for elem of the form OPvar=OPvar, where they aren't the
|
/* look for elem of the form OPvar=OPvar, where they aren't the
|
||||||
|
@ -710,12 +710,12 @@ private void aecpgenkill(ref GlobalOptimizer go, int flowxx)
|
||||||
elem* e1;
|
elem* e1;
|
||||||
elem* e2;
|
elem* e2;
|
||||||
if ((op == OPeq || op == OPstreq) &&
|
if ((op == OPeq || op == OPstreq) &&
|
||||||
(e1 = n.EV.E1).Eoper == OPvar &&
|
(e1 = n.E1).Eoper == OPvar &&
|
||||||
(e2 = n.EV.E2).Eoper == OPvar &&
|
(e2 = n.E2).Eoper == OPvar &&
|
||||||
!((e1.Ety | e2.Ety) & (mTYvolatile | mTYshared)) &&
|
!((e1.Ety | e2.Ety) & (mTYvolatile | mTYshared)) &&
|
||||||
(!config.fpxmmregs ||
|
(!config.fpxmmregs ||
|
||||||
(!tyfloating(e1.EV.Vsym.Stype.Tty) == !tyfloating(e2.EV.Vsym.Stype.Tty))) &&
|
(!tyfloating(e1.Vsym.Stype.Tty) == !tyfloating(e2.Vsym.Stype.Tty))) &&
|
||||||
e1.EV.Vsym != e2.EV.Vsym)
|
e1.Vsym != e2.Vsym)
|
||||||
{
|
{
|
||||||
n.Eexp = cast(uint)go.expnod.length;
|
n.Eexp = cast(uint)go.expnod.length;
|
||||||
go.expnod.push(n);
|
go.expnod.push(n);
|
||||||
|
@ -740,7 +740,7 @@ private void aecpgenkill(ref GlobalOptimizer go, int flowxx)
|
||||||
const op = n.Eoper;
|
const op = n.Eoper;
|
||||||
if (OTunary(op))
|
if (OTunary(op))
|
||||||
{
|
{
|
||||||
ae = asgaeelems(n.EV.E1);
|
ae = asgaeelems(n.E1);
|
||||||
// Disallow starred references to avoid problems with VBE's
|
// Disallow starred references to avoid problems with VBE's
|
||||||
// being hoisted before tests of an invalid pointer.
|
// being hoisted before tests of an invalid pointer.
|
||||||
if (flowxx == VBE && op == OPind)
|
if (flowxx == VBE && op == OPind)
|
||||||
|
@ -752,9 +752,9 @@ private void aecpgenkill(ref GlobalOptimizer go, int flowxx)
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
if (ERTOL(n))
|
if (ERTOL(n))
|
||||||
ae = asgaeelems(n.EV.E2) & asgaeelems(n.EV.E1);
|
ae = asgaeelems(n.E2) & asgaeelems(n.E1);
|
||||||
else
|
else
|
||||||
ae = asgaeelems(n.EV.E1) & asgaeelems(n.EV.E2);
|
ae = asgaeelems(n.E1) & asgaeelems(n.E2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ae = true;
|
ae = true;
|
||||||
|
@ -830,14 +830,14 @@ private void aecpgenkill(ref GlobalOptimizer go, int flowxx)
|
||||||
vec_free(b.Bgen2);
|
vec_free(b.Bgen2);
|
||||||
vec_free(b.Bkill2);
|
vec_free(b.Bkill2);
|
||||||
elem* e;
|
elem* e;
|
||||||
for (e = b.Belem; e.Eoper == OPcomma; e = e.EV.E2)
|
for (e = b.Belem; e.Eoper == OPcomma; e = e.E2)
|
||||||
accumaecp(b.Bgen,b.Bkill,e.EV.E1);
|
accumaecp(b.Bgen,b.Bkill,e.E1);
|
||||||
if (e.Eoper == OPandand || e.Eoper == OPoror)
|
if (e.Eoper == OPandand || e.Eoper == OPoror)
|
||||||
{
|
{
|
||||||
accumaecp(b.Bgen,b.Bkill,e.EV.E1);
|
accumaecp(b.Bgen,b.Bkill,e.E1);
|
||||||
vec_t Kr = vec_calloc(go.expnod.length);
|
vec_t Kr = vec_calloc(go.expnod.length);
|
||||||
vec_t Gr = vec_calloc(go.expnod.length);
|
vec_t Gr = vec_calloc(go.expnod.length);
|
||||||
accumaecp(Gr,Kr,e.EV.E2);
|
accumaecp(Gr,Kr,e.E2);
|
||||||
|
|
||||||
// We might or might not have executed E2
|
// We might or might not have executed E2
|
||||||
// KILL1 = KILL | Kr
|
// KILL1 = KILL | Kr
|
||||||
|
@ -946,13 +946,13 @@ private void defstarkill()
|
||||||
{
|
{
|
||||||
const op = n.Eoper;
|
const op = n.Eoper;
|
||||||
assert(op == OPeq || op == OPstreq);
|
assert(op == OPeq || op == OPstreq);
|
||||||
assert(n.EV.E1.Eoper==OPvar && n.EV.E2.Eoper==OPvar);
|
assert(n.E1.Eoper==OPvar && n.E2.Eoper==OPvar);
|
||||||
|
|
||||||
// Set bit in defkill if either the left or the
|
// Set bit in defkill if either the left or the
|
||||||
// right variable is killed by an ambiguous def.
|
// right variable is killed by an ambiguous def.
|
||||||
|
|
||||||
if (Symbol_isAffected(*n.EV.E1.EV.Vsym) ||
|
if (Symbol_isAffected(*n.E1.Vsym) ||
|
||||||
Symbol_isAffected(*n.EV.E2.EV.Vsym))
|
Symbol_isAffected(*n.E2.Vsym))
|
||||||
{
|
{
|
||||||
vec_setbit(i + 1,defkill);
|
vec_setbit(i + 1,defkill);
|
||||||
}
|
}
|
||||||
|
@ -970,12 +970,12 @@ private void defstarkill()
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OPvar:
|
case OPvar:
|
||||||
if (Symbol_isAffected(*n.EV.Vsym))
|
if (Symbol_isAffected(*n.Vsym))
|
||||||
vec_setbit(i,defkill);
|
vec_setbit(i,defkill);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPind: // if a 'starred' ref
|
case OPind: // if a 'starred' ref
|
||||||
if (tybasic(n.EV.E1.Ety) == TYimmutPtr)
|
if (tybasic(n.E1.Ety) == TYimmutPtr)
|
||||||
break;
|
break;
|
||||||
goto case OPstrlen;
|
goto case OPstrlen;
|
||||||
|
|
||||||
|
@ -996,18 +996,18 @@ private void defstarkill()
|
||||||
if (OTunary(op))
|
if (OTunary(op))
|
||||||
{
|
{
|
||||||
Lunary:
|
Lunary:
|
||||||
if (vec_testbit(n.EV.E1.Eexp,defkill))
|
if (vec_testbit(n.E1.Eexp,defkill))
|
||||||
vec_setbit(i,defkill);
|
vec_setbit(i,defkill);
|
||||||
if (vec_testbit(n.EV.E1.Eexp,starkill))
|
if (vec_testbit(n.E1.Eexp,starkill))
|
||||||
vec_setbit(i,starkill);
|
vec_setbit(i,starkill);
|
||||||
}
|
}
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
if (vec_testbit(n.EV.E1.Eexp,defkill) ||
|
if (vec_testbit(n.E1.Eexp,defkill) ||
|
||||||
vec_testbit(n.EV.E2.Eexp,defkill))
|
vec_testbit(n.E2.Eexp,defkill))
|
||||||
vec_setbit(i,defkill);
|
vec_setbit(i,defkill);
|
||||||
if (vec_testbit(n.EV.E1.Eexp,starkill) ||
|
if (vec_testbit(n.E1.Eexp,starkill) ||
|
||||||
vec_testbit(n.EV.E2.Eexp,starkill))
|
vec_testbit(n.E2.Eexp,starkill))
|
||||||
vec_setbit(i,starkill);
|
vec_setbit(i,starkill);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1115,8 +1115,8 @@ private void accumaecpx(elem *n)
|
||||||
case OPcolon2:
|
case OPcolon2:
|
||||||
{ vec_t Gl,Kl,Gr,Kr;
|
{ vec_t Gl,Kl,Gr,Kr;
|
||||||
|
|
||||||
aecpelem(Gl,Kl, n.EV.E1, go.exptop);
|
aecpelem(Gl,Kl, n.E1, go.exptop);
|
||||||
aecpelem(Gr,Kr, n.EV.E2, go.exptop);
|
aecpelem(Gr,Kr, n.E2, go.exptop);
|
||||||
|
|
||||||
/* KILL |= Kl | Kr */
|
/* KILL |= Kl | Kr */
|
||||||
/* GEN =((GEN - Kl) | Gl) & */
|
/* GEN =((GEN - Kl) | Gl) & */
|
||||||
|
@ -1142,10 +1142,10 @@ private void accumaecpx(elem *n)
|
||||||
case OPoror:
|
case OPoror:
|
||||||
{ vec_t Gr,Kr;
|
{ vec_t Gr,Kr;
|
||||||
|
|
||||||
accumaecpx(n.EV.E1);
|
accumaecpx(n.E1);
|
||||||
aecpelem(Gr,Kr, n.EV.E2, go.exptop);
|
aecpelem(Gr,Kr, n.E2, go.exptop);
|
||||||
|
|
||||||
if (el_returns(n.EV.E2))
|
if (el_returns(n.E2))
|
||||||
{
|
{
|
||||||
// KILL |= Kr
|
// KILL |= Kr
|
||||||
// GEN &= (GEN - Kr) | Gr
|
// GEN &= (GEN - Kr) | Gr
|
||||||
|
@ -1170,12 +1170,12 @@ private void accumaecpx(elem *n)
|
||||||
|
|
||||||
case OPeq:
|
case OPeq:
|
||||||
case OPstreq:
|
case OPstreq:
|
||||||
accumaecpx(n.EV.E2);
|
accumaecpx(n.E2);
|
||||||
goto case OPnegass;
|
goto case OPnegass;
|
||||||
|
|
||||||
case OPnegass:
|
case OPnegass:
|
||||||
accumaecpx(n.EV.E1);
|
accumaecpx(n.E1);
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPvp_fp:
|
case OPvp_fp:
|
||||||
|
@ -1185,30 +1185,30 @@ private void accumaecpx(elem *n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPprefetch:
|
case OPprefetch:
|
||||||
accumaecpx(n.EV.E1); // don't check E2
|
accumaecpx(n.E1); // don't check E2
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (OTunary(op))
|
if (OTunary(op))
|
||||||
{
|
{
|
||||||
case OPind: // most common unary operator
|
case OPind: // most common unary operator
|
||||||
accumaecpx(n.EV.E1);
|
accumaecpx(n.E1);
|
||||||
debug assert(!OTassign(op));
|
debug assert(!OTassign(op));
|
||||||
}
|
}
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
if (OTrtol(op) && ERTOL(n))
|
if (OTrtol(op) && ERTOL(n))
|
||||||
{
|
{
|
||||||
accumaecpx(n.EV.E2);
|
accumaecpx(n.E2);
|
||||||
accumaecpx(n.EV.E1);
|
accumaecpx(n.E1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
accumaecpx(n.EV.E1);
|
accumaecpx(n.E1);
|
||||||
accumaecpx(n.EV.E2);
|
accumaecpx(n.E2);
|
||||||
}
|
}
|
||||||
if (OTassign(op)) // if assignment operator
|
if (OTassign(op)) // if assignment operator
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1228,7 +1228,7 @@ private void accumaecpx(elem *n)
|
||||||
else /* unambiguous def elem */
|
else /* unambiguous def elem */
|
||||||
{
|
{
|
||||||
assert(t.Eoper == OPvar);
|
assert(t.Eoper == OPvar);
|
||||||
Symbol* s = t.EV.Vsym; // ptr to var being def'd
|
Symbol* s = t.Vsym; // ptr to var being def'd
|
||||||
foreach (uint i; 1 .. go.exptop) // for each ae elem
|
foreach (uint i; 1 .. go.exptop) // for each ae elem
|
||||||
{
|
{
|
||||||
elem *e = go.expnod[i];
|
elem *e = go.expnod[i];
|
||||||
|
@ -1236,7 +1236,7 @@ private void accumaecpx(elem *n)
|
||||||
/* If it could be changed by the definition, */
|
/* If it could be changed by the definition, */
|
||||||
/* set bit in KILL. */
|
/* set bit in KILL. */
|
||||||
|
|
||||||
if (e.EV.E1.EV.Vsym == s || e.EV.E2.EV.Vsym == s)
|
if (e.E1.Vsym == s || e.E2.Vsym == s)
|
||||||
vec_setclear(i,KILL,GEN);
|
vec_setclear(i,KILL,GEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1274,7 +1274,7 @@ private void accumaecpx(elem *n)
|
||||||
else /* unambiguous def elem */
|
else /* unambiguous def elem */
|
||||||
{
|
{
|
||||||
assert(t.Eoper == OPvar);
|
assert(t.Eoper == OPvar);
|
||||||
Symbol* s = t.EV.Vsym; // idx of var being def'd
|
Symbol* s = t.Vsym; // idx of var being def'd
|
||||||
if (!(s.Sflags & SFLunambig))
|
if (!(s.Sflags & SFLunambig))
|
||||||
{
|
{
|
||||||
vec_orass(KILL,go.starkill); /* kill all 'starred' refs */
|
vec_orass(KILL,go.starkill); /* kill all 'starred' refs */
|
||||||
|
@ -1289,18 +1289,18 @@ private void accumaecpx(elem *n)
|
||||||
/* set bit in KILL. */
|
/* set bit in KILL. */
|
||||||
if (eop == OPvar)
|
if (eop == OPvar)
|
||||||
{
|
{
|
||||||
if (e.EV.Vsym != s)
|
if (e.Vsym != s)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTunary(eop))
|
else if (OTunary(eop))
|
||||||
{
|
{
|
||||||
if (!vec_testbit(e.EV.E1.Eexp,KILL))
|
if (!vec_testbit(e.E1.Eexp,KILL))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTbinary(eop))
|
else if (OTbinary(eop))
|
||||||
{
|
{
|
||||||
if (!vec_testbit(e.EV.E1.Eexp,KILL) &&
|
if (!vec_testbit(e.E1.Eexp,KILL) &&
|
||||||
!vec_testbit(e.EV.E2.Eexp,KILL))
|
!vec_testbit(e.E2.Eexp,KILL))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1499,9 +1499,9 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OPvar:
|
case OPvar:
|
||||||
if (symbol_isintab(n.EV.Vsym))
|
if (symbol_isintab(n.Vsym))
|
||||||
{
|
{
|
||||||
const si = n.EV.Vsym.Ssymnum;
|
const si = n.Vsym.Ssymnum;
|
||||||
|
|
||||||
assert(cast(uint)si < globsym.length);
|
assert(cast(uint)si < globsym.length);
|
||||||
if (!vec_testbit(si,KILL)) // if not in KILL
|
if (!vec_testbit(si,KILL)) // if not in KILL
|
||||||
|
@ -1513,8 +1513,8 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
case OPcolon2:
|
case OPcolon2:
|
||||||
{
|
{
|
||||||
vec_t Gl,Kl,Gr,Kr;
|
vec_t Gl,Kl,Gr,Kr;
|
||||||
lvelem(Gl,Kl, n.EV.E1,ambigsym, globsym.length);
|
lvelem(Gl,Kl, n.E1,ambigsym, globsym.length);
|
||||||
lvelem(Gr,Kr, n.EV.E2,ambigsym, globsym.length);
|
lvelem(Gr,Kr, n.E2,ambigsym, globsym.length);
|
||||||
|
|
||||||
/* GEN |= (Gl | Gr) - KILL */
|
/* GEN |= (Gl | Gr) - KILL */
|
||||||
/* KILL |= (Kl & Kr) - GEN */
|
/* KILL |= (Kl & Kr) - GEN */
|
||||||
|
@ -1537,8 +1537,8 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
case OPoror:
|
case OPoror:
|
||||||
{
|
{
|
||||||
vec_t Gr,Kr;
|
vec_t Gr,Kr;
|
||||||
accumlv(GEN,KILL,n.EV.E1,ambigsym);
|
accumlv(GEN,KILL,n.E1,ambigsym);
|
||||||
lvelem(Gr,Kr, n.EV.E2,ambigsym, globsym.length);
|
lvelem(Gr,Kr, n.E2,ambigsym, globsym.length);
|
||||||
|
|
||||||
/* GEN |= Gr - KILL */
|
/* GEN |= Gr - KILL */
|
||||||
/* KILL |= 0 */
|
/* KILL |= 0 */
|
||||||
|
@ -1562,14 +1562,14 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
case OPmemcpy:
|
case OPmemcpy:
|
||||||
case OPmemset:
|
case OPmemset:
|
||||||
debug assert(OTrtol(op));
|
debug assert(OTrtol(op));
|
||||||
accumlv(GEN,KILL,n.EV.E2,ambigsym);
|
accumlv(GEN,KILL,n.E2,ambigsym);
|
||||||
accumlv(GEN,KILL,n.EV.E1,ambigsym);
|
accumlv(GEN,KILL,n.E1,ambigsym);
|
||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
case OPstrcat:
|
case OPstrcat:
|
||||||
debug assert(!OTrtol(op));
|
debug assert(!OTrtol(op));
|
||||||
accumlv(GEN,KILL,n.EV.E1,ambigsym);
|
accumlv(GEN,KILL,n.E1,ambigsym);
|
||||||
accumlv(GEN,KILL,n.EV.E2,ambigsym);
|
accumlv(GEN,KILL,n.E2,ambigsym);
|
||||||
L1:
|
L1:
|
||||||
vec_orass(GEN,ambigsym);
|
vec_orass(GEN,ambigsym);
|
||||||
vec_subass(GEN,KILL);
|
vec_subass(GEN,KILL);
|
||||||
|
@ -1579,13 +1579,13 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
case OPstreq:
|
case OPstreq:
|
||||||
{
|
{
|
||||||
/* Avoid GENing the lvalue of an = */
|
/* Avoid GENing the lvalue of an = */
|
||||||
accumlv(GEN,KILL,n.EV.E2,ambigsym);
|
accumlv(GEN,KILL,n.E2,ambigsym);
|
||||||
const t = n.EV.E1;
|
const t = n.E1;
|
||||||
if (t.Eoper != OPvar)
|
if (t.Eoper != OPvar)
|
||||||
accumlv(GEN,KILL,t.EV.E1,ambigsym);
|
accumlv(GEN,KILL,t.E1,ambigsym);
|
||||||
else /* unambiguous assignment */
|
else /* unambiguous assignment */
|
||||||
{
|
{
|
||||||
const s = t.EV.Vsym;
|
const s = t.Vsym;
|
||||||
symbol_debug(s);
|
symbol_debug(s);
|
||||||
|
|
||||||
uint tsz = tysize(t.Ety);
|
uint tsz = tysize(t.Ety);
|
||||||
|
@ -1595,7 +1595,7 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
/* if not GENed already, KILL it */
|
/* if not GENed already, KILL it */
|
||||||
if (symbol_isintab(s) &&
|
if (symbol_isintab(s) &&
|
||||||
!vec_testbit(s.Ssymnum,GEN) &&
|
!vec_testbit(s.Ssymnum,GEN) &&
|
||||||
t.EV.Voffset == 0 &&
|
t.Voffset == 0 &&
|
||||||
tsz == type_size(s.Stype)
|
tsz == type_size(s.Stype)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -1610,8 +1610,8 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
case OPmemcmp:
|
case OPmemcmp:
|
||||||
case OPstrcmp:
|
case OPstrcmp:
|
||||||
case OPbt: // much like OPind
|
case OPbt: // much like OPind
|
||||||
accumlv(GEN,KILL,n.EV.E1,ambigsym);
|
accumlv(GEN,KILL,n.E1,ambigsym);
|
||||||
accumlv(GEN,KILL,n.EV.E2,ambigsym);
|
accumlv(GEN,KILL,n.E2,ambigsym);
|
||||||
vec_orass(GEN,ambigsym);
|
vec_orass(GEN,ambigsym);
|
||||||
vec_subass(GEN,KILL);
|
vec_subass(GEN,KILL);
|
||||||
break;
|
break;
|
||||||
|
@ -1620,7 +1620,7 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
case OPucall:
|
case OPucall:
|
||||||
case OPucallns:
|
case OPucallns:
|
||||||
case OPstrlen:
|
case OPstrlen:
|
||||||
accumlv(GEN,KILL,n.EV.E1,ambigsym);
|
accumlv(GEN,KILL,n.E1,ambigsym);
|
||||||
|
|
||||||
/* If it was a *p elem, set bits in GEN for all symbols */
|
/* If it was a *p elem, set bits in GEN for all symbols */
|
||||||
/* it could have referenced, but only if bits in KILL */
|
/* it could have referenced, but only if bits in KILL */
|
||||||
|
@ -1633,22 +1633,22 @@ private void accumlv(vec_t GEN, vec_t KILL, const(elem)* n, const vec_t ambigsym
|
||||||
default:
|
default:
|
||||||
if (OTunary(op))
|
if (OTunary(op))
|
||||||
{
|
{
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTrtol(op) && ERTOL(n))
|
else if (OTrtol(op) && ERTOL(n))
|
||||||
{
|
{
|
||||||
accumlv(GEN,KILL,n.EV.E2,ambigsym);
|
accumlv(GEN,KILL,n.E2,ambigsym);
|
||||||
|
|
||||||
/* Note that lvalues of op=,i++,i-- elems */
|
/* Note that lvalues of op=,i++,i-- elems */
|
||||||
/* are GENed. */
|
/* are GENed. */
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
accumlv(GEN,KILL,n.EV.E1,ambigsym);
|
accumlv(GEN,KILL,n.E1,ambigsym);
|
||||||
n = n.EV.E2;
|
n = n.E2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1764,8 +1764,8 @@ private void accumvbe(vec_t GEN,vec_t KILL,elem *n)
|
||||||
{
|
{
|
||||||
vec_t Gl,Gr,Kl,Kr;
|
vec_t Gl,Gr,Kl,Kr;
|
||||||
|
|
||||||
aecpelem(Gl,Kl, n.EV.E1, go.exptop);
|
aecpelem(Gl,Kl, n.E1, go.exptop);
|
||||||
aecpelem(Gr,Kr, n.EV.E2, go.exptop);
|
aecpelem(Gr,Kr, n.E2, go.exptop);
|
||||||
|
|
||||||
/* GEN |=((Gr - Kl) | (Gl - Kr)) - KILL */
|
/* GEN |=((Gr - Kl) | (Gl - Kr)) - KILL */
|
||||||
vec_subass(Gr,Kl);
|
vec_subass(Gr,Kl);
|
||||||
|
@ -1788,36 +1788,36 @@ private void accumvbe(vec_t GEN,vec_t KILL,elem *n)
|
||||||
|
|
||||||
case OPandand:
|
case OPandand:
|
||||||
case OPoror:
|
case OPoror:
|
||||||
accumvbe(GEN,KILL,n.EV.E1);
|
accumvbe(GEN,KILL,n.E1);
|
||||||
/* WARNING: just so happens that it works this way. */
|
/* WARNING: just so happens that it works this way. */
|
||||||
/* Be careful about (b+c)||(b+c) being VBEs, only the */
|
/* Be careful about (b+c)||(b+c) being VBEs, only the */
|
||||||
/* first should be GENed. Doing things this way instead */
|
/* first should be GENed. Doing things this way instead */
|
||||||
/* of (GEN |= Gr - KILL) and (KILL |= Kr - GEN) will */
|
/* of (GEN |= Gr - KILL) and (KILL |= Kr - GEN) will */
|
||||||
/* ensure this. */
|
/* ensure this. */
|
||||||
accumvbe(GEN,KILL,n.EV.E2);
|
accumvbe(GEN,KILL,n.E2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPnegass:
|
case OPnegass:
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (t.Eoper != OPvar)
|
if (t.Eoper != OPvar)
|
||||||
{
|
{
|
||||||
accumvbe(GEN,KILL,t.EV.E1);
|
accumvbe(GEN,KILL,t.E1);
|
||||||
if (OTbinary(t.Eoper))
|
if (OTbinary(t.Eoper))
|
||||||
accumvbe(GEN,KILL,t.EV.E2);
|
accumvbe(GEN,KILL,t.E2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPcall:
|
case OPcall:
|
||||||
case OPcallns:
|
case OPcallns:
|
||||||
accumvbe(GEN,KILL,n.EV.E2);
|
accumvbe(GEN,KILL,n.E2);
|
||||||
goto case OPucall;
|
goto case OPucall;
|
||||||
|
|
||||||
case OPucall:
|
case OPucall:
|
||||||
case OPucallns:
|
case OPucallns:
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
// Do not VBE indirect function calls
|
// Do not VBE indirect function calls
|
||||||
if (t.Eoper == OPind)
|
if (t.Eoper == OPind)
|
||||||
t = t.EV.E1;
|
t = t.E1;
|
||||||
accumvbe(GEN,KILL,t);
|
accumvbe(GEN,KILL,t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1829,22 +1829,22 @@ private void accumvbe(vec_t GEN,vec_t KILL,elem *n)
|
||||||
default:
|
default:
|
||||||
if (OTunary(op))
|
if (OTunary(op))
|
||||||
{
|
{
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
accumvbe(GEN,KILL,t);
|
accumvbe(GEN,KILL,t);
|
||||||
}
|
}
|
||||||
else if (ERTOL(n))
|
else if (ERTOL(n))
|
||||||
{
|
{
|
||||||
accumvbe(GEN,KILL,n.EV.E2);
|
accumvbe(GEN,KILL,n.E2);
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
// do not GEN the lvalue of an assignment op
|
// do not GEN the lvalue of an assignment op
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{
|
{
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (t.Eoper != OPvar)
|
if (t.Eoper != OPvar)
|
||||||
{
|
{
|
||||||
accumvbe(GEN,KILL,t.EV.E1);
|
accumvbe(GEN,KILL,t.E1);
|
||||||
if (OTbinary(t.Eoper))
|
if (OTbinary(t.Eoper))
|
||||||
accumvbe(GEN,KILL,t.EV.E2);
|
accumvbe(GEN,KILL,t.E2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1855,17 +1855,17 @@ private void accumvbe(vec_t GEN,vec_t KILL,elem *n)
|
||||||
/* do not GEN the lvalue of an assignment op */
|
/* do not GEN the lvalue of an assignment op */
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{
|
{
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (t.Eoper != OPvar)
|
if (t.Eoper != OPvar)
|
||||||
{
|
{
|
||||||
accumvbe(GEN,KILL,t.EV.E1);
|
accumvbe(GEN,KILL,t.E1);
|
||||||
if (OTbinary(t.Eoper))
|
if (OTbinary(t.Eoper))
|
||||||
accumvbe(GEN,KILL,t.EV.E2);
|
accumvbe(GEN,KILL,t.E2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
accumvbe(GEN,KILL,n.EV.E1);
|
accumvbe(GEN,KILL,n.E1);
|
||||||
accumvbe(GEN,KILL,n.EV.E2);
|
accumvbe(GEN,KILL,n.E2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1920,7 +1920,7 @@ private void accumvbe(vec_t GEN,vec_t KILL,elem *n)
|
||||||
else /* unambiguous definition */
|
else /* unambiguous definition */
|
||||||
{
|
{
|
||||||
assert(t.Eoper == OPvar);
|
assert(t.Eoper == OPvar);
|
||||||
Symbol* s = t.EV.Vsym; // ptr to var being def'd
|
Symbol* s = t.Vsym; // ptr to var being def'd
|
||||||
if (!(s.Sflags & SFLunambig))
|
if (!(s.Sflags & SFLunambig))
|
||||||
vec_orass(KILL,go.starkill);/* kill all 'starred' refs */
|
vec_orass(KILL,go.starkill);/* kill all 'starred' refs */
|
||||||
foreach (uint i; 1 .. go.exptop) // for each vbe elem
|
foreach (uint i; 1 .. go.exptop) // for each vbe elem
|
||||||
|
@ -1932,18 +1932,18 @@ private void accumvbe(vec_t GEN,vec_t KILL,elem *n)
|
||||||
/* set bit in KILL. */
|
/* set bit in KILL. */
|
||||||
if (eop == OPvar)
|
if (eop == OPvar)
|
||||||
{
|
{
|
||||||
if (e.EV.Vsym != s)
|
if (e.Vsym != s)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTbinary(eop))
|
else if (OTbinary(eop))
|
||||||
{
|
{
|
||||||
if (!vec_testbit(e.EV.E1.Eexp,KILL) &&
|
if (!vec_testbit(e.E1.Eexp,KILL) &&
|
||||||
!vec_testbit(e.EV.E2.Eexp,KILL))
|
!vec_testbit(e.E2.Eexp,KILL))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (OTunary(eop))
|
else if (OTunary(eop))
|
||||||
{
|
{
|
||||||
if (!vec_testbit(e.EV.E1.Eexp,KILL))
|
if (!vec_testbit(e.E1.Eexp,KILL))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else /* OPconst or OPrelconst or OPstring */
|
else /* OPconst or OPrelconst or OPstring */
|
||||||
|
|
|
@ -118,13 +118,13 @@ Loop:
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OPcomma:
|
case OPcomma:
|
||||||
local_exp(lt,e.EV.E1,0);
|
local_exp(lt,e.E1,0);
|
||||||
e = e.EV.E2;
|
e = e.E2;
|
||||||
goto Loop;
|
goto Loop;
|
||||||
|
|
||||||
case OPandand:
|
case OPandand:
|
||||||
case OPoror:
|
case OPoror:
|
||||||
local_exp(lt,e.EV.E1,1);
|
local_exp(lt,e.E1,1);
|
||||||
lt.setLength(0); // we can do better than this, fix later
|
lt.setLength(0); // we can do better than this, fix later
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -134,9 +134,9 @@ Loop:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPinfo:
|
case OPinfo:
|
||||||
if (e.EV.E1.Eoper == OPmark)
|
if (e.E1.Eoper == OPmark)
|
||||||
{ lt.setLength(0);
|
{ lt.setLength(0);
|
||||||
e = e.EV.E2;
|
e = e.E2;
|
||||||
goto Loop;
|
goto Loop;
|
||||||
}
|
}
|
||||||
goto case_bin;
|
goto case_bin;
|
||||||
|
@ -150,18 +150,18 @@ Loop:
|
||||||
case OPddtor:
|
case OPddtor:
|
||||||
lt.setLength(0); // don't move expressions across ctor/dtor
|
lt.setLength(0); // don't move expressions across ctor/dtor
|
||||||
// boundaries, it would goof up EH cleanup
|
// boundaries, it would goof up EH cleanup
|
||||||
local_exp(lt,e.EV.E1,0);
|
local_exp(lt,e.E1,0);
|
||||||
lt.setLength(0);
|
lt.setLength(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPeq:
|
case OPeq:
|
||||||
case OPstreq:
|
case OPstreq:
|
||||||
case OPvecsto:
|
case OPvecsto:
|
||||||
e1 = e.EV.E1;
|
e1 = e.E1;
|
||||||
local_exp(lt,e.EV.E2,1);
|
local_exp(lt,e.E2,1);
|
||||||
if (e1.Eoper == OPvar)
|
if (e1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
const s = e1.EV.Vsym;
|
const s = e1.Vsym;
|
||||||
if (s.Sflags & SFLunambig)
|
if (s.Sflags & SFLunambig)
|
||||||
{ local_symdef(lt, s);
|
{ local_symdef(lt, s);
|
||||||
if (!goal)
|
if (!goal)
|
||||||
|
@ -173,9 +173,9 @@ Loop:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(!OTleaf(e1.Eoper));
|
assert(!OTleaf(e1.Eoper));
|
||||||
local_exp(lt,e1.EV.E1,1);
|
local_exp(lt,e1.E1,1);
|
||||||
if (OTbinary(e1.Eoper))
|
if (OTbinary(e1.Eoper))
|
||||||
local_exp(lt,e1.EV.E2,1);
|
local_exp(lt,e1.E2,1);
|
||||||
local_ambigdef(lt);
|
local_ambigdef(lt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -195,35 +195,35 @@ Loop:
|
||||||
case OPorass:
|
case OPorass:
|
||||||
case OPcmpxchg:
|
case OPcmpxchg:
|
||||||
if (ERTOL(e))
|
if (ERTOL(e))
|
||||||
{ local_exp(lt,e.EV.E2,1);
|
{ local_exp(lt,e.E2,1);
|
||||||
case OPnegass:
|
case OPnegass:
|
||||||
e1 = e.EV.E1;
|
e1 = e.E1;
|
||||||
op1 = e1.Eoper;
|
op1 = e1.Eoper;
|
||||||
if (op1 != OPvar)
|
if (op1 != OPvar)
|
||||||
{
|
{
|
||||||
local_exp(lt,e1.EV.E1,1);
|
local_exp(lt,e1.E1,1);
|
||||||
if (OTbinary(op1))
|
if (OTbinary(op1))
|
||||||
local_exp(lt,e1.EV.E2,1);
|
local_exp(lt,e1.E2,1);
|
||||||
}
|
}
|
||||||
else if (lt.length && (op == OPaddass || op == OPxorass))
|
else if (lt.length && (op == OPaddass || op == OPxorass))
|
||||||
{
|
{
|
||||||
const s = e1.EV.Vsym;
|
const s = e1.Vsym;
|
||||||
foreach (u; 0 .. lt.length)
|
foreach (u; 0 .. lt.length)
|
||||||
{
|
{
|
||||||
auto em = lt[u].e;
|
auto em = lt[u].e;
|
||||||
if (em.Eoper == op &&
|
if (em.Eoper == op &&
|
||||||
em.EV.E1.EV.Vsym == s &&
|
em.E1.Vsym == s &&
|
||||||
tysize(em.Ety) == tysize(e1.Ety) &&
|
tysize(em.Ety) == tysize(e1.Ety) &&
|
||||||
!tyfloating(em.Ety) &&
|
!tyfloating(em.Ety) &&
|
||||||
em.EV.E1.EV.Voffset == e1.EV.Voffset &&
|
em.E1.Voffset == e1.Voffset &&
|
||||||
!el_sideeffect(em.EV.E2)
|
!el_sideeffect(em.E2)
|
||||||
)
|
)
|
||||||
{ // Change (x += a),(x += b) to
|
{ // Change (x += a),(x += b) to
|
||||||
// (x + a),(x += a + b)
|
// (x + a),(x += a + b)
|
||||||
go.changes++;
|
go.changes++;
|
||||||
e.EV.E2 = el_bin(opeqtoop(op),e.EV.E2.Ety,em.EV.E2,e.EV.E2);
|
e.E2 = el_bin(opeqtoop(op),e.E2.Ety,em.E2,e.E2);
|
||||||
em.Eoper = cast(ubyte)opeqtoop(op);
|
em.Eoper = cast(ubyte)opeqtoop(op);
|
||||||
em.EV.E2 = el_copytree(em.EV.E2);
|
em.E2 = el_copytree(em.E2);
|
||||||
local_rem(lt, u);
|
local_rem(lt, u);
|
||||||
|
|
||||||
debug if (debugc)
|
debug if (debugc)
|
||||||
|
@ -240,29 +240,29 @@ Loop:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
e1 = e.EV.E1;
|
e1 = e.E1;
|
||||||
op1 = e1.Eoper;
|
op1 = e1.Eoper;
|
||||||
if (op1 != OPvar)
|
if (op1 != OPvar)
|
||||||
{
|
{
|
||||||
local_exp(lt,e1.EV.E1,1);
|
local_exp(lt,e1.E1,1);
|
||||||
if (OTbinary(op1))
|
if (OTbinary(op1))
|
||||||
local_exp(lt,e1.EV.E2,1);
|
local_exp(lt,e1.E2,1);
|
||||||
}
|
}
|
||||||
if (lt.length)
|
if (lt.length)
|
||||||
{
|
{
|
||||||
Symbol* s;
|
Symbol* s;
|
||||||
if (op1 == OPvar &&
|
if (op1 == OPvar &&
|
||||||
((s = e1.EV.Vsym).Sflags & SFLunambig))
|
((s = e1.Vsym).Sflags & SFLunambig))
|
||||||
local_symref(lt, s);
|
local_symref(lt, s);
|
||||||
else
|
else
|
||||||
local_ambigref(lt);
|
local_ambigref(lt);
|
||||||
}
|
}
|
||||||
local_exp(lt,e.EV.E2,1);
|
local_exp(lt,e.E2,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol* s;
|
Symbol* s;
|
||||||
if (op1 == OPvar &&
|
if (op1 == OPvar &&
|
||||||
((s = e1.EV.Vsym).Sflags & SFLunambig))
|
((s = e1.Vsym).Sflags & SFLunambig))
|
||||||
{ local_symref(lt, s);
|
{ local_symref(lt, s);
|
||||||
local_symdef(lt, s);
|
local_symdef(lt, s);
|
||||||
if (op == OPaddass || op == OPxorass)
|
if (op == OPaddass || op == OPxorass)
|
||||||
|
@ -276,15 +276,15 @@ Loop:
|
||||||
|
|
||||||
case OPstrlen:
|
case OPstrlen:
|
||||||
case OPind:
|
case OPind:
|
||||||
local_exp(lt,e.EV.E1,1);
|
local_exp(lt,e.E1,1);
|
||||||
local_ambigref(lt);
|
local_ambigref(lt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPstrcmp:
|
case OPstrcmp:
|
||||||
case OPmemcmp:
|
case OPmemcmp:
|
||||||
case OPbt:
|
case OPbt:
|
||||||
local_exp(lt,e.EV.E1,1);
|
local_exp(lt,e.E1,1);
|
||||||
local_exp(lt,e.EV.E2,1);
|
local_exp(lt,e.E2,1);
|
||||||
local_ambigref(lt);
|
local_ambigref(lt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -293,21 +293,21 @@ Loop:
|
||||||
case OPstrcat:
|
case OPstrcat:
|
||||||
case OPcall:
|
case OPcall:
|
||||||
case OPcallns:
|
case OPcallns:
|
||||||
local_exp(lt,e.EV.E2,1);
|
local_exp(lt,e.E2,1);
|
||||||
local_exp(lt,e.EV.E1,1);
|
local_exp(lt,e.E1,1);
|
||||||
goto Lrd;
|
goto Lrd;
|
||||||
|
|
||||||
case OPstrctor:
|
case OPstrctor:
|
||||||
case OPucall:
|
case OPucall:
|
||||||
case OPucallns:
|
case OPucallns:
|
||||||
local_exp(lt,e.EV.E1,1);
|
local_exp(lt,e.E1,1);
|
||||||
goto Lrd;
|
goto Lrd;
|
||||||
|
|
||||||
case OPbtc:
|
case OPbtc:
|
||||||
case OPbtr:
|
case OPbtr:
|
||||||
case OPbts:
|
case OPbts:
|
||||||
local_exp(lt,e.EV.E1,1);
|
local_exp(lt,e.E1,1);
|
||||||
local_exp(lt,e.EV.E2,1);
|
local_exp(lt,e.E2,1);
|
||||||
goto Lrd;
|
goto Lrd;
|
||||||
|
|
||||||
case OPasm:
|
case OPasm:
|
||||||
|
@ -316,25 +316,25 @@ Loop:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPmemset:
|
case OPmemset:
|
||||||
local_exp(lt,e.EV.E2,1);
|
local_exp(lt,e.E2,1);
|
||||||
if (e.EV.E1.Eoper == OPvar)
|
if (e.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
/* Don't want to rearrange (p = get(); p memset 0;)
|
/* Don't want to rearrange (p = get(); p memset 0;)
|
||||||
* as elemxxx() will rearrange it back.
|
* as elemxxx() will rearrange it back.
|
||||||
*/
|
*/
|
||||||
const s = e.EV.E1.EV.Vsym;
|
const s = e.E1.Vsym;
|
||||||
if (s.Sflags & SFLunambig)
|
if (s.Sflags & SFLunambig)
|
||||||
local_symref(lt, s);
|
local_symref(lt, s);
|
||||||
else
|
else
|
||||||
local_ambigref(lt); // ambiguous reference
|
local_ambigref(lt); // ambiguous reference
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
local_exp(lt,e.EV.E1,1);
|
local_exp(lt,e.E1,1);
|
||||||
local_ambigdef(lt);
|
local_ambigdef(lt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPvar:
|
case OPvar:
|
||||||
const s = e.EV.Vsym;
|
const s = e.Vsym;
|
||||||
if (lt.length)
|
if (lt.length)
|
||||||
{
|
{
|
||||||
// If potential candidate for replacement
|
// If potential candidate for replacement
|
||||||
|
@ -343,11 +343,11 @@ Loop:
|
||||||
foreach (const u; 0 .. lt.length)
|
foreach (const u; 0 .. lt.length)
|
||||||
{
|
{
|
||||||
auto em = lt[u].e;
|
auto em = lt[u].e;
|
||||||
if (em.EV.E1.EV.Vsym == s &&
|
if (em.E1.Vsym == s &&
|
||||||
(em.Eoper == OPeq || em.Eoper == OPstreq))
|
(em.Eoper == OPeq || em.Eoper == OPstreq))
|
||||||
{
|
{
|
||||||
if (tysize(em.Ety) == tysize(e.Ety) &&
|
if (tysize(em.Ety) == tysize(e.Ety) &&
|
||||||
em.EV.E1.EV.Voffset == e.EV.Voffset &&
|
em.E1.Voffset == e.Voffset &&
|
||||||
((tyfloating(em.Ety) != 0) == (tyfloating(e.Ety) != 0) ||
|
((tyfloating(em.Ety) != 0) == (tyfloating(e.Ety) != 0) ||
|
||||||
/** Hack to fix https://issues.dlang.org/show_bug.cgi?id=10226
|
/** Hack to fix https://issues.dlang.org/show_bug.cgi?id=10226
|
||||||
* Recognize assignments of float vectors to void16, as used by
|
* Recognize assignments of float vectors to void16, as used by
|
||||||
|
@ -358,8 +358,8 @@ Loop:
|
||||||
* wrong code.
|
* wrong code.
|
||||||
* Ref: https://issues.dlang.org/show_bug.cgi?id=18034
|
* Ref: https://issues.dlang.org/show_bug.cgi?id=18034
|
||||||
*/
|
*/
|
||||||
(em.EV.E2.Eoper != OPvecfill || tybasic(e.Ety) == tybasic(em.Ety)) &&
|
(em.E2.Eoper != OPvecfill || tybasic(e.Ety) == tybasic(em.Ety)) &&
|
||||||
!local_preserveAssignmentTo(em.EV.E1.Ety))
|
!local_preserveAssignmentTo(em.E1.Ety))
|
||||||
{
|
{
|
||||||
|
|
||||||
debug if (debugc)
|
debug if (debugc)
|
||||||
|
@ -371,7 +371,7 @@ Loop:
|
||||||
go.changes++;
|
go.changes++;
|
||||||
em.Ety = e.Ety;
|
em.Ety = e.Ety;
|
||||||
el_copy(e,em);
|
el_copy(e,em);
|
||||||
em.EV.E1 = em.EV.E2 = null;
|
em.E1 = em.E2 = null;
|
||||||
em.Eoper = OPconst;
|
em.Eoper = OPconst;
|
||||||
}
|
}
|
||||||
local_rem(lt, u);
|
local_rem(lt, u);
|
||||||
|
@ -386,9 +386,9 @@ Loop:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPremquo:
|
case OPremquo:
|
||||||
if (e.EV.E1.Eoper != OPvar)
|
if (e.E1.Eoper != OPvar)
|
||||||
goto case_bin;
|
goto case_bin;
|
||||||
const s = e.EV.E1.EV.Vsym;
|
const s = e.E1.Vsym;
|
||||||
if (lt.length)
|
if (lt.length)
|
||||||
{
|
{
|
||||||
if (s.Sflags & SFLunambig)
|
if (s.Sflags & SFLunambig)
|
||||||
|
@ -397,7 +397,7 @@ Loop:
|
||||||
local_ambigref(lt); // ambiguous reference
|
local_ambigref(lt); // ambiguous reference
|
||||||
}
|
}
|
||||||
goal = 1;
|
goal = 1;
|
||||||
e = e.EV.E2;
|
e = e.E2;
|
||||||
goto Loop;
|
goto Loop;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -409,16 +409,16 @@ Loop:
|
||||||
{
|
{
|
||||||
const f = lt[u].flags;
|
const f = lt[u].flags;
|
||||||
elem* eu = lt[u].e;
|
elem* eu = lt[u].e;
|
||||||
const s = eu.EV.E1.EV.Vsym;
|
const s = eu.E1.Vsym;
|
||||||
const f1 = local_getflags(e.EV.E1,s);
|
const f1 = local_getflags(e.E1,s);
|
||||||
const f2 = local_getflags(e.EV.E2,s);
|
const f2 = local_getflags(e.E2,s);
|
||||||
if (f1 & f2 & LFsymref || // if both reference or
|
if (f1 & f2 & LFsymref || // if both reference or
|
||||||
(f1 | f2) & LFsymdef || // either define
|
(f1 | f2) & LFsymdef || // either define
|
||||||
f & LFambigref && (f1 | f2) & LFambigdef ||
|
f & LFambigref && (f1 | f2) & LFambigdef ||
|
||||||
f & LFambigdef && (f1 | f2) & (LFambigref | LFambigdef)
|
f & LFambigdef && (f1 | f2) & (LFambigref | LFambigdef)
|
||||||
)
|
)
|
||||||
local_rem(lt, u);
|
local_rem(lt, u);
|
||||||
else if (f & LFunambigdef && local_chkrem(e,eu.EV.E2))
|
else if (f & LFunambigdef && local_chkrem(e,eu.E2))
|
||||||
local_rem(lt, u);
|
local_rem(lt, u);
|
||||||
else
|
else
|
||||||
u++;
|
u++;
|
||||||
|
@ -426,14 +426,14 @@ Loop:
|
||||||
}
|
}
|
||||||
if (OTunary(e.Eoper))
|
if (OTunary(e.Eoper))
|
||||||
{ goal = 1;
|
{ goal = 1;
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
goto Loop;
|
goto Loop;
|
||||||
}
|
}
|
||||||
case_bin:
|
case_bin:
|
||||||
if (OTbinary(e.Eoper))
|
if (OTbinary(e.Eoper))
|
||||||
{ local_exp(lt,e.EV.E1,1);
|
{ local_exp(lt,e.E1,1);
|
||||||
goal = 1;
|
goal = 1;
|
||||||
e = e.EV.E2;
|
e = e.E2;
|
||||||
goto Loop;
|
goto Loop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -454,22 +454,22 @@ private bool local_chkrem(const elem* e, const(elem)* eu)
|
||||||
{
|
{
|
||||||
elem_debug(eu);
|
elem_debug(eu);
|
||||||
const op = eu.Eoper;
|
const op = eu.Eoper;
|
||||||
if (OTassign(op) && eu.EV.E1.Eoper == OPvar)
|
if (OTassign(op) && eu.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
const s = eu.EV.E1.EV.Vsym;
|
const s = eu.E1.Vsym;
|
||||||
const f1 = local_getflags(e.EV.E1,s);
|
const f1 = local_getflags(e.E1,s);
|
||||||
const f2 = local_getflags(e.EV.E2,s);
|
const f2 = local_getflags(e.E2,s);
|
||||||
if ((f1 | f2) & (LFsymref | LFsymdef)) // if either reference or define
|
if ((f1 | f2) & (LFsymref | LFsymdef)) // if either reference or define
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (OTbinary(op))
|
if (OTbinary(op))
|
||||||
{
|
{
|
||||||
if (local_chkrem(e,eu.EV.E2))
|
if (local_chkrem(e,eu.E2))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!OTunary(op))
|
else if (!OTunary(op))
|
||||||
break; // leaf node
|
break; // leaf node
|
||||||
eu = eu.EV.E1;
|
eu = eu.E1;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -481,15 +481,15 @@ private bool local_chkrem(const elem* e, const(elem)* eu)
|
||||||
private void local_ins(ref Barray!loc_t lt, elem *e)
|
private void local_ins(ref Barray!loc_t lt, elem *e)
|
||||||
{
|
{
|
||||||
elem_debug(e);
|
elem_debug(e);
|
||||||
if (e.EV.E1.Eoper == OPvar)
|
if (e.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
const s = e.EV.E1.EV.Vsym;
|
const s = e.E1.Vsym;
|
||||||
symbol_debug(s);
|
symbol_debug(s);
|
||||||
if (s.Sflags & SFLunambig) // if can only be referenced directly
|
if (s.Sflags & SFLunambig) // if can only be referenced directly
|
||||||
{
|
{
|
||||||
const flags = local_getflags(e.EV.E2,null);
|
const flags = local_getflags(e.E2,null);
|
||||||
if (!(flags & (LFvolatile | LFinp | LFoutp)) &&
|
if (!(flags & (LFvolatile | LFinp | LFoutp)) &&
|
||||||
!(e.EV.E1.Ety & (mTYvolatile | mTYshared)))
|
!(e.E1.Ety & (mTYvolatile | mTYshared)))
|
||||||
{
|
{
|
||||||
// Add e to the candidate array
|
// Add e to the candidate array
|
||||||
//printf("local_ins('%s'), loctop = %d\n",s.Sident.ptr,lt.length);
|
//printf("local_ins('%s'), loctop = %d\n",s.Sident.ptr,lt.length);
|
||||||
|
@ -526,9 +526,9 @@ private int local_getflags(const(elem)* e, const Symbol* s)
|
||||||
{
|
{
|
||||||
case OPeq:
|
case OPeq:
|
||||||
case OPstreq:
|
case OPstreq:
|
||||||
if (e.EV.E1.Eoper == OPvar)
|
if (e.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
const s1 = e.EV.E1.EV.Vsym;
|
const s1 = e.E1.Vsym;
|
||||||
if (s1.Sflags & SFLunambig)
|
if (s1.Sflags & SFLunambig)
|
||||||
flags |= (s1 == s) ? LFsymdef : LFunambigdef;
|
flags |= (s1 == s) ? LFsymdef : LFunambigdef;
|
||||||
else
|
else
|
||||||
|
@ -552,9 +552,9 @@ private int local_getflags(const(elem)* e, const Symbol* s)
|
||||||
case OPxorass:
|
case OPxorass:
|
||||||
case OPorass:
|
case OPorass:
|
||||||
case OPcmpxchg:
|
case OPcmpxchg:
|
||||||
if (e.EV.E1.Eoper == OPvar)
|
if (e.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
const s1 = e.EV.E1.EV.Vsym;
|
const s1 = e.E1.Vsym;
|
||||||
if (s1.Sflags & SFLunambig)
|
if (s1.Sflags & SFLunambig)
|
||||||
flags |= (s1 == s) ? LFsymdef | LFsymref
|
flags |= (s1 == s) ? LFsymdef | LFsymref
|
||||||
: LFunambigdef | LFunambigref;
|
: LFunambigdef | LFunambigref;
|
||||||
|
@ -564,8 +564,8 @@ private int local_getflags(const(elem)* e, const Symbol* s)
|
||||||
else
|
else
|
||||||
flags |= LFambigdef | LFambigref;
|
flags |= LFambigdef | LFambigref;
|
||||||
L1:
|
L1:
|
||||||
flags |= local_getflags(e.EV.E2,s);
|
flags |= local_getflags(e.E2,s);
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPucall:
|
case OPucall:
|
||||||
|
@ -587,9 +587,9 @@ private int local_getflags(const(elem)* e, const Symbol* s)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPvar:
|
case OPvar:
|
||||||
if (e.EV.Vsym == s)
|
if (e.Vsym == s)
|
||||||
flags |= LFsymref;
|
flags |= LFsymref;
|
||||||
else if (!(e.EV.Vsym.Sflags & SFLunambig))
|
else if (!(e.Vsym.Sflags & SFLunambig))
|
||||||
flags |= LFambigref;
|
flags |= LFambigref;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -616,14 +616,14 @@ private int local_getflags(const(elem)* e, const Symbol* s)
|
||||||
{
|
{
|
||||||
if (tyfloating(e.Ety))
|
if (tyfloating(e.Ety))
|
||||||
flags |= LFfloat;
|
flags |= LFfloat;
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
}
|
}
|
||||||
else if (OTbinary(e.Eoper))
|
else if (OTbinary(e.Eoper))
|
||||||
{
|
{
|
||||||
if (tyfloating(e.Ety))
|
if (tyfloating(e.Ety))
|
||||||
flags |= LFfloat;
|
flags |= LFfloat;
|
||||||
flags |= local_getflags(e.EV.E2,s);
|
flags |= local_getflags(e.E2,s);
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -232,28 +232,28 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
if (op == OPcolon || op == OPcolon2)
|
if (op == OPcolon || op == OPcolon2)
|
||||||
{
|
{
|
||||||
L = vec_clone(IN);
|
L = vec_clone(IN);
|
||||||
switch (el_returns(n.EV.E1) * 2 | el_returns(n.EV.E2))
|
switch (el_returns(n.E1) * 2 | el_returns(n.E2))
|
||||||
{
|
{
|
||||||
case 3: // E1 and E2 return
|
case 3: // E1 and E2 return
|
||||||
conpropwalk(n.EV.E1,L);
|
conpropwalk(n.E1,L);
|
||||||
conpropwalk(n.EV.E2,IN);
|
conpropwalk(n.E2,IN);
|
||||||
vec_orass(IN,L); // IN = L | R
|
vec_orass(IN,L); // IN = L | R
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // E1 returns
|
case 2: // E1 returns
|
||||||
conpropwalk(n.EV.E1,IN);
|
conpropwalk(n.E1,IN);
|
||||||
conpropwalk(n.EV.E2,L);
|
conpropwalk(n.E2,L);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // E2 returns
|
case 1: // E2 returns
|
||||||
conpropwalk(n.EV.E1,L);
|
conpropwalk(n.E1,L);
|
||||||
conpropwalk(n.EV.E2,IN);
|
conpropwalk(n.E2,IN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0: // neither returns
|
case 0: // neither returns
|
||||||
conpropwalk(n.EV.E1,L);
|
conpropwalk(n.E1,L);
|
||||||
vec_copy(L,IN);
|
vec_copy(L,IN);
|
||||||
conpropwalk(n.EV.E2,L);
|
conpropwalk(n.E2,L);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -263,10 +263,10 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
}
|
}
|
||||||
else if (op == OPandand || op == OPoror)
|
else if (op == OPandand || op == OPoror)
|
||||||
{
|
{
|
||||||
conpropwalk(n.EV.E1,IN);
|
conpropwalk(n.E1,IN);
|
||||||
R = vec_clone(IN);
|
R = vec_clone(IN);
|
||||||
conpropwalk(n.EV.E2,R);
|
conpropwalk(n.E2,R);
|
||||||
if (el_returns(n.EV.E2))
|
if (el_returns(n.E2))
|
||||||
vec_orass(IN,R); // IN |= R
|
vec_orass(IN,R); // IN |= R
|
||||||
vec_free(R);
|
vec_free(R);
|
||||||
}
|
}
|
||||||
|
@ -274,15 +274,15 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
goto L3;
|
goto L3;
|
||||||
else if (ERTOL(n))
|
else if (ERTOL(n))
|
||||||
{
|
{
|
||||||
conpropwalk(n.EV.E2,IN);
|
conpropwalk(n.E2,IN);
|
||||||
L3:
|
L3:
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{
|
{
|
||||||
if (t.Eoper == OPvar)
|
if (t.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
// Note that the following ignores OPnegass
|
// Note that the following ignores OPnegass
|
||||||
if (OTopeq(op) && sytab[t.EV.Vsym.Sclass] & SCRD)
|
if (OTopeq(op) && sytab[t.Vsym.Sclass] & SCRD)
|
||||||
{
|
{
|
||||||
Barray!(elem*) rdl;
|
Barray!(elem*) rdl;
|
||||||
listrds(IN,t,null,&rdl);
|
listrds(IN,t,null,&rdl);
|
||||||
|
@ -293,7 +293,7 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
|
|
||||||
e = el_copytree(e);
|
e = el_copytree(e);
|
||||||
e.Ety = t.Ety;
|
e.Ety = t.Ety;
|
||||||
n.EV.E2 = el_bin(opeqtoop(op),n.Ety,e,n.EV.E2);
|
n.E2 = el_bin(opeqtoop(op),n.Ety,e,n.E2);
|
||||||
n.Eoper = OPeq;
|
n.Eoper = OPeq;
|
||||||
}
|
}
|
||||||
rdl.dtor();
|
rdl.dtor();
|
||||||
|
@ -308,17 +308,17 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{ t = n.EV.E1;
|
{ t = n.E1;
|
||||||
if (t.Eoper != OPvar)
|
if (t.Eoper != OPvar)
|
||||||
conpropwalk(t,IN);
|
conpropwalk(t,IN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
conpropwalk(n.EV.E1,IN);
|
conpropwalk(n.E1,IN);
|
||||||
conpropwalk(n.EV.E2,IN);
|
conpropwalk(n.E2,IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect data for subsequent optimizations
|
// Collect data for subsequent optimizations
|
||||||
if (OTbinary(op) && n.EV.E1.Eoper == OPvar && n.EV.E2.Eoper == OPconst)
|
if (OTbinary(op) && n.E1.Eoper == OPvar && n.E2.Eoper == OPconst)
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
|
@ -327,15 +327,15 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
case OPle:
|
case OPle:
|
||||||
case OPge:
|
case OPge:
|
||||||
// Collect compare elems and their rd's in the rellist list
|
// Collect compare elems and their rd's in the rellist list
|
||||||
if (tyintegral(n.EV.E1.Ety) &&
|
if (tyintegral(n.E1.Ety) &&
|
||||||
tyintegral(n.EV.E2.Ety)
|
tyintegral(n.E2.Ety)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//printf("appending to rellist\n"); elem_print(n);
|
//printf("appending to rellist\n"); elem_print(n);
|
||||||
//printf("\trellist IN: "); vec_print(IN); printf("\n");
|
//printf("\trellist IN: "); vec_print(IN); printf("\n");
|
||||||
auto pdata = eqrelinc.rellist.push();
|
auto pdata = eqrelinc.rellist.push();
|
||||||
pdata.emplace(n, thisblock);
|
pdata.emplace(n, thisblock);
|
||||||
listrds(IN, n.EV.E1, null, &pdata.rdlist);
|
listrds(IN, n.E1, null, &pdata.rdlist);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -344,24 +344,24 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
case OPpostinc:
|
case OPpostinc:
|
||||||
case OPpostdec:
|
case OPpostdec:
|
||||||
// Collect increment elems and their rd's in the inclist list
|
// Collect increment elems and their rd's in the inclist list
|
||||||
if (tyintegral(n.EV.E1.Ety))
|
if (tyintegral(n.E1.Ety))
|
||||||
{
|
{
|
||||||
//printf("appending to inclist\n"); elem_print(n);
|
//printf("appending to inclist\n"); elem_print(n);
|
||||||
//printf("\tinclist IN: "); vec_print(IN); printf("\n");
|
//printf("\tinclist IN: "); vec_print(IN); printf("\n");
|
||||||
auto pdata = eqrelinc.inclist.push();
|
auto pdata = eqrelinc.inclist.push();
|
||||||
pdata.emplace(n, thisblock);
|
pdata.emplace(n, thisblock);
|
||||||
listrds(IN, n.EV.E1, null, &pdata.rdlist);
|
listrds(IN, n.E1, null, &pdata.rdlist);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPne:
|
case OPne:
|
||||||
case OPeqeq:
|
case OPeqeq:
|
||||||
// Collect compare elems and their rd's in the rellist list
|
// Collect compare elems and their rd's in the rellist list
|
||||||
if (tyintegral(n.EV.E1.Ety) && !tyvector(n.Ety))
|
if (tyintegral(n.E1.Ety) && !tyvector(n.Ety))
|
||||||
{ //printf("appending to eqeqlist\n"); elem_print(n);
|
{ //printf("appending to eqeqlist\n"); elem_print(n);
|
||||||
auto pdata = eqrelinc.eqeqlist.push();
|
auto pdata = eqrelinc.eqeqlist.push();
|
||||||
pdata.emplace(n, thisblock);
|
pdata.emplace(n, thisblock);
|
||||||
listrds(IN, n.EV.E1, null, &pdata.rdlist);
|
listrds(IN, n.E1, null, &pdata.rdlist);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -376,9 +376,9 @@ private void constantPropagation(block* thisblock, ref EqRelInc eqrelinc)
|
||||||
|
|
||||||
/* now we get to the part that checks to see if we can */
|
/* now we get to the part that checks to see if we can */
|
||||||
/* propagate a constant. */
|
/* propagate a constant. */
|
||||||
if (op == OPvar && sytab[n.EV.Vsym.Sclass] & SCRD)
|
if (op == OPvar && sytab[n.Vsym.Sclass] & SCRD)
|
||||||
{
|
{
|
||||||
//printf("const prop: %s\n", n.EV.Vsym.Sident.ptr);
|
//printf("const prop: %s\n", n.Vsym.Sident.ptr);
|
||||||
Barray!(elem*) rdl;
|
Barray!(elem*) rdl;
|
||||||
listrds(IN,n,null,&rdl);
|
listrds(IN,n,null,&rdl);
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ private void chkrd(elem *n, Barray!(elem*) rdlist)
|
||||||
Symbol *sv;
|
Symbol *sv;
|
||||||
int unambig;
|
int unambig;
|
||||||
|
|
||||||
sv = n.EV.Vsym;
|
sv = n.Vsym;
|
||||||
assert(sytab[sv.Sclass] & SCRD);
|
assert(sytab[sv.Sclass] & SCRD);
|
||||||
if (sv.Sflags & SFLnord) // if already printed a warning
|
if (sv.Sflags & SFLnord) // if already printed a warning
|
||||||
return;
|
return;
|
||||||
|
@ -423,9 +423,9 @@ private void chkrd(elem *n, Barray!(elem*) rdlist)
|
||||||
return;
|
return;
|
||||||
if (OTassign(d.Eoper))
|
if (OTassign(d.Eoper))
|
||||||
{
|
{
|
||||||
if (d.EV.E1.Eoper == OPvar)
|
if (d.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
if (d.EV.E1.EV.Vsym == sv)
|
if (d.E1.Vsym == sv)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!unambig)
|
else if (!unambig)
|
||||||
|
@ -514,13 +514,13 @@ private elem * chkprop(elem *n, Barray!(elem*) rdlist)
|
||||||
//printf("checkprop: "); WReqn(n); printf("\n");
|
//printf("checkprop: "); WReqn(n); printf("\n");
|
||||||
assert(n && n.Eoper == OPvar);
|
assert(n && n.Eoper == OPvar);
|
||||||
elem_debug(n);
|
elem_debug(n);
|
||||||
sv = n.EV.Vsym;
|
sv = n.Vsym;
|
||||||
assert(sytab[sv.Sclass] & SCRD);
|
assert(sytab[sv.Sclass] & SCRD);
|
||||||
nty = n.Ety;
|
nty = n.Ety;
|
||||||
if (!tyscalar(nty))
|
if (!tyscalar(nty))
|
||||||
goto noprop;
|
goto noprop;
|
||||||
nsize = cast(uint)size(nty);
|
nsize = cast(uint)size(nty);
|
||||||
noff = n.EV.Voffset;
|
noff = n.Voffset;
|
||||||
unambig = sv.Sflags & SFLunambig;
|
unambig = sv.Sflags & SFLunambig;
|
||||||
foreach (d; rdlist)
|
foreach (d; rdlist)
|
||||||
{
|
{
|
||||||
|
@ -535,11 +535,11 @@ private elem * chkprop(elem *n, Barray!(elem*) rdlist)
|
||||||
|
|
||||||
if (OTassign(d.Eoper)) // if assignment elem
|
if (OTassign(d.Eoper)) // if assignment elem
|
||||||
{
|
{
|
||||||
elem *t = d.EV.E1;
|
elem *t = d.E1;
|
||||||
|
|
||||||
if (t.Eoper == OPvar)
|
if (t.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
assert(t.EV.Vsym == sv);
|
assert(t.Vsym == sv);
|
||||||
|
|
||||||
if (d.Eoper == OPstreq ||
|
if (d.Eoper == OPstreq ||
|
||||||
!tyscalar(t.Ety))
|
!tyscalar(t.Ety))
|
||||||
|
@ -550,10 +550,10 @@ private elem * chkprop(elem *n, Barray!(elem*) rdlist)
|
||||||
|
|
||||||
/* Everything must match or we must skip this variable */
|
/* Everything must match or we must skip this variable */
|
||||||
/* (in case of assigning to overlapping unions, etc.) */
|
/* (in case of assigning to overlapping unions, etc.) */
|
||||||
if (t.EV.Voffset != noff ||
|
if (t.Voffset != noff ||
|
||||||
/* If sizes match, we are ok */
|
/* If sizes match, we are ok */
|
||||||
size(t.Ety) != nsize &&
|
size(t.Ety) != nsize &&
|
||||||
!(d.EV.E2.Eoper == OPconst && size(t.Ety) > nsize && !tyfloating(d.EV.E2.Ety)))
|
!(d.E2.Eoper == OPconst && size(t.Ety) > nsize && !tyfloating(d.E2.Ety)))
|
||||||
goto noprop;
|
goto noprop;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -573,15 +573,15 @@ private elem * chkprop(elem *n, Barray!(elem*) rdlist)
|
||||||
goto noprop; /* could be affected */
|
goto noprop; /* could be affected */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d.EV.E2.Eoper == OPconst || d.EV.E2.Eoper == OPrelconst)
|
if (d.E2.Eoper == OPconst || d.E2.Eoper == OPrelconst)
|
||||||
{
|
{
|
||||||
if (foundelem) /* already found one */
|
if (foundelem) /* already found one */
|
||||||
{ /* then they must be the same */
|
{ /* then they must be the same */
|
||||||
if (!el_match(foundelem,d.EV.E2))
|
if (!el_match(foundelem,d.E2))
|
||||||
goto noprop;
|
goto noprop;
|
||||||
}
|
}
|
||||||
else /* else this is it */
|
else /* else this is it */
|
||||||
foundelem = d.EV.E2;
|
foundelem = d.E2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto noprop;
|
goto noprop;
|
||||||
|
@ -625,11 +625,11 @@ void listrds(vec_t IN,elem *e,vec_t f, Barray!(elem*)* rdlist)
|
||||||
//printf("listrds: "); WReqn(e); printf("\n");
|
//printf("listrds: "); WReqn(e); printf("\n");
|
||||||
assert(IN);
|
assert(IN);
|
||||||
assert(e.Eoper == OPvar);
|
assert(e.Eoper == OPvar);
|
||||||
s = e.EV.Vsym;
|
s = e.Vsym;
|
||||||
ty = e.Ety;
|
ty = e.Ety;
|
||||||
if (tyscalar(ty))
|
if (tyscalar(ty))
|
||||||
nsize = cast(uint)size(ty);
|
nsize = cast(uint)size(ty);
|
||||||
noff = e.EV.Voffset;
|
noff = e.Voffset;
|
||||||
unambig = s.Sflags & SFLunambig;
|
unambig = s.Sflags & SFLunambig;
|
||||||
if (f)
|
if (f)
|
||||||
vec_clear(f);
|
vec_clear(f);
|
||||||
|
@ -641,16 +641,16 @@ void listrds(vec_t IN,elem *e,vec_t f, Barray!(elem*)* rdlist)
|
||||||
if (op == OPasm) // assume ASM elems define everything
|
if (op == OPasm) // assume ASM elems define everything
|
||||||
goto listit;
|
goto listit;
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{ elem *t = d.EV.E1;
|
{ elem *t = d.E1;
|
||||||
|
|
||||||
if (t.Eoper == OPvar && t.EV.Vsym == s)
|
if (t.Eoper == OPvar && t.Vsym == s)
|
||||||
{ if (op == OPstreq)
|
{ if (op == OPstreq)
|
||||||
goto listit;
|
goto listit;
|
||||||
if (!tyscalar(ty) || !tyscalar(t.Ety))
|
if (!tyscalar(ty) || !tyscalar(t.Ety))
|
||||||
goto listit;
|
goto listit;
|
||||||
// If t does not overlap e, then it doesn't affect things
|
// If t does not overlap e, then it doesn't affect things
|
||||||
if (noff + nsize > t.EV.Voffset &&
|
if (noff + nsize > t.Voffset &&
|
||||||
t.EV.Voffset + size(t.Ety) > noff)
|
t.Voffset + size(t.Ety) > noff)
|
||||||
goto listit; // it's an assignment to s
|
goto listit; // it's an assignment to s
|
||||||
}
|
}
|
||||||
else if (t.Eoper != OPvar && !unambig)
|
else if (t.Eoper != OPvar && !unambig)
|
||||||
|
@ -689,11 +689,11 @@ private void eqeqranges(ref Elemdatas eqeqlist)
|
||||||
foreach (ref rel; eqeqlist)
|
foreach (ref rel; eqeqlist)
|
||||||
{
|
{
|
||||||
e = rel.pelem;
|
e = rel.pelem;
|
||||||
v = e.EV.E1.EV.Vsym;
|
v = e.E1.Vsym;
|
||||||
if (!(sytab[v.Sclass] & SCRD))
|
if (!(sytab[v.Sclass] & SCRD))
|
||||||
continue;
|
continue;
|
||||||
sz = tysize(e.EV.E1.Ety);
|
sz = tysize(e.E1.Ety);
|
||||||
c = el_tolong(e.EV.E2);
|
c = el_tolong(e.E2);
|
||||||
|
|
||||||
result = -1; // result not known yet
|
result = -1; // result not known yet
|
||||||
foreach (erd; rel.rdlist)
|
foreach (erd; rel.rdlist)
|
||||||
|
@ -704,18 +704,18 @@ private void eqeqranges(ref Elemdatas eqeqlist)
|
||||||
|
|
||||||
elem_debug(erd);
|
elem_debug(erd);
|
||||||
if (erd.Eoper != OPeq ||
|
if (erd.Eoper != OPeq ||
|
||||||
(erd1 = erd.EV.E1).Eoper != OPvar ||
|
(erd1 = erd.E1).Eoper != OPvar ||
|
||||||
erd.EV.E2.Eoper != OPconst
|
erd.E2.Eoper != OPconst
|
||||||
)
|
)
|
||||||
goto L1;
|
goto L1;
|
||||||
szrd = tysize(erd1.Ety);
|
szrd = tysize(erd1.Ety);
|
||||||
if (erd1.EV.Voffset + szrd <= e.EV.E1.EV.Voffset ||
|
if (erd1.Voffset + szrd <= e.E1.Voffset ||
|
||||||
e.EV.E1.EV.Voffset + sz <= erd1.EV.Voffset)
|
e.E1.Voffset + sz <= erd1.Voffset)
|
||||||
continue; // doesn't affect us, skip it
|
continue; // doesn't affect us, skip it
|
||||||
if (szrd != sz || e.EV.E1.EV.Voffset != erd1.EV.Voffset)
|
if (szrd != sz || e.E1.Voffset != erd1.Voffset)
|
||||||
goto L1; // overlapping - forget it
|
goto L1; // overlapping - forget it
|
||||||
|
|
||||||
tmp = (c == el_tolong(erd.EV.E2));
|
tmp = (c == el_tolong(erd.E2));
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
result = tmp;
|
result = tmp;
|
||||||
else if (result != tmp)
|
else if (result != tmp)
|
||||||
|
@ -724,9 +724,9 @@ private void eqeqranges(ref Elemdatas eqeqlist)
|
||||||
if (result >= 0)
|
if (result >= 0)
|
||||||
{
|
{
|
||||||
//printf("replacing with %d\n",result);
|
//printf("replacing with %d\n",result);
|
||||||
el_free(e.EV.E1);
|
el_free(e.E1);
|
||||||
el_free(e.EV.E2);
|
el_free(e.E2);
|
||||||
e.EV.Vint = (e.Eoper == OPeqeq) ? result : result ^ 1;
|
e.Vint = (e.Eoper == OPeqeq) ? result : result ^ 1;
|
||||||
e.Eoper = OPconst;
|
e.Eoper = OPconst;
|
||||||
}
|
}
|
||||||
L1:
|
L1:
|
||||||
|
@ -765,8 +765,8 @@ private void intranges(ref Elemdatas rellist, ref Elemdatas inclist)
|
||||||
{
|
{
|
||||||
rb = rel.pblock;
|
rb = rel.pblock;
|
||||||
//printf("rel.pelem: "); WReqn(rel.pelem); printf("\n");
|
//printf("rel.pelem: "); WReqn(rel.pelem); printf("\n");
|
||||||
assert(rel.pelem.EV.E1.Eoper == OPvar);
|
assert(rel.pelem.E1.Eoper == OPvar);
|
||||||
v = rel.pelem.EV.E1.EV.Vsym;
|
v = rel.pelem.E1.Vsym;
|
||||||
|
|
||||||
// RD info is only reliable for registers and autos
|
// RD info is only reliable for registers and autos
|
||||||
if (!(sytab[v.Sclass] & SCRD))
|
if (!(sytab[v.Sclass] & SCRD))
|
||||||
|
@ -797,10 +797,10 @@ private void intranges(ref Elemdatas rellist, ref Elemdatas inclist)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* lvalues should be unambiguous defs */
|
/* lvalues should be unambiguous defs */
|
||||||
if (rdeq.EV.E1.Eoper != OPvar || rdinc.EV.E1.Eoper != OPvar)
|
if (rdeq.E1.Eoper != OPvar || rdinc.E1.Eoper != OPvar)
|
||||||
continue;
|
continue;
|
||||||
/* rvalues should be constants */
|
/* rvalues should be constants */
|
||||||
if (rdeq.EV.E2.Eoper != OPconst || rdinc.EV.E2.Eoper != OPconst)
|
if (rdeq.E2.Eoper != OPconst || rdinc.E2.Eoper != OPconst)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Ensure that the only defs reaching the increment elem (rdinc) */
|
/* Ensure that the only defs reaching the increment elem (rdinc) */
|
||||||
|
@ -841,12 +841,12 @@ private void intranges(ref Elemdatas rellist, ref Elemdatas inclist)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gather initial, increment, and final values for loop */
|
/* Gather initial, increment, and final values for loop */
|
||||||
initial = el_tolong(rdeq.EV.E2);
|
initial = el_tolong(rdeq.E2);
|
||||||
increment = el_tolong(rdinc.EV.E2);
|
increment = el_tolong(rdinc.E2);
|
||||||
if (incop == OPpostdec || incop == OPminass)
|
if (incop == OPpostdec || incop == OPminass)
|
||||||
increment = -increment;
|
increment = -increment;
|
||||||
relatop = rel.pelem.Eoper;
|
relatop = rel.pelem.Eoper;
|
||||||
final_ = el_tolong(rel.pelem.EV.E2);
|
final_ = el_tolong(rel.pelem.E2);
|
||||||
//printf("initial = %d, increment = %d, final_ = %d\n",initial,increment,final_);
|
//printf("initial = %d, increment = %d, final_ = %d\n",initial,increment,final_);
|
||||||
|
|
||||||
/* Determine if we can make the relational an unsigned */
|
/* Determine if we can make the relational an unsigned */
|
||||||
|
@ -872,9 +872,9 @@ private void intranges(ref Elemdatas rellist, ref Elemdatas inclist)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
makeuns:
|
makeuns:
|
||||||
if (!tyuns(rel.pelem.EV.E2.Ety))
|
if (!tyuns(rel.pelem.E2.Ety))
|
||||||
{
|
{
|
||||||
rel.pelem.EV.E2.Ety = touns(rel.pelem.EV.E2.Ety);
|
rel.pelem.E2.Ety = touns(rel.pelem.E2.Ety);
|
||||||
rel.pelem.Nflags |= NFLtouns;
|
rel.pelem.Nflags |= NFLtouns;
|
||||||
|
|
||||||
debug
|
debug
|
||||||
|
@ -893,12 +893,12 @@ private void intranges(ref Elemdatas rellist, ref Elemdatas inclist)
|
||||||
rb.BC == BCiftrue &&
|
rb.BC == BCiftrue &&
|
||||||
list_block(rb.Bsucc) == rb &&
|
list_block(rb.Bsucc) == rb &&
|
||||||
rb.Belem.Eoper == OPcomma &&
|
rb.Belem.Eoper == OPcomma &&
|
||||||
rb.Belem.EV.E1 == rdinc &&
|
rb.Belem.E1 == rdinc &&
|
||||||
rb.Belem.EV.E2 == rel.pelem
|
rb.Belem.E2 == rel.pelem
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rel.pelem.Eoper = OPeq;
|
rel.pelem.Eoper = OPeq;
|
||||||
rel.pelem.Ety = rel.pelem.EV.E1.Ety;
|
rel.pelem.Ety = rel.pelem.E1.Ety;
|
||||||
rb.BC = BCgoto;
|
rb.BC = BCgoto;
|
||||||
list_subtract(&rb.Bsucc,rb);
|
list_subtract(&rb.Bsucc,rb);
|
||||||
list_subtract(&rb.Bpred,rb);
|
list_subtract(&rb.Bpred,rb);
|
||||||
|
@ -946,8 +946,8 @@ public bool findloopparameters(elem* erel, ref elem* rdeq, ref elem* rdinc)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(erel.EV.E1.Eoper == OPvar);
|
assert(erel.E1.Eoper == OPvar);
|
||||||
Symbol* v = erel.EV.E1.EV.Vsym;
|
Symbol* v = erel.E1.Vsym;
|
||||||
|
|
||||||
// RD info is only reliable for registers and autos
|
// RD info is only reliable for registers and autos
|
||||||
if (!(sytab[v.Sclass] & SCRD))
|
if (!(sytab[v.Sclass] & SCRD))
|
||||||
|
@ -1021,14 +1021,14 @@ public bool findloopparameters(elem* erel, ref elem* rdeq, ref elem* rdinc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// lvalues should be unambiguous defs
|
// lvalues should be unambiguous defs
|
||||||
if (rdeq.Eoper != OPeq || rdeq.EV.E1.Eoper != OPvar || rdinc.EV.E1.Eoper != OPvar)
|
if (rdeq.Eoper != OPeq || rdeq.E1.Eoper != OPvar || rdinc.E1.Eoper != OPvar)
|
||||||
{
|
{
|
||||||
if (log) printf("\tnot OPvar\n");
|
if (log) printf("\tnot OPvar\n");
|
||||||
return returnResult(false);
|
return returnResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rvalues should be constants
|
// rvalues should be constants
|
||||||
if (rdeq.EV.E2.Eoper != OPconst || rdinc.EV.E2.Eoper != OPconst)
|
if (rdeq.E2.Eoper != OPconst || rdinc.E2.Eoper != OPconst)
|
||||||
{
|
{
|
||||||
if (log) printf("\tnot OPconst\n");
|
if (log) printf("\tnot OPconst\n");
|
||||||
return returnResult(false);
|
return returnResult(false);
|
||||||
|
@ -1163,26 +1163,26 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
if (op == OPcolon || op == OPcolon2)
|
if (op == OPcolon || op == OPcolon2)
|
||||||
{
|
{
|
||||||
vec_t L = vec_clone(IN);
|
vec_t L = vec_clone(IN);
|
||||||
cpwalk(n.EV.E1,L);
|
cpwalk(n.E1,L);
|
||||||
cpwalk(n.EV.E2,IN);
|
cpwalk(n.E2,IN);
|
||||||
vec_andass(IN,L); // IN = L & R
|
vec_andass(IN,L); // IN = L & R
|
||||||
vec_free(L);
|
vec_free(L);
|
||||||
}
|
}
|
||||||
else if (op == OPandand || op == OPoror)
|
else if (op == OPandand || op == OPoror)
|
||||||
{
|
{
|
||||||
cpwalk(n.EV.E1,IN);
|
cpwalk(n.E1,IN);
|
||||||
vec_t L = vec_clone(IN);
|
vec_t L = vec_clone(IN);
|
||||||
cpwalk(n.EV.E2,L);
|
cpwalk(n.E2,L);
|
||||||
vec_andass(IN,L); // IN = L & R
|
vec_andass(IN,L); // IN = L & R
|
||||||
vec_free(L);
|
vec_free(L);
|
||||||
}
|
}
|
||||||
else if (OTunary(op))
|
else if (OTunary(op))
|
||||||
{
|
{
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (OTassign(op))
|
if (OTassign(op))
|
||||||
{
|
{
|
||||||
if (t.Eoper == OPind)
|
if (t.Eoper == OPind)
|
||||||
cpwalk(t.EV.E1,IN);
|
cpwalk(t.E1,IN);
|
||||||
}
|
}
|
||||||
else if (op == OPctor || op == OPdtor)
|
else if (op == OPctor || op == OPdtor)
|
||||||
{
|
{
|
||||||
|
@ -1201,8 +1201,8 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
}
|
}
|
||||||
else if (OTassign(op))
|
else if (OTassign(op))
|
||||||
{
|
{
|
||||||
cpwalk(n.EV.E2,IN);
|
cpwalk(n.E2,IN);
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
if (t.Eoper == OPind)
|
if (t.Eoper == OPind)
|
||||||
cpwalk(t,IN);
|
cpwalk(t,IN);
|
||||||
else
|
else
|
||||||
|
@ -1213,13 +1213,13 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
}
|
}
|
||||||
else if (ERTOL(n))
|
else if (ERTOL(n))
|
||||||
{
|
{
|
||||||
cpwalk(n.EV.E2,IN);
|
cpwalk(n.E2,IN);
|
||||||
cpwalk(n.EV.E1,IN);
|
cpwalk(n.E1,IN);
|
||||||
}
|
}
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
cpwalk(n.EV.E1,IN);
|
cpwalk(n.E1,IN);
|
||||||
cpwalk(n.EV.E2,IN);
|
cpwalk(n.E2,IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OTdef(op)) // if definition elem
|
if (OTdef(op)) // if definition elem
|
||||||
|
@ -1236,7 +1236,7 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
|
|
||||||
/* If this elem could kill the lvalue or the rvalue, */
|
/* If this elem could kill the lvalue or the rvalue, */
|
||||||
/* Clear bit in IN. */
|
/* Clear bit in IN. */
|
||||||
v = go.expnod[i].EV.E1.EV.Vsym;
|
v = go.expnod[i].E1.Vsym;
|
||||||
if (ambig)
|
if (ambig)
|
||||||
{
|
{
|
||||||
if (Symbol_isAffected(*v))
|
if (Symbol_isAffected(*v))
|
||||||
|
@ -1244,11 +1244,11 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (v == t.EV.Vsym)
|
if (v == t.Vsym)
|
||||||
goto clr;
|
goto clr;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = go.expnod[i].EV.E2.EV.Vsym;
|
v = go.expnod[i].E2.Vsym;
|
||||||
if (ambig)
|
if (ambig)
|
||||||
{
|
{
|
||||||
if (Symbol_isAffected(*v))
|
if (Symbol_isAffected(*v))
|
||||||
|
@ -1256,7 +1256,7 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (v == t.EV.Vsym)
|
if (v == t.Vsym)
|
||||||
goto clr;
|
goto clr;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -1267,13 +1267,13 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
|
|
||||||
/* If this is a copy elem in go.expnod[] */
|
/* If this is a copy elem in go.expnod[] */
|
||||||
/* Set bit in IN. */
|
/* Set bit in IN. */
|
||||||
if ((op == OPeq || op == OPstreq) && n.EV.E1.Eoper == OPvar &&
|
if ((op == OPeq || op == OPstreq) && n.E1.Eoper == OPvar &&
|
||||||
n.EV.E2.Eoper == OPvar && n.Eexp)
|
n.E2.Eoper == OPvar && n.Eexp)
|
||||||
vec_setbit(n.Eexp,IN);
|
vec_setbit(n.Eexp,IN);
|
||||||
}
|
}
|
||||||
else if (op == OPvar && !nocp) // if reference to variable v
|
else if (op == OPvar && !nocp) // if reference to variable v
|
||||||
{
|
{
|
||||||
Symbol *v = n.EV.Vsym;
|
Symbol *v = n.Vsym;
|
||||||
|
|
||||||
//printf("Checking copyprop for '%s', ty=x%x\n", v.Sident.ptr,n.Ety);
|
//printf("Checking copyprop for '%s', ty=x%x\n", v.Sident.ptr,n.Ety);
|
||||||
symbol_debug(v);
|
symbol_debug(v);
|
||||||
|
@ -1289,28 +1289,28 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
elem* c = go.expnod[i];
|
elem* c = go.expnod[i];
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
uint csz = tysize(c.EV.E1.Ety);
|
uint csz = tysize(c.E1.Ety);
|
||||||
if (c.Eoper == OPstreq)
|
if (c.Eoper == OPstreq)
|
||||||
csz = cast(uint)type_size(c.ET);
|
csz = cast(uint)type_size(c.ET);
|
||||||
assert(cast(int)csz >= 0);
|
assert(cast(int)csz >= 0);
|
||||||
|
|
||||||
//printf(" looking at: ("); WReqn(c); printf("), ty=x%x\n",c.EV.E1.Ety);
|
//printf(" looking at: ("); WReqn(c); printf("), ty=x%x\n",c.E1.Ety);
|
||||||
/* Not only must symbol numbers match, but */
|
/* Not only must symbol numbers match, but */
|
||||||
/* offsets too (in case of arrays) and sizes */
|
/* offsets too (in case of arrays) and sizes */
|
||||||
/* (in case of unions). */
|
/* (in case of unions). */
|
||||||
if (v == c.EV.E1.EV.Vsym &&
|
if (v == c.E1.Vsym &&
|
||||||
n.EV.Voffset >= c.EV.E1.EV.Voffset &&
|
n.Voffset >= c.E1.Voffset &&
|
||||||
n.EV.Voffset + sz <= c.EV.E1.EV.Voffset + csz)
|
n.Voffset + sz <= c.E1.Voffset + csz)
|
||||||
{
|
{
|
||||||
if (foundelem)
|
if (foundelem)
|
||||||
{
|
{
|
||||||
if (c.EV.E2.EV.Vsym != f)
|
if (c.E2.Vsym != f)
|
||||||
goto noprop;
|
goto noprop;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foundelem = c;
|
foundelem = c;
|
||||||
f = foundelem.EV.E2.EV.Vsym;
|
f = foundelem.E2.Vsym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1324,11 +1324,11 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
}
|
}
|
||||||
|
|
||||||
type *nt = n.ET;
|
type *nt = n.ET;
|
||||||
targ_size_t noffset = n.EV.Voffset;
|
targ_size_t noffset = n.Voffset;
|
||||||
el_copy(n,foundelem.EV.E2);
|
el_copy(n,foundelem.E2);
|
||||||
n.Ety = ty; // retain original type
|
n.Ety = ty; // retain original type
|
||||||
n.ET = nt;
|
n.ET = nt;
|
||||||
n.EV.Voffset += noffset - foundelem.EV.E1.EV.Voffset;
|
n.Voffset += noffset - foundelem.E1.Voffset;
|
||||||
|
|
||||||
/* original => rewrite
|
/* original => rewrite
|
||||||
* v = f
|
* v = f
|
||||||
|
@ -1340,7 +1340,7 @@ private bool copyPropWalk(elem *n,vec_t IN)
|
||||||
foreach (j; 1 .. go.exptop)
|
foreach (j; 1 .. go.exptop)
|
||||||
{
|
{
|
||||||
//printf("go.expnod[%d]: ", j); elem_print(go.expnod[j]);
|
//printf("go.expnod[%d]: ", j); elem_print(go.expnod[j]);
|
||||||
if (go.expnod[j].EV.E2 == n)
|
if (go.expnod[j].E2 == n)
|
||||||
{
|
{
|
||||||
recalc = true;
|
recalc = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1405,8 +1405,8 @@ public void rmdeadass()
|
||||||
elem *nv;
|
elem *nv;
|
||||||
|
|
||||||
n = assnod[j];
|
n = assnod[j];
|
||||||
nv = n.EV.E1;
|
nv = n.E1;
|
||||||
v = nv.EV.Vsym;
|
v = nv.Vsym;
|
||||||
if (!symbol_isintab(v)) // not considered
|
if (!symbol_isintab(v)) // not considered
|
||||||
continue;
|
continue;
|
||||||
//printf("assnod[%d]: ",j); WReqn(n); printf("\n");
|
//printf("assnod[%d]: ",j); WReqn(n); printf("\n");
|
||||||
|
@ -1425,10 +1425,10 @@ public void rmdeadass()
|
||||||
*/
|
*/
|
||||||
if (OTbinary(n.Eoper))
|
if (OTbinary(n.Eoper))
|
||||||
{
|
{
|
||||||
elem* e2 = n.EV.E2;
|
elem* e2 = n.E2;
|
||||||
if (e2.Eoper == OPvar &&
|
if (e2.Eoper == OPvar &&
|
||||||
config.fpxmmregs &&
|
config.fpxmmregs &&
|
||||||
!tyfloating(v.Stype.Tty) != !tyfloating(e2.EV.Vsym.Stype.Tty)
|
!tyfloating(v.Stype.Tty) != !tyfloating(e2.Vsym.Stype.Tty)
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1461,7 +1461,7 @@ public void elimass(elem *n)
|
||||||
switch (n.Eoper)
|
switch (n.Eoper)
|
||||||
{
|
{
|
||||||
case OPvecsto:
|
case OPvecsto:
|
||||||
n.EV.E2.Eoper = OPcomma;
|
n.E2.Eoper = OPcomma;
|
||||||
goto case OPeq;
|
goto case OPeq;
|
||||||
|
|
||||||
case OPeq:
|
case OPeq:
|
||||||
|
@ -1470,10 +1470,10 @@ public void elimass(elem *n)
|
||||||
/* Watch out for (a=b=c) stuff! */
|
/* Watch out for (a=b=c) stuff! */
|
||||||
/* Don't screw up assnod[]. */
|
/* Don't screw up assnod[]. */
|
||||||
n.Eoper = OPcomma;
|
n.Eoper = OPcomma;
|
||||||
n.Ety |= n.EV.E2.Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared
|
n.Ety |= n.E2.Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared
|
||||||
| mTYfar
|
| mTYfar
|
||||||
);
|
);
|
||||||
n.EV.E1.Eoper = OPconst;
|
n.E1.Eoper = OPconst;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Convert (V op= e) to (V op e) */
|
/* Convert (V op= e) to (V op e) */
|
||||||
|
@ -1493,8 +1493,8 @@ public void elimass(elem *n)
|
||||||
|
|
||||||
case OPpostinc: /* (V i++ c) => V */
|
case OPpostinc: /* (V i++ c) => V */
|
||||||
case OPpostdec: /* (V i-- c) => V */
|
case OPpostdec: /* (V i-- c) => V */
|
||||||
e1 = n.EV.E1;
|
e1 = n.E1;
|
||||||
el_free(n.EV.E2);
|
el_free(n.E2);
|
||||||
el_copy(n,e1);
|
el_copy(n,e1);
|
||||||
el_free(e1);
|
el_free(e1);
|
||||||
break;
|
break;
|
||||||
|
@ -1511,7 +1511,7 @@ public void elimass(elem *n)
|
||||||
|
|
||||||
case OPcmpxchg:
|
case OPcmpxchg:
|
||||||
n.Eoper = OPcomma;
|
n.Eoper = OPcomma;
|
||||||
n.EV.E2.Eoper = OPcomma;
|
n.E2.Eoper = OPcomma;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1529,14 +1529,14 @@ public void elimass(elem *n)
|
||||||
private uint numasg(elem *e)
|
private uint numasg(elem *e)
|
||||||
{
|
{
|
||||||
assert(e);
|
assert(e);
|
||||||
if (OTassign(e.Eoper) && e.EV.E1.Eoper == OPvar)
|
if (OTassign(e.Eoper) && e.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
e.Nflags |= NFLassign;
|
e.Nflags |= NFLassign;
|
||||||
return 1 + numasg(e.EV.E1) + (OTbinary(e.Eoper) ? numasg(e.EV.E2) : 0);
|
return 1 + numasg(e.E1) + (OTbinary(e.Eoper) ? numasg(e.E2) : 0);
|
||||||
}
|
}
|
||||||
e.Nflags &= ~NFLassign;
|
e.Nflags &= ~NFLassign;
|
||||||
return OTunary(e.Eoper) ? numasg(e.EV.E1) :
|
return OTunary(e.Eoper) ? numasg(e.E1) :
|
||||||
OTbinary(e.Eoper) ? numasg(e.EV.E1) + numasg(e.EV.E2) : 0;
|
OTbinary(e.Eoper) ? numasg(e.E1) + numasg(e.E2) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************
|
/******************************
|
||||||
|
@ -1567,8 +1567,8 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
vec_t Pr = vec_clone(POSS);
|
vec_t Pr = vec_clone(POSS);
|
||||||
vec_t Dl = vec_calloc(vec_numbits(POSS));
|
vec_t Dl = vec_calloc(vec_numbits(POSS));
|
||||||
vec_t Dr = vec_calloc(vec_numbits(POSS));
|
vec_t Dr = vec_calloc(vec_numbits(POSS));
|
||||||
accumda(n.EV.E1,Dl,Pl);
|
accumda(n.E1,Dl,Pl);
|
||||||
accumda(n.EV.E2,Dr,Pr);
|
accumda(n.E2,Dr,Pr);
|
||||||
|
|
||||||
/* D |= P & (Dl & Dr) | ~P & (Dl | Dr) */
|
/* D |= P & (Dl & Dr) | ~P & (Dl | Dr) */
|
||||||
/* P = P & (Pl & Pr) | ~P & (Pl | Pr) */
|
/* P = P & (Pl & Pr) | ~P & (Pl | Pr) */
|
||||||
|
@ -1587,13 +1587,13 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
case OPandand:
|
case OPandand:
|
||||||
case OPoror:
|
case OPoror:
|
||||||
{
|
{
|
||||||
accumda(n.EV.E1,DEAD,POSS);
|
accumda(n.E1,DEAD,POSS);
|
||||||
// Substituting into the above equations Pl=P and Dl=0:
|
// Substituting into the above equations Pl=P and Dl=0:
|
||||||
// D |= Dr - P
|
// D |= Dr - P
|
||||||
// P = Pr
|
// P = Pr
|
||||||
vec_t Pr = vec_clone(POSS);
|
vec_t Pr = vec_clone(POSS);
|
||||||
vec_t Dr = vec_calloc(vec_numbits(POSS));
|
vec_t Dr = vec_calloc(vec_numbits(POSS));
|
||||||
accumda(n.EV.E2,Dr,Pr);
|
accumda(n.E2,Dr,Pr);
|
||||||
vec_subass(Dr,POSS);
|
vec_subass(Dr,POSS);
|
||||||
vec_orass(DEAD,Dr);
|
vec_orass(DEAD,Dr);
|
||||||
vec_copy(POSS,Pr);
|
vec_copy(POSS,Pr);
|
||||||
|
@ -1603,8 +1603,8 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
|
|
||||||
case OPvar:
|
case OPvar:
|
||||||
{
|
{
|
||||||
Symbol *v = n.EV.Vsym;
|
Symbol *v = n.Vsym;
|
||||||
targ_size_t voff = n.EV.Voffset;
|
targ_size_t voff = n.Voffset;
|
||||||
uint vsize = tysize(n.Ety);
|
uint vsize = tysize(n.Ety);
|
||||||
|
|
||||||
// We have a reference. Clear all bits in POSS that
|
// We have a reference. Clear all bits in POSS that
|
||||||
|
@ -1612,12 +1612,12 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
|
|
||||||
foreach (const i; 0 .. assnod.length)
|
foreach (const i; 0 .. assnod.length)
|
||||||
{
|
{
|
||||||
elem *ti = assnod[i].EV.E1;
|
elem *ti = assnod[i].E1;
|
||||||
if (v == ti.EV.Vsym &&
|
if (v == ti.Vsym &&
|
||||||
((vsize == -1 || tysize(ti.Ety) == -1) ||
|
((vsize == -1 || tysize(ti.Ety) == -1) ||
|
||||||
// If symbol references overlap
|
// If symbol references overlap
|
||||||
(voff + vsize > ti.EV.Voffset &&
|
(voff + vsize > ti.Voffset &&
|
||||||
ti.EV.Voffset + tysize(ti.Ety) > voff)
|
ti.Voffset + tysize(ti.Ety) > voff)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -1633,8 +1633,8 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPbt:
|
case OPbt:
|
||||||
accumda(n.EV.E1,DEAD,POSS);
|
accumda(n.E1,DEAD,POSS);
|
||||||
accumda(n.EV.E2,DEAD,POSS);
|
accumda(n.E2,DEAD,POSS);
|
||||||
vec_subass(POSS,ambigref); // remove possibly refed
|
vec_subass(POSS,ambigref); // remove possibly refed
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1642,7 +1642,7 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
case OPucall:
|
case OPucall:
|
||||||
case OPucallns:
|
case OPucallns:
|
||||||
case OPvp_fp:
|
case OPvp_fp:
|
||||||
accumda(n.EV.E1,DEAD,POSS);
|
accumda(n.E1,DEAD,POSS);
|
||||||
vec_subass(POSS,ambigref); // remove possibly refed
|
vec_subass(POSS,ambigref); // remove possibly refed
|
||||||
// assignments from list
|
// assignments from list
|
||||||
// of possibly dead ones
|
// of possibly dead ones
|
||||||
|
@ -1656,11 +1656,11 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
case OPmemcpy:
|
case OPmemcpy:
|
||||||
case OPstrcpy:
|
case OPstrcpy:
|
||||||
case OPmemset:
|
case OPmemset:
|
||||||
accumda(n.EV.E2,DEAD,POSS);
|
accumda(n.E2,DEAD,POSS);
|
||||||
goto case OPstrlen;
|
goto case OPstrlen;
|
||||||
|
|
||||||
case OPstrlen:
|
case OPstrlen:
|
||||||
accumda(n.EV.E1,DEAD,POSS);
|
accumda(n.E1,DEAD,POSS);
|
||||||
vec_subass(POSS,ambigref); // remove possibly refed
|
vec_subass(POSS,ambigref); // remove possibly refed
|
||||||
// assignments from list
|
// assignments from list
|
||||||
// of possibly dead ones
|
// of possibly dead ones
|
||||||
|
@ -1669,8 +1669,8 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
case OPstrcat:
|
case OPstrcat:
|
||||||
case OPstrcmp:
|
case OPstrcmp:
|
||||||
case OPmemcmp:
|
case OPmemcmp:
|
||||||
accumda(n.EV.E1,DEAD,POSS);
|
accumda(n.E1,DEAD,POSS);
|
||||||
accumda(n.EV.E2,DEAD,POSS);
|
accumda(n.E2,DEAD,POSS);
|
||||||
vec_subass(POSS,ambigref); // remove possibly refed
|
vec_subass(POSS,ambigref); // remove possibly refed
|
||||||
// assignments from list
|
// assignments from list
|
||||||
// of possibly dead ones
|
// of possibly dead ones
|
||||||
|
@ -1682,20 +1682,20 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
elem *t;
|
elem *t;
|
||||||
|
|
||||||
if (ERTOL(n))
|
if (ERTOL(n))
|
||||||
accumda(n.EV.E2,DEAD,POSS);
|
accumda(n.E2,DEAD,POSS);
|
||||||
t = n.EV.E1;
|
t = n.E1;
|
||||||
// if not (v = expression) then gen refs of left tree
|
// if not (v = expression) then gen refs of left tree
|
||||||
if (op != OPeq && op != OPstreq)
|
if (op != OPeq && op != OPstreq)
|
||||||
accumda(n.EV.E1,DEAD,POSS);
|
accumda(n.E1,DEAD,POSS);
|
||||||
else if (OTunary(t.Eoper)) // if (*e = expression)
|
else if (OTunary(t.Eoper)) // if (*e = expression)
|
||||||
accumda(t.EV.E1,DEAD,POSS);
|
accumda(t.E1,DEAD,POSS);
|
||||||
else if (OTbinary(t.Eoper))
|
else if (OTbinary(t.Eoper))
|
||||||
{
|
{
|
||||||
accumda(t.EV.E1,DEAD,POSS);
|
accumda(t.E1,DEAD,POSS);
|
||||||
accumda(t.EV.E2,DEAD,POSS);
|
accumda(t.E2,DEAD,POSS);
|
||||||
}
|
}
|
||||||
if (!ERTOL(n) && op != OPnegass)
|
if (!ERTOL(n) && op != OPnegass)
|
||||||
accumda(n.EV.E2,DEAD,POSS);
|
accumda(n.E2,DEAD,POSS);
|
||||||
|
|
||||||
// if unambiguous assignment, post all possibilities
|
// if unambiguous assignment, post all possibilities
|
||||||
// to DEAD
|
// to DEAD
|
||||||
|
@ -1706,7 +1706,7 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
tsz = cast(uint)type_size(n.ET);
|
tsz = cast(uint)type_size(n.ET);
|
||||||
foreach (const i; 0 .. assnod.length)
|
foreach (const i; 0 .. assnod.length)
|
||||||
{
|
{
|
||||||
elem *ti = assnod[i].EV.E1;
|
elem *ti = assnod[i].E1;
|
||||||
|
|
||||||
uint tisz = tysize(ti.Ety);
|
uint tisz = tysize(ti.Ety);
|
||||||
if (assnod[i].Eoper == OPstreq)
|
if (assnod[i].Eoper == OPstreq)
|
||||||
|
@ -1714,11 +1714,11 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
|
|
||||||
// There may be some problem with this next
|
// There may be some problem with this next
|
||||||
// statement with unions.
|
// statement with unions.
|
||||||
if (ti.EV.Vsym == t.EV.Vsym &&
|
if (ti.Vsym == t.Vsym &&
|
||||||
ti.EV.Voffset == t.EV.Voffset &&
|
ti.Voffset == t.Voffset &&
|
||||||
tisz == tsz &&
|
tisz == tsz &&
|
||||||
!(t.Ety & (mTYvolatile | mTYshared)) &&
|
!(t.Ety & (mTYvolatile | mTYshared)) &&
|
||||||
//t.EV.Vsym.Sflags & SFLunambig &&
|
//t.Vsym.Sflags & SFLunambig &&
|
||||||
vec_testbit(i,POSS))
|
vec_testbit(i,POSS))
|
||||||
{
|
{
|
||||||
vec_setbit(i,DEAD);
|
vec_setbit(i,DEAD);
|
||||||
|
@ -1735,7 +1735,7 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
// if variable could be referenced by a pointer
|
// if variable could be referenced by a pointer
|
||||||
// or a function call, mark the assignment in
|
// or a function call, mark the assignment in
|
||||||
// ambigref
|
// ambigref
|
||||||
if (!(t.EV.Vsym.Sflags & SFLunambig))
|
if (!(t.Vsym.Sflags & SFLunambig))
|
||||||
{
|
{
|
||||||
vec_setbit(i,ambigref);
|
vec_setbit(i,ambigref);
|
||||||
|
|
||||||
|
@ -1752,20 +1752,20 @@ private void accumda(elem *n,vec_t DEAD, vec_t POSS)
|
||||||
}
|
}
|
||||||
else if (OTrtol(op))
|
else if (OTrtol(op))
|
||||||
{
|
{
|
||||||
accumda(n.EV.E2,DEAD,POSS);
|
accumda(n.E2,DEAD,POSS);
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
goto LtailRecurse; // accumda(n.EV.E1,DEAD,POSS);
|
goto LtailRecurse; // accumda(n.E1,DEAD,POSS);
|
||||||
}
|
}
|
||||||
else if (OTbinary(op))
|
else if (OTbinary(op))
|
||||||
{
|
{
|
||||||
accumda(n.EV.E1,DEAD,POSS);
|
accumda(n.E1,DEAD,POSS);
|
||||||
n = n.EV.E2;
|
n = n.E2;
|
||||||
goto LtailRecurse; // accumda(n.EV.E2,DEAD,POSS);
|
goto LtailRecurse; // accumda(n.E2,DEAD,POSS);
|
||||||
}
|
}
|
||||||
else if (OTunary(op))
|
else if (OTunary(op))
|
||||||
{
|
{
|
||||||
n = n.EV.E1;
|
n = n.E1;
|
||||||
goto LtailRecurse; // accumda(n.EV.E1,DEAD,POSS);
|
goto LtailRecurse; // accumda(n.E1,DEAD,POSS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1842,12 +1842,12 @@ public void deadvar()
|
||||||
@trusted
|
@trusted
|
||||||
private void dvwalk(elem *n,uint i)
|
private void dvwalk(elem *n,uint i)
|
||||||
{
|
{
|
||||||
for (; true; n = n.EV.E1)
|
for (; true; n = n.E1)
|
||||||
{
|
{
|
||||||
assert(n);
|
assert(n);
|
||||||
if (n.Eoper == OPvar || n.Eoper == OPrelconst)
|
if (n.Eoper == OPvar || n.Eoper == OPrelconst)
|
||||||
{
|
{
|
||||||
Symbol *s = n.EV.Vsym;
|
Symbol *s = n.Vsym;
|
||||||
|
|
||||||
s.Sflags &= ~SFLdead;
|
s.Sflags &= ~SFLdead;
|
||||||
if (s.Srange)
|
if (s.Srange)
|
||||||
|
@ -1856,7 +1856,7 @@ private void dvwalk(elem *n,uint i)
|
||||||
else if (!OTleaf(n.Eoper))
|
else if (!OTleaf(n.Eoper))
|
||||||
{
|
{
|
||||||
if (OTbinary(n.Eoper))
|
if (OTbinary(n.Eoper))
|
||||||
dvwalk(n.EV.E2,i);
|
dvwalk(n.E2,i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -68,7 +68,7 @@ extern (D) private void sliceStructs_Gather(ref const symtab_t symtab, SymInfo[]
|
||||||
{
|
{
|
||||||
case OPvar:
|
case OPvar:
|
||||||
{
|
{
|
||||||
const si = e.EV.Vsym.Ssymnum;
|
const si = e.Vsym.Ssymnum;
|
||||||
if (si != SYMIDX.max && sia[si].canSlice)
|
if (si != SYMIDX.max && sia[si].canSlice)
|
||||||
{
|
{
|
||||||
assert(si < symtab.length);
|
assert(si < symtab.length);
|
||||||
|
@ -88,7 +88,7 @@ extern (D) private void sliceStructs_Gather(ref const symtab_t symtab, SymInfo[]
|
||||||
foreach (ref ty; sia[si].ty)
|
foreach (ref ty; sia[si].ty)
|
||||||
ty = TYnptr;
|
ty = TYnptr;
|
||||||
|
|
||||||
const s = e.EV.Vsym;
|
const s = e.Vsym;
|
||||||
const t = s.Stype;
|
const t = s.Stype;
|
||||||
if (tybasic(t.Tty) == TYstruct)
|
if (tybasic(t.Tty) == TYstruct)
|
||||||
{
|
{
|
||||||
|
@ -169,13 +169,13 @@ extern (D) private void sliceStructs_Gather(ref const symtab_t symtab, SymInfo[]
|
||||||
if (OTassign(e.Eoper))
|
if (OTassign(e.Eoper))
|
||||||
{
|
{
|
||||||
if (OTbinary(e.Eoper))
|
if (OTbinary(e.Eoper))
|
||||||
sliceStructs_Gather(symtab, sia, e.EV.E2);
|
sliceStructs_Gather(symtab, sia, e.E2);
|
||||||
|
|
||||||
// Assignment to a whole var will disallow SROA
|
// Assignment to a whole var will disallow SROA
|
||||||
if (e.EV.E1.Eoper == OPvar)
|
if (e.E1.Eoper == OPvar)
|
||||||
{
|
{
|
||||||
const e1 = e.EV.E1;
|
const e1 = e.E1;
|
||||||
const si = e1.EV.Vsym.Ssymnum;
|
const si = e1.Vsym.Ssymnum;
|
||||||
if (si != SYMIDX.max && sia[si].canSlice)
|
if (si != SYMIDX.max && sia[si].canSlice)
|
||||||
{
|
{
|
||||||
assert(si < symtab.length);
|
assert(si < symtab.length);
|
||||||
|
@ -193,23 +193,23 @@ extern (D) private void sliceStructs_Gather(ref const symtab_t symtab, SymInfo[]
|
||||||
// https://github.com/dlang/dmd/pull/8034
|
// https://github.com/dlang/dmd/pull/8034
|
||||||
else if (!(config.exe & EX_OSX))
|
else if (!(config.exe & EX_OSX))
|
||||||
{
|
{
|
||||||
sliceStructs_Gather(symtab, sia, e.EV.E1);
|
sliceStructs_Gather(symtab, sia, e.E1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (OTunary(e.Eoper))
|
if (OTunary(e.Eoper))
|
||||||
{
|
{
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (OTbinary(e.Eoper))
|
if (OTbinary(e.Eoper))
|
||||||
{
|
{
|
||||||
sliceStructs_Gather(symtab, sia, e.EV.E2);
|
sliceStructs_Gather(symtab, sia, e.E2);
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -233,7 +233,7 @@ extern (D) private void sliceStructs_Replace(ref symtab_t symtab, const SymInfo[
|
||||||
{
|
{
|
||||||
case OPvar:
|
case OPvar:
|
||||||
{
|
{
|
||||||
Symbol *s = e.EV.Vsym;
|
Symbol *s = e.Vsym;
|
||||||
const si = s.Ssymnum;
|
const si = s.Ssymnum;
|
||||||
//printf("e: %d %d\n", si, sia[si].canSlice);
|
//printf("e: %d %d\n", si, sia[si].canSlice);
|
||||||
//elem_print(e);
|
//elem_print(e);
|
||||||
|
@ -252,12 +252,12 @@ extern (D) private void sliceStructs_Replace(ref symtab_t symtab, const SymInfo[
|
||||||
el_copy(e2, e);
|
el_copy(e2, e);
|
||||||
Symbol *s1 = symtab[sia[si].si0 + 1]; // +1 for second slice
|
Symbol *s1 = symtab[sia[si].si0 + 1]; // +1 for second slice
|
||||||
e2.Ety = sia[si].ty[1];
|
e2.Ety = sia[si].ty[1];
|
||||||
e2.EV.Vsym = s1;
|
e2.Vsym = s1;
|
||||||
e2.EV.Voffset = 0;
|
e2.Voffset = 0;
|
||||||
|
|
||||||
e.Eoper = OPpair;
|
e.Eoper = OPpair;
|
||||||
e.EV.E1 = e1;
|
e.E1 = e1;
|
||||||
e.EV.E2 = e2;
|
e.E2 = e2;
|
||||||
|
|
||||||
if (tycomplex(e.Ety))
|
if (tycomplex(e.Ety))
|
||||||
{
|
{
|
||||||
|
@ -288,8 +288,8 @@ extern (D) private void sliceStructs_Replace(ref symtab_t symtab, const SymInfo[
|
||||||
else // the nth slice
|
else // the nth slice
|
||||||
{
|
{
|
||||||
if (log) { printf("slicing slice %d ", n); elem_print(e); }
|
if (log) { printf("slicing slice %d ", n); elem_print(e); }
|
||||||
e.EV.Vsym = symtab[sia[si].si0 + n];
|
e.Vsym = symtab[sia[si].si0 + n];
|
||||||
e.EV.Voffset -= n * SLICESIZE;
|
e.Voffset -= n * SLICESIZE;
|
||||||
//printf("replaced with:\n");
|
//printf("replaced with:\n");
|
||||||
//elem_print(e);
|
//elem_print(e);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ extern (D) private void sliceStructs_Replace(ref symtab_t symtab, const SymInfo[
|
||||||
|
|
||||||
case OPrelconst:
|
case OPrelconst:
|
||||||
{
|
{
|
||||||
Symbol *s = e.EV.Vsym;
|
Symbol *s = e.Vsym;
|
||||||
const si = s.Ssymnum;
|
const si = s.Ssymnum;
|
||||||
//printf("e: %d %d\n", si, sia[si].canSlice);
|
//printf("e: %d %d\n", si, sia[si].canSlice);
|
||||||
//elem_print(e);
|
//elem_print(e);
|
||||||
|
@ -314,13 +314,13 @@ extern (D) private void sliceStructs_Replace(ref symtab_t symtab, const SymInfo[
|
||||||
default:
|
default:
|
||||||
if (OTunary(e.Eoper))
|
if (OTunary(e.Eoper))
|
||||||
{
|
{
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (OTbinary(e.Eoper))
|
if (OTbinary(e.Eoper))
|
||||||
{
|
{
|
||||||
sliceStructs_Replace(symtab, sia, e.EV.E2);
|
sliceStructs_Replace(symtab, sia, e.E2);
|
||||||
e = e.EV.E1;
|
e = e.E1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -537,7 +537,7 @@ int nthSlice(const(elem)* e)
|
||||||
|
|
||||||
/* See if e fits in a slice
|
/* See if e fits in a slice
|
||||||
*/
|
*/
|
||||||
const lwr = e.EV.Voffset;
|
const lwr = e.Voffset;
|
||||||
const upr = lwr + sz;
|
const upr = lwr + sz;
|
||||||
if (0 <= lwr && upr <= sliceSize)
|
if (0 <= lwr && upr <= sliceSize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue