Skip to content

Commit

Permalink
[DA] Improve dump to show source and sink of the dependence
Browse files Browse the repository at this point in the history
Summary:
The current da printer shows the dependence without indicating
which instructions are being considered as the src vs dst. It
also silently ignores call instructions, despite the fact that
they create confused dependence edges to other memory
instructions. This patch addresses these two issues plus a
couple of minor non-functional improvements.

Authored By: bmahjour

Reviewer: dmgreen, fhahn, philip.pfaffe, chandlerc

Reviewed By: dmgreen, fhahn

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D71088
  • Loading branch information
bmahjour committed Dec 11, 2019
1 parent 24a4d27 commit 916d37a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
17 changes: 7 additions & 10 deletions llvm/lib/Analysis/DependenceAnalysis.cpp
Expand Up @@ -170,25 +170,25 @@ void DependenceAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredTransitive<LoopInfoWrapperPass>();
}


// Used to test the dependence analyzer.
// Looks through the function, noting loads and stores.
// Looks through the function, noting instructions that may access memory.
// Calls depends() on every possible pair and prints out the result.
// Ignores all other instructions.
static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA) {
auto *F = DA->getFunction();
for (inst_iterator SrcI = inst_begin(F), SrcE = inst_end(F); SrcI != SrcE;
++SrcI) {
if (isa<StoreInst>(*SrcI) || isa<LoadInst>(*SrcI)) {
if (SrcI->mayReadOrWriteMemory()) {
for (inst_iterator DstI = SrcI, DstE = inst_end(F);
DstI != DstE; ++DstI) {
if (isa<StoreInst>(*DstI) || isa<LoadInst>(*DstI)) {
OS << "da analyze - ";
if (DstI->mayReadOrWriteMemory()) {
OS << "Src:" << *SrcI << " --> Dst:" << *DstI << "\n";
OS << " da analyze - ";
if (auto D = DA->depends(&*SrcI, &*DstI, true)) {
D->dump(OS);
for (unsigned Level = 1; Level <= D->getLevels(); Level++) {
if (D->isSplitable(Level)) {
OS << "da analyze - split level = " << Level;
OS << " da analyze - split level = " << Level;
OS << ", iteration = " << *DA->getSplitIteration(*D, Level);
OS << "!\n";
}
Expand Down Expand Up @@ -3413,8 +3413,7 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
if (Src == Dst)
PossiblyLoopIndependent = false;

if ((!Src->mayReadFromMemory() && !Src->mayWriteToMemory()) ||
(!Dst->mayReadFromMemory() && !Dst->mayWriteToMemory()))
if (!(Src->mayReadOrWriteMemory() && Dst->mayReadOrWriteMemory()))
// if both instructions don't reference memory, there's no dependence
return nullptr;

Expand Down Expand Up @@ -3786,8 +3785,6 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
return std::make_unique<FullDependence>(std::move(Result));
}



//===----------------------------------------------------------------------===//
// getSplitIteration -
// Rather than spend rarely-used space recording the splitting iteration
Expand Down
50 changes: 50 additions & 0 deletions llvm/test/Analysis/DependenceAnalysis/Dump.ll
@@ -0,0 +1,50 @@
; RUN: opt < %s -disable-output "-passes=print<da>" -aa-pipeline=basic-aa 2>&1 \
; RUN: | FileCheck %s

;; Test to make sure the dump shows the src and dst
;; instructions (including call instructions).
;;
;; void bar(float * restrict A);
;; void foo(float * restrict A, int n) {
;; for (int i = 0; i < n; i++) {
;; A[i] = i;
;; bar(A);
;; }
;; }

; CHECK-LABEL: foo

; CHECK: Src: store float %conv, float* %arrayidx, align 4 --> Dst: store float %conv, float* %arrayidx, align 4
; CHECK-NEXT: da analyze - none!
; CHECK-NEXT: Src: store float %conv, float* %arrayidx, align 4 --> Dst: call void @bar(float* %A)
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: call void @bar(float* %A) --> Dst: call void @bar(float* %A)
; CHECK-NEXT: da analyze - confused!

define void @foo(float* noalias %A, i32 signext %n) {
entry:
%cmp1 = icmp slt i32 0, %n
br i1 %cmp1, label %for.body.lr.ph, label %for.end

for.body.lr.ph: ; preds = %entry
br label %for.body

for.body: ; preds = %for.body.lr.ph, %for.body
%i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
%conv = sitofp i32 %i.02 to float
%idxprom = zext i32 %i.02 to i64
%arrayidx = getelementptr inbounds float, float* %A, i64 %idxprom
store float %conv, float* %arrayidx, align 4
call void @bar(float* %A) #3
%inc = add nuw nsw i32 %i.02, 1
%cmp = icmp slt i32 %inc, %n
br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge

for.cond.for.end_crit_edge: ; preds = %for.body
br label %for.end

for.end: ; preds = %for.cond.for.end_crit_edge, %entry
ret void
}

declare void @bar(float*)

0 comments on commit 916d37a

Please sign in to comment.