Index: llvm/trunk/include/llvm/Analysis/Passes.h =================================================================== --- llvm/trunk/include/llvm/Analysis/Passes.h +++ llvm/trunk/include/llvm/Analysis/Passes.h @@ -162,6 +162,14 @@ // 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 Index: llvm/trunk/include/llvm/IR/InstIterator.h =================================================================== --- llvm/trunk/include/llvm/IR/InstIterator.h +++ llvm/trunk/include/llvm/IR/InstIterator.h @@ -127,20 +127,32 @@ 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 Index: llvm/trunk/include/llvm/InitializePasses.h =================================================================== --- llvm/trunk/include/llvm/InitializePasses.h +++ llvm/trunk/include/llvm/InitializePasses.h @@ -199,6 +199,7 @@ void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); +void initializeMemDerefPrinterPass(PassRegistry&); void initializeMemoryDependenceAnalysisPass(PassRegistry&); void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); Index: llvm/trunk/include/llvm/LinkAllPasses.h =================================================================== --- llvm/trunk/include/llvm/LinkAllPasses.h +++ llvm/trunk/include/llvm/LinkAllPasses.h @@ -168,6 +168,7 @@ (void) llvm::createSeparateConstOffsetFromGEPPass(); (void) llvm::createRewriteSymbolsPass(); (void) llvm::createStraightLineStrengthReducePass(); + (void) llvm::createMemDerefPrinter(); (void)new llvm::IntervalPartition(); (void)new llvm::ScalarEvolution(); Index: llvm/trunk/lib/Analysis/Analysis.cpp =================================================================== --- llvm/trunk/lib/Analysis/Analysis.cpp +++ llvm/trunk/lib/Analysis/Analysis.cpp @@ -55,6 +55,7 @@ initializeLintPass(Registry); initializeLoopInfoWrapperPassPass(Registry); initializeMemDepPrinterPass(Registry); + initializeMemDerefPrinterPass(Registry); initializeMemoryDependenceAnalysisPass(Registry); initializeModuleDebugInfoPrinterPass(Registry); initializePostDominatorTreePass(Registry); Index: llvm/trunk/lib/Analysis/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Analysis/CMakeLists.txt +++ llvm/trunk/lib/Analysis/CMakeLists.txt @@ -38,6 +38,7 @@ LoopInfo.cpp LoopPass.cpp MemDepPrinter.cpp + MemDerefPrinter.cpp MemoryBuiltins.cpp MemoryDependenceAnalysis.cpp ModuleDebugInfoPrinter.cpp Index: llvm/trunk/lib/Analysis/MemDerefPrinter.cpp =================================================================== --- llvm/trunk/lib/Analysis/MemDerefPrinter.cpp +++ llvm/trunk/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"; + } +} Index: llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll =================================================================== --- llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ llvm/trunk/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)