Skip to content

Commit c606923

Browse files
committed
[VPlan] Add VPPhiAccessors to provide interface for phi recipes (NFC)
Add a VPPhiAccessors class to provide interfaces to access incoming values and blocks, with corresponding iterators. The first user is VPWidenPhiRecipe, with the other phi-like recipes following soon. This will also be used to verify def-use chains where users are phi-like recipes, simplifying llvm#124838.
1 parent 0fc05ca commit c606923

File tree

3 files changed

+87
-30
lines changed

3 files changed

+87
-30
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3058,11 +3058,9 @@ void InnerLoopVectorizer::fixNonInductionPHIs(VPTransformState &State) {
30583058
PHINode *NewPhi = cast<PHINode>(State.get(VPPhi));
30593059
// Make sure the builder has a valid insert point.
30603060
Builder.SetInsertPoint(NewPhi);
3061-
for (unsigned Idx = 0; Idx < VPPhi->getNumOperands(); ++Idx) {
3062-
VPValue *Inc = VPPhi->getIncomingValue(Idx);
3063-
VPBasicBlock *VPBB = VPPhi->getIncomingBlock(Idx);
3061+
3062+
for (const auto &[Inc, VPBB] : VPPhi->incoming_values_and_blocks())
30643063
NewPhi->addIncoming(State.get(Inc), State.CFG.VPBB2IRBB[VPBB]);
3065-
}
30663064
}
30673065
}
30683066
}

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,62 @@ class VPIRInstruction : public VPRecipeBase {
10891089
void extractLastLaneOfOperand(VPBuilder &Builder);
10901090
};
10911091

1092+
/// Helper type to provide functions to access incoming values and blocks for
1093+
/// phi-like recipes. RecipeTy must be a sub-class of VPRecipeBase.
1094+
template <typename RecipeTy> class VPPhiAccessors {
1095+
/// Return a VPRecipeBase* to the current object.
1096+
const VPRecipeBase *getAsRecipe() const {
1097+
return static_cast<const RecipeTy *>(this);
1098+
}
1099+
1100+
public:
1101+
/// Returns the \p I th incoming VPValue.
1102+
VPValue *getIncomingValue(unsigned I) const {
1103+
return getAsRecipe()->getOperand(I);
1104+
}
1105+
1106+
/// Returns an interator range over the incoming values
1107+
VPUser::const_operand_range incoming_values() const {
1108+
return getAsRecipe()->operands();
1109+
}
1110+
1111+
/// Returns the \p I th incoming block.
1112+
const VPBasicBlock *getIncomingBlock(unsigned Idx) const;
1113+
1114+
using const_incoming_block_iterator =
1115+
mapped_iterator<detail::index_iterator,
1116+
std::function<const VPBasicBlock *(size_t)>>;
1117+
using const_incoming_blocks_range =
1118+
iterator_range<const_incoming_block_iterator>;
1119+
1120+
const_incoming_block_iterator incoming_block_begin() const {
1121+
return const_incoming_block_iterator(
1122+
detail::index_iterator(0),
1123+
[this](size_t Idx) { return getIncomingBlock(Idx); });
1124+
}
1125+
const_incoming_block_iterator incoming_block_end() const {
1126+
return const_incoming_block_iterator(
1127+
detail::index_iterator(getAsRecipe()->getVPDefID() ==
1128+
VPDef::VPWidenIntOrFpInductionSC
1129+
? 2
1130+
: getAsRecipe()->getNumOperands()),
1131+
[this](size_t Idx) { return getIncomingBlock(Idx); });
1132+
}
1133+
1134+
/// Returns an iterator range over the incoming blocks.
1135+
const_incoming_blocks_range incoming_blocks() const {
1136+
return make_range(incoming_block_begin(), incoming_block_end());
1137+
}
1138+
1139+
/// Returns an iterator range over pairs of incoming values and corrsponding
1140+
/// incoming blocks.
1141+
detail::zippy<llvm::detail::zip_shortest, VPUser::const_operand_range,
1142+
const_incoming_blocks_range>
1143+
incoming_values_and_blocks() const {
1144+
return zip(incoming_values(), incoming_blocks());
1145+
}
1146+
};
1147+
10921148
/// An overlay for VPIRInstructions wrapping PHI nodes enabling convenient use
10931149
/// cast/dyn_cast/isa and execute() implementation.
10941150
struct VPIRPhi : public VPIRInstruction {
@@ -1947,7 +2003,8 @@ class VPScalarPHIRecipe : public VPHeaderPHIRecipe {
19472003
/// recipe is placed in an entry block to a (non-replicate) region, it must have
19482004
/// exactly 2 incoming values, the first from the predecessor of the region and
19492005
/// the second from the exiting block of the region.
1950-
class VPWidenPHIRecipe : public VPSingleDefRecipe {
2006+
class VPWidenPHIRecipe : public VPSingleDefRecipe,
2007+
public VPPhiAccessors<VPWidenPHIRecipe> {
19512008
/// Name to use for the generated IR instruction for the widened phi.
19522009
std::string Name;
19532010

@@ -1978,12 +2035,6 @@ class VPWidenPHIRecipe : public VPSingleDefRecipe {
19782035
void print(raw_ostream &O, const Twine &Indent,
19792036
VPSlotTracker &SlotTracker) const override;
19802037
#endif
1981-
1982-
/// Returns the \p I th incoming VPBasicBlock.
1983-
VPBasicBlock *getIncomingBlock(unsigned I);
1984-
1985-
/// Returns the \p I th incoming VPValue.
1986-
VPValue *getIncomingValue(unsigned I) { return getOperand(I); }
19872038
};
19882039

19892040
/// A recipe for handling first-order recurrence phis. The start value is the

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,29 @@ void VPIRInstruction::print(raw_ostream &O, const Twine &Indent,
10161016
}
10171017
#endif
10181018

1019+
static const VPBasicBlock *getIncomingBlockForRecipe(const VPRecipeBase *R,
1020+
unsigned I) {
1021+
const VPBasicBlock *Parent = R->getParent();
1022+
const VPBlockBase *Pred = nullptr;
1023+
if (Parent->getNumPredecessors() > 0) {
1024+
Pred = Parent->getPredecessors()[I];
1025+
} else {
1026+
auto *Region = Parent->getParent();
1027+
assert(Region && !Region->isReplicator() && Region->getEntry() == Parent &&
1028+
"must be in the entry block of a non-replicate region");
1029+
assert(
1030+
I < 2 &&
1031+
(R->getNumOperands() == 2 || isa<VPWidenIntOrFpInductionRecipe>(R)) &&
1032+
"when placed in an entry block, only 2 incoming blocks are available");
1033+
1034+
// I == 0 selects the predecessor of the region, I == 1 selects the region
1035+
// itself whose exiting block feeds the phi across the backedge.
1036+
Pred = I == 0 ? Region->getSinglePredecessor() : Region;
1037+
}
1038+
1039+
return Pred->getExitingBasicBlock();
1040+
}
1041+
10191042
void VPIRPhi::execute(VPTransformState &State) {
10201043
PHINode *Phi = &getIRPhi();
10211044
for (const auto &[Idx, Op] : enumerate(operands())) {
@@ -3608,25 +3631,10 @@ void VPReductionPHIRecipe::print(raw_ostream &O, const Twine &Indent,
36083631
}
36093632
#endif
36103633

3611-
VPBasicBlock *VPWidenPHIRecipe::getIncomingBlock(unsigned I) {
3612-
VPBasicBlock *Parent = getParent();
3613-
VPBlockBase *Pred = nullptr;
3614-
if (Parent->getNumPredecessors() > 0) {
3615-
Pred = Parent->getPredecessors()[I];
3616-
} else {
3617-
auto *Region = Parent->getParent();
3618-
assert(Region && !Region->isReplicator() && Region->getEntry() == Parent &&
3619-
"must be in the entry block of a non-replicate region");
3620-
assert(
3621-
I < 2 && getNumOperands() == 2 &&
3622-
"when placed in an entry block, only 2 incoming blocks are available");
3623-
3624-
// I == 0 selects the predecessor of the region, I == 1 selects the region
3625-
// itself whose exiting block feeds the phi across the backedge.
3626-
Pred = I == 0 ? Region->getSinglePredecessor() : Region;
3627-
}
3628-
3629-
return Pred->getExitingBasicBlock();
3634+
template <>
3635+
const VPBasicBlock *
3636+
VPPhiAccessors<VPWidenPHIRecipe>::getIncomingBlock(unsigned Idx) const {
3637+
return getIncomingBlockForRecipe(getAsRecipe(), Idx);
36303638
}
36313639

36323640
void VPWidenPHIRecipe::execute(VPTransformState &State) {

0 commit comments

Comments
 (0)