Skip to content

[SLP] Allow targets to add cost for nonstandard conditions #95328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

jrbyrnes
Copy link
Contributor

There are conditions in which vectorization is profitable, but are not expressible by the current cost model. As an example, the vectorization profit may entirely be based on conditions of the users of the tree entry.

This gives targets a chance to express things of this nature.

@jrbyrnes jrbyrnes requested review from arsenm and alexey-bataev June 12, 2024 23:04
@llvmbot llvmbot added vectorizers llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Jun 12, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 12, 2024

@llvm/pr-subscribers-backend-amdgpu
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: Jeffrey Byrnes (jrbyrnes)

Changes

There are conditions in which vectorization is profitable, but are not expressible by the current cost model. As an example, the vectorization profit may entirely be based on conditions of the users of the tree entry.

This gives targets a chance to express things of this nature.


Full diff: https://github.com/llvm/llvm-project/pull/95328.diff

5 Files Affected:

  • (modified) llvm/include/llvm/Analysis/TargetTransformInfo.h (+16)
  • (modified) llvm/include/llvm/Analysis/TargetTransformInfoImpl.h (+5)
  • (modified) llvm/include/llvm/CodeGen/BasicTTIImpl.h (+5)
  • (modified) llvm/lib/Analysis/TargetTransformInfo.cpp (+5)
  • (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+8)
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index f55f21c94a85a..49117ca8c74c5 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -891,6 +891,11 @@ class TargetTransformInfo {
                                            bool Insert, bool Extract,
                                            TTI::TargetCostKind CostKind) const;
 
+  /// Whether or not there is any target-specific condition that imposes an
+  /// overhead for scalarization
+  bool hasScalarizationOverhead(ArrayRef<Value *> VL,
+                                std::pair<bool, bool> &ScalarizationKind) const;
+
   /// Estimate the overhead of scalarizing an instructions unique
   /// non-constant operands. The (potentially vector) types to use for each of
   /// argument are passes via Tys.
@@ -1921,6 +1926,10 @@ class TargetTransformInfo::Concept {
   getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
                                    ArrayRef<Type *> Tys,
                                    TargetCostKind CostKind) = 0;
+
+  virtual bool
+  hasScalarizationOverhead(ArrayRef<Value *> VL,
+                           std::pair<bool, bool> &ScalarizationKind) = 0;
   virtual bool supportsEfficientVectorElementLoadStore() = 0;
   virtual bool supportsTailCalls() = 0;
   virtual bool supportsTailCallFor(const CallBase *CB) = 0;
@@ -2456,6 +2465,13 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
     return Impl.getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
                                          CostKind);
   }
+
+  bool
+  hasScalarizationOverhead(ArrayRef<Value *> VL,
+                           std::pair<bool, bool> &ScalarizationKind) override {
+    return Impl.hasScalarizationOverhead(VL, ScalarizationKind);
+  }
+
   InstructionCost
   getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
                                    ArrayRef<Type *> Tys,
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 7828bdc1f1f43..1d3e6752006d9 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -371,6 +371,11 @@ class TargetTransformInfoImplBase {
     return 0;
   }
 
+  bool hasScalarizationOverhead(ArrayRef<Value *> VL,
+                                std::pair<bool, bool> &ScalarizationKind) {
+    return false;
+  }
+
   InstructionCost
   getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
                                    ArrayRef<Type *> Tys,
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 9f8d3ded9b3c1..2aa36c724bc03 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -807,6 +807,11 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
                                              CostKind);
   }
 
+  bool hasScalarizationOverhead(ArrayRef<Value *> VL,
+                                std::pair<bool, bool> &ScalarizationKind) {
+    return false;
+  }
+
   /// Estimate the overhead of scalarizing an instructions unique
   /// non-constant operands. The (potentially vector) types to use for each of
   /// argument are passes via Tys.
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 7e721cbc87f3f..81b1e6b181bb0 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -594,6 +594,11 @@ InstructionCost TargetTransformInfo::getScalarizationOverhead(
                                            CostKind);
 }
 
+bool TargetTransformInfo::hasScalarizationOverhead(
+    ArrayRef<Value *> VL, std::pair<bool, bool> &ScalarizeKind) const {
+  return TTIImpl->hasScalarizationOverhead(VLm ScalarizeKind);
+}
+
 InstructionCost TargetTransformInfo::getOperandsScalarizationOverhead(
     ArrayRef<const Value *> Args, ArrayRef<Type *> Tys,
     TTI::TargetCostKind CostKind) const {
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index ae0819c964bef..f189e9b6ba14b 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -9084,6 +9084,14 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
         E, ScalarTy, *TTI, VectorizedVals, *this, CheckedExtracts);
   }
   InstructionCost CommonCost = 0;
+  std::pair<bool, bool> ScalarizationKind(false, false);
+  if (TTI->hasScalarizationOverhead(VL, ScalarizationKind)) {
+    APInt DemandedElts = APInt::getAllOnes(VL.size());
+    CommonCost -= TTI->getScalarizationOverhead(
+        VecTy, DemandedElts,
+        /*Insert*/ ScalarizationKind.first,
+        /*Extract*/ ScalarizationKind.second, CostKind);
+  }
   SmallVector<int> Mask;
   bool IsReverseOrder = isReverseOrder(E->ReorderIndices);
   if (!E->ReorderIndices.empty() &&

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include target implementation and test?

Comment on lines 894 to 897
/// Whether or not there is any target-specific condition that imposes an
/// overhead for scalarization
bool hasScalarizationOverhead(ArrayRef<Value *> VL,
std::pair<bool, bool> &ScalarizationKind) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What can this express that getOperandsScalarizationOverhead and getScalarizationOverhead do not?

I'm already confused by every function in TTI having multiple versions of ~everything

Copy link
Contributor Author

@jrbyrnes jrbyrnes Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What can this express that getOperandsScalarizationOverhead and getScalarizationOverhead do not?

Those functions are used to calculate the cost of the scalarized sequence based on the inserts/extracts needed and the legalization costs based on TLI. For the purpose here, we can use either to calculate the cost of scalarization, but we need a mechanism to control whether or not to include this scalarization overhead for a particular tree entry (which is what this new hook is used for).

Even if we wanted to implement this control in those functions, I think we would still need to query targets as to whether or not there needs to be a cost accounting for the SelectionDAG issue workaround (assuming we could generalize the conditions in which the SelectionDAG issue occurred). Perhaps renaming the hook would help (e.g. hasSelectionDAGScalarizationOverhead)?

jrbyrnes added 3 commits June 13, 2024 11:43
Change-Id: Ia995bc646e5f050083bd6277eeabe0b5ab410f47
Change-Id: I0de224f42d77bb25fcbae5ccd6ad863560d0bb1d
Change-Id: If5ac53d5235ee8c65c53454b209c9f155c17edc4
@jrbyrnes
Copy link
Contributor Author

Add implementation of hasScalarizationOverhead and test.

Rebased on top of #91016 in order to facilitate the test

jrbyrnes added 2 commits June 13, 2024 13:28
Change-Id: Ideeafb60bc63c8bc09faa33f09dfb89f2c379819
Change-Id: Iee3e2c5036fc946df05aa45a6122e8913cf9a916
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AMDGPU llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms vectorizers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants