Skip to content

Commit

Permalink
[AMDGPU] Add metadata for runtime
Browse files Browse the repository at this point in the history
Added emitting metadata to elf for runtime.

Runtime requires certain information (metadata) about kernels to be able to execute and query them. Such information is emitted to an elf section as a key-value pair stream.

Differential Revision: https://reviews.llvm.org/D21849

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275566 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
yxsamliu committed Jul 15, 2016
1 parent 48ed4ab commit 6b0141c
Show file tree
Hide file tree
Showing 4 changed files with 1,219 additions and 0 deletions.
229 changes: 229 additions & 0 deletions lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "AMDGPURuntimeMetadata.h"

using namespace ::AMDGPU;
using namespace llvm;

// TODO: This should get the default rounding mode from the kernel. We just set
Expand Down Expand Up @@ -111,6 +113,7 @@ void AMDGPUAsmPrinter::EmitStartOfAsmFile(Module &M) {
AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(STI->getFeatureBits());
TS->EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor, ISA.Stepping,
"AMD", "AMDGPU");
emitStartOfRuntimeMetadata(M);
}

void AMDGPUAsmPrinter::EmitFunctionBodyStart() {
Expand Down Expand Up @@ -244,6 +247,8 @@ bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
}

emitRuntimeMetadata(*MF.getFunction());

return false;
}

Expand Down Expand Up @@ -740,3 +745,227 @@ bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
*TM.getSubtargetImpl(*MF->getFunction())->getRegisterInfo());
return false;
}

// Emit a key and an integer value for runtime metadata.
static void emitRuntimeMDIntValue(std::unique_ptr<MCStreamer> &Streamer,
RuntimeMD::Key K, uint64_t V,
unsigned Size) {
Streamer->EmitIntValue(K, 1);
Streamer->EmitIntValue(V, Size);
}

// Emit a key and a string value for runtime metadata.
static void emitRuntimeMDStringValue(std::unique_ptr<MCStreamer> &Streamer,
RuntimeMD::Key K, StringRef S) {
Streamer->EmitIntValue(K, 1);
Streamer->EmitIntValue(S.size(), 4);
Streamer->EmitBytes(S);
}

// Emit a key and three integer values for runtime metadata.
// The three integer values are obtained from MDNode \p Node;
static void emitRuntimeMDThreeIntValues(std::unique_ptr<MCStreamer> &Streamer,
RuntimeMD::Key K, MDNode *Node,
unsigned Size) {
Streamer->EmitIntValue(K, 1);
Streamer->EmitIntValue(mdconst::extract<ConstantInt>(
Node->getOperand(0))->getZExtValue(), Size);
Streamer->EmitIntValue(mdconst::extract<ConstantInt>(
Node->getOperand(1))->getZExtValue(), Size);
Streamer->EmitIntValue(mdconst::extract<ConstantInt>(
Node->getOperand(2))->getZExtValue(), Size);
}

void AMDGPUAsmPrinter::emitStartOfRuntimeMetadata(const Module &M) {
OutStreamer->SwitchSection(getObjFileLowering().getContext()
.getELFSection(RuntimeMD::SectionName, ELF::SHT_PROGBITS, 0));

emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyMDVersion,
RuntimeMD::MDVersion << 8 | RuntimeMD::MDRevision, 2);
if (auto MD = M.getNamedMetadata("opencl.ocl.version")) {
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyLanguage,
RuntimeMD::OpenCL_C, 1);
auto Node = MD->getOperand(0);
unsigned short Major = mdconst::extract<ConstantInt>(Node->getOperand(0))
->getZExtValue();
unsigned short Minor = mdconst::extract<ConstantInt>(Node->getOperand(1))
->getZExtValue();
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyLanguageVersion,
Major * 100 + Minor * 10, 2);
}
}

static Twine getOCLTypeName(Type *Ty, bool isSigned) {
if (VectorType* VecTy = dyn_cast<VectorType>(Ty)) {
Type* EleTy = VecTy->getElementType();
unsigned Size = VecTy->getVectorNumElements();
return getOCLTypeName(EleTy, isSigned) + Twine(Size);
}
switch (Ty->getTypeID()) {
case Type::HalfTyID: return "half";
case Type::FloatTyID: return "float";
case Type::DoubleTyID: return "double";
case Type::IntegerTyID: {
if (!isSigned)
return Twine('u') + getOCLTypeName(Ty, true);
auto IntTy = cast<IntegerType>(Ty);
auto BW = IntTy->getIntegerBitWidth();
switch (BW) {
case 8:
return "char";
case 16:
return "short";
case 32:
return "int";
case 64:
return "long";
default:
return Twine("i") + Twine(BW);
}
}
default:
llvm_unreachable("invalid type");
}
}

static RuntimeMD::KernelArg::ValueType getRuntimeMDValueType(
Type *Ty, StringRef TypeName) {
if (auto VT = dyn_cast<VectorType>(Ty))
return getRuntimeMDValueType(VT->getElementType(), TypeName);
else if (auto PT = dyn_cast<PointerType>(Ty))
return getRuntimeMDValueType(PT->getElementType(), TypeName);
else if (Ty->isHalfTy())
return RuntimeMD::KernelArg::F16;
else if (Ty->isFloatTy())
return RuntimeMD::KernelArg::F32;
else if (Ty->isDoubleTy())
return RuntimeMD::KernelArg::F64;
else if (IntegerType* intTy = dyn_cast<IntegerType>(Ty)) {
bool Signed = !TypeName.startswith("u");
switch (intTy->getIntegerBitWidth()) {
case 8:
return Signed ? RuntimeMD::KernelArg::I8 : RuntimeMD::KernelArg::U8;
case 16:
return Signed ? RuntimeMD::KernelArg::I16 : RuntimeMD::KernelArg::U16;
case 32:
return Signed ? RuntimeMD::KernelArg::I32 : RuntimeMD::KernelArg::U32;
case 64:
return Signed ? RuntimeMD::KernelArg::I64 : RuntimeMD::KernelArg::U64;
default:
// Runtime does not recognize other integer types. Report as
// struct type.
return RuntimeMD::KernelArg::Struct;
}
} else
return RuntimeMD::KernelArg::Struct;
}

void AMDGPUAsmPrinter::emitRuntimeMetadata(const Function &F) {
if (!F.getMetadata("kernel_arg_type"))
return;

MCContext &Context = getObjFileLowering().getContext();
OutStreamer->SwitchSection(
Context.getELFSection(RuntimeMD::SectionName, ELF::SHT_PROGBITS, 0));
OutStreamer->EmitIntValue(RuntimeMD::KeyKernelBegin, 1);
emitRuntimeMDStringValue(OutStreamer, RuntimeMD::KeyKernelName, F.getName());

for (auto &Arg:F.args()) {
// Emit KeyArgBegin.
unsigned I = Arg.getArgNo();
OutStreamer->EmitIntValue(RuntimeMD::KeyArgBegin, 1);

// Emit KeyArgSize and KeyArgAlign.
auto T = Arg.getType();
auto DL = F.getParent()->getDataLayout();
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyArgSize,
DL.getTypeAllocSize(T), 4);
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyArgAlign,
DL.getABITypeAlignment(T), 4);

// Emit KeyArgTypeName.
auto TypeName = dyn_cast<MDString>(F.getMetadata(
"kernel_arg_type")->getOperand(I))->getString();
emitRuntimeMDStringValue(OutStreamer, RuntimeMD::KeyArgTypeName, TypeName);

// Emit KeyArgName.
if (auto ArgNameMD = F.getMetadata("kernel_arg_name")) {
auto ArgName = cast<MDString>(ArgNameMD->getOperand(
I))->getString();
emitRuntimeMDStringValue(OutStreamer, RuntimeMD::KeyArgName, ArgName);
}

// Emit KeyArgIsVolatile, KeyArgIsRestrict, KeyArgIsConst and KeyArgIsPipe.
auto TypeQual = cast<MDString>(F.getMetadata(
"kernel_arg_type_qual")->getOperand(I))->getString();
SmallVector<StringRef, 1> SplitQ;
TypeQual.split(SplitQ, " ", -1, false/* drop empty entry*/);
for (auto &I:SplitQ) {
auto Key = StringSwitch<RuntimeMD::Key>(I)
.Case("volatile", RuntimeMD::KeyArgIsVolatile)
.Case("restrict", RuntimeMD::KeyArgIsRestrict)
.Case("const", RuntimeMD::KeyArgIsConst)
.Case("pipe", RuntimeMD::KeyArgIsPipe)
.Default(RuntimeMD::KeyNull);
OutStreamer->EmitIntValue(Key, 1);
}

// Emit KeyArgTypeKind.
auto BaseTypeName = cast<MDString>(
F.getMetadata("kernel_arg_base_type")->getOperand(I))->getString();
auto TypeKind = StringSwitch<RuntimeMD::KernelArg::TypeKind>(BaseTypeName)
.Case("sampler_t", RuntimeMD::KernelArg::Sampler)
.Case("queue_t", RuntimeMD::KernelArg::Queue)
.Cases("image1d_t", "image1d_array_t", "image1d_buffer_t",
"image2d_t" , "image2d_array_t", RuntimeMD::KernelArg::Image)
.Cases("image2d_depth_t", "image2d_array_depth_t",
"image2d_msaa_t", "image2d_array_msaa_t",
"image2d_msaa_depth_t", RuntimeMD::KernelArg::Image)
.Cases("image2d_array_msaa_depth_t", "image3d_t",
RuntimeMD::KernelArg::Image)
.Default(isa<PointerType>(T) ? RuntimeMD::KernelArg::Pointer :
RuntimeMD::KernelArg::Value);
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyArgTypeKind, TypeKind, 1);

// Emit KeyArgValueType.
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyArgValueType,
getRuntimeMDValueType(T, BaseTypeName), 2);

// Emit KeyArgAccQual.
auto AccQual = cast<MDString>(F.getMetadata(
"kernel_arg_access_qual")->getOperand(I))->getString();
auto AQ = StringSwitch<RuntimeMD::KernelArg::AccessQualifer>(AccQual)
.Case("read_only", RuntimeMD::KernelArg::ReadOnly)
.Case("write_only", RuntimeMD::KernelArg::WriteOnly)
.Case("read_write", RuntimeMD::KernelArg::ReadWrite)
.Default(RuntimeMD::KernelArg::None);
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyArgAccQual,
AQ, 1);

// Emit KeyArgAddrQual.
if (isa<PointerType>(T))
emitRuntimeMDIntValue(OutStreamer, RuntimeMD::KeyArgAddrQual,
T->getPointerAddressSpace(), 1);

// Emit KeyArgEnd
OutStreamer->EmitIntValue(RuntimeMD::KeyArgEnd, 1);
}

// Emit KeyReqdWorkGroupSize, KeyWorkGroupSizeHint, and KeyVecTypeHint.
if (auto RWGS = F.getMetadata("reqd_work_group_size"))
emitRuntimeMDThreeIntValues(OutStreamer, RuntimeMD::KeyReqdWorkGroupSize,
RWGS, 4);
if (auto WGSH = F.getMetadata("work_group_size_hint"))
emitRuntimeMDThreeIntValues(OutStreamer, RuntimeMD::KeyWorkGroupSizeHint,
WGSH, 4);
if (auto VTH = F.getMetadata("vec_type_hint")) {
auto TypeName = getOCLTypeName(cast<ValueAsMetadata>(
VTH->getOperand(0))->getType(), mdconst::extract<ConstantInt>(
VTH->getOperand(1))->getZExtValue()).str();
emitRuntimeMDStringValue(OutStreamer, RuntimeMD::KeyVecTypeHint,
TypeName);
}

// Emit KeyKernelEnd
OutStreamer->EmitIntValue(RuntimeMD::KeyKernelEnd, 1);
}
4 changes: 4 additions & 0 deletions lib/Target/AMDGPU/AMDGPUAsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ class AMDGPUAsmPrinter final : public AsmPrinter {
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &O) override;

void emitStartOfRuntimeMetadata(const Module &M);

void emitRuntimeMetadata(const Function &F);

protected:
std::vector<std::string> DisasmLines, HexLines;
size_t DisasmLineMaxLen;
Expand Down
Loading

0 comments on commit 6b0141c

Please sign in to comment.