Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,9 @@ void SPIRVPassConfig::addISelPrepare() {
// If an address space cast is not removed while targeting Vulkan, lowering
// will fail during MIR lowering.
addPass(createInferAddressSpacesPass());
}

if (TM.getSubtargetImpl()->isShader() || TM.getSubtargetImpl()->isKernel()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there another valid target? Should the condition be removed instead?

Copy link
Contributor Author

@MrSidims MrSidims Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, will remove

Copy link
Contributor Author

@MrSidims MrSidims Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or actually, given there is the following PR, let me summon @AlexVlx to answer if it can break something on their end (TargetTriple.getVendor() == Triple::AMD falls under IsKernel, but still).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this does indeed cause issues, I think. We don't / cannot run passes over SPIR-V, asides from those that are absolutely necessary for successful lowering / obtaining valid SPIR-V (see #154765 for a bit more on this). We use -disable-llvm-optzns, but it'd not work here. Would it be at all possible to guard against enabling these for AMDGCNSPIRV? I.e. have the current check be replaced for a check on the vendor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me move it to draft actually. May be just implementing https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/INTEL/SPV_INTEL_unstructured_loop_controls.asciidoc is the right direction. I haven't though about it for some reasons before Nathan's comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cheers, apologies for the inconvenience.

// 1. Simplify loop for subsequent transformations. After this steps, loops
// have the following properties:
// - loops have a single entry edge (pre-header to loop header).
Expand Down
80 changes: 80 additions & 0 deletions llvm/test/CodeGen/SPIRV/structurizer/kernel-loop.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
; RUN: llc -mtriple=spirv64-unknown-opencl -O0 %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-opencl %s -o - -filetype=obj | spirv-val %}

; This test verifies that the structurizer pass runs for OpenCL kernels,
; generating structured control flow with OpLoopMerge instructions and
; translating loop metadata to appropriate LoopControl operands.

; CHECK: OpEntryPoint Kernel %[[#kernel_unroll:]] "test_kernel_unroll"
; CHECK: OpEntryPoint Kernel %[[#kernel_dontunroll:]] "test_kernel_dontunroll"

; Verify unroll metadata is translated to Unroll LoopControl
; CHECK: %[[#kernel_unroll]] = OpFunction
; CHECK: OpLabel
; CHECK: OpLoopMerge %[[#]] %[[#]] Unroll
; CHECK: OpFunctionEnd

; Verify dont_unroll metadata is translated to DontUnroll LoopControl
; CHECK: %[[#kernel_dontunroll]] = OpFunction
; CHECK: OpLabel
; CHECK: OpLoopMerge %[[#]] %[[#]] DontUnroll
; CHECK: OpFunctionEnd

define spir_kernel void @test_kernel_unroll(ptr addrspace(1) %out) {
entry:
%i = alloca i32, align 4
store i32 0, ptr %i, align 4
br label %for.cond

for.cond:
%0 = load i32, ptr %i, align 4
%cmp = icmp slt i32 %0, 10
br i1 %cmp, label %for.body, label %for.end

for.body:
%1 = load i32, ptr %i, align 4
%arrayidx = getelementptr inbounds i32, ptr addrspace(1) %out, i64 0
store i32 %1, ptr addrspace(1) %arrayidx, align 4
br label %for.inc

for.inc:
%2 = load i32, ptr %i, align 4
%inc = add nsw i32 %2, 1
store i32 %inc, ptr %i, align 4
br label %for.cond, !llvm.loop !0

for.end:
ret void
}

define spir_kernel void @test_kernel_dontunroll(ptr addrspace(1) %out) {
entry:
%i = alloca i32, align 4
store i32 0, ptr %i, align 4
br label %for.cond

for.cond:
%0 = load i32, ptr %i, align 4
%cmp = icmp slt i32 %0, 10
br i1 %cmp, label %for.body, label %for.end

for.body:
%1 = load i32, ptr %i, align 4
%arrayidx = getelementptr inbounds i32, ptr addrspace(1) %out, i64 0
store i32 %1, ptr addrspace(1) %arrayidx, align 4
br label %for.inc

for.inc:
%2 = load i32, ptr %i, align 4
%inc = add nsw i32 %2, 1
store i32 %inc, ptr %i, align 4
br label %for.cond, !llvm.loop !2

for.end:
ret void
}

!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.unroll.full"}
!2 = distinct !{!2, !3}
!3 = !{!"llvm.loop.unroll.disable"}