6354 – Optimizer bug on x86_64: Bitshift optimized out when foreach and scope(failure) are used

D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6354 - Optimizer bug on x86_64: Bitshift optimized out when foreach and scope(failure) are used
Summary: Optimizer bug on x86_64: Bitshift optimized out when foreach and scope(failur...
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P2 critical
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
Reported: 2011年07月20日 01:03 UTC by Jonathan M Davis
Modified: 2015年06月09日 05:15 UTC (History)
2 users (show)

See Also:


Attachments
Add an attachment (proposed patch, testcase, etc.)

Note You need to log in before you can comment on or make changes to this issue.
Description Jonathan M Davis 2011年07月20日 01:03:12 UTC
Okay. This is a weird one, but it only happens on x86_64 when compiling with -O, so presumably it's a bug in the optmizer for x86_64. This code
import std.stdio;
ushort swapEndian(ushort val)
{
 return ((val & 0xff00U) >> 8) |
 ((val & 0x00ffU) << 8);
}
void main()
{
 foreach(j; 0 .. 2)
 {
 scope(failure) writefln("j: %s", j);
 ushort left = 0xffU;
 left <<= (ushort.sizeof - 1) * 8;
 ushort right = 0xffU;
 writefln("%s %s %s %s", swapEndian(left), right, swapEndian(right), left);
 assert(swapEndian(left) == right);
 }
}
does this:
 
255 65280 255 65280
j: 0
core.exception.AssertError@q(25): Assertion failure
----------------
----------------
Thee writefln at the bottom can be removed, but it helps show what's going on, since the correct output for this program would be
255 255 65280 65280
255 255 65280 65280
While the program does fail on the first iteration, removing the loop makes it so that it succeeds, so the foreach somehow helps cause the bug. Removing the scope(failure) also helps contribute, since removing _it_ gets rid of the bug. However, it fails regardless of whether it's a scope(failure), scope(success), or scope(exit). It also fails regardless of what's in the scope statement (e.g. it fails with scope(failure) int i;). You can also get rid of swapEndian and replace the call to it with its body and have the failure occur
assert((((left & 0xff00U) >> 8) | ((left & 0x00ffU) << 8)) == right);
so the function call isn't part of the problem (but it's easier to read with swapEndian in there, so I left in there). I can narrow it down to this at it still fails
void main()
{
 foreach(j; 0 .. 2)
 {
 scope(failure) int i = 0;
 ushort left = 0xffU;
 left <<= (ushort.sizeof - 1) * 8;
 assert((((left & 0xff00U) >> 8) | ((left & 0x00ffU) << 8)) == 0xffu);
 }
}
However, sometimes, some combination of changes in between those two states succeeds - probably depending on what the optimizer decides that it can optimize out.
In any case, it seems that something is causing the optimizer to think that it can optimize out the bitshifts. And it's something that's going to cause test failures if the swapEndian stuff that I'm currently working on for Phobos gets merged in, so it would be nice if it could be fixed soon.
Comment 2 github-bugzilla 2012年12月27日 14:58:21 UTC
Commits pushed to master at https://github.com/D-Programming-Language/phobos
https://github.com/D-Programming-Language/phobos/commit/3bb400d4920a3d611fbe8b7b2500d815eb69d13e
Decommented unittest that was blocked by bug 6354, which has since been fixed.
https://github.com/D-Programming-Language/phobos/commit/901500b1605209638c4deadc38b2d7236be06880
Merge pull request #1039 from mnembrini/decommentbug
Decommented unittest that was blocked by bug 6354, which has since been ...


AltStyle によって変換されたページ (->オリジナル) /