summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Analysis/Passes.h8
-rw-r--r--llvm/include/llvm/IR/InstIterator.h12
-rw-r--r--llvm/include/llvm/InitializePasses.h1
-rw-r--r--llvm/include/llvm/LinkAllPasses.h1
-rw-r--r--llvm/lib/Analysis/Analysis.cpp1
-rw-r--r--llvm/lib/Analysis/CMakeLists.txt1
-rw-r--r--llvm/lib/Analysis/MemDerefPrinter.cpp61
-rw-r--r--llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll33
8 files changed, 118 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/Passes.h b/llvm/include/llvm/Analysis/Passes.h
index 10a56059ae1..530faa7b5b9 100644
--- a/llvm/include/llvm/Analysis/Passes.h
+++ b/llvm/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/llvm/include/llvm/IR/InstIterator.h b/llvm/include/llvm/IR/InstIterator.h
index 75e93bd2ff8..0bb2854fc2e 100644
--- a/llvm/include/llvm/IR/InstIterator.h
+++ b/llvm/include/llvm/IR/InstIterator.h
@@ -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
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 695b41cb128..85162a27f9a 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/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/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h
index 0e5fb0d2609..4b1858b5365 100644
--- a/llvm/include/llvm/LinkAllPasses.h
+++ b/llvm/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/llvm/lib/Analysis/Analysis.cpp b/llvm/lib/Analysis/Analysis.cpp
index 92858e72c69..1bfb06d2c9c 100644
--- a/llvm/lib/Analysis/Analysis.cpp
+++ b/llvm/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/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 78ce0e90b76..351fab9136f 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/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/llvm/lib/Analysis/MemDerefPrinter.cpp b/llvm/lib/Analysis/MemDerefPrinter.cpp
new file mode 100644
index 00000000000..64cec181a2f
--- /dev/null
+++ b/llvm/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<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/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll b/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll
new file mode 100644
index 00000000000..1ec3fefc565
--- /dev/null
+++ b/llvm/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)
OpenPOWER on IntegriCloud