Bug 13341 – Wrong optimization for ref parameters and if statement

Status
RESOLVED
Resolution
WORKSFORME
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-08-20T13:58:00Z
Last change time
2016-08-09T22:08:15Z
Keywords
wrong-code
Assigned to
nobody
Creator
sinkuupump

Comments

Comment #0 by sinkuupump — 2014-08-20T13:58:15Z
This code produces unexpected AssertError when it is compiled with -O and -inline. ``` // core.checkedint.addu uint addu(uint x, uint y, ref bool overflow) { uint r = x + y; if (r < x || r < y) overflow = true; return r; } void main() { bool of; foreach (i; 0 .. 1) { addu(0, i, of); assert(!of); // fails } } ``` Reduced a bit: ``` void addu(uint y, ref bool overflow) { if (0 < y) overflow = true; } void main() { bool of; foreach (i; 0 .. 1) { addu(i, of); assert(!of); // fails } } ``` Oddly, following code doesn't write anything to stdout, though the assert still fails. ``` import std.stdio; void addu(uint y, ref bool overflow) { if (0 < y) { writeln("if (0 < y)"); overflow = true; } } // omitted ```
Comment #1 by sinkuupump — 2014-08-21T07:53:00Z
This was introduced in DMD2.047.
Comment #2 by yebblies — 2014-09-07T18:50:03Z
This is a hard one... Somehow the optimizer makes a jump from el:003B2620 cnt=0 , TYbool 003B2A60 003B29A0 el:003B2A60 cnt=0 , TYint 003B2D5C 003B2E1C el:003B2D5C cnt=0 , TYvoid 003B29E0 003B2D1C el:003B29E0 cnt=0 && TYvoid 003B26A0 003B2960 el:003B26A0 cnt=0 var TYunsigned __key1 el:003B2960 cnt=0 = TYbool 003B2720 003B2920 el:003B2720 cnt=0 var TYbool of el:003B2920 cnt=0 const TYbool 1 el:003B2D1C cnt=0 || TYvoid 003B2AE0 003B2CDC el:003B2AE0 cnt=0 ^ TYbool 003B2AA0 003B26E0 el:003B2AA0 cnt=0 var TYbool of el:003B26E0 cnt=0 const TYbool 1 el:003B2CDC cnt=0 call TYvoid 003B2C9C 003B2C5C el:003B2C9C cnt=0 var TYD func _D5testx8__assertFiZv el:003B2C5C cnt=0 const TYint 13L el:003B2E1C cnt=0 += TYint 003B2D9C 003B2DDC el:003B2D9C cnt=0 var TYint __key1 el:003B2DDC cnt=0 const TYint 1L el:003B29A0 cnt=0 < TYbool 003B2860 003B2820 el:003B2860 cnt=0 var TYint __key1 el:003B2820 cnt=0 const TYunsigned 1L to el:003B10D4 cnt=0 , TYbool 003B1560 003B2A20 el:003B1560 cnt=0 = TYbool 003B1360 003B15A0 el:003B1360 cnt=0 var TYbool of el:003B15A0 cnt=0 const TYbool 0 el:003B2A20 cnt=0 , TYbool 003B1460 003B2218 el:003B1460 cnt=0 = TYint 003B1114 003B14A0 el:003B1114 cnt=0 var TYint __key1 el:003B14A0 cnt=0 const TYint 0L el:003B2218 cnt=0 = TYbool 003B2720 003B2920 el:003B2720 cnt=0 var TYbool of el:003B2920 cnt=0 const TYbool 1 ... then eliminates most of the code because now 'of' is always 1. I think this is happening in loopopt, but I don't know the code well enough to find the cause.
Comment #3 by ag0aep6g — 2016-08-09T22:08:15Z
Assert passes since 2.071. Closing as WORKSFORME.