diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 98e9c91f64f..3867b896504 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -140,11 +140,14 @@ public: const TargetLibraryInfo *TLI, AliasAnalysis *AA, DominatorTree *DT) : TheLoop(L), SE(SE), DL(DL), TLI(TLI), AA(AA), DT(DT), NumLoads(0), - NumStores(0), MaxSafeDepDistBytes(-1U) {} + NumStores(0), MaxSafeDepDistBytes(-1U), CanVecMem(false) {} + + /// \brief Analyze the loop. Replaces symbolic strides using Strides. + void analyzeLoop(ValueToValueMap &Strides); /// Return true we can analyze the memory accesses in the loop and there are - /// no memory dependence cycles. Replaces symbolic strides using Strides. - bool canVectorizeMemory(ValueToValueMap &Strides); + /// no memory dependence cycles. + bool canVectorizeMemory() { return CanVecMem; } RuntimePointerCheck *getRuntimePointerCheck() { return &PtrRtCheck; } @@ -189,6 +192,9 @@ private: unsigned MaxSafeDepDistBytes; + /// \brief Cache the result of analyzeLoop. + bool CanVecMem; + /// \brief The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. Optional Report; diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp index 8d64553d1de..5001b5fa3f1 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -854,7 +854,7 @@ bool MemoryDepChecker::areDepsSafe(AccessAnalysis::DepCandidates &AccessSets, return true; } -bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { +void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) { typedef SmallVector ValueVector; typedef SmallPtrSet ValueSet; @@ -897,7 +897,8 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { emitAnalysis(VectorizationReport(Ld) << "read with atomic ordering or volatile read"); DEBUG(dbgs() << "LV: Found a non-simple load.\n"); - return false; + CanVecMem = false; + return; } NumLoads++; Loads.push_back(Ld); @@ -911,13 +912,15 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { if (!St) { emitAnalysis(VectorizationReport(it) << "instruction cannot be vectorized"); - return false; + CanVecMem = false; + return; } if (!St->isSimple() && !IsAnnotatedParallel) { emitAnalysis(VectorizationReport(St) << "write with atomic ordering or volatile write"); DEBUG(dbgs() << "LV: Found a non-simple store.\n"); - return false; + CanVecMem = false; + return; } NumStores++; Stores.push_back(St); @@ -933,7 +936,8 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { // care if the pointers are *restrict*. if (!Stores.size()) { DEBUG(dbgs() << "LV: Found a read-only loop!\n"); - return true; + CanVecMem = true; + return; } AccessAnalysis::DepCandidates DependentAccesses; @@ -956,7 +960,8 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { VectorizationReport(ST) << "write to a loop invariant address could not be vectorized"); DEBUG(dbgs() << "LV: We don't allow storing to uniform addresses\n"); - return false; + CanVecMem = false; + return; } // If we did *not* see this pointer before, insert it to the read-write @@ -979,7 +984,8 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { DEBUG(dbgs() << "LV: A loop annotated parallel, ignore memory dependency " << "checks.\n"); - return true; + CanVecMem = true; + return; } for (I = Loads.begin(), IE = Loads.end(); I != IE; ++I) { @@ -1014,7 +1020,8 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { // other reads in this loop then is it safe to vectorize. if (NumReadWrites == 1 && NumReads == 0) { DEBUG(dbgs() << "LV: Found a write-only loop!\n"); - return true; + CanVecMem = true; + return; } // Build dependence sets and check whether we need a runtime pointer bounds @@ -1055,12 +1062,13 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { DEBUG(dbgs() << "LV: We can't vectorize because we can't find " << "the array bounds.\n"); PtrRtCheck.reset(); - return false; + CanVecMem = false; + return; } PtrRtCheck.Need = NeedRTCheck; - bool CanVecMem = true; + CanVecMem = true; if (Accesses.isDependencyCheckNeeded()) { DEBUG(dbgs() << "LV: Checking memory dependencies\n"); CanVecMem = DepChecker.areDepsSafe( @@ -1093,7 +1101,8 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { << " dependent memory operations checked at runtime"); DEBUG(dbgs() << "LV: Can't vectorize with memory checks\n"); PtrRtCheck.reset(); - return false; + CanVecMem = false; + return; } CanVecMem = true; @@ -1106,8 +1115,6 @@ bool LoopAccessInfo::canVectorizeMemory(ValueToValueMap &Strides) { DEBUG(dbgs() << "LV: We" << (NeedRTCheck ? "" : " don't") << " need a runtime memory check.\n"); - - return CanVecMem; } bool LoopAccessInfo::blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 8b671355ebd..2ba7913119f 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -3807,11 +3807,11 @@ void LoopVectorizationLegality::collectLoopUniforms() { } bool LoopVectorizationLegality::canVectorizeMemory() { - bool Success = LAI.canVectorizeMemory(Strides); + LAI.analyzeLoop(Strides); auto &OptionalReport = LAI.getReport(); if (OptionalReport) emitAnalysis(*OptionalReport); - return Success; + return LAI.canVectorizeMemory(); } static bool hasMultipleUsesOf(Instruction *I,