LLVM 用数组索引替换指针算术

标签 llvm

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

最佳答案

没有 LLVM 转换可以执行此操作。我编写了自己的 instcombine 转换来做到这一点。

关于LLVM 用数组索引替换指针算术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22706444/

相关文章:

c++ - 如何在 LLVM pass 中的模块末尾插入函数调用?

clang - 在哪里可以找到 LangOptions 方法的详尽列表

clang - 如何在基于libtooling的工具中获取编译命令

windows - Windows 上 LLVM 汇编语言中的 Hello World

c++ - 链接 clang-llvm

compiler-construction - 如何在LLVM IR中高效实现闭包?

objective-c - __block 属性声明

llvm - 性能比较 - gcc 和 llvm-gcc

x86 - 为什么 0xE1 0x4F 在 LLVM 和 NDISASM 中反汇编为不同的指令?

llvm - 带有 LLVM 段错误的 Printf float