Skip to content

Commit 331ee99

Browse files
committed
fix Issue 22372 - Loop index incorrectly optimised out for -release -O
1 parent f223e95 commit 331ee99

1 file changed

Lines changed: 41 additions & 3 deletions

File tree

dm/src/dmc/gloop.d

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/**
2+
* Global loop optimizations
3+
*
24
* Compiler implementation of the
35
* $(LINK2 http://www.dlang.org, D programming language).
46
*
@@ -10,7 +12,6 @@
1012
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/gloop.d
1113
*/
1214

13-
1415
module dmd.backend.gloop;
1516

1617
version (SCPP)
@@ -76,6 +77,7 @@ nothrow:
7677
/*************************
7778
* Reset memory so this allocation can be re-used.
7879
*/
80+
@trusted
7981
void reset()
8082
{
8183
vec_free(Lloop);
@@ -149,7 +151,7 @@ nothrow:
149151
}
150152
}
151153

152-
@trusted
154+
@system
153155
enum FLELIM = cast(Symbol *)-1;
154156

155157
struct Iv
@@ -159,6 +161,7 @@ nothrow:
159161
elem **IVincr; // pointer to parent of IV increment elem
160162
Barray!famlist IVfamily; // variables in this family
161163

164+
@trusted
162165
void reset()
163166
{
164167
foreach (ref fl; IVfamily)
@@ -2843,6 +2846,9 @@ private void elimbasivs(ref loop l)
28432846
if (!biv.IVfamily.length)
28442847
continue;
28452848

2849+
if (catchRef(X, l))
2850+
continue;
2851+
28462852
elem* ref_ = *pref;
28472853

28482854
/* Replace (X) with (X != 0) */
@@ -3135,7 +3141,6 @@ private void elimbasivs(ref loop l)
31353141
} /* for */
31363142
}
31373143

3138-
31393144
/***********************
31403145
* Eliminate opeq IVs that are not used outside the loop.
31413146
*/
@@ -3343,6 +3348,39 @@ Lf2:
33433348
return false;
33443349
}
33453350

3351+
/*****************************
3352+
* If loop is in a try block, see if there are references to x in an enclosing
3353+
* try block. This is because the loop may throw and transfer control
3354+
* outside the try block, and that will count as a use of x.
3355+
* Params:
3356+
* x = basic induction variable symbol
3357+
* l = loop x is in
3358+
* Returns:
3359+
* true if x is used outside the try block
3360+
*/
3361+
@trusted
3362+
private bool catchRef(Symbol* x, ref loop l)
3363+
{
3364+
block* btry = l.Lhead.Btry;
3365+
if (!btry)
3366+
return false; // not in a try block
3367+
3368+
foreach (i, b; dfo[])
3369+
{
3370+
if (vec_testbit(b.Bdfoidx, l.Lloop))
3371+
continue;
3372+
/* this is conservative, just checking if x is used outside the loop.
3373+
* A better check would see if the body of the loop throws, and would
3374+
* check the enclosing catch/finally blocks and their exit blocks.
3375+
* https://issues.dlang.org/show_bug.cgi?22104
3376+
*/
3377+
if (vec_testbit(x.Ssymnum, b.Binlv))
3378+
return true;
3379+
}
3380+
3381+
return false;
3382+
}
3383+
33463384
/************************************
33473385
* Input:
33483386
* x basic IV symbol

0 commit comments

Comments
 (0)