test-branch-combine.cc 25.9 KB
Newer Older
1 2 3 4
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/base/overflowing-math.h"
6
#include "src/objects/objects-inl.h"
7
#include "test/cctest/cctest.h"
8
#include "test/cctest/compiler/test-codegen.h"
9 10
#include "test/cctest/compiler/value-helper.h"

11 12 13
namespace v8 {
namespace internal {
namespace compiler {
14 15 16 17 18 19 20 21 22

static IrOpcode::Value int32cmp_opcodes[] = {
    IrOpcode::kWord32Equal, IrOpcode::kInt32LessThan,
    IrOpcode::kInt32LessThanOrEqual, IrOpcode::kUint32LessThan,
    IrOpcode::kUint32LessThanOrEqual};


TEST(BranchCombineWord32EqualZero_1) {
  // Test combining a branch with x == 0
23
  RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
24 25 26 27
  int32_t eq_constant = -1033;
  int32_t ne_constant = 825118;
  Node* p0 = m.Parameter(0);

28
  RawMachineLabel blocka, blockb;
29 30 31 32 33 34
  m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(eq_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(ne_constant));

35
  FOR_INT32_INPUTS(a) {
36 37 38 39 40 41 42 43 44 45 46 47
    int32_t expect = a == 0 ? eq_constant : ne_constant;
    CHECK_EQ(expect, m.Call(a));
  }
}


TEST(BranchCombineWord32EqualZero_chain) {
  // Test combining a branch with a chain of x == 0 == 0 == 0 ...
  int32_t eq_constant = -1133;
  int32_t ne_constant = 815118;

  for (int k = 0; k < 6; k++) {
48
    RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
49
    Node* p0 = m.Parameter(0);
50
    RawMachineLabel blocka, blockb;
51 52 53 54 55 56 57 58 59 60
    Node* cond = p0;
    for (int j = 0; j < k; j++) {
      cond = m.Word32Equal(cond, m.Int32Constant(0));
    }
    m.Branch(cond, &blocka, &blockb);
    m.Bind(&blocka);
    m.Return(m.Int32Constant(eq_constant));
    m.Bind(&blockb);
    m.Return(m.Int32Constant(ne_constant));

61
    FOR_INT32_INPUTS(a) {
62 63 64 65 66 67 68 69 70 71
      int32_t expect = (k & 1) == 1 ? (a == 0 ? eq_constant : ne_constant)
                                    : (a == 0 ? ne_constant : eq_constant);
      CHECK_EQ(expect, m.Call(a));
    }
  }
}


TEST(BranchCombineInt32LessThanZero_1) {
  // Test combining a branch with x < 0
72
  RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
73 74 75 76
  int32_t eq_constant = -1433;
  int32_t ne_constant = 845118;
  Node* p0 = m.Parameter(0);

77
  RawMachineLabel blocka, blockb;
78 79 80 81 82 83
  m.Branch(m.Int32LessThan(p0, m.Int32Constant(0)), &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(eq_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(ne_constant));

84
  FOR_INT32_INPUTS(a) {
85 86 87 88 89 90 91 92
    int32_t expect = a < 0 ? eq_constant : ne_constant;
    CHECK_EQ(expect, m.Call(a));
  }
}


TEST(BranchCombineUint32LessThan100_1) {
  // Test combining a branch with x < 100
93
  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
94 95 96 97
  int32_t eq_constant = 1471;
  int32_t ne_constant = 88845718;
  Node* p0 = m.Parameter(0);

98
  RawMachineLabel blocka, blockb;
99 100 101 102 103 104
  m.Branch(m.Uint32LessThan(p0, m.Int32Constant(100)), &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(eq_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(ne_constant));

105
  FOR_UINT32_INPUTS(a) {
106 107 108 109 110 111 112 113
    int32_t expect = a < 100 ? eq_constant : ne_constant;
    CHECK_EQ(expect, m.Call(a));
  }
}


TEST(BranchCombineUint32LessThanOrEqual100_1) {
  // Test combining a branch with x <= 100
114
  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
115 116 117 118
  int32_t eq_constant = 1479;
  int32_t ne_constant = 77845719;
  Node* p0 = m.Parameter(0);

119
  RawMachineLabel blocka, blockb;
120 121 122 123 124 125
  m.Branch(m.Uint32LessThanOrEqual(p0, m.Int32Constant(100)), &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(eq_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(ne_constant));

126
  FOR_UINT32_INPUTS(a) {
127 128 129 130 131 132 133 134
    int32_t expect = a <= 100 ? eq_constant : ne_constant;
    CHECK_EQ(expect, m.Call(a));
  }
}


TEST(BranchCombineZeroLessThanInt32_1) {
  // Test combining a branch with 0 < x
135
  RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
136 137 138 139
  int32_t eq_constant = -2033;
  int32_t ne_constant = 225118;
  Node* p0 = m.Parameter(0);

140
  RawMachineLabel blocka, blockb;
141 142 143 144 145 146
  m.Branch(m.Int32LessThan(m.Int32Constant(0), p0), &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(eq_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(ne_constant));

147
  FOR_INT32_INPUTS(a) {
148 149 150 151 152 153 154 155
    int32_t expect = 0 < a ? eq_constant : ne_constant;
    CHECK_EQ(expect, m.Call(a));
  }
}


TEST(BranchCombineInt32GreaterThanZero_1) {
  // Test combining a branch with x > 0
156
  RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
157 158 159 160
  int32_t eq_constant = -1073;
  int32_t ne_constant = 825178;
  Node* p0 = m.Parameter(0);

161
  RawMachineLabel blocka, blockb;
162 163 164 165 166 167
  m.Branch(m.Int32GreaterThan(p0, m.Int32Constant(0)), &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(eq_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(ne_constant));

168
  FOR_INT32_INPUTS(a) {
169 170 171 172 173 174 175 176
    int32_t expect = a > 0 ? eq_constant : ne_constant;
    CHECK_EQ(expect, m.Call(a));
  }
}


TEST(BranchCombineWord32EqualP) {
  // Test combining a branch with an Word32Equal.
177 178
  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
179 180 181 182 183
  int32_t eq_constant = -1035;
  int32_t ne_constant = 825018;
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);

184
  RawMachineLabel blocka, blockb;
185 186 187 188 189 190
  m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(eq_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(ne_constant));

191 192
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
193 194 195 196 197 198 199 200 201 202 203 204
      int32_t expect = a == b ? eq_constant : ne_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}


TEST(BranchCombineWord32EqualI) {
  int32_t eq_constant = -1135;
  int32_t ne_constant = 925718;

  for (int left = 0; left < 2; left++) {
205
    FOR_INT32_INPUTS(a) {
206
      RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
207 208 209 210

      Node* p0 = m.Int32Constant(a);
      Node* p1 = m.Parameter(0);

211
      RawMachineLabel blocka, blockb;
212 213 214 215 216 217 218
      if (left == 1) m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
      if (left == 0) m.Branch(m.Word32Equal(p1, p0), &blocka, &blockb);
      m.Bind(&blocka);
      m.Return(m.Int32Constant(eq_constant));
      m.Bind(&blockb);
      m.Return(m.Int32Constant(ne_constant));

219
      FOR_INT32_INPUTS(b) {
220 221 222 223 224 225 226 227 228 229 230 231 232
        int32_t expect = a == b ? eq_constant : ne_constant;
        CHECK_EQ(expect, m.Call(b));
      }
    }
  }
}


TEST(BranchCombineInt32CmpP) {
  int32_t eq_constant = -1235;
  int32_t ne_constant = 725018;

  for (int op = 0; op < 2; op++) {
233 234
    RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                         MachineType::Int32());
235 236 237
    Node* p0 = m.Parameter(0);
    Node* p1 = m.Parameter(1);

238
    RawMachineLabel blocka, blockb;
239 240 241 242 243 244 245
    if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
    if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
    m.Bind(&blocka);
    m.Return(m.Int32Constant(eq_constant));
    m.Bind(&blockb);
    m.Return(m.Int32Constant(ne_constant));

246 247
    FOR_INT32_INPUTS(a) {
      FOR_INT32_INPUTS(b) {
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
        int32_t expect = 0;
        if (op == 0) expect = a < b ? eq_constant : ne_constant;
        if (op == 1) expect = a <= b ? eq_constant : ne_constant;
        CHECK_EQ(expect, m.Call(a, b));
      }
    }
  }
}


TEST(BranchCombineInt32CmpI) {
  int32_t eq_constant = -1175;
  int32_t ne_constant = 927711;

  for (int op = 0; op < 2; op++) {
263
    FOR_INT32_INPUTS(a) {
264
      RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
265 266 267
      Node* p0 = m.Int32Constant(a);
      Node* p1 = m.Parameter(0);

268
      RawMachineLabel blocka, blockb;
269 270 271 272 273 274 275
      if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
      if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
      m.Bind(&blocka);
      m.Return(m.Int32Constant(eq_constant));
      m.Bind(&blockb);
      m.Return(m.Int32Constant(ne_constant));

276
      FOR_INT32_INPUTS(b) {
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
        int32_t expect = 0;
        if (op == 0) expect = a < b ? eq_constant : ne_constant;
        if (op == 1) expect = a <= b ? eq_constant : ne_constant;
        CHECK_EQ(expect, m.Call(b));
      }
    }
  }
}


// Now come the sophisticated tests for many input shape combinations.

// Materializes a boolean (1 or 0) from a comparison.
class CmpMaterializeBoolGen : public BinopGen<int32_t> {
 public:
  CompareWrapper w;
  bool invert;

  CmpMaterializeBoolGen(IrOpcode::Value opcode, bool i)
      : w(opcode), invert(i) {}

298
  void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) override {
299 300 301 302
    Node* cond = w.MakeNode(m, a, b);
    if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
    m->Return(cond);
  }
303
  int32_t expected(int32_t a, int32_t b) override {
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
    if (invert) return !w.Int32Compare(a, b) ? 1 : 0;
    return w.Int32Compare(a, b) ? 1 : 0;
  }
};


// Generates a branch and return one of two values from a comparison.
class CmpBranchGen : public BinopGen<int32_t> {
 public:
  CompareWrapper w;
  bool invert;
  bool true_first;
  int32_t eq_constant;
  int32_t ne_constant;

  CmpBranchGen(IrOpcode::Value opcode, bool i, bool t, int32_t eq, int32_t ne)
      : w(opcode), invert(i), true_first(t), eq_constant(eq), ne_constant(ne) {}

322
  void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) override {
323
    RawMachineLabel blocka, blockb;
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
    Node* cond = w.MakeNode(m, a, b);
    if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
    m->Branch(cond, &blocka, &blockb);
    if (true_first) {
      m->Bind(&blocka);
      m->Return(m->Int32Constant(eq_constant));
      m->Bind(&blockb);
      m->Return(m->Int32Constant(ne_constant));
    } else {
      m->Bind(&blockb);
      m->Return(m->Int32Constant(ne_constant));
      m->Bind(&blocka);
      m->Return(m->Int32Constant(eq_constant));
    }
  }
339
  int32_t expected(int32_t a, int32_t b) override {
340 341 342 343 344 345 346
    if (invert) return !w.Int32Compare(a, b) ? eq_constant : ne_constant;
    return w.Int32Compare(a, b) ? eq_constant : ne_constant;
  }
};


TEST(BranchCombineInt32CmpAllInputShapes_materialized) {
347
  for (size_t i = 0; i < arraysize(int32cmp_opcodes); i++) {
348 349 350 351 352 353 354 355
    CmpMaterializeBoolGen gen(int32cmp_opcodes[i], false);
    Int32BinopInputShapeTester tester(&gen);
    tester.TestAllInputShapes();
  }
}


TEST(BranchCombineInt32CmpAllInputShapes_inverted_materialized) {
356
  for (size_t i = 0; i < arraysize(int32cmp_opcodes); i++) {
357 358 359 360 361 362 363 364
    CmpMaterializeBoolGen gen(int32cmp_opcodes[i], true);
    Int32BinopInputShapeTester tester(&gen);
    tester.TestAllInputShapes();
  }
}


TEST(BranchCombineInt32CmpAllInputShapes_branch_true) {
365
  for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
366 367 368 369 370 371 372 373
    CmpBranchGen gen(int32cmp_opcodes[i], false, false, 995 + i, -1011 - i);
    Int32BinopInputShapeTester tester(&gen);
    tester.TestAllInputShapes();
  }
}


TEST(BranchCombineInt32CmpAllInputShapes_branch_false) {
374
  for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
375 376 377 378 379 380 381 382
    CmpBranchGen gen(int32cmp_opcodes[i], false, true, 795 + i, -2011 - i);
    Int32BinopInputShapeTester tester(&gen);
    tester.TestAllInputShapes();
  }
}


TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_true) {
383
  for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
384 385 386 387 388 389 390 391
    CmpBranchGen gen(int32cmp_opcodes[i], true, false, 695 + i, -3011 - i);
    Int32BinopInputShapeTester tester(&gen);
    tester.TestAllInputShapes();
  }
}


TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_false) {
392
  for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
393 394 395 396 397 398 399 400
    CmpBranchGen gen(int32cmp_opcodes[i], true, true, 595 + i, -4011 - i);
    Int32BinopInputShapeTester tester(&gen);
    tester.TestAllInputShapes();
  }
}


TEST(BranchCombineFloat64Compares) {
401
  double inf = V8_INFINITY;
402
  double nan = std::numeric_limits<double>::quiet_NaN();
403 404 405 406 407 408 409 410 411 412 413 414
  double inputs[] = {0.0, 1.0, -1.0, -inf, inf, nan};

  int32_t eq_constant = -1733;
  int32_t ne_constant = 915118;

  double input_a = 0.0;
  double input_b = 0.0;

  CompareWrapper cmps[] = {CompareWrapper(IrOpcode::kFloat64Equal),
                           CompareWrapper(IrOpcode::kFloat64LessThan),
                           CompareWrapper(IrOpcode::kFloat64LessThanOrEqual)};

415
  for (size_t c = 0; c < arraysize(cmps); c++) {
416 417 418
    CompareWrapper cmp = cmps[c];
    for (int invert = 0; invert < 2; invert++) {
      RawMachineAssemblerTester<int32_t> m;
419 420
      Node* a = m.LoadFromPointer(&input_a, MachineType::Float64());
      Node* b = m.LoadFromPointer(&input_b, MachineType::Float64());
421

422
      RawMachineLabel blocka, blockb;
423 424 425 426 427 428 429 430
      Node* cond = cmp.MakeNode(&m, a, b);
      if (invert) cond = m.Word32Equal(cond, m.Int32Constant(0));
      m.Branch(cond, &blocka, &blockb);
      m.Bind(&blocka);
      m.Return(m.Int32Constant(eq_constant));
      m.Bind(&blockb);
      m.Return(m.Int32Constant(ne_constant));

431 432
      for (size_t i = 0; i < arraysize(inputs); ++i) {
        for (size_t j = 0; j < arraysize(inputs); ++j) {
433
          input_a = inputs[i];
434
          input_b = inputs[j];
435 436 437 438 439 440 441 442 443 444 445
          int32_t expected =
              invert ? (cmp.Float64Compare(input_a, input_b) ? ne_constant
                                                             : eq_constant)
                     : (cmp.Float64Compare(input_a, input_b) ? eq_constant
                                                             : ne_constant);
          CHECK_EQ(expected, m.Call());
        }
      }
    }
  }
}
446

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
TEST(BranchCombineEffectLevel) {
  // Test that the load doesn't get folded into the branch, as there's a store
  // between them. See http://crbug.com/611976.
  int32_t input = 0;

  RawMachineAssemblerTester<int32_t> m;
  Node* a = m.LoadFromPointer(&input, MachineType::Int32());
  Node* compare = m.Word32And(a, m.Int32Constant(1));
  Node* equal = m.Word32Equal(compare, m.Int32Constant(0));
  m.StoreToPointer(&input, MachineRepresentation::kWord32, m.Int32Constant(1));

  RawMachineLabel blocka, blockb;
  m.Branch(equal, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(42));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(0));

  CHECK_EQ(42, m.Call());
}

468 469 470 471 472 473
TEST(BranchCombineInt32AddLessThanZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
474 475 476
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
477 478 479 480 481 482 483 484 485
  Node* compare = m.Int32LessThan(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

486 487
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
488 489
      int32_t expect =
          (base::AddWithWraparound(a, b) < 0) ? t_constant : f_constant;
490 491 492 493 494 495 496 497 498 499 500
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineInt32AddGreaterThanOrEqualZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
501 502 503
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
504 505 506 507 508 509 510 511 512
  Node* compare = m.Int32GreaterThanOrEqual(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

513 514
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
515 516
      int32_t expect =
          (base::AddWithWraparound(a, b) >= 0) ? t_constant : f_constant;
517 518 519 520 521 522 523 524 525 526 527
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineInt32ZeroGreaterThanAdd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
528 529 530
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
531 532 533 534 535 536 537 538 539
  Node* compare = m.Int32GreaterThan(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

540 541
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
542 543
      int32_t expect =
          (0 > base::AddWithWraparound(a, b)) ? t_constant : f_constant;
544 545 546 547 548 549 550 551 552 553 554
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineInt32ZeroLessThanOrEqualAdd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
555 556 557
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
558 559 560 561 562 563 564 565 566
  Node* compare = m.Int32LessThanOrEqual(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

567 568
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
569 570
      int32_t expect =
          (0 <= base::AddWithWraparound(a, b)) ? t_constant : f_constant;
571 572 573 574 575 576 577 578 579 580 581
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32AddLessThanOrEqualZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
582 583 584
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
585 586 587 588 589 590 591 592 593
  Node* compare = m.Uint32LessThanOrEqual(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

594 595
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
596 597 598 599 600 601 602 603 604 605 606 607
      int32_t expect = (a + b <= 0) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32AddGreaterThanZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
608 609 610
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
611 612 613 614 615 616 617 618 619
  Node* compare = m.Uint32GreaterThan(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

620 621
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
622 623 624 625 626 627 628 629 630 631 632 633
      int32_t expect = (a + b > 0) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32ZeroGreaterThanOrEqualAdd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
634 635 636
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
637 638 639 640 641 642 643 644 645
  Node* compare = m.Uint32GreaterThanOrEqual(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

646 647
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
648 649 650 651 652 653 654 655 656 657 658 659
      int32_t expect = (0 >= a + b) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32ZeroLessThanAdd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
660 661 662
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Int32Add(p0, p1);
663 664 665 666 667 668 669 670 671
  Node* compare = m.Uint32LessThan(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

672 673
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
674 675 676 677 678 679 680 681 682 683 684 685
      int32_t expect = (0 < a + b) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineWord32AndLessThanZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
686 687 688
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
689 690 691 692 693 694 695 696 697
  Node* compare = m.Int32LessThan(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

698 699
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
700 701 702 703 704 705 706 707 708 709 710 711
      int32_t expect = ((a & b) < 0) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineWord32AndGreaterThanOrEqualZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
712 713 714
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
715 716 717 718 719 720 721 722 723
  Node* compare = m.Int32GreaterThanOrEqual(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

724 725
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
726 727 728 729 730 731 732 733 734 735 736 737
      int32_t expect = ((a & b) >= 0) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineInt32ZeroGreaterThanAnd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
738 739 740
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
741 742 743 744 745 746 747 748 749
  Node* compare = m.Int32GreaterThan(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

750 751
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
752 753 754 755 756 757 758 759 760 761 762 763
      int32_t expect = (0 > (a & b)) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineInt32ZeroLessThanOrEqualAnd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
                                       MachineType::Int32());
764 765 766
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
767 768 769 770 771 772 773 774 775
  Node* compare = m.Int32LessThanOrEqual(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

776 777
  FOR_INT32_INPUTS(a) {
    FOR_INT32_INPUTS(b) {
778 779 780 781 782 783 784 785 786 787 788 789
      int32_t expect = (0 <= (a & b)) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32AndLessThanOrEqualZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
790 791 792
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
793 794 795 796 797 798 799 800 801
  Node* compare = m.Uint32LessThanOrEqual(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

802 803
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
804 805 806 807 808 809 810 811 812 813 814 815
      int32_t expect = ((a & b) <= 0) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32AndGreaterThanZero) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
816 817 818
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
819 820 821 822 823 824 825 826 827
  Node* compare = m.Uint32GreaterThan(add, m.Int32Constant(0));

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

828 829
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
830 831 832 833 834 835 836 837 838 839 840 841
      int32_t expect = ((a & b) > 0) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32ZeroGreaterThanOrEqualAnd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
842 843 844
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
845 846 847 848 849 850 851 852 853
  Node* compare = m.Uint32GreaterThanOrEqual(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

854 855
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
856 857 858 859 860 861 862 863 864 865 866 867
      int32_t expect = (0 >= (a & b)) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

TEST(BranchCombineUint32ZeroLessThanAnd) {
  int32_t t_constant = -1033;
  int32_t f_constant = 825118;

  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
                                       MachineType::Uint32());
868 869 870
  Node* p0 = m.Parameter(0);
  Node* p1 = m.Parameter(1);
  Node* add = m.Word32And(p0, p1);
871 872 873 874 875 876 877 878 879
  Node* compare = m.Uint32LessThan(m.Int32Constant(0), add);

  RawMachineLabel blocka, blockb;
  m.Branch(compare, &blocka, &blockb);
  m.Bind(&blocka);
  m.Return(m.Int32Constant(t_constant));
  m.Bind(&blockb);
  m.Return(m.Int32Constant(f_constant));

880 881
  FOR_UINT32_INPUTS(a) {
    FOR_UINT32_INPUTS(b) {
882 883 884 885 886 887
      int32_t expect = (0 < (a & b)) ? t_constant : f_constant;
      CHECK_EQ(expect, m.Call(a, b));
    }
  }
}

888 889 890
}  // namespace compiler
}  // namespace internal
}  // namespace v8