35 VPPostDominatorTree VPPDT;
38 VPPostDominanceFrontier VPPDF;
42 using EdgeMaskCacheTy =
43 DenseMap<std::pair<const VPBasicBlock *, const VPBasicBlock *>,
45 using BlockMaskCacheTy = DenseMap<const VPBasicBlock *, VPValue *>;
46 EdgeMaskCacheTy EdgeMaskCache;
48 BlockMaskCacheTy BlockMaskCache;
51 void createSwitchEdgeMasks(
const VPInstruction *SI);
55 VPValue *createEdgeMask(
const VPBasicBlock *Src,
const VPBasicBlock *Dst);
59 void setBlockInMask(
const VPBasicBlock *VPBB, VPValue *Mask) {
62 assert(!getBlockInMask(VPBB) &&
"Mask already set");
63 BlockMaskCache[VPBB] =
Mask;
68 VPValue *setEdgeMask(
const VPBasicBlock *Src,
const VPBasicBlock *Dst,
70 assert(Src != Dst &&
"Src and Dst must be different");
71 assert(!getEdgeMask(Src, Dst) &&
"Mask already set");
72 return EdgeMaskCache[{Src, Dst}] =
Mask;
77 if (VPValue *Mask = getBlockInMask(VPBB))
78 if (VPRecipeBase *MaskR =
Mask->getDefiningRecipe())
79 if (MaskR->getParent() == VPBB)
80 return std::next(MaskR->getIterator());
84 using EdgeTy = std::pair<const VPBasicBlock *, const VPBasicBlock *>;
88 MapVector<EdgeTy, VPValue *> computeBlendEdges(VPPhi *Phi);
92 VPValue *createBlendMaskForEdges(
ArrayRef<EdgeTy> Edges, VPBasicBlock *VPBB);
95 VPPredicator(VPlan &Plan) : VPDT(Plan), VPPDT(Plan), VPPDF(VPPDT) {}
98 VPValue *getBlockInMask(
const VPBasicBlock *VPBB)
const {
99 return BlockMaskCache.
lookup(VPBB);
103 VPValue *getEdgeMask(
const VPBasicBlock *Src,
const VPBasicBlock *Dst)
const {
104 return EdgeMaskCache.
lookup({Src, Dst});
108 void createBlockInMask(VPBasicBlock *VPBB);
111 void convertPhisToBlends(VPBasicBlock *VPBB);
120 VPValue *EdgeMask = getEdgeMask(Src, Dst);
124 VPValue *SrcMask = getBlockInMask(Src);
127 if (Src->getNumSuccessors() == 1)
128 return setEdgeMask(Src, Dst, SrcMask);
131 if (
Term->getOpcode() == Instruction::Switch) {
132 createSwitchEdgeMasks(Term);
133 return getEdgeMask(Src, Dst);
137 "Unsupported terminator");
138 if (Src->getSuccessors()[0] == Src->getSuccessors()[1])
139 return setEdgeMask(Src, Dst, SrcMask);
141 EdgeMask =
Term->getOperand(0);
142 assert(EdgeMask &&
"No Edge Mask found for condition");
144 if (Src->getSuccessors()[0] != Dst)
154 return setEdgeMask(Src, Dst, EdgeMask);
157void VPPredicator::createBlockInMask(VPBasicBlock *VPBB) {
164 assert(IDom &&
"Block in loop must have immediate dominator");
167 setBlockInMask(VPBB, getBlockInMask(IDomBB));
172 VPValue *BlockMask =
nullptr;
174 for (
auto *Predecessor : SetVector<VPBlockBase *>(
179 setBlockInMask(VPBB, EdgeMask);
184 BlockMask = EdgeMask;
188 BlockMask = Builder.
createOr(BlockMask, EdgeMask, {});
191 setBlockInMask(VPBB, BlockMask);
194void VPPredicator::createSwitchEdgeMasks(
const VPInstruction *SI) {
195 const VPBasicBlock *Src =
SI->getParent();
200 VPValue *
Cond =
SI->getOperand(0);
202 MapVector<VPBasicBlock *, SmallVector<VPValue *>> Dst2Compares;
205 assert(!getEdgeMask(Src, Dst) &&
"Edge masks already created");
208 if (Dst == DefaultDst)
210 auto &Compares = Dst2Compares[Dst];
211 VPValue *
V =
SI->getOperand(Idx + 1);
217 VPValue *SrcMask = getBlockInMask(Src);
218 VPValue *DefaultMask =
nullptr;
219 for (
const auto &[Dst, Conds] : Dst2Compares) {
223 VPValue *
Mask = Conds[0];
228 setEdgeMask(Src, Dst, Mask);
234 DefaultMask = DefaultMask ? Builder.
createOr(DefaultMask, Mask) :
Mask;
238 DefaultMask = Builder.
createNot(DefaultMask);
244 DefaultMask = SrcMask;
246 setEdgeMask(Src, DefaultDst, DefaultMask);
262MapVector<VPPredicator::EdgeTy, VPValue *>
263VPPredicator::computeBlendEdges(VPPhi *Phi) {
264 MapVector<EdgeTy, VPValue *> Edges;
267 auto AddEdge = [&Edges](
const VPBlockBase *From,
const VPBlockBase *To,
271 "Clobbering an edge?");
275 for (
auto [InVal, InVPBB] :
Phi->incoming_values_and_blocks())
276 AddEdge(InVPBB,
Phi->getParent(), InVal);
278 SetVector<const VPBlockBase *> Worklist(
from_range,
Phi->incoming_blocks());
279 while (!Worklist.empty()) {
288 VPValue *Common = *OutVals.
begin();
293 for (EdgeTy
Edge : OutEdges)
298 "VPBB must have a post-dominance frontier entry");
299 for (
const VPBlockBase *Frontier : VPPDF.
find(VPBB)->second) {
300 for (
const VPBlockBase *FrontierSucc : Frontier->getSuccessors())
302 AddEdge(Frontier, FrontierSucc, Common);
311 VPBasicBlock *VPBB) {
325 const VPBasicBlock *PostDom = Edges[0].second;
329 assert(VPPDT.
dominates(VPBB, PostDom) &&
"VPBB doesn't postdominate edges");
331 return getBlockInMask(PostDom);
334 VPValue *
Mask =
nullptr;
335 for (
auto [Src, ConstDst] : Edges) {
336 auto *Dst =
const_cast<VPBasicBlock *
>(ConstDst);
339 VPBuilder::InsertPointGuard Guard(Builder);
341 EdgeMask = createEdgeMask(Src, Dst);
348void VPPredicator::convertPhisToBlends(VPBasicBlock *VPBB) {
352 for (VPRecipeBase &R : VPBB->
phis())
354 for (VPPhi *PhiR : Phis) {
362 return !match(V, m_Poison());
365 PhiR->replaceAllUsesWith(NotPoison.empty() ? PhiR->getIncomingValue(0)
366 : *NotPoison.begin());
367 PhiR->eraseFromParent();
371 MapVector<VPValue *, SmallVector<EdgeTy>> InValEdgesMap;
372 for (
auto [
Edge, Val] : computeBlendEdges(PhiR))
373 InValEdgesMap[Val].push_back(
Edge);
378 auto InVs = PhiR->incoming_values();
379 return std::distance(InVs.begin(),
find(InVs,
L.first)) <
380 std::distance(InVs.begin(),
find(InVs,
R.first));
384 for (
const auto &[InVPV, Edges] : InValEdges) {
385 OperandsWithMask.push_back(InVPV);
386 OperandsWithMask.push_back(createBlendMaskForEdges(Edges, VPBB));
390 new VPBlendRecipe(IRPhi, OperandsWithMask, *PhiR, PhiR->getDebugLoc());
392 PhiR->replaceAllUsesWith(Blend);
393 PhiR->eraseFromParent();
424 VPI->addMask(BlockMask);
436 if (Successors.size() > 1)
441 for (
auto *Succ : Successors)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
std::pair< BasicBlock *, BasicBlock * > Edge
This file implements dominator tree analysis for a single level of a VPlan's H-CFG.
This file contains the declarations of the Vectorization Plan base classes:
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
DomTreeNodeBase * getIDom() const
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
ValueT lookup(const KeyT &Key) const
VectorType takeVector()
Clear the MapVector and return the underlying vector.
bool contains(const KeyT &Key) const
VectorType::iterator erase(typename VectorType::iterator Iterator)
Remove the element given by Iterator.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
RecipeListTy::iterator iterator
Instruction iterators...
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.
const VPBlocksTy & getPredecessors() const
const VPBasicBlock * getEntryBasicBlock() const
const VPBlocksTy & getSuccessors() const
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.
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
VPInstruction * createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
T * insert(T *R)
Insert R at the current insertion point. Returns R unchanged.
VPInstruction * createNot(VPValue *Operand, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
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.
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...
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...
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
LLVM_ABI_FOR_TEST bool isOuterLoop() const
Returns true if this VPlan is for an outer loop, i.e., its vector loop region contains a nested loop ...
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.
NodeAddr< PhiNode * > Phi
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.
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr from_range_t from_range
auto cast_or_null(const Y &Val)
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
auto reverse(ContainerTy &&C)
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...
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - 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.