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