[llvm] [VPlan] Compute blend masks from minimum set of edge masks (PR #201783)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 13:51:57 PDT 2026
================
@@ -233,6 +245,103 @@ void VPPredicator::createSwitchEdgeMasks(const VPInstruction *SI) {
setEdgeMask(Src, DefaultDst, DefaultMask);
}
+// Start by keeping track of what edges lead to which value. Then see if any
+// node has the same value for all outgoing edges. If so then propagate that
+// value up to every node it postdominates. E.g:
+//
+// Entry Edges = {C->ɸ : %x, D->ɸ : %x, F->ɸ : %y}
+// / \ [C,D,F all outgoing edges equal: go up postdom frontier]
+// A B ~> {A->C : %x, A->D : %x, Entry->B : %y}
+// / \ |\ [A all outgoing edges equal: go up postdom frontier]
+// C D | E ~> {Entry->A : %x, Entry->B : %y}
+// \ \ |/
+// \ | F
+// \ | /
+// ɸ = phi [%x, C], [%x, D], [%y, F]
+MapVector<VPPredicator::EdgeTy, VPValue *>
+VPPredicator::computeBlendEdges(VPPhi *Phi) {
+ MapVector<EdgeTy, VPValue *> Edges;
+
+ // Mark the given edge as providing the value \p V.
+ auto AddEdge = [&Edges](const VPBlockBase *From, const VPBlockBase *To,
+ VPValue *V) {
+ EdgeTy Edge = {cast<VPBasicBlock>(From), cast<VPBasicBlock>(To)};
+ assert((!Edges.contains(Edge) || Edges.lookup(Edge) == V) &&
+ "Clobbering an edge?");
+ Edges[Edge] = V;
+ };
+
+ for (auto [InVal, InVPBB] : Phi->incoming_values_and_blocks())
+ AddEdge(InVPBB, Phi->getParent(), InVal);
+
+ SetVector<const VPBlockBase *> Worklist(from_range, Phi->incoming_blocks());
+ while (!Worklist.empty()) {
+ auto *VPBB = cast<VPBasicBlock>(Worklist.pop_back_val());
+
+ // Check that all outgoing edges from VPBB have the same value.
+ SmallVector<EdgeTy> OutEdges;
+ for (const VPBlockBase *Succ : VPBB->getSuccessors())
+ OutEdges.emplace_back(VPBB, cast<VPBasicBlock>(Succ));
+ auto OutVals =
+ map_range(OutEdges, [&Edges](EdgeTy E) { return Edges.lookup(E); });
+ VPValue *Common = *OutVals.begin();
+ if (!Common || !all_equal(OutVals))
+ continue;
+
+ // They have the same value: we can move the edges up.
+ for (EdgeTy Edge : OutEdges)
+ Edges.erase(Edge);
+
+ // Iterate up through the post dominance frontier.
+ for (const VPBlockBase *Frontier : VPPDF.find(VPBB)->second) {
+ for (const VPBlockBase *FrontierSucc : Frontier->getSuccessors())
+ if (VPPDT.dominates(VPBB, FrontierSucc))
+ AddEdge(Frontier, FrontierSucc, Common);
+ Worklist.insert(cast<VPBasicBlock>(Frontier));
+ }
+ }
+
+ return Edges;
+}
+
+VPValue *VPPredicator::createBlendMaskForEdges(ArrayRef<EdgeTy> Edges,
+ VPBasicBlock *VPBB) {
+ // If the nearest common postdominator to all of Edges destinations isn't VPBB
+ // then we can use its block in-mask. E.g:
+ //
+ // A ... B
+ // \ \ /
+ // \ C
+ // \ /
+ // ... D ...
+ // \ | /
+ // VPBB
+ //
+ // If the edges are A->D and B->C, PostDom will be D. We can reuse Ds block
+ // in-mask.
+ const VPBasicBlock *PostDom = Edges[0].second;
+ for (auto [_, VPBB] : drop_begin(Edges))
----------------
fhahn wrote:
would be good to avoid shadowing `VPBB`
```suggestion
for (auto [_, DstVPBB] : drop_begin(Edges))
```
https://github.com/llvm/llvm-project/pull/201783
More information about the llvm-commits
mailing list