Comment #2 by moritzwarning — 2011-04-03T16:30:07Z
It works when a dummy function call is inserted before "if (pd[F.EXPPOS_SHORT] == 0)" inside feqrel.
Comment #3 by clugdbug — 2011-12-21T13:02:13Z
This sounds like a compiler bug. Does it still fail on 2.057?
Comment #4 by bugzilla — 2012-04-23T17:34:36Z
(In reply to comment #3)
> Does it still fail on 2.057?
Works on 32 bit Linux, fails on 64 bit Linux. Test program:
import std.math;
void main() {
assert(feqrel(real.min_normal/8,real.min_normal/17)==3);
}
Comment #5 by clugdbug — 2012-05-08T22:08:29Z
Original title: feqrel fails assert in std.math on x86_64 systems
Reduced test case shows it is a backend bug.
The common subexpression *px gets extended to int when calculating b. Inside the assert it is treated as *cast(int *)px, so that it picks up x[1] instead of just x[0]. It seems to only apply to comparisons with 0.
Subtle and disastrous, raising severity to blocker.
void main()
{
ushort[2] x = void;
x[0] = 0;
x[1] = 0x1234;
ushort *px = &x[0];
uint b = px[0]; // this causes the next line to fail
assert(px[0] == 0);
}
It generates
cmp dword ptr -010h[RBP],0
should be word ptr, which doesn't exist in 64bit.
My pull request is wrong. The correct fix is in cgcod.c, line 1795.
In moving to 64 bit, commit 3cdb9f520e0bac17f6da00ef9de86c81e23429aa
made this change:
c = genc(NULL,0x81 ^ byte,modregrm(2,7,BPRM),
FLcs,i, FLconst,(targ_uns) 0);
- if (REGSIZE == 4 && sz == 2)
+ if (I32 && sz == 2)
c->Iflags |= CFopsize;
}
But this is wrong, it should be
+ if ((I32 || I64) && sz == 2)
This code is now in cod3.c, testcse(), line 1795.