1 //===- AttributorTest.cpp - Attributor unit tests ------------------------===//
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 "llvm/Transforms/IPO/Attributor.h"
10 #include "AttributorTestBase.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Analysis/CGSCCPassManager.h"
13 #include "llvm/Analysis/CallGraphSCCPass.h"
14 #include "llvm/Analysis/LoopAnalysisManager.h"
15 #include "llvm/AsmParser/Parser.h"
16 #include "llvm/Support/Allocator.h"
17 #include "llvm/Testing/Support/Error.h"
18 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
19 #include "gtest/gtest.h"
24 TEST_F(AttributorTestBase
, IRPPositionCallBaseContext
) {
25 const char *ModuleString
= R
"(
26 define i32 @foo(i32 %a) {
32 parseModule(ModuleString
);
34 Function
*F
= M
->getFunction("foo");
36 IRPosition::function(*F
, (const llvm::CallBase
*)(uintptr_t)0xDEADBEEF);
37 EXPECT_TRUE(Pos
.hasCallBaseContext());
38 EXPECT_FALSE(Pos
.stripCallBaseContext().hasCallBaseContext());
41 TEST_F(AttributorTestBase
, TestCast
) {
42 const char *ModuleString
= R
"(
43 define i32 @foo(i32 %a, i32 %b) {
50 Module
&M
= parseModule(ModuleString
);
52 SetVector
<Function
*> Functions
;
57 CallGraphUpdater CGUpdater
;
58 BumpPtrAllocator Allocator
;
59 InformationCache
InfoCache(M
, AG
, Allocator
, nullptr);
60 AttributorConfig
AC(CGUpdater
);
61 Attributor
A(Functions
, InfoCache
, AC
);
63 Function
*F
= M
.getFunction("foo");
65 const AbstractAttribute
*AA
=
66 &A
.getOrCreateAAFor
<AAIsDead
>(IRPosition::function(*F
));
70 const auto *SFail
= dyn_cast
<AAAlign
>(AA
);
71 const auto *SSucc
= dyn_cast
<AAIsDead
>(AA
);
73 ASSERT_EQ(SFail
, nullptr);
77 TEST_F(AttributorTestBase
, AAReachabilityTest
) {
78 const char *ModuleString
= R
"(
79 @x = external global i32
80 define internal void @func4() {
85 define internal void @func3() {
90 define internal void @func8() {
95 define internal void @func2() {
101 define internal void @func1() {
107 declare void @unknown()
108 define internal void @func5(void ()* %ptr) {
115 define internal void @func6() {
117 call void @func5(void ()* @func3)
121 define internal void @func7() {
128 define internal void @func9() {
135 define void @func10() {
144 Module
&M
= parseModule(ModuleString
);
146 SetVector
<Function
*> Functions
;
148 for (Function
&F
: M
)
149 Functions
.insert(&F
);
151 CallGraphUpdater CGUpdater
;
152 BumpPtrAllocator Allocator
;
153 InformationCache
InfoCache(M
, AG
, Allocator
, nullptr);
154 AttributorConfig
AC(CGUpdater
);
155 AC
.DeleteFns
= false;
156 Attributor
A(Functions
, InfoCache
, AC
);
158 Function
&F1
= *M
.getFunction("func1");
159 Function
&F3
= *M
.getFunction("func3");
160 Function
&F4
= *M
.getFunction("func4");
161 Function
&F6
= *M
.getFunction("func6");
162 Function
&F7
= *M
.getFunction("func7");
163 Function
&F9
= *M
.getFunction("func9");
165 // call void @func2()
166 CallBase
&F7FirstCB
= static_cast<CallBase
&>(*F7
.getEntryBlock().begin());
167 // call void @func2()
168 Instruction
&F9FirstInst
= *F9
.getEntryBlock().begin();
170 Instruction
&F9SecondInst
= *++(F9
.getEntryBlock().begin());
172 const AAFunctionReachability
&F1AA
=
173 A
.getOrCreateAAFor
<AAFunctionReachability
>(IRPosition::function(F1
));
175 const AAFunctionReachability
&F6AA
=
176 A
.getOrCreateAAFor
<AAFunctionReachability
>(IRPosition::function(F6
));
178 const AAFunctionReachability
&F7AA
=
179 A
.getOrCreateAAFor
<AAFunctionReachability
>(IRPosition::function(F7
));
181 const AAFunctionReachability
&F9AA
=
182 A
.getOrCreateAAFor
<AAFunctionReachability
>(IRPosition::function(F9
));
184 F1AA
.canReach(A
, F3
);
185 F1AA
.canReach(A
, F4
);
186 F6AA
.canReach(A
, F4
);
187 F7AA
.canReach(A
, F7FirstCB
, F3
);
188 F7AA
.canReach(A
, F7FirstCB
, F4
);
189 F9AA
.instructionCanReach(A
, F9FirstInst
, F3
);
190 F9AA
.instructionCanReach(A
, F9FirstInst
, F4
);
194 ASSERT_TRUE(F1AA
.canReach(A
, F3
));
195 ASSERT_FALSE(F1AA
.canReach(A
, F4
));
197 ASSERT_TRUE(F7AA
.canReach(A
, F7FirstCB
, F3
));
198 ASSERT_FALSE(F7AA
.canReach(A
, F7FirstCB
, F4
));
200 // Assumed to be reacahable, since F6 can reach a function with
202 ASSERT_TRUE(F6AA
.canReach(A
, F4
));
204 // The second instruction of F9 can't reach the first call.
205 ASSERT_FALSE(F9AA
.instructionCanReach(A
, F9SecondInst
, F3
));
207 // The first instruction of F9 can reach the first call.
208 ASSERT_TRUE(F9AA
.instructionCanReach(A
, F9FirstInst
, F3
));
209 // Because func10 calls the func4 after the call to func9 it is reachable but
210 // as it requires backwards logic we would need AA::isPotentiallyReachable.
211 ASSERT_FALSE(F9AA
.instructionCanReach(A
, F9FirstInst
, F4
));