Skip to content

Commit b357af4

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 #124838.
1 parent 9f37cdc commit b357af4

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
@@ -1085,6 +1085,62 @@ class VPIRInstruction : public VPRecipeBase {
10851085
void extractLastLaneOfOperand(VPBuilder &Builder);
10861086
};
10871087

1088+
/// Helper type to provide functions to access incoming values and blocks for
1089+
/// phi-like recipes. RecipeTy must be a sub-class of VPRecipeBase.
1090+
template <typename RecipeTy> class VPPhiAccessors {
1091+
/// Return a VPRecipeBase* to the current object.
1092+
const VPRecipeBase *getAsRecipe() const {
1093+
return static_cast<const RecipeTy *>(this);
1094+
}
1095+
1096+
public:
1097+
/// Returns the \p I th incoming VPValue.
1098+
VPValue *getIncomingValue(unsigned I) const {
1099+
return getAsRecipe()->getOperand(I);
1100+
}
1101+
1102+
/// Returns an interator range over the incoming values
1103+
VPUser::const_operand_range incoming_values() const {
1104+
return getAsRecipe()->operands();
1105+
}
1106+
1107+
/// Returns the \p I th incoming block.
1108+
const VPBasicBlock *getIncomingBlock(unsigned Idx) const;
1109+
1110+
using const_incoming_block_iterator =
1111+
mapped_iterator<detail::index_iterator,
1112+
std::function<const VPBasicBlock *(size_t)>>;
1113+
using const_incoming_blocks_range =
1114+
iterator_range<const_incoming_block_iterator>;
1115+
1116+
const_incoming_block_iterator incoming_block_begin() const {
1117+
return const_incoming_block_iterator(
1118+
detail::index_iterator(0),
1119+
[this](size_t Idx) { return getIncomingBlock(Idx); });
1120+
}
1121+
const_incoming_block_iterator incoming_block_end() const {
1122+
return const_incoming_block_iterator(
1123+
detail::index_iterator(getAsRecipe()->getVPDefID() ==
1124+
VPDef::VPWidenIntOrFpInductionSC
1125+
? 2
1126+
: getAsRecipe()->getNumOperands()),
1127+
[this](size_t Idx) { return getIncomingBlock(Idx); });
1128+
}
1129+
1130+
/// Returns an iterator range over the incoming blocks.
1131+
const_incoming_blocks_range incoming_blocks() const {
1132+
return make_range(incoming_block_begin(), incoming_block_end());
1133+
}
1134+
1135+
/// Returns an iterator range over pairs of incoming values and corrsponding
1136+
/// incoming blocks.
1137+
detail::zippy<llvm::detail::zip_shortest, VPUser::const_operand_range,
1138+
const_incoming_blocks_range>
1139+
incoming_values_and_blocks() const {
1140+
return zip(incoming_values(), incoming_blocks());
1141+
}
1142+
};
1143+
10881144
/// VPWidenRecipe is a recipe for producing a widened instruction using the
10891145
/// opcode and operands of the recipe. This recipe covers most of the
10901146
/// traditional vectorization cases where each recipe transforms into a
@@ -1944,7 +2000,8 @@ class VPScalarPHIRecipe : public VPHeaderPHIRecipe {
19442000
/// recipe is placed in an entry block to a (non-replicate) region, it must have
19452001
/// exactly 2 incoming values, the first from the predecessor of the region and
19462002
/// the second from the exiting block of the region.
1947-
class VPWidenPHIRecipe : public VPSingleDefRecipe {
2003+
class VPWidenPHIRecipe : public VPSingleDefRecipe,
2004+
public VPPhiAccessors<VPWidenPHIRecipe> {
19482005
public:
19492006
/// Create a new VPWidenPHIRecipe for \p Phi with start value \p Start and
19502007
/// debug location \p DL.
@@ -1970,12 +2027,6 @@ class VPWidenPHIRecipe : public VPSingleDefRecipe {
19702027
void print(raw_ostream &O, const Twine &Indent,
19712028
VPSlotTracker &SlotTracker) const override;
19722029
#endif
1973-
1974-
/// Returns the \p I th incoming VPBasicBlock.
1975-
VPBasicBlock *getIncomingBlock(unsigned I);
1976-
1977-
/// Returns the \p I th incoming VPValue.
1978-
VPValue *getIncomingValue(unsigned I) { return getOperand(I); }
19792030
};
19802031

19812032
/// 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
@@ -1031,6 +1031,29 @@ void VPIRInstruction::print(raw_ostream &O, const Twine &Indent,
10311031
}
10321032
#endif
10331033

1034+
static const VPBasicBlock *getIncomingBlockForRecipe(const VPRecipeBase *R,
1035+
unsigned I) {
1036+
const VPBasicBlock *Parent = R->getParent();
1037+
const VPBlockBase *Pred = nullptr;
1038+
if (Parent->getNumPredecessors() > 0) {
1039+
Pred = Parent->getPredecessors()[I];
1040+
} else {
1041+
auto *Region = Parent->getParent();
1042+
assert(Region && !Region->isReplicator() && Region->getEntry() == Parent &&
1043+
"must be in the entry block of a non-replicate region");
1044+
assert(
1045+
I < 2 &&
1046+
(R->getNumOperands() == 2 || isa<VPWidenIntOrFpInductionRecipe>(R)) &&
1047+
"when placed in an entry block, only 2 incoming blocks are available");
1048+
1049+
// I == 0 selects the predecessor of the region, I == 1 selects the region
1050+
// itself whose exiting block feeds the phi across the backedge.
1051+
Pred = I == 0 ? Region->getSinglePredecessor() : Region;
1052+
}
1053+
1054+
return Pred->getExitingBasicBlock();
1055+
}
1056+
10341057
void VPWidenCallRecipe::execute(VPTransformState &State) {
10351058
assert(State.VF.isVector() && "not widening");
10361059
State.setDebugLocFrom(getDebugLoc());
@@ -3580,25 +3603,10 @@ void VPReductionPHIRecipe::print(raw_ostream &O, const Twine &Indent,
35803603
}
35813604
#endif
35823605

3583-
VPBasicBlock *VPWidenPHIRecipe::getIncomingBlock(unsigned I) {
3584-
VPBasicBlock *Parent = getParent();
3585-
VPBlockBase *Pred = nullptr;
3586-
if (Parent->getNumPredecessors() > 0) {
3587-
Pred = Parent->getPredecessors()[I];
3588-
} else {
3589-
auto *Region = Parent->getParent();
3590-
assert(Region && !Region->isReplicator() && Region->getEntry() == Parent &&
3591-
"must be in the entry block of a non-replicate region");
3592-
assert(
3593-
I < 2 && getNumOperands() == 2 &&
3594-
"when placed in an entry block, only 2 incoming blocks are available");
3595-
3596-
// I == 0 selects the predecessor of the region, I == 1 selects the region
3597-
// itself whose exiting block feeds the phi across the backedge.
3598-
Pred = I == 0 ? Region->getSinglePredecessor() : Region;
3599-
}
3600-
3601-
return Pred->getExitingBasicBlock();
3606+
template <>
3607+
const VPBasicBlock *
3608+
VPPhiAccessors<VPWidenPHIRecipe>::getIncomingBlock(unsigned Idx) const {
3609+
return getIncomingBlockForRecipe(getAsRecipe(), Idx);
36023610
}
36033611

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

0 commit comments

Comments
 (0)