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

Yoonseo Choi via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 13 15:50:28 PDT 2026


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

None

>From 4ae0664abbc91b3c2ed227b910cc3ab3a970018b Mon Sep 17 00:00:00 2001
From: Yoonseo Choi <yoonchoi at amd.com>
Date: Mon, 13 Apr 2026 17:45:07 -0500
Subject: [PATCH] Fold calls to amdgcn intrinsics into poison values when
 amdgpu-no attrs exist

---
 .../AMDGPU/AMDGPUInstCombineIntrinsic.cpp     | 56 ++++++++++++++++++
 .../AMDGPU/llvm.amdgcn.cluster.id.ll          | 58 +++++++++++++++++++
 .../AMDGPU/llvm.amdgcn.dispatch.id.ll         | 33 +++++++++++
 .../AMDGPU/llvm.amdgcn.dispatch.ptr.ll        | 49 ++++++++++++++++
 .../AMDGPU/llvm.amdgcn.lds.kernel.id.ll       | 33 +++++++++++
 .../AMDGPU/llvm.amdgcn.queue.ptr.ll           | 49 ++++++++++++++++
 .../AMDGPU/llvm.amdgcn.workgroup.id.ll        | 58 +++++++++++++++++++
 .../AMDGPU/llvm.amdgcn.workitem.id.ll         | 58 +++++++++++++++++++
 8 files changed, 394 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.cluster.id.ll
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.id.ll
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.ptr.ll
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.lds.kernel.id.ll
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.queue.ptr.ll
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workgroup.id.ll
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workitem.id.ll

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 463d63a88f690..03e9a0177bb9f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -749,6 +749,62 @@ 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) }



More information about the llvm-commits mailing list