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