-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
[DXIL] Define and generate DXILAttribute
and DXILProperty
#117072
base: main
Are you sure you want to change the base?
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
In design discussion I used the terms 'function attribute' vs 'queryable attribute'. In this commit I change the terminology to Reviewer suggestions are very welcomed to this naming. |
473f6df
to
b157913
Compare
@llvm/pr-subscribers-tablegen @llvm/pr-subscribers-backend-directx Author: Finn Plummer (inbelic) Changes
Note: Resolves #114461 Patch is 124.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/117072.diff 56 Files Affected:
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 36228a5e0dce18..8a44a6efd4bd33 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -266,18 +266,30 @@ def miss : DXILShaderStage;
def all_stages : DXILShaderStage;
// Denote support for DXIL Op to have been removed
def removed : DXILShaderStage;
+
// DXIL Op attributes
+// A function attribute denotes that there is a corresponding LLVM function
+// attribute that will be set when building the DXIL op. The mapping for
+// non-trivial cases is defined by setDXILAttribute in DXILOpBuilder.cpp
class DXILAttribute;
-def ReadOnly : DXILAttribute;
def ReadNone : DXILAttribute;
-def IsDerivative : DXILAttribute;
-def IsGradient : DXILAttribute;
-def IsFeedback : DXILAttribute;
-def IsWave : DXILAttribute;
-def NeedsUniformInputs : DXILAttribute;
-def IsBarrier : DXILAttribute;
+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<Version ver, list<DXILOpParamType> ols> {
Version dxil_version = ver;
@@ -291,7 +303,7 @@ class Stages<Version ver, list<DXILShaderStage> st> {
class Attributes<Version ver = DXIL1_0, list<DXILAttribute> attrs> {
Version dxil_version = ver;
- list<DXILAttribute> op_attrs = attrs;
+ list<DXILAttribute> fn_attrs = attrs;
}
// Abstraction DXIL Operation
@@ -322,6 +334,9 @@ class DXILOp<int opcode, DXILOpClass opclass> {
// Versioned attributes of operation
list<Attributes> attributes = [];
+
+ // List of properties. Default to no properties.
+ list<DXILProperty> properties = [];
}
// Concrete definitions of DXIL Operations
@@ -729,6 +744,7 @@ def CreateHandle : DXILOp<57, createHandle> {
let arguments = [Int8Ty, Int32Ty, Int32Ty, Int1Ty];
let result = HandleTy;
let stages = [Stages<DXIL1_0, [all_stages]>, Stages<DXIL1_6, [removed]>];
+ let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
}
def BufferLoad : DXILOp<68, bufferLoad> {
@@ -740,6 +756,7 @@ def BufferLoad : DXILOp<68, bufferLoad> {
[Overloads<DXIL1_0,
[ResRetHalfTy, ResRetFloatTy, ResRetInt16Ty, ResRetInt32Ty]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
+ let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
}
def BufferStore : DXILOp<69, bufferStore> {
@@ -768,6 +785,7 @@ def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> {
let result = Int1Ty;
let overloads = [Overloads<DXIL1_0, [Int32Ty]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
+ let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
}
def Discard : DXILOp<82, discard> {
@@ -833,8 +851,8 @@ def Dot4AddI8Packed : DXILOp<163, dot4AddPacked> {
let LLVMIntrinsic = int_dx_dot4add_i8packed;
let arguments = [Int32Ty, Int32Ty, Int32Ty];
let result = Int32Ty;
- let attributes = [Attributes<DXIL1_0, [ReadNone]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
+ let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
def Dot4AddU8Packed : DXILOp<164, dot4AddPacked> {
@@ -843,8 +861,8 @@ def Dot4AddU8Packed : DXILOp<164, dot4AddPacked> {
let LLVMIntrinsic = int_dx_dot4add_u8packed;
let arguments = [Int32Ty, Int32Ty, Int32Ty];
let result = Int32Ty;
- let attributes = [Attributes<DXIL1_0, [ReadNone]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
+ let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
def AnnotateHandle : DXILOp<216, annotateHandle> {
@@ -852,6 +870,7 @@ def AnnotateHandle : DXILOp<216, annotateHandle> {
let arguments = [HandleTy, ResPropsTy];
let result = HandleTy;
let stages = [Stages<DXIL1_6, [all_stages]>];
+ let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
def CreateHandleFromBinding : DXILOp<217, createHandleFromBinding> {
@@ -859,6 +878,7 @@ def CreateHandleFromBinding : DXILOp<217, createHandleFromBinding> {
let arguments = [ResBindTy, Int32Ty, Int1Ty];
let result = HandleTy;
let stages = [Stages<DXIL1_6, [all_stages]>];
+ let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
def WaveActiveAnyTrue : DXILOp<113, waveAnyTrue> {
@@ -875,7 +895,6 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
let arguments = [];
let result = Int1Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
- let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
@@ -885,7 +904,6 @@ def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
let result = OverloadTy;
let overloads = [Overloads<DXIL1_0, [HalfTy, FloatTy, DoubleTy, Int1Ty, Int16Ty, Int32Ty, Int64Ty]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
- let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
@@ -894,7 +912,7 @@ def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
let arguments = [];
let result = Int32Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
- let attributes = [Attributes<DXIL1_0, [ReadNone]>];
+ let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
}
def WaveAllBitCount : DXILOp<135, waveAllOp> {
@@ -903,5 +921,4 @@ def WaveAllBitCount : DXILOp<135, waveAllOp> {
let arguments = [Int1Ty];
let result = Int32Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
- let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
diff --git a/llvm/lib/Target/DirectX/DXILConstants.h b/llvm/lib/Target/DirectX/DXILConstants.h
index 022cd57795a063..229401d6b271aa 100644
--- a/llvm/lib/Target/DirectX/DXILConstants.h
+++ b/llvm/lib/Target/DirectX/DXILConstants.h
@@ -30,6 +30,16 @@ enum class OpParamType : unsigned {
#include "DXILOperation.inc"
};
+enum class Attribute : unsigned {
+#define DXIL_ATTRIBUTE(Name) Name,
+#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 5d5bb3eacace25..cae3f2ea43bf8e 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -54,7 +54,7 @@ struct OpStage {
struct OpAttribute {
Version DXILVersion;
- uint32_t ValidAttrs;
+ llvm::SmallVector<dxil::Attribute> ValidAttrs;
};
static const char *getOverloadTypeName(OverloadKind Kind) {
@@ -159,6 +159,7 @@ struct OpCodeProperty {
llvm::SmallVector<OpOverload> Overloads;
llvm::SmallVector<OpStage> Stages;
llvm::SmallVector<OpAttribute> Attributes;
+ llvm::SmallVector<dxil::Property> Properties;
int OverloadParamIndex; // parameter index which control the overload.
// When < 0, should be only 1 overload type.
};
@@ -367,6 +368,20 @@ static std::optional<size_t> getPropIndex(ArrayRef<T> PropList,
return std::nullopt;
}
+static void setDXILAttribute(CallInst *CI, dxil::Attribute Attr) {
+ switch (Attr) {
+ case dxil::Attribute::ReadNone:
+ return CI->setDoesNotAccessMemory();
+ case dxil::Attribute::ReadOnly:
+ return CI->setOnlyReadsMemory();
+ case dxil::Attribute::NoReturn:
+ return CI->setDoesNotReturn();
+ case dxil::Attribute::NoDuplicate:
+ return CI->setCannotDuplicate();
+ }
+ llvm_unreachable("Invalid function attribute specified for DXIL operation");
+}
+
namespace llvm {
namespace dxil {
@@ -461,7 +476,17 @@ Expected<CallInst *> DXILOpBuilder::tryCreateOp(dxil::OpCode OpCode,
OpArgs.push_back(IRB.getInt32(llvm::to_underlying(OpCode)));
OpArgs.append(Args.begin(), Args.end());
- return IRB.CreateCall(DXILFn, OpArgs, Name);
+ // Create the function call instruction
+ CallInst *CI = IRB.CreateCall(DXILFn, OpArgs, Name);
+
+ // We then need to attach available function attributes
+ for (auto OpAttr : Prop->Attributes)
+ if (VersionTuple(OpAttr.DXILVersion.Major, OpAttr.DXILVersion.Minor) <=
+ DXILVersion)
+ for (auto Attr : OpAttr.ValidAttrs)
+ setDXILAttribute(CI, Attr);
+
+ return CI;
}
CallInst *DXILOpBuilder::createOp(dxil::OpCode OpCode, ArrayRef<Value *> Args,
diff --git a/llvm/test/CodeGen/DirectX/BufferLoad.ll b/llvm/test/CodeGen/DirectX/BufferLoad.ll
index 24d65fe1648c15..874c81df29b64a 100644
--- a/llvm/test/CodeGen/DirectX/BufferLoad.ll
+++ b/llvm/test/CodeGen/DirectX/BufferLoad.ll
@@ -16,7 +16,7 @@ define void @loadv4f32() {
; The temporary casts should all have been cleaned up
; CHECK-NOT: %dx.cast_handle
- ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef)
+ ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR:]]
%data0 = call <4 x float> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 0)
@@ -33,7 +33,7 @@ define void @loadv4f32() {
call void @scalar_user(float %data0_0)
call void @scalar_user(float %data0_2)
- ; CHECK: [[DATA4:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 4, i32 undef)
+ ; CHECK: [[DATA4:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 4, i32 undef) #[[#ATTR]]
%data4 = call <4 x float> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 4)
@@ -47,7 +47,7 @@ define void @loadv4f32() {
; CHECK: insertelement <4 x float>
call void @vector_user(<4 x float> %data4)
- ; CHECK: [[DATA12:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 12, i32 undef)
+ ; CHECK: [[DATA12:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 12, i32 undef) #[[#ATTR]]
%data12 = call <4 x float> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 12)
@@ -69,7 +69,7 @@ define void @index_dynamic(i32 %bufindex, i32 %elemindex) {
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_0_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false)
- ; CHECK: [[LOAD:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 %bufindex, i32 undef)
+ ; CHECK: [[LOAD:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 %bufindex, i32 undef) #[[#ATTR]]
%load = call <4 x float> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 %bufindex)
@@ -104,7 +104,7 @@ define void @loadf32() {
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_0_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false)
- ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef)
+ ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
%data0 = call float @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", float, 0, 0, 0) %buffer, i32 0)
@@ -122,7 +122,7 @@ define void @loadv2f32() {
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_v2f32_0_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false)
- ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef)
+ ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
%data0 = call <2 x float> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <2 x float>, 0, 0, 0) %buffer, i32 0)
@@ -136,12 +136,12 @@ define void @loadv4f32_checkbit() {
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_0_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false)
- ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef)
+ ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
%data0 = call {<4 x float>, i1} @llvm.dx.typedBufferLoad.checkbit.f32(
target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 0)
; CHECK: [[STATUS:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 4
- ; CHECK: [[MAPPED:%.*]] = call i1 @dx.op.checkAccessFullyMapped.i32(i32 71, i32 [[STATUS]]
+ ; CHECK: [[MAPPED:%.*]] = call i1 @dx.op.checkAccessFullyMapped.i32(i32 71, i32 [[STATUS]]) #[[#ATTR]]
%check = extractvalue {<4 x float>, i1} %data0, 1
; CHECK: call void @check_user(i1 [[MAPPED]])
@@ -157,7 +157,7 @@ define void @loadv4i32() {
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4i32_0_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false)
- ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef)
+ ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
%data0 = call <4 x i32> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) %buffer, i32 0)
@@ -171,7 +171,7 @@ define void @loadv4f16() {
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f16_0_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false)
- ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f16 @dx.op.bufferLoad.f16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef)
+ ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f16 @dx.op.bufferLoad.f16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
%data0 = call <4 x half> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %buffer, i32 0)
@@ -185,9 +185,11 @@ define void @loadv4i16() {
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4i16_0_0_0(
i32 0, i32 0, i32 1, i32 0, i1 false)
- ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i16 @dx.op.bufferLoad.i16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef)
+ ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i16 @dx.op.bufferLoad.i16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
%data0 = call <4 x i16> @llvm.dx.typedBufferLoad(
target("dx.TypedBuffer", <4 x i16>, 0, 0, 0) %buffer, i32 0)
ret void
}
+
+; CHECK: attributes #[[#ATTR]] = {{{.*}} memory(read) {{.*}}}
diff --git a/llvm/test/CodeGen/DirectX/BufferStore.ll b/llvm/test/CodeGen/DirectX/BufferStore.ll
index 9ea7735be59c81..68849bc71edd22 100644
--- a/llvm/test/CodeGen/DirectX/BufferStore.ll
+++ b/llvm/test/CodeGen/DirectX/BufferStore.ll
@@ -17,7 +17,7 @@ define void @storefloat(<4 x float> %data, i32 %index) {
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x float> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x float> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x float> %data, i32 3
- ; CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, float [[DATA0_0]], float [[DATA0_1]], float [[DATA0_2]], float [[DATA0_3]], i8 15)
+ ; CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, float [[DATA0_0]], float [[DATA0_1]], float [[DATA0_2]], float [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.typedBufferStore(
target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %buffer,
i32 %index, <4 x float> %data)
@@ -37,7 +37,7 @@ define void @storeint(<4 x i32> %data, i32 %index) {
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x i32> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x i32> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x i32> %data, i32 3
- ; CHECK: call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, i32 [[DATA0_0]], i32 [[DATA0_1]], i32 [[DATA0_2]], i32 [[DATA0_3]], i8 15)
+ ; CHECK: call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, i32 [[DATA0_0]], i32 [[DATA0_1]], i32 [[DATA0_2]], i32 [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.typedBufferStore(
target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %buffer,
i32 %index, <4 x i32> %data)
@@ -60,7 +60,7 @@ define void @storehalf(<4 x half> %data, i32 %index) {
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x half> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x half> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x half> %data, i32 3
- ; CHECK: call void @dx.op.bufferStore.f16(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, half [[DATA0_0]], half [[DATA0_1]], half [[DATA0_2]], half [[DATA0_3]], i8 15)
+ ; CHECK: call void @dx.op.bufferStore.f16(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, half [[DATA0_0]], half [[DATA0_1]], half [[DATA0_2]], half [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.typedBufferStore(
target("dx.TypedBuffer", <4 x half>, 1, 0, 0) %buffer,
i32 %index, <4 x half> %data)
@@ -83,7 +83,7 @@ define void @storei16(<4 x i16> %data, i32 %index) {
; CHECK: [[DATA0_1:%.*]] = extractelement <4 x i16> %data, i32 1
; CHECK: [[DATA0_2:%.*]] = extractelement <4 x i16> %data, i32 2
; CHECK: [[DATA0_3:%.*]] = extractelement <4 x i16> %data, i32 3
- ; CHECK: call void @dx.op.bufferStore.i16(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, i16 [[DATA0_0]], i16 [[DATA0_1]], i16 [[DATA0_2]], i16 [[DATA0_3]], i8 15)
+ ; CHECK: call void @dx.op.bufferStore.i16(i32 69, %dx.types.Handle [[HANDLE]], i32 %index, i32 undef, i16 [[DATA0_0]], i16 [[DATA0_1]], i16 [[DATA0_2]], i16 [[DATA0_3]], i8 15){{$}}
call void @llvm.dx.typedBufferStore(
target("dx.TypedBuffer", <4 x i16>, 1, 0, 0) %buffer,
i32 %index, <4 x i16> %data)
diff --git a/llvm/test/CodeGen/DirectX/CreateHandle.ll b/llvm/test/CodeGen/DirectX/CreateHandle.ll
index 40b3b2c7122722..6f1a17386db9b0 100644
--- a/llvm/test/CodeGen/DirectX/CreateHandle.ll
+++ b/llvm/test/CodeGen/DirectX/CreateHandle.ll
@@ -19,14 +19,14 @@ define void @test_buffers() {
%typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0(
i32 3, i32 5, i32 1, i32 4, i1 false)
- ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 4, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 4, i1 false) #[[#ATTR:]]
; CHECK-NOT: @llvm.dx.cast.handle
; RWBuffer<int> Buf : register(u7, space2)
%typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1)
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t(
i32 2, i32 7, i32 1, i32 6, i1 false)
- ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 6, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 6, i1 false) #[[#ATTR]]
; Buffer<uint4> Buf[24] : register(t3, space5)
; Buffer<uint4> typed2 = Buf[4]
@@ -34,20 +34,20 @@ define void @test_buffers() {
%typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
@llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0_0t(
i32 5, i32 3, i32 24, i32 7, i1 false)
- ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 3, i32 7, i1 false)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 3, i32 7, i1 false) #[[#ATTR]]
; struct S { float4 a; uint4 b; };
; StructuredBuffer<S> Buf : register(t2, space4)
%struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
@llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
i32 4, i32 2, i32 1, i32 10, i1 true)
- ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 10, i1 true)
+ ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 10, i1 true) #[[#ATTR]]
; ByteAddressBuffer Buf : register(t8, space1)
%byteaddr0 = call target("dx.RawBuffer", i8, 0, 0)
@llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(
i32 1, i32...
[truncated]
|
llvm/utils/TableGen/DXILEmitter.cpp
Outdated
OS << " return false;\n"; | ||
OS << "}\n\n"; | ||
} | ||
static void emitDXILPropertyHelper(raw_ostream &OS) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't be tested until we use it in #114565. So we could wait until there to implement this
llvm/lib/Target/DirectX/DXIL.td
Outdated
class DXILProperty; | ||
|
||
def IsBarrier : DXILProperty; | ||
def IsDerivative : DXILProperty; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was set, but never actually used in hctdb.py. What was actually used is the is_gradient value. This change demonstrates it can be removed from DXC with no consequences: microsoft/DirectXShaderCompiler#7023
As such, I think we should remove this property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Furthermore, do we want to undefine all the properties and only define them when an op that uses them is added? Currently all but isWave/isBarrier
. It would prevent having any other redundant properties by being easier to track.
- switch to using DXILAttribute to only denote function attributes - attribute enums can't be or'd together as is currently implemented, so we switch to using a list of attributes in DXILOpBuilder.cpp and DXILEmitter.cpp
- correct all uses of ReadOnly/ReadNone to be consistent with hctdb.py in DXC - all fix order of attributes in each op
- testcases are update to check updated attribute types - there are some CHECK-NOT tests to ensure that previously set attributes no longer emit an attribute
- 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
- instead of generating a query helper for each property, just use a general one for all property enums
- before this change, we would be required to define OpCodeProperty and all used structs to use hasProperty, which for all uses outside of DXILOpBuilder is not usable.
- remove `IsDerivative` property as it was not used in `hctdb.py`
1c40803
to
2e4d5c2
Compare
Rebased to resolve existing conflicts. I also added some more commits to this pr regarding formatting and |
llvm/lib/Target/DirectX/DXIL.td
Outdated
@@ -51,195 +51,194 @@ def SplitDoubleTy : DXILOpParamType; | |||
|
|||
class DXILOpClass; | |||
|
|||
defset list<DXILOpClass> OpClasses = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formatting changes make this diff a lot harder to read and much larger than it really should be. In general if you have a large format-only diff it is best to put that in a separate NFC PR so that the functional change can be reviewed separately.
Can you break this out into a separate formatting-only NFC change?
- update existing wave ops to specify the `IsWave` property - update the `Barrier` op to specify the `IsBarrier` property
b99955f
to
147395e
Compare
DXILAttribute
to denote a function attribute, compatible to how it was define in DXC/LLVM 3.7DXILAttribute
is emitted to be a list of attributes instead of an "or" of the enumsDXILAttribute
to LLVM function attributes inDXILOpBuilder.cpp
. A custom mapping is defined.llvm/test/CodeGen/DirectX
of all ops with attributes to match that attributes are setDXILProperty
to denote the other type of attributes from DXC.DXILProperty
as an enum and generate helper functions to check if an opcode holds a given property.DXIL.td
to specify applicableDXILProperty
s on opsNote:
DXILProperty
was referred to as 'queryable attributes' in design discussion. Changed to property to allow for better expression inDXIL.td
Resolves #114461
Resolves #115912