[llvm] [LV][RFC] Generating conditional VPBB that will be skip when the mask is inactive in VPlan. (PR #141900)
Alexey Bataev via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 17 12:18:28 PDT 2025
================
@@ -4426,3 +4405,146 @@ void VPlanTransforms::addExitUsersForFirstOrderRecurrences(VPlan &Plan,
}
}
}
+
+void VPlanTransforms::optimizeConditionalVPBB(VPlan &Plan) {
+ VPDominatorTree VPDT;
+ VPDT.recalculate(Plan);
+
+ VPValue *HeaderMask = findHeaderMask(Plan);
+
+ // Get the mask from the store recipes.
+ auto GetMask = [&HeaderMask](VPRecipeBase &R) -> VPValue * {
+ using namespace llvm::VPlanPatternMatch;
+ if (isa<VPWidenStoreRecipe, VPWidenStoreEVLRecipe>(R)) {
+ VPValue *OrigMask = cast<VPWidenMemoryRecipe>(R).getMask();
+ if (!OrigMask || OrigMask == HeaderMask ||
+ match(OrigMask, m_VPInstruction<VPInstruction::ActiveLaneMask>(
+ m_VPValue(), m_VPValue())))
+ return nullptr;
+
+ return OrigMask;
+ }
+ return nullptr;
+ };
+
+ // First, collect all masked stores.
+ SmallVector<std::pair<VPRecipeBase *, VPValue *>> MaskedStores;
+ ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
+ Plan.getEntry());
+ for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
+ for (VPRecipeBase &R : *VPBB) {
+ if (VPValue *Mask = GetMask(R))
+ MaskedStores.emplace_back(&R, Mask);
+ }
+ }
+
+ DenseSet<VPRecipeBase *> Candidates;
+ auto AddOperandsToCandidates = [&Candidates](VPRecipeBase *R) {
+ for (VPValue *Op : R->operands())
+ if (VPRecipeBase *OpR = Op->getDefiningRecipe())
+ Candidates.insert(OpR);
+ };
+
+ SmallVector<SetVector<VPRecipeBase *>> Tries;
+ while (!MaskedStores.empty()) {
+ auto [LR, M] = MaskedStores.pop_back_val();
+ Candidates.clear();
+ AddOperandsToCandidates(LR);
+
+ SetVector<VPRecipeBase *> CurrentTree;
+ CurrentTree.insert(LR);
+
+ VPBasicBlock *MaskBlock =
+ M->hasDefiningRecipe() ? M->getDefiningRecipe()->getParent() : nullptr;
+ auto End = MaskBlock == LR->getParent()
+ ? M->getDefiningRecipe()->getReverseIterator()
+ : LR->getParent()->getFirstNonPhi()->getReverseIterator();
+ // Greedily add all recipes that are used to compute the stored value to the
+ // tree. All users of the added recipe must dominate the store
+ // recipe.
+ for (VPRecipeBase &R : make_range(LR->getReverseIterator(), End)) {
+ // Recipe is not a part of the tree
+ if (!Candidates.contains(&R))
+ continue;
+
+ if (any_of(R.definedValues(), [&LR = LR, &VPDT](VPValue *Def) {
+ for (VPUser *U : Def->users()) {
+ if (auto *UR = dyn_cast<VPRecipeBase>(U)) {
+ if (UR == LR || VPDT.properlyDominates(UR, LR))
+ continue;
+ }
+ return true;
+ }
+ return false;
+ }))
+ continue;
+
+ CurrentTree.insert(&R);
+ AddOperandsToCandidates(&R);
+ }
+ // The previous traversal could have added recipes that are used by
+ // non-added recipes, which need to be removed from the list.
+ DenseSet<VPRecipeBase *> ToRemove;
----------------
alexey-bataev wrote:
```suggestion
SmallDenseSet<VPRecipeBase *, 8> ToRemove;
```
https://github.com/llvm/llvm-project/pull/141900
More information about the llvm-commits
mailing list