[llvm] [SLP]Prefer copyable over alternate (PR #183777)
Ryan Buchner via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 00:16:50 PST 2026
================
@@ -11503,26 +11515,225 @@ class InstructionsCompatibilityAnalysis {
llvm_unreachable("Unexpected vectorization of the instructions.");
}
+ /// Check if the specified \p VL list of values is better to represent as
+ /// uniform with copyables, as modeled via \p CopyableS, or as alternate (or
+ /// uniform with compatible ops), modeled via \p S.
+ /// Performs the analysis of the operands, choosing the preferred main
+ /// instruction and checking the matching of the operands for the main
+ /// instruction and copyable elements.
+ bool isCopyablePreferable(ArrayRef<Value *> VL, const BoUpSLP &R,
+ const InstructionsState &S,
+ const InstructionsState &CopyableS) {
+ // If all elements are vectorized already - keep as is.
+ if (all_of(VL, [&](Value *V) {
+ return isa<PoisonValue>(V) || R.isVectorized(V);
+ }))
+ return false;
+ Instruction *SMain = S.getMainOp();
+ Instruction *SAlt = S.isAltShuffle() ? S.getAltOp() : nullptr;
+ const bool IsCommutative = ::isCommutative(SMain);
+ const bool IsAltCommutative =
+ S.isAltShuffle() ? ::isCommutative(SAlt) : false;
+ const bool IsMainCommutative = ::isCommutative(MainOp);
+ SmallVector<BoUpSLP::ValueList> Ops;
+ buildOriginalOperands(S, SMain, Ops);
+ // Try to find better candidate for S main instruction, which operands have
+ // better matching.
+ auto CheckOperands = [](Value *Op, Value *SMainOp) {
+ auto *OpI = dyn_cast<BinaryOperator>(Op);
+ if (!OpI)
+ return false;
+ auto *SMainOpI = dyn_cast<BinaryOperator>(SMainOp);
+ if (!SMainOpI)
+ return true;
+ return any_of(OpI->operands(), [&](Value *V) {
+ auto *I = dyn_cast<Instruction>(V);
+ return I && I->getOpcode() == SMainOpI->getOpcode();
+ });
+ };
+ SmallPtrSet<Value *, 8> Operands;
+ for (Value *V : VL) {
+ auto *I = dyn_cast<Instruction>(V);
+ if (!I || I == SMain)
+ continue;
+ Instruction *MatchingOp = S.getMatchingMainOpOrAltOp(I);
+ if (MatchingOp != SMain)
+ continue;
+ SmallVector<BoUpSLP::ValueList> VOps;
+ buildOriginalOperands(S, I, VOps);
+ Operands.insert(I->op_begin(), I->op_end());
+ if (any_of(enumerate(VOps), [&](const auto &P) {
+ return CheckOperands(P.value()[0], Ops[P.index()][0]);
+ })) {
+ SMain = I;
+ Ops.swap(VOps);
+ break;
+ }
+ }
+ SmallVector<BoUpSLP::ValueList> MainOps;
+ buildOriginalOperands(S, MainOp, MainOps);
+
+ auto BuildFirstOperandCandidates =
+ [&](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates,
+ ArrayRef<BoUpSLP::ValueList> Ops, Value *Op0, Value *Op1,
+ bool IsCommutative) {
+ Candidates.emplace_back(Ops[0][0], Op0);
+ if (IsCommutative)
+ Candidates.emplace_back(Ops[0][0], Op1);
+ };
+
+ auto BuildSecondOperandCandidates =
+ [&](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates,
+ ArrayRef<BoUpSLP::ValueList> Ops, int PrevBestIdx, Value *Op0,
+ Value *Op1, bool IsCommutative) {
+ if (PrevBestIdx != 1)
+ Candidates.emplace_back(Ops[1][0], Op1);
+ if (PrevBestIdx != 0 && IsCommutative)
+ Candidates.emplace_back(Ops[1][0], Op0);
+ };
+
+ auto FindBestCandidate =
+ [&](ArrayRef<std::pair<Value *, Value *>> Candidates, bool &IsConst,
+ int &Score) {
+ auto Res = R.findBestRootPair(Candidates);
+ Score = Res.second;
+ IsConst =
+ Res.second == BoUpSLP::LookAheadHeuristics::ScoreConstants &&
+ isConstant(Candidates[Res.first.value_or(0)].first) &&
+ isConstant(Candidates[Res.first.value_or(0)].second);
+ if (IsConst) {
+ // Check if there are splat candidates and consider them better
+ // option.
+ for (const auto [Idx, P] : enumerate(Candidates)) {
+ if (!isConstant(P.first) && !isConstant(P.second) &&
+ P.second == P.first) {
+ Res.first = Idx;
+ IsConst = false;
+ Score = isa<LoadInst>(Candidates[Res.first.value_or(0)].first)
+ ? BoUpSLP::LookAheadHeuristics::ScoreSplatLoads
+ : BoUpSLP::LookAheadHeuristics::ScoreSplat;
+ break;
+ }
+ }
+ }
+ return Res.first;
+ };
+
+ for (Value *V : VL) {
+ auto *I = dyn_cast<Instruction>(V);
+ if (!I || (I == MainOp && (!S.isAltShuffle() || I == SMain)) ||
+ (!S.isAltShuffle() && I == SMain))
+ continue;
+ SmallVector<BoUpSLP::ValueList> VOps;
+ buildOriginalOperands(S, (S.isAltShuffle() && I == SMain) ? MainOp : I,
----------------
bababuck wrote:
>From the above condition, if `I == SMain`, then `S.isAltShuffle() == true`. S could simplify to `I == SMain ? MainOp : I`. Not sure if that helps readability though.
https://github.com/llvm/llvm-project/pull/183777
More information about the llvm-commits
mailing list