DFG should have a KnownBooleanUse for cases where we are required to know that the child is a boolean and it's not OK to speculate
https://bugs.webkit.org/show_bug.cgi?id=148286

Reviewed by Benjamin Poulain.

This enables us to ensure that the Branch or LogicalNot after an effectful CompareXYZ can
be marked as !mayExit(). I need that for https://bugs.webkit.org/show_bug.cgi?id=145204.

* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::observeUseKindOnNode):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::SafeToExecuteEdge::operator()):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::speculate):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculateBooleanOperand::SpeculateBooleanOperand):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):
* dfg/DFGUseKind.cpp:
(WTF::printInternal):
* dfg/DFGUseKind.h:
(JSC::DFG::typeFilterFor):
(JSC::DFG::shouldNotHaveTypeCheck):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::boolify):
(JSC::FTL::DFG::LowerDFGToLLVM::lowBoolean):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@188747 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 98b009e..ff675d9 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -356,9 +356,19 @@
         }
             
         case LogicalNot: {
-            if (node->child1()->shouldSpeculateBoolean())
-                fixEdge<BooleanUse>(node->child1());
-            else if (node->child1()->shouldSpeculateObjectOrOther())
+            if (node->child1()->shouldSpeculateBoolean()) {
+                if (node->child1()->result() == NodeResultBoolean) {
+                    // This is necessary in case we have a bytecode instruction implemented by:
+                    //
+                    // a: CompareEq(...)
+                    // b: LogicalNot(@a)
+                    //
+                    // In that case, CompareEq might have a side-effect. Then, we need to make
+                    // sure that we know that Branch does not exit.
+                    fixEdge<KnownBooleanUse>(node->child1());
+                } else
+                    fixEdge<BooleanUse>(node->child1());
+            } else if (node->child1()->shouldSpeculateObjectOrOther())
                 fixEdge<ObjectOrOtherUse>(node->child1());
             else if (node->child1()->shouldSpeculateInt32OrBoolean())
                 fixIntOrBooleanEdge(node->child1());
@@ -819,9 +829,19 @@
         }
             
         case Branch: {
-            if (node->child1()->shouldSpeculateBoolean())
-                fixEdge<BooleanUse>(node->child1());
-            else if (node->child1()->shouldSpeculateObjectOrOther())
+            if (node->child1()->shouldSpeculateBoolean()) {
+                if (node->child1()->result() == NodeResultBoolean) {
+                    // This is necessary in case we have a bytecode instruction implemented by:
+                    //
+                    // a: CompareEq(...)
+                    // b: Branch(@a)
+                    //
+                    // In that case, CompareEq might have a side-effect. Then, we need to make
+                    // sure that we know that Branch does not exit.
+                    fixEdge<KnownBooleanUse>(node->child1());
+                } else
+                    fixEdge<BooleanUse>(node->child1());
+            } else if (node->child1()->shouldSpeculateObjectOrOther())
                 fixEdge<ObjectOrOtherUse>(node->child1());
             else if (node->child1()->shouldSpeculateInt32OrBoolean())
                 fixIntOrBooleanEdge(node->child1());
@@ -1777,6 +1797,7 @@
         VariableAccessData* variable = node->variableAccessData();
         switch (useKind) {
         case Int32Use:
+        case KnownInt32Use:
             if (alwaysUnboxSimplePrimitives()
                 || isInt32Speculation(variable->prediction()))
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
@@ -1789,6 +1810,7 @@
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
             break;
         case BooleanUse:
+        case KnownBooleanUse:
             if (alwaysUnboxSimplePrimitives()
                 || isBooleanSpeculation(variable->prediction()))
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);