| Index: test/cctest/compiler/test-run-machops.cc
|
| diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc
|
| index c660a7319d75325c81bdd1be69e32a36d4d36406..45a7a77f29d93919d57ed9fecf2a75b7491c57f8 100644
|
| --- a/test/cctest/compiler/test-run-machops.cc
|
| +++ b/test/cctest/compiler/test-run-machops.cc
|
| @@ -3891,14 +3891,6 @@ static bool sadd_overflow(int32_t x, int32_t y, int32_t* val) {
|
| }
|
|
|
|
|
| -static bool ssub_overflow(int32_t x, int32_t y, int32_t* val) {
|
| - int32_t v =
|
| - static_cast<int32_t>(static_cast<uint32_t>(x) - static_cast<uint32_t>(y));
|
| - *val = v;
|
| - return (((v ^ x) & (v ^ ~y)) >> 31) & 1;
|
| -}
|
| -
|
| -
|
| TEST(RunInt32AddWithOverflowP) {
|
| int32_t actual_val = -1;
|
| RawMachineAssemblerTester<int32_t> m;
|
| @@ -3987,6 +3979,109 @@ TEST(RunInt32AddWithOverflowInBranchP) {
|
| }
|
|
|
|
|
| +static bool uadd_overflow(uint32_t x, uint32_t y, uint32_t* val) {
|
| + uint32_t v = x + y;
|
| + *val = v;
|
| + return (((x & y) | ((x | y) & ~v)) >> 31) & 1;
|
| +}
|
| +
|
| +
|
| +TEST(RunUint32AddWithOverflowP) {
|
| + uint32_t actual_val = -1;
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + Node* add = m.Uint32AddWithOverflow(bt.param0, bt.param1);
|
| + Node* val = m.Projection(0, add);
|
| + Node* ovf = m.Projection(1, add);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + bt.AddReturn(ovf);
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t expected_val;
|
| + int expected_ovf = uadd_overflow(*i, *j, &expected_val);
|
| + CHECK_EQ(expected_ovf, bt.call(*i, *j));
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunUint32AddWithOverflowImm) {
|
| + uint32_t actual_val = -1, expected_val = 0;
|
| + FOR_UINT32_INPUTS(i) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + Node* add = m.Uint32AddWithOverflow(m.Int32Constant(*i), m.Parameter(0));
|
| + Node* val = m.Projection(0, add);
|
| + Node* ovf = m.Projection(1, add);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + m.Return(ovf);
|
| + FOR_UINT32_INPUTS(j) {
|
| + int expected_ovf = uadd_overflow(*i, *j, &expected_val);
|
| + CHECK_EQ(expected_ovf, m.Call(*j));
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + Node* add = m.Uint32AddWithOverflow(m.Parameter(0), m.Int32Constant(*i));
|
| + Node* val = m.Projection(0, add);
|
| + Node* ovf = m.Projection(1, add);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + m.Return(ovf);
|
| + FOR_UINT32_INPUTS(j) {
|
| + int expected_ovf = uadd_overflow(*j, *i, &expected_val);
|
| + CHECK_EQ(expected_ovf, m.Call(*j));
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| + FOR_UINT32_INPUTS(j) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* add =
|
| + m.Uint32AddWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j));
|
| + Node* val = m.Projection(0, add);
|
| + Node* ovf = m.Projection(1, add);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + m.Return(ovf);
|
| + int expected_ovf = uadd_overflow(*i, *j, &expected_val);
|
| + CHECK_EQ(expected_ovf, m.Call());
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunUint32AddWithOverflowInBranchP) {
|
| + int constant = 911999;
|
| + MLabel blocka, blockb;
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + Node* sub = m.Uint32AddWithOverflow(bt.param0, bt.param1);
|
| + Node* ovf = m.Projection(1, sub);
|
| + m.Branch(ovf, &blocka, &blockb);
|
| + m.Bind(&blocka);
|
| + bt.AddReturn(m.Int32Constant(constant));
|
| + m.Bind(&blockb);
|
| + Node* val = m.Projection(0, sub);
|
| + bt.AddReturn(val);
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t expected;
|
| + if (uadd_overflow(*i, *j, &expected)) expected = constant;
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +static bool ssub_overflow(int32_t x, int32_t y, int32_t* val) {
|
| + int32_t v =
|
| + static_cast<int32_t>(static_cast<uint32_t>(x) - static_cast<uint32_t>(y));
|
| + *val = v;
|
| + return (((v ^ x) & (v ^ ~y)) >> 31) & 1;
|
| +}
|
| +
|
| +
|
| TEST(RunInt32SubWithOverflowP) {
|
| int32_t actual_val = -1;
|
| RawMachineAssemblerTester<int32_t> m;
|
| @@ -4074,4 +4169,99 @@ TEST(RunInt32SubWithOverflowInBranchP) {
|
| }
|
| }
|
|
|
| +
|
| +static bool usub_overflow(uint32_t x, uint32_t y, uint32_t* val) {
|
| + uint32_t v = x - y;
|
| + *val = v;
|
| + return (((~x & y) | ((~x | y) & v)) >> 31) & 1;
|
| +}
|
| +
|
| +
|
| +TEST(RunUint32SubWithOverflowP) {
|
| + uint32_t actual_val = -1;
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + Node* sub = m.Uint32SubWithOverflow(bt.param0, bt.param1);
|
| + Node* val = m.Projection(0, sub);
|
| + Node* ovf = m.Projection(1, sub);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + bt.AddReturn(ovf);
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t expected_val;
|
| + int expected_ovf = usub_overflow(*i, *j, &expected_val);
|
| + CHECK_EQ(expected_ovf, bt.call(*i, *j));
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunUint32SubWithOverflowImm) {
|
| + uint32_t actual_val = -1, expected_val = 0;
|
| + FOR_UINT32_INPUTS(i) {
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + Node* add = m.Uint32SubWithOverflow(m.Int32Constant(*i), m.Parameter(0));
|
| + Node* val = m.Projection(0, add);
|
| + Node* ovf = m.Projection(1, add);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + m.Return(ovf);
|
| + FOR_UINT32_INPUTS(j) {
|
| + int expected_ovf = usub_overflow(*i, *j, &expected_val);
|
| + CHECK_EQ(expected_ovf, m.Call(*j));
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| + {
|
| + RawMachineAssemblerTester<int32_t> m(kMachineWord32);
|
| + Node* add = m.Uint32SubWithOverflow(m.Parameter(0), m.Int32Constant(*i));
|
| + Node* val = m.Projection(0, add);
|
| + Node* ovf = m.Projection(1, add);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + m.Return(ovf);
|
| + FOR_UINT32_INPUTS(j) {
|
| + int expected_ovf = usub_overflow(*j, *i, &expected_val);
|
| + CHECK_EQ(expected_ovf, m.Call(*j));
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| + FOR_UINT32_INPUTS(j) {
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Node* add =
|
| + m.Uint32SubWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j));
|
| + Node* val = m.Projection(0, add);
|
| + Node* ovf = m.Projection(1, add);
|
| + m.StoreToPointer(&actual_val, kMachineWord32, val);
|
| + m.Return(ovf);
|
| + int expected_ovf = usub_overflow(*i, *j, &expected_val);
|
| + CHECK_EQ(expected_ovf, m.Call());
|
| + CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(RunUint32SubWithOverflowInBranchP) {
|
| + int constant = 911999;
|
| + MLabel blocka, blockb;
|
| + RawMachineAssemblerTester<int32_t> m;
|
| + Int32BinopTester bt(&m);
|
| + Node* sub = m.Uint32SubWithOverflow(bt.param0, bt.param1);
|
| + Node* ovf = m.Projection(1, sub);
|
| + m.Branch(ovf, &blocka, &blockb);
|
| + m.Bind(&blocka);
|
| + bt.AddReturn(m.Int32Constant(constant));
|
| + m.Bind(&blockb);
|
| + Node* val = m.Projection(0, sub);
|
| + bt.AddReturn(val);
|
| + FOR_UINT32_INPUTS(i) {
|
| + FOR_UINT32_INPUTS(j) {
|
| + uint32_t expected;
|
| + if (usub_overflow(*i, *j, &expected)) expected = constant;
|
| + CHECK_EQ(expected, bt.call(*i, *j));
|
| + }
|
| + }
|
| +}
|
| +
|
| #endif // V8_TURBOFAN_TARGET
|
|
|