[llvm] [SPIR-V] Fix verifier crash on aggregate extract into a mutated callsite (PR #203729)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 13 15:01:52 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Dmitry Sidorov (MrSidims)

<details>
<summary>Changes</summary>

SPIRVPrepareFunctions rewrites indirect/inline-asm callsite signatures so aggregate params become i32 value-ids, but leaves the operands for SPIRVEmitIntrinsics to tokenize. An aggregate-returning spv_extractv result passed to such a call was never tokenized, so it no longer matched the mutated callee signature, tripping the IR verifier ("Call parameter type does not match function signature!").

Mutate the spv_extractv result to i32 when it feeds a callsite param that was rewritten to a value-id. Real SPIR-V type is recovered from the value attributes later during selection.

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


3 Files Affected:

- (modified) llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp (+16) 
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/extractvalue-aggregate-mutated-callsite-indirect.ll (+21) 
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_inline_assembly/extractvalue-aggregate-mutated-callsite-asm.ll (+21) 


``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 89b6dad3d5239..ff78983ac05f8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2409,6 +2409,22 @@ Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
   auto *NewI =
       B.CreateIntrinsic(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 (NewI->getType()->isAggregateType()) {
+    for (Use &U : NewI->uses()) {
+      auto *CB = dyn_cast<CallBase>(U.getUser());
+      if (!CB || !CB->isArgOperand(&U))
+        continue;
+      unsigned ArgNo = CB->getArgOperandNo(&U);
+      FunctionType *FT = CB->getFunctionType();
+      if (ArgNo < FT->getNumParams() &&
+          !FT->getParamType(ArgNo)->isAggregateType()) {
+        NewI->mutateType(B.getInt32Ty());
+        break;
+      }
+    }
+  }
   return NewI;
 }
 
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/extractvalue-aggregate-mutated-callsite-indirect.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/extractvalue-aggregate-mutated-callsite-indirect.ll
new file mode 100644
index 0000000000000..df533da7592be
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/extractvalue-aggregate-mutated-callsite-indirect.ll
@@ -0,0 +1,21 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s
+; TODO: add spirv-val
+
+; An aggregate extractvalue feeding an indirect call used to crash the verifier.
+
+%struct.Inner = type { float, float }
+%struct.Outer = type { %struct.Inner, %struct.Inner }
+
+; CHECK: %[[#Inner:]] = OpTypeStruct
+; CHECK: %[[#Outer:]] = OpTypeStruct %[[#Inner]] %[[#Inner]]
+; CHECK: %[[#Null:]] = OpConstantNull %[[#Outer]]
+
+; CHECK: OpFunction
+; CHECK: %[[#Field:]] = OpCompositeExtract %[[#Inner]] %[[#Null]] 1
+; CHECK: %[[#]] = OpFunctionPointerCallINTEL %[[#]] %[[#]] %[[#Field]]
+define spir_func i32 @f(ptr %fp) {
+entry:
+  %a = extractvalue %struct.Outer zeroinitializer, 1
+  %r = call spir_func i32 %fp(%struct.Inner %a)
+  ret i32 %r
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_inline_assembly/extractvalue-aggregate-mutated-callsite-asm.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_inline_assembly/extractvalue-aggregate-mutated-callsite-asm.ll
new file mode 100644
index 0000000000000..9b282eb022e07
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_inline_assembly/extractvalue-aggregate-mutated-callsite-asm.ll
@@ -0,0 +1,21 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_inline_assembly %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_inline_assembly %s -o - -filetype=obj | spirv-val %}
+
+; An aggregate extractvalue feeding an inline-asm call used to crash the verifier.
+
+%struct.Inner = type { float, float }
+%struct.Outer = type { %struct.Inner, %struct.Inner }
+
+; CHECK: %[[#Inner:]] = OpTypeStruct
+; CHECK: %[[#Outer:]] = OpTypeStruct %[[#Inner]] %[[#Inner]]
+; CHECK: %[[#Null:]] = OpConstantNull %[[#Outer]]
+
+; CHECK: OpFunction
+; CHECK: %[[#Field:]] = OpCompositeExtract %[[#Inner]] %[[#Null]] 1
+; CHECK: %[[#]] = OpAsmCallINTEL %[[#]] %[[#]] %[[#Field]]
+define i32 @f() {
+entry:
+  %a = extractvalue %struct.Outer zeroinitializer, 1
+  %r = call i32 asm sideeffect "", "=r,r"(%struct.Inner %a)
+  ret i32 %r
+}

``````````

</details>


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


More information about the llvm-commits mailing list