Introduce print-memderefs to test isDereferenceablePointer
authorRamkumar Ramachandra <artagnon@gmail.com>
Fri, 6 Feb 2015 01:46:42 +0000 (01:46 +0000)
committerRamkumar Ramachandra <artagnon@gmail.com>
Fri, 6 Feb 2015 01:46:42 +0000 (01:46 +0000)
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

include/llvm/Analysis/Passes.h
include/llvm/IR/InstIterator.h
include/llvm/InitializePasses.h
include/llvm/LinkAllPasses.h
lib/Analysis/Analysis.cpp
lib/Analysis/CMakeLists.txt
lib/Analysis/MemDerefPrinter.cpp [new file with mode: 0644]
test/Analysis/ValueTracking/memory-dereferenceable.ll [new file with mode: 0644]

index 10a56059ae10cd5d5ef60d5a8620c0a715e9c8ca..530faa7b5b9dd09b4dba1c22e8c191fb18d32d7b 100644 (file)
@@ -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
index 75e93bd2ff8c9e473f9418618b77c18c7809b74a..0bb2854fc2e44605ece73c5af7ba21b330360154 100644 (file)
@@ -127,20 +127,32 @@ typedef InstIterator<const iplist<BasicBlock>,
 
 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_iterator> inst_range(Function *F) {
+  return iterator_range<inst_iterator>(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<const_inst_iterator> inst_range(const Function *F) {
+  return iterator_range<const_inst_iterator>(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_iterator> inst_range(Function &F) {
+  return iterator_range<inst_iterator>(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<const_inst_iterator> inst_range(const Function &F) {
+  return iterator_range<const_inst_iterator>(inst_begin(F), inst_end(F));
+}
 
 } // End llvm namespace
 
index 695b41cb1283ba804af0d58a5f7988ce8e47905c..85162a27f9a74914c73843be27913e7a4e970fdd 100644 (file)
@@ -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&);
index 0e5fb0d2609b95674042ed5e121b500a90a63560..4b1858b5365ff9bb9ed48f21e8e9b0eb3b2b9ac2 100644 (file)
@@ -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();
index 92858e72c69457ff99648d877053224f5b1178ef..1bfb06d2c9c167d22d639e72d5f0b5796882a4fa 100644 (file)
@@ -55,6 +55,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
   initializeLintPass(Registry);
   initializeLoopInfoWrapperPassPass(Registry);
   initializeMemDepPrinterPass(Registry);
+  initializeMemDerefPrinterPass(Registry);
   initializeMemoryDependenceAnalysisPass(Registry);
   initializeModuleDebugInfoPrinterPass(Registry);
   initializePostDominatorTreePass(Registry);
index 78ce0e90b760a47b545e9eefad1b159bcc7df854..351fab9136ff87e818dd2104aba373d6a36d6f2b 100644 (file)
@@ -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 (file)
index 0000000..64cec18
--- /dev/null
@@ -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<Value *, 4> 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<LoadInst>(&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 (file)
index 0000000..1ec3fef
--- /dev/null
@@ -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)