LLVM 循环不变代码运动 (-licm) 通过

LLVM Loop Invariant Code Motion (-licm) pass

我有一些简单的 C 循环代码,我想简化 尽可能。这是原始的 C 文件:

#include <stdio.h>

char *foo(char *s)
{
    while (*s == 'a' || *s == 'b')
    {
        s++;
    }
    return s;
}

int main(int argc, char **argv)
{
    char *s1 = argv[1];
    char *s2 = foo(s1);
    return 0;
}

我试过使用 opt-licm 标志,应该是:

remove as much code from the body of a loop as possible. It does this by either hoisting code into the preheader block

但是当我查看循环体时,我发现第 21 行和第 22 行确实冗余,因为 %s.addr 不是 更改,因此可以安全删除第 21 和 22 行,而不是 %tmp3 我们可以使用第 23 行的 %tmp1 继续。

 13 while.cond:                                       ; preds = %while.body, %entry
 14   %tmp = load i8*, i8** %s.addr, align 8
 15   %tmp1 = load i8, i8* %tmp, align 1
 16   %conv = sext i8 %tmp1 to i32
 17   %cmp = icmp eq i32 %conv, 97
 18   br i1 %cmp, label %lor.end, label %lor.rhs
 19 
 20 lor.rhs:                                          ; preds = %while.cond
 21   %tmp2 = load i8*, i8** %s.addr, align 8
 22   %tmp3 = load i8, i8* %tmp2, align 1
 23   %conv2 = sext i8 %tmp3 to i32
 24   %cmp3 = icmp eq i32 %conv2, 98
 25   br label %lor.end

我错过了什么?有没有其他通行证可以实现这个目标?

您没有注意到 %s.addr 在 while 循环中不是不变的。循环不变代码运动优化识别在迭代之间不改变的表达式,并尝试将它们从循环中移除。您正在寻找的是常见的子表达式消除之类的东西。此优化识别同一子表达式的重复计算,并尝试删除除一个以外的所有子表达式。 在我的 opt 版本中,此优化由 -early-cse 开关启用。