diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:11:55 +0000 |
commit | 5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch) | |
tree | 1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/llvm/lib/Analysis/VectorUtils.cpp | |
parent | 3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff) | |
parent | 312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/VectorUtils.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Analysis/VectorUtils.cpp | 131 |
1 files changed, 69 insertions, 62 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/VectorUtils.cpp b/contrib/llvm-project/llvm/lib/Analysis/VectorUtils.cpp index 87f0bb690477..91d8c31fa062 100644 --- a/contrib/llvm-project/llvm/lib/Analysis/VectorUtils.cpp +++ b/contrib/llvm-project/llvm/lib/Analysis/VectorUtils.cpp @@ -12,7 +12,6 @@ #include "llvm/Analysis/VectorUtils.h" #include "llvm/ADT/EquivalenceClasses.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Analysis/DemandedBits.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopIterator.h" @@ -92,6 +91,8 @@ bool llvm::isTriviallyVectorizable(Intrinsic::ID ID) { case Intrinsic::canonicalize: case Intrinsic::fptosi_sat: case Intrinsic::fptoui_sat: + case Intrinsic::lrint: + case Intrinsic::llrint: return true; default: return false; @@ -123,6 +124,8 @@ bool llvm::isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, switch (ID) { case Intrinsic::fptosi_sat: case Intrinsic::fptoui_sat: + case Intrinsic::lrint: + case Intrinsic::llrint: return OpdIdx == -1 || OpdIdx == 0; case Intrinsic::is_fpclass: return OpdIdx == 0; @@ -1158,14 +1161,11 @@ void InterleavedAccessInfo::analyzeInterleaving( LLVM_DEBUG(dbgs() << "LV: Creating an interleave group with:" << *B << '\n'); GroupB = createInterleaveGroup(B, DesB.Stride, DesB.Alignment); - } else if (CompletedLoadGroups.contains(GroupB)) { - // Skip B if no new instructions can be added to its load group. - continue; + if (B->mayWriteToMemory()) + StoreGroups.insert(GroupB); + else + LoadGroups.insert(GroupB); } - if (B->mayWriteToMemory()) - StoreGroups.insert(GroupB); - else - LoadGroups.insert(GroupB); } for (auto AI = std::next(BI); AI != E; ++AI) { @@ -1191,38 +1191,62 @@ void InterleavedAccessInfo::analyzeInterleaving( // Because accesses (2) and (3) are dependent, we can group (2) with (1) // but not with (4). If we did, the dependent access (3) would be within // the boundaries of the (2, 4) group. - if (!canReorderMemAccessesForInterleavedGroups(&*AI, &*BI)) { - // If a dependence exists and A is already in a group, we know that A - // must be a store since A precedes B and WAR dependences are allowed. - // Thus, A would be sunk below B. We release A's group to prevent this - // illegal code motion. A will then be free to form another group with - // instructions that precede it. - if (isInterleaved(A)) { - InterleaveGroup<Instruction> *StoreGroup = getInterleaveGroup(A); - - LLVM_DEBUG(dbgs() << "LV: Invalidated store group due to " - "dependence between " << *A << " and "<< *B << '\n'); - - StoreGroups.remove(StoreGroup); - releaseGroup(StoreGroup); - } - // If B is a load and part of an interleave group, no earlier loads can - // be added to B's interleave group, because this would mean the load B - // would need to be moved across store A. Mark the interleave group as - // complete. - if (GroupB && isa<LoadInst>(B)) { - LLVM_DEBUG(dbgs() << "LV: Marking interleave group for " << *B - << " as complete.\n"); - - CompletedLoadGroups.insert(GroupB); + auto DependentMember = [&](InterleaveGroup<Instruction> *Group, + StrideEntry *A) -> Instruction * { + for (uint32_t Index = 0; Index < Group->getFactor(); ++Index) { + Instruction *MemberOfGroupB = Group->getMember(Index); + if (MemberOfGroupB && !canReorderMemAccessesForInterleavedGroups( + A, &*AccessStrideInfo.find(MemberOfGroupB))) + return MemberOfGroupB; } + return nullptr; + }; - // If a dependence exists and A is not already in a group (or it was - // and we just released it), B might be hoisted above A (if B is a - // load) or another store might be sunk below A (if B is a store). In - // either case, we can't add additional instructions to B's group. B - // will only form a group with instructions that it precedes. - break; + auto GroupA = getInterleaveGroup(A); + // If A is a load, dependencies are tolerable, there's nothing to do here. + // If both A and B belong to the same (store) group, they are independent, + // even if dependencies have not been recorded. + // If both GroupA and GroupB are null, there's nothing to do here. + if (A->mayWriteToMemory() && GroupA != GroupB) { + Instruction *DependentInst = nullptr; + // If GroupB is a load group, we have to compare AI against all + // members of GroupB because if any load within GroupB has a dependency + // on AI, we need to mark GroupB as complete and also release the + // store GroupA (if A belongs to one). The former prevents incorrect + // hoisting of load B above store A while the latter prevents incorrect + // sinking of store A below load B. + if (GroupB && LoadGroups.contains(GroupB)) + DependentInst = DependentMember(GroupB, &*AI); + else if (!canReorderMemAccessesForInterleavedGroups(&*AI, &*BI)) + DependentInst = B; + + if (DependentInst) { + // A has a store dependence on B (or on some load within GroupB) and + // is part of a store group. Release A's group to prevent illegal + // sinking of A below B. A will then be free to form another group + // with instructions that precede it. + if (GroupA && StoreGroups.contains(GroupA)) { + LLVM_DEBUG(dbgs() << "LV: Invalidated store group due to " + "dependence between " + << *A << " and " << *DependentInst << '\n'); + StoreGroups.remove(GroupA); + releaseGroup(GroupA); + } + // If B is a load and part of an interleave group, no earlier loads + // can be added to B's interleave group, because this would mean the + // DependentInst would move across store A. Mark the interleave group + // as complete. + if (GroupB && LoadGroups.contains(GroupB)) { + LLVM_DEBUG(dbgs() << "LV: Marking interleave group for " << *B + << " as complete.\n"); + CompletedLoadGroups.insert(GroupB); + } + } + } + if (CompletedLoadGroups.contains(GroupB)) { + // Skip trying to add A to B, continue to look for other conflicting A's + // in groups to be released. + continue; } // At this point, we've checked for illegal code motion. If either A or B @@ -1432,22 +1456,6 @@ void InterleaveGroup<Instruction>::addMetadata(Instruction *NewInst) const { } } -std::string VFABI::mangleTLIVectorName(StringRef VectorName, - StringRef ScalarName, unsigned numArgs, - ElementCount VF, bool Masked) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - Out << "_ZGV" << VFABI::_LLVM_ << (Masked ? "M" : "N"); - if (VF.isScalable()) - Out << 'x'; - else - Out << VF.getFixedValue(); - for (unsigned I = 0; I < numArgs; ++I) - Out << "v"; - Out << "_" << ScalarName << "(" << VectorName << ")"; - return std::string(Out.str()); -} - void VFABI::getVectorVariantNames( const CallInst &CI, SmallVectorImpl<std::string> &VariantMappings) { const StringRef S = CI.getFnAttr(VFABI::MappingsAttrName).getValueAsString(); @@ -1458,15 +1466,14 @@ void VFABI::getVectorVariantNames( S.split(ListAttr, ","); for (const auto &S : SetVector<StringRef>(ListAttr.begin(), ListAttr.end())) { -#ifndef NDEBUG - LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << S << "'\n"); std::optional<VFInfo> Info = - VFABI::tryDemangleForVFABI(S, *(CI.getModule())); - assert(Info && "Invalid name for a VFABI variant."); - assert(CI.getModule()->getFunction(Info->VectorName) && - "Vector function is missing."); -#endif - VariantMappings.push_back(std::string(S)); + VFABI::tryDemangleForVFABI(S, CI.getFunctionType()); + if (Info && CI.getModule()->getFunction(Info->VectorName)) { + LLVM_DEBUG(dbgs() << "VFABI: Adding mapping '" << S << "' for " << CI + << "\n"); + VariantMappings.push_back(std::string(S)); + } else + LLVM_DEBUG(dbgs() << "VFABI: Invalid mapping '" << S << "'\n"); } } |