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
,
97 /// A wrapper pass for the legacy pass manager to use with the above custom AA
99 class TestCustomAAWrapperPass
: public ImmutablePass
{
100 std::function
<void()> CB
;
101 std::unique_ptr
<TestCustomAAResult
> Result
;
106 explicit TestCustomAAWrapperPass(
107 std::function
<void()> CB
= std::function
<void()>())
108 : ImmutablePass(ID
), CB(std::move(CB
)) {
109 initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
112 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
113 AU
.setPreservesAll();
114 AU
.addRequired
<TargetLibraryInfoWrapperPass
>();
117 bool doInitialization(Module
&M
) override
{
118 Result
.reset(new TestCustomAAResult(std::move(CB
)));
122 bool doFinalization(Module
&M
) override
{
127 TestCustomAAResult
&getResult() { return *Result
; }
128 const TestCustomAAResult
&getResult() const { return *Result
; }
132 char TestCustomAAWrapperPass::ID
= 0;
133 INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass
, "test-custom-aa",
134 "Test Custom AA Wrapper Pass", false, true)
135 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass
)
136 INITIALIZE_PASS_END(TestCustomAAWrapperPass
, "test-custom-aa",
137 "Test Custom AA Wrapper Pass", false, true)
141 class AliasAnalysisTest
: public testing::Test
{
145 TargetLibraryInfoImpl TLII
;
146 TargetLibraryInfo TLI
;
147 std::unique_ptr
<AssumptionCache
> AC
;
148 std::unique_ptr
<BasicAAResult
> BAR
;
149 std::unique_ptr
<AAResults
> AAR
;
151 AliasAnalysisTest() : M("AliasAnalysisTest", C
), TLI(TLII
) {}
153 AAResults
&getAAResults(Function
&F
) {
154 // Reset the Function AA results first to clear out any references.
155 AAR
.reset(new AAResults(TLI
));
157 // Build the various AA results and register them.
158 AC
.reset(new AssumptionCache(F
));
159 BAR
.reset(new BasicAAResult(M
.getDataLayout(), F
, TLI
, *AC
));
160 AAR
->addAAResult(*BAR
);
166 TEST_F(AliasAnalysisTest
, getModRefInfo
) {
169 FunctionType::get(Type::getVoidTy(C
), std::vector
<Type
*>(), false);
170 auto *F
= Function::Create(FTy
, Function::ExternalLinkage
, "f", M
);
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
);
177 auto *Store1
= new StoreInst(Value
, Addr
, BB
);
178 auto *Load1
= new LoadInst(IntType
, Addr
, "load", BB
);
179 auto *Add1
= BinaryOperator::CreateAdd(Value
, Value
, "add", BB
);
180 auto *VAArg1
= new VAArgInst(Addr
, PtrType
, "vaarg", BB
);
181 auto *CmpXChg1
= new AtomicCmpXchgInst(
182 Addr
, ConstantInt::get(IntType
, 0), ConstantInt::get(IntType
, 1),
183 AtomicOrdering::Monotonic
, AtomicOrdering::Monotonic
,
184 SyncScope::System
, BB
);
186 new AtomicRMWInst(AtomicRMWInst::Xchg
, Addr
, ConstantInt::get(IntType
, 1),
187 AtomicOrdering::Monotonic
, SyncScope::System
, BB
);
189 ReturnInst::Create(C
, nullptr, BB
);
191 auto &AA
= getAAResults(*F
);
193 // Check basic results
194 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
);
208 class AAPassInfraTest
: public testing::Test
{
212 std::unique_ptr
<Module
> M
;
216 : M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
218 " %lx = load i32, i32* %x\n"
219 " %ly = load i32, i32* %y\n"
220 " %sum = add i32 %lx, %ly\n"
224 assert(M
&& "Failed to build the module!");
228 TEST_F(AAPassInfraTest
, injectExternalAA
) {
229 legacy::PassManager PM
;
231 // Register our custom AA's wrapper pass manually.
232 bool IsCustomAAQueried
= false;
233 PM
.add(new TestCustomAAWrapperPass([&] { IsCustomAAQueried
= true; }));
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());
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
246 PM
.add(new AATestPass());
249 // Finally, ensure that our custom AA was indeed queried.
250 EXPECT_TRUE(IsCustomAAQueried
);
253 } // end anonymous namspace