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/bits.h" 6 #include "src/compiler/graph-unittest.h" 7 #include "src/compiler/js-graph.h" 8 #include "src/compiler/machine-operator-reducer.h" 9 #include "src/compiler/typer.h" 10 11 namespace v8 { 12 namespace internal { 13 namespace compiler { 14 15 class MachineOperatorReducerTest : public GraphTest { 16 public: 17 explicit MachineOperatorReducerTest(int num_parameters = 2) 18 : GraphTest(num_parameters) {} 19 20 protected: 21 Reduction Reduce(Node* node) { 22 Typer typer(zone()); 23 JSOperatorBuilder javascript(zone()); 24 JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine_); 25 MachineOperatorReducer reducer(&jsgraph); 26 return reducer.Reduce(node); 27 } 28 29 MachineOperatorBuilder* machine() { return &machine_; } 30 31 private: 32 MachineOperatorBuilder machine_; 33 }; 34 35 36 template <typename T> 37 class MachineOperatorReducerTestWithParam 38 : public MachineOperatorReducerTest, 39 public ::testing::WithParamInterface<T> { 40 public: 41 explicit MachineOperatorReducerTestWithParam(int num_parameters = 2) 42 : MachineOperatorReducerTest(num_parameters) {} 43 virtual ~MachineOperatorReducerTestWithParam() {} 44 }; 45 46 47 namespace { 48 49 static const float kFloat32Values[] = { 50 -std::numeric_limits<float>::infinity(), -2.70497e+38f, -1.4698e+37f, 51 -1.22813e+35f, -1.20555e+35f, -1.34584e+34f, 52 -1.0079e+32f, -6.49364e+26f, -3.06077e+25f, 53 -1.46821e+25f, -1.17658e+23f, -1.9617e+22f, 54 -2.7357e+20f, -1.48708e+13f, -1.89633e+12f, 55 -4.66622e+11f, -2.22581e+11f, -1.45381e+10f, 56 -1.3956e+09f, -1.32951e+09f, -1.30721e+09f, 57 -1.19756e+09f, -9.26822e+08f, -6.35647e+08f, 58 -4.00037e+08f, -1.81227e+08f, -5.09256e+07f, 59 -964300.0f, -192446.0f, -28455.0f, 60 -27194.0f, -26401.0f, -20575.0f, 61 -17069.0f, -9167.0f, -960.178f, 62 -113.0f, -62.0f, -15.0f, 63 -7.0f, -0.0256635f, -4.60374e-07f, 64 -3.63759e-10f, -4.30175e-14f, -5.27385e-15f, 65 -1.48084e-15f, -1.05755e-19f, -3.2995e-21f, 66 -1.67354e-23f, -1.11885e-23f, -1.78506e-30f, 67 -5.07594e-31f, -3.65799e-31f, -1.43718e-34f, 68 -1.27126e-38f, -0.0f, 0.0f, 69 1.17549e-38f, 1.56657e-37f, 4.08512e-29f, 70 3.31357e-28f, 6.25073e-22f, 4.1723e-13f, 71 1.44343e-09f, 5.27004e-08f, 9.48298e-08f, 72 5.57888e-07f, 4.89988e-05f, 0.244326f, 73 12.4895f, 19.0f, 47.0f, 74 106.0f, 538.324f, 564.536f, 75 819.124f, 7048.0f, 12611.0f, 76 19878.0f, 20309.0f, 797056.0f, 77 1.77219e+09f, 1.51116e+11f, 4.18193e+13f, 78 3.59167e+16f, 3.38211e+19f, 2.67488e+20f, 79 1.78831e+21f, 9.20914e+21f, 8.35654e+23f, 80 1.4495e+24f, 5.94015e+25f, 4.43608e+30f, 81 2.44502e+33f, 2.61152e+33f, 1.38178e+37f, 82 1.71306e+37f, 3.31899e+38f, 3.40282e+38f, 83 std::numeric_limits<float>::infinity()}; 84 85 86 static const double kFloat64Values[] = { 87 -V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212, 88 -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100, 89 -1.67813e+72, -2.3382e+55, -3.179e+30, -1.441e+09, -1.0647e+09, 90 -7.99361e+08, -5.77375e+08, -2.20984e+08, -32757, -13171, 91 -9970, -3984, -107, -105, -92, 92 -77, -61, -0.000208163, -1.86685e-06, -1.17296e-10, 93 -9.26358e-11, -5.08004e-60, -1.74753e-65, -1.06561e-71, -5.67879e-79, 94 -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263, 95 -4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278, -2.03855e-282, 96 -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0, 0.0, 97 2.22507e-308, 1.30127e-270, 7.62898e-260, 4.00313e-249, 3.16829e-233, 98 1.85244e-228, 2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94, 99 1.35292e-90, 2.85394e-83, 1.78323e-77, 5.4967e-57, 1.03207e-25, 100 4.57401e-25, 1.58738e-05, 2, 125, 2310, 101 9636, 14802, 17168, 28945, 29305, 102 4.81336e+07, 1.41207e+08, 4.65962e+08, 1.40499e+09, 2.12648e+09, 103 8.80006e+30, 1.4446e+45, 1.12164e+54, 2.48188e+89, 6.71121e+102, 104 3.074e+112, 4.9699e+152, 5.58383e+166, 4.30654e+172, 7.08824e+185, 105 9.6586e+214, 2.028e+223, 6.63277e+243, 1.56192e+261, 1.23202e+269, 106 5.72883e+289, 8.5798e+290, 1.40256e+294, 1.79769e+308, V8_INFINITY}; 107 108 109 static const int32_t kInt32Values[] = { 110 -2147483647 - 1, -1914954528, -1698749618, -1578693386, -1577976073, 111 -1573998034, -1529085059, -1499540537, -1299205097, -1090814845, 112 -938186388, -806828902, -750927650, -520676892, -513661538, 113 -453036354, -433622833, -282638793, -28375, -27788, 114 -22770, -18806, -14173, -11956, -11200, 115 -10212, -8160, -3751, -2758, -1522, 116 -121, -120, -118, -117, -106, 117 -84, -80, -74, -59, -52, 118 -48, -39, -35, -17, -11, 119 -10, -9, -7, -5, 0, 120 9, 12, 17, 23, 29, 121 31, 33, 35, 40, 47, 122 55, 56, 62, 64, 67, 123 68, 69, 74, 79, 84, 124 89, 90, 97, 104, 118, 125 124, 126, 127, 7278, 17787, 126 24136, 24202, 25570, 26680, 30242, 127 32399, 420886487, 642166225, 821912648, 822577803, 128 851385718, 1212241078, 1411419304, 1589626102, 1596437184, 129 1876245816, 1954730266, 2008792749, 2045320228, 2147483647}; 130 131 132 static const int64_t kInt64Values[] = { 133 V8_INT64_C(-9223372036854775807) - 1, V8_INT64_C(-8974392461363618006), 134 V8_INT64_C(-8874367046689588135), V8_INT64_C(-8269197512118230839), 135 V8_INT64_C(-8146091527100606733), V8_INT64_C(-7550917981466150848), 136 V8_INT64_C(-7216590251577894337), V8_INT64_C(-6464086891160048440), 137 V8_INT64_C(-6365616494908257190), V8_INT64_C(-6305630541365849726), 138 V8_INT64_C(-5982222642272245453), V8_INT64_C(-5510103099058504169), 139 V8_INT64_C(-5496838675802432701), V8_INT64_C(-4047626578868642657), 140 V8_INT64_C(-4033755046900164544), V8_INT64_C(-3554299241457877041), 141 V8_INT64_C(-2482258764588614470), V8_INT64_C(-1688515425526875335), 142 V8_INT64_C(-924784137176548532), V8_INT64_C(-725316567157391307), 143 V8_INT64_C(-439022654781092241), V8_INT64_C(-105545757668917080), 144 V8_INT64_C(-2088319373), V8_INT64_C(-2073699916), 145 V8_INT64_C(-1844949911), V8_INT64_C(-1831090548), 146 V8_INT64_C(-1756711933), V8_INT64_C(-1559409497), 147 V8_INT64_C(-1281179700), V8_INT64_C(-1211513985), 148 V8_INT64_C(-1182371520), V8_INT64_C(-785934753), 149 V8_INT64_C(-767480697), V8_INT64_C(-705745662), 150 V8_INT64_C(-514362436), V8_INT64_C(-459916580), 151 V8_INT64_C(-312328082), V8_INT64_C(-302949707), 152 V8_INT64_C(-285499304), V8_INT64_C(-125701262), 153 V8_INT64_C(-95139843), V8_INT64_C(-32768), 154 V8_INT64_C(-27542), V8_INT64_C(-23600), 155 V8_INT64_C(-18582), V8_INT64_C(-17770), 156 V8_INT64_C(-9086), V8_INT64_C(-9010), 157 V8_INT64_C(-8244), V8_INT64_C(-2890), 158 V8_INT64_C(-103), V8_INT64_C(-34), 159 V8_INT64_C(-27), V8_INT64_C(-25), 160 V8_INT64_C(-9), V8_INT64_C(-7), 161 V8_INT64_C(0), V8_INT64_C(2), 162 V8_INT64_C(38), V8_INT64_C(58), 163 V8_INT64_C(65), V8_INT64_C(93), 164 V8_INT64_C(111), V8_INT64_C(1003), 165 V8_INT64_C(1267), V8_INT64_C(12797), 166 V8_INT64_C(23122), V8_INT64_C(28200), 167 V8_INT64_C(30888), V8_INT64_C(42648848), 168 V8_INT64_C(116836693), V8_INT64_C(263003643), 169 V8_INT64_C(571039860), V8_INT64_C(1079398689), 170 V8_INT64_C(1145196402), V8_INT64_C(1184846321), 171 V8_INT64_C(1758281648), V8_INT64_C(1859991374), 172 V8_INT64_C(1960251588), V8_INT64_C(2042443199), 173 V8_INT64_C(296220586027987448), V8_INT64_C(1015494173071134726), 174 V8_INT64_C(1151237951914455318), V8_INT64_C(1331941174616854174), 175 V8_INT64_C(2022020418667972654), V8_INT64_C(2450251424374977035), 176 V8_INT64_C(3668393562685561486), V8_INT64_C(4858229301215502171), 177 V8_INT64_C(4919426235170669383), V8_INT64_C(5034286595330341762), 178 V8_INT64_C(5055797915536941182), V8_INT64_C(6072389716149252074), 179 V8_INT64_C(6185309910199801210), V8_INT64_C(6297328311011094138), 180 V8_INT64_C(6932372858072165827), V8_INT64_C(8483640924987737210), 181 V8_INT64_C(8663764179455849203), V8_INT64_C(8877197042645298254), 182 V8_INT64_C(8901543506779157333), V8_INT64_C(9223372036854775807)}; 183 184 185 static const uint32_t kUint32Values[] = { 186 0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8, 0xcc0de5bf, 187 0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc, 0x11223344, 188 0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc, 0x002b3b4c, 189 0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761, 0x7fffff00, 190 0x761c4761, 0x80000000, 0x88888888, 0xa0000000, 0xdddddddd, 0xe0000000, 191 0xeeeeeeee, 0xfffffffd, 0xf0000000, 0x007fffff, 0x003fffff, 0x001fffff, 192 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff, 193 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff}; 194 195 } // namespace 196 197 198 // ----------------------------------------------------------------------------- 199 // Unary operators 200 201 202 namespace { 203 204 struct UnaryOperator { 205 const Operator* (MachineOperatorBuilder::*constructor)(); 206 const char* constructor_name; 207 }; 208 209 210 std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) { 211 return os << unop.constructor_name; 212 } 213 214 215 static const UnaryOperator kUnaryOperators[] = { 216 {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"}, 217 {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"}, 218 {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"}, 219 {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"}, 220 {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"}, 221 {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"}, 222 {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"}, 223 {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}}; 224 225 } // namespace 226 227 228 typedef MachineOperatorReducerTestWithParam<UnaryOperator> 229 MachineUnaryOperatorReducerTest; 230 231 232 TEST_P(MachineUnaryOperatorReducerTest, Parameter) { 233 const UnaryOperator unop = GetParam(); 234 Reduction reduction = 235 Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0))); 236 EXPECT_FALSE(reduction.Changed()); 237 } 238 239 240 INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest, 241 MachineUnaryOperatorReducerTest, 242 ::testing::ValuesIn(kUnaryOperators)); 243 244 245 // ----------------------------------------------------------------------------- 246 // ChangeFloat64ToFloat32 247 248 249 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) { 250 TRACED_FOREACH(float, x, kFloat32Values) { 251 Reduction reduction = Reduce(graph()->NewNode( 252 machine()->ChangeFloat32ToFloat64(), Float32Constant(x))); 253 ASSERT_TRUE(reduction.Changed()); 254 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(x)); 255 } 256 } 257 258 259 // ----------------------------------------------------------------------------- 260 // ChangeFloat64ToInt32 261 262 263 TEST_F(MachineOperatorReducerTest, 264 ChangeFloat64ToInt32WithChangeInt32ToFloat64) { 265 Node* value = Parameter(0); 266 Reduction reduction = Reduce(graph()->NewNode( 267 machine()->ChangeFloat64ToInt32(), 268 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value))); 269 ASSERT_TRUE(reduction.Changed()); 270 EXPECT_EQ(value, reduction.replacement()); 271 } 272 273 274 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) { 275 TRACED_FOREACH(int32_t, x, kInt32Values) { 276 Reduction reduction = Reduce(graph()->NewNode( 277 machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x)))); 278 ASSERT_TRUE(reduction.Changed()); 279 EXPECT_THAT(reduction.replacement(), IsInt32Constant(x)); 280 } 281 } 282 283 284 // ----------------------------------------------------------------------------- 285 // ChangeFloat64ToUint32 286 287 288 TEST_F(MachineOperatorReducerTest, 289 ChangeFloat64ToUint32WithChangeUint32ToFloat64) { 290 Node* value = Parameter(0); 291 Reduction reduction = Reduce(graph()->NewNode( 292 machine()->ChangeFloat64ToUint32(), 293 graph()->NewNode(machine()->ChangeUint32ToFloat64(), value))); 294 ASSERT_TRUE(reduction.Changed()); 295 EXPECT_EQ(value, reduction.replacement()); 296 } 297 298 299 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) { 300 TRACED_FOREACH(uint32_t, x, kUint32Values) { 301 Reduction reduction = Reduce(graph()->NewNode( 302 machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x)))); 303 ASSERT_TRUE(reduction.Changed()); 304 EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x))); 305 } 306 } 307 308 309 // ----------------------------------------------------------------------------- 310 // ChangeInt32ToFloat64 311 312 313 TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) { 314 TRACED_FOREACH(int32_t, x, kInt32Values) { 315 Reduction reduction = Reduce( 316 graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x))); 317 ASSERT_TRUE(reduction.Changed()); 318 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(FastI2D(x))); 319 } 320 } 321 322 323 // ----------------------------------------------------------------------------- 324 // ChangeInt32ToInt64 325 326 327 TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) { 328 TRACED_FOREACH(int32_t, x, kInt32Values) { 329 Reduction reduction = Reduce( 330 graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x))); 331 ASSERT_TRUE(reduction.Changed()); 332 EXPECT_THAT(reduction.replacement(), IsInt64Constant(x)); 333 } 334 } 335 336 337 // ----------------------------------------------------------------------------- 338 // ChangeUint32ToFloat64 339 340 341 TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) { 342 TRACED_FOREACH(uint32_t, x, kUint32Values) { 343 Reduction reduction = 344 Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(), 345 Int32Constant(bit_cast<int32_t>(x)))); 346 ASSERT_TRUE(reduction.Changed()); 347 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(FastUI2D(x))); 348 } 349 } 350 351 352 // ----------------------------------------------------------------------------- 353 // ChangeUint32ToUint64 354 355 356 TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) { 357 TRACED_FOREACH(uint32_t, x, kUint32Values) { 358 Reduction reduction = 359 Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(), 360 Int32Constant(bit_cast<int32_t>(x)))); 361 ASSERT_TRUE(reduction.Changed()); 362 EXPECT_THAT(reduction.replacement(), 363 IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x)))); 364 } 365 } 366 367 368 // ----------------------------------------------------------------------------- 369 // TruncateFloat64ToFloat32 370 371 372 TEST_F(MachineOperatorReducerTest, 373 TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) { 374 Node* value = Parameter(0); 375 Reduction reduction = Reduce(graph()->NewNode( 376 machine()->TruncateFloat64ToFloat32(), 377 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value))); 378 ASSERT_TRUE(reduction.Changed()); 379 EXPECT_EQ(value, reduction.replacement()); 380 } 381 382 383 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) { 384 TRACED_FOREACH(double, x, kFloat64Values) { 385 Reduction reduction = Reduce(graph()->NewNode( 386 machine()->TruncateFloat64ToFloat32(), Float64Constant(x))); 387 ASSERT_TRUE(reduction.Changed()); 388 EXPECT_THAT(reduction.replacement(), IsFloat32Constant(DoubleToFloat32(x))); 389 } 390 } 391 392 393 // ----------------------------------------------------------------------------- 394 // TruncateFloat64ToInt32 395 396 397 TEST_F(MachineOperatorReducerTest, 398 TruncateFloat64ToInt32WithChangeInt32ToFloat64) { 399 Node* value = Parameter(0); 400 Reduction reduction = Reduce(graph()->NewNode( 401 machine()->TruncateFloat64ToInt32(), 402 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value))); 403 ASSERT_TRUE(reduction.Changed()); 404 EXPECT_EQ(value, reduction.replacement()); 405 } 406 407 408 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) { 409 TRACED_FOREACH(double, x, kFloat64Values) { 410 Reduction reduction = Reduce(graph()->NewNode( 411 machine()->TruncateFloat64ToInt32(), Float64Constant(x))); 412 ASSERT_TRUE(reduction.Changed()); 413 EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x))); 414 } 415 } 416 417 418 // ----------------------------------------------------------------------------- 419 // TruncateInt64ToInt32 420 421 422 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) { 423 Node* value = Parameter(0); 424 Reduction reduction = Reduce(graph()->NewNode( 425 machine()->TruncateInt64ToInt32(), 426 graph()->NewNode(machine()->ChangeInt32ToInt64(), value))); 427 ASSERT_TRUE(reduction.Changed()); 428 EXPECT_EQ(value, reduction.replacement()); 429 } 430 431 432 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) { 433 TRACED_FOREACH(int64_t, x, kInt64Values) { 434 Reduction reduction = Reduce( 435 graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x))); 436 ASSERT_TRUE(reduction.Changed()); 437 EXPECT_THAT(reduction.replacement(), 438 IsInt32Constant(bit_cast<int32_t>( 439 static_cast<uint32_t>(bit_cast<uint64_t>(x))))); 440 } 441 } 442 443 444 // ----------------------------------------------------------------------------- 445 // Word32Ror 446 447 448 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) { 449 Node* value = Parameter(0); 450 Node* shift = Parameter(1); 451 Node* shl = graph()->NewNode(machine()->Word32Shl(), value, shift); 452 Node* shr = graph()->NewNode( 453 machine()->Word32Shr(), value, 454 graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift)); 455 456 // (x << y) | (x >> (32 - y)) => x ror y 457 Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr); 458 Reduction reduction1 = Reduce(node1); 459 EXPECT_TRUE(reduction1.Changed()); 460 EXPECT_EQ(reduction1.replacement(), node1); 461 EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, shift)); 462 463 // (x >> (32 - y)) | (x << y) => x ror y 464 Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl); 465 Reduction reduction2 = Reduce(node2); 466 EXPECT_TRUE(reduction2.Changed()); 467 EXPECT_EQ(reduction2.replacement(), node2); 468 EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, shift)); 469 } 470 471 472 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) { 473 Node* value = Parameter(0); 474 TRACED_FORRANGE(int32_t, k, 0, 31) { 475 Node* shl = 476 graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k)); 477 Node* shr = 478 graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k)); 479 480 // (x << K) | (x >> ((32 - K) - y)) => x ror K 481 Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr); 482 Reduction reduction1 = Reduce(node1); 483 EXPECT_TRUE(reduction1.Changed()); 484 EXPECT_EQ(reduction1.replacement(), node1); 485 EXPECT_THAT(reduction1.replacement(), 486 IsWord32Ror(value, IsInt32Constant(k))); 487 488 // (x >> (32 - K)) | (x << K) => x ror K 489 Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl); 490 Reduction reduction2 = Reduce(node2); 491 EXPECT_TRUE(reduction2.Changed()); 492 EXPECT_EQ(reduction2.replacement(), node2); 493 EXPECT_THAT(reduction2.replacement(), 494 IsWord32Ror(value, IsInt32Constant(k))); 495 } 496 } 497 498 499 TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) { 500 Node* value = Parameter(0); 501 Node* node = 502 graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0)); 503 Reduction reduction = Reduce(node); 504 EXPECT_TRUE(reduction.Changed()); 505 EXPECT_EQ(reduction.replacement(), value); 506 } 507 508 509 TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) { 510 TRACED_FOREACH(int32_t, x, kUint32Values) { 511 TRACED_FORRANGE(int32_t, y, 0, 31) { 512 Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x), 513 Int32Constant(y)); 514 Reduction reduction = Reduce(node); 515 EXPECT_TRUE(reduction.Changed()); 516 EXPECT_THAT(reduction.replacement(), 517 IsInt32Constant(base::bits::RotateRight32(x, y))); 518 } 519 } 520 } 521 522 523 // ----------------------------------------------------------------------------- 524 // Int32AddWithOverflow 525 526 527 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) { 528 Node* p0 = Parameter(0); 529 { 530 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), 531 Int32Constant(0), p0); 532 533 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); 534 ASSERT_TRUE(r.Changed()); 535 EXPECT_THAT(r.replacement(), IsInt32Constant(0)); 536 537 r = Reduce(graph()->NewNode(common()->Projection(0), add)); 538 ASSERT_TRUE(r.Changed()); 539 EXPECT_EQ(p0, r.replacement()); 540 } 541 { 542 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0, 543 Int32Constant(0)); 544 545 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); 546 ASSERT_TRUE(r.Changed()); 547 EXPECT_THAT(r.replacement(), IsInt32Constant(0)); 548 549 r = Reduce(graph()->NewNode(common()->Projection(0), add)); 550 ASSERT_TRUE(r.Changed()); 551 EXPECT_EQ(p0, r.replacement()); 552 } 553 } 554 555 556 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) { 557 TRACED_FOREACH(int32_t, x, kInt32Values) { 558 TRACED_FOREACH(int32_t, y, kInt32Values) { 559 int32_t z; 560 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), 561 Int32Constant(x), Int32Constant(y)); 562 563 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); 564 ASSERT_TRUE(r.Changed()); 565 EXPECT_THAT(r.replacement(), 566 IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z))); 567 568 r = Reduce(graph()->NewNode(common()->Projection(0), add)); 569 ASSERT_TRUE(r.Changed()); 570 EXPECT_THAT(r.replacement(), IsInt32Constant(z)); 571 } 572 } 573 } 574 575 576 // ----------------------------------------------------------------------------- 577 // Int32SubWithOverflow 578 579 580 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) { 581 Node* p0 = Parameter(0); 582 Node* add = 583 graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0)); 584 585 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); 586 ASSERT_TRUE(r.Changed()); 587 EXPECT_THAT(r.replacement(), IsInt32Constant(0)); 588 589 r = Reduce(graph()->NewNode(common()->Projection(0), add)); 590 ASSERT_TRUE(r.Changed()); 591 EXPECT_EQ(p0, r.replacement()); 592 } 593 594 595 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) { 596 TRACED_FOREACH(int32_t, x, kInt32Values) { 597 TRACED_FOREACH(int32_t, y, kInt32Values) { 598 int32_t z; 599 Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), 600 Int32Constant(x), Int32Constant(y)); 601 602 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); 603 ASSERT_TRUE(r.Changed()); 604 EXPECT_THAT(r.replacement(), 605 IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z))); 606 607 r = Reduce(graph()->NewNode(common()->Projection(0), add)); 608 ASSERT_TRUE(r.Changed()); 609 EXPECT_THAT(r.replacement(), IsInt32Constant(z)); 610 } 611 } 612 } 613 614 } // namespace compiler 615 } // namespace internal 616 } // namespace v8 617