[llvm] [NFC][TTI] Introduce getInstructionUniformity API for uniformity analysis (PR #168903)
Pankaj Dwivedi via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 10 08:34:04 PST 2025
https://github.com/PankajDwivedi-25 updated https://github.com/llvm/llvm-project/pull/168903
>From 1a7ca4c56ec3afd6a1581c19eb3ad2b59aa9011f Mon Sep 17 00:00:00 2001
From: Pankaj kumar divedi <Pankajkumar.divedi at amd.com>
Date: Thu, 20 Nov 2025 22:12:51 +0530
Subject: [PATCH 1/3] add target hook getInstructionUniformity
---
.../include/llvm/Analysis/TargetTransformInfo.h | 10 ++++++++++
.../llvm/Analysis/TargetTransformInfoImpl.h | 4 ++++
llvm/lib/Analysis/TargetTransformInfo.cpp | 5 +++++
llvm/lib/Analysis/UniformityAnalysis.cpp | 17 ++++++++++++-----
llvm/lib/CodeGen/MachineUniformityAnalysis.cpp | 13 ++++++++-----
.../Target/AMDGPU/AMDGPUTargetTransformInfo.cpp | 11 +++++++++++
.../Target/AMDGPU/AMDGPUTargetTransformInfo.h | 2 ++
.../Target/NVPTX/NVPTXTargetTransformInfo.cpp | 8 ++++++++
.../lib/Target/NVPTX/NVPTXTargetTransformInfo.h | 2 ++
9 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 0f17312b03827..9d5aaab82905d 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/Uniformity.h"
#include "llvm/Analysis/IVDescriptors.h"
#include "llvm/Analysis/InterestingMemoryOperand.h"
#include "llvm/IR/FMF.h"
@@ -468,6 +469,15 @@ class TargetTransformInfo {
// even taking non-uniform arguments
LLVM_ABI bool isAlwaysUniform(const Value *V) const;
+ /// Get target-specific uniformity information for an instruction.
+ /// This allows targets to provide more fine-grained control over
+ /// uniformity analysis by specifying whether specific instructions
+ /// should always or never be considered uniform, or require custom
+ /// operand-based analysis.
+ /// \param V The value to query for uniformity information.
+ /// \return InstructionUniformity.
+ LLVM_ABI InstructionUniformity getInstructionUniformity(const Value *V) const;
+
/// Query the target whether the specified address space cast from FromAS to
/// ToAS is valid.
LLVM_ABI bool isValidAddrSpaceCast(unsigned FromAS, unsigned ToAS) const;
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index aacb88d2f9684..60b3c6f397e4f 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -135,6 +135,10 @@ class TargetTransformInfoImplBase {
virtual bool isAlwaysUniform(const Value *V) const { return false; }
+ virtual InstructionUniformity getInstructionUniformity(const Value *V) const {
+ return InstructionUniformity::Default;
+ }
+
virtual bool isValidAddrSpaceCast(unsigned FromAS, unsigned ToAS) const {
return false;
}
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 0426ac7e62fab..301dcba5b1cb7 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -306,6 +306,11 @@ bool llvm::TargetTransformInfo::isAlwaysUniform(const Value *V) const {
return TTIImpl->isAlwaysUniform(V);
}
+InstructionUniformity
+llvm::TargetTransformInfo::getInstructionUniformity(const Value *V) const {
+ return TTIImpl->getInstructionUniformity(V);
+}
+
bool llvm::TargetTransformInfo::isValidAddrSpaceCast(unsigned FromAS,
unsigned ToAS) const {
return TTIImpl->isValidAddrSpaceCast(FromAS, ToAS);
diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index 2e4063f5db14e..b56534935d7c2 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -31,15 +31,22 @@ bool llvm::GenericUniformityAnalysisImpl<SSAContext>::markDefsDivergent(
template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
for (auto &I : instructions(F)) {
- if (TTI->isSourceOfDivergence(&I))
- markDivergent(I);
- else if (TTI->isAlwaysUniform(&I))
+ InstructionUniformity IU = TTI->getInstructionUniformity(&I);
+ switch (IU) {
+ case InstructionUniformity::AlwaysUniform:
addUniformOverride(I);
+ continue;
+ case InstructionUniformity::NeverUniform:
+ markDivergent(I);
+ continue;
+ case InstructionUniformity::Default:
+ break;
+ }
}
for (auto &Arg : F.args()) {
- if (TTI->isSourceOfDivergence(&Arg)) {
+ if (TTI->getInstructionUniformity(&Arg) ==
+ InstructionUniformity::NeverUniform)
markDivergent(&Arg);
- }
}
}
diff --git a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
index e4b82ce83fda6..238d29d386574 100644
--- a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
+++ b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
@@ -53,13 +53,16 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
for (const MachineBasicBlock &block : F) {
for (const MachineInstr &instr : block) {
auto uniformity = InstrInfo.getInstructionUniformity(instr);
- if (uniformity == InstructionUniformity::AlwaysUniform) {
- addUniformOverride(instr);
- continue;
- }
- if (uniformity == InstructionUniformity::NeverUniform) {
+ switch (uniformity) {
+ case InstructionUniformity::AlwaysUniform:
+ addUniformOverride(instr);
+ break;
+ case InstructionUniformity::NeverUniform:
markDivergent(instr);
+ break;
+ case InstructionUniformity::Default:
+ break;
}
}
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
index 03d16fdd54c42..48b8376d23a66 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
@@ -1574,3 +1574,14 @@ unsigned GCNTTIImpl::getNumberOfParts(Type *Tp) const {
}
return BaseT::getNumberOfParts(Tp);
}
+
+InstructionUniformity
+GCNTTIImpl::getInstructionUniformity(const Value *V) const {
+ if (isAlwaysUniform(V))
+ return InstructionUniformity::AlwaysUniform;
+
+ if (isSourceOfDivergence(V))
+ return InstructionUniformity::NeverUniform;
+
+ return InstructionUniformity::Default;
+}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
index 20da8344c9d37..c2e102c9bab8e 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
@@ -302,6 +302,8 @@ class GCNTTIImpl final : public BasicTTIImplBase<GCNTTIImpl> {
/// together under a single i32 value. Otherwise fall back to base
/// implementation.
unsigned getNumberOfParts(Type *Tp) const override;
+
+ InstructionUniformity getInstructionUniformity(const Value *V) const override;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp
index 64593e6439184..c9920ae320d86 100644
--- a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp
@@ -635,3 +635,11 @@ void NVPTXTTIImpl::collectKernelLaunchBounds(
if (MaxNTID.size() > 2)
LB.push_back({"maxntidz", MaxNTID[2]});
}
+
+InstructionUniformity
+NVPTXTTIImpl::getInstructionUniformity(const Value *V) const {
+ if (isSourceOfDivergence(V))
+ return InstructionUniformity::NeverUniform;
+
+ return InstructionUniformity::Default;
+}
diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
index 78eb751cf3c2e..bb4d9a05ad805 100644
--- a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
+++ b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
@@ -195,6 +195,8 @@ class NVPTXTTIImpl final : public BasicTTIImplBase<NVPTXTTIImpl> {
// Self-referential globals are not supported.
return false;
}
+
+ InstructionUniformity getInstructionUniformity(const Value *V) const override;
};
} // end namespace llvm
>From b3db6e5d3608516b4c24fd42319d7b66ca3249b8 Mon Sep 17 00:00:00 2001
From: Pankaj kumar divedi <Pankajkumar.divedi at amd.com>
Date: Wed, 10 Dec 2025 18:39:51 +0530
Subject: [PATCH 2/3] remove unused hook from target
---
llvm/include/llvm/Analysis/TargetTransformInfo.h | 11 -----------
.../llvm/Analysis/TargetTransformInfoImpl.h | 4 ----
llvm/include/llvm/CodeGen/BasicTTIImpl.h | 4 ----
llvm/lib/Analysis/TargetTransformInfo.cpp | 15 ++++-----------
.../lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h | 10 ++++++++--
llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h | 6 ++++--
6 files changed, 16 insertions(+), 34 deletions(-)
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 9d5aaab82905d..23c36a4ae7848 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -458,17 +458,6 @@ class TargetTransformInfo {
/// uniformity analysis and assume all values are uniform.
LLVM_ABI bool hasBranchDivergence(const Function *F = nullptr) const;
- /// Returns whether V is a source of divergence.
- ///
- /// This function provides the target-dependent information for
- /// the target-independent UniformityAnalysis.
- LLVM_ABI bool isSourceOfDivergence(const Value *V) const;
-
- // Returns true for the target specific
- // set of operations which produce uniform result
- // even taking non-uniform arguments
- LLVM_ABI bool isAlwaysUniform(const Value *V) const;
-
/// Get target-specific uniformity information for an instruction.
/// This allows targets to provide more fine-grained control over
/// uniformity analysis by specifying whether specific instructions
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 60b3c6f397e4f..cf29228c19bd3 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -131,10 +131,6 @@ class TargetTransformInfoImplBase {
return false;
}
- virtual bool isSourceOfDivergence(const Value *V) const { return false; }
-
- virtual bool isAlwaysUniform(const Value *V) const { return false; }
-
virtual InstructionUniformity getInstructionUniformity(const Value *V) const {
return InstructionUniformity::Default;
}
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index f58525754d7a5..f2bace22b3d94 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -424,10 +424,6 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return false;
}
- bool isSourceOfDivergence(const Value *V) const override { return false; }
-
- bool isAlwaysUniform(const Value *V) const override { return false; }
-
bool isValidAddrSpaceCast(unsigned FromAS, unsigned ToAS) const override {
return false;
}
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 301dcba5b1cb7..7989dd86c7b76 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -294,20 +294,13 @@ bool TargetTransformInfo::hasBranchDivergence(const Function *F) const {
return TTIImpl->hasBranchDivergence(F);
}
-bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
+InstructionUniformity
+llvm::TargetTransformInfo::getInstructionUniformity(const Value *V) const {
+ // Calls with the NoDivergenceSource attribute are always uniform.
if (const auto *Call = dyn_cast<CallBase>(V)) {
if (Call->hasFnAttr(Attribute::NoDivergenceSource))
- return false;
+ return InstructionUniformity::AlwaysUniform;
}
- return TTIImpl->isSourceOfDivergence(V);
-}
-
-bool llvm::TargetTransformInfo::isAlwaysUniform(const Value *V) const {
- return TTIImpl->isAlwaysUniform(V);
-}
-
-InstructionUniformity
-llvm::TargetTransformInfo::getInstructionUniformity(const Value *V) const {
return TTIImpl->getInstructionUniformity(V);
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
index c2e102c9bab8e..cc507b01b2e32 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
@@ -101,6 +101,14 @@ class GCNTTIImpl final : public BasicTTIImplBase<GCNTTIImpl> {
std::pair<InstructionCost, MVT> getTypeLegalizationCost(Type *Ty) const;
+ /// \returns true if the result of the value could potentially be
+ /// different across workitems in a wavefront.
+ bool isSourceOfDivergence(const Value *V) const;
+
+ /// Returns true for the target specific set of operations which produce
+ /// uniform result even taking non-uniform arguments.
+ bool isAlwaysUniform(const Value *V) const;
+
public:
explicit GCNTTIImpl(const AMDGPUTargetMachine *TM, const Function &F);
@@ -174,8 +182,6 @@ class GCNTTIImpl final : public BasicTTIImplBase<GCNTTIImpl> {
const Value *Op1) const override;
bool isReadRegisterSourceOfDivergence(const IntrinsicInst *ReadReg) const;
- bool isSourceOfDivergence(const Value *V) const override;
- bool isAlwaysUniform(const Value *V) const override;
bool isValidAddrSpaceCast(unsigned FromAS, unsigned ToAS) const override {
// Address space casts must cast between different address spaces.
diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
index bb4d9a05ad805..ce502488dfe22 100644
--- a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
+++ b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
@@ -37,6 +37,10 @@ class NVPTXTTIImpl final : public BasicTTIImplBase<NVPTXTTIImpl> {
const NVPTXSubtarget *getST() const { return ST; };
const NVPTXTargetLowering *getTLI() const { return TLI; };
+ /// \returns true if the result of the value could potentially be
+ /// different across threads in a warp.
+ bool isSourceOfDivergence(const Value *V) const;
+
public:
explicit NVPTXTTIImpl(const NVPTXTargetMachine *TM, const Function &F)
: BaseT(TM, F.getDataLayout()), ST(TM->getSubtargetImpl()),
@@ -46,8 +50,6 @@ class NVPTXTTIImpl final : public BasicTTIImplBase<NVPTXTTIImpl> {
return true;
}
- bool isSourceOfDivergence(const Value *V) const override;
-
unsigned getFlatAddressSpace() const override {
return AddressSpace::ADDRESS_SPACE_GENERIC;
}
>From 580219e73b3c041ac0af738eec29dda381dc75e9 Mon Sep 17 00:00:00 2001
From: Pankaj kumar divedi <Pankajkumar.divedi at amd.com>
Date: Wed, 10 Dec 2025 22:03:50 +0530
Subject: [PATCH 3/3] address review
---
llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
index cc507b01b2e32..4dcf381a9af93 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
@@ -101,8 +101,8 @@ class GCNTTIImpl final : public BasicTTIImplBase<GCNTTIImpl> {
std::pair<InstructionCost, MVT> getTypeLegalizationCost(Type *Ty) const;
- /// \returns true if the result of the value could potentially be
- /// different across workitems in a wavefront.
+ /// \returns true if V might be divergent even when all of its operands
+ /// are uniform.
bool isSourceOfDivergence(const Value *V) const;
/// Returns true for the target specific set of operations which produce
More information about the llvm-commits
mailing list