llvm-project
e16c737a - [SPIRV] Expand aggregate instructions with mutated-type uses (#206835)

Commit
1 day ago
[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@anthropic.com> Signed-off-by: Nick Sarnie <nick.sarnie@intel.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Parents
Loading