diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2024-07-27 23:34:35 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-10-23 18:26:01 +0000 |
commit | 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch) | |
tree | 6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp | |
parent | 6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff) | |
parent | ac9a064cb179f3425b310fa2847f8764ac970a4d (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp index 37a356c43e29..cafec165f6d6 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp @@ -261,20 +261,20 @@ void LoopVectorizeHints::getHintsFromMetadata() { assert(LoopID->getNumOperands() > 0 && "requires at least one operand"); assert(LoopID->getOperand(0) == LoopID && "invalid loop id"); - for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i) { + for (const MDOperand &MDO : llvm::drop_begin(LoopID->operands())) { const MDString *S = nullptr; SmallVector<Metadata *, 4> Args; // The expected hint is either a MDString or a MDNode with the first // operand a MDString. - if (const MDNode *MD = dyn_cast<MDNode>(LoopID->getOperand(i))) { + if (const MDNode *MD = dyn_cast<MDNode>(MDO)) { if (!MD || MD->getNumOperands() == 0) continue; S = dyn_cast<MDString>(MD->getOperand(0)); for (unsigned i = 1, ie = MD->getNumOperands(); i < ie; ++i) Args.push_back(MD->getOperand(i)); } else { - S = dyn_cast<MDString>(LoopID->getOperand(i)); + S = dyn_cast<MDString>(MDO); assert(Args.size() == 0 && "too many arguments for MDString"); } @@ -692,7 +692,7 @@ void LoopVectorizationLegality::addInductionPhi( InductionCastsToIgnore.insert(*Casts.begin()); Type *PhiTy = Phi->getType(); - const DataLayout &DL = Phi->getModule()->getDataLayout(); + const DataLayout &DL = Phi->getDataLayout(); // Get the widest type. if (!PhiTy->isFloatingPointTy()) { @@ -1067,6 +1067,15 @@ bool LoopVectorizationLegality::canVectorizeMemory() { if (!LAI->canVectorizeMemory()) return false; + if (LAI->hasLoadStoreDependenceInvolvingLoopInvariantAddress()) { + reportVectorizationFailure("We don't allow storing to uniform addresses", + "write to a loop invariant address could not " + "be vectorized", + "CantVectorizeStoreToLoopInvariantAddress", ORE, + TheLoop); + return false; + } + // We can vectorize stores to invariant address when final reduction value is // guaranteed to be stored at the end of the loop. Also, if decision to // vectorize loop is made, runtime checks are added so as to make sure that @@ -1102,13 +1111,12 @@ bool LoopVectorizationLegality::canVectorizeMemory() { } } - if (LAI->hasDependenceInvolvingLoopInvariantAddress()) { + if (LAI->hasStoreStoreDependenceInvolvingLoopInvariantAddress()) { // For each invariant address, check its last stored value is the result // of one of our reductions. // - // We do not check if dependence with loads exists because they are - // currently rejected earlier in LoopAccessInfo::analyzeLoop. In case this - // behaviour changes we have to modify this code. + // We do not check if dependence with loads exists because that is already + // checked via hasLoadStoreDependenceInvolvingLoopInvariantAddress. ScalarEvolution *SE = PSE.getSE(); SmallVector<StoreInst *, 4> UnhandledStores; for (StoreInst *SI : LAI->getStoresToInvariantAddresses()) { @@ -1498,6 +1506,16 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) { return false; } + if (isa<SCEVCouldNotCompute>(PSE.getBackedgeTakenCount())) { + reportVectorizationFailure("could not determine number of loop iterations", + "could not determine number of loop iterations", + "CantComputeNumberOfIterations", ORE, TheLoop); + if (DoExtraAnalysis) + Result = false; + else + return false; + } + LLVM_DEBUG(dbgs() << "LV: We can vectorize this loop" << (LAI->getRuntimePointerChecking()->Need ? " (with a runtime bound check)" @@ -1525,7 +1543,7 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) { return Result; } -bool LoopVectorizationLegality::prepareToFoldTailByMasking() { +bool LoopVectorizationLegality::canFoldTailByMasking() const { LLVM_DEBUG(dbgs() << "LV: checking if tail can be folded by masking.\n"); @@ -1552,26 +1570,47 @@ bool LoopVectorizationLegality::prepareToFoldTailByMasking() { } } + for (const auto &Entry : getInductionVars()) { + PHINode *OrigPhi = Entry.first; + for (User *U : OrigPhi->users()) { + auto *UI = cast<Instruction>(U); + if (!TheLoop->contains(UI)) { + LLVM_DEBUG(dbgs() << "LV: Cannot fold tail by masking, loop IV has an " + "outside user for " + << *UI << "\n"); + return false; + } + } + } + // The list of pointers that we can safely read and write to remains empty. SmallPtrSet<Value *, 8> SafePointers; - // Collect masked ops in temporary set first to avoid partially populating - // MaskedOp if a block cannot be predicated. + // Check all blocks for predication, including those that ordinarily do not + // need predication such as the header block. SmallPtrSet<const Instruction *, 8> TmpMaskedOp; - - // Check and mark all blocks for predication, including those that ordinarily - // do not need predication such as the header block. for (BasicBlock *BB : TheLoop->blocks()) { if (!blockCanBePredicated(BB, SafePointers, TmpMaskedOp)) { - LLVM_DEBUG(dbgs() << "LV: Cannot fold tail by masking as requested.\n"); + LLVM_DEBUG(dbgs() << "LV: Cannot fold tail by masking.\n"); return false; } } LLVM_DEBUG(dbgs() << "LV: can fold tail by masking.\n"); - MaskedOp.insert(TmpMaskedOp.begin(), TmpMaskedOp.end()); return true; } +void LoopVectorizationLegality::prepareToFoldTailByMasking() { + // The list of pointers that we can safely read and write to remains empty. + SmallPtrSet<Value *, 8> SafePointers; + + // Mark all blocks for predication, including those that ordinarily do not + // need predication such as the header block. + for (BasicBlock *BB : TheLoop->blocks()) { + [[maybe_unused]] bool R = blockCanBePredicated(BB, SafePointers, MaskedOp); + assert(R && "Must be able to predicate block when tail-folding."); + } +} + } // namespace llvm |