This is an archive of the discontinued LLVM Phabricator instance.

Make the MemDepPrinter to print something
Needs RevisionPublic

Authored by dmikushin on Dec 4 2013, 4:01 PM.

Details

Reviewers
None
Summary

While exploring dependency analysis capabilities, I've discovered by current design MemDepPrinter has a print() function, which is never called anywhere. Thus, opt -print-memdeps never prints anything. This trivial patch change the pass to print the dependencies right from the function pass.

Diff Detail

Event Timeline

Example:

$ cat example.c
void vector_sum(int length, float* in1, float* in2, float* out)
{
	for (int i = 0; i < length; i++)
		out[i] = in1[i] + in2[i];
}

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	if (argc != 2) return 1;

	int length = atoi(argv[1]);

	float* in1 = (float*)malloc(length * sizeof(float));
	float* in2 = (float*)malloc(length * sizeof(float));
	float* out = (float*)malloc(length * sizeof(float));
	for (int i = 0; i < length; i++)
	{
		in1[i] = drand48();
		in2[i] = drand48();
	}
	
	vector_sum(length, in1, in2, out);
	
	//printf("%f\n", out[length - 1]);
	
	return 0;
}

$ clang -emit-llvm -c -S -O1 example.c -o - | opt -memdep -print-memdeps -o /dev/null
Function vector_sum memory dependencies:

    Unknown in block %for.body
    Unknown in block %entry
  %0 = load float* %arrayidx, align 4, !tbaa !1

    Unknown in block %for.body
    Unknown in block %entry
  %1 = load float* %arrayidx2, align 4, !tbaa !1

    Def from:   %1 = load float* %arrayidx2, align 4, !tbaa !1
  store float %add, float* %arrayidx4, align 4, !tbaa !1


Function main memory dependencies:

    Unknown in block %entry
  %0 = load i8** %arrayidx, align 8, !tbaa !1

    Clobber from:   %0 = load i8** %arrayidx, align 8, !tbaa !1
  %call = tail call i32 @atoi(i8* %0) #3

    Clobber from:   %call = tail call i32 @atoi(i8* %0) #3
  %call1 = tail call noalias i8* @malloc(i64 %mul) #4

    Clobber from:   %call1 = tail call noalias i8* @malloc(i64 %mul) #4
  %call4 = tail call noalias i8* @malloc(i64 %mul) #4

    Clobber from:   %call4 = tail call noalias i8* @malloc(i64 %mul) #4
  %call7 = tail call noalias i8* @malloc(i64 %mul) #4

    Clobber in block %if.end from:   %call7 = tail call noalias i8* @malloc(i64 %mul) #4
    Clobber in block %for.body from:   store float %conv14, float* %arrayidx16, align 4, !tbaa !5
  %call10 = tail call double @drand48() #4

    Clobber from:   %call10 = tail call double @drand48() #4
  store float %conv11, float* %arrayidx12, align 4, !tbaa !5

    Clobber from:   store float %conv11, float* %arrayidx12, align 4, !tbaa !5
  %call13 = tail call double @drand48() #4

    Clobber from:   %call13 = tail call double @drand48() #4
  store float %conv14, float* %arrayidx16, align 4, !tbaa !5

    Clobber in block %if.end from:   %call7 = tail call noalias i8* @malloc(i64 %mul) #4
    Clobber in block %for.body from:   store float %conv14, float* %arrayidx16, align 4, !tbaa !5
  tail call void @vector_sum(i32 %call, float* %1, float* %2, float* %3)


Function atoi memory dependencies:

    NonFuncLocal
  %call = tail call i64 @strtol(i8* nocapture %__nptr, i8** null, i32 10) #3

The print-memdeps pass was written to be used with opt's -analyze feature. If you run opt -print-memdeps -analyze, it prints.

sunfish requested changes to this revision.Dec 5 2013, 11:57 AM

print is called from -analyze.

Hi Dan,

OK, I missed that because other -print-* passes are just printing to stderr without -analyze... So is -analyze necessary?

Also, I have a question: why for the store from 2 loads in the IR code below I get store having only single Def dependency on one of the loads, not on both of them?

Thanks,

  • D.
define void @vector_sum(i32 %length, float* nocapture readonly %in1, float* nocapture readonly %in2, float* nocapture %out) #0 {
entry:
  %cmp9 = icmp sgt i32 %length, 0
  br i1 %cmp9, label %for.body, label %for.end

for.body:                     ; preds = %entry, %for.body
  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
  %arrayidx = getelementptr inbounds float* %in1, i64 %indvars.iv
  %0 = load float* %arrayidx, align 4, !tbaa !1
  %arrayidx2 = getelementptr inbounds float* %in2, i64 %indvars.iv
  %1 = load float* %arrayidx2, align 4, !tbaa !1
  %add = fadd float %0, %1
  %arrayidx4 = getelementptr inbounds float* %out, i64 %indvars.iv
  store float %add, float* %arrayidx4, align 4, !tbaa !1
  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
  %exitcond = icmp eq i32 %lftr.wideiv, %length
  br i1 %exitcond, label %for.end, label %for.body

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

$ clang -emit-llvm example.c -O1 -S -o - | opt -memdep -print-memdeps -o /dev/null

Function vector_sum memory dependencies:

    Unknown in block %for.body
    Unknown in block %entry
  %0 = load float* %arrayidx, align 4, !tbaa !1

    Unknown in block %for.body
    Unknown in block %entry
  %1 = load float* %arrayidx2, align 4, !tbaa !1

    Def from:   %1 = load float* %arrayidx2, align 4, !tbaa !1
  store float %add, float* %arrayidx4, align 4, !tbaa !1
sunfish resigned from this revision.Sep 15 2015, 10:17 AM
sunfish removed a reviewer: sunfish.

I am not presently using the memdep printer pass, so if it's not working properly, it's fine with me to remove it from the tree.