209 lines · cpp
1//===- llvm/unittests/Target/DirectX/PointerTypeAnalysisTests.cpp ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DirectXTargetMachine.h"10#include "llvm/Analysis/DXILResource.h"11#include "llvm/AsmParser/Parser.h"12#include "llvm/CodeGen/CommandFlags.h"13#include "llvm/IR/Instructions.h"14#include "llvm/IR/IntrinsicsDirectX.h"15#include "llvm/IR/LLVMContext.h"16#include "llvm/IR/Module.h"17#include "llvm/IR/Type.h"18#include "llvm/Passes/PassBuilder.h"19#include "llvm/Support/Casting.h"20#include "llvm/Support/SourceMgr.h"21 22#include "gtest/gtest.h"23 24using namespace llvm;25using namespace llvm::dxil;26 27namespace {28class UniqueResourceFromUseTest : public testing::Test {29protected:30 PassBuilder *PB;31 ModuleAnalysisManager *MAM;32 LLVMContext *Context;33 virtual void SetUp() {34 Context = new LLVMContext();35 MAM = new ModuleAnalysisManager();36 PB = new PassBuilder();37 PB->registerModuleAnalyses(*MAM);38 MAM->registerPass([&] { return DXILResourceTypeAnalysis(); });39 MAM->registerPass([&] { return DXILResourceAnalysis(); });40 }41 42 std::unique_ptr<Module> parseAsm(StringRef Asm) {43 SMDiagnostic Error;44 std::unique_ptr<Module> M = parseAssemblyString(Asm, Error, *Context);45 EXPECT_TRUE(M) << "Bad assembly?: " << Error.getMessage();46 return M;47 }48 49 virtual void TearDown() {50 delete PB;51 delete MAM;52 delete Context;53 }54};55 56// Test that several calls to decrement on the same resource don't raise a57// Diagnositic and resolves to a single decrement entry58TEST_F(UniqueResourceFromUseTest, TestResourceCounterDecrement) {59 StringRef Assembly = R"(60define void @main() {61entry:62 %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, ptr null)63 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)64 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)65 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)66 ret void67}68 )";69 70 auto M = parseAsm(Assembly);71 72 DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);73 74 for (const Function &F : M->functions()) {75 if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding)76 continue;77 78 for (const User *U : F.users()) {79 const CallInst *CI = cast<CallInst>(U);80 const auto *const Binding = DRM.find(CI);81 ASSERT_EQ(Binding->CounterDirection, ResourceCounterDirection::Decrement);82 }83 }84}85 86// Test that several calls to increment on the same resource don't raise a87// Diagnositic and resolves to a single increment entry88TEST_F(UniqueResourceFromUseTest, TestResourceCounterIncrement) {89 StringRef Assembly = R"(90define void @main() {91entry:92 %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, ptr null)93 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)94 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)95 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)96 ret void97}98 )";99 100 auto M = parseAsm(Assembly);101 102 DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);103 104 for (const Function &F : M->functions()) {105 if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding)106 continue;107 108 for (const User *U : F.users()) {109 const CallInst *CI = cast<CallInst>(U);110 const auto *const Binding = DRM.find(CI);111 ASSERT_EQ(Binding->CounterDirection, ResourceCounterDirection::Increment);112 }113 }114}115 116// Test that looking up a resource that doesn't have the counter updated117// resoves to unknown118TEST_F(UniqueResourceFromUseTest, TestResourceCounterUnknown) {119 StringRef Assembly = R"(120define void @main() {121entry:122 %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, ptr null)123 ret void124}125 )";126 127 auto M = parseAsm(Assembly);128 129 DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);130 131 for (const Function &F : M->functions()) {132 if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding)133 continue;134 135 for (const User *U : F.users()) {136 const CallInst *CI = cast<CallInst>(U);137 const auto *const Binding = DRM.find(CI);138 ASSERT_EQ(Binding->CounterDirection, ResourceCounterDirection::Unknown);139 }140 }141}142 143// Test that multiple different resources with unique incs/decs aren't144// marked invalid145TEST_F(UniqueResourceFromUseTest, TestResourceCounterMultiple) {146 StringRef Assembly = R"(147define void @main() {148entry:149 %handle1 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, ptr null)150 %handle2 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 4, i32 3, i32 2, i32 1, ptr null)151 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle1, i8 -1)152 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle2, i8 1)153 ret void154}155 )";156 157 auto M = parseAsm(Assembly);158 159 DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);160 161 ResourceCounterDirection Dirs[2] = {ResourceCounterDirection::Decrement,162 ResourceCounterDirection::Increment};163 ResourceCounterDirection *Dir = Dirs;164 165 for (const Function &F : M->functions()) {166 if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding)167 continue;168 169 uint32_t ExpectedDirsIndex = 0;170 for (const User *U : F.users()) {171 const CallInst *CI = cast<CallInst>(U);172 const auto *const Binding = DRM.find(CI);173 ASSERT_TRUE(ExpectedDirsIndex < 2);174 ASSERT_EQ(Binding->CounterDirection, Dir[ExpectedDirsIndex]);175 ExpectedDirsIndex++;176 }177 }178}179 180// Test that single different resources with unique incs/decs is marked invalid181TEST_F(UniqueResourceFromUseTest, TestResourceCounterInvalid) {182 StringRef Assembly = R"(183define void @main() {184entry:185 %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, ptr null)186 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)187 call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)188 ret void189}190 )";191 192 auto M = parseAsm(Assembly);193 194 DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);195 196 for (const Function &F : M->functions()) {197 if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding)198 continue;199 200 for (const User *U : F.users()) {201 const CallInst *CI = cast<CallInst>(U);202 const auto *const Binding = DRM.find(CI);203 ASSERT_EQ(Binding->CounterDirection, ResourceCounterDirection::Invalid);204 }205 }206}207 208} // namespace209