Skip to content

[SYCL][Fusion][NoSTL] Simplify kernel attributes by making them less generic #12376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
61 changes: 44 additions & 17 deletions sycl-fusion/common/include/Kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <array>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

Expand Down Expand Up @@ -108,18 +109,6 @@ struct SYCLKernelBinaryInfo {
uint64_t BinarySize = 0;
};

///
/// Describe a SYCL/OpenCL kernel attribute by its name and values.
struct SYCLKernelAttribute {
using AttributeValueList = std::vector<std::string>;

SYCLKernelAttribute(std::string Name)
: AttributeName{std::move(Name)}, Values{} {}

std::string AttributeName;
AttributeValueList Values;
};

///
/// Encode usage of parameters for the actual kernel function.
enum ArgUsage : uint8_t {
Expand Down Expand Up @@ -149,10 +138,6 @@ struct SYCLArgumentDescriptor {
DynArray<ArgUsageUT> UsageMask;
};

///
/// List of SYCL/OpenCL kernel attributes.
using AttributeList = std::vector<SYCLKernelAttribute>;

///
/// Class to model a three-dimensional index.
class Indices {
Expand Down Expand Up @@ -193,6 +178,48 @@ class Indices {
size_t Values[Size];
};

///
/// Describe a SYCL/OpenCL kernel attribute by its kind and values.
struct SYCLKernelAttribute {
enum class AttrKind { Invalid, ReqdWorkGroupSize, WorkGroupSizeHint };

static constexpr auto ReqdWorkGroupSizeName = "reqd_work_group_size";
static constexpr auto WorkGroupSizeHintName = "work_group_size_hint";

static AttrKind parseKind(const char *Name) {
auto Kind = AttrKind::Invalid;
if (std::strcmp(Name, ReqdWorkGroupSizeName) == 0) {
Kind = AttrKind::ReqdWorkGroupSize;
} else if (std::strcmp(Name, WorkGroupSizeHintName) == 0) {
Kind = AttrKind::WorkGroupSizeHint;
}
return Kind;
}

AttrKind Kind;
Indices Values;

SYCLKernelAttribute() : Kind(AttrKind::Invalid) {}
SYCLKernelAttribute(AttrKind Kind, const Indices &Values)
: Kind(Kind), Values(Values) {}

const char *getName() const {
assert(Kind != AttrKind::Invalid);
switch (Kind) {
case AttrKind::ReqdWorkGroupSize:
return ReqdWorkGroupSizeName;
case AttrKind::WorkGroupSizeHint:
return WorkGroupSizeHintName;
default:
return "__invalid__";
}
}
};

///
/// List of SYCL/OpenCL kernel attributes.
using SYCLAttributeList = DynArray<SYCLKernelAttribute>;

///
/// Class to model SYCL nd_range
class NDRange {
Expand Down Expand Up @@ -306,7 +333,7 @@ struct SYCLKernelInfo {

SYCLArgumentDescriptor Args;

AttributeList Attributes;
SYCLAttributeList Attributes;

NDRange NDR;

Expand Down
44 changes: 23 additions & 21 deletions sycl-fusion/jit-compiler/lib/translation/KernelTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,19 @@ using namespace jit_compiler::translation;
using namespace llvm;

///
/// Get an attribute value consisting of NumValues scalar constant integers
/// from the MDNode.
static void getAttributeValues(std::vector<std::string> &Values, MDNode *MD) {
for (const auto &MDOp : MD->operands()) {
auto *ConstantMD = cast<ConstantAsMetadata>(MDOp);
auto *ConstInt = cast<ConstantInt>(ConstantMD->getValue());
Values.push_back(std::to_string(ConstInt->getZExtValue()));
}
/// Get an `Indices` object from the MDNode's three constant integer operands.
static Indices getAttributeValues(MDNode *MD) {
assert(MD->getNumOperands() == Indices::size());
Indices Res;
std::transform(MD->op_begin(), MD->op_end(), Res.begin(),
[](const auto &MDOp) {
auto *ConstantMD = cast<ConstantAsMetadata>(MDOp);
auto *ConstInt = cast<ConstantInt>(ConstantMD->getValue());
return ConstInt->getZExtValue();
});
return Res;
}

// NOLINTNEXTLINE(readability-identifier-naming)
static const char *REQD_WORK_GROUP_SIZE_ATTR = "reqd_work_group_size";
// NOLINTNEXTLINE(readability-identifier-naming)
static const char *WORK_GROUP_SIZE_HINT_ATTR = "work_group_size_hint";

///
/// Restore kernel attributes for the kernel in Info from the metadata
/// attached to its kernel function in the LLVM module Mod.
Expand All @@ -48,16 +46,20 @@ static const char *WORK_GROUP_SIZE_HINT_ATTR = "work_group_size_hint";
static void restoreKernelAttributes(Module *Mod, SYCLKernelInfo &Info) {
auto *KernelFunction = Mod->getFunction(Info.Name);
assert(KernelFunction && "Kernel function not present in module");
if (auto *MD = KernelFunction->getMetadata(REQD_WORK_GROUP_SIZE_ATTR)) {
SYCLKernelAttribute ReqdAttr{REQD_WORK_GROUP_SIZE_ATTR};
getAttributeValues(ReqdAttr.Values, MD);
Info.Attributes.push_back(ReqdAttr);
SmallVector<SYCLKernelAttribute, 2> Attrs;
using AttrKind = SYCLKernelAttribute::AttrKind;
if (auto *MD = KernelFunction->getMetadata(
SYCLKernelAttribute::ReqdWorkGroupSizeName)) {
Attrs.emplace_back(AttrKind::ReqdWorkGroupSize, getAttributeValues(MD));
}
if (auto *MD = KernelFunction->getMetadata(WORK_GROUP_SIZE_HINT_ATTR)) {
SYCLKernelAttribute HintAttr{WORK_GROUP_SIZE_HINT_ATTR};
getAttributeValues(HintAttr.Values, MD);
Info.Attributes.push_back(HintAttr);
if (auto *MD = KernelFunction->getMetadata(
SYCLKernelAttribute::WorkGroupSizeHintName)) {
Attrs.emplace_back(AttrKind::WorkGroupSizeHint, getAttributeValues(MD));
}
if (Attrs.empty())
return;
Info.Attributes = SYCLAttributeList{Attrs.size()};
llvm::copy(Attrs, Info.Attributes.begin());
}

llvm::Expected<std::unique_ptr<llvm::Module>>
Expand Down
65 changes: 27 additions & 38 deletions sycl-fusion/passes/kernel-fusion/SYCLKernelFusion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,10 @@ Error SYCLKernelFusion::fuseKernel(
assert(FusedParamKinds.size() == FusedArgUsageMask.size());
jit_compiler::SYCLKernelInfo KI{FusedKernelName.str(),
FusedParamKinds.size()};
KI.Attributes = KernelAttributeList{FusedAttributes.size()};
llvm::copy(FusedParamKinds, KI.Args.Kinds.begin());
llvm::copy(FusedArgUsageMask, KI.Args.UsageMask.begin());
KI.Attributes.insert(KI.Attributes.end(), FusedAttributes.begin(),
FusedAttributes.end());
llvm::copy(FusedAttributes, KI.Attributes.begin());
ModInfo->addKernel(KI);
}
jit_compiler::SYCLKernelInfo &FusedKernelInfo =
Expand Down Expand Up @@ -700,16 +700,16 @@ void SYCLKernelFusion::attachKernelAttributeMD(
// Attach kernel attribute information as metadata to a kernel function.
for (jit_compiler::SYCLKernelAttribute &KernelAttr :
FusedKernelInfo.Attributes) {
if (KernelAttr.AttributeName == "reqd_work_group_size" ||
KernelAttr.AttributeName == "work_group_size_hint") {
if (KernelAttr.Kind == KernelAttrKind::ReqdWorkGroupSize ||
KernelAttr.Kind == KernelAttrKind::WorkGroupSizeHint) {
// 'reqd_work_group_size' and 'work_group_size_hint' get attached as
// metadata with their three values as constant integer metadata.
SmallVector<Metadata *, 3> MDValues;
for (std::string &Val : KernelAttr.Values) {
for (auto Val : KernelAttr.Values) {
MDValues.push_back(ConstantAsMetadata::get(
ConstantInt::get(Type::getInt32Ty(LLVMCtx), std::stoi(Val))));
ConstantInt::get(Type::getInt32Ty(LLVMCtx), Val)));
}
attachFusedMetadata(FusedFunction, KernelAttr.AttributeName, MDValues);
attachFusedMetadata(FusedFunction, KernelAttr.getName(), MDValues);
}
// The two kernel attributes above are currently the only attributes
// attached as metadata, so we don't do anything for other attributes.
Expand Down Expand Up @@ -773,7 +773,7 @@ void SYCLKernelFusion::mergeKernelAttributes(
// want to keep it anyways.
for (const jit_compiler::SYCLKernelAttribute &OtherAttr : Other) {
SYCLKernelFusion::KernelAttr *Attr =
getAttribute(Attributes, OtherAttr.AttributeName);
getAttribute(Attributes, OtherAttr.Kind);
SYCLKernelFusion::AttrMergeResult MergeResult =
mergeAttribute(Attr, OtherAttr);
switch (MergeResult) {
Expand All @@ -786,7 +786,7 @@ void SYCLKernelFusion::mergeKernelAttributes(
addAttribute(Attributes, OtherAttr);
break;
case AttrMergeResult::RemoveAttr:
removeAttribute(Attributes, OtherAttr.AttributeName);
removeAttribute(Attributes, OtherAttr.Kind);
break;
case AttrMergeResult::Error:
llvm_unreachable("Failed to merge attribute");
Expand All @@ -798,14 +798,15 @@ void SYCLKernelFusion::mergeKernelAttributes(
SYCLKernelFusion::AttrMergeResult
SYCLKernelFusion::mergeAttribute(KernelAttr *Attr,
const KernelAttr &Other) const {
if (Other.AttributeName == "reqd_work_group_size") {
switch (Other.Kind) {
case KernelAttrKind::ReqdWorkGroupSize:
return mergeReqdWorkgroupSize(Attr, Other);
}
if (Other.AttributeName == "work_group_size_hint") {
case KernelAttrKind::WorkGroupSizeHint:
return mergeWorkgroupSizeHint(Attr, Other);
default:
// Unknown attribute name, return an error.
return SYCLKernelFusion::AttrMergeResult::Error;
}
// Unknown attribute name, return an error.
return SYCLKernelFusion::AttrMergeResult::Error;
}

SYCLKernelFusion::AttrMergeResult
Expand All @@ -816,11 +817,9 @@ SYCLKernelFusion::mergeReqdWorkgroupSize(KernelAttr *Attr,
// new one
return SYCLKernelFusion::AttrMergeResult::AddAttr;
}
for (size_t I = 0; I < 3; ++I) {
if (getAttrValueAsInt(*Attr, I) != getAttrValueAsInt(Other, I)) {
// Two different required work-group sizes, causes an error.
return SYCLKernelFusion::AttrMergeResult::Error;
}
if (Attr->Values != Other.Values) {
// Two different required work-group sizes, causes an error.
return SYCLKernelFusion::AttrMergeResult::Error;
}
// The required workgroup sizes are identical, keep it.
return SYCLKernelFusion::AttrMergeResult::KeepAttr;
Expand All @@ -834,20 +833,18 @@ SYCLKernelFusion::mergeWorkgroupSizeHint(KernelAttr *Attr,
// the new one
return SYCLKernelFusion::AttrMergeResult::AddAttr;
}
for (size_t I = 0; I < 3; ++I) {
if (getAttrValueAsInt(*Attr, I) != getAttrValueAsInt(Other, I)) {
// Two different hints, remove the hint altogether.
return SYCLKernelFusion::AttrMergeResult::RemoveAttr;
}
if (Attr->Values != Other.Values) {
// Two different hints, remove the hint altogether.
return SYCLKernelFusion::AttrMergeResult::RemoveAttr;
}
// The given hint is identical, keep it.
return SYCLKernelFusion::AttrMergeResult::KeepAttr;
}

SYCLKernelFusion::KernelAttr *
SYCLKernelFusion::getAttribute(MutableAttributeList &Attributes,
StringRef AttrName) const {
auto *It = findAttribute(Attributes, AttrName);
KernelAttrKind AttrKind) const {
auto *It = findAttribute(Attributes, AttrKind);
if (It != Attributes.end()) {
return &*It;
}
Expand All @@ -860,25 +857,17 @@ void SYCLKernelFusion::addAttribute(MutableAttributeList &Attributes,
}

void SYCLKernelFusion::removeAttribute(MutableAttributeList &Attributes,
StringRef AttrName) const {
auto *It = findAttribute(Attributes, AttrName);
KernelAttrKind AttrKind) const {
auto *It = findAttribute(Attributes, AttrKind);
if (It != Attributes.end()) {
Attributes.erase(It);
}
}

SYCLKernelFusion::MutableAttributeList::iterator
SYCLKernelFusion::findAttribute(MutableAttributeList &Attributes,
StringRef AttrName) const {
KernelAttrKind AttrKind) const {
return llvm::find_if(Attributes, [=](SYCLKernelFusion::KernelAttr &Attr) {
return Attr.AttributeName == AttrName.str();
return Attr.Kind == AttrKind;
});
}

unsigned SYCLKernelFusion::getAttrValueAsInt(const KernelAttr &Attr,
size_t Idx) const {
assert(Idx < Attr.Values.size());
unsigned Result = 0;
StringRef(Attr.Values[Idx]).getAsInteger(0, Result);
return Result;
}
19 changes: 8 additions & 11 deletions sycl-fusion/passes/kernel-fusion/SYCLKernelFusion.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,10 @@ class SYCLKernelFusion : public llvm::PassInfoMixin<SYCLKernelFusion> {
jit_compiler::SYCLArgumentDescriptor &InputDef,
const llvm::ArrayRef<bool> ParamUseMask) const;

using KernelAttributeList = jit_compiler::AttributeList;
using KernelAttributeList = jit_compiler::SYCLAttributeList;

using KernelAttr = jit_compiler::SYCLKernelAttribute;
using KernelAttrKind = jit_compiler::SYCLKernelAttribute::AttrKind;

///
/// Indicates the result of merging two attributes of the same kind.
Expand Down Expand Up @@ -187,30 +188,26 @@ class SYCLKernelFusion : public llvm::PassInfoMixin<SYCLKernelFusion> {
const KernelAttr &Other) const;

///
/// Get the attribute with the specified name from the list or return nullptr
/// Get the attribute with the specified kind from the list or return nullptr
/// in case no such attribute is present.
KernelAttr *getAttribute(MutableAttributeList &Attributes,
llvm::StringRef AttrName) const;
KernelAttrKind AttrKind) const;

///
/// Add the attribute to the list.
void addAttribute(MutableAttributeList &Attributes,
const KernelAttr &Attr) const;

///
/// Remove the attribute with the specified name from the list, if present.
/// Remove the attribute with the specified kind from the list, if present.
void removeAttribute(MutableAttributeList &Attributes,
llvm::StringRef AttrName) const;
KernelAttrKind AttrKind) const;

///
/// Find the attribute with the specified name in the list, or return the
/// Find the attribute with the specified kind in the list, or return the
/// end() iterator if no such attribute is present.
MutableAttributeList::iterator findAttribute(MutableAttributeList &Attributes,
llvm::StringRef AttrName) const;

///
/// Retrieve the attribute value at the given index as unsigned integer.
unsigned getAttrValueAsInt(const KernelAttr &Attr, size_t Idx) const;
KernelAttrKind AttrKind) const;
};

#endif // SYCL_FUSION_PASSES_SYCLKERNELFUSION_H
25 changes: 14 additions & 11 deletions sycl-fusion/passes/kernel-info/SYCLKernelInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,25 @@ void SYCLModuleInfoAnalysis::loadModuleInfoFromMetadata(Module &M) {
KernelInfo.Args.UsageMask.begin(), getUInt<ArgUsageUT>);

// Operands 3..n: Attributes
for (; It != End; ++It) {
auto *AIMD = cast<MDNode>(*It);
assert(AIMD->getNumOperands() > 1);
KernelInfo.Attributes = jit_compiler::SYCLAttributeList{
static_cast<size_t>(std::distance(It, End))};
std::transform(It, End, KernelInfo.Attributes.begin(), [](const auto &Op) {
auto *AIMD = cast<MDNode>(Op);
assert(AIMD->getNumOperands() == 4);
const auto *AttrIt = AIMD->op_begin(), *AttrEnd = AIMD->op_end();

// Operand 0: Attribute name
auto Name = cast<MDString>(*AttrIt)->getString().str();
auto Kind = SYCLKernelAttribute::parseKind(Name.c_str());
assert(Kind != SYCLKernelAttribute::AttrKind::Invalid);
++AttrIt;

// Operands 1..m: String values
auto &KernelAttr = KernelInfo.Attributes.emplace_back(std::move(Name));
for (; AttrIt != AttrEnd; ++AttrIt) {
auto Value = cast<MDString>(*AttrIt)->getString().str();
KernelAttr.Values.emplace_back(std::move(Value));
}
}
// Operands 1..3: Values
Indices Values;
std::transform(AttrIt, AttrEnd, Values.begin(), getUInt<size_t>);

return SYCLKernelAttribute{Kind, Values};
});

ModuleInfo->addKernel(KernelInfo);
}
Expand Down Expand Up @@ -156,7 +159,7 @@ PreservedAnalyses SYCLModuleInfoPrinter::run(Module &Mod,

Out.indent(Indent) << "Attributes:\n";
for (const auto &AttrInfo : KernelInfo.Attributes) {
Out.indent(Indent * 2) << AttrInfo.AttributeName << ':';
Out.indent(Indent * 2) << AttrInfo.getName() << ':';
Out.PadToColumn(Pad);
llvm::interleaveComma(AttrInfo.Values, Out);
Out << '\n';
Expand Down
Loading