@@ -16,7 +16,9 @@ class ScalarEvolution;
1616class SCEV ;
1717} // namespace llvm
1818
19- namespace llvm ::vputils {
19+ namespace llvm {
20+
21+ namespace vputils {
2022// / Returns true if only the first lane of \p Def is used.
2123bool onlyFirstLaneUsed (const VPValue *Def);
2224
@@ -67,6 +69,152 @@ bool isHeaderMask(const VPValue *V, VPlan &Plan);
6769// / VPDerivedIV or VPCanonicalIVPHI).
6870bool isUniformAcrossVFsAndUFs (VPValue *V);
6971
70- } // end namespace llvm::vputils
72+ } // namespace vputils
73+
74+ // ===----------------------------------------------------------------------===//
75+ // Utilities for modifying predecessors and successors of VPlan blocks.
76+ // ===----------------------------------------------------------------------===//
77+
78+ // / Class that provides utilities for VPBlockBases in VPlan.
79+ class VPBlockUtils {
80+ public:
81+ VPBlockUtils () = delete ;
82+
83+ // / Insert disconnected VPBlockBase \p NewBlock after \p BlockPtr. Add \p
84+ // / NewBlock as successor of \p BlockPtr and \p BlockPtr as predecessor of \p
85+ // / NewBlock, and propagate \p BlockPtr parent to \p NewBlock. \p BlockPtr's
86+ // / successors are moved from \p BlockPtr to \p NewBlock. \p NewBlock must
87+ // / have neither successors nor predecessors.
88+ static void insertBlockAfter (VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
89+ assert (NewBlock->getSuccessors ().empty () &&
90+ NewBlock->getPredecessors ().empty () &&
91+ " Can't insert new block with predecessors or successors." );
92+ NewBlock->setParent (BlockPtr->getParent ());
93+ SmallVector<VPBlockBase *> Succs (BlockPtr->successors ());
94+ for (VPBlockBase *Succ : Succs) {
95+ disconnectBlocks (BlockPtr, Succ);
96+ connectBlocks (NewBlock, Succ);
97+ }
98+ connectBlocks (BlockPtr, NewBlock);
99+ }
100+
101+ // / Insert disconnected block \p NewBlock before \p Blockptr. First
102+ // / disconnects all predecessors of \p BlockPtr and connects them to \p
103+ // / NewBlock. Add \p NewBlock as predecessor of \p BlockPtr and \p BlockPtr as
104+ // / successor of \p NewBlock.
105+ static void insertBlockBefore (VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
106+ assert (NewBlock->getSuccessors ().empty () &&
107+ NewBlock->getPredecessors ().empty () &&
108+ " Can't insert new block with predecessors or successors." );
109+ NewBlock->setParent (BlockPtr->getParent ());
110+ for (VPBlockBase *Pred : to_vector (BlockPtr->predecessors ())) {
111+ disconnectBlocks (Pred, BlockPtr);
112+ connectBlocks (Pred, NewBlock);
113+ }
114+ connectBlocks (NewBlock, BlockPtr);
115+ }
116+
117+ // / Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
118+ // / BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
119+ // / BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
120+ // / parent to \p IfTrue and \p IfFalse. \p BlockPtr must have no successors
121+ // / and \p IfTrue and \p IfFalse must have neither successors nor
122+ // / predecessors.
123+ static void insertTwoBlocksAfter (VPBlockBase *IfTrue, VPBlockBase *IfFalse,
124+ VPBlockBase *BlockPtr) {
125+ assert (IfTrue->getSuccessors ().empty () &&
126+ " Can't insert IfTrue with successors." );
127+ assert (IfFalse->getSuccessors ().empty () &&
128+ " Can't insert IfFalse with successors." );
129+ BlockPtr->setTwoSuccessors (IfTrue, IfFalse);
130+ IfTrue->setPredecessors ({BlockPtr});
131+ IfFalse->setPredecessors ({BlockPtr});
132+ IfTrue->setParent (BlockPtr->getParent ());
133+ IfFalse->setParent (BlockPtr->getParent ());
134+ }
135+
136+ // / Connect VPBlockBases \p From and \p To bi-directionally. If \p PredIdx is
137+ // / -1, append \p From to the predecessors of \p To, otherwise set \p To's
138+ // / predecessor at \p PredIdx to \p From. If \p SuccIdx is -1, append \p To to
139+ // / the successors of \p From, otherwise set \p From's successor at \p SuccIdx
140+ // / to \p To. Both VPBlockBases must have the same parent, which can be null.
141+ // / Both VPBlockBases can be already connected to other VPBlockBases.
142+ static void connectBlocks (VPBlockBase *From, VPBlockBase *To,
143+ unsigned PredIdx = -1u , unsigned SuccIdx = -1u ) {
144+ assert ((From->getParent () == To->getParent ()) &&
145+ " Can't connect two block with different parents" );
146+ assert ((SuccIdx != -1u || From->getNumSuccessors () < 2 ) &&
147+ " Blocks can't have more than two successors." );
148+ if (SuccIdx == -1u )
149+ From->appendSuccessor (To);
150+ else
151+ From->getSuccessors ()[SuccIdx] = To;
152+
153+ if (PredIdx == -1u )
154+ To->appendPredecessor (From);
155+ else
156+ To->getPredecessors ()[PredIdx] = From;
157+ }
158+
159+ // / Disconnect VPBlockBases \p From and \p To bi-directionally. Remove \p To
160+ // / from the successors of \p From and \p From from the predecessors of \p To.
161+ static void disconnectBlocks (VPBlockBase *From, VPBlockBase *To) {
162+ assert (To && " Successor to disconnect is null." );
163+ From->removeSuccessor (To);
164+ To->removePredecessor (From);
165+ }
166+
167+ // / Reassociate all the blocks connected to \p Old so that they now point to
168+ // / \p New.
169+ static void reassociateBlocks (VPBlockBase *Old, VPBlockBase *New) {
170+ for (auto *Pred : to_vector (Old->getPredecessors ()))
171+ Pred->replaceSuccessor (Old, New);
172+ for (auto *Succ : to_vector (Old->getSuccessors ()))
173+ Succ->replacePredecessor (Old, New);
174+ New->setPredecessors (Old->getPredecessors ());
175+ New->setSuccessors (Old->getSuccessors ());
176+ Old->clearPredecessors ();
177+ Old->clearSuccessors ();
178+ }
179+
180+ // / Return an iterator range over \p Range which only includes \p BlockTy
181+ // / blocks. The accesses are casted to \p BlockTy.
182+ template <typename BlockTy, typename T>
183+ static auto blocksOnly (const T &Range) {
184+ // Create BaseTy with correct const-ness based on BlockTy.
185+ using BaseTy = std::conditional_t <std::is_const<BlockTy>::value,
186+ const VPBlockBase, VPBlockBase>;
187+
188+ // We need to first create an iterator range over (const) BlocktTy & instead
189+ // of (const) BlockTy * for filter_range to work properly.
190+ auto Mapped =
191+ map_range (Range, [](BaseTy *Block) -> BaseTy & { return *Block; });
192+ auto Filter = make_filter_range (
193+ Mapped, [](BaseTy &Block) { return isa<BlockTy>(&Block); });
194+ return map_range (Filter, [](BaseTy &Block) -> BlockTy * {
195+ return cast<BlockTy>(&Block);
196+ });
197+ }
198+
199+ // / Inserts \p BlockPtr on the edge between \p From and \p To. That is, update
200+ // / \p From's successor to \p To to point to \p BlockPtr and \p To's
201+ // / predecessor from \p From to \p BlockPtr. \p From and \p To are added to \p
202+ // / BlockPtr's predecessors and successors respectively. There must be a
203+ // / single edge between \p From and \p To.
204+ static void insertOnEdge (VPBlockBase *From, VPBlockBase *To,
205+ VPBlockBase *BlockPtr) {
206+ auto &Successors = From->getSuccessors ();
207+ auto &Predecessors = To->getPredecessors ();
208+ assert (count (Successors, To) == 1 && count (Predecessors, From) == 1 &&
209+ " must have single between From and To" );
210+ unsigned SuccIdx = std::distance (Successors.begin (), find (Successors, To));
211+ unsigned PredIx =
212+ std::distance (Predecessors.begin (), find (Predecessors, From));
213+ VPBlockUtils::connectBlocks (From, BlockPtr, -1 , SuccIdx);
214+ VPBlockUtils::connectBlocks (BlockPtr, To, PredIx, -1 );
215+ }
216+ };
217+
218+ } // namespace llvm
71219
72220#endif
0 commit comments