llvm-project/llvm/unittests/Target/DirectX/ResourceBindingAnalysisTests.cpp
Justin Bogner 3f066f5fcf
[HLSL][DirectX] Extract HLSLBinding out of DXILResource. NFC (#150633)
We extract the binding logic out of the DXILResource analysis passes into the
FrontendHLSL library. This will allow us to use this logic for resource and
root signature bindings in both the DirectX backend and the HLSL frontend.
2025-07-31 08:35:47 -07:00

133 lines
4.1 KiB
C++

//===- llvm/unittests/Target/DirectX/ResourceBindingAnalysisTests.cpp -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Analysis/DXILResource.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/DXILABI.h"
#include "gtest/gtest.h"
#include <cstdint>
using namespace llvm;
using namespace llvm::dxil;
namespace {
class ResourceBindingAnalysisTest : public testing::Test {
protected:
PassBuilder *PB;
ModuleAnalysisManager *MAM;
LLVMContext *Context;
virtual void SetUp() {
PB = new PassBuilder();
MAM = new ModuleAnalysisManager();
Context = new LLVMContext();
PB->registerModuleAnalyses(*MAM);
MAM->registerPass([&] { return DXILResourceBindingAnalysis(); });
}
std::unique_ptr<Module> parseAsm(StringRef Asm) {
SMDiagnostic Error;
std::unique_ptr<Module> M = parseAssemblyString(Asm, Error, *Context);
EXPECT_TRUE(M) << "Bad assembly?: " << Error.getMessage();
return M;
}
virtual void TearDown() {
delete PB;
delete MAM;
delete Context;
}
};
TEST_F(ResourceBindingAnalysisTest, TestTrivialCase) {
// RWBuffer<float> Buf : register(u5);
StringRef Assembly = R"(
define void @main() {
entry:
%handle = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 5, i32 1, i32 0, i1 false, ptr null)
ret void
}
)";
auto M = parseAsm(Assembly);
DXILResourceBindingInfo &DRBI =
MAM->getResult<DXILResourceBindingAnalysis>(*M);
EXPECT_EQ(false, DRBI.hasImplicitBinding());
EXPECT_EQ(false, DRBI.hasOverlappingBinding());
}
TEST_F(ResourceBindingAnalysisTest, TestOverlap) {
// StructuredBuffer<float> A[] : register(t0, space2);
// StructuredBuffer<float> B : register(t4, space2); /* overlapping */
StringRef Assembly = R"(
define void @main() {
entry:
%handleA = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 0, i32 -1, i32 100, i1 false, ptr null)
%handleB = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 4, i32 1, i32 0, i1 false, ptr null)
ret void
}
)";
auto M = parseAsm(Assembly);
DXILResourceBindingInfo &DRBI =
MAM->getResult<DXILResourceBindingAnalysis>(*M);
EXPECT_EQ(false, DRBI.hasImplicitBinding());
EXPECT_EQ(true, DRBI.hasOverlappingBinding());
}
TEST_F(ResourceBindingAnalysisTest, TestExactOverlap) {
// StructuredBuffer<float> A : register(t5);
// StructuredBuffer<float> B : register(t5);
StringRef Assembly = R"(
@A.str = private unnamed_addr constant [2 x i8] c"A\00", align 1
@B.str = private unnamed_addr constant [2 x i8] c"B\00", align 1
define void @main() {
entry:
%handleA = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 5, i32 1, i32 0, i1 false, ptr @A.str)
%handleB = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 5, i32 1, i32 0, i1 false, ptr @B.str)
ret void
}
)";
auto M = parseAsm(Assembly);
DXILResourceBindingInfo &DRBI =
MAM->getResult<DXILResourceBindingAnalysis>(*M);
EXPECT_EQ(false, DRBI.hasImplicitBinding());
EXPECT_EQ(true, DRBI.hasOverlappingBinding());
}
TEST_F(ResourceBindingAnalysisTest, TestImplicitFlag) {
// RWBuffer<float> A : register(u5, space100);
// RWBuffer<float> B;
StringRef Assembly = R"(
define void @main() {
entry:
%handleA = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 100, i32 5, i32 1, i32 0, i1 false, ptr null)
%handleB = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefromimplicitbinding(i32 0, i32 0, i32 1, i32 0, i1 false, ptr null)
ret void
}
)";
auto M = parseAsm(Assembly);
DXILResourceBindingInfo &DRBI =
MAM->getResult<DXILResourceBindingAnalysis>(*M);
EXPECT_TRUE(DRBI.hasImplicitBinding());
EXPECT_FALSE(DRBI.hasOverlappingBinding());
}
} // namespace