[B3] Add more tests for Check and fix bugs this found
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Nov 2015 19:14:49 +0000 (19:14 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Nov 2015 19:14:49 +0000 (19:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=151073

Reviewed by Saam Barati.

Adds tests for compare/Check fusion. The "MegaCombo" test found a bug in our implementation
of forEachArg: Air::spillEverything() was expecting that the Arg& to point to the actual Arg
so that it can mutate it. But this wasn't the case in B3::CheckSpecial. This fixes that bug.

* b3/B3CheckSpecial.cpp:
(JSC::B3::Air::numB3Args):
(JSC::B3::CheckSpecial::hiddenBranch):
(JSC::B3::CheckSpecial::commitHiddenBranch):
(JSC::B3::CheckSpecial::forEachArg):
* b3/B3CheckSpecial.h:
* b3/testb3.cpp:
(JSC::B3::testSimpleCheck):
(JSC::B3::testCheckLessThan):
(JSC::B3::testCheckMegaCombo):
(JSC::B3::genericTestCompare):
(JSC::B3::run):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@192257 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/b3/B3CheckSpecial.cpp
Source/JavaScriptCore/b3/B3CheckSpecial.h
Source/JavaScriptCore/b3/testb3.cpp

index a5cc669..d4403a1 100644 (file)
@@ -1,5 +1,29 @@
 2015-11-09  Filip Pizlo  <fpizlo@apple.com>
 
+        [B3] Add more tests for Check and fix bugs this found
+        https://bugs.webkit.org/show_bug.cgi?id=151073
+
+        Reviewed by Saam Barati.
+
+        Adds tests for compare/Check fusion. The "MegaCombo" test found a bug in our implementation
+        of forEachArg: Air::spillEverything() was expecting that the Arg& to point to the actual Arg
+        so that it can mutate it. But this wasn't the case in B3::CheckSpecial. This fixes that bug.
+
+        * b3/B3CheckSpecial.cpp:
+        (JSC::B3::Air::numB3Args):
+        (JSC::B3::CheckSpecial::hiddenBranch):
+        (JSC::B3::CheckSpecial::commitHiddenBranch):
+        (JSC::B3::CheckSpecial::forEachArg):
+        * b3/B3CheckSpecial.h:
+        * b3/testb3.cpp:
+        (JSC::B3::testSimpleCheck):
+        (JSC::B3::testCheckLessThan):
+        (JSC::B3::testCheckMegaCombo):
+        (JSC::B3::genericTestCompare):
+        (JSC::B3::run):
+
+2015-11-09  Filip Pizlo  <fpizlo@apple.com>
+
         [B3] Add a test for CCall with double arguments and results
         https://bugs.webkit.org/show_bug.cgi?id=151064
 
index 99e7449..70ad874 100644 (file)
@@ -45,8 +45,7 @@ unsigned numB3Args(Inst& inst)
     case CheckAdd:
     case CheckSub:
     case CheckMul:
-        // ResCond, Tmp, Tmp
-        return 3;
+        return 2;
     case Check:
         return 1;
     default:
@@ -93,9 +92,19 @@ Inst CheckSpecial::hiddenBranch(const Inst& inst) const
     return hiddenBranch;
 }
 
+void CheckSpecial::commitHiddenBranch(Inst& original, Inst& hiddenBranch)
+{
+    ASSERT(hiddenBranch.args.size() == m_numCheckArgs);
+    ASSERT(hiddenBranch.opcode = m_checkOpcode);
+    for (unsigned i = 0; i < m_numCheckArgs; ++i)
+        original.args[i + 1] = hiddenBranch.args[i];
+}
+
 void CheckSpecial::forEachArg(Inst& inst, const ScopedLambda<Inst::EachArgCallback>& callback)
 {
-    hiddenBranch(inst).forEachArg(callback);
+    Inst hidden = hiddenBranch(inst);
+    hidden.forEachArg(callback);
+    commitHiddenBranch(inst, hidden);
     forEachArgImpl(numB3Args(inst), m_numCheckArgs + 1, inst, callback);
 }
 
index 31a6925..5f305fd 100644 (file)
@@ -116,6 +116,9 @@ protected:
     // Constructs and returns the Inst representing the branch that this will use.
     Air::Inst hiddenBranch(const Air::Inst&) const;
 
+    // If we edited the hidden branch, this installs the edits into the given inst.
+    void commitHiddenBranch(Air::Inst& original, Air::Inst& hiddenBranch);
+
     void forEachArg(Air::Inst&, const ScopedLambda<Air::Inst::EachArgCallback>&) override;
     bool isValid(Air::Inst&) override;
     bool admitsStack(Air::Inst&, unsigned argIndex) override;
index dc2c258..ffcd531 100644 (file)
@@ -2401,6 +2401,95 @@ void testSimpleCheck()
     CHECK(invoke<int>(*code, 1) == 42);
 }
 
+void testCheckLessThan()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* arg = root->appendNew<Value>(
+        proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    CheckValue* check = root->appendNew<CheckValue>(
+        proc, Check, Origin(),
+        root->appendNew<Value>(
+            proc, LessThan, Origin(), arg,
+            root->appendNew<Const32Value>(proc, Origin(), 42)));
+    check->setGenerator(
+        [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+            CHECK(params.reps.size() == 1);
+            CHECK(params.reps[0].isConstant());
+            CHECK(params.reps[0].value() == 1);
+
+            // This should always work because a function this simple should never have callee
+            // saves.
+            jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
+            jit.emitFunctionEpilogue();
+            jit.ret();
+        });
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
+
+    auto code = compile(proc);
+    
+    CHECK(invoke<int>(*code, 42) == 0);
+    CHECK(invoke<int>(*code, 1000) == 0);
+    CHECK(invoke<int>(*code, 41) == 42);
+    CHECK(invoke<int>(*code, 0) == 42);
+    CHECK(invoke<int>(*code, -1) == 42);
+}
+
+void testCheckMegaCombo()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* index = root->appendNew<Value>(
+        proc, ZExt32, Origin(),
+        root->appendNew<Value>(
+            proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
+
+    Value* ptr = root->appendNew<Value>(
+        proc, Add, Origin(), base,
+        root->appendNew<Value>(
+            proc, Shl, Origin(), index,
+            root->appendNew<Const32Value>(proc, Origin(), 1)));
+    
+    CheckValue* check = root->appendNew<CheckValue>(
+        proc, Check, Origin(),
+        root->appendNew<Value>(
+            proc, LessThan, Origin(),
+            root->appendNew<MemoryValue>(proc, Load8S, Origin(), ptr),
+            root->appendNew<Const32Value>(proc, Origin(), 42)));
+    check->setGenerator(
+        [&] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+            CHECK(params.reps.size() == 1);
+            CHECK(params.reps[0].isConstant());
+            CHECK(params.reps[0].value() == 1);
+
+            // This should always work because a function this simple should never have callee
+            // saves.
+            jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
+            jit.emitFunctionEpilogue();
+            jit.ret();
+        });
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
+
+    auto code = compile(proc);
+
+    int8_t value;
+    value = 42;
+    CHECK(invoke<int>(*code, &value - 2, 1) == 0);
+    value = 127;
+    CHECK(invoke<int>(*code, &value - 2, 1) == 0);
+    value = 41;
+    CHECK(invoke<int>(*code, &value - 2, 1) == 42);
+    value = 0;
+    CHECK(invoke<int>(*code, &value - 2, 1) == 42);
+    value = -1;
+    CHECK(invoke<int>(*code, &value - 2, 1) == 42);
+}
+
 template<typename LeftFunctor, typename RightFunctor>
 void genericTestCompare(
     B3::Opcode opcode, const LeftFunctor& leftFunctor, const RightFunctor& rightFunctor,
@@ -3151,6 +3240,8 @@ void run(const char* filter)
 
     RUN(testSimplePatchpoint());
     RUN(testSimpleCheck());
+    RUN(testCheckLessThan());
+    RUN(testCheckMegaCombo());
 
     RUN(testCompare(Equal, 42, 42));
     RUN(testCompare(NotEqual, 42, 42));