216 lines · cpp
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-exception6//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 21namespace llvm {22 23TEST_F(AttributorTestBase, IRPPositionCallBaseContext) {24 const char *ModuleString = R"(25 define i32 @foo(i32 %a) {26 entry:27 ret i32 %a28 }29 )";30 31 parseModule(ModuleString);32 33 Function *F = M->getFunction("foo");34 IRPosition Pos =35 IRPosition::function(*F, (const llvm::CallBase *)(uintptr_t)0xDEADBEEF);36 EXPECT_TRUE(Pos.hasCallBaseContext());37 EXPECT_FALSE(Pos.stripCallBaseContext().hasCallBaseContext());38}39 40TEST_F(AttributorTestBase, TestCast) {41 const char *ModuleString = R"(42 define i32 @foo(i32 %a, i32 %b) {43 entry:44 %c = add i32 %a, %b45 ret i32 %c46 }47 )";48 49 Module &M = parseModule(ModuleString);50 51 SetVector<Function *> Functions;52 AnalysisGetter AG;53 for (Function &F : M)54 Functions.insert(&F);55 56 CallGraphUpdater CGUpdater;57 BumpPtrAllocator Allocator;58 InformationCache InfoCache(M, AG, Allocator, nullptr);59 AttributorConfig AC(CGUpdater);60 Attributor A(Functions, InfoCache, AC);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 76TEST_F(AttributorTestBase, AAReachabilityTest) {77 const char *ModuleString = R"(78 @x = external global i3279 define void @func4() {80 store i32 0, ptr @x81 ret void82 }83 84 define internal void @func3() {85 store i32 0, ptr @x86 ret void87 }88 89 define internal void @func8() {90 store i32 0, ptr @x91 ret void92 }93 94 define internal void @func2() {95 entry:96 call void @func3()97 ret void98 }99 100 define void @func1() {101 entry:102 call void @func2()103 ret void104 }105 106 declare void @unknown()107 define internal void @func5(ptr %ptr) {108 entry:109 call void %ptr()110 call void @unknown()111 ret void112 }113 114 define void @func6() {115 entry:116 store i32 0, ptr @x117 call void @func5(ptr @func3)118 ret void119 }120 121 define void @func7() {122 entry:123 call void @func2()124 call void @func4()125 ret void126 }127 128 define internal void @func9() {129 entry:130 call void @func2()131 call void @func8()132 ret void133 }134 135 define void @func10() {136 entry:137 call void @func9()138 call void @func4()139 ret void140 }141 142 )";143 144 Module &M = parseModule(ModuleString);145 146 SetVector<Function *> Functions;147 AnalysisGetter AG;148 for (Function &F : M)149 Functions.insert(&F);150 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);157 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");164 165 // call void @func2()166 CallBase &F7FirstCB = static_cast<CallBase &>(*F7.getEntryBlock().begin());167 // call void @func2()168 Instruction &F9FirstInst = *F9.getEntryBlock().begin();169 // call void @func8170 Instruction &F9SecondInst = *++(F9.getEntryBlock().begin());171 172 const AAInterFnReachability &F1AA =173 *A.getOrCreateAAFor<AAInterFnReachability>(IRPosition::function(F1));174 175 const AAInterFnReachability &F6AA =176 *A.getOrCreateAAFor<AAInterFnReachability>(IRPosition::function(F6));177 178 const AAInterFnReachability &F7AA =179 *A.getOrCreateAAFor<AAInterFnReachability>(IRPosition::function(F7));180 181 const AAInterFnReachability &F9AA =182 *A.getOrCreateAAFor<AAInterFnReachability>(IRPosition::function(F9));183 184 F1AA.canReach(A, F3);185 F1AA.canReach(A, F4);186 F6AA.canReach(A, F4);187 F7AA.instructionCanReach(A, F7FirstCB, F3);188 F7AA.instructionCanReach(A, F7FirstCB, F4);189 F9AA.instructionCanReach(A, F9SecondInst, F3);190 F9AA.instructionCanReach(A, F9FirstInst, F3);191 F9AA.instructionCanReach(A, F9FirstInst, F4);192 193 A.run();194 195 ASSERT_TRUE(F1AA.canReach(A, F3));196 ASSERT_FALSE(F1AA.canReach(A, F4));197 198 ASSERT_TRUE(F7AA.instructionCanReach(A, F7FirstCB, F3));199 ASSERT_TRUE(F7AA.instructionCanReach(A, F7FirstCB, F4));200 201 // Assumed to be reacahable, since F6 can reach a function with202 // a unknown callee.203 ASSERT_TRUE(F6AA.canReach(A, F4));204 205 // The second instruction of F9 can't reach the first call.206 ASSERT_FALSE(F9AA.instructionCanReach(A, F9SecondInst, F3));207 208 // The first instruction of F9 can reach the first call.209 ASSERT_TRUE(F9AA.instructionCanReach(A, F9FirstInst, F3));210 // Because func10 calls the func4 after the call to func9 it is reachable but211 // as it requires backwards logic we would need AA::isPotentiallyReachable.212 ASSERT_FALSE(F9AA.instructionCanReach(A, F9FirstInst, F4));213}214 215} // namespace llvm216