Skip to content

Conversation

@RonDahan101
Copy link
Contributor

Now, each target, depending on the load/store instruction, can indicate whether it is safe to vectorize histogram operations.

For example, this allows distinguishing between different pointer address spaces.

Now, each target, depending on the load/store instruction, can indicate
whether it is safe to vectorize histogram operations.

For example, this allows distinguishing between different pointer address spaces.
@github-actions
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added vectorizers llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Feb 23, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 23, 2025

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: None (RonDahan101)

Changes

Now, each target, depending on the load/store instruction, can indicate whether it is safe to vectorize histogram operations.

For example, this allows distinguishing between different pointer address spaces.


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

4 Files Affected:

  • (modified) llvm/include/llvm/Analysis/TargetTransformInfo.h (+9)
  • (modified) llvm/include/llvm/Analysis/TargetTransformInfoImpl.h (+16)
  • (modified) llvm/lib/Analysis/TargetTransformInfo.cpp (+5)
  • (modified) llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp (+3)
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 9048481b49189..94a565a99ab41 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -805,6 +805,9 @@ class TargetTransformInfo {
   bool isLegalMaskedScatter(Type *DataType, Align Alignment) const;
   /// Return true if the target supports masked gather.
   bool isLegalMaskedGather(Type *DataType, Align Alignment) const;
+  /// Return true if the target supports vectorization of histograms.
+  bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                        const StoreInst *SI) const;
   /// Return true if the target forces scalarizing of llvm.masked.gather
   /// intrinsics.
   bool forceScalarizeMaskedGather(VectorType *Type, Align Alignment) const;
@@ -2028,6 +2031,8 @@ class TargetTransformInfo::Concept {
                                     ElementCount NumElements) const = 0;
   virtual bool isLegalMaskedScatter(Type *DataType, Align Alignment) = 0;
   virtual bool isLegalMaskedGather(Type *DataType, Align Alignment) = 0;
+  virtual bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                                const StoreInst *SI) = 0;
   virtual bool forceScalarizeMaskedGather(VectorType *DataType,
                                           Align Alignment) = 0;
   virtual bool forceScalarizeMaskedScatter(VectorType *DataType,
@@ -2589,6 +2594,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
   bool isLegalMaskedGather(Type *DataType, Align Alignment) override {
     return Impl.isLegalMaskedGather(DataType, Alignment);
   }
+  bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                        const StoreInst *SI) override {
+    return Impl.isLegalForHistogramVectorization(LI, SI);
+  }
   bool forceScalarizeMaskedGather(VectorType *DataType,
                                   Align Alignment) override {
     return Impl.forceScalarizeMaskedGather(DataType, Alignment);
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index a8d6dd18266bb..de93612ffffda 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -310,6 +310,22 @@ class TargetTransformInfoImplBase {
     return false;
   }
 
+  bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                        const StoreInst *SI) const {
+    // TODO: Currently, when a target wants to use histogram intrinsics, it adds
+    // the
+    // `-enable-histogram-loop-vectorization` flag to Clang.
+    //
+    // Once the histogram option is enabled by default, we will need to update
+    // the default hook to return `false`, and each target that wants automatic
+    // histogram vectorization will need to override it to return `true`.
+    //
+    // Additionally, we will need to deprecate the
+    // `-enable-histogram-loop-vectorization` flag, as it will no longer be
+    // necessary.
+    return true;
+  }
+
   bool forceScalarizeMaskedGather(VectorType *DataType, Align Alignment) const {
     return false;
   }
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 7df7038f6dd47..7a020d55abad2 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -492,6 +492,11 @@ bool TargetTransformInfo::isLegalMaskedGather(Type *DataType,
   return TTIImpl->isLegalMaskedGather(DataType, Alignment);
 }
 
+bool TargetTransformInfo::isLegalForHistogramVectorization(
+    const LoadInst *LI, const StoreInst *SI) const {
+  return TTIImpl->isLegalForHistogramVectorization(LI, SI);
+}
+
 bool TargetTransformInfo::isLegalAltInstr(
     VectorType *VecTy, unsigned Opcode0, unsigned Opcode1,
     const SmallBitVector &OpcodeMask) const {
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 420cbc5384ce4..4045fd315d5bd 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -1193,6 +1193,9 @@ bool LoopVectorizationLegality::canVectorizeIndirectUnsafeDependences() {
   if (!LI || !SI)
     return false;
 
+  if (!TTI->isLegalForHistogramVectorization(LI, SI))
+    return false;
+
   LLVM_DEBUG(dbgs() << "LV: Checking for a histogram on: " << *SI << "\n");
   return findHistogram(LI, SI, TheLoop, LAI->getPSE(), Histograms);
 }

@llvmbot
Copy link
Member

llvmbot commented Feb 23, 2025

@llvm/pr-subscribers-vectorizers

Author: None (RonDahan101)

Changes

Now, each target, depending on the load/store instruction, can indicate whether it is safe to vectorize histogram operations.

For example, this allows distinguishing between different pointer address spaces.


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

4 Files Affected:

  • (modified) llvm/include/llvm/Analysis/TargetTransformInfo.h (+9)
  • (modified) llvm/include/llvm/Analysis/TargetTransformInfoImpl.h (+16)
  • (modified) llvm/lib/Analysis/TargetTransformInfo.cpp (+5)
  • (modified) llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp (+3)
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 9048481b49189..94a565a99ab41 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -805,6 +805,9 @@ class TargetTransformInfo {
   bool isLegalMaskedScatter(Type *DataType, Align Alignment) const;
   /// Return true if the target supports masked gather.
   bool isLegalMaskedGather(Type *DataType, Align Alignment) const;
+  /// Return true if the target supports vectorization of histograms.
+  bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                        const StoreInst *SI) const;
   /// Return true if the target forces scalarizing of llvm.masked.gather
   /// intrinsics.
   bool forceScalarizeMaskedGather(VectorType *Type, Align Alignment) const;
@@ -2028,6 +2031,8 @@ class TargetTransformInfo::Concept {
                                     ElementCount NumElements) const = 0;
   virtual bool isLegalMaskedScatter(Type *DataType, Align Alignment) = 0;
   virtual bool isLegalMaskedGather(Type *DataType, Align Alignment) = 0;
+  virtual bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                                const StoreInst *SI) = 0;
   virtual bool forceScalarizeMaskedGather(VectorType *DataType,
                                           Align Alignment) = 0;
   virtual bool forceScalarizeMaskedScatter(VectorType *DataType,
@@ -2589,6 +2594,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
   bool isLegalMaskedGather(Type *DataType, Align Alignment) override {
     return Impl.isLegalMaskedGather(DataType, Alignment);
   }
+  bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                        const StoreInst *SI) override {
+    return Impl.isLegalForHistogramVectorization(LI, SI);
+  }
   bool forceScalarizeMaskedGather(VectorType *DataType,
                                   Align Alignment) override {
     return Impl.forceScalarizeMaskedGather(DataType, Alignment);
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index a8d6dd18266bb..de93612ffffda 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -310,6 +310,22 @@ class TargetTransformInfoImplBase {
     return false;
   }
 
+  bool isLegalForHistogramVectorization(const LoadInst *LI,
+                                        const StoreInst *SI) const {
+    // TODO: Currently, when a target wants to use histogram intrinsics, it adds
+    // the
+    // `-enable-histogram-loop-vectorization` flag to Clang.
+    //
+    // Once the histogram option is enabled by default, we will need to update
+    // the default hook to return `false`, and each target that wants automatic
+    // histogram vectorization will need to override it to return `true`.
+    //
+    // Additionally, we will need to deprecate the
+    // `-enable-histogram-loop-vectorization` flag, as it will no longer be
+    // necessary.
+    return true;
+  }
+
   bool forceScalarizeMaskedGather(VectorType *DataType, Align Alignment) const {
     return false;
   }
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 7df7038f6dd47..7a020d55abad2 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -492,6 +492,11 @@ bool TargetTransformInfo::isLegalMaskedGather(Type *DataType,
   return TTIImpl->isLegalMaskedGather(DataType, Alignment);
 }
 
+bool TargetTransformInfo::isLegalForHistogramVectorization(
+    const LoadInst *LI, const StoreInst *SI) const {
+  return TTIImpl->isLegalForHistogramVectorization(LI, SI);
+}
+
 bool TargetTransformInfo::isLegalAltInstr(
     VectorType *VecTy, unsigned Opcode0, unsigned Opcode1,
     const SmallBitVector &OpcodeMask) const {
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 420cbc5384ce4..4045fd315d5bd 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -1193,6 +1193,9 @@ bool LoopVectorizationLegality::canVectorizeIndirectUnsafeDependences() {
   if (!LI || !SI)
     return false;
 
+  if (!TTI->isLegalForHistogramVectorization(LI, SI))
+    return false;
+
   LLVM_DEBUG(dbgs() << "LV: Checking for a histogram on: " << *SI << "\n");
   return findHistogram(LI, SI, TheLoop, LAI->getPSE(), Histograms);
 }

@RonDahan101
Copy link
Contributor Author

@RonDahan101
Copy link
Contributor Author

return false;
}

bool isLegalForHistogramVectorization(const LoadInst *LI,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering if you could add the load and store to the parameters in IntrinsicCostAttributes when asking for the cost of a histogram intrinsic, and return Invalid if the target doesn't support it instead of introducing a new method.

I guess this is a fast way of rejecting something in a different address space though, without going through the rest of the analysis.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When investigating your approach, I realized that IntrinsicCostAttributes already contains the GEP pointer, which includes the address space information. By adjusting the cost (or simply marking it as invalid), I can control which histogram operations I'd like to support.
Thank you for the feedback!
I'll go ahead and close the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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