Bug 16189 – Optimizer bug, with simple test case

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-06-21T15:08:35Z
Last change time
2018-03-26T01:54:04Z
Keywords
industry, wrong-code
Assigned to
No Owner
Creator
Kirill Kryukov

Comments

Comment #0 by kkryukov — 2016-06-21T15:08:35Z
Consider this code: === a.d === struct T { long a, b; } T[] data = [{0,0}]; void main() { int a = 0; for (int i = 0; i >= 0; i--) { data[0] = data[a]; a--; } assert(a == -1); // Fails with -O } === end === Fails when built with "-O", succeeds without "-O". The full command line: dmd a.d -ofa.exe -O dmd a.d -ofb.exe Windows 7, dmd 2.071.0 If you add "-m64" to dmd command, the bug disappears, but re-appears if "int a" is changed to "long a". Reduced from a large project with the help of dustmite and a lot of "WTF!".
Comment #1 by ag0aep6g — 2016-06-21T18:54:38Z
Slightly more reduced: ---- void main() { ubyte[9][1] data; size_t a = 0; loop: data[0] = data[a]; a--; bool b = false; if (b) goto loop; assert(a == -1); // Fails with -O } ---- Also happens on Linux.
Comment #2 by kkryukov — 2016-06-22T01:20:48Z
A possible workaround: change "a--;" into "{ auto a2 = a - 1; a = a2; }". (This is NOT to suggest that the bug does not need fixing, as it's annoying as hell that even simplest C-like code does not work correctly.) As for previous reduction - it hurts my eyes to see size_t (unsigned type) compared for equality with -1, so I suggest to at least use ptrdiff_t.
Comment #3 by ketmar — 2016-06-23T12:00:07Z
funny thing: adding `asm { nop; }` anywhere in `main` seems to turn the optimizer off, and the code works again. a hackish way to control optimizer on per-function basis. ;-)
Comment #4 by kkryukov — 2016-08-02T03:33:10Z
I thought this might be a regression, so I tested dmd versions down to 2.050. But no, the bug is there in each and every one of them.
Comment #5 by greensunny12 — 2018-02-07T15:20:07Z
See also the discussion in the forum: https://forum.dlang.org/post/[email protected] My summary: The optimizer seems to be confused and wrongly precomputes a. Note that if you remove e.g. "if (b) goto loop;", a will be correctly statically set in the printf too: --- mov RSI,0FFFFFFFFh ; look ma - a is now -1 lea RDI,FLAT:.rodata[00h][RIP] xor EAX,EAX ; set eax to 0 call printf@PLT32 --- For comparison the assembly of -O. Here with printf and a different value to be compared with a because it's easier to read: --- main: push RBP mov RBP,RSP sub RSP,010h lea RAX,-010h[RBP] xor ECX,ECX mov [RAX],RCX mov 8[RAX],CL lea RSI,-010h[RBP] lea RDI,-010h[RBP] movsd movsb mov RSI,01C71C71C71C71C70h ; 2 function argument (value of a) lea RDI,FLAT:.rodata[00h][RIP] ; "%d" (1st function argument) xor EAX,EAX ; set eax to 0 call printf@PLT32 ; printf("%d", a) mov EDX,0Ch lea RSI,_TMP0@PC32[RIP] ; load function arguments (in reverse order) lea RDI,_TMP0@PC32[RIP] call __assert@PLT32 ; values load, let's call assert add [RAX],AL .text.main ends end ----
Comment #6 by bitter.taste — 2018-02-20T19:57:18Z
The LICM pass is too eager and given this small snippet ``` void main() { ubyte[9][1] data; size_t a = 0; loop: data[0] = data[a]; a--; bool b = false; if (b) goto loop; assert(a == -1); // Fails with -O } ``` `a' is considered to be as an "index" variable into `data' with starting value 0 and that's decremented until `a < 1', this condition is most likely derived by the bound-checking condition. As a result we get ``` Adding (a(1) = ((_TMP1(3) - #data(0)) / 9LL )) to exit block B4 ``` that doesn't play well with the constant folding pass ``` const prop (_TMP1(3) replaced by #data(0).xfffffffffffffff7) ``` as shown by ``` const prop (a(1) replaced by 2049638230412172400LL ) ```
Comment #7 by bugzilla — 2018-03-24T08:14:42Z
Comment #8 by github-bugzilla — 2018-03-26T01:54:03Z
Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/27dd8373a06cafa7e6038bf853cf15ab9575518d fix Issue 16189 - Optimizer bug, with simple test case https://github.com/dlang/dmd/commit/88a963a8ce44d062d45c34677a697ff2bd1fe2fa Merge pull request #8074 from WalterBright/fix16189 fix Issue 16189 - Optimizer bug, with simple test case