| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <functional> | 5 #include <functional> |
| 6 #include <limits> | 6 #include <limits> |
| 7 | 7 |
| 8 #include "test/cctest/cctest.h" | 8 #include "test/cctest/cctest.h" |
| 9 #include "test/cctest/compiler/codegen-tester.h" | 9 #include "test/cctest/compiler/codegen-tester.h" |
| 10 #include "test/cctest/compiler/value-helper.h" | 10 #include "test/cctest/compiler/value-helper.h" |
| (...skipping 3873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3884 | 3884 |
| 3885 | 3885 |
| 3886 static bool sadd_overflow(int32_t x, int32_t y, int32_t* val) { | 3886 static bool sadd_overflow(int32_t x, int32_t y, int32_t* val) { |
| 3887 int32_t v = | 3887 int32_t v = |
| 3888 static_cast<int32_t>(static_cast<uint32_t>(x) + static_cast<uint32_t>(y)); | 3888 static_cast<int32_t>(static_cast<uint32_t>(x) + static_cast<uint32_t>(y)); |
| 3889 *val = v; | 3889 *val = v; |
| 3890 return (((v ^ x) & (v ^ y)) >> 31) & 1; | 3890 return (((v ^ x) & (v ^ y)) >> 31) & 1; |
| 3891 } | 3891 } |
| 3892 | 3892 |
| 3893 | 3893 |
| 3894 static bool ssub_overflow(int32_t x, int32_t y, int32_t* val) { | |
| 3895 int32_t v = | |
| 3896 static_cast<int32_t>(static_cast<uint32_t>(x) - static_cast<uint32_t>(y)); | |
| 3897 *val = v; | |
| 3898 return (((v ^ x) & (v ^ ~y)) >> 31) & 1; | |
| 3899 } | |
| 3900 | |
| 3901 | |
| 3902 TEST(RunInt32AddWithOverflowP) { | 3894 TEST(RunInt32AddWithOverflowP) { |
| 3903 int32_t actual_val = -1; | 3895 int32_t actual_val = -1; |
| 3904 RawMachineAssemblerTester<int32_t> m; | 3896 RawMachineAssemblerTester<int32_t> m; |
| 3905 Int32BinopTester bt(&m); | 3897 Int32BinopTester bt(&m); |
| 3906 Node* add = m.Int32AddWithOverflow(bt.param0, bt.param1); | 3898 Node* add = m.Int32AddWithOverflow(bt.param0, bt.param1); |
| 3907 Node* val = m.Projection(0, add); | 3899 Node* val = m.Projection(0, add); |
| 3908 Node* ovf = m.Projection(1, add); | 3900 Node* ovf = m.Projection(1, add); |
| 3909 m.StoreToPointer(&actual_val, kMachineWord32, val); | 3901 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 3910 bt.AddReturn(ovf); | 3902 bt.AddReturn(ovf); |
| 3911 FOR_INT32_INPUTS(i) { | 3903 FOR_INT32_INPUTS(i) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3980 FOR_UINT32_INPUTS(i) { | 3972 FOR_UINT32_INPUTS(i) { |
| 3981 FOR_UINT32_INPUTS(j) { | 3973 FOR_UINT32_INPUTS(j) { |
| 3982 int32_t expected; | 3974 int32_t expected; |
| 3983 if (sadd_overflow(*i, *j, &expected)) expected = constant; | 3975 if (sadd_overflow(*i, *j, &expected)) expected = constant; |
| 3984 CHECK_EQ(expected, bt.call(*i, *j)); | 3976 CHECK_EQ(expected, bt.call(*i, *j)); |
| 3985 } | 3977 } |
| 3986 } | 3978 } |
| 3987 } | 3979 } |
| 3988 | 3980 |
| 3989 | 3981 |
| 3982 static bool uadd_overflow(uint32_t x, uint32_t y, uint32_t* val) { |
| 3983 uint32_t v = x + y; |
| 3984 *val = v; |
| 3985 return (((x & y) | ((x | y) & ~v)) >> 31) & 1; |
| 3986 } |
| 3987 |
| 3988 |
| 3989 TEST(RunUint32AddWithOverflowP) { |
| 3990 uint32_t actual_val = -1; |
| 3991 RawMachineAssemblerTester<int32_t> m; |
| 3992 Int32BinopTester bt(&m); |
| 3993 Node* add = m.Uint32AddWithOverflow(bt.param0, bt.param1); |
| 3994 Node* val = m.Projection(0, add); |
| 3995 Node* ovf = m.Projection(1, add); |
| 3996 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 3997 bt.AddReturn(ovf); |
| 3998 FOR_UINT32_INPUTS(i) { |
| 3999 FOR_UINT32_INPUTS(j) { |
| 4000 uint32_t expected_val; |
| 4001 int expected_ovf = uadd_overflow(*i, *j, &expected_val); |
| 4002 CHECK_EQ(expected_ovf, bt.call(*i, *j)); |
| 4003 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4004 } |
| 4005 } |
| 4006 } |
| 4007 |
| 4008 |
| 4009 TEST(RunUint32AddWithOverflowImm) { |
| 4010 uint32_t actual_val = -1, expected_val = 0; |
| 4011 FOR_UINT32_INPUTS(i) { |
| 4012 { |
| 4013 RawMachineAssemblerTester<int32_t> m(kMachineWord32); |
| 4014 Node* add = m.Uint32AddWithOverflow(m.Int32Constant(*i), m.Parameter(0)); |
| 4015 Node* val = m.Projection(0, add); |
| 4016 Node* ovf = m.Projection(1, add); |
| 4017 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 4018 m.Return(ovf); |
| 4019 FOR_UINT32_INPUTS(j) { |
| 4020 int expected_ovf = uadd_overflow(*i, *j, &expected_val); |
| 4021 CHECK_EQ(expected_ovf, m.Call(*j)); |
| 4022 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4023 } |
| 4024 } |
| 4025 { |
| 4026 RawMachineAssemblerTester<int32_t> m(kMachineWord32); |
| 4027 Node* add = m.Uint32AddWithOverflow(m.Parameter(0), m.Int32Constant(*i)); |
| 4028 Node* val = m.Projection(0, add); |
| 4029 Node* ovf = m.Projection(1, add); |
| 4030 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 4031 m.Return(ovf); |
| 4032 FOR_UINT32_INPUTS(j) { |
| 4033 int expected_ovf = uadd_overflow(*j, *i, &expected_val); |
| 4034 CHECK_EQ(expected_ovf, m.Call(*j)); |
| 4035 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4036 } |
| 4037 } |
| 4038 FOR_UINT32_INPUTS(j) { |
| 4039 RawMachineAssemblerTester<int32_t> m; |
| 4040 Node* add = |
| 4041 m.Uint32AddWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j)); |
| 4042 Node* val = m.Projection(0, add); |
| 4043 Node* ovf = m.Projection(1, add); |
| 4044 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 4045 m.Return(ovf); |
| 4046 int expected_ovf = uadd_overflow(*i, *j, &expected_val); |
| 4047 CHECK_EQ(expected_ovf, m.Call()); |
| 4048 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4049 } |
| 4050 } |
| 4051 } |
| 4052 |
| 4053 |
| 4054 TEST(RunUint32AddWithOverflowInBranchP) { |
| 4055 int constant = 911999; |
| 4056 MLabel blocka, blockb; |
| 4057 RawMachineAssemblerTester<int32_t> m; |
| 4058 Int32BinopTester bt(&m); |
| 4059 Node* sub = m.Uint32AddWithOverflow(bt.param0, bt.param1); |
| 4060 Node* ovf = m.Projection(1, sub); |
| 4061 m.Branch(ovf, &blocka, &blockb); |
| 4062 m.Bind(&blocka); |
| 4063 bt.AddReturn(m.Int32Constant(constant)); |
| 4064 m.Bind(&blockb); |
| 4065 Node* val = m.Projection(0, sub); |
| 4066 bt.AddReturn(val); |
| 4067 FOR_UINT32_INPUTS(i) { |
| 4068 FOR_UINT32_INPUTS(j) { |
| 4069 uint32_t expected; |
| 4070 if (uadd_overflow(*i, *j, &expected)) expected = constant; |
| 4071 CHECK_EQ(expected, bt.call(*i, *j)); |
| 4072 } |
| 4073 } |
| 4074 } |
| 4075 |
| 4076 |
| 4077 static bool ssub_overflow(int32_t x, int32_t y, int32_t* val) { |
| 4078 int32_t v = |
| 4079 static_cast<int32_t>(static_cast<uint32_t>(x) - static_cast<uint32_t>(y)); |
| 4080 *val = v; |
| 4081 return (((v ^ x) & (v ^ ~y)) >> 31) & 1; |
| 4082 } |
| 4083 |
| 4084 |
| 3990 TEST(RunInt32SubWithOverflowP) { | 4085 TEST(RunInt32SubWithOverflowP) { |
| 3991 int32_t actual_val = -1; | 4086 int32_t actual_val = -1; |
| 3992 RawMachineAssemblerTester<int32_t> m; | 4087 RawMachineAssemblerTester<int32_t> m; |
| 3993 Int32BinopTester bt(&m); | 4088 Int32BinopTester bt(&m); |
| 3994 Node* add = m.Int32SubWithOverflow(bt.param0, bt.param1); | 4089 Node* add = m.Int32SubWithOverflow(bt.param0, bt.param1); |
| 3995 Node* val = m.Projection(0, add); | 4090 Node* val = m.Projection(0, add); |
| 3996 Node* ovf = m.Projection(1, add); | 4091 Node* ovf = m.Projection(1, add); |
| 3997 m.StoreToPointer(&actual_val, kMachineWord32, val); | 4092 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 3998 bt.AddReturn(ovf); | 4093 bt.AddReturn(ovf); |
| 3999 FOR_INT32_INPUTS(i) { | 4094 FOR_INT32_INPUTS(i) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4067 bt.AddReturn(val); | 4162 bt.AddReturn(val); |
| 4068 FOR_UINT32_INPUTS(i) { | 4163 FOR_UINT32_INPUTS(i) { |
| 4069 FOR_UINT32_INPUTS(j) { | 4164 FOR_UINT32_INPUTS(j) { |
| 4070 int32_t expected; | 4165 int32_t expected; |
| 4071 if (ssub_overflow(*i, *j, &expected)) expected = constant; | 4166 if (ssub_overflow(*i, *j, &expected)) expected = constant; |
| 4072 CHECK_EQ(expected, bt.call(*i, *j)); | 4167 CHECK_EQ(expected, bt.call(*i, *j)); |
| 4073 } | 4168 } |
| 4074 } | 4169 } |
| 4075 } | 4170 } |
| 4076 | 4171 |
| 4172 |
| 4173 static bool usub_overflow(uint32_t x, uint32_t y, uint32_t* val) { |
| 4174 uint32_t v = x - y; |
| 4175 *val = v; |
| 4176 return (((~x & y) | ((~x | y) & v)) >> 31) & 1; |
| 4177 } |
| 4178 |
| 4179 |
| 4180 TEST(RunUint32SubWithOverflowP) { |
| 4181 uint32_t actual_val = -1; |
| 4182 RawMachineAssemblerTester<int32_t> m; |
| 4183 Int32BinopTester bt(&m); |
| 4184 Node* sub = m.Uint32SubWithOverflow(bt.param0, bt.param1); |
| 4185 Node* val = m.Projection(0, sub); |
| 4186 Node* ovf = m.Projection(1, sub); |
| 4187 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 4188 bt.AddReturn(ovf); |
| 4189 FOR_UINT32_INPUTS(i) { |
| 4190 FOR_UINT32_INPUTS(j) { |
| 4191 uint32_t expected_val; |
| 4192 int expected_ovf = usub_overflow(*i, *j, &expected_val); |
| 4193 CHECK_EQ(expected_ovf, bt.call(*i, *j)); |
| 4194 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4195 } |
| 4196 } |
| 4197 } |
| 4198 |
| 4199 |
| 4200 TEST(RunUint32SubWithOverflowImm) { |
| 4201 uint32_t actual_val = -1, expected_val = 0; |
| 4202 FOR_UINT32_INPUTS(i) { |
| 4203 { |
| 4204 RawMachineAssemblerTester<int32_t> m(kMachineWord32); |
| 4205 Node* add = m.Uint32SubWithOverflow(m.Int32Constant(*i), m.Parameter(0)); |
| 4206 Node* val = m.Projection(0, add); |
| 4207 Node* ovf = m.Projection(1, add); |
| 4208 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 4209 m.Return(ovf); |
| 4210 FOR_UINT32_INPUTS(j) { |
| 4211 int expected_ovf = usub_overflow(*i, *j, &expected_val); |
| 4212 CHECK_EQ(expected_ovf, m.Call(*j)); |
| 4213 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4214 } |
| 4215 } |
| 4216 { |
| 4217 RawMachineAssemblerTester<int32_t> m(kMachineWord32); |
| 4218 Node* add = m.Uint32SubWithOverflow(m.Parameter(0), m.Int32Constant(*i)); |
| 4219 Node* val = m.Projection(0, add); |
| 4220 Node* ovf = m.Projection(1, add); |
| 4221 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 4222 m.Return(ovf); |
| 4223 FOR_UINT32_INPUTS(j) { |
| 4224 int expected_ovf = usub_overflow(*j, *i, &expected_val); |
| 4225 CHECK_EQ(expected_ovf, m.Call(*j)); |
| 4226 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4227 } |
| 4228 } |
| 4229 FOR_UINT32_INPUTS(j) { |
| 4230 RawMachineAssemblerTester<int32_t> m; |
| 4231 Node* add = |
| 4232 m.Uint32SubWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j)); |
| 4233 Node* val = m.Projection(0, add); |
| 4234 Node* ovf = m.Projection(1, add); |
| 4235 m.StoreToPointer(&actual_val, kMachineWord32, val); |
| 4236 m.Return(ovf); |
| 4237 int expected_ovf = usub_overflow(*i, *j, &expected_val); |
| 4238 CHECK_EQ(expected_ovf, m.Call()); |
| 4239 CHECK_EQ(static_cast<int>(expected_val), static_cast<int>(actual_val)); |
| 4240 } |
| 4241 } |
| 4242 } |
| 4243 |
| 4244 |
| 4245 TEST(RunUint32SubWithOverflowInBranchP) { |
| 4246 int constant = 911999; |
| 4247 MLabel blocka, blockb; |
| 4248 RawMachineAssemblerTester<int32_t> m; |
| 4249 Int32BinopTester bt(&m); |
| 4250 Node* sub = m.Uint32SubWithOverflow(bt.param0, bt.param1); |
| 4251 Node* ovf = m.Projection(1, sub); |
| 4252 m.Branch(ovf, &blocka, &blockb); |
| 4253 m.Bind(&blocka); |
| 4254 bt.AddReturn(m.Int32Constant(constant)); |
| 4255 m.Bind(&blockb); |
| 4256 Node* val = m.Projection(0, sub); |
| 4257 bt.AddReturn(val); |
| 4258 FOR_UINT32_INPUTS(i) { |
| 4259 FOR_UINT32_INPUTS(j) { |
| 4260 uint32_t expected; |
| 4261 if (usub_overflow(*i, *j, &expected)) expected = constant; |
| 4262 CHECK_EQ(expected, bt.call(*i, *j)); |
| 4263 } |
| 4264 } |
| 4265 } |
| 4266 |
| 4077 #endif // V8_TURBOFAN_TARGET | 4267 #endif // V8_TURBOFAN_TARGET |
| OLD | NEW |