Bug 6877 – [XMM] regression, clobbered float value
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2011-11-01T16:04:00Z
Last change time
2011-11-01T21:19:12Z
Keywords
wrong-code
Assigned to
nobody
Creator
code
Comments
Comment #0 by code — 2011-11-01T16:04:48Z
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 by code — 2011-11-01T19:28:58Z
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.