1*0b57cec5SDimitry Andric //===-------- LoopDataPrefetch.cpp - Loop Data Prefetching Pass -----------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements a Loop Data Prefetching Pass. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopDataPrefetch.h" 14*0b57cec5SDimitry Andric 15*0b57cec5SDimitry Andric #define DEBUG_TYPE "loop-data-prefetch" 16*0b57cec5SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 18*0b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 19*0b57cec5SDimitry Andric #include "llvm/Analysis/CodeMetrics.h" 20*0b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 21*0b57cec5SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 22*0b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h" 23*0b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpander.h" 24*0b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h" 25*0b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 26*0b57cec5SDimitry Andric #include "llvm/IR/CFG.h" 27*0b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 28*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 29*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 30*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 31*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 32*0b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 33*0b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 34*0b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h" 35*0b57cec5SDimitry Andric using namespace llvm; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric // By default, we limit this to creating 16 PHIs (which is a little over half 38*0b57cec5SDimitry Andric // of the allocatable register set). 39*0b57cec5SDimitry Andric static cl::opt<bool> 40*0b57cec5SDimitry Andric PrefetchWrites("loop-prefetch-writes", cl::Hidden, cl::init(false), 41*0b57cec5SDimitry Andric cl::desc("Prefetch write addresses")); 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric static cl::opt<unsigned> 44*0b57cec5SDimitry Andric PrefetchDistance("prefetch-distance", 45*0b57cec5SDimitry Andric cl::desc("Number of instructions to prefetch ahead"), 46*0b57cec5SDimitry Andric cl::Hidden); 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric static cl::opt<unsigned> 49*0b57cec5SDimitry Andric MinPrefetchStride("min-prefetch-stride", 50*0b57cec5SDimitry Andric cl::desc("Min stride to add prefetches"), cl::Hidden); 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric static cl::opt<unsigned> MaxPrefetchIterationsAhead( 53*0b57cec5SDimitry Andric "max-prefetch-iters-ahead", 54*0b57cec5SDimitry Andric cl::desc("Max number of iterations to prefetch ahead"), cl::Hidden); 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric STATISTIC(NumPrefetches, "Number of prefetches inserted"); 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric namespace { 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric /// Loop prefetch implementation class. 61*0b57cec5SDimitry Andric class LoopDataPrefetch { 62*0b57cec5SDimitry Andric public: 63*0b57cec5SDimitry Andric LoopDataPrefetch(AssumptionCache *AC, LoopInfo *LI, ScalarEvolution *SE, 64*0b57cec5SDimitry Andric const TargetTransformInfo *TTI, 65*0b57cec5SDimitry Andric OptimizationRemarkEmitter *ORE) 66*0b57cec5SDimitry Andric : AC(AC), LI(LI), SE(SE), TTI(TTI), ORE(ORE) {} 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric bool run(); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric private: 71*0b57cec5SDimitry Andric bool runOnLoop(Loop *L); 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric /// Check if the stride of the accesses is large enough to 74*0b57cec5SDimitry Andric /// warrant a prefetch. 75*0b57cec5SDimitry Andric bool isStrideLargeEnough(const SCEVAddRecExpr *AR); 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric unsigned getMinPrefetchStride() { 78*0b57cec5SDimitry Andric if (MinPrefetchStride.getNumOccurrences() > 0) 79*0b57cec5SDimitry Andric return MinPrefetchStride; 80*0b57cec5SDimitry Andric return TTI->getMinPrefetchStride(); 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric unsigned getPrefetchDistance() { 84*0b57cec5SDimitry Andric if (PrefetchDistance.getNumOccurrences() > 0) 85*0b57cec5SDimitry Andric return PrefetchDistance; 86*0b57cec5SDimitry Andric return TTI->getPrefetchDistance(); 87*0b57cec5SDimitry Andric } 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric unsigned getMaxPrefetchIterationsAhead() { 90*0b57cec5SDimitry Andric if (MaxPrefetchIterationsAhead.getNumOccurrences() > 0) 91*0b57cec5SDimitry Andric return MaxPrefetchIterationsAhead; 92*0b57cec5SDimitry Andric return TTI->getMaxPrefetchIterationsAhead(); 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric AssumptionCache *AC; 96*0b57cec5SDimitry Andric LoopInfo *LI; 97*0b57cec5SDimitry Andric ScalarEvolution *SE; 98*0b57cec5SDimitry Andric const TargetTransformInfo *TTI; 99*0b57cec5SDimitry Andric OptimizationRemarkEmitter *ORE; 100*0b57cec5SDimitry Andric }; 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric /// Legacy class for inserting loop data prefetches. 103*0b57cec5SDimitry Andric class LoopDataPrefetchLegacyPass : public FunctionPass { 104*0b57cec5SDimitry Andric public: 105*0b57cec5SDimitry Andric static char ID; // Pass ID, replacement for typeid 106*0b57cec5SDimitry Andric LoopDataPrefetchLegacyPass() : FunctionPass(ID) { 107*0b57cec5SDimitry Andric initializeLoopDataPrefetchLegacyPassPass(*PassRegistry::getPassRegistry()); 108*0b57cec5SDimitry Andric } 109*0b57cec5SDimitry Andric 110*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 111*0b57cec5SDimitry Andric AU.addRequired<AssumptionCacheTracker>(); 112*0b57cec5SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 113*0b57cec5SDimitry Andric AU.addRequired<LoopInfoWrapperPass>(); 114*0b57cec5SDimitry Andric AU.addPreserved<LoopInfoWrapperPass>(); 115*0b57cec5SDimitry Andric AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); 116*0b57cec5SDimitry Andric AU.addRequired<ScalarEvolutionWrapperPass>(); 117*0b57cec5SDimitry Andric AU.addPreserved<ScalarEvolutionWrapperPass>(); 118*0b57cec5SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 119*0b57cec5SDimitry Andric } 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric bool runOnFunction(Function &F) override; 122*0b57cec5SDimitry Andric }; 123*0b57cec5SDimitry Andric } 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric char LoopDataPrefetchLegacyPass::ID = 0; 126*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(LoopDataPrefetchLegacyPass, "loop-data-prefetch", 127*0b57cec5SDimitry Andric "Loop Data Prefetch", false, false) 128*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) 129*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 130*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 131*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass) 132*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) 133*0b57cec5SDimitry Andric INITIALIZE_PASS_END(LoopDataPrefetchLegacyPass, "loop-data-prefetch", 134*0b57cec5SDimitry Andric "Loop Data Prefetch", false, false) 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric FunctionPass *llvm::createLoopDataPrefetchPass() { 137*0b57cec5SDimitry Andric return new LoopDataPrefetchLegacyPass(); 138*0b57cec5SDimitry Andric } 139*0b57cec5SDimitry Andric 140*0b57cec5SDimitry Andric bool LoopDataPrefetch::isStrideLargeEnough(const SCEVAddRecExpr *AR) { 141*0b57cec5SDimitry Andric unsigned TargetMinStride = getMinPrefetchStride(); 142*0b57cec5SDimitry Andric // No need to check if any stride goes. 143*0b57cec5SDimitry Andric if (TargetMinStride <= 1) 144*0b57cec5SDimitry Andric return true; 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric const auto *ConstStride = dyn_cast<SCEVConstant>(AR->getStepRecurrence(*SE)); 147*0b57cec5SDimitry Andric // If MinStride is set, don't prefetch unless we can ensure that stride is 148*0b57cec5SDimitry Andric // larger. 149*0b57cec5SDimitry Andric if (!ConstStride) 150*0b57cec5SDimitry Andric return false; 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric unsigned AbsStride = std::abs(ConstStride->getAPInt().getSExtValue()); 153*0b57cec5SDimitry Andric return TargetMinStride <= AbsStride; 154*0b57cec5SDimitry Andric } 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric PreservedAnalyses LoopDataPrefetchPass::run(Function &F, 157*0b57cec5SDimitry Andric FunctionAnalysisManager &AM) { 158*0b57cec5SDimitry Andric LoopInfo *LI = &AM.getResult<LoopAnalysis>(F); 159*0b57cec5SDimitry Andric ScalarEvolution *SE = &AM.getResult<ScalarEvolutionAnalysis>(F); 160*0b57cec5SDimitry Andric AssumptionCache *AC = &AM.getResult<AssumptionAnalysis>(F); 161*0b57cec5SDimitry Andric OptimizationRemarkEmitter *ORE = 162*0b57cec5SDimitry Andric &AM.getResult<OptimizationRemarkEmitterAnalysis>(F); 163*0b57cec5SDimitry Andric const TargetTransformInfo *TTI = &AM.getResult<TargetIRAnalysis>(F); 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric LoopDataPrefetch LDP(AC, LI, SE, TTI, ORE); 166*0b57cec5SDimitry Andric bool Changed = LDP.run(); 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric if (Changed) { 169*0b57cec5SDimitry Andric PreservedAnalyses PA; 170*0b57cec5SDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 171*0b57cec5SDimitry Andric PA.preserve<LoopAnalysis>(); 172*0b57cec5SDimitry Andric return PA; 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric return PreservedAnalyses::all(); 176*0b57cec5SDimitry Andric } 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric bool LoopDataPrefetchLegacyPass::runOnFunction(Function &F) { 179*0b57cec5SDimitry Andric if (skipFunction(F)) 180*0b57cec5SDimitry Andric return false; 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 183*0b57cec5SDimitry Andric ScalarEvolution *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 184*0b57cec5SDimitry Andric AssumptionCache *AC = 185*0b57cec5SDimitry Andric &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 186*0b57cec5SDimitry Andric OptimizationRemarkEmitter *ORE = 187*0b57cec5SDimitry Andric &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); 188*0b57cec5SDimitry Andric const TargetTransformInfo *TTI = 189*0b57cec5SDimitry Andric &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 190*0b57cec5SDimitry Andric 191*0b57cec5SDimitry Andric LoopDataPrefetch LDP(AC, LI, SE, TTI, ORE); 192*0b57cec5SDimitry Andric return LDP.run(); 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric bool LoopDataPrefetch::run() { 196*0b57cec5SDimitry Andric // If PrefetchDistance is not set, don't run the pass. This gives an 197*0b57cec5SDimitry Andric // opportunity for targets to run this pass for selected subtargets only 198*0b57cec5SDimitry Andric // (whose TTI sets PrefetchDistance). 199*0b57cec5SDimitry Andric if (getPrefetchDistance() == 0) 200*0b57cec5SDimitry Andric return false; 201*0b57cec5SDimitry Andric assert(TTI->getCacheLineSize() && "Cache line size is not set for target"); 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric bool MadeChange = false; 204*0b57cec5SDimitry Andric 205*0b57cec5SDimitry Andric for (Loop *I : *LI) 206*0b57cec5SDimitry Andric for (auto L = df_begin(I), LE = df_end(I); L != LE; ++L) 207*0b57cec5SDimitry Andric MadeChange |= runOnLoop(*L); 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric return MadeChange; 210*0b57cec5SDimitry Andric } 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric bool LoopDataPrefetch::runOnLoop(Loop *L) { 213*0b57cec5SDimitry Andric bool MadeChange = false; 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andric // Only prefetch in the inner-most loop 216*0b57cec5SDimitry Andric if (!L->empty()) 217*0b57cec5SDimitry Andric return MadeChange; 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric SmallPtrSet<const Value *, 32> EphValues; 220*0b57cec5SDimitry Andric CodeMetrics::collectEphemeralValues(L, AC, EphValues); 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric // Calculate the number of iterations ahead to prefetch 223*0b57cec5SDimitry Andric CodeMetrics Metrics; 224*0b57cec5SDimitry Andric for (const auto BB : L->blocks()) { 225*0b57cec5SDimitry Andric // If the loop already has prefetches, then assume that the user knows 226*0b57cec5SDimitry Andric // what they are doing and don't add any more. 227*0b57cec5SDimitry Andric for (auto &I : *BB) 228*0b57cec5SDimitry Andric if (CallInst *CI = dyn_cast<CallInst>(&I)) 229*0b57cec5SDimitry Andric if (Function *F = CI->getCalledFunction()) 230*0b57cec5SDimitry Andric if (F->getIntrinsicID() == Intrinsic::prefetch) 231*0b57cec5SDimitry Andric return MadeChange; 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric Metrics.analyzeBasicBlock(BB, *TTI, EphValues); 234*0b57cec5SDimitry Andric } 235*0b57cec5SDimitry Andric unsigned LoopSize = Metrics.NumInsts; 236*0b57cec5SDimitry Andric if (!LoopSize) 237*0b57cec5SDimitry Andric LoopSize = 1; 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric unsigned ItersAhead = getPrefetchDistance() / LoopSize; 240*0b57cec5SDimitry Andric if (!ItersAhead) 241*0b57cec5SDimitry Andric ItersAhead = 1; 242*0b57cec5SDimitry Andric 243*0b57cec5SDimitry Andric if (ItersAhead > getMaxPrefetchIterationsAhead()) 244*0b57cec5SDimitry Andric return MadeChange; 245*0b57cec5SDimitry Andric 246*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Prefetching " << ItersAhead 247*0b57cec5SDimitry Andric << " iterations ahead (loop size: " << LoopSize << ") in " 248*0b57cec5SDimitry Andric << L->getHeader()->getParent()->getName() << ": " << *L); 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric SmallVector<std::pair<Instruction *, const SCEVAddRecExpr *>, 16> PrefLoads; 251*0b57cec5SDimitry Andric for (const auto BB : L->blocks()) { 252*0b57cec5SDimitry Andric for (auto &I : *BB) { 253*0b57cec5SDimitry Andric Value *PtrValue; 254*0b57cec5SDimitry Andric Instruction *MemI; 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric if (LoadInst *LMemI = dyn_cast<LoadInst>(&I)) { 257*0b57cec5SDimitry Andric MemI = LMemI; 258*0b57cec5SDimitry Andric PtrValue = LMemI->getPointerOperand(); 259*0b57cec5SDimitry Andric } else if (StoreInst *SMemI = dyn_cast<StoreInst>(&I)) { 260*0b57cec5SDimitry Andric if (!PrefetchWrites) continue; 261*0b57cec5SDimitry Andric MemI = SMemI; 262*0b57cec5SDimitry Andric PtrValue = SMemI->getPointerOperand(); 263*0b57cec5SDimitry Andric } else continue; 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric unsigned PtrAddrSpace = PtrValue->getType()->getPointerAddressSpace(); 266*0b57cec5SDimitry Andric if (PtrAddrSpace) 267*0b57cec5SDimitry Andric continue; 268*0b57cec5SDimitry Andric 269*0b57cec5SDimitry Andric if (L->isLoopInvariant(PtrValue)) 270*0b57cec5SDimitry Andric continue; 271*0b57cec5SDimitry Andric 272*0b57cec5SDimitry Andric const SCEV *LSCEV = SE->getSCEV(PtrValue); 273*0b57cec5SDimitry Andric const SCEVAddRecExpr *LSCEVAddRec = dyn_cast<SCEVAddRecExpr>(LSCEV); 274*0b57cec5SDimitry Andric if (!LSCEVAddRec) 275*0b57cec5SDimitry Andric continue; 276*0b57cec5SDimitry Andric 277*0b57cec5SDimitry Andric // Check if the stride of the accesses is large enough to warrant a 278*0b57cec5SDimitry Andric // prefetch. 279*0b57cec5SDimitry Andric if (!isStrideLargeEnough(LSCEVAddRec)) 280*0b57cec5SDimitry Andric continue; 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric // We don't want to double prefetch individual cache lines. If this load 283*0b57cec5SDimitry Andric // is known to be within one cache line of some other load that has 284*0b57cec5SDimitry Andric // already been prefetched, then don't prefetch this one as well. 285*0b57cec5SDimitry Andric bool DupPref = false; 286*0b57cec5SDimitry Andric for (const auto &PrefLoad : PrefLoads) { 287*0b57cec5SDimitry Andric const SCEV *PtrDiff = SE->getMinusSCEV(LSCEVAddRec, PrefLoad.second); 288*0b57cec5SDimitry Andric if (const SCEVConstant *ConstPtrDiff = 289*0b57cec5SDimitry Andric dyn_cast<SCEVConstant>(PtrDiff)) { 290*0b57cec5SDimitry Andric int64_t PD = std::abs(ConstPtrDiff->getValue()->getSExtValue()); 291*0b57cec5SDimitry Andric if (PD < (int64_t) TTI->getCacheLineSize()) { 292*0b57cec5SDimitry Andric DupPref = true; 293*0b57cec5SDimitry Andric break; 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric } 297*0b57cec5SDimitry Andric if (DupPref) 298*0b57cec5SDimitry Andric continue; 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric const SCEV *NextLSCEV = SE->getAddExpr(LSCEVAddRec, SE->getMulExpr( 301*0b57cec5SDimitry Andric SE->getConstant(LSCEVAddRec->getType(), ItersAhead), 302*0b57cec5SDimitry Andric LSCEVAddRec->getStepRecurrence(*SE))); 303*0b57cec5SDimitry Andric if (!isSafeToExpand(NextLSCEV, *SE)) 304*0b57cec5SDimitry Andric continue; 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric PrefLoads.push_back(std::make_pair(MemI, LSCEVAddRec)); 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andric Type *I8Ptr = Type::getInt8PtrTy(BB->getContext(), PtrAddrSpace); 309*0b57cec5SDimitry Andric SCEVExpander SCEVE(*SE, I.getModule()->getDataLayout(), "prefaddr"); 310*0b57cec5SDimitry Andric Value *PrefPtrValue = SCEVE.expandCodeFor(NextLSCEV, I8Ptr, MemI); 311*0b57cec5SDimitry Andric 312*0b57cec5SDimitry Andric IRBuilder<> Builder(MemI); 313*0b57cec5SDimitry Andric Module *M = BB->getParent()->getParent(); 314*0b57cec5SDimitry Andric Type *I32 = Type::getInt32Ty(BB->getContext()); 315*0b57cec5SDimitry Andric Function *PrefetchFunc = 316*0b57cec5SDimitry Andric Intrinsic::getDeclaration(M, Intrinsic::prefetch); 317*0b57cec5SDimitry Andric Builder.CreateCall( 318*0b57cec5SDimitry Andric PrefetchFunc, 319*0b57cec5SDimitry Andric {PrefPtrValue, 320*0b57cec5SDimitry Andric ConstantInt::get(I32, MemI->mayReadFromMemory() ? 0 : 1), 321*0b57cec5SDimitry Andric ConstantInt::get(I32, 3), ConstantInt::get(I32, 1)}); 322*0b57cec5SDimitry Andric ++NumPrefetches; 323*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Access: " << *PtrValue << ", SCEV: " << *LSCEV 324*0b57cec5SDimitry Andric << "\n"); 325*0b57cec5SDimitry Andric ORE->emit([&]() { 326*0b57cec5SDimitry Andric return OptimizationRemark(DEBUG_TYPE, "Prefetched", MemI) 327*0b57cec5SDimitry Andric << "prefetched memory access"; 328*0b57cec5SDimitry Andric }); 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric MadeChange = true; 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric } 333*0b57cec5SDimitry Andric 334*0b57cec5SDimitry Andric return MadeChange; 335*0b57cec5SDimitry Andric } 336