brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 8d90b30 Raw
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