blob: 40436ef99b8ca182d38302b6df0b26768792e0df [file] [log] [blame]
Daniel Berlinb2d22762015-04-13 23:05:45 +00001//===--- 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"
Chandler Carruth2be10752015-10-21 12:15:19 +000011#include "llvm/ADT/SetVector.h"
Chandler Carruth7b560d42015-09-09 17:55:00 +000012#include "llvm/Analysis/AssumptionCache.h"
Chandler Carruth17e0bc32015-08-06 07:33:15 +000013#include "llvm/Analysis/BasicAliasAnalysis.h"
Chandler Carruth7b560d42015-09-09 17:55:00 +000014#include "llvm/Analysis/TargetLibraryInfo.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000015#include "llvm/AsmParser/Parser.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000016#include "llvm/IR/Constants.h"
17#include "llvm/IR/Instructions.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000018#include "llvm/IR/InstIterator.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000019#include "llvm/IR/LLVMContext.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000020#include "llvm/IR/LegacyPassManager.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000021#include "llvm/IR/Module.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000022#include "llvm/Support/CommandLine.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000023#include "llvm/Support/SourceMgr.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000024#include "gtest/gtest.h"
25
Chandler Carruth2be10752015-10-21 12:15:19 +000026using namespace llvm;
27
28// Set up some test passes.
Daniel Berlinb2d22762015-04-13 23:05:45 +000029namespace llvm {
Chandler Carruth2be10752015-10-21 12:15:19 +000030void initializeAATestPassPass(PassRegistry&);
31void initializeTestCustomAAWrapperPassPass(PassRegistry&);
32}
33
34namespace {
35struct AATestPass : FunctionPass {
36 static char ID;
37 AATestPass() : FunctionPass(ID) {
38 initializeAATestPassPass(*PassRegistry::getPassRegistry());
39 }
40
41 void getAnalysisUsage(AnalysisUsage &AU) const override {
42 AU.addRequired<AAResultsWrapperPass>();
43 AU.setPreservesAll();
44 }
45
46 bool runOnFunction(Function &F) override {
47 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
48
49 SetVector<Value *> Pointers;
50 for (Argument &A : F.args())
51 if (A.getType()->isPointerTy())
52 Pointers.insert(&A);
53 for (Instruction &I : instructions(F))
54 if (I.getType()->isPointerTy())
55 Pointers.insert(&I);
56
57 for (Value *P1 : Pointers)
58 for (Value *P2 : Pointers)
59 (void)AA.alias(P1, MemoryLocation::UnknownSize, P2,
60 MemoryLocation::UnknownSize);
61
62 return false;
63 }
64};
65}
66
67char AATestPass::ID = 0;
68INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
69 false, true)
70INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
71INITIALIZE_PASS_END(AATestPass, "aa-test-pass", "Alias Analysis Test Pass",
72 false, true)
73
74namespace {
75/// A test customizable AA result. It merely accepts a callback to run whenever
76/// it receives an alias query. Useful for testing that a particular AA result
77/// is reached.
78struct TestCustomAAResult : AAResultBase<TestCustomAAResult> {
79 friend AAResultBase<TestCustomAAResult>;
80
81 std::function<void()> CB;
82
Chandler Carruth12884f72016-03-02 15:56:53 +000083 explicit TestCustomAAResult(std::function<void()> CB)
84 : AAResultBase(), CB(std::move(CB)) {}
Chandler Carruth2be10752015-10-21 12:15:19 +000085 TestCustomAAResult(TestCustomAAResult &&Arg)
86 : AAResultBase(std::move(Arg)), CB(std::move(Arg.CB)) {}
87
88 bool invalidate(Function &, const PreservedAnalyses &) { return false; }
89
90 AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
91 CB();
92 return MayAlias;
93 }
94};
95}
96
97namespace {
98/// A wrapper pass for the legacy pass manager to use with the above custom AA
99/// result.
100class TestCustomAAWrapperPass : public ImmutablePass {
101 std::function<void()> CB;
102 std::unique_ptr<TestCustomAAResult> Result;
103
104public:
105 static char ID;
106
107 explicit TestCustomAAWrapperPass(
108 std::function<void()> CB = std::function<void()>())
109 : ImmutablePass(ID), CB(std::move(CB)) {
110 initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
111 }
112
113 void getAnalysisUsage(AnalysisUsage &AU) const override {
114 AU.setPreservesAll();
115 AU.addRequired<TargetLibraryInfoWrapperPass>();
116 }
117
118 bool doInitialization(Module &M) override {
Chandler Carruth12884f72016-03-02 15:56:53 +0000119 Result.reset(new TestCustomAAResult(std::move(CB)));
Chandler Carruth2be10752015-10-21 12:15:19 +0000120 return true;
121 }
122
123 bool doFinalization(Module &M) override {
124 Result.reset();
125 return true;
126 }
127
128 TestCustomAAResult &getResult() { return *Result; }
129 const TestCustomAAResult &getResult() const { return *Result; }
130};
131}
132
133char TestCustomAAWrapperPass::ID = 0;
134INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
135 "Test Custom AA Wrapper Pass", false, true)
136INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
137INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
138 "Test Custom AA Wrapper Pass", false, true)
139
Daniel Berlinb2d22762015-04-13 23:05:45 +0000140namespace {
141
142class AliasAnalysisTest : public testing::Test {
143protected:
Daniel Berlinb2d22762015-04-13 23:05:45 +0000144 LLVMContext C;
145 Module M;
Chandler Carruth7b560d42015-09-09 17:55:00 +0000146 TargetLibraryInfoImpl TLII;
147 TargetLibraryInfo TLI;
148 std::unique_ptr<AssumptionCache> AC;
149 std::unique_ptr<BasicAAResult> BAR;
150 std::unique_ptr<AAResults> AAR;
151
152 AliasAnalysisTest() : M("AliasAnalysisTest", C), TLI(TLII) {}
153
154 AAResults &getAAResults(Function &F) {
155 // Reset the Function AA results first to clear out any references.
Chandler Carruth12884f72016-03-02 15:56:53 +0000156 AAR.reset(new AAResults(TLI));
Chandler Carruth7b560d42015-09-09 17:55:00 +0000157
158 // Build the various AA results and register them.
159 AC.reset(new AssumptionCache(F));
160 BAR.reset(new BasicAAResult(M.getDataLayout(), TLI, *AC));
161 AAR->addAAResult(*BAR);
162
163 return *AAR;
164 }
Daniel Berlinb2d22762015-04-13 23:05:45 +0000165};
166
167TEST_F(AliasAnalysisTest, getModRefInfo) {
168 // Setup function.
169 FunctionType *FTy =
170 FunctionType::get(Type::getVoidTy(C), std::vector<Type *>(), false);
171 auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
172 auto *BB = BasicBlock::Create(C, "entry", F);
173 auto IntType = Type::getInt32Ty(C);
174 auto PtrType = Type::getInt32PtrTy(C);
175 auto *Value = ConstantInt::get(IntType, 42);
176 auto *Addr = ConstantPointerNull::get(PtrType);
177
178 auto *Store1 = new StoreInst(Value, Addr, BB);
179 auto *Load1 = new LoadInst(Addr, "load", BB);
180 auto *Add1 = BinaryOperator::CreateAdd(Value, Value, "add", BB);
Daniel Berlinec1de3f2015-04-28 19:19:14 +0000181 auto *VAArg1 = new VAArgInst(Addr, PtrType, "vaarg", BB);
JF Bastien800f87a2016-04-06 21:19:33 +0000182 auto *CmpXChg1 = new AtomicCmpXchgInst(
183 Addr, ConstantInt::get(IntType, 0), ConstantInt::get(IntType, 1),
184 AtomicOrdering::Monotonic, AtomicOrdering::Monotonic, CrossThread, BB);
Daniel Berlinec1de3f2015-04-28 19:19:14 +0000185 auto *AtomicRMW =
186 new AtomicRMWInst(AtomicRMWInst::Xchg, Addr, ConstantInt::get(IntType, 1),
JF Bastien800f87a2016-04-06 21:19:33 +0000187 AtomicOrdering::Monotonic, CrossThread, BB);
Daniel Berlinb2d22762015-04-13 23:05:45 +0000188
189 ReturnInst::Create(C, nullptr, BB);
190
Chandler Carruth7b560d42015-09-09 17:55:00 +0000191 auto &AA = getAAResults(*F);
192
Daniel Berlinb2d22762015-04-13 23:05:45 +0000193 // Check basic results
Chandler Carruth7b560d42015-09-09 17:55:00 +0000194 EXPECT_EQ(AA.getModRefInfo(Store1, MemoryLocation()), MRI_Mod);
195 EXPECT_EQ(AA.getModRefInfo(Store1), MRI_Mod);
196 EXPECT_EQ(AA.getModRefInfo(Load1, MemoryLocation()), MRI_Ref);
197 EXPECT_EQ(AA.getModRefInfo(Load1), MRI_Ref);
198 EXPECT_EQ(AA.getModRefInfo(Add1, MemoryLocation()), MRI_NoModRef);
199 EXPECT_EQ(AA.getModRefInfo(Add1), MRI_NoModRef);
200 EXPECT_EQ(AA.getModRefInfo(VAArg1, MemoryLocation()), MRI_ModRef);
201 EXPECT_EQ(AA.getModRefInfo(VAArg1), MRI_ModRef);
202 EXPECT_EQ(AA.getModRefInfo(CmpXChg1, MemoryLocation()), MRI_ModRef);
203 EXPECT_EQ(AA.getModRefInfo(CmpXChg1), MRI_ModRef);
204 EXPECT_EQ(AA.getModRefInfo(AtomicRMW, MemoryLocation()), MRI_ModRef);
205 EXPECT_EQ(AA.getModRefInfo(AtomicRMW), MRI_ModRef);
Daniel Berlinb2d22762015-04-13 23:05:45 +0000206}
207
Chandler Carruth2be10752015-10-21 12:15:19 +0000208class AAPassInfraTest : public testing::Test {
209protected:
Mehdi Amini03b42e42016-04-14 21:59:01 +0000210 LLVMContext C;
Chandler Carruth2be10752015-10-21 12:15:19 +0000211 SMDiagnostic Err;
212 std::unique_ptr<Module> M;
213
214public:
215 AAPassInfraTest()
Mehdi Amini03b42e42016-04-14 21:59:01 +0000216 : M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
Chandler Carruth2be10752015-10-21 12:15:19 +0000217 "entry:\n"
218 " %lx = load i32, i32* %x\n"
219 " %ly = load i32, i32* %y\n"
220 " %sum = add i32 %lx, %ly\n"
221 " ret i32 %sum\n"
222 "}\n",
223 Err, C)) {
224 assert(M && "Failed to build the module!");
225 }
226};
227
228TEST_F(AAPassInfraTest, injectExternalAA) {
229 legacy::PassManager PM;
230
231 // Register our custom AA's wrapper pass manually.
232 bool IsCustomAAQueried = false;
233 PM.add(new TestCustomAAWrapperPass([&] { IsCustomAAQueried = true; }));
234
235 // Now add the external AA wrapper with a lambda which queries for the
236 // wrapper around our custom AA and adds it to the results.
237 PM.add(createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) {
238 if (auto *WrapperPass = P.getAnalysisIfAvailable<TestCustomAAWrapperPass>())
239 AAR.addAAResult(WrapperPass->getResult());
240 }));
241
242 // And run a pass that will make some alias queries. This will automatically
243 // trigger the rest of the alias analysis stack to be run. It is analagous to
244 // building a full pass pipeline with any of the existing pass manager
245 // builders.
246 PM.add(new AATestPass());
247 PM.run(*M);
248
249 // Finally, ensure that our custom AA was indeed queried.
250 EXPECT_TRUE(IsCustomAAQueried);
251}
252
Daniel Berlinb2d22762015-04-13 23:05:45 +0000253} // end anonymous namspace