LLVM 23.0.0git
HexagonVectorLoopCarriedReuse.cpp
Go to the documentation of this file.
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
17#include "Hexagon.h"
18#include "llvm/ADT/SetVector.h"
20#include "llvm/ADT/Statistic.h"
24#include "llvm/IR/BasicBlock.h"
26#include "llvm/IR/IRBuilder.h"
27#include "llvm/IR/Instruction.h"
30#include "llvm/IR/Intrinsics.h"
31#include "llvm/IR/IntrinsicsHexagon.h"
32#include "llvm/IR/Use.h"
33#include "llvm/IR/Value.h"
35#include "llvm/Pass.h"
39#include "llvm/Support/Debug.h"
43#include <cassert>
44#include <map>
45#include <memory>
46#include <set>
47
48using namespace llvm;
49
50#define DEBUG_TYPE "hexagon-vlcr"
51
52STATISTIC(HexagonNumVectorLoopCarriedReuse,
53 "Number of values that were reused from a previous iteration.");
54
56 "hexagon-vlcr-iteration-lim", cl::Hidden,
57 cl::desc("Maximum distance of loop carried dependences that are handled"),
58 cl::init(2));
59
60namespace {
61
62 // See info about DepChain in the comments at the top of this file.
63 using ChainOfDependences = SmallVector<Instruction *, 4>;
64
65 class DepChain {
66 ChainOfDependences Chain;
67
68 public:
69 bool isIdentical(DepChain &Other) const {
70 if (Other.size() != size())
71 return false;
72 ChainOfDependences &OtherChain = Other.getChain();
73 for (int i = 0; i < size(); ++i) {
74 if (Chain[i] != OtherChain[i])
75 return false;
76 }
77 return true;
78 }
79
80 ChainOfDependences &getChain() {
81 return Chain;
82 }
83
84 int size() const {
85 return Chain.size();
86 }
87
88 void clear() {
89 Chain.clear();
90 }
91
92 void push_back(Instruction *I) {
93 Chain.push_back(I);
94 }
95
96 int iterations() const {
97 return size() - 1;
98 }
99
100 Instruction *front() const {
101 return Chain.front();
102 }
103
104 Instruction *back() const {
105 return Chain.back();
106 }
107
108 Instruction *&operator[](const int index) {
109 return Chain[index];
110 }
111
112 friend raw_ostream &operator<< (raw_ostream &OS, const DepChain &D);
113 };
114
115 [[maybe_unused]]
116 raw_ostream &operator<<(raw_ostream &OS, const DepChain &D) {
117 const ChainOfDependences &CD = D.Chain;
118 int ChainSize = CD.size();
119 OS << "**DepChain Start::**\n";
120 for (int i = 0; i < ChainSize -1; ++i) {
121 OS << *(CD[i]) << " -->\n";
122 }
123 OS << *CD[ChainSize-1] << "\n";
124 return OS;
125 }
126
127 struct ReuseValue {
128 Instruction *Inst2Replace = nullptr;
129
130 // In the new PHI node that we'll construct this is the value that'll be
131 // used over the backedge. This is the value that gets reused from a
132 // previous iteration.
133 Instruction *BackedgeInst = nullptr;
134 std::map<Instruction *, DepChain *> DepChains;
135 int Iterations = -1;
136
137 ReuseValue() = default;
138
139 void reset() {
140 Inst2Replace = nullptr;
141 BackedgeInst = nullptr;
142 DepChains.clear();
143 Iterations = -1;
144 }
145 bool isDefined() { return Inst2Replace != nullptr; }
146 };
147
148 [[maybe_unused]]
149 raw_ostream &operator<<(raw_ostream &OS, const ReuseValue &RU) {
150 OS << "** ReuseValue ***\n";
151 OS << "Instruction to Replace: " << *(RU.Inst2Replace) << "\n";
152 OS << "Backedge Instruction: " << *(RU.BackedgeInst) << "\n";
153 return OS;
154 }
155
156 class HexagonVectorLoopCarriedReuseLegacyPass : public LoopPass {
157 public:
158 static char ID;
159
160 explicit HexagonVectorLoopCarriedReuseLegacyPass() : LoopPass(ID) {}
161
162 StringRef getPassName() const override {
163 return "Hexagon-specific loop carried reuse for HVX vectors";
164 }
165
166 void getAnalysisUsage(AnalysisUsage &AU) const override {
169 AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
171 AU.setPreservesCFG();
172 }
173
174 bool runOnLoop(Loop *L, LPPassManager &LPM) override;
175 };
176
177 class HexagonVectorLoopCarriedReuse {
178 public:
179 HexagonVectorLoopCarriedReuse(Loop *L, OptimizationRemarkEmitter &ORE)
180 : CurLoop(L), ORE(ORE) {};
181
182 bool run();
183
184 private:
185 SetVector<DepChain *> Dependences;
186 std::set<Instruction *> ReplacedInsts;
187 Loop *CurLoop;
188 OptimizationRemarkEmitter &ORE;
189 ReuseValue ReuseCandidate;
190
191 bool doVLCR();
192 void findLoopCarriedDeps();
193 void findValueToReuse();
194 void findDepChainFromPHI(Instruction *I, DepChain &D);
195 void reuseValue();
196 Value *findValueInBlock(Value *Op, BasicBlock *BB);
197 DepChain *getDepChainBtwn(Instruction *I1, Instruction *I2, int Iters);
198 bool isEquivalentOperation(Instruction *I1, Instruction *I2);
199 bool canReplace(Instruction *I);
200 bool isCallInstCommutative(CallInst *C);
201 };
202
203} // end anonymous namespace
204
205char HexagonVectorLoopCarriedReuseLegacyPass::ID = 0;
206
207INITIALIZE_PASS_BEGIN(HexagonVectorLoopCarriedReuseLegacyPass, "hexagon-vlcr",
208 "Hexagon-specific predictive commoning for HVX vectors",
209 false, false)
210INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
211INITIALIZE_PASS_DEPENDENCY(LCSSAWrapperPass)
213INITIALIZE_PASS_END(HexagonVectorLoopCarriedReuseLegacyPass, "hexagon-vlcr",
214 "Hexagon-specific predictive commoning for HVX vectors",
216
220 LPMUpdater &U) {
221 OptimizationRemarkEmitter ORE(L.getHeader()->getParent());
222 HexagonVectorLoopCarriedReuse Vlcr(&L, ORE);
223 if (!Vlcr.run())
224 return PreservedAnalyses::all();
227 return PA;
228}
229
230bool HexagonVectorLoopCarriedReuseLegacyPass::runOnLoop(Loop *L,
231 LPPassManager &LPM) {
232 if (skipLoop(L))
233 return false;
234 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
235 HexagonVectorLoopCarriedReuse Vlcr(L, ORE);
236 return Vlcr.run();
237}
238
239bool HexagonVectorLoopCarriedReuse::run() {
240 if (!CurLoop->getLoopPreheader()) {
241 ORE.emit([&]() {
242 return OptimizationRemarkMissed(DEBUG_TYPE, "NoPreheader",
243 CurLoop->getStartLoc(),
244 CurLoop->getHeader())
245 << "loop has no preheader";
246 });
247 return false;
248 }
249
250 // Work only on innermost loops.
251 if (!CurLoop->getSubLoops().empty()) {
252 ORE.emit([&]() {
253 return OptimizationRemarkMissed(DEBUG_TYPE, "NotInnermostLoop",
254 CurLoop->getStartLoc(),
255 CurLoop->getHeader())
256 << "pass only works on innermost loops";
257 });
258 return false;
259 }
260
261 // Work only on single basic blocks loops.
262 if (CurLoop->getNumBlocks() != 1) {
263 ORE.emit([&]() {
264 return OptimizationRemarkMissed(DEBUG_TYPE, "MultipleBlocks",
265 CurLoop->getStartLoc(),
266 CurLoop->getHeader())
267 << "loop has multiple basic blocks";
268 });
269 return false;
270 }
271
272 return doVLCR();
273}
274
275bool HexagonVectorLoopCarriedReuse::isCallInstCommutative(CallInst *C) {
276 switch (C->getCalledFunction()->getIntrinsicID()) {
277 case Intrinsic::hexagon_V6_vaddb:
278 case Intrinsic::hexagon_V6_vaddb_128B:
279 case Intrinsic::hexagon_V6_vaddh:
280 case Intrinsic::hexagon_V6_vaddh_128B:
281 case Intrinsic::hexagon_V6_vaddw:
282 case Intrinsic::hexagon_V6_vaddw_128B:
283 case Intrinsic::hexagon_V6_vaddubh:
284 case Intrinsic::hexagon_V6_vaddubh_128B:
285 case Intrinsic::hexagon_V6_vadduhw:
286 case Intrinsic::hexagon_V6_vadduhw_128B:
287 case Intrinsic::hexagon_V6_vaddhw:
288 case Intrinsic::hexagon_V6_vaddhw_128B:
289 case Intrinsic::hexagon_V6_vmaxb:
290 case Intrinsic::hexagon_V6_vmaxb_128B:
291 case Intrinsic::hexagon_V6_vmaxh:
292 case Intrinsic::hexagon_V6_vmaxh_128B:
293 case Intrinsic::hexagon_V6_vmaxw:
294 case Intrinsic::hexagon_V6_vmaxw_128B:
295 case Intrinsic::hexagon_V6_vmaxub:
296 case Intrinsic::hexagon_V6_vmaxub_128B:
297 case Intrinsic::hexagon_V6_vmaxuh:
298 case Intrinsic::hexagon_V6_vmaxuh_128B:
299 case Intrinsic::hexagon_V6_vminub:
300 case Intrinsic::hexagon_V6_vminub_128B:
301 case Intrinsic::hexagon_V6_vminuh:
302 case Intrinsic::hexagon_V6_vminuh_128B:
303 case Intrinsic::hexagon_V6_vminb:
304 case Intrinsic::hexagon_V6_vminb_128B:
305 case Intrinsic::hexagon_V6_vminh:
306 case Intrinsic::hexagon_V6_vminh_128B:
307 case Intrinsic::hexagon_V6_vminw:
308 case Intrinsic::hexagon_V6_vminw_128B:
309 case Intrinsic::hexagon_V6_vmpyub:
310 case Intrinsic::hexagon_V6_vmpyub_128B:
311 case Intrinsic::hexagon_V6_vmpyuh:
312 case Intrinsic::hexagon_V6_vmpyuh_128B:
313 case Intrinsic::hexagon_V6_vavgub:
314 case Intrinsic::hexagon_V6_vavgub_128B:
315 case Intrinsic::hexagon_V6_vavgh:
316 case Intrinsic::hexagon_V6_vavgh_128B:
317 case Intrinsic::hexagon_V6_vavguh:
318 case Intrinsic::hexagon_V6_vavguh_128B:
319 case Intrinsic::hexagon_V6_vavgw:
320 case Intrinsic::hexagon_V6_vavgw_128B:
321 case Intrinsic::hexagon_V6_vavgb:
322 case Intrinsic::hexagon_V6_vavgb_128B:
323 case Intrinsic::hexagon_V6_vavguw:
324 case Intrinsic::hexagon_V6_vavguw_128B:
325 case Intrinsic::hexagon_V6_vabsdiffh:
326 case Intrinsic::hexagon_V6_vabsdiffh_128B:
327 case Intrinsic::hexagon_V6_vabsdiffub:
328 case Intrinsic::hexagon_V6_vabsdiffub_128B:
329 case Intrinsic::hexagon_V6_vabsdiffuh:
330 case Intrinsic::hexagon_V6_vabsdiffuh_128B:
331 case Intrinsic::hexagon_V6_vabsdiffw:
332 case Intrinsic::hexagon_V6_vabsdiffw_128B:
333 return true;
334 default:
335 return false;
336 }
337}
338
339bool HexagonVectorLoopCarriedReuse::isEquivalentOperation(Instruction *I1,
340 Instruction *I2) {
341 if (!I1->isSameOperationAs(I2))
342 return false;
343 // This check is in place specifically for intrinsics. isSameOperationAs will
344 // return two for any two hexagon intrinsics because they are essentially the
345 // same instruction (CallInst). We need to scratch the surface to see if they
346 // are calls to the same function.
347 if (CallInst *C1 = dyn_cast<CallInst>(I1)) {
348 if (CallInst *C2 = dyn_cast<CallInst>(I2)) {
349 if (C1->getCalledFunction() != C2->getCalledFunction())
350 return false;
351 }
352 }
353
354 // If both the Instructions are of Vector Type and any of the element
355 // is integer constant, check their values too for equivalence.
356 if (I1->getType()->isVectorTy() && I2->getType()->isVectorTy()) {
357 unsigned NumOperands = I1->getNumOperands();
358 for (unsigned i = 0; i < NumOperands; ++i) {
359 ConstantInt *C1 = dyn_cast<ConstantInt>(I1->getOperand(i));
360 ConstantInt *C2 = dyn_cast<ConstantInt>(I2->getOperand(i));
361 if(!C1) continue;
362 assert(C2);
363 if (C1->getSExtValue() != C2->getSExtValue())
364 return false;
365 }
366 }
367
368 return true;
369}
370
371bool HexagonVectorLoopCarriedReuse::canReplace(Instruction *I) {
372 const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
373 if (!II)
374 return true;
375
376 switch (II->getIntrinsicID()) {
377 case Intrinsic::hexagon_V6_hi:
378 case Intrinsic::hexagon_V6_lo:
379 case Intrinsic::hexagon_V6_hi_128B:
380 case Intrinsic::hexagon_V6_lo_128B:
381 LLVM_DEBUG(dbgs() << "Not considering for reuse: " << *II << "\n");
382 return false;
383 default:
384 return true;
385 }
386}
387void HexagonVectorLoopCarriedReuse::findValueToReuse() {
388 for (auto *D : Dependences) {
389 LLVM_DEBUG(dbgs() << "Processing dependence " << *(D->front()) << "\n");
390 if (D->iterations() > HexagonVLCRIterationLim) {
392 dbgs()
393 << ".. Skipping because number of iterations > than the limit\n");
394 continue;
395 }
396
397 PHINode *PN = cast<PHINode>(D->front());
398 Instruction *BEInst = D->back();
399 int Iters = D->iterations();
400 BasicBlock *BB = PN->getParent();
401 LLVM_DEBUG(dbgs() << "Checking if any uses of " << *PN
402 << " can be reused\n");
403
404 SmallVector<Instruction *, 4> PNUsers;
405 for (Use &U : PN->uses()) {
406 Instruction *User = cast<Instruction>(U.getUser());
407
408 if (User->getParent() != BB)
409 continue;
410 if (ReplacedInsts.count(User)) {
411 LLVM_DEBUG(dbgs() << *User
412 << " has already been replaced. Skipping...\n");
413 continue;
414 }
415 if (isa<PHINode>(User))
416 continue;
417 if (User->mayHaveSideEffects())
418 continue;
419 if (!canReplace(User))
420 continue;
421
422 PNUsers.push_back(User);
423 }
424 LLVM_DEBUG(dbgs() << PNUsers.size() << " use(s) of the PHI in the block\n");
425
426 // For each interesting use I of PN, find an Instruction BEUser that
427 // performs the same operation as I on BEInst and whose other operands,
428 // if any, can also be rematerialized in OtherBB. We stop when we find the
429 // first such Instruction BEUser. This is because once BEUser is
430 // rematerialized in OtherBB, we may find more such "fixup" opportunities
431 // in this block. So, we'll start over again.
432 for (Instruction *I : PNUsers) {
433 for (Use &U : BEInst->uses()) {
434 Instruction *BEUser = cast<Instruction>(U.getUser());
435
436 if (BEUser->getParent() != BB)
437 continue;
438 if (!isEquivalentOperation(I, BEUser))
439 continue;
440
441 int NumOperands = I->getNumOperands();
442
443 // Take operands of each PNUser one by one and try to find DepChain
444 // with every operand of the BEUser. If any of the operands of BEUser
445 // has DepChain with current operand of the PNUser, break the matcher
446 // loop. Keep doing this for Every PNUser operand. If PNUser operand
447 // does not have DepChain with any of the BEUser operand, break the
448 // outer matcher loop, mark the BEUser as null and reset the ReuseCandidate.
449 // This ensures that DepChain exist for all the PNUser operand with
450 // BEUser operand. This also ensures that DepChains are independent of
451 // the positions in PNUser and BEUser.
452 std::map<Instruction *, DepChain *> DepChains;
453 CallInst *C1 = dyn_cast<CallInst>(I);
454 if ((I && I->isCommutative()) || (C1 && isCallInstCommutative(C1))) {
455 bool Found = false;
456 for (int OpNo = 0; OpNo < NumOperands; ++OpNo) {
457 Value *Op = I->getOperand(OpNo);
459 Found = false;
460 for (int T = 0; T < NumOperands; ++T) {
461 Value *BEOp = BEUser->getOperand(T);
462 Instruction *BEOpInst = dyn_cast<Instruction>(BEOp);
463 if (!OpInst && !BEOpInst) {
464 if (Op == BEOp) {
465 Found = true;
466 break;
467 }
468 }
469
470 if ((OpInst && !BEOpInst) || (!OpInst && BEOpInst))
471 continue;
472
473 DepChain *D = getDepChainBtwn(OpInst, BEOpInst, Iters);
474
475 if (D) {
476 Found = true;
477 DepChains[OpInst] = D;
478 break;
479 }
480 }
481 if (!Found) {
482 BEUser = nullptr;
483 break;
484 }
485 }
486 } else {
487
488 for (int OpNo = 0; OpNo < NumOperands; ++OpNo) {
489 Value *Op = I->getOperand(OpNo);
490 Value *BEOp = BEUser->getOperand(OpNo);
491
493 if (!OpInst) {
494 if (Op == BEOp)
495 continue;
496 // Do not allow reuse to occur when the operands may be different
497 // values.
498 BEUser = nullptr;
499 break;
500 }
501
502 Instruction *BEOpInst = dyn_cast<Instruction>(BEOp);
503 DepChain *D = getDepChainBtwn(OpInst, BEOpInst, Iters);
504
505 if (D) {
506 DepChains[OpInst] = D;
507 } else {
508 BEUser = nullptr;
509 break;
510 }
511 }
512 }
513 if (BEUser) {
514 LLVM_DEBUG(dbgs() << "Found Value for reuse.\n");
515 ReuseCandidate.Inst2Replace = I;
516 ReuseCandidate.BackedgeInst = BEUser;
517 ReuseCandidate.DepChains = std::move(DepChains);
518 ReuseCandidate.Iterations = Iters;
519 return;
520 }
521 ReuseCandidate.reset();
522 }
523 }
524 }
525 ReuseCandidate.reset();
526}
527
528Value *HexagonVectorLoopCarriedReuse::findValueInBlock(Value *Op,
529 BasicBlock *BB) {
530 PHINode *PN = dyn_cast<PHINode>(Op);
531 assert(PN);
532 Value *ValueInBlock = PN->getIncomingValueForBlock(BB);
533 return ValueInBlock;
534}
535
536void HexagonVectorLoopCarriedReuse::reuseValue() {
537 LLVM_DEBUG(dbgs() << ReuseCandidate);
538 Instruction *Inst2Replace = ReuseCandidate.Inst2Replace;
539 Instruction *BEInst = ReuseCandidate.BackedgeInst;
540 int NumOperands = Inst2Replace->getNumOperands();
541 std::map<Instruction *, DepChain *> &DepChains = ReuseCandidate.DepChains;
542 int Iterations = ReuseCandidate.Iterations;
543 BasicBlock *LoopPH = CurLoop->getLoopPreheader();
544 assert(!DepChains.empty() && "No DepChains");
545 LLVM_DEBUG(dbgs() << "reuseValue is making the following changes\n");
546
547 SmallVector<Instruction *, 4> InstsInPreheader;
548 for (int i = 0; i < Iterations; ++i) {
549 Instruction *InstInPreheader = Inst2Replace->clone();
550 for (int j = 0; j < NumOperands; ++j) {
551 Instruction *I = dyn_cast<Instruction>(Inst2Replace->getOperand(j));
552 if (!I)
553 continue;
554 // Get the DepChain corresponding to this operand.
555 DepChain &D = *DepChains[I];
556 // Get the PHI for the iteration number and find
557 // the incoming value from the Loop Preheader for
558 // that PHI.
559 Value *ValInPreheader = findValueInBlock(D[i], LoopPH);
560 InstInPreheader->setOperand(j, ValInPreheader);
561 }
562 InstsInPreheader.push_back(InstInPreheader);
563 InstInPreheader->setName(Inst2Replace->getName() + ".hexagon.vlcr");
564 InstInPreheader->insertBefore(LoopPH->getTerminator()->getIterator());
565 LLVM_DEBUG(dbgs() << "Added " << *InstInPreheader << " to "
566 << LoopPH->getName() << "\n");
567 }
568 BasicBlock *BB = BEInst->getParent();
569 IRBuilder<> IRB(BB);
570 IRB.SetInsertPoint(BB, BB->getFirstNonPHIIt());
571 Value *BEVal = BEInst;
572 PHINode *NewPhi;
573 for (int i = Iterations-1; i >=0 ; --i) {
574 Instruction *InstInPreheader = InstsInPreheader[i];
575 NewPhi = IRB.CreatePHI(InstInPreheader->getType(), 2);
576 NewPhi->addIncoming(InstInPreheader, LoopPH);
577 NewPhi->addIncoming(BEVal, BB);
578 LLVM_DEBUG(dbgs() << "Adding " << *NewPhi << " to " << BB->getName()
579 << "\n");
580 BEVal = NewPhi;
581 }
582 // We are in LCSSA form. So, a value defined inside the Loop is used only
583 // inside the loop. So, the following is safe.
584 Inst2Replace->replaceAllUsesWith(NewPhi);
585 ReplacedInsts.insert(Inst2Replace);
586 ++HexagonNumVectorLoopCarriedReuse;
587 ORE.emit([&]() {
588 return OptimizationRemark(DEBUG_TYPE, "VectorReuse",
589 Inst2Replace->getDebugLoc(),
590 Inst2Replace->getParent())
591 << "reused loop-carried vector value";
592 });
593}
594
595bool HexagonVectorLoopCarriedReuse::doVLCR() {
596 assert(CurLoop->getSubLoops().empty() &&
597 "Can do VLCR on the innermost loop only");
598 assert((CurLoop->getNumBlocks() == 1) &&
599 "Can do VLCR only on single block loops");
600
601 bool Changed = false;
602 bool Continue;
603
604 LLVM_DEBUG(dbgs() << "Working on Loop: " << *CurLoop->getHeader() << "\n");
605 do {
606 // Reset datastructures.
607 Dependences.clear();
608 Continue = false;
609
610 findLoopCarriedDeps();
611 findValueToReuse();
612 if (ReuseCandidate.isDefined()) {
613 reuseValue();
614 Changed = true;
615 Continue = true;
616 } else if (!Changed) {
617 ORE.emit([&]() {
618 return OptimizationRemarkMissed(DEBUG_TYPE, "NoCandidateFound",
619 CurLoop->getStartLoc(),
620 CurLoop->getHeader())
621 << "no loop-carried reuse candidate found";
622 });
623 }
624 llvm::for_each(Dependences, std::default_delete<DepChain>());
625 } while (Continue);
626 return Changed;
627}
628
629void HexagonVectorLoopCarriedReuse::findDepChainFromPHI(Instruction *I,
630 DepChain &D) {
631 PHINode *PN = dyn_cast<PHINode>(I);
632 if (!PN) {
633 D.push_back(I);
634 return;
635 } else {
636 auto NumIncomingValues = PN->getNumIncomingValues();
637 if (NumIncomingValues != 2) {
638 D.clear();
639 return;
640 }
641
642 BasicBlock *BB = PN->getParent();
643 if (BB != CurLoop->getHeader()) {
644 D.clear();
645 return;
646 }
647
648 Value *BEVal = PN->getIncomingValueForBlock(BB);
649 Instruction *BEInst = dyn_cast<Instruction>(BEVal);
650 // This is a single block loop with a preheader, so at least
651 // one value should come over the backedge.
652 assert(BEInst && "There should be a value over the backedge");
653
654 Value *PreHdrVal =
656 if(!PreHdrVal || !isa<Instruction>(PreHdrVal)) {
657 D.clear();
658 return;
659 }
660 D.push_back(PN);
661 findDepChainFromPHI(BEInst, D);
662 }
663}
664
665DepChain *HexagonVectorLoopCarriedReuse::getDepChainBtwn(Instruction *I1,
666 Instruction *I2,
667 int Iters) {
668 for (auto *D : Dependences) {
669 if (D->front() == I1 && D->back() == I2 && D->iterations() == Iters)
670 return D;
671 }
672 return nullptr;
673}
674
675void HexagonVectorLoopCarriedReuse::findLoopCarriedDeps() {
676 BasicBlock *BB = CurLoop->getHeader();
677 for (auto I = BB->begin(), E = BB->end(); I != E && isa<PHINode>(I); ++I) {
678 auto *PN = cast<PHINode>(I);
679 if (!isa<VectorType>(PN->getType()))
680 continue;
681
682 DepChain *D = new DepChain();
683 findDepChainFromPHI(PN, *D);
684 if (D->size() != 0)
685 Dependences.insert(D);
686 else
687 delete D;
688 }
689 LLVM_DEBUG(dbgs() << "Found " << Dependences.size() << " dependences\n");
690 LLVM_DEBUG(for (const DepChain *D : Dependences) dbgs() << *D << "\n";);
691}
692
694 return new HexagonVectorLoopCarriedReuseLegacyPass();
695}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
static cl::opt< int > HexagonVLCRIterationLim("hexagon-vlcr-iteration-lim", cl::Hidden, cl::desc("Maximum distance of loop carried dependences that are handled"), cl::init(2))
This defines the Use class.
#define I(x, y, z)
Definition MD5.cpp:57
#define T
uint64_t IntrinsicInst * II
LoopAnalysisManager LAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
LLVM_ABI AnalysisUsage & addRequiredID(const void *ID)
Definition Pass.cpp:284
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:270
iterator end()
Definition BasicBlock.h:474
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:461
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition Constants.h:174
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
unsigned getNumBlocks() const
Get the number of blocks in this loop in constant time.
const std::vector< LoopT * > & getSubLoops() const
Return the loops contained entirely within this loop.
BlockT * getHeader() const
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
DebugLoc getStartLoc() const
Return the debug location of the start of this loop.
Definition LoopInfo.cpp:659
OptimizationRemarkEmitter legacy analysis pass.
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for missed-optimization remarks.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Value * getIncomingValueForBlock(const BasicBlock *BB) const
unsigned getNumIncomingValues() const
Return the number of incoming edges.
Pass interface - Implemented by all 'passes'.
Definition Pass.h:99
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
void setOperand(unsigned i, Value *Val)
Definition User.h:212
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:393
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:552
iterator_range< use_iterator > uses()
Definition Value.h:380
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:318
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Changed
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
@ User
could "use" a pointer
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
LLVM_ABI Instruction & back() const
LLVM_ABI Instruction & front() const
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1731
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1668
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI char & LCSSAID
Definition LCSSA.cpp:526
LLVM_ABI char & LoopSimplifyID
AnalysisManager< Loop, LoopStandardAnalysisResults & > LoopAnalysisManager
The loop analysis manager.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Other
Any other memory.
Definition ModRef.h:68
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Pass * createHexagonVectorLoopCarriedReuseLegacyPass()
@ Continue
Definition DWP.h:26
PreservedAnalyses run(Loop &L, LoopAnalysisManager &LAM, LoopStandardAnalysisResults &AR, LPMUpdater &U)
Run pass over the Loop.
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...