1 //===--- AliasAnalysisTest.cpp - Mixed TBAA unit tests --------------------===//
3 // 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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/AliasAnalysis.h"
10 #include "llvm/ADT/SetVector.h"
11 #include "llvm/Analysis/AssumptionCache.h"
12 #include "llvm/Analysis/BasicAliasAnalysis.h"
13 #include "llvm/Analysis/TargetLibraryInfo.h"
14 #include "llvm/AsmParser/Parser.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/InstIterator.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/IR/LegacyPassManager.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "gtest/gtest.h"
26 // Set up some test passes.
28 void initializeAATestPassPass(PassRegistry
&);
29 void initializeTestCustomAAWrapperPassPass(PassRegistry
&);
33 struct AATestPass
: FunctionPass
{
35 AATestPass() : FunctionPass(ID
) {
36 initializeAATestPassPass(*PassRegistry::getPassRegistry());
39 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
40 AU
.addRequired
<AAResultsWrapperPass
>();
44 bool runOnFunction(Function
&F
) override
{
45 AliasAnalysis
&AA
= getAnalysis
<AAResultsWrapperPass
>().getAAResults();
47 SetVector
<Value
*> Pointers
;
48 for (Argument
&A
: F
.args())
49 if (A
.getType()->isPointerTy())
51 for (Instruction
&I
: instructions(F
))
52 if (I
.getType()->isPointerTy())
55 for (Value
*P1
: Pointers
)
56 for (Value
*P2
: Pointers
)
57 (void)AA
.alias(P1
, LocationSize::unknown(), P2
,
58 LocationSize::unknown());
65 char AATestPass::ID
= 0;
66 INITIALIZE_PASS_BEGIN(AATestPass
, "aa-test-pas", "Alias Analysis Test Pass",
68 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass
)
69 INITIALIZE_PASS_END(AATestPass
, "aa-test-pass", "Alias Analysis Test Pass",
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
76 struct TestCustomAAResult
: AAResultBase
<TestCustomAAResult
> {
77 friend AAResultBase
<TestCustomAAResult
>;
79 std::function
<void()> CB
;
81 explicit TestCustomAAResult(std::function
<void()> CB
)
82 : AAResultBase(), CB(std::move(CB
)) {}
83 TestCustomAAResult(TestCustomAAResult
&&Arg
)
84 : AAResultBase(std::move(Arg
)), CB(std::move(Arg
.CB
)) {}
86 bool invalidate(Function
&, const PreservedAnalyses
&) { return false; }
88 AliasResult
alias(const MemoryLocation
&LocA
, const MemoryLocation
&LocB
) {
96 /// A wrapper pass for the legacy pass manager to use with the above custom AA
98 class TestCustomAAWrapperPass
: public ImmutablePass
{
99 std::function
<void()> CB
;
100 std::unique_ptr
<TestCustomAAResult
> Result
;
105 explicit TestCustomAAWrapperPass(
106 std::function
<void()> CB
= std::function
<void()>())
107 : ImmutablePass(ID
), CB(std::move(CB
)) {
108 initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
111 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
112 AU
.setPreservesAll();
113 AU
.addRequired
<TargetLibraryInfoWrapperPass
>();
116 bool doInitialization(Module
&M
) override
{
117 Result
.reset(new TestCustomAAResult(std::move(CB
)));
121 bool doFinalization(Module
&M
) override
{
126 TestCustomAAResult
&getResult() { return *Result
; }
127 const TestCustomAAResult
&getResult() const { return *Result
; }
131 char TestCustomAAWrapperPass::ID
= 0;
132 INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass
, "test-custom-aa",
133 "Test Custom AA Wrapper Pass", false, true)
134 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass
)
135 INITIALIZE_PASS_END(TestCustomAAWrapperPass
, "test-custom-aa",
136 "Test Custom AA Wrapper Pass", false, true)
140 class AliasAnalysisTest
: public testing::Test
{
144 TargetLibraryInfoImpl TLII
;
145 TargetLibraryInfo TLI
;
146 std::unique_ptr
<AssumptionCache
> AC
;
147 std::unique_ptr
<BasicAAResult
> BAR
;
148 std::unique_ptr
<AAResults
> AAR
;
150 AliasAnalysisTest() : M("AliasAnalysisTest", C
), TLI(TLII
) {}
152 AAResults
&getAAResults(Function
&F
) {
153 // Reset the Function AA results first to clear out any references.
154 AAR
.reset(new AAResults(TLI
));
156 // Build the various AA results and register them.
157 AC
.reset(new AssumptionCache(F
));
158 BAR
.reset(new BasicAAResult(M
.getDataLayout(), F
, TLI
, *AC
));
159 AAR
->addAAResult(*BAR
);
165 TEST_F(AliasAnalysisTest
, getModRefInfo
) {
168 FunctionType::get(Type::getVoidTy(C
), std::vector
<Type
*>(), false);
169 auto *F
= Function::Create(FTy
, Function::ExternalLinkage
, "f", M
);
170 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
);
176 auto *Store1
= new StoreInst(Value
, Addr
, BB
);
177 auto *Load1
= new LoadInst(IntType
, Addr
, "load", BB
);
178 auto *Add1
= BinaryOperator::CreateAdd(Value
, Value
, "add", BB
);
179 auto *VAArg1
= new VAArgInst(Addr
, PtrType
, "vaarg", BB
);
180 auto *CmpXChg1
= new AtomicCmpXchgInst(
181 Addr
, ConstantInt::get(IntType
, 0), ConstantInt::get(IntType
, 1),
182 AtomicOrdering::Monotonic
, AtomicOrdering::Monotonic
,
183 SyncScope::System
, BB
);
185 new AtomicRMWInst(AtomicRMWInst::Xchg
, Addr
, ConstantInt::get(IntType
, 1),
186 AtomicOrdering::Monotonic
, SyncScope::System
, BB
);
188 ReturnInst::Create(C
, nullptr, BB
);
190 auto &AA
= getAAResults(*F
);
192 // Check basic results
193 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
);
207 class AAPassInfraTest
: public testing::Test
{
211 std::unique_ptr
<Module
> M
;
215 : M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
217 " %lx = load i32, i32* %x\n"
218 " %ly = load i32, i32* %y\n"
219 " %sum = add i32 %lx, %ly\n"
223 assert(M
&& "Failed to build the module!");
227 TEST_F(AAPassInfraTest
, injectExternalAA
) {
228 legacy::PassManager PM
;
230 // Register our custom AA's wrapper pass manually.
231 bool IsCustomAAQueried
= false;
232 PM
.add(new TestCustomAAWrapperPass([&] { IsCustomAAQueried
= true; }));
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());
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
245 PM
.add(new AATestPass());
248 // Finally, ensure that our custom AA was indeed queried.
249 EXPECT_TRUE(IsCustomAAQueried
);
252 } // end anonymous namspace