[llvm] [LLVM] New NoDivergenceSource function attribute (PR #111832)

Tim Renouf via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 12 00:21:36 PDT 2024


https://github.com/trenouf updated https://github.com/llvm/llvm-project/pull/111832

>From 3bb577263d38831e579d8b114ed599ab799ae2ab Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Wed, 9 Oct 2024 18:48:50 +0100
Subject: [PATCH 1/6] [LLVM] New NoDivergenceSource function attribute

A call to a function that has this attribute is not a source of
divergence, as used by UniformityAnalysis. That allows a front-end
to use known-name calls as an instruction extension mechanism (e.g.
https://github.com/GPUOpen-Drivers/llvm-dialects ) without such a
call being a source of divergence.
---
 llvm/docs/LangRef.rst                            | 10 ++++++++++
 llvm/include/llvm/Bitcode/LLVMBitCodes.h         |  1 +
 llvm/include/llvm/IR/Attributes.td               |  3 +++
 llvm/lib/Analysis/UniformityAnalysis.cpp         |  9 ++++++++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp        |  2 ++
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp        |  2 ++
 llvm/lib/Transforms/Utils/CodeExtractor.cpp      |  1 +
 .../AMDGPU/nodivergencesource.ll                 | 16 ++++++++++++++++
 llvm/test/Bitcode/attributes.ll                  |  6 ++++++
 9 files changed, 49 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Analysis/UniformityAnalysis/AMDGPU/nodivergencesource.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 0c7279de06cd68..4c94ffbc1d7376 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2082,6 +2082,16 @@ example:
     function call, use of ``longjmp``, or other means. It is a compiler hint that
     is used at module level to improve dataflow analysis, dropped during linking,
     and has no effect on functions defined in the current module.
+``nodivergencesource``
+    A call to this function is not a source of divergence. In uniformity
+    analysis, a *source of divergence* is an instruction that generates
+    divergence even if its inputs are uniform. A call with no further information
+    would normally be considered a source of divergence; setting this attribute
+    on a function means that a call to it is not a source of divergence.
+
+    This is useful where known-name calls are being used as an extension
+    mechanism for instructions, as for example in `llvm-dialects
+    <https://github.com/GPUOpen-Drivers/llvm-dialects>`.
 ``noduplicate``
     This attribute indicates that calls to the function cannot be
     duplicated. A call to a ``noduplicate`` function may be moved
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index cbd92fd52fc75a..a6959d9b62742a 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -764,6 +764,7 @@ enum AttributeKindCodes {
   ATTR_KIND_SANITIZE_REALTIME_UNSAFE = 97,
   ATTR_KIND_CORO_ELIDE_SAFE = 98,
   ATTR_KIND_NO_EXT = 99,
+  ATTR_KIND_NO_DIVERGENCE_SOURCE = 100,
 };
 
 enum ComdatSelectionKindCodes {
diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td
index d05a6ca92aaba0..b6d36a5f7ae4fb 100644
--- a/llvm/include/llvm/IR/Attributes.td
+++ b/llvm/include/llvm/IR/Attributes.td
@@ -183,6 +183,9 @@ def NoCallback : EnumAttr<"nocallback", IntersectAnd, [FnAttr]>;
 /// Function creates no aliases of pointer.
 def NoCapture : EnumAttr<"nocapture", IntersectAnd, [ParamAttr]>;
 
+/// Function is not a source of divergence.
+def NoDivergenceSource : EnumAttr<"nodivergencesource", IntersectAnd, [FnAttr]>;
+
 /// Call cannot be duplicated.
 def NoDuplicate : EnumAttr<"noduplicate", IntersectPreserve, [FnAttr]>;
 
diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index 2d617db431c588..b0be6379a15125 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -32,7 +32,14 @@ bool llvm::GenericUniformityAnalysisImpl<SSAContext>::markDefsDivergent(
 
 template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
   for (auto &I : instructions(F)) {
-    if (TTI->isSourceOfDivergence(&I))
+    bool NoDivergenceSource = false;
+    if (auto Call = dyn_cast<CallInst>(&I)) {
+      if (Function *Callee = Call->getCalledFunction()) {
+        if (Callee->hasFnAttribute(Attribute::NoDivergenceSource))
+          NoDivergenceSource = true;
+      }
+    }
+    if (!NoDivergenceSource && TTI->isSourceOfDivergence(&I))
       markDivergent(I);
     else if (TTI->isAlwaysUniform(&I))
       addUniformOverride(I);
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 6f997510b03609..b8dc5ecbf7abda 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2048,6 +2048,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
     return Attribute::NoCallback;
   case bitc::ATTR_KIND_NO_CAPTURE:
     return Attribute::NoCapture;
+  case bitc::ATTR_KIND_NO_DIVERGENCE_SOURCE:
+    return Attribute::NoDivergenceSource;
   case bitc::ATTR_KIND_NO_DUPLICATE:
     return Attribute::NoDuplicate;
   case bitc::ATTR_KIND_NOFREE:
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index d9086bfebbd2a9..a44b6a8614357d 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -761,6 +761,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
     return bitc::ATTR_KIND_NO_CALLBACK;
   case Attribute::NoCapture:
     return bitc::ATTR_KIND_NO_CAPTURE;
+  case Attribute::NoDivergenceSource:
+    return bitc::ATTR_KIND_NO_DIVERGENCE_SOURCE;
   case Attribute::NoDuplicate:
     return bitc::ATTR_KIND_NO_DUPLICATE;
   case Attribute::NoFree:
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
index f58448dd9562d5..5b42099398f8ff 100644
--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -917,6 +917,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
       case Attribute::NoFPClass:
       case Attribute::CoroDestroyOnlyWhenComplete:
       case Attribute::CoroElideSafe:
+      case Attribute::NoDivergenceSource:
         continue;
       // Those attributes should be safe to propagate to the extracted function.
       case Attribute::AlwaysInline:
diff --git a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/nodivergencesource.ll b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/nodivergencesource.ll
new file mode 100644
index 00000000000000..9c893ac3ba76a0
--- /dev/null
+++ b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/nodivergencesource.ll
@@ -0,0 +1,16 @@
+; RUN: opt -mtriple amdgcn-- -passes='print<uniformity>' -disable-output %s 2>&1 | FileCheck %s
+
+; CHECK: DIVERGENT: %divergentval
+; CHECK-NOT: DIVERGENT: %uniformval
+; CHECK: %uniformval
+define void @test() {
+  %divergentval = call i32 @normalfunc()
+  %uniformval = call i32 @nodivergencesourcefunc()
+  ret void
+}
+
+declare i32 @normalfunc() #0
+declare i32 @nodivergencesourcefunc() #1
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind nodivergencesource }
diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
index a66eda19ff5735..737f49aa86a7ba 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -537,6 +537,11 @@ define void @f91(ptr dead_on_unwind %p) {
   ret void
 }
 
+; CHECK: define void @f94() [[NODIVERGENCESOURCE:#[0-9]+]]
+define void @f94() nodivergencesource {
+  ret void;
+}
+
 ; CHECK: define range(i32 -1, 42) i32 @range_attribute(<4 x i32> range(i32 -1, 42) %a)
 define range(i32 -1, 42) i32 @range_attribute(<4 x i32> range(i32 -1, 42) %a) {
   ret i32 0
@@ -615,4 +620,5 @@ define void @initializes(ptr initializes((-4, 0), (4, 8)) %a) {
 ; CHECK: attributes [[FNRETTHUNKEXTERN]] = { fn_ret_thunk_extern }
 ; CHECK: attributes [[SKIPPROFILE]] = { skipprofile }
 ; CHECK: attributes [[OPTDEBUG]] = { optdebug }
+; CHECK: attributes [[NODIVERGENCESOURCE]] = { nodivergencesource }
 ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }

>From e1905675f2e6b4c7723936b93ce85433b69f260d Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Thu, 10 Oct 2024 16:02:40 +0100
Subject: [PATCH 2/6] Use CallBase::hasFnAttr

---
 llvm/lib/Analysis/UniformityAnalysis.cpp | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index b0be6379a15125..3675b22057fa8c 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -33,12 +33,8 @@ bool llvm::GenericUniformityAnalysisImpl<SSAContext>::markDefsDivergent(
 template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
   for (auto &I : instructions(F)) {
     bool NoDivergenceSource = false;
-    if (auto Call = dyn_cast<CallInst>(&I)) {
-      if (Function *Callee = Call->getCalledFunction()) {
-        if (Callee->hasFnAttribute(Attribute::NoDivergenceSource))
-          NoDivergenceSource = true;
-      }
-    }
+    if (auto Call = dyn_cast<CallBase>(&I))
+      NoDivergenceSource = Call->hasFnAttr(Attribute::NoDivergenceSource);
     if (!NoDivergenceSource && TTI->isSourceOfDivergence(&I))
       markDivergent(I);
     else if (TTI->isAlwaysUniform(&I))

>From 795bbbaf25315437ad5ea2f775bbcc2d6db56cf6 Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Fri, 11 Oct 2024 14:56:58 +0100
Subject: [PATCH 3/6] Move check to TargetTransformInfo

---
 llvm/lib/Analysis/TargetTransformInfo.cpp | 4 ++++
 llvm/lib/Analysis/UniformityAnalysis.cpp  | 5 +----
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 3dc29fc7cd77b1..fd6627577d7f2a 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -288,6 +288,10 @@ bool TargetTransformInfo::hasBranchDivergence(const Function *F) const {
 }
 
 bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
+  if (auto Call = dyn_cast<CallBase>(V)) {
+    if (Call->hasFnAttr(Attribute::NoDivergenceSource))
+      return false;
+  }
   return TTIImpl->isSourceOfDivergence(V);
 }
 
diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index 3675b22057fa8c..2d617db431c588 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -32,10 +32,7 @@ bool llvm::GenericUniformityAnalysisImpl<SSAContext>::markDefsDivergent(
 
 template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
   for (auto &I : instructions(F)) {
-    bool NoDivergenceSource = false;
-    if (auto Call = dyn_cast<CallBase>(&I))
-      NoDivergenceSource = Call->hasFnAttr(Attribute::NoDivergenceSource);
-    if (!NoDivergenceSource && TTI->isSourceOfDivergence(&I))
+    if (TTI->isSourceOfDivergence(&I))
       markDivergent(I);
     else if (TTI->isAlwaysUniform(&I))
       addUniformOverride(I);

>From c578054ab5f2a6bbdf619c76a79f5386c347235a Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Fri, 11 Oct 2024 17:09:49 +0100
Subject: [PATCH 4/6] Remove last para. Un-auto a variable.

---
 llvm/docs/LangRef.rst                     | 4 ----
 llvm/lib/Analysis/TargetTransformInfo.cpp | 2 +-
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 4c94ffbc1d7376..506115aa9370b4 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2088,10 +2088,6 @@ example:
     divergence even if its inputs are uniform. A call with no further information
     would normally be considered a source of divergence; setting this attribute
     on a function means that a call to it is not a source of divergence.
-
-    This is useful where known-name calls are being used as an extension
-    mechanism for instructions, as for example in `llvm-dialects
-    <https://github.com/GPUOpen-Drivers/llvm-dialects>`.
 ``noduplicate``
     This attribute indicates that calls to the function cannot be
     duplicated. A call to a ``noduplicate`` function may be moved
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index fd6627577d7f2a..2b597e77703f77 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -288,7 +288,7 @@ bool TargetTransformInfo::hasBranchDivergence(const Function *F) const {
 }
 
 bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
-  if (auto Call = dyn_cast<CallBase>(V)) {
+  if (const CallBase *Call = dyn_cast<CallBase>(V)) {
     if (Call->hasFnAttr(Attribute::NoDivergenceSource))
       return false;
   }

>From 7cd27b81b39e93ed45c6788113f5912e34bb68a2 Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Fri, 11 Oct 2024 18:44:59 +0100
Subject: [PATCH 5/6] Reinstate auto but with *, as recommended in review

---
 llvm/lib/Analysis/TargetTransformInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 65fc639feadd0b..2b7bb626f6c07c 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -292,7 +292,7 @@ bool TargetTransformInfo::hasBranchDivergence(const Function *F) const {
 }
 
 bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
-  if (const CallBase *Call = dyn_cast<CallBase>(V)) {
+  if (auto *Call = dyn_cast<CallBase>(V)) {
     if (Call->hasFnAttr(Attribute::NoDivergenceSource))
       return false;
   }

>From a27951a2127a9eca84c2e9920b343034813074f3 Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Fri, 11 Oct 2024 18:55:08 +0100
Subject: [PATCH 6/6] const

---
 llvm/lib/Analysis/TargetTransformInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 2b7bb626f6c07c..a6c9b6111cab11 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -292,7 +292,7 @@ bool TargetTransformInfo::hasBranchDivergence(const Function *F) const {
 }
 
 bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
-  if (auto *Call = dyn_cast<CallBase>(V)) {
+  if (const auto *Call = dyn_cast<CallBase>(V)) {
     if (Call->hasFnAttr(Attribute::NoDivergenceSource))
       return false;
   }



More information about the llvm-commits mailing list