<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[193683] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/193683">193683</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2015-12-07 18:56:16 -0800 (Mon, 07 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Add Float support to B3
https://bugs.webkit.org/show_bug.cgi?id=151974

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2015-12-07
Reviewed by Filip Pizlo.

This patch adds comprehensive float support to B3.

The new phase reduceDoubleToFloat() gives us a primitive
version of what LLVM was giving us on floats.
It needs to support conversions accross Phis but that can
be added later.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/MacroAssembler.h:
(JSC::MacroAssembler::moveDoubleConditionallyFloat):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::sqrtFloat):
(JSC::MacroAssemblerX86Common::loadFloat):
(JSC::MacroAssemblerX86Common::storeFloat):
(JSC::MacroAssemblerX86Common::convertDoubleToFloat):
(JSC::MacroAssemblerX86Common::convertFloatToDouble):
(JSC::MacroAssemblerX86Common::addFloat):
(JSC::MacroAssemblerX86Common::divFloat):
(JSC::MacroAssemblerX86Common::subFloat):
(JSC::MacroAssemblerX86Common::mulFloat):
(JSC::MacroAssemblerX86Common::branchDouble):
(JSC::MacroAssemblerX86Common::branchFloat):
(JSC::MacroAssemblerX86Common::moveConditionallyDouble):
(JSC::MacroAssemblerX86Common::moveConditionallyFloat):
(JSC::MacroAssemblerX86Common::jumpAfterFloatingPointCompare):
(JSC::MacroAssemblerX86Common::moveConditionallyAfterFloatingPointCompare):
* assembler/X86Assembler.h:
(JSC::X86Assembler::addss_rr):
(JSC::X86Assembler::addss_mr):
(JSC::X86Assembler::cvtsd2ss_mr):
(JSC::X86Assembler::cvtss2sd_mr):
(JSC::X86Assembler::movss_rm):
(JSC::X86Assembler::movss_mr):
(JSC::X86Assembler::mulss_rr):
(JSC::X86Assembler::mulss_mr):
(JSC::X86Assembler::subss_rr):
(JSC::X86Assembler::subss_mr):
(JSC::X86Assembler::ucomiss_rr):
(JSC::X86Assembler::ucomiss_mr):
(JSC::X86Assembler::divss_rr):
(JSC::X86Assembler::divss_mr):
(JSC::X86Assembler::sqrtss_rr):
(JSC::X86Assembler::sqrtss_mr):
* b3/B3Const32Value.cpp:
(JSC::B3::Const32Value::bitwiseCastConstant):
* b3/B3Const32Value.h:
* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::doubleToFloatConstant):
(JSC::B3::ConstDoubleValue::sqrtConstant):
* b3/B3ConstDoubleValue.h:
* b3/B3ConstFloatValue.cpp: Added.
(JSC::B3::ConstFloatValue::~ConstFloatValue):
(JSC::B3::ConstFloatValue::negConstant):
(JSC::B3::ConstFloatValue::addConstant):
(JSC::B3::ConstFloatValue::subConstant):
(JSC::B3::ConstFloatValue::mulConstant):
(JSC::B3::ConstFloatValue::bitwiseCastConstant):
(JSC::B3::ConstFloatValue::floatToDoubleConstant):
(JSC::B3::ConstFloatValue::sqrtConstant):
(JSC::B3::ConstFloatValue::divConstant):
(JSC::B3::ConstFloatValue::equalConstant):
(JSC::B3::ConstFloatValue::notEqualConstant):
(JSC::B3::ConstFloatValue::lessThanConstant):
(JSC::B3::ConstFloatValue::greaterThanConstant):
(JSC::B3::ConstFloatValue::lessEqualConstant):
(JSC::B3::ConstFloatValue::greaterEqualConstant):
(JSC::B3::ConstFloatValue::dumpMeta):
* b3/B3ConstFloatValue.h: Copied from Source/JavaScriptCore/b3/B3ConstDoubleValue.h.
* b3/B3Generate.cpp:
(JSC::B3::generateToAir):
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::tryOpcodeForType):
(JSC::B3::Air::LowerToAir::opcodeForType):
(JSC::B3::Air::LowerToAir::appendUnOp):
(JSC::B3::Air::LowerToAir::appendBinOp):
(JSC::B3::Air::LowerToAir::appendShift):
(JSC::B3::Air::LowerToAir::tryAppendStoreUnOp):
(JSC::B3::Air::LowerToAir::tryAppendStoreBinOp):
(JSC::B3::Air::LowerToAir::moveForType):
(JSC::B3::Air::LowerToAir::relaxedMoveForType):
(JSC::B3::Air::LowerToAir::createGenericCompare):
(JSC::B3::Air::LowerToAir::createBranch):
(JSC::B3::Air::LowerToAir::createCompare):
(JSC::B3::Air::LowerToAir::createSelect):
(JSC::B3::Air::LowerToAir::lower):
* b3/B3MemoryValue.cpp:
(JSC::B3::MemoryValue::accessByteSize): Deleted.
* b3/B3MemoryValue.h:
* b3/B3MoveConstants.cpp:
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::addIntConstant):
* b3/B3ReduceDoubleToFloat.cpp: Added.
(JSC::B3::reduceDoubleToFloat):
* b3/B3ReduceDoubleToFloat.h: Copied from Source/JavaScriptCore/b3/B3Type.cpp.
* b3/B3ReduceStrength.cpp:
* b3/B3Type.cpp:
(WTF::printInternal):
* b3/B3Type.h:
(JSC::B3::isFloat):
(JSC::B3::sizeofType):
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::doubleToFloatConstant):
(JSC::B3::Value::floatToDoubleConstant):
(JSC::B3::Value::sqrtConstant):
(JSC::B3::Value::asTriState):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::checkOpcode):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/B3ValueInlines.h:
(JSC::B3::Value::isConstant):
(JSC::B3::Value::hasFloat):
(JSC::B3::Value::asFloat):
(JSC::B3::Value::hasNumber):
(JSC::B3::Value::isNegativeZero):
(JSC::B3::Value::representableAs):
(JSC::B3::Value::asNumber):
* b3/B3ValueKey.cpp:
(JSC::B3::ValueKey::materialize):
* b3/B3ValueKey.h:
(JSC::B3::ValueKey::ValueKey):
(JSC::B3::ValueKey::floatValue):
* b3/air/AirArg.h:
(JSC::B3::Air::Arg::typeForB3Type):
(JSC::B3::Air::Arg::widthForB3Type):
* b3/air/AirFixPartialRegisterStalls.cpp:
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::testAddArgFloat):
(JSC::B3::testAddArgsFloat):
(JSC::B3::testAddArgImmFloat):
(JSC::B3::testAddImmArgFloat):
(JSC::B3::testAddImmsFloat):
(JSC::B3::testAddArgFloatWithUselessDoubleConversion):
(JSC::B3::testAddArgsFloatWithUselessDoubleConversion):
(JSC::B3::testAddArgsFloatWithEffectfulDoubleConversion):
(JSC::B3::testMulArgFloat):
(JSC::B3::testMulArgsFloat):
(JSC::B3::testMulArgImmFloat):
(JSC::B3::testMulImmArgFloat):
(JSC::B3::testMulImmsFloat):
(JSC::B3::testMulArgFloatWithUselessDoubleConversion):
(JSC::B3::testMulArgsFloatWithUselessDoubleConversion):
(JSC::B3::testMulArgsFloatWithEffectfulDoubleConversion):
(JSC::B3::testDivArgFloat):
(JSC::B3::testDivArgsFloat):
(JSC::B3::testDivArgImmFloat):
(JSC::B3::testDivImmArgFloat):
(JSC::B3::testDivImmsFloat):
(JSC::B3::testDivArgFloatWithUselessDoubleConversion):
(JSC::B3::testDivArgsFloatWithUselessDoubleConversion):
(JSC::B3::testDivArgsFloatWithEffectfulDoubleConversion):
(JSC::B3::testSubArgFloat):
(JSC::B3::testSubArgsFloat):
(JSC::B3::testSubArgImmFloat):
(JSC::B3::testSubImmArgFloat):
(JSC::B3::testSubImmsFloat):
(JSC::B3::testSubArgFloatWithUselessDoubleConversion):
(JSC::B3::testSubArgsFloatWithUselessDoubleConversion):
(JSC::B3::testSubArgsFloatWithEffectfulDoubleConversion):
(JSC::B3::testClzMem32):
(JSC::B3::testSqrtArg):
(JSC::B3::testSqrtImm):
(JSC::B3::testSqrtMem):
(JSC::B3::testSqrtArgWithUselessDoubleConversion):
(JSC::B3::testSqrtArgWithEffectfulDoubleConversion):
(JSC::B3::testDoubleArgToInt64BitwiseCast):
(JSC::B3::testDoubleImmToInt64BitwiseCast):
(JSC::B3::testTwoBitwiseCastOnDouble):
(JSC::B3::testBitwiseCastOnDoubleInMemory):
(JSC::B3::testInt64BArgToDoubleBitwiseCast):
(JSC::B3::testInt64BImmToDoubleBitwiseCast):
(JSC::B3::testTwoBitwiseCastOnInt64):
(JSC::B3::testBitwiseCastOnInt64InMemory):
(JSC::B3::testFloatImmToInt32BitwiseCast):
(JSC::B3::testBitwiseCastOnFloatInMemory):
(JSC::B3::testInt32BArgToFloatBitwiseCast):
(JSC::B3::testInt32BImmToFloatBitwiseCast):
(JSC::B3::testTwoBitwiseCastOnInt32):
(JSC::B3::testBitwiseCastOnInt32InMemory):
(JSC::B3::testConvertDoubleToFloatArg):
(JSC::B3::testConvertDoubleToFloatImm):
(JSC::B3::testConvertDoubleToFloatMem):
(JSC::B3::testConvertFloatToDoubleArg):
(JSC::B3::testConvertFloatToDoubleImm):
(JSC::B3::testConvertFloatToDoubleMem):
(JSC::B3::testConvertDoubleToFloatToDoubleToFloat):
(JSC::B3::testLoadFloatConvertDoubleConvertFloatStoreFloat):
(JSC::B3::testFroundArg):
(JSC::B3::testFroundMem):
(JSC::B3::testStore32):
(JSC::B3::modelLoad):
(JSC::B3::float&gt;):
(JSC::B3::double&gt;):
(JSC::B3::testLoad):
(JSC::B3::testStoreFloat):
(JSC::B3::testReturnFloat):
(JSC::B3::simpleFunctionFloat):
(JSC::B3::testCallSimpleFloat):
(JSC::B3::functionWithHellaFloatArguments):
(JSC::B3::testCallFunctionWithHellaFloatArguments):
(JSC::B3::testSelectCompareFloat):
(JSC::B3::testSelectCompareFloatToDouble):
(JSC::B3::testSelectDoubleCompareFloat):
(JSC::B3::testSelectFloatCompareFloat):
(JSC::B3::populateWithInterestingValues):
(JSC::B3::floatingPointOperands):
(JSC::B3::int64Operands):
(JSC::B3::run):
(JSC::B3::testStore): Deleted.
(JSC::B3::posInfinity): Deleted.
(JSC::B3::negInfinity): Deleted.
(JSC::B3::doubleOperands): Deleted.
* ftl/FTLB3Output.cpp:
(JSC::FTL::Output::loadFloatToDouble):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::fround):
* ftl/FTLCommonValues.cpp:
(JSC::FTL::CommonValues::CommonValues):
* ftl/FTLCommonValues.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/MacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerX86Assemblerh">trunk/Source/JavaScriptCore/assembler/X86Assembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const32Valuecpp">trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const32Valueh">trunk/Source/JavaScriptCore/b3/B3Const32Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstDoubleValuecpp">trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstDoubleValueh">trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Generatecpp">trunk/Source/JavaScriptCore/b3/B3Generate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerToAircpp">trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3MemoryValuecpp">trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3MemoryValueh">trunk/Source/JavaScriptCore/b3/B3MemoryValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3MoveConstantscpp">trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Opcodecpp">trunk/Source/JavaScriptCore/b3/B3Opcode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Opcodeh">trunk/Source/JavaScriptCore/b3/B3Opcode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedurecpp">trunk/Source/JavaScriptCore/b3/B3Procedure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp">trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Typecpp">trunk/Source/JavaScriptCore/b3/B3Type.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Typeh">trunk/Source/JavaScriptCore/b3/B3Type.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Validatecpp">trunk/Source/JavaScriptCore/b3/B3Validate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Valuecpp">trunk/Source/JavaScriptCore/b3/B3Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Valueh">trunk/Source/JavaScriptCore/b3/B3Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ValueInlinesh">trunk/Source/JavaScriptCore/b3/B3ValueInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ValueKeycpp">trunk/Source/JavaScriptCore/b3/B3ValueKey.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ValueKeyh">trunk/Source/JavaScriptCore/b3/B3ValueKey.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirArgh">trunk/Source/JavaScriptCore/b3/air/AirArg.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixPartialRegisterStallscpp">trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOpcodeopcodes">trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputcpp">trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputh">trunk/Source/JavaScriptCore/ftl/FTLB3Output.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCommonValuescpp">trunk/Source/JavaScriptCore/ftl/FTLCommonValues.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCommonValuesh">trunk/Source/JavaScriptCore/ftl/FTLCommonValues.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstFloatValuecpp">trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstFloatValueh">trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloatcpp">trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloath">trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -104,6 +104,7 @@
</span><span class="cx">     b3/B3Const32Value.cpp
</span><span class="cx">     b3/B3Const64Value.cpp
</span><span class="cx">     b3/B3ConstDoubleValue.cpp
</span><ins>+    b3/B3ConstFloatValue.cpp
</ins><span class="cx">     b3/B3ConstrainedValue.cpp
</span><span class="cx">     b3/B3ControlValue.cpp
</span><span class="cx">     b3/B3DataSection.cpp
</span><span class="lines">@@ -124,6 +125,7 @@
</span><span class="cx">     b3/B3PhaseScope.cpp
</span><span class="cx">     b3/B3PhiChildren.cpp
</span><span class="cx">     b3/B3Procedure.cpp
</span><ins>+    b3/B3ReduceDoubleToFloat.cpp
</ins><span class="cx">     b3/B3ReduceStrength.cpp
</span><span class="cx">     b3/B3StackmapGenerationParams.cpp
</span><span class="cx">     b3/B3StackmapSpecial.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -1,3 +1,237 @@
</span><ins>+2015-12-07  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Add Float support to B3
+        https://bugs.webkit.org/show_bug.cgi?id=151974
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds comprehensive float support to B3.
+
+        The new phase reduceDoubleToFloat() gives us a primitive
+        version of what LLVM was giving us on floats.
+        It needs to support conversions accross Phis but that can
+        be added later.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::moveDoubleConditionallyFloat):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::sqrtFloat):
+        (JSC::MacroAssemblerX86Common::loadFloat):
+        (JSC::MacroAssemblerX86Common::storeFloat):
+        (JSC::MacroAssemblerX86Common::convertDoubleToFloat):
+        (JSC::MacroAssemblerX86Common::convertFloatToDouble):
+        (JSC::MacroAssemblerX86Common::addFloat):
+        (JSC::MacroAssemblerX86Common::divFloat):
+        (JSC::MacroAssemblerX86Common::subFloat):
+        (JSC::MacroAssemblerX86Common::mulFloat):
+        (JSC::MacroAssemblerX86Common::branchDouble):
+        (JSC::MacroAssemblerX86Common::branchFloat):
+        (JSC::MacroAssemblerX86Common::moveConditionallyDouble):
+        (JSC::MacroAssemblerX86Common::moveConditionallyFloat):
+        (JSC::MacroAssemblerX86Common::jumpAfterFloatingPointCompare):
+        (JSC::MacroAssemblerX86Common::moveConditionallyAfterFloatingPointCompare):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::addss_rr):
+        (JSC::X86Assembler::addss_mr):
+        (JSC::X86Assembler::cvtsd2ss_mr):
+        (JSC::X86Assembler::cvtss2sd_mr):
+        (JSC::X86Assembler::movss_rm):
+        (JSC::X86Assembler::movss_mr):
+        (JSC::X86Assembler::mulss_rr):
+        (JSC::X86Assembler::mulss_mr):
+        (JSC::X86Assembler::subss_rr):
+        (JSC::X86Assembler::subss_mr):
+        (JSC::X86Assembler::ucomiss_rr):
+        (JSC::X86Assembler::ucomiss_mr):
+        (JSC::X86Assembler::divss_rr):
+        (JSC::X86Assembler::divss_mr):
+        (JSC::X86Assembler::sqrtss_rr):
+        (JSC::X86Assembler::sqrtss_mr):
+        * b3/B3Const32Value.cpp:
+        (JSC::B3::Const32Value::bitwiseCastConstant):
+        * b3/B3Const32Value.h:
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::doubleToFloatConstant):
+        (JSC::B3::ConstDoubleValue::sqrtConstant):
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3ConstFloatValue.cpp: Added.
+        (JSC::B3::ConstFloatValue::~ConstFloatValue):
+        (JSC::B3::ConstFloatValue::negConstant):
+        (JSC::B3::ConstFloatValue::addConstant):
+        (JSC::B3::ConstFloatValue::subConstant):
+        (JSC::B3::ConstFloatValue::mulConstant):
+        (JSC::B3::ConstFloatValue::bitwiseCastConstant):
+        (JSC::B3::ConstFloatValue::floatToDoubleConstant):
+        (JSC::B3::ConstFloatValue::sqrtConstant):
+        (JSC::B3::ConstFloatValue::divConstant):
+        (JSC::B3::ConstFloatValue::equalConstant):
+        (JSC::B3::ConstFloatValue::notEqualConstant):
+        (JSC::B3::ConstFloatValue::lessThanConstant):
+        (JSC::B3::ConstFloatValue::greaterThanConstant):
+        (JSC::B3::ConstFloatValue::lessEqualConstant):
+        (JSC::B3::ConstFloatValue::greaterEqualConstant):
+        (JSC::B3::ConstFloatValue::dumpMeta):
+        * b3/B3ConstFloatValue.h: Copied from Source/JavaScriptCore/b3/B3ConstDoubleValue.h.
+        * b3/B3Generate.cpp:
+        (JSC::B3::generateToAir):
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::tryOpcodeForType):
+        (JSC::B3::Air::LowerToAir::opcodeForType):
+        (JSC::B3::Air::LowerToAir::appendUnOp):
+        (JSC::B3::Air::LowerToAir::appendBinOp):
+        (JSC::B3::Air::LowerToAir::appendShift):
+        (JSC::B3::Air::LowerToAir::tryAppendStoreUnOp):
+        (JSC::B3::Air::LowerToAir::tryAppendStoreBinOp):
+        (JSC::B3::Air::LowerToAir::moveForType):
+        (JSC::B3::Air::LowerToAir::relaxedMoveForType):
+        (JSC::B3::Air::LowerToAir::createGenericCompare):
+        (JSC::B3::Air::LowerToAir::createBranch):
+        (JSC::B3::Air::LowerToAir::createCompare):
+        (JSC::B3::Air::LowerToAir::createSelect):
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3MemoryValue.cpp:
+        (JSC::B3::MemoryValue::accessByteSize): Deleted.
+        * b3/B3MemoryValue.h:
+        * b3/B3MoveConstants.cpp:
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3Procedure.cpp:
+        (JSC::B3::Procedure::addIntConstant):
+        * b3/B3ReduceDoubleToFloat.cpp: Added.
+        (JSC::B3::reduceDoubleToFloat):
+        * b3/B3ReduceDoubleToFloat.h: Copied from Source/JavaScriptCore/b3/B3Type.cpp.
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Type.cpp:
+        (WTF::printInternal):
+        * b3/B3Type.h:
+        (JSC::B3::isFloat):
+        (JSC::B3::sizeofType):
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::doubleToFloatConstant):
+        (JSC::B3::Value::floatToDoubleConstant):
+        (JSC::B3::Value::sqrtConstant):
+        (JSC::B3::Value::asTriState):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::checkOpcode):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/B3ValueInlines.h:
+        (JSC::B3::Value::isConstant):
+        (JSC::B3::Value::hasFloat):
+        (JSC::B3::Value::asFloat):
+        (JSC::B3::Value::hasNumber):
+        (JSC::B3::Value::isNegativeZero):
+        (JSC::B3::Value::representableAs):
+        (JSC::B3::Value::asNumber):
+        * b3/B3ValueKey.cpp:
+        (JSC::B3::ValueKey::materialize):
+        * b3/B3ValueKey.h:
+        (JSC::B3::ValueKey::ValueKey):
+        (JSC::B3::ValueKey::floatValue):
+        * b3/air/AirArg.h:
+        (JSC::B3::Air::Arg::typeForB3Type):
+        (JSC::B3::Air::Arg::widthForB3Type):
+        * b3/air/AirFixPartialRegisterStalls.cpp:
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::testAddArgFloat):
+        (JSC::B3::testAddArgsFloat):
+        (JSC::B3::testAddArgImmFloat):
+        (JSC::B3::testAddImmArgFloat):
+        (JSC::B3::testAddImmsFloat):
+        (JSC::B3::testAddArgFloatWithUselessDoubleConversion):
+        (JSC::B3::testAddArgsFloatWithUselessDoubleConversion):
+        (JSC::B3::testAddArgsFloatWithEffectfulDoubleConversion):
+        (JSC::B3::testMulArgFloat):
+        (JSC::B3::testMulArgsFloat):
+        (JSC::B3::testMulArgImmFloat):
+        (JSC::B3::testMulImmArgFloat):
+        (JSC::B3::testMulImmsFloat):
+        (JSC::B3::testMulArgFloatWithUselessDoubleConversion):
+        (JSC::B3::testMulArgsFloatWithUselessDoubleConversion):
+        (JSC::B3::testMulArgsFloatWithEffectfulDoubleConversion):
+        (JSC::B3::testDivArgFloat):
+        (JSC::B3::testDivArgsFloat):
+        (JSC::B3::testDivArgImmFloat):
+        (JSC::B3::testDivImmArgFloat):
+        (JSC::B3::testDivImmsFloat):
+        (JSC::B3::testDivArgFloatWithUselessDoubleConversion):
+        (JSC::B3::testDivArgsFloatWithUselessDoubleConversion):
+        (JSC::B3::testDivArgsFloatWithEffectfulDoubleConversion):
+        (JSC::B3::testSubArgFloat):
+        (JSC::B3::testSubArgsFloat):
+        (JSC::B3::testSubArgImmFloat):
+        (JSC::B3::testSubImmArgFloat):
+        (JSC::B3::testSubImmsFloat):
+        (JSC::B3::testSubArgFloatWithUselessDoubleConversion):
+        (JSC::B3::testSubArgsFloatWithUselessDoubleConversion):
+        (JSC::B3::testSubArgsFloatWithEffectfulDoubleConversion):
+        (JSC::B3::testClzMem32):
+        (JSC::B3::testSqrtArg):
+        (JSC::B3::testSqrtImm):
+        (JSC::B3::testSqrtMem):
+        (JSC::B3::testSqrtArgWithUselessDoubleConversion):
+        (JSC::B3::testSqrtArgWithEffectfulDoubleConversion):
+        (JSC::B3::testDoubleArgToInt64BitwiseCast):
+        (JSC::B3::testDoubleImmToInt64BitwiseCast):
+        (JSC::B3::testTwoBitwiseCastOnDouble):
+        (JSC::B3::testBitwiseCastOnDoubleInMemory):
+        (JSC::B3::testInt64BArgToDoubleBitwiseCast):
+        (JSC::B3::testInt64BImmToDoubleBitwiseCast):
+        (JSC::B3::testTwoBitwiseCastOnInt64):
+        (JSC::B3::testBitwiseCastOnInt64InMemory):
+        (JSC::B3::testFloatImmToInt32BitwiseCast):
+        (JSC::B3::testBitwiseCastOnFloatInMemory):
+        (JSC::B3::testInt32BArgToFloatBitwiseCast):
+        (JSC::B3::testInt32BImmToFloatBitwiseCast):
+        (JSC::B3::testTwoBitwiseCastOnInt32):
+        (JSC::B3::testBitwiseCastOnInt32InMemory):
+        (JSC::B3::testConvertDoubleToFloatArg):
+        (JSC::B3::testConvertDoubleToFloatImm):
+        (JSC::B3::testConvertDoubleToFloatMem):
+        (JSC::B3::testConvertFloatToDoubleArg):
+        (JSC::B3::testConvertFloatToDoubleImm):
+        (JSC::B3::testConvertFloatToDoubleMem):
+        (JSC::B3::testConvertDoubleToFloatToDoubleToFloat):
+        (JSC::B3::testLoadFloatConvertDoubleConvertFloatStoreFloat):
+        (JSC::B3::testFroundArg):
+        (JSC::B3::testFroundMem):
+        (JSC::B3::testStore32):
+        (JSC::B3::modelLoad):
+        (JSC::B3::float&gt;):
+        (JSC::B3::double&gt;):
+        (JSC::B3::testLoad):
+        (JSC::B3::testStoreFloat):
+        (JSC::B3::testReturnFloat):
+        (JSC::B3::simpleFunctionFloat):
+        (JSC::B3::testCallSimpleFloat):
+        (JSC::B3::functionWithHellaFloatArguments):
+        (JSC::B3::testCallFunctionWithHellaFloatArguments):
+        (JSC::B3::testSelectCompareFloat):
+        (JSC::B3::testSelectCompareFloatToDouble):
+        (JSC::B3::testSelectDoubleCompareFloat):
+        (JSC::B3::testSelectFloatCompareFloat):
+        (JSC::B3::populateWithInterestingValues):
+        (JSC::B3::floatingPointOperands):
+        (JSC::B3::int64Operands):
+        (JSC::B3::run):
+        (JSC::B3::testStore): Deleted.
+        (JSC::B3::posInfinity): Deleted.
+        (JSC::B3::negInfinity): Deleted.
+        (JSC::B3::doubleOperands): Deleted.
+        * ftl/FTLB3Output.cpp:
+        (JSC::FTL::Output::loadFloatToDouble):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::fround):
+        * ftl/FTLCommonValues.cpp:
+        (JSC::FTL::CommonValues::CommonValues):
+        * ftl/FTLCommonValues.h:
+
</ins><span class="cx"> 2015-12-07  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         FTL B3 should be able to flag the tag constants as being super important so that B3 can hoist them and Air can force them into registers
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -1131,6 +1131,10 @@
</span><span class="cx">                 41DEA1321B9F3163006D65DD /* BuiltinUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DEA1311B9F3154006D65DD /* BuiltinUtils.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 4340A4841A9051AF00D73CCA /* MathCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4340A4821A9051AF00D73CCA /* MathCommon.cpp */; };
</span><span class="cx">                 4340A4851A9051AF00D73CCA /* MathCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 4340A4831A9051AF00D73CCA /* MathCommon.h */; };
</span><ins>+                43422A621C158E6A00E2EB98 /* B3ConstFloatValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43422A601C15871B00E2EB98 /* B3ConstFloatValue.cpp */; };
+                43422A631C158E6D00E2EB98 /* B3ConstFloatValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 43422A611C15871B00E2EB98 /* B3ConstFloatValue.h */; };
+                43422A661C16267500E2EB98 /* B3ReduceDoubleToFloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43422A641C16221E00E2EB98 /* B3ReduceDoubleToFloat.cpp */; };
+                43422A671C16267800E2EB98 /* B3ReduceDoubleToFloat.h in Headers */ = {isa = PBXBuildFile; fileRef = 43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */; };
</ins><span class="cx">                 4443AE3316E188D90076F110 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
</span><span class="cx">                 451539B912DC994500EF7AC4 /* Yarr.h in Headers */ = {isa = PBXBuildFile; fileRef = 451539B812DC994500EF7AC4 /* Yarr.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 52678F8E1A031009006A306D /* BasicBlockLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52678F8C1A031009006A306D /* BasicBlockLocation.cpp */; };
</span><span class="lines">@@ -1994,12 +1998,12 @@
</span><span class="cx">                 FE1220281BE7F5910039E6F2 /* JITAddGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1220251BE7F5640039E6F2 /* JITAddGenerator.cpp */; };
</span><span class="cx">                 FE187A011BFBE55E0038BBCA /* JITMulGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */; };
</span><span class="cx">                 FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */; };
</span><del>-                FE187A0D1C030D5C0038BBCA /* JITDivGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0B1C0229230038BBCA /* JITDivGenerator.h */; settings = {ASSET_TAGS = (); }; };
-                FE187A0E1C030D640038BBCA /* JITDivGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */; settings = {ASSET_TAGS = (); }; };
-                FE187A0F1C030D6C0038BBCA /* SnippetOperand.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */; settings = {ASSET_TAGS = (); }; };
-                FE187A181C0E13DD0038BBCA /* FTLInlineCacheDescriptorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A171C0E13C60038BBCA /* FTLInlineCacheDescriptorInlines.h */; settings = {ASSET_TAGS = (); }; };
-                FE187A191C0E13E30038BBCA /* FTLCompileBinaryOp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE187A151C0E13C60038BBCA /* FTLCompileBinaryOp.cpp */; settings = {ASSET_TAGS = (); }; };
-                FE187A1A1C0E13E60038BBCA /* FTLCompileBinaryOp.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A161C0E13C60038BBCA /* FTLCompileBinaryOp.h */; settings = {ASSET_TAGS = (); }; };
</del><ins>+                FE187A0D1C030D5C0038BBCA /* JITDivGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0B1C0229230038BBCA /* JITDivGenerator.h */; };
+                FE187A0E1C030D640038BBCA /* JITDivGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */; };
+                FE187A0F1C030D6C0038BBCA /* SnippetOperand.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */; };
+                FE187A181C0E13DD0038BBCA /* FTLInlineCacheDescriptorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A171C0E13C60038BBCA /* FTLInlineCacheDescriptorInlines.h */; };
+                FE187A191C0E13E30038BBCA /* FTLCompileBinaryOp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE187A151C0E13C60038BBCA /* FTLCompileBinaryOp.cpp */; };
+                FE187A1A1C0E13E60038BBCA /* FTLCompileBinaryOp.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A161C0E13C60038BBCA /* FTLCompileBinaryOp.h */; };
</ins><span class="cx">                 FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1C0FFC1B193E9800B53FCA /* Exception.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1C0FFE1B194FD100B53FCA /* Exception.cpp */; };
</span><span class="cx">                 FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE20CE9B15F04A9500DF3430 /* LLIntCLoop.cpp */; };
</span><span class="lines">@@ -3199,6 +3203,10 @@
</span><span class="cx">                 41DEA1311B9F3154006D65DD /* BuiltinUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinUtils.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4340A4821A9051AF00D73CCA /* MathCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathCommon.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4340A4831A9051AF00D73CCA /* MathCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathCommon.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                43422A601C15871B00E2EB98 /* B3ConstFloatValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ConstFloatValue.cpp; path = b3/B3ConstFloatValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                43422A611C15871B00E2EB98 /* B3ConstFloatValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ConstFloatValue.h; path = b3/B3ConstFloatValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                43422A641C16221E00E2EB98 /* B3ReduceDoubleToFloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ReduceDoubleToFloat.cpp; path = b3/B3ReduceDoubleToFloat.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ReduceDoubleToFloat.h; path = b3/B3ReduceDoubleToFloat.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 449097EE0F8F81B50076A327 /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 451539B812DC994500EF7AC4 /* Yarr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Yarr.h; path = yarr/Yarr.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 45E12D8806A49B0F00E9DF84 /* jsc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsc.cpp; sourceTree = &quot;&lt;group&gt;&quot;; tabWidth = 4; };
</span><span class="lines">@@ -4588,6 +4596,8 @@
</span><span class="cx">                                 0FEC84C61BDACDAC0080FF74 /* B3Const64Value.h */,
</span><span class="cx">                                 0FEC84C71BDACDAC0080FF74 /* B3ConstDoubleValue.cpp */,
</span><span class="cx">                                 0FEC84C81BDACDAC0080FF74 /* B3ConstDoubleValue.h */,
</span><ins>+                                43422A601C15871B00E2EB98 /* B3ConstFloatValue.cpp */,
+                                43422A611C15871B00E2EB98 /* B3ConstFloatValue.h */,
</ins><span class="cx">                                 0FEC85B21BDED9570080FF74 /* B3ConstPtrValue.h */,
</span><span class="cx">                                 0F338DF31BE93D550013C88F /* B3ConstrainedValue.cpp */,
</span><span class="cx">                                 0F338DF41BE93D550013C88F /* B3ConstrainedValue.h */,
</span><span class="lines">@@ -4596,6 +4606,8 @@
</span><span class="cx">                                 0F338E011BF0276C0013C88F /* B3DataSection.cpp */,
</span><span class="cx">                                 0F338E021BF0276C0013C88F /* B3DataSection.h */,
</span><span class="cx">                                 0F33FCFA1C1625BE00323F67 /* B3Dominators.h */,
</span><ins>+                                43422A641C16221E00E2EB98 /* B3ReduceDoubleToFloat.cpp */,
+                                43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */,
</ins><span class="cx">                                 0FEC85C41BE16F5A0080FF74 /* B3Effects.cpp */,
</span><span class="cx">                                 0FEC85BE1BE167A00080FF74 /* B3Effects.h */,
</span><span class="cx">                                 0FEC84CB1BDACDAC0080FF74 /* B3FrequencyClass.cpp */,
</span><span class="lines">@@ -7002,6 +7014,7 @@
</span><span class="cx">                                 0F2B9CE319D0BA7D00B1D1B5 /* DFGAvailabilityMap.h in Headers */,
</span><span class="cx">                                 0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */,
</span><span class="cx">                                 0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */,
</span><ins>+                                43422A631C158E6D00E2EB98 /* B3ConstFloatValue.h in Headers */,
</ins><span class="cx">                                 0FFB921A16D02EC50055A5DB /* DFGBasicBlockInlines.h in Headers */,
</span><span class="cx">                                 A7D89CF417A0B8CC00773AD8 /* DFGBlockInsertionSet.h in Headers */,
</span><span class="cx">                                 0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */,
</span><span class="lines">@@ -7603,6 +7616,7 @@
</span><span class="cx">                                 0F4680CD14BBB17D00BFE272 /* LowLevelInterpreter.h in Headers */,
</span><span class="cx">                                 14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */,
</span><span class="cx">                                 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */,
</span><ins>+                                43422A671C16267800E2EB98 /* B3ReduceDoubleToFloat.h in Headers */,
</ins><span class="cx">                                 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */,
</span><span class="cx">                                 A1A009C01831A22D00CF8711 /* MacroAssemblerARM64.h in Headers */,
</span><span class="cx">                                 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */,
</span><span class="lines">@@ -8403,6 +8417,7 @@
</span><span class="cx">                                 0FFA549716B8835000B3A982 /* A64DOpcode.cpp in Sources */,
</span><span class="cx">                                 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */,
</span><span class="cx">                                 0FEC856D1BDACDC70080FF74 /* AirAllocateStack.cpp in Sources */,
</span><ins>+                                43422A661C16267500E2EB98 /* B3ReduceDoubleToFloat.cpp in Sources */,
</ins><span class="cx">                                 0FEC856F1BDACDC70080FF74 /* AirArg.cpp in Sources */,
</span><span class="cx">                                 0FEC85711BDACDC70080FF74 /* AirBasicBlock.cpp in Sources */,
</span><span class="cx">                                 0FEC85731BDACDC70080FF74 /* AirCCallSpecial.cpp in Sources */,
</span><span class="lines">@@ -8458,6 +8473,7 @@
</span><span class="cx">                                 0FEC85271BDACDAC0080FF74 /* B3PatchpointValue.cpp in Sources */,
</span><span class="cx">                                 0FEC85291BDACDAC0080FF74 /* B3PhaseScope.cpp in Sources */,
</span><span class="cx">                                 0FEC852B1BDACDAC0080FF74 /* B3Procedure.cpp in Sources */,
</span><ins>+                                43422A621C158E6A00E2EB98 /* B3ConstFloatValue.cpp in Sources */,
</ins><span class="cx">                                 0FEC85BC1BE1462F0080FF74 /* B3ReduceStrength.cpp in Sources */,
</span><span class="cx">                                 0FEC85301BDACDAC0080FF74 /* B3StackmapSpecial.cpp in Sources */,
</span><span class="cx">                                 0FEC85321BDACDAC0080FF74 /* B3StackSlotKind.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssembler.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -1356,6 +1356,13 @@
</span><span class="cx">         moveDouble(src, dest);
</span><span class="cx">         falseCase.link(this);
</span><span class="cx">     }
</span><ins>+
+    void moveDoubleConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, FPRegisterID src, FPRegisterID dest)
+    {
+        Jump falseCase = branchFloat(invert(cond), left, right);
+        moveDouble(src, dest);
+        falseCase.link(this);
+    }
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void lea(Address address, RegisterID dest)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">         NonZero = X86Assembler::ConditionNE
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    // FIXME: it would be neat to rename this to FloatingPointCondition in every assembler.
</ins><span class="cx">     enum DoubleCondition {
</span><span class="cx">         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
</span><span class="cx">         DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
</span><span class="lines">@@ -523,6 +524,16 @@
</span><span class="cx">         m_assembler.sqrtsd_mr(src.offset, src.base, dst);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void sqrtFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.sqrtss_rr(src, dst);
+    }
+
+    void sqrtFloat(Address src, FPRegisterID dst)
+    {
+        m_assembler.sqrtss_mr(src.offset, src.base, dst);
+    }
+
</ins><span class="cx">     void absDouble(FPRegisterID src, FPRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(src != dst);
</span><span class="lines">@@ -779,12 +790,19 @@
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="cx">         m_assembler.movsd_mr(address.offset, address.base, dest);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     void loadDouble(BaseIndex address, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="cx">         m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
</span><span class="cx">     }
</span><ins>+
+    void loadFloat(ImplicitAddress address, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movss_mr(address.offset, address.base, dest);
+    }
+
</ins><span class="cx">     void loadFloat(BaseIndex address, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="lines">@@ -802,7 +820,13 @@
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="cx">         m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    void storeFloat(FPRegisterID src, ImplicitAddress address)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movss_rm(src, address.offset, address.base);
+    }
+
</ins><span class="cx">     void storeFloat(FPRegisterID src, BaseIndex address)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="lines">@@ -815,12 +839,24 @@
</span><span class="cx">         m_assembler.cvtsd2ss_rr(src, dst);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void convertDoubleToFloat(Address address, FPRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvtsd2ss_mr(address.offset, address.base, dst);
+    }
+
</ins><span class="cx">     void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="cx">         m_assembler.cvtss2sd_rr(src, dst);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void convertFloatToDouble(Address address, FPRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvtss2sd_mr(address.offset, address.base, dst);
+    }
+
</ins><span class="cx">     void addDouble(FPRegisterID src, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="lines">@@ -844,6 +880,18 @@
</span><span class="cx">         m_assembler.addsd_mr(src.offset, src.base, dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void addFloat(FPRegisterID src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.addss_rr(src, dest);
+    }
+
+    void addFloat(Address src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.addss_mr(src.offset, src.base, dest);
+    }
+
</ins><span class="cx">     void divDouble(FPRegisterID src, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="lines">@@ -865,6 +913,18 @@
</span><span class="cx">         m_assembler.divsd_mr(src.offset, src.base, dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void divFloat(FPRegisterID src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.divss_rr(src, dest);
+    }
+
+    void divFloat(Address src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.divss_mr(src.offset, src.base, dest);
+    }
+
</ins><span class="cx">     void subDouble(FPRegisterID src, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="lines">@@ -886,6 +946,18 @@
</span><span class="cx">         m_assembler.subsd_mr(src.offset, src.base, dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void subFloat(FPRegisterID src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.subss_rr(src, dest);
+    }
+
+    void subFloat(Address src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.subss_mr(src.offset, src.base, dest);
+    }
+
</ins><span class="cx">     void mulDouble(FPRegisterID src, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="lines">@@ -909,6 +981,18 @@
</span><span class="cx">         m_assembler.mulsd_mr(src.offset, src.base, dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void mulFloat(FPRegisterID src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.mulss_rr(src, dest);
+    }
+
+    void mulFloat(Address src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.mulss_mr(src.offset, src.base, dest);
+    }
+
</ins><span class="cx">     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span><span class="lines">@@ -929,27 +1013,18 @@
</span><span class="cx">             m_assembler.ucomisd_rr(left, right);
</span><span class="cx">         else
</span><span class="cx">             m_assembler.ucomisd_rr(right, left);
</span><ins>+        return jumpAfterFloatingPointCompare(cond, left, right);
+    }
</ins><span class="cx"> 
</span><del>-        if (cond == DoubleEqual) {
-            if (left == right)
-                return Jump(m_assembler.jnp());
-            Jump isUnordered(m_assembler.jp());
-            Jump result = Jump(m_assembler.je());
-            isUnordered.link(this);
-            return result;
-        } else if (cond == DoubleNotEqualOrUnordered) {
-            if (left == right)
-                return Jump(m_assembler.jp());
-            Jump isUnordered(m_assembler.jp());
-            Jump isEqual(m_assembler.je());
-            isUnordered.link(this);
-            Jump result = jump();
-            isEqual.link(this);
-            return result;
-        }
</del><ins>+    Jump branchFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
+    {
+        ASSERT(isSSE2Present());
</ins><span class="cx"> 
</span><del>-        ASSERT(!(cond &amp; DoubleConditionBitSpecial));
-        return Jump(m_assembler.jCC(static_cast&lt;X86Assembler::Condition&gt;(cond &amp; ~DoubleConditionBits)));
</del><ins>+        if (cond &amp; DoubleConditionBitInvert)
+            m_assembler.ucomiss_rr(left, right);
+        else
+            m_assembler.ucomiss_rr(right, left);
+        return jumpAfterFloatingPointCompare(cond, left, right);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Truncates 'src' to an integer, and places the resulting 'dest'.
</span><span class="lines">@@ -1126,32 +1201,18 @@
</span><span class="cx">             m_assembler.ucomisd_rr(left, right);
</span><span class="cx">         else
</span><span class="cx">             m_assembler.ucomisd_rr(right, left);
</span><ins>+        moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
+    }
</ins><span class="cx"> 
</span><del>-        if (cond == DoubleEqual) {
-            if (left == right) {
-                m_assembler.cmovnpq_rr(src, dest);
-                return;
-            }
</del><ins>+    void moveConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
+    {
+        ASSERT(isSSE2Present());
</ins><span class="cx"> 
</span><del>-            Jump isUnordered(m_assembler.jp());
-            m_assembler.cmoveq_rr(src, dest);
-            isUnordered.link(this);
-            return;
-        }
-
-        if (cond == DoubleNotEqualOrUnordered) {
-            if (left == right) {
-                m_assembler.cmovpq_rr(src, dest);
-                return;
-            }
-
-            m_assembler.cmovpq_rr(src, dest);
-            m_assembler.cmovneq_rr(src, dest);
-            return;
-        }
-
-        ASSERT(!(cond &amp; DoubleConditionBitSpecial));
-        m_assembler.cmovq_rr(static_cast&lt;X86Assembler::Condition&gt;(cond &amp; ~DoubleConditionBits), src, dest);
</del><ins>+        if (cond &amp; DoubleConditionBitInvert)
+            m_assembler.ucomiss_rr(left, right);
+        else
+            m_assembler.ucomiss_rr(right, left);
+        moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void swap(RegisterID reg1, RegisterID reg2)
</span><span class="lines">@@ -1797,6 +1858,62 @@
</span><span class="cx">         skipNonZeroCase.link(this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Jump jumpAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
+    {
+        if (cond == DoubleEqual) {
+            if (left == right)
+                return Jump(m_assembler.jnp());
+            Jump isUnordered(m_assembler.jp());
+            Jump result = Jump(m_assembler.je());
+            isUnordered.link(this);
+            return result;
+        }
+        if (cond == DoubleNotEqualOrUnordered) {
+            if (left == right)
+                return Jump(m_assembler.jp());
+            Jump isUnordered(m_assembler.jp());
+            Jump isEqual(m_assembler.je());
+            isUnordered.link(this);
+            Jump result = jump();
+            isEqual.link(this);
+            return result;
+        }
+
+        ASSERT(!(cond &amp; DoubleConditionBitSpecial));
+        return Jump(m_assembler.jCC(static_cast&lt;X86Assembler::Condition&gt;(cond &amp; ~DoubleConditionBits)));
+    }
+
+#if CPU(X86_64)
+    void moveConditionallyAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
+    {
+        if (cond == DoubleEqual) {
+            if (left == right) {
+                m_assembler.cmovnpq_rr(src, dest);
+                return;
+            }
+
+            Jump isUnordered(m_assembler.jp());
+            m_assembler.cmoveq_rr(src, dest);
+            isUnordered.link(this);
+            return;
+        }
+
+        if (cond == DoubleNotEqualOrUnordered) {
+            if (left == right) {
+                m_assembler.cmovpq_rr(src, dest);
+                return;
+            }
+
+            m_assembler.cmovpq_rr(src, dest);
+            m_assembler.cmovneq_rr(src, dest);
+            return;
+        }
+
+        ASSERT(!(cond &amp; DoubleConditionBitSpecial));
+        cmov(static_cast&lt;X86Assembler::Condition&gt;(cond &amp; ~DoubleConditionBits), src, dest);
+    }
+#endif
+
</ins><span class="cx"> #if CPU(X86)
</span><span class="cx"> #if OS(MAC_OS_X)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerX86Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/X86Assembler.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -1940,6 +1940,18 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void addss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+    }
+
+    void addss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
+    }
+
</ins><span class="cx"> #if !CPU(X86_64)
</span><span class="cx">     void addsd_mr(const void* address, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="lines">@@ -1988,12 +2000,24 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_CVTSD2SS_VsdWsd, dst, (RegisterID)src);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void cvtsd2ss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_CVTSD2SS_VsdWsd, dst, base, offset);
+    }
+
</ins><span class="cx">     void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F3);
</span><span class="cx">         m_formatter.twoByteOp(OP2_CVTSS2SD_VsdWsd, dst, (RegisterID)src);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    void cvtss2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_CVTSS2SD_VsdWsd, dst, base, offset);
+    }
+
</ins><span class="cx"> #if CPU(X86_64)
</span><span class="cx">     void cvttsd2siq_rr(XMMRegisterID src, RegisterID dst)
</span><span class="cx">     {
</span><span class="lines">@@ -2051,6 +2075,12 @@
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F2);
</span><span class="cx">         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
</span><span class="cx">     }
</span><ins>+
+    void movss_rm(XMMRegisterID src, int offset, RegisterID base)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
+    }
</ins><span class="cx">     
</span><span class="cx">     void movss_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
</span><span class="cx">     {
</span><span class="lines">@@ -2069,7 +2099,13 @@
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F2);
</span><span class="cx">         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, dst, base, index, scale, offset);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    void movss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
+    }
+
</ins><span class="cx">     void movss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F3);
</span><span class="lines">@@ -2101,6 +2137,18 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void mulss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+    }
+
+    void mulss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset);
+    }
+
</ins><span class="cx">     void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_66);
</span><span class="lines">@@ -2140,6 +2188,18 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void subss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+    }
+
+    void subss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset);
+    }
+
</ins><span class="cx">     void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_66);
</span><span class="lines">@@ -2152,6 +2212,16 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, base, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void ucomiss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+    }
+
+    void ucomiss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, base, offset);
+    }
+
</ins><span class="cx">     void divsd_rr(XMMRegisterID src, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.prefix(PRE_SSE_F2);
</span><span class="lines">@@ -2164,6 +2234,18 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, base, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void divss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+    }
+
+    void divss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, base, offset);
+    }
+
</ins><span class="cx">     void xorps_rr(XMMRegisterID src, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
</span><span class="lines">@@ -2197,6 +2279,18 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, base, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void sqrtss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+    }
+
+    void sqrtss_mr(int offset, RegisterID base, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, base, offset);
+    }
+
</ins><span class="cx">     // Misc instructions:
</span><span class="cx"> 
</span><span class="cx">     void int3()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const32Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -154,6 +154,11 @@
</span><span class="cx">     return proc.add&lt;Const32Value&gt;(origin(), static_cast&lt;int32_t&gt;(static_cast&lt;uint32_t&gt;(m_value) &gt;&gt; (other-&gt;asInt32() &amp; 31)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* Const32Value::bitwiseCastConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstFloatValue&gt;(origin(), bitwise_cast&lt;float&gt;(m_value));
+}
+
</ins><span class="cx"> TriState Const32Value::equalConstant(const Value* other) const
</span><span class="cx"> {
</span><span class="cx">     if (!other-&gt;hasInt32())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const32Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const32Value.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const32Value.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Const32Value.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx">     Value* shlConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* sShrConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* zShrConstant(Procedure&amp;, const Value* other) const override;
</span><ins>+    Value* bitwiseCastConstant(Procedure&amp;) const override;
</ins><span class="cx"> 
</span><span class="cx">     TriState equalConstant(const Value* other) const override;
</span><span class="cx">     TriState notEqualConstant(const Value* other) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3ConstFloatValue.h&quot;
</ins><span class="cx"> #include &quot;B3ProcedureInlines.h&quot;
</span><span class="cx"> #include &quot;B3ValueInlines.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -73,6 +74,16 @@
</span><span class="cx">     return proc.add&lt;Const64Value&gt;(origin(), bitwise_cast&lt;int64_t&gt;(m_value));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* ConstDoubleValue::doubleToFloatConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstFloatValue&gt;(origin(), static_cast&lt;float&gt;(m_value));
+}
+
+Value* ConstDoubleValue::sqrtConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstDoubleValue&gt;(origin(), sqrt(m_value));
+}
+
</ins><span class="cx"> Value* ConstDoubleValue::divConstant(Procedure&amp; proc, const Value* other) const
</span><span class="cx"> {
</span><span class="cx">     if (!other-&gt;hasDouble())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -47,6 +47,8 @@
</span><span class="cx">     Value* divConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* mulConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* bitwiseCastConstant(Procedure&amp;) const override;
</span><ins>+    Value* doubleToFloatConstant(Procedure&amp;) const override;
+    Value* sqrtConstant(Procedure&amp;) const override;
</ins><span class="cx"> 
</span><span class="cx">     TriState equalConstant(const Value* other) const override;
</span><span class="cx">     TriState notEqualConstant(const Value* other) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstFloatValuecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp (0 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -0,0 +1,144 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;B3ConstFloatValue.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;B3ConstDoubleValue.h&quot;
+#include &quot;B3ProcedureInlines.h&quot;
+#include &quot;B3ValueInlines.h&quot;
+
+namespace JSC { namespace B3 {
+
+ConstFloatValue::~ConstFloatValue()
+{
+}
+
+Value* ConstFloatValue::negConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstFloatValue&gt;(origin(), -m_value);
+}
+
+Value* ConstFloatValue::addConstant(Procedure&amp; proc, int32_t other) const
+{
+    return proc.add&lt;ConstFloatValue&gt;(origin(), m_value + static_cast&lt;float&gt;(other));
+}
+
+Value* ConstFloatValue::addConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return nullptr;
+    return proc.add&lt;ConstFloatValue&gt;(origin(), m_value + other-&gt;asFloat());
+}
+
+Value* ConstFloatValue::subConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return nullptr;
+    return proc.add&lt;ConstFloatValue&gt;(origin(), m_value - other-&gt;asFloat());
+}
+
+Value* ConstFloatValue::mulConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return nullptr;
+    return proc.add&lt;ConstFloatValue&gt;(origin(), m_value * other-&gt;asFloat());
+}
+
+Value* ConstFloatValue::bitwiseCastConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;Const32Value&gt;(origin(), bitwise_cast&lt;int32_t&gt;(m_value));
+}
+
+Value* ConstFloatValue::floatToDoubleConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstDoubleValue&gt;(origin(), static_cast&lt;double&gt;(m_value));
+}
+
+Value* ConstFloatValue::sqrtConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstFloatValue&gt;(origin(), static_cast&lt;float&gt;(sqrt(m_value)));
+}
+
+Value* ConstFloatValue::divConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return nullptr;
+    return proc.add&lt;ConstFloatValue&gt;(origin(), m_value / other-&gt;asFloat());
+}
+
+TriState ConstFloatValue::equalConstant(const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return MixedTriState;
+    return triState(m_value == other-&gt;asFloat());
+}
+
+TriState ConstFloatValue::notEqualConstant(const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return MixedTriState;
+    return triState(m_value != other-&gt;asFloat());
+}
+
+TriState ConstFloatValue::lessThanConstant(const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return MixedTriState;
+    return triState(m_value &lt; other-&gt;asFloat());
+}
+
+TriState ConstFloatValue::greaterThanConstant(const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return MixedTriState;
+    return triState(m_value &gt; other-&gt;asFloat());
+}
+
+TriState ConstFloatValue::lessEqualConstant(const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return MixedTriState;
+    return triState(m_value &lt;= other-&gt;asFloat());
+}
+
+TriState ConstFloatValue::greaterEqualConstant(const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return MixedTriState;
+    return triState(m_value &gt;= other-&gt;asFloat());
+}
+
+void ConstFloatValue::dumpMeta(CommaPrinter&amp; comma, PrintStream&amp; out) const
+{
+    out.print(comma);
+    out.printf(&quot;%le&quot;, m_value);
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstFloatValueh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h (0 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -0,0 +1,80 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef B3ConstFloatValue_h
+#define B3ConstFloatValue_h
+
+#if ENABLE(B3_JIT)
+
+#include &quot;B3Value.h&quot;
+
+namespace JSC { namespace B3 {
+
+class JS_EXPORT_PRIVATE ConstFloatValue : public Value {
+public:
+    static bool accepts(Opcode opcode) { return opcode == ConstFloat; }
+
+    ~ConstFloatValue();
+
+    float value() const { return m_value; }
+
+    Value* negConstant(Procedure&amp;) const override;
+    Value* addConstant(Procedure&amp;, int32_t other) const override;
+    Value* addConstant(Procedure&amp;, const Value* other) const override;
+    Value* subConstant(Procedure&amp;, const Value* other) const override;
+    Value* divConstant(Procedure&amp;, const Value* other) const override;
+    Value* mulConstant(Procedure&amp;, const Value* other) const override;
+    Value* bitwiseCastConstant(Procedure&amp;) const override;
+    Value* floatToDoubleConstant(Procedure&amp;) const override;
+    Value* sqrtConstant(Procedure&amp;) const override;
+
+    TriState equalConstant(const Value* other) const override;
+    TriState notEqualConstant(const Value* other) const override;
+    TriState lessThanConstant(const Value* other) const override;
+    TriState greaterThanConstant(const Value* other) const override;
+    TriState lessEqualConstant(const Value* other) const override;
+    TriState greaterEqualConstant(const Value* other) const override;
+
+protected:
+    void dumpMeta(CommaPrinter&amp;, PrintStream&amp;) const override;
+
+private:
+    friend class Procedure;
+
+    ConstFloatValue(unsigned index, Origin origin, float value)
+        : Value(index, CheckedOpcode, ConstFloat, Float, origin)
+        , m_value(value)
+    {
+    }
+
+    float m_value;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3ConstFloatValue_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Generatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Generate.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;B3LowerToAir.h&quot;
</span><span class="cx"> #include &quot;B3MoveConstants.h&quot;
</span><span class="cx"> #include &quot;B3Procedure.h&quot;
</span><ins>+#include &quot;B3ReduceDoubleToFloat.h&quot;
</ins><span class="cx"> #include &quot;B3ReduceStrength.h&quot;
</span><span class="cx"> #include &quot;B3TimingScope.h&quot;
</span><span class="cx"> #include &quot;B3Validate.h&quot;
</span><span class="lines">@@ -73,6 +74,8 @@
</span><span class="cx">     lowerMacros(procedure);
</span><span class="cx"> 
</span><span class="cx">     if (optLevel &gt;= 1) {
</span><ins>+        reduceDoubleToFloat(procedure);
+
</ins><span class="cx">         reduceStrength(procedure);
</span><span class="cx">         
</span><span class="cx">         // FIXME: Add more optimizations here.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -478,7 +478,7 @@
</span><span class="cx"> 
</span><span class="cx">     // By convention, we use Oops to mean &quot;I don't know&quot;.
</span><span class="cx">     Air::Opcode tryOpcodeForType(
</span><del>-        Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble, Type type)
</del><ins>+        Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble, Air::Opcode opcodeFloat, Type type)
</ins><span class="cx">     {
</span><span class="cx">         Air::Opcode opcode;
</span><span class="cx">         switch (type) {
</span><span class="lines">@@ -488,6 +488,9 @@
</span><span class="cx">         case Int64:
</span><span class="cx">             opcode = opcode64;
</span><span class="cx">             break;
</span><ins>+        case Float:
+            opcode = opcodeFloat;
+            break;
</ins><span class="cx">         case Double:
</span><span class="cx">             opcode = opcodeDouble;
</span><span class="cx">             break;
</span><span class="lines">@@ -499,18 +502,28 @@
</span><span class="cx">         return opcode;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Air::Opcode tryOpcodeForType(Air::Opcode opcode32, Air::Opcode opcode64, Type type)
+    {
+        return tryOpcodeForType(opcode32, opcode64, Air::Oops, Air::Oops, type);
+    }
+
</ins><span class="cx">     Air::Opcode opcodeForType(
</span><del>-        Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble, Type type)
</del><ins>+        Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble, Air::Opcode opcodeFloat, Type type)
</ins><span class="cx">     {
</span><del>-        Air::Opcode opcode = tryOpcodeForType(opcode32, opcode64, opcodeDouble, type);
</del><ins>+        Air::Opcode opcode = tryOpcodeForType(opcode32, opcode64, opcodeDouble, opcodeFloat, type);
</ins><span class="cx">         RELEASE_ASSERT(opcode != Air::Oops);
</span><span class="cx">         return opcode;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    template&lt;Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble&gt;
</del><ins>+    Air::Opcode opcodeForType(Air::Opcode opcode32, Air::Opcode opcode64, Type type)
+    {
+        return tryOpcodeForType(opcode32, opcode64, Air::Oops, Air::Oops, type);
+    }
+
+    template&lt;Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble = Air::Oops, Air::Opcode opcodeFloat = Air::Oops&gt;
</ins><span class="cx">     void appendUnOp(Value* value)
</span><span class="cx">     {
</span><del>-        Air::Opcode opcode = opcodeForType(opcode32, opcode64, opcodeDouble, value-&gt;type());
</del><ins>+        Air::Opcode opcode = opcodeForType(opcode32, opcode64, opcodeDouble, opcodeFloat, value-&gt;type());
</ins><span class="cx">         
</span><span class="cx">         Tmp result = tmp(m_value);
</span><span class="cx"> 
</span><span class="lines">@@ -565,12 +578,10 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    template&lt;
-        Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble,
-        Commutativity commutativity = NotCommutative&gt;
</del><ins>+    template&lt;Air::Opcode opcode32, Air::Opcode opcode64, Air::Opcode opcodeDouble, Air::Opcode opcodeFloat, Commutativity commutativity = NotCommutative&gt;
</ins><span class="cx">     void appendBinOp(Value* left, Value* right)
</span><span class="cx">     {
</span><del>-        Air::Opcode opcode = opcodeForType(opcode32, opcode64, opcodeDouble, left-&gt;type());
</del><ins>+        Air::Opcode opcode = opcodeForType(opcode32, opcode64, opcodeDouble, opcodeFloat, left-&gt;type());
</ins><span class="cx">         
</span><span class="cx">         Tmp result = tmp(m_value);
</span><span class="cx">         
</span><span class="lines">@@ -648,10 +659,16 @@
</span><span class="cx">         append(opcode, tmp(right), result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template&lt;Air::Opcode opcode32, Air::Opcode opcode64, Commutativity commutativity = NotCommutative&gt;
+    void appendBinOp(Value* left, Value* right)
+    {
+        appendBinOp&lt;opcode32, opcode64, Air::Oops, Air::Oops, commutativity&gt;(left, right);
+    }
+
</ins><span class="cx">     template&lt;Air::Opcode opcode32, Air::Opcode opcode64&gt;
</span><span class="cx">     void appendShift(Value* value, Value* amount)
</span><span class="cx">     {
</span><del>-        Air::Opcode opcode = opcodeForType(opcode32, opcode64, Air::Oops, value-&gt;type());
</del><ins>+        Air::Opcode opcode = opcodeForType(opcode32, opcode64, value-&gt;type());
</ins><span class="cx">         
</span><span class="cx">         if (imm(amount)) {
</span><span class="cx">             append(Move, tmp(value), tmp(m_value));
</span><span class="lines">@@ -667,7 +684,7 @@
</span><span class="cx">     template&lt;Air::Opcode opcode32, Air::Opcode opcode64&gt;
</span><span class="cx">     bool tryAppendStoreUnOp(Value* value)
</span><span class="cx">     {
</span><del>-        Air::Opcode opcode = tryOpcodeForType(opcode32, opcode64, Air::Oops, value-&gt;type());
</del><ins>+        Air::Opcode opcode = tryOpcodeForType(opcode32, opcode64, value-&gt;type());
</ins><span class="cx">         if (opcode == Air::Oops)
</span><span class="cx">             return false;
</span><span class="cx">         
</span><span class="lines">@@ -690,7 +707,7 @@
</span><span class="cx">         Air::Opcode opcode32, Air::Opcode opcode64, Commutativity commutativity = NotCommutative&gt;
</span><span class="cx">     bool tryAppendStoreBinOp(Value* left, Value* right)
</span><span class="cx">     {
</span><del>-        Air::Opcode opcode = tryOpcodeForType(opcode32, opcode64, Air::Oops, left-&gt;type());
</del><ins>+        Air::Opcode opcode = tryOpcodeForType(opcode32, opcode64, left-&gt;type());
</ins><span class="cx">         if (opcode == Air::Oops)
</span><span class="cx">             return false;
</span><span class="cx">         
</span><span class="lines">@@ -749,11 +766,15 @@
</span><span class="cx">         case Int64:
</span><span class="cx">             RELEASE_ASSERT(is64Bit());
</span><span class="cx">             return Move;
</span><ins>+        case Float:
+            return MoveFloat;
</ins><span class="cx">         case Double:
</span><span class="cx">             return MoveDouble;
</span><del>-        default:
-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+        case Void:
+            break;
</ins><span class="cx">         }
</span><ins>+        RELEASE_ASSERT_NOT_REACHED();
+        return Air::Oops;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Air::Opcode relaxedMoveForType(Type type)
</span><span class="lines">@@ -762,11 +783,14 @@
</span><span class="cx">         case Int32:
</span><span class="cx">         case Int64:
</span><span class="cx">             return Move;
</span><ins>+        case Float:
</ins><span class="cx">         case Double:
</span><span class="cx">             return MoveDouble;
</span><del>-        default:
-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+        case Void:
+            break;
</ins><span class="cx">         }
</span><ins>+        RELEASE_ASSERT_NOT_REACHED();
+        return Air::Oops;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename... Arguments&gt;
</span><span class="lines">@@ -833,12 +857,13 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Create an Inst to do the comparison specified by the given value.
</span><del>-    template&lt;typename CompareFunctor, typename TestFunctor, typename CompareDoubleFunctor&gt;
</del><ins>+    template&lt;typename CompareFunctor, typename TestFunctor, typename CompareDoubleFunctor, typename CompareFloatFunctor&gt;
</ins><span class="cx">     Inst createGenericCompare(
</span><span class="cx">         Value* value,
</span><span class="cx">         const CompareFunctor&amp; compare, // Signature: (Arg::Width, Arg relCond, Arg, Arg) -&gt; Inst
</span><span class="cx">         const TestFunctor&amp; test, // Signature: (Arg::Width, Arg resCond, Arg, Arg) -&gt; Inst
</span><span class="cx">         const CompareDoubleFunctor&amp; compareDouble, // Signature: (Arg doubleCond, Arg, Arg) -&gt; Inst
</span><ins>+        const CompareFloatFunctor&amp; compareFloat, // Signature: (Arg doubleCond, Arg, Arg) -&gt; Inst
</ins><span class="cx">         bool inverted = false)
</span><span class="cx">     {
</span><span class="cx">         // Chew through any negations. It's not strictly necessary for this to be a loop, but we like
</span><span class="lines">@@ -962,7 +987,9 @@
</span><span class="cx">                 return compare(width, relCond, tmpPromise(left), tmpPromise(right));
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            // Double comparisons can't really do anything smart.
</del><ins>+            // Floating point comparisons can't really do anything smart.
+            if (value-&gt;child(0)-&gt;type() == Float)
+                return compareFloat(doubleCond, tmpPromise(left), tmpPromise(right));
</ins><span class="cx">             return compareDouble(doubleCond, tmpPromise(left), tmpPromise(right));
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="lines">@@ -1168,6 +1195,14 @@
</span><span class="cx">                 }
</span><span class="cx">                 return Inst();
</span><span class="cx">             },
</span><ins>+            [this] (Arg doubleCond, const ArgPromise&amp; left, const ArgPromise&amp; right) -&gt; Inst {
+                if (isValidForm(BranchFloat, Arg::DoubleCond, left.kind(), right.kind())) {
+                    return Inst(
+                        BranchFloat, m_value, doubleCond,
+                        left.consume(*this), right.consume(*this));
+                }
+                return Inst();
+            },
</ins><span class="cx">             inverted);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1226,6 +1261,10 @@
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=150903
</span><span class="cx">                 return Inst();
</span><span class="cx">             },
</span><ins>+            [this] (const Arg&amp;, const ArgPromise&amp;, const ArgPromise&amp;) -&gt; Inst {
+                // FIXME: Implement this.
+                return Inst();
+            },
</ins><span class="cx">             inverted);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1235,6 +1274,7 @@
</span><span class="cx">         Air::Opcode moveConditionallyTest32;
</span><span class="cx">         Air::Opcode moveConditionallyTest64;
</span><span class="cx">         Air::Opcode moveConditionallyDouble;
</span><ins>+        Air::Opcode moveConditionallyFloat;
</ins><span class="cx">         Tmp source;
</span><span class="cx">         Tmp destination;
</span><span class="cx">     };
</span><span class="lines">@@ -1302,6 +1342,14 @@
</span><span class="cx">                 }
</span><span class="cx">                 return Inst();
</span><span class="cx">             },
</span><ins>+            [&amp;] (Arg doubleCond, const ArgPromise&amp; left, const ArgPromise&amp; right) -&gt; Inst {
+                if (isValidForm(config.moveConditionallyFloat, Arg::DoubleCond, left.kind(), right.kind(), Arg::Tmp, Arg::Tmp)) {
+                    return Inst(
+                        config.moveConditionallyFloat, m_value, doubleCond,
+                        left.consume(*this), right.consume(*this), config.source, config.destination);
+                }
+                return Inst();
+            },
</ins><span class="cx">             inverted);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1370,21 +1418,21 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Add: {
</span><del>-            appendBinOp&lt;Add32, Add64, AddDouble, Commutative&gt;(
</del><ins>+            appendBinOp&lt;Add32, Add64, AddDouble, AddFloat, Commutative&gt;(
</ins><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Sub: {
</span><span class="cx">             if (m_value-&gt;child(0)-&gt;isInt(0))
</span><del>-                appendUnOp&lt;Neg32, Neg64, Air::Oops&gt;(m_value-&gt;child(1));
</del><ins>+                appendUnOp&lt;Neg32, Neg64&gt;(m_value-&gt;child(1));
</ins><span class="cx">             else
</span><del>-                appendBinOp&lt;Sub32, Sub64, SubDouble&gt;(m_value-&gt;child(0), m_value-&gt;child(1));
</del><ins>+                appendBinOp&lt;Sub32, Sub64, SubDouble, SubFloat&gt;(m_value-&gt;child(0), m_value-&gt;child(1));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Mul: {
</span><del>-            appendBinOp&lt;Mul32, Mul64, MulDouble, Commutative&gt;(
</del><ins>+            appendBinOp&lt;Mul32, Mul64, MulDouble, MulFloat, Commutative&gt;(
</ins><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -1418,28 +1466,28 @@
</span><span class="cx">             }
</span><span class="cx">             ASSERT(isFloat(m_value-&gt;type()));
</span><span class="cx"> 
</span><del>-            appendBinOp&lt;Air::Oops, Air::Oops, DivDouble&gt;(m_value-&gt;child(0), m_value-&gt;child(1));
</del><ins>+            appendBinOp&lt;Air::Oops, Air::Oops, DivDouble, DivFloat&gt;(m_value-&gt;child(0), m_value-&gt;child(1));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case BitAnd: {
</span><del>-            appendBinOp&lt;And32, And64, Air::Oops, Commutative&gt;(
</del><ins>+            appendBinOp&lt;And32, And64, Commutative&gt;(
</ins><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case BitOr: {
</span><del>-            appendBinOp&lt;Or32, Or64, Air::Oops, Commutative&gt;(
</del><ins>+            appendBinOp&lt;Or32, Or64, Commutative&gt;(
</ins><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case BitXor: {
</span><span class="cx">             if (m_value-&gt;child(1)-&gt;isInt(-1)) {
</span><del>-                appendUnOp&lt;Not32, Not64, Air::Oops&gt;(m_value-&gt;child(0));
</del><ins>+                appendUnOp&lt;Not32, Not64&gt;(m_value-&gt;child(0));
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><del>-            appendBinOp&lt;Xor32, Xor64, Air::Oops, Commutative&gt;(
</del><ins>+            appendBinOp&lt;Xor32, Xor64, Commutative&gt;(
</ins><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -1449,7 +1497,7 @@
</span><span class="cx">                 // This optimization makes sense on X86. I don't know if it makes sense anywhere else.
</span><span class="cx">                 append(Move, tmp(m_value-&gt;child(0)), tmp(m_value));
</span><span class="cx">                 append(
</span><del>-                    opcodeForType(Add32, Add64, Air::Oops, m_value-&gt;child(0)-&gt;type()),
</del><ins>+                    opcodeForType(Add32, Add64, m_value-&gt;child(0)-&gt;type()),
</ins><span class="cx">                     tmp(m_value), tmp(m_value));
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="lines">@@ -1469,17 +1517,17 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Clz: {
</span><del>-            appendUnOp&lt;CountLeadingZeros32, CountLeadingZeros64, Air::Oops&gt;(m_value-&gt;child(0));
</del><ins>+            appendUnOp&lt;CountLeadingZeros32, CountLeadingZeros64&gt;(m_value-&gt;child(0));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Sqrt: {
</span><del>-            appendUnOp&lt;Air::Oops, Air::Oops, SqrtDouble&gt;(m_value-&gt;child(0));
</del><ins>+            appendUnOp&lt;Air::Oops, Air::Oops, SqrtDouble, SqrtFloat&gt;(m_value-&gt;child(0));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case BitwiseCast: {
</span><del>-            appendUnOp&lt;Air::Oops, Move64ToDouble, MoveDoubleTo64&gt;(m_value-&gt;child(0));
</del><ins>+            appendUnOp&lt;MoveInt32ToPacked, Move64ToDouble, MoveDoubleTo64, MovePackedToInt32&gt;(m_value-&gt;child(0));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1545,6 +1593,16 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case FloatToDouble: {
+            appendUnOp&lt;Air::Oops, Air::Oops, Air::Oops, ConvertFloatToDouble&gt;(m_value-&gt;child(0));
+            return;
+        }
+
+        case DoubleToFloat: {
+            appendUnOp&lt;Air::Oops, Air::Oops, ConvertDoubleToFloat&gt;(m_value-&gt;child(0));
+            return;
+        }
+
</ins><span class="cx">         case ArgumentReg: {
</span><span class="cx">             m_prologue.append(Inst(
</span><span class="cx">                 moveForType(m_value-&gt;type()), m_value,
</span><span class="lines">@@ -1565,10 +1623,12 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case ConstDouble: {
</del><ins>+        case ConstDouble:
+        case ConstFloat: {
</ins><span class="cx">             // We expect that the moveConstants() phase has run, and any doubles referenced from
</span><span class="cx">             // stackmaps get fused.
</span><del>-            RELEASE_ASSERT(isIdentical(m_value-&gt;asDouble(), 0.0));
</del><ins>+            RELEASE_ASSERT(m_value-&gt;opcode() == ConstFloat || isIdentical(m_value-&gt;asDouble(), 0.0));
+            RELEASE_ASSERT(m_value-&gt;opcode() == ConstDouble || isIdentical(m_value-&gt;asFloat(), 0.0));
</ins><span class="cx">             append(MoveZeroToDouble, tmp(m_value));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -1614,6 +1674,7 @@
</span><span class="cx">                 config.moveConditionallyTest32 = MoveConditionallyTest32;
</span><span class="cx">                 config.moveConditionallyTest64 = MoveConditionallyTest64;
</span><span class="cx">                 config.moveConditionallyDouble = MoveConditionallyDouble;
</span><ins>+                config.moveConditionallyFloat = MoveConditionallyFloat;
</ins><span class="cx">             } else {
</span><span class="cx">                 // FIXME: it's not obvious that these are particularly efficient.
</span><span class="cx">                 config.moveConditionally32 = MoveDoubleConditionally32;
</span><span class="lines">@@ -1621,6 +1682,7 @@
</span><span class="cx">                 config.moveConditionallyTest32 = MoveDoubleConditionallyTest32;
</span><span class="cx">                 config.moveConditionallyTest64 = MoveDoubleConditionallyTest64;
</span><span class="cx">                 config.moveConditionallyDouble = MoveDoubleConditionallyDouble;
</span><ins>+                config.moveConditionallyFloat = MoveDoubleConditionallyFloat;
</ins><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             m_insts.last().append(createSelect(m_value-&gt;child(0), config));
</span><span class="lines">@@ -1628,7 +1690,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case IToD: {
</span><del>-            appendUnOp&lt;ConvertInt32ToDouble, ConvertInt64ToDouble, Air::Oops&gt;(m_value-&gt;child(0));
</del><ins>+            appendUnOp&lt;ConvertInt32ToDouble, ConvertInt64ToDouble&gt;(m_value-&gt;child(0));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1689,6 +1751,7 @@
</span><span class="cx">             case Int64:
</span><span class="cx">                 append(Move, Tmp(GPRInfo::returnValueGPR), tmp(cCall));
</span><span class="cx">                 break;
</span><ins>+            case Float:
</ins><span class="cx">             case Double:
</span><span class="cx">                 append(MoveDouble, Tmp(FPRInfo::returnValueFPR), tmp(cCall));
</span><span class="cx">                 break;
</span><span class="lines">@@ -1753,7 +1816,7 @@
</span><span class="cx">                 append(Move, tmp(right), result);
</span><span class="cx"> 
</span><span class="cx">                 Air::Opcode opcode =
</span><del>-                    opcodeForType(BranchNeg32, BranchNeg64, Air::Oops, checkValue-&gt;type());
</del><ins>+                    opcodeForType(BranchNeg32, BranchNeg64, checkValue-&gt;type());
</ins><span class="cx">                 CheckSpecial* special = ensureCheckSpecial(opcode, 2);
</span><span class="cx"> 
</span><span class="cx">                 Inst inst(Patch, checkValue, Arg::special(special));
</span><span class="lines">@@ -1771,14 +1834,14 @@
</span><span class="cx">             StackmapSpecial::RoleMode stackmapRole = StackmapSpecial::SameAsRep;
</span><span class="cx">             switch (m_value-&gt;opcode()) {
</span><span class="cx">             case CheckAdd:
</span><del>-                opcode = opcodeForType(BranchAdd32, BranchAdd64, Air::Oops, m_value-&gt;type());
</del><ins>+                opcode = opcodeForType(BranchAdd32, BranchAdd64, m_value-&gt;type());
</ins><span class="cx">                 commutativity = Commutative;
</span><span class="cx">                 break;
</span><span class="cx">             case CheckSub:
</span><del>-                opcode = opcodeForType(BranchSub32, BranchSub64, Air::Oops, m_value-&gt;type());
</del><ins>+                opcode = opcodeForType(BranchSub32, BranchSub64, m_value-&gt;type());
</ins><span class="cx">                 break;
</span><span class="cx">             case CheckMul:
</span><del>-                opcode = opcodeForType(BranchMul32, BranchMul64, Air::Oops, checkValue-&gt;type());
</del><ins>+                opcode = opcodeForType(BranchMul32, BranchMul64, checkValue-&gt;type());
</ins><span class="cx">                 stackmapRole = StackmapSpecial::ForceLateUse;
</span><span class="cx">                 break;
</span><span class="cx">             default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3MemoryValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -45,9 +45,6 @@
</span><span class="cx">     case Load16S:
</span><span class="cx">     case Store16:
</span><span class="cx">         return 2;
</span><del>-    case LoadFloat:
-    case StoreFloat:
-        return 4;
</del><span class="cx">     case Load:
</span><span class="cx">         return sizeofType(type());
</span><span class="cx">     case Store:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3MemoryValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3MemoryValue.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3MemoryValue.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3MemoryValue.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -42,11 +42,9 @@
</span><span class="cx">         case Load8S:
</span><span class="cx">         case Load16Z:
</span><span class="cx">         case Load16S:
</span><del>-        case LoadFloat:
</del><span class="cx">         case Load:
</span><span class="cx">         case Store8:
</span><span class="cx">         case Store16:
</span><del>-        case StoreFloat:
</del><span class="cx">         case Store:
</span><span class="cx">             return true;
</span><span class="cx">         default:
</span><span class="lines">@@ -89,12 +87,8 @@
</span><span class="cx">             case Load16S:
</span><span class="cx">                 ASSERT(type == Int32);
</span><span class="cx">                 break;
</span><del>-            case LoadFloat:
-                ASSERT(type == Double);
-                break;
</del><span class="cx">             case Store8:
</span><span class="cx">             case Store16:
</span><del>-            case StoreFloat:
</del><span class="cx">             case Store:
</span><span class="cx">                 ASSERT(type == Void);
</span><span class="cx">                 break;
</span><span class="lines">@@ -106,7 +100,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Use this form for loads where the return type is implied.
</span><span class="cx">     MemoryValue(unsigned index, Opcode opcode, Origin origin, Value* pointer, int32_t offset = 0)
</span><del>-        : MemoryValue(index, opcode, opcode == LoadFloat ? Double : Int32, origin, pointer, offset)
</del><ins>+        : MemoryValue(index, opcode, Int32, origin, pointer, offset)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -122,7 +116,6 @@
</span><span class="cx">             switch (opcode) {
</span><span class="cx">             case Store8:
</span><span class="cx">             case Store16:
</span><del>-            case StoreFloat:
</del><span class="cx">             case Store:
</span><span class="cx">                 break;
</span><span class="cx">             default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3MoveConstantscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -256,7 +256,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool goesInTable(const ValueKey&amp; key)
</span><span class="cx">     {
</span><del>-        return key.opcode() == ConstDouble &amp;&amp; key != doubleZero();
</del><ins>+        return (key.opcode() == ConstDouble &amp;&amp; key != doubleZero())
+        || (key.opcode() == ConstFloat &amp;&amp; key != floatZero());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool needsMotion(const ValueKey&amp; key)
</span><span class="lines">@@ -269,6 +270,11 @@
</span><span class="cx">         return ValueKey(ConstDouble, Double, 0.0);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static ValueKey floatZero()
+    {
+        return ValueKey(ConstFloat, Double, 0.0);
+    }
+
</ins><span class="cx">     Procedure&amp; m_proc;
</span><span class="cx">     Vector&lt;Value*&gt; m_toRemove;
</span><span class="cx">     HashMap&lt;ValueKey, unsigned&gt; m_constTable;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Opcodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Opcode.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -92,6 +92,9 @@
</span><span class="cx">     case ConstDouble:
</span><span class="cx">         out.print(&quot;ConstDouble&quot;);
</span><span class="cx">         return;
</span><ins>+    case ConstFloat:
+        out.print(&quot;ConstFloat&quot;);
+        return;
</ins><span class="cx">     case StackSlot:
</span><span class="cx">         out.print(&quot;StackSlot&quot;);
</span><span class="cx">         return;
</span><span class="lines">@@ -161,15 +164,18 @@
</span><span class="cx">     case Trunc:
</span><span class="cx">         out.print(&quot;Trunc&quot;);
</span><span class="cx">         return;
</span><del>-    case FRound:
-        out.print(&quot;FRound&quot;);
-        return;
</del><span class="cx">     case IToD:
</span><span class="cx">         out.print(&quot;IToD&quot;);
</span><span class="cx">         return;
</span><span class="cx">     case DToI32:
</span><span class="cx">         out.print(&quot;DToI32&quot;);
</span><span class="cx">         return;
</span><ins>+    case FloatToDouble:
+        out.print(&quot;FloatToDouble&quot;);
+        return;
+    case DoubleToFloat:
+        out.print(&quot;DoubleToFloat&quot;);
+        return;
</ins><span class="cx">     case Equal:
</span><span class="cx">         out.print(&quot;Equal&quot;);
</span><span class="cx">         return;
</span><span class="lines">@@ -215,9 +221,6 @@
</span><span class="cx">     case Load16S:
</span><span class="cx">         out.print(&quot;Load16S&quot;);
</span><span class="cx">         return;
</span><del>-    case LoadFloat:
-        out.print(&quot;LoadFloat&quot;);
-        return;
</del><span class="cx">     case Load:
</span><span class="cx">         out.print(&quot;Load&quot;);
</span><span class="cx">         return;
</span><span class="lines">@@ -227,9 +230,6 @@
</span><span class="cx">     case Store16:
</span><span class="cx">         out.print(&quot;Store16&quot;);
</span><span class="cx">         return;
</span><del>-    case StoreFloat:
-        out.print(&quot;StoreFloat&quot;);
-        return;
</del><span class="cx">     case Store:
</span><span class="cx">         out.print(&quot;Store&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Opcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Opcode.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx">     Const32,
</span><span class="cx">     Const64,
</span><span class="cx">     ConstDouble,
</span><ins>+    ConstFloat,
</ins><span class="cx"> 
</span><span class="cx">     // The magical stack slot. This is viewed as executing at the top of the program regardless of
</span><span class="cx">     // where in control flow you put it. Each instance of a StackSlot Value gets a disjoint range of
</span><span class="lines">@@ -96,12 +97,13 @@
</span><span class="cx">     ZExt32,
</span><span class="cx">     // Takes Int64 and returns Int32:
</span><span class="cx">     Trunc,
</span><del>-    // Takes and returns Double:
-    FRound,
</del><span class="cx">     // Takes ints and returns Double:
</span><span class="cx">     IToD,
</span><span class="cx">     // Takes Double and returns Int32:
</span><span class="cx">     DToI32,
</span><ins>+    // Convert between double and float.
+    FloatToDouble,
+    DoubleToFloat,
</ins><span class="cx"> 
</span><span class="cx">     // Polymorphic comparisons, usable with any value type. Returns int32 0 or 1. Note that &quot;Not&quot;
</span><span class="cx">     // is just Equal(x, 0), and &quot;ToBoolean&quot; is just NotEqual(x, 0).
</span><span class="lines">@@ -128,8 +130,6 @@
</span><span class="cx">     Load8S,
</span><span class="cx">     Load16Z,
</span><span class="cx">     Load16S,
</span><del>-    // This returns Double:
-    LoadFloat,
</del><span class="cx">     // This returns whatever the return type is:
</span><span class="cx">     Load,
</span><span class="cx"> 
</span><span class="lines">@@ -137,9 +137,7 @@
</span><span class="cx">     // These take an Int32 value:
</span><span class="cx">     Store8,
</span><span class="cx">     Store16,
</span><del>-    // This takes a Double value:
-    StoreFloat,
-    // This is a polymorphic store for Int32, Int64, and Double:
</del><ins>+    // This is a polymorphic store for Int32, Int64, Float, and Double.
</ins><span class="cx">     Store,
</span><span class="cx"> 
</span><span class="cx">     // This is a regular ordinary C function call, using the system C calling convention. Make sure
</span><span class="lines">@@ -237,6 +235,7 @@
</span><span class="cx">     case Const32:
</span><span class="cx">     case Const64:
</span><span class="cx">     case ConstDouble:
</span><ins>+    case ConstFloat:
</ins><span class="cx">         return true;
</span><span class="cx">     default:
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -69,6 +69,8 @@
</span><span class="cx">         return add&lt;Const64Value&gt;(origin, value);
</span><span class="cx">     case Double:
</span><span class="cx">         return add&lt;ConstDoubleValue&gt;(origin, static_cast&lt;double&gt;(value));
</span><ins>+    case Float:
+        return add&lt;ConstFloatValue&gt;(origin, static_cast&lt;float&gt;(value));
</ins><span class="cx">     default:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         return nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloatcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp (0 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -0,0 +1,153 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;B3ReduceDoubleToFloat.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;B3BasicBlock.h&quot;
+#include &quot;B3PhaseScope.h&quot;
+#include &quot;B3ValueInlines.h&quot;
+
+namespace JSC { namespace B3 {
+
+namespace {
+void attemptSimplification(Value* candidate)
+{
+    switch (candidate-&gt;opcode()) {
+    case Add:
+    case Sub:
+    case Mul:
+    case Div:
+        if (candidate-&gt;child(0)-&gt;opcode() == FloatToDouble &amp;&amp; candidate-&gt;child(1)-&gt;opcode() == FloatToDouble) {
+            candidate-&gt;child(0) = candidate-&gt;child(0)-&gt;child(0);
+            candidate-&gt;child(1) = candidate-&gt;child(1)-&gt;child(0);
+            candidate-&gt;setType(Float);
+        }
+        break;
+    case Sqrt:
+        if (candidate-&gt;child(0)-&gt;opcode() == FloatToDouble) {
+            candidate-&gt;child(0) = candidate-&gt;child(0)-&gt;child(0);
+            candidate-&gt;setType(Float);
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+} // namespace
+
+// The goal of this phase is to transform Double operations
+// into float if the Double result is never used as Double.
+//
+// In C, that would be something like:
+//     float add(float a, float b) {
+//         return (double)a + (double)b;
+//     }
+//
+// Such operation arise in JS because there are is no Float type
+// and float operations are generated by adding double-to-float rounding.
+//
+// The operations can be done entirely without Double conversion.
+// Using float in place remove the useless conversion, and the float
+// ops is sometime massively cheaper (SQRT for example).
+//
+// If the Double value is used as Double, we do not do the conversion.
+// It is cheaper to do a conversion than repeat any floating-point operation.
+void reduceDoubleToFloat(Procedure&amp; procedure)
+{
+    // FIXME: We should tune this phase for performance and make it part of ReduceStrength.
+    // ReduceStrength can eliminate nodes that prevents us from simplifying operations.
+    PhaseScope phaseScope(procedure, &quot;reduceDoubleToFloat&quot;);
+
+    HashSet&lt;Value*&gt; candidates;
+
+    // First, we find any value that is converted to float
+    // and only used as float.
+    // We also simplify comparisons since that's always safe and we
+    // don't want them to appear in the next loop.
+    for (BasicBlock* block : procedure) {
+        for (Value* value : *block) {
+            value-&gt;performSubstitution();
+
+            switch (value-&gt;opcode()) {
+            case DoubleToFloat:
+                candidates.add(value-&gt;child(0));
+                break;
+            case Equal:
+            case NotEqual:
+            case LessThan:
+            case GreaterThan:
+            case LessEqual:
+            case GreaterEqual:
+                if (value-&gt;child(0)-&gt;opcode() == FloatToDouble &amp;&amp; value-&gt;child(1)-&gt;opcode() == FloatToDouble) {
+                    value-&gt;child(0) = value-&gt;child(0)-&gt;child(0);
+                    value-&gt;child(1) = value-&gt;child(1)-&gt;child(0);
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+    for (BasicBlock* block : procedure) {
+        for (Value* value : *block) {
+            if (value-&gt;opcode() == DoubleToFloat)
+                continue;
+
+            for (Value* child : value-&gt;children()) {
+                if (child-&gt;type() == Double)
+                    candidates.remove(child);
+            }
+        }
+    }
+
+    if (candidates.isEmpty())
+        return;
+
+    // Second, we go over the candidates and attempt to simplify them.
+    // This leaves the graph in an invalid state where Float Values are
+    // used by DoubleToFloat Values. This is only temporary.
+    for (Value* candidate : candidates)
+        attemptSimplification(candidate);
+
+    // Finally, remove the DoubleToFloat made useless by the simplifications.
+    for (BasicBlock* block : procedure) {
+        for (Value* value : *block) {
+            if (value-&gt;opcode() == DoubleToFloat &amp;&amp; value-&gt;child(0)-&gt;type() == Float)
+                value-&gt;replaceWithIdentity(value-&gt;child(0));
+        }
+    }
+
+    // We do not clean all the useless nodes and conversions. ReduceStrength does that better.
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloath"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.h (0 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef B3ReduceDoubleToFloat_h
+#define B3ReduceDoubleToFloat_h
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 {
+
+class Procedure;
+
+// Change Double operations to Float operations when the difference is not observable
+// and doing so is likely beneficial.
+void reduceDoubleToFloat(Procedure&amp;);
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3ReduceDoubleToFloat_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -486,6 +486,15 @@
</span><span class="cx"> 
</span><span class="cx">             break;
</span><span class="cx"> 
</span><ins>+        case Sqrt:
+            // Turn this: Sqrt(constant)
+            // Into this: sqrt&lt;value-&gt;type()&gt;(constant)
+            if (Value* constant = m_value-&gt;child(0)-&gt;sqrtConstant(m_proc)) {
+                replaceWithNewValue(constant);
+                break;
+            }
+            break;
+
</ins><span class="cx">         case BitwiseCast:
</span><span class="cx">             // Turn this: BitwiseCast(constant)
</span><span class="cx">             // Into this: bitwise_cast&lt;value-&gt;type()&gt;(constant)
</span><span class="lines">@@ -542,6 +551,32 @@
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx"> 
</span><ins>+        case FloatToDouble:
+            // Turn this: FloatToDouble(constant)
+            // Into this: ConstDouble(constant)
+            if (Value* constant = m_value-&gt;child(0)-&gt;floatToDoubleConstant(m_proc)) {
+                replaceWithNewValue(constant);
+                break;
+            }
+            break;
+
+        case DoubleToFloat:
+            // Turn this: DoubleToFloat(FloatToDouble(value))
+            // Into this: value
+            if (m_value-&gt;child(0)-&gt;opcode() == FloatToDouble) {
+                m_value-&gt;replaceWithIdentity(m_value-&gt;child(0)-&gt;child(0));
+                m_changed = true;
+                break;
+            }
+
+            // Turn this: DoubleToFloat(constant)
+            // Into this: ConstFloat(constant)
+            if (Value* constant = m_value-&gt;child(0)-&gt;doubleToFloatConstant(m_proc)) {
+                replaceWithNewValue(constant);
+                break;
+            }
+            break;
+
</ins><span class="cx">         case Select:
</span><span class="cx">             // Turn this: Select(constant, a, b)
</span><span class="cx">             // Into this: constant ? a : b
</span><span class="lines">@@ -596,11 +631,9 @@
</span><span class="cx">         case Load8S:
</span><span class="cx">         case Load16Z:
</span><span class="cx">         case Load16S:
</span><del>-        case LoadFloat:
</del><span class="cx">         case Load:
</span><span class="cx">         case Store8:
</span><span class="cx">         case Store16:
</span><del>-        case StoreFloat:
</del><span class="cx">         case Store: {
</span><span class="cx">             Value* address = m_value-&gt;lastChild();
</span><span class="cx">             MemoryValue* memory = m_value-&gt;as&lt;MemoryValue&gt;();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Typecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Type.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Type.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Type.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -46,6 +46,9 @@
</span><span class="cx">     case Int64:
</span><span class="cx">         out.print(&quot;Int64&quot;);
</span><span class="cx">         return;
</span><ins>+    case Float:
+        out.print(&quot;Float&quot;);
+        return;
</ins><span class="cx">     case Double:
</span><span class="cx">         out.print(&quot;Double&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Typeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Type.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Type.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Type.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx">     Void,
</span><span class="cx">     Int32,
</span><span class="cx">     Int64,
</span><ins>+    Float,
</ins><span class="cx">     Double
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -47,7 +48,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline bool isFloat(Type type)
</span><span class="cx"> {
</span><del>-    return type == Double;
</del><ins>+    return type == Float || type == Double;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline Type pointerType()
</span><span class="lines">@@ -63,6 +64,7 @@
</span><span class="cx">     case Void:
</span><span class="cx">         return 0;
</span><span class="cx">     case Int32:
</span><ins>+    case Float:
</ins><span class="cx">         return 4;
</span><span class="cx">     case Int64:
</span><span class="cx">     case Double:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Validatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Validate.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -134,6 +134,10 @@
</span><span class="cx">                 VALIDATE(!value-&gt;numChildren(), (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() == Double, (&quot;At &quot;, *value));
</span><span class="cx">                 break;
</span><ins>+            case ConstFloat:
+                VALIDATE(!value-&gt;numChildren(), (&quot;At &quot;, *value));
+                VALIDATE(value-&gt;type() == Float, (&quot;At &quot;, *value));
+                break;
</ins><span class="cx">             case StackSlot:
</span><span class="cx">             case FramePointer:
</span><span class="cx">                 VALIDATE(!value-&gt;numChildren(), (&quot;At &quot;, *value));
</span><span class="lines">@@ -177,7 +181,9 @@
</span><span class="cx">                 VALIDATE(value-&gt;type() != value-&gt;child(0)-&gt;type(), (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(
</span><span class="cx">                     (value-&gt;type() == Int64 &amp;&amp; value-&gt;child(0)-&gt;type() == Double)
</span><del>-                    || (value-&gt;type() == Double &amp;&amp; value-&gt;child(0)-&gt;type() == Int64),
</del><ins>+                    || (value-&gt;type() == Double &amp;&amp; value-&gt;child(0)-&gt;type() == Int64)
+                    || (value-&gt;type() == Float &amp;&amp; value-&gt;child(0)-&gt;type() == Int32)
+                    || (value-&gt;type() == Int32 &amp;&amp; value-&gt;child(0)-&gt;type() == Float),
</ins><span class="cx">                     (&quot;At &quot;, *value));
</span><span class="cx">                 break;
</span><span class="cx">             case SExt8:
</span><span class="lines">@@ -203,10 +209,9 @@
</span><span class="cx">                 VALIDATE(value-&gt;type() == Int32, (&quot;At &quot;, *value));
</span><span class="cx">                 break;
</span><span class="cx">             case Sqrt:
</span><del>-            case FRound:
</del><span class="cx">                 VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
</span><del>-                VALIDATE(value-&gt;child(0)-&gt;type() == Double, (&quot;At &quot;, *value));
-                VALIDATE(value-&gt;type() == Double, (&quot;At &quot;, *value));
</del><ins>+                VALIDATE(isFloat(value-&gt;child(0)-&gt;type()), (&quot;At &quot;, *value));
+                VALIDATE(isFloat(value-&gt;type()), (&quot;At &quot;, *value));
</ins><span class="cx">                 break;
</span><span class="cx">             case IToD:
</span><span class="cx">                 VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
</span><span class="lines">@@ -218,6 +223,16 @@
</span><span class="cx">                 VALIDATE(value-&gt;child(0)-&gt;type() == Double, (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() == Int32, (&quot;At &quot;, *value));
</span><span class="cx">                 break;
</span><ins>+            case FloatToDouble:
+                VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
+                VALIDATE(value-&gt;child(0)-&gt;type() == Float, (&quot;At &quot;, *value));
+                VALIDATE(value-&gt;type() == Double, (&quot;At &quot;, *value));
+                break;
+            case DoubleToFloat:
+                VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
+                VALIDATE(value-&gt;child(0)-&gt;type() == Double, (&quot;At &quot;, *value));
+                VALIDATE(value-&gt;type() == Float, (&quot;At &quot;, *value));
+                break;
</ins><span class="cx">             case Equal:
</span><span class="cx">             case NotEqual:
</span><span class="cx">             case LessThan:
</span><span class="lines">@@ -252,12 +267,6 @@
</span><span class="cx">                 VALIDATE(value-&gt;type() == Int32, (&quot;At &quot;, *value));
</span><span class="cx">                 validateStackAccess(value);
</span><span class="cx">                 break;
</span><del>-            case LoadFloat:
-                VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
-                VALIDATE(value-&gt;child(0)-&gt;type() == pointerType(), (&quot;At &quot;, *value));
-                VALIDATE(value-&gt;type() == Double, (&quot;At &quot;, *value));
-                validateStackAccess(value);
-                break;
</del><span class="cx">             case Load:
</span><span class="cx">                 VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;child(0)-&gt;type() == pointerType(), (&quot;At &quot;, *value));
</span><span class="lines">@@ -272,13 +281,6 @@
</span><span class="cx">                 VALIDATE(value-&gt;type() == Void, (&quot;At &quot;, *value));
</span><span class="cx">                 validateStackAccess(value);
</span><span class="cx">                 break;
</span><del>-            case StoreFloat:
-                VALIDATE(value-&gt;numChildren() == 2, (&quot;At &quot;, *value));
-                VALIDATE(value-&gt;child(0)-&gt;type() == Double, (&quot;At &quot;, *value));
-                VALIDATE(value-&gt;child(1)-&gt;type() == pointerType(), (&quot;At &quot;, *value));
-                VALIDATE(value-&gt;type() == Void, (&quot;At &quot;, *value));
-                validateStackAccess(value);
-                break;
</del><span class="cx">             case Store:
</span><span class="cx">                 VALIDATE(value-&gt;numChildren() == 2, (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;child(1)-&gt;type() == pointerType(), (&quot;At &quot;, *value));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -199,6 +199,21 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* Value::doubleToFloatConstant(Procedure&amp;) const
+{
+    return nullptr;
+}
+
+Value* Value::floatToDoubleConstant(Procedure&amp;) const
+{
+    return nullptr;
+}
+
+Value* Value::sqrtConstant(Procedure&amp;) const
+{
+    return nullptr;
+}
+
</ins><span class="cx"> TriState Value::equalConstant(const Value*) const
</span><span class="cx"> {
</span><span class="cx">     return MixedTriState;
</span><span class="lines">@@ -298,6 +313,8 @@
</span><span class="cx">     case ConstDouble:
</span><span class="cx">         // Use &quot;!= 0&quot; to really emphasize what this mean with respect to NaN and such.
</span><span class="cx">         return triState(asDouble() != 0);
</span><ins>+    case ConstFloat:
+        return triState(asFloat() != 0.);
</ins><span class="cx">     default:
</span><span class="cx">         return MixedTriState;
</span><span class="cx">     }
</span><span class="lines">@@ -312,6 +329,7 @@
</span><span class="cx">     case Const32:
</span><span class="cx">     case Const64:
</span><span class="cx">     case ConstDouble:
</span><ins>+    case ConstFloat:
</ins><span class="cx">     case StackSlot:
</span><span class="cx">     case ArgumentReg:
</span><span class="cx">     case FramePointer:
</span><span class="lines">@@ -334,9 +352,10 @@
</span><span class="cx">     case SExt32:
</span><span class="cx">     case ZExt32:
</span><span class="cx">     case Trunc:
</span><del>-    case FRound:
</del><span class="cx">     case IToD:
</span><span class="cx">     case DToI32:
</span><ins>+    case FloatToDouble:
+    case DoubleToFloat:
</ins><span class="cx">     case Equal:
</span><span class="cx">     case NotEqual:
</span><span class="cx">     case LessThan:
</span><span class="lines">@@ -356,14 +375,12 @@
</span><span class="cx">     case Load8S:
</span><span class="cx">     case Load16Z:
</span><span class="cx">     case Load16S:
</span><del>-    case LoadFloat:
</del><span class="cx">     case Load:
</span><span class="cx">         result.reads = as&lt;MemoryValue&gt;()-&gt;range();
</span><span class="cx">         result.controlDependent = true;
</span><span class="cx">         break;
</span><span class="cx">     case Store8:
</span><span class="cx">     case Store16:
</span><del>-    case StoreFloat:
</del><span class="cx">     case Store:
</span><span class="cx">         result.writes = as&lt;MemoryValue&gt;()-&gt;range();
</span><span class="cx">         result.controlDependent = true;
</span><span class="lines">@@ -410,9 +427,10 @@
</span><span class="cx">     case ZExt32:
</span><span class="cx">     case Clz:
</span><span class="cx">     case Trunc:
</span><del>-    case FRound:
</del><span class="cx">     case IToD:
</span><span class="cx">     case DToI32:
</span><ins>+    case FloatToDouble:
+    case DoubleToFloat:
</ins><span class="cx">     case Check:
</span><span class="cx">         return ValueKey(opcode(), type(), child(0));
</span><span class="cx">     case Add:
</span><span class="lines">@@ -447,6 +465,8 @@
</span><span class="cx">         return ValueKey(Const64, type(), asInt64());
</span><span class="cx">     case ConstDouble:
</span><span class="cx">         return ValueKey(ConstDouble, type(), asDouble());
</span><ins>+    case ConstFloat:
+        return ValueKey(ConstFloat, type(), asFloat());
</ins><span class="cx">     case ArgumentReg:
</span><span class="cx">         return ValueKey(
</span><span class="cx">             ArgumentReg, type(),
</span><span class="lines">@@ -477,6 +497,7 @@
</span><span class="cx">     ASSERT(!Const32Value::accepts(opcode));
</span><span class="cx">     ASSERT(!Const64Value::accepts(opcode));
</span><span class="cx">     ASSERT(!ConstDoubleValue::accepts(opcode));
</span><ins>+    ASSERT(!ConstFloatValue::accepts(opcode));
</ins><span class="cx">     ASSERT(!ControlValue::accepts(opcode));
</span><span class="cx">     ASSERT(!MemoryValue::accepts(opcode));
</span><span class="cx">     ASSERT(!PatchpointValue::accepts(opcode));
</span><span class="lines">@@ -527,15 +548,24 @@
</span><span class="cx">     case SExt32:
</span><span class="cx">     case ZExt32:
</span><span class="cx">         return Int64;
</span><del>-    case FRound:
</del><ins>+    case FloatToDouble:
</ins><span class="cx">     case IToD:
</span><span class="cx">         return Double;
</span><ins>+    case DoubleToFloat:
+        return Float;
</ins><span class="cx">     case BitwiseCast:
</span><del>-        if (firstChild-&gt;type() == Int64)
</del><ins>+        switch (firstChild-&gt;type()) {
+        case Int64:
</ins><span class="cx">             return Double;
</span><del>-        if (firstChild-&gt;type() == Double)
</del><ins>+        case Double:
</ins><span class="cx">             return Int64;
</span><del>-        ASSERT_NOT_REACHED();
</del><ins>+        case Int32:
+            return Float;
+        case Float:
+            return Int32;
+        case Void:
+            ASSERT_NOT_REACHED();
+        }
</ins><span class="cx">         return Void;
</span><span class="cx">     case Nop:
</span><span class="cx">         return Void;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3Value.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -71,8 +71,8 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned numChildren() const { return m_children.size(); }
</span><span class="cx"> 
</span><del>-    // This computes the type using the opcode.
</del><span class="cx">     Type type() const { return m_type; }
</span><ins>+    void setType(Type type) { m_type = type; }
</ins><span class="cx"> 
</span><span class="cx">     // This is useful when lowering. Note that this is only valid for non-void values.
</span><span class="cx">     Air::Arg::Type airType() const { return Air::Arg::typeForB3Type(type()); }
</span><span class="lines">@@ -128,7 +128,10 @@
</span><span class="cx">     virtual Value* sShrConstant(Procedure&amp;, const Value* other) const;
</span><span class="cx">     virtual Value* zShrConstant(Procedure&amp;, const Value* other) const;
</span><span class="cx">     virtual Value* bitwiseCastConstant(Procedure&amp;) const;
</span><del>-    
</del><ins>+    virtual Value* doubleToFloatConstant(Procedure&amp;) const;
+    virtual Value* floatToDoubleConstant(Procedure&amp;) const;
+    virtual Value* sqrtConstant(Procedure&amp;) const;
+
</ins><span class="cx">     virtual TriState equalConstant(const Value* other) const;
</span><span class="cx">     virtual TriState notEqualConstant(const Value* other) const;
</span><span class="cx">     virtual TriState lessThanConstant(const Value* other) const;
</span><span class="lines">@@ -166,6 +169,9 @@
</span><span class="cx">     double asDouble() const;
</span><span class="cx">     bool isEqualToDouble(double) const; // We say &quot;isEqualToDouble&quot; because &quot;isDouble&quot; would be a bit equality.
</span><span class="cx"> 
</span><ins>+    bool hasFloat() const;
+    float asFloat() const;
+
</ins><span class="cx">     bool hasNumber() const;
</span><span class="cx">     template&lt;typename T&gt; bool representableAs() const;
</span><span class="cx">     template&lt;typename T&gt; T asNumber() const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ValueInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ValueInlines.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ValueInlines.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3ValueInlines.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;B3Const32Value.h&quot;
</span><span class="cx"> #include &quot;B3Const64Value.h&quot;
</span><span class="cx"> #include &quot;B3ConstDoubleValue.h&quot;
</span><ins>+#include &quot;B3ConstFloatValue.h&quot;
</ins><span class="cx"> #include &quot;B3PatchpointValue.h&quot;
</span><span class="cx"> #include &quot;B3Procedure.h&quot;
</span><span class="cx"> #include &quot;B3Value.h&quot;
</span><span class="lines">@@ -141,9 +142,19 @@
</span><span class="cx">     return hasDouble() &amp;&amp; asDouble() == value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool Value::hasFloat() const
+{
+    return !!as&lt;ConstFloatValue&gt;();
+}
+
+inline float Value::asFloat() const
+{
+    return as&lt;ConstFloatValue&gt;()-&gt;value();
+}
+
</ins><span class="cx"> inline bool Value::hasNumber() const
</span><span class="cx"> {
</span><del>-    return hasInt() || hasDouble();
</del><ins>+    return hasInt() || hasDouble() || hasFloat();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline bool Value::isNegativeZero() const
</span><span class="lines">@@ -152,6 +163,10 @@
</span><span class="cx">         double value = asDouble();
</span><span class="cx">         return !value &amp;&amp; std::signbit(value);
</span><span class="cx">     }
</span><ins>+    if (hasFloat()) {
+        float value = asFloat();
+        return !value &amp;&amp; std::signbit(value);
+    }
</ins><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -165,6 +180,8 @@
</span><span class="cx">         return isRepresentableAs&lt;T&gt;(asInt64());
</span><span class="cx">     case ConstDouble:
</span><span class="cx">         return isRepresentableAs&lt;T&gt;(asDouble());
</span><ins>+    case ConstFloat:
+        return isRepresentableAs&lt;T&gt;(asFloat());
</ins><span class="cx">     default:
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="lines">@@ -180,6 +197,8 @@
</span><span class="cx">         return static_cast&lt;T&gt;(asInt64());
</span><span class="cx">     case ConstDouble:
</span><span class="cx">         return static_cast&lt;T&gt;(asDouble());
</span><ins>+    case ConstFloat:
+        return static_cast&lt;T&gt;(asFloat());
</ins><span class="cx">     default:
</span><span class="cx">         return T();
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ValueKeycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ValueKey.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ValueKey.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3ValueKey.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -46,14 +46,17 @@
</span><span class="cx">     case FramePointer:
</span><span class="cx">         return proc.add&lt;Value&gt;(opcode(), type(), origin);
</span><span class="cx">     case Identity:
</span><ins>+    case Sqrt:
</ins><span class="cx">     case SExt8:
</span><span class="cx">     case SExt16:
</span><span class="cx">     case SExt32:
</span><span class="cx">     case ZExt32:
</span><ins>+    case Clz:
</ins><span class="cx">     case Trunc:
</span><del>-    case FRound:
</del><span class="cx">     case IToD:
</span><span class="cx">     case DToI32:
</span><ins>+    case FloatToDouble:
+    case DoubleToFloat:
</ins><span class="cx">     case Check:
</span><span class="cx">         return proc.add&lt;Value&gt;(opcode(), type(), origin, child(proc, 0));
</span><span class="cx">     case Add:
</span><span class="lines">@@ -85,6 +88,8 @@
</span><span class="cx">         return proc.add&lt;Const64Value&gt;(origin, value());
</span><span class="cx">     case ConstDouble:
</span><span class="cx">         return proc.add&lt;ConstDoubleValue&gt;(origin, doubleValue());
</span><ins>+    case ConstFloat:
+        return proc.add&lt;ConstFloatValue&gt;(origin, floatValue());
</ins><span class="cx">     case ArgumentReg:
</span><span class="cx">         return proc.add&lt;ArgumentRegValue&gt;(origin, Reg::fromIndex(static_cast&lt;unsigned&gt;(value())));
</span><span class="cx">     default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ValueKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ValueKey.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ValueKey.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/B3ValueKey.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -78,12 +78,20 @@
</span><span class="cx">         u.doubleValue = value;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ValueKey(Opcode opcode, Type type, float value)
+        : m_opcode(opcode)
+        , m_type(type)
+    {
+        u.floatValue = value;
+    }
+
</ins><span class="cx">     Opcode opcode() const { return m_opcode; }
</span><span class="cx">     Type type() const { return m_type; }
</span><span class="cx">     unsigned childIndex(unsigned index) const { return u.indices[index]; }
</span><span class="cx">     Value* child(Procedure&amp;, unsigned index) const;
</span><span class="cx">     int64_t value() const { return u.value; }
</span><span class="cx">     double doubleValue() const { return u.doubleValue; }
</span><ins>+    double floatValue() const { return u.floatValue; }
</ins><span class="cx"> 
</span><span class="cx">     bool operator==(const ValueKey&amp; other) const
</span><span class="cx">     {
</span><span class="lines">@@ -147,6 +155,7 @@
</span><span class="cx">         unsigned indices[3];
</span><span class="cx">         int64_t value;
</span><span class="cx">         double doubleValue;
</span><ins>+        float floatValue;
</ins><span class="cx"> 
</span><span class="cx">         U()
</span><span class="cx">         {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirArgh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirArg.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirArg.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/air/AirArg.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -211,6 +211,7 @@
</span><span class="cx">         case Int32:
</span><span class="cx">         case Int64:
</span><span class="cx">             return GP;
</span><ins>+        case Float:
</ins><span class="cx">         case Double:
</span><span class="cx">             return FP;
</span><span class="cx">         }
</span><span class="lines">@@ -225,6 +226,7 @@
</span><span class="cx">             ASSERT_NOT_REACHED();
</span><span class="cx">             return Width8;
</span><span class="cx">         case Int32:
</span><ins>+        case Float:
</ins><span class="cx">             return Width32;
</span><span class="cx">         case Int64:
</span><span class="cx">         case Double:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixPartialRegisterStallscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -46,6 +46,8 @@
</span><span class="cx"> bool hasPartialXmmRegUpdate(const Inst&amp; inst)
</span><span class="cx"> {
</span><span class="cx">     switch (inst.opcode) {
</span><ins>+    case ConvertDoubleToFloat:
+    case ConvertFloatToDouble:
</ins><span class="cx">     case ConvertInt32ToDouble:
</span><span class="cx">     case ConvertInt64ToDouble:
</span><span class="cx">     case SqrtDouble:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -82,6 +82,10 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span><span class="cx"> 
</span><ins>+AddFloat U:F, UD:F
+    Tmp, Tmp
+    Addr, Tmp
+
</ins><span class="cx"> Sub32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Imm, Addr
</span><span class="lines">@@ -97,6 +101,10 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span><span class="cx"> 
</span><ins>+SubFloat U:F, UD:F
+    Tmp, Tmp
+    Addr, Tmp
+
</ins><span class="cx"> Neg32 UD:G
</span><span class="cx">     Tmp
</span><span class="cx">     Addr
</span><span class="lines">@@ -118,10 +126,18 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span><span class="cx"> 
</span><ins>+MulFloat U:F, UD:F
+    Tmp, Tmp
+    Addr, Tmp
+
</ins><span class="cx"> DivDouble U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span><span class="cx"> 
</span><ins>+DivFloat U:F, UD:F
+    Tmp, Tmp
+    Addr, Tmp
+
</ins><span class="cx"> X86ConvertToDoubleWord32 U:G, D:G
</span><span class="cx">     Tmp*, Tmp*
</span><span class="cx"> 
</span><span class="lines">@@ -207,6 +223,10 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span><span class="cx"> 
</span><ins>+SqrtFloat U:F, UD:F
+    Tmp, Tmp
+    Addr, Tmp
+
</ins><span class="cx"> ConvertInt32ToDouble U:G, D:F
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span><span class="lines">@@ -222,6 +242,14 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span><span class="cx"> 
</span><ins>+ConvertDoubleToFloat U:F, D:F
+    Tmp, Tmp
+    Addr, Tmp
+
+ConvertFloatToDouble U:F, D:F
+    Tmp, Tmp
+    Addr, Tmp
+
</ins><span class="cx"> # Note that Move operates over the full register size, which is either 32-bit or 64-bit depending on
</span><span class="cx"> # the platform. I'm not entirely sure that this is a good thing; it might be better to just have a
</span><span class="cx"> # Move64 instruction. OTOH, our MacroAssemblers already have this notion of &quot;move()&quot; that basically
</span><span class="lines">@@ -248,6 +276,13 @@
</span><span class="cx"> SignExtend32ToPtr U:G, D:G
</span><span class="cx">     Tmp, Tmp
</span><span class="cx"> 
</span><ins>+MoveFloat U:F, D:F
+    Tmp, Tmp as moveDouble
+    Addr, Tmp as loadFloat
+    Index, Tmp as loadFloat
+    Tmp, Addr as storeFloat
+    Tmp, Index as storeFloat
+
</ins><span class="cx"> MoveDouble U:F, D:F
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp as loadDouble
</span><span class="lines">@@ -262,10 +297,18 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp as loadDouble
</span><span class="cx"> 
</span><ins>+MoveInt32ToPacked U:G, D:F
+    Tmp, Tmp
+    Addr, Tmp as loadFloat
+
</ins><span class="cx"> MoveDoubleTo64 U:F, D:G
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp as load64
</span><span class="cx"> 
</span><ins>+MovePackedToInt32 U:F, D:G
+    Tmp, Tmp
+    Addr, Tmp as load32
+
</ins><span class="cx"> Load8 U:G, D:G
</span><span class="cx">     Addr, Tmp
</span><span class="cx">     Index, Tmp
</span><span class="lines">@@ -341,6 +384,9 @@
</span><span class="cx"> BranchDouble U:G, U:F, U:F /branch
</span><span class="cx">     DoubleCond, Tmp, Tmp
</span><span class="cx"> 
</span><ins>+BranchFloat U:G, U:F, U:F /branch
+    DoubleCond, Tmp, Tmp
+
</ins><span class="cx"> BranchAdd32 U:G, U:G, UD:G /branch
</span><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx">     ResCond, Imm, Tmp
</span><span class="lines">@@ -396,6 +442,9 @@
</span><span class="cx"> MoveConditionallyDouble U:G, U:F, U:F, U:G, UD:G
</span><span class="cx">     DoubleCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><ins>+MoveConditionallyFloat U:G, U:F, U:F, U:G, UD:G
+    DoubleCond, Tmp, Tmp, Tmp, Tmp
+
</ins><span class="cx"> MoveDoubleConditionally32 U:G, U:G, U:G, U:F, UD:F
</span><span class="cx">     RelCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><span class="lines">@@ -413,6 +462,9 @@
</span><span class="cx"> MoveDoubleConditionallyDouble U:G, U:F, U:F, U:F, UD:F
</span><span class="cx">     DoubleCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><ins>+MoveDoubleConditionallyFloat U:G, U:F, U:F, U:F, UD:F
+    DoubleCond, Tmp, Tmp, Tmp, Tmp
+
</ins><span class="cx"> Jump /branch
</span><span class="cx"> 
</span><span class="cx"> Ret /terminal
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -306,6 +306,141 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), a + b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testAddArgFloat(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), floatValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a + a)));
+}
+
+void testAddArgsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), floatValue1, floatValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a + b)));
+}
+
+void testAddArgImmFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), floatValue, constValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a + b)));
+}
+
+void testAddImmArgFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), constValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a + b)));
+}
+
+void testAddImmsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* constValue1 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* constValue2 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), constValue1, constValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc), bitwise_cast&lt;int32_t&gt;(a + b)));
+}
+
+void testAddArgFloatWithUselessDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentInt32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentInt32);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), asDouble, asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a + a)));
+}
+
+void testAddArgsFloatWithUselessDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a + b)));
+}
+
+void testAddArgsFloatWithEffectfulDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* doubleAddress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2);
+    root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), result, doubleAddress);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), &amp;effect), bitwise_cast&lt;int32_t&gt;(a + b)));
+    CHECK(isIdentical(effect, static_cast&lt;double&gt;(a) + static_cast&lt;double&gt;(b)));
+}
+
</ins><span class="cx"> void testMulArg(int a)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -509,6 +644,141 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), a * b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testMulArgFloat(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), floatValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a * a)));
+}
+
+void testMulArgsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), floatValue1, floatValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a * b)));
+}
+
+void testMulArgImmFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), floatValue, constValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a * b)));
+}
+
+void testMulImmArgFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), constValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a * b)));
+}
+
+void testMulImmsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* constValue1 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* constValue2 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), constValue1, constValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc), bitwise_cast&lt;int32_t&gt;(a * b)));
+}
+
+void testMulArgFloatWithUselessDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentInt32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentInt32);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), asDouble, asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a * a)));
+}
+
+void testMulArgsFloatWithUselessDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a * b)));
+}
+
+void testMulArgsFloatWithEffectfulDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mul, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* doubleMulress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2);
+    root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), result, doubleMulress);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), &amp;effect), bitwise_cast&lt;int32_t&gt;(a * b)));
+    CHECK(isIdentical(effect, static_cast&lt;double&gt;(a) * static_cast&lt;double&gt;(b)));
+}
+
</ins><span class="cx"> void testDivArgDouble(double a)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -573,6 +843,141 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), a / b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testDivArgFloat(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), floatValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a / a)));
+}
+
+void testDivArgsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), floatValue1, floatValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a / b)));
+}
+
+void testDivArgImmFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), floatValue, constValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a / b)));
+}
+
+void testDivImmArgFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), constValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a / b)));
+}
+
+void testDivImmsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* constValue1 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* constValue2 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), constValue1, constValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc), bitwise_cast&lt;int32_t&gt;(a / b)));
+}
+
+void testDivArgFloatWithUselessDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentInt32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentInt32);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), asDouble, asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a / a)));
+}
+
+void testDivArgsFloatWithUselessDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a / b)));
+}
+
+void testDivArgsFloatWithEffectfulDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Div, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* doubleDivress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2);
+    root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), result, doubleDivress);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), &amp;effect), bitwise_cast&lt;int32_t&gt;(a / b)));
+    CHECK(isIdentical(effect, static_cast&lt;double&gt;(a) / static_cast&lt;double&gt;(b)));
+}
+
</ins><span class="cx"> void testSubArg(int a)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -772,6 +1177,141 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), a - b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testSubArgFloat(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), floatValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a - a)));
+}
+
+void testSubArgsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), floatValue1, floatValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a - b)));
+}
+
+void testSubArgImmFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), floatValue, constValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a - b)));
+}
+
+void testSubImmArgFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), constValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a - b)));
+}
+
+void testSubImmsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* constValue1 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* constValue2 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), constValue1, constValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc), bitwise_cast&lt;int32_t&gt;(a - b)));
+}
+
+void testSubArgFloatWithUselessDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentInt32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentInt32);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), asDouble, asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(a - a)));
+}
+
+void testSubArgsFloatWithUselessDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(a - b)));
+}
+
+void testSubArgsFloatWithEffectfulDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* asDouble1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* asDouble2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), asDouble1, asDouble2);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* doubleSubress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2);
+    root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), result, doubleSubress);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), &amp;effect), bitwise_cast&lt;int32_t&gt;(a - b)));
+    CHECK(isIdentical(effect, static_cast&lt;double&gt;(a) - static_cast&lt;double&gt;(b)));
+}
+
</ins><span class="cx"> void testBitAndArgs(int64_t a, int64_t b)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -2015,6 +2555,81 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, &amp;a), sqrt(a)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testSqrtArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sqrt, Origin(), argument);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(sqrt(a)))));
+}
+
+void testSqrtImm(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sqrt, Origin(), argument);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(sqrt(a)))));
+}
+
+void testSqrtMem(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadFloat = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Float, Origin(), address);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sqrt, Origin(), loadFloat);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, &amp;a), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(sqrt(a)))));
+}
+
+void testSqrtArgWithUselessDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sqrt, Origin(), asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(sqrt(a)))));
+}
+
+void testSqrtArgWithEffectfulDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Sqrt, Origin(), asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    Value* doubleAddress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2);
+    root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), result, doubleAddress);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), &amp;effect), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(sqrt(a)))));
+    CHECK(isIdentical(effect, sqrt(a)));
+}
+
</ins><span class="cx"> void testDoubleArgToInt64BitwiseCast(double value)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -2119,10 +2734,215 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, &amp;value), bitwise_cast&lt;double&gt;(value)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void testStore(int value)
</del><ins>+void testFloatImmToInt32BitwiseCast(float value)
</ins><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="cx">     BasicBlock* root = proc.addBlock();
</span><ins>+    Value* argument = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), value);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, BitwiseCast, Origin(), argument));
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc), bitwise_cast&lt;int32_t&gt;(value)));
+}
+
+void testBitwiseCastOnFloatInMemory(float value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadFloat = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Float, Origin(), address);
+    Value* cast = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), loadFloat);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), cast);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, &amp;value), bitwise_cast&lt;int32_t&gt;(value)));
+}
+
+void testInt32BArgToFloatBitwiseCast(int32_t value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, BitwiseCast, Origin(), argument));
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, value), bitwise_cast&lt;float&gt;(value)));
+}
+
+void testInt32BImmToFloatBitwiseCast(int32_t value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;Const64Value&gt;(proc, Origin(), value);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, BitwiseCast, Origin(), argument));
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc), bitwise_cast&lt;float&gt;(value)));
+}
+
+void testTwoBitwiseCastOnInt32(int32_t value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* first = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument);
+    Value* second = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), first);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), second);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, value), value));
+}
+
+void testBitwiseCastOnInt32InMemory(int32_t value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadFloat = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, Origin(), address);
+    Value* cast = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), loadFloat);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), cast);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, &amp;value), bitwise_cast&lt;float&gt;(value)));
+}
+
+void testConvertDoubleToFloatArg(double value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* asFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asFloat);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, value), static_cast&lt;float&gt;(value)));
+}
+
+void testConvertDoubleToFloatImm(double value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), value);
+    Value* asFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asFloat);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc), static_cast&lt;float&gt;(value)));
+}
+
+void testConvertDoubleToFloatMem(double value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadedDouble = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Double, Origin(), address);
+    Value* asFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), loadedDouble);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asFloat);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, &amp;value), static_cast&lt;float&gt;(value)));
+}
+
+void testConvertFloatToDoubleArg(float value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asDouble);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, bitwise_cast&lt;int32_t&gt;(value)), static_cast&lt;double&gt;(value)));
+}
+
+void testConvertFloatToDoubleImm(float value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), value);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asDouble);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), static_cast&lt;double&gt;(value)));
+}
+
+void testConvertFloatToDoubleMem(float value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadedFloat = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Float, Origin(), address);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), loadedFloat);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asDouble);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, &amp;value), static_cast&lt;double&gt;(value)));
+}
+
+void testConvertDoubleToFloatToDoubleToFloat(double value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* asFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), argument);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), asFloat);
+    Value* asFloatAgain = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), asDouble);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asFloatAgain);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, value), static_cast&lt;float&gt;(value)));
+}
+
+void testLoadFloatConvertDoubleConvertFloatStoreFloat(float value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* src = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* dst = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1);
+    MemoryValue* loadedFloat = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Float, Origin(), src);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), loadedFloat);
+    Value* asFloatAgain = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), asDouble);
+    root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), asFloatAgain, dst);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 0));
+
+    float input = value;
+    float output = 0.;
+    CHECK(!compileAndRun&lt;int64_t&gt;(proc, &amp;input, &amp;output));
+    CHECK(isIdentical(input, output));
+}
+
+void testFroundArg(double value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* asFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), argument);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), asFloat);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asDouble);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, value), static_cast&lt;double&gt;(static_cast&lt;float&gt;(value))));
+}
+
+void testFroundMem(double value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadedDouble = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Double, Origin(), address);
+    Value* asFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), loadedDouble);
+    Value* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), asFloat);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), asDouble);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, &amp;value), static_cast&lt;double&gt;(static_cast&lt;float&gt;(value))));
+}
+
+void testStore32(int value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
</ins><span class="cx">     int slot = 0xbaadbeef;
</span><span class="cx">     root-&gt;appendNew&lt;MemoryValue&gt;(
</span><span class="cx">         proc, Store, Origin(),
</span><span class="lines">@@ -2613,22 +3433,28 @@
</span><span class="cx">     CHECK(compileAndRun&lt;int&gt;(proc, value) == value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-int32_t modelLoad(int32_t value)
</del><ins>+template&lt;typename LoadedType, typename EffectiveType&gt;
+EffectiveType modelLoad(EffectiveType value)
</ins><span class="cx"> {
</span><span class="cx">     union {
</span><del>-        int32_t original;
-        T loaded;
</del><ins>+        EffectiveType original;
+        LoadedType loaded;
</ins><span class="cx">     } u;
</span><span class="cx"> 
</span><span class="cx">     u.original = value;
</span><del>-    if (std::is_signed&lt;T&gt;::value)
-        return static_cast&lt;int32_t&gt;(u.loaded);
-    return static_cast&lt;int32_t&gt;(static_cast&lt;uint32_t&gt;(u.loaded));
</del><ins>+    if (std::is_signed&lt;LoadedType&gt;::value)
+        return static_cast&lt;EffectiveType&gt;(u.loaded);
+    return static_cast&lt;EffectiveType&gt;(static_cast&lt;typename std::make_unsigned&lt;EffectiveType&gt;::type&gt;(u.loaded));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-void testLoad(B3::Opcode opcode, int32_t value)
</del><ins>+template&lt;&gt;
+float modelLoad&lt;float, float&gt;(float value) { return value; }
+
+template&lt;&gt;
+double modelLoad&lt;double, double&gt;(double value) { return value; }
+
+template&lt;B3::Type type, typename CType, typename InputType&gt;
+void testLoad(B3::Opcode opcode, InputType value)
</ins><span class="cx"> {
</span><span class="cx">     // Simple load from an absolute address.
</span><span class="cx">     {
</span><span class="lines">@@ -2638,10 +3464,10 @@
</span><span class="cx">         root-&gt;appendNew&lt;ControlValue&gt;(
</span><span class="cx">             proc, Return, Origin(),
</span><span class="cx">             root-&gt;appendNew&lt;MemoryValue&gt;(
</span><del>-                proc, opcode, Int32, Origin(),
</del><ins>+                proc, opcode, type, Origin(),
</ins><span class="cx">                 root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;value)));
</span><span class="cx"> 
</span><del>-        CHECK(compileAndRun&lt;int32_t&gt;(proc) == modelLoad&lt;T&gt;(value));
</del><ins>+        CHECK(isIdentical(compileAndRun&lt;CType&gt;(proc), modelLoad&lt;CType&gt;(value)));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Simple load from an address in a register.
</span><span class="lines">@@ -2652,10 +3478,10 @@
</span><span class="cx">         root-&gt;appendNew&lt;ControlValue&gt;(
</span><span class="cx">             proc, Return, Origin(),
</span><span class="cx">             root-&gt;appendNew&lt;MemoryValue&gt;(
</span><del>-                proc, opcode, Int32, Origin(),
</del><ins>+                proc, opcode, type, Origin(),
</ins><span class="cx">                 root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0)));
</span><span class="cx"> 
</span><del>-        CHECK(compileAndRun&lt;int32_t&gt;(proc, &amp;value) == modelLoad&lt;T&gt;(value));
</del><ins>+        CHECK(isIdentical(compileAndRun&lt;CType&gt;(proc, &amp;value), modelLoad&lt;CType&gt;(value)));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Simple load from an address in a register, at an offset.
</span><span class="lines">@@ -2666,11 +3492,11 @@
</span><span class="cx">         root-&gt;appendNew&lt;ControlValue&gt;(
</span><span class="cx">             proc, Return, Origin(),
</span><span class="cx">             root-&gt;appendNew&lt;MemoryValue&gt;(
</span><del>-                proc, opcode, Int32, Origin(),
</del><ins>+                proc, opcode, type, Origin(),
</ins><span class="cx">                 root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0),
</span><del>-                sizeof(int32_t)));
</del><ins>+                sizeof(InputType)));
</ins><span class="cx"> 
</span><del>-        CHECK(compileAndRun&lt;int32_t&gt;(proc, &amp;value - 1) == modelLoad&lt;T&gt;(value));
</del><ins>+        CHECK(isIdentical(compileAndRun&lt;CType&gt;(proc, &amp;value - 1), modelLoad&lt;CType&gt;(value)));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Load from a simple base-index with various scales.
</span><span class="lines">@@ -2681,7 +3507,7 @@
</span><span class="cx">         root-&gt;appendNew&lt;ControlValue&gt;(
</span><span class="cx">             proc, Return, Origin(),
</span><span class="cx">             root-&gt;appendNew&lt;MemoryValue&gt;(
</span><del>-                proc, opcode, Int32, Origin(),
</del><ins>+                proc, opcode, type, Origin(),
</ins><span class="cx">                 root-&gt;appendNew&lt;Value&gt;(
</span><span class="cx">                     proc, Add, Origin(),
</span><span class="cx">                     root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0),
</span><span class="lines">@@ -2690,7 +3516,7 @@
</span><span class="cx">                         root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1),
</span><span class="cx">                         root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), logScale)))));
</span><span class="cx"> 
</span><del>-        CHECK(compileAndRun&lt;int32_t&gt;(proc, &amp;value - 2, (sizeof(int32_t) * 2) &gt;&gt; logScale) == modelLoad&lt;T&gt;(value));
</del><ins>+        CHECK(isIdentical(compileAndRun&lt;CType&gt;(proc, &amp;value - 2, (sizeof(InputType) * 2) &gt;&gt; logScale), modelLoad&lt;CType&gt;(value)));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Load from a simple base-index with various scales, but commuted.
</span><span class="lines">@@ -2701,7 +3527,7 @@
</span><span class="cx">         root-&gt;appendNew&lt;ControlValue&gt;(
</span><span class="cx">             proc, Return, Origin(),
</span><span class="cx">             root-&gt;appendNew&lt;MemoryValue&gt;(
</span><del>-                proc, opcode, Int32, Origin(),
</del><ins>+                proc, opcode, type, Origin(),
</ins><span class="cx">                 root-&gt;appendNew&lt;Value&gt;(
</span><span class="cx">                     proc, Add, Origin(),
</span><span class="cx">                     root-&gt;appendNew&lt;Value&gt;(
</span><span class="lines">@@ -2710,10 +3536,66 @@
</span><span class="cx">                         root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), logScale)),
</span><span class="cx">                     root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0))));
</span><span class="cx"> 
</span><del>-        CHECK(compileAndRun&lt;int32_t&gt;(proc, &amp;value - 2, (sizeof(int32_t) * 2) &gt;&gt; logScale) == modelLoad&lt;T&gt;(value));
</del><ins>+        CHECK(isIdentical(compileAndRun&lt;CType&gt;(proc, &amp;value - 2, (sizeof(InputType) * 2) &gt;&gt; logScale), modelLoad&lt;CType&gt;(value)));
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T&gt;
+void testLoad(B3::Opcode opcode, int32_t value)
+{
+    return testLoad&lt;Int32, T&gt;(opcode, value);
+}
+
+template&lt;B3::Type type, typename T&gt;
+void testLoad(T value)
+{
+    return testLoad&lt;type, T&gt;(Load, value);
+}
+
+void testStoreFloat(double input)
+{
+    // Simple store from an address in a register.
+    {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+        Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+        Value* argumentAsFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), argument);
+
+        Value* destinationAddress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+        root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), argumentAsFloat, destinationAddress);
+
+        root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 0));
+
+        float output = 0.;
+        CHECK(!compileAndRun&lt;int64_t&gt;(proc, input, &amp;output));
+        CHECK(isIdentical(static_cast&lt;float&gt;(input), output));
+    }
+
+    // Simple indexed store.
+    {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+        Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+        Value* argumentAsFloat = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), argument);
+
+        Value* destinationBaseAddress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+        Value* index = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1);
+        Value* scaledIndex = root-&gt;appendNew&lt;Value&gt;(
+            proc, Shl, Origin(),
+            index,
+            root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 2));
+        Value* destinationAddress = root-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), scaledIndex, destinationBaseAddress);
+
+        root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), argumentAsFloat, destinationAddress);
+
+        root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 0));
+
+        float output = 0.;
+        CHECK(!compileAndRun&lt;int64_t&gt;(proc, input, &amp;output - 1, 1));
+        CHECK(isIdentical(static_cast&lt;float&gt;(input), output));
+    }
+}
+
</ins><span class="cx"> void testSpillGP()
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -4971,6 +5853,17 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), value));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testReturnFloat(float value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), value));
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc), value));
+}
+
</ins><span class="cx"> double simpleFunctionDouble(double a, double b)
</span><span class="cx"> {
</span><span class="cx">     return a + b;
</span><span class="lines">@@ -4991,6 +5884,32 @@
</span><span class="cx">     CHECK(compileAndRun&lt;double&gt;(proc, a, b) == a + b);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+float simpleFunctionFloat(float a, float b)
+{
+    return a + b;
+}
+
+void testCallSimpleFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;CCallValue&gt;(
+            proc, Float, Origin(),
+            root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), bitwise_cast&lt;void*&gt;(simpleFunctionFloat)),
+            floatValue1,
+            floatValue2));
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), a + b));
+}
+
</ins><span class="cx"> double functionWithHellaDoubleArguments(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j, double k, double l, double m, double n, double o, double p, double q, double r, double s, double t, double u, double v, double w, double x, double y, double z)
</span><span class="cx"> {
</span><span class="cx">     return a * pow(2, 0) + b * pow(2, 1) + c * pow(2, 2) + d * pow(2, 3) + e * pow(2, 4) + f * pow(2, 5) + g * pow(2, 6) + h * pow(2, 7) + i * pow(2, 8) + j * pow(2, 9) + k * pow(2, 10) + l * pow(2, 11) + m * pow(2, 12) + n * pow(2, 13) + o * pow(2, 14) + p * pow(2, 15) + q * pow(2, 16) + r * pow(2, 17) + s * pow(2, 18) + t * pow(2, 19) + u * pow(2, 20) + v * pow(2, 21) + w * pow(2, 22) + x * pow(2, 23) + y * pow(2, 24) + z * pow(2, 25);
</span><span class="lines">@@ -5015,6 +5934,30 @@
</span><span class="cx">     CHECK(compileAndRun&lt;double&gt;(proc) == functionWithHellaDoubleArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+float functionWithHellaFloatArguments(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p, float q, float r, float s, float t, float u, float v, float w, float x, float y, float z)
+{
+    return a * pow(2, 0) + b * pow(2, 1) + c * pow(2, 2) + d * pow(2, 3) + e * pow(2, 4) + f * pow(2, 5) + g * pow(2, 6) + h * pow(2, 7) + i * pow(2, 8) + j * pow(2, 9) + k * pow(2, 10) + l * pow(2, 11) + m * pow(2, 12) + n * pow(2, 13) + o * pow(2, 14) + p * pow(2, 15) + q * pow(2, 16) + r * pow(2, 17) + s * pow(2, 18) + t * pow(2, 19) + u * pow(2, 20) + v * pow(2, 21) + w * pow(2, 22) + x * pow(2, 23) + y * pow(2, 24) + z * pow(2, 25);
+}
+
+void testCallFunctionWithHellaFloatArguments()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Vector&lt;Value*&gt; args;
+    for (unsigned i = 0; i &lt; 26; ++i)
+        args.append(root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), i + 1));
+
+    CCallValue* call = root-&gt;appendNew&lt;CCallValue&gt;(
+        proc, Float, Origin(),
+        root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), bitwise_cast&lt;void*&gt;(functionWithHellaFloatArguments)));
+    call-&gt;children().appendVector(args);
+    
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), call);
+
+    CHECK(compileAndRun&lt;float&gt;(proc) == functionWithHellaFloatArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26));
+}
+
</ins><span class="cx"> void testChillDiv(int num, int den, int res)
</span><span class="cx"> {
</span><span class="cx">     // Test non-constant.
</span><span class="lines">@@ -5367,6 +6310,78 @@
</span><span class="cx">     CHECK(invoke&lt;intptr_t&gt;(*code, 42.52, 42.52, 524978245, 352) == 352);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;B3::Opcode opcode&gt;
+void testSelectCompareFloat(float a, float b, bool (*operation)(float, float))
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Select, Origin(),
+            root-&gt;appendNew&lt;Value&gt;(
+                proc, opcode, Origin(),
+                floatValue1,
+                floatValue2),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR3)));
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), 42, -5), operation(a, b) ? 42 : -5));
+}
+
+void testSelectCompareFloat(float a, float b)
+{
+    testSelectCompareFloat&lt;Equal&gt;(a, b, [](float a, float b) -&gt; bool { return a == b; });
+    testSelectCompareFloat&lt;NotEqual&gt;(a, b, [](float a, float b) -&gt; bool { return a != b; });
+    testSelectCompareFloat&lt;LessThan&gt;(a, b, [](float a, float b) -&gt; bool { return a &lt; b; });
+    testSelectCompareFloat&lt;GreaterThan&gt;(a, b, [](float a, float b) -&gt; bool { return a &gt; b; });
+    testSelectCompareFloat&lt;LessEqual&gt;(a, b, [](float a, float b) -&gt; bool { return a &lt;= b; });
+    testSelectCompareFloat&lt;GreaterEqual&gt;(a, b, [](float a, float b) -&gt; bool { return a &gt;= b; });
+}
+
+template&lt;B3::Opcode opcode&gt;
+void testSelectCompareFloatToDouble(float a, float b, bool (*operation)(float, float))
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* doubleValue1 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue1);
+    Value* doubleValue2 = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue2);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Select, Origin(),
+            root-&gt;appendNew&lt;Value&gt;(
+                proc, opcode, Origin(),
+                doubleValue1,
+                doubleValue2),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR3)));
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), 42, -5), operation(a, b) ? 42 : -5));
+}
+
+void testSelectCompareFloatToDouble(float a, float b)
+{
+    testSelectCompareFloatToDouble&lt;Equal&gt;(a, b, [](float a, float b) -&gt; bool { return a == b; });
+    testSelectCompareFloatToDouble&lt;NotEqual&gt;(a, b, [](float a, float b) -&gt; bool { return a != b; });
+    testSelectCompareFloatToDouble&lt;LessThan&gt;(a, b, [](float a, float b) -&gt; bool { return a &lt; b; });
+    testSelectCompareFloatToDouble&lt;GreaterThan&gt;(a, b, [](float a, float b) -&gt; bool { return a &gt; b; });
+    testSelectCompareFloatToDouble&lt;LessEqual&gt;(a, b, [](float a, float b) -&gt; bool { return a &lt;= b; });
+    testSelectCompareFloatToDouble&lt;GreaterEqual&gt;(a, b, [](float a, float b) -&gt; bool { return a &gt;= b; });
+}
+
</ins><span class="cx"> void testSelectDouble()
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -5431,6 +6446,62 @@
</span><span class="cx">     CHECK(invoke&lt;double&gt;(*code, 42.52, 42.52, 524978245.9, 352.0) == 352.0);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testSelectDoubleCompareFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Select, Origin(),
+            root-&gt;appendNew&lt;Value&gt;(
+                proc, LessThan, Origin(),
+                floatValue1,
+                floatValue2),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR1)));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), 42.1, -M_PI), a &lt; b ? 42.1 : -M_PI));
+}
+
+void testSelectFloatCompareFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* argument3int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR2));
+    Value* argument4int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR3));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* floatValue3 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument3int32);
+    Value* floatValue4 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument4int32);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Select, Origin(),
+            root-&gt;appendNew&lt;Value&gt;(
+                proc, LessThan, Origin(),
+                floatValue1,
+                floatValue2),
+            floatValue3,
+            floatValue4));
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b), bitwise_cast&lt;int32_t&gt;(1.1f), bitwise_cast&lt;int32_t&gt;(-42.f)), a &lt; b ? 1.1f : -42.f));
+}
+
</ins><span class="cx"> void testSelectFold(intptr_t value)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -5487,47 +6558,47 @@
</span><span class="cx">     return -zero();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Some convenience functions for brevity of the test output.
-double posInfinity()
-{
-    return std::numeric_limits&lt;double&gt;::infinity();
-}
-
-double negInfinity()
-{
-    return -std::numeric_limits&lt;double&gt;::infinity();
-}
-
</del><span class="cx"> template&lt;typename Type&gt;
</span><span class="cx"> struct Operand {
</span><span class="cx">     const char* name;
</span><span class="cx">     Type value;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-typedef Operand&lt;double&gt; DoubleOperand;
</del><span class="cx"> typedef Operand&lt;int64_t&gt; Int64Operand;
</span><span class="cx"> typedef Operand&lt;int32_t&gt; Int32Operand;
</span><span class="cx"> 
</span><del>-static const std::array&lt;DoubleOperand, 9&gt;&amp; doubleOperands()
</del><ins>+template&lt;typename FloatType&gt;
+void populateWithInterestingValues(Vector&lt;Operand&lt;FloatType&gt;&gt;&amp; operands)
</ins><span class="cx"> {
</span><del>-    static const std::array&lt;DoubleOperand, 9&gt; operands = {{
-        { &quot;M_PI&quot;, M_PI },
-        { &quot;-M_PI&quot;, -M_PI },
-        { &quot;1.&quot;, 1 },
-        { &quot;-1.&quot;, -1 },
-        { &quot;0&quot;, 0 },
-        { &quot;negativeZero()&quot;, negativeZero() },
-        { &quot;posInfinity()&quot;, posInfinity() },
-        { &quot;negInfinity()&quot;, negInfinity() },
-        { &quot;PNaN&quot;, PNaN },
-    }};
</del><ins>+    operands.append({ &quot;0.&quot;, static_cast&lt;FloatType&gt;(0.) });
+    operands.append({ &quot;-0.&quot;, static_cast&lt;FloatType&gt;(-0.) });
+    operands.append({ &quot;1.&quot;, static_cast&lt;FloatType&gt;(0.) });
+    operands.append({ &quot;-1.&quot;, static_cast&lt;FloatType&gt;(-0.) });
+    operands.append({ &quot;2.&quot;, static_cast&lt;FloatType&gt;(2.) });
+    operands.append({ &quot;-2.&quot;, static_cast&lt;FloatType&gt;(2.) });
+    operands.append({ &quot;M_PI&quot;, static_cast&lt;FloatType&gt;(M_PI) });
+    operands.append({ &quot;-M_PI&quot;, static_cast&lt;FloatType&gt;(-M_PI) });
+    operands.append({ &quot;min&quot;, std::numeric_limits&lt;FloatType&gt;::min() });
+    operands.append({ &quot;max&quot;, std::numeric_limits&lt;FloatType&gt;::max() });
+    operands.append({ &quot;lowest&quot;, std::numeric_limits&lt;FloatType&gt;::lowest() });
+    operands.append({ &quot;epsilon&quot;, std::numeric_limits&lt;FloatType&gt;::epsilon() });
+    operands.append({ &quot;infiniti&quot;, std::numeric_limits&lt;FloatType&gt;::infinity() });
+    operands.append({ &quot;-infiniti&quot;, - std::numeric_limits&lt;FloatType&gt;::infinity() });
+    operands.append({ &quot;PNaN&quot;, static_cast&lt;FloatType&gt;(PNaN) });
+}
+
+template&lt;typename FloatType&gt;
+Vector&lt;Operand&lt;FloatType&gt;&gt; floatingPointOperands()
+{
+    Vector&lt;Operand&lt;FloatType&gt;&gt; operands;
+    populateWithInterestingValues(operands);
</ins><span class="cx">     return operands;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static Vector&lt;Int64Operand&gt; int64Operands()
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;Int64Operand&gt; operands;
</span><del>-    for (DoubleOperand doubleOperand : doubleOperands())
</del><ins>+    for (const auto&amp; doubleOperand : floatingPointOperands&lt;double&gt;())
</ins><span class="cx">         operands.append({ doubleOperand.name, bitwise_cast&lt;int64_t&gt;(doubleOperand.value) });
</span><span class="cx">     operands.append({ &quot;1&quot;, 1 });
</span><span class="cx">     operands.append({ &quot;-1&quot;, -1 });
</span><span class="lines">@@ -5646,6 +6717,14 @@
</span><span class="cx">     RUN(testAddImmsDouble(0, 0));
</span><span class="cx">     RUN(testAddImmsDouble(0, negativeZero()));
</span><span class="cx">     RUN(testAddImmsDouble(negativeZero(), negativeZero()));
</span><ins>+    RUN_UNARY(testAddArgFloat, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testAddArgsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testAddArgImmFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testAddImmArgFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testAddImmsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testAddArgFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testAddArgsFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testAddArgsFloatWithEffectfulDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</ins><span class="cx"> 
</span><span class="cx">     RUN(testMulArg(5));
</span><span class="cx">     RUN(testMulAddArg(5));
</span><span class="lines">@@ -5687,11 +6766,19 @@
</span><span class="cx">     RUN(testMulArgs32(1, 2));
</span><span class="cx">     RUN(testMulLoadTwice());
</span><span class="cx"> 
</span><del>-    RUN_UNARY(testMulArgDouble, doubleOperands());
-    RUN_BINARY(testMulArgsDouble, doubleOperands(), doubleOperands());
-    RUN_BINARY(testMulArgImmDouble, doubleOperands(), doubleOperands());
-    RUN_BINARY(testMulImmArgDouble, doubleOperands(), doubleOperands());
-    RUN_BINARY(testMulImmsDouble, doubleOperands(), doubleOperands());
</del><ins>+    RUN_UNARY(testMulArgDouble, floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testMulArgsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testMulArgImmDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testMulImmArgDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testMulImmsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testMulArgFloat, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testMulArgsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testMulArgImmFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testMulImmArgFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testMulImmsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testMulArgFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testMulArgsFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testMulArgsFloatWithEffectfulDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</ins><span class="cx"> 
</span><span class="cx">     RUN(testDivArgDouble(M_PI));
</span><span class="cx">     RUN(testDivArgsDouble(M_PI, 1));
</span><span class="lines">@@ -5716,6 +6803,14 @@
</span><span class="cx">     RUN(testDivImmsDouble(0, 0));
</span><span class="cx">     RUN(testDivImmsDouble(0, negativeZero()));
</span><span class="cx">     RUN(testDivImmsDouble(negativeZero(), negativeZero()));
</span><ins>+    RUN_UNARY(testDivArgFloat, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testDivArgsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testDivArgImmFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testDivImmArgFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testDivImmsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testDivArgFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</ins><span class="cx"> 
</span><span class="cx">     RUN(testSubArg(24));
</span><span class="cx">     RUN(testSubArgs(1, 1));
</span><span class="lines">@@ -5747,11 +6842,19 @@
</span><span class="cx">     RUN(testSubImmArg32(-13, 42));
</span><span class="cx">     RUN_UNARY(testNegValueSubOne32, int64Operands());
</span><span class="cx"> 
</span><del>-    RUN_UNARY(testSubArgDouble, doubleOperands());
-    RUN_BINARY(testSubArgsDouble, doubleOperands(), doubleOperands());
-    RUN_BINARY(testSubArgImmDouble, doubleOperands(), doubleOperands());
-    RUN_BINARY(testSubImmArgDouble, doubleOperands(), doubleOperands());
-    RUN_BINARY(testSubImmsDouble, doubleOperands(), doubleOperands());
</del><ins>+    RUN_UNARY(testSubArgDouble, floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testSubArgsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testSubArgImmDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testSubImmArgDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testSubImmsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testSubArgFloat, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSubArgsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSubArgImmFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSubImmArgFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSubImmsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testSubArgFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSubArgsFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSubArgsFloatWithEffectfulDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</ins><span class="cx"> 
</span><span class="cx">     RUN(testBitAndArgs(43, 43));
</span><span class="cx">     RUN(testBitAndArgs(43, 0));
</span><span class="lines">@@ -6037,20 +7140,43 @@
</span><span class="cx">     RUN_UNARY(testClzArg32, int32Operands());
</span><span class="cx">     RUN_UNARY(testClzMem32, int64Operands());
</span><span class="cx"> 
</span><del>-    RUN_UNARY(testSqrtArg, doubleOperands());
-    RUN_UNARY(testSqrtImm, doubleOperands());
-    RUN_UNARY(testSqrtMem, doubleOperands());
</del><ins>+    RUN_UNARY(testSqrtArg, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testSqrtImm, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testSqrtMem, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testSqrtArg, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testSqrtImm, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testSqrtMem, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testSqrtArgWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testSqrtArgWithEffectfulDoubleConversion, floatingPointOperands&lt;float&gt;());
</ins><span class="cx"> 
</span><del>-    RUN_UNARY(testDoubleArgToInt64BitwiseCast, doubleOperands());
-    RUN_UNARY(testDoubleImmToInt64BitwiseCast, doubleOperands());
-    RUN_UNARY(testTwoBitwiseCastOnDouble, doubleOperands());
-    RUN_UNARY(testBitwiseCastOnDoubleInMemory, doubleOperands());
</del><ins>+    RUN_UNARY(testDoubleArgToInt64BitwiseCast, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testDoubleImmToInt64BitwiseCast, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testTwoBitwiseCastOnDouble, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testBitwiseCastOnDoubleInMemory, floatingPointOperands&lt;double&gt;());
</ins><span class="cx">     RUN_UNARY(testInt64BArgToDoubleBitwiseCast, int64Operands());
</span><span class="cx">     RUN_UNARY(testInt64BImmToDoubleBitwiseCast, int64Operands());
</span><span class="cx">     RUN_UNARY(testTwoBitwiseCastOnInt64, int64Operands());
</span><span class="cx">     RUN_UNARY(testBitwiseCastOnInt64InMemory, int64Operands());
</span><ins>+    RUN_UNARY(testFloatImmToInt32BitwiseCast, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testBitwiseCastOnFloatInMemory, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testInt32BArgToFloatBitwiseCast, int32Operands());
+    RUN_UNARY(testInt32BImmToFloatBitwiseCast, int32Operands());
+    RUN_UNARY(testTwoBitwiseCastOnInt32, int32Operands());
+    RUN_UNARY(testBitwiseCastOnInt32InMemory, int32Operands());
</ins><span class="cx"> 
</span><del>-    RUN(testStore(44));
</del><ins>+    RUN_UNARY(testConvertDoubleToFloatArg, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testConvertDoubleToFloatImm, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testConvertDoubleToFloatMem, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testConvertFloatToDoubleArg, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testConvertFloatToDoubleImm, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testConvertFloatToDoubleMem, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testConvertDoubleToFloatToDoubleToFloat, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testStoreFloat, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testLoadFloatConvertDoubleConvertFloatStoreFloat, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testFroundArg, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testFroundMem, floatingPointOperands&lt;double&gt;());
+
+    RUN(testStore32(44));
</ins><span class="cx">     RUN(testStoreConstant(49));
</span><span class="cx">     RUN(testStoreConstantPtr(49));
</span><span class="cx">     RUN(testTrunc((static_cast&lt;int64_t&gt;(1) &lt;&lt; 40) + 42));
</span><span class="lines">@@ -6164,14 +7290,17 @@
</span><span class="cx">     RUN(testCompare(BitAnd, 42, 42));
</span><span class="cx">     RUN(testCompare(BitAnd, 42, 0));
</span><span class="cx"> 
</span><del>-    RUN(testLoad&lt;int32_t&gt;(Load, 60));
-    RUN(testLoad&lt;int32_t&gt;(Load, -60));
-    RUN(testLoad&lt;int32_t&gt;(Load, 1000));
-    RUN(testLoad&lt;int32_t&gt;(Load, -1000));
-    RUN(testLoad&lt;int32_t&gt;(Load, 1000000));
-    RUN(testLoad&lt;int32_t&gt;(Load, -1000000));
-    RUN(testLoad&lt;int32_t&gt;(Load, 1000000000));
-    RUN(testLoad&lt;int32_t&gt;(Load, -1000000000));
</del><ins>+    RUN(testLoad&lt;Int32&gt;(60));
+    RUN(testLoad&lt;Int32&gt;(-60));
+    RUN(testLoad&lt;Int32&gt;(1000));
+    RUN(testLoad&lt;Int32&gt;(-1000));
+    RUN(testLoad&lt;Int32&gt;(1000000));
+    RUN(testLoad&lt;Int32&gt;(-1000000));
+    RUN(testLoad&lt;Int32&gt;(1000000000));
+    RUN(testLoad&lt;Int32&gt;(-1000000000));
+    RUN_UNARY(testLoad&lt;Int64&gt;, int64Operands());
+    RUN_UNARY(testLoad&lt;Float&gt;, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testLoad&lt;Double&gt;, floatingPointOperands&lt;double&gt;());
</ins><span class="cx">     
</span><span class="cx">     RUN(testLoad&lt;int8_t&gt;(Load8S, 60));
</span><span class="cx">     RUN(testLoad&lt;int8_t&gt;(Load8S, -60));
</span><span class="lines">@@ -6222,9 +7351,12 @@
</span><span class="cx">     RUN(testReturnDouble(0.0));
</span><span class="cx">     RUN(testReturnDouble(negativeZero()));
</span><span class="cx">     RUN(testReturnDouble(42.5));
</span><ins>+    RUN_UNARY(testReturnFloat, floatingPointOperands&lt;float&gt;());
</ins><span class="cx"> 
</span><span class="cx">     RUN(testCallSimpleDouble(1, 2));
</span><span class="cx">     RUN(testCallFunctionWithHellaDoubleArguments());
</span><ins>+    RUN_BINARY(testCallSimpleFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN(testCallFunctionWithHellaFloatArguments());
</ins><span class="cx"> 
</span><span class="cx">     RUN(testChillDiv(4, 2, 2));
</span><span class="cx">     RUN(testChillDiv(1, 0, 0));
</span><span class="lines">@@ -6311,9 +7443,13 @@
</span><span class="cx">     RUN(testBasicSelect());
</span><span class="cx">     RUN(testSelectTest());
</span><span class="cx">     RUN(testSelectCompareDouble());
</span><ins>+    RUN_BINARY(testSelectCompareFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSelectCompareFloatToDouble, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</ins><span class="cx">     RUN(testSelectDouble());
</span><span class="cx">     RUN(testSelectDoubleTest());
</span><span class="cx">     RUN(testSelectDoubleCompareDouble());
</span><ins>+    RUN_BINARY(testSelectDoubleCompareFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testSelectFloatCompareFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</ins><span class="cx">     RUN(testSelectFold(42));
</span><span class="cx">     RUN(testSelectFold(43));
</span><span class="cx">     RUN(testSelectInvert());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -99,9 +99,8 @@
</span><span class="cx"> 
</span><span class="cx"> LValue Output::loadFloatToDouble(TypedPointer pointer)
</span><span class="cx"> {
</span><del>-    LValue load = m_block-&gt;appendNew&lt;B3::MemoryValue&gt;(m_proc, B3::LoadFloat, B3::Double, origin(), pointer.value());
-    pointer.heap().decorateInstruction(load, *m_heaps);
-    return load;
</del><ins>+    LValue loadedFloat = load(pointer, floatType);
+    return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::FloatToDouble, origin(), loadedFloat);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Output::store(LValue value, TypedPointer pointer)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -198,9 +198,8 @@
</span><span class="cx">     LValue intToPtr(LValue value, LType type) { CRASH(); }
</span><span class="cx">     LValue ptrToInt(LValue value, LType type) { CRASH(); }
</span><span class="cx">     LValue bitCast(LValue, LType);
</span><ins>+    LValue fround(LValue doubleValue);
</ins><span class="cx"> 
</span><del>-    LValue fround(LValue doubleValue) { CRASH(); }
-
</del><span class="cx">     LValue load(TypedPointer, LType);
</span><span class="cx">     void store(LValue, TypedPointer);
</span><span class="cx"> 
</span><span class="lines">@@ -487,6 +486,12 @@
</span><span class="cx">     return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::BitwiseCast, origin(), value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline LValue Output::fround(LValue doubleValue)
+{
+    LValue asFloat = m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::DoubleToFloat, origin(), doubleValue);
+    return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::FloatToDouble, origin(), asFloat);
+}
+
</ins><span class="cx"> #if COMPILER(CLANG)
</span><span class="cx"> #pragma clang diagnostic pop
</span><span class="cx"> #endif // COMPILER(CLANG)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCommonValuescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCommonValues.cpp (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCommonValues.cpp        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/ftl/FTLCommonValues.cpp        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx">     , int32(B3::Int32)
</span><span class="cx">     , int64(B3::Int64)
</span><span class="cx">     , intPtr(B3::pointerType())
</span><ins>+    , floatType(B3::Doule)
</ins><span class="cx">     , doubleType(B3::Double)
</span><span class="cx"> #else
</span><span class="cx">     : voidType(FTL::voidType(context))
</span><span class="lines">@@ -56,10 +57,10 @@
</span><span class="cx">     , int32(int32Type(context))
</span><span class="cx">     , int64(int64Type(context))
</span><span class="cx">     , intPtr(intPtrType(context))
</span><ins>+    , floatType(FTL::floatType(context))
</ins><span class="cx">     , doubleType(FTL::doubleType(context))
</span><span class="cx">     , int8(int8Type(context))
</span><span class="cx">     , int16(int16Type(context))
</span><del>-    , floatType(FTL::floatType(context))
</del><span class="cx">     , ref8(pointerType(int8))
</span><span class="cx">     , ref16(pointerType(int16))
</span><span class="cx">     , ref32(pointerType(int32))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCommonValuesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCommonValues.h (193682 => 193683)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCommonValues.h        2015-12-08 02:46:22 UTC (rev 193682)
+++ trunk/Source/JavaScriptCore/ftl/FTLCommonValues.h        2015-12-08 02:56:16 UTC (rev 193683)
</span><span class="lines">@@ -58,11 +58,11 @@
</span><span class="cx">     const LType int32;
</span><span class="cx">     const LType int64;
</span><span class="cx">     const LType intPtr;
</span><ins>+    const LType floatType;
</ins><span class="cx">     const LType doubleType;
</span><span class="cx"> #if !FTL_USES_B3
</span><span class="cx">     const LType int8;
</span><span class="cx">     const LType int16;
</span><del>-    const LType floatType;
</del><span class="cx">     const LType ref8;
</span><span class="cx">     const LType ref16;
</span><span class="cx">     const LType ref32;
</span></span></pre>
</div>
</div>

</body>
</html>