D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3496 - ICE(cgelem.c, optimizer bug) cast(void *)(x&1)== null.
Summary: ICE(cgelem.c, optimizer bug) cast(void *)(x&1)== null.
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: Other Windows
: P2 normal
Assignee: No Owner
URL:
Keywords: ice-on-valid-code, patch
Depends on:
Blocks:
 
Reported: 2009-11-11 09:51 UTC by David Simcha
Modified: 2014-02-15 13:13 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description David Simcha 2009-11-11 09:51:33 UTC
struct Node {
    size_t _left;

    Node* left() {
        return cast(Node*) (_left & 1);
    }

    bool useLeft() {
        return left is null;
    }
}

Result:

Internal error: ..\ztc\cgelem.c 3387

This one is really hard to reproduce.  If you change this test program in even very small ways, it's no longer reproduced.
Comment 1 Don 2009-11-12 07:17:10 UTC
I can't reproduce this (on Windows) with either D2 or D1. I tried several compiler versions, it compiled correctly in all cases.
Comment 2 David Simcha 2009-11-13 08:02:26 UTC
Didn't realize it at the time, but I've looked into this further.  It only happens when you compile w/ -O -inline.
Comment 3 Don 2009-11-13 12:42:02 UTC
Reduced test case. Compile with -O (-inline not required). Not a regression; fails on DMD0.165.

bool foo() {
    int x;
    return cast(void*) (x & 1) == null;
}

Internal error: ztc\cgelem.c 3387

Really peculiar thing is that replacing & with | or ^ makes the bug disappear.
Comment 4 Don 2009-11-13 13:17:00 UTC
This assert is actually completely harmless. It's part of a check for if the equality comparison can be reduced to a single byte comparison. This can happen if it's a pointer with all the high bits clear, which includes null. Here are 3 cases which trigger the same bug.

bool foo() 
{
    int x;
//  return cast(void*) (x & 1) == null;   // Case 1
//  return cast(void*) (x & 1) == cast(void *)(2);  // Case 2
    return cast(bool function()) (x & 1) == null;    // Case 3
}


================
PATCH:

cgelem.c, line 3387.
	/* Try to convert to byte/word comparison for ((x & c)==d)
	   when mask c essentially casts x to a smaller type
	 */
	if (OPTIMIZER &&
	    e1->Eoper == OPand &&
	    e1->E2->Eoper == OPconst &&
	    (sz = tysize(e2->Ety)) > CHARSIZE)
	{   int op;

-	    assert(tyintegral(e2->Ety));	    
+	    assert(tyintegral(e2->Ety) || (e2->Ety == TYnptr));	    
#if TX86		/* ending up with byte ops in A regs */
	    if (!(el_tolong(e2) & ~CHARMASK) &&
		!(el_tolong(e1->E2) & ~CHARMASK)
	       )
	    {
Comment 5 Leandro Lucarella 2009-11-23 06:48:08 UTC
SVN commit: http://www.dsource.org/projects/dmd/changeset/267
Comment 6 David Simcha 2009-12-05 18:33:06 UTC
Fixed 2.037.
Comment 7 Walter Bright 2009-12-06 00:47:30 UTC
Fixed dmd 1.053 and 2.037