Bug 8091 – Optimizer generates wrong code when reducing comparisons.
Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-05-12T13:24:00Z
Last change time
2012-05-17T20:01:38Z
Keywords
wrong-code
Assigned to
nobody
Creator
k.hanazuki
Comments
Comment #0 by k.hanazuki — 2012-05-12T13:24:17Z
DMD optimizer generates a wrong code for the program below.
The second assertion unexpectedly fails if you specify -O flag to DMD,
while it passes as expected without optimization.
$ dmd -m32 -run test.d # fine
$ dmd -m32 -O -run test.d # AssertError@test(8): Assertion failure
Tested against DMDv2.060 (git HEAD) on 32-bit Linux.
Found by hos_lyric <https://twitter.com/#!/hos_lyric_/status/201270597265793024>.
----
int solve(int n) {
int a = (n % 3 == 0) ? 1 : (n % 3 == 1) ? 1 : 0;
return (a != 0) ? a : 0;
}
void main() {
assert(solve(0) == 1);
assert(solve(1) == 1); // line 8, fails with -O
assert(solve(2) == 0);
}
Comment #1 by k.hanazuki — 2012-05-12T23:58:16Z
more simplification:
----
int solve(int n) {
int a = (n == 0) ? 1 : (n == 1) ? 1 : 0;
return (a != 0) ? a : 0;
}
void main() {
assert(solve(0) == 1);
assert(solve(1) == 1); // fails with -O
assert(solve(2) == 0);
}
Comment #2 by clugdbug — 2012-05-16T12:17:27Z
Marginally reduced (this is what the early optimizer passes turn this into):
int solve(int n) {
int a = n ? (n>=1u) : 1;
return a ? a : 0;
}
void main() {
assert(solve(1) == 1);
}
It looks as after common subexpression elimination of a, the branch address from the >= is out by 1. The generated code is:
push EAX
cmp dword ptr -4[EBP],0
je L1C
mov ECX,1
cmp dword ptr -4[EBP],1
jae L1F
mov ECX,0
jmp short L1F <--- wrong address
L1C: xor ECX,ECX
inc ECX
L1F: je L25 <---- shouldn't jump here
mov EAX,ECX <---- should jump here instead
jmp short L27
L25: xor EAX,EAX
L27: mov ESP,EBP
Comment #3 by github-bugzilla — 2012-05-17T19:59:04Z