xref: /llvm-project/llvm/unittests/Analysis/BasicAliasAnalysisTest.cpp (revision 6c2fbc3a68ba6d4bd1c8c2c43c98cff5e82f2ba4)
140dc63e1SGeorge Burgess IV //===- BasicAliasAnalysisTest.cpp - Unit tests for BasicAA ----------------===//
240dc63e1SGeorge Burgess IV //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
640dc63e1SGeorge Burgess IV //
740dc63e1SGeorge Burgess IV //===----------------------------------------------------------------------===//
840dc63e1SGeorge Burgess IV //
940dc63e1SGeorge Burgess IV // Targeted tests that are hard/convoluted to make happen with just `opt`.
1040dc63e1SGeorge Burgess IV //
1140dc63e1SGeorge Burgess IV 
1240dc63e1SGeorge Burgess IV #include "llvm/Analysis/BasicAliasAnalysis.h"
1340dc63e1SGeorge Burgess IV #include "llvm/Analysis/AliasAnalysis.h"
142ce38b3fSdfukalov #include "llvm/Analysis/AssumptionCache.h"
152ce38b3fSdfukalov #include "llvm/Analysis/TargetLibraryInfo.h"
1640dc63e1SGeorge Burgess IV #include "llvm/AsmParser/Parser.h"
1740dc63e1SGeorge Burgess IV #include "llvm/IR/Dominators.h"
1840dc63e1SGeorge Burgess IV #include "llvm/IR/IRBuilder.h"
1940dc63e1SGeorge Burgess IV #include "llvm/IR/LLVMContext.h"
2040dc63e1SGeorge Burgess IV #include "llvm/IR/Module.h"
2140dc63e1SGeorge Burgess IV #include "llvm/Support/SourceMgr.h"
2240dc63e1SGeorge Burgess IV #include "gtest/gtest.h"
2340dc63e1SGeorge Burgess IV 
2440dc63e1SGeorge Burgess IV using namespace llvm;
2540dc63e1SGeorge Burgess IV 
2640dc63e1SGeorge Burgess IV // FIXME: This is duplicated between this file and MemorySSATest. Refactor.
2740dc63e1SGeorge Burgess IV const static char DLString[] = "e-i64:64-f80:128-n8:16:32:64-S128";
2840dc63e1SGeorge Burgess IV 
2940dc63e1SGeorge Burgess IV /// There's a lot of common setup between these tests. This fixture helps reduce
3040dc63e1SGeorge Burgess IV /// that. Tests should mock up a function, store it in F, and then call
3140dc63e1SGeorge Burgess IV /// setupAnalyses().
3240dc63e1SGeorge Burgess IV class BasicAATest : public testing::Test {
3340dc63e1SGeorge Burgess IV protected:
3440dc63e1SGeorge Burgess IV   // N.B. Many of these members depend on each other (e.g. the Module depends on
3540dc63e1SGeorge Burgess IV   // the Context, etc.). So, order matters here (and in TestAnalyses).
3640dc63e1SGeorge Burgess IV   LLVMContext C;
3740dc63e1SGeorge Burgess IV   Module M;
3840dc63e1SGeorge Burgess IV   IRBuilder<> B;
3940dc63e1SGeorge Burgess IV   DataLayout DL;
4040dc63e1SGeorge Burgess IV   TargetLibraryInfoImpl TLII;
4140dc63e1SGeorge Burgess IV   TargetLibraryInfo TLI;
4240dc63e1SGeorge Burgess IV   Function *F;
4340dc63e1SGeorge Burgess IV 
4440dc63e1SGeorge Burgess IV   // Things that we need to build after the function is created.
4540dc63e1SGeorge Burgess IV   struct TestAnalyses {
4640dc63e1SGeorge Burgess IV     DominatorTree DT;
4740dc63e1SGeorge Burgess IV     AssumptionCache AC;
4840dc63e1SGeorge Burgess IV     BasicAAResult BAA;
49c5bf4520SNikita Popov     AAResults AAR;
50ba664d90SNikita Popov     SimpleAAQueryInfo AAQI;
5140dc63e1SGeorge Burgess IV 
TestAnalysesBasicAATest::TestAnalyses5240dc63e1SGeorge Burgess IV     TestAnalyses(BasicAATest &Test)
53bfc779e4SAlina Sbirlea         : DT(*Test.F), AC(*Test.F), BAA(Test.DL, *Test.F, Test.TLI, AC, &DT),
54c5bf4520SNikita Popov           AAR(Test.TLI), AAQI(AAR) {
55c5bf4520SNikita Popov       AAR.addAAResult(BAA);
56c5bf4520SNikita Popov     }
5740dc63e1SGeorge Burgess IV   };
5840dc63e1SGeorge Burgess IV 
59d4b6fcb3SFangrui Song   std::optional<TestAnalyses> Analyses;
6040dc63e1SGeorge Burgess IV 
setupAnalyses()61bfc779e4SAlina Sbirlea   TestAnalyses &setupAnalyses() {
6240dc63e1SGeorge Burgess IV     assert(F);
6340dc63e1SGeorge Burgess IV     Analyses.emplace(*this);
64d152e50cSKazu Hirata     return *Analyses;
6540dc63e1SGeorge Burgess IV   }
6640dc63e1SGeorge Burgess IV 
6740dc63e1SGeorge Burgess IV public:
BasicAATest()6840dc63e1SGeorge Burgess IV   BasicAATest()
698e55e337SNikita Popov       : M("BasicAATest", C), B(C), DL(DLString), TLI(TLII), F(nullptr) {}
7040dc63e1SGeorge Burgess IV };
7140dc63e1SGeorge Burgess IV 
7240dc63e1SGeorge Burgess IV // Check that a function arg can't trivially alias a global when we're accessing
7340dc63e1SGeorge Burgess IV // >sizeof(global) bytes through that arg, unless the access size is just an
7440dc63e1SGeorge Burgess IV // upper-bound.
TEST_F(BasicAATest,AliasInstWithObjectOfImpreciseSize)75f5b91f2aSPeter Smith TEST_F(BasicAATest, AliasInstWithObjectOfImpreciseSize) {
767e0802aeSArthur Eubanks   F = Function::Create(FunctionType::get(B.getVoidTy(), {B.getPtrTy()}, false),
7740dc63e1SGeorge Burgess IV                        GlobalValue::ExternalLinkage, "F", &M);
7840dc63e1SGeorge Burgess IV 
7940dc63e1SGeorge Burgess IV   BasicBlock *Entry(BasicBlock::Create(C, "", F));
8040dc63e1SGeorge Burgess IV   B.SetInsertPoint(Entry);
8140dc63e1SGeorge Burgess IV 
8240dc63e1SGeorge Burgess IV   Value *IncomingI32Ptr = F->arg_begin();
8340dc63e1SGeorge Burgess IV 
8440dc63e1SGeorge Burgess IV   auto *GlobalPtr =
8540dc63e1SGeorge Burgess IV       cast<GlobalVariable>(M.getOrInsertGlobal("some_global", B.getInt8Ty()));
8640dc63e1SGeorge Burgess IV 
8740dc63e1SGeorge Burgess IV   // Without sufficiently restricted linkage/an init, some of the object size
8840dc63e1SGeorge Burgess IV   // checking bits get more conservative.
8940dc63e1SGeorge Burgess IV   GlobalPtr->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
9040dc63e1SGeorge Burgess IV   GlobalPtr->setInitializer(B.getInt8(0));
9140dc63e1SGeorge Burgess IV 
92bfc779e4SAlina Sbirlea   auto &AllAnalyses = setupAnalyses();
93bfc779e4SAlina Sbirlea   BasicAAResult &BasicAA = AllAnalyses.BAA;
94bfc779e4SAlina Sbirlea   AAQueryInfo &AAQI = AllAnalyses.AAQI;
9540dc63e1SGeorge Burgess IV   ASSERT_EQ(
9640dc63e1SGeorge Burgess IV       BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::precise(4)),
9702988fceSDavid Goldblatt                     MemoryLocation(GlobalPtr, LocationSize::precise(1)), AAQI,
9802988fceSDavid Goldblatt                     nullptr),
9940dc63e1SGeorge Burgess IV       AliasResult::NoAlias);
10040dc63e1SGeorge Burgess IV 
10140dc63e1SGeorge Burgess IV   ASSERT_EQ(
10240dc63e1SGeorge Burgess IV       BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::upperBound(4)),
10302988fceSDavid Goldblatt                     MemoryLocation(GlobalPtr, LocationSize::precise(1)), AAQI,
10402988fceSDavid Goldblatt                     nullptr),
10540dc63e1SGeorge Burgess IV       AliasResult::MayAlias);
10640dc63e1SGeorge Burgess IV }
10740dc63e1SGeorge Burgess IV 
10840dc63e1SGeorge Burgess IV // Check that we fall back to MayAlias if we see an access of an entire object
10940dc63e1SGeorge Burgess IV // that's just an upper-bound.
TEST_F(BasicAATest,AliasInstWithFullObjectOfImpreciseSize)110f5b91f2aSPeter Smith TEST_F(BasicAATest, AliasInstWithFullObjectOfImpreciseSize) {
11140dc63e1SGeorge Burgess IV   F = Function::Create(
11240dc63e1SGeorge Burgess IV       FunctionType::get(B.getVoidTy(), {B.getInt64Ty()}, false),
11340dc63e1SGeorge Burgess IV       GlobalValue::ExternalLinkage, "F", &M);
11440dc63e1SGeorge Burgess IV 
11540dc63e1SGeorge Burgess IV   BasicBlock *Entry(BasicBlock::Create(C, "", F));
11640dc63e1SGeorge Burgess IV   B.SetInsertPoint(Entry);
11740dc63e1SGeorge Burgess IV 
11840dc63e1SGeorge Burgess IV   Value *ArbitraryI32 = F->arg_begin();
11940dc63e1SGeorge Burgess IV   AllocaInst *I8 = B.CreateAlloca(B.getInt8Ty(), B.getInt32(2));
12040dc63e1SGeorge Burgess IV   auto *I8AtUncertainOffset =
121*6c2fbc3aSNikita Popov       cast<GetElementPtrInst>(B.CreatePtrAdd(I8, ArbitraryI32));
12240dc63e1SGeorge Burgess IV 
123bfc779e4SAlina Sbirlea   auto &AllAnalyses = setupAnalyses();
124bfc779e4SAlina Sbirlea   BasicAAResult &BasicAA = AllAnalyses.BAA;
125bfc779e4SAlina Sbirlea   AAQueryInfo &AAQI = AllAnalyses.AAQI;
12640dc63e1SGeorge Burgess IV   ASSERT_EQ(BasicAA.alias(
12740dc63e1SGeorge Burgess IV                 MemoryLocation(I8, LocationSize::precise(2)),
128bfc779e4SAlina Sbirlea                 MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1)),
12902988fceSDavid Goldblatt                 AAQI, nullptr),
13040dc63e1SGeorge Burgess IV             AliasResult::PartialAlias);
13140dc63e1SGeorge Burgess IV 
13240dc63e1SGeorge Burgess IV   ASSERT_EQ(BasicAA.alias(
13340dc63e1SGeorge Burgess IV                 MemoryLocation(I8, LocationSize::upperBound(2)),
134bfc779e4SAlina Sbirlea                 MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1)),
13502988fceSDavid Goldblatt                 AAQI, nullptr),
13640dc63e1SGeorge Burgess IV             AliasResult::MayAlias);
13740dc63e1SGeorge Burgess IV }
1387e0802aeSArthur Eubanks 
TEST_F(BasicAATest,PartialAliasOffsetPhi)1397e0802aeSArthur Eubanks TEST_F(BasicAATest, PartialAliasOffsetPhi) {
1407e0802aeSArthur Eubanks   F = Function::Create(
1417e0802aeSArthur Eubanks       FunctionType::get(B.getVoidTy(), {B.getPtrTy(), B.getInt1Ty()}, false),
1427e0802aeSArthur Eubanks       GlobalValue::ExternalLinkage, "F", &M);
1437e0802aeSArthur Eubanks 
1447e0802aeSArthur Eubanks   Value *Ptr = F->arg_begin();
1457e0802aeSArthur Eubanks   Value *I = F->arg_begin() + 1;
1467e0802aeSArthur Eubanks 
1477e0802aeSArthur Eubanks   BasicBlock *Entry(BasicBlock::Create(C, "", F));
1487e0802aeSArthur Eubanks   BasicBlock *B1(BasicBlock::Create(C, "", F));
1497e0802aeSArthur Eubanks   BasicBlock *B2(BasicBlock::Create(C, "", F));
1507e0802aeSArthur Eubanks   BasicBlock *End(BasicBlock::Create(C, "", F));
1517e0802aeSArthur Eubanks 
1527e0802aeSArthur Eubanks   B.SetInsertPoint(Entry);
1537e0802aeSArthur Eubanks   B.CreateCondBr(I, B1, B2);
1547e0802aeSArthur Eubanks 
1557e0802aeSArthur Eubanks   B.SetInsertPoint(B1);
156*6c2fbc3aSNikita Popov   auto *Ptr1 = cast<GetElementPtrInst>(B.CreatePtrAdd(Ptr, B.getInt32(1)));
1577e0802aeSArthur Eubanks   B.CreateBr(End);
1587e0802aeSArthur Eubanks 
1597e0802aeSArthur Eubanks   B.SetInsertPoint(B2);
160*6c2fbc3aSNikita Popov   auto *Ptr2 = cast<GetElementPtrInst>(B.CreatePtrAdd(Ptr, B.getInt32(1)));
1617e0802aeSArthur Eubanks   B.CreateBr(End);
1627e0802aeSArthur Eubanks 
1637e0802aeSArthur Eubanks   B.SetInsertPoint(End);
1647e0802aeSArthur Eubanks   auto *Phi = B.CreatePHI(B.getPtrTy(), 2);
1657e0802aeSArthur Eubanks   Phi->addIncoming(Ptr1, B1);
1667e0802aeSArthur Eubanks   Phi->addIncoming(Ptr2, B2);
1677e0802aeSArthur Eubanks   B.CreateRetVoid();
1687e0802aeSArthur Eubanks 
1697e0802aeSArthur Eubanks   auto &AllAnalyses = setupAnalyses();
1707e0802aeSArthur Eubanks   BasicAAResult &BasicAA = AllAnalyses.BAA;
1717e0802aeSArthur Eubanks   AAQueryInfo &AAQI = AllAnalyses.AAQI;
17202988fceSDavid Goldblatt   AliasResult AR = BasicAA.alias(MemoryLocation(Ptr, LocationSize::precise(2)),
17302988fceSDavid Goldblatt                                  MemoryLocation(Phi, LocationSize::precise(1)),
17402988fceSDavid Goldblatt                                  AAQI, nullptr);
1757e0802aeSArthur Eubanks   ASSERT_EQ(AR.getOffset(), 1);
1767e0802aeSArthur Eubanks }
1777e0802aeSArthur Eubanks 
TEST_F(BasicAATest,PartialAliasOffsetSelect)1787e0802aeSArthur Eubanks TEST_F(BasicAATest, PartialAliasOffsetSelect) {
1797e0802aeSArthur Eubanks   F = Function::Create(
1807e0802aeSArthur Eubanks       FunctionType::get(B.getVoidTy(), {B.getPtrTy(), B.getInt1Ty()}, false),
1817e0802aeSArthur Eubanks       GlobalValue::ExternalLinkage, "F", &M);
1827e0802aeSArthur Eubanks 
1837e0802aeSArthur Eubanks   Value *Ptr = F->arg_begin();
1847e0802aeSArthur Eubanks   Value *I = F->arg_begin() + 1;
1857e0802aeSArthur Eubanks 
1867e0802aeSArthur Eubanks   BasicBlock *Entry(BasicBlock::Create(C, "", F));
1877e0802aeSArthur Eubanks   B.SetInsertPoint(Entry);
1887e0802aeSArthur Eubanks 
189*6c2fbc3aSNikita Popov   auto *Ptr1 = cast<GetElementPtrInst>(B.CreatePtrAdd(Ptr, B.getInt32(1)));
190*6c2fbc3aSNikita Popov   auto *Ptr2 = cast<GetElementPtrInst>(B.CreatePtrAdd(Ptr, B.getInt32(1)));
1917e0802aeSArthur Eubanks   auto *Select = B.CreateSelect(I, Ptr1, Ptr2);
1927e0802aeSArthur Eubanks   B.CreateRetVoid();
1937e0802aeSArthur Eubanks 
1947e0802aeSArthur Eubanks   auto &AllAnalyses = setupAnalyses();
1957e0802aeSArthur Eubanks   BasicAAResult &BasicAA = AllAnalyses.BAA;
1967e0802aeSArthur Eubanks   AAQueryInfo &AAQI = AllAnalyses.AAQI;
19702988fceSDavid Goldblatt   AliasResult AR = BasicAA.alias(
19802988fceSDavid Goldblatt       MemoryLocation(Ptr, LocationSize::precise(2)),
19902988fceSDavid Goldblatt       MemoryLocation(Select, LocationSize::precise(1)), AAQI, nullptr);
2007e0802aeSArthur Eubanks   ASSERT_EQ(AR.getOffset(), 1);
2017e0802aeSArthur Eubanks }
202