testJitDCEinGVN.cpp (4264B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "jit/IonAnalysis.h" 9 #include "jit/MIRGenerator.h" 10 #include "jit/MIRGraph.h" 11 #include "jit/ValueNumbering.h" 12 13 #include "jsapi-tests/testJitMinimalFunc.h" 14 #include "jsapi-tests/tests.h" 15 16 using namespace js; 17 using namespace js::jit; 18 19 BEGIN_TEST(testJitDCEinGVN_ins) { 20 MinimalFunc func; 21 MBasicBlock* block = func.createEntryBlock(); 22 23 // mul0 = p * p 24 // mul1 = mul0 * mul0 25 // return p 26 MParameter* p = func.createParameter(); 27 block->add(p); 28 MMul* mul0 = MMul::New(func.alloc, p, p, MIRType::Double); 29 block->add(mul0); 30 if (!mul0->typePolicy()->adjustInputs(func.alloc, mul0)) { 31 return false; 32 } 33 MMul* mul1 = MMul::New(func.alloc, mul0, mul0, MIRType::Double); 34 block->add(mul1); 35 if (!mul1->typePolicy()->adjustInputs(func.alloc, mul1)) { 36 return false; 37 } 38 MReturn* ret = MReturn::New(func.alloc, p); 39 block->end(ret); 40 41 if (!func.runGVN()) { 42 return false; 43 } 44 45 // mul0 and mul1 should be deleted. 46 for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) { 47 CHECK(!ins->isMul() || 48 (ins->getOperand(0) != p && ins->getOperand(1) != p)); 49 CHECK(!ins->isMul() || 50 (ins->getOperand(0) != mul0 && ins->getOperand(1) != mul0)); 51 } 52 return true; 53 } 54 END_TEST(testJitDCEinGVN_ins) 55 56 BEGIN_TEST(testJitDCEinGVN_phi) { 57 MinimalFunc func; 58 MBasicBlock* block = func.createEntryBlock(); 59 MBasicBlock* thenBlock1 = func.createBlock(block); 60 MBasicBlock* thenBlock2 = func.createBlock(block); 61 MBasicBlock* elifBlock = func.createBlock(block); 62 MBasicBlock* elseBlock = func.createBlock(block); 63 MBasicBlock* joinBlock = func.createBlock(block); 64 65 // if (p) { 66 // x = 1.0; 67 // y = 3.0; 68 // } else if (q) { 69 // x = 2.0; 70 // y = 4.0; 71 // } else { 72 // x = 1.0; 73 // y = 5.0; 74 // } 75 // x = phi(1.0, 2.0, 1.0); 76 // y = phi(3.0, 4.0, 5.0); 77 // z = x * y; 78 // return y; 79 80 MConstant* c1 = MConstant::NewDouble(func.alloc, 1.0); 81 block->add(c1); 82 MPhi* x = MPhi::New(func.alloc); 83 MPhi* y = MPhi::New(func.alloc); 84 85 // if (p) { 86 MParameter* p = func.createParameter(); 87 block->add(p); 88 block->end(MTest::New(func.alloc, p, thenBlock1, elifBlock)); 89 90 // x = 1.0 91 // y = 3.0; 92 MOZ_RELEASE_ASSERT(x->addInputSlow(c1)); 93 MConstant* c3 = MConstant::NewDouble(func.alloc, 3.0); 94 thenBlock1->add(c3); 95 MOZ_RELEASE_ASSERT(y->addInputSlow(c3)); 96 thenBlock1->end(MGoto::New(func.alloc, joinBlock)); 97 MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock1)); 98 99 // } else if (q) { 100 MParameter* q = func.createParameter(); 101 elifBlock->add(q); 102 elifBlock->end(MTest::New(func.alloc, q, thenBlock2, elseBlock)); 103 104 // x = 2.0 105 // y = 4.0; 106 MConstant* c2 = MConstant::NewDouble(func.alloc, 2.0); 107 thenBlock2->add(c2); 108 MOZ_RELEASE_ASSERT(x->addInputSlow(c2)); 109 MConstant* c4 = MConstant::NewDouble(func.alloc, 4.0); 110 thenBlock2->add(c4); 111 MOZ_RELEASE_ASSERT(y->addInputSlow(c4)); 112 thenBlock2->end(MGoto::New(func.alloc, joinBlock)); 113 MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock2)); 114 115 // } else { 116 // x = 1.0 117 // y = 5.0; 118 // } 119 MOZ_RELEASE_ASSERT(x->addInputSlow(c1)); 120 MConstant* c5 = MConstant::NewDouble(func.alloc, 5.0); 121 elseBlock->add(c5); 122 MOZ_RELEASE_ASSERT(y->addInputSlow(c5)); 123 elseBlock->end(MGoto::New(func.alloc, joinBlock)); 124 MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, elseBlock)); 125 126 // x = phi(1.0, 2.0, 1.0) 127 // y = phi(3.0, 4.0, 5.0) 128 // z = x * y 129 // return y 130 joinBlock->addPhi(x); 131 joinBlock->addPhi(y); 132 MMul* z = MMul::New(func.alloc, x, y, MIRType::Double); 133 joinBlock->add(z); 134 MReturn* ret = MReturn::New(func.alloc, y); 135 joinBlock->end(ret); 136 137 if (!func.runGVN()) { 138 return false; 139 } 140 141 // c1 should be deleted. 142 for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) { 143 CHECK(!ins->isConstant() || (ins->toConstant()->numberToDouble() != 1.0)); 144 } 145 return true; 146 } 147 END_TEST(testJitDCEinGVN_phi)