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
- trunk/Source/_javascript_Core/ChangeLog
- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp
- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h
- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp
- trunk/Source/_javascript_Core/b3/B3Opcode.cpp
- trunk/Source/_javascript_Core/b3/B3Opcode.h
- trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp
- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp
- trunk/Source/_javascript_Core/b3/B3Validate.cpp
- trunk/Source/_javascript_Core/b3/B3Value.cpp
- trunk/Source/_javascript_Core/b3/B3Value.h
- trunk/Source/_javascript_Core/b3/testb3.cpp
- trunk/Source/_javascript_Core/ftl/FTLB3Output.h
- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp
- trunk/Source/_javascript_Core/ftl/FTLOutput.h
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
