1//===- LoadsTest.cpp - local load analysis unit tests ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Analysis/Loads.h"
10#include "llvm/AsmParser/Parser.h"
11#include "llvm/IR/Constants.h"
12#include "llvm/IR/Instructions.h"
13#include "llvm/IR/LLVMContext.h"
14#include "llvm/IR/Module.h"
15#include "llvm/Support/SourceMgr.h"
16#include "gtest/gtest.h"
17
18using namespace llvm;
19
20static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
21 SMDiagnostic Err;
22 std::unique_ptr<Module> Mod = parseAssemblyString(AsmString: IR, Err, Context&: C);
23 if (!Mod)
24 Err.print(ProgName: "AnalysisTests", S&: errs());
25 return Mod;
26}
27
28TEST(LoadsTest, FindAvailableLoadedValueSameBasePtrConstantOffsetsNullAA) {
29 LLVMContext C;
30 std::unique_ptr<Module> M = parseIR(C,
31 IR: R"IR(
32target datalayout = "p:64:64:64:32"
33%class = type <{ i32, i32 }>
34
35define i32 @f() {
36entry:
37 %o = alloca %class
38 %f1 = getelementptr inbounds %class, %class* %o, i32 0, i32 0
39 store i32 42, i32* %f1
40 %f2 = getelementptr inbounds %class, %class* %o, i32 0, i32 1
41 store i32 43, i32* %f2
42 %v = load i32, i32* %f1
43 ret i32 %v
44}
45)IR");
46 auto *GV = M->getNamedValue(Name: "f");
47 ASSERT_TRUE(GV);
48 auto *F = dyn_cast<Function>(Val: GV);
49 ASSERT_TRUE(F);
50 Instruction *Inst = &F->front().front();
51 auto *AI = dyn_cast<AllocaInst>(Val: Inst);
52 ASSERT_TRUE(AI);
53 Inst = &*++F->front().rbegin();
54 auto *LI = dyn_cast<LoadInst>(Val: Inst);
55 ASSERT_TRUE(LI);
56 BasicBlock::iterator BBI(LI);
57 Value *Loaded = FindAvailableLoadedValue(
58 Load: LI, ScanBB: LI->getParent(), ScanFrom&: BBI, MaxInstsToScan: 0, AA: nullptr, IsLoadCSE: nullptr);
59 ASSERT_TRUE(Loaded);
60 auto *CI = dyn_cast<ConstantInt>(Val: Loaded);
61 ASSERT_TRUE(CI);
62 ASSERT_TRUE(CI->equalsInt(42));
63}
64
65TEST(LoadsTest, CanReplacePointersIfEqual) {
66 LLVMContext C;
67 std::unique_ptr<Module> M = parseIR(C,
68 IR: R"IR(
69@y = common global [1 x i32] zeroinitializer, align 4
70@x = common global [1 x i32] zeroinitializer, align 4
71declare void @use(i32*)
72
73define void @f(i32* %p1, i32* %p2, i64 %i) {
74 call void @use(i32* getelementptr inbounds ([1 x i32], [1 x i32]* @y, i64 0, i64 0))
75
76 %p1_idx = getelementptr inbounds i32, i32* %p1, i64 %i
77 call void @use(i32* %p1_idx)
78
79 %icmp = icmp eq i32* %p1, getelementptr inbounds ([1 x i32], [1 x i32]* @y, i64 0, i64 0)
80 %ptrInt = ptrtoint i32* %p1 to i64
81 ret void
82}
83)IR");
84 const DataLayout &DL = M->getDataLayout();
85 auto *GV = M->getNamedValue(Name: "f");
86 ASSERT_TRUE(GV);
87 auto *F = dyn_cast<Function>(Val: GV);
88 ASSERT_TRUE(F);
89
90 Value *P1 = &*F->arg_begin();
91 Value *P2 = F->getArg(i: 1);
92 Value *NullPtr = Constant::getNullValue(Ty: P1->getType());
93 auto InstIter = F->front().begin();
94 CallInst *UserOfY = cast<CallInst>(Val: &*InstIter);
95 Value *ConstDerefPtr = UserOfY->getArgOperand(i: 0);
96 // We cannot replace two pointers in arbitrary instructions unless we are
97 // replacing with null, a constant dereferencable pointer or they have the
98 // same underlying object.
99 EXPECT_FALSE(canReplacePointersIfEqual(ConstDerefPtr, P1, DL));
100 EXPECT_FALSE(canReplacePointersIfEqual(P1, P2, DL));
101 EXPECT_TRUE(canReplacePointersIfEqual(P1, ConstDerefPtr, DL));
102 EXPECT_TRUE(canReplacePointersIfEqual(P1, NullPtr, DL));
103
104 GetElementPtrInst *BasedOnP1 = cast<GetElementPtrInst>(Val: &*++InstIter);
105 EXPECT_TRUE(canReplacePointersIfEqual(BasedOnP1, P1, DL));
106 EXPECT_FALSE(canReplacePointersIfEqual(BasedOnP1, P2, DL));
107
108 // We can replace two arbitrary pointers in icmp and ptrtoint instructions.
109 auto P1UseIter = P1->use_begin();
110 const Use &PtrToIntUse = *P1UseIter;
111 const Use &IcmpUse = *++P1UseIter;
112 const Use &GEPUse = *++P1UseIter;
113 EXPECT_FALSE(canReplacePointersInUseIfEqual(GEPUse, P2, DL));
114 EXPECT_TRUE(canReplacePointersInUseIfEqual(PtrToIntUse, P2, DL));
115 EXPECT_TRUE(canReplacePointersInUseIfEqual(IcmpUse, P2, DL));
116}
117

source code of llvm/unittests/Analysis/LoadsTest.cpp