[llvm] 6c2bf97 - [AMDGPU] InstCombine: fold invalid calls to amdgcn intrinsics into poison values (#191904)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 10:52:56 PDT 2026
Author: Yoonseo Choi
Date: 2026-04-16T13:52:52-04:00
New Revision: 6c2bf97994c949da8d3252e7fcb18a6d7c70b098
URL: https://github.com/llvm/llvm-project/commit/6c2bf97994c949da8d3252e7fcb18a6d7c70b098
DIFF: https://github.com/llvm/llvm-project/commit/6c2bf97994c949da8d3252e7fcb18a6d7c70b098.diff
LOG: [AMDGPU] InstCombine: fold invalid calls to amdgcn intrinsics into poison values (#191904)
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.
Added:
llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.cluster.id.ll
llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.id.ll
llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.ptr.ll
llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.lds.kernel.id.ll
llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.queue.ptr.ll
llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workgroup.id.ll
llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workitem.id.ll
Modified:
llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 463d63a88f690..152e773d5af07 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -749,6 +749,61 @@ 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: {
+ if (!ST->hasClusters())
+ return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
+ 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..87ec11bff35a4
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.cluster.id.ll
@@ -0,0 +1,80 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 < %s | FileCheck %s --check-prefix=GFX1100
+; RUN: opt -S -passes='instcombine' -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 < %s | FileCheck %s --check-prefix=GFX1250
+
+; When amdgpu-no-cluster-id-x is set, calling the intrinsic is UB and the
+; call should be folded to poison on any target.
+define i32 @no_cluster_id_x() #0 {
+; GFX1100-LABEL: define i32 @no_cluster_id_x(
+; GFX1100-SAME: ) #[[ATTR0:[0-9]+]] {
+; GFX1100-NEXT: [[ENTRY:.*:]]
+; GFX1100-NEXT: ret i32 poison
+;
+; GFX1250-LABEL: define i32 @no_cluster_id_x(
+; GFX1250-SAME: ) #[[ATTR0:[0-9]+]] {
+; GFX1250-NEXT: [[ENTRY:.*:]]
+; GFX1250-NEXT: ret i32 poison
+;
+entry:
+ %tmp = call i32 @llvm.amdgcn.cluster.id.x()
+ ret i32 %tmp
+}
+
+define i32 @no_cluster_id_y() #1 {
+; GFX1100-LABEL: define i32 @no_cluster_id_y(
+; GFX1100-SAME: ) #[[ATTR1:[0-9]+]] {
+; GFX1100-NEXT: [[ENTRY:.*:]]
+; GFX1100-NEXT: ret i32 poison
+;
+; GFX1250-LABEL: define i32 @no_cluster_id_y(
+; GFX1250-SAME: ) #[[ATTR1:[0-9]+]] {
+; GFX1250-NEXT: [[ENTRY:.*:]]
+; GFX1250-NEXT: ret i32 poison
+;
+entry:
+ %tmp = call i32 @llvm.amdgcn.cluster.id.y()
+ ret i32 %tmp
+}
+
+define i32 @no_cluster_id_z() #2 {
+; GFX1100-LABEL: define i32 @no_cluster_id_z(
+; GFX1100-SAME: ) #[[ATTR2:[0-9]+]] {
+; GFX1100-NEXT: [[ENTRY:.*:]]
+; GFX1100-NEXT: ret i32 poison
+;
+; GFX1250-LABEL: define i32 @no_cluster_id_z(
+; GFX1250-SAME: ) #[[ATTR2:[0-9]+]] {
+; GFX1250-NEXT: [[ENTRY:.*:]]
+; GFX1250-NEXT: ret i32 poison
+;
+entry:
+ %tmp = call i32 @llvm.amdgcn.cluster.id.z()
+ ret i32 %tmp
+}
+
+; Without the attribute, the call folds to poison on targets without the
+; cluster feature (gfx1100), but is kept on cluster-capable targets (gfx1250).
+define i32 @cluster_id_x_no_attr() {
+; GFX1100-LABEL: define i32 @cluster_id_x_no_attr(
+; GFX1100-SAME: ) #[[ATTR3:[0-9]+]] {
+; GFX1100-NEXT: [[ENTRY:.*:]]
+; GFX1100-NEXT: ret i32 poison
+;
+; GFX1250-LABEL: define i32 @cluster_id_x_no_attr(
+; GFX1250-SAME: ) #[[ATTR3:[0-9]+]] {
+; GFX1250-NEXT: [[ENTRY:.*:]]
+; GFX1250-NEXT: [[TMP:%.*]] = call i32 @llvm.amdgcn.cluster.id.x()
+; GFX1250-NEXT: ret i32 [[TMP]]
+;
+entry:
+ %tmp = call i32 @llvm.amdgcn.cluster.id.x()
+ ret i32 %tmp
+}
+
+declare i32 @llvm.amdgcn.cluster.id.x()
+declare i32 @llvm.amdgcn.cluster.id.y()
+declare i32 @llvm.amdgcn.cluster.id.z()
+
+attributes #0 = { "amdgpu-no-cluster-id-x" }
+attributes #1 = { "amdgpu-no-cluster-id-y" }
+attributes #2 = { "amdgpu-no-cluster-id-z" }
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..d55beb67ca822
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.id.ll
@@ -0,0 +1,32 @@
+; 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()
+
+attributes #0 = { "amdgpu-no-dispatch-id" }
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..74cd63be6c706
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dispatch.ptr.ll
@@ -0,0 +1,48 @@
+; 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()
+
+attributes #0 = { "amdgpu-no-dispatch-ptr" }
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..c699b21c802f4
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.lds.kernel.id.ll
@@ -0,0 +1,32 @@
+; 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()
+
+attributes #0 = { "amdgpu-no-lds-kernel-id" }
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..013e70e0b38d8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.queue.ptr.ll
@@ -0,0 +1,48 @@
+; 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()
+
+attributes #0 = { "amdgpu-no-queue-ptr" }
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..34efd980c3e30
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workgroup.id.ll
@@ -0,0 +1,57 @@
+; 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()
+declare i32 @llvm.amdgcn.workgroup.id.y()
+declare i32 @llvm.amdgcn.workgroup.id.z()
+
+attributes #0 = { "amdgpu-no-workgroup-id-x" }
+attributes #1 = { "amdgpu-no-workgroup-id-y" }
+attributes #2 = { "amdgpu-no-workgroup-id-z" }
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..3972b9ae8d168
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.workitem.id.ll
@@ -0,0 +1,57 @@
+; 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()
+declare i32 @llvm.amdgcn.workitem.id.y()
+declare i32 @llvm.amdgcn.workitem.id.z()
+
+attributes #0 = { "amdgpu-no-workitem-id-x" }
+attributes #1 = { "amdgpu-no-workitem-id-y" }
+attributes #2 = { "amdgpu-no-workitem-id-z" }
More information about the llvm-commits
mailing list