[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