我想使用LLVM 3.1来使用指针算法转换循环,而不是使用数组索引。例如(为了清楚起见,用C而不是bitcode显示):
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文件的注释中看到了类似示例的更改,仅使用整数循环变量。但我无法看到任何引用指针算法的例子来使用数组下标,就像在docs中订阅的那样。是否有可能实现我正在寻找的结果?
修改
下面是上面两个“f”函数的bitcode(在mem2reg之后)。关键区别在于循环内的GEP,在第一种情况下是从前一次迭代递增指针,在第二种情况下是每次使用基指针和索引i计算指针。这就是我想要的 - 根据归纳变量i来存储地址。
Bitcode for first 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
}
Bitcode for second 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
}
答案 0 :(得分:1)
没有LLVM转换可以做到这一点。我写了自己的instcombine转换来做它。