Skip to content

Commit 5df36e4

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 c305e73 commit 5df36e4

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
@@ -3069,11 +3069,9 @@ void InnerLoopVectorizer::fixNonInductionPHIs(VPTransformState &State) {
30693069
PHINode *NewPhi = cast<PHINode>(State.get(VPPhi));
30703070
// Make sure the builder has a valid insert point.
30713071
Builder.SetInsertPoint(NewPhi);
3072-
for (unsigned Idx = 0; Idx < VPPhi->getNumOperands(); ++Idx) {
3073-
VPValue *Inc = VPPhi->getIncomingValue(Idx);
3074-
VPBasicBlock *VPBB = VPPhi->getIncomingBlock(Idx);
3072+
3073+
for (const auto &[Inc, VPBB] : VPPhi->incoming_values_and_blocks())
30753074
NewPhi->addIncoming(State.get(Inc), State.CFG.VPBB2IRBB[VPBB]);
3076-
}
30773075
}
30783076
}
30793077
}

llvm/lib/Transforms/Vectorize/VPlan.h

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

1091+
/// Helper type to provide functions to access incoming values and blocks for
1092+
/// phi-like recipes. RecipeTy must be a sub-class of VPRecipeBase.
1093+
template <typename RecipeTy> class VPPhiAccessors {
1094+
/// Return a VPRecipeBase* to the current object.
1095+
const VPRecipeBase *getAsRecipe() const {
1096+
return static_cast<const RecipeTy *>(this);
1097+
}
1098+
1099+
public:
1100+
/// Returns the \p I th incoming VPValue.
1101+
VPValue *getIncomingValue(unsigned I) const {
1102+
return getAsRecipe()->getOperand(I);
1103+
}
1104+
1105+
/// Returns an interator range over the incoming values
1106+
VPUser::const_operand_range incoming_values() const {
1107+
return getAsRecipe()->operands();
1108+
}
1109+
1110+
/// Returns the \p I th incoming block.
1111+
const VPBasicBlock *getIncomingBlock(unsigned Idx) const;
1112+
1113+
using const_incoming_block_iterator =
1114+
mapped_iterator<detail::index_iterator,
1115+
std::function<const VPBasicBlock *(size_t)>>;
1116+
using const_incoming_blocks_range =
1117+
iterator_range<const_incoming_block_iterator>;
1118+
1119+
const_incoming_block_iterator incoming_block_begin() const {
1120+
return const_incoming_block_iterator(
1121+
detail::index_iterator(0),
1122+
[this](size_t Idx) { return getIncomingBlock(Idx); });
1123+
}
1124+
const_incoming_block_iterator incoming_block_end() const {
1125+
return const_incoming_block_iterator(
1126+
detail::index_iterator(getAsRecipe()->getVPDefID() ==
1127+
VPDef::VPWidenIntOrFpInductionSC
1128+
? 2
1129+
: getAsRecipe()->getNumOperands()),
1130+
[this](size_t Idx) { return getIncomingBlock(Idx); });
1131+
}
1132+
1133+
/// Returns an iterator range over the incoming blocks.
1134+
const_incoming_blocks_range incoming_blocks() const {
1135+
return make_range(incoming_block_begin(), incoming_block_end());
1136+
}
1137+
1138+
/// Returns an iterator range over pairs of incoming values and corrsponding
1139+
/// incoming blocks.
1140+
detail::zippy<llvm::detail::zip_shortest, VPUser::const_operand_range,
1141+
const_incoming_blocks_range>
1142+
incoming_values_and_blocks() const {
1143+
return zip(incoming_values(), incoming_blocks());
1144+
}
1145+
};
1146+
10911147
/// An overlay for VPIRInstructions wrapping PHI nodes enabling convenient use
10921148
/// cast/dyn_cast/isa and execute() implementation.
10931149
struct VPIRPhi : public VPIRInstruction {
@@ -1968,7 +2024,8 @@ class VPScalarPHIRecipe : public VPHeaderPHIRecipe {
19682024
/// recipe is placed in an entry block to a (non-replicate) region, it must have
19692025
/// exactly 2 incoming values, the first from the predecessor of the region and
19702026
/// the second from the exiting block of the region.
1971-
class VPWidenPHIRecipe : public VPSingleDefRecipe {
2027+
class VPWidenPHIRecipe : public VPSingleDefRecipe,
2028+
public VPPhiAccessors<VPWidenPHIRecipe> {
19722029
public:
19732030
/// Create a new VPWidenPHIRecipe for \p Phi with start value \p Start and
19742031
/// debug location \p DL.
@@ -1994,12 +2051,6 @@ class VPWidenPHIRecipe : public VPSingleDefRecipe {
19942051
void print(raw_ostream &O, const Twine &Indent,
19952052
VPSlotTracker &SlotTracker) const override;
19962053
#endif
1997-
1998-
/// Returns the \p I th incoming VPBasicBlock.
1999-
VPBasicBlock *getIncomingBlock(unsigned I);
2000-
2001-
/// Returns the \p I th incoming VPValue.
2002-
VPValue *getIncomingValue(unsigned I) { return getOperand(I); }
20032054
};
20042055

20052056
/// 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
@@ -1005,6 +1005,29 @@ void VPIRInstruction::print(raw_ostream &O, const Twine &Indent,
10051005
}
10061006
#endif
10071007

1008+
static const VPBasicBlock *getIncomingBlockForRecipe(const VPRecipeBase *R,
1009+
unsigned I) {
1010+
const VPBasicBlock *Parent = R->getParent();
1011+
const VPBlockBase *Pred = nullptr;
1012+
if (Parent->getNumPredecessors() > 0) {
1013+
Pred = Parent->getPredecessors()[I];
1014+
} else {
1015+
auto *Region = Parent->getParent();
1016+
assert(Region && !Region->isReplicator() && Region->getEntry() == Parent &&
1017+
"must be in the entry block of a non-replicate region");
1018+
assert(
1019+
I < 2 &&
1020+
(R->getNumOperands() == 2 || isa<VPWidenIntOrFpInductionRecipe>(R)) &&
1021+
"when placed in an entry block, only 2 incoming blocks are available");
1022+
1023+
// I == 0 selects the predecessor of the region, I == 1 selects the region
1024+
// itself whose exiting block feeds the phi across the backedge.
1025+
Pred = I == 0 ? Region->getSinglePredecessor() : Region;
1026+
}
1027+
1028+
return Pred->getExitingBasicBlock();
1029+
}
1030+
10081031
void VPIRPhi::execute(VPTransformState &State) {
10091032
PHINode *Phi = &getIRPhi();
10101033
for (const auto &[Idx, Op] : enumerate(operands())) {
@@ -3599,25 +3622,10 @@ void VPReductionPHIRecipe::print(raw_ostream &O, const Twine &Indent,
35993622
}
36003623
#endif
36013624

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

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

0 commit comments

Comments
 (0)