[llvm] [SLP] Normalize copyable operand order via majority voting (PR #191631)
Alexey Bataev via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 08:05:48 PDT 2026
================
@@ -11931,12 +11931,76 @@ class InstructionsCompatibilityAnalysis {
if (S.areInstructionsWithCopyableElements()) {
MainOp = S.getMainOp();
MainOpcode = S.getOpcode();
+ const bool IsCommutative =
+ isCommutative(MainOp) && MainOp->getNumOperands() == 2;
Operands.assign(MainOp->getNumOperands(),
BoUpSLP::ValueList(VL.size(), nullptr));
+ // Build operands and simultaneously count (ID0, ID1) pair
+ // frequencies for commutative operand normalization. Pairs and
+ // their inverses are tracked under a canonical key so that
+ // (Load, Add) and (Add, Load) contribute to the same bucket.
+ struct PairInfo {
+ unsigned FwdCount = 0;
+ unsigned RevCount = 0;
+ unsigned MinID = 0;
+ unsigned MaxID = 0;
+ };
+ SmallMapVector<std::pair<unsigned, unsigned>, PairInfo, 8> PairCounts;
+ unsigned MajID0 = 0, MajID1 = 0;
for (auto [Idx, V] : enumerate(VL)) {
SmallVector<Value *> OperandsForValue = getOperands(S, V);
for (auto [OperandIdx, Operand] : enumerate(OperandsForValue))
Operands[OperandIdx][Idx] = Operand;
+ if (!IsCommutative || S.isCopyableElement(V) || isa<PoisonValue>(V))
+ continue;
+ unsigned ID0 = OperandsForValue[0]->getValueID();
+ unsigned ID1 = OperandsForValue[1]->getValueID();
+ if (ID0 == ID1)
+ continue;
+ unsigned MinID = std::min(ID0, ID1);
+ unsigned MaxID = std::max(ID0, ID1);
+ auto [It, Inserted] =
+ PairCounts.try_emplace(std::make_pair(MinID, MaxID));
+ PairInfo &Info = It->second;
+ if (Inserted) {
+ Info.MinID = MinID;
+ Info.MaxID = MaxID;
+ }
+ if (ID0 < ID1)
+ ++Info.FwdCount;
+ else
+ ++Info.RevCount;
+ }
+ // Find the most frequent (ID0, ID1) pair across non-copyable
+ // lanes. Select the orientation (original or inverse) that has
+ // more votes as the majority pattern.
+ unsigned BestCount = 0;
+ for (const auto &P : PairCounts) {
+ const PairInfo &Info = P.second;
+ unsigned Total = Info.FwdCount + Info.RevCount;
+ if (Total > BestCount) {
+ BestCount = Total;
+ if (Info.FwdCount >= Info.RevCount) {
+ MajID0 = Info.MinID;
+ MajID1 = Info.MaxID;
+ } else {
+ MajID0 = Info.MaxID;
+ MajID1 = Info.MinID;
+ }
+ }
+ }
+ // For commutative ops, swap lanes whose operand types are the
+ // exact inverse of the majority pattern, making the non-copyable
----------------
alexey-bataev wrote:
Just another heuristic, which does not pessimize the vectorization result
https://github.com/llvm/llvm-project/pull/191631
More information about the llvm-commits
mailing list