Title: [194314] trunk/Source/_javascript_Core
Revision
194314
Author
[email protected]
Date
2015-12-19 08:52:11 -0800 (Sat, 19 Dec 2015)

Log Message

[JSC] Add EqualOrUnordered to B3
https://bugs.webkit.org/show_bug.cgi?id=152425

Patch by Benjamin Poulain <[email protected]> on 2015-12-19
Reviewed by Mark Lam.

Add EqualOrUnordered to B3 and use it to implements
FTL::Output's NotEqualAndOrdered.

* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::equalOrUnordered):
* b3/B3ConstDoubleValue.h:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::createGenericCompare):
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceDoubleToFloat.cpp:
(JSC::B3::reduceDoubleToFloat):
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::equalOrUnordered):
(JSC::B3::Value::returnsBool):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/testb3.cpp:
(JSC::B3::testBranchEqualOrUnorderedArgs):
(JSC::B3::testBranchNotEqualAndOrderedArgs):
(JSC::B3::testBranchEqualOrUnorderedDoubleArgImm):
(JSC::B3::testBranchEqualOrUnorderedFloatArgImm):
(JSC::B3::testBranchEqualOrUnorderedDoubleImms):
(JSC::B3::testBranchEqualOrUnorderedFloatImms):
(JSC::B3::testBranchEqualOrUnorderedFloatWithUselessDoubleConversion):
(JSC::B3::run):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::doubleNotEqualAndOrdered):
(JSC::FTL::Output::doubleNotEqual): Deleted.
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::boolify):
* ftl/FTLOutput.h:
(JSC::FTL::Output::doubleNotEqualAndOrdered):
(JSC::FTL::Output::doubleNotEqual): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (194313 => 194314)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-19 16:52:11 UTC (rev 194314)
@@ -1,5 +1,53 @@
 2015-12-19  Benjamin Poulain  <[email protected]>
 
+        [JSC] Add EqualOrUnordered to B3
+        https://bugs.webkit.org/show_bug.cgi?id=152425
+
+        Reviewed by Mark Lam.
+
+        Add EqualOrUnordered to B3 and use it to implements
+        FTL::Output's NotEqualAndOrdered.
+
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::equalOrUnordered):
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::createGenericCompare):
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceDoubleToFloat.cpp:
+        (JSC::B3::reduceDoubleToFloat):
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::equalOrUnordered):
+        (JSC::B3::Value::returnsBool):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/testb3.cpp:
+        (JSC::B3::testBranchEqualOrUnorderedArgs):
+        (JSC::B3::testBranchNotEqualAndOrderedArgs):
+        (JSC::B3::testBranchEqualOrUnorderedDoubleArgImm):
+        (JSC::B3::testBranchEqualOrUnorderedFloatArgImm):
+        (JSC::B3::testBranchEqualOrUnorderedDoubleImms):
+        (JSC::B3::testBranchEqualOrUnorderedFloatImms):
+        (JSC::B3::testBranchEqualOrUnorderedFloatWithUselessDoubleConversion):
+        (JSC::B3::run):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::doubleNotEqualAndOrdered):
+        (JSC::FTL::Output::doubleNotEqual): Deleted.
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::boolify):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::doubleNotEqualAndOrdered):
+        (JSC::FTL::Output::doubleNotEqual): Deleted.
+
+2015-12-19  Benjamin Poulain  <[email protected]>
+
         [JSC] B3: Add indexed addressing when lowering BitwiseCast
         https://bugs.webkit.org/show_bug.cgi?id=152432
 

Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -158,6 +158,17 @@
     return triState(m_value >= other->asDouble());
 }
 
+TriState ConstDoubleValue::equalOrUnorderedConstant(const Value* other) const
+{
+    if (std::isnan(m_value))
+        return TrueTriState;
+
+    if (!other->hasDouble())
+        return MixedTriState;
+    double otherValue = other->asDouble();
+    return triState(std::isunordered(m_value, otherValue) || m_value == otherValue);
+}
+
 void ConstDoubleValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
 {
     out.print(comma);

Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h	2015-12-19 16:52:11 UTC (rev 194314)
@@ -60,6 +60,7 @@
     TriState greaterThanConstant(const Value* other) const override;
     TriState lessEqualConstant(const Value* other) const override;
     TriState greaterEqualConstant(const Value* other) const override;
+    TriState equalOrUnorderedConstant(const Value* other) const override;
 
 protected:
     void dumpMeta(CommaPrinter&, PrintStream&) const override;

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -1154,6 +1154,9 @@
                 return createRelCond(MacroAssembler::LessThanOrEqual, MacroAssembler::DoubleLessThanOrEqual);
             case GreaterEqual:
                 return createRelCond(MacroAssembler::GreaterThanOrEqual, MacroAssembler::DoubleGreaterThanOrEqual);
+            case EqualOrUnordered:
+                // The integer condition is never used in this case.
+                return createRelCond(MacroAssembler::Equal, MacroAssembler::DoubleEqualOrUnordered);
             case Above:
                 // We use a bogus double condition because these integer comparisons won't got down that
                 // path anyway.
@@ -1841,7 +1844,8 @@
         case Above:
         case Below:
         case AboveEqual:
-        case BelowEqual: {
+        case BelowEqual:
+        case EqualOrUnordered: {
             m_insts.last().append(createCompare(m_value));
             return;
         }

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -215,6 +215,9 @@
     case BelowEqual:
         out.print("BelowEqual");
         return;
+    case EqualOrUnordered:
+        out.print("EqualOrUnordered");
+        return;
     case Select:
         out.print("Select");
         return;

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3Opcode.h	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h	2015-12-19 16:52:11 UTC (rev 194314)
@@ -123,6 +123,9 @@
     AboveEqual,
     BelowEqual,
 
+    // Unordered floating point compare: values are equal or either one is NaN.
+    EqualOrUnordered,
+
     // SSA form of conditional move. The first child is evaluated for truthiness. If true, the second child
     // is returned. Otherwise, the third child is returned.
     Select,

Modified: trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -106,6 +106,7 @@
             case GreaterThan:
             case LessEqual:
             case GreaterEqual:
+            case EqualOrUnordered:
                 if (value->child(0)->opcode() == FloatToDouble && value->child(1)->opcode() == FloatToDouble) {
                     value->child(0) = value->child(0)->child(0);
                     value->child(1) = value->child(1)->child(0);

Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -1010,6 +1010,19 @@
                     m_value->child(0)->belowEqualConstant(m_value->child(1))));
             break;
 
+        case EqualOrUnordered:
+            handleCommutativity();
+
+            // Turn this: Equal(const1, const2)
+            // Into this: isunordered(const1, const2) || const1 == const2.
+            // Turn this: Equal(value, const_NaN)
+            // Into this: 1.
+            replaceWithNewValue(
+                m_proc.addBoolConstant(
+                    m_value->origin(),
+                    m_value->child(1)->equalOrUnorderedConstant(m_value->child(0))));
+            break;
+
         case CheckAdd:
             if (replaceWithNewValue(m_value->child(0)->checkAddConstant(m_proc, m_value->child(1))))
                 break;

Modified: trunk/Source/_javascript_Core/b3/B3Validate.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3Validate.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3Validate.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -255,6 +255,12 @@
                 VALIDATE(isInt(value->child(0)->type()), ("At ", *value));
                 VALIDATE(value->type() == Int32, ("At ", *value));
                 break;
+            case EqualOrUnordered:
+                VALIDATE(value->numChildren() == 2, ("At ", *value));
+                VALIDATE(value->child(0)->type() == value->child(1)->type(), ("At ", *value));
+                VALIDATE(isFloat(value->child(0)->type()), ("At ", *value));
+                VALIDATE(value->type() == Int32, ("At ", *value));
+                break;
             case Select:
                 VALIDATE(value->numChildren() == 3, ("At ", *value));
                 VALIDATE(isInt(value->child(0)->type()), ("At ", *value));

Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3Value.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -286,6 +286,11 @@
     return MixedTriState;
 }
 
+TriState Value::equalOrUnorderedConstant(const Value*) const
+{
+    return MixedTriState;
+}
+
 Value* Value::invertedCompare(Procedure& proc) const
 {
     if (!numChildren())
@@ -315,6 +320,7 @@
     case Below:
     case AboveEqual:
     case BelowEqual:
+    case EqualOrUnordered:
         return true;
     case Phi:
         // FIXME: We should have a story here.
@@ -390,6 +396,7 @@
     case Below:
     case AboveEqual:
     case BelowEqual:
+    case EqualOrUnordered:
     case Select:
         break;
     case Div:
@@ -484,6 +491,7 @@
     case Below:
     case AboveEqual:
     case BelowEqual:
+    case EqualOrUnordered:
     case CheckAdd:
     case CheckSub:
     case CheckMul:
@@ -578,6 +586,7 @@
     case Below:
     case AboveEqual:
     case BelowEqual:
+    case EqualOrUnordered:
         return Int32;
     case SExt32:
     case ZExt32:

Modified: trunk/Source/_javascript_Core/b3/B3Value.h (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/B3Value.h	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/B3Value.h	2015-12-19 16:52:11 UTC (rev 194314)
@@ -145,6 +145,7 @@
     virtual TriState belowConstant(const Value* other) const;
     virtual TriState aboveEqualConstant(const Value* other) const;
     virtual TriState belowEqualConstant(const Value* other) const;
+    virtual TriState equalOrUnorderedConstant(const Value* other) const;
 
     // If the value is a comparison then this returns the inverted form of that comparison, if
     // possible. It can be impossible for double comparisons, where for example LessThan and

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -5096,6 +5096,290 @@
     CHECK(invoke<int>(*code, 0) == 0);
 }
 
+void testBranchEqualOrUnorderedArgs(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        root->appendNew<Value>(
+            proc, EqualOrUnordered, Origin(),
+            argumentA,
+            argumentB),
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
+}
+
+void testBranchEqualOrUnorderedArgs(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        root->appendNew<Value>(
+            proc, EqualOrUnordered, Origin(),
+            argumentA,
+            argumentB),
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
+}
+
+void testBranchNotEqualAndOrderedArgs(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
+    Value* equalOrUnordered = root->appendNew<Value>(
+        proc, EqualOrUnordered, Origin(),
+        argumentA,
+        argumentB);
+    Value* notEqualAndOrdered = root->appendNew<Value>(
+        proc, Equal, Origin(),
+        root->appendNew<Const32Value>(proc, Origin(), 0),
+        equalOrUnordered);
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        notEqualAndOrdered,
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
+}
+
+void testBranchNotEqualAndOrderedArgs(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentB = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* equalOrUnordered = root->appendNew<Value>(
+        proc, EqualOrUnordered, Origin(),
+        argumentA,
+        argumentB);
+    Value* notEqualAndOrdered = root->appendNew<Value>(
+        proc, Equal, Origin(),
+        root->appendNew<Const32Value>(proc, Origin(), 0),
+        equalOrUnordered);
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        notEqualAndOrdered,
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (!std::isunordered(a, b) && a != b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
+}
+
+void testBranchEqualOrUnorderedDoubleArgImm(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        root->appendNew<Value>(
+            proc, EqualOrUnordered, Origin(),
+            argumentA,
+            argumentB),
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc, a) == expected);
+}
+
+void testBranchEqualOrUnorderedFloatArgImm(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
+
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        root->appendNew<Value>(
+            proc, EqualOrUnordered, Origin(),
+            argumentA,
+            argumentB),
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc, &a) == expected);
+}
+
+void testBranchEqualOrUnorderedDoubleImms(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
+    Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        root->appendNew<Value>(
+            proc, EqualOrUnordered, Origin(),
+            argumentA,
+            argumentB),
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc) == expected);
+}
+
+void testBranchEqualOrUnorderedFloatImms(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
+    Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
+
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        root->appendNew<Value>(
+            proc, EqualOrUnordered, Origin(),
+            argumentA,
+            argumentB),
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc) == expected);
+}
+
+void testBranchEqualOrUnorderedFloatWithUselessDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    BasicBlock* thenCase = proc.addBlock();
+    BasicBlock* elseCase = proc.addBlock();
+
+    Value* argument1 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2 = root->appendNew<MemoryValue>(proc, Load, Float, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* argument1AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument1);
+    Value* argument2AsDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argument2);
+
+    root->appendNew<ControlValue>(
+        proc, Branch, Origin(),
+        root->appendNew<Value>(
+            proc, EqualOrUnordered, Origin(),
+            argument1AsDouble,
+            argument2AsDouble),
+        FrequentedBlock(thenCase), FrequentedBlock(elseCase));
+
+    thenCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        thenCase->appendNew<Const32Value>(proc, Origin(), 42));
+
+    elseCase->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        elseCase->appendNew<Const32Value>(proc, Origin(), -13));
+
+    int64_t expected = (std::isunordered(a, b) || a == b) ? 42 : -13;
+    CHECK(compileAndRun<int64_t>(proc, &a, &b) == expected);
+}
+
 void testBranchFold(int value)
 {
     Procedure proc;
@@ -9122,6 +9406,17 @@
     RUN(testBranchEqualEqual());
     RUN(testBranchEqualCommute());
     RUN(testBranchEqualEqual1());
+    RUN_BINARY(testBranchEqualOrUnorderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBranchEqualOrUnorderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBranchEqualOrUnorderedDoubleArgImm, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBranchEqualOrUnorderedFloatArgImm, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBranchEqualOrUnorderedDoubleImms, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBranchEqualOrUnorderedFloatImms, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBranchEqualOrUnorderedFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBranchNotEqualAndOrderedArgs, floatingPointOperands<float>(), floatingPointOperands<float>());
     RUN(testBranchFold(42));
     RUN(testBranchFold(0));
     RUN(testDiamondFold(42));

Modified: trunk/Source/_javascript_Core/ftl/FTLB3Output.h (194313 => 194314)


--- trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-12-19 16:52:11 UTC (rev 194314)
@@ -336,7 +336,11 @@
     LValue doubleLessThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right); }
     LValue doubleGreaterThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right); }
     LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right); }
-    LValue doubleNotEqual(LValue left, LValue right) { CRASH(); }
+    LValue doubleNotEqualAndOrdered(LValue left, LValue right)
+    {
+        LValue equalOrUnordered = m_block->appendNew<B3::Value>(m_proc, B3::EqualOrUnordered, origin(), left, right);
+        return bitXor(equalOrUnordered, int32One);
+    }
     LValue doubleLessThanOrUnordered(LValue left, LValue right)
     {
         return m_block->appendNew<B3::Value>(

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (194313 => 194314)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-12-19 16:52:11 UTC (rev 194314)
@@ -7305,7 +7305,7 @@
         case Int32Use:
             return m_out.notZero32(lowInt32(edge));
         case DoubleRepUse:
-            return m_out.doubleNotEqual(lowDouble(edge), m_out.doubleZero);
+            return m_out.doubleNotEqualAndOrdered(lowDouble(edge), m_out.doubleZero);
         case ObjectOrOtherUse:
             return m_out.bitNot(
                 equalNullOrUndefined(
@@ -7399,9 +7399,7 @@
                 unsure(doubleCase), unsure(notDoubleCase));
             
             m_out.appendTo(doubleCase, notDoubleCase);
-            // Note that doubleNotEqual() really means not-equal-and-ordered. It will return false
-            // if value is NaN.
-            LValue doubleIsTruthy = m_out.doubleNotEqual(
+            LValue doubleIsTruthy = m_out.doubleNotEqualAndOrdered(
                 unboxDouble(value), m_out.constDouble(0));
             results.append(m_out.anchor(doubleIsTruthy));
             m_out.jump(continuation);

Modified: trunk/Source/_javascript_Core/ftl/FTLOutput.h (194313 => 194314)


--- trunk/Source/_javascript_Core/ftl/FTLOutput.h	2015-12-19 13:26:38 UTC (rev 194313)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.h	2015-12-19 16:52:11 UTC (rev 194314)
@@ -376,7 +376,7 @@
     LValue doubleLessThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOLE, left, right); }
     LValue doubleGreaterThan(LValue left, LValue right) { return fcmp(LLVMRealOGT, left, right); }
     LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOGE, left, right); }
-    LValue doubleNotEqual(LValue left, LValue right) { return fcmp(LLVMRealONE, left, right); }
+    LValue doubleNotEqualAndOrdered(LValue left, LValue right) { return fcmp(LLVMRealONE, left, right); }
     LValue doubleLessThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULT, left, right); }
     LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULE, left, right); }
     LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUGT, left, right); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to