32 using EdgeMaskCacheTy =
33 DenseMap<std::pair<const VPBasicBlock *, const VPBasicBlock *>,
35 using BlockMaskCacheTy = DenseMap<VPBasicBlock *, VPValue *>;
36 EdgeMaskCacheTy EdgeMaskCache;
38 BlockMaskCacheTy BlockMaskCache;
41 void createSwitchEdgeMasks(VPInstruction *SI);
45 VPValue *createEdgeMask(VPBasicBlock *Src, VPBasicBlock *Dst);
48 VPValue *getBlockInMask(VPBasicBlock *VPBB)
const {
49 return BlockMaskCache.
lookup(VPBB);
54 void setBlockInMask(VPBasicBlock *VPBB, VPValue *Mask) {
57 assert(!getBlockInMask(VPBB) &&
"Mask already set");
58 BlockMaskCache[VPBB] =
Mask;
63 VPValue *setEdgeMask(
const VPBasicBlock *Src,
const VPBasicBlock *Dst,
65 assert(Src != Dst &&
"Src and Dst must be different");
66 assert(!getEdgeMask(Src, Dst) &&
"Mask already set");
67 return EdgeMaskCache[{Src, Dst}] =
Mask;
72 VPValue *getEdgeMask(
const VPBasicBlock *Src,
const VPBasicBlock *Dst)
const {
73 return EdgeMaskCache.
lookup({Src, Dst});
77 void createHeaderMask(VPBasicBlock *HeaderVPBB,
bool FoldTail);
81 VPValue *createBlockInMask(VPBasicBlock *VPBB);
84 void convertPhisToBlends(VPBasicBlock *VPBB);
86 const BlockMaskCacheTy getBlockMaskCache()
const {
return BlockMaskCache; }
94 VPValue *EdgeMask = getEdgeMask(Src, Dst);
98 VPValue *SrcMask = getBlockInMask(Src);
101 if (Src->getNumSuccessors() == 1)
102 return setEdgeMask(Src, Dst, SrcMask);
105 if (
Term->getOpcode() == Instruction::Switch) {
106 createSwitchEdgeMasks(Term);
107 return getEdgeMask(Src, Dst);
111 "Unsupported terminator");
112 if (Src->getSuccessors()[0] == Src->getSuccessors()[1])
113 return setEdgeMask(Src, Dst, SrcMask);
115 EdgeMask =
Term->getOperand(0);
116 assert(EdgeMask &&
"No Edge Mask found for condition");
118 if (Src->getSuccessors()[0] != Dst)
128 return setEdgeMask(Src, Dst, EdgeMask);
131VPValue *VPPredicator::createBlockInMask(VPBasicBlock *VPBB) {
136 VPValue *BlockMask =
nullptr;
138 for (
auto *Predecessor : SetVector<VPBlockBase *>(
143 setBlockInMask(VPBB, EdgeMask);
148 BlockMask = EdgeMask;
152 BlockMask = Builder.
createOr(BlockMask, EdgeMask, {});
155 setBlockInMask(VPBB, BlockMask);
159void VPPredicator::createHeaderMask(VPBasicBlock *HeaderVPBB,
bool FoldTail) {
161 setBlockInMask(HeaderVPBB,
nullptr);
170 auto &Plan = *HeaderVPBB->
getPlan();
171 auto *
IV =
new VPWidenCanonicalIVRecipe(Plan.getCanonicalIV());
175 VPValue *BTC = Plan.getOrCreateBackedgeTakenCount();
177 setBlockInMask(HeaderVPBB, BlockMask);
180void VPPredicator::createSwitchEdgeMasks(VPInstruction *SI) {
181 VPBasicBlock *Src =
SI->getParent();
186 VPValue *
Cond =
SI->getOperand(0);
188 MapVector<VPBasicBlock *, SmallVector<VPValue *>> Dst2Compares;
191 assert(!getEdgeMask(Src, Dst) &&
"Edge masks already created");
194 if (Dst == DefaultDst)
196 auto &Compares = Dst2Compares[Dst];
197 VPValue *
V =
SI->getOperand(Idx + 1);
203 VPValue *SrcMask = getBlockInMask(Src);
204 VPValue *DefaultMask =
nullptr;
205 for (
const auto &[Dst, Conds] : Dst2Compares) {
209 VPValue *
Mask = Conds[0];
214 setEdgeMask(Src, Dst, Mask);
220 DefaultMask = DefaultMask ? Builder.
createOr(DefaultMask, Mask) :
Mask;
224 DefaultMask = Builder.
createNot(DefaultMask);
228 setEdgeMask(Src, DefaultDst, DefaultMask);
231void VPPredicator::convertPhisToBlends(VPBasicBlock *VPBB) {
233 for (VPRecipeBase &R : VPBB->
phis())
235 for (VPPhi *PhiR : Phis) {
243 for (
const auto &[InVPV, InVPBB] : PhiR->incoming_values_and_blocks()) {
245 VPValue *EdgeMask = getEdgeMask(InVPBB, VPBB);
248 "Distinct incoming values with one having a full mask");
256 new VPBlendRecipe(IRPhi, OperandsWithMask, PhiR->getDebugLoc());
258 PhiR->replaceAllUsesWith(Blend);
259 PhiR->eraseFromParent();
263DenseMap<VPBasicBlock *, VPValue *>
278 if (VPBB == Header) {
279 Predicator.createHeaderMask(Header, FoldTail);
291 if (Successors.size() > 1)
296 for (
auto *Succ : Successors)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
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.
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.
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.
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...
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.
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.
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...
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.