[llvm] [AMDGPU] InstCombine: fold invalid calls to amdgcn intrinsics into poison values (PR #191904)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 13 17:46:03 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Yoonseo Choi (yoonseoch)

<details>
<summary>Changes</summary>

Replace a call to amdgpu intrinsic into a poison value when the call is invalid because of "amdgpu-no-<xyz>" attribute in the caller function. 

Upon https://github.com/llvm/llvm-project/pull/186925#pullrequestreview-3983414064

Assisted by claude-4.6-sonnet-medium through CURSOR. 

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


8 Files Affected:

- (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+53) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.cluster.id.ll (+58) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.id.ll (+33) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.ptr.ll (+49) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.lds.kernel.id.ll (+33) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.queue.ptr.ll (+49) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workgroup.id.ll (+58) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workitem.id.ll (+58) 


``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 463d63a88f690..b85b46d32278c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -749,6 +749,59 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
 
     return std::nullopt;
   }
+  case Intrinsic::amdgcn_dispatch_ptr: {
+    if (II.getFunction()->hasFnAttribute("amdgpu-no-dispatch-ptr"))
+      return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+    return std::nullopt;
+  }
+  case Intrinsic::amdgcn_queue_ptr: {
+    if (II.getFunction()->hasFnAttribute("amdgpu-no-queue-ptr"))
+      return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+    return std::nullopt;
+  }
+  case Intrinsic::amdgcn_dispatch_id: {
+    if (II.getFunction()->hasFnAttribute("amdgpu-no-dispatch-id"))
+      return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+    return std::nullopt;
+  }
+  case Intrinsic::amdgcn_workgroup_id_x:
+  case Intrinsic::amdgcn_workgroup_id_y:
+  case Intrinsic::amdgcn_workgroup_id_z: {
+    StringRef Attr =
+        IID == Intrinsic::amdgcn_workgroup_id_x   ? "amdgpu-no-workgroup-id-x"
+        : IID == Intrinsic::amdgcn_workgroup_id_y ? "amdgpu-no-workgroup-id-y"
+                                                  : "amdgpu-no-workgroup-id-z";
+    if (II.getFunction()->hasFnAttribute(Attr))
+      return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+    return std::nullopt;
+  }
+  case Intrinsic::amdgcn_workitem_id_x:
+  case Intrinsic::amdgcn_workitem_id_y:
+  case Intrinsic::amdgcn_workitem_id_z: {
+    StringRef Attr =
+        IID == Intrinsic::amdgcn_workitem_id_x   ? "amdgpu-no-workitem-id-x"
+        : IID == Intrinsic::amdgcn_workitem_id_y ? "amdgpu-no-workitem-id-y"
+                                                 : "amdgpu-no-workitem-id-z";
+    if (II.getFunction()->hasFnAttribute(Attr))
+      return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+    return std::nullopt;
+  }
+  case Intrinsic::amdgcn_lds_kernel_id: {
+    if (II.getFunction()->hasFnAttribute("amdgpu-no-lds-kernel-id"))
+      return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+    return std::nullopt;
+  }
+  case Intrinsic::amdgcn_cluster_id_x:
+  case Intrinsic::amdgcn_cluster_id_y:
+  case Intrinsic::amdgcn_cluster_id_z: {
+    StringRef Attr =
+        IID == Intrinsic::amdgcn_cluster_id_x   ? "amdgpu-no-cluster-id-x"
+        : IID == Intrinsic::amdgcn_cluster_id_y ? "amdgpu-no-cluster-id-y"
+                                                : "amdgpu-no-cluster-id-z";
+    if (II.getFunction()->hasFnAttribute(Attr))
+      return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+    return std::nullopt;
+  }
   case Intrinsic::amdgcn_rcp: {
     Value *Src = II.getArgOperand(0);
     if (isa<PoisonValue>(Src))
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.cluster.id.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.cluster.id.ll
new file mode 100644
index 0000000000000..08bf22431d362
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.cluster.id.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa < %s | FileCheck %s
+
+; When amdgpu-no-cluster-id-x is set, calling the intrinsic is UB and the
+; call should be folded to poison.
+define i32 @no_cluster_id_x() #0 {
+; CHECK-LABEL: define i32 @no_cluster_id_x(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.cluster.id.x()
+  ret i32 %tmp
+}
+
+define i32 @no_cluster_id_y() #1 {
+; CHECK-LABEL: define i32 @no_cluster_id_y(
+; CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.cluster.id.y()
+  ret i32 %tmp
+}
+
+define i32 @no_cluster_id_z() #2 {
+; CHECK-LABEL: define i32 @no_cluster_id_z(
+; CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.cluster.id.z()
+  ret i32 %tmp
+}
+
+; Without the attribute the calls are kept.
+define i32 @cluster_id_x_no_attr() {
+; CHECK-LABEL: define i32 @cluster_id_x_no_attr() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP:%.*]] = call i32 @llvm.amdgcn.cluster.id.x()
+; CHECK-NEXT:    ret i32 [[TMP]]
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.cluster.id.x()
+  ret i32 %tmp
+}
+
+declare i32 @llvm.amdgcn.cluster.id.x() #3
+declare i32 @llvm.amdgcn.cluster.id.y() #3
+declare i32 @llvm.amdgcn.cluster.id.z() #3
+
+attributes #0 = { "amdgpu-no-cluster-id-x" }
+attributes #1 = { "amdgpu-no-cluster-id-y" }
+attributes #2 = { "amdgpu-no-cluster-id-z" }
+attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.id.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.id.ll
new file mode 100644
index 0000000000000..855bf00a22f40
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.id.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa < %s | FileCheck %s
+
+; When amdgpu-no-dispatch-id is set, calling the intrinsic is UB and the
+; call should be folded to poison.
+define i64 @no_dispatch_id() #0 {
+; CHECK-LABEL: define i64 @no_dispatch_id(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i64 poison
+;
+entry:
+  %tmp = call i64 @llvm.amdgcn.dispatch.id()
+  ret i64 %tmp
+}
+
+; Without the attribute the call is kept.
+define i64 @dispatch_id_no_attr() {
+; CHECK-LABEL: define i64 @dispatch_id_no_attr() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP:%.*]] = call i64 @llvm.amdgcn.dispatch.id()
+; CHECK-NEXT:    ret i64 [[TMP]]
+;
+entry:
+  %tmp = call i64 @llvm.amdgcn.dispatch.id()
+  ret i64 %tmp
+}
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare i64 @llvm.amdgcn.dispatch.id() #1
+
+attributes #0 = { "amdgpu-no-dispatch-id" }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.ptr.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.ptr.ll
new file mode 100644
index 0000000000000..b2c25cde0a57c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.ptr.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa < %s | FileCheck %s
+
+; When amdgpu-no-dispatch-ptr is set, calling the intrinsic is UB and the
+; call should be folded to poison.
+define ptr addrspace(4) @no_dispatch_ptr() #0 {
+; CHECK-LABEL: define ptr addrspace(4) @no_dispatch_ptr(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret ptr addrspace(4) poison
+;
+entry:
+  %tmp = call ptr addrspace(4) @llvm.amdgcn.dispatch.ptr()
+  ret ptr addrspace(4) %tmp
+}
+
+; When amdgpu-no-dispatch-ptr is set, a load from the intrinsic's returned
+; pointer is also UB. The call folds to poison and loading from poison yields
+; poison via existing InstCombine rules.
+define i32 @no_dispatch_ptr_load() #0 {
+; CHECK-LABEL: define i32 @no_dispatch_ptr_load(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    store i1 true, ptr poison, align 1
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %ptr = call ptr addrspace(4) @llvm.amdgcn.dispatch.ptr()
+  %val = load i32, ptr addrspace(4) %ptr
+  ret i32 %val
+}
+
+; Without the attribute the call is kept.
+define ptr addrspace(4) @dispatch_ptr_no_attr() {
+; CHECK-LABEL: define ptr addrspace(4) @dispatch_ptr_no_attr() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP:%.*]] = call ptr addrspace(4) @llvm.amdgcn.dispatch.ptr()
+; CHECK-NEXT:    ret ptr addrspace(4) [[TMP]]
+;
+entry:
+  %tmp = call ptr addrspace(4) @llvm.amdgcn.dispatch.ptr()
+  ret ptr addrspace(4) %tmp
+}
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare ptr addrspace(4) @llvm.amdgcn.dispatch.ptr() #1
+
+attributes #0 = { "amdgpu-no-dispatch-ptr" }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.lds.kernel.id.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.lds.kernel.id.ll
new file mode 100644
index 0000000000000..c5858dae45c1c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.lds.kernel.id.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa < %s | FileCheck %s
+
+; When amdgpu-no-lds-kernel-id is set, calling the intrinsic is UB and the
+; call should be folded to poison.
+define i32 @no_lds_kernel_id() #0 {
+; CHECK-LABEL: define i32 @no_lds_kernel_id(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.lds.kernel.id()
+  ret i32 %tmp
+}
+
+; Without the attribute the call is kept.
+define i32 @lds_kernel_id_no_attr() {
+; CHECK-LABEL: define i32 @lds_kernel_id_no_attr() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP:%.*]] = call i32 @llvm.amdgcn.lds.kernel.id()
+; CHECK-NEXT:    ret i32 [[TMP]]
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.lds.kernel.id()
+  ret i32 %tmp
+}
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare i32 @llvm.amdgcn.lds.kernel.id() #1
+
+attributes #0 = { "amdgpu-no-lds-kernel-id" }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.queue.ptr.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.queue.ptr.ll
new file mode 100644
index 0000000000000..b87a6e1aa5f97
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.queue.ptr.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa < %s | FileCheck %s
+
+; When amdgpu-no-queue-ptr is set, calling the intrinsic is UB and the
+; call should be folded to poison.
+define ptr addrspace(4) @no_queue_ptr() #0 {
+; CHECK-LABEL: define ptr addrspace(4) @no_queue_ptr(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret ptr addrspace(4) poison
+;
+entry:
+  %tmp = call ptr addrspace(4) @llvm.amdgcn.queue.ptr()
+  ret ptr addrspace(4) %tmp
+}
+
+; When amdgpu-no-queue-ptr is set, a load from the intrinsic's returned
+; pointer is also UB. The call folds to poison and loading from poison yields
+; poison via existing InstCombine rules.
+define i32 @no_queue_ptr_load() #0 {
+; CHECK-LABEL: define i32 @no_queue_ptr_load(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    store i1 true, ptr poison, align 1
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %ptr = call ptr addrspace(4) @llvm.amdgcn.queue.ptr()
+  %val = load i32, ptr addrspace(4) %ptr
+  ret i32 %val
+}
+
+; Without the attribute the call is kept.
+define ptr addrspace(4) @queue_ptr_no_attr() {
+; CHECK-LABEL: define ptr addrspace(4) @queue_ptr_no_attr() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP:%.*]] = call ptr addrspace(4) @llvm.amdgcn.queue.ptr()
+; CHECK-NEXT:    ret ptr addrspace(4) [[TMP]]
+;
+entry:
+  %tmp = call ptr addrspace(4) @llvm.amdgcn.queue.ptr()
+  ret ptr addrspace(4) %tmp
+}
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare ptr addrspace(4) @llvm.amdgcn.queue.ptr() #1
+
+attributes #0 = { "amdgpu-no-queue-ptr" }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workgroup.id.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workgroup.id.ll
new file mode 100644
index 0000000000000..30386785ef2fd
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workgroup.id.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa < %s | FileCheck %s
+
+; When amdgpu-no-workgroup-id-x is set, calling the intrinsic is UB and the
+; call should be folded to poison.
+define i32 @no_workgroup_id_x() #0 {
+; CHECK-LABEL: define i32 @no_workgroup_id_x(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workgroup.id.x()
+  ret i32 %tmp
+}
+
+define i32 @no_workgroup_id_y() #1 {
+; CHECK-LABEL: define i32 @no_workgroup_id_y(
+; CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workgroup.id.y()
+  ret i32 %tmp
+}
+
+define i32 @no_workgroup_id_z() #2 {
+; CHECK-LABEL: define i32 @no_workgroup_id_z(
+; CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workgroup.id.z()
+  ret i32 %tmp
+}
+
+; Without the attribute the calls are kept.
+define i32 @workgroup_id_x_no_attr() {
+; CHECK-LABEL: define i32 @workgroup_id_x_no_attr() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP:%.*]] = call i32 @llvm.amdgcn.workgroup.id.x()
+; CHECK-NEXT:    ret i32 [[TMP]]
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workgroup.id.x()
+  ret i32 %tmp
+}
+
+declare i32 @llvm.amdgcn.workgroup.id.x() #3
+declare i32 @llvm.amdgcn.workgroup.id.y() #3
+declare i32 @llvm.amdgcn.workgroup.id.z() #3
+
+attributes #0 = { "amdgpu-no-workgroup-id-x" }
+attributes #1 = { "amdgpu-no-workgroup-id-y" }
+attributes #2 = { "amdgpu-no-workgroup-id-z" }
+attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workitem.id.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workitem.id.ll
new file mode 100644
index 0000000000000..aa85ebf03b85c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workitem.id.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa < %s | FileCheck %s
+
+; When amdgpu-no-workitem-id-x is set, calling the intrinsic is UB and the
+; call should be folded to poison.
+define i32 @no_workitem_id_x() #0 {
+; CHECK-LABEL: define i32 @no_workitem_id_x(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workitem.id.x()
+  ret i32 %tmp
+}
+
+define i32 @no_workitem_id_y() #1 {
+; CHECK-LABEL: define i32 @no_workitem_id_y(
+; CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workitem.id.y()
+  ret i32 %tmp
+}
+
+define i32 @no_workitem_id_z() #2 {
+; CHECK-LABEL: define i32 @no_workitem_id_z(
+; CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workitem.id.z()
+  ret i32 %tmp
+}
+
+; Without the attribute the calls are kept.
+define i32 @workitem_id_x_no_attr() {
+; CHECK-LABEL: define i32 @workitem_id_x_no_attr() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()
+; CHECK-NEXT:    ret i32 [[TMP]]
+;
+entry:
+  %tmp = call i32 @llvm.amdgcn.workitem.id.x()
+  ret i32 %tmp
+}
+
+declare i32 @llvm.amdgcn.workitem.id.x() #3
+declare i32 @llvm.amdgcn.workitem.id.y() #3
+declare i32 @llvm.amdgcn.workitem.id.z() #3
+
+attributes #0 = { "amdgpu-no-workitem-id-x" }
+attributes #1 = { "amdgpu-no-workitem-id-y" }
+attributes #2 = { "amdgpu-no-workitem-id-z" }
+attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

``````````

</details>


https://github.com/llvm/llvm-project/pull/191904


More information about the llvm-commits mailing list