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