@@ -532,6 +532,7 @@ class VPBlockBase {
532
532
VPBlocksTy &getSuccessors () { return Successors; }
533
533
534
534
iterator_range<VPBlockBase **> successors () { return Successors; }
535
+ iterator_range<VPBlockBase **> predecessors () { return Predecessors; }
535
536
536
537
const VPBlocksTy &getPredecessors () const { return Predecessors; }
537
538
VPBlocksTy &getPredecessors () { return Predecessors; }
@@ -724,6 +725,11 @@ class VPLiveOut : public VPUser {
724
725
725
726
PHINode *getPhi () const { return Phi; }
726
727
728
+ // / Live-outs are marked as only using the first part during the transition
729
+ // / to unrolling directly on VPlan.
730
+ // / TODO: Remove after unroller transition.
731
+ bool onlyFirstPartUsed (const VPValue *Op) const override { return true ; }
732
+
727
733
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
728
734
// / Print the VPLiveOut to \p O.
729
735
void print (raw_ostream &O, VPSlotTracker &SlotTracker) const ;
@@ -1226,11 +1232,24 @@ class VPRecipeWithIRFlags : public VPSingleDefRecipe {
1226
1232
#endif
1227
1233
};
1228
1234
1235
+ // / Helper to access the operand that contains the unroll part for this recipe
1236
+ // / after unrolling.
1237
+ template <unsigned PartOpIdx> class VPUnrollPartAccessor {
1238
+ protected:
1239
+ // / Return the VPValue operand containing the unroll part or null if there is
1240
+ // / no such operand.
1241
+ VPValue *getUnrollPartOperand (VPUser &U) const ;
1242
+
1243
+ // / Return the unroll part.
1244
+ unsigned getUnrollPart (VPUser &U) const ;
1245
+ };
1246
+
1229
1247
// / This is a concrete Recipe that models a single VPlan-level instruction.
1230
1248
// / While as any Recipe it may generate a sequence of IR instructions when
1231
1249
// / executed, these instructions would always form a single-def expression as
1232
1250
// / the VPInstruction is also a single def-use vertex.
1233
- class VPInstruction : public VPRecipeWithIRFlags {
1251
+ class VPInstruction : public VPRecipeWithIRFlags ,
1252
+ public VPUnrollPartAccessor<1 > {
1234
1253
friend class VPlanSlp ;
1235
1254
1236
1255
public:
@@ -1764,7 +1783,8 @@ class VPWidenGEPRecipe : public VPRecipeWithIRFlags {
1764
1783
// / A recipe to compute the pointers for widened memory accesses of IndexTy for
1765
1784
// / all parts. If IsReverse is true, compute pointers for accessing the input in
1766
1785
// / reverse order per part.
1767
- class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
1786
+ class VPVectorPointerRecipe : public VPRecipeWithIRFlags ,
1787
+ public VPUnrollPartAccessor<1 > {
1768
1788
Type *IndexedTy;
1769
1789
bool IsReverse;
1770
1790
@@ -1789,7 +1809,7 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
1789
1809
bool onlyFirstPartUsed (const VPValue *Op) const override {
1790
1810
assert (is_contained (operands (), Op) &&
1791
1811
" Op must be an operand of the recipe" );
1792
- assert (getNumOperands () == 1 && " must have a single operand " );
1812
+ assert (getNumOperands () <= 2 && " must have at most two operands " );
1793
1813
return true ;
1794
1814
}
1795
1815
@@ -1948,6 +1968,12 @@ class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe {
1948
1968
VPValue *getVFValue () { return getOperand (2 ); }
1949
1969
const VPValue *getVFValue () const { return getOperand (2 ); }
1950
1970
1971
+ VPValue *getSplatVFValue () {
1972
+ // If the recipe has been unrolled (4 operands), return the VPValue for the
1973
+ // induction increment.
1974
+ return getNumOperands () == 5 ? getOperand (3 ) : nullptr ;
1975
+ }
1976
+
1951
1977
// / Returns the first defined value as TruncInst, if it is one or nullptr
1952
1978
// / otherwise.
1953
1979
TruncInst *getTruncInst () { return Trunc; }
@@ -1967,9 +1993,17 @@ class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe {
1967
1993
Type *getScalarType () const {
1968
1994
return Trunc ? Trunc->getType () : IV->getType ();
1969
1995
}
1996
+
1997
+ // / Returns the VPValue representing the value of this induction at
1998
+ // / the last unrolled part, if it exists. Returns itself if unrolling did not
1999
+ // / take place.
2000
+ VPValue *getLastUnrolledPartOperand () {
2001
+ return getNumOperands () == 5 ? getOperand (4 ) : this ;
2002
+ }
1970
2003
};
1971
2004
1972
- class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe {
2005
+ class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe ,
2006
+ public VPUnrollPartAccessor<3 > {
1973
2007
const InductionDescriptor &IndDesc;
1974
2008
1975
2009
bool IsScalarAfterVectorization;
@@ -2006,6 +2040,13 @@ class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe {
2006
2040
// / Returns the induction descriptor for the recipe.
2007
2041
const InductionDescriptor &getInductionDescriptor () const { return IndDesc; }
2008
2042
2043
+ // / Returns the VPValue representing the value of this induction at
2044
+ // / the first unrolled part, if it exists. Returns itself if unrolling did not
2045
+ // / take place.
2046
+ VPValue *getFirstUnrolledPartOperand () {
2047
+ return getUnrollPart (*this ) == 0 ? this : getOperand (2 );
2048
+ }
2049
+
2009
2050
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2010
2051
// / Print the recipe.
2011
2052
void print (raw_ostream &O, const Twine &Indent,
@@ -2088,7 +2129,8 @@ struct VPFirstOrderRecurrencePHIRecipe : public VPHeaderPHIRecipe {
2088
2129
// / A recipe for handling reduction phis. The start value is the first operand
2089
2130
// / of the recipe and the incoming value from the backedge is the second
2090
2131
// / operand.
2091
- class VPReductionPHIRecipe : public VPHeaderPHIRecipe {
2132
+ class VPReductionPHIRecipe : public VPHeaderPHIRecipe ,
2133
+ public VPUnrollPartAccessor<2 > {
2092
2134
// / Descriptor for the reduction.
2093
2135
const RecurrenceDescriptor &RdxDesc;
2094
2136
@@ -2907,7 +2949,10 @@ class VPActiveLaneMaskPHIRecipe : public VPHeaderPHIRecipe {
2907
2949
~VPActiveLaneMaskPHIRecipe () override = default ;
2908
2950
2909
2951
VPActiveLaneMaskPHIRecipe *clone () override {
2910
- return new VPActiveLaneMaskPHIRecipe (getOperand (0 ), getDebugLoc ());
2952
+ auto *R = new VPActiveLaneMaskPHIRecipe (getOperand (0 ), getDebugLoc ());
2953
+ if (getNumOperands () == 2 )
2954
+ R->addOperand (getOperand (1 ));
2955
+ return R;
2911
2956
}
2912
2957
2913
2958
VP_CLASSOF_IMPL (VPDef::VPActiveLaneMaskPHISC)
@@ -2966,7 +3011,8 @@ class VPEVLBasedIVPHIRecipe : public VPHeaderPHIRecipe {
2966
3011
};
2967
3012
2968
3013
// / A Recipe for widening the canonical induction variable of the vector loop.
2969
- class VPWidenCanonicalIVRecipe : public VPSingleDefRecipe {
3014
+ class VPWidenCanonicalIVRecipe : public VPSingleDefRecipe ,
3015
+ public VPUnrollPartAccessor<1 > {
2970
3016
public:
2971
3017
VPWidenCanonicalIVRecipe (VPCanonicalIVPHIRecipe *CanonicalIV)
2972
3018
: VPSingleDefRecipe(VPDef::VPWidenCanonicalIVSC, {CanonicalIV}) {}
@@ -3052,7 +3098,8 @@ class VPDerivedIVRecipe : public VPSingleDefRecipe {
3052
3098
3053
3099
// / A recipe for handling phi nodes of integer and floating-point inductions,
3054
3100
// / producing their scalar values.
3055
- class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags {
3101
+ class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags ,
3102
+ public VPUnrollPartAccessor<2 > {
3056
3103
Instruction::BinaryOps InductionOpcode;
3057
3104
3058
3105
public:
@@ -3548,6 +3595,11 @@ class VPlan {
3548
3595
3549
3596
bool hasUF (unsigned UF) const { return UFs.empty () || UFs.contains (UF); }
3550
3597
3598
+ unsigned getUF () const {
3599
+ assert (UFs.size () == 1 && " Expected a single UF" );
3600
+ return UFs[0 ];
3601
+ }
3602
+
3551
3603
void setUF (unsigned UF) {
3552
3604
assert (hasUF (UF) && " Cannot set the UF not already in plan" );
3553
3605
UFs.clear ();
@@ -3732,6 +3784,22 @@ class VPBlockUtils {
3732
3784
connectBlocks (BlockPtr, NewBlock);
3733
3785
}
3734
3786
3787
+ // / Insert disconnected block \p NewBlock before \p Blockptr. First
3788
+ // / disconnects all predecessors of \p BlockPtr and connects them to \p
3789
+ // / NewBlock. Add \p NewBlock as predecessor of \p BlockPtr and \p BlockPtr as
3790
+ // / successor of \p NewBlock.
3791
+ static void insertBlockBefore (VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
3792
+ assert (NewBlock->getSuccessors ().empty () &&
3793
+ NewBlock->getPredecessors ().empty () &&
3794
+ " Can't insert new block with predecessors or successors." );
3795
+ NewBlock->setParent (BlockPtr->getParent ());
3796
+ for (VPBlockBase *Pred : to_vector (BlockPtr->predecessors ())) {
3797
+ disconnectBlocks (Pred, BlockPtr);
3798
+ connectBlocks (Pred, NewBlock);
3799
+ }
3800
+ connectBlocks (NewBlock, BlockPtr);
3801
+ }
3802
+
3735
3803
// / Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
3736
3804
// / BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
3737
3805
// / BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
0 commit comments