Skip to content

Commit

Permalink
Support SPV_INTEL_maximum_registers extension
Browse files Browse the repository at this point in the history
.
  • Loading branch information
KorovinVlad authored and igcbot committed Aug 24, 2024
1 parent b0eac28 commit 69efb32
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 13 deletions.
23 changes: 23 additions & 0 deletions IGC/VectorCompiler/include/vc/Utils/GenX/KernelInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ SPDX-License-Identifier: MIT
#include "llvm/GenXIntrinsics/GenXMetadata.h"

#include <cstdint>
#include <optional>
#include <type_traits>
#include <unordered_map>

Expand Down Expand Up @@ -116,6 +117,14 @@ template <typename Ty = llvm::Value> Ty *getValueAsMetadata(llvm::Metadata *M) {
return nullptr;
}

template <typename Ty = llvm::Value>
Ty *getValueAsMetadata(const llvm::Metadata *M) {
if (auto *VM = llvm::dyn_cast<llvm::ValueAsMetadata>(M))
if (auto *V = llvm::dyn_cast<Ty>(VM->getValue()))
return V;
return nullptr;
}

// Number of barriers can only be 0, 1, 2, 4, 8, 16, 24, 32.
// Alignment here means choosing nearest overlapping legal number of barriers.
static unsigned alignBarrierCnt(unsigned BarrierCnt) {
Expand Down Expand Up @@ -178,6 +187,13 @@ class KernelMetadata {
Fixed = 4,
};

// TODO: Use SPIR-V headers.
enum class ExecutionMode {
MaximumRegistersINTEL = 6461,
MaximumRegistersIdINTEL = 6462,
NamedMaximumRegistersINTEL = 6463
};

private:
const llvm::Function *F = nullptr;
llvm::MDNode *ExternalNode = nullptr;
Expand All @@ -195,6 +211,9 @@ class KernelMetadata {
std::vector<int> BTIs;
ArgToImplicitLinearization Linearization;

// Optional SPIR-V execution mode.
std::optional<unsigned> GRFSize;

public:
// default constructor
KernelMetadata() {}
Expand All @@ -221,6 +240,8 @@ class KernelMetadata {
void updateBTIndicesMD(std::vector<int> &&BTIs);
void updateSLMSizeMD(unsigned Size);

void parseExecutionMode(llvm::MDNode *SpirvExecutionMode);

bool hasArgLinearization(llvm::Argument *Arg) const {
return Linearization.count(Arg);
}
Expand Down Expand Up @@ -269,6 +290,8 @@ class KernelMetadata {
return ArgTypeDescs[Idx];
}

std::optional<unsigned> getGRFSize() const { return GRFSize; }

enum { AK_NORMAL, AK_SAMPLER, AK_SURFACE };
RegCategory getArgCategory(unsigned Idx) const {
switch (getArgKind(Idx) & 7) {
Expand Down
34 changes: 22 additions & 12 deletions IGC/VectorCompiler/lib/GenXCodeGen/GenXCisaBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -907,10 +907,11 @@ static bool isExtOperandBaled(Use &U, const GenXBaling *Baling) {

// Args:
// HasBarrier - whether kernel has barrier or sbarrier
void addKernelAttrsFromMetadata(VISAKernel &Kernel,
const vc::KernelMetadata &KM,
const GenXSubtarget *Subtarget,
bool HasBarrier) {
static void addKernelAttrsFromMetadata(VISAKernel &Kernel,
const vc::KernelMetadata &KM,
const GenXSubtarget *Subtarget,
const GenXBackendConfig *BC,
bool HasBarrier) {
unsigned SLMSizeInKb = divideCeil(KM.getSLMSize(), 1024);
if (SLMSizeInKb > Subtarget->getMaxSlmSize())
report_fatal_error("SLM size exceeds target limits");
Expand Down Expand Up @@ -943,6 +944,21 @@ void addKernelAttrsFromMetadata(VISAKernel &Kernel,
static_cast<uint8_t>(KM.getAlignedBarrierCnt(HasBarrier));
Kernel.AddKernelAttribute("NBarrierCnt", sizeof(BarrierCnt), &BarrierCnt);
}

// Default number of registers.
unsigned NumGRF = 128;
// Set by compile option.
if (BC->isAutoLargeGRFMode())
NumGRF = 0;
if (BC->getGRFSize())
NumGRF = BC->getGRFSize();
// Set by kernel metadata.
if (KM.getGRFSize()) {
unsigned NumGRFPerKernel = *KM.getGRFSize();
if (NumGRFPerKernel == 0 || Subtarget->isValidGRFSize(NumGRFPerKernel))
NumGRF = NumGRFPerKernel;
}
Kernel.AddKernelAttribute("NumGRF", sizeof(NumGRF), &NumGRF);
}

// Legalize name for using as filename or in visa asm
Expand Down Expand Up @@ -1001,7 +1017,8 @@ void GenXKernelBuilder::runOnKernel() {
IGC_ASSERT_MESSAGE(Kernel, "Kernel initialization failed!");
LLVM_DEBUG(dbgs() << "=== PROCESS KERNEL(" << KernelName << ") ===\n");

addKernelAttrsFromMetadata(*Kernel, TheKernelMetadata, Subtarget, HasBarrier);
addKernelAttrsFromMetadata(*Kernel, TheKernelMetadata, Subtarget,
BackendConfig, HasBarrier);

// Set CM target for all functions produced by VC.
// See visa spec for CMTarget value (section 4, Kernel).
Expand Down Expand Up @@ -5818,13 +5835,6 @@ collectFinalizerArgs(StringSaver &Saver, const GenXSubtarget &ST,
if (ST.needsWANoMaskFusedEU() && !DisableNoMaskWA)
addArgument("-noMaskWA");

unsigned GRFSize = BC.getGRFSize();
if (GRFSize > 0) {
addArgument("-TotalGRFNum");
addArgument(to_string(GRFSize));
} else if (BC.isAutoLargeGRFMode())
addArgument("-autoGRFSelection");

if (ST.hasFusedEU()) {
addArgument("-fusedCallWA");
addArgument("1");
Expand Down
17 changes: 17 additions & 0 deletions IGC/VectorCompiler/lib/GenXCodeGen/GenXSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ SPDX-License-Identifier: MIT
#include "Probe/Assertion.h"
#include "common/StringMacros.hpp"

#include <unordered_set>

using namespace llvm;

#define DEBUG_TYPE "subtarget"
Expand Down Expand Up @@ -274,3 +276,18 @@ bool GenXSubtarget::isInternalIntrinsicSupported(unsigned ID) const {

return true;
}

bool GenXSubtarget::isValidGRFSize(unsigned Size) const {
switch (TargetId) {
case GenXSubtarget::XeHP:
case GenXSubtarget::XeHPG:
case GenXSubtarget::XeLPG:
case GenXSubtarget::XeLPGPlus:
case GenXSubtarget::XeHPC:
case GenXSubtarget::XeHPCVG:
case GenXSubtarget::Xe2:
return Size == 128 || Size == 256;
default:
return Size == 128; // platforms <= TGL
}
}
1 change: 1 addition & 0 deletions IGC/VectorCompiler/lib/GenXCodeGen/GenXSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ class GenXSubtarget final : public GenXGenSubtargetInfo {
PreDefined_Surface stackSurface() const { return StackSurf; }

bool isIntrinsicSupported(unsigned ID) const;
bool isValidGRFSize(unsigned Size) const;
};

} // namespace llvm
Expand Down
46 changes: 45 additions & 1 deletion IGC/VectorCompiler/lib/Utils/GenX/KernelInfo.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*========================== begin_copyright_notice ============================
Copyright (C) 2021-2022 Intel Corporation
Copyright (C) 2021-2024 Intel Corporation
SPDX-License-Identifier: MIT
Expand Down Expand Up @@ -47,6 +47,12 @@ static MDNode *findExternalNode(const Function &F) {
genx::KernelMDOp::ArgTypeDescs);
}

static MDNode *findSpirvExecutionModeNode(const Function &F) {
constexpr unsigned FunctionRef = 0;
constexpr unsigned MinNumOps = 3;
return findNode(F, "spirv.ExecutionMode", FunctionRef, MinNumOps);
};

void vc::internal::createInternalMD(Function &F) {
IGC_ASSERT_MESSAGE(!findInternalNode(F),
"Internal node has already been created!");
Expand Down Expand Up @@ -104,6 +110,13 @@ static RetTy extractConstantIntMD(const MDOperand &Op) {
return static_cast<RetTy>(V->getZExtValue());
}

template <typename RetTy = unsigned>
static RetTy extractConstantIntMD(const Metadata &Op) {
const auto *V = getValueAsMetadata<ConstantInt>(&Op);
IGC_ASSERT_MESSAGE(V, "Unexpected null value in metadata");
return static_cast<RetTy>(V->getZExtValue());
}

template <typename Cont>
static void extractConstantsFromMDNode(const MDNode *N, Cont &C) {
if (!N)
Expand Down Expand Up @@ -247,6 +260,11 @@ vc::KernelMetadata::KernelMetadata(const Function *F) {
}
if (LinearizationNode)
Linearization = extractLinearizationMD(*F, LinearizationNode);

MDNode *SpirvExecutionMode = findSpirvExecutionModeNode(*F);
if (!SpirvExecutionMode)
return;
parseExecutionMode(SpirvExecutionMode);
}

static MDNode *createArgLinearizationMD(const ImplicitLinearizationInfo &Info) {
Expand Down Expand Up @@ -339,6 +357,32 @@ void vc::KernelMetadata::updateSLMSizeMD(unsigned Size) {
ValueAsMetadata::get(C));
}

void vc::KernelMetadata::parseExecutionMode(MDNode *SpirvExecutionMode) {
IGC_ASSERT(SpirvExecutionMode->getNumOperands() >= 3);

auto &EMode = SpirvExecutionMode->getOperand(1);
auto &EModeVal = SpirvExecutionMode->getOperand(2);
auto EModeId = static_cast<ExecutionMode>(extractConstantIntMD(EMode));
switch (EModeId) {
case ExecutionMode::MaximumRegistersINTEL:
GRFSize = extractConstantIntMD(*(EModeVal.get()));
return;
case ExecutionMode::MaximumRegistersIdINTEL: {
auto *GRFSizeNode = cast<MDNode>(EModeVal.get());
GRFSize = extractConstantIntMD(*(GRFSizeNode->getOperand(0)));
return;
}
case ExecutionMode::NamedMaximumRegistersINTEL: {
auto *NamedExecMode = cast<MDString>(EModeVal.get());
IGC_ASSERT_EXIT_MESSAGE(!NamedExecMode->getString().compare("AutoINTEL"),
"Unhandled NamedMaximumRegisters value");
GRFSize = 0;
return;
}
}
IGC_ASSERT_EXIT_MESSAGE(0, "Unhandled execution mode!");
}

bool vc::hasKernel(const Module &M) {
NamedMDNode *KernelsMD = M.getNamedMetadata(genx::FunctionMD::GenXKernels);
if (!KernelsMD)
Expand Down
30 changes: 30 additions & 0 deletions IGC/VectorCompiler/test/CisaBuilder/exec_mode.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
;=========================== begin_copyright_notice ============================
;
; Copyright (C) 2024 Intel Corporation
;
; SPDX-License-Identifier: MIT
;
;============================ end_copyright_notice =============================

; COM: This test verifies that spirv.ExecutionMode metadata is not corrupted
; COM: somewhere in VC pipeline.

; RUN: llc %s -march=genx64 -mcpu=Xe2 -vc-skip-ocl-runtime-info -finalizer-opts='-dumpvisa -dumpcommonisa -isaasmToConsole' -o /dev/null | \
; RUN: FileCheck %s

; CHECK: .kernel_attr NumGRF=256
define dllexport spir_kernel void @kernel(i32 %arg) local_unnamed_addr #0 {
ret void
}

attributes #0 = { noinline nounwind "CMGenxMain" }

!genx.kernels = !{!2}
!genx.kernel.internal = !{!3}
!spirv.ExecutionMode = !{!4}

!0 = !{i32 24}
!1 = !{}
!2 = !{void (i32)* @kernel, !"kernel", !0, i32 0, !0, !1, !1, i32 0}
!3 = !{void (i32)* @kernel, null, null, null, null}
!4 = !{void (i32)* @kernel, i32 6461, i32 256}
67 changes: 67 additions & 0 deletions IGC/VectorCompiler/test/CisaBuilder/grf_size.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
;=========================== begin_copyright_notice ============================
;
; Copyright (C) 2024 Intel Corporation
;
; SPDX-License-Identifier: MIT
;
;============================ end_copyright_notice =============================

; COM: ;;;;;;;;;; RUNNERS ;;;;;;;;;;

; RUN: %opt %use_old_pass_manager% -march=genx64 -mtriple=spir64-unknown-unknown -mcpu=XeHPC \
; RUN: -GenXModule -GenXNumberingWrapper -GenXLiveRangesWrapper -GenXCisaBuilderPass -GenXFinalizer \
; RUN: -disable-verify -finalizer-opts="-dumpcommonisa -isaasmToConsole" < %s | FileCheck %s

; CHECK: .kernel_attr NumGRF=256
define dllexport spir_kernel void @test_256_uint(i32 %arg) #0 {
ret void
}

; CHECK: .kernel_attr NumGRF=256
define dllexport spir_kernel void @test_256_node(i32 %arg) #0 {
ret void
}

; CHECK: .kernel_attr NumGRF=0
define dllexport spir_kernel void @test_auto(i32 %arg) #0 {
ret void
}

; CHECK: .kernel_attr NumGRF=128
define dllexport spir_kernel void @test_default(i32 %arg) #0 {
ret void
}

; CHECK: .kernel_attr NumGRF=128
define dllexport spir_kernel void @test_invalid(i32 %arg) #0 {
ret void
}

attributes #0 = { "CMGenxMain" "VC.Stack.Amount"="0" "target-cpu"="XeHPC" }

!genx.kernels = !{!2, !5, !9, !12, !14}
!genx.kernel.internal = !{!3, !6, !10, !13, !15}
!spirv.ExecutionMode = !{!4, !7, !11, !16}

!0 = !{i32 24}
!1 = !{}

!2 = !{void (i32)* @test_256_uint, !"test_256_uint", !0, i32 0, !0, !1, !1, i32 0}
!3 = !{void (i32)* @test_256_uint, null, null, null, null}
!4 = !{void (i32)* @test_256_uint, i32 6461, i32 256}

!5 = !{void (i32)* @test_256_node, !"test_256_node", !0, i32 0, !0, !1, !1, i32 0}
!6 = !{void (i32)* @test_256_node, null, null, null, null}
!7 = !{void (i32)* @test_256_node, i32 6462, !8}
!8 = !{i32 256}

!9 = !{void (i32)* @test_auto, !"test_auto", !0, i32 0, !0, !1, !1, i32 0}
!10 = !{void (i32)* @test_auto, null, null, null, null}
!11 = !{void (i32)* @test_auto, i32 6463, !"AutoINTEL"}

!12 = !{void (i32)* @test_default, !"test_default", !0, i32 0, !0, !1, !1, i32 0}
!13 = !{void (i32)* @test_default, null, null, null, null}

!14 = !{void (i32)* @test_invalid, !"test_invalid", !0, i32 0, !0, !1, !1, i32 0}
!15 = !{void (i32)* @test_invalid, null, null, null, null}
!16 = !{void (i32)* @test_invalid, i32 6461, i32 200}

0 comments on commit 69efb32

Please sign in to comment.