Home | History | Annotate | Download | only in Analysis
      1 //===--- AliasAnalysisTest.cpp - Mixed TBAA unit tests --------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/Analysis/AliasAnalysis.h"
     11 #include "llvm/ADT/SetVector.h"
     12 #include "llvm/Analysis/AssumptionCache.h"
     13 #include "llvm/Analysis/BasicAliasAnalysis.h"
     14 #include "llvm/Analysis/TargetLibraryInfo.h"
     15 #include "llvm/AsmParser/Parser.h"
     16 #include "llvm/IR/Constants.h"
     17 #include "llvm/IR/InstIterator.h"
     18 #include "llvm/IR/Instructions.h"
     19 #include "llvm/IR/LLVMContext.h"
     20 #include "llvm/IR/LegacyPassManager.h"
     21 #include "llvm/IR/Module.h"
     22 #include "llvm/Support/SourceMgr.h"
     23 #include "gtest/gtest.h"
     24 
     25 using namespace llvm;
     26 
     27 // Set up some test passes.
     28 namespace llvm {
     29 void initializeAATestPassPass(PassRegistry&);
     30 void initializeTestCustomAAWrapperPassPass(PassRegistry&);
     31 }
     32 
     33 namespace {
     34 struct AATestPass : FunctionPass {
     35   static char ID;
     36   AATestPass() : FunctionPass(ID) {
     37     initializeAATestPassPass(*PassRegistry::getPassRegistry());
     38   }
     39 
     40   void getAnalysisUsage(AnalysisUsage &AU) const override {
     41     AU.addRequired<AAResultsWrapperPass>();
     42     AU.setPreservesAll();
     43   }
     44 
     45   bool runOnFunction(Function &F) override {
     46     AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
     47 
     48     SetVector<Value *> Pointers;
     49     for (Argument &A : F.args())
     50       if (A.getType()->isPointerTy())
     51         Pointers.insert(&A);
     52     for (Instruction &I : instructions(F))
     53       if (I.getType()->isPointerTy())
     54         Pointers.insert(&I);
     55 
     56     for (Value *P1 : Pointers)
     57       for (Value *P2 : Pointers)
     58         (void)AA.alias(P1, MemoryLocation::UnknownSize, P2,
     59                        MemoryLocation::UnknownSize);
     60 
     61     return false;
     62   }
     63 };
     64 }
     65 
     66 char AATestPass::ID = 0;
     67 INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
     68                       false, true)
     69 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
     70 INITIALIZE_PASS_END(AATestPass, "aa-test-pass", "Alias Analysis Test Pass",
     71                     false, true)
     72 
     73 namespace {
     74 /// A test customizable AA result. It merely accepts a callback to run whenever
     75 /// it receives an alias query. Useful for testing that a particular AA result
     76 /// is reached.
     77 struct TestCustomAAResult : AAResultBase<TestCustomAAResult> {
     78   friend AAResultBase<TestCustomAAResult>;
     79 
     80   std::function<void()> CB;
     81 
     82   explicit TestCustomAAResult(std::function<void()> CB)
     83       : AAResultBase(), CB(std::move(CB)) {}
     84   TestCustomAAResult(TestCustomAAResult &&Arg)
     85       : AAResultBase(std::move(Arg)), CB(std::move(Arg.CB)) {}
     86 
     87   bool invalidate(Function &, const PreservedAnalyses &) { return false; }
     88 
     89   AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
     90     CB();
     91     return MayAlias;
     92   }
     93 };
     94 }
     95 
     96 namespace {
     97 /// A wrapper pass for the legacy pass manager to use with the above custom AA
     98 /// result.
     99 class TestCustomAAWrapperPass : public ImmutablePass {
    100   std::function<void()> CB;
    101   std::unique_ptr<TestCustomAAResult> Result;
    102 
    103 public:
    104   static char ID;
    105 
    106   explicit TestCustomAAWrapperPass(
    107       std::function<void()> CB = std::function<void()>())
    108       : ImmutablePass(ID), CB(std::move(CB)) {
    109     initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
    110   }
    111 
    112   void getAnalysisUsage(AnalysisUsage &AU) const override {
    113     AU.setPreservesAll();
    114     AU.addRequired<TargetLibraryInfoWrapperPass>();
    115   }
    116 
    117   bool doInitialization(Module &M) override {
    118     Result.reset(new TestCustomAAResult(std::move(CB)));
    119     return true;
    120   }
    121 
    122   bool doFinalization(Module &M) override {
    123     Result.reset();
    124     return true;
    125   }
    126 
    127   TestCustomAAResult &getResult() { return *Result; }
    128   const TestCustomAAResult &getResult() const { return *Result; }
    129 };
    130 }
    131 
    132 char TestCustomAAWrapperPass::ID = 0;
    133 INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
    134                 "Test Custom AA Wrapper Pass", false, true)
    135 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
    136 INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
    137                 "Test Custom AA Wrapper Pass", false, true)
    138 
    139 namespace {
    140 
    141 class AliasAnalysisTest : public testing::Test {
    142 protected:
    143   LLVMContext C;
    144   Module M;
    145   TargetLibraryInfoImpl TLII;
    146   TargetLibraryInfo TLI;
    147   std::unique_ptr<AssumptionCache> AC;
    148   std::unique_ptr<BasicAAResult> BAR;
    149   std::unique_ptr<AAResults> AAR;
    150 
    151   AliasAnalysisTest() : M("AliasAnalysisTest", C), TLI(TLII) {}
    152 
    153   AAResults &getAAResults(Function &F) {
    154     // Reset the Function AA results first to clear out any references.
    155     AAR.reset(new AAResults(TLI));
    156 
    157     // Build the various AA results and register them.
    158     AC.reset(new AssumptionCache(F));
    159     BAR.reset(new BasicAAResult(M.getDataLayout(), TLI, *AC));
    160     AAR->addAAResult(*BAR);
    161 
    162     return *AAR;
    163   }
    164 };
    165 
    166 TEST_F(AliasAnalysisTest, getModRefInfo) {
    167   // Setup function.
    168   FunctionType *FTy =
    169       FunctionType::get(Type::getVoidTy(C), std::vector<Type *>(), false);
    170   auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
    171   auto *BB = BasicBlock::Create(C, "entry", F);
    172   auto IntType = Type::getInt32Ty(C);
    173   auto PtrType = Type::getInt32PtrTy(C);
    174   auto *Value = ConstantInt::get(IntType, 42);
    175   auto *Addr = ConstantPointerNull::get(PtrType);
    176 
    177   auto *Store1 = new StoreInst(Value, Addr, BB);
    178   auto *Load1 = new LoadInst(Addr, "load", BB);
    179   auto *Add1 = BinaryOperator::CreateAdd(Value, Value, "add", BB);
    180   auto *VAArg1 = new VAArgInst(Addr, PtrType, "vaarg", BB);
    181   auto *CmpXChg1 = new AtomicCmpXchgInst(
    182       Addr, ConstantInt::get(IntType, 0), ConstantInt::get(IntType, 1),
    183       AtomicOrdering::Monotonic, AtomicOrdering::Monotonic, CrossThread, BB);
    184   auto *AtomicRMW =
    185       new AtomicRMWInst(AtomicRMWInst::Xchg, Addr, ConstantInt::get(IntType, 1),
    186                         AtomicOrdering::Monotonic, CrossThread, BB);
    187 
    188   ReturnInst::Create(C, nullptr, BB);
    189 
    190   auto &AA = getAAResults(*F);
    191 
    192   // Check basic results
    193   EXPECT_EQ(AA.getModRefInfo(Store1, MemoryLocation()), MRI_Mod);
    194   EXPECT_EQ(AA.getModRefInfo(Store1), MRI_Mod);
    195   EXPECT_EQ(AA.getModRefInfo(Load1, MemoryLocation()), MRI_Ref);
    196   EXPECT_EQ(AA.getModRefInfo(Load1), MRI_Ref);
    197   EXPECT_EQ(AA.getModRefInfo(Add1, MemoryLocation()), MRI_NoModRef);
    198   EXPECT_EQ(AA.getModRefInfo(Add1), MRI_NoModRef);
    199   EXPECT_EQ(AA.getModRefInfo(VAArg1, MemoryLocation()), MRI_ModRef);
    200   EXPECT_EQ(AA.getModRefInfo(VAArg1), MRI_ModRef);
    201   EXPECT_EQ(AA.getModRefInfo(CmpXChg1, MemoryLocation()), MRI_ModRef);
    202   EXPECT_EQ(AA.getModRefInfo(CmpXChg1), MRI_ModRef);
    203   EXPECT_EQ(AA.getModRefInfo(AtomicRMW, MemoryLocation()), MRI_ModRef);
    204   EXPECT_EQ(AA.getModRefInfo(AtomicRMW), MRI_ModRef);
    205 }
    206 
    207 class AAPassInfraTest : public testing::Test {
    208 protected:
    209   LLVMContext C;
    210   SMDiagnostic Err;
    211   std::unique_ptr<Module> M;
    212 
    213 public:
    214   AAPassInfraTest()
    215       : M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
    216                               "entry:\n"
    217                               "  %lx = load i32, i32* %x\n"
    218                               "  %ly = load i32, i32* %y\n"
    219                               "  %sum = add i32 %lx, %ly\n"
    220                               "  ret i32 %sum\n"
    221                               "}\n",
    222                               Err, C)) {
    223     assert(M && "Failed to build the module!");
    224   }
    225 };
    226 
    227 TEST_F(AAPassInfraTest, injectExternalAA) {
    228   legacy::PassManager PM;
    229 
    230   // Register our custom AA's wrapper pass manually.
    231   bool IsCustomAAQueried = false;
    232   PM.add(new TestCustomAAWrapperPass([&] { IsCustomAAQueried = true; }));
    233 
    234   // Now add the external AA wrapper with a lambda which queries for the
    235   // wrapper around our custom AA and adds it to the results.
    236   PM.add(createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) {
    237     if (auto *WrapperPass = P.getAnalysisIfAvailable<TestCustomAAWrapperPass>())
    238       AAR.addAAResult(WrapperPass->getResult());
    239   }));
    240 
    241   // And run a pass that will make some alias queries. This will automatically
    242   // trigger the rest of the alias analysis stack to be run. It is analagous to
    243   // building a full pass pipeline with any of the existing pass manager
    244   // builders.
    245   PM.add(new AATestPass());
    246   PM.run(*M);
    247 
    248   // Finally, ensure that our custom AA was indeed queried.
    249   EXPECT_TRUE(IsCustomAAQueried);
    250 }
    251 
    252 } // end anonymous namspace
    253