How to track down a bad llvm optimization pass

Joakim via digitalmars-d-ldc digitalmars-d-ldc at
Wed Jun 22 02:44:46 PDT 2016

On Wednesday, 22 June 2016 at 08:54:22 UTC, Joakim wrote:
> On Tuesday, 21 June 2016 at 19:41:59 UTC, Dan Olson wrote:
>> On Tuesday, 21 June 2016 at 07:00:35 UTC, Joakim wrote:
>>> On Tuesday, 21 June 2016 at 05:51:56 UTC, Joakim wrote:
>>>> On Monday, 20 June 2016 at 20:15:52 UTC, Rainer Schuetze 
>>>> wrote:
>>>>> On 19.06.2016 08:58, Joakim wrote:
>>>>>> [...]
>>>>> If it fails in a specific optimization pass, it has already 
>>>>> passed a number of verification passes. When I posted some 
>>>>> bug reports, the LLVM people (who have been very helpful) 
>>>>> considered it an LLVM bug if an invalid IR passes the 
>>>>> verifier. So even if some assumptions are broken, I would 
>>>>> suggest to report to the LLVM bug tracker.
>>>> OK, will do.  I think the fact that the exact same ldc 
>>>> frontend linked with llvm 3.7.1 doesn't have this problem, 
>>>> only when linked against llvm 3.8.0, indicates this most 
>>>> likely isn't a problem on our end.
>>> Filed:
>> Hmmm.  I looked at failing code in std.conv.  I think it does 
>> a negative shift, which is undefined in C.  It is the 
>> opSlice() method.
> I just tried the three-line reduced test case on linux/x64 with 
> the official ldc 1.0.0 release linked against 3.8.0 and it 
> asserts there too.  However, if I compile all of the std.conv 
> unittests and run them all, they all pass.
> It appears that you've found a clear off-by-one bug.  I didn't 
> investigate our end because the tests were all passing 
> otherwise- I now see that dmd doesn't assert even against the 
> reduced test case- but I should have examined that code more 
> closely.  It would have helped if llvm and/or the ddmd frontend 
> had flagged that Phobos was shifting by a negative number, 
> rather than passing it through silently for either correct or 
> junk codegen.
> I agree that the real fix for this bug should go in Phobos, but 
> perhaps we can also improve the spots where this negative shift 
> was most silently discarded so far, whether ddmd or llvm.

I experimented a bit with this, using the latest dmd 2.071.0 
release for linux/x64 and the following test that mimics what 
std.conv was doing wrong:

int check_shift(int x) { return 16 >>> ((2 - x) * 4);}
     assert(check_shift(3)  ==  16);
     //assert(( 16 >>> (2-3) * 4)  ==  16);

If the second assert isn't commented out, dmd always evaluates 
that expression at compile-time and gives this error:

shift.d(5): Error: shift by -4 is outside the range 0..31

If it's left commented out and the file is compiled with this 

./2.071.0/linux/bin64/dmd -O -unittest -main shift.d

the resulting binary asserts at runtime on line 4, ie the first 
assert.  If I compile again with inlining,

./2.071.0/linux/bin64/dmd -O -inline -unittest -main shift.d

the test passes!

The codegen for dmd seems all over the place here.

More information about the digitalmars-d-ldc mailing list