LLVM使用数组索引替换指针算法

时间:2014-03-28 07:13:43

标签: llvm

我想使用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
}

1 个答案:

答案 0 :(得分:1)

没有LLVM转换可以做到这一点。我写了自己的instcombine转换来做它。