diff --git a/src/dmd/backend/cg87.d b/src/dmd/backend/cg87.d index b05dd007d927..429693e1755b 100644 --- a/src/dmd/backend/cg87.d +++ b/src/dmd/backend/cg87.d @@ -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)) diff --git a/src/dmd/backend/cod2.d b/src/dmd/backend/cod2.d index e178916b9c2e..78a00bb4d09c 100644 --- a/src/dmd/backend/cod2.d +++ b/src/dmd/backend/cod2.d @@ -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); diff --git a/test/runnable/test18772.d b/test/runnable/test18772.d index cc99bb2446c4..d818a3c80932 100644 --- a/test/runnable/test18772.d +++ b/test/runnable/test18772.d @@ -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(); }