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