@@ -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.
10941150struct 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
0 commit comments