[llvm] cd459f2 - [SPIRV] Split wide shader PHIs before applying explicit supported types (#213806)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 4 13:47:26 PDT 2026
Author: Farzon Lotfi
Date: 2026-08-04T16:47:21-04:00
New Revision: cd459f2466e408ebf9dcd455c58a43952d6a5903
URL: https://github.com/llvm/llvm-project/commit/cd459f2466e408ebf9dcd455c58a43952d6a5903
DIFF: https://github.com/llvm/llvm-project/commit/cd459f2466e408ebf9dcd455c58a43952d6a5903.diff
LOG: [SPIRV] Split wide shader PHIs before applying explicit supported types (#213806)
fixes #213802
Apply the maximum-vector-size rule before the explicit PHI legality
rules for type. This way if we see a size 16 vector we split it
beforehand.
In more precise words this preserves existing legality rules while
ensuring shader PHIs wider than four lanes are split first.
Assisted by Copilot (GPT 5.6 Sol)
Added:
Modified:
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
llvm/test/CodeGen/SPIRV/instructions/phi-large-vector-shader.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 75ac58447f8a6..0c7320e91ee5f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -165,18 +165,18 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
HasArbitraryPrecisionInts ||
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions) ||
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4);
- auto extendedScalarsAndVectors =
+ auto ExtendedScalarsAndVectors =
[IsExtendedInts](const LegalityQuery &Query) {
const LLT Ty = Query.Types[0];
return IsExtendedInts && Ty.isValid() && !Ty.isPointerOrPointerVector();
};
- auto extendedScalarsAndVectorsProduct = [IsExtendedInts](
+ auto ExtendedScalarsAndVectorsProduct = [IsExtendedInts](
const LegalityQuery &Query) {
const LLT Ty1 = Query.Types[0], Ty2 = Query.Types[1];
return IsExtendedInts && Ty1.isValid() && Ty2.isValid() &&
!Ty1.isPointerOrPointerVector() && !Ty2.isPointerOrPointerVector();
};
- auto extendedPtrsScalarsAndVectors =
+ auto ExtendedPtrsScalarsAndVectors =
[IsExtendedInts](const LegalityQuery &Query) {
const LLT Ty = Query.Types[0];
return IsExtendedInts && Ty.isValid();
@@ -331,7 +331,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
G_BITREVERSE, G_SADDSAT, G_UADDSAT, G_SSUBSAT,
G_USUBSAT, G_SCMP, G_UCMP})
.legalFor(allIntScalarsAndVectors)
- .legalIf(extendedScalarsAndVectors);
+ .legalIf(ExtendedScalarsAndVectors);
getActionDefinitionsBuilder({G_SSHLSAT, G_USHLSAT}).lower();
@@ -352,11 +352,11 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
getActionDefinitionsBuilder(G_CTPOP)
.legalForCartesianProduct(allIntScalarsAndVectors)
- .legalIf(extendedScalarsAndVectorsProduct);
+ .legalIf(ExtendedScalarsAndVectorsProduct);
getActionDefinitionsBuilder({G_TRUNC, G_ZEXT, G_SEXT, G_ANYEXT})
.legalForCartesianProduct(allScalarsAndVectors)
- .legalIf(extendedScalarsAndVectorsProduct)
+ .legalIf(ExtendedScalarsAndVectorsProduct)
.moreElementsToNextPow2(0)
.fewerElementsIf(vectorElementCountIsGreaterThan(0, MaxVectorSize),
LegalizeMutations::changeElementCountTo(
@@ -370,12 +370,12 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
.lower();
getActionDefinitionsBuilder(G_PHI)
- .legalFor(allPtrsScalarsAndVectors)
- .legalIf(extendedPtrsScalarsAndVectors)
- .moreElementsToNextPow2(0)
.fewerElementsIf(vectorElementCountIsGreaterThan(0, MaxVectorSize),
LegalizeMutations::changeElementCountTo(
- 0, ElementCount::getFixed(MaxVectorSize)));
+ 0, ElementCount::getFixed(MaxVectorSize)))
+ .legalFor(allPtrsScalarsAndVectors)
+ .legalIf(ExtendedPtrsScalarsAndVectors)
+ .moreElementsToNextPow2(0);
getActionDefinitionsBuilder(G_BITCAST).legalIf(
all(typeInSet(0, allPtrsScalarsAndVectors),
diff --git a/llvm/test/CodeGen/SPIRV/instructions/phi-large-vector-shader.ll b/llvm/test/CodeGen/SPIRV/instructions/phi-large-vector-shader.ll
index 434cab6f4a88c..9520164f012c1 100644
--- a/llvm/test/CodeGen/SPIRV/instructions/phi-large-vector-shader.ll
+++ b/llvm/test/CodeGen/SPIRV/instructions/phi-large-vector-shader.ll
@@ -1,25 +1,33 @@
; RUN: llc -O0 -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
; In Shader execution models the SPIR-V max vector size is 4, so a G_PHI on
; a wider vector must be split into multiple PHIs of width 4.
+; Unlike the 32 element case, the 16 case is listed as a legal type by the
+; backend, so it must be split before applying the explicit legality rules.
; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0
; CHECK-DAG: %[[#V4:]] = OpTypeVector %[[#I32]] 4
-; CHECK-COUNT-8: %[[#PHI:]] = OpPhi %[[#V4]]
-; CHECK: OpCompositeExtract %[[#I32]] %[[#PHI]]
- at A = internal addrspace(10) global [8 x <4 x i32>] zeroinitializer
- at Out = internal addrspace(10) global [8 x <4 x i32>] zeroinitializer
+ at A16 = internal addrspace(10) global [4 x <4 x i32>] zeroinitializer
+ at Out16 = internal addrspace(10) global [4 x <4 x i32>] zeroinitializer
+ at A32 = internal addrspace(10) global [8 x <4 x i32>] zeroinitializer
+ at Out32 = internal addrspace(10) global [8 x <4 x i32>] zeroinitializer
@Cond = internal addrspace(10) global i32 zeroinitializer
-define void @main() local_unnamed_addr #0 {
+; CHECK-LABEL: OpFunction %{{[0-9]+}} None %{{[0-9]+}} ; -- Begin function phi_v32
+; CHECK-COUNT-8: %[[#]] = OpPhi %[[#V4]]
+; CHECK: OpCompositeExtract %[[#I32]]
+; CHECK-NOT: OpPhi
+; CHECK: OpFunctionEnd
+
+define internal void @phi_v32() {
entry:
%c = load i32, ptr addrspace(10) @Cond
%cond = icmp ne i32 %c, 0
- %p0 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @A, i32 0, i32 0
+ %p0 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @A32, i32 0, i32 0
%a0 = load <4 x i32>, ptr addrspace(10) %p0
- %p1 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @A, i32 0, i32 1
+ %p1 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @A32, i32 0, i32 1
%a1 = load <4 x i32>, ptr addrspace(10) %p1
%ab = shufflevector <4 x i32> %a0, <4 x i32> %a1,
<8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -51,23 +59,77 @@ merge:
%s5 = shufflevector <32 x i32> %p, <32 x i32> poison, <4 x i32> <i32 20, i32 21, i32 22, i32 23>
%s6 = shufflevector <32 x i32> %p, <32 x i32> poison, <4 x i32> <i32 24, i32 25, i32 26, i32 27>
%s7 = shufflevector <32 x i32> %p, <32 x i32> poison, <4 x i32> <i32 28, i32 29, i32 30, i32 31>
- %o0 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 0
+ %o0 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 0
store <4 x i32> %s0, ptr addrspace(10) %o0
- %o1 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 1
+ %o1 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 1
store <4 x i32> %s1, ptr addrspace(10) %o1
- %o2 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 2
+ %o2 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 2
store <4 x i32> %s2, ptr addrspace(10) %o2
- %o3 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 3
+ %o3 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 3
store <4 x i32> %s3, ptr addrspace(10) %o3
- %o4 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 4
+ %o4 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 4
store <4 x i32> %s4, ptr addrspace(10) %o4
- %o5 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 5
+ %o5 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 5
store <4 x i32> %s5, ptr addrspace(10) %o5
- %o6 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 6
+ %o6 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 6
store <4 x i32> %s6, ptr addrspace(10) %o6
- %o7 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out, i32 0, i32 7
+ %o7 = getelementptr [8 x <4 x i32>], ptr addrspace(10) @Out32, i32 0, i32 7
store <4 x i32> %s7, ptr addrspace(10) %o7
ret void
}
+; CHECK-LABEL: OpFunction %{{[0-9]+}} None %{{[0-9]+}} ; -- Begin function phi_v16
+; CHECK-COUNT-4: %[[#]] = OpPhi %[[#V4]]
+; CHECK: OpCompositeExtract %[[#I32]]
+; CHECK-NOT: OpPhi
+; CHECK: OpFunctionEnd
+
+define internal void @phi_v16() {
+entry:
+ %c = load i32, ptr addrspace(10) @Cond
+ %cond = icmp ne i32 %c, 0
+ %p0 = getelementptr [4 x <4 x i32>], ptr addrspace(10) @A16, i32 0, i32 0
+ %a0 = load <4 x i32>, ptr addrspace(10) %p0
+ %p1 = getelementptr [4 x <4 x i32>], ptr addrspace(10) @A16, i32 0, i32 1
+ %a1 = load <4 x i32>, ptr addrspace(10) %p1
+ %ab = shufflevector <4 x i32> %a0, <4 x i32> %a1,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %wide_a = shufflevector <8 x i32> %ab, <8 x i32> %ab,
+ <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7,
+ i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %wide_b = shufflevector <8 x i32> %ab, <8 x i32> %ab,
+ <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15,
+ i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ br i1 %cond, label %then, label %else
+
+then:
+ br label %merge
+
+else:
+ br label %merge
+
+merge:
+ %p = phi <16 x i32> [ %wide_a, %then ], [ %wide_b, %else ]
+ %s0 = shufflevector <16 x i32> %p, <16 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %s1 = shufflevector <16 x i32> %p, <16 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %s2 = shufflevector <16 x i32> %p, <16 x i32> poison, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+ %s3 = shufflevector <16 x i32> %p, <16 x i32> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+ %o0 = getelementptr [4 x <4 x i32>], ptr addrspace(10) @Out16, i32 0, i32 0
+ store <4 x i32> %s0, ptr addrspace(10) %o0
+ %o1 = getelementptr [4 x <4 x i32>], ptr addrspace(10) @Out16, i32 0, i32 1
+ store <4 x i32> %s1, ptr addrspace(10) %o1
+ %o2 = getelementptr [4 x <4 x i32>], ptr addrspace(10) @Out16, i32 0, i32 2
+ store <4 x i32> %s2, ptr addrspace(10) %o2
+ %o3 = getelementptr [4 x <4 x i32>], ptr addrspace(10) @Out16, i32 0, i32 3
+ store <4 x i32> %s3, ptr addrspace(10) %o3
+ ret void
+}
+
+define void @main() local_unnamed_addr #0 {
+entry:
+ call void @phi_v16()
+ call void @phi_v32()
+ ret void
+}
+
attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
More information about the llvm-commits
mailing list