Skip to content
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

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
50 changes: 36 additions & 14 deletions llvm/lib/Target/DirectX/DXIL.td
Original file line number Diff line number Diff line change
Expand Up @@ -266,18 +266,29 @@ 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 IsGradient : DXILProperty;
def IsFeedback : DXILProperty;
def IsWave : DXILProperty;
def RequiresUniformInputs : DXILProperty;

class Overloads<Version ver, list<DXILOpParamType> ols> {
Version dxil_version = ver;
Expand All @@ -291,7 +302,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;
}

defvar BarrierMode_DeviceMemoryBarrier = 2;
Expand Down Expand Up @@ -376,6 +387,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
Expand Down Expand Up @@ -783,6 +797,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> {
Expand All @@ -794,6 +809,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> {
Expand Down Expand Up @@ -822,6 +838,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> {
Expand Down Expand Up @@ -896,8 +913,8 @@ def Dot4AddI8Packed : DXILOp<163, dot4AddPacked> {
let intrinsics = [ IntrinSelect<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> {
Expand All @@ -906,22 +923,24 @@ def Dot4AddU8Packed : DXILOp<164, dot4AddPacked> {
let intrinsics = [ IntrinSelect<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> {
let Doc = "annotate handle with resource properties";
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> {
let Doc = "create resource handle from binding";
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> {
Expand All @@ -930,6 +949,7 @@ def WaveActiveAnyTrue : DXILOp<113, waveAnyTrue> {
let arguments = [Int1Ty];
let result = Int1Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
let properties = [IsWave];
}

def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
Expand All @@ -938,7 +958,7 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
let arguments = [];
let result = Int1Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
let properties = [IsWave];
}

def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> {
Expand All @@ -948,7 +968,7 @@ 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]>];
let properties = [IsWave];
}

def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
Expand All @@ -957,7 +977,8 @@ 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]>];
let properties = [IsWave];
}

def WaveAllBitCount : DXILOp<135, waveAllOp> {
Expand All @@ -966,7 +987,7 @@ def WaveAllBitCount : DXILOp<135, waveAllOp> {
let arguments = [Int1Ty];
let result = Int32Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
let properties = [IsWave];
}

def Barrier : DXILOp<80, barrier> {
Expand All @@ -981,4 +1002,5 @@ def Barrier : DXILOp<80, barrier> {
let result = VoidTy;
let stages = [Stages<DXIL1_0, [compute, library]>];
let attributes = [Attributes<DXIL1_0, []>];
let properties = [IsBarrier];
}
10 changes: 10 additions & 0 deletions llvm/lib/Target/DirectX/DXILConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
29 changes: 27 additions & 2 deletions llvm/lib/Target/DirectX/DXILOpBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct OpStage {

struct OpAttribute {
Version DXILVersion;
uint32_t ValidAttrs;
llvm::SmallVector<dxil::Attribute> ValidAttrs;
};

static const char *getOverloadTypeName(OverloadKind Kind) {
Expand Down Expand Up @@ -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.
};
Expand Down Expand Up @@ -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 {

Expand Down Expand Up @@ -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,
Expand Down
24 changes: 13 additions & 11 deletions llvm/test/CodeGen/DirectX/BufferLoad.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)

Expand All @@ -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)

Expand All @@ -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)

Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand All @@ -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]])
Expand All @@ -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)

Expand All @@ -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)

Expand All @@ -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) {{.*}}}
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/DirectX/BufferStore.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
Loading
Loading