[Issue 3558] Optimizer bug results in false if condition being taken

d-bugmail at puremagic.com d-bugmail at puremagic.com
Thu Feb 11 14:24:14 PST 2010


http://d.puremagic.com/issues/show_bug.cgi?id=3558


Don <clugdbug at yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |patch


--- Comment #5 from Don <clugdbug at yahoo.com.au> 2010-02-11 14:24:13 PST ---
This was hard to track down! I had to delve into most of the back-end to work
out what's going on here. As usual with these nightmare bugs, the fix is
simple:

PATCH: cod1.c, loaddata(), line 3365.

    else if (sz == 8)
    {   code *c1;
        int i;

        c = allocreg(&regm,&reg,TYoffset);    /* get a register */
        i = sz - REGSIZE;
        ce = loadea(e,&cs,0x8B,reg,i,0,0);    /* MOV reg,data+6 */
        if (tyfloating(tym))        // TYdouble or TYdouble_alias
        gen2(ce,0xD1,modregrm(3,4,reg));    // SHL reg,1
        c = cat(c,ce);

        while ((i -= REGSIZE) >= 0)
        {
        c1 = loadea(e,&cs,0x0B,reg,i,regm,0);    // OR reg,data+i
+        if (i == 0)
+            c1->Iflags |= CFpsw;   // We need the flags
        c = cat(c,c1);
        }
    }
    else if (sz == LNGDBLSIZE)            // TYldouble

ROOT CAUSE: 
A condition of the form 'if (x)', where x is long or ulong, is coded as:  asm {
mov reg, low_dword; OR reg, high_dword; } But, the code needs to mark the flags
as needing to be preserved. (CFpsw, I have no idea what that stands for!).
Then, later on, in cgsched.c, the Pentium scheduler thinks it can move this
instruction behind other flag-modifying instructions, and it wants to do that
in this case in order to do instruction pairing for the U and V pipes.

In the original test case, there's an ADD which gets moved after the OR. Then,
the branch instruction which follows this gets the flags from the ADD instead
of the OR, and so it branches incorrectly. The bug is only manifested in weird
cases where pairing opportunities arise, so it is extremely fragile. It's not
really an optimiser bug, but it only happens when there are pairing advantages
when instructions are moved around, which only happens when many registers are
being used and modified, and this in turn only happens when variables are in
registers.

BTW: This bug probably also affects the 16-bit C compiler in the 4-byte int
case; the flags aren't marked as required for any of the comparisons.

That's a long explanation, but it took me ages to track this down.
I think I need a beer.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list