diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 93ee959bfa7..0cdde4c2564 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -134,11 +134,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; } @@ -182,6 +185,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 927ae494548..6ebb0eff812 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -812,7 +812,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; @@ -855,7 +855,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); @@ -869,13 +870,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); @@ -891,7 +894,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; @@ -914,7 +918,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 @@ -937,7 +942,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) { @@ -972,7 +978,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 @@ -1013,12 +1020,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( @@ -1051,7 +1059,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; @@ -1064,8 +1073,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) { diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index abb38d19ea1..1def103d970 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -3825,11 +3825,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,