Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (201207 => 201208)
--- trunk/Source/_javascript_Core/ChangeLog 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-05-20 02:44:02 UTC (rev 201208)
@@ -1,5 +1,87 @@
2016-05-19 Benjamin Poulain <[email protected]>
+ [JSC] Improve int->float conversion in FTL
+ https://bugs.webkit.org/show_bug.cgi?id=157936
+
+ Reviewed by Filip Pizlo.
+
+ The integer -> floating point lowering was very barebone.
+
+ For example, converting a constant integer to double
+ was doing:
+ mov #const, %eax
+ xor %xmm0, %xmm0
+ cvtsi2sd %eax, %xmm0
+
+ Conversion from integer to float was also missing.
+ We were always converting to double then rounding the double
+ to float.
+
+ This patch adds the basics:
+ -Constant folding.
+ -Integer to Float opcode.
+ -Reducing int->double to int->float when used by DoubleToFloat.
+
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::convertInt32ToFloat):
+ * assembler/MacroAssemblerX86_64.h:
+ (JSC::MacroAssemblerX86_64::convertInt64ToDouble):
+ (JSC::MacroAssemblerX86_64::convertInt64ToFloat):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::cvtsi2ss_rr):
+ (JSC::X86Assembler::cvtsi2ssq_rr):
+ (JSC::X86Assembler::cvtsi2sdq_mr):
+ (JSC::X86Assembler::cvtsi2ssq_mr):
+ (JSC::X86Assembler::cvtsi2ss_mr):
+ * assembler/MacroAssemblerARM64.h:
+ * b3/B3Const32Value.cpp:
+ (JSC::B3::Const32Value::iToDConstant):
+ (JSC::B3::Const32Value::iToFConstant):
+ * b3/B3Const32Value.h:
+ * b3/B3Const64Value.cpp:
+ (JSC::B3::Const64Value::iToDConstant):
+ (JSC::B3::Const64Value::iToFConstant):
+ * b3/B3Const64Value.h:
+ * b3/B3LowerToAir.cpp:
+ (JSC::B3::Air::LowerToAir::lower):
+ * b3/B3Opcode.cpp:
+ (WTF::printInternal):
+ * b3/B3Opcode.h:
+ * b3/B3ReduceDoubleToFloat.cpp:
+ * b3/B3ReduceStrength.cpp:
+ * b3/B3Validate.cpp:
+ * b3/B3Value.cpp:
+ (JSC::B3::Value::iToDConstant):
+ (JSC::B3::Value::iToFConstant):
+ (JSC::B3::Value::isRounded):
+ (JSC::B3::Value::effects):
+ (JSC::B3::Value::key):
+ (JSC::B3::Value::typeFor):
+ * b3/B3Value.h:
+ * b3/B3ValueKey.cpp:
+ (JSC::B3::ValueKey::materialize):
+ * b3/air/AirFixPartialRegisterStalls.cpp:
+ * b3/air/AirOpcode.opcodes:
+ * b3/testb3.cpp:
+ (JSC::B3::int64Operands):
+ (JSC::B3::testIToD64Arg):
+ (JSC::B3::testIToF64Arg):
+ (JSC::B3::testIToD32Arg):
+ (JSC::B3::testIToF32Arg):
+ (JSC::B3::testIToD64Mem):
+ (JSC::B3::testIToF64Mem):
+ (JSC::B3::testIToD32Mem):
+ (JSC::B3::testIToF32Mem):
+ (JSC::B3::testIToD64Imm):
+ (JSC::B3::testIToF64Imm):
+ (JSC::B3::testIToD32Imm):
+ (JSC::B3::testIToF32Imm):
+ (JSC::B3::testIToDReducedToIToF64Arg):
+ (JSC::B3::testIToDReducedToIToF32Arg):
+ (JSC::B3::run):
+
+2016-05-19 Benjamin Poulain <[email protected]>
+
[JSC] FTL can crash on stack overflow
https://bugs.webkit.org/show_bug.cgi?id=157881
rdar://problem/24665964
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (201207 => 201208)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -1607,11 +1607,21 @@
load32(address.m_ptr, getCachedDataTempRegisterIDAndInvalidate());
convertInt32ToDouble(dataTempRegister, dest);
}
+
+ void convertInt32ToFloat(RegisterID src, FPRegisterID dest)
+ {
+ m_assembler.scvtf<32, 32>(dest, src);
+ }
void convertInt64ToDouble(RegisterID src, FPRegisterID dest)
{
m_assembler.scvtf<64, 64>(dest, src);
}
+
+ void convertInt64ToFloat(RegisterID src, FPRegisterID dest)
+ {
+ m_assembler.scvtf<32, 64>(dest, src);
+ }
void divDouble(FPRegisterID src, FPRegisterID dest)
{
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (201207 => 201208)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -1543,6 +1543,18 @@
m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
}
+ void convertInt32ToFloat(RegisterID src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.cvtsi2ss_rr(src, dest);
+ }
+
+ void convertInt32ToFloat(Address src, FPRegisterID dest)
+ {
+ ASSERT(isSSE2Present());
+ m_assembler.cvtsi2ss_mr(src.offset, src.base, dest);
+ }
+
Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
{
ASSERT(isSSE2Present());
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (201207 => 201208)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -1233,6 +1233,21 @@
m_assembler.cvtsi2sdq_rr(src, dest);
}
+ void convertInt64ToDouble(Address src, FPRegisterID dest)
+ {
+ m_assembler.cvtsi2sdq_mr(src.offset, src.base, dest);
+ }
+
+ void convertInt64ToFloat(RegisterID src, FPRegisterID dest)
+ {
+ m_assembler.cvtsi2ssq_rr(src, dest);
+ }
+
+ void convertInt64ToFloat(Address src, FPRegisterID dest)
+ {
+ m_assembler.cvtsi2ssq_mr(src.offset, src.base, dest);
+ }
+
static bool supportsFloatingPoint() { return true; }
static bool supportsFloatingPointTruncate() { return true; }
static bool supportsFloatingPointSqrt() { return true; }
Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (201207 => 201208)
--- trunk/Source/_javascript_Core/assembler/X86Assembler.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -2172,12 +2172,36 @@
m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
}
+ void cvtsi2ss_rr(RegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F3);
+ m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
+ }
+
#if CPU(X86_64)
void cvtsi2sdq_rr(RegisterID src, XMMRegisterID dst)
{
m_formatter.prefix(PRE_SSE_F2);
m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
}
+
+ void cvtsi2ssq_rr(RegisterID src, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F3);
+ m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
+ }
+
+ void cvtsi2sdq_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F2);
+ m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
+ }
+
+ void cvtsi2ssq_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F3);
+ m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
+ }
#endif
void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
@@ -2186,6 +2210,12 @@
m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
}
+ void cvtsi2ss_mr(int offset, RegisterID base, XMMRegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F3);
+ m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
+ }
+
#if !CPU(X86_64)
void cvtsi2sd_mr(const void* address, XMMRegisterID dst)
{
Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Const32Value.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -166,6 +166,16 @@
return proc.add<ConstFloatValue>(origin(), bitwise_cast<float>(m_value));
}
+Value* Const32Value::iToDConstant(Procedure& proc) const
+{
+ return proc.add<ConstDoubleValue>(origin(), static_cast<double>(m_value));
+}
+
+Value* Const32Value::iToFConstant(Procedure& proc) const
+{
+ return proc.add<ConstFloatValue>(origin(), static_cast<float>(m_value));
+}
+
TriState Const32Value::equalConstant(const Value* other) const
{
if (!other->hasInt32())
Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.h (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Const32Value.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -58,6 +58,8 @@
Value* sShrConstant(Procedure&, const Value* other) const override;
Value* zShrConstant(Procedure&, const Value* other) const override;
Value* bitwiseCastConstant(Procedure&) const override;
+ Value* iToDConstant(Procedure&) const override;
+ Value* iToFConstant(Procedure&) const override;
TriState equalConstant(const Value* other) const override;
TriState notEqualConstant(const Value* other) const override;
Modified: trunk/Source/_javascript_Core/b3/B3Const64Value.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Const64Value.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -166,6 +166,16 @@
return proc.add<ConstDoubleValue>(origin(), bitwise_cast<double>(m_value));
}
+Value* Const64Value::iToDConstant(Procedure& proc) const
+{
+ return proc.add<ConstDoubleValue>(origin(), static_cast<double>(m_value));
+}
+
+Value* Const64Value::iToFConstant(Procedure& proc) const
+{
+ return proc.add<ConstFloatValue>(origin(), static_cast<float>(m_value));
+}
+
TriState Const64Value::equalConstant(const Value* other) const
{
if (!other->hasInt64())
Modified: trunk/Source/_javascript_Core/b3/B3Const64Value.h (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Const64Value.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -58,6 +58,8 @@
Value* sShrConstant(Procedure&, const Value* other) const override;
Value* zShrConstant(Procedure&, const Value* other) const override;
Value* bitwiseCastConstant(Procedure&) const override;
+ Value* iToDConstant(Procedure&) const override;
+ Value* iToFConstant(Procedure&) const override;
TriState equalConstant(const Value* other) const override;
TriState notEqualConstant(const Value* other) const override;
Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -2150,6 +2150,11 @@
return;
}
+ case IToF: {
+ appendUnOp<ConvertInt32ToFloat, ConvertInt64ToFloat>(m_value->child(0));
+ return;
+ }
+
case B3::CCall: {
CCallValue* cCall = m_value->as<CCallValue>();
Modified: trunk/Source/_javascript_Core/b3/B3Opcode.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Opcode.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -188,6 +188,9 @@
case IToD:
out.print("IToD");
return;
+ case IToF:
+ out.print("IToF");
+ return;
case FloatToDouble:
out.print("FloatToDouble");
return;
Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Opcode.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -111,10 +111,11 @@
ZExt32,
// Takes Int64 and returns Int32:
Trunc,
- // Takes ints and returns Double. Note that we don't currently provide the opposite operation,
+ // Takes ints and returns floating point value. Note that we don't currently provide the opposite operation,
// because double-to-int conversions have weirdly different semantics on different platforms. Use
// a patchpoint if you need to do that.
IToD,
+ IToF,
// Convert between double and float.
FloatToDouble,
DoubleToFloat,
Modified: trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -311,6 +311,13 @@
}
break;
}
+ case IToD: {
+ Value* iToF = insertionSet.insert<Value>(index, IToF, value->origin(), value->child(0));
+ value->setType(Float);
+ value->replaceWithIdentity(iToF);
+ m_convertedValue.add(value);
+ break;
+ }
case FloatToDouble:
// This happens if we round twice.
// Typically, this is indirect through Phi-Upsilons.
Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -1324,6 +1324,24 @@
}
break;
+ case IToD:
+ // Turn this: IToD(constant)
+ // Into this: ConstDouble(constant)
+ if (Value* constant = m_value->child(0)->iToDConstant(m_proc)) {
+ replaceWithNewValue(constant);
+ break;
+ }
+ break;
+
+ case IToF:
+ // Turn this: IToF(constant)
+ // Into this: ConstFloat(constant)
+ if (Value* constant = m_value->child(0)->iToFConstant(m_proc)) {
+ replaceWithNewValue(constant);
+ break;
+ }
+ break;
+
case FloatToDouble:
// Turn this: FloatToDouble(constant)
// Into this: ConstDouble(constant)
Modified: trunk/Source/_javascript_Core/b3/B3Validate.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Validate.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Validate.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -252,6 +252,11 @@
VALIDATE(isInt(value->child(0)->type()), ("At ", *value));
VALIDATE(value->type() == Double, ("At ", *value));
break;
+ case IToF:
+ VALIDATE(value->numChildren() == 1, ("At ", *value));
+ VALIDATE(isInt(value->child(0)->type()), ("At ", *value));
+ VALIDATE(value->type() == Float, ("At ", *value));
+ break;
case FloatToDouble:
VALIDATE(value->numChildren() == 1, ("At ", *value));
VALIDATE(value->child(0)->type() == Float, ("At ", *value));
Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Value.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -267,6 +267,16 @@
return nullptr;
}
+Value* Value::iToDConstant(Procedure&) const
+{
+ return nullptr;
+}
+
+Value* Value::iToFConstant(Procedure&) const
+{
+ return nullptr;
+}
+
Value* Value::doubleToFloatConstant(Procedure&) const
{
return nullptr;
@@ -368,6 +378,7 @@
case Floor:
case Ceil:
case IToD:
+ case IToF:
return true;
case ConstDouble: {
@@ -470,6 +481,7 @@
case ZExt32:
case Trunc:
case IToD:
+ case IToF:
case FloatToDouble:
case DoubleToFloat:
case Equal:
@@ -553,6 +565,7 @@
case Clz:
case Trunc:
case IToD:
+ case IToF:
case FloatToDouble:
case DoubleToFloat:
case Check:
@@ -690,6 +703,7 @@
case IToD:
return Double;
case DoubleToFloat:
+ case IToF:
return Float;
case BitwiseCast:
switch (firstChild->type()) {
Modified: trunk/Source/_javascript_Core/b3/B3Value.h (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3Value.h 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3Value.h 2016-05-20 02:44:02 UTC (rev 201208)
@@ -133,6 +133,8 @@
virtual Value* sShrConstant(Procedure&, const Value* other) const;
virtual Value* zShrConstant(Procedure&, const Value* other) const;
virtual Value* bitwiseCastConstant(Procedure&) const;
+ virtual Value* iToDConstant(Procedure&) const;
+ virtual Value* iToFConstant(Procedure&) const;
virtual Value* doubleToFloatConstant(Procedure&) const;
virtual Value* floatToDoubleConstant(Procedure&) const;
virtual Value* absConstant(Procedure&) const;
Modified: trunk/Source/_javascript_Core/b3/B3ValueKey.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/B3ValueKey.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/B3ValueKey.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -68,6 +68,7 @@
case Clz:
case Trunc:
case IToD:
+ case IToF:
case FloatToDouble:
case DoubleToFloat:
case Check:
Modified: trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -50,6 +50,8 @@
case ConvertFloatToDouble:
case ConvertInt32ToDouble:
case ConvertInt64ToDouble:
+ case ConvertInt32ToFloat:
+ case ConvertInt64ToFloat:
case SqrtDouble:
case SqrtFloat:
case CeilDouble:
Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2016-05-20 02:44:02 UTC (rev 201208)
@@ -480,7 +480,16 @@
64: ConvertInt64ToDouble U:G:64, D:F:64
Tmp, Tmp
+ x86_64: Addr, Tmp
+ConvertInt32ToFloat U:G:32, D:F:32
+ Tmp, Tmp
+ x86: Addr, Tmp
+
+64: ConvertInt64ToFloat U:G:64, D:F:32
+ Tmp, Tmp
+ x86_64: Addr, Tmp
+
CountLeadingZeros32 U:G:32, ZD:G:32
Tmp, Tmp
x86: Addr, Tmp
Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (201207 => 201208)
--- trunk/Source/_javascript_Core/b3/testb3.cpp 2016-05-20 02:37:53 UTC (rev 201207)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp 2016-05-20 02:44:02 UTC (rev 201208)
@@ -150,6 +150,7 @@
static Vector<Int64Operand> int64Operands()
{
Vector<Int64Operand> operands;
+ operands.append({ "0", 0 });
operands.append({ "1", 1 });
operands.append({ "-1", -1 });
operands.append({ "42", 42 });
@@ -4755,6 +4756,201 @@
CHECK(isIdentical(compileAndRun<double>(proc, &value), static_cast<double>(static_cast<float>(value))));
}
+void testIToD64Arg()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Origin(), GPRInfo::argumentGPR0);
+ Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsDouble);
+
+ auto code = compile(proc);
+ for (auto testValue : int64Operands())
+ CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value)));
+}
+
+void testIToF64Arg()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Origin(), GPRInfo::argumentGPR0);
+ Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloat);
+
+ auto code = compile(proc);
+ for (auto testValue : int64Operands())
+ CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
+}
+
+void testIToD32Arg()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsDouble);
+
+ auto code = compile(proc);
+ for (auto testValue : int32Operands())
+ CHECK(isIdentical(invoke<double>(*code, testValue.value), static_cast<double>(testValue.value)));
+}
+
+void testIToF32Arg()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloat);
+
+ auto code = compile(proc);
+ for (auto testValue : int32Operands())
+ CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
+}
+
+void testIToD64Mem()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
+ Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsDouble);
+
+ auto code = compile(proc);
+ int64_t inMemoryValue;
+ for (auto testValue : int64Operands()) {
+ inMemoryValue = testValue.value;
+ CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value)));
+ CHECK(inMemoryValue == testValue.value);
+ }
+}
+
+void testIToF64Mem()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), address);
+ Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloat);
+
+ auto code = compile(proc);
+ int64_t inMemoryValue;
+ for (auto testValue : int64Operands()) {
+ inMemoryValue = testValue.value;
+ CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value)));
+ CHECK(inMemoryValue == testValue.value);
+ }
+}
+
+void testIToD32Mem()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
+ Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), loadedSrc);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsDouble);
+
+ auto code = compile(proc);
+ int32_t inMemoryValue;
+ for (auto testValue : int32Operands()) {
+ inMemoryValue = testValue.value;
+ CHECK(isIdentical(invoke<double>(*code, &inMemoryValue), static_cast<double>(testValue.value)));
+ CHECK(inMemoryValue == testValue.value);
+ }
+}
+
+void testIToF32Mem()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ MemoryValue* loadedSrc = root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), address);
+ Value* srcAsFloat = root->appendNew<Value>(proc, IToF, Origin(), loadedSrc);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloat);
+
+ auto code = compile(proc);
+ int32_t inMemoryValue;
+ for (auto testValue : int32Operands()) {
+ inMemoryValue = testValue.value;
+ CHECK(isIdentical(invoke<float>(*code, &inMemoryValue), static_cast<float>(testValue.value)));
+ CHECK(inMemoryValue == testValue.value);
+ }
+}
+
+void testIToD64Imm(int64_t value)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Origin(), value);
+ Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloatingPoint);
+ CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
+}
+
+void testIToF64Imm(int64_t value)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Origin(), value);
+ Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloatingPoint);
+ CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
+}
+
+void testIToD32Imm(int32_t value)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Origin(), value);
+ Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToD, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloatingPoint);
+ CHECK(isIdentical(compileAndRun<double>(proc), static_cast<double>(value)));
+}
+
+void testIToF32Imm(int32_t value)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Origin(), value);
+ Value* srcAsFloatingPoint = root->appendNew<Value>(proc, IToF, Origin(), src);
+ root->appendNew<ControlValue>(proc, Return, Origin(), srcAsFloatingPoint);
+ CHECK(isIdentical(compileAndRun<float>(proc), static_cast<float>(value)));
+}
+
+void testIToDReducedToIToF64Arg()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Origin(), GPRInfo::argumentGPR0);
+ Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
+ Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble);
+ root->appendNew<ControlValue>(proc, Return, Origin(), floatResult);
+
+ auto code = compile(proc);
+ for (auto testValue : int64Operands())
+ CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
+}
+
+void testIToDReducedToIToF32Arg()
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* src = "" Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* srcAsDouble = root->appendNew<Value>(proc, IToD, Origin(), src);
+ Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), srcAsDouble);
+ root->appendNew<ControlValue>(proc, Return, Origin(), floatResult);
+
+ auto code = compile(proc);
+ for (auto testValue : int32Operands())
+ CHECK(isIdentical(invoke<float>(*code, testValue.value), static_cast<float>(testValue.value)));
+}
+
void testStore32(int value)
{
Procedure proc;
@@ -12540,6 +12736,21 @@
RUN_UNARY(testFroundArg, floatingPointOperands<double>());
RUN_UNARY(testFroundMem, floatingPointOperands<double>());
+ RUN(testIToD64Arg());
+ RUN(testIToF64Arg());
+ RUN(testIToD32Arg());
+ RUN(testIToF32Arg());
+ RUN(testIToD64Mem());
+ RUN(testIToF64Mem());
+ RUN(testIToD32Mem());
+ RUN(testIToF32Mem());
+ RUN_UNARY(testIToD64Imm, int64Operands());
+ RUN_UNARY(testIToF64Imm, int64Operands());
+ RUN_UNARY(testIToD32Imm, int32Operands());
+ RUN_UNARY(testIToF32Imm, int32Operands());
+ RUN(testIToDReducedToIToF64Arg());
+ RUN(testIToDReducedToIToF32Arg());
+
RUN(testStore32(44));
RUN(testStoreConstant(49));
RUN(testStoreConstantPtr(49));