@@ -866,6 +866,7 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPValue {
866866 case VPRecipeBase::VPWidenCallSC:
867867 case VPRecipeBase::VPWidenCanonicalIVSC:
868868 case VPRecipeBase::VPWidenCastSC:
869+ case VPRecipeBase::VPWidenCastEVLSC:
869870 case VPRecipeBase::VPWidenGEPSC:
870871 case VPRecipeBase::VPWidenIntrinsicSC:
871872 case VPRecipeBase::VPWidenSC:
@@ -1063,6 +1064,7 @@ class VPRecipeWithIRFlags : public VPSingleDefRecipe {
10631064 R->getVPDefID () == VPRecipeBase::VPWidenEVLSC ||
10641065 R->getVPDefID () == VPRecipeBase::VPWidenGEPSC ||
10651066 R->getVPDefID () == VPRecipeBase::VPWidenCastSC ||
1067+ R->getVPDefID () == VPRecipeBase::VPWidenCastEVLSC ||
10661068 R->getVPDefID () == VPRecipeBase::VPReplicateSC ||
10671069 R->getVPDefID () == VPRecipeBase::VPReverseVectorPointerSC ||
10681070 R->getVPDefID () == VPRecipeBase::VPVectorPointerSC;
@@ -1542,19 +1544,28 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags {
15421544 // / Result type for the cast.
15431545 Type *ResultTy;
15441546
1545- public :
1546- VPWidenCastRecipe (Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy ,
1547- CastInst &UI)
1547+ protected :
1548+ VPWidenCastRecipe (unsigned VPDefOpcode, Instruction::CastOps Opcode,
1549+ VPValue *Op, Type *ResultTy, CastInst &UI)
15481550 : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op, UI), Opcode(Opcode),
15491551 ResultTy (ResultTy) {
15501552 assert (UI.getOpcode () == Opcode &&
15511553 " opcode of underlying cast doesn't match" );
15521554 }
15531555
1554- VPWidenCastRecipe (Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
1556+ VPWidenCastRecipe (unsigned VPDefOpcode, Instruction::CastOps Opcode,
1557+ VPValue *Op, Type *ResultTy)
15551558 : VPRecipeWithIRFlags(VPDef::VPWidenCastSC, Op), Opcode(Opcode),
15561559 ResultTy(ResultTy) {}
15571560
1561+ public:
1562+ VPWidenCastRecipe (Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy,
1563+ CastInst &UI)
1564+ : VPWidenCastRecipe(VPDef::VPWidenCastSC, Opcode, Op, ResultTy, UI) {}
1565+
1566+ VPWidenCastRecipe (Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
1567+ : VPWidenCastRecipe(VPDef::VPWidenCastSC, Opcode, Op, ResultTy) {}
1568+
15581569 ~VPWidenCastRecipe () override = default ;
15591570
15601571 VPWidenCastRecipe *clone () override {
@@ -1565,7 +1576,15 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags {
15651576 return new VPWidenCastRecipe (Opcode, getOperand (0 ), ResultTy);
15661577 }
15671578
1568- VP_CLASSOF_IMPL (VPDef::VPWidenCastSC)
1579+ static inline bool classof (const VPRecipeBase *R) {
1580+ return R->getVPDefID () == VPRecipeBase::VPWidenCastSC ||
1581+ R->getVPDefID () == VPRecipeBase::VPWidenCastEVLSC;
1582+ }
1583+
1584+ static inline bool classof (const VPUser *U) {
1585+ auto *R = dyn_cast<VPRecipeBase>(U);
1586+ return R && classof (R);
1587+ }
15691588
15701589 // / Produce widened copies of the cast.
15711590 void execute (VPTransformState &State) override ;
@@ -1586,6 +1605,54 @@ class VPWidenCastRecipe : public VPRecipeWithIRFlags {
15861605 Type *getResultType () const { return ResultTy; }
15871606};
15881607
1608+ // A recipe for widening cast operation with vector-predication intrinsics with
1609+ // / explicit vector length (EVL).
1610+ class VPWidenCastEVLRecipe : public VPWidenCastRecipe {
1611+ using VPRecipeWithIRFlags::transferFlags;
1612+
1613+ public:
1614+ VPWidenCastEVLRecipe (Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy,
1615+ VPValue &EVL)
1616+ : VPWidenCastRecipe(VPDef::VPWidenCastEVLSC, Opcode, Op, ResultTy) {
1617+ addOperand (&EVL);
1618+ }
1619+ VPWidenCastEVLRecipe (VPWidenCastRecipe &W, VPValue &EVL)
1620+ : VPWidenCastEVLRecipe(W.getOpcode(), W.getOperand(0 ), W.getResultType(),
1621+ EVL) {
1622+ transferFlags (W);
1623+ }
1624+
1625+ ~VPWidenCastEVLRecipe () override = default ;
1626+
1627+ VPWidenCastEVLRecipe *clone () final {
1628+ llvm_unreachable (" VPWidenEVLRecipe cannot be cloned" );
1629+ return nullptr ;
1630+ }
1631+
1632+ VP_CLASSOF_IMPL (VPDef::VPWidenCastEVLSC)
1633+
1634+ VPValue *getEVL () { return getOperand (getNumOperands () - 1 ); }
1635+ const VPValue *getEVL () const { return getOperand (getNumOperands () - 1 ); }
1636+
1637+ // / Produce a vp-intrinsic copies of the cast.
1638+ void execute (VPTransformState &State) final ;
1639+
1640+ // / Returns true if the recipe only uses the first lane of operand \p Op.
1641+ bool onlyFirstLaneUsed (const VPValue *Op) const override {
1642+ assert (is_contained (operands (), Op) &&
1643+ " Op must be an operand of the recipe" );
1644+ // EVL in that recipe is always the last operand, thus any use before means
1645+ // the VPValue should be vectorized.
1646+ return getEVL () == Op;
1647+ }
1648+
1649+ #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1650+ // / Print the recipe.
1651+ void print (raw_ostream &O, const Twine &Indent,
1652+ VPSlotTracker &SlotTracker) const final ;
1653+ #endif
1654+ };
1655+
15891656// / VPScalarCastRecipe is a recipe to create scalar cast instructions.
15901657class VPScalarCastRecipe : public VPSingleDefRecipe {
15911658 Instruction::CastOps Opcode;
0 commit comments