问题
I'm asking a question similar to this post about an LLVM alias analysis that seems to give incorrect results. Since it contains considerable re-writing, I have decided to post it as a separate question. I'm running this very simple code:
char *foo()
{
int i;
int size;
char *s=malloc(5);
char *p=malloc(8);
while ((i < size) && (s < p))
{
i--;
}
return NULL;
}
Every time my code runs into an icmp
instruction, I ask whether
its operands can be aliases of one another. For the first comparison
it trivially answers no, but for the second comparison between
%tmp2
and %tmp3
it answers yes.
Here is the resulting LLVM bitcode:
; Function Attrs: nounwind uwtable
define internal i8* @foo() #0 {
entry:
%i = alloca i32, align 4
%s = alloca i8*, align 8
%p = alloca i8*, align 8
%size = alloca i32, align 4
%call = call noalias i8* @malloc(i64 8) #3
store i8* %call, i8** %s, align 8
%call1 = call noalias i8* @malloc(i64 13) #3
store i8* %call1, i8** %p, align 8
br label %while.cond
while.cond: ; preds = %while.body, %entry
%tmp = load i32, i32* %i, align 4
%tmp1 = load i32, i32* %size, align 4
%cmp = icmp sgt i32 %tmp, %tmp1
br i1 %cmp, label %land.rhs, label %while.end
land.rhs: ; preds = %while.cond
%tmp2 = load i8*, i8** %p, align 8
%tmp3 = load i8*, i8** %s, align 8
%cmp2 = icmp ult i8* %tmp2, %tmp3
br i1 %cmp2, label %while.body, label %while.end
while.body: ; preds = %land.rhs
%tmp5 = load i32, i32* %i, align 4
%dec = add nsw i32 %tmp5, -1
store i32 %dec, i32* %i, align 4
br label %while.cond
while.end: ; preds = %while.cond, %land.rhs
ret i8* null
}
When I looked at the specifications
of the pass -basicaa
in the LLVM documentation, it explicitly says that (emphasis mine):
Distinct globals, stack allocations, and heap allocations can never alias.
But this is the case here, with two different heap allocations. What's going on?
EDIT:
Here is the output of print-alias-sets
opt -basicaa -aa-eval -globals-aa -scev-aa -loop-simplify -instnamer -print-alias-sets -indvars -simplifycfg -view-cfg -o ./examples/input.ready.bc ./examples/input.bc
Alias Set Tracker: 4 alias sets for 4 pointer values.
AliasSet[0x563ec3312a90, 1] must alias, Mod Pointers: (i32* %argc.addr, 4)
AliasSet[0x563ec3312b30, 1] must alias, Mod Pointers: (i8*** %argv.addr, 8)
AliasSet[0x563ec3312bd0, 1] must alias, Mod/Ref Pointers: (i32* %i, 4)
AliasSet[0x563ec3312c70, 2] may alias, Mod/Ref Pointers: (i8* %arrayidx, 1)
3 Unknown instructions: i8* %call, i32 %call1, i8* %call2
Alias Set Tracker: 3 alias sets for 3 pointer values.
AliasSet[0x563ec3312a90, 1] must alias, Mod/Ref Pointers: (i8** %lp.addr, 8)
AliasSet[0x563ec3312b80, 1] must alias, Mod Pointers: (i32* %size.addr, 4)
AliasSet[0x563ec3312ae0, 1] must alias, Mod/Ref Pointers: (i32* %i, 4)
Alias Set Tracker: 5 alias sets for 4 pointer values.
AliasSet[0x563ec3312b80, 1] may alias, Mod/Ref
2 Unknown instructions: i8* %call, i8* %call1
AliasSet[0x563ec3312bd0, 1] must alias, Mod/Ref Pointers: (i8** %s, 8)
AliasSet[0x563ec33129f0, 1] must alias, Mod/Ref Pointers: (i8** %p, 8)
AliasSet[0x563ec33229c0, 1] must alias, Mod/Ref Pointers: (i32* %i, 4)
AliasSet[0x563ec3322a60, 1] must alias, Ref Pointers: (i32* %size, 4)
===== Alias Analysis Evaluator Report =====
94 Total Alias Queries Performed
73 no alias responses (77.6%)
18 may alias responses (19.1%)
2 partial alias responses (2.1%)
1 must alias responses (1.0%)
Alias Analysis Evaluator Pointer Alias Summary: 77%/19%/2%/1%
54 Total ModRef Queries Performed
17 no mod/ref responses (31.4%)
0 mod responses (0.0%)
3 ref responses (5.5%)
34 mod & ref responses (62.9%)
Alias Analysis Evaluator Mod/Ref Summary: 31%/0%/5%/62%
ANOTHER EDIT:
Here's how I check for aliasing from within the (Loop) pass:
virtual bool runOnLoop(Loop *loop, LPPassManager &LPM)
{
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
for (auto it = loop->block_begin(); it != loop->block_end(); it++)
{
for (auto inst = (*it)->begin(); inst != (*it)->end(); inst++)
{
Instruction *i = (Instruction *) inst;
if (strncmp(i->getOpcodeName(),"icmp",4) == 0)
{
CmpInst *ci = (CmpInst *) i;
if (AA->isNoAlias(
ci->getOperand(0),
ci->getOperand(1)))
{
errs() << ci->getOperand(0)->getName().str();
errs() << " and ";
errs() << ci->getOperand(1)->getName().str();
errs() << " are NOT aliases\n";
}
else
{
errs() << ci->getOperand(0)->getName().str();
errs() << " and ";
errs() << ci->getOperand(1)->getName().str();
errs() << " are aliases of one another\n";
}
}
}
}
回答1:
The different heap allocations are correctly regarded as separate (i.e. non-aliasing) and you can check that by adding this instruction at the end of the entry basic block:
%cmp3 = icmp ult i8* %call, %call1
For the alias analysis to properly "kick in", you need to run it over optimized code.
In this case also adding -mem2reg
should do it.
Moreover, make sure that the function you're analyzing is not marked with the optnone
attribute (disassemble and check in the readable IR code), which will disable optimizations for it.
来源:https://stackoverflow.com/questions/51400856/incorrect-llvm-alias-analysis