summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Analysis/BasicAliasAnalysisTest.cpp
blob: 068774cdecea92ebbbf980a610c76fb9c386574a (plain)
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
//===- 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/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;

    TestAnalyses(BasicAATest &Test)
        : DT(*Test.F), AC(*Test.F), BAA(Test.DL, *Test.F, Test.TLI, AC, &DT) {}
  };

  llvm::Optional<TestAnalyses> Analyses;

  BasicAAResult &setupAnalyses() {
    assert(F);
    Analyses.emplace(*this);
    return Analyses->BAA;
  }

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));

  BasicAAResult &BasicAA = setupAnalyses();
  ASSERT_EQ(
      BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::precise(4)),
                    MemoryLocation(GlobalPtr, LocationSize::precise(1))),
      AliasResult::NoAlias);

  ASSERT_EQ(
      BasicAA.alias(MemoryLocation(IncomingI32Ptr, LocationSize::upperBound(4)),
                    MemoryLocation(GlobalPtr, LocationSize::precise(1))),
      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));

  BasicAAResult &BasicAA = setupAnalyses();
  ASSERT_EQ(BasicAA.alias(
                MemoryLocation(I8, LocationSize::precise(2)),
                MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1))),
            AliasResult::PartialAlias);

  ASSERT_EQ(BasicAA.alias(
                MemoryLocation(I8, LocationSize::upperBound(2)),
                MemoryLocation(I8AtUncertainOffset, LocationSize::precise(1))),
            AliasResult::MayAlias);
}
OpenPOWER on IntegriCloud