[llvm] [SPIR-V] Lower nested aggregate insertvalue operands (PR #204239)

Tim Besard via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 6 00:54:57 PDT 2026


================
@@ -2465,6 +2465,17 @@ SPIRVEmitIntrinsicsImpl::visitExtractValueInst(ExtractValueInst &I) {
     Args.push_back(B.getInt32(Op));
   Instruction *NewI = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_extractv,
                                                       {I.getType()}, {Args});
+  // If this aggregate extract feeds another insertvalue, the extracted
+  // composite is used as a SPIR-V value-id by llvm.spv.insertv. Keep the real
+  // aggregate type in metadata, but expose the value itself as i32 so the
+  // intrinsic signature remains valid.
+  if (NewI->getType()->isAggregateType() &&
+      any_of(I.users(), [](User *U) { return isa<InsertValueInst>(U); })) {
----------------
maleadt wrote:

Ah, I hadn't considered already-lowered intrinsics. I'm not sure simply adding `spv_insertv` here works though, since AFAIU the signature of that intrinsic would then need to be changed as well. LLM-generated example:

> Suppose the aggregate extract is the value being inserted:
> 
> ```llvm
> %e = extractvalue [1 x [1 x i64]] %outer, 0
> %i = insertvalue [1 x [1 x i64]] %base, [1 x i64] %e, 0
> ```
> 
> If the extract is lowered first, it becomes an `i32` SPIR-V value ID, and the subsequent insertion is correctly overloaded for `i32`:
> 
> ```llvm
> %e = call i32 @llvm.spv.extractv.i32(i32 %outer, i32 0)
> 
> %i = call i32 (i32, i32, ...)
>     @llvm.spv.insertv.i32(i32 %base, i32 %e, i32 0)
> ```
> 
> But if the insertion has already been lowered while `%e` still has its aggregate type, its declaration is overloaded for `[1 x i64]`:
> 
> ```llvm
> %e = extractvalue [1 x [1 x i64]] %outer, 0
> 
> %i = call i32 (i32, [1 x i64], ...)
>     @llvm.spv.insertv.a1i64(
>         i32 %base, [1 x i64] %e, i32 0)
> ```
> 
> Now `visitExtractValueInst` notices the `spv_insertv` user and mutates `%e` to `i32`. Merely replacing the operand would produce:
> 
> ```llvm
> %e = call i32 @llvm.spv.extractv.i32(i32 %outer, i32 0)
> 
> ; Invalid: the declaration expects [1 x i64], but %e is now i32.
> %i = call i32 (i32, [1 x i64], ...)
>     @llvm.spv.insertv.a1i64(
>         i32 %base, i32 %e, i32 0)
> ```
> 
> The call would also need to be retargeted:
> 
> ```llvm
> %i = call i32 (i32, i32, ...)
>     @llvm.spv.insertv.i32(
>         i32 %base, i32 %e, i32 0)
> ```

Maybe we should make it so that aggregate conversion happens before visiting insertions?

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


More information about the llvm-commits mailing list