Skip to content

Commit

Permalink
Merge pull request #8074 from WalterBright/fix16189
Browse files Browse the repository at this point in the history
fix Issue 16189 - Optimizer bug, with simple test case
  • Loading branch information
wilzbach authored Mar 26, 2018
2 parents 9e8518c + 27dd837 commit 88a963a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 32 deletions.
64 changes: 32 additions & 32 deletions src/dmd/backend/gloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -2766,38 +2766,31 @@ STATIC bool funcprev(Iv *biv,famlist *fl)
*/

STATIC void elimbasivs(loop *l)
{ famlist *fl;
unsigned i;
tym_t ty;
elem **pref,*fofe,*C2;
symbol *X;
int refcount;

cmes2("elimbasivs(%p)\n",l);
for (Iv *biv = l->Livlist; biv; biv = biv->IVnext) // for each basic IV
{

{
cmes2("elimbasivs(%p)\n",l);
for (Iv *biv = l->Livlist; biv; biv = biv->IVnext) // for each basic IV
{
/* Can't eliminate this basic IV if we have a goal for the */
/* increment elem. */
// Be careful about Nflags being in a union...
if (!((*biv->IVincr)->Nflags & NFLnogoal))
elem* einc = *biv->IVincr;
if (!(einc->Nflags & NFLnogoal))
continue;

X = biv->IVbasic;
Symbol* X = biv->IVbasic;
assert(symbol_isintab(X));
ty = X->ty();
pref = onlyref(X,l,*biv->IVincr,&refcount);
tym_t ty = X->ty();
int refcount;
elem** pref = onlyref(X,l,einc,&refcount);

/* if only ref of X is of the form (X) or (X relop e) or (e relop X) */
if (pref != NULL && refcount <= 1)
{ elem *ref;
tym_t flty;

fl = biv->IVfamily;
{
famlist* fl = biv->IVfamily;
if (!fl) // if no elems in family of biv
continue;

ref = *pref;
elem* ref = *pref;

/* Replace (X) with (X != 0) */
if (ref->Eoper == OPvar)
Expand All @@ -2809,7 +2802,7 @@ STATIC void elimbasivs(loop *l)

// Don't do the replacement if we would replace a
// signed comparison with an unsigned one
flty = fl->FLty;
tym_t flty = fl->FLty;
if (tyuns(ref->E1->Ety) | tyuns(ref->E2->Ety))
flty = touns(flty);

Expand All @@ -2820,9 +2813,8 @@ STATIC void elimbasivs(loop *l)

/* if we have (e relop X), replace it with (X relop e) */
if (ref->E2->Eoper == OPvar && ref->E2->EV.sp.Vsym == X)
{ elem *tmp;

tmp = ref->E2;
{
elem* tmp = ref->E2;
ref->E2 = ref->E1;
ref->E1 = tmp;
ref->Eoper = swaprel(ref->Eoper);
Expand All @@ -2832,11 +2824,8 @@ STATIC void elimbasivs(loop *l)
// then we can't do it
if (fl->c1->Eoper == OPconst)
{
targ_llong c1;
int sz;

c1 = el_tolong(fl->c1);
sz = tysize(ty);
targ_llong c1 = el_tolong(fl->c1);
const int sz = tysize(ty);
if (sz == SHORTSIZE &&
((ref->E2->Eoper == OPconst &&
c1 * el_tolong(ref->E2) & ~0x7FFFL) ||
Expand All @@ -2858,6 +2847,15 @@ STATIC void elimbasivs(loop *l)
continue;
}

/* If the incr is a decrement, and the relational is < or <=,
* and its unsigned, then don't do it because it could drop below 0.
* https://issues.dlang.org/show_bug.cgi?id=16189
*/
if ((einc->Eoper == OPminass || einc->E2->Eoper == OPconst && el_tolong(einc->E2) < 0) &&
(ref->Eoper == OPlt || ref->Eoper == OPle) &&
(tyuns(ref->E1->Ety) | tyuns(ref->E2->Ety)))
continue;

/* If loop started out with a signed conditional that was
* replaced with an unsigned one, don't do it if c2
* is less than 0.
Expand Down Expand Up @@ -2889,8 +2887,8 @@ STATIC void elimbasivs(loop *l)
refE2 = el_una(OP32_16,flty,refE2);

/* replace e with e*c1 + c2 */
C2 = el_copytree(fl->c2);
fofe = el_bin(OPadd,flty,
elem* C2 = el_copytree(fl->c2);
elem* fofe = el_bin(OPadd,flty,
el_bin(OPmul,refE2->Ety,
refE2,
el_copytree(fl->c1)),
Expand Down Expand Up @@ -2922,7 +2920,7 @@ STATIC void elimbasivs(loop *l)
ref->E2 = refE2;
ref->Eoper = refEoper;

elimass(*biv->IVincr); // dump the increment elem
elimass(einc); // dump the increment elem

// replace X with T
assert(ref->E1->EV.sp.Voffset == 0);
Expand Down Expand Up @@ -2973,6 +2971,7 @@ STATIC void elimbasivs(loop *l)
/* if X is live on entry to any successor S outside loop */
/* prepend elem X=(T-c2)/c1 to S.Belem */

unsigned i;
foreach (i,dfotop,l->Lexit) /* for each exit block */
{ elem *ne;
block *b;
Expand Down Expand Up @@ -3050,6 +3049,7 @@ STATIC void elimbasivs(loop *l)
}
else if (refcount == 0) /* if no uses of IV in loop */
{ /* Eliminate the basic IV if it is not live on any successor */
unsigned i;
foreach (i,dfotop,l->Lexit) /* for each exit block */
{
for (list_t bl = dfo[i]->Bsucc; bl; bl = list_next(bl))
Expand Down
18 changes: 18 additions & 0 deletions test/runnable/mars1.d
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,23 @@ void testdivcmp()
assert(foo(5, 4));
}

////////////////////////////////////////////////////////////////////////

// https://issues.dlang.org/show_bug.cgi?id=16189

void test16189()
{
ubyte[9][1] data;
uint a = 0;
loop:
data[0] = data[a];
a--;
bool b = false;
if (b) goto loop;
assert(a == -1); // was failing with -O
}


////////////////////////////////////////////////////////////////////////

// https://issues.dlang.org/show_bug.cgi?id=16997
Expand Down Expand Up @@ -1809,6 +1826,7 @@ int main()
test6();
testeqeqranges();
testdivcmp();
test16189();
test16997();
test18315();
test18461();
Expand Down

0 comments on commit 88a963a

Please sign in to comment.