1 //===- AttributorTest.cpp - Attributor unit tests ------------------------===// 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-exception 6 // 7 //===---------------------------------------------------------------------===// 8 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" 20 #include <memory> 21 22 namespace llvm { 23 24 TEST_F(AttributorTestBase, IRPPositionCallBaseContext) { 25 const char *ModuleString = R"( 26 define i32 @foo(i32 %a) { 27 entry: 28 ret i32 %a 29 } 30 )"; 31 32 parseModule(ModuleString); 33 34 Function *F = M->getFunction("foo"); 35 IRPosition Pos = 36 IRPosition::function(*F, (const llvm::CallBase *)(uintptr_t)0xDEADBEEF); 37 EXPECT_TRUE(Pos.hasCallBaseContext()); 38 EXPECT_FALSE(Pos.stripCallBaseContext().hasCallBaseContext()); 39 } 40 41 TEST_F(AttributorTestBase, TestCast) { 42 const char *ModuleString = R"( 43 define i32 @foo(i32 %a, i32 %b) { 44 entry: 45 %c = add i32 %a, %b 46 ret i32 %c 47 } 48 )"; 49 50 Module &M = parseModule(ModuleString); 51 52 SetVector<Function *> Functions; 53 AnalysisGetter AG; 54 for (Function &F : M) 55 Functions.insert(&F); 56 57 CallGraphUpdater CGUpdater; 58 BumpPtrAllocator Allocator; 59 InformationCache InfoCache(M, AG, Allocator, nullptr); 60 Attributor A(Functions, InfoCache, CGUpdater); 61 62 Function *F = M.getFunction("foo"); 63 64 const AbstractAttribute *AA = 65 &A.getOrCreateAAFor<AAIsDead>(IRPosition::function(*F)); 66 67 EXPECT_TRUE(AA); 68 69 const auto *SFail = dyn_cast<AAAlign>(AA); 70 const auto *SSucc = dyn_cast<AAIsDead>(AA); 71 72 ASSERT_EQ(SFail, nullptr); 73 ASSERT_TRUE(SSucc); 74 } 75 76 TEST_F(AttributorTestBase, AAReachabilityTest) { 77 const char *ModuleString = R"( 78 @x = global i32 0 79 define void @func4() { 80 store i32 0, i32* @x 81 ret void 82 } 83 84 define void @func3() { 85 store i32 0, i32* @x 86 ret void 87 } 88 89 define void @func2() { 90 entry: 91 call void @func3() 92 ret void 93 } 94 95 define void @func1() { 96 entry: 97 call void @func2() 98 ret void 99 } 100 101 define void @func5(void ()* %unknown) { 102 entry: 103 call void %unknown() 104 ret void 105 } 106 107 define void @func6() { 108 entry: 109 call void @func5(void ()* @func3) 110 ret void 111 } 112 113 define void @func7() { 114 entry: 115 call void @func2() 116 call void @func4() 117 ret void 118 } 119 )"; 120 121 Module &M = parseModule(ModuleString); 122 123 SetVector<Function *> Functions; 124 AnalysisGetter AG; 125 for (Function &F : M) 126 Functions.insert(&F); 127 128 CallGraphUpdater CGUpdater; 129 BumpPtrAllocator Allocator; 130 InformationCache InfoCache(M, AG, Allocator, nullptr); 131 Attributor A(Functions, InfoCache, CGUpdater); 132 133 Function *F1 = M.getFunction("func1"); 134 Function *F3 = M.getFunction("func3"); 135 Function *F4 = M.getFunction("func4"); 136 Function *F6 = M.getFunction("func6"); 137 Function *F7 = M.getFunction("func7"); 138 139 // call void @func2() 140 CallBase &F7FirstCB = 141 *static_cast<CallBase *>(F7->getEntryBlock().getFirstNonPHI()); 142 143 const AAFunctionReachability &F1AA = 144 A.getOrCreateAAFor<AAFunctionReachability>(IRPosition::function(*F1)); 145 146 const AAFunctionReachability &F6AA = 147 A.getOrCreateAAFor<AAFunctionReachability>(IRPosition::function(*F6)); 148 149 const AAFunctionReachability &F7AA = 150 A.getOrCreateAAFor<AAFunctionReachability>(IRPosition::function(*F7)); 151 152 F1AA.canReach(A, F3); 153 F1AA.canReach(A, F4); 154 F6AA.canReach(A, F4); 155 F7AA.canReach(A, F7FirstCB, F3); 156 F7AA.canReach(A, F7FirstCB, F4); 157 158 A.run(); 159 160 ASSERT_TRUE(F1AA.canReach(A, F3)); 161 ASSERT_FALSE(F1AA.canReach(A, F4)); 162 163 ASSERT_TRUE(F7AA.canReach(A, F7FirstCB, F3)); 164 ASSERT_FALSE(F7AA.canReach(A, F7FirstCB, F4)); 165 166 // Assumed to be reacahable, since F6 can reach a function with 167 // a unknown callee. 168 ASSERT_TRUE(F6AA.canReach(A, F4)); 169 } 170 171 } // namespace llvm 172