From 084cdd0644603cb0deba83a9d629d89d7acec466 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Wed, 20 Nov 2024 21:48:30 +0000 Subject: [PATCH] define DXILProperty for queryable attributes - define these properties in DXIL.td and DXILConstants.h - emit DXIL definitions as enumerations - emit some helper functions to query OpCodeProp for each property class --- llvm/lib/Target/DirectX/DXIL.td | 15 ++++++ llvm/lib/Target/DirectX/DXILConstants.h | 5 ++ llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 1 + llvm/utils/TableGen/DXILEmitter.cpp | 59 ++++++++++++++++++++++- 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index d5e414f3bedae0..45dae53bfd92f1 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -279,6 +279,18 @@ def ReadOnly : DXILAttribute; def NoDuplicate : DXILAttribute; def NoReturn : DXILAttribute; +// A property is simply used to mark a DXIL op belongs to a sub-group of +// DXIL ops, and it is used to query if a particular holds this property. +// This is used for static analysis of DXIL ops. +class DXILProperty; + +def IsBarrier : DXILProperty; +def IsDerivative : DXILProperty; +def IsGradient : DXILProperty; +def IsFeedback : DXILProperty; +def IsWave : DXILProperty; +def RequiresUniformInputs : DXILProperty; + class Overloads ols> { Version dxil_version = ver; list overload_types = ols; @@ -322,6 +334,9 @@ class DXILOp { // Versioned attributes of operation list attributes = []; + + // List of properties. Default to no properties. + list properties = []; } // Concrete definitions of DXIL Operations diff --git a/llvm/lib/Target/DirectX/DXILConstants.h b/llvm/lib/Target/DirectX/DXILConstants.h index d93892f27a0d29..229401d6b271aa 100644 --- a/llvm/lib/Target/DirectX/DXILConstants.h +++ b/llvm/lib/Target/DirectX/DXILConstants.h @@ -35,6 +35,11 @@ enum class Attribute : unsigned { #include "DXILOperation.inc" }; +enum class Property : unsigned { +#define DXIL_PROPERTY(Name) Name, +#include "DXILOperation.inc" +}; + } // namespace dxil } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp index f1b72cea75c5e7..cae3f2ea43bf8e 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp @@ -159,6 +159,7 @@ struct OpCodeProperty { llvm::SmallVector Overloads; llvm::SmallVector Stages; llvm::SmallVector Attributes; + llvm::SmallVector Properties; int OverloadParamIndex; // parameter index which control the overload. // When < 0, should be only 1 overload type. }; diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp index b6dd3bc445b2c8..7ed5475d4f9b29 100644 --- a/llvm/utils/TableGen/DXILEmitter.cpp +++ b/llvm/utils/TableGen/DXILEmitter.cpp @@ -42,6 +42,7 @@ struct DXILOperationDesc { SmallVector OverloadRecs; SmallVector StageRecs; SmallVector AttrRecs; + SmallVector PropRecs; StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which // means no map exists SmallVector @@ -149,6 +150,13 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { AttrRecs.push_back(CR); } + Recs = R->getValueAsListOfDefs("properties"); + + // Get property records + for (const Record *CR : Recs) { + PropRecs.push_back(CR); + } + // Get the operation class OpClass = R->getValueAsDef("OpClass")->getName(); @@ -318,6 +326,28 @@ static std::string getAttributeListString(ArrayRef Recs) { return ListString; } +/// Return a string representation of valid property information denoted +// by input records +// +/// \param Recs A vector of records of TableGen Property records +/// \return std::string string representation of properties list string +// {Attr1, Attr2, ...} +static std::string getPropertyListString(ArrayRef Recs) { + std::string ListString = ""; + std::string Prefix = ""; + ListString.append("{"); + + std::string CommaPrefix = ""; + for (const auto *Rec : Recs) { + ListString.append(CommaPrefix) + .append("dxil::Property::") + .append(Rec->getName()); + CommaPrefix = ", "; + } + ListString.append("}"); + return ListString; +} + /// Emit a mapping of DXIL opcode to opname static void emitDXILOpCodes(ArrayRef Ops, raw_ostream &OS) { OS << "#ifdef DXIL_OPCODE\n"; @@ -356,6 +386,30 @@ static void emitDXILAttributes(const RecordKeeper &Records, raw_ostream &OS) { OS << "#endif\n\n"; } +/// Emit a list of DXIL op properties and their query functions +static void emitDXILProperties(const RecordKeeper &Records, raw_ostream &OS) { + // Generate their definitions + OS << "#ifdef DXIL_PROPERTY\n"; + for (const Record *Prop: Records.getAllDerivedDefinitions("DXILProperty")) + OS << "DXIL_PROPERTY(" << Prop->getName() << ")\n"; + OS << "#undef DXIL_PROPERTY\n"; + OS << "#endif\n\n"; +} + +static void emitDXILPropertyHelpers(const RecordKeeper &Records, raw_ostream &OS) { + // Generate their helper functions + for (const Record *Prop: Records.getAllDerivedDefinitions("DXILProperty")) { + OS << "[[maybe_unused]]\n"; + OS << "static bool has" << Prop->getName() << "(dxil::OpCode Op) {\n"; + OS << " auto *OpCodeProp = getOpCodeProperty(Op);\n"; + OS << " for (auto Prop : OpCodeProp->Properties)\n"; + OS << " if (Prop == dxil::Property::" << Prop->getName() << ")\n"; + OS << " return true;\n"; + OS << " return false;\n"; + OS << "}\n\n"; + } +} + /// Emit a list of DXIL op function types static void emitDXILOpFunctionTypes(ArrayRef Ops, raw_ostream &OS) { @@ -426,7 +480,8 @@ static void emitDXILOperationTable(ArrayRef Ops, << OpClassStrings.get(Op.OpClass.data()) << ", " << getOverloadMaskString(Op.OverloadRecs) << ", " << getStageMaskString(Op.StageRecs) << ", " - << getAttributeListString(Op.AttrRecs) << ", " << Op.OverloadParamIndex + << getAttributeListString(Op.AttrRecs) << ", " + << getPropertyListString(Op.PropRecs) << ", " << Op.OverloadParamIndex << " }"; Prefix = ",\n"; } @@ -532,11 +587,13 @@ static void emitDxilOperation(const RecordKeeper &Records, raw_ostream &OS) { emitDXILOpClasses(Records, OS); emitDXILOpParamTypes(Records, OS); emitDXILAttributes(Records, OS); + emitDXILProperties(Records, OS); emitDXILOpFunctionTypes(DXILOps, OS); emitDXILIntrinsicMap(DXILOps, OS); OS << "#ifdef DXIL_OP_OPERATION_TABLE\n\n"; emitDXILOperationTableDataStructs(Records, OS); emitDXILOperationTable(DXILOps, OS); + emitDXILPropertyHelpers(Records, OS); OS << "#undef DXIL_OP_OPERATION_TABLE\n"; OS << "#endif\n\n"; }