Skip to content
Merged
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
4 changes: 4 additions & 0 deletions llvm/docs/SPIRVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,10 @@ SPIR-V backend, along with their descriptions and argument details.
- 32-bit Integer
- `[32-bit Integer]`
- Retrieves the thread ID within a workgroup. Essential for identifying execution context in parallel compute operations.
* - `int_spv_flattened_thread_id_in_group`
- 32-bit Integer
- `[32-bit Integer]`
- Provides a flattened index for a given thread within a given group (SV_GroupIndex)
* - `int_spv_create_handle`
- Pointer
- `[8-bit Integer]`
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/IntrinsicsSPIRV.td
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ let TargetPrefix = "spv" in {
def int_spv_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
def int_spv_group_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
def int_spv_thread_id_in_group : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
def int_spv_flattened_thread_id_in_group : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrWillReturn]>;
def int_spv_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>;
def int_spv_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>;
def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
Expand Down
46 changes: 46 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool loadVec3BuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
bool loadBuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
bool loadHandleBeforePosition(Register &HandleReg, const SPIRVType *ResType,
GIntrinsic &HandleDef, MachineInstr &Pos) const;
};
Expand Down Expand Up @@ -3059,6 +3062,15 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
// builtin variable
return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupId, ResVReg, ResType,
I);
case Intrinsic::spv_flattened_thread_id_in_group:
// The HLSL SV_GroupIndex semantic is lowered to
// llvm.spv.flattened.thread.id.in.group() intrinsic in LLVM IR for SPIR-V
// backend.
//
// In SPIR-V backend, llvm.spv.flattened.thread.id.in.group is translated to
// a `LocalInvocationIndex` builtin variable
return loadBuiltinInputID(SPIRV::BuiltIn::LocalInvocationIndex, ResVReg,
ResType, I);
case Intrinsic::spv_fdot:
return selectFloatDot(ResVReg, ResType, I);
case Intrinsic::spv_udot:
Expand Down Expand Up @@ -4005,6 +4017,40 @@ bool SPIRVInstructionSelector::loadVec3BuiltinInputID(
return Result && MIB.constrainAllUses(TII, TRI, RBI);
}

// Generate the instructions to load 32-bit integer builtin input IDs/Indices.
// Like LocalInvocationIndex
bool SPIRVInstructionSelector::loadBuiltinInputID(
SPIRV::BuiltIn::BuiltIn BuiltInValue, Register ResVReg,
const SPIRVType *ResType, MachineInstr &I) const {
MachineIRBuilder MIRBuilder(I);
const SPIRVType *PtrType = GR.getOrCreateSPIRVPointerType(
ResType, MIRBuilder, SPIRV::StorageClass::Input);

// Create new register for the input ID builtin variable.
Register NewRegister =
MIRBuilder.getMRI()->createVirtualRegister(GR.getRegClass(PtrType));
MIRBuilder.getMRI()->setType(
NewRegister,
LLT::pointer(storageClassToAddressSpace(SPIRV::StorageClass::Input),
GR.getPointerSize()));
GR.assignSPIRVTypeToVReg(PtrType, NewRegister, MIRBuilder.getMF());

// Build global variable with the necessary decorations for the input ID
// builtin variable.
Register Variable = GR.buildGlobalVariable(
NewRegister, PtrType, getLinkStringForBuiltIn(BuiltInValue), nullptr,
SPIRV::StorageClass::Input, nullptr, true, true,
SPIRV::LinkageType::Import, MIRBuilder, false);
Comment on lines +4040 to +4043
Copy link
Contributor

Choose a reason for hiding this comment

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

Changing this to false will build a variable without any linkage attribute.

Suggested change
Register Variable = GR.buildGlobalVariable(
NewRegister, PtrType, getLinkStringForBuiltIn(BuiltInValue), nullptr,
SPIRV::StorageClass::Input, nullptr, true, true,
SPIRV::LinkageType::Import, MIRBuilder, false);
Register Variable = GR.buildGlobalVariable(
NewRegister, PtrType, getLinkStringForBuiltIn(BuiltInValue), nullptr,
SPIRV::StorageClass::Input, nullptr, true, false,
SPIRV::LinkageType::Import, MIRBuilder, false);


// Load uint value from the global variable.
auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpLoad))
.addDef(ResVReg)
.addUse(GR.getSPIRVTypeID(ResType))
.addUse(Variable);

return MIB.constrainAllUses(TII, TRI, RBI);
}

SPIRVType *SPIRVInstructionSelector::widenTypeToVec4(const SPIRVType *Type,
MachineInstr &I) const {
MachineIRBuilder MIRBuilder(I);
Expand Down
32 changes: 32 additions & 0 deletions llvm/test/CodeGen/SPIRV/hlsl-intrinsics/SV_GroupIndex.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-unknown %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}

; CHECK-DAG: %[[#int:]] = OpTypeInt 32 0
; CHECK-DAG: %[[#ptr_Input_int:]] = OpTypePointer Input %[[#int]]
; CHECK-DAG: %[[#LocalInvocationIndex:]] = OpVariable %[[#ptr_Input_int]] Input

; CHECK-DAG: OpEntryPoint GLCompute {{.*}} %[[#LocalInvocationIndex]]
; CHECK-DAG: OpName %[[#LocalInvocationIndex]] "__spirv_BuiltInLocalInvocationIndex"
; CHECK-DAG: OpDecorate %[[#LocalInvocationIndex]] LinkageAttributes "__spirv_BuiltInLocalInvocationIndex" Import
; CHECK-DAG: OpDecorate %[[#LocalInvocationIndex]] BuiltIn LocalInvocationIndex

target triple = "spirv-unknown-vulkan-library"

declare void @local_index_user(i32)

; Function Attrs: convergent noinline norecurse
define void @main() #1 {
entry:

; CHECK: %[[#load:]] = OpLoad %[[#int]] %[[#LocalInvocationIndex]]
%1 = call i32 @llvm.spv.flattened.thread.id.in.group()

call spir_func void @local_index_user(i32 %1)
ret void
}

; Function Attrs: nounwind willreturn memory(none)
declare i32 @llvm.spv.flattened.thread.id.in.group() #3

attributes #1 = { convergent noinline norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
attributes #3 = { nounwind willreturn memory(none) }