[all-commits] [llvm/llvm-project] e16c73: [SPIRV] Expand aggregate instructions with mutated...

Nick Sarnie via All-commits all-commits at lists.llvm.org
Tue Jul 7 07:11:14 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: e16c737a52fa9c5144299282f4da519e898af2a5
      https://github.com/llvm/llvm-project/commit/e16c737a52fa9c5144299282f4da519e898af2a5
  Author: Nick Sarnie <nick.sarnie at intel.com>
  Date:   2026-07-07 (Tue, 07 Jul 2026)

  Changed paths:
    M llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
    A llvm/test/CodeGen/SPIRV/instructions/phi-aggregate-call.ll
    A llvm/test/CodeGen/SPIRV/instructions/phi-aggregate-with-overflow-zeroinitializer.ll
    A llvm/test/CodeGen/SPIRV/instructions/phi-aggregate-with-overflow.ll
    A llvm/test/CodeGen/SPIRV/instructions/select-freeze-aggregate-with-overflow.ll

  Log Message:
  -----------
  [SPIRV] Expand aggregate instructions with mutated-type uses (#206835)

This is a workaround for the problem in GH issue
https://github.com/llvm/llvm-project/issues/203586.

The problem is that we need to mutate aggregate-typed PHI nodes to
`i32`, however that means all incoming values need to have a matching
type, but we can't always easily mutate the incoming types to i32, as in
the case in the GH issue with a math intrinsic that returns a struct
by-value.

We do the same mutation for some other cases like `freeze`, the
workaround is the same.

The workaround is to expand the incoming values to a form that will also
be mutated to i32 so the types match. An example transformation is
below:

Before
```
...
bb1:                                              ; preds = %entry
  %0 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
  br label %epilog
...
  %2 = phi { i64, i1 } [ %1, %bb0 ], [ %0, %bb1 ]
```

After
```
...
bb1:                                              ; preds = %entry
  %0 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
  %1 = extractvalue { i64, i1 } %0, 0
  %2 = insertvalue { i64, i1 } poison, i64 %1, 0
  %3 = extractvalue { i64, i1 } %0, 1
  %4 = insertvalue { i64, i1 } %2, i1 %3, 1
  br label %epilog
...
  %10 = phi { i64, i1 } [ %9, %bb0 ], [ %4, %bb1 ]
```

`insertvalue` get replaced with a SPIR-V intrinsic later in the pass
which is also type-mutated, so the IR is correct:

```
...
bb1:                                              ; preds = %entry
  %0 = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
  call void @llvm.spv.value.md(metadata !0)
  call void (...) @llvm.fake.use({ i64, i1 } %0)
  %1 = extractvalue { i64, i1 } %0, 0
  call void @llvm.spv.assign.type.i64(i64 %1, metadata i64 poison)
  call void @llvm.spv.assign.type.i32(i32 undef, metadata { i64, i1 } poison)
  %2 = call i32 (i32, i64, ...) @llvm.spv.insertv.i64(i32 undef, i64 %1, i32 0)
  call void @llvm.spv.assign.type.i32(i32 %2, metadata { i64, i1 } poison)
  %3 = extractvalue { i64, i1 } %0, 1
  call void @llvm.spv.assign.type.i1(i1 %3, metadata i1 poison)
  %4 = call i32 (i32, i1, ...) @llvm.spv.insertv.i1(i32 %2, i1 %3, i32 1)
  call void @llvm.spv.assign.type.i32(i32 %4, metadata { i64, i1 } poison)
  br label %epilog
...
  %10 = phi i32 [ %9, %bb0 ], [ %4, %bb1 ]
```

This is the simplest change I could come up with, my other ideas were
much more complicated and/or risky.

This fix is important for us because this pattern comes up in libc's
implementation on FMA, so this is blocking SPIR-V libc support.

Fixes: https://github.com/llvm/llvm-project/issues/203586

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply at anthropic.com>

Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply at anthropic.com>



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list