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/Instructions.h" 12 #include "llvm/IR/LLVMContext.h" 13 #include "llvm/IR/Module.h" 14 #include "llvm/Support/SourceMgr.h" 15 #include "gtest/gtest.h" 16 17 using namespace llvm; 18 19 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 20 SMDiagnostic Err; 21 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 22 if (!Mod) 23 Err.print("AnalysisTests", errs()); 24 return Mod; 25 } 26 27 TEST(LoadsTest, FindAvailableLoadedValueSameBasePtrConstantOffsetsNullAA) { 28 LLVMContext C; 29 std::unique_ptr<Module> M = parseIR(C, 30 R"IR( 31 target datalayout = "p:64:64:64:32" 32 %class = type <{ i32, i32 }> 33 34 define i32 @f() { 35 entry: 36 %o = alloca %class 37 %f1 = getelementptr inbounds %class, %class* %o, i32 0, i32 0 38 store i32 42, i32* %f1 39 %f2 = getelementptr inbounds %class, %class* %o, i32 0, i32 1 40 store i32 43, i32* %f2 41 %v = load i32, i32* %f1 42 ret i32 %v 43 } 44 )IR"); 45 auto *GV = M->getNamedValue("f"); 46 ASSERT_TRUE(GV); 47 auto *F = dyn_cast<Function>(GV); 48 ASSERT_TRUE(F); 49 Instruction *Inst = &F->front().front(); 50 auto *AI = dyn_cast<AllocaInst>(Inst); 51 ASSERT_TRUE(AI); 52 Inst = &*++F->front().rbegin(); 53 auto *LI = dyn_cast<LoadInst>(Inst); 54 ASSERT_TRUE(LI); 55 BasicBlock::iterator BBI(LI); 56 Value *Loaded = FindAvailableLoadedValue( 57 LI, LI->getParent(), BBI, 0, nullptr, nullptr); 58 ASSERT_TRUE(Loaded); 59 auto *CI = dyn_cast<ConstantInt>(Loaded); 60 ASSERT_TRUE(CI); 61 ASSERT_TRUE(CI->equalsInt(42)); 62 } 63 64 TEST(LoadsTest, CanReplacePointersIfEqual) { 65 LLVMContext C; 66 std::unique_ptr<Module> M = parseIR(C, 67 R"IR( 68 @y = common global [1 x i32] zeroinitializer, align 4 69 @x = common global [1 x i32] zeroinitializer, align 4 70 71 declare void @use(i32*) 72 73 define void @f(i32* %p) { 74 call void @use(i32* getelementptr inbounds ([1 x i32], [1 x i32]* @y, i64 0, i64 0)) 75 call void @use(i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1)) 76 ret void 77 } 78 )IR"); 79 const auto &DL = M->getDataLayout(); 80 auto *GV = M->getNamedValue("f"); 81 ASSERT_TRUE(GV); 82 auto *F = dyn_cast<Function>(GV); 83 ASSERT_TRUE(F); 84 85 // NOTE: the implementation of canReplacePointersIfEqual is incomplete. 86 // Currently the only the cases it returns false for are really sound and 87 // returning true means unknown. 88 Value *P = &*F->arg_begin(); 89 auto InstIter = F->front().begin(); 90 Value *ConstDerefPtr = *cast<CallInst>(&*InstIter)->arg_begin(); 91 // ConstDerefPtr is a constant pointer that is provably de-referenceable. We 92 // can replace an arbitrary pointer with it. 93 EXPECT_TRUE(canReplacePointersIfEqual(P, ConstDerefPtr, DL, nullptr)); 94 95 ++InstIter; 96 Value *ConstUnDerefPtr = *cast<CallInst>(&*InstIter)->arg_begin(); 97 // ConstUndDerefPtr is a constant pointer that is provably not 98 // de-referenceable. We cannot replace an arbitrary pointer with it. 99 EXPECT_FALSE( 100 canReplacePointersIfEqual(ConstDerefPtr, ConstUnDerefPtr, DL, nullptr)); 101 } 102