Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/base/overflowing-math.h"
6 : #include "src/objects-inl.h"
7 : #include "test/cctest/cctest.h"
8 : #include "test/cctest/compiler/codegen-tester.h"
9 : #include "test/cctest/compiler/value-helper.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 : namespace compiler {
14 :
15 : static IrOpcode::Value int32cmp_opcodes[] = {
16 : IrOpcode::kWord32Equal, IrOpcode::kInt32LessThan,
17 : IrOpcode::kInt32LessThanOrEqual, IrOpcode::kUint32LessThan,
18 : IrOpcode::kUint32LessThanOrEqual};
19 :
20 :
21 26660 : TEST(BranchCombineWord32EqualZero_1) {
22 : // Test combining a branch with x == 0
23 4 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
24 : int32_t eq_constant = -1033;
25 : int32_t ne_constant = 825118;
26 4 : Node* p0 = m.Parameter(0);
27 :
28 4 : RawMachineLabel blocka, blockb;
29 4 : m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &blocka, &blockb);
30 4 : m.Bind(&blocka);
31 4 : m.Return(m.Int32Constant(eq_constant));
32 4 : m.Bind(&blockb);
33 4 : m.Return(m.Int32Constant(ne_constant));
34 :
35 468 : FOR_INT32_INPUTS(a) {
36 232 : int32_t expect = a == 0 ? eq_constant : ne_constant;
37 232 : CHECK_EQ(expect, m.Call(a));
38 : }
39 4 : }
40 :
41 :
42 26660 : TEST(BranchCombineWord32EqualZero_chain) {
43 : // Test combining a branch with a chain of x == 0 == 0 == 0 ...
44 : int32_t eq_constant = -1133;
45 : int32_t ne_constant = 815118;
46 :
47 52 : for (int k = 0; k < 6; k++) {
48 24 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
49 24 : Node* p0 = m.Parameter(0);
50 24 : RawMachineLabel blocka, blockb;
51 : Node* cond = p0;
52 144 : for (int j = 0; j < k; j++) {
53 60 : cond = m.Word32Equal(cond, m.Int32Constant(0));
54 : }
55 24 : m.Branch(cond, &blocka, &blockb);
56 24 : m.Bind(&blocka);
57 24 : m.Return(m.Int32Constant(eq_constant));
58 24 : m.Bind(&blockb);
59 24 : m.Return(m.Int32Constant(ne_constant));
60 :
61 2808 : FOR_INT32_INPUTS(a) {
62 1392 : int32_t expect = (k & 1) == 1 ? (a == 0 ? eq_constant : ne_constant)
63 1392 : : (a == 0 ? ne_constant : eq_constant);
64 1392 : CHECK_EQ(expect, m.Call(a));
65 : }
66 : }
67 4 : }
68 :
69 :
70 26660 : TEST(BranchCombineInt32LessThanZero_1) {
71 : // Test combining a branch with x < 0
72 4 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
73 : int32_t eq_constant = -1433;
74 : int32_t ne_constant = 845118;
75 4 : Node* p0 = m.Parameter(0);
76 :
77 4 : RawMachineLabel blocka, blockb;
78 4 : m.Branch(m.Int32LessThan(p0, m.Int32Constant(0)), &blocka, &blockb);
79 4 : m.Bind(&blocka);
80 4 : m.Return(m.Int32Constant(eq_constant));
81 4 : m.Bind(&blockb);
82 4 : m.Return(m.Int32Constant(ne_constant));
83 :
84 468 : FOR_INT32_INPUTS(a) {
85 232 : int32_t expect = a < 0 ? eq_constant : ne_constant;
86 232 : CHECK_EQ(expect, m.Call(a));
87 : }
88 4 : }
89 :
90 :
91 26660 : TEST(BranchCombineUint32LessThan100_1) {
92 : // Test combining a branch with x < 100
93 4 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
94 : int32_t eq_constant = 1471;
95 : int32_t ne_constant = 88845718;
96 4 : Node* p0 = m.Parameter(0);
97 :
98 4 : RawMachineLabel blocka, blockb;
99 4 : m.Branch(m.Uint32LessThan(p0, m.Int32Constant(100)), &blocka, &blockb);
100 4 : m.Bind(&blocka);
101 4 : m.Return(m.Int32Constant(eq_constant));
102 4 : m.Bind(&blockb);
103 4 : m.Return(m.Int32Constant(ne_constant));
104 :
105 468 : FOR_UINT32_INPUTS(a) {
106 232 : int32_t expect = a < 100 ? eq_constant : ne_constant;
107 232 : CHECK_EQ(expect, m.Call(a));
108 : }
109 4 : }
110 :
111 :
112 26660 : TEST(BranchCombineUint32LessThanOrEqual100_1) {
113 : // Test combining a branch with x <= 100
114 4 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
115 : int32_t eq_constant = 1479;
116 : int32_t ne_constant = 77845719;
117 4 : Node* p0 = m.Parameter(0);
118 :
119 4 : RawMachineLabel blocka, blockb;
120 4 : m.Branch(m.Uint32LessThanOrEqual(p0, m.Int32Constant(100)), &blocka, &blockb);
121 4 : m.Bind(&blocka);
122 4 : m.Return(m.Int32Constant(eq_constant));
123 4 : m.Bind(&blockb);
124 4 : m.Return(m.Int32Constant(ne_constant));
125 :
126 468 : FOR_UINT32_INPUTS(a) {
127 232 : int32_t expect = a <= 100 ? eq_constant : ne_constant;
128 232 : CHECK_EQ(expect, m.Call(a));
129 : }
130 4 : }
131 :
132 :
133 26660 : TEST(BranchCombineZeroLessThanInt32_1) {
134 : // Test combining a branch with 0 < x
135 4 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
136 : int32_t eq_constant = -2033;
137 : int32_t ne_constant = 225118;
138 4 : Node* p0 = m.Parameter(0);
139 :
140 4 : RawMachineLabel blocka, blockb;
141 4 : m.Branch(m.Int32LessThan(m.Int32Constant(0), p0), &blocka, &blockb);
142 4 : m.Bind(&blocka);
143 4 : m.Return(m.Int32Constant(eq_constant));
144 4 : m.Bind(&blockb);
145 4 : m.Return(m.Int32Constant(ne_constant));
146 :
147 468 : FOR_INT32_INPUTS(a) {
148 232 : int32_t expect = 0 < a ? eq_constant : ne_constant;
149 232 : CHECK_EQ(expect, m.Call(a));
150 : }
151 4 : }
152 :
153 :
154 26660 : TEST(BranchCombineInt32GreaterThanZero_1) {
155 : // Test combining a branch with x > 0
156 4 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
157 : int32_t eq_constant = -1073;
158 : int32_t ne_constant = 825178;
159 4 : Node* p0 = m.Parameter(0);
160 :
161 4 : RawMachineLabel blocka, blockb;
162 8 : m.Branch(m.Int32GreaterThan(p0, m.Int32Constant(0)), &blocka, &blockb);
163 4 : m.Bind(&blocka);
164 4 : m.Return(m.Int32Constant(eq_constant));
165 4 : m.Bind(&blockb);
166 4 : m.Return(m.Int32Constant(ne_constant));
167 :
168 468 : FOR_INT32_INPUTS(a) {
169 232 : int32_t expect = a > 0 ? eq_constant : ne_constant;
170 232 : CHECK_EQ(expect, m.Call(a));
171 : }
172 4 : }
173 :
174 :
175 26660 : TEST(BranchCombineWord32EqualP) {
176 : // Test combining a branch with an Word32Equal.
177 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
178 4 : MachineType::Int32());
179 : int32_t eq_constant = -1035;
180 : int32_t ne_constant = 825018;
181 4 : Node* p0 = m.Parameter(0);
182 4 : Node* p1 = m.Parameter(1);
183 :
184 4 : RawMachineLabel blocka, blockb;
185 4 : m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
186 4 : m.Bind(&blocka);
187 4 : m.Return(m.Int32Constant(eq_constant));
188 4 : m.Bind(&blockb);
189 4 : m.Return(m.Int32Constant(ne_constant));
190 :
191 468 : FOR_INT32_INPUTS(a) {
192 27144 : FOR_INT32_INPUTS(b) {
193 13456 : int32_t expect = a == b ? eq_constant : ne_constant;
194 13456 : CHECK_EQ(expect, m.Call(a, b));
195 : }
196 : }
197 4 : }
198 :
199 :
200 26660 : TEST(BranchCombineWord32EqualI) {
201 : int32_t eq_constant = -1135;
202 : int32_t ne_constant = 925718;
203 :
204 20 : for (int left = 0; left < 2; left++) {
205 936 : FOR_INT32_INPUTS(a) {
206 464 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
207 :
208 464 : Node* p0 = m.Int32Constant(a);
209 464 : Node* p1 = m.Parameter(0);
210 :
211 464 : RawMachineLabel blocka, blockb;
212 464 : if (left == 1) m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
213 464 : if (left == 0) m.Branch(m.Word32Equal(p1, p0), &blocka, &blockb);
214 464 : m.Bind(&blocka);
215 464 : m.Return(m.Int32Constant(eq_constant));
216 464 : m.Bind(&blockb);
217 464 : m.Return(m.Int32Constant(ne_constant));
218 :
219 54288 : FOR_INT32_INPUTS(b) {
220 26912 : int32_t expect = a == b ? eq_constant : ne_constant;
221 26912 : CHECK_EQ(expect, m.Call(b));
222 : }
223 : }
224 : }
225 4 : }
226 :
227 :
228 26660 : TEST(BranchCombineInt32CmpP) {
229 : int32_t eq_constant = -1235;
230 : int32_t ne_constant = 725018;
231 :
232 20 : for (int op = 0; op < 2; op++) {
233 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
234 8 : MachineType::Int32());
235 8 : Node* p0 = m.Parameter(0);
236 8 : Node* p1 = m.Parameter(1);
237 :
238 8 : RawMachineLabel blocka, blockb;
239 8 : if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
240 8 : if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
241 8 : m.Bind(&blocka);
242 8 : m.Return(m.Int32Constant(eq_constant));
243 8 : m.Bind(&blockb);
244 8 : m.Return(m.Int32Constant(ne_constant));
245 :
246 936 : FOR_INT32_INPUTS(a) {
247 54288 : FOR_INT32_INPUTS(b) {
248 : int32_t expect = 0;
249 26912 : if (op == 0) expect = a < b ? eq_constant : ne_constant;
250 26912 : if (op == 1) expect = a <= b ? eq_constant : ne_constant;
251 26912 : CHECK_EQ(expect, m.Call(a, b));
252 : }
253 : }
254 : }
255 4 : }
256 :
257 :
258 26660 : TEST(BranchCombineInt32CmpI) {
259 : int32_t eq_constant = -1175;
260 : int32_t ne_constant = 927711;
261 :
262 20 : for (int op = 0; op < 2; op++) {
263 936 : FOR_INT32_INPUTS(a) {
264 464 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
265 464 : Node* p0 = m.Int32Constant(a);
266 464 : Node* p1 = m.Parameter(0);
267 :
268 464 : RawMachineLabel blocka, blockb;
269 464 : if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
270 464 : if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
271 464 : m.Bind(&blocka);
272 464 : m.Return(m.Int32Constant(eq_constant));
273 464 : m.Bind(&blockb);
274 464 : m.Return(m.Int32Constant(ne_constant));
275 :
276 54288 : FOR_INT32_INPUTS(b) {
277 : int32_t expect = 0;
278 26912 : if (op == 0) expect = a < b ? eq_constant : ne_constant;
279 26912 : if (op == 1) expect = a <= b ? eq_constant : ne_constant;
280 26912 : CHECK_EQ(expect, m.Call(b));
281 : }
282 : }
283 : }
284 4 : }
285 :
286 :
287 : // Now come the sophisticated tests for many input shape combinations.
288 :
289 : // Materializes a boolean (1 or 0) from a comparison.
290 80 : class CmpMaterializeBoolGen : public BinopGen<int32_t> {
291 : public:
292 : CompareWrapper w;
293 : bool invert;
294 :
295 : CmpMaterializeBoolGen(IrOpcode::Value opcode, bool i)
296 80 : : w(opcode), invert(i) {}
297 :
298 2720 : void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) override {
299 2720 : Node* cond = w.MakeNode(m, a, b);
300 2720 : if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
301 2720 : m->Return(cond);
302 2720 : }
303 686720 : int32_t expected(int32_t a, int32_t b) override {
304 686720 : if (invert) return !w.Int32Compare(a, b) ? 1 : 0;
305 343360 : return w.Int32Compare(a, b) ? 1 : 0;
306 : }
307 : };
308 :
309 :
310 : // Generates a branch and return one of two values from a comparison.
311 160 : class CmpBranchGen : public BinopGen<int32_t> {
312 : public:
313 : CompareWrapper w;
314 : bool invert;
315 : bool true_first;
316 : int32_t eq_constant;
317 : int32_t ne_constant;
318 :
319 : CmpBranchGen(IrOpcode::Value opcode, bool i, bool t, int32_t eq, int32_t ne)
320 160 : : w(opcode), invert(i), true_first(t), eq_constant(eq), ne_constant(ne) {}
321 :
322 5440 : void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) override {
323 5440 : RawMachineLabel blocka, blockb;
324 5440 : Node* cond = w.MakeNode(m, a, b);
325 5440 : if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
326 5440 : m->Branch(cond, &blocka, &blockb);
327 5440 : if (true_first) {
328 2720 : m->Bind(&blocka);
329 2720 : m->Return(m->Int32Constant(eq_constant));
330 2720 : m->Bind(&blockb);
331 2720 : m->Return(m->Int32Constant(ne_constant));
332 : } else {
333 2720 : m->Bind(&blockb);
334 2720 : m->Return(m->Int32Constant(ne_constant));
335 2720 : m->Bind(&blocka);
336 2720 : m->Return(m->Int32Constant(eq_constant));
337 : }
338 5440 : }
339 1373440 : int32_t expected(int32_t a, int32_t b) override {
340 1373440 : if (invert) return !w.Int32Compare(a, b) ? eq_constant : ne_constant;
341 686720 : return w.Int32Compare(a, b) ? eq_constant : ne_constant;
342 : }
343 : };
344 :
345 :
346 26660 : TEST(BranchCombineInt32CmpAllInputShapes_materialized) {
347 44 : for (size_t i = 0; i < arraysize(int32cmp_opcodes); i++) {
348 20 : CmpMaterializeBoolGen gen(int32cmp_opcodes[i], false);
349 : Int32BinopInputShapeTester tester(&gen);
350 20 : tester.TestAllInputShapes();
351 : }
352 4 : }
353 :
354 :
355 26660 : TEST(BranchCombineInt32CmpAllInputShapes_inverted_materialized) {
356 44 : for (size_t i = 0; i < arraysize(int32cmp_opcodes); i++) {
357 20 : CmpMaterializeBoolGen gen(int32cmp_opcodes[i], true);
358 : Int32BinopInputShapeTester tester(&gen);
359 20 : tester.TestAllInputShapes();
360 : }
361 4 : }
362 :
363 :
364 26660 : TEST(BranchCombineInt32CmpAllInputShapes_branch_true) {
365 44 : for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
366 20 : CmpBranchGen gen(int32cmp_opcodes[i], false, false, 995 + i, -1011 - i);
367 : Int32BinopInputShapeTester tester(&gen);
368 20 : tester.TestAllInputShapes();
369 : }
370 4 : }
371 :
372 :
373 26660 : TEST(BranchCombineInt32CmpAllInputShapes_branch_false) {
374 44 : for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
375 20 : CmpBranchGen gen(int32cmp_opcodes[i], false, true, 795 + i, -2011 - i);
376 : Int32BinopInputShapeTester tester(&gen);
377 20 : tester.TestAllInputShapes();
378 : }
379 4 : }
380 :
381 :
382 26660 : TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_true) {
383 44 : for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
384 20 : CmpBranchGen gen(int32cmp_opcodes[i], true, false, 695 + i, -3011 - i);
385 : Int32BinopInputShapeTester tester(&gen);
386 20 : tester.TestAllInputShapes();
387 : }
388 4 : }
389 :
390 :
391 26660 : TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_false) {
392 44 : for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
393 20 : CmpBranchGen gen(int32cmp_opcodes[i], true, true, 595 + i, -4011 - i);
394 : Int32BinopInputShapeTester tester(&gen);
395 20 : tester.TestAllInputShapes();
396 : }
397 4 : }
398 :
399 :
400 26660 : TEST(BranchCombineFloat64Compares) {
401 : double inf = V8_INFINITY;
402 : double nan = std::numeric_limits<double>::quiet_NaN();
403 4 : double inputs[] = {0.0, 1.0, -1.0, -inf, inf, nan};
404 :
405 : int32_t eq_constant = -1733;
406 : int32_t ne_constant = 915118;
407 :
408 4 : double input_a = 0.0;
409 4 : double input_b = 0.0;
410 :
411 : CompareWrapper cmps[] = {CompareWrapper(IrOpcode::kFloat64Equal),
412 : CompareWrapper(IrOpcode::kFloat64LessThan),
413 : CompareWrapper(IrOpcode::kFloat64LessThanOrEqual)};
414 :
415 28 : for (size_t c = 0; c < arraysize(cmps); c++) {
416 12 : CompareWrapper cmp = cmps[c];
417 60 : for (int invert = 0; invert < 2; invert++) {
418 24 : RawMachineAssemblerTester<int32_t> m;
419 24 : Node* a = m.LoadFromPointer(&input_a, MachineType::Float64());
420 24 : Node* b = m.LoadFromPointer(&input_b, MachineType::Float64());
421 :
422 24 : RawMachineLabel blocka, blockb;
423 24 : Node* cond = cmp.MakeNode(&m, a, b);
424 24 : if (invert) cond = m.Word32Equal(cond, m.Int32Constant(0));
425 24 : m.Branch(cond, &blocka, &blockb);
426 24 : m.Bind(&blocka);
427 24 : m.Return(m.Int32Constant(eq_constant));
428 24 : m.Bind(&blockb);
429 24 : m.Return(m.Int32Constant(ne_constant));
430 :
431 312 : for (size_t i = 0; i < arraysize(inputs); ++i) {
432 1872 : for (size_t j = 0; j < arraysize(inputs); ++j) {
433 864 : input_a = inputs[i];
434 864 : input_b = inputs[j];
435 : int32_t expected =
436 432 : invert ? (cmp.Float64Compare(input_a, input_b) ? ne_constant
437 : : eq_constant)
438 432 : : (cmp.Float64Compare(input_a, input_b) ? eq_constant
439 1728 : : ne_constant);
440 864 : CHECK_EQ(expected, m.Call());
441 : }
442 : }
443 : }
444 : }
445 4 : }
446 :
447 26660 : TEST(BranchCombineEffectLevel) {
448 : // Test that the load doesn't get folded into the branch, as there's a store
449 : // between them. See http://crbug.com/611976.
450 4 : int32_t input = 0;
451 :
452 4 : RawMachineAssemblerTester<int32_t> m;
453 4 : Node* a = m.LoadFromPointer(&input, MachineType::Int32());
454 4 : Node* compare = m.Word32And(a, m.Int32Constant(1));
455 4 : Node* equal = m.Word32Equal(compare, m.Int32Constant(0));
456 4 : m.StoreToPointer(&input, MachineRepresentation::kWord32, m.Int32Constant(1));
457 :
458 4 : RawMachineLabel blocka, blockb;
459 4 : m.Branch(equal, &blocka, &blockb);
460 4 : m.Bind(&blocka);
461 4 : m.Return(m.Int32Constant(42));
462 4 : m.Bind(&blockb);
463 4 : m.Return(m.Int32Constant(0));
464 :
465 4 : CHECK_EQ(42, m.Call());
466 4 : }
467 :
468 26660 : TEST(BranchCombineInt32AddLessThanZero) {
469 : int32_t t_constant = -1033;
470 : int32_t f_constant = 825118;
471 :
472 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
473 4 : MachineType::Int32());
474 4 : Node* a = m.Parameter(0);
475 4 : Node* b = m.Parameter(1);
476 4 : Node* add = m.Int32Add(a, b);
477 4 : Node* compare = m.Int32LessThan(add, m.Int32Constant(0));
478 :
479 4 : RawMachineLabel blocka, blockb;
480 4 : m.Branch(compare, &blocka, &blockb);
481 4 : m.Bind(&blocka);
482 4 : m.Return(m.Int32Constant(t_constant));
483 4 : m.Bind(&blockb);
484 4 : m.Return(m.Int32Constant(f_constant));
485 :
486 468 : FOR_INT32_INPUTS(a) {
487 27144 : FOR_INT32_INPUTS(b) {
488 : int32_t expect =
489 13456 : (base::AddWithWraparound(a, b) < 0) ? t_constant : f_constant;
490 13456 : CHECK_EQ(expect, m.Call(a, b));
491 : }
492 : }
493 4 : }
494 :
495 26660 : TEST(BranchCombineInt32AddGreaterThanOrEqualZero) {
496 : int32_t t_constant = -1033;
497 : int32_t f_constant = 825118;
498 :
499 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
500 4 : MachineType::Int32());
501 4 : Node* a = m.Parameter(0);
502 4 : Node* b = m.Parameter(1);
503 4 : Node* add = m.Int32Add(a, b);
504 4 : Node* compare = m.Int32GreaterThanOrEqual(add, m.Int32Constant(0));
505 :
506 4 : RawMachineLabel blocka, blockb;
507 4 : m.Branch(compare, &blocka, &blockb);
508 4 : m.Bind(&blocka);
509 4 : m.Return(m.Int32Constant(t_constant));
510 4 : m.Bind(&blockb);
511 4 : m.Return(m.Int32Constant(f_constant));
512 :
513 468 : FOR_INT32_INPUTS(a) {
514 27144 : FOR_INT32_INPUTS(b) {
515 : int32_t expect =
516 13456 : (base::AddWithWraparound(a, b) >= 0) ? t_constant : f_constant;
517 13456 : CHECK_EQ(expect, m.Call(a, b));
518 : }
519 : }
520 4 : }
521 :
522 26660 : TEST(BranchCombineInt32ZeroGreaterThanAdd) {
523 : int32_t t_constant = -1033;
524 : int32_t f_constant = 825118;
525 :
526 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
527 4 : MachineType::Int32());
528 4 : Node* a = m.Parameter(0);
529 4 : Node* b = m.Parameter(1);
530 4 : Node* add = m.Int32Add(a, b);
531 4 : Node* compare = m.Int32GreaterThan(m.Int32Constant(0), add);
532 :
533 4 : RawMachineLabel blocka, blockb;
534 4 : m.Branch(compare, &blocka, &blockb);
535 4 : m.Bind(&blocka);
536 4 : m.Return(m.Int32Constant(t_constant));
537 4 : m.Bind(&blockb);
538 4 : m.Return(m.Int32Constant(f_constant));
539 :
540 468 : FOR_INT32_INPUTS(a) {
541 27144 : FOR_INT32_INPUTS(b) {
542 : int32_t expect =
543 13456 : (0 > base::AddWithWraparound(a, b)) ? t_constant : f_constant;
544 13456 : CHECK_EQ(expect, m.Call(a, b));
545 : }
546 : }
547 4 : }
548 :
549 26660 : TEST(BranchCombineInt32ZeroLessThanOrEqualAdd) {
550 : int32_t t_constant = -1033;
551 : int32_t f_constant = 825118;
552 :
553 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
554 4 : MachineType::Int32());
555 4 : Node* a = m.Parameter(0);
556 4 : Node* b = m.Parameter(1);
557 4 : Node* add = m.Int32Add(a, b);
558 4 : Node* compare = m.Int32LessThanOrEqual(m.Int32Constant(0), add);
559 :
560 4 : RawMachineLabel blocka, blockb;
561 4 : m.Branch(compare, &blocka, &blockb);
562 4 : m.Bind(&blocka);
563 4 : m.Return(m.Int32Constant(t_constant));
564 4 : m.Bind(&blockb);
565 4 : m.Return(m.Int32Constant(f_constant));
566 :
567 468 : FOR_INT32_INPUTS(a) {
568 27144 : FOR_INT32_INPUTS(b) {
569 : int32_t expect =
570 13456 : (0 <= base::AddWithWraparound(a, b)) ? t_constant : f_constant;
571 13456 : CHECK_EQ(expect, m.Call(a, b));
572 : }
573 : }
574 4 : }
575 :
576 26660 : TEST(BranchCombineUint32AddLessThanOrEqualZero) {
577 : int32_t t_constant = -1033;
578 : int32_t f_constant = 825118;
579 :
580 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
581 4 : MachineType::Uint32());
582 4 : Node* a = m.Parameter(0);
583 4 : Node* b = m.Parameter(1);
584 4 : Node* add = m.Int32Add(a, b);
585 4 : Node* compare = m.Uint32LessThanOrEqual(add, m.Int32Constant(0));
586 :
587 4 : RawMachineLabel blocka, blockb;
588 4 : m.Branch(compare, &blocka, &blockb);
589 4 : m.Bind(&blocka);
590 4 : m.Return(m.Int32Constant(t_constant));
591 4 : m.Bind(&blockb);
592 4 : m.Return(m.Int32Constant(f_constant));
593 :
594 468 : FOR_UINT32_INPUTS(a) {
595 27144 : FOR_UINT32_INPUTS(b) {
596 13456 : int32_t expect = (a + b <= 0) ? t_constant : f_constant;
597 13456 : CHECK_EQ(expect, m.Call(a, b));
598 : }
599 : }
600 4 : }
601 :
602 26660 : TEST(BranchCombineUint32AddGreaterThanZero) {
603 : int32_t t_constant = -1033;
604 : int32_t f_constant = 825118;
605 :
606 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
607 4 : MachineType::Uint32());
608 4 : Node* a = m.Parameter(0);
609 4 : Node* b = m.Parameter(1);
610 4 : Node* add = m.Int32Add(a, b);
611 4 : Node* compare = m.Uint32GreaterThan(add, m.Int32Constant(0));
612 :
613 4 : RawMachineLabel blocka, blockb;
614 4 : m.Branch(compare, &blocka, &blockb);
615 4 : m.Bind(&blocka);
616 4 : m.Return(m.Int32Constant(t_constant));
617 4 : m.Bind(&blockb);
618 4 : m.Return(m.Int32Constant(f_constant));
619 :
620 468 : FOR_UINT32_INPUTS(a) {
621 27144 : FOR_UINT32_INPUTS(b) {
622 13456 : int32_t expect = (a + b > 0) ? t_constant : f_constant;
623 13456 : CHECK_EQ(expect, m.Call(a, b));
624 : }
625 : }
626 4 : }
627 :
628 26660 : TEST(BranchCombineUint32ZeroGreaterThanOrEqualAdd) {
629 : int32_t t_constant = -1033;
630 : int32_t f_constant = 825118;
631 :
632 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
633 4 : MachineType::Uint32());
634 4 : Node* a = m.Parameter(0);
635 4 : Node* b = m.Parameter(1);
636 4 : Node* add = m.Int32Add(a, b);
637 4 : Node* compare = m.Uint32GreaterThanOrEqual(m.Int32Constant(0), add);
638 :
639 4 : RawMachineLabel blocka, blockb;
640 4 : m.Branch(compare, &blocka, &blockb);
641 4 : m.Bind(&blocka);
642 4 : m.Return(m.Int32Constant(t_constant));
643 4 : m.Bind(&blockb);
644 4 : m.Return(m.Int32Constant(f_constant));
645 :
646 468 : FOR_UINT32_INPUTS(a) {
647 27144 : FOR_UINT32_INPUTS(b) {
648 13456 : int32_t expect = (0 >= a + b) ? t_constant : f_constant;
649 13456 : CHECK_EQ(expect, m.Call(a, b));
650 : }
651 : }
652 4 : }
653 :
654 26660 : TEST(BranchCombineUint32ZeroLessThanAdd) {
655 : int32_t t_constant = -1033;
656 : int32_t f_constant = 825118;
657 :
658 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
659 4 : MachineType::Uint32());
660 4 : Node* a = m.Parameter(0);
661 4 : Node* b = m.Parameter(1);
662 4 : Node* add = m.Int32Add(a, b);
663 4 : Node* compare = m.Uint32LessThan(m.Int32Constant(0), add);
664 :
665 4 : RawMachineLabel blocka, blockb;
666 4 : m.Branch(compare, &blocka, &blockb);
667 4 : m.Bind(&blocka);
668 4 : m.Return(m.Int32Constant(t_constant));
669 4 : m.Bind(&blockb);
670 4 : m.Return(m.Int32Constant(f_constant));
671 :
672 468 : FOR_UINT32_INPUTS(a) {
673 27144 : FOR_UINT32_INPUTS(b) {
674 13456 : int32_t expect = (0 < a + b) ? t_constant : f_constant;
675 13456 : CHECK_EQ(expect, m.Call(a, b));
676 : }
677 : }
678 4 : }
679 :
680 26660 : TEST(BranchCombineWord32AndLessThanZero) {
681 : int32_t t_constant = -1033;
682 : int32_t f_constant = 825118;
683 :
684 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
685 4 : MachineType::Int32());
686 4 : Node* a = m.Parameter(0);
687 4 : Node* b = m.Parameter(1);
688 4 : Node* add = m.Word32And(a, b);
689 4 : Node* compare = m.Int32LessThan(add, m.Int32Constant(0));
690 :
691 4 : RawMachineLabel blocka, blockb;
692 4 : m.Branch(compare, &blocka, &blockb);
693 4 : m.Bind(&blocka);
694 4 : m.Return(m.Int32Constant(t_constant));
695 4 : m.Bind(&blockb);
696 4 : m.Return(m.Int32Constant(f_constant));
697 :
698 468 : FOR_INT32_INPUTS(a) {
699 27144 : FOR_INT32_INPUTS(b) {
700 13456 : int32_t expect = ((a & b) < 0) ? t_constant : f_constant;
701 13456 : CHECK_EQ(expect, m.Call(a, b));
702 : }
703 : }
704 4 : }
705 :
706 26660 : TEST(BranchCombineWord32AndGreaterThanOrEqualZero) {
707 : int32_t t_constant = -1033;
708 : int32_t f_constant = 825118;
709 :
710 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
711 4 : MachineType::Int32());
712 4 : Node* a = m.Parameter(0);
713 4 : Node* b = m.Parameter(1);
714 4 : Node* add = m.Word32And(a, b);
715 4 : Node* compare = m.Int32GreaterThanOrEqual(add, m.Int32Constant(0));
716 :
717 4 : RawMachineLabel blocka, blockb;
718 4 : m.Branch(compare, &blocka, &blockb);
719 4 : m.Bind(&blocka);
720 4 : m.Return(m.Int32Constant(t_constant));
721 4 : m.Bind(&blockb);
722 4 : m.Return(m.Int32Constant(f_constant));
723 :
724 468 : FOR_INT32_INPUTS(a) {
725 27144 : FOR_INT32_INPUTS(b) {
726 13456 : int32_t expect = ((a & b) >= 0) ? t_constant : f_constant;
727 13456 : CHECK_EQ(expect, m.Call(a, b));
728 : }
729 : }
730 4 : }
731 :
732 26660 : TEST(BranchCombineInt32ZeroGreaterThanAnd) {
733 : int32_t t_constant = -1033;
734 : int32_t f_constant = 825118;
735 :
736 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
737 4 : MachineType::Int32());
738 4 : Node* a = m.Parameter(0);
739 4 : Node* b = m.Parameter(1);
740 4 : Node* add = m.Word32And(a, b);
741 4 : Node* compare = m.Int32GreaterThan(m.Int32Constant(0), add);
742 :
743 4 : RawMachineLabel blocka, blockb;
744 4 : m.Branch(compare, &blocka, &blockb);
745 4 : m.Bind(&blocka);
746 4 : m.Return(m.Int32Constant(t_constant));
747 4 : m.Bind(&blockb);
748 4 : m.Return(m.Int32Constant(f_constant));
749 :
750 468 : FOR_INT32_INPUTS(a) {
751 27144 : FOR_INT32_INPUTS(b) {
752 13456 : int32_t expect = (0 > (a & b)) ? t_constant : f_constant;
753 13456 : CHECK_EQ(expect, m.Call(a, b));
754 : }
755 : }
756 4 : }
757 :
758 26660 : TEST(BranchCombineInt32ZeroLessThanOrEqualAnd) {
759 : int32_t t_constant = -1033;
760 : int32_t f_constant = 825118;
761 :
762 : RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
763 4 : MachineType::Int32());
764 4 : Node* a = m.Parameter(0);
765 4 : Node* b = m.Parameter(1);
766 4 : Node* add = m.Word32And(a, b);
767 4 : Node* compare = m.Int32LessThanOrEqual(m.Int32Constant(0), add);
768 :
769 4 : RawMachineLabel blocka, blockb;
770 4 : m.Branch(compare, &blocka, &blockb);
771 4 : m.Bind(&blocka);
772 4 : m.Return(m.Int32Constant(t_constant));
773 4 : m.Bind(&blockb);
774 4 : m.Return(m.Int32Constant(f_constant));
775 :
776 468 : FOR_INT32_INPUTS(a) {
777 27144 : FOR_INT32_INPUTS(b) {
778 13456 : int32_t expect = (0 <= (a & b)) ? t_constant : f_constant;
779 13456 : CHECK_EQ(expect, m.Call(a, b));
780 : }
781 : }
782 4 : }
783 :
784 26660 : TEST(BranchCombineUint32AndLessThanOrEqualZero) {
785 : int32_t t_constant = -1033;
786 : int32_t f_constant = 825118;
787 :
788 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
789 4 : MachineType::Uint32());
790 4 : Node* a = m.Parameter(0);
791 4 : Node* b = m.Parameter(1);
792 4 : Node* add = m.Word32And(a, b);
793 4 : Node* compare = m.Uint32LessThanOrEqual(add, m.Int32Constant(0));
794 :
795 4 : RawMachineLabel blocka, blockb;
796 4 : m.Branch(compare, &blocka, &blockb);
797 4 : m.Bind(&blocka);
798 4 : m.Return(m.Int32Constant(t_constant));
799 4 : m.Bind(&blockb);
800 4 : m.Return(m.Int32Constant(f_constant));
801 :
802 468 : FOR_UINT32_INPUTS(a) {
803 27144 : FOR_UINT32_INPUTS(b) {
804 13456 : int32_t expect = ((a & b) <= 0) ? t_constant : f_constant;
805 13456 : CHECK_EQ(expect, m.Call(a, b));
806 : }
807 : }
808 4 : }
809 :
810 26660 : TEST(BranchCombineUint32AndGreaterThanZero) {
811 : int32_t t_constant = -1033;
812 : int32_t f_constant = 825118;
813 :
814 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
815 4 : MachineType::Uint32());
816 4 : Node* a = m.Parameter(0);
817 4 : Node* b = m.Parameter(1);
818 4 : Node* add = m.Word32And(a, b);
819 4 : Node* compare = m.Uint32GreaterThan(add, m.Int32Constant(0));
820 :
821 4 : RawMachineLabel blocka, blockb;
822 4 : m.Branch(compare, &blocka, &blockb);
823 4 : m.Bind(&blocka);
824 4 : m.Return(m.Int32Constant(t_constant));
825 4 : m.Bind(&blockb);
826 4 : m.Return(m.Int32Constant(f_constant));
827 :
828 468 : FOR_UINT32_INPUTS(a) {
829 27144 : FOR_UINT32_INPUTS(b) {
830 13456 : int32_t expect = ((a & b) > 0) ? t_constant : f_constant;
831 13456 : CHECK_EQ(expect, m.Call(a, b));
832 : }
833 : }
834 4 : }
835 :
836 26660 : TEST(BranchCombineUint32ZeroGreaterThanOrEqualAnd) {
837 : int32_t t_constant = -1033;
838 : int32_t f_constant = 825118;
839 :
840 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
841 4 : MachineType::Uint32());
842 4 : Node* a = m.Parameter(0);
843 4 : Node* b = m.Parameter(1);
844 4 : Node* add = m.Word32And(a, b);
845 4 : Node* compare = m.Uint32GreaterThanOrEqual(m.Int32Constant(0), add);
846 :
847 4 : RawMachineLabel blocka, blockb;
848 4 : m.Branch(compare, &blocka, &blockb);
849 4 : m.Bind(&blocka);
850 4 : m.Return(m.Int32Constant(t_constant));
851 4 : m.Bind(&blockb);
852 4 : m.Return(m.Int32Constant(f_constant));
853 :
854 468 : FOR_UINT32_INPUTS(a) {
855 27144 : FOR_UINT32_INPUTS(b) {
856 13456 : int32_t expect = (0 >= (a & b)) ? t_constant : f_constant;
857 13456 : CHECK_EQ(expect, m.Call(a, b));
858 : }
859 : }
860 4 : }
861 :
862 26660 : TEST(BranchCombineUint32ZeroLessThanAnd) {
863 : int32_t t_constant = -1033;
864 : int32_t f_constant = 825118;
865 :
866 : RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
867 4 : MachineType::Uint32());
868 4 : Node* a = m.Parameter(0);
869 4 : Node* b = m.Parameter(1);
870 4 : Node* add = m.Word32And(a, b);
871 4 : Node* compare = m.Uint32LessThan(m.Int32Constant(0), add);
872 :
873 4 : RawMachineLabel blocka, blockb;
874 4 : m.Branch(compare, &blocka, &blockb);
875 4 : m.Bind(&blocka);
876 4 : m.Return(m.Int32Constant(t_constant));
877 4 : m.Bind(&blockb);
878 4 : m.Return(m.Int32Constant(f_constant));
879 :
880 468 : FOR_UINT32_INPUTS(a) {
881 27144 : FOR_UINT32_INPUTS(b) {
882 13456 : int32_t expect = (0 < (a & b)) ? t_constant : f_constant;
883 13456 : CHECK_EQ(expect, m.Call(a, b));
884 : }
885 : }
886 4 : }
887 :
888 : } // namespace compiler
889 : } // namespace internal
890 79968 : } // namespace v8
|