我希望使用LLVM 3.1将使用指针算术的循环转换为使用数组索引。例如(为了清晰起见,以C而不是位码显示):
void f() {
int buf[10];
int i;
int *p = buf;
for (i = 0; i < 10; i++)
*p++ = 0;
}
应该转换成
void f() {
int buf[10];
int i;
int *p = buf;
for (i = 0; i < 10; i++)
p[i] = 0;
}
并且
void g(int *p, int n) {
int *end = p + n;
for (; p < end, p++)
*p = 0;
}
应该转换为
void g(int *p, int n) {
int i;
for (i = 0; i < n, i++)
p[i] = 0;
}
我尝试使用
opt -mem2reg -indvars <bc-file> -S
但我没有看到任何变化。 我确实看到了像IndVarSimplify.cpp文件中评论中那样的示例发生了变化,仅使用整数循环变量。 但是我没有看到任何指针算术被升级为使用数组下标的示例,正如文档中所述。 我是否能够达到我想要的结果?
编辑:
下面是上面两个“f”函数的位码(经过mem2reg处理)。 主要区别在于循环内部的GEP,其中在第一种情况下指针从上一次迭代开始递增,在第二种情况下,每次使用基本指针和索引i计算指针。 这就是我想要的 - 根据归纳变量i存储地址。
第一个f的位码:
define void @f() nounwind uwtable {
entry:
%buf = alloca [10 x i32], align 16
%arraydecay = getelementptr inbounds [10 x i32]* %buf, i32 0, i32 0
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%p.0 = phi i32* [ %arraydecay, %entry ], [ %incdec.ptr, %for.inc ]
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
%cmp = icmp slt i32 %i.0, 10
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%incdec.ptr = getelementptr inbounds i32* %p.0, i32 1
store i32 0, i32* %p.0, align 4
br label %for.inc
for.inc: ; preds = %for.body
%inc = add nsw i32 %i.0, 1
br label %for.cond
for.end: ; preds = %for.cond
ret void
}
第二个f的位码:
define void @f() nounwind uwtable {
entry:
%buf = alloca [10 x i32], align 16
%arraydecay = getelementptr inbounds [10 x i32]* %buf, i32 0, i32 0
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
%cmp = icmp slt i32 %i.0, 10
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%idxprom = sext i32 %i.0 to i64
%arrayidx = getelementptr inbounds i32* %arraydecay, i64 %idxprom
store i32 0, i32* %arrayidx, align 4
br label %for.inc
for.inc: ; preds = %for.body
%inc = add nsw i32 %i.0, 1
br label %for.cond
for.end: ; preds = %for.cond
ret void
}