[llvm] [SPIR-V] Rewrite extractvalue over aggregate spv_extractv result (PR #200065)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Thu May 28 07:29:38 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/200065

>From 6f11cfde1230a6e90a679d4de748ffbda93623c0 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 27 May 2026 23:37:13 +0200
Subject: [PATCH 1/2] [SPIR-V] Rewrite extractvalue over aggregate spv_extractv
 result

Chained extractvalue from an aggregate-returning call left raw IR over a multi-register spv_extractv, crashing later in foldImm. Mutate the producer to i32 and convert the user too
---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 10 ++++++--
 .../extractvalue-aggregate-chain.ll           | 23 +++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index b6e71c7b76348..08d80851cda8a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -2254,10 +2254,16 @@ Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) {
 }
 
 Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
-  if (I.getAggregateOperand()->getType()->isAggregateType())
-    return &I;
   IRBuilder<> B(I.getParent());
   B.SetInsertPoint(&I);
+  if (I.getAggregateOperand()->getType()->isAggregateType()) {
+    // Mutate an aggregate-returning spv_extractv producer to i32 so
+    // IRTranslator does not see a multi-register value.
+    CallBase *CB = dyn_cast<CallBase>(I.getAggregateOperand());
+    if (!CB || CB->getIntrinsicID() != Intrinsic::spv_extractv)
+      return &I;
+    CB->mutateType(B.getInt32Ty());
+  }
   SmallVector<Value *> Args(I.operands());
   for (auto &Op : I.indices())
     Args.push_back(B.getInt32(Op));
diff --git a/llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll b/llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll
new file mode 100644
index 0000000000000..64364a5d88ace
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll
@@ -0,0 +1,23 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Chained extractvalue from an aggregate-returning call used to crash in
+; foldImm because the outer extractvalue was left as raw IR over a
+; multi-register spv_extractv result.
+
+%ty = type { ptr addrspace(4), ptr addrspace(4), [8 x i8] }
+
+declare %ty @arr_ret()
+
+; CHECK: OpFunction
+; CHECK: [[AGG:%[0-9]+]] = OpFunctionCall {{%[0-9]+}} {{%[0-9]+}}
+; CHECK: [[ARR:%[0-9]+]] = OpCompositeExtract {{%[0-9]+}} [[AGG]] 2
+; CHECK: [[ELT:%[0-9]+]] = OpCompositeExtract {{%[0-9]+}} [[ARR]] 0
+; CHECK: OpStore {{%[0-9]+}} [[ELT]]
+define void @chain(ptr addrspace(4) %p) {
+  %1 = call %ty @arr_ret()
+  %2 = extractvalue %ty %1, 2
+  %3 = extractvalue [8 x i8] %2, 0
+  store i8 %3, ptr addrspace(4) %p, align 1
+  ret void
+}

>From 6755f334c77c2f9e58ca3ff998e463ecdd0454f7 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 28 May 2026 16:29:26 +0200
Subject: [PATCH 2/2] Address comments

---
 .../SPIRV/instructions/extractvalue-aggregate-chain.ll    | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll b/llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll
index 64364a5d88ace..c7391a54db12f 100644
--- a/llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll
+++ b/llvm/test/CodeGen/SPIRV/instructions/extractvalue-aggregate-chain.ll
@@ -10,10 +10,10 @@
 declare %ty @arr_ret()
 
 ; CHECK: OpFunction
-; CHECK: [[AGG:%[0-9]+]] = OpFunctionCall {{%[0-9]+}} {{%[0-9]+}}
-; CHECK: [[ARR:%[0-9]+]] = OpCompositeExtract {{%[0-9]+}} [[AGG]] 2
-; CHECK: [[ELT:%[0-9]+]] = OpCompositeExtract {{%[0-9]+}} [[ARR]] 0
-; CHECK: OpStore {{%[0-9]+}} [[ELT]]
+; CHECK: %[[#AGG:]] = OpFunctionCall %[[#]] %[[#]]
+; CHECK: %[[#ARR:]] = OpCompositeExtract %[[#]] %[[#AGG]] 2
+; CHECK: %[[#ELT:]] = OpCompositeExtract %[[#]] %[[#ARR]] 0
+; CHECK: OpStore %[[#]] %[[#ELT]]
 define void @chain(ptr addrspace(4) %p) {
   %1 = call %ty @arr_ret()
   %2 = extractvalue %ty %1, 2



More information about the llvm-commits mailing list