tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

testJitFoldsTo.cpp (7054B)


      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(testJitFoldsTo_DivReciprocal) {
     20  MinimalFunc func;
     21  MBasicBlock* block = func.createEntryBlock();
     22 
     23  // return p / 4.0
     24  MParameter* p = func.createParameter();
     25  block->add(p);
     26  MConstant* c = MConstant::NewDouble(func.alloc, 4.0);
     27  block->add(c);
     28  MDiv* div = MDiv::New(func.alloc, p, c, MIRType::Double);
     29  block->add(div);
     30  if (!div->typePolicy()->adjustInputs(func.alloc, div)) {
     31    return false;
     32  }
     33  MDefinition* left = div->getOperand(0);
     34  MReturn* ret = MReturn::New(func.alloc, div);
     35  block->end(ret);
     36 
     37  if (!func.runGVN()) {
     38    return false;
     39  }
     40 
     41  // Test that the div got folded to p * 0.25.
     42  MDefinition* op = ret->getOperand(0);
     43  CHECK(op->isMul());
     44  CHECK(op->getOperand(0) == left);
     45  CHECK(op->getOperand(1)->isConstant());
     46  CHECK(op->getOperand(1)->toConstant()->numberToDouble() == 0.25);
     47  return true;
     48 }
     49 END_TEST(testJitFoldsTo_DivReciprocal)
     50 
     51 BEGIN_TEST(testJitFoldsTo_NoDivReciprocal) {
     52  MinimalFunc func;
     53  MBasicBlock* block = func.createEntryBlock();
     54 
     55  // return p / 5.0
     56  MParameter* p = func.createParameter();
     57  block->add(p);
     58  MConstant* c = MConstant::NewDouble(func.alloc, 5.0);
     59  block->add(c);
     60  MDiv* div = MDiv::New(func.alloc, p, c, MIRType::Double);
     61  block->add(div);
     62  if (!div->typePolicy()->adjustInputs(func.alloc, div)) {
     63    return false;
     64  }
     65  MDefinition* left = div->getOperand(0);
     66  MDefinition* right = div->getOperand(1);
     67  MReturn* ret = MReturn::New(func.alloc, div);
     68  block->end(ret);
     69 
     70  if (!func.runGVN()) {
     71    return false;
     72  }
     73 
     74  // Test that the div didn't get folded.
     75  MDefinition* op = ret->getOperand(0);
     76  CHECK(op->isDiv());
     77  CHECK(op->getOperand(0) == left);
     78  CHECK(op->getOperand(1) == right);
     79  return true;
     80 }
     81 END_TEST(testJitFoldsTo_NoDivReciprocal)
     82 
     83 BEGIN_TEST(testJitNotNot) {
     84  MinimalFunc func;
     85  MBasicBlock* block = func.createEntryBlock();
     86 
     87  // return Not(Not(p))
     88  MParameter* p = func.createParameter();
     89  block->add(p);
     90  MNot* not0 = MNot::New(func.alloc, p);
     91  block->add(not0);
     92  MNot* not1 = MNot::New(func.alloc, not0);
     93  block->add(not1);
     94  MReturn* ret = MReturn::New(func.alloc, not1);
     95  block->end(ret);
     96 
     97  if (!func.runGVN()) {
     98    return false;
     99  }
    100 
    101  // Test that the nots did not get folded.
    102  MDefinition* op = ret->getOperand(0);
    103  CHECK(op->isNot());
    104  CHECK(op->getOperand(0)->isNot());
    105  CHECK(op->getOperand(0)->getOperand(0) == p);
    106  return true;
    107 }
    108 END_TEST(testJitNotNot)
    109 
    110 BEGIN_TEST(testJitNotNotNot) {
    111  MinimalFunc func;
    112  MBasicBlock* block = func.createEntryBlock();
    113 
    114  // return Not(Not(Not(p)))
    115  MParameter* p = func.createParameter();
    116  block->add(p);
    117  MNot* not0 = MNot::New(func.alloc, p);
    118  block->add(not0);
    119  MNot* not1 = MNot::New(func.alloc, not0);
    120  block->add(not1);
    121  MNot* not2 = MNot::New(func.alloc, not1);
    122  block->add(not2);
    123  MReturn* ret = MReturn::New(func.alloc, not2);
    124  block->end(ret);
    125 
    126  if (!func.runGVN()) {
    127    return false;
    128  }
    129 
    130  // Test that the nots got folded.
    131  MDefinition* op = ret->getOperand(0);
    132  CHECK(op->isNot());
    133  CHECK(op->getOperand(0) == p);
    134  return true;
    135 }
    136 END_TEST(testJitNotNotNot)
    137 
    138 BEGIN_TEST(testJitNotTest) {
    139  MinimalFunc func;
    140  MBasicBlock* block = func.createEntryBlock();
    141  MBasicBlock* then = func.createBlock(block);
    142  MBasicBlock* else_ = func.createBlock(block);
    143  MBasicBlock* exit = func.createBlock(block);
    144 
    145  // MTest(Not(p))
    146  MParameter* p = func.createParameter();
    147  block->add(p);
    148  MNot* not0 = MNot::New(func.alloc, p);
    149  block->add(not0);
    150  MTest* test = MTest::New(func.alloc, not0, then, else_);
    151  block->end(test);
    152 
    153  then->end(MGoto::New(func.alloc, exit));
    154 
    155  else_->end(MGoto::New(func.alloc, exit));
    156 
    157  MReturn* ret = MReturn::New(func.alloc, p);
    158  exit->end(ret);
    159 
    160  MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
    161 
    162  if (!func.runGVN()) {
    163    return false;
    164  }
    165 
    166  // Test that the not got folded.
    167  test = block->lastIns()->toTest();
    168  CHECK(test->getOperand(0) == p);
    169  CHECK(test->getSuccessor(0) == else_);
    170  CHECK(test->getSuccessor(1) == then);
    171  return true;
    172 }
    173 END_TEST(testJitNotTest)
    174 
    175 BEGIN_TEST(testJitNotNotTest) {
    176  MinimalFunc func;
    177  MBasicBlock* block = func.createEntryBlock();
    178  MBasicBlock* then = func.createBlock(block);
    179  MBasicBlock* else_ = func.createBlock(block);
    180  MBasicBlock* exit = func.createBlock(block);
    181 
    182  // MTest(Not(Not(p)))
    183  MParameter* p = func.createParameter();
    184  block->add(p);
    185  MNot* not0 = MNot::New(func.alloc, p);
    186  block->add(not0);
    187  MNot* not1 = MNot::New(func.alloc, not0);
    188  block->add(not1);
    189  MTest* test = MTest::New(func.alloc, not1, then, else_);
    190  block->end(test);
    191 
    192  then->end(MGoto::New(func.alloc, exit));
    193 
    194  else_->end(MGoto::New(func.alloc, exit));
    195 
    196  MReturn* ret = MReturn::New(func.alloc, p);
    197  exit->end(ret);
    198 
    199  MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
    200 
    201  if (!func.runGVN()) {
    202    return false;
    203  }
    204 
    205  // Test that the nots got folded.
    206  test = block->lastIns()->toTest();
    207  CHECK(test->getOperand(0) == p);
    208  CHECK(test->getSuccessor(0) == then);
    209  CHECK(test->getSuccessor(1) == else_);
    210  return true;
    211 }
    212 END_TEST(testJitNotNotTest)
    213 
    214 BEGIN_TEST(testJitFoldsTo_UnsignedDiv) {
    215  MinimalFunc func;
    216  MBasicBlock* block = func.createEntryBlock();
    217 
    218  // return 1.0 / 0xffffffff
    219  MConstant* c0 = MConstant::NewInt32(func.alloc, 1);
    220  block->add(c0);
    221  MConstant* c1 = MConstant::NewInt32(func.alloc, 0xffffffff);
    222  block->add(c1);
    223  MDiv* div = MDiv::New(func.alloc, c0, c1, MIRType::Int32, /*unsignd=*/true);
    224  block->add(div);
    225  MReturn* ret = MReturn::New(func.alloc, div);
    226  block->end(ret);
    227 
    228  if (!func.runGVN()) {
    229    return false;
    230  }
    231 
    232  // Test that the div got folded to 0.
    233  MConstant* op = ret->getOperand(0)->toConstant();
    234  CHECK(mozilla::NumbersAreIdentical(op->numberToDouble(), 0.0));
    235  return true;
    236 }
    237 END_TEST(testJitFoldsTo_UnsignedDiv)
    238 
    239 BEGIN_TEST(testJitFoldsTo_UnsignedMod) {
    240  MinimalFunc func;
    241  MBasicBlock* block = func.createEntryBlock();
    242 
    243  // return 1.0 % 0xffffffff
    244  MConstant* c0 = MConstant::NewInt32(func.alloc, 1);
    245  block->add(c0);
    246  MConstant* c1 = MConstant::NewInt32(func.alloc, 0xffffffff);
    247  block->add(c1);
    248  MMod* mod = MMod::New(func.alloc, c0, c1, MIRType::Int32, /*unsignd=*/true);
    249  block->add(mod);
    250  MReturn* ret = MReturn::New(func.alloc, mod);
    251  block->end(ret);
    252 
    253  if (!func.runGVN()) {
    254    return false;
    255  }
    256 
    257  // Test that the mod got folded to 1.
    258  MConstant* op = ret->getOperand(0)->toConstant();
    259  CHECK(mozilla::NumbersAreIdentical(op->numberToDouble(), 1.0));
    260  return true;
    261 }
    262 END_TEST(testJitFoldsTo_UnsignedMod)