blob: 7a842575df47d6ca4fd21711069ec8426bb593bc [file] [log] [blame]
Daniel Berlinb2d22762015-04-13 23:05:45 +00001//===--- AliasAnalysisTest.cpp - Mixed TBAA unit tests --------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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-exception
Daniel Berlinb2d22762015-04-13 23:05:45 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Analysis/AliasAnalysis.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000010#include "llvm/ADT/SetVector.h"
Daniel Jasperaec2fa32016-12-19 08:22:17 +000011#include "llvm/Analysis/AssumptionCache.h"
Chandler Carruth17e0bc32015-08-06 07:33:15 +000012#include "llvm/Analysis/BasicAliasAnalysis.h"
Chandler Carruth7b560d42015-09-09 17:55:00 +000013#include "llvm/Analysis/TargetLibraryInfo.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000014#include "llvm/AsmParser/Parser.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000015#include "llvm/IR/Constants.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000016#include "llvm/IR/InstIterator.h"
Mehdi Aminib550cb12016-04-18 09:17:29 +000017#include "llvm/IR/Instructions.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000018#include "llvm/IR/LLVMContext.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000019#include "llvm/IR/LegacyPassManager.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000020#include "llvm/IR/Module.h"
Chandler Carruth2be10752015-10-21 12:15:19 +000021#include "llvm/Support/SourceMgr.h"
Daniel Berlinb2d22762015-04-13 23:05:45 +000022#include "gtest/gtest.h"
23
Chandler Carruth2be10752015-10-21 12:15:19 +000024using namespace llvm;
25
26// Set up some test passes.
Daniel Berlinb2d22762015-04-13 23:05:45 +000027namespace llvm {
Chandler Carruth2be10752015-10-21 12:15:19 +000028void initializeAATestPassPass(PassRegistry&);
29void initializeTestCustomAAWrapperPassPass(PassRegistry&);
30}
31
32namespace {
33struct AATestPass : FunctionPass {
34 static char ID;
35 AATestPass() : FunctionPass(ID) {
36 initializeAATestPassPass(*PassRegistry::getPassRegistry());
37 }
38
39 void getAnalysisUsage(AnalysisUsage &AU) const override {
40 AU.addRequired<AAResultsWrapperPass>();
41 AU.setPreservesAll();
42 }
43
44 bool runOnFunction(Function &F) override {
45 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
46
47 SetVector<Value *> Pointers;
48 for (Argument &A : F.args())
49 if (A.getType()->isPointerTy())
50 Pointers.insert(&A);
51 for (Instruction &I : instructions(F))
52 if (I.getType()->isPointerTy())
53 Pointers.insert(&I);
54
55 for (Value *P1 : Pointers)
56 for (Value *P2 : Pointers)
George Burgess IV6ef80022018-10-10 21:28:44 +000057 (void)AA.alias(P1, LocationSize::unknown(), P2,
58 LocationSize::unknown());
Chandler Carruth2be10752015-10-21 12:15:19 +000059
60 return false;
61 }
62};
63}
64
65char AATestPass::ID = 0;
66INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
67 false, true)
68INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
69INITIALIZE_PASS_END(AATestPass, "aa-test-pass", "Alias Analysis Test Pass",
70 false, true)
71
72namespace {
73/// A test customizable AA result. It merely accepts a callback to run whenever
74/// it receives an alias query. Useful for testing that a particular AA result
75/// is reached.
76struct TestCustomAAResult : AAResultBase<TestCustomAAResult> {
77 friend AAResultBase<TestCustomAAResult>;
78
79 std::function<void()> CB;
80
Chandler Carruth12884f72016-03-02 15:56:53 +000081 explicit TestCustomAAResult(std::function<void()> CB)
82 : AAResultBase(), CB(std::move(CB)) {}
Chandler Carruth2be10752015-10-21 12:15:19 +000083 TestCustomAAResult(TestCustomAAResult &&Arg)
84 : AAResultBase(std::move(Arg)), CB(std::move(Arg.CB)) {}
85
86 bool invalidate(Function &, const PreservedAnalyses &) { return false; }
87
88 AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
89 CB();
90 return MayAlias;
91 }
92};
93}
94
95namespace {
96/// A wrapper pass for the legacy pass manager to use with the above custom AA
97/// result.
98class TestCustomAAWrapperPass : public ImmutablePass {
99 std::function<void()> CB;
100 std::unique_ptr<TestCustomAAResult> Result;
101
102public:
103 static char ID;
104
105 explicit TestCustomAAWrapperPass(
106 std::function<void()> CB = std::function<void()>())
107 : ImmutablePass(ID), CB(std::move(CB)) {
108 initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
109 }
110
111 void getAnalysisUsage(AnalysisUsage &AU) const override {
112 AU.setPreservesAll();
113 AU.addRequired<TargetLibraryInfoWrapperPass>();
114 }
115
116 bool doInitialization(Module &M) override {
Chandler Carruth12884f72016-03-02 15:56:53 +0000117 Result.reset(new TestCustomAAResult(std::move(CB)));
Chandler Carruth2be10752015-10-21 12:15:19 +0000118 return true;
119 }
120
121 bool doFinalization(Module &M) override {
122 Result.reset();
123 return true;
124 }
125
126 TestCustomAAResult &getResult() { return *Result; }
127 const TestCustomAAResult &getResult() const { return *Result; }
128};
129}
130
131char TestCustomAAWrapperPass::ID = 0;
132INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
133 "Test Custom AA Wrapper Pass", false, true)
134INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
135INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
136 "Test Custom AA Wrapper Pass", false, true)
137
Daniel Berlinb2d22762015-04-13 23:05:45 +0000138namespace {
139
140class AliasAnalysisTest : public testing::Test {
141protected:
Daniel Berlinb2d22762015-04-13 23:05:45 +0000142 LLVMContext C;
143 Module M;
Chandler Carruth7b560d42015-09-09 17:55:00 +0000144 TargetLibraryInfoImpl TLII;
145 TargetLibraryInfo TLI;
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000146 std::unique_ptr<AssumptionCache> AC;
Chandler Carruth7b560d42015-09-09 17:55:00 +0000147 std::unique_ptr<BasicAAResult> BAR;
148 std::unique_ptr<AAResults> AAR;
149
150 AliasAnalysisTest() : M("AliasAnalysisTest", C), TLI(TLII) {}
151
152 AAResults &getAAResults(Function &F) {
153 // Reset the Function AA results first to clear out any references.
Chandler Carruth12884f72016-03-02 15:56:53 +0000154 AAR.reset(new AAResults(TLI));
Chandler Carruth7b560d42015-09-09 17:55:00 +0000155
156 // Build the various AA results and register them.
Daniel Jasperaec2fa32016-12-19 08:22:17 +0000157 AC.reset(new AssumptionCache(F));
Manoj Gupta77eeac32018-07-09 22:27:23 +0000158 BAR.reset(new BasicAAResult(M.getDataLayout(), F, TLI, *AC));
Chandler Carruth7b560d42015-09-09 17:55:00 +0000159 AAR->addAAResult(*BAR);
160
161 return *AAR;
162 }
Daniel Berlinb2d22762015-04-13 23:05:45 +0000163};
164
165TEST_F(AliasAnalysisTest, getModRefInfo) {
166 // Setup function.
167 FunctionType *FTy =
168 FunctionType::get(Type::getVoidTy(C), std::vector<Type *>(), false);
James Y Knightfadf2502019-01-31 21:51:58 +0000169 auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
Daniel Berlinb2d22762015-04-13 23:05:45 +0000170 auto *BB = BasicBlock::Create(C, "entry", F);
171 auto IntType = Type::getInt32Ty(C);
172 auto PtrType = Type::getInt32PtrTy(C);
173 auto *Value = ConstantInt::get(IntType, 42);
174 auto *Addr = ConstantPointerNull::get(PtrType);
175
176 auto *Store1 = new StoreInst(Value, Addr, BB);
177 auto *Load1 = new LoadInst(Addr, "load", BB);
178 auto *Add1 = BinaryOperator::CreateAdd(Value, Value, "add", BB);
Daniel Berlinec1de3f2015-04-28 19:19:14 +0000179 auto *VAArg1 = new VAArgInst(Addr, PtrType, "vaarg", BB);
JF Bastien800f87a2016-04-06 21:19:33 +0000180 auto *CmpXChg1 = new AtomicCmpXchgInst(
181 Addr, ConstantInt::get(IntType, 0), ConstantInt::get(IntType, 1),
Konstantin Zhuravlyovbb80d3e2017-07-11 22:23:00 +0000182 AtomicOrdering::Monotonic, AtomicOrdering::Monotonic,
183 SyncScope::System, BB);
Daniel Berlinec1de3f2015-04-28 19:19:14 +0000184 auto *AtomicRMW =
185 new AtomicRMWInst(AtomicRMWInst::Xchg, Addr, ConstantInt::get(IntType, 1),
Konstantin Zhuravlyovbb80d3e2017-07-11 22:23:00 +0000186 AtomicOrdering::Monotonic, SyncScope::System, BB);
Daniel Berlinb2d22762015-04-13 23:05:45 +0000187
188 ReturnInst::Create(C, nullptr, BB);
189
Chandler Carruth7b560d42015-09-09 17:55:00 +0000190 auto &AA = getAAResults(*F);
191
Daniel Berlinb2d22762015-04-13 23:05:45 +0000192 // Check basic results
Alina Sbirlea193429f2017-12-07 22:41:34 +0000193 EXPECT_EQ(AA.getModRefInfo(Store1, MemoryLocation()), ModRefInfo::Mod);
194 EXPECT_EQ(AA.getModRefInfo(Store1, None), ModRefInfo::Mod);
195 EXPECT_EQ(AA.getModRefInfo(Load1, MemoryLocation()), ModRefInfo::Ref);
196 EXPECT_EQ(AA.getModRefInfo(Load1, None), ModRefInfo::Ref);
197 EXPECT_EQ(AA.getModRefInfo(Add1, MemoryLocation()), ModRefInfo::NoModRef);
198 EXPECT_EQ(AA.getModRefInfo(Add1, None), ModRefInfo::NoModRef);
199 EXPECT_EQ(AA.getModRefInfo(VAArg1, MemoryLocation()), ModRefInfo::ModRef);
200 EXPECT_EQ(AA.getModRefInfo(VAArg1, None), ModRefInfo::ModRef);
201 EXPECT_EQ(AA.getModRefInfo(CmpXChg1, MemoryLocation()), ModRefInfo::ModRef);
202 EXPECT_EQ(AA.getModRefInfo(CmpXChg1, None), ModRefInfo::ModRef);
203 EXPECT_EQ(AA.getModRefInfo(AtomicRMW, MemoryLocation()), ModRefInfo::ModRef);
204 EXPECT_EQ(AA.getModRefInfo(AtomicRMW, None), ModRefInfo::ModRef);
Daniel Berlinb2d22762015-04-13 23:05:45 +0000205}
206
Chandler Carruth2be10752015-10-21 12:15:19 +0000207class AAPassInfraTest : public testing::Test {
208protected:
Mehdi Amini03b42e42016-04-14 21:59:01 +0000209 LLVMContext C;
Chandler Carruth2be10752015-10-21 12:15:19 +0000210 SMDiagnostic Err;
211 std::unique_ptr<Module> M;
212
213public:
214 AAPassInfraTest()
Mehdi Amini03b42e42016-04-14 21:59:01 +0000215 : M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
Chandler Carruth2be10752015-10-21 12:15:19 +0000216 "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
227TEST_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
Daniel Berlinb2d22762015-04-13 23:05:45 +0000252} // end anonymous namspace