Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / js / src / jsapi-tests / testJitFoldsTo.cpp
blob9537e1dcf754e82093cd379654b0c8af19d36bd1
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/. */
8 #include "jit/IonAnalysis.h"
9 #include "jit/MIRGenerator.h"
10 #include "jit/MIRGraph.h"
11 #include "jit/ValueNumbering.h"
13 #include "jsapi-tests/testJitMinimalFunc.h"
14 #include "jsapi-tests/tests.h"
16 using namespace js;
17 using namespace js::jit;
19 BEGIN_TEST(testJitFoldsTo_DivReciprocal) {
20 MinimalFunc func;
21 MBasicBlock* block = func.createEntryBlock();
23 // return p / 4.0
24 MParameter* p = func.createParameter();
25 block->add(p);
26 MConstant* c = MConstant::New(func.alloc, DoubleValue(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;
33 MDefinition* left = div->getOperand(0);
34 MReturn* ret = MReturn::New(func.alloc, div);
35 block->end(ret);
37 if (!func.runGVN()) {
38 return false;
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;
49 END_TEST(testJitFoldsTo_DivReciprocal)
51 BEGIN_TEST(testJitFoldsTo_NoDivReciprocal) {
52 MinimalFunc func;
53 MBasicBlock* block = func.createEntryBlock();
55 // return p / 5.0
56 MParameter* p = func.createParameter();
57 block->add(p);
58 MConstant* c = MConstant::New(func.alloc, DoubleValue(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;
65 MDefinition* left = div->getOperand(0);
66 MDefinition* right = div->getOperand(1);
67 MReturn* ret = MReturn::New(func.alloc, div);
68 block->end(ret);
70 if (!func.runGVN()) {
71 return false;
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;
81 END_TEST(testJitFoldsTo_NoDivReciprocal)
83 BEGIN_TEST(testJitNotNot) {
84 MinimalFunc func;
85 MBasicBlock* block = func.createEntryBlock();
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);
97 if (!func.runGVN()) {
98 return false;
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;
108 END_TEST(testJitNotNot)
110 BEGIN_TEST(testJitNotNotNot) {
111 MinimalFunc func;
112 MBasicBlock* block = func.createEntryBlock();
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);
126 if (!func.runGVN()) {
127 return false;
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;
136 END_TEST(testJitNotNotNot)
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);
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);
153 then->end(MGoto::New(func.alloc, exit));
155 else_->end(MGoto::New(func.alloc, exit));
157 MReturn* ret = MReturn::New(func.alloc, p);
158 exit->end(ret);
160 MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
162 if (!func.runGVN()) {
163 return false;
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;
173 END_TEST(testJitNotTest)
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);
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);
192 then->end(MGoto::New(func.alloc, exit));
194 else_->end(MGoto::New(func.alloc, exit));
196 MReturn* ret = MReturn::New(func.alloc, p);
197 exit->end(ret);
199 MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
201 if (!func.runGVN()) {
202 return false;
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;
212 END_TEST(testJitNotNotTest)
214 BEGIN_TEST(testJitFoldsTo_UnsignedDiv) {
215 MinimalFunc func;
216 MBasicBlock* block = func.createEntryBlock();
218 // return 1.0 / 0xffffffff
219 MConstant* c0 = MConstant::New(func.alloc, Int32Value(1));
220 block->add(c0);
221 MConstant* c1 = MConstant::New(func.alloc, Int32Value(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);
228 if (!func.runGVN()) {
229 return false;
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;
237 END_TEST(testJitFoldsTo_UnsignedDiv)
239 BEGIN_TEST(testJitFoldsTo_UnsignedMod) {
240 MinimalFunc func;
241 MBasicBlock* block = func.createEntryBlock();
243 // return 1.0 % 0xffffffff
244 MConstant* c0 = MConstant::New(func.alloc, Int32Value(1));
245 block->add(c0);
246 MConstant* c1 = MConstant::New(func.alloc, Int32Value(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);
253 if (!func.runGVN()) {
254 return false;
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;
262 END_TEST(testJitFoldsTo_UnsignedMod)