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/Type.h"
14 #include "llvm/IR/TypedPointerType.h"
15 #include "llvm/Support/SourceMgr.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
20 using ::testing::Contains
;
21 using ::testing::Pair
;
24 using namespace llvm::dxil
;
26 template <typename T
> struct IsA
{
27 friend bool operator==(const Value
*V
, const IsA
&) { return isa
<T
>(V
); }
30 TEST(PointerTypeAnalysis
, DigressToi8
) {
31 StringRef Assembly
= R
"(
32 define i64 @test(ptr %p) {
41 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
42 ASSERT_TRUE(M
) << "Bad assembly?";
44 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
45 ASSERT_EQ(Map
.size(), 2u);
46 Type
*I8Ptr
= TypedPointerType::get(Type::getInt8Ty(Context
), 0);
47 Type
*FnTy
= FunctionType::get(Type::getInt64Ty(Context
), {I8Ptr
}, false);
50 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
51 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I8Ptr
)));
54 TEST(PointerTypeAnalysis
, DiscoverStore
) {
55 StringRef Assembly
= R
"(
56 define i32 @test(ptr %p) {
64 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
65 ASSERT_TRUE(M
) << "Bad assembly?";
67 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
68 ASSERT_EQ(Map
.size(), 2u);
69 Type
*I32Ptr
= TypedPointerType::get(Type::getInt32Ty(Context
), 0);
70 Type
*FnTy
= FunctionType::get(Type::getInt32Ty(Context
), {I32Ptr
}, false);
73 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
74 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I32Ptr
)));
77 TEST(PointerTypeAnalysis
, DiscoverLoad
) {
78 StringRef Assembly
= R
"(
79 define i32 @test(ptr %p) {
87 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
88 ASSERT_TRUE(M
) << "Bad assembly?";
90 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
91 ASSERT_EQ(Map
.size(), 2u);
92 Type
*I32Ptr
= TypedPointerType::get(Type::getInt32Ty(Context
), 0);
93 Type
*FnTy
= FunctionType::get(Type::getInt32Ty(Context
), {I32Ptr
}, false);
96 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
97 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I32Ptr
)));
100 TEST(PointerTypeAnalysis
, DiscoverGEP
) {
101 StringRef Assembly
= R
"(
102 define ptr @test(ptr %p) {
103 %p2 = getelementptr i64, ptr %p, i64 1
110 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
111 ASSERT_TRUE(M
) << "Bad assembly?";
113 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
114 ASSERT_EQ(Map
.size(), 3u);
116 Type
*I64Ptr
= TypedPointerType::get(Type::getInt64Ty(Context
), 0);
117 Type
*FnTy
= FunctionType::get(I64Ptr
, {I64Ptr
}, false);
120 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
121 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I64Ptr
)));
122 EXPECT_THAT(Map
, Contains(Pair(IsA
<GetElementPtrInst
>(), I64Ptr
)));
125 TEST(PointerTypeAnalysis
, TraceIndirect
) {
126 StringRef Assembly
= R
"(
127 define i64 @test(ptr %p) {
128 %p2 = load ptr, ptr %p
129 %v = load i64, ptr %p2
136 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
137 ASSERT_TRUE(M
) << "Bad assembly?";
139 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
140 ASSERT_EQ(Map
.size(), 3u);
142 Type
*I64Ptr
= TypedPointerType::get(Type::getInt64Ty(Context
), 0);
143 Type
*I64PtrPtr
= TypedPointerType::get(I64Ptr
, 0);
144 Type
*FnTy
= FunctionType::get(Type::getInt64Ty(Context
), {I64PtrPtr
}, false);
147 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
148 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I64PtrPtr
)));
149 EXPECT_THAT(Map
, Contains(Pair(IsA
<LoadInst
>(), I64Ptr
)));
152 TEST(PointerTypeAnalysis
, WithNoOpCasts
) {
153 StringRef Assembly
= R
"(
154 define i64 @test(ptr %p) {
155 %1 = bitcast ptr %p to ptr
156 %2 = bitcast ptr %p to ptr
157 store i32 0, ptr %1, align 4
158 %3 = load i64, ptr %2, align 8
165 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
166 ASSERT_TRUE(M
) << "Bad assembly?";
168 PointerTypeMap Map
= PointerTypeAnalysis::run(*M
);
169 ASSERT_EQ(Map
.size(), 4u);
171 Type
*I8Ptr
= TypedPointerType::get(Type::getInt8Ty(Context
), 0);
172 Type
*I32Ptr
= TypedPointerType::get(Type::getInt32Ty(Context
), 0);
173 Type
*I64Ptr
= TypedPointerType::get(Type::getInt64Ty(Context
), 0);
174 Type
*FnTy
= FunctionType::get(Type::getInt64Ty(Context
), {I8Ptr
}, false);
177 Contains(Pair(IsA
<Function
>(), TypedPointerType::get(FnTy
, 0))));
178 EXPECT_THAT(Map
, Contains(Pair(IsA
<Argument
>(), I8Ptr
)));
179 EXPECT_THAT(Map
, Contains(Pair(IsA
<BitCastInst
>(), I64Ptr
)));
180 EXPECT_THAT(Map
, Contains(Pair(IsA
<BitCastInst
>(), I32Ptr
)));