summaryrefslogtreecommitdiffstats
path: root/js/src/jsapi-tests/testJitDCEinGVN.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsapi-tests/testJitDCEinGVN.cpp')
-rw-r--r--js/src/jsapi-tests/testJitDCEinGVN.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/js/src/jsapi-tests/testJitDCEinGVN.cpp b/js/src/jsapi-tests/testJitDCEinGVN.cpp
new file mode 100644
index 0000000000..286d36aa14
--- /dev/null
+++ b/js/src/jsapi-tests/testJitDCEinGVN.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "jit/IonAnalysis.h"
+#include "jit/MIRGenerator.h"
+#include "jit/MIRGraph.h"
+#include "jit/ValueNumbering.h"
+
+#include "jsapi-tests/testJitMinimalFunc.h"
+#include "jsapi-tests/tests.h"
+
+using namespace js;
+using namespace js::jit;
+
+BEGIN_TEST(testJitDCEinGVN_ins) {
+ MinimalFunc func;
+ MBasicBlock* block = func.createEntryBlock();
+
+ // mul0 = p * p
+ // mul1 = mul0 * mul0
+ // return p
+ MParameter* p = func.createParameter();
+ block->add(p);
+ MMul* mul0 = MMul::New(func.alloc, p, p, MIRType::Double);
+ block->add(mul0);
+ if (!mul0->typePolicy()->adjustInputs(func.alloc, mul0)) {
+ return false;
+ }
+ MMul* mul1 = MMul::New(func.alloc, mul0, mul0, MIRType::Double);
+ block->add(mul1);
+ if (!mul1->typePolicy()->adjustInputs(func.alloc, mul1)) {
+ return false;
+ }
+ MReturn* ret = MReturn::New(func.alloc, p);
+ block->end(ret);
+
+ if (!func.runGVN()) {
+ return false;
+ }
+
+ // mul0 and mul1 should be deleted.
+ for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
+ CHECK(!ins->isMul() ||
+ (ins->getOperand(0) != p && ins->getOperand(1) != p));
+ CHECK(!ins->isMul() ||
+ (ins->getOperand(0) != mul0 && ins->getOperand(1) != mul0));
+ }
+ return true;
+}
+END_TEST(testJitDCEinGVN_ins)
+
+BEGIN_TEST(testJitDCEinGVN_phi) {
+ MinimalFunc func;
+ MBasicBlock* block = func.createEntryBlock();
+ MBasicBlock* thenBlock1 = func.createBlock(block);
+ MBasicBlock* thenBlock2 = func.createBlock(block);
+ MBasicBlock* elifBlock = func.createBlock(block);
+ MBasicBlock* elseBlock = func.createBlock(block);
+ MBasicBlock* joinBlock = func.createBlock(block);
+
+ // if (p) {
+ // x = 1.0;
+ // y = 3.0;
+ // } else if (q) {
+ // x = 2.0;
+ // y = 4.0;
+ // } else {
+ // x = 1.0;
+ // y = 5.0;
+ // }
+ // x = phi(1.0, 2.0, 1.0);
+ // y = phi(3.0, 4.0, 5.0);
+ // z = x * y;
+ // return y;
+
+ MConstant* c1 = MConstant::New(func.alloc, DoubleValue(1.0));
+ block->add(c1);
+ MPhi* x = MPhi::New(func.alloc);
+ MPhi* y = MPhi::New(func.alloc);
+
+ // if (p) {
+ MParameter* p = func.createParameter();
+ block->add(p);
+ block->end(MTest::New(func.alloc, p, thenBlock1, elifBlock));
+
+ // x = 1.0
+ // y = 3.0;
+ MOZ_RELEASE_ASSERT(x->addInputSlow(c1));
+ MConstant* c3 = MConstant::New(func.alloc, DoubleValue(3.0));
+ thenBlock1->add(c3);
+ MOZ_RELEASE_ASSERT(y->addInputSlow(c3));
+ thenBlock1->end(MGoto::New(func.alloc, joinBlock));
+ MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock1));
+
+ // } else if (q) {
+ MParameter* q = func.createParameter();
+ elifBlock->add(q);
+ elifBlock->end(MTest::New(func.alloc, q, thenBlock2, elseBlock));
+
+ // x = 2.0
+ // y = 4.0;
+ MConstant* c2 = MConstant::New(func.alloc, DoubleValue(2.0));
+ thenBlock2->add(c2);
+ MOZ_RELEASE_ASSERT(x->addInputSlow(c2));
+ MConstant* c4 = MConstant::New(func.alloc, DoubleValue(4.0));
+ thenBlock2->add(c4);
+ MOZ_RELEASE_ASSERT(y->addInputSlow(c4));
+ thenBlock2->end(MGoto::New(func.alloc, joinBlock));
+ MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock2));
+
+ // } else {
+ // x = 1.0
+ // y = 5.0;
+ // }
+ MOZ_RELEASE_ASSERT(x->addInputSlow(c1));
+ MConstant* c5 = MConstant::New(func.alloc, DoubleValue(5.0));
+ elseBlock->add(c5);
+ MOZ_RELEASE_ASSERT(y->addInputSlow(c5));
+ elseBlock->end(MGoto::New(func.alloc, joinBlock));
+ MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, elseBlock));
+
+ // x = phi(1.0, 2.0, 1.0)
+ // y = phi(3.0, 4.0, 5.0)
+ // z = x * y
+ // return y
+ joinBlock->addPhi(x);
+ joinBlock->addPhi(y);
+ MMul* z = MMul::New(func.alloc, x, y, MIRType::Double);
+ joinBlock->add(z);
+ MReturn* ret = MReturn::New(func.alloc, y);
+ joinBlock->end(ret);
+
+ if (!func.runGVN()) {
+ return false;
+ }
+
+ // c1 should be deleted.
+ for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
+ CHECK(!ins->isConstant() || (ins->toConstant()->numberToDouble() != 1.0));
+ }
+ return true;
+}
+END_TEST(testJitDCEinGVN_phi)