[llvm] [SPIR-V] Fix direct return of aggregate extractvalue (PR #209762)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 07:05:46 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-spir-v

Author: Tim Besard (maleadt)

<details>
<summary>Changes</summary>

SPIRVPrepareFunctions rewrites aggregate function returns to i32 value IDs, but an aggregate extractvalue used directly by ret kept its original type, leaving invalid IR for the verifier. Mutate the lowered spv_extractv result when it feeds a rewritten return so the LLVM type matches while the registry preserves the aggregate SPIR-V type.

Closes https://github.com/llvm/llvm-project/issues/208899.
Replaces https://github.com/llvm/llvm-project/pull/209027 (that PR seems spam? although the diagnosis was largely correct)

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


2 Files Affected:

- (modified) llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp (+11-3) 
- (added) llvm/test/CodeGen/SPIRV/instructions/ret-single-element-array.ll (+18) 


``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 19e1e71488ee3..2fe8f3f831634 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2455,11 +2455,19 @@ Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
   Instruction *NewI = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_extractv,
                                                       {I.getType()}, {Args});
   replaceAllUsesWithAndErase(B, &I, NewI);
-  // If the aggregate result feeds a callsite whose aggregate params were
-  // rewritten to i32 value-ids by SPIRVPrepareFunctions, mutate it to match.
+  // If the aggregate result feeds a return or callsite whose type was rewritten
+  // to an i32 value-id by SPIRVPrepareFunctions, mutate it to match.
   if (NewI->getType()->isAggregateType()) {
     for (const Use &U : NewI->uses()) {
-      auto *CB = dyn_cast<CallBase>(U.getUser());
+      User *Usr = U.getUser();
+      if (auto *RI = dyn_cast<ReturnInst>(Usr)) {
+        if (RI->getFunction()->getReturnType() != NewI->getType()) {
+          NewI->mutateType(B.getInt32Ty());
+          break;
+        }
+        continue;
+      }
+      auto *CB = dyn_cast<CallBase>(Usr);
       if (!CB || !CB->isArgOperand(&U))
         continue;
       unsigned ArgNo = CB->getArgOperandNo(&U);
diff --git a/llvm/test/CodeGen/SPIRV/instructions/ret-single-element-array.ll b/llvm/test/CodeGen/SPIRV/instructions/ret-single-element-array.ll
new file mode 100644
index 0000000000000..fc1b7a74402d1
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/instructions/ret-single-element-array.ll
@@ -0,0 +1,18 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK-DAG: %[[#Float:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#One:]] = OpConstant %[[#]] 1
+; CHECK-DAG: %[[#Array:]] = OpTypeArray %[[#Float]] %[[#One]]
+; CHECK-DAG: %[[#Nested:]] = OpTypeArray %[[#Array]] %[[#One]]
+; CHECK: OpFunction
+; CHECK: %[[#X:]] = OpFunctionParameter %[[#Float]]
+; CHECK: %[[#NestedVal:]] = OpCompositeInsert %[[#Nested]] %[[#X]] %[[#]] 0 0
+; CHECK: %[[#Ret:]] = OpCompositeExtract %[[#Array]] %[[#NestedVal]] 0
+; CHECK: OpReturnValue %[[#Ret]]
+
+define spir_func [1 x float] @single_element_array(float %x) {
+entry:
+  %nested = insertvalue [1 x [1 x float]] zeroinitializer, float %x, 0, 0
+  %ret = extractvalue [1 x [1 x float]] %nested, 0
+  ret [1 x float] %ret
+}

``````````

</details>


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


More information about the llvm-commits mailing list