@@ -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.
10931149struct 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> {
19722029public:
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
0 commit comments