LLVM: lib/Transforms/Vectorize/VPlanPredicator.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
21
22using namespace llvm;
24
25namespace {
26class VPPredicator {
27
28 VPBuilder Builder;
29
30
31
32 using EdgeMaskCacheTy =
33 DenseMap<std::pair<const VPBasicBlock *, const VPBasicBlock *>,
34 VPValue *>;
35 using BlockMaskCacheTy = DenseMap<VPBasicBlock *, VPValue *>;
36 EdgeMaskCacheTy EdgeMaskCache;
37
38 BlockMaskCacheTy BlockMaskCache;
39
40
41 void createSwitchEdgeMasks(VPInstruction *SI);
42
43
44
45 VPValue *createEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst);
46
47
48
49 void setBlockInMask(VPBasicBlock *VPBB, VPValue *Mask) {
50
51
52 assert(!getBlockInMask(VPBB) && "Mask already set");
53 BlockMaskCache[VPBB] = Mask;
54 }
55
56
57
58 VPValue *setEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst,
59 VPValue *Mask) {
60 assert(Src != Dst && "Src and Dst must be different");
61 assert(!getEdgeMask(Src, Dst) && "Mask already set");
62 return EdgeMaskCache[{Src, Dst}] = Mask;
63 }
64
65public:
66
67 VPValue *getBlockInMask(VPBasicBlock *VPBB) const {
68 return BlockMaskCache.lookup(VPBB);
69 }
70
71
72 VPValue *getEdgeMask(const VPBasicBlock *Src, const VPBasicBlock *Dst) const {
73 return EdgeMaskCache.lookup({Src, Dst});
74 }
75
76
77 void createHeaderMask(VPBasicBlock *HeaderVPBB, bool FoldTail);
78
79
80
81 VPValue *createBlockInMask(VPBasicBlock *VPBB);
82
83
84 void convertPhisToBlends(VPBasicBlock *VPBB);
85
86 const BlockMaskCacheTy getBlockMaskCache() const { return BlockMaskCache; }
87};
88}
89
92
93
94 VPValue *EdgeMask = getEdgeMask(Src, Dst);
95 if (EdgeMask)
96 return EdgeMask;
97
98 VPValue *SrcMask = getBlockInMask(Src);
99
100
101 if (Src->getNumSuccessors() == 1)
102 return setEdgeMask(Src, Dst, SrcMask);
103
105 if (Term->getOpcode() == Instruction::Switch) {
106 createSwitchEdgeMasks(Term);
107 return getEdgeMask(Src, Dst);
108 }
109
111 "Unsupported terminator");
112 if (Src->getSuccessors()[0] == Src->getSuccessors()[1])
113 return setEdgeMask(Src, Dst, SrcMask);
114
115 EdgeMask = Term->getOperand(0);
116 assert(EdgeMask && "No Edge Mask found for condition");
117
118 if (Src->getSuccessors()[0] != Dst)
119 EdgeMask = Builder.createNot(EdgeMask, Term->getDebugLoc());
120
121 if (SrcMask) {
122
123
124
126 }
127
128 return setEdgeMask(Src, Dst, EdgeMask);
129}
130
131VPValue *VPPredicator::createBlockInMask(VPBasicBlock *VPBB) {
132
134
135
136 VPValue *BlockMask = nullptr;
137
138 for (auto *Predecessor : SetVector<VPBlockBase *>(
140 VPValue *EdgeMask = createEdgeMask(cast(Predecessor), VPBB);
141 if (!EdgeMask) {
142
143 setBlockInMask(VPBB, EdgeMask);
144 return EdgeMask;
145 }
146
147 if (!BlockMask) {
148 BlockMask = EdgeMask;
149 continue;
150 }
151
152 BlockMask = Builder.createOr(BlockMask, EdgeMask, {});
153 }
154
155 setBlockInMask(VPBB, BlockMask);
156 return BlockMask;
157}
158
159void VPPredicator::createHeaderMask(VPBasicBlock *HeaderVPBB, bool FoldTail) {
160 if (!FoldTail) {
161 setBlockInMask(HeaderVPBB, nullptr);
162 return;
163 }
164
165
166
167
168
169
170 auto &Plan = *HeaderVPBB->getPlan();
171 auto *IV =
175
176 VPValue *BTC = Plan.getOrCreateBackedgeTakenCount();
178 setBlockInMask(HeaderVPBB, BlockMask);
179}
180
181void VPPredicator::createSwitchEdgeMasks(VPInstruction *SI) {
182 VPBasicBlock *Src = SI->getParent();
183
184
185
186
187 VPValue *Cond = SI->getOperand(0);
188 VPBasicBlock *DefaultDst = cast(Src->getSuccessors()[0]);
189 MapVector<VPBasicBlock *, SmallVector<VPValue *>> Dst2Compares;
190 for (const auto &[Idx, Succ] : enumerate(drop_begin(Src->getSuccessors()))) {
192 assert(!getEdgeMask(Src, Dst) && "Edge masks already created");
193
194
195 if (Dst == DefaultDst)
196 continue;
197 auto &Compares = Dst2Compares[Dst];
198 VPValue *V = SI->getOperand(Idx + 1);
200 }
201
202
203
204 VPValue *SrcMask = getBlockInMask(Src);
205 VPValue *DefaultMask = nullptr;
206 for (const auto &[Dst, Conds] : Dst2Compares) {
207
208
209
210 VPValue *Mask = Conds[0];
213 if (SrcMask)
215 setEdgeMask(Src, Dst, Mask);
216
217
218
219
220
221 DefaultMask = DefaultMask ? Builder.createOr(DefaultMask, Mask) : Mask;
222 }
223
224 if (DefaultMask) {
225 DefaultMask = Builder.createNot(DefaultMask);
226 if (SrcMask)
227 DefaultMask = Builder.createLogicalAnd(SrcMask, DefaultMask);
228 }
229 setEdgeMask(Src, DefaultDst, DefaultMask);
230}
231
232void VPPredicator::convertPhisToBlends(VPBasicBlock *VPBB) {
234 for (VPRecipeBase &R : VPBB->phis())
236 for (VPPhi *PhiR : Phis) {
237
238
239
240
241
242
244 for (const auto &[InVPV, InVPBB] : PhiR->incoming_values_and_blocks()) {
245 OperandsWithMask.push_back(InVPV);
246 VPValue *EdgeMask = getEdgeMask(InVPBB, VPBB);
247 if (!EdgeMask) {
249 "Distinct incoming values with one having a full mask");
250 break;
251 }
252
253 OperandsWithMask.push_back(EdgeMask);
254 }
256 auto *Blend =
257 new VPBlendRecipe(IRPhi, OperandsWithMask, PhiR->getDebugLoc());
258 Builder.insert(Blend);
259 PhiR->replaceAllUsesWith(Blend);
260 PhiR->eraseFromParent();
261 }
262}
263
264DenseMap<VPBasicBlock *, VPValue *>
267
268
271 Header);
274
276
277
278
279 if (VPBB == Header) {
280 Predicator.createHeaderMask(Header, FoldTail);
281 continue;
282 }
283
285 Predicator.convertPhisToBlends(VPBB);
286 }
287
288
292 if (Successors.size() > 1)
294
295
296
297 for (auto *Succ : Successors)
299 if (PrevVPBB)
301
302 PrevVPBB = VPBB;
303 }
304
305
306
307
308
309 if (FoldTail) {
311 "only a single-exit block is supported currently");
314 "the exit block must have middle block as single predecessor");
315
320 continue;
321
322
324 VPValue *LastActiveLane =
326 auto *Ext =
328 R.getVPSingleValue()->replaceAllUsesWith(Ext);
329 }
330 }
331 return Predicator.getBlockMaskCache();
332}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
This file provides utility VPlan to VPlan transformations.
This file contains the declarations of the Vectorization Plan base classes:
static const uint32_t IV[8]
@ ICMP_ULE
unsigned less or equal
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
void push_back(const T &Elt)
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
iterator getFirstNonPhi()
Return the position of the first non-phi node recipe in the block.
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
VPRegionBlock * getParent()
const VPBlocksTy & getPredecessors() const
const VPBasicBlock * getEntryBasicBlock() const
const VPBlocksTy & getSuccessors() const
static auto blocksOnly(const T &Range)
Return an iterator range over Range which only includes BlockTy blocks.
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
VPlan-based builder utility analogous to IRBuilder.
VPInstruction * createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createNot(VPValue *Operand, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
void insert(VPRecipeBase *R)
Insert R at the current insertion point.
VPInstruction * createICmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
Create a new ICmp VPInstruction with predicate Pred and operands A and B.
void setInsertPoint(VPBasicBlock *TheBB)
This specifies that created VPInstructions should be appended to the end of the specified block.
@ ExtractLane
Extracts a single lane (first operand) from a set of vector operands.
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
iplist< VPRecipeBase >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
VPCanonicalIVPHIRecipe * getCanonicalIV()
Returns the canonical induction recipe of the region.
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
ArrayRef< VPIRBasicBlock * > getExitBlocks() const
Return an ArrayRef containing VPIRBasicBlocks wrapping the exit blocks of the original scalar loop.
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
VPBasicBlock * getMiddleBlock()
Returns the 'middle' block of the plan, that is the block that selects whether to execute the scalar ...
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
bool match(Val *V, const Pattern &P)
VPInstruction_match< VPInstruction::ExtractLastLane, Op0_t > m_ExtractLastLane(const Op0_t &Op0)
VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > m_ExtractLastPart(const Op0_t &Op0)
class_match< VPValue > m_VPValue()
Match an arbitrary VPValue and ignore it.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
auto cast_or_null(const Y &Val)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
static DenseMap< VPBasicBlock *, VPValue * > introduceMasksAndLinearize(VPlan &Plan, bool FoldTail)
Predicate and linearize the control-flow in the only loop region of Plan.
Definition VPlanPredicator.cpp:265