@@ -4260,13 +4260,34 @@ class BoUpSLP {
42604260 bool areAltOperandsProfitable(const InstructionsState &S,
42614261 ArrayRef<Value *> VL) const;
42624262
4263+ /// Contains all the outputs of legality analysis for a list of values to
4264+ /// vectorize.
4265+ class ScalarsVectorizationLegality {
4266+ InstructionsState S;
4267+ bool IsLegal;
4268+ bool TryToFindDuplicates;
4269+ bool TrySplitVectorize;
4270+
4271+ public:
4272+ ScalarsVectorizationLegality(InstructionsState S, bool IsLegal,
4273+ bool TryToFindDuplicates = true,
4274+ bool TrySplitVectorize = false)
4275+ : S(S), IsLegal(IsLegal), TryToFindDuplicates(TryToFindDuplicates),
4276+ TrySplitVectorize(TrySplitVectorize) {
4277+ assert((!IsLegal || (S.valid() && TryToFindDuplicates)) &&
4278+ "Inconsistent state");
4279+ }
4280+ const InstructionsState &getInstructionsState() const { return S; };
4281+ bool isLegal() const { return IsLegal; }
4282+ bool tryToFindDuplicates() const { return TryToFindDuplicates; }
4283+ bool trySplitVectorize() const { return TrySplitVectorize; }
4284+ };
4285+
42634286 /// Checks if the specified list of the instructions/values can be vectorized
42644287 /// in general.
4265- bool isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
4266- const EdgeInfo &UserTreeIdx,
4267- InstructionsState &S,
4268- bool &TryToFindDuplicates,
4269- bool &TrySplitVectorize) const;
4288+ ScalarsVectorizationLegality
4289+ getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
4290+ const EdgeInfo &UserTreeIdx) const;
42704291
42714292 /// Checks if the specified list of the instructions/values can be vectorized
42724293 /// and fills required data before actual scheduling of the instructions.
@@ -9764,25 +9785,21 @@ bool BoUpSLP::canBuildSplitNode(ArrayRef<Value *> VL,
97649785 return true;
97659786}
97669787
9767- bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
9768- const EdgeInfo &UserTreeIdx,
9769- InstructionsState &S,
9770- bool &TryToFindDuplicates,
9771- bool &TrySplitVectorize) const {
9788+ BoUpSLP::ScalarsVectorizationLegality
9789+ BoUpSLP::getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
9790+ const EdgeInfo &UserTreeIdx) const {
97729791 assert((allConstant(VL) || allSameType(VL)) && "Invalid types!");
97739792
9774- S = getSameOpcode(VL, *TLI);
9775- TryToFindDuplicates = true;
9776- TrySplitVectorize = false;
9793+ InstructionsState S = getSameOpcode(VL, *TLI);
97779794
97789795 // Don't go into catchswitch blocks, which can happen with PHIs.
97799796 // Such blocks can only have PHIs and the catchswitch. There is no
97809797 // place to insert a shuffle if we need to, so just avoid that issue.
97819798 if (S && isa<CatchSwitchInst>(S.getMainOp()->getParent()->getTerminator())) {
97829799 LLVM_DEBUG(dbgs() << "SLP: bundle in catchswitch block.\n");
97839800 // Do not try to pack to avoid extra instructions here.
9784- TryToFindDuplicates = false;
9785- return false;
9801+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false,
9802+ /*TryToFindDuplicates=*/ false) ;
97869803 }
97879804
97889805 // Check if this is a duplicate of another entry.
@@ -9792,14 +9809,14 @@ bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
97929809 if (E->isSame(VL)) {
97939810 LLVM_DEBUG(dbgs() << "SLP: Perfect diamond merge at " << *S.getMainOp()
97949811 << ".\n");
9795- return false;
9812+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
97969813 }
97979814 SmallPtrSet<Value *, 8> Values(llvm::from_range, E->Scalars);
97989815 if (all_of(VL, [&](Value *V) {
97999816 return isa<PoisonValue>(V) || Values.contains(V);
98009817 })) {
98019818 LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n");
9802- return false;
9819+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
98039820 }
98049821 }
98059822 }
@@ -9816,23 +9833,23 @@ bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
98169833 cast<Instruction>(I)->getOpcode() == S.getOpcode();
98179834 })))) {
98189835 LLVM_DEBUG(dbgs() << "SLP: Gathering due to max recursion depth.\n");
9819- return false;
9836+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
98209837 }
98219838
98229839 // Don't handle scalable vectors
98239840 if (S && S.getOpcode() == Instruction::ExtractElement &&
98249841 isa<ScalableVectorType>(
98259842 cast<ExtractElementInst>(S.getMainOp())->getVectorOperandType())) {
98269843 LLVM_DEBUG(dbgs() << "SLP: Gathering due to scalable vector type.\n");
9827- return false;
9844+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
98289845 }
98299846
98309847 // Don't handle vectors.
98319848 if (!SLPReVec && getValueType(VL.front())->isVectorTy()) {
98329849 LLVM_DEBUG(dbgs() << "SLP: Gathering due to vector type.\n");
98339850 // Do not try to pack to avoid extra instructions here.
9834- TryToFindDuplicates = false;
9835- return false;
9851+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false,
9852+ /*TryToFindDuplicates=*/ false) ;
98369853 }
98379854
98389855 // If all of the operands are identical or constant we have a simple solution.
@@ -9922,11 +9939,12 @@ bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
99229939 if (!S) {
99239940 LLVM_DEBUG(dbgs() << "SLP: Try split and if failed, gathering due to "
99249941 "C,S,B,O, small shuffle. \n");
9925- TrySplitVectorize = true;
9926- return false;
9942+ return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
9943+ /*TryToFindDuplicates=*/true,
9944+ /*TrySplitVectorize=*/true);
99279945 }
99289946 LLVM_DEBUG(dbgs() << "SLP: Gathering due to C,S,B,O, small shuffle. \n");
9929- return false;
9947+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
99309948 }
99319949
99329950 // Don't vectorize ephemeral values.
@@ -9936,8 +9954,8 @@ bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
99369954 LLVM_DEBUG(dbgs() << "SLP: The instruction (" << *V
99379955 << ") is ephemeral.\n");
99389956 // Do not try to pack to avoid extra instructions here.
9939- TryToFindDuplicates = false;
9940- return false;
9957+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false,
9958+ /*TryToFindDuplicates=*/ false) ;
99419959 }
99429960 }
99439961 }
@@ -9986,7 +10004,7 @@ bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
998610004 if (PreferScalarize) {
998710005 LLVM_DEBUG(dbgs() << "SLP: The instructions are in tree and alternate "
998810006 "node is not profitable.\n");
9989- return false;
10007+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
999010008 }
999110009 }
999210010
@@ -9995,7 +10013,7 @@ bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
999510013 for (Value *V : VL) {
999610014 if (UserIgnoreList->contains(V)) {
999710015 LLVM_DEBUG(dbgs() << "SLP: Gathering due to gathered scalar.\n");
9998- return false;
10016+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
999910017 }
1000010018 }
1000110019 }
@@ -10025,9 +10043,9 @@ bool BoUpSLP::isLegalToVectorizeScalars(ArrayRef<Value *> VL, unsigned Depth,
1002510043 // Do not vectorize EH and non-returning blocks, not profitable in most
1002610044 // cases.
1002710045 LLVM_DEBUG(dbgs() << "SLP: bundle in unreachable block.\n");
10028- return false;
10046+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ false) ;
1002910047 }
10030- return true;
10048+ return ScalarsVectorizationLegality(S, /*IsLegal=*/ true) ;
1003110049}
1003210050
1003310051void BoUpSLP::buildTreeRec(ArrayRef<Value *> VLRef, unsigned Depth,
@@ -10038,7 +10056,6 @@ void BoUpSLP::buildTreeRec(ArrayRef<Value *> VLRef, unsigned Depth,
1003810056 SmallVector<int> ReuseShuffleIndices;
1003910057 SmallVector<Value *> VL(VLRef.begin(), VLRef.end());
1004010058
10041- InstructionsState S = InstructionsState::invalid();
1004210059 // Tries to build split node.
1004310060 auto TrySplitNode = [&](const InstructionsState &LocalState) {
1004410061 SmallVector<Value *> Op1, Op2;
@@ -10072,17 +10089,17 @@ void BoUpSLP::buildTreeRec(ArrayRef<Value *> VLRef, unsigned Depth,
1007210089 return true;
1007310090 };
1007410091
10075- bool TryToPackDuplicates;
10076- bool TrySplitVectorize ;
10077- if (!isLegalToVectorizeScalars(VL, Depth, UserTreeIdx, S, TryToPackDuplicates,
10078- TrySplitVectorize )) {
10079- if (TrySplitVectorize ) {
10092+ ScalarsVectorizationLegality SVL =
10093+ getScalarsVectorizationLegality(VL, Depth, UserTreeIdx) ;
10094+ const InstructionsState &S = SVL.getInstructionsState();
10095+ if (!SVL.isLegal( )) {
10096+ if (SVL.trySplitVectorize() ) {
1008010097 auto [MainOp, AltOp] = getMainAltOpsNoStateVL(VL);
1008110098 // Last chance to try to vectorize alternate node.
1008210099 if (MainOp && AltOp && TrySplitNode(InstructionsState(MainOp, AltOp)))
1008310100 return;
1008410101 }
10085- if (TryToPackDuplicates )
10102+ if (SVL.tryToFindDuplicates() )
1008610103 tryToFindDuplicates(VL, ReuseShuffleIndices, *TTI, *TLI, S, UserTreeIdx);
1008710104
1008810105 newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
0 commit comments