我要问一个类似于this post的问题,关于LLVM别名分析似乎给出了不正确的结果。 由于包含大量重写, 我决定将其发布为单独的问题。 我正在运行以下非常简单的代码:
char *foo()
{
int i;
int size;
char *s=malloc(5);
char *p=malloc(8);
while ((i < size) && (s < p))
{
i--;
}
return NULL;
}
每次我的代码遇到一条icmp
指令时,我都会问
其操作数可以是彼此的别名。第一次比较
它简单地回答“否”,但第二个比较
%tmp2
和%tmp3
会回答是。
这是生成的LLVM位代码:
; 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
}
当我看规格时
the LLVM documentation中-basicaa
的密码,它明确表示(强调我):
不同的全局变量,堆栈分配和堆分配绝对不能混叠。
但是在这种情况下,有两个不同的堆分配。 发生了什么事?
编辑:
这是打印别名集的输出
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%
另一项编辑:
这是我从(循环)传递中检查别名的方法:
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";
}
}
}
}
答案 0 :(得分:1)
不同的堆分配被正确地认为是独立的(即非混叠),您可以通过在基本条目的末尾添加此指令来进行检查:
%cmp3 = icmp ult i8* %call, %call1
要使别名分析正确地“插入”,您需要在优化的代码上运行它。
在这种情况下,还应添加-mem2reg
。
此外,请确保您要分析的功能未标记有optnone
属性(反汇编并检入可读的IR代码),这将禁用该功能的优化。