[llvm] [SPIR-V] Fix crash on direct aggregate return of an intrinsic call result (PR #206491)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 29 06:30:18 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Arseniy Obolenskiy (aobolensk)

<details>
<summary>Changes</summary>



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


2 Files Affected:

- (modified) llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp (+32) 
- (modified) llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll (+13) 


``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index f55e128245cd3..125ab8fcaa5e7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -283,6 +283,7 @@ class SPIRVEmitIntrinsics
   void insertSpirvDecorations(Instruction *I, IRBuilder<> &B);
   void insertConstantsForFPFastMathDefault(Module &M);
   Value *buildSpvUndefComposite(Type *AggrTy, IRBuilder<> &B);
+  void reconstructAggregateReturns(Function &Func, IRBuilder<> &B);
   void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B);
   void processParamTypes(Function *F, IRBuilder<> &B);
   void processParamTypesByFunHeader(Function *F, IRBuilder<> &B);
@@ -2679,6 +2680,36 @@ Value *SPIRVEmitIntrinsics::buildSpvUndefComposite(Type *AggrTy,
   return Composite;
 }
 
+// If a function directly returns an aggregate-typed call result,
+// the ReturnInst carries an aggregate while the function signature
+// was rewritten to i32 by SPIRVPrepareFunctions. Rebuild the return value
+// via extractvalue/insertvalue so the regular spv_extractv/spv_insertv
+// lowering produces a valid OpReturnValue.
+void SPIRVEmitIntrinsics::reconstructAggregateReturns(Function &Func,
+                                                      IRBuilder<> &B) {
+  for (BasicBlock &BB : Func) {
+    auto *RI = dyn_cast<ReturnInst>(BB.getTerminator());
+    if (!RI)
+      continue;
+    Value *RetVal = RI->getReturnValue();
+    if (!RetVal || !RetVal->getType()->isAggregateType())
+      continue;
+    if (!isa<CallBase>(RetVal))
+      continue;
+    Type *AggrTy = RetVal->getType();
+    uint64_t NumElts = isa<StructType>(AggrTy)
+                           ? cast<StructType>(AggrTy)->getNumElements()
+                           : cast<ArrayType>(AggrTy)->getNumElements();
+    B.SetInsertPoint(RI);
+    Value *Rebuilt = PoisonValue::get(AggrTy);
+    for (uint64_t I = 0; I < NumElts; ++I) {
+      Value *Elt = B.CreateExtractValue(RetVal, I);
+      Rebuilt = B.CreateInsertValue(Rebuilt, Elt, I);
+    }
+    RI->setOperand(0, Rebuilt);
+  }
+}
+
 void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
                                              IRBuilder<> &B) {
 
@@ -3599,6 +3630,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
   for (auto &GV : Func.getParent()->globals())
     processGlobalValue(GV, B);
 
+  reconstructAggregateReturns(Func, B);
   preprocessUndefsAndPoisons(B);
   simplifyNullAddrSpaceCasts();
   preprocessCompositeConstants(B);
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll
index 5827c563f3253..976936d043f5a 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll
@@ -85,3 +85,16 @@ entry:
   store <2 x i8> %zext_ofl, ptr %out_overflow
   ret void
 }
+
+; CHECK: OpFunction
+; CHECK: %[[#AR:]] = OpFunctionParameter %[[#Int]]
+; CHECK: %[[#BR:]] = OpFunctionParameter %[[#Int]]
+; CHECK: %[[#ResR:]] = OpIAdd %[[#Int]] %[[#AR]] %[[#BR]]
+; CHECK: %[[#Ins0:]] = OpCompositeInsert %[[#StructR:]] %[[#ResR]] %[[#]] 0
+; CHECK: %[[#Ins1:]] = OpCompositeInsert %[[#StructR]] %[[#]] %[[#Ins0]] 1
+; CHECK: OpReturnValue %[[#Ins1]]
+define spir_func { i32, i1 } @test_sadd_overflow_ret(i32 %a, i32 %b) {
+entry:
+  %res = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
+  ret { i32, i1 } %res
+}

``````````

</details>


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


More information about the llvm-commits mailing list