1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
//===- BasicAliasAnalysisTest.cpp - Unit tests for BasicAA ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Targeted tests that are hard/convoluted to make happen with just `opt`.
//
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
// FIXME: This is duplicated between this file and MemorySSATest. Refactor.
const static char DLString[] = "e-i64:64-f80:128-n8:16:32:64-S128";
/// There's a lot of common setup between these tests. This fixture helps reduce
/// that. Tests should mock up a function, store it in F, and then call
/// setupAnalyses().
class BasicAATest : public testing::Test {
protected:
// N.B. Many of these members depend on each other (e.g. the Module depends on
// the Context, etc.). So, order matters here (and in TestAnalyses).
LLVMContext C;
Module M;
IRBuilder<> B;
DataLayout DL;
TargetLibraryInfoImpl TLII;
TargetLibraryInfo TLI;
Function *F;
// Things that we need to build after the function is created.
struct TestAnalyses {
DominatorTree DT;
AssumptionCache AC;
BasicAAResult BAA;
SimpleAAQueryInfo AAQI;
TestAnalyses(BasicAATest &Test)
: DT(*Test.F), AC(*Test.F), BAA(Test.DL, *Test.F, Test.TLI, AC, &DT),
AAQI() {}
};
llvm::Optional<TestAnalyses> Analyses;
TestAnalyses &setupAnalyses() {
assert(F);
Analyses.emplace(*this);
return Analyses.getValue();
}
public:
BasicAATest()
: M("BasicAATest", C), B(C), DL(DLString), TLI(TLII), F(nullptr) {}
};
// Check that a function arg can't trivially alias a global when we're accessing
// >sizeof(global) bytes through that arg, unless the access size is just an
// upper-bound.
TEST_F(BasicAATest, AliasInstWithObjectOfImpreciseSize) {
F = Function::Create(
FunctionType::get(B.getVoidTy(), {B.getInt32Ty()->getPointerTo()}, false),
GlobalValue::ExternalLinkage, "F", &M);
BasicBlock *Entry(BasicBlock::Create(C, "", F));
B.SetInsertPoint(Entry);
Value *IncomingI32Ptr = F->arg_begin();
auto *GlobalPtr =
cast<GlobalVariable>(M.getOrInsertGlobal("some_global", B.getInt8Ty()));
// Without sufficiently restricted linkage/an init, some of the object size
// checking bits get more conservative.
GlobalPtr->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
GlobalPtr->setInitializer(B.getInt8(0));
auto &AllAnalyses = setupAnalyses();
BasicAAResult &BasicAA = AllAnalyses.BAA;
AAQueryInfo &AAQI = AllAnalyses.AAQI;
ASSERT_EQ(
BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::precise(4)),
MemoryLocation(GlobalPtr, LocationSize::precise(1)), AAQI),
AliasResult::NoAlias);
ASSERT_EQ(
BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::upperBound(4)),
MemoryLocation(GlobalPtr, LocationSize::precise(1)), AAQI),
AliasResult::MayAlias);
}
// Check that we fall back to MayAlias if we see an access of an entire object
// that's just an upper-bound.
TEST_F(BasicAATest, AliasInstWithFullObjectOfImpreciseSize) {
F = Function::Create(
FunctionType::get(B.getVoidTy(), {B.getInt64Ty()}, false),
GlobalValue::ExternalLinkage, "F", &M);
BasicBlock *Entry(BasicBlock::Create(C, "", F));
B.SetInsertPoint(Entry);
Value *ArbitraryI32 = F->arg_begin();
AllocaInst *I8 = B.CreateAlloca(B.getInt8Ty(), B.getInt32(2));
auto *I8AtUncertainOffset =
cast<GetElementPtrInst>(B.CreateGEP(B.getInt8Ty(), I8, ArbitraryI32));
auto &AllAnalyses = setupAnalyses();
BasicAAResult &BasicAA = AllAnalyses.BAA;
AAQueryInfo &AAQI = AllAnalyses.AAQI;
ASSERT_EQ(BasicAA.alias(
MemoryLocation(I8, LocationSize::precise(2)),
MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1)),
AAQI),
AliasResult::PartialAlias);
ASSERT_EQ(BasicAA.alias(
MemoryLocation(I8, LocationSize::upperBound(2)),
MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1)),
AAQI),
AliasResult::MayAlias);
}
|