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