xref: /aosp_15_r20/external/llvm/unittests/Analysis/AliasAnalysisTest.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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