D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6877 - [XMM] regression, clobbered float value
Summary: [XMM] regression, clobbered float value
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P2 normal
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2011-11-01 16:04 UTC by Martin Nowak
Modified: 2011-11-01 21:19 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Martin Nowak 2011-11-01 16:04:48 UTC
struct Matrix
{
    float[3][3] data;

    ref float[3] opIndex(size_t idx)
    {
        assert(0 <= idx && idx <= 2);
        return this.data[idx];
    }

    static Matrix identityMatrix()
    {
        Matrix id;
        id.data[0][0] = 1.0f; id.data[0][1] = 0.0f; id.data[0][2] = 0.0f;
        id.data[1][0] = 0.0f; id.data[1][1] = 1.0f; id.data[1][2] = 0.0f;
        id.data[2][0] = 0.0f; id.data[2][1] = 0.0f; id.data[2][2] = 1.0f;
        return id;
    }

    void setRotate(float deg)
    {
        this = identityMatrix();
        setSinCos(0.5f * deg, 0.2f * deg);
    }

    void setSinCos(float sinV, float cosV)
    {
        this[0][0] = cosV;
        this[0][1] = -sinV; // <- !!! BUG HERE BUG !!!

        // alternatively with this
        // *(cast(uint*)&(this[0][1])) = (*cast(uint*)&sinV) ^ 0x80000000;
        // thus it is not the OPneg that fails

        this[1][0] = sinV;
        this[1][1] = cosV;
    }
}

extern(C) int printf(in char* format, ...);

void main()
{
    Matrix m;
    m.setRotate(4);

    // should be -2
    printf("%g\n", m.data[0][1]);
}

---

Needed Flags: -O -inline, NOT -release, compilation with config.fpxmmregs

The is NaN where it should have been -2.
I could not reduce this test case any further.

This regression was introduced with:
https://github.com/D-Programming-Language/dmd/commit/82b5c12653c16097426ce990ecacc97525666302
Comment 1 Martin Nowak 2011-11-01 19:28:58 UTC
struct Matrix
{
    void setSinCos(float sinV)
    {
        // use parameter, so it becomes a register veriable
        a = sinV * sinV;

        // refer to value of parameter
        version (none)
            val = -sinV;
        else // which 'eleq' optimizes to
            *cast(uint*)&val = (*cast(uint*)&sinV) ^ 0x80000000;
    }
    float a, val;
}

extern(C) int printf(in char* format, ...);

void main()
{
    Matrix m;
    printf("%g\n", m.val);
    // indirect to prevent CTFE
    auto dg = &m.setSinCos;
    dg(2.0);
    printf("%g\n", m.val);
}

-----------------------------------------------------

sinV is a register variable residing in xmm2.
The load for the left xor operand is done with
  mov   %edx, %eax
which should be
  movd %xmm2, %eax
instead, same modrm though.