Skip to content

Commit 8ba4ff3

Browse files
authored
[DirectX][NFC] Change specification of overload types and attribute in DXIL.td (#81184)
- Specify overload types of DXIL Operation as list of types instead of a string. - Add supported DXIL type record definitions to `DXIL.td` leveraging `LLVMType` to avoid duplicate definitions. - Spell out DXIL Operation Attribute specification string. - Make corresponding changes to process the records in DXILEmitter.cpp
1 parent 1f90af1 commit 8ba4ff3

File tree

2 files changed

+133
-71
lines changed

2 files changed

+133
-71
lines changed

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
include "llvm/IR/Intrinsics.td"
15+
include "llvm/IR/Attributes.td"
1516

1617
// Abstract representation of the class a DXIL Operation belongs to.
1718
class DXILOpClass<string name> {
@@ -34,12 +35,29 @@ def BinaryUintCategory : DXILOpCategory<"Binary uint">;
3435
def UnaryFloatCategory : DXILOpCategory<"Unary float">;
3536
def ComputeIDCategory : DXILOpCategory<"Compute/Mesh/Amplification shader">;
3637

38+
// Following are the scalar types supported by DXIL operations and are synonymous
39+
// to llvm_*_ty defined for readability and ease of use in the context of this file.
40+
41+
def voidTy : LLVMType<isVoid>;
42+
43+
// Floating point types
44+
def f16Ty : LLVMType<f16>;
45+
def f32Ty : LLVMType<f32>;
46+
def f64Ty : LLVMType<f64>;
47+
48+
// Integer types
49+
def i1Ty : LLVMType<i1>;
50+
def i8Ty : LLVMType<i8>;
51+
def i16Ty : LLVMType<i16>;
52+
def i32Ty : LLVMType<i32>;
53+
def i64Ty : LLVMType<i64>;
54+
3755
// The parameter description for a DXIL operation
3856
class DXILOpParameter<int pos, string type, string name, string doc,
3957
bit isConstant = 0, string enumName = "",
4058
int maxValue = 0> {
4159
int Pos = pos; // Position in parameter list
42-
string LLVMType = type; // LLVM type name, $o for overload, $r for resource
60+
string Type = type; // LLVM type name, $o for overload, $r for resource
4361
// type, $cb for legacy cbuffer, $u4 for u4 struct
4462
string Name = name; // Short, unique parameter name
4563
string Doc = doc; // Description of this parameter
@@ -56,9 +74,11 @@ class DXILOperationDesc {
5674
DXILOpCategory OpCategory; // Category of the operation
5775
string Doc = ""; // Description of the operation
5876
list<DXILOpParameter> Params = []; // Parameter list of the operation
59-
string OverloadTypes = ""; // Overload types, if applicable
60-
string Attributes = ""; // Attribute shorthands: rn=does not access
61-
// memory,ro=only reads from memory,
77+
list<LLVMType> OverloadTypes = []; // Overload types, if applicable
78+
EnumAttr Attribute; // Operation Attribute. Leverage attributes defined in Attributes.td
79+
// ReadNone - operation does not access memory.
80+
// ReadOnly - only reads from memory.
81+
// "ReadMemory" - reads memory
6282
bit IsDerivative = 0; // Whether this is some kind of derivative
6383
bit IsGradient = 0; // Whether this requires a gradient calculation
6484
bit IsFeedback = 0; // Whether this is a sampler feedback operation
@@ -71,7 +91,7 @@ class DXILOperationDesc {
7191
}
7292

7393
class DXILOperation<string name, int opCode, DXILOpClass opClass, DXILOpCategory opCategory, string doc,
74-
string oloadTypes, string attrs, list<DXILOpParameter> params,
94+
list<LLVMType> oloadTypes, EnumAttr attrs, list<DXILOpParameter> params,
7595
list<string> statsGroup = []> : DXILOperationDesc {
7696
let OpName = name;
7797
let OpCode = opCode;
@@ -80,15 +100,15 @@ class DXILOperation<string name, int opCode, DXILOpClass opClass, DXILOpCategory
80100
let OpClass = opClass;
81101
let OpCategory = opCategory;
82102
let OverloadTypes = oloadTypes;
83-
let Attributes = attrs;
103+
let Attribute = attrs;
84104
let StatsGroup = statsGroup;
85105
}
86106

87107
// LLVM intrinsic that DXIL operation maps to.
88108
class LLVMIntrinsic<Intrinsic llvm_intrinsic_> { Intrinsic llvm_intrinsic = llvm_intrinsic_; }
89109

90110
def Sin : DXILOperation<"Sin", 13, UnaryClass, UnaryFloatCategory, "returns sine(theta) for theta in radians.",
91-
"half;float;", "rn",
111+
[f16Ty,f32Ty], ReadNone,
92112
[
93113
DXILOpParameter<0, "$o", "", "operation result">,
94114
DXILOpParameter<1, "i32", "opcode", "DXIL opcode">,
@@ -98,7 +118,7 @@ def Sin : DXILOperation<"Sin", 13, UnaryClass, UnaryFloatCategory, "returns sine
98118
LLVMIntrinsic<int_sin>;
99119

100120
def UMax : DXILOperation< "UMax", 39, BinaryClass, BinaryUintCategory, "unsigned integer maximum. UMax(a,b) = a > b ? a : b",
101-
"i16;i32;i64;", "rn",
121+
[i16Ty,i32Ty,i64Ty], ReadNone,
102122
[
103123
DXILOpParameter<0, "$o", "", "operation result">,
104124
DXILOpParameter<1, "i32", "opcode", "DXIL opcode">,
@@ -108,15 +128,15 @@ def UMax : DXILOperation< "UMax", 39, BinaryClass, BinaryUintCategory, "unsign
108128
["uints"]>,
109129
LLVMIntrinsic<int_umax>;
110130

111-
def ThreadId : DXILOperation< "ThreadId", 93, ThreadIdClass, ComputeIDCategory, "reads the thread ID", "i32;", "rn",
131+
def ThreadId : DXILOperation< "ThreadId", 93, ThreadIdClass, ComputeIDCategory, "reads the thread ID", [i32Ty], ReadNone,
112132
[
113133
DXILOpParameter<0, "i32", "", "thread ID component">,
114134
DXILOpParameter<1, "i32", "opcode", "DXIL opcode">,
115135
DXILOpParameter<2, "i32", "component", "component to read (x,y,z)">
116136
]>,
117137
LLVMIntrinsic<int_dx_thread_id>;
118138

119-
def GroupId : DXILOperation< "GroupId", 94, GroupIdClass, ComputeIDCategory, "reads the group ID (SV_GroupID)", "i32;", "rn",
139+
def GroupId : DXILOperation< "GroupId", 94, GroupIdClass, ComputeIDCategory, "reads the group ID (SV_GroupID)", [i32Ty], ReadNone,
120140
[
121141
DXILOpParameter<0, "i32", "", "group ID component">,
122142
DXILOpParameter<1, "i32", "opcode", "DXIL opcode">,
@@ -125,7 +145,7 @@ def GroupId : DXILOperation< "GroupId", 94, GroupIdClass, ComputeIDCategory, "r
125145
LLVMIntrinsic<int_dx_group_id>;
126146

127147
def ThreadIdInGroup : DXILOperation< "ThreadIdInGroup", 95, ThreadIdInGroupClass, ComputeIDCategory,
128-
"reads the thread ID within the group (SV_GroupThreadID)", "i32;", "rn",
148+
"reads the thread ID within the group (SV_GroupThreadID)", [i32Ty], ReadNone,
129149
[
130150
DXILOpParameter<0, "i32", "", "thread ID in group component">,
131151
DXILOpParameter<1, "i32", "opcode", "DXIL opcode">,
@@ -134,7 +154,7 @@ def ThreadIdInGroup : DXILOperation< "ThreadIdInGroup", 95, ThreadIdInGroupClas
134154
LLVMIntrinsic<int_dx_thread_id_in_group>;
135155

136156
def FlattenedThreadIdInGroup : DXILOperation< "FlattenedThreadIdInGroup", 96, FlattenedThreadIdInGroupClass, ComputeIDCategory,
137-
"provides a flattened index for a given thread within a given group (SV_GroupIndex)", "i32;", "rn",
157+
"provides a flattened index for a given thread within a given group (SV_GroupIndex)", [i32Ty], ReadNone,
138158
[
139159
DXILOpParameter<0, "i32", "", "result">,
140160
DXILOpParameter<1, "i32", "opcode", "DXIL opcode">

llvm/utils/TableGen/DXILEmitter.cpp

Lines changed: 101 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ struct DXILOperationDesc {
4949
StringRef Doc; // the documentation description of this instruction
5050

5151
SmallVector<DXILParameter> Params; // the operands that this instruction takes
52-
StringRef OverloadTypes; // overload types if applicable
53-
StringRef FnAttr; // attribute shorthands: rn=does not access
54-
// memory,ro=only reads from memory
52+
SmallVector<ParameterKind> OverloadTypes; // overload types if applicable
53+
StringRef Attr; // operation attribute; reference to string representation
54+
// of llvm::Attribute::AttrKind
5555
StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which
56-
// means no map exist
56+
// means no map exists
5757
bool IsDeriv = false; // whether this is some kind of derivative
5858
bool IsGradient = false; // whether this requires a gradient calculation
5959
bool IsFeedback = false; // whether this is a sampler feedback op
@@ -70,37 +70,32 @@ struct DXILOperationDesc {
7070
int OverloadParamIndex; // parameter index which control the overload.
7171
// When < 0, should be only 1 overload type.
7272
SmallVector<StringRef, 4> counters; // counters for this inst.
73-
DXILOperationDesc(const Record *R) {
74-
OpName = R->getValueAsString("OpName");
75-
OpCode = R->getValueAsInt("OpCode");
76-
OpClass = R->getValueAsDef("OpClass")->getValueAsString("Name");
77-
Category = R->getValueAsDef("OpCategory")->getValueAsString("Name");
78-
79-
if (R->getValue("llvm_intrinsic")) {
80-
auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic");
81-
auto DefName = IntrinsicDef->getName();
82-
assert(DefName.starts_with("int_") && "invalid intrinsic name");
83-
// Remove the int_ from intrinsic name.
84-
Intrinsic = DefName.substr(4);
85-
}
86-
87-
Doc = R->getValueAsString("Doc");
88-
89-
ListInit *ParamList = R->getValueAsListInit("Params");
90-
OverloadParamIndex = -1;
91-
for (unsigned I = 0; I < ParamList->size(); ++I) {
92-
Record *Param = ParamList->getElementAsRecord(I);
93-
Params.emplace_back(DXILParameter(Param));
94-
auto &CurParam = Params.back();
95-
if (CurParam.Kind >= ParameterKind::OVERLOAD)
96-
OverloadParamIndex = I;
97-
}
98-
OverloadTypes = R->getValueAsString("OverloadTypes");
99-
FnAttr = R->getValueAsString("Attributes");
100-
}
73+
DXILOperationDesc(const Record *);
10174
};
10275
} // end anonymous namespace
10376

77+
// Convert DXIL type name string to dxil::ParameterKind
78+
//
79+
// @param typeNameStr Type name string
80+
// @return ParameterKind as defined in llvm/Support/DXILABI.h
81+
static ParameterKind getDXILTypeNameToKind(StringRef typeNameStr) {
82+
return StringSwitch<ParameterKind>(typeNameStr)
83+
.Case("voidTy", ParameterKind::VOID)
84+
.Case("f16Ty", ParameterKind::HALF)
85+
.Case("f32Ty", ParameterKind::FLOAT)
86+
.Case("f64Ty", ParameterKind::DOUBLE)
87+
.Case("i1Ty", ParameterKind::I1)
88+
.Case("i8Ty", ParameterKind::I8)
89+
.Case("i16Ty", ParameterKind::I16)
90+
.Case("i32Ty", ParameterKind::I32)
91+
.Case("i64Ty", ParameterKind::I64)
92+
.Case("overloadTy", ParameterKind::OVERLOAD)
93+
.Case("handleTy", ParameterKind::DXIL_HANDLE)
94+
.Case("cbufferRetTy", ParameterKind::CBUFFER_RET)
95+
.Case("resourceRetTy", ParameterKind::RESOURCE_RET)
96+
.Default(ParameterKind::INVALID);
97+
}
98+
10499
static ParameterKind parameterTypeNameToKind(StringRef Name) {
105100
return StringSwitch<ParameterKind>(Name)
106101
.Case("void", ParameterKind::VOID)
@@ -119,10 +114,44 @@ static ParameterKind parameterTypeNameToKind(StringRef Name) {
119114
.Default(ParameterKind::INVALID);
120115
}
121116

117+
DXILOperationDesc::DXILOperationDesc(const Record *R) {
118+
OpName = R->getValueAsString("OpName");
119+
OpCode = R->getValueAsInt("OpCode");
120+
OpClass = R->getValueAsDef("OpClass")->getValueAsString("Name");
121+
Category = R->getValueAsDef("OpCategory")->getValueAsString("Name");
122+
123+
if (R->getValue("llvm_intrinsic")) {
124+
auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic");
125+
auto DefName = IntrinsicDef->getName();
126+
assert(DefName.starts_with("int_") && "invalid intrinsic name");
127+
// Remove the int_ from intrinsic name.
128+
Intrinsic = DefName.substr(4);
129+
}
130+
131+
Doc = R->getValueAsString("Doc");
132+
133+
ListInit *ParamList = R->getValueAsListInit("Params");
134+
OverloadParamIndex = -1;
135+
for (unsigned I = 0; I < ParamList->size(); ++I) {
136+
Record *Param = ParamList->getElementAsRecord(I);
137+
Params.emplace_back(DXILParameter(Param));
138+
auto &CurParam = Params.back();
139+
if (CurParam.Kind >= ParameterKind::OVERLOAD)
140+
OverloadParamIndex = I;
141+
}
142+
ListInit *OverloadTypeList = R->getValueAsListInit("OverloadTypes");
143+
144+
for (unsigned I = 0; I < OverloadTypeList->size(); ++I) {
145+
Record *R = OverloadTypeList->getElementAsRecord(I);
146+
OverloadTypes.emplace_back(getDXILTypeNameToKind(R->getNameInitAsString()));
147+
}
148+
Attr = StringRef(R->getValue("Attribute")->getNameInitAsString());
149+
}
150+
122151
DXILParameter::DXILParameter(const Record *R) {
123152
Name = R->getValueAsString("Name");
124153
Pos = R->getValueAsInt("Pos");
125-
Kind = parameterTypeNameToKind(R->getValueAsString("LLVMType"));
154+
Kind = parameterTypeNameToKind(R->getValueAsString("Type"));
126155
if (R->getValue("Doc"))
127156
Doc = R->getValueAsString("Doc");
128157
IsConst = R->getValueAsBit("IsConstant");
@@ -267,38 +296,51 @@ static void emitDXILIntrinsicMap(std::vector<DXILOperationDesc> &Ops,
267296
OS << "\n";
268297
}
269298

270-
static std::string emitDXILOperationFnAttr(StringRef FnAttr) {
271-
return StringSwitch<std::string>(FnAttr)
272-
.Case("rn", "Attribute::ReadNone")
273-
.Case("ro", "Attribute::ReadOnly")
299+
// Convert operation attribute string to Attribute enum
300+
//
301+
// @param Attr string reference
302+
// @return std::string Attribute enum string
303+
static std::string emitDXILOperationAttr(StringRef Attr) {
304+
return StringSwitch<std::string>(Attr)
305+
.Case("ReadNone", "Attribute::ReadNone")
306+
.Case("ReadOnly", "Attribute::ReadOnly")
274307
.Default("Attribute::None");
275308
}
276309

277-
static std::string getOverloadKind(StringRef Overload) {
278-
return StringSwitch<std::string>(Overload)
279-
.Case("half", "OverloadKind::HALF")
280-
.Case("float", "OverloadKind::FLOAT")
281-
.Case("double", "OverloadKind::DOUBLE")
282-
.Case("i1", "OverloadKind::I1")
283-
.Case("i16", "OverloadKind::I16")
284-
.Case("i32", "OverloadKind::I32")
285-
.Case("i64", "OverloadKind::I64")
286-
.Case("udt", "OverloadKind::UserDefineType")
287-
.Case("obj", "OverloadKind::ObjectType")
288-
.Default("OverloadKind::VOID");
310+
static std::string overloadKindStr(ParameterKind Overload) {
311+
switch (Overload) {
312+
case ParameterKind::HALF:
313+
return "OverloadKind::HALF";
314+
case ParameterKind::FLOAT:
315+
return "OverloadKind::FLOAT";
316+
case ParameterKind::DOUBLE:
317+
return "OverloadKind::DOUBLE";
318+
case ParameterKind::I1:
319+
return "OverloadKind::I1";
320+
case ParameterKind::I8:
321+
return "OverloadKind::I8";
322+
case ParameterKind::I16:
323+
return "OverloadKind::I16";
324+
case ParameterKind::I32:
325+
return "OverloadKind::I32";
326+
case ParameterKind::I64:
327+
return "OverloadKind::I64";
328+
case ParameterKind::VOID:
329+
return "OverloadKind::VOID";
330+
default:
331+
return "OverloadKind::UNKNOWN";
332+
}
289333
}
290334

291-
static std::string getDXILOperationOverload(StringRef Overloads) {
292-
SmallVector<StringRef> OverloadStrs;
293-
Overloads.split(OverloadStrs, ';', /*MaxSplit*/ -1, /*KeepEmpty*/ false);
335+
static std::string
336+
getDXILOperationOverloads(SmallVector<ParameterKind> Overloads) {
294337
// Format is: OverloadKind::FLOAT | OverloadKind::HALF
295-
assert(!OverloadStrs.empty() && "Invalid overloads");
296-
auto It = OverloadStrs.begin();
338+
auto It = Overloads.begin();
297339
std::string Result;
298340
raw_string_ostream OS(Result);
299-
OS << getOverloadKind(*It);
300-
for (++It; It != OverloadStrs.end(); ++It) {
301-
OS << " | " << getOverloadKind(*It);
341+
OS << overloadKindStr(*It);
342+
for (++It; It != Overloads.end(); ++It) {
343+
OS << " | " << overloadKindStr(*It);
302344
}
303345
return OS.str();
304346
}
@@ -368,8 +410,8 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
368410
OS << " { dxil::OpCode::" << Op.OpName << ", "
369411
<< OpStrings.get(Op.OpName.str()) << ", OpCodeClass::" << Op.OpClass
370412
<< ", " << OpClassStrings.get(getDXILOpClassName(Op.OpClass)) << ", "
371-
<< getDXILOperationOverload(Op.OverloadTypes) << ", "
372-
<< emitDXILOperationFnAttr(Op.FnAttr) << ", " << Op.OverloadParamIndex
413+
<< getDXILOperationOverloads(Op.OverloadTypes) << ", "
414+
<< emitDXILOperationAttr(Op.Attr) << ", " << Op.OverloadParamIndex
373415
<< ", " << Op.Params.size() << ", "
374416
<< Parameters.get(ParameterMap[Op.OpClass]) << " },\n";
375417
}

0 commit comments

Comments
 (0)