DependenceAnalysisWrapperPass is confused with Simple Flow Dependence

Hi,

I’m trying to do dependency analysis using LLVM DependenceAnalysisWrapperPass (Clang/LLVM6.0.0).
But, I’m confused by the results.

For example, I tried this simple C program (simple.c).

int main(int argc, char** argv)
{
volatile int x = 1, y = 2;
y = x;
return 0;
}

If I output the IR, I get this.

define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 !dbg !7 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
call void @llvm.dbg.value(metadata i32 %0, metadata !15, metadata !DIExpression()), !dbg !20
call void @llvm.dbg.value(metadata i8** %1, metadata !16, metadata !DIExpression()), !dbg !21
%5 = bitcast i32* %3 to i8*, !dbg !22
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %5), !dbg !22
call void @llvm.dbg.value(metadata i32 1, metadata !17, metadata !DIExpression()), !dbg !23
store volatile i32 1, i32* %3, align 4, !dbg !23
%6 = bitcast i32* %4 to i8*, !dbg !22
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %6), !dbg !22
call void @llvm.dbg.value(metadata i32 2, metadata !19, metadata !DIExpression()), !dbg !24
store volatile i32 2, i32* %4, align 4, !dbg !24
%7 = load volatile i32, i32* %3, align 4, !dbg !25
call void @llvm.dbg.value(metadata i32 %7, metadata !17, metadata !DIExpression()), !dbg !23
call void @llvm.dbg.value(metadata i32 %7, metadata !19, metadata !DIExpression()), !dbg !24
store volatile i32 %7, i32* %4, align 4, !dbg !26
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %6), !dbg !27
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %5), !dbg !27
ret i32 0, !dbg !28
}

Since there is obvious flow dependence in y = x, that is, READ(%7 = load volatile i32, i32* %3, align 4, !dbg !25) and WRITE(store volatile i32 %7, i32* %4, align 4, !dbg !26),
I expect that the LLVM DependenceAnalysisWrapperPass can easily detect this flow dependence.

So I wrote simple dependence analysis pass (libmyirpass.so) to confirm it.

bool runOnFunction(Function &F)
{
DependenceInfo *depinfo;
depinfo = &getAnalysis<DependenceAnalysisWrapperPass>().getDI();
for (inst_iterator Iit = inst_begin(F), Iit_end = inst_end(F); Iit != Iit_end; Iit++) {
   Instruction &Dst = *Iit;
   for (inst_iterator Jit = inst_begin(F), Jit_end = inst_end(F); Jit != Jit_end; Jit++) {
     unique_ptr<Dependence> infoPtr;
     Instruction &Src = *Jit;
     Dependence *dep;
     infoPtr = depinfo->depends(&Src, &Dst, false); /* depends(&Src, &Dest, true); */
     dep = infoPtr.get();
     if (dep != NULL) {
       if (dep->isConfused()) errs() << "[C] ";
       dep->getDst()->print(errs(), false);
       errs() << " ---> ";
       dep->getSrc()->print(errs(), false);
       errs() << "\n";
     }
   }
}
return false;
}

However, DependenceAnalysisWrapperPass is confused with this simple flow dependence, i.e., dep->isConfused() returns true,
so it outputs this message if I compile simple.c with libmyirpass.so by clang-6.0.0.

$ clang++ -g -O0 -std=c++11 -Xclang -load -Xclang ./libmyirpass.so simple.c
...
[C] store volatile i32 %7, i32* %4, align 4, !dbg !26 ---> %7 = load volatile i32, i32* %3, align 4, !dbg !25

I see the same issue with use of both "PassManagerBuilder::EP_EarlyAsPossible" and "PassManagerBuilder::EP_OptimizerLast".

I’m wondering why DependenceAnalysisWrapperPass is confused with this simple flow dependence.
If I’m misunderstanding about this dependence analysis, please correct me.

Thanks,
Kento

Hi,

You can dump the debug trace by adding -debug option or -debug-only=“da” to opt
Normally Pass authors would print details in debug trace.

Or, you can just trace it with gdb, it works well for me all the time.

Bests,
Bekket