How to get better results from LLVM's MemoryDependenceAnalysis pass? - llvm

I am trying to use the results of LLVMs built-in MemoryDependenceAnalysis (MDA) in a custom LLVM pass that I'm working on. Given some instruction which reads from memory (a load, for example), i'd like MDA to tell me all of the previous instructions which may have Defined or Clobbered it. If my understanding of the MDA documentation serves me correctly, MDA should be able to give me this info. However, I'm having a hard time getting the precision that I need out of it. Here's the relevant snippet of a simple test program i have been toying around with:
%1 = alloca i32, align 4
%result = alloca i32, align 4
%x = alloca i32, align 4
%xp = alloca i32*, align 8
store i32 0, i32* %1
store i32 5, i32* %result, align 4, !dbg !14
store i32 7, i32* %x, align 4, !dbg !16
store i32* %x, i32** %xp, align 8, !dbg !19
%2 = load i32* %x, align 4, !dbg !20
%3 = icmp eq i32 %2, 4, !dbg !20
br i1 %3, label %4, label %7, !dbg !22, !dataware.bbuid !23
; <label>:4 ; preds = %0
%5 = load i32** %xp, align 8, !dbg !24
%6 = load i32* %5, align 4, !dbg !26
store i32 %6, i32* %result, align 4, !dbg !27
br label %8, !dbg !28, !dataware.bbuid !29
; <label>:7 ; preds = %0
store i32 42, i32* %result, align 4, !dbg !30
br label %8, !dataware.bbuid !32
The command im using to run the analysis:
opt-3.6 -enable-tbaa -tbaa -basicaa -libcall-aa -scev-aa -globalsmodref-aa -domtree -memdep -print-memdeps -gvn -analyze test.bc
For some instructions, I am getting results as expected. For example, It tells me that %5 = load i32** %xp is dependent on store i32* %x, i32** %xp. However, it doesn't determine that %6 = load i32* %5 is dependent on store i32 7, i32* %x. Here's a snippet of the output:
Def in block %0 from: store i32* %x, i32** %xp, align 8, !dbg !19
%5 = load i32** %xp, align 8, !dbg !24
Unknown in block %4
%6 = load i32* %5, align 4, !dbg !26
The latter case (which it apparently doesn't know how to reason about) seems like it should be easy enough to detect, even with sub-optimal alias analysis. How do I go about investigating why the results of MDA are sub-optimal? And do you have suggestions for getting more precise results? Are there some additional analysis passes I can add to cause MDA to work better? Im using opt 3.6.0 - maybe MDA has been improved since this release?
Thanks.

I got the same results as you obtained. You might use a simpler pointer analysis result to infer that %5 and %x mayalias which in turn infer that the store to %x is potentially loaded from %5.
opt -basicaa -aa-eval -print-all-alias-modref-info test.bc -disable-output
MayAlias: i32* %5, i32* %x

Related

Selection DAG from LLVM IR?

I have fetched LLVM-IR via
clang -S -emit-llvm demo.c
where demo.c is as follows
int demo(int a, int b){
int c = a+b;
return c;
}
The IR looks like
define dso_local i32 #demo(i32 %0, i32 %1) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
%5 = alloca i32, align 4
store i32 %0, i32* %3, align 4
store i32 %1, i32* %4, align 4
%6 = load i32, i32* %3, align 4
%7 = load i32, i32* %4, align 4
%8 = add nsw i32 %6, %7
store i32 %8, i32* %5, align 4
%9 = load i32, i32* %5, align 4
ret i32 %9
}
from here I need only extract target independent selection DAG information so that I can use DAG information to my own pipeline. So is there any way to get information till selection DAG, or should I need to write my own selection DAG, if it is yes , what are those exact ways to encounter? any suggestion will be helpful to me.
I have built via
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake --build .
the after compiling using clang I execute the file demo.ll via
llc -fast-isel=false -view-dag-combine1-dags foo.ll
and
llc -debug foo.ll
but both the command giving same error

Why is LLVM AliasAnalysis unable to precisely decide alias relationships between pointers that are dereferenced twice?

I'm very confused by the LLVM AliasAnalysis implementation.
Say I have this program:
int* key = malloc(4);
*key = 10;
*key = 11;
It gets transformed to IR code like this:
%3 = call noalias i8* #malloc(i64 4) #2
%4 = bitcast i8* %3 to i32*
store i32* %4, i32** %2, align 8
%5 = load i32*, i32** %2, align 8
store i32 10, i32* %5, align 4
%6 = load i32*, i32** %2, align 8
store i32 11, i32* %6, align 4
Than I ask LLVM to print out the alias relationship between %5 and %6, by using the function static_cast<uint16_t>(AA_->getModRefInfo(FirstStore, MemoryLocation(SecondStorePointer))). It then shows that they may alias (as ModRefInfo::Mod) with each other. Why is LLVM unable to detect that they must alias each other? Is there any way I can fix it?

Is there any way to avoid deletion of duplicate load instruction when compiled using LLVM

I am working on creating LLVM front-end module pass. So, Basically I need to duplicate all load instructions and store in a different register. At -O0 for clang, opt and llc tool, this duplicated load instruction is removed. I looked at the final assembly using objdump, I could see that duplicate load instruction was removed. I want a solution that somehow does not delete duplicate load instruction.
Actual C program is,
int main(){
int* p = (int *)(0x600000);//Some address
int x=0x01, y=0x01;
int z;
z=x+y;
*p=z;
}
The corresponding IR is,
define i32 #main() #0 {
entry:
%p = alloca i32*, align 8
%x = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i32, align 4
store i32* inttoptr (i64 6291456 to i32*), i32** %p, align 8
store i32 1, i32* %x, align 4
store i32 1, i32* %y, align 4
%0 = load i32, i32* %x, align 4
%1 = load i32, i32* %y, align 4
%add = add nsw i32 %0, %1
store i32 %add, i32* %z, align 4
%2 = load i32, i32* %z, align 4
%3 = load i32*, i32** %p, align 8
store i32 %2, i32* %3, align 4
ret i32 0
}
But when my pass is enabled, this IR will change and I duplicate only load instructions with load address being same memory even for duplicated load.
The changed IR would be,
define i32 #main() #0 {
entry:
%p = alloca i32*, align 8
%x = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i32, align 4
store i32* inttoptr (i64 6291456 to i32*), i32** %p, align 8
store i32 1, i32* %x, align 4
store i32 1, i32* %y, align 4
%0 = load i32, i32* %x, align 4
%1 = load i32, i32* %y, align 4
%2 = load i32, i32* %x, align 4 //Added
%3 = load i32, i32* %y, align 4 //Added
%add = add nsw i32 %0, %1
store i32 %add, i32* %z, align 4
%4 = load i32, i32* %z, align 4
%5 = load i32*, i32** %p, align 8
%6 = load i32, i32* %z, align 4 //Added
%7 = load i32*, i32** %p, align 8 //Added
store i32 %4, i32* %5, align 4
ret i32 0
}
I am able to see the changed IR at IR level but not at the final assembly level after llc. I think llc is removing all duplicated loads. How do I stop llc from removing?
Note: I tried making all variables volatile. For this it works, I am able to see duplicated loads after llc. But, this is not a proper solution. I cannot make all thousand variables volatile :(.

LLVM: Instruction does not dominate all uses - No control flow

I implemented a function pass which iterates over basic block instructions and tracks all instructions that have a type of IntegerTy.
Here is the snippet of the pass that does it:
if (!I->isTerminator()){
Type::TypeID datatype = I->getType()->getTypeID();
if (datatype == llvm::Type::IntegerTyID) {
IRBuilder<> IRB(I);
Value* v_value = IRB.CreateZExt(I, IRB.getInt64Ty());
Value *args[] = {v_value};
IRB.CreateCall(NNT_log_int, args);
}
}
However the IRB.CreateZExt(I, IRB.getInt64Ty()); command seems to create a Instruction does not dominate all uses! problem.
I understand the nature of the issue (here and here there are similar problems).
My point of confusion that I apply this pass to a toy program with no if statements or any other control flow statements, yet I still encounter this problem.
The error message:
Instruction does not dominate all uses!
%2 = load i32, i32* %y, align 4
%1 = zext i32 %2 to i64
Instruction does not dominate all uses!
%4 = load i32, i32* %y, align 4
%3 = zext i32 %4 to i64
Note the fact that the inserted zext instructions name a constant with a counter number less than the previous instruction - I think this is the problem but I have no idea why my pass does this!!!
Here is the IR of my toy program before the application of the pass:
; Function Attrs: noinline nounwind optnone uwtable
define i32 #_Z3fooi(i32 %x) #4 {
entry:
%x.addr = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
store i32 0, i32* %y, align 4
%0 = load i32, i32* %x.addr, align 4
%add = add nsw i32 %0, 3
store i32 %add, i32* %y, align 4
%1 = load i32, i32* %y, align 4
store i32 %1, i32* %x.addr, align 4
%2 = load i32, i32* %y, align 4
ret i32 %2
}
; Function Attrs: noinline nounwind optnone uwtable
define i32 #_Z3bari(i32 %panos) #4 {
entry:
%panos.addr = alloca i32, align 4
%y = alloca i32, align 4
store i32 %panos, i32* %panos.addr, align 4
%0 = load i32, i32* %panos.addr, align 4
%add = add nsw i32 %0, 2
store i32 %add, i32* %y, align 4
%1 = load i32, i32* %y, align 4
ret i32 %1
}
Also, note that that the problematic instructions are before a terminator - Again I think that this is related.
Any ideas will be highly appreciated !
Your zext instruction uses I, but you're inserting it before I. When you create the IRBuilder, you should pass in the instruction after I as the insert point. For example like this:
IRBuilder<> IRB(I->getNextNode());

About Variables Used Within BasicBlock

I want to ask a question about LLVM IR language. For a basicblock, variables used are always loaded prior to usage, and stored after usage. Two example basic blocks are as follows:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i8**, align 8
%i = alloca i32, align 4
%fact = alloca i32, align 4
%n = alloca i32, align 4
store i32 0, i32* %1
store i32 %argc, i32* %2, align 4
store i8** %argv, i8*** %3, align 8
%4 = load i8*** %3, align 8
%5 = getelementptr inbounds i8** %4, i64 1
%6 = load i8** %5, align 8
%7 = call i32 (i8*, ...)* bitcast (i32 (...)* #atoi to i32 (i8*, ...)*)(i8* %6)
store i32 %7, i32* %n, align 4
store i32 1, i32* %fact, align 4
store i32 1, i32* %i, align 4
br label %8
%9 = load i32* %i, align 4
%10 = load i32* %n, align 4
%11 = icmp sle i32 %9, %10
br i1 %11, label %12, label %19
For control flow, define first basic block as A, second basic block as B, control flow is from A to B.
I wonder, for the usage of %7, program store %7 to %n pointer in A, and load %n pointer to %10 to get access to it, which are like:
store i32 %7, i32* %n, align 4
%10 = load i32* %n, align 4
%11 = icmp sle i32 %9, %10
I wonder if I could just DROP store and load instructions, and directly use value %7, which is as follows:
%11 = icmp sle i32 %9, %7
Is this OK? Could anyone talk about the reason behind it?
My description may be obscure. I could explain it more clear if you have questions on it.
Thanks
It is possible to refer to virtual registers from other basic blocks.
Since you provided an incomplete example, I can just speculate if %7 can be directly used in the comparison:
If you optimize the code with LLVM's opt tool, the register will probably not be stored and reloaded and the comparison will directly use %7 (or a phi function dependent on the value).
You can try the mem2reg register pass:
opt -mem2reg <your file>.ll -o <target file>.ll