Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/dmd/backend/cg87.d
Original file line number Diff line number Diff line change
Expand Up @@ -3646,6 +3646,20 @@ void fixresult_complex87(ref CodeBuilder cdb,elem *e,regm_t retregs,regm_t *pret
cdb.genf2(0xDD,modregrm(3,3,0)); // FPOP
pop87();
}
else if (tym == TYllong)
{
// passing cfloat through register for I64
assert(retregs & mST01, "this float expression is not implemented");
pop87();
cdb.genfltreg(ESC(MFfloat,1),BX,4); // FSTP floatreg
pop87();
cdb.genfltreg(ESC(MFfloat,1),BX,0); // FSTP floatreg+4
genfwait(cdb);
const reg = findreg(*pretregs);
getregs(cdb,reg);
cdb.genfltreg(LOD, reg, 0); // MOV ECX,floatreg
code_orrex(cdb.last(), REX_W); // extend to RCX
}
else if (tym == TYcfloat && *pretregs & (mAX|mDX) && retregs & mST01)
{
if (*pretregs & mPSW && !(retregs & mPSW))
Expand Down
3 changes: 2 additions & 1 deletion src/dmd/backend/cod2.d
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,8 @@ void cdmul(ref CodeBuilder cdb,elem *e,regm_t *pretregs)
config.fpxmmregs && oper != OPmod && tyxmmreg(tyml) &&
!(*pretregs & mST0) &&
!(ty == TYldouble || ty == TYildouble) && // watch out for shrinkLongDoubleConstantIfPossible()
!tycomplex(ty) // SIMD code is not set up to deal with complex mul/div
!tycomplex(ty) && // SIMD code is not set up to deal with complex mul/div
!(ty == TYllong) // or passing to function through integer register
)
{
orthxmm(cdb,e,pretregs);
Expand Down
89 changes: 85 additions & 4 deletions test/runnable/test18772.d
Original file line number Diff line number Diff line change
@@ -1,13 +1,94 @@
float fun(cfloat z)
float getreal_rcx(cfloat z)
{
return z.re;
}
float getimag_rcx(cfloat z)
{
return z.im;
}

void main()
float getreal_rdx(cfloat z, int)
{
return z.re;
}
float getimag_rdx(cfloat z, int)
{
return z.im;
}

float getreal_r8(cfloat z, int, int)
{
return z.re;
}
float getimag_r8(cfloat z, int, int)
{
return z.im;
}

float getreal_r9(cfloat z, int, int, int)
{
return z.re;
}
float getimag_r9(cfloat z, int, int, int)
{
return z.im;
}

float getreal_stack(cfloat z, int, int, int, int)
{
return z.re;
}
float getimag_stack(cfloat z, int, int, int, int)
{
return z.im;
}

void test18772()
{
cfloat[1] A;
float[1] B;
int i = 0;
version(D_LP64) {} else // disabled because of wrong codegen: https://issues.dlang.org/show_bug.cgi?id=20089
double C = fun(A[i] * B[i]);
A[0] = 2.0f + 4i;
B[0] = 3.0f;
assert(6.0 == getreal_rcx(A[i] * B[i]));
assert(12.0 == getimag_rcx(A[i] * B[i]));

assert(6.0 == getreal_rdx(A[i] * B[i], 1));
assert(12.0 == getimag_rdx(A[i] * B[i], 1));

assert(6.0 == getreal_r8(A[i] * B[i], 1, 2));
assert(12.0 == getimag_r8(A[i] * B[i], 1, 2));

assert(6.0 == getreal_r9(A[i] * B[i], 1, 2, 3));
assert(12.0 == getimag_r9(A[i] * B[i], 1, 2, 3));

assert(6.0 == getreal_stack(A[i] * B[i], 1, 2, 3, 4));
assert(12.0 == getimag_stack(A[i] * B[i], 1, 2, 3, 4));
}

void test(T)()
{
static auto getre0(T z)
{
return z.re;
}
static auto getim0(T z)
{
return z.im;
}

T z = 3 + 4i;
auto d = z.re;

assert(getre0(d * z) == d * 3);
assert(getim0(d * z) == d * 4);
}

void main()
{
test18772();

test!cfloat();
test!cdouble();
test!creal();
}