Skip to content

Commit

Permalink
[Backport to 18] Support SPV_INTEL_maximum_registers extension (#2344) (
Browse files Browse the repository at this point in the history
#2388)

Spec:
KhronosGroup/SPIRV-Registry#235

Co-authored-by: Viktoria Maximova <[email protected]>
  • Loading branch information
KorovinVlad and vmaksimo authored Mar 6, 2024
1 parent f8a1094 commit d970c91
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/LLVMSPIRVExtensions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ EXT(SPV_INTEL_fpga_argument_interfaces)
EXT(SPV_INTEL_fpga_latency_control)
EXT(SPV_INTEL_fp_max_error)
EXT(SPV_INTEL_cache_controls)
EXT(SPV_INTEL_maximum_registers)
42 changes: 42 additions & 0 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4306,6 +4306,48 @@ bool SPIRVToLLVM::transMetadata() {
F->setMetadata(kSPIR2MD::IntelFPGAIPInterface,
MDNode::get(*Context, InterfaceMDVec));
}
if (auto *EM = BF->getExecutionMode(ExecutionModeMaximumRegistersINTEL)) {
NamedMDNode *ExecModeMD =
M->getOrInsertNamedMetadata(kSPIRVMD::ExecutionMode);

SmallVector<Metadata *, 4> ValueVec;
ValueVec.push_back(ConstantAsMetadata::get(F));
ValueVec.push_back(
ConstantAsMetadata::get(getUInt32(M, EM->getExecutionMode())));
ValueVec.push_back(
ConstantAsMetadata::get(getUInt32(M, EM->getLiterals()[0])));
ExecModeMD->addOperand(MDNode::get(*Context, ValueVec));
}
if (auto *EM = BF->getExecutionMode(ExecutionModeMaximumRegistersIdINTEL)) {
NamedMDNode *ExecModeMD =
M->getOrInsertNamedMetadata(kSPIRVMD::ExecutionMode);

SmallVector<Metadata *, 4> ValueVec;
ValueVec.push_back(ConstantAsMetadata::get(F));
ValueVec.push_back(
ConstantAsMetadata::get(getUInt32(M, EM->getExecutionMode())));

auto *ExecOp = BF->getModule()->getValue(EM->getLiterals()[0]);
ValueVec.push_back(
MDNode::get(*Context, ConstantAsMetadata::get(cast<ConstantInt>(
transValue(ExecOp, nullptr, nullptr)))));
ExecModeMD->addOperand(MDNode::get(*Context, ValueVec));
}
if (auto *EM =
BF->getExecutionMode(ExecutionModeNamedMaximumRegistersINTEL)) {
NamedMDNode *ExecModeMD =
M->getOrInsertNamedMetadata(kSPIRVMD::ExecutionMode);

SmallVector<Metadata *, 4> ValueVec;
ValueVec.push_back(ConstantAsMetadata::get(F));
ValueVec.push_back(
ConstantAsMetadata::get(getUInt32(M, EM->getExecutionMode())));

assert(EM->getLiterals()[0] == 0 &&
"Invalid named maximum number of registers");
ValueVec.push_back(MDString::get(*Context, "AutoINTEL"));
ExecModeMD->addOperand(MDNode::get(*Context, ValueVec));
}
}
NamedMDNode *MemoryModelMD =
M->getOrInsertNamedMetadata(kSPIRVMD::MemoryModel);
Expand Down
37 changes: 36 additions & 1 deletion lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,10 @@ SPIRVFunction *LLVMToSPIRVBase::transFunctionDecl(Function *F) {

transFPGAFunctionMetadata(BF, F);

transFunctionMetadataAsUserSemanticDecoration(BF, F);
if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_maximum_registers))
transFunctionMetadataAsExecutionMode(BF, F);
else
transFunctionMetadataAsUserSemanticDecoration(BF, F);

transAuxDataInst(BF, F);

Expand Down Expand Up @@ -1118,6 +1121,38 @@ void LLVMToSPIRVBase::transFPGAFunctionMetadata(SPIRVFunction *BF,
transMetadataDecorations(FDecoMD, BF);
}

void LLVMToSPIRVBase::transFunctionMetadataAsExecutionMode(SPIRVFunction *BF,
Function *F) {
SmallVector<MDNode *, 1> RegisterAllocModeMDs;
F->getMetadata("RegisterAllocMode", RegisterAllocModeMDs);

for (unsigned I = 0; I < RegisterAllocModeMDs.size(); I++) {
auto *RegisterAllocMode = RegisterAllocModeMDs[I]->getOperand(0).get();
if (isa<MDString>(RegisterAllocMode)) {
StringRef Str = getMDOperandAsString(RegisterAllocModeMDs[I], 0);
NamedMaximumNumberOfRegisters NamedValue =
SPIRVNamedMaximumNumberOfRegistersNameMap::rmap(Str.str());
BF->addExecutionMode(BM->add(new SPIRVExecutionMode(
OpExecutionMode, BF, ExecutionModeNamedMaximumRegistersINTEL,
NamedValue)));
} else if (isa<MDNode>(RegisterAllocMode)) {
auto *RegisterAllocNodeMDOp =
getMDOperandAsMDNode(RegisterAllocModeMDs[I], 0);
int Num = getMDOperandAsInt(RegisterAllocNodeMDOp, 0);
auto *Const =
BM->addConstant(transType(Type::getInt32Ty(F->getContext())), Num);
BF->addExecutionMode(BM->add(new SPIRVExecutionModeId(
BF, ExecutionModeMaximumRegistersIdINTEL, Const->getId())));
} else {
int64_t RegisterAllocVal =
mdconst::dyn_extract<ConstantInt>(RegisterAllocMode)->getZExtValue();
BF->addExecutionMode(BM->add(new SPIRVExecutionMode(
OpExecutionMode, BF, ExecutionModeMaximumRegistersINTEL,
RegisterAllocVal)));
}
}
}

void LLVMToSPIRVBase::transFunctionMetadataAsUserSemanticDecoration(
SPIRVFunction *BF, Function *F) {
if (auto *RegisterAllocModeMD = F->getMetadata("RegisterAllocMode")) {
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/SPIRVWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class LLVMToSPIRVBase : protected BuiltinCallHelper {
SPIRVFunction *transFunctionDecl(Function *F);
void transVectorComputeMetadata(Function *F);
void transFPGAFunctionMetadata(SPIRVFunction *BF, Function *F);
void transFunctionMetadataAsExecutionMode(SPIRVFunction *BF, Function *F);
void transFunctionMetadataAsUserSemanticDecoration(SPIRVFunction *BF,
Function *F);
void transAuxDataInst(SPIRVFunction *BF, Function *F);
Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,9 @@ void SPIRVExecutionMode::decode(std::istream &I) {
case ExecutionModeSchedulerTargetFmaxMhzINTEL:
case ExecutionModeRegisterMapInterfaceINTEL:
case ExecutionModeStreamingInterfaceINTEL:
case ExecutionModeMaximumRegistersINTEL:
case ExecutionModeMaximumRegistersIdINTEL:
case ExecutionModeNamedMaximumRegistersINTEL:
WordLiterals.resize(1);
break;
default:
Expand Down
19 changes: 18 additions & 1 deletion lib/SPIRV/libSPIRV/SPIRVEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,17 @@ class SPIRVExecutionMode : public SPIRVAnnotation {
}
}

std::optional<ExtensionID> getRequiredExtension() const override {
switch (static_cast<unsigned>(ExecMode)) {
case ExecutionModeMaximumRegistersINTEL:
case ExecutionModeMaximumRegistersIdINTEL:
case ExecutionModeNamedMaximumRegistersINTEL:
return ExtensionID::SPV_INTEL_maximum_registers;
default:
return {};
}
}

protected:
_SPIRV_DCL_ENCDEC
SPIRVExecutionModeKind ExecMode;
Expand Down Expand Up @@ -757,6 +768,11 @@ class SPIRVComponentExecutionModes {
return IsDenorm(EMK) || IsRoundingMode(EMK) || IsFPMode(EMK) ||
IsOtherFP(EMK);
};
auto IsMaxRegisters = [&](auto EMK) {
return EMK == ExecutionModeMaximumRegistersINTEL ||
EMK == ExecutionModeMaximumRegistersIdINTEL ||
EMK == ExecutionModeNamedMaximumRegistersINTEL;
};
auto IsCompatible = [&](SPIRVExecutionMode *EM0, SPIRVExecutionMode *EM1) {
if (EM0->getTargetId() != EM1->getTargetId())
return true;
Expand All @@ -770,7 +786,8 @@ class SPIRVComponentExecutionModes {
return true;
return !(IsDenorm(EMK0) && IsDenorm(EMK1)) &&
!(IsRoundingMode(EMK0) && IsRoundingMode(EMK1)) &&
!(IsFPMode(EMK0) && IsFPMode(EMK1));
!(IsFPMode(EMK0) && IsFPMode(EMK1)) &&
!(IsMaxRegisters(EMK0) && IsMaxRegisters(EMK1));
};
for (auto I = ExecModes.begin(); I != ExecModes.end(); ++I) {
assert(IsCompatible(ExecMode, (*I).second) &&
Expand Down
6 changes: 6 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ template <> inline void SPIRVMap<SPIRVExecutionModeKind, SPIRVCapVec>::init() {
{CapabilityFPGAKernelAttributesINTEL});
ADD_VEC_INIT(ExecutionModeNamedBarrierCountINTEL,
{CapabilityVectorComputeINTEL});
ADD_VEC_INIT(ExecutionModeMaximumRegistersINTEL,
{CapabilityRegisterLimitsINTEL});
ADD_VEC_INIT(ExecutionModeMaximumRegistersIdINTEL,
{CapabilityRegisterLimitsINTEL});
ADD_VEC_INIT(ExecutionModeNamedMaximumRegistersINTEL,
{CapabilityRegisterLimitsINTEL});
}

template <> inline void SPIRVMap<SPIRVMemoryModelKind, SPIRVCapVec>::init() {
Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ inline bool isValid(spv::ExecutionModel V) {
case ExecutionModelCallableKHR:
case ExecutionModeRegisterMapInterfaceINTEL:
case ExecutionModeStreamingInterfaceINTEL:
case ExecutionModeMaximumRegistersINTEL:
case ExecutionModeMaximumRegistersIdINTEL:
case ExecutionModeNamedMaximumRegistersINTEL:
return true;
default:
return false;
Expand Down
8 changes: 8 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
add(CapabilityFPGAArgumentInterfacesINTEL, "FPGAArgumentInterfacesINTEL");
add(CapabilityFPGALatencyControlINTEL, "FPGALatencyControlINTEL");
add(CapabilityFPMaxErrorINTEL, "FPMaxErrorINTEL");
add(CapabilityRegisterLimitsINTEL, "RegisterLimitsINTEL");
// From spirv_internal.hpp
add(internal::CapabilityFastCompositeINTEL, "FastCompositeINTEL");
add(internal::CapabilityOptNoneINTEL, "OptNoneINTEL");
Expand Down Expand Up @@ -691,6 +692,13 @@ template <> inline void SPIRVMap<HostAccessQualifier, std::string>::init() {
}
SPIRV_DEF_NAMEMAP(HostAccessQualifier, SPIRVHostAccessQualifierNameMap)

template <>
inline void SPIRVMap<NamedMaximumNumberOfRegisters, std::string>::init() {
add(NamedMaximumNumberOfRegistersAutoINTEL, "AutoINTEL");
}
SPIRV_DEF_NAMEMAP(NamedMaximumNumberOfRegisters,
SPIRVNamedMaximumNumberOfRegistersNameMap);

} /* namespace SPIRV */

#endif // SPIRV_LIBSPIRV_SPIRVNAMEMAPENUM_H
1 change: 1 addition & 0 deletions lib/SPIRV/libSPIRV/SPIRVStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ SPIRV_DEF_ENCDEC(SPIRVDebugExtOpKind)
SPIRV_DEF_ENCDEC(NonSemanticAuxDataOpKind)
SPIRV_DEF_ENCDEC(InitializationModeQualifier)
SPIRV_DEF_ENCDEC(HostAccessQualifier)
SPIRV_DEF_ENCDEC(NamedMaximumNumberOfRegisters)
SPIRV_DEF_ENCDEC(LinkageType)

// Read a string with padded 0's at the end so that they form a stream of
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/libSPIRV/SPIRVStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ SPIRV_DEC_ENCDEC(SPIRVDebugExtOpKind)
SPIRV_DEC_ENCDEC(NonSemanticAuxDataOpKind)
SPIRV_DEC_ENCDEC(InitializationModeQualifier)
SPIRV_DEC_ENCDEC(HostAccessQualifier)
SPIRV_DEC_ENCDEC(NamedMaximumNumberOfRegisters)
SPIRV_DEC_ENCDEC(LinkageType)

const SPIRVEncoder &operator<<(const SPIRVEncoder &O, const std::string &Str);
Expand Down
2 changes: 1 addition & 1 deletion spirv-headers-tag.conf
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1c6bb2743599e6eb6f37b2969acc0aef812e32e3
b73e168ca5e123dcf3dea8a34b19a5130f421ae1
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
; RUN: llvm-as %s -o %t.bc
; RUN: llvm-spirv -spirv-text --spirv-ext=+SPV_INTEL_maximum_registers %t.bc
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_maximum_registers -o %t.spv
; RUN: llvm-spirv -r %t.spv -spirv-target-env=SPV-IR -o - | llvm-dis -o %t.rev.ll
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM

; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC0:]] "main_l3"
; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC1:]] "main_l6"
; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC2:]] "main_l9"
; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC3:]] "main_l13"
; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC4:]] "main_l19"

; CHECK-SPIRV: ExecutionMode [[#FUNC0]] 6461 2
; CHECK-SPIRV: ExecutionMode [[#FUNC1]] 6461 1
; CHECK-SPIRV: ExecutionMode [[#FUNC2]] 6463 0
; CHECK-SPIRV: ExecutionModeId [[#FUNC3]] 6462 [[#Const3:]]
; CHECK-SPIRV: TypeInt [[#TypeInt:]] 32 0
; CHECK-SPIRV: Constant [[#TypeInt]] [[#Const3]] 3

; CHECK-SPIRV-NOT: ExecutionMode [[#FUNC4]]

; CHECK-LLVM: !spirv.ExecutionMode = !{![[#FLAG0:]], ![[#FLAG1:]], ![[#FLAG2:]], ![[#FLAG3:]]}
; CHECK-LLVM: ![[#FLAG0]] = !{ptr @main_l3, i32 6461, i32 2}
; CHECK-LLVM: ![[#FLAG1]] = !{ptr @main_l6, i32 6461, i32 1}
; CHECK-LLVM: ![[#FLAG2]] = !{ptr @main_l9, i32 6463, !"AutoINTEL"}
; CHECK-LLVM: ![[#FLAG3]] = !{ptr @main_l13, i32 6462, ![[#VAL:]]}
; CHECK-LLVM: ![[#VAL]] = !{i32 3}

target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
target triple = "spir64"

; Function Attrs: noinline nounwind optnone
define weak dso_local spir_kernel void @main_l3() #0 !RegisterAllocMode !10 {
newFuncRoot:
ret void
}

; Function Attrs: noinline nounwind optnone
define weak dso_local spir_kernel void @main_l6() #0 !RegisterAllocMode !11 {
newFuncRoot:
ret void
}

; Function Attrs: noinline nounwind optnone
define weak dso_local spir_kernel void @main_l9() #0 !RegisterAllocMode !12 {
newFuncRoot:
ret void
}

; Function Attrs: noinline nounwind optnone
define weak dso_local spir_kernel void @main_l13() #0 !RegisterAllocMode !13 {
newFuncRoot:
ret void
}

; Function Attrs: noinline nounwind optnone
define weak dso_local spir_kernel void @main_l19() #0 {
newFuncRoot:
ret void
}

attributes #0 = { noinline nounwind optnone }


!opencl.compiler.options = !{!0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0}
!spirv.Source = !{!2, !3, !3, !3, !3, !3, !2, !3, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2}
!llvm.module.flags = !{!4, !5, !6, !7, !8}
!spirv.MemoryModel = !{!9, !9, !9, !9, !9, !9}
!spirv.ExecutionMode = !{}

!0 = !{}
!2 = !{i32 4, i32 200000}
!3 = !{i32 3, i32 200000}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 7, !"openmp", i32 50}
!6 = !{i32 7, !"openmp-device", i32 50}
!7 = !{i32 8, !"PIC Level", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = !{i32 2, i32 2}
!10 = !{i32 2}
!11 = !{i32 1}
!12 = !{!"AutoINTEL"}
!13 = !{!14}
!14 = !{i32 3}

0 comments on commit d970c91

Please sign in to comment.