[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