@@ -909,6 +909,7 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPValue {
909909 case VPRecipeBase::VPEVLBasedIVPHISC:
910910 case VPRecipeBase::VPExpandSCEVSC:
911911 case VPRecipeBase::VPInstructionSC:
912+ case VPRecipeBase::VPReductionEVLSC:
912913 case VPRecipeBase::VPReductionSC:
913914 case VPRecipeBase::VPReplicateSC:
914915 case VPRecipeBase::VPScalarIVStepsSC:
@@ -2171,17 +2172,27 @@ class VPReductionRecipe : public VPSingleDefRecipe {
21712172 // / The recurrence decriptor for the reduction in question.
21722173 const RecurrenceDescriptor &RdxDesc;
21732174 bool IsOrdered;
2175+ // / Whether the reduction is conditional.
2176+ bool IsConditional = false ;
2177+
2178+ protected:
2179+ VPReductionRecipe (const unsigned char SC, const RecurrenceDescriptor &R,
2180+ Instruction *I, ArrayRef<VPValue *> Operands,
2181+ VPValue *CondOp, bool IsOrdered)
2182+ : VPSingleDefRecipe(SC, Operands, I), RdxDesc(R), IsOrdered(IsOrdered) {
2183+ if (CondOp) {
2184+ IsConditional = true ;
2185+ addOperand (CondOp);
2186+ }
2187+ }
21742188
21752189public:
21762190 VPReductionRecipe (const RecurrenceDescriptor &R, Instruction *I,
21772191 VPValue *ChainOp, VPValue *VecOp, VPValue *CondOp,
21782192 bool IsOrdered)
2179- : VPSingleDefRecipe(VPDef::VPReductionSC,
2180- ArrayRef<VPValue *>({ChainOp, VecOp}), I),
2181- RdxDesc (R), IsOrdered(IsOrdered) {
2182- if (CondOp)
2183- addOperand (CondOp);
2184- }
2193+ : VPReductionRecipe(VPDef::VPReductionSC, R, I,
2194+ ArrayRef<VPValue *>({ChainOp, VecOp}), CondOp,
2195+ IsOrdered) {}
21852196
21862197 ~VPReductionRecipe () override = default ;
21872198
@@ -2190,7 +2201,15 @@ class VPReductionRecipe : public VPSingleDefRecipe {
21902201 getVecOp (), getCondOp (), IsOrdered);
21912202 }
21922203
2193- VP_CLASSOF_IMPL (VPDef::VPReductionSC)
2204+ static inline bool classof (const VPRecipeBase *R) {
2205+ return R->getVPDefID () == VPRecipeBase::VPReductionSC ||
2206+ R->getVPDefID () == VPRecipeBase::VPReductionEVLSC;
2207+ }
2208+
2209+ static inline bool classof (const VPUser *U) {
2210+ auto *R = dyn_cast<VPRecipeBase>(U);
2211+ return R && classof (R);
2212+ }
21942213
21952214 // / Generate the reduction in the loop
21962215 void execute (VPTransformState &State) override ;
@@ -2201,13 +2220,62 @@ class VPReductionRecipe : public VPSingleDefRecipe {
22012220 VPSlotTracker &SlotTracker) const override ;
22022221#endif
22032222
2223+ // / Return the recurrence decriptor for the in-loop reduction.
2224+ const RecurrenceDescriptor &getRecurrenceDescriptor () const {
2225+ return RdxDesc;
2226+ }
2227+ // / Return true if the in-loop reduction is ordered.
2228+ bool isOrdered () const { return IsOrdered; };
2229+ // / Return true if the in-loop reduction is conditional.
2230+ bool isConditional () const { return IsConditional; };
22042231 // / The VPValue of the scalar Chain being accumulated.
22052232 VPValue *getChainOp () const { return getOperand (0 ); }
22062233 // / The VPValue of the vector value to be reduced.
22072234 VPValue *getVecOp () const { return getOperand (1 ); }
22082235 // / The VPValue of the condition for the block.
22092236 VPValue *getCondOp () const {
2210- return getNumOperands () > 2 ? getOperand (2 ) : nullptr ;
2237+ return isConditional () ? getOperand (getNumOperands () - 1 ) : nullptr ;
2238+ }
2239+ };
2240+
2241+ // / A recipe to represent inloop reduction operations with vector-predication
2242+ // / intrinsics, performing a reduction on a vector operand with the explicit
2243+ // / vector length (EVL) into a scalar value, and adding the result to a chain.
2244+ // / The Operands are {ChainOp, VecOp, EVL, [Condition]}.
2245+ class VPReductionEVLRecipe : public VPReductionRecipe {
2246+ public:
2247+ VPReductionEVLRecipe (VPReductionRecipe *R, VPValue *EVL, VPValue *CondOp)
2248+ : VPReductionRecipe(
2249+ VPDef::VPReductionEVLSC, R->getRecurrenceDescriptor (),
2250+ cast_or_null<Instruction>(R->getUnderlyingValue ()),
2251+ ArrayRef<VPValue *>({R->getChainOp (), R->getVecOp (), EVL}), CondOp,
2252+ R->isOrdered()) {}
2253+
2254+ ~VPReductionEVLRecipe () override = default ;
2255+
2256+ VPReductionEVLRecipe *clone () override {
2257+ llvm_unreachable (" cloning not implemented yet" );
2258+ }
2259+
2260+ VP_CLASSOF_IMPL (VPDef::VPReductionEVLSC)
2261+
2262+ // / Generate the reduction in the loop
2263+ void execute(VPTransformState &State) override ;
2264+
2265+ #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2266+ // / Print the recipe.
2267+ void print (raw_ostream &O, const Twine &Indent,
2268+ VPSlotTracker &SlotTracker) const override ;
2269+ #endif
2270+
2271+ // / The VPValue of the explicit vector length.
2272+ VPValue *getEVL () const { return getOperand (2 ); }
2273+
2274+ // / Returns true if the recipe only uses the first lane of operand \p Op.
2275+ bool onlyFirstLaneUsed (const VPValue *Op) const override {
2276+ assert (is_contained (operands (), Op) &&
2277+ " Op must be an operand of the recipe" );
2278+ return Op == getEVL ();
22112279 }
22122280};
22132281
0 commit comments