-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Lower llvm.dx.rawBufferLoad to dxil ops #116845
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
Lower llvm.dx.rawBufferLoad to dxil ops #116845
Conversation
When lowering some resource use intrisics to DXIL operations, it needs to know the information of the resource that the intrisics are using. This PR adds Resource uses to Resource Handle map in DXILResourceMap. It helps the resource uses to find the resource information. This PR is also useful to llvm#106188
This PR lowers the @llvm.dx.rawBufferLoad intrinsic to @dx.op.rawBufferLoad
You can test this locally with the following command:git-clang-format --diff cd418030de7ae75750bc4e48d1238baf03c675e5 3a8f3a1996ed2c87aae08632fcb4fc08893cfae1 --extensions h,cpp -- llvm/include/llvm/Analysis/DXILResource.h llvm/lib/Analysis/DXILResource.cpp llvm/lib/Target/DirectX/DXILOpLowering.cpp View the diff from clang-format here.diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index be4fad8a84..ed9644bff0 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -791,19 +791,18 @@ void DXILResourceMap::updateResourceMap(CallInst *origCallInst,
}
}
- void DXILResourceMap::updateResUseMap(CallInst *origResUse,
+void DXILResourceMap::updateResUseMap(CallInst *origResUse,
std::vector<Value *> &multiNewResUse) {
- assert((origResUse != nullptr) && "Wrong Inputs");
+ assert((origResUse != nullptr) && "Wrong Inputs");
- for (int i = 0; i < multiNewResUse.size(); ++i) {
- CallInst *newResUse = dyn_cast<CallInst>(multiNewResUse[i]);
- assert(newResUse != nullptr);
+ for (int i = 0; i < multiNewResUse.size(); ++i) {
+ CallInst *newResUse = dyn_cast<CallInst>(multiNewResUse[i]);
+ assert(newResUse != nullptr);
- bool keepOrigResUseInMap =
- i == (multiNewResUse.size() - 1) ? false : true;
- updateResUseMapCommon(origResUse, newResUse, keepOrigResUseInMap);
- }
+ bool keepOrigResUseInMap = i == (multiNewResUse.size() - 1) ? false : true;
+ updateResUseMapCommon(origResUse, newResUse, keepOrigResUseInMap);
}
+}
void DXILResourceMap::print(raw_ostream &OS) const {
for (unsigned I = 0, E = Resources.size(); I != E; ++I) {
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index d2b6f05fc9..a8c8b8c870 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -778,7 +778,7 @@ public:
assert(It != DRM.end() && "Resource not in map?");
dxil::ResourceInfo &RI = *It;
- ResourceKind RCKind = RI.getResourceKind();
+ ResourceKind RCKind = RI.getResourceKind();
assert((RCKind == dxil::ResourceKind::StructuredBuffer) ||
(RCKind == dxil::ResourceKind::RawBuffer));
|
@llvm/pr-subscribers-backend-directx @llvm/pr-subscribers-llvm-analysis Author: Zhengxing li (lizhengxing) ChangesIt's the draft PR of llvm.dx.rawbufferload. There are 3 commits. I separate the DXILResourceMap change in the Raw Buffer Load PR to the third commit. [Changes in DXILResourceMap for lowering llvm.dx.rawbufferload to dxil… · lizhengxing/llvm-project@5abec9d](3a8f3a1) Patch is 30.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116845.diff 8 Files Affected:
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 6b577c02f05450..7f64688fba183a 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -264,6 +264,8 @@ class ResourceInfo {
class DXILResourceMap {
SmallVector<dxil::ResourceInfo> Resources;
DenseMap<CallInst *, unsigned> CallMap;
+ // Mapping from Resource use to Resource Handle
+ DenseMap<CallInst *, CallInst *> ResUseToHandleMap;
unsigned FirstUAV = 0;
unsigned FirstCBuffer = 0;
unsigned FirstSampler = 0;
@@ -335,6 +337,36 @@ class DXILResourceMap {
}
void print(raw_ostream &OS) const;
+
+ void updateResourceMap(CallInst *origCallInst, CallInst *newCallInst);
+
+ // Update ResUseMap with multiple new resource uses
+ void updateResUseMap(CallInst *origResUse,
+ std::vector<Value *> &multiNewResUse);
+
+ // Update ResUseMap with single new resource use
+ void updateResUseMap(CallInst *origResUse, CallInst *newResUse) {
+ assert((origResUse != nullptr) && (newResUse != nullptr) &&
+ (origResUse != newResUse) && "Wrong Inputs");
+
+ updateResUseMapCommon(origResUse, newResUse, /*keepOrigResUseInMap=*/false);
+ }
+
+ CallInst *findResHandleByUse(CallInst *resUse) {
+ auto Pos = ResUseToHandleMap.find(resUse);
+ assert((Pos != ResUseToHandleMap.end()) &&
+ "Can't find the resource handle");
+
+ return Pos->second;
+ }
+
+private:
+ void updateResUseMapCommon(CallInst *origResUse, CallInst *newResUse,
+ bool keepOrigResUseInMap) {
+ ResUseToHandleMap.try_emplace(newResUse, findResHandleByUse(origResUse));
+ if (!keepOrigResUseInMap)
+ ResUseToHandleMap.erase(origResUse);
+ }
};
class DXILResourceAnalysis : public AnalysisInfoMixin<DXILResourceAnalysis> {
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 48a9595f844f05..d8be8d002a0917 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -27,6 +27,9 @@ def int_dx_handle_fromBinding
[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
[IntrNoMem]>;
+def int_dx_rawBufferLoad
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty, llvm_i32_ty]>;
+
def int_dx_typedBufferLoad
: DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty],
[IntrReadMem]>;
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 2802480481690d..be4fad8a84a171 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -719,6 +719,12 @@ DXILResourceMap::DXILResourceMap(
if (Resources.empty() || RI != Resources.back())
Resources.push_back(RI);
CallMap[CI] = Resources.size() - 1;
+
+ // Build ResUseToHandleMap
+ for (auto it = CI->users().begin(); it != CI->users().end(); ++it) {
+ CallInst *CI_Use = dyn_cast<CallInst>(*it);
+ ResUseToHandleMap[CI_Use] = CI;
+ }
}
unsigned Size = Resources.size();
@@ -744,6 +750,61 @@ DXILResourceMap::DXILResourceMap(
}
}
+// Parameter origCallInst: original Resource Handle
+// Parameter newCallInst: new Resource Handle
+//
+// This function is needed when origCallInst's lowered to newCallInst.
+//
+// Because origCallInst and its uses will be replaced by newCallInst and new def
+// instructions after lowering. The [origCallInst, resource info] entry in
+// CallMap and [origCallInst's use, origCallInst] entries in ResUseToHandleMap
+// have to be updated per the changes in lowering.
+//
+// What this function does are:
+// 1. Add [newCallInst, resource info] entry in CallMap
+// 2. Remove [origCallInst, resource info] entry in CallMap
+// 3. Remap [origCallInst's use, origCallInst] entries to
+// [origCallInst's use, newCallInst] entries in ResUseToHandleMap
+//
+// Remove those entries related to origCallInst in maps is necessary since
+// origCallInst's no longer existing after lowering. Moreover, keeping those
+// entries in maps will crash DXILResourceMap::print function
+//
+// FYI:
+// Make sure to invoke this function before origCallInst->replaceAllUsesWith()
+// and origCallInst->eraseFromParent() since this function needs to visit
+// origCallInst and its uses.
+//
+void DXILResourceMap::updateResourceMap(CallInst *origCallInst,
+ CallInst *newCallInst) {
+ assert((origCallInst != nullptr) && (newCallInst != nullptr) &&
+ (origCallInst != newCallInst));
+
+ CallMap.try_emplace(newCallInst, CallMap[origCallInst]);
+ CallMap.erase(origCallInst);
+
+ // Update ResUseToHandleMap since Resource Handle changed
+ for (auto it = origCallInst->users().begin();
+ it != origCallInst->users().end(); ++it) {
+ CallInst *CI_Use = dyn_cast<CallInst>(*it);
+ ResUseToHandleMap[CI_Use] = newCallInst;
+ }
+}
+
+ void DXILResourceMap::updateResUseMap(CallInst *origResUse,
+ std::vector<Value *> &multiNewResUse) {
+ assert((origResUse != nullptr) && "Wrong Inputs");
+
+ for (int i = 0; i < multiNewResUse.size(); ++i) {
+ CallInst *newResUse = dyn_cast<CallInst>(multiNewResUse[i]);
+ assert(newResUse != nullptr);
+
+ bool keepOrigResUseInMap =
+ i == (multiNewResUse.size() - 1) ? false : true;
+ updateResUseMapCommon(origResUse, newResUse, keepOrigResUseInMap);
+ }
+ }
+
void DXILResourceMap::print(raw_ostream &OS) const {
for (unsigned I = 0, E = Resources.size(); I != E; ++I) {
OS << "Binding " << I << ":\n";
@@ -756,6 +817,14 @@ void DXILResourceMap::print(raw_ostream &OS) const {
CI->print(OS);
OS << "\n";
}
+
+ for (const auto &[ResUse, ResHandle] : ResUseToHandleMap) {
+ OS << "\n";
+ OS << "Resource " << CallMap.find(ResHandle)->second;
+ OS << " is used by ";
+ ResUse->print(OS);
+ OS << "\n";
+ }
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 1a8e110491cc87..a638371d6031ad 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -854,6 +854,17 @@ def AnnotateHandle : DXILOp<216, annotateHandle> {
let stages = [Stages<DXIL1_6, [all_stages]>];
}
+def RawBufferLoad : DXILOp<139, rawBufferLoad> {
+ let Doc = "reads from a ByteAddressBuffer or StructuredBuffer";
+ // Handle, Coord0, Coord1, mask, alignment
+ let arguments = [HandleTy, Int32Ty, Int32Ty, Int8Ty, Int32Ty];
+ let result = OverloadTy;
+ let overloads =
+ [Overloads<DXIL1_0,
+ [ResRetHalfTy, ResRetFloatTy, ResRetInt16Ty, ResRetInt32Ty]>];
+ let stages = [Stages<DXIL1_0, [all_stages]>];
+}
+
def CreateHandleFromBinding : DXILOp<217, createHandleFromBinding> {
let Doc = "create resource handle from binding";
let arguments = [ResBindTy, Int32Ty, Int1Ty];
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index 9f124394363a38..d2b6f05fc936bd 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -249,6 +249,8 @@ class OpLowerer {
removeResourceGlobals(CI);
+ DRM.updateResourceMap(CI, *OpCall);
+
CI->replaceAllUsesWith(Cast);
CI->eraseFromParent();
return Error::success();
@@ -295,6 +297,8 @@ class OpLowerer {
removeResourceGlobals(CI);
+ DRM.updateResourceMap(CI, *OpBind);
+
CI->replaceAllUsesWith(Cast);
CI->eraseFromParent();
@@ -479,6 +483,9 @@ class OpLowerer {
OpCode::BufferLoad, Args, CI->getName(), NewRetTy);
if (Error E = OpCall.takeError())
return E;
+
+ DRM.updateResUseMap(CI, *OpCall);
+
if (Error E = replaceResRetUses(CI, *OpCall, HasCheckBit))
return E;
@@ -547,6 +554,8 @@ class OpLowerer {
if (Error E = OpCall.takeError())
return E;
+ DRM.updateResUseMap(CI, *OpCall);
+
CI->eraseFromParent();
return Error::success();
});
@@ -619,6 +628,193 @@ class OpLowerer {
});
}
+ Value *GenerateRawBufLd(Value *handle, Value *bufIdx, Value *offset, Type *Ty,
+ IRBuilder<> &Builder, unsigned NumComponents,
+ Constant *alignment) {
+ if (bufIdx == nullptr) {
+ // This is actually a byte address buffer load with a struct template
+ // type. The call takes only one coordinates for the offset.
+ bufIdx = offset;
+ offset = UndefValue::get(offset->getType());
+ }
+
+ // NumComponents 1: mask = 1 // Mask_X;
+ // NumComponents 2: mask = 3 // Mask_X | Mask_Y
+ // NumComponents 3: mask = 7 // Mask_X | Mask_Y | Mask_Z
+ // NumComponents 4: mask = 15 // Mask_X | Mask_Y | Mask_Z | Mask_W
+ assert((NumComponents) > 0 && (NumComponents < 5));
+ Constant *mask =
+ ConstantInt::get(Builder.getInt8Ty(), ((1 << NumComponents) - 1));
+
+ Value *Args[] = {handle, bufIdx, offset, mask, alignment};
+ Type *NewRetTy = OpBuilder.getResRetType(Ty->getScalarType());
+ Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
+ OpCode::RawBufferLoad, Args, "", NewRetTy); // TODO: Need name argument?
+ if (Error E = OpCall.takeError())
+ return nullptr;
+
+ return *OpCall;
+ }
+
+ void TranslateRawBufVecLd(Type *Ty, unsigned ElemCount, IRBuilder<> &Builder,
+ Value *handle, Value *bufIdx, Value *baseOffset,
+ const DataLayout &DL, std::vector<Value *> &bufLds,
+ unsigned baseAlign, bool isScalarTy) {
+ Type *VecEltTy = Ty->getScalarType();
+
+ unsigned EltSize = DL.getTypeAllocSize(VecEltTy);
+ unsigned alignment = std::min(baseAlign, EltSize);
+ Constant *alignmentVal =
+ ConstantInt::get(M.getContext(), APInt(32, alignment));
+
+ if (baseOffset == nullptr) {
+ baseOffset = ConstantInt::get(Builder.getInt32Ty(), 0);
+ }
+
+ std::vector<Value *> elts(ElemCount);
+ unsigned rest = (ElemCount % 4);
+ for (unsigned i = 0; i < ElemCount - rest; i += 4) {
+ Value *bufLd = GenerateRawBufLd(handle, bufIdx, baseOffset, Ty, Builder,
+ 4, alignmentVal);
+ bufLds.emplace_back(bufLd);
+
+ baseOffset = Builder.CreateAdd(
+ baseOffset, ConstantInt::get(Builder.getInt32Ty(), 4 * EltSize));
+ }
+
+ if (rest) {
+ Value *bufLd = GenerateRawBufLd(handle, bufIdx, baseOffset, Ty, Builder,
+ rest, alignmentVal);
+ bufLds.emplace_back(bufLd);
+ }
+ }
+
+ Error replaceMultiResRetsUses(CallInst *Intrin,
+ std::vector<Value *> &bufLds) {
+ IRBuilder<> &IRB = OpBuilder.getIRB();
+
+ // TODO: HasCheckBit????
+
+ Type *OldTy = Intrin->getType();
+
+ // For scalars, we just extract the first element.
+ if (!isa<FixedVectorType>(OldTy)) {
+ CallInst *Op = dyn_cast<CallInst>(bufLds[0]);
+ assert(Op != nullptr);
+ Value *EVI = IRB.CreateExtractValue(Op, 0);
+
+ Intrin->replaceAllUsesWith(EVI);
+ DRM.updateResUseMap(Intrin, Op);
+ Intrin->eraseFromParent();
+
+ return Error::success();
+ }
+
+ const auto *VecTy = cast<FixedVectorType>(OldTy);
+ const unsigned N = VecTy->getNumElements();
+
+ std::vector<Value *> Extracts(N);
+
+ // The users of the operation should all be scalarized, so we attempt to
+ // replace the extractelements with extractvalues directly.
+ for (Use &U : make_early_inc_range(Intrin->uses())) {
+ if (auto *EEI = dyn_cast<ExtractElementInst>(U.getUser())) {
+ if (auto *IndexOp = dyn_cast<ConstantInt>(EEI->getIndexOperand())) {
+ size_t IndexVal = IndexOp->getZExtValue();
+ assert(IndexVal < N && "Index into buffer load out of range");
+ if (!Extracts[IndexVal]) {
+ CallInst *Op = dyn_cast<CallInst>(bufLds[IndexVal / 4]);
+ assert(Op != nullptr);
+ Extracts[IndexVal] = IRB.CreateExtractValue(Op, IndexVal % 4);
+ }
+ EEI->replaceAllUsesWith(Extracts[IndexVal]);
+ EEI->eraseFromParent();
+ } else {
+ // Need to handle DynamicAccesses here???
+ }
+ }
+ }
+
+ // If there's a dynamic access we need to round trip through stack memory so
+ // that we don't leave vectors around.
+ //
+ // TODO: dynamic access for rawbuffer??????
+ //
+
+ // If we still have uses, then we're not fully scalarized and need to
+ // recreate the vector. This should only happen for things like exported
+ // functions from libraries.
+ if (!Intrin->use_empty()) {
+ for (int I = 0, E = N; I != E; ++I)
+ if (!Extracts[I]) {
+ CallInst *Op = dyn_cast<CallInst>(bufLds[I / 4]);
+ assert(Op != nullptr);
+ Extracts[I] = IRB.CreateExtractValue(Op, I % 4);
+ }
+
+ Value *Vec = UndefValue::get(OldTy);
+ for (int I = 0, E = N; I != E; ++I)
+ Vec = IRB.CreateInsertElement(Vec, Extracts[I], I);
+
+ Intrin->replaceAllUsesWith(Vec);
+ }
+
+ // TODO:
+ // Remove the dx.op.rawbufferload without any uses now?
+
+ DRM.updateResUseMap(Intrin, bufLds);
+ Intrin->eraseFromParent();
+
+ return Error::success();
+ }
+
+ [[nodiscard]] bool lowerRawBufferLoad(Function &F) {
+ IRBuilder<> &IRB = OpBuilder.getIRB();
+
+ return replaceFunction(F, [&](CallInst *CI) -> Error {
+ IRB.SetInsertPoint(CI);
+
+ auto *It = DRM.find(DRM.findResHandleByUse(CI));
+ assert(It != DRM.end() && "Resource not in map?");
+ dxil::ResourceInfo &RI = *It;
+
+ ResourceKind RCKind = RI.getResourceKind();
+ assert((RCKind == dxil::ResourceKind::StructuredBuffer) ||
+ (RCKind == dxil::ResourceKind::RawBuffer));
+
+ Type *Ty = CI->getType();
+ std::vector<Value *> bufLds;
+ // TODO: Need check Bool type load???
+
+ unsigned numComponents = 1;
+ if (Ty->isVectorTy()) {
+ numComponents = dyn_cast<FixedVectorType>(Ty)->getNumElements();
+ }
+
+ Value *Handle =
+ createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());
+ Value *bufIdx = CI->getArgOperand(1);
+ Value *baseOffset = CI->getArgOperand(2);
+
+ bool isScalarTy = !Ty->isVectorTy();
+
+ if (RCKind == dxil::ResourceKind::StructuredBuffer) {
+ TranslateRawBufVecLd(Ty, numComponents, IRB, Handle, bufIdx, baseOffset,
+ F.getDataLayout(), bufLds,
+ /*baseAlign (in bytes)*/ 8, isScalarTy);
+ } else {
+ TranslateRawBufVecLd(Ty, numComponents, IRB, Handle, bufIdx, baseOffset,
+ F.getDataLayout(), bufLds,
+ /*baseAlign (in bytes)*/ 4, isScalarTy);
+ }
+
+ if (Error E = replaceMultiResRetsUses(CI, bufLds))
+ return E;
+
+ return Error::success();
+ });
+ }
+
bool lowerIntrinsics() {
bool Updated = false;
bool HasErrors = false;
@@ -638,6 +834,9 @@ class OpLowerer {
case Intrinsic::dx_handle_fromBinding:
HasErrors |= lowerHandleFromBinding(F);
break;
+ case Intrinsic::dx_rawBufferLoad:
+ HasErrors |= lowerRawBufferLoad(F);
+ break;
case Intrinsic::dx_typedBufferLoad:
HasErrors |= lowerTypedBufferLoad(F, /*HasCheckBit=*/false);
break;
diff --git a/llvm/test/Analysis/DXILResource/resource-map.ll b/llvm/test/Analysis/DXILResource/resource-map.ll
new file mode 100644
index 00000000000000..65255d4c942e53
--- /dev/null
+++ b/llvm/test/Analysis/DXILResource/resource-map.ll
@@ -0,0 +1,36 @@
+; RUN: opt -S -disable-output -disable-output -passes="print<dxil-resource>" < %s 2>&1 | FileCheck %s
+
+define void @test_typedbuffer() {
+ ; RWBuffer<float4> Buf : register(u5, space3)
+ %uav1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0(
+ i32 3, i32 5, i32 1, i32 0, i1 false)
+ ; CHECK: Binding [[UAV1:[0-9]+]]:
+ ; CHECK: Symbol: ptr undef
+ ; CHECK: Name: ""
+ ; CHECK: Binding:
+ ; CHECK: Record ID: 0
+ ; CHECK: Space: 3
+ ; CHECK: Lower Bound: 5
+ ; CHECK: Size: 1
+ ; CHECK: Class: UAV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Globally Coherent: 0
+ ; CHECK: HasCounter: 0
+ ; CHECK: IsROV: 0
+ ; CHECK: Element Type: f32
+ ; CHECK: Element Count: 4
+
+ ; CHECK: Call bound to [[UAV1]]: %uav1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
+ ; CHECK-DAG: Resource [[UAV1]] is used by %data0 = call <4 x float> @llvm.dx.typedBufferLoad.v4f32.tdx.TypedBuffer_v4f32_1_0_0t(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i32 0)
+ ; CHECK-DAG: Resource [[UAV1]] is used by call void @llvm.dx.typedBufferStore.tdx.TypedBuffer_v4f32_1_0_0t.v4f32(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i32 2, <4 x float> %data0)
+
+ %data0 = call <4 x float> @llvm.dx.typedBufferLoad(
+ target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i32 0)
+ call void @llvm.dx.typedBufferStore(
+ target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1,
+ i32 2, <4 x float> %data0)
+
+ ret void
+}
+
diff --git a/llvm/test/CodeGen/DirectX/DXILResource/dxil-resource-map.ll b/llvm/test/CodeGen/DirectX/DXILResource/dxil-resource-map.ll
new file mode 100644
index 00000000000000..ac5f3d16145974
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/DXILResource/dxil-resource-map.ll
@@ -0,0 +1,48 @@
+; RUN: opt -S -disable-output -disable-output -passes="print<dxil-resource>,dxil-op-lower,print<dxil-resource>" -mtriple=dxil-pc-shadermodel6.6-compute < %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK_SM66
+; RUN: opt -S -disable-output -disable-output -passes="print<dxil-resource>,dxil-op-lower,print<dxil-resource>" -mtriple=dxil-pc-shadermodel6.2-compute < %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK_SM62
+
+define void @test_typedbuffer() {
+ ; RWBuffer<float4> Buf : register(u5, space3)
+ %uav1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+ @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0(
+ i32 3, i32 5, i32 1, i32 0, i1 false)
+ ; CHECK: Binding [[UAV1:[0-9]+]]:
+ ; CHECK: Symbol: ptr undef
+ ; CHECK: Name: ""
+ ; CHECK: Binding:
+ ; CHECK: Record ID: 0
+ ; CHECK: Space: 3
+ ; CHECK: Lower Bound: 5
+ ; CHECK: Size: 1
+ ; CHECK: Class: UAV
+ ; CHECK: Kind: TypedBuffer
+ ; CHECK: Globally Coherent: 0
+ ; CHECK: HasCounter: 0
+ ; CHECK: IsROV: 0
+ ; CHECK: Element Type: f32
+ ; CHECK: Element Count: 4
+
+ ; CHECK: Call bound to [[UAV1]]: %uav1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
+ ; CHECK-DAG: Resource [[UAV1]] is used by %data0 = call <4 x float> @llvm.dx.typedBufferLoad.v4f32.tdx.TypedBuffer_v4f32_1_0_0t(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i32 0)
+ ; CHECK-DAG: Resource [[UAV1]] is used by call void @llvm.dx.typedBufferStore.tdx.TypedBuffer_v4f32_1_0_0t.v4f32(target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i32 2, <4 x float> %data0)
+
+ %data0 = call <4 x float> @llvm.dx.typedBufferLoad(
+ target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1, i32 0)
+ call void @llvm.dx.typedBufferStore(
+ target("dx.TypedBuffer", <4 x float>, 1, 0, 0) %uav1,
+ i32 2, <4 x float> %data0)
+
+ ;
+ ;;; After dxil-op-lower, the DXILResourceMap info should be updated.
+ ;
+ ; CHECK_SM66: Call bound to [[UAV1]]: %uav11 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 5, i32 5, i32 3, i8 1 }, i32 0, i1 false)
+ ; CHECK_SM66-DAG: Resource [[UAV1]] is used by %data02 = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %uav1_annot, i32 0, i32 undef)
+ ; CHECK_SM66-DAG: Resource [[UAV1]] is used by call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %uav1_annot, i32 2, i32 undef, float %9, float %10, float %11, float %12, i8 1...
[truncated]
|
@lizhengxing - looks like there's some conflicts that need resolving before completing this. The description mentions it is a draft. Is this PR still something you want us to review and take in? |
No, there's no review needed for this draft PR. I'll re-work the PR based on Justin's feedback. |
Should we convert it to draft then? |
Done. Converted it to draft. |
I think this is superceded by #121012. Sorry to step on your toes here but things changed somewhat significantly in the area. |
As @bogner mentioned in the latest comment, things changed a lot in the area. |
It's the draft PR of llvm.dx.rawbufferload.
There are 3 commits.
The DXILResourceMap change: [[DirectX] Add Resource uses to Resource Handle map in DXILResourceMap · lizhengxing/llvm-project@392daa1](8e1bca0)
The Raw Buffer Load change: [Lower llvm.dx.rawbufferload to dxil ops · lizhengxing/llvm-project@731703f](27c361b)
I separate the DXILResourceMap change in the Raw Buffer Load PR to the third commit. [Changes in DXILResourceMap for lowering llvm.dx.rawbufferload to dxil… · lizhengxing/llvm-project@5abec9d](3a8f3a1)