blob: 42a4210feba26019aafac24cf398c4d50017fc76 [file] [log] [blame]
Daniel Berlinb4f64382015-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 Carruth198a6c52015-10-21 12:15:19 +000011#include "llvm/ADT/SetVector.h"
Daniel Jasper8de3a542016-12-19 08:22:17 +000012#include "llvm/Analysis/AssumptionCache.h"
Chandler Carruth734c7782015-08-06 07:33:15 +000013#include "llvm/Analysis/BasicAliasAnalysis.h"
Chandler Carruth91468332015-09-09 17:55:00 +000014#include "llvm/Analysis/TargetLibraryInfo.h"
Chandler Carruth198a6c52015-10-21 12:15:19 +000015#include "llvm/AsmParser/Parser.h"
Daniel Berlinb4f64382015-04-13 23:05:45 +000016#include "llvm/IR/Constants.h"
Chandler Carruth198a6c52015-10-21 12:15:19 +000017#include "llvm/IR/InstIterator.h"
Mehdi Aminif6071e12016-04-18 09:17:29 +000018#include "llvm/IR/Instructions.h"
Daniel Berlinb4f64382015-04-13 23:05:45 +000019#include "llvm/IR/LLVMContext.h"
Chandler Carruth198a6c52015-10-21 12:15:19 +000020#include "llvm/IR/LegacyPassManager.h"
Daniel Berlinb4f64382015-04-13 23:05:45 +000021#include "llvm/IR/Module.h"
Chandler Carruth198a6c52015-10-21 12:15:19 +000022#include "llvm/Support/SourceMgr.h"
Daniel Berlinb4f64382015-04-13 23:05:45 +000023#include "gtest/gtest.h"
24
Chandler Carruth198a6c52015-10-21 12:15:19 +000025using namespace llvm;
26
27// Set up some test passes.
Daniel Berlinb4f64382015-04-13 23:05:45 +000028namespace llvm {
Chandler Carruth198a6c52015-10-21 12:15:19 +000029void initializeAATestPassPass(PassRegistry&);
30void initializeTestCustomAAWrapperPassPass(PassRegistry&);
31}
32
33namespace {
34struct 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)
George Burgess IVea46abe2018-10-10 21:28:44 +000058 (void)AA.alias(P1, LocationSize::unknown(), P2,
59 LocationSize::unknown());
Chandler Carruth198a6c52015-10-21 12:15:19 +000060
61 return false;
62 }
63};
64}
65
66char AATestPass::ID = 0;
67INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
68 false, true)
69INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
70INITIALIZE_PASS_END(AATestPass, "aa-test-pass", "Alias Analysis Test Pass",
71 false, true)
72
73namespace {
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.
77struct TestCustomAAResult : AAResultBase<TestCustomAAResult> {
78 friend AAResultBase<TestCustomAAResult>;
79
80 std::function<void()> CB;
81
Chandler Carruthcf88e922016-03-02 15:56:53 +000082 explicit TestCustomAAResult(std::function<void()> CB)
83 : AAResultBase(), CB(std::move(CB)) {}
Chandler Carruth198a6c52015-10-21 12:15:19 +000084 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
96namespace {
97/// A wrapper pass for the legacy pass manager to use with the above custom AA
98/// result.
99class TestCustomAAWrapperPass : public ImmutablePass {
100 std::function<void()> CB;
101 std::unique_ptr<TestCustomAAResult> Result;
102
103public:
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 {
Chandler Carruthcf88e922016-03-02 15:56:53 +0000118 Result.reset(new TestCustomAAResult(std::move(CB)));
Chandler Carruth198a6c52015-10-21 12:15:19 +0000119 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
132char TestCustomAAWrapperPass::ID = 0;
133INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
134 "Test Custom AA Wrapper Pass", false, true)
135INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
136INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
137 "Test Custom AA Wrapper Pass", false, true)
138
Daniel Berlinb4f64382015-04-13 23:05:45 +0000139namespace {
140
141class AliasAnalysisTest : public testing::Test {
142protected:
Daniel Berlinb4f64382015-04-13 23:05:45 +0000143 LLVMContext C;
144 Module M;
Chandler Carruth91468332015-09-09 17:55:00 +0000145 TargetLibraryInfoImpl TLII;
146 TargetLibraryInfo TLI;
Daniel Jasper8de3a542016-12-19 08:22:17 +0000147 std::unique_ptr<AssumptionCache> AC;
Chandler Carruth91468332015-09-09 17:55:00 +0000148 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.
Chandler Carruthcf88e922016-03-02 15:56:53 +0000155 AAR.reset(new AAResults(TLI));
Chandler Carruth91468332015-09-09 17:55:00 +0000156
157 // Build the various AA results and register them.
Daniel Jasper8de3a542016-12-19 08:22:17 +0000158 AC.reset(new AssumptionCache(F));
Manoj Guptac6da6862018-07-09 22:27:23 +0000159 BAR.reset(new BasicAAResult(M.getDataLayout(), F, TLI, *AC));
Chandler Carruth91468332015-09-09 17:55:00 +0000160 AAR->addAAResult(*BAR);
161
162 return *AAR;
163 }
Daniel Berlinb4f64382015-04-13 23:05:45 +0000164};
165
166TEST_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);
Daniel Berlinb1e1aa02015-04-28 19:19:14 +0000180 auto *VAArg1 = new VAArgInst(Addr, PtrType, "vaarg", BB);
JF Bastienb36d1a82016-04-06 21:19:33 +0000181 auto *CmpXChg1 = new AtomicCmpXchgInst(
182 Addr, ConstantInt::get(IntType, 0), ConstantInt::get(IntType, 1),
Konstantin Zhuravlyov8f856852017-07-11 22:23:00 +0000183 AtomicOrdering::Monotonic, AtomicOrdering::Monotonic,
184 SyncScope::System, BB);
Daniel Berlinb1e1aa02015-04-28 19:19:14 +0000185 auto *AtomicRMW =
186 new AtomicRMWInst(AtomicRMWInst::Xchg, Addr, ConstantInt::get(IntType, 1),
Konstantin Zhuravlyov8f856852017-07-11 22:23:00 +0000187 AtomicOrdering::Monotonic, SyncScope::System, BB);
Daniel Berlinb4f64382015-04-13 23:05:45 +0000188
189 ReturnInst::Create(C, nullptr, BB);
190
Chandler Carruth91468332015-09-09 17:55:00 +0000191 auto &AA = getAAResults(*F);
192
Daniel Berlinb4f64382015-04-13 23:05:45 +0000193 // Check basic results
Alina Sbirleac94e8962017-12-07 22:41:34 +0000194 EXPECT_EQ(AA.getModRefInfo(Store1, MemoryLocation()), ModRefInfo::Mod);
195 EXPECT_EQ(AA.getModRefInfo(Store1, None), ModRefInfo::Mod);
196 EXPECT_EQ(AA.getModRefInfo(Load1, MemoryLocation()), ModRefInfo::Ref);
197 EXPECT_EQ(AA.getModRefInfo(Load1, None), ModRefInfo::Ref);
198 EXPECT_EQ(AA.getModRefInfo(Add1, MemoryLocation()), ModRefInfo::NoModRef);
199 EXPECT_EQ(AA.getModRefInfo(Add1, None), ModRefInfo::NoModRef);
200 EXPECT_EQ(AA.getModRefInfo(VAArg1, MemoryLocation()), ModRefInfo::ModRef);
201 EXPECT_EQ(AA.getModRefInfo(VAArg1, None), ModRefInfo::ModRef);
202 EXPECT_EQ(AA.getModRefInfo(CmpXChg1, MemoryLocation()), ModRefInfo::ModRef);
203 EXPECT_EQ(AA.getModRefInfo(CmpXChg1, None), ModRefInfo::ModRef);
204 EXPECT_EQ(AA.getModRefInfo(AtomicRMW, MemoryLocation()), ModRefInfo::ModRef);
205 EXPECT_EQ(AA.getModRefInfo(AtomicRMW, None), ModRefInfo::ModRef);
Daniel Berlinb4f64382015-04-13 23:05:45 +0000206}
207
Chandler Carruth198a6c52015-10-21 12:15:19 +0000208class AAPassInfraTest : public testing::Test {
209protected:
Mehdi Amini8be77072016-04-14 21:59:01 +0000210 LLVMContext C;
Chandler Carruth198a6c52015-10-21 12:15:19 +0000211 SMDiagnostic Err;
212 std::unique_ptr<Module> M;
213
214public:
215 AAPassInfraTest()
Mehdi Amini8be77072016-04-14 21:59:01 +0000216 : M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
Chandler Carruth198a6c52015-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 Berlinb4f64382015-04-13 23:05:45 +0000253} // end anonymous namspace