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;
49ba664d90SNikita Popov SimpleAAQueryInfo AAQI;
5040dc63e1SGeorge Burgess IV
TestAnalysesBasicAATest::TestAnalyses5140dc63e1SGeorge Burgess IV TestAnalyses(BasicAATest &Test)
52bfc779e4SAlina Sbirlea : DT(*Test.F), AC(*Test.F), BAA(Test.DL, *Test.F, Test.TLI, AC, &DT),
53bfc779e4SAlina Sbirlea AAQI() {}
5440dc63e1SGeorge Burgess IV };
5540dc63e1SGeorge Burgess IV
5640dc63e1SGeorge Burgess IV llvm::Optional<TestAnalyses> Analyses;
5740dc63e1SGeorge Burgess IV
setupAnalyses()58bfc779e4SAlina Sbirlea TestAnalyses &setupAnalyses() {
5940dc63e1SGeorge Burgess IV assert(F);
6040dc63e1SGeorge Burgess IV Analyses.emplace(*this);
61*d152e50cSKazu Hirata return *Analyses;
6240dc63e1SGeorge Burgess IV }
6340dc63e1SGeorge Burgess IV
6440dc63e1SGeorge Burgess IV public:
BasicAATest()6540dc63e1SGeorge Burgess IV BasicAATest()
667e0802aeSArthur Eubanks : M("BasicAATest", C), B(C), DL(DLString), TLI(TLII), F(nullptr) {
677e0802aeSArthur Eubanks C.setOpaquePointers(true);
687e0802aeSArthur Eubanks }
6940dc63e1SGeorge Burgess IV };
7040dc63e1SGeorge Burgess IV
7140dc63e1SGeorge Burgess IV // Check that a function arg can't trivially alias a global when we're accessing
7240dc63e1SGeorge Burgess IV // >sizeof(global) bytes through that arg, unless the access size is just an
7340dc63e1SGeorge Burgess IV // upper-bound.
TEST_F(BasicAATest,AliasInstWithObjectOfImpreciseSize)74f5b91f2aSPeter Smith TEST_F(BasicAATest, AliasInstWithObjectOfImpreciseSize) {
757e0802aeSArthur Eubanks F = Function::Create(FunctionType::get(B.getVoidTy(), {B.getPtrTy()}, false),
7640dc63e1SGeorge Burgess IV GlobalValue::ExternalLinkage, "F", &M);
7740dc63e1SGeorge Burgess IV
7840dc63e1SGeorge Burgess IV BasicBlock *Entry(BasicBlock::Create(C, "", F));
7940dc63e1SGeorge Burgess IV B.SetInsertPoint(Entry);
8040dc63e1SGeorge Burgess IV
8140dc63e1SGeorge Burgess IV Value *IncomingI32Ptr = F->arg_begin();
8240dc63e1SGeorge Burgess IV
8340dc63e1SGeorge Burgess IV auto *GlobalPtr =
8440dc63e1SGeorge Burgess IV cast<GlobalVariable>(M.getOrInsertGlobal("some_global", B.getInt8Ty()));
8540dc63e1SGeorge Burgess IV
8640dc63e1SGeorge Burgess IV // Without sufficiently restricted linkage/an init, some of the object size
8740dc63e1SGeorge Burgess IV // checking bits get more conservative.
8840dc63e1SGeorge Burgess IV GlobalPtr->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
8940dc63e1SGeorge Burgess IV GlobalPtr->setInitializer(B.getInt8(0));
9040dc63e1SGeorge Burgess IV
91bfc779e4SAlina Sbirlea auto &AllAnalyses = setupAnalyses();
92bfc779e4SAlina Sbirlea BasicAAResult &BasicAA = AllAnalyses.BAA;
93bfc779e4SAlina Sbirlea AAQueryInfo &AAQI = AllAnalyses.AAQI;
9440dc63e1SGeorge Burgess IV ASSERT_EQ(
9540dc63e1SGeorge Burgess IV BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::precise(4)),
96bfc779e4SAlina Sbirlea MemoryLocation(GlobalPtr, LocationSize::precise(1)), AAQI),
9740dc63e1SGeorge Burgess IV AliasResult::NoAlias);
9840dc63e1SGeorge Burgess IV
9940dc63e1SGeorge Burgess IV ASSERT_EQ(
10040dc63e1SGeorge Burgess IV BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::upperBound(4)),
101bfc779e4SAlina Sbirlea MemoryLocation(GlobalPtr, LocationSize::precise(1)), AAQI),
10240dc63e1SGeorge Burgess IV AliasResult::MayAlias);
10340dc63e1SGeorge Burgess IV }
10440dc63e1SGeorge Burgess IV
10540dc63e1SGeorge Burgess IV // Check that we fall back to MayAlias if we see an access of an entire object
10640dc63e1SGeorge Burgess IV // that's just an upper-bound.
TEST_F(BasicAATest,AliasInstWithFullObjectOfImpreciseSize)107f5b91f2aSPeter Smith TEST_F(BasicAATest, AliasInstWithFullObjectOfImpreciseSize) {
10840dc63e1SGeorge Burgess IV F = Function::Create(
10940dc63e1SGeorge Burgess IV FunctionType::get(B.getVoidTy(), {B.getInt64Ty()}, false),
11040dc63e1SGeorge Burgess IV GlobalValue::ExternalLinkage, "F", &M);
11140dc63e1SGeorge Burgess IV
11240dc63e1SGeorge Burgess IV BasicBlock *Entry(BasicBlock::Create(C, "", F));
11340dc63e1SGeorge Burgess IV B.SetInsertPoint(Entry);
11440dc63e1SGeorge Burgess IV
11540dc63e1SGeorge Burgess IV Value *ArbitraryI32 = F->arg_begin();
11640dc63e1SGeorge Burgess IV AllocaInst *I8 = B.CreateAlloca(B.getInt8Ty(), B.getInt32(2));
11740dc63e1SGeorge Burgess IV auto *I8AtUncertainOffset =
1187716075aSJames Y Knight cast<GetElementPtrInst>(B.CreateGEP(B.getInt8Ty(), I8, ArbitraryI32));
11940dc63e1SGeorge Burgess IV
120bfc779e4SAlina Sbirlea auto &AllAnalyses = setupAnalyses();
121bfc779e4SAlina Sbirlea BasicAAResult &BasicAA = AllAnalyses.BAA;
122bfc779e4SAlina Sbirlea AAQueryInfo &AAQI = AllAnalyses.AAQI;
12340dc63e1SGeorge Burgess IV ASSERT_EQ(BasicAA.alias(
12440dc63e1SGeorge Burgess IV MemoryLocation(I8, LocationSize::precise(2)),
125bfc779e4SAlina Sbirlea MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1)),
126bfc779e4SAlina Sbirlea AAQI),
12740dc63e1SGeorge Burgess IV AliasResult::PartialAlias);
12840dc63e1SGeorge Burgess IV
12940dc63e1SGeorge Burgess IV ASSERT_EQ(BasicAA.alias(
13040dc63e1SGeorge Burgess IV MemoryLocation(I8, LocationSize::upperBound(2)),
131bfc779e4SAlina Sbirlea MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1)),
132bfc779e4SAlina Sbirlea AAQI),
13340dc63e1SGeorge Burgess IV AliasResult::MayAlias);
13440dc63e1SGeorge Burgess IV }
1357e0802aeSArthur Eubanks
TEST_F(BasicAATest,PartialAliasOffsetPhi)1367e0802aeSArthur Eubanks TEST_F(BasicAATest, PartialAliasOffsetPhi) {
1377e0802aeSArthur Eubanks F = Function::Create(
1387e0802aeSArthur Eubanks FunctionType::get(B.getVoidTy(), {B.getPtrTy(), B.getInt1Ty()}, false),
1397e0802aeSArthur Eubanks GlobalValue::ExternalLinkage, "F", &M);
1407e0802aeSArthur Eubanks
1417e0802aeSArthur Eubanks Value *Ptr = F->arg_begin();
1427e0802aeSArthur Eubanks Value *I = F->arg_begin() + 1;
1437e0802aeSArthur Eubanks
1447e0802aeSArthur Eubanks BasicBlock *Entry(BasicBlock::Create(C, "", F));
1457e0802aeSArthur Eubanks BasicBlock *B1(BasicBlock::Create(C, "", F));
1467e0802aeSArthur Eubanks BasicBlock *B2(BasicBlock::Create(C, "", F));
1477e0802aeSArthur Eubanks BasicBlock *End(BasicBlock::Create(C, "", F));
1487e0802aeSArthur Eubanks
1497e0802aeSArthur Eubanks B.SetInsertPoint(Entry);
1507e0802aeSArthur Eubanks B.CreateCondBr(I, B1, B2);
1517e0802aeSArthur Eubanks
1527e0802aeSArthur Eubanks B.SetInsertPoint(B1);
1537e0802aeSArthur Eubanks auto *Ptr1 =
1547e0802aeSArthur Eubanks cast<GetElementPtrInst>(B.CreateGEP(B.getInt8Ty(), Ptr, B.getInt32(1)));
1557e0802aeSArthur Eubanks B.CreateBr(End);
1567e0802aeSArthur Eubanks
1577e0802aeSArthur Eubanks B.SetInsertPoint(B2);
1587e0802aeSArthur Eubanks auto *Ptr2 =
1597e0802aeSArthur Eubanks cast<GetElementPtrInst>(B.CreateGEP(B.getInt8Ty(), Ptr, B.getInt32(1)));
1607e0802aeSArthur Eubanks B.CreateBr(End);
1617e0802aeSArthur Eubanks
1627e0802aeSArthur Eubanks B.SetInsertPoint(End);
1637e0802aeSArthur Eubanks auto *Phi = B.CreatePHI(B.getPtrTy(), 2);
1647e0802aeSArthur Eubanks Phi->addIncoming(Ptr1, B1);
1657e0802aeSArthur Eubanks Phi->addIncoming(Ptr2, B2);
1667e0802aeSArthur Eubanks B.CreateRetVoid();
1677e0802aeSArthur Eubanks
1687e0802aeSArthur Eubanks auto &AllAnalyses = setupAnalyses();
1697e0802aeSArthur Eubanks BasicAAResult &BasicAA = AllAnalyses.BAA;
1707e0802aeSArthur Eubanks AAQueryInfo &AAQI = AllAnalyses.AAQI;
1717e0802aeSArthur Eubanks AliasResult AR =
1727e0802aeSArthur Eubanks BasicAA.alias(MemoryLocation(Ptr, LocationSize::precise(2)),
1737e0802aeSArthur Eubanks MemoryLocation(Phi, LocationSize::precise(1)), AAQI);
1747e0802aeSArthur Eubanks ASSERT_EQ(AR.getOffset(), 1);
1757e0802aeSArthur Eubanks }
1767e0802aeSArthur Eubanks
TEST_F(BasicAATest,PartialAliasOffsetSelect)1777e0802aeSArthur Eubanks TEST_F(BasicAATest, PartialAliasOffsetSelect) {
1787e0802aeSArthur Eubanks F = Function::Create(
1797e0802aeSArthur Eubanks FunctionType::get(B.getVoidTy(), {B.getPtrTy(), B.getInt1Ty()}, false),
1807e0802aeSArthur Eubanks GlobalValue::ExternalLinkage, "F", &M);
1817e0802aeSArthur Eubanks
1827e0802aeSArthur Eubanks Value *Ptr = F->arg_begin();
1837e0802aeSArthur Eubanks Value *I = F->arg_begin() + 1;
1847e0802aeSArthur Eubanks
1857e0802aeSArthur Eubanks BasicBlock *Entry(BasicBlock::Create(C, "", F));
1867e0802aeSArthur Eubanks B.SetInsertPoint(Entry);
1877e0802aeSArthur Eubanks
1887e0802aeSArthur Eubanks auto *Ptr1 =
1897e0802aeSArthur Eubanks cast<GetElementPtrInst>(B.CreateGEP(B.getInt8Ty(), Ptr, B.getInt32(1)));
1907e0802aeSArthur Eubanks auto *Ptr2 =
1917e0802aeSArthur Eubanks cast<GetElementPtrInst>(B.CreateGEP(B.getInt8Ty(), Ptr, B.getInt32(1)));
1927e0802aeSArthur Eubanks auto *Select = B.CreateSelect(I, Ptr1, Ptr2);
1937e0802aeSArthur Eubanks B.CreateRetVoid();
1947e0802aeSArthur Eubanks
1957e0802aeSArthur Eubanks auto &AllAnalyses = setupAnalyses();
1967e0802aeSArthur Eubanks BasicAAResult &BasicAA = AllAnalyses.BAA;
1977e0802aeSArthur Eubanks AAQueryInfo &AAQI = AllAnalyses.AAQI;
1987e0802aeSArthur Eubanks AliasResult AR =
1997e0802aeSArthur Eubanks BasicAA.alias(MemoryLocation(Ptr, LocationSize::precise(2)),
2007e0802aeSArthur Eubanks MemoryLocation(Select, LocationSize::precise(1)), AAQI);
2017e0802aeSArthur Eubanks ASSERT_EQ(AR.getOffset(), 1);
2027e0802aeSArthur Eubanks }
203