Bug 5809 – [64 bit] wrong code for *p==0, when widening conversion occurs

Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2011-04-03T16:28:00Z
Last change time
2015-06-09T05:11:37Z
Keywords
pull, wrong-code
Assigned to
nobody
Creator
moritzwarning

Comments

Comment #0 by moritzwarning — 2011-04-03T16:28:16Z
On x86_64 systems this assert fails because feqrel returns to 0. assert(feqrel(real.min_normal/8,real.min_normal/17)==3);
Comment #1 by moritzwarning — 2011-04-03T16:28:44Z
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.
Comment #6 by clugdbug — 2012-05-10T00:53:24Z
Comment #7 by clugdbug — 2012-05-10T07:02:10Z
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.
Comment #8 by clugdbug — 2012-05-10T07:22:16Z
Comment #9 by github-bugzilla — 2012-05-10T10:05:33Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/7c2ea37c476a2d7a289f54cbf1ee0e692d7a69a0 Fix issue 5809: [64 bit] wrong code for *p==0, when widening conversion occurs Bug was introduced in commit 3cdb9f52, but it never worked on 64bits, so it is not a regression.