1*9880d681SAndroid Build Coastguard Worker //===------ PPCLoopPreIncPrep.cpp - Loop Pre-Inc. AM Prep. Pass -----------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements a pass to prepare loops for pre-increment addressing
11*9880d681SAndroid Build Coastguard Worker // modes. Additional PHIs are created for loop induction variables used by
12*9880d681SAndroid Build Coastguard Worker // load/store instructions so that the pre-increment forms can be used.
13*9880d681SAndroid Build Coastguard Worker // Generically, this means transforming loops like this:
14*9880d681SAndroid Build Coastguard Worker // for (int i = 0; i < n; ++i)
15*9880d681SAndroid Build Coastguard Worker // array[i] = c;
16*9880d681SAndroid Build Coastguard Worker // to look like this:
17*9880d681SAndroid Build Coastguard Worker // T *p = array[-1];
18*9880d681SAndroid Build Coastguard Worker // for (int i = 0; i < n; ++i)
19*9880d681SAndroid Build Coastguard Worker // *++p = c;
20*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
21*9880d681SAndroid Build Coastguard Worker
22*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "ppc-loop-preinc-prep"
23*9880d681SAndroid Build Coastguard Worker #include "PPC.h"
24*9880d681SAndroid Build Coastguard Worker #include "PPCTargetMachine.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DepthFirstIterator.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallSet.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CodeMetrics.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/InstructionSimplify.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/LoopInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ScalarEvolution.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ScalarEvolutionExpander.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ScalarEvolutionExpressions.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CFG.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Dominators.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/BasicBlockUtils.h"
45*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/Local.h"
46*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/LoopUtils.h"
47*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/ValueMapper.h"
48*9880d681SAndroid Build Coastguard Worker using namespace llvm;
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker // By default, we limit this to creating 16 PHIs (which is a little over half
51*9880d681SAndroid Build Coastguard Worker // of the allocatable register set).
52*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> MaxVars("ppc-preinc-prep-max-vars",
53*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::init(16),
54*9880d681SAndroid Build Coastguard Worker cl::desc("Potential PHI threshold for PPC preinc loop prep"));
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker namespace llvm {
57*9880d681SAndroid Build Coastguard Worker void initializePPCLoopPreIncPrepPass(PassRegistry&);
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker namespace {
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker class PPCLoopPreIncPrep : public FunctionPass {
63*9880d681SAndroid Build Coastguard Worker public:
64*9880d681SAndroid Build Coastguard Worker static char ID; // Pass ID, replacement for typeid
PPCLoopPreIncPrep()65*9880d681SAndroid Build Coastguard Worker PPCLoopPreIncPrep() : FunctionPass(ID), TM(nullptr) {
66*9880d681SAndroid Build Coastguard Worker initializePPCLoopPreIncPrepPass(*PassRegistry::getPassRegistry());
67*9880d681SAndroid Build Coastguard Worker }
PPCLoopPreIncPrep(PPCTargetMachine & TM)68*9880d681SAndroid Build Coastguard Worker PPCLoopPreIncPrep(PPCTargetMachine &TM) : FunctionPass(ID), TM(&TM) {
69*9880d681SAndroid Build Coastguard Worker initializePPCLoopPreIncPrepPass(*PassRegistry::getPassRegistry());
70*9880d681SAndroid Build Coastguard Worker }
71*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const72*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
73*9880d681SAndroid Build Coastguard Worker AU.addPreserved<DominatorTreeWrapperPass>();
74*9880d681SAndroid Build Coastguard Worker AU.addRequired<LoopInfoWrapperPass>();
75*9880d681SAndroid Build Coastguard Worker AU.addPreserved<LoopInfoWrapperPass>();
76*9880d681SAndroid Build Coastguard Worker AU.addRequired<ScalarEvolutionWrapperPass>();
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override;
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker bool runOnLoop(Loop *L);
82*9880d681SAndroid Build Coastguard Worker void simplifyLoopLatch(Loop *L);
83*9880d681SAndroid Build Coastguard Worker bool rotateLoop(Loop *L);
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker private:
86*9880d681SAndroid Build Coastguard Worker PPCTargetMachine *TM;
87*9880d681SAndroid Build Coastguard Worker DominatorTree *DT;
88*9880d681SAndroid Build Coastguard Worker LoopInfo *LI;
89*9880d681SAndroid Build Coastguard Worker ScalarEvolution *SE;
90*9880d681SAndroid Build Coastguard Worker bool PreserveLCSSA;
91*9880d681SAndroid Build Coastguard Worker };
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker char PPCLoopPreIncPrep::ID = 0;
95*9880d681SAndroid Build Coastguard Worker static const char *name = "Prepare loop for pre-inc. addressing modes";
INITIALIZE_PASS_BEGIN(PPCLoopPreIncPrep,DEBUG_TYPE,name,false,false)96*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(PPCLoopPreIncPrep, DEBUG_TYPE, name, false, false)
97*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
98*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
99*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(PPCLoopPreIncPrep, DEBUG_TYPE, name, false, false)
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createPPCLoopPreIncPrepPass(PPCTargetMachine &TM) {
102*9880d681SAndroid Build Coastguard Worker return new PPCLoopPreIncPrep(TM);
103*9880d681SAndroid Build Coastguard Worker }
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker namespace {
106*9880d681SAndroid Build Coastguard Worker struct BucketElement {
BucketElement__anon4a08ee820211::BucketElement107*9880d681SAndroid Build Coastguard Worker BucketElement(const SCEVConstant *O, Instruction *I) : Offset(O), Instr(I) {}
BucketElement__anon4a08ee820211::BucketElement108*9880d681SAndroid Build Coastguard Worker BucketElement(Instruction *I) : Offset(nullptr), Instr(I) {}
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker const SCEVConstant *Offset;
111*9880d681SAndroid Build Coastguard Worker Instruction *Instr;
112*9880d681SAndroid Build Coastguard Worker };
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker struct Bucket {
Bucket__anon4a08ee820211::Bucket115*9880d681SAndroid Build Coastguard Worker Bucket(const SCEV *B, Instruction *I) : BaseSCEV(B),
116*9880d681SAndroid Build Coastguard Worker Elements(1, BucketElement(I)) {}
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker const SCEV *BaseSCEV;
119*9880d681SAndroid Build Coastguard Worker SmallVector<BucketElement, 16> Elements;
120*9880d681SAndroid Build Coastguard Worker };
121*9880d681SAndroid Build Coastguard Worker }
122*9880d681SAndroid Build Coastguard Worker
IsPtrInBounds(Value * BasePtr)123*9880d681SAndroid Build Coastguard Worker static bool IsPtrInBounds(Value *BasePtr) {
124*9880d681SAndroid Build Coastguard Worker Value *StrippedBasePtr = BasePtr;
125*9880d681SAndroid Build Coastguard Worker while (BitCastInst *BC = dyn_cast<BitCastInst>(StrippedBasePtr))
126*9880d681SAndroid Build Coastguard Worker StrippedBasePtr = BC->getOperand(0);
127*9880d681SAndroid Build Coastguard Worker if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(StrippedBasePtr))
128*9880d681SAndroid Build Coastguard Worker return GEP->isInBounds();
129*9880d681SAndroid Build Coastguard Worker
130*9880d681SAndroid Build Coastguard Worker return false;
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker
GetPointerOperand(Value * MemI)133*9880d681SAndroid Build Coastguard Worker static Value *GetPointerOperand(Value *MemI) {
134*9880d681SAndroid Build Coastguard Worker if (LoadInst *LMemI = dyn_cast<LoadInst>(MemI)) {
135*9880d681SAndroid Build Coastguard Worker return LMemI->getPointerOperand();
136*9880d681SAndroid Build Coastguard Worker } else if (StoreInst *SMemI = dyn_cast<StoreInst>(MemI)) {
137*9880d681SAndroid Build Coastguard Worker return SMemI->getPointerOperand();
138*9880d681SAndroid Build Coastguard Worker } else if (IntrinsicInst *IMemI = dyn_cast<IntrinsicInst>(MemI)) {
139*9880d681SAndroid Build Coastguard Worker if (IMemI->getIntrinsicID() == Intrinsic::prefetch)
140*9880d681SAndroid Build Coastguard Worker return IMemI->getArgOperand(0);
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker return 0;
144*9880d681SAndroid Build Coastguard Worker }
145*9880d681SAndroid Build Coastguard Worker
runOnFunction(Function & F)146*9880d681SAndroid Build Coastguard Worker bool PPCLoopPreIncPrep::runOnFunction(Function &F) {
147*9880d681SAndroid Build Coastguard Worker if (skipFunction(F))
148*9880d681SAndroid Build Coastguard Worker return false;
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
151*9880d681SAndroid Build Coastguard Worker SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
152*9880d681SAndroid Build Coastguard Worker auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
153*9880d681SAndroid Build Coastguard Worker DT = DTWP ? &DTWP->getDomTree() : nullptr;
154*9880d681SAndroid Build Coastguard Worker PreserveLCSSA = mustPreserveAnalysisID(LCSSAID);
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker for (auto I = LI->begin(), IE = LI->end(); I != IE; ++I)
159*9880d681SAndroid Build Coastguard Worker for (auto L = df_begin(*I), LE = df_end(*I); L != LE; ++L)
160*9880d681SAndroid Build Coastguard Worker MadeChange |= runOnLoop(*L);
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker return MadeChange;
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker
runOnLoop(Loop * L)165*9880d681SAndroid Build Coastguard Worker bool PPCLoopPreIncPrep::runOnLoop(Loop *L) {
166*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker // Only prep. the inner-most loop
169*9880d681SAndroid Build Coastguard Worker if (!L->empty())
170*9880d681SAndroid Build Coastguard Worker return MadeChange;
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "PIP: Examining: " << *L << "\n");
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker BasicBlock *Header = L->getHeader();
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker const PPCSubtarget *ST =
177*9880d681SAndroid Build Coastguard Worker TM ? TM->getSubtargetImpl(*Header->getParent()) : nullptr;
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker unsigned HeaderLoopPredCount =
180*9880d681SAndroid Build Coastguard Worker std::distance(pred_begin(Header), pred_end(Header));
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker // Collect buckets of comparable addresses used by loads and stores.
183*9880d681SAndroid Build Coastguard Worker SmallVector<Bucket, 16> Buckets;
184*9880d681SAndroid Build Coastguard Worker for (Loop::block_iterator I = L->block_begin(), IE = L->block_end();
185*9880d681SAndroid Build Coastguard Worker I != IE; ++I) {
186*9880d681SAndroid Build Coastguard Worker for (BasicBlock::iterator J = (*I)->begin(), JE = (*I)->end();
187*9880d681SAndroid Build Coastguard Worker J != JE; ++J) {
188*9880d681SAndroid Build Coastguard Worker Value *PtrValue;
189*9880d681SAndroid Build Coastguard Worker Instruction *MemI;
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker if (LoadInst *LMemI = dyn_cast<LoadInst>(J)) {
192*9880d681SAndroid Build Coastguard Worker MemI = LMemI;
193*9880d681SAndroid Build Coastguard Worker PtrValue = LMemI->getPointerOperand();
194*9880d681SAndroid Build Coastguard Worker } else if (StoreInst *SMemI = dyn_cast<StoreInst>(J)) {
195*9880d681SAndroid Build Coastguard Worker MemI = SMemI;
196*9880d681SAndroid Build Coastguard Worker PtrValue = SMemI->getPointerOperand();
197*9880d681SAndroid Build Coastguard Worker } else if (IntrinsicInst *IMemI = dyn_cast<IntrinsicInst>(J)) {
198*9880d681SAndroid Build Coastguard Worker if (IMemI->getIntrinsicID() == Intrinsic::prefetch) {
199*9880d681SAndroid Build Coastguard Worker MemI = IMemI;
200*9880d681SAndroid Build Coastguard Worker PtrValue = IMemI->getArgOperand(0);
201*9880d681SAndroid Build Coastguard Worker } else continue;
202*9880d681SAndroid Build Coastguard Worker } else continue;
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker unsigned PtrAddrSpace = PtrValue->getType()->getPointerAddressSpace();
205*9880d681SAndroid Build Coastguard Worker if (PtrAddrSpace)
206*9880d681SAndroid Build Coastguard Worker continue;
207*9880d681SAndroid Build Coastguard Worker
208*9880d681SAndroid Build Coastguard Worker // There are no update forms for Altivec vector load/stores.
209*9880d681SAndroid Build Coastguard Worker if (ST && ST->hasAltivec() &&
210*9880d681SAndroid Build Coastguard Worker PtrValue->getType()->getPointerElementType()->isVectorTy())
211*9880d681SAndroid Build Coastguard Worker continue;
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker if (L->isLoopInvariant(PtrValue))
214*9880d681SAndroid Build Coastguard Worker continue;
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard Worker const SCEV *LSCEV = SE->getSCEVAtScope(PtrValue, L);
217*9880d681SAndroid Build Coastguard Worker if (const SCEVAddRecExpr *LARSCEV = dyn_cast<SCEVAddRecExpr>(LSCEV)) {
218*9880d681SAndroid Build Coastguard Worker if (LARSCEV->getLoop() != L)
219*9880d681SAndroid Build Coastguard Worker continue;
220*9880d681SAndroid Build Coastguard Worker } else {
221*9880d681SAndroid Build Coastguard Worker continue;
222*9880d681SAndroid Build Coastguard Worker }
223*9880d681SAndroid Build Coastguard Worker
224*9880d681SAndroid Build Coastguard Worker bool FoundBucket = false;
225*9880d681SAndroid Build Coastguard Worker for (auto &B : Buckets) {
226*9880d681SAndroid Build Coastguard Worker const SCEV *Diff = SE->getMinusSCEV(LSCEV, B.BaseSCEV);
227*9880d681SAndroid Build Coastguard Worker if (const auto *CDiff = dyn_cast<SCEVConstant>(Diff)) {
228*9880d681SAndroid Build Coastguard Worker B.Elements.push_back(BucketElement(CDiff, MemI));
229*9880d681SAndroid Build Coastguard Worker FoundBucket = true;
230*9880d681SAndroid Build Coastguard Worker break;
231*9880d681SAndroid Build Coastguard Worker }
232*9880d681SAndroid Build Coastguard Worker }
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker if (!FoundBucket) {
235*9880d681SAndroid Build Coastguard Worker if (Buckets.size() == MaxVars)
236*9880d681SAndroid Build Coastguard Worker return MadeChange;
237*9880d681SAndroid Build Coastguard Worker Buckets.push_back(Bucket(LSCEV, MemI));
238*9880d681SAndroid Build Coastguard Worker }
239*9880d681SAndroid Build Coastguard Worker }
240*9880d681SAndroid Build Coastguard Worker }
241*9880d681SAndroid Build Coastguard Worker
242*9880d681SAndroid Build Coastguard Worker if (Buckets.empty())
243*9880d681SAndroid Build Coastguard Worker return MadeChange;
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker BasicBlock *LoopPredecessor = L->getLoopPredecessor();
246*9880d681SAndroid Build Coastguard Worker // If there is no loop predecessor, or the loop predecessor's terminator
247*9880d681SAndroid Build Coastguard Worker // returns a value (which might contribute to determining the loop's
248*9880d681SAndroid Build Coastguard Worker // iteration space), insert a new preheader for the loop.
249*9880d681SAndroid Build Coastguard Worker if (!LoopPredecessor ||
250*9880d681SAndroid Build Coastguard Worker !LoopPredecessor->getTerminator()->getType()->isVoidTy()) {
251*9880d681SAndroid Build Coastguard Worker LoopPredecessor = InsertPreheaderForLoop(L, DT, LI, PreserveLCSSA);
252*9880d681SAndroid Build Coastguard Worker if (LoopPredecessor)
253*9880d681SAndroid Build Coastguard Worker MadeChange = true;
254*9880d681SAndroid Build Coastguard Worker }
255*9880d681SAndroid Build Coastguard Worker if (!LoopPredecessor)
256*9880d681SAndroid Build Coastguard Worker return MadeChange;
257*9880d681SAndroid Build Coastguard Worker
258*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "PIP: Found " << Buckets.size() << " buckets\n");
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker SmallSet<BasicBlock *, 16> BBChanged;
261*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Buckets.size(); i != e; ++i) {
262*9880d681SAndroid Build Coastguard Worker // The base address of each bucket is transformed into a phi and the others
263*9880d681SAndroid Build Coastguard Worker // are rewritten as offsets of that variable.
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker // We have a choice now of which instruction's memory operand we use as the
266*9880d681SAndroid Build Coastguard Worker // base for the generated PHI. Always picking the first instruction in each
267*9880d681SAndroid Build Coastguard Worker // bucket does not work well, specifically because that instruction might
268*9880d681SAndroid Build Coastguard Worker // be a prefetch (and there are no pre-increment dcbt variants). Otherwise,
269*9880d681SAndroid Build Coastguard Worker // the choice is somewhat arbitrary, because the backend will happily
270*9880d681SAndroid Build Coastguard Worker // generate direct offsets from both the pre-incremented and
271*9880d681SAndroid Build Coastguard Worker // post-incremented pointer values. Thus, we'll pick the first non-prefetch
272*9880d681SAndroid Build Coastguard Worker // instruction in each bucket, and adjust the recurrence and other offsets
273*9880d681SAndroid Build Coastguard Worker // accordingly.
274*9880d681SAndroid Build Coastguard Worker for (int j = 0, je = Buckets[i].Elements.size(); j != je; ++j) {
275*9880d681SAndroid Build Coastguard Worker if (auto *II = dyn_cast<IntrinsicInst>(Buckets[i].Elements[j].Instr))
276*9880d681SAndroid Build Coastguard Worker if (II->getIntrinsicID() == Intrinsic::prefetch)
277*9880d681SAndroid Build Coastguard Worker continue;
278*9880d681SAndroid Build Coastguard Worker
279*9880d681SAndroid Build Coastguard Worker // If we'd otherwise pick the first element anyway, there's nothing to do.
280*9880d681SAndroid Build Coastguard Worker if (j == 0)
281*9880d681SAndroid Build Coastguard Worker break;
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker // If our chosen element has no offset from the base pointer, there's
284*9880d681SAndroid Build Coastguard Worker // nothing to do.
285*9880d681SAndroid Build Coastguard Worker if (!Buckets[i].Elements[j].Offset ||
286*9880d681SAndroid Build Coastguard Worker Buckets[i].Elements[j].Offset->isZero())
287*9880d681SAndroid Build Coastguard Worker break;
288*9880d681SAndroid Build Coastguard Worker
289*9880d681SAndroid Build Coastguard Worker const SCEV *Offset = Buckets[i].Elements[j].Offset;
290*9880d681SAndroid Build Coastguard Worker Buckets[i].BaseSCEV = SE->getAddExpr(Buckets[i].BaseSCEV, Offset);
291*9880d681SAndroid Build Coastguard Worker for (auto &E : Buckets[i].Elements) {
292*9880d681SAndroid Build Coastguard Worker if (E.Offset)
293*9880d681SAndroid Build Coastguard Worker E.Offset = cast<SCEVConstant>(SE->getMinusSCEV(E.Offset, Offset));
294*9880d681SAndroid Build Coastguard Worker else
295*9880d681SAndroid Build Coastguard Worker E.Offset = cast<SCEVConstant>(SE->getNegativeSCEV(Offset));
296*9880d681SAndroid Build Coastguard Worker }
297*9880d681SAndroid Build Coastguard Worker
298*9880d681SAndroid Build Coastguard Worker std::swap(Buckets[i].Elements[j], Buckets[i].Elements[0]);
299*9880d681SAndroid Build Coastguard Worker break;
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker
302*9880d681SAndroid Build Coastguard Worker const SCEVAddRecExpr *BasePtrSCEV =
303*9880d681SAndroid Build Coastguard Worker cast<SCEVAddRecExpr>(Buckets[i].BaseSCEV);
304*9880d681SAndroid Build Coastguard Worker if (!BasePtrSCEV->isAffine())
305*9880d681SAndroid Build Coastguard Worker continue;
306*9880d681SAndroid Build Coastguard Worker
307*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "PIP: Transforming: " << *BasePtrSCEV << "\n");
308*9880d681SAndroid Build Coastguard Worker assert(BasePtrSCEV->getLoop() == L &&
309*9880d681SAndroid Build Coastguard Worker "AddRec for the wrong loop?");
310*9880d681SAndroid Build Coastguard Worker
311*9880d681SAndroid Build Coastguard Worker // The instruction corresponding to the Bucket's BaseSCEV must be the first
312*9880d681SAndroid Build Coastguard Worker // in the vector of elements.
313*9880d681SAndroid Build Coastguard Worker Instruction *MemI = Buckets[i].Elements.begin()->Instr;
314*9880d681SAndroid Build Coastguard Worker Value *BasePtr = GetPointerOperand(MemI);
315*9880d681SAndroid Build Coastguard Worker assert(BasePtr && "No pointer operand");
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker Type *I8Ty = Type::getInt8Ty(MemI->getParent()->getContext());
318*9880d681SAndroid Build Coastguard Worker Type *I8PtrTy = Type::getInt8PtrTy(MemI->getParent()->getContext(),
319*9880d681SAndroid Build Coastguard Worker BasePtr->getType()->getPointerAddressSpace());
320*9880d681SAndroid Build Coastguard Worker
321*9880d681SAndroid Build Coastguard Worker const SCEV *BasePtrStartSCEV = BasePtrSCEV->getStart();
322*9880d681SAndroid Build Coastguard Worker if (!SE->isLoopInvariant(BasePtrStartSCEV, L))
323*9880d681SAndroid Build Coastguard Worker continue;
324*9880d681SAndroid Build Coastguard Worker
325*9880d681SAndroid Build Coastguard Worker const SCEVConstant *BasePtrIncSCEV =
326*9880d681SAndroid Build Coastguard Worker dyn_cast<SCEVConstant>(BasePtrSCEV->getStepRecurrence(*SE));
327*9880d681SAndroid Build Coastguard Worker if (!BasePtrIncSCEV)
328*9880d681SAndroid Build Coastguard Worker continue;
329*9880d681SAndroid Build Coastguard Worker BasePtrStartSCEV = SE->getMinusSCEV(BasePtrStartSCEV, BasePtrIncSCEV);
330*9880d681SAndroid Build Coastguard Worker if (!isSafeToExpand(BasePtrStartSCEV, *SE))
331*9880d681SAndroid Build Coastguard Worker continue;
332*9880d681SAndroid Build Coastguard Worker
333*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "PIP: New start is: " << *BasePtrStartSCEV << "\n");
334*9880d681SAndroid Build Coastguard Worker
335*9880d681SAndroid Build Coastguard Worker PHINode *NewPHI = PHINode::Create(I8PtrTy, HeaderLoopPredCount,
336*9880d681SAndroid Build Coastguard Worker MemI->hasName() ? MemI->getName() + ".phi" : "",
337*9880d681SAndroid Build Coastguard Worker Header->getFirstNonPHI());
338*9880d681SAndroid Build Coastguard Worker
339*9880d681SAndroid Build Coastguard Worker SCEVExpander SCEVE(*SE, Header->getModule()->getDataLayout(), "pistart");
340*9880d681SAndroid Build Coastguard Worker Value *BasePtrStart = SCEVE.expandCodeFor(BasePtrStartSCEV, I8PtrTy,
341*9880d681SAndroid Build Coastguard Worker LoopPredecessor->getTerminator());
342*9880d681SAndroid Build Coastguard Worker
343*9880d681SAndroid Build Coastguard Worker // Note that LoopPredecessor might occur in the predecessor list multiple
344*9880d681SAndroid Build Coastguard Worker // times, and we need to add it the right number of times.
345*9880d681SAndroid Build Coastguard Worker for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header);
346*9880d681SAndroid Build Coastguard Worker PI != PE; ++PI) {
347*9880d681SAndroid Build Coastguard Worker if (*PI != LoopPredecessor)
348*9880d681SAndroid Build Coastguard Worker continue;
349*9880d681SAndroid Build Coastguard Worker
350*9880d681SAndroid Build Coastguard Worker NewPHI->addIncoming(BasePtrStart, LoopPredecessor);
351*9880d681SAndroid Build Coastguard Worker }
352*9880d681SAndroid Build Coastguard Worker
353*9880d681SAndroid Build Coastguard Worker Instruction *InsPoint = &*Header->getFirstInsertionPt();
354*9880d681SAndroid Build Coastguard Worker GetElementPtrInst *PtrInc = GetElementPtrInst::Create(
355*9880d681SAndroid Build Coastguard Worker I8Ty, NewPHI, BasePtrIncSCEV->getValue(),
356*9880d681SAndroid Build Coastguard Worker MemI->hasName() ? MemI->getName() + ".inc" : "", InsPoint);
357*9880d681SAndroid Build Coastguard Worker PtrInc->setIsInBounds(IsPtrInBounds(BasePtr));
358*9880d681SAndroid Build Coastguard Worker for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header);
359*9880d681SAndroid Build Coastguard Worker PI != PE; ++PI) {
360*9880d681SAndroid Build Coastguard Worker if (*PI == LoopPredecessor)
361*9880d681SAndroid Build Coastguard Worker continue;
362*9880d681SAndroid Build Coastguard Worker
363*9880d681SAndroid Build Coastguard Worker NewPHI->addIncoming(PtrInc, *PI);
364*9880d681SAndroid Build Coastguard Worker }
365*9880d681SAndroid Build Coastguard Worker
366*9880d681SAndroid Build Coastguard Worker Instruction *NewBasePtr;
367*9880d681SAndroid Build Coastguard Worker if (PtrInc->getType() != BasePtr->getType())
368*9880d681SAndroid Build Coastguard Worker NewBasePtr = new BitCastInst(PtrInc, BasePtr->getType(),
369*9880d681SAndroid Build Coastguard Worker PtrInc->hasName() ? PtrInc->getName() + ".cast" : "", InsPoint);
370*9880d681SAndroid Build Coastguard Worker else
371*9880d681SAndroid Build Coastguard Worker NewBasePtr = PtrInc;
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker if (Instruction *IDel = dyn_cast<Instruction>(BasePtr))
374*9880d681SAndroid Build Coastguard Worker BBChanged.insert(IDel->getParent());
375*9880d681SAndroid Build Coastguard Worker BasePtr->replaceAllUsesWith(NewBasePtr);
376*9880d681SAndroid Build Coastguard Worker RecursivelyDeleteTriviallyDeadInstructions(BasePtr);
377*9880d681SAndroid Build Coastguard Worker
378*9880d681SAndroid Build Coastguard Worker // Keep track of the replacement pointer values we've inserted so that we
379*9880d681SAndroid Build Coastguard Worker // don't generate more pointer values than necessary.
380*9880d681SAndroid Build Coastguard Worker SmallPtrSet<Value *, 16> NewPtrs;
381*9880d681SAndroid Build Coastguard Worker NewPtrs.insert( NewBasePtr);
382*9880d681SAndroid Build Coastguard Worker
383*9880d681SAndroid Build Coastguard Worker for (auto I = std::next(Buckets[i].Elements.begin()),
384*9880d681SAndroid Build Coastguard Worker IE = Buckets[i].Elements.end(); I != IE; ++I) {
385*9880d681SAndroid Build Coastguard Worker Value *Ptr = GetPointerOperand(I->Instr);
386*9880d681SAndroid Build Coastguard Worker assert(Ptr && "No pointer operand");
387*9880d681SAndroid Build Coastguard Worker if (NewPtrs.count(Ptr))
388*9880d681SAndroid Build Coastguard Worker continue;
389*9880d681SAndroid Build Coastguard Worker
390*9880d681SAndroid Build Coastguard Worker Instruction *RealNewPtr;
391*9880d681SAndroid Build Coastguard Worker if (!I->Offset || I->Offset->getValue()->isZero()) {
392*9880d681SAndroid Build Coastguard Worker RealNewPtr = NewBasePtr;
393*9880d681SAndroid Build Coastguard Worker } else {
394*9880d681SAndroid Build Coastguard Worker Instruction *PtrIP = dyn_cast<Instruction>(Ptr);
395*9880d681SAndroid Build Coastguard Worker if (PtrIP && isa<Instruction>(NewBasePtr) &&
396*9880d681SAndroid Build Coastguard Worker cast<Instruction>(NewBasePtr)->getParent() == PtrIP->getParent())
397*9880d681SAndroid Build Coastguard Worker PtrIP = 0;
398*9880d681SAndroid Build Coastguard Worker else if (isa<PHINode>(PtrIP))
399*9880d681SAndroid Build Coastguard Worker PtrIP = &*PtrIP->getParent()->getFirstInsertionPt();
400*9880d681SAndroid Build Coastguard Worker else if (!PtrIP)
401*9880d681SAndroid Build Coastguard Worker PtrIP = I->Instr;
402*9880d681SAndroid Build Coastguard Worker
403*9880d681SAndroid Build Coastguard Worker GetElementPtrInst *NewPtr = GetElementPtrInst::Create(
404*9880d681SAndroid Build Coastguard Worker I8Ty, PtrInc, I->Offset->getValue(),
405*9880d681SAndroid Build Coastguard Worker I->Instr->hasName() ? I->Instr->getName() + ".off" : "", PtrIP);
406*9880d681SAndroid Build Coastguard Worker if (!PtrIP)
407*9880d681SAndroid Build Coastguard Worker NewPtr->insertAfter(cast<Instruction>(PtrInc));
408*9880d681SAndroid Build Coastguard Worker NewPtr->setIsInBounds(IsPtrInBounds(Ptr));
409*9880d681SAndroid Build Coastguard Worker RealNewPtr = NewPtr;
410*9880d681SAndroid Build Coastguard Worker }
411*9880d681SAndroid Build Coastguard Worker
412*9880d681SAndroid Build Coastguard Worker if (Instruction *IDel = dyn_cast<Instruction>(Ptr))
413*9880d681SAndroid Build Coastguard Worker BBChanged.insert(IDel->getParent());
414*9880d681SAndroid Build Coastguard Worker
415*9880d681SAndroid Build Coastguard Worker Instruction *ReplNewPtr;
416*9880d681SAndroid Build Coastguard Worker if (Ptr->getType() != RealNewPtr->getType()) {
417*9880d681SAndroid Build Coastguard Worker ReplNewPtr = new BitCastInst(RealNewPtr, Ptr->getType(),
418*9880d681SAndroid Build Coastguard Worker Ptr->hasName() ? Ptr->getName() + ".cast" : "");
419*9880d681SAndroid Build Coastguard Worker ReplNewPtr->insertAfter(RealNewPtr);
420*9880d681SAndroid Build Coastguard Worker } else
421*9880d681SAndroid Build Coastguard Worker ReplNewPtr = RealNewPtr;
422*9880d681SAndroid Build Coastguard Worker
423*9880d681SAndroid Build Coastguard Worker Ptr->replaceAllUsesWith(ReplNewPtr);
424*9880d681SAndroid Build Coastguard Worker RecursivelyDeleteTriviallyDeadInstructions(Ptr);
425*9880d681SAndroid Build Coastguard Worker
426*9880d681SAndroid Build Coastguard Worker NewPtrs.insert(RealNewPtr);
427*9880d681SAndroid Build Coastguard Worker }
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Worker MadeChange = true;
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker
432*9880d681SAndroid Build Coastguard Worker for (Loop::block_iterator I = L->block_begin(), IE = L->block_end();
433*9880d681SAndroid Build Coastguard Worker I != IE; ++I) {
434*9880d681SAndroid Build Coastguard Worker if (BBChanged.count(*I))
435*9880d681SAndroid Build Coastguard Worker DeleteDeadPHIs(*I);
436*9880d681SAndroid Build Coastguard Worker }
437*9880d681SAndroid Build Coastguard Worker
438*9880d681SAndroid Build Coastguard Worker return MadeChange;
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker
441