From: Ramkumar Ramachandra Date: Fri, 6 Feb 2015 01:46:42 +0000 (+0000) Subject: Introduce print-memderefs to test isDereferenceablePointer X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ab28439f9a5381997cd8335e9974b21f2193b23c;p=oota-llvm.git Introduce print-memderefs to test isDereferenceablePointer Since testing the function indirectly is tricky, introduce a direct print-memderefs pass, in the same spirit as print-memdeps, which prints dereferenceability information matched by FileCheck. Differential Revision: http://reviews.llvm.org/D7075 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228369 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 10a56059ae1..530faa7b5b9 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -162,6 +162,14 @@ namespace llvm { // createJumpInstrTableInfoPass - This creates a pass that stores information // about the jump tables created by JumpInstrTables ImmutablePass *createJumpInstrTableInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createMemDerefPrinter - This pass collects memory dereferenceability + // information and prints it with -analyze. + // + FunctionPass *createMemDerefPrinter(); + } #endif diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 75e93bd2ff8..0bb2854fc2e 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -127,20 +127,32 @@ typedef InstIterator, inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline iterator_range inst_range(Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function *F) { return const_inst_iterator(*F); } inline const_inst_iterator inst_end(const Function *F) { return const_inst_iterator(*F, true); } +inline iterator_range inst_range(const Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline iterator_range inst_range(Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function &F) { return const_inst_iterator(F); } inline const_inst_iterator inst_end(const Function &F) { return const_inst_iterator(F, true); } +inline iterator_range inst_range(const Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} } // End llvm namespace diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 695b41cb128..85162a27f9a 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -199,6 +199,7 @@ void initializeMachineTraceMetricsPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); +void initializeMemDerefPrinterPass(PassRegistry&); void initializeMemoryDependenceAnalysisPass(PassRegistry&); void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 0e5fb0d2609..4b1858b5365 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -168,6 +168,7 @@ namespace { (void) llvm::createSeparateConstOffsetFromGEPPass(); (void) llvm::createRewriteSymbolsPass(); (void) llvm::createStraightLineStrengthReducePass(); + (void) llvm::createMemDerefPrinter(); (void)new llvm::IntervalPartition(); (void)new llvm::ScalarEvolution(); diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp index 92858e72c69..1bfb06d2c9c 100644 --- a/lib/Analysis/Analysis.cpp +++ b/lib/Analysis/Analysis.cpp @@ -55,6 +55,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeLintPass(Registry); initializeLoopInfoWrapperPassPass(Registry); initializeMemDepPrinterPass(Registry); + initializeMemDerefPrinterPass(Registry); initializeMemoryDependenceAnalysisPass(Registry); initializeModuleDebugInfoPrinterPass(Registry); initializePostDominatorTreePass(Registry); diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 78ce0e90b76..351fab9136f 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -38,6 +38,7 @@ add_llvm_library(LLVMAnalysis LoopInfo.cpp LoopPass.cpp MemDepPrinter.cpp + MemDerefPrinter.cpp MemoryBuiltins.cpp MemoryDependenceAnalysis.cpp ModuleDebugInfoPrinter.cpp diff --git a/lib/Analysis/MemDerefPrinter.cpp b/lib/Analysis/MemDerefPrinter.cpp new file mode 100644 index 00000000000..64cec181a2f --- /dev/null +++ b/lib/Analysis/MemDerefPrinter.cpp @@ -0,0 +1,61 @@ +//===- MemDerefPrinter.cpp - Printer for isDereferenceablePointer ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct MemDerefPrinter : public FunctionPass { + SmallVector Vec; + + static char ID; // Pass identifcation, replacement for typeid + MemDerefPrinter() : FunctionPass(ID) { + initializeMemDerefPrinterPass(*PassRegistry::getPassRegistry()); + } + bool runOnFunction(Function &F) override; + void print(raw_ostream &OS, const Module * = nullptr) const override; + void releaseMemory() override { + Vec.clear(); + } + }; +} + +char MemDerefPrinter::ID = 0; +INITIALIZE_PASS(MemDerefPrinter, "print-memderefs", + "Memory Dereferenciblity of pointers in function", false, true) + +FunctionPass *llvm::createMemDerefPrinter() { + return new MemDerefPrinter(); +} + +bool MemDerefPrinter::runOnFunction(Function &F) { + for (auto &I: inst_range(F)) { + if (LoadInst *LI = dyn_cast(&I)) { + Value *PO = LI->getPointerOperand(); + if (PO->isDereferenceablePointer(nullptr)) + Vec.push_back(PO); + } + } + return false; +} + +void MemDerefPrinter::print(raw_ostream &OS, const Module *M) const { + OS << "The following are dereferenceable:\n"; + for (auto &V: Vec) { + V->print(OS); + OS << "\n\n"; + } +} diff --git a/test/Analysis/ValueTracking/memory-dereferenceable.ll b/test/Analysis/ValueTracking/memory-dereferenceable.ll new file mode 100644 index 00000000000..1ec3fefc565 --- /dev/null +++ b/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -0,0 +1,33 @@ +; RUN: opt -print-memderefs -analyze -S <%s | FileCheck %s + +; Uses the print-deref (+ analyze to print) pass to run +; isDereferenceablePointer() on many load instruction operands + +declare zeroext i1 @return_i1() + +@globalstr = global [6 x i8] c"hello\00" + +define void @test(i32 addrspace(1)* byval %dparam) { +; CHECK: The following are dereferenceable: +; CHECK: %globalptr +; CHECK: %alloca +; CHECK: %dparam +; We haven't yet taught it to look through relocations +; CHECK-NOT: %relocate +; CHECK-NOT: %nparam +entry: + %globalptr = getelementptr inbounds [6 x i8]* @globalstr, i32 0, i32 0 + %load1 = load i8* %globalptr + %alloca = alloca i1 + %load2 = load i1* %alloca + %load3 = load i32 addrspace(1)* %dparam + %tok = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4) + %load4 = load i32 addrspace(1)* %relocate + %nparam = getelementptr i32 addrspace(1)* %dparam, i32 5 + %load5 = load i32 addrspace(1)* %nparam + ret void +} + +declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...) +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)