[llvm] r229898 - [LoopAccesses] Add -analyze support
Adam Nemet
anemet at apple.com
Thu Feb 19 11:15:19 PST 2015
Author: anemet
Date: Thu Feb 19 13:15:19 2015
New Revision: 229898
URL: http://llvm.org/viewvc/llvm-project?rev=229898&view=rev
Log:
[LoopAccesses] Add -analyze support
The LoopInfo in combination with depth_first is used to enumerate the
loops.
Right now -analyze is not yet complete. It only prints the result of
the analysis, the report and the run-time checks. Printing the unsafe
depedences will require a bit more reshuffling which I'd like to do in a
follow-on to this patchset. Unsafe dependences are currently checked
via -debug-only=loop-accesses in the new test.
This is part of the patchset that converts LoopAccessAnalysis into an
actual analysis pass.
Added:
llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks-no-dbg.ll
llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll
Modified:
llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h
llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp
Modified: llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h?rev=229898&r1=229897&r2=229898&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h Thu Feb 19 13:15:19 2015
@@ -122,10 +122,16 @@ public:
void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr,
unsigned DepSetId, unsigned ASId, ValueToValueMap &Strides);
+ /// \brief No run-time memory checking is necessary.
+ bool empty() const { return Pointers.empty(); }
+
/// \brief Decide whether we need to issue a run-time check for pointer at
/// index \p I and \p J to prove their independence.
bool needsChecking(unsigned I, unsigned J) const;
+ /// \brief Print the list run-time memory checks necessary.
+ void print(raw_ostream &OS, unsigned Depth = 0) const;
+
/// This flag indicates if we need to add the runtime check.
bool Need;
/// Holds the pointers that we need to check.
@@ -176,6 +182,9 @@ public:
/// couldn't analyze the loop.
Optional<LoopAccessReport> &getReport() { return Report; }
+ /// \brief Print the information about the memory accesses in the loop.
+ void print(raw_ostream &OS, unsigned Depth = 0) const;
+
/// \brief Used to ensure that if the analysis was run with speculating the
/// value of symbolic strides, the client queries it with the same assumption.
/// Only used in DEBUG build but we don't want NDEBUG-depedent ABI.
@@ -258,6 +267,9 @@ public:
LoopAccessInfoMap.clear();
}
+ /// \brief Print the result of the analysis when invoked with -analyze.
+ void print(raw_ostream &OS, const Module *M = nullptr) const override;
+
private:
/// \brief The cache.
DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap;
Modified: llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp?rev=229898&r1=229897&r2=229898&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp Thu Feb 19 13:15:19 2015
@@ -135,6 +135,23 @@ bool LoopAccessInfo::RuntimePointerCheck
return true;
}
+void LoopAccessInfo::RuntimePointerCheck::print(raw_ostream &OS,
+ unsigned Depth) const {
+ unsigned NumPointers = Pointers.size();
+ if (NumPointers == 0)
+ return;
+
+ OS.indent(Depth) << "Run-time memory checks:\n";
+ unsigned N = 0;
+ for (unsigned I = 0; I < NumPointers; ++I)
+ for (unsigned J = I + 1; J < NumPointers; ++J)
+ if (needsChecking(I, J)) {
+ OS.indent(Depth) << N++ << ":\n";
+ OS.indent(Depth + 2) << *Pointers[I] << "\n";
+ OS.indent(Depth + 2) << *Pointers[J] << "\n";
+ }
+}
+
namespace {
/// \brief Analyses memory accesses in a loop.
///
@@ -1291,6 +1308,24 @@ LoopAccessInfo::LoopAccessInfo(Loop *L,
analyzeLoop(Strides);
}
+void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const {
+ if (CanVecMem) {
+ if (PtrRtCheck.empty())
+ OS.indent(Depth) << "Memory dependences are safe\n";
+ else
+ OS.indent(Depth) << "Memory dependences are safe with run-time checks\n";
+ }
+
+ if (Report)
+ OS.indent(Depth) << "Report: " << Report->str() << "\n";
+
+ // FIXME: Print unsafe dependences
+
+ // List the pair of accesses need run-time checks to prove independence.
+ PtrRtCheck.print(OS, Depth);
+ OS << "\n";
+}
+
LoopAccessInfo &LoopAccessAnalysis::getInfo(Loop *L, ValueToValueMap &Strides) {
auto &LAI = LoopAccessInfoMap[L];
@@ -1308,6 +1343,20 @@ LoopAccessInfo &LoopAccessAnalysis::getI
return *LAI.get();
}
+void LoopAccessAnalysis::print(raw_ostream &OS, const Module *M) const {
+ LoopAccessAnalysis &LAA = *const_cast<LoopAccessAnalysis *>(this);
+
+ LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
+ ValueToValueMap NoSymbolicStrides;
+
+ for (Loop *TopLevelLoop : *LI)
+ for (Loop *L : depth_first(TopLevelLoop)) {
+ OS.indent(2) << L->getHeader()->getName() << ":\n";
+ auto &LAI = LAA.getInfo(L, NoSymbolicStrides);
+ LAI.print(OS, 4);
+ }
+}
+
bool LoopAccessAnalysis::runOnFunction(Function &F) {
SE = &getAnalysis<ScalarEvolution>();
DL = F.getParent()->getDataLayout();
@@ -1323,6 +1372,7 @@ void LoopAccessAnalysis::getAnalysisUsag
AU.addRequired<ScalarEvolution>();
AU.addRequired<AliasAnalysis>();
AU.addRequired<DominatorTreeWrapperPass>();
+ AU.addRequired<LoopInfoWrapperPass>();
AU.setPreservesAll();
}
@@ -1335,6 +1385,7 @@ INITIALIZE_PASS_BEGIN(LoopAccessAnalysis
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_END(LoopAccessAnalysis, LAA_NAME, laa_name, false, true)
namespace llvm {
Added: llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks-no-dbg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks-no-dbg.ll?rev=229898&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks-no-dbg.ll (added)
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks-no-dbg.ll Thu Feb 19 13:15:19 2015
@@ -0,0 +1,60 @@
+; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
+
+; FIXME: This is the non-debug version of unsafe-and-rt-checks.ll not
+; requiring "asserts". Once we can check memory dependences without -debug,
+; we should remove this test.
+
+; Analyze this loop:
+; for (i = 0; i < n; i++)
+; A[i + 1] = A[i] * B[i] * C[i];
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; CHECK: Report: unsafe dependent memory operations in loop
+
+; CHECK: Run-time memory checks:
+; CHECK-NEXT: 0:
+; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16* %a, i64 %add
+; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16* %b, i64 %storemerge3
+; CHECK-NEXT: 1:
+; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16* %a, i64 %add
+; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16* %c, i64 %storemerge3
+
+ at n = global i32 20, align 4
+ at B = common global i16* null, align 8
+ at A = common global i16* null, align 8
+ at C = common global i16* null, align 8
+
+define void @f() {
+entry:
+ %a = load i16** @A, align 8
+ %b = load i16** @B, align 8
+ %c = load i16** @C, align 8
+ br label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %storemerge3 = phi i64 [ 0, %entry ], [ %add, %for.body ]
+
+ %arrayidxA = getelementptr inbounds i16* %a, i64 %storemerge3
+ %loadA = load i16* %arrayidxA, align 2
+
+ %arrayidxB = getelementptr inbounds i16* %b, i64 %storemerge3
+ %loadB = load i16* %arrayidxB, align 2
+
+ %arrayidxC = getelementptr inbounds i16* %c, i64 %storemerge3
+ %loadC = load i16* %arrayidxC, align 2
+
+ %mul = mul i16 %loadB, %loadA
+ %mul1 = mul i16 %mul, %loadC
+
+ %add = add nuw nsw i64 %storemerge3, 1
+ %arrayidxA_plus_2 = getelementptr inbounds i16* %a, i64 %add
+ store i16 %mul1, i16* %arrayidxA_plus_2, align 2
+
+ %exitcond = icmp eq i64 %add, 20
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}
Added: llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll?rev=229898&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll (added)
+++ llvm/trunk/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll Thu Feb 19 13:15:19 2015
@@ -0,0 +1,61 @@
+; RUN: opt -loop-accesses -analyze < %s | FileCheck %s
+; RUN: opt -loop-accesses -analyze -debug-only=loop-accesses < %s 2>&1 | FileCheck %s --check-prefix=DEBUG
+; REQUIRES: asserts
+
+; Analyze this loop:
+; for (i = 0; i < n; i++)
+; A[i + 1] = A[i] * B[i] * C[i];
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; CHECK: Report: unsafe dependent memory operations in loop
+
+; DEBUG: LAA: Distance for %loadA = load i16* %arrayidxA, align 2 to store i16 %mul1, i16* %arrayidxA_plus_2, align 2: 2
+; DEBUG-NEXT: LAA: Failure because of Positive distance 2
+
+; CHECK: Run-time memory checks:
+; CHECK-NEXT: 0:
+; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16* %a, i64 %add
+; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16* %b, i64 %storemerge3
+; CHECK-NEXT: 1:
+; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16* %a, i64 %add
+; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16* %c, i64 %storemerge3
+
+ at n = global i32 20, align 4
+ at B = common global i16* null, align 8
+ at A = common global i16* null, align 8
+ at C = common global i16* null, align 8
+
+define void @f() {
+entry:
+ %a = load i16** @A, align 8
+ %b = load i16** @B, align 8
+ %c = load i16** @C, align 8
+ br label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %storemerge3 = phi i64 [ 0, %entry ], [ %add, %for.body ]
+
+ %arrayidxA = getelementptr inbounds i16* %a, i64 %storemerge3
+ %loadA = load i16* %arrayidxA, align 2
+
+ %arrayidxB = getelementptr inbounds i16* %b, i64 %storemerge3
+ %loadB = load i16* %arrayidxB, align 2
+
+ %arrayidxC = getelementptr inbounds i16* %c, i64 %storemerge3
+ %loadC = load i16* %arrayidxC, align 2
+
+ %mul = mul i16 %loadB, %loadA
+ %mul1 = mul i16 %mul, %loadC
+
+ %add = add nuw nsw i64 %storemerge3, 1
+ %arrayidxA_plus_2 = getelementptr inbounds i16* %a, i64 %add
+ store i16 %mul1, i16* %arrayidxA_plus_2, align 2
+
+ %exitcond = icmp eq i64 %add, 20
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body
+ ret void
+}
More information about the llvm-commits
mailing list