@@ -16,7 +16,9 @@ class ScalarEvolution;
16
16
class SCEV ;
17
17
} // namespace llvm
18
18
19
- namespace llvm ::vputils {
19
+ namespace llvm {
20
+
21
+ namespace vputils {
20
22
// / Returns true if only the first lane of \p Def is used.
21
23
bool onlyFirstLaneUsed (const VPValue *Def);
22
24
@@ -67,6 +69,152 @@ bool isHeaderMask(const VPValue *V, VPlan &Plan);
67
69
// / VPDerivedIV or VPCanonicalIVPHI).
68
70
bool isUniformAcrossVFsAndUFs (VPValue *V);
69
71
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
71
219
72
220
#endif
0 commit comments