[llvm] [VectorUtils] Add InterleaveGroup::members() (NFCI) (PR #195122)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 30 13:09:42 PDT 2026
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/195122
>From 8dd5c43e38daf7be1452308286e5519408bc30a5 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 30 Apr 2026 17:19:37 +0100
Subject: [PATCH 1/2] [VectorUtils] Add InterleaveGroup::members() (NFCI)
We need to iterate over all non-null members of a group in multiple
places. Add members helper, as suggested in
https://github.com/llvm/llvm-project/pull/190191.
---
llvm/include/llvm/Analysis/VectorUtils.h | 11 +++++
.../Transforms/Vectorize/LoopVectorize.cpp | 45 +++++++------------
llvm/lib/Transforms/Vectorize/VPlan.h | 9 ++--
.../Transforms/Vectorize/VPlanTransforms.cpp | 8 +---
4 files changed, 34 insertions(+), 39 deletions(-)
diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index 9f7a606d89306..3fd4de926683c 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -14,6 +14,8 @@
#define LLVM_ANALYSIS_VECTORUTILS_H
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/IR/Module.h"
@@ -595,6 +597,15 @@ template <typename InstTy> class InterleaveGroup {
return Members.lookup(Key);
}
+ /// Return an iterator range over the non-null members of this group, in
+ /// index order.
+ auto members() const {
+ return make_filter_range(
+ map_range(seq<uint32_t>(0, Factor),
+ [this](uint32_t I) { return getMember(I); }),
+ [](InstTy *I) { return I != nullptr; });
+ }
+
/// Get the index for the given member. Unlike the key in the member
/// map, the index starts from 0.
uint32_t getIndex(const InstTy *Instr) const {
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index fdc2cfe34d47c..f1b8276764976 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -956,13 +956,11 @@ class LoopVectorizationCostModel {
if (W != CM_Interleave)
OtherMemberCost = InsertPosCost = Cost / Grp->getNumMembers();
;
- for (unsigned Idx = 0; Idx < Grp->getFactor(); ++Idx) {
- if (auto *I = Grp->getMember(Idx)) {
- if (Grp->getInsertPos() == I)
- WideningDecisions[{I, VF}] = {W, InsertPosCost};
- else
- WideningDecisions[{I, VF}] = {W, OtherMemberCost};
- }
+ for (auto *I : Grp->members()) {
+ if (Grp->getInsertPos() == I)
+ WideningDecisions[{I, VF}] = {W, InsertPosCost};
+ else
+ WideningDecisions[{I, VF}] = {W, OtherMemberCost};
}
}
@@ -2560,10 +2558,7 @@ bool LoopVectorizationCostModel::interleavedAccessCanBeWidened(
// If the group involves a non-integral pointer, we may not be able to
// losslessly cast all values to a common type.
bool ScalarNI = DL.isNonIntegralPointerType(ScalarTy);
- for (unsigned Idx = 0; Idx < InterleaveFactor; Idx++) {
- Instruction *Member = Group->getMember(Idx);
- if (!Member)
- continue;
+ for (Instruction *Member : Group->members()) {
auto *MemberTy = getLoadStoreType(Member);
bool MemberNI = DL.isNonIntegralPointerType(MemberTy);
// Don't coerce non-integral pointers to integers or vice versa.
@@ -4833,12 +4828,9 @@ void LoopVectorizationCostModel::setCostBasedWideningDecision(ElementCount VF) {
// the cost will actually be assigned to one instruction.
if (const auto *Group = getInterleavedAccessGroup(&I)) {
if (Decision == CM_Scalarize) {
- for (unsigned Idx = 0; Idx < Group->getFactor(); ++Idx) {
- if (auto *I = Group->getMember(Idx)) {
- setWideningDecision(I, VF, Decision,
- getMemInstScalarizationCost(I, VF));
- }
- }
+ for (auto *I : Group->members())
+ setWideningDecision(I, VF, Decision,
+ getMemInstScalarizationCost(I, VF));
} else {
setWideningDecision(Group, VF, Decision, Cost);
}
@@ -4913,17 +4905,14 @@ void LoopVectorizationCostModel::setCostBasedWideningDecision(ElementCount VF) {
// Scalarize all members of this interleaved group when any member
// is used as an address. The address-used load skips scalarization
// overhead, other members include it.
- for (unsigned Idx = 0; Idx < Group->getFactor(); ++Idx) {
- if (Instruction *Member = Group->getMember(Idx)) {
- InstructionCost Cost =
- AddrDefs.contains(Member)
- ? (VF.getKnownMinValue() *
- getMemoryInstructionCost(Member,
- ElementCount::getFixed(1)))
- : getMemInstScalarizationCost(Member, VF);
- setWideningDecision(Member, VF, CM_Scalarize, Cost);
- UpdateMemOpUserCost(cast<LoadInst>(Member));
- }
+ for (Instruction *Member : Group->members()) {
+ InstructionCost Cost = AddrDefs.contains(Member)
+ ? (VF.getKnownMinValue() *
+ getMemoryInstructionCost(
+ Member, ElementCount::getFixed(1)))
+ : getMemInstScalarizationCost(Member, VF);
+ setWideningDecision(Member, VF, CM_Scalarize, Cost);
+ UpdateMemOpUserCost(cast<LoadInst>(Member));
}
}
} else {
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 2b9edcc83a04f..ff056df396eb4 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -2867,11 +2867,10 @@ class LLVM_ABI_FOR_TEST VPInterleaveBase : public VPRecipeBase,
assert((!Mask || !IG->isReverse()) &&
"Reversed masked interleave-group not supported.");
if (StoredValues.empty()) {
- for (unsigned I = 0; I < IG->getFactor(); ++I)
- if (Instruction *Inst = IG->getMember(I)) {
- assert(!Inst->getType()->isVoidTy() && "must have result");
- new VPRecipeValue(this, Inst);
- }
+ for (Instruction *Inst : IG->members()) {
+ assert(!Inst->getType()->isVoidTy() && "must have result");
+ new VPRecipeValue(this, Inst);
+ }
} else {
for (auto *SV : StoredValues)
addOperand(SV);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 3b3b01973225e..e721012aadd39 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -3490,12 +3490,8 @@ void VPlanTransforms::dropPoisonGeneratingRecipes(
const InterleaveGroup<Instruction> *InterGroup =
InterleaveRec->getInterleaveGroup();
bool NeedPredication = false;
- for (int I = 0, NumMembers = InterGroup->getNumMembers();
- I < NumMembers; ++I) {
- Instruction *Member = InterGroup->getMember(I);
- if (Member)
- NeedPredication |= BlockNeedsPredication(Member->getParent());
- }
+ for (Instruction *Member : InterGroup->members())
+ NeedPredication |= BlockNeedsPredication(Member->getParent());
if (NeedPredication)
CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
>From 728c0e06c1cacc59de776e3854eb364f9f263b0a Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 30 Apr 2026 21:09:08 +0100
Subject: [PATCH 2/2] !fixup replace auto with Instruction
---
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index f1b8276764976..fc5844a6d179b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -4828,7 +4828,7 @@ void LoopVectorizationCostModel::setCostBasedWideningDecision(ElementCount VF) {
// the cost will actually be assigned to one instruction.
if (const auto *Group = getInterleavedAccessGroup(&I)) {
if (Decision == CM_Scalarize) {
- for (auto *I : Group->members())
+ for (Instruction *I : Group->members())
setWideningDecision(I, VF, Decision,
getMemInstScalarizationCost(I, VF));
} else {
More information about the llvm-commits
mailing list