1 //===- llvm/unittests/Target/DirectX/PointerTypeAnalysisTests.cpp ---------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 #include "DirectXIRPasses/PointerTypeAnalysis.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/Instructions.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/IR/Type.h"
15 #include "llvm/IR/TypedPointerType.h"
16 #include "llvm/Support/SourceMgr.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
21 using ::testing::Contains
;
22 using ::testing::Pair
;
25 using namespace llvm::dxil
;
27 template <typename T
> struct IsA
{
28 friend bool operator==(const Value
*V
, const IsA
&) { return isa
<T
>(V
); }
31 TEST(PointerTypeAnalysis
, DigressToi8
) {
32 StringRef Assembly
= R
"(
33 define i64 @test(ptr %p) {
42 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
43 ASSERT_TRUE(M
) << "Bad assembly?";
45 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
46 ASSERT_EQ(Map
.size(), 2u);
47 Type
*I8Ptr
= TypedPointerType::get(Type::getInt8Ty(Context
), 0);
48 Type
*FnTy
= FunctionType::get(Type::getInt64Ty(Context
), {I8Ptr
}, false);
51 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
52 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I8Ptr
)));
55 TEST(PointerTypeAnalysis
, DiscoverStore
) {
56 StringRef Assembly
= R
"(
57 define i32 @test(ptr %p) {
65 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
66 ASSERT_TRUE(M
) << "Bad assembly?";
68 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
69 ASSERT_EQ(Map
.size(), 2u);
70 Type
*I32Ptr
= TypedPointerType::get(Type::getInt32Ty(Context
), 0);
71 Type
*FnTy
= FunctionType::get(Type::getInt32Ty(Context
), {I32Ptr
}, false);
74 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
75 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I32Ptr
)));
78 TEST(PointerTypeAnalysis
, DiscoverLoad
) {
79 StringRef Assembly
= R
"(
80 define i32 @test(ptr %p) {
88 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
89 ASSERT_TRUE(M
) << "Bad assembly?";
91 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
92 ASSERT_EQ(Map
.size(), 2u);
93 Type
*I32Ptr
= TypedPointerType::get(Type::getInt32Ty(Context
), 0);
94 Type
*FnTy
= FunctionType::get(Type::getInt32Ty(Context
), {I32Ptr
}, false);
97 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
98 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I32Ptr
)));
101 TEST(PointerTypeAnalysis
, DiscoverGEP
) {
102 StringRef Assembly
= R
"(
103 define ptr @test(ptr %p) {
104 %p2 = getelementptr i64, ptr %p, i64 1
111 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
112 ASSERT_TRUE(M
) << "Bad assembly?";
114 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
115 ASSERT_EQ(Map
.size(), 3u);
117 Type
*I64Ptr
= TypedPointerType::get(Type::getInt64Ty(Context
), 0);
118 Type
*FnTy
= FunctionType::get(I64Ptr
, {I64Ptr
}, false);
121 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
122 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I64Ptr
)));
123 EXPECT_THAT(Map
, Contains(Pair(IsA
<GetElementPtrInst
>(), I64Ptr
)));
126 TEST(PointerTypeAnalysis
, TraceIndirect
) {
127 StringRef Assembly
= R
"(
128 define i64 @test(ptr %p) {
129 %p2 = load ptr, ptr %p
130 %v = load i64, ptr %p2
137 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
138 ASSERT_TRUE(M
) << "Bad assembly?";
140 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
141 ASSERT_EQ(Map
.size(), 3u);
143 Type
*I64Ptr
= TypedPointerType::get(Type::getInt64Ty(Context
), 0);
144 Type
*I64PtrPtr
= TypedPointerType::get(I64Ptr
, 0);
145 Type
*FnTy
= FunctionType::get(Type::getInt64Ty(Context
), {I64PtrPtr
}, false);
148 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
149 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I64PtrPtr
)));
150 EXPECT_THAT(Map
, Contains(Pair(IsA
<LoadInst
>(), I64Ptr
)));
153 TEST(PointerTypeAnalysis
, WithNoOpCasts
) {
154 StringRef Assembly
= R
"(
155 define i64 @test(ptr %p) {
156 %1 = bitcast ptr %p to ptr
157 %2 = bitcast ptr %p to ptr
158 store i32 0, ptr %1, align 4
159 %3 = load i64, ptr %2, align 8
166 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
167 ASSERT_TRUE(M
) << "Bad assembly?";
169 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
170 ASSERT_EQ(Map
.size(), 4u);
172 Type
*I8Ptr
= TypedPointerType::get(Type::getInt8Ty(Context
), 0);
173 Type
*I32Ptr
= TypedPointerType::get(Type::getInt32Ty(Context
), 0);
174 Type
*I64Ptr
= TypedPointerType::get(Type::getInt64Ty(Context
), 0);
175 Type
*FnTy
= FunctionType::get(Type::getInt64Ty(Context
), {I8Ptr
}, false);
178 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
179 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I8Ptr
)));
180 EXPECT_THAT(Map
, Contains(Pair(IsA
<BitCastInst
>(), I64Ptr
)));
181 EXPECT_THAT(Map
, Contains(Pair(IsA
<BitCastInst
>(), I32Ptr
)));