diff options
Diffstat (limited to 'js/src/jsapi-tests/testJitFoldsTo.cpp')
-rw-r--r-- | js/src/jsapi-tests/testJitFoldsTo.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/js/src/jsapi-tests/testJitFoldsTo.cpp b/js/src/jsapi-tests/testJitFoldsTo.cpp new file mode 100644 index 0000000000..9537e1dcf7 --- /dev/null +++ b/js/src/jsapi-tests/testJitFoldsTo.cpp @@ -0,0 +1,262 @@ +/* -*- 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(testJitFoldsTo_DivReciprocal) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + + // return p / 4.0 + MParameter* p = func.createParameter(); + block->add(p); + MConstant* c = MConstant::New(func.alloc, DoubleValue(4.0)); + block->add(c); + MDiv* div = MDiv::New(func.alloc, p, c, MIRType::Double); + block->add(div); + if (!div->typePolicy()->adjustInputs(func.alloc, div)) { + return false; + } + MDefinition* left = div->getOperand(0); + MReturn* ret = MReturn::New(func.alloc, div); + block->end(ret); + + if (!func.runGVN()) { + return false; + } + + // Test that the div got folded to p * 0.25. + MDefinition* op = ret->getOperand(0); + CHECK(op->isMul()); + CHECK(op->getOperand(0) == left); + CHECK(op->getOperand(1)->isConstant()); + CHECK(op->getOperand(1)->toConstant()->numberToDouble() == 0.25); + return true; +} +END_TEST(testJitFoldsTo_DivReciprocal) + +BEGIN_TEST(testJitFoldsTo_NoDivReciprocal) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + + // return p / 5.0 + MParameter* p = func.createParameter(); + block->add(p); + MConstant* c = MConstant::New(func.alloc, DoubleValue(5.0)); + block->add(c); + MDiv* div = MDiv::New(func.alloc, p, c, MIRType::Double); + block->add(div); + if (!div->typePolicy()->adjustInputs(func.alloc, div)) { + return false; + } + MDefinition* left = div->getOperand(0); + MDefinition* right = div->getOperand(1); + MReturn* ret = MReturn::New(func.alloc, div); + block->end(ret); + + if (!func.runGVN()) { + return false; + } + + // Test that the div didn't get folded. + MDefinition* op = ret->getOperand(0); + CHECK(op->isDiv()); + CHECK(op->getOperand(0) == left); + CHECK(op->getOperand(1) == right); + return true; +} +END_TEST(testJitFoldsTo_NoDivReciprocal) + +BEGIN_TEST(testJitNotNot) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + + // return Not(Not(p)) + MParameter* p = func.createParameter(); + block->add(p); + MNot* not0 = MNot::New(func.alloc, p); + block->add(not0); + MNot* not1 = MNot::New(func.alloc, not0); + block->add(not1); + MReturn* ret = MReturn::New(func.alloc, not1); + block->end(ret); + + if (!func.runGVN()) { + return false; + } + + // Test that the nots did not get folded. + MDefinition* op = ret->getOperand(0); + CHECK(op->isNot()); + CHECK(op->getOperand(0)->isNot()); + CHECK(op->getOperand(0)->getOperand(0) == p); + return true; +} +END_TEST(testJitNotNot) + +BEGIN_TEST(testJitNotNotNot) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + + // return Not(Not(Not(p))) + MParameter* p = func.createParameter(); + block->add(p); + MNot* not0 = MNot::New(func.alloc, p); + block->add(not0); + MNot* not1 = MNot::New(func.alloc, not0); + block->add(not1); + MNot* not2 = MNot::New(func.alloc, not1); + block->add(not2); + MReturn* ret = MReturn::New(func.alloc, not2); + block->end(ret); + + if (!func.runGVN()) { + return false; + } + + // Test that the nots got folded. + MDefinition* op = ret->getOperand(0); + CHECK(op->isNot()); + CHECK(op->getOperand(0) == p); + return true; +} +END_TEST(testJitNotNotNot) + +BEGIN_TEST(testJitNotTest) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + MBasicBlock* then = func.createBlock(block); + MBasicBlock* else_ = func.createBlock(block); + MBasicBlock* exit = func.createBlock(block); + + // MTest(Not(p)) + MParameter* p = func.createParameter(); + block->add(p); + MNot* not0 = MNot::New(func.alloc, p); + block->add(not0); + MTest* test = MTest::New(func.alloc, not0, then, else_); + block->end(test); + + then->end(MGoto::New(func.alloc, exit)); + + else_->end(MGoto::New(func.alloc, exit)); + + MReturn* ret = MReturn::New(func.alloc, p); + exit->end(ret); + + MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then)); + + if (!func.runGVN()) { + return false; + } + + // Test that the not got folded. + test = block->lastIns()->toTest(); + CHECK(test->getOperand(0) == p); + CHECK(test->getSuccessor(0) == else_); + CHECK(test->getSuccessor(1) == then); + return true; +} +END_TEST(testJitNotTest) + +BEGIN_TEST(testJitNotNotTest) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + MBasicBlock* then = func.createBlock(block); + MBasicBlock* else_ = func.createBlock(block); + MBasicBlock* exit = func.createBlock(block); + + // MTest(Not(Not(p))) + MParameter* p = func.createParameter(); + block->add(p); + MNot* not0 = MNot::New(func.alloc, p); + block->add(not0); + MNot* not1 = MNot::New(func.alloc, not0); + block->add(not1); + MTest* test = MTest::New(func.alloc, not1, then, else_); + block->end(test); + + then->end(MGoto::New(func.alloc, exit)); + + else_->end(MGoto::New(func.alloc, exit)); + + MReturn* ret = MReturn::New(func.alloc, p); + exit->end(ret); + + MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then)); + + if (!func.runGVN()) { + return false; + } + + // Test that the nots got folded. + test = block->lastIns()->toTest(); + CHECK(test->getOperand(0) == p); + CHECK(test->getSuccessor(0) == then); + CHECK(test->getSuccessor(1) == else_); + return true; +} +END_TEST(testJitNotNotTest) + +BEGIN_TEST(testJitFoldsTo_UnsignedDiv) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + + // return 1.0 / 0xffffffff + MConstant* c0 = MConstant::New(func.alloc, Int32Value(1)); + block->add(c0); + MConstant* c1 = MConstant::New(func.alloc, Int32Value(0xffffffff)); + block->add(c1); + MDiv* div = MDiv::New(func.alloc, c0, c1, MIRType::Int32, /*unsignd=*/true); + block->add(div); + MReturn* ret = MReturn::New(func.alloc, div); + block->end(ret); + + if (!func.runGVN()) { + return false; + } + + // Test that the div got folded to 0. + MConstant* op = ret->getOperand(0)->toConstant(); + CHECK(mozilla::NumbersAreIdentical(op->numberToDouble(), 0.0)); + return true; +} +END_TEST(testJitFoldsTo_UnsignedDiv) + +BEGIN_TEST(testJitFoldsTo_UnsignedMod) { + MinimalFunc func; + MBasicBlock* block = func.createEntryBlock(); + + // return 1.0 % 0xffffffff + MConstant* c0 = MConstant::New(func.alloc, Int32Value(1)); + block->add(c0); + MConstant* c1 = MConstant::New(func.alloc, Int32Value(0xffffffff)); + block->add(c1); + MMod* mod = MMod::New(func.alloc, c0, c1, MIRType::Int32, /*unsignd=*/true); + block->add(mod); + MReturn* ret = MReturn::New(func.alloc, mod); + block->end(ret); + + if (!func.runGVN()) { + return false; + } + + // Test that the mod got folded to 1. + MConstant* op = ret->getOperand(0)->toConstant(); + CHECK(mozilla::NumbersAreIdentical(op->numberToDouble(), 1.0)); + return true; +} +END_TEST(testJitFoldsTo_UnsignedMod) |