Bug 22372 – Loop index incorrectly optimised out for -release -O
Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2021-10-09T10:29:59Z
Last change time
2021-10-12T09:00:44Z
Keywords
backend, pull
Assigned to
No Owner
Creator
Teodor Dutu
Comments
Comment #0 by teodor.dutu — 2021-10-09T10:29:59Z
When compiling the code below with the -O -release flags, the index used by the for loop gets optimised out by the compiler. Thus, when throws2ndCall throws, the value of i in the catch body is 0 instead of 1.
This behaviour seems to occur when the size of S is somewhat larger. When S only contains 1 or 2 ints, the behaviour is the one expected. The error appears from a size of 3 ints and above.
static size_t n;
void throws2ndCall(T)(ref T x)
{
if (n == 1)
throw new Exception("n == 1");
++n;
}
void foo(T)(scope T[] arr)
{
size_t i;
try
{
for (i = 0; i < arr.length; i++)
throws2ndCall(arr[i]);
}
catch (Exception o)
{
printf("Exception: i = %lu; n = %lu\n", i, n); // prints 0 and 1
assert(i == n); // this fails
}
}
void main()
{
static struct S { int a1, a2, a3; }
foo([S(), S()]);
}
DMD64 D Compiler v2.098.0: -release -O
Comment #3 by johan_forsberg_86 — 2021-10-09T22:17:45Z
If you make size_t i static the behaviour is correct
Comment #4 by teodor.dutu — 2021-10-09T22:21:24Z
(In reply to Imperatorn from comment #3)
> If you make size_t i static the behaviour is correct
Yes, this would fix the issue, but it would be a hack rather than a solution. The bug would still persist in DMD's backend.
Comment #5 by johan_forsberg_86 — 2021-10-09T22:23:20Z
Lol, of course. It was just an observation.
Another observation:
If you change type from size_t to int or uint the behaviour is correct
by digging further it looks like the problem resides in dmd.backend.gloop reference counting system. OPInd would be ignored, so when a loop body only contains an IndexExp and that the IndexExp subscript is the IV (increment value ?), DMD thinks that the IV is not used.
Comment #8 by dlang-bot — 2021-10-11T10:23:22Z
@teodutu created dlang/druntime pull request #3585 "Use workaround until issue 22372 is fixed" mentioning this issue:
- Use workaround until issue 22372 is fixed
Signed-off-by: Teodor Dutu <[email protected]>
https://github.com/dlang/druntime/pull/3585
Comment #9 by dlang-bot — 2021-10-11T11:03:26Z
dlang/druntime pull request #3585 "Use workaround until issue 22372 is fixed" was merged into master:
- 06615791bcd20ed0edba68869babf76c22787caf by Teodor Dutu:
Use workaround until issue 22372 is fixed
Signed-off-by: Teodor Dutu <[email protected]>
https://github.com/dlang/druntime/pull/3585
Comment #10 by bugzilla — 2021-10-12T05:17:01Z
A simplified version:
import core.stdc.stdio;
struct S { int a1, a2, a3; }
void throws2ndCall(ref S x)
{
__gshared bool b;
if (b)
throw new Exception("n == 1");
b = true;
}
void main()
{
S[] arr = [S(), S()];
size_t i;
try
{
for (i = 0; i < 2; i++)
throws2ndCall(arr[i]);
}
catch (Exception o)
{
printf("Exception: i = %lu\n", i); // prints 0
assert(i == 1); // this fails
}
}
Comment #11 by dlang-bot — 2021-10-12T07:02:59Z
@WalterBright created dlang/dmd pull request #13158 "fix Issue 22372 - Loop index incorrectly optimised out for -release -O" fixing this issue:
- fix Issue 22372 - Loop index incorrectly optimised out for -release -O
https://github.com/dlang/dmd/pull/13158
Comment #12 by dlang-bot — 2021-10-12T09:00:44Z
dlang/dmd pull request #13158 "fix Issue 22372 - Loop index incorrectly optimised out for -release -O" was merged into master:
- 3e2a24503b338def775a3d65ca756de63a3efd3d by Walter Bright:
fix Issue 22372 - Loop index incorrectly optimised out for -release -O
https://github.com/dlang/dmd/pull/13158