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

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 04:19:16 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: gretay-amd

<details>
<summary>Changes</summary>

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)). 


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


2 Files Affected:

- (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+5) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/preserve-callsite-attrs.ll (+29) 


``````````diff
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
new file mode 100644
index 0000000000000..1e49c668a7c5b
--- /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) #[[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
+  %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) }

``````````

</details>


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


More information about the llvm-commits mailing list