1 //===- HexagonVectorLoopCarriedReuse.cpp ----------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This pass removes the computation of provably redundant expressions that have 10 // been computed earlier in a previous iteration. It relies on the use of PHIs 11 // to identify loop carried dependences. This is scalar replacement for vector 12 // types. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "HexagonVectorLoopCarriedReuse.h" 17 #include "llvm/ADT/SetVector.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/Statistic.h" 20 #include "llvm/Analysis/LoopInfo.h" 21 #include "llvm/Analysis/LoopPass.h" 22 #include "llvm/IR/BasicBlock.h" 23 #include "llvm/IR/DerivedTypes.h" 24 #include "llvm/IR/IRBuilder.h" 25 #include "llvm/IR/Instruction.h" 26 #include "llvm/IR/Instructions.h" 27 #include "llvm/IR/IntrinsicInst.h" 28 #include "llvm/IR/Intrinsics.h" 29 #include "llvm/IR/IntrinsicsHexagon.h" 30 #include "llvm/IR/Use.h" 31 #include "llvm/IR/User.h" 32 #include "llvm/IR/Value.h" 33 #include "llvm/InitializePasses.h" 34 #include "llvm/Pass.h" 35 #include "llvm/Support/Casting.h" 36 #include "llvm/Support/CommandLine.h" 37 #include "llvm/Support/Compiler.h" 38 #include "llvm/Support/Debug.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include "llvm/Transforms/Scalar.h" 41 #include "llvm/Transforms/Utils.h" 42 #include <algorithm> 43 #include <cassert> 44 #include <cstddef> 45 #include <map> 46 #include <memory> 47 #include <set> 48 49 using namespace llvm; 50 51 #define DEBUG_TYPE "hexagon-vlcr" 52 53 STATISTIC(HexagonNumVectorLoopCarriedReuse, 54 "Number of values that were reused from a previous iteration."); 55 56 static cl::opt<int> HexagonVLCRIterationLim("hexagon-vlcr-iteration-lim", 57 cl::Hidden, 58 cl::desc("Maximum distance of loop carried dependences that are handled"), 59 cl::init(2), cl::ZeroOrMore); 60 61 namespace llvm { 62 63 void initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PassRegistry &); 64 Pass *createHexagonVectorLoopCarriedReuseLegacyPass(); 65 66 } // end namespace llvm 67 68 namespace { 69 70 // See info about DepChain in the comments at the top of this file. 71 using ChainOfDependences = SmallVector<Instruction *, 4>; 72 73 class DepChain { 74 ChainOfDependences Chain; 75 76 public: 77 bool isIdentical(DepChain &Other) const { 78 if (Other.size() != size()) 79 return false; 80 ChainOfDependences &OtherChain = Other.getChain(); 81 for (int i = 0; i < size(); ++i) { 82 if (Chain[i] != OtherChain[i]) 83 return false; 84 } 85 return true; 86 } 87 88 ChainOfDependences &getChain() { 89 return Chain; 90 } 91 92 int size() const { 93 return Chain.size(); 94 } 95 96 void clear() { 97 Chain.clear(); 98 } 99 100 void push_back(Instruction *I) { 101 Chain.push_back(I); 102 } 103 104 int iterations() const { 105 return size() - 1; 106 } 107 108 Instruction *front() const { 109 return Chain.front(); 110 } 111 112 Instruction *back() const { 113 return Chain.back(); 114 } 115 116 Instruction *&operator[](const int index) { 117 return Chain[index]; 118 } 119 120 friend raw_ostream &operator<< (raw_ostream &OS, const DepChain &D); 121 }; 122 123 LLVM_ATTRIBUTE_UNUSED 124 raw_ostream &operator<<(raw_ostream &OS, const DepChain &D) { 125 const ChainOfDependences &CD = D.Chain; 126 int ChainSize = CD.size(); 127 OS << "**DepChain Start::**\n"; 128 for (int i = 0; i < ChainSize -1; ++i) { 129 OS << *(CD[i]) << " -->\n"; 130 } 131 OS << *CD[ChainSize-1] << "\n"; 132 return OS; 133 } 134 135 struct ReuseValue { 136 Instruction *Inst2Replace = nullptr; 137 138 // In the new PHI node that we'll construct this is the value that'll be 139 // used over the backedge. This is the value that gets reused from a 140 // previous iteration. 141 Instruction *BackedgeInst = nullptr; 142 std::map<Instruction *, DepChain *> DepChains; 143 int Iterations = -1; 144 145 ReuseValue() = default; 146 147 void reset() { 148 Inst2Replace = nullptr; 149 BackedgeInst = nullptr; 150 DepChains.clear(); 151 Iterations = -1; 152 } 153 bool isDefined() { return Inst2Replace != nullptr; } 154 }; 155 156 LLVM_ATTRIBUTE_UNUSED 157 raw_ostream &operator<<(raw_ostream &OS, const ReuseValue &RU) { 158 OS << "** ReuseValue ***\n"; 159 OS << "Instruction to Replace: " << *(RU.Inst2Replace) << "\n"; 160 OS << "Backedge Instruction: " << *(RU.BackedgeInst) << "\n"; 161 return OS; 162 } 163 164 class HexagonVectorLoopCarriedReuseLegacyPass : public LoopPass { 165 public: 166 static char ID; 167 168 explicit HexagonVectorLoopCarriedReuseLegacyPass() : LoopPass(ID) { 169 PassRegistry *PR = PassRegistry::getPassRegistry(); 170 initializeHexagonVectorLoopCarriedReuseLegacyPassPass(*PR); 171 } 172 173 StringRef getPassName() const override { 174 return "Hexagon-specific loop carried reuse for HVX vectors"; 175 } 176 177 void getAnalysisUsage(AnalysisUsage &AU) const override { 178 AU.addRequiredID(LoopSimplifyID); 179 AU.addRequiredID(LCSSAID); 180 AU.addPreservedID(LCSSAID); 181 AU.setPreservesCFG(); 182 } 183 184 bool runOnLoop(Loop *L, LPPassManager &LPM) override; 185 }; 186 187 class HexagonVectorLoopCarriedReuse { 188 public: 189 HexagonVectorLoopCarriedReuse(Loop *L) : CurLoop(L){}; 190 191 bool run(); 192 193 private: 194 SetVector<DepChain *> Dependences; 195 std::set<Instruction *> ReplacedInsts; 196 Loop *CurLoop; 197 ReuseValue ReuseCandidate; 198 199 bool doVLCR(); 200 void findLoopCarriedDeps(); 201 void findValueToReuse(); 202 void findDepChainFromPHI(Instruction *I, DepChain &D); 203 void reuseValue(); 204 Value *findValueInBlock(Value *Op, BasicBlock *BB); 205 DepChain *getDepChainBtwn(Instruction *I1, Instruction *I2, int Iters); 206 bool isEquivalentOperation(Instruction *I1, Instruction *I2); 207 bool canReplace(Instruction *I); 208 bool isCallInstCommutative(CallInst *C); 209 }; 210 211 } // end anonymous namespace 212 213 char HexagonVectorLoopCarriedReuseLegacyPass::ID = 0; 214 215 INITIALIZE_PASS_BEGIN(HexagonVectorLoopCarriedReuseLegacyPass, "hexagon-vlcr", 216 "Hexagon-specific predictive commoning for HVX vectors", 217 false, false) 218 INITIALIZE_PASS_DEPENDENCY(LoopSimplify) 219 INITIALIZE_PASS_DEPENDENCY(LCSSAWrapperPass) 220 INITIALIZE_PASS_END(HexagonVectorLoopCarriedReuseLegacyPass, "hexagon-vlcr", 221 "Hexagon-specific predictive commoning for HVX vectors", 222 false, false) 223 224 PreservedAnalyses 225 HexagonVectorLoopCarriedReusePass::run(Loop &L, LoopAnalysisManager &LAM, 226 LoopStandardAnalysisResults &AR, 227 LPMUpdater &U) { 228 HexagonVectorLoopCarriedReuse Vlcr(&L); 229 if (!Vlcr.run()) 230 return PreservedAnalyses::all(); 231 PreservedAnalyses PA; 232 PA.preserveSet<CFGAnalyses>(); 233 return PA; 234 } 235 236 bool HexagonVectorLoopCarriedReuseLegacyPass::runOnLoop(Loop *L, 237 LPPassManager &LPM) { 238 if (skipLoop(L)) 239 return false; 240 HexagonVectorLoopCarriedReuse Vlcr(L); 241 return Vlcr.run(); 242 } 243 244 bool HexagonVectorLoopCarriedReuse::run() { 245 if (!CurLoop->getLoopPreheader()) 246 return false; 247 248 // Work only on innermost loops. 249 if (!CurLoop->getSubLoops().empty()) 250 return false; 251 252 // Work only on single basic blocks loops. 253 if (CurLoop->getNumBlocks() != 1) 254 return false; 255 256 return doVLCR(); 257 } 258 259 bool HexagonVectorLoopCarriedReuse::isCallInstCommutative(CallInst *C) { 260 switch (C->getCalledFunction()->getIntrinsicID()) { 261 case Intrinsic::hexagon_V6_vaddb: 262 case Intrinsic::hexagon_V6_vaddb_128B: 263 case Intrinsic::hexagon_V6_vaddh: 264 case Intrinsic::hexagon_V6_vaddh_128B: 265 case Intrinsic::hexagon_V6_vaddw: 266 case Intrinsic::hexagon_V6_vaddw_128B: 267 case Intrinsic::hexagon_V6_vaddubh: 268 case Intrinsic::hexagon_V6_vaddubh_128B: 269 case Intrinsic::hexagon_V6_vadduhw: 270 case Intrinsic::hexagon_V6_vadduhw_128B: 271 case Intrinsic::hexagon_V6_vaddhw: 272 case Intrinsic::hexagon_V6_vaddhw_128B: 273 case Intrinsic::hexagon_V6_vmaxb: 274 case Intrinsic::hexagon_V6_vmaxb_128B: 275 case Intrinsic::hexagon_V6_vmaxh: 276 case Intrinsic::hexagon_V6_vmaxh_128B: 277 case Intrinsic::hexagon_V6_vmaxw: 278 case Intrinsic::hexagon_V6_vmaxw_128B: 279 case Intrinsic::hexagon_V6_vmaxub: 280 case Intrinsic::hexagon_V6_vmaxub_128B: 281 case Intrinsic::hexagon_V6_vmaxuh: 282 case Intrinsic::hexagon_V6_vmaxuh_128B: 283 case Intrinsic::hexagon_V6_vminub: 284 case Intrinsic::hexagon_V6_vminub_128B: 285 case Intrinsic::hexagon_V6_vminuh: 286 case Intrinsic::hexagon_V6_vminuh_128B: 287 case Intrinsic::hexagon_V6_vminb: 288 case Intrinsic::hexagon_V6_vminb_128B: 289 case Intrinsic::hexagon_V6_vminh: 290 case Intrinsic::hexagon_V6_vminh_128B: 291 case Intrinsic::hexagon_V6_vminw: 292 case Intrinsic::hexagon_V6_vminw_128B: 293 case Intrinsic::hexagon_V6_vmpyub: 294 case Intrinsic::hexagon_V6_vmpyub_128B: 295 case Intrinsic::hexagon_V6_vmpyuh: 296 case Intrinsic::hexagon_V6_vmpyuh_128B: 297 case Intrinsic::hexagon_V6_vavgub: 298 case Intrinsic::hexagon_V6_vavgub_128B: 299 case Intrinsic::hexagon_V6_vavgh: 300 case Intrinsic::hexagon_V6_vavgh_128B: 301 case Intrinsic::hexagon_V6_vavguh: 302 case Intrinsic::hexagon_V6_vavguh_128B: 303 case Intrinsic::hexagon_V6_vavgw: 304 case Intrinsic::hexagon_V6_vavgw_128B: 305 case Intrinsic::hexagon_V6_vavgb: 306 case Intrinsic::hexagon_V6_vavgb_128B: 307 case Intrinsic::hexagon_V6_vavguw: 308 case Intrinsic::hexagon_V6_vavguw_128B: 309 case Intrinsic::hexagon_V6_vabsdiffh: 310 case Intrinsic::hexagon_V6_vabsdiffh_128B: 311 case Intrinsic::hexagon_V6_vabsdiffub: 312 case Intrinsic::hexagon_V6_vabsdiffub_128B: 313 case Intrinsic::hexagon_V6_vabsdiffuh: 314 case Intrinsic::hexagon_V6_vabsdiffuh_128B: 315 case Intrinsic::hexagon_V6_vabsdiffw: 316 case Intrinsic::hexagon_V6_vabsdiffw_128B: 317 return true; 318 default: 319 return false; 320 } 321 } 322 323 bool HexagonVectorLoopCarriedReuse::isEquivalentOperation(Instruction *I1, 324 Instruction *I2) { 325 if (!I1->isSameOperationAs(I2)) 326 return false; 327 // This check is in place specifically for intrinsics. isSameOperationAs will 328 // return two for any two hexagon intrinsics because they are essentially the 329 // same instruciton (CallInst). We need to scratch the surface to see if they 330 // are calls to the same function. 331 if (CallInst *C1 = dyn_cast<CallInst>(I1)) { 332 if (CallInst *C2 = dyn_cast<CallInst>(I2)) { 333 if (C1->getCalledFunction() != C2->getCalledFunction()) 334 return false; 335 } 336 } 337 338 // If both the Instructions are of Vector Type and any of the element 339 // is integer constant, check their values too for equivalence. 340 if (I1->getType()->isVectorTy() && I2->getType()->isVectorTy()) { 341 unsigned NumOperands = I1->getNumOperands(); 342 for (unsigned i = 0; i < NumOperands; ++i) { 343 ConstantInt *C1 = dyn_cast<ConstantInt>(I1->getOperand(i)); 344 ConstantInt *C2 = dyn_cast<ConstantInt>(I2->getOperand(i)); 345 if(!C1) continue; 346 assert(C2); 347 if (C1->getSExtValue() != C2->getSExtValue()) 348 return false; 349 } 350 } 351 352 return true; 353 } 354 355 bool HexagonVectorLoopCarriedReuse::canReplace(Instruction *I) { 356 const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I); 357 if (!II) 358 return true; 359 360 switch (II->getIntrinsicID()) { 361 case Intrinsic::hexagon_V6_hi: 362 case Intrinsic::hexagon_V6_lo: 363 case Intrinsic::hexagon_V6_hi_128B: 364 case Intrinsic::hexagon_V6_lo_128B: 365 LLVM_DEBUG(dbgs() << "Not considering for reuse: " << *II << "\n"); 366 return false; 367 default: 368 return true; 369 } 370 } 371 void HexagonVectorLoopCarriedReuse::findValueToReuse() { 372 for (auto *D : Dependences) { 373 LLVM_DEBUG(dbgs() << "Processing dependence " << *(D->front()) << "\n"); 374 if (D->iterations() > HexagonVLCRIterationLim) { 375 LLVM_DEBUG( 376 dbgs() 377 << ".. Skipping because number of iterations > than the limit\n"); 378 continue; 379 } 380 381 PHINode *PN = cast<PHINode>(D->front()); 382 Instruction *BEInst = D->back(); 383 int Iters = D->iterations(); 384 BasicBlock *BB = PN->getParent(); 385 LLVM_DEBUG(dbgs() << "Checking if any uses of " << *PN 386 << " can be reused\n"); 387 388 SmallVector<Instruction *, 4> PNUsers; 389 for (auto UI = PN->use_begin(), E = PN->use_end(); UI != E; ++UI) { 390 Use &U = *UI; 391 Instruction *User = cast<Instruction>(U.getUser()); 392 393 if (User->getParent() != BB) 394 continue; 395 if (ReplacedInsts.count(User)) { 396 LLVM_DEBUG(dbgs() << *User 397 << " has already been replaced. Skipping...\n"); 398 continue; 399 } 400 if (isa<PHINode>(User)) 401 continue; 402 if (User->mayHaveSideEffects()) 403 continue; 404 if (!canReplace(User)) 405 continue; 406 407 PNUsers.push_back(User); 408 } 409 LLVM_DEBUG(dbgs() << PNUsers.size() << " use(s) of the PHI in the block\n"); 410 411 // For each interesting use I of PN, find an Instruction BEUser that 412 // performs the same operation as I on BEInst and whose other operands, 413 // if any, can also be rematerialized in OtherBB. We stop when we find the 414 // first such Instruction BEUser. This is because once BEUser is 415 // rematerialized in OtherBB, we may find more such "fixup" opportunities 416 // in this block. So, we'll start over again. 417 for (Instruction *I : PNUsers) { 418 for (auto UI = BEInst->use_begin(), E = BEInst->use_end(); UI != E; 419 ++UI) { 420 Use &U = *UI; 421 Instruction *BEUser = cast<Instruction>(U.getUser()); 422 423 if (BEUser->getParent() != BB) 424 continue; 425 if (!isEquivalentOperation(I, BEUser)) 426 continue; 427 428 int NumOperands = I->getNumOperands(); 429 430 // Take operands of each PNUser one by one and try to find DepChain 431 // with every operand of the BEUser. If any of the operands of BEUser 432 // has DepChain with current operand of the PNUser, break the matcher 433 // loop. Keep doing this for Every PNUser operand. If PNUser operand 434 // does not have DepChain with any of the BEUser operand, break the 435 // outer matcher loop, mark the BEUser as null and reset the ReuseCandidate. 436 // This ensures that DepChain exist for all the PNUser operand with 437 // BEUser operand. This also ensures that DepChains are independent of 438 // the positions in PNUser and BEUser. 439 std::map<Instruction *, DepChain *> DepChains; 440 CallInst *C1 = dyn_cast<CallInst>(I); 441 if ((I && I->isCommutative()) || (C1 && isCallInstCommutative(C1))) { 442 bool Found = false; 443 for (int OpNo = 0; OpNo < NumOperands; ++OpNo) { 444 Value *Op = I->getOperand(OpNo); 445 Instruction *OpInst = dyn_cast<Instruction>(Op); 446 Found = false; 447 for (int T = 0; T < NumOperands; ++T) { 448 Value *BEOp = BEUser->getOperand(T); 449 Instruction *BEOpInst = dyn_cast<Instruction>(BEOp); 450 if (!OpInst && !BEOpInst) { 451 if (Op == BEOp) { 452 Found = true; 453 break; 454 } 455 } 456 457 if ((OpInst && !BEOpInst) || (!OpInst && BEOpInst)) 458 continue; 459 460 DepChain *D = getDepChainBtwn(OpInst, BEOpInst, Iters); 461 462 if (D) { 463 Found = true; 464 DepChains[OpInst] = D; 465 break; 466 } 467 } 468 if (!Found) { 469 BEUser = nullptr; 470 break; 471 } 472 } 473 } else { 474 475 for (int OpNo = 0; OpNo < NumOperands; ++OpNo) { 476 Value *Op = I->getOperand(OpNo); 477 Value *BEOp = BEUser->getOperand(OpNo); 478 479 Instruction *OpInst = dyn_cast<Instruction>(Op); 480 if (!OpInst) { 481 if (Op == BEOp) 482 continue; 483 // Do not allow reuse to occur when the operands may be different 484 // values. 485 BEUser = nullptr; 486 break; 487 } 488 489 Instruction *BEOpInst = dyn_cast<Instruction>(BEOp); 490 DepChain *D = getDepChainBtwn(OpInst, BEOpInst, Iters); 491 492 if (D) { 493 DepChains[OpInst] = D; 494 } else { 495 BEUser = nullptr; 496 break; 497 } 498 } 499 } 500 if (BEUser) { 501 LLVM_DEBUG(dbgs() << "Found Value for reuse.\n"); 502 ReuseCandidate.Inst2Replace = I; 503 ReuseCandidate.BackedgeInst = BEUser; 504 ReuseCandidate.DepChains = DepChains; 505 ReuseCandidate.Iterations = Iters; 506 return; 507 } 508 ReuseCandidate.reset(); 509 } 510 } 511 } 512 ReuseCandidate.reset(); 513 } 514 515 Value *HexagonVectorLoopCarriedReuse::findValueInBlock(Value *Op, 516 BasicBlock *BB) { 517 PHINode *PN = dyn_cast<PHINode>(Op); 518 assert(PN); 519 Value *ValueInBlock = PN->getIncomingValueForBlock(BB); 520 return ValueInBlock; 521 } 522 523 void HexagonVectorLoopCarriedReuse::reuseValue() { 524 LLVM_DEBUG(dbgs() << ReuseCandidate); 525 Instruction *Inst2Replace = ReuseCandidate.Inst2Replace; 526 Instruction *BEInst = ReuseCandidate.BackedgeInst; 527 int NumOperands = Inst2Replace->getNumOperands(); 528 std::map<Instruction *, DepChain *> &DepChains = ReuseCandidate.DepChains; 529 int Iterations = ReuseCandidate.Iterations; 530 BasicBlock *LoopPH = CurLoop->getLoopPreheader(); 531 assert(!DepChains.empty() && "No DepChains"); 532 LLVM_DEBUG(dbgs() << "reuseValue is making the following changes\n"); 533 534 SmallVector<Instruction *, 4> InstsInPreheader; 535 for (int i = 0; i < Iterations; ++i) { 536 Instruction *InstInPreheader = Inst2Replace->clone(); 537 SmallVector<Value *, 4> Ops; 538 for (int j = 0; j < NumOperands; ++j) { 539 Instruction *I = dyn_cast<Instruction>(Inst2Replace->getOperand(j)); 540 if (!I) 541 continue; 542 // Get the DepChain corresponding to this operand. 543 DepChain &D = *DepChains[I]; 544 // Get the PHI for the iteration number and find 545 // the incoming value from the Loop Preheader for 546 // that PHI. 547 Value *ValInPreheader = findValueInBlock(D[i], LoopPH); 548 InstInPreheader->setOperand(j, ValInPreheader); 549 } 550 InstsInPreheader.push_back(InstInPreheader); 551 InstInPreheader->setName(Inst2Replace->getName() + ".hexagon.vlcr"); 552 InstInPreheader->insertBefore(LoopPH->getTerminator()); 553 LLVM_DEBUG(dbgs() << "Added " << *InstInPreheader << " to " 554 << LoopPH->getName() << "\n"); 555 } 556 BasicBlock *BB = BEInst->getParent(); 557 IRBuilder<> IRB(BB); 558 IRB.SetInsertPoint(BB->getFirstNonPHI()); 559 Value *BEVal = BEInst; 560 PHINode *NewPhi; 561 for (int i = Iterations-1; i >=0 ; --i) { 562 Instruction *InstInPreheader = InstsInPreheader[i]; 563 NewPhi = IRB.CreatePHI(InstInPreheader->getType(), 2); 564 NewPhi->addIncoming(InstInPreheader, LoopPH); 565 NewPhi->addIncoming(BEVal, BB); 566 LLVM_DEBUG(dbgs() << "Adding " << *NewPhi << " to " << BB->getName() 567 << "\n"); 568 BEVal = NewPhi; 569 } 570 // We are in LCSSA form. So, a value defined inside the Loop is used only 571 // inside the loop. So, the following is safe. 572 Inst2Replace->replaceAllUsesWith(NewPhi); 573 ReplacedInsts.insert(Inst2Replace); 574 ++HexagonNumVectorLoopCarriedReuse; 575 } 576 577 bool HexagonVectorLoopCarriedReuse::doVLCR() { 578 assert(CurLoop->getSubLoops().empty() && 579 "Can do VLCR on the innermost loop only"); 580 assert((CurLoop->getNumBlocks() == 1) && 581 "Can do VLCR only on single block loops"); 582 583 bool Changed = false; 584 bool Continue; 585 586 LLVM_DEBUG(dbgs() << "Working on Loop: " << *CurLoop->getHeader() << "\n"); 587 do { 588 // Reset datastructures. 589 Dependences.clear(); 590 Continue = false; 591 592 findLoopCarriedDeps(); 593 findValueToReuse(); 594 if (ReuseCandidate.isDefined()) { 595 reuseValue(); 596 Changed = true; 597 Continue = true; 598 } 599 llvm::for_each(Dependences, std::default_delete<DepChain>()); 600 } while (Continue); 601 return Changed; 602 } 603 604 void HexagonVectorLoopCarriedReuse::findDepChainFromPHI(Instruction *I, 605 DepChain &D) { 606 PHINode *PN = dyn_cast<PHINode>(I); 607 if (!PN) { 608 D.push_back(I); 609 return; 610 } else { 611 auto NumIncomingValues = PN->getNumIncomingValues(); 612 if (NumIncomingValues != 2) { 613 D.clear(); 614 return; 615 } 616 617 BasicBlock *BB = PN->getParent(); 618 if (BB != CurLoop->getHeader()) { 619 D.clear(); 620 return; 621 } 622 623 Value *BEVal = PN->getIncomingValueForBlock(BB); 624 Instruction *BEInst = dyn_cast<Instruction>(BEVal); 625 // This is a single block loop with a preheader, so at least 626 // one value should come over the backedge. 627 assert(BEInst && "There should be a value over the backedge"); 628 629 Value *PreHdrVal = 630 PN->getIncomingValueForBlock(CurLoop->getLoopPreheader()); 631 if(!PreHdrVal || !isa<Instruction>(PreHdrVal)) { 632 D.clear(); 633 return; 634 } 635 D.push_back(PN); 636 findDepChainFromPHI(BEInst, D); 637 } 638 } 639 640 DepChain *HexagonVectorLoopCarriedReuse::getDepChainBtwn(Instruction *I1, 641 Instruction *I2, 642 int Iters) { 643 for (auto *D : Dependences) { 644 if (D->front() == I1 && D->back() == I2 && D->iterations() == Iters) 645 return D; 646 } 647 return nullptr; 648 } 649 650 void HexagonVectorLoopCarriedReuse::findLoopCarriedDeps() { 651 BasicBlock *BB = CurLoop->getHeader(); 652 for (auto I = BB->begin(), E = BB->end(); I != E && isa<PHINode>(I); ++I) { 653 auto *PN = cast<PHINode>(I); 654 if (!isa<VectorType>(PN->getType())) 655 continue; 656 657 DepChain *D = new DepChain(); 658 findDepChainFromPHI(PN, *D); 659 if (D->size() != 0) 660 Dependences.insert(D); 661 else 662 delete D; 663 } 664 LLVM_DEBUG(dbgs() << "Found " << Dependences.size() << " dependences\n"); 665 LLVM_DEBUG(for (size_t i = 0; i < Dependences.size(); 666 ++i) { dbgs() << *Dependences[i] << "\n"; }); 667 } 668 669 Pass *llvm::createHexagonVectorLoopCarriedReuseLegacyPass() { 670 return new HexagonVectorLoopCarriedReuseLegacyPass(); 671 } 672