[llvm] [AMDGPU] Preserve call-site attributes rebuilding an intrinsic (PR #201549)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 04:18:42 PDT 2026


https://github.com/gretay-amd created https://github.com/llvm/llvm-project/pull/201549

This PR copies the original call-site attributes onto the new call. 

`AMDGPUCodeGenPrepare` uses `IC.Builder.CreateIntrinsic` to rebuild intrinsic calls. `CreateIntrinsic` only inherits attributes from the intrinsic declaration, and any call-site only attributes are silently dropped. 

The change is needed in both `modifyIntrinsicCall simplifications` and `simplifyAMDGCNMemoryIntrinsicDemanded`. The new test exercises both transformations firing in sequence on the same `image.sample` call. Two commits: the first adds the test that drops the attribute and then the second commit fixes the bug and the test.

This fix was originally introduced by @dstutt  in the context of waterfall intrinsics #192409, but the issue and the fix are independent (see review comment [r3348760419](https://github.com/llvm/llvm-project/pull/192409#discussion_r3348760419)). 


>From ea118ac2fcc3cdc7feb47ee7e0ff17b129a1624e Mon Sep 17 00:00:00 2001
From: Greta Yorsh <Greta.Yorsh at amd.com>
Date: Thu, 4 Jun 2026 12:06:48 +0100
Subject: [PATCH 1/2] [AMDGPU] Add test for call-site attribute preservation in
 InstCombine

Pre-commit: the CHECK lines capture current (buggy) behavior where
InstCombine's AMDGPU intrinsic rewrites drop call-site-only attributes
(here, memory(argmem: read) via #1) when rebuilding the call with
IC.Builder.CreateIntrinsic. A follow-up commit fixes the rewrites and
updates the expected output.

Assisted-by: Claude <noreply at anthropic.com>
---
 .../AMDGPU/preserve-callsite-attrs.ll         | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll

diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll b/llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll
new file mode 100644
index 0000000000000..d2c2d1f0f9b81
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll
@@ -0,0 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=instcombine -mtriple=amdgcn-amd-amdhsa %s | FileCheck %s
+
+; InstCombine runs two transforms on the same image.sample call:
+;   1. modifyIntrinsicCall: lod = 0.0 rewrites image.sample.l.1d to
+;      image.sample.lz.1d, dropping the lod operand.
+;   2. simplifyAMDGCNMemoryIntrinsicDemanded: only lanes 0 and 1 are used,
+;      so the dmask shrinks from 15 to 3 and the return type shrinks from
+;      <4 x float> to <2 x float>.
+; Each transform rebuilds the call with IC.Builder.CreateIntrinsic, which
+; would drop any call-site-only attributes (here, memory(argmem: read)
+; attached via #1). The new call is guaranteed to inherit attributes from
+; the intrinsic declaration, but not call-site attributes.
+define amdgpu_ps <2 x float> @image_l_to_lz_shrink(<8 x i32> inreg %rsrc, float %s, <4 x i32> inreg %samp) {
+; CHECK-LABEL: @image_l_to_lz_shrink(
+; CHECK-NEXT:    [[V4:%.*]] = call <2 x float> @llvm.amdgcn.image.sample.lz.1d.v2f32.f32.v8i32.v4i32(i32 3, float [[S:%.*]], <8 x i32> [[RSRC:%.*]], <4 x i32> [[SAMP:%.*]], i1 false, i32 0, i32 0)
+; CHECK-NEXT:    ret <2 x float> [[V4]]
+;
+  %v4 = call <4 x float> @llvm.amdgcn.image.sample.l.1d.v4f32.f32.v8i32.v4i32(i32 15, float %s, float 0.0, <8 x i32> %rsrc, <4 x i32> %samp, i1 false, i32 0, i32 0) #1
+  %e0 = extractelement <4 x float> %v4, i32 0
+  %e1 = extractelement <4 x float> %v4, i32 1
+  %r0 = insertelement <2 x float> poison, float %e0, i32 0
+  %r1 = insertelement <2 x float> %r0, float %e1, i32 1
+  ret <2 x float> %r1
+}
+
+declare <4 x float> @llvm.amdgcn.image.sample.l.1d.v4f32.f32.v8i32.v4i32(i32, float, float, <8 x i32>, <4 x i32>, i1, i32, i32)
+
+attributes #1 = { memory(argmem: read) }

>From 539982ea67b8eee0b5fee0c6986199eb60ee033a Mon Sep 17 00:00:00 2001
From: Greta Yorsh <Greta.Yorsh at amd.com>
Date: Thu, 4 Jun 2026 12:07:11 +0100
Subject: [PATCH 2/2] [AMDGPU] Preserve call-site attributes when InstCombine
 rebuilds an intrinsic

AMDGPUCodeGenPrepare uses IC.Builder.CreateIntrinsic to rebuild intrinsics
calls. CreateIntrinsic only inherits attributes from the intrinsic
declaration, so any call-site only attributes are silently dropped.

Copy the original AttributeList onto the new call in both helpers so
call-site attributes survive the rebuild.

The change is needed in both modifyIntrinsicCall simplifications) and
simplifyAMDGCNMemoryIntrinsicDemanded (used for example by the
demanded-elements dmask shrink).

The test update shows the added #[[ATTR1]] on the rebuilt call.

Assisted-by: Claude <noreply at anthropic.com>
---
 llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp        | 5 +++++
 .../Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 2370c379e75f5..4b5eb0ee6abd3 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -143,6 +143,9 @@ static std::optional<Instruction *> modifyIntrinsicCall(
   NewCall->copyMetadata(OldIntr);
   if (isa<FPMathOperator>(NewCall))
     NewCall->copyFastMathFlags(&OldIntr);
+  // Copy attributes
+  AttributeList OldAttrList = OldIntr.getAttributes();
+  NewCall->setAttributes(OldAttrList);
 
   // Erase and replace uses
   if (!InstToReplace.getType()->isVoidTy())
@@ -2379,6 +2382,8 @@ static Value *simplifyAMDGCNMemoryIntrinsicDemanded(InstCombiner &IC,
       IC.Builder.CreateIntrinsic(II.getIntrinsicID(), OverloadTys, Args);
   NewCall->takeName(&II);
   NewCall->copyMetadata(II);
+  AttributeList OldAttrList = II.getAttributes();
+  NewCall->setAttributes(OldAttrList);
 
   if (IsLoad) {
     if (NewNumElts == 1) {
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll b/llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll
index d2c2d1f0f9b81..1e49c668a7c5b 100644
--- a/llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll
@@ -13,7 +13,7 @@
 ; the intrinsic declaration, but not call-site attributes.
 define amdgpu_ps <2 x float> @image_l_to_lz_shrink(<8 x i32> inreg %rsrc, float %s, <4 x i32> inreg %samp) {
 ; CHECK-LABEL: @image_l_to_lz_shrink(
-; CHECK-NEXT:    [[V4:%.*]] = call <2 x float> @llvm.amdgcn.image.sample.lz.1d.v2f32.f32.v8i32.v4i32(i32 3, float [[S:%.*]], <8 x i32> [[RSRC:%.*]], <4 x i32> [[SAMP:%.*]], i1 false, i32 0, i32 0)
+; CHECK-NEXT:    [[V4:%.*]] = call <2 x float> @llvm.amdgcn.image.sample.lz.1d.v2f32.f32.v8i32.v4i32(i32 3, float [[S:%.*]], <8 x i32> [[RSRC:%.*]], <4 x i32> [[SAMP:%.*]], i1 false, i32 0, i32 0) #[[ATTR1:[0-9]+]]
 ; CHECK-NEXT:    ret <2 x float> [[V4]]
 ;
   %v4 = call <4 x float> @llvm.amdgcn.image.sample.l.1d.v4f32.f32.v8i32.v4i32(i32 15, float %s, float 0.0, <8 x i32> %rsrc, <4 x i32> %samp, i1 false, i32 0, i32 0) #1



More information about the llvm-commits mailing list