LLVM使用库函数进行优化

8

从以下代码开始

void lib_memset( unsigned char *dest, unsigned char c, unsigned int n)
{
    while(n--)
    {
        *dest=c;
        dest++;
    }
}

使用LLVM作为交叉编译器

clang -Wall -m32 -emit-llvm -fno-builtin --target=arm-none-eabi  -c lib_memset.c -o lib_memset.bc
opt -std-compile-opts -strip-debug -march=arm -mcpu=mpcore -mtriple=arm-none-eabi lib_memset.bc -o lib_memset.opt.bc
llc -march=arm -mcpu=mpcore -disable-simplify-libcalls  lib_memset.opt.bc -o lib_memset.opt.s
llc -march=arm -mcpu=mpcore -disable-simplify-libcalls  lib_memset.bc -o lib_memset.s

当使用优化器时,它会检测并用真正的memset替换它。

lib_memset:
    push    {r11, lr}
    mov r3, r1
    mov r11, sp
    cmp r2, #0
    beq .LBB0_2
    mov r1, r2
    mov r2, r3
    bl  __aeabi_memset
.LBB0_2:                                @ %while.end
    pop {r11, pc}

但是它没有实现它。
我不想让它使用库调用,而是希望它针对我给定的目标编译我提供的代码。我以为-disable-simplify-libcalls可以做到这一点,但事实并非如此。
我曾经认为我已经解决了这个问题,但现在找不到如何解决它了。我需要优化器,我不想出现实现库和需要库之间的循环依赖问题等。可以使用汇编来避免编译器的干扰,但其实并不应该这样做。

-ffreestanding是什么意思?同样的问题? - artless noise
1
糟糕!在优化步骤中需要使用-disable-simplify-libcalls选项,而不是仅在llc步骤中使用...这样就解决了。 - old_timer
2个回答

12
clang -Wall -m32 -emit-llvm -fno-builtin --target=arm-none-eabi -ffreestanding -c lib_memset.c -o lib_memset.bc
opt -std-compile-opts -strip-debug -march=arm -mcpu=mpcore -mtriple=arm-none-eabi -disable-simplify-libcalls  lib_memset.bc -o lib_memset.opt.bc
llc -march=arm -mcpu=mpcore -disable-simplify-libcalls -mtriple=arm-none-eabi  lib_memset.opt.bc -o lib_memset.opt.s
llc -march=arm -mcpu=mpcore -disable-simplify-libcalls -mtriple=arm-none-eabi  lib_memset.bc -o lib_memset.s

由于添加 -ffreestanding 时出现了无用的噪音,我决定重新阅读llc和opt的所有--help选项,并发现-disable-simplify-libcalls是opt和llc的一个选项,将其添加到opt中可以解决问题。

lib_memset:
    cmp r2, #0
    bxeq    lr
.LBB0_1:
    strb    r1, [r0], #1
    subs    r2, r2, #1
    bne .LBB0_1
    bx  lr

我不喜欢回答自己的问题,可以坐在这里一会儿,以便下次也许能找到答案,或者如果SO神们决定留下来那也没关系...


3
回答自己的问题并没有问题。在你能够接受它之前需要等待两天,这样其他人也有机会回复。你应该将它保留在这里,以防将来有人遇到相同的问题。 - Lundin

1

我遇到了同样的问题,如果还有人需要帮助,这是我解决它的方法 - 我修改了llvm源代码中的LoopIdiomRecognize.cpp文件:

有一段代码检查函数名是否为memset或memcpy,如果是则取消优化,所以我将其改为:

StringRef Name = L->getHeader()->getParent()->getName();
  if (Name == "memset" || Name == "memcpy")

StringRef Name = L->getHeader()->getParent()->getName();
  if (Name.endswith("memset") || Name == "memcpy")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接