1 //===- llvm/unittests/Transforms/Vectorize/VPlanTest.cpp - VPlan tests ----===// 2 // 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "../lib/Transforms/Vectorize/VPlan.h" 11 #include "../lib/Transforms/Vectorize/VPlanCFG.h" 12 #include "VPlanTestBase.h" 13 #include "llvm/ADT/DepthFirstIterator.h" 14 #include "llvm/ADT/PostOrderIterator.h" 15 #include "llvm/Analysis/VectorUtils.h" 16 #include "llvm/IR/Instruction.h" 17 #include "llvm/IR/Instructions.h" 18 #include "gtest/gtest.h" 19 #include <string> 20 21 namespace llvm { 22 namespace { 23 24 #define CHECK_ITERATOR(Range1, ...) \ 25 do { \ 26 std::vector<VPInstruction *> Tmp = {__VA_ARGS__}; \ 27 EXPECT_EQ((size_t)std::distance(Range1.begin(), Range1.end()), \ 28 Tmp.size()); \ 29 for (auto Pair : zip(Range1, make_range(Tmp.begin(), Tmp.end()))) \ 30 EXPECT_EQ(&std::get<0>(Pair), std::get<1>(Pair)); \ 31 } while (0) 32 33 TEST(VPInstructionTest, insertBefore) { 34 VPInstruction *I1 = new VPInstruction(0, {}); 35 VPInstruction *I2 = new VPInstruction(1, {}); 36 VPInstruction *I3 = new VPInstruction(2, {}); 37 38 VPBasicBlock VPBB1; 39 VPBB1.appendRecipe(I1); 40 41 I2->insertBefore(I1); 42 CHECK_ITERATOR(VPBB1, I2, I1); 43 44 I3->insertBefore(I2); 45 CHECK_ITERATOR(VPBB1, I3, I2, I1); 46 } 47 48 TEST(VPInstructionTest, eraseFromParent) { 49 VPInstruction *I1 = new VPInstruction(0, {}); 50 VPInstruction *I2 = new VPInstruction(1, {}); 51 VPInstruction *I3 = new VPInstruction(2, {}); 52 53 VPBasicBlock VPBB1; 54 VPBB1.appendRecipe(I1); 55 VPBB1.appendRecipe(I2); 56 VPBB1.appendRecipe(I3); 57 58 I2->eraseFromParent(); 59 CHECK_ITERATOR(VPBB1, I1, I3); 60 61 I1->eraseFromParent(); 62 CHECK_ITERATOR(VPBB1, I3); 63 64 I3->eraseFromParent(); 65 EXPECT_TRUE(VPBB1.empty()); 66 } 67 68 TEST(VPInstructionTest, moveAfter) { 69 VPInstruction *I1 = new VPInstruction(0, {}); 70 VPInstruction *I2 = new VPInstruction(1, {}); 71 VPInstruction *I3 = new VPInstruction(2, {}); 72 73 VPBasicBlock VPBB1; 74 VPBB1.appendRecipe(I1); 75 VPBB1.appendRecipe(I2); 76 VPBB1.appendRecipe(I3); 77 78 I1->moveAfter(I2); 79 80 CHECK_ITERATOR(VPBB1, I2, I1, I3); 81 82 VPInstruction *I4 = new VPInstruction(4, {}); 83 VPInstruction *I5 = new VPInstruction(5, {}); 84 VPBasicBlock VPBB2; 85 VPBB2.appendRecipe(I4); 86 VPBB2.appendRecipe(I5); 87 88 I3->moveAfter(I4); 89 90 CHECK_ITERATOR(VPBB1, I2, I1); 91 CHECK_ITERATOR(VPBB2, I4, I3, I5); 92 EXPECT_EQ(I3->getParent(), I4->getParent()); 93 } 94 95 TEST(VPInstructionTest, moveBefore) { 96 VPInstruction *I1 = new VPInstruction(0, {}); 97 VPInstruction *I2 = new VPInstruction(1, {}); 98 VPInstruction *I3 = new VPInstruction(2, {}); 99 100 VPBasicBlock VPBB1; 101 VPBB1.appendRecipe(I1); 102 VPBB1.appendRecipe(I2); 103 VPBB1.appendRecipe(I3); 104 105 I1->moveBefore(VPBB1, I3->getIterator()); 106 107 CHECK_ITERATOR(VPBB1, I2, I1, I3); 108 109 VPInstruction *I4 = new VPInstruction(4, {}); 110 VPInstruction *I5 = new VPInstruction(5, {}); 111 VPBasicBlock VPBB2; 112 VPBB2.appendRecipe(I4); 113 VPBB2.appendRecipe(I5); 114 115 I3->moveBefore(VPBB2, I4->getIterator()); 116 117 CHECK_ITERATOR(VPBB1, I2, I1); 118 CHECK_ITERATOR(VPBB2, I3, I4, I5); 119 EXPECT_EQ(I3->getParent(), I4->getParent()); 120 121 VPBasicBlock VPBB3; 122 123 I4->moveBefore(VPBB3, VPBB3.end()); 124 125 CHECK_ITERATOR(VPBB1, I2, I1); 126 CHECK_ITERATOR(VPBB2, I3, I5); 127 CHECK_ITERATOR(VPBB3, I4); 128 EXPECT_EQ(&VPBB3, I4->getParent()); 129 } 130 131 TEST(VPInstructionTest, setOperand) { 132 VPValue *VPV1 = new VPValue(); 133 VPValue *VPV2 = new VPValue(); 134 VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2}); 135 EXPECT_EQ(1u, VPV1->getNumUsers()); 136 EXPECT_EQ(I1, *VPV1->user_begin()); 137 EXPECT_EQ(1u, VPV2->getNumUsers()); 138 EXPECT_EQ(I1, *VPV2->user_begin()); 139 140 // Replace operand 0 (VPV1) with VPV3. 141 VPValue *VPV3 = new VPValue(); 142 I1->setOperand(0, VPV3); 143 EXPECT_EQ(0u, VPV1->getNumUsers()); 144 EXPECT_EQ(1u, VPV2->getNumUsers()); 145 EXPECT_EQ(I1, *VPV2->user_begin()); 146 EXPECT_EQ(1u, VPV3->getNumUsers()); 147 EXPECT_EQ(I1, *VPV3->user_begin()); 148 149 // Replace operand 1 (VPV2) with VPV3. 150 I1->setOperand(1, VPV3); 151 EXPECT_EQ(0u, VPV1->getNumUsers()); 152 EXPECT_EQ(0u, VPV2->getNumUsers()); 153 EXPECT_EQ(2u, VPV3->getNumUsers()); 154 EXPECT_EQ(I1, *VPV3->user_begin()); 155 EXPECT_EQ(I1, *std::next(VPV3->user_begin())); 156 157 // Replace operand 0 (VPV3) with VPV4. 158 VPValue *VPV4 = new VPValue(); 159 I1->setOperand(0, VPV4); 160 EXPECT_EQ(1u, VPV3->getNumUsers()); 161 EXPECT_EQ(I1, *VPV3->user_begin()); 162 EXPECT_EQ(I1, *VPV4->user_begin()); 163 164 // Replace operand 1 (VPV3) with VPV4. 165 I1->setOperand(1, VPV4); 166 EXPECT_EQ(0u, VPV3->getNumUsers()); 167 EXPECT_EQ(I1, *VPV4->user_begin()); 168 EXPECT_EQ(I1, *std::next(VPV4->user_begin())); 169 170 delete I1; 171 delete VPV1; 172 delete VPV2; 173 delete VPV3; 174 delete VPV4; 175 } 176 177 TEST(VPInstructionTest, replaceAllUsesWith) { 178 VPValue *VPV1 = new VPValue(); 179 VPValue *VPV2 = new VPValue(); 180 VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2}); 181 182 // Replace all uses of VPV1 with VPV3. 183 VPValue *VPV3 = new VPValue(); 184 VPV1->replaceAllUsesWith(VPV3); 185 EXPECT_EQ(VPV3, I1->getOperand(0)); 186 EXPECT_EQ(VPV2, I1->getOperand(1)); 187 EXPECT_EQ(0u, VPV1->getNumUsers()); 188 EXPECT_EQ(1u, VPV2->getNumUsers()); 189 EXPECT_EQ(I1, *VPV2->user_begin()); 190 EXPECT_EQ(1u, VPV3->getNumUsers()); 191 EXPECT_EQ(I1, *VPV3->user_begin()); 192 193 // Replace all uses of VPV2 with VPV3. 194 VPV2->replaceAllUsesWith(VPV3); 195 EXPECT_EQ(VPV3, I1->getOperand(0)); 196 EXPECT_EQ(VPV3, I1->getOperand(1)); 197 EXPECT_EQ(0u, VPV1->getNumUsers()); 198 EXPECT_EQ(0u, VPV2->getNumUsers()); 199 EXPECT_EQ(2u, VPV3->getNumUsers()); 200 EXPECT_EQ(I1, *VPV3->user_begin()); 201 202 // Replace all uses of VPV3 with VPV1. 203 VPV3->replaceAllUsesWith(VPV1); 204 EXPECT_EQ(VPV1, I1->getOperand(0)); 205 EXPECT_EQ(VPV1, I1->getOperand(1)); 206 EXPECT_EQ(2u, VPV1->getNumUsers()); 207 EXPECT_EQ(I1, *VPV1->user_begin()); 208 EXPECT_EQ(0u, VPV2->getNumUsers()); 209 EXPECT_EQ(0u, VPV3->getNumUsers()); 210 211 VPInstruction *I2 = new VPInstruction(0, {VPV1, VPV2}); 212 EXPECT_EQ(3u, VPV1->getNumUsers()); 213 VPV1->replaceAllUsesWith(VPV3); 214 EXPECT_EQ(3u, VPV3->getNumUsers()); 215 216 delete I1; 217 delete I2; 218 delete VPV1; 219 delete VPV2; 220 delete VPV3; 221 } 222 223 TEST(VPInstructionTest, releaseOperandsAtDeletion) { 224 VPValue *VPV1 = new VPValue(); 225 VPValue *VPV2 = new VPValue(); 226 VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2}); 227 228 EXPECT_EQ(1u, VPV1->getNumUsers()); 229 EXPECT_EQ(I1, *VPV1->user_begin()); 230 EXPECT_EQ(1u, VPV2->getNumUsers()); 231 EXPECT_EQ(I1, *VPV2->user_begin()); 232 233 delete I1; 234 235 EXPECT_EQ(0u, VPV1->getNumUsers()); 236 EXPECT_EQ(0u, VPV2->getNumUsers()); 237 238 delete VPV1; 239 delete VPV2; 240 } 241 242 using VPBasicBlockTest = VPlanTestBase; 243 244 TEST_F(VPBasicBlockTest, getPlan) { 245 { 246 VPlan &Plan = getPlan(); 247 VPBasicBlock *VPBB1 = Plan.getEntry(); 248 VPBasicBlock *VPBB2 = new VPBasicBlock(); 249 VPBasicBlock *VPBB3 = new VPBasicBlock(); 250 VPBasicBlock *VPBB4 = new VPBasicBlock(); 251 252 // VPBB1 253 // / \ 254 // VPBB2 VPBB3 255 // \ / 256 // VPBB4 257 VPBlockUtils::connectBlocks(VPBB1, VPBB2); 258 VPBlockUtils::connectBlocks(VPBB1, VPBB3); 259 VPBlockUtils::connectBlocks(VPBB2, VPBB4); 260 VPBlockUtils::connectBlocks(VPBB3, VPBB4); 261 VPBlockUtils::connectBlocks(VPBB4, Plan.getScalarHeader()); 262 263 EXPECT_EQ(&Plan, VPBB1->getPlan()); 264 EXPECT_EQ(&Plan, VPBB2->getPlan()); 265 EXPECT_EQ(&Plan, VPBB3->getPlan()); 266 EXPECT_EQ(&Plan, VPBB4->getPlan()); 267 } 268 269 { 270 VPlan &Plan = getPlan(); 271 VPBasicBlock *VPBB1 = Plan.getEntry(); 272 // VPBasicBlock is the entry into the VPlan, followed by a region. 273 VPBasicBlock *R1BB1 = new VPBasicBlock(); 274 VPBasicBlock *R1BB2 = new VPBasicBlock(); 275 VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1"); 276 VPBlockUtils::connectBlocks(R1BB1, R1BB2); 277 278 VPBlockUtils::connectBlocks(VPBB1, R1); 279 280 VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 281 282 EXPECT_EQ(&Plan, VPBB1->getPlan()); 283 EXPECT_EQ(&Plan, R1->getPlan()); 284 EXPECT_EQ(&Plan, R1BB1->getPlan()); 285 EXPECT_EQ(&Plan, R1BB2->getPlan()); 286 } 287 288 { 289 VPlan &Plan = getPlan(); 290 VPBasicBlock *R1BB1 = new VPBasicBlock(); 291 VPBasicBlock *R1BB2 = new VPBasicBlock(); 292 VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1"); 293 VPBlockUtils::connectBlocks(R1BB1, R1BB2); 294 295 VPBasicBlock *R2BB1 = new VPBasicBlock(); 296 VPBasicBlock *R2BB2 = new VPBasicBlock(); 297 VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2"); 298 VPBlockUtils::connectBlocks(R2BB1, R2BB2); 299 300 VPBasicBlock *VPBB1 = Plan.getEntry(); 301 VPBlockUtils::connectBlocks(VPBB1, R1); 302 VPBlockUtils::connectBlocks(VPBB1, R2); 303 304 VPBasicBlock *VPBB2 = new VPBasicBlock(); 305 VPBlockUtils::connectBlocks(R1, VPBB2); 306 VPBlockUtils::connectBlocks(R2, VPBB2); 307 308 VPBlockUtils::connectBlocks(R2, Plan.getScalarHeader()); 309 310 EXPECT_EQ(&Plan, VPBB1->getPlan()); 311 EXPECT_EQ(&Plan, R1->getPlan()); 312 EXPECT_EQ(&Plan, R1BB1->getPlan()); 313 EXPECT_EQ(&Plan, R1BB2->getPlan()); 314 EXPECT_EQ(&Plan, R2->getPlan()); 315 EXPECT_EQ(&Plan, R2BB1->getPlan()); 316 EXPECT_EQ(&Plan, R2BB2->getPlan()); 317 EXPECT_EQ(&Plan, VPBB2->getPlan()); 318 } 319 } 320 321 TEST_F(VPBasicBlockTest, TraversingIteratorTest) { 322 { 323 // VPBasicBlocks only 324 // VPBB1 325 // / \ 326 // VPBB2 VPBB3 327 // \ / 328 // VPBB4 329 // 330 VPlan &Plan = getPlan(); 331 VPBasicBlock *VPBB1 = Plan.getEntry(); 332 VPBasicBlock *VPBB2 = new VPBasicBlock(); 333 VPBasicBlock *VPBB3 = new VPBasicBlock(); 334 VPBasicBlock *VPBB4 = new VPBasicBlock(); 335 336 VPBlockUtils::connectBlocks(VPBB1, VPBB2); 337 VPBlockUtils::connectBlocks(VPBB1, VPBB3); 338 VPBlockUtils::connectBlocks(VPBB2, VPBB4); 339 VPBlockUtils::connectBlocks(VPBB3, VPBB4); 340 341 VPBlockDeepTraversalWrapper<const VPBlockBase *> Start(VPBB1); 342 SmallVector<const VPBlockBase *> FromIterator(depth_first(Start)); 343 EXPECT_EQ(4u, FromIterator.size()); 344 EXPECT_EQ(VPBB1, FromIterator[0]); 345 EXPECT_EQ(VPBB2, FromIterator[1]); 346 347 VPBlockUtils::connectBlocks(VPBB4, Plan.getScalarHeader()); 348 } 349 350 { 351 // 2 consecutive regions. 352 // VPBB0 353 // | 354 // R1 { 355 // \ 356 // R1BB1 357 // / \ |--| 358 // R1BB2 R1BB3 -| 359 // \ / 360 // R1BB4 361 // } 362 // | 363 // R2 { 364 // \ 365 // R2BB1 366 // | 367 // R2BB2 368 // 369 VPlan &Plan = getPlan(); 370 VPBasicBlock *VPBB0 = Plan.getEntry(); 371 VPBasicBlock *R1BB1 = new VPBasicBlock(); 372 VPBasicBlock *R1BB2 = new VPBasicBlock(); 373 VPBasicBlock *R1BB3 = new VPBasicBlock(); 374 VPBasicBlock *R1BB4 = new VPBasicBlock(); 375 VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB4, "R1"); 376 R1BB2->setParent(R1); 377 R1BB3->setParent(R1); 378 VPBlockUtils::connectBlocks(VPBB0, R1); 379 VPBlockUtils::connectBlocks(R1BB1, R1BB2); 380 VPBlockUtils::connectBlocks(R1BB1, R1BB3); 381 VPBlockUtils::connectBlocks(R1BB2, R1BB4); 382 VPBlockUtils::connectBlocks(R1BB3, R1BB4); 383 // Cycle. 384 VPBlockUtils::connectBlocks(R1BB3, R1BB3); 385 386 VPBasicBlock *R2BB1 = new VPBasicBlock(); 387 VPBasicBlock *R2BB2 = new VPBasicBlock(); 388 VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2"); 389 VPBlockUtils::connectBlocks(R2BB1, R2BB2); 390 VPBlockUtils::connectBlocks(R1, R2); 391 392 // Successors of R1. 393 SmallVector<const VPBlockBase *> FromIterator( 394 VPAllSuccessorsIterator<VPBlockBase *>(R1), 395 VPAllSuccessorsIterator<VPBlockBase *>::end(R1)); 396 EXPECT_EQ(1u, FromIterator.size()); 397 EXPECT_EQ(R1BB1, FromIterator[0]); 398 399 // Depth-first. 400 VPBlockDeepTraversalWrapper<VPBlockBase *> Start(R1); 401 FromIterator.clear(); 402 copy(df_begin(Start), df_end(Start), std::back_inserter(FromIterator)); 403 EXPECT_EQ(8u, FromIterator.size()); 404 EXPECT_EQ(R1, FromIterator[0]); 405 EXPECT_EQ(R1BB1, FromIterator[1]); 406 EXPECT_EQ(R1BB2, FromIterator[2]); 407 EXPECT_EQ(R1BB4, FromIterator[3]); 408 EXPECT_EQ(R2, FromIterator[4]); 409 EXPECT_EQ(R2BB1, FromIterator[5]); 410 EXPECT_EQ(R2BB2, FromIterator[6]); 411 EXPECT_EQ(R1BB3, FromIterator[7]); 412 413 // const VPBasicBlocks only. 414 FromIterator.clear(); 415 copy(VPBlockUtils::blocksOnly<const VPBasicBlock>(depth_first(Start)), 416 std::back_inserter(FromIterator)); 417 EXPECT_EQ(6u, FromIterator.size()); 418 EXPECT_EQ(R1BB1, FromIterator[0]); 419 EXPECT_EQ(R1BB2, FromIterator[1]); 420 EXPECT_EQ(R1BB4, FromIterator[2]); 421 EXPECT_EQ(R2BB1, FromIterator[3]); 422 EXPECT_EQ(R2BB2, FromIterator[4]); 423 EXPECT_EQ(R1BB3, FromIterator[5]); 424 425 // VPRegionBlocks only. 426 SmallVector<VPRegionBlock *> FromIteratorVPRegion( 427 VPBlockUtils::blocksOnly<VPRegionBlock>(depth_first(Start))); 428 EXPECT_EQ(2u, FromIteratorVPRegion.size()); 429 EXPECT_EQ(R1, FromIteratorVPRegion[0]); 430 EXPECT_EQ(R2, FromIteratorVPRegion[1]); 431 432 // Post-order. 433 FromIterator.clear(); 434 copy(post_order(Start), std::back_inserter(FromIterator)); 435 EXPECT_EQ(8u, FromIterator.size()); 436 EXPECT_EQ(R2BB2, FromIterator[0]); 437 EXPECT_EQ(R2BB1, FromIterator[1]); 438 EXPECT_EQ(R2, FromIterator[2]); 439 EXPECT_EQ(R1BB4, FromIterator[3]); 440 EXPECT_EQ(R1BB2, FromIterator[4]); 441 EXPECT_EQ(R1BB3, FromIterator[5]); 442 EXPECT_EQ(R1BB1, FromIterator[6]); 443 EXPECT_EQ(R1, FromIterator[7]); 444 445 VPBlockUtils::connectBlocks(R2, Plan.getScalarHeader()); 446 } 447 448 { 449 // 2 nested regions. 450 // VPBB1 451 // | 452 // R1 { 453 // R1BB1 454 // / \ 455 // R2 { | 456 // \ | 457 // R2BB1 | 458 // | \ R1BB2 459 // R2BB2-| | 460 // \ | 461 // R2BB3 | 462 // } / 463 // \ / 464 // R1BB3 465 // } 466 // | 467 // VPBB2 468 // 469 VPlan &Plan = getPlan(); 470 VPBasicBlock *R1BB1 = new VPBasicBlock("R1BB1"); 471 VPBasicBlock *R1BB2 = new VPBasicBlock("R1BB2"); 472 VPBasicBlock *R1BB3 = new VPBasicBlock("R1BB3"); 473 VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB3, "R1"); 474 475 VPBasicBlock *R2BB1 = new VPBasicBlock("R2BB1"); 476 VPBasicBlock *R2BB2 = new VPBasicBlock("R2BB2"); 477 VPBasicBlock *R2BB3 = new VPBasicBlock("R2BB3"); 478 VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB3, "R2"); 479 R2BB2->setParent(R2); 480 VPBlockUtils::connectBlocks(R2BB1, R2BB2); 481 VPBlockUtils::connectBlocks(R2BB2, R2BB1); 482 VPBlockUtils::connectBlocks(R2BB2, R2BB3); 483 484 R2->setParent(R1); 485 VPBlockUtils::connectBlocks(R1BB1, R2); 486 R1BB2->setParent(R1); 487 VPBlockUtils::connectBlocks(R1BB1, R1BB2); 488 VPBlockUtils::connectBlocks(R1BB2, R1BB3); 489 VPBlockUtils::connectBlocks(R2, R1BB3); 490 491 VPBasicBlock *VPBB1 = Plan.getEntry(); 492 VPBlockUtils::connectBlocks(VPBB1, R1); 493 VPBasicBlock *VPBB2 = new VPBasicBlock("VPBB2"); 494 VPBlockUtils::connectBlocks(R1, VPBB2); 495 496 // Depth-first. 497 VPBlockDeepTraversalWrapper<VPBlockBase *> Start(VPBB1); 498 SmallVector<VPBlockBase *> FromIterator(depth_first(Start)); 499 EXPECT_EQ(10u, FromIterator.size()); 500 EXPECT_EQ(VPBB1, FromIterator[0]); 501 EXPECT_EQ(R1, FromIterator[1]); 502 EXPECT_EQ(R1BB1, FromIterator[2]); 503 EXPECT_EQ(R2, FromIterator[3]); 504 EXPECT_EQ(R2BB1, FromIterator[4]); 505 EXPECT_EQ(R2BB2, FromIterator[5]); 506 EXPECT_EQ(R2BB3, FromIterator[6]); 507 EXPECT_EQ(R1BB3, FromIterator[7]); 508 EXPECT_EQ(VPBB2, FromIterator[8]); 509 EXPECT_EQ(R1BB2, FromIterator[9]); 510 511 // Post-order. 512 FromIterator.clear(); 513 FromIterator.append(po_begin(Start), po_end(Start)); 514 EXPECT_EQ(10u, FromIterator.size()); 515 EXPECT_EQ(VPBB2, FromIterator[0]); 516 EXPECT_EQ(R1BB3, FromIterator[1]); 517 EXPECT_EQ(R2BB3, FromIterator[2]); 518 EXPECT_EQ(R2BB2, FromIterator[3]); 519 EXPECT_EQ(R2BB1, FromIterator[4]); 520 EXPECT_EQ(R2, FromIterator[5]); 521 EXPECT_EQ(R1BB2, FromIterator[6]); 522 EXPECT_EQ(R1BB1, FromIterator[7]); 523 EXPECT_EQ(R1, FromIterator[8]); 524 EXPECT_EQ(VPBB1, FromIterator[9]); 525 526 VPBlockUtils::connectBlocks(VPBB2, Plan.getScalarHeader()); 527 } 528 529 { 530 // VPBB1 531 // | 532 // R1 { 533 // \ 534 // R2 { 535 // R2BB1 536 // | 537 // R2BB2 538 // } 539 // 540 VPlan &Plan = getPlan(); 541 VPBasicBlock *R2BB1 = new VPBasicBlock("R2BB1"); 542 VPBasicBlock *R2BB2 = new VPBasicBlock("R2BB2"); 543 VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2"); 544 VPBlockUtils::connectBlocks(R2BB1, R2BB2); 545 546 VPRegionBlock *R1 = new VPRegionBlock(R2, R2, "R1"); 547 R2->setParent(R1); 548 549 VPBasicBlock *VPBB1 = Plan.getEntry(); 550 VPBlockUtils::connectBlocks(VPBB1, R1); 551 552 // Depth-first. 553 VPBlockDeepTraversalWrapper<VPBlockBase *> Start(VPBB1); 554 SmallVector<VPBlockBase *> FromIterator(depth_first(Start)); 555 EXPECT_EQ(5u, FromIterator.size()); 556 EXPECT_EQ(VPBB1, FromIterator[0]); 557 EXPECT_EQ(R1, FromIterator[1]); 558 EXPECT_EQ(R2, FromIterator[2]); 559 EXPECT_EQ(R2BB1, FromIterator[3]); 560 EXPECT_EQ(R2BB2, FromIterator[4]); 561 562 // Post-order. 563 FromIterator.clear(); 564 FromIterator.append(po_begin(Start), po_end(Start)); 565 EXPECT_EQ(5u, FromIterator.size()); 566 EXPECT_EQ(R2BB2, FromIterator[0]); 567 EXPECT_EQ(R2BB1, FromIterator[1]); 568 EXPECT_EQ(R2, FromIterator[2]); 569 EXPECT_EQ(R1, FromIterator[3]); 570 EXPECT_EQ(VPBB1, FromIterator[4]); 571 572 VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); 573 } 574 575 { 576 // Nested regions with both R3 and R2 being exit nodes without successors. 577 // The successors of R1 should be used. 578 // 579 // VPBB1 580 // | 581 // R1 { 582 // \ 583 // R2 { 584 // \ 585 // R2BB1 586 // | 587 // R3 { 588 // R3BB1 589 // } 590 // } 591 // | 592 // VPBB2 593 // 594 VPlan &Plan = getPlan(); 595 VPBasicBlock *R3BB1 = new VPBasicBlock("R3BB1"); 596 VPRegionBlock *R3 = new VPRegionBlock(R3BB1, R3BB1, "R3"); 597 598 VPBasicBlock *R2BB1 = new VPBasicBlock("R2BB1"); 599 VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R3, "R2"); 600 R3->setParent(R2); 601 VPBlockUtils::connectBlocks(R2BB1, R3); 602 603 VPRegionBlock *R1 = new VPRegionBlock(R2, R2, "R1"); 604 R2->setParent(R1); 605 606 VPBasicBlock *VPBB1 = Plan.getEntry(); 607 VPBasicBlock *VPBB2 = new VPBasicBlock("VPBB2"); 608 VPBlockUtils::connectBlocks(VPBB1, R1); 609 VPBlockUtils::connectBlocks(R1, VPBB2); 610 611 // Depth-first. 612 VPBlockDeepTraversalWrapper<VPBlockBase *> Start(VPBB1); 613 SmallVector<VPBlockBase *> FromIterator(depth_first(Start)); 614 EXPECT_EQ(7u, FromIterator.size()); 615 EXPECT_EQ(VPBB1, FromIterator[0]); 616 EXPECT_EQ(R1, FromIterator[1]); 617 EXPECT_EQ(R2, FromIterator[2]); 618 EXPECT_EQ(R2BB1, FromIterator[3]); 619 EXPECT_EQ(R3, FromIterator[4]); 620 EXPECT_EQ(R3BB1, FromIterator[5]); 621 EXPECT_EQ(VPBB2, FromIterator[6]); 622 623 SmallVector<VPBlockBase *> FromIteratorVPBB; 624 copy(VPBlockUtils::blocksOnly<VPBasicBlock>(depth_first(Start)), 625 std::back_inserter(FromIteratorVPBB)); 626 EXPECT_EQ(VPBB1, FromIteratorVPBB[0]); 627 EXPECT_EQ(R2BB1, FromIteratorVPBB[1]); 628 EXPECT_EQ(R3BB1, FromIteratorVPBB[2]); 629 EXPECT_EQ(VPBB2, FromIteratorVPBB[3]); 630 631 // Post-order. 632 FromIterator.clear(); 633 copy(post_order(Start), std::back_inserter(FromIterator)); 634 EXPECT_EQ(7u, FromIterator.size()); 635 EXPECT_EQ(VPBB2, FromIterator[0]); 636 EXPECT_EQ(R3BB1, FromIterator[1]); 637 EXPECT_EQ(R3, FromIterator[2]); 638 EXPECT_EQ(R2BB1, FromIterator[3]); 639 EXPECT_EQ(R2, FromIterator[4]); 640 EXPECT_EQ(R1, FromIterator[5]); 641 EXPECT_EQ(VPBB1, FromIterator[6]); 642 643 // Post-order, const VPRegionBlocks only. 644 VPBlockDeepTraversalWrapper<const VPBlockBase *> StartConst(VPBB1); 645 SmallVector<const VPRegionBlock *> FromIteratorVPRegion( 646 VPBlockUtils::blocksOnly<const VPRegionBlock>(post_order(StartConst))); 647 EXPECT_EQ(3u, FromIteratorVPRegion.size()); 648 EXPECT_EQ(R3, FromIteratorVPRegion[0]); 649 EXPECT_EQ(R2, FromIteratorVPRegion[1]); 650 EXPECT_EQ(R1, FromIteratorVPRegion[2]); 651 652 // Post-order, VPBasicBlocks only. 653 FromIterator.clear(); 654 copy(VPBlockUtils::blocksOnly<VPBasicBlock>(post_order(Start)), 655 std::back_inserter(FromIterator)); 656 EXPECT_EQ(FromIterator.size(), 4u); 657 EXPECT_EQ(VPBB2, FromIterator[0]); 658 EXPECT_EQ(R3BB1, FromIterator[1]); 659 EXPECT_EQ(R2BB1, FromIterator[2]); 660 EXPECT_EQ(VPBB1, FromIterator[3]); 661 662 VPBlockUtils::connectBlocks(VPBB2, Plan.getScalarHeader()); 663 } 664 } 665 666 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 667 TEST_F(VPBasicBlockTest, print) { 668 VPInstruction *TC = new VPInstruction(Instruction::Add, {}); 669 VPlan &Plan = getPlan(TC); 670 VPBasicBlock *VPBB0 = Plan.getEntry(); 671 VPBB0->appendRecipe(TC); 672 673 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 674 VPInstruction *I2 = new VPInstruction(Instruction::Sub, {I1}); 675 VPInstruction *I3 = new VPInstruction(Instruction::Br, {I1, I2}); 676 677 VPBasicBlock *VPBB1 = new VPBasicBlock(); 678 VPBB1->appendRecipe(I1); 679 VPBB1->appendRecipe(I2); 680 VPBB1->appendRecipe(I3); 681 VPBB1->setName("bb1"); 682 683 VPInstruction *I4 = new VPInstruction(Instruction::Mul, {I2, I1}); 684 VPInstruction *I5 = new VPInstruction(Instruction::Ret, {I4}); 685 VPBasicBlock *VPBB2 = new VPBasicBlock(); 686 VPBB2->appendRecipe(I4); 687 VPBB2->appendRecipe(I5); 688 VPBB2->setName("bb2"); 689 690 VPBlockUtils::connectBlocks(VPBB1, VPBB2); 691 692 // Check printing an instruction without associated VPlan. 693 { 694 std::string I3Dump; 695 raw_string_ostream OS(I3Dump); 696 VPSlotTracker SlotTracker; 697 I3->print(OS, "", SlotTracker); 698 EXPECT_EQ("EMIT br <badref>, <badref>", I3Dump); 699 } 700 701 VPBlockUtils::connectBlocks(VPBB2, Plan.getScalarHeader()); 702 VPBlockUtils::connectBlocks(VPBB0, VPBB1); 703 std::string FullDump; 704 raw_string_ostream OS(FullDump); 705 Plan.printDOT(OS); 706 707 const char *ExpectedStr = R"(digraph VPlan { 708 graph [labelloc=t, fontsize=30; label="Vectorization Plan\n for UF\>=1\nvp\<%1\> = original trip-count\n"] 709 node [shape=rect, fontname=Courier, fontsize=30] 710 edge [fontname=Courier, fontsize=30] 711 compound=true 712 N0 [label = 713 "preheader:\l" + 714 " EMIT vp\<%1\> = add\l" + 715 "Successor(s): bb1\l" 716 ] 717 N0 -> N1 [ label=""] 718 N1 [label = 719 "bb1:\l" + 720 " EMIT vp\<%2\> = add\l" + 721 " EMIT vp\<%3\> = sub vp\<%2\>\l" + 722 " EMIT br vp\<%2\>, vp\<%3\>\l" + 723 "Successor(s): bb2\l" 724 ] 725 N1 -> N2 [ label=""] 726 N2 [label = 727 "bb2:\l" + 728 " EMIT vp\<%5\> = mul vp\<%3\>, vp\<%2\>\l" + 729 " EMIT ret vp\<%5\>\l" + 730 "Successor(s): ir-bb\<scalar.header\>\l" 731 ] 732 N2 -> N3 [ label=""] 733 N3 [label = 734 "ir-bb\<scalar.header\>:\l" + 735 "No successors\l" 736 ] 737 } 738 )"; 739 EXPECT_EQ(ExpectedStr, FullDump); 740 741 const char *ExpectedBlock1Str = R"(bb1: 742 EMIT vp<%2> = add 743 EMIT vp<%3> = sub vp<%2> 744 EMIT br vp<%2>, vp<%3> 745 Successor(s): bb2 746 )"; 747 std::string Block1Dump; 748 raw_string_ostream OS1(Block1Dump); 749 VPBB1->print(OS1); 750 EXPECT_EQ(ExpectedBlock1Str, Block1Dump); 751 752 // Ensure that numbering is good when dumping the second block in isolation. 753 const char *ExpectedBlock2Str = R"(bb2: 754 EMIT vp<%5> = mul vp<%3>, vp<%2> 755 EMIT ret vp<%5> 756 Successor(s): ir-bb<scalar.header> 757 )"; 758 std::string Block2Dump; 759 raw_string_ostream OS2(Block2Dump); 760 VPBB2->print(OS2); 761 EXPECT_EQ(ExpectedBlock2Str, Block2Dump); 762 763 { 764 std::string I3Dump; 765 raw_string_ostream OS(I3Dump); 766 VPSlotTracker SlotTracker(&Plan); 767 I3->print(OS, "", SlotTracker); 768 EXPECT_EQ("EMIT br vp<%2>, vp<%3>", I3Dump); 769 } 770 771 { 772 std::string I4Dump; 773 raw_string_ostream OS(I4Dump); 774 OS << *I4; 775 EXPECT_EQ("EMIT vp<%5> = mul vp<%3>, vp<%2>", I4Dump); 776 } 777 } 778 779 TEST_F(VPBasicBlockTest, printPlanWithVFsAndUFs) { 780 VPInstruction *TC = new VPInstruction(Instruction::Sub, {}); 781 VPlan &Plan = getPlan(TC); 782 VPBasicBlock *VPBB0 = Plan.getEntry(); 783 VPBB0->appendRecipe(TC); 784 785 VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); 786 VPBasicBlock *VPBB1 = new VPBasicBlock(); 787 VPBB1->appendRecipe(I1); 788 VPBB1->setName("bb1"); 789 790 VPBlockUtils::connectBlocks(VPBB1, Plan.getScalarHeader()); 791 VPBlockUtils::connectBlocks(VPBB0, VPBB1); 792 Plan.setName("TestPlan"); 793 Plan.addVF(ElementCount::getFixed(4)); 794 795 { 796 std::string FullDump; 797 raw_string_ostream OS(FullDump); 798 Plan.print(OS); 799 800 const char *ExpectedStr = R"(VPlan 'TestPlan for VF={4},UF>=1' { 801 vp<%1> = original trip-count 802 803 preheader: 804 EMIT vp<%1> = sub 805 Successor(s): bb1 806 807 bb1: 808 EMIT vp<%2> = add 809 Successor(s): ir-bb<scalar.header> 810 811 ir-bb<scalar.header>: 812 No successors 813 } 814 )"; 815 EXPECT_EQ(ExpectedStr, FullDump); 816 } 817 818 { 819 Plan.addVF(ElementCount::getScalable(8)); 820 std::string FullDump; 821 raw_string_ostream OS(FullDump); 822 Plan.print(OS); 823 824 const char *ExpectedStr = R"(VPlan 'TestPlan for VF={4,vscale x 8},UF>=1' { 825 vp<%1> = original trip-count 826 827 preheader: 828 EMIT vp<%1> = sub 829 Successor(s): bb1 830 831 bb1: 832 EMIT vp<%2> = add 833 Successor(s): ir-bb<scalar.header> 834 835 ir-bb<scalar.header>: 836 No successors 837 } 838 )"; 839 EXPECT_EQ(ExpectedStr, FullDump); 840 } 841 842 { 843 Plan.setUF(4); 844 std::string FullDump; 845 raw_string_ostream OS(FullDump); 846 Plan.print(OS); 847 848 const char *ExpectedStr = R"(VPlan 'TestPlan for VF={4,vscale x 8},UF={4}' { 849 vp<%1> = original trip-count 850 851 preheader: 852 EMIT vp<%1> = sub 853 Successor(s): bb1 854 855 bb1: 856 EMIT vp<%2> = add 857 Successor(s): ir-bb<scalar.header> 858 859 ir-bb<scalar.header>: 860 No successors 861 } 862 )"; 863 EXPECT_EQ(ExpectedStr, FullDump); 864 } 865 } 866 #endif 867 868 using VPRecipeTest = VPlanTestBase; 869 TEST_F(VPRecipeTest, CastVPInstructionToVPUser) { 870 VPValue Op1; 871 VPValue Op2; 872 VPInstruction Recipe(Instruction::Add, {&Op1, &Op2}); 873 EXPECT_TRUE(isa<VPUser>(&Recipe)); 874 VPRecipeBase *BaseR = &Recipe; 875 EXPECT_TRUE(isa<VPUser>(BaseR)); 876 EXPECT_EQ(&Recipe, BaseR); 877 } 878 879 TEST_F(VPRecipeTest, CastVPWidenRecipeToVPUser) { 880 IntegerType *Int32 = IntegerType::get(C, 32); 881 auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32), 882 PoisonValue::get(Int32)); 883 VPValue Op1; 884 VPValue Op2; 885 SmallVector<VPValue *, 2> Args; 886 Args.push_back(&Op1); 887 Args.push_back(&Op1); 888 VPWidenRecipe WidenR(*AI, make_range(Args.begin(), Args.end())); 889 EXPECT_TRUE(isa<VPUser>(&WidenR)); 890 VPRecipeBase *WidenRBase = &WidenR; 891 EXPECT_TRUE(isa<VPUser>(WidenRBase)); 892 EXPECT_EQ(&WidenR, WidenRBase); 893 delete AI; 894 } 895 896 TEST_F(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) { 897 IntegerType *Int32 = IntegerType::get(C, 32); 898 FunctionType *FTy = FunctionType::get(Int32, false); 899 Function *Fn = Function::Create(FTy, GlobalValue::ExternalLinkage, 0); 900 auto *Call = CallInst::Create(FTy, Fn); 901 VPValue Op1; 902 VPValue Op2; 903 VPValue CalledFn(Call->getCalledFunction()); 904 SmallVector<VPValue *, 2> Args; 905 Args.push_back(&Op1); 906 Args.push_back(&Op2); 907 Args.push_back(&CalledFn); 908 VPWidenCallRecipe Recipe(Call, Fn, Args); 909 EXPECT_TRUE(isa<VPUser>(&Recipe)); 910 VPRecipeBase *BaseR = &Recipe; 911 EXPECT_TRUE(isa<VPUser>(BaseR)); 912 EXPECT_EQ(&Recipe, BaseR); 913 914 VPValue *VPV = &Recipe; 915 EXPECT_TRUE(VPV->getDefiningRecipe()); 916 EXPECT_EQ(&Recipe, VPV->getDefiningRecipe()); 917 918 delete Call; 919 delete Fn; 920 } 921 922 TEST_F(VPRecipeTest, CastVPWidenSelectRecipeToVPUserAndVPDef) { 923 IntegerType *Int1 = IntegerType::get(C, 1); 924 IntegerType *Int32 = IntegerType::get(C, 32); 925 auto *SelectI = SelectInst::Create( 926 PoisonValue::get(Int1), PoisonValue::get(Int32), PoisonValue::get(Int32)); 927 VPValue Op1; 928 VPValue Op2; 929 VPValue Op3; 930 SmallVector<VPValue *, 4> Args; 931 Args.push_back(&Op1); 932 Args.push_back(&Op2); 933 Args.push_back(&Op3); 934 VPWidenSelectRecipe WidenSelectR(*SelectI, 935 make_range(Args.begin(), Args.end())); 936 EXPECT_TRUE(isa<VPUser>(&WidenSelectR)); 937 VPRecipeBase *BaseR = &WidenSelectR; 938 EXPECT_TRUE(isa<VPUser>(BaseR)); 939 EXPECT_EQ(&WidenSelectR, BaseR); 940 941 VPValue *VPV = &WidenSelectR; 942 EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDefiningRecipe())); 943 EXPECT_EQ(&WidenSelectR, VPV->getDefiningRecipe()); 944 945 delete SelectI; 946 } 947 948 TEST_F(VPRecipeTest, CastVPWidenGEPRecipeToVPUserAndVPDef) { 949 IntegerType *Int32 = IntegerType::get(C, 32); 950 PointerType *Int32Ptr = PointerType::get(Int32, 0); 951 auto *GEP = GetElementPtrInst::Create(Int32, PoisonValue::get(Int32Ptr), 952 PoisonValue::get(Int32)); 953 VPValue Op1; 954 VPValue Op2; 955 SmallVector<VPValue *, 4> Args; 956 Args.push_back(&Op1); 957 Args.push_back(&Op2); 958 VPWidenGEPRecipe Recipe(GEP, make_range(Args.begin(), Args.end())); 959 EXPECT_TRUE(isa<VPUser>(&Recipe)); 960 VPRecipeBase *BaseR = &Recipe; 961 EXPECT_TRUE(isa<VPUser>(BaseR)); 962 EXPECT_EQ(&Recipe, BaseR); 963 964 VPValue *VPV = &Recipe; 965 EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDefiningRecipe())); 966 EXPECT_EQ(&Recipe, VPV->getDefiningRecipe()); 967 968 delete GEP; 969 } 970 971 TEST_F(VPRecipeTest, CastVPBlendRecipeToVPUser) { 972 IntegerType *Int32 = IntegerType::get(C, 32); 973 auto *Phi = PHINode::Create(Int32, 1); 974 VPValue I1; 975 VPValue I2; 976 VPValue M2; 977 SmallVector<VPValue *, 4> Args; 978 Args.push_back(&I1); 979 Args.push_back(&I2); 980 Args.push_back(&M2); 981 VPBlendRecipe Recipe(Phi, Args); 982 EXPECT_TRUE(isa<VPUser>(&Recipe)); 983 VPRecipeBase *BaseR = &Recipe; 984 EXPECT_TRUE(isa<VPUser>(BaseR)); 985 delete Phi; 986 } 987 988 TEST_F(VPRecipeTest, CastVPInterleaveRecipeToVPUser) { 989 VPValue Addr; 990 VPValue Mask; 991 InterleaveGroup<Instruction> IG(4, false, Align(4)); 992 VPInterleaveRecipe Recipe(&IG, &Addr, {}, &Mask, false); 993 EXPECT_TRUE(isa<VPUser>(&Recipe)); 994 VPRecipeBase *BaseR = &Recipe; 995 EXPECT_TRUE(isa<VPUser>(BaseR)); 996 EXPECT_EQ(&Recipe, BaseR); 997 } 998 999 TEST_F(VPRecipeTest, CastVPReplicateRecipeToVPUser) { 1000 VPValue Op1; 1001 VPValue Op2; 1002 SmallVector<VPValue *, 4> Args; 1003 Args.push_back(&Op1); 1004 Args.push_back(&Op2); 1005 1006 IntegerType *Int32 = IntegerType::get(C, 32); 1007 FunctionType *FTy = FunctionType::get(Int32, false); 1008 auto *Call = CallInst::Create(FTy, PoisonValue::get(FTy)); 1009 VPReplicateRecipe Recipe(Call, make_range(Args.begin(), Args.end()), true); 1010 EXPECT_TRUE(isa<VPUser>(&Recipe)); 1011 VPRecipeBase *BaseR = &Recipe; 1012 EXPECT_TRUE(isa<VPUser>(BaseR)); 1013 delete Call; 1014 } 1015 1016 TEST_F(VPRecipeTest, CastVPBranchOnMaskRecipeToVPUser) { 1017 VPValue Mask; 1018 VPBranchOnMaskRecipe Recipe(&Mask); 1019 EXPECT_TRUE(isa<VPUser>(&Recipe)); 1020 VPRecipeBase *BaseR = &Recipe; 1021 EXPECT_TRUE(isa<VPUser>(BaseR)); 1022 EXPECT_EQ(&Recipe, BaseR); 1023 } 1024 1025 TEST_F(VPRecipeTest, CastVPWidenMemoryRecipeToVPUserAndVPDef) { 1026 IntegerType *Int32 = IntegerType::get(C, 32); 1027 PointerType *Int32Ptr = PointerType::get(Int32, 0); 1028 auto *Load = 1029 new LoadInst(Int32, PoisonValue::get(Int32Ptr), "", false, Align(1)); 1030 VPValue Addr; 1031 VPValue Mask; 1032 VPWidenLoadRecipe Recipe(*Load, &Addr, &Mask, true, false, {}); 1033 EXPECT_TRUE(isa<VPUser>(&Recipe)); 1034 VPRecipeBase *BaseR = &Recipe; 1035 EXPECT_TRUE(isa<VPUser>(BaseR)); 1036 EXPECT_EQ(&Recipe, BaseR); 1037 1038 VPValue *VPV = Recipe.getVPSingleValue(); 1039 EXPECT_TRUE(isa<VPRecipeBase>(VPV->getDefiningRecipe())); 1040 EXPECT_EQ(&Recipe, VPV->getDefiningRecipe()); 1041 1042 delete Load; 1043 } 1044 1045 TEST_F(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) { 1046 IntegerType *Int1 = IntegerType::get(C, 1); 1047 IntegerType *Int32 = IntegerType::get(C, 32); 1048 PointerType *Int32Ptr = PointerType::get(Int32, 0); 1049 1050 { 1051 auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32), 1052 PoisonValue::get(Int32)); 1053 VPValue Op1; 1054 VPValue Op2; 1055 SmallVector<VPValue *, 2> Args; 1056 Args.push_back(&Op1); 1057 Args.push_back(&Op1); 1058 VPWidenRecipe Recipe(*AI, make_range(Args.begin(), Args.end())); 1059 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1060 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1061 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1062 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1063 delete AI; 1064 } 1065 1066 { 1067 auto *SelectI = 1068 SelectInst::Create(PoisonValue::get(Int1), PoisonValue::get(Int32), 1069 PoisonValue::get(Int32)); 1070 VPValue Op1; 1071 VPValue Op2; 1072 VPValue Op3; 1073 SmallVector<VPValue *, 4> Args; 1074 Args.push_back(&Op1); 1075 Args.push_back(&Op2); 1076 Args.push_back(&Op3); 1077 VPWidenSelectRecipe Recipe(*SelectI, make_range(Args.begin(), Args.end())); 1078 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1079 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1080 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1081 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1082 delete SelectI; 1083 } 1084 1085 { 1086 auto *GEP = GetElementPtrInst::Create(Int32, PoisonValue::get(Int32Ptr), 1087 PoisonValue::get(Int32)); 1088 VPValue Op1; 1089 VPValue Op2; 1090 SmallVector<VPValue *, 4> Args; 1091 Args.push_back(&Op1); 1092 Args.push_back(&Op2); 1093 VPWidenGEPRecipe Recipe(GEP, make_range(Args.begin(), Args.end())); 1094 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1095 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1096 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1097 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1098 delete GEP; 1099 } 1100 1101 { 1102 VPValue Mask; 1103 VPBranchOnMaskRecipe Recipe(&Mask); 1104 EXPECT_TRUE(Recipe.mayHaveSideEffects()); 1105 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1106 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1107 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1108 } 1109 1110 { 1111 VPValue ChainOp; 1112 VPValue VecOp; 1113 VPValue CondOp; 1114 VPReductionRecipe Recipe(RecurrenceDescriptor(), nullptr, &ChainOp, &CondOp, 1115 &VecOp, false); 1116 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1117 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1118 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1119 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1120 } 1121 1122 { 1123 VPValue ChainOp; 1124 VPValue VecOp; 1125 VPValue CondOp; 1126 VPReductionRecipe Recipe(RecurrenceDescriptor(), nullptr, &ChainOp, &CondOp, 1127 &VecOp, false); 1128 VPValue EVL; 1129 VPReductionEVLRecipe EVLRecipe(Recipe, EVL, &CondOp); 1130 EXPECT_FALSE(EVLRecipe.mayHaveSideEffects()); 1131 EXPECT_FALSE(EVLRecipe.mayReadFromMemory()); 1132 EXPECT_FALSE(EVLRecipe.mayWriteToMemory()); 1133 EXPECT_FALSE(EVLRecipe.mayReadOrWriteMemory()); 1134 } 1135 1136 { 1137 auto *Load = 1138 new LoadInst(Int32, PoisonValue::get(Int32Ptr), "", false, Align(1)); 1139 VPValue Addr; 1140 VPValue Mask; 1141 VPWidenLoadRecipe Recipe(*Load, &Addr, &Mask, true, false, {}); 1142 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1143 EXPECT_TRUE(Recipe.mayReadFromMemory()); 1144 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1145 EXPECT_TRUE(Recipe.mayReadOrWriteMemory()); 1146 delete Load; 1147 } 1148 1149 { 1150 auto *Store = new StoreInst(PoisonValue::get(Int32), 1151 PoisonValue::get(Int32Ptr), false, Align(1)); 1152 VPValue Addr; 1153 VPValue Mask; 1154 VPValue StoredV; 1155 VPWidenStoreRecipe Recipe(*Store, &Addr, &StoredV, &Mask, false, false, {}); 1156 EXPECT_TRUE(Recipe.mayHaveSideEffects()); 1157 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1158 EXPECT_TRUE(Recipe.mayWriteToMemory()); 1159 EXPECT_TRUE(Recipe.mayReadOrWriteMemory()); 1160 delete Store; 1161 } 1162 1163 { 1164 FunctionType *FTy = FunctionType::get(Int32, false); 1165 Function *Fn = Function::Create(FTy, GlobalValue::ExternalLinkage, 0); 1166 auto *Call = CallInst::Create(FTy, Fn); 1167 VPValue Op1; 1168 VPValue Op2; 1169 VPValue CalledFn(Call->getCalledFunction()); 1170 SmallVector<VPValue *, 3> Args; 1171 Args.push_back(&Op1); 1172 Args.push_back(&Op2); 1173 Args.push_back(&CalledFn); 1174 VPWidenCallRecipe Recipe(Call, Fn, Args); 1175 EXPECT_TRUE(Recipe.mayHaveSideEffects()); 1176 EXPECT_TRUE(Recipe.mayReadFromMemory()); 1177 EXPECT_TRUE(Recipe.mayWriteToMemory()); 1178 EXPECT_TRUE(Recipe.mayReadOrWriteMemory()); 1179 delete Call; 1180 delete Fn; 1181 } 1182 1183 { 1184 // Test for a call to a function without side-effects. 1185 Module M("", C); 1186 Function *TheFn = 1187 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::thread_pointer); 1188 1189 auto *Call = CallInst::Create(TheFn->getFunctionType(), TheFn); 1190 VPValue Op1; 1191 VPValue Op2; 1192 VPValue CalledFn(TheFn); 1193 SmallVector<VPValue *, 3> Args; 1194 Args.push_back(&Op1); 1195 Args.push_back(&Op2); 1196 Args.push_back(&CalledFn); 1197 VPWidenCallRecipe Recipe(Call, TheFn, Args); 1198 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1199 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1200 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1201 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1202 delete Call; 1203 } 1204 1205 { 1206 VPValue Op1; 1207 VPValue Op2; 1208 InductionDescriptor IndDesc; 1209 VPScalarIVStepsRecipe Recipe(IndDesc, &Op1, &Op2); 1210 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1211 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1212 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1213 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1214 } 1215 1216 // The initial implementation is conservative with respect to VPInstructions. 1217 { 1218 VPValue Op1; 1219 VPValue Op2; 1220 VPInstruction VPInst(Instruction::Add, {&Op1, &Op2}); 1221 VPRecipeBase &Recipe = VPInst; 1222 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1223 EXPECT_TRUE(Recipe.mayReadFromMemory()); 1224 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1225 EXPECT_TRUE(Recipe.mayReadOrWriteMemory()); 1226 } 1227 { 1228 VPValue Op1; 1229 VPPredInstPHIRecipe Recipe(&Op1, {}); 1230 EXPECT_FALSE(Recipe.mayHaveSideEffects()); 1231 EXPECT_FALSE(Recipe.mayReadFromMemory()); 1232 EXPECT_FALSE(Recipe.mayWriteToMemory()); 1233 EXPECT_FALSE(Recipe.mayReadOrWriteMemory()); 1234 } 1235 } 1236 1237 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1238 TEST_F(VPRecipeTest, dumpRecipeInPlan) { 1239 VPlan &Plan = getPlan(); 1240 VPBasicBlock *VPBB0 = Plan.getEntry(); 1241 VPBasicBlock *VPBB1 = new VPBasicBlock(); 1242 VPBlockUtils::connectBlocks(VPBB1, Plan.getScalarHeader()); 1243 VPBlockUtils::connectBlocks(VPBB0, VPBB1); 1244 1245 IntegerType *Int32 = IntegerType::get(C, 32); 1246 auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32), 1247 PoisonValue::get(Int32)); 1248 AI->setName("a"); 1249 SmallVector<VPValue *, 2> Args; 1250 VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1)); 1251 VPValue *ExtVPV2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2)); 1252 Args.push_back(ExtVPV1); 1253 Args.push_back(ExtVPV2); 1254 VPWidenRecipe *WidenR = 1255 new VPWidenRecipe(*AI, make_range(Args.begin(), Args.end())); 1256 VPBB1->appendRecipe(WidenR); 1257 1258 { 1259 // Use EXPECT_EXIT to capture stderr and compare against expected output. 1260 // 1261 // Test VPValue::dump(). 1262 VPValue *VPV = WidenR; 1263 EXPECT_EXIT( 1264 { 1265 VPV->dump(); 1266 exit(0); 1267 }, 1268 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>"); 1269 1270 VPDef *Def = WidenR; 1271 EXPECT_EXIT( 1272 { 1273 Def->dump(); 1274 exit(0); 1275 }, 1276 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>"); 1277 1278 EXPECT_EXIT( 1279 { 1280 WidenR->dump(); 1281 exit(0); 1282 }, 1283 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>"); 1284 1285 // Test VPRecipeBase::dump(). 1286 VPRecipeBase *R = WidenR; 1287 EXPECT_EXIT( 1288 { 1289 R->dump(); 1290 exit(0); 1291 }, 1292 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>"); 1293 1294 // Test VPDef::dump(). 1295 VPDef *D = WidenR; 1296 EXPECT_EXIT( 1297 { 1298 D->dump(); 1299 exit(0); 1300 }, 1301 testing::ExitedWithCode(0), "WIDEN ir<%a> = add ir<1>, ir<2>"); 1302 } 1303 1304 delete AI; 1305 } 1306 1307 TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesInPlan) { 1308 VPlan &Plan = getPlan(); 1309 VPBasicBlock *VPBB0 = Plan.getEntry(); 1310 VPBasicBlock *VPBB1 = new VPBasicBlock(); 1311 VPBlockUtils::connectBlocks(VPBB1, Plan.getScalarHeader()); 1312 VPBlockUtils::connectBlocks(VPBB0, VPBB1); 1313 1314 IntegerType *Int32 = IntegerType::get(C, 32); 1315 auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32), 1316 PoisonValue::get(Int32)); 1317 AI->setName("a"); 1318 SmallVector<VPValue *, 2> Args; 1319 VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1)); 1320 VPValue *ExtVPV2 = Plan.getOrAddLiveIn(AI); 1321 Args.push_back(ExtVPV1); 1322 Args.push_back(ExtVPV2); 1323 VPInstruction *I1 = new VPInstruction(Instruction::Add, {ExtVPV1, ExtVPV2}); 1324 VPInstruction *I2 = new VPInstruction(Instruction::Mul, {I1, I1}); 1325 VPBB1->appendRecipe(I1); 1326 VPBB1->appendRecipe(I2); 1327 1328 // Check printing I1. 1329 { 1330 // Use EXPECT_EXIT to capture stderr and compare against expected output. 1331 // 1332 // Test VPValue::dump(). 1333 VPValue *VPV = I1; 1334 EXPECT_EXIT( 1335 { 1336 VPV->dump(); 1337 exit(0); 1338 }, 1339 testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>"); 1340 1341 // Test VPRecipeBase::dump(). 1342 VPRecipeBase *R = I1; 1343 EXPECT_EXIT( 1344 { 1345 R->dump(); 1346 exit(0); 1347 }, 1348 testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>"); 1349 1350 // Test VPDef::dump(). 1351 VPDef *D = I1; 1352 EXPECT_EXIT( 1353 { 1354 D->dump(); 1355 exit(0); 1356 }, 1357 testing::ExitedWithCode(0), "EMIT vp<%1> = add ir<1>, ir<%a>"); 1358 } 1359 // Check printing I2. 1360 { 1361 // Use EXPECT_EXIT to capture stderr and compare against expected output. 1362 // 1363 // Test VPValue::dump(). 1364 VPValue *VPV = I2; 1365 EXPECT_EXIT( 1366 { 1367 VPV->dump(); 1368 exit(0); 1369 }, 1370 testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>"); 1371 1372 // Test VPRecipeBase::dump(). 1373 VPRecipeBase *R = I2; 1374 EXPECT_EXIT( 1375 { 1376 R->dump(); 1377 exit(0); 1378 }, 1379 testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>"); 1380 1381 // Test VPDef::dump(). 1382 VPDef *D = I2; 1383 EXPECT_EXIT( 1384 { 1385 D->dump(); 1386 exit(0); 1387 }, 1388 testing::ExitedWithCode(0), "EMIT vp<%2> = mul vp<%1>, vp<%1>"); 1389 } 1390 delete AI; 1391 } 1392 1393 TEST_F(VPRecipeTest, dumpRecipeUnnamedVPValuesNotInPlanOrBlock) { 1394 IntegerType *Int32 = IntegerType::get(C, 32); 1395 auto *AI = BinaryOperator::CreateAdd(PoisonValue::get(Int32), 1396 PoisonValue::get(Int32)); 1397 AI->setName("a"); 1398 VPValue *ExtVPV1 = new VPValue(ConstantInt::get(Int32, 1)); 1399 VPValue *ExtVPV2 = new VPValue(AI); 1400 1401 VPInstruction *I1 = new VPInstruction(Instruction::Add, {ExtVPV1, ExtVPV2}); 1402 VPInstruction *I2 = new VPInstruction(Instruction::Mul, {I1, I1}); 1403 1404 // Check printing I1. 1405 { 1406 // Use EXPECT_EXIT to capture stderr and compare against expected output. 1407 // 1408 // Test VPValue::dump(). 1409 VPValue *VPV = I1; 1410 EXPECT_EXIT( 1411 { 1412 VPV->dump(); 1413 exit(0); 1414 }, 1415 testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>"); 1416 1417 // Test VPRecipeBase::dump(). 1418 VPRecipeBase *R = I1; 1419 EXPECT_EXIT( 1420 { 1421 R->dump(); 1422 exit(0); 1423 }, 1424 testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>"); 1425 1426 // Test VPDef::dump(). 1427 VPDef *D = I1; 1428 EXPECT_EXIT( 1429 { 1430 D->dump(); 1431 exit(0); 1432 }, 1433 testing::ExitedWithCode(0), "EMIT <badref> = add ir<1>, ir<%a>"); 1434 } 1435 // Check printing I2. 1436 { 1437 // Use EXPECT_EXIT to capture stderr and compare against expected output. 1438 // 1439 // Test VPValue::dump(). 1440 VPValue *VPV = I2; 1441 EXPECT_EXIT( 1442 { 1443 VPV->dump(); 1444 exit(0); 1445 }, 1446 testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>"); 1447 1448 // Test VPRecipeBase::dump(). 1449 VPRecipeBase *R = I2; 1450 EXPECT_EXIT( 1451 { 1452 R->dump(); 1453 exit(0); 1454 }, 1455 testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>"); 1456 1457 // Test VPDef::dump(). 1458 VPDef *D = I2; 1459 EXPECT_EXIT( 1460 { 1461 D->dump(); 1462 exit(0); 1463 }, 1464 testing::ExitedWithCode(0), "EMIT <badref> = mul <badref>, <badref>"); 1465 } 1466 1467 delete I2; 1468 delete I1; 1469 delete ExtVPV2; 1470 delete ExtVPV1; 1471 delete AI; 1472 } 1473 1474 #endif 1475 1476 TEST_F(VPRecipeTest, CastVPReductionRecipeToVPUser) { 1477 VPValue ChainOp; 1478 VPValue VecOp; 1479 VPValue CondOp; 1480 VPReductionRecipe Recipe(RecurrenceDescriptor(), nullptr, &ChainOp, &CondOp, 1481 &VecOp, false); 1482 EXPECT_TRUE(isa<VPUser>(&Recipe)); 1483 VPRecipeBase *BaseR = &Recipe; 1484 EXPECT_TRUE(isa<VPUser>(BaseR)); 1485 } 1486 1487 TEST_F(VPRecipeTest, CastVPReductionEVLRecipeToVPUser) { 1488 VPValue ChainOp; 1489 VPValue VecOp; 1490 VPValue CondOp; 1491 VPReductionRecipe Recipe(RecurrenceDescriptor(), nullptr, &ChainOp, &CondOp, 1492 &VecOp, false); 1493 VPValue EVL; 1494 VPReductionEVLRecipe EVLRecipe(Recipe, EVL, &CondOp); 1495 EXPECT_TRUE(isa<VPUser>(&EVLRecipe)); 1496 VPRecipeBase *BaseR = &EVLRecipe; 1497 EXPECT_TRUE(isa<VPUser>(BaseR)); 1498 } 1499 1500 struct VPDoubleValueDef : public VPRecipeBase { 1501 VPDoubleValueDef(ArrayRef<VPValue *> Operands) : VPRecipeBase(99, Operands) { 1502 new VPValue(nullptr, this); 1503 new VPValue(nullptr, this); 1504 } 1505 1506 VPRecipeBase *clone() override { return nullptr; } 1507 1508 void execute(struct VPTransformState &State) override {} 1509 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1510 void print(raw_ostream &O, const Twine &Indent, 1511 VPSlotTracker &SlotTracker) const override {} 1512 #endif 1513 }; 1514 1515 TEST(VPDoubleValueDefTest, traverseUseLists) { 1516 // Check that the def-use chains of a multi-def can be traversed in both 1517 // directions. 1518 1519 // Create a new VPDef which defines 2 values and has 2 operands. 1520 VPInstruction Op0(20, {}); 1521 VPInstruction Op1(30, {}); 1522 VPDoubleValueDef DoubleValueDef({&Op0, &Op1}); 1523 1524 // Create a new users of the defined values. 1525 VPInstruction I1( 1526 1, {DoubleValueDef.getVPValue(0), DoubleValueDef.getVPValue(1)}); 1527 VPInstruction I2(2, {DoubleValueDef.getVPValue(0)}); 1528 VPInstruction I3(3, {DoubleValueDef.getVPValue(1)}); 1529 1530 // Check operands of the VPDef (traversing upwards). 1531 SmallVector<VPValue *, 4> DoubleOperands(DoubleValueDef.op_begin(), 1532 DoubleValueDef.op_end()); 1533 EXPECT_EQ(2u, DoubleOperands.size()); 1534 EXPECT_EQ(&Op0, DoubleOperands[0]); 1535 EXPECT_EQ(&Op1, DoubleOperands[1]); 1536 1537 // Check users of the defined values (traversing downwards). 1538 SmallVector<VPUser *, 4> DoubleValueDefV0Users( 1539 DoubleValueDef.getVPValue(0)->user_begin(), 1540 DoubleValueDef.getVPValue(0)->user_end()); 1541 EXPECT_EQ(2u, DoubleValueDefV0Users.size()); 1542 EXPECT_EQ(&I1, DoubleValueDefV0Users[0]); 1543 EXPECT_EQ(&I2, DoubleValueDefV0Users[1]); 1544 1545 SmallVector<VPUser *, 4> DoubleValueDefV1Users( 1546 DoubleValueDef.getVPValue(1)->user_begin(), 1547 DoubleValueDef.getVPValue(1)->user_end()); 1548 EXPECT_EQ(2u, DoubleValueDefV1Users.size()); 1549 EXPECT_EQ(&I1, DoubleValueDefV1Users[0]); 1550 EXPECT_EQ(&I3, DoubleValueDefV1Users[1]); 1551 1552 // Now check that we can get the right VPDef for each defined value. 1553 EXPECT_EQ(&DoubleValueDef, I1.getOperand(0)->getDefiningRecipe()); 1554 EXPECT_EQ(&DoubleValueDef, I1.getOperand(1)->getDefiningRecipe()); 1555 EXPECT_EQ(&DoubleValueDef, I2.getOperand(0)->getDefiningRecipe()); 1556 EXPECT_EQ(&DoubleValueDef, I3.getOperand(0)->getDefiningRecipe()); 1557 } 1558 1559 TEST_F(VPRecipeTest, CastToVPSingleDefRecipe) { 1560 VPValue Start; 1561 VPEVLBasedIVPHIRecipe R(&Start, {}); 1562 VPRecipeBase *B = &R; 1563 EXPECT_TRUE(isa<VPSingleDefRecipe>(B)); 1564 // TODO: check other VPSingleDefRecipes. 1565 } 1566 1567 } // namespace 1568 } // namespace llvm 1569