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