LLVM和GCC MIPS代码生成,有任何基准测试吗?

7

我想知道适用于MIPS代码的“最好”的免费/OSS编译器是GCC还是LLVM,或者有比它们更好的选择吗?

我对生成的汇编代码快速和内存限制的性能比代码大小更感兴趣。

换句话说,llvm-opt是否比gcc -O3更好地完成了这项工作?


这不是一个答案,但据我所知,LLVM在x86上的表现比GCC更好。 - Calyth
1
你为什么这么说呢?从我看到的基准测试结果来看,LLVM 2.4 与 GCC 4.2 非常接近,而且我从未见过针对 GCC 4.3 的基准测试。当 GCC 4.4 推出新的优化框架时,LLVM 2.5 会更好吗?还是基本上差不多? - Paulo Lopes
1
据我所知,关于GCC和LLVM的很好的比较通常相对较少(与他们的邮件列表上基于个别证据的笼统陈述相反)。你最好的选择是自己对与你相关的代码进行比较。 - Laurynas Biveinis
3个回答

2

1

我不了解MIPS,我尝试了ARM和LLVM代码比当前的GCC慢10-20%。所涉及的测试基于zlib。单独进行解压缩和压缩再解压缩。使用了clang和llvm-gcc。我更喜欢clang,因为-m32在64位主机上实际起作用。对于所涉及的测试,我发现不使用-O2(或-O3)可以产生最快的代码。将字节码模块链接成一个大模块,并执行一次标准优化的opt,以获得最快的代码。llc默认为-O2,这确实有助于性能。

编辑:

针对MIPS的GCC和LLVM / Clang之间的有趣测试。

void dummy ( unsigned int );
void dowait ( void )
{
    unsigned int ra;
    for(ra=0x80000;ra;ra--) dummy(ra);
}

gcc生成:

9d006034 <dowait>:
9d006034:   27bdffe8    addiu   sp,sp,-24
9d006038:   afb00010    sw  s0,16(sp)
9d00603c:   afbf0014    sw  ra,20(sp)
9d006040:   3c100008    lui s0,0x8
9d006044:   02002021    move    a0,s0
9d006048:   0f40180a    jal 9d006028 <dummy>
9d00604c:   2610ffff    addiu   s0,s0,-1
9d006050:   1600fffd    bnez    s0,9d006048 <dowait+0x14>
9d006054:   02002021    move    a0,s0
9d006058:   8fbf0014    lw  ra,20(sp)
9d00605c:   8fb00010    lw  s0,16(sp)
9d006060:   03e00008    jr  ra
9d006064:   27bd0018    addiu   sp,sp,24

在汇编后使用 LLVM

9d006034 <dowait>:
9d006034:   27bdffe8    addiu   sp,sp,-24
9d006038:   afbf0014    sw  ra,20(sp)
9d00603c:   afb00010    sw  s0,16(sp)
9d006040:   3c020008    lui v0,0x8
9d006044:   34440000    ori a0,v0,0x0
9d006048:   2490ffff    addiu   s0,a0,-1
9d00604c:   0f40180a    jal 9d006028 <dummy>
9d006050:   00000000    nop
9d006054:   00102021    addu    a0,zero,s0
9d006058:   1600fffb    bnez    s0,9d006048 <dowait+0x14>
9d00605c:   00000000    nop
9d006060:   8fb00010    lw  s0,16(sp)
9d006064:   8fbf0014    lw  ra,20(sp)
9d006068:   27bd0018    addiu   sp,sp,24
9d00606c:   03e00008    jr  ra
9d006070:   00000000    nop

我之所以说“组装”是因为我看到gnu-as做过这样的事情

.globl PUT32
PUT32:
    sw $a1,0($a0)
    jr $ra
    nop

请为我重新排列汇编代码:

9d00601c <PUT32>:
9d00601c:   03e00008    jr  ra
9d006020:   ac850000    sw  a1,0(a0)
9d006024:   00000000    nop

LLVM和GCC生成的代码之间的区别在于指令被放置在分支延迟槽中。我使用clang和llc生成汇编输出,然后使用binutils、GNU as创建二进制文件。因此,对于我的手工组装代码来说,这是一个好奇点:

ori $sp,$sp,0x2000
jal notmain
nop

它为我进行了优化:

9d006004:   0f401820    jal 9d006080 <notmain>
9d006008:   37bd2000    ori sp,sp,0x2000
9d00600c:   00000000    nop

但是llc生成的代码

addiu   $16, $4, -1
jal dummy
nop

不是

9d006048:   2490ffff    addiu   s0,a0,-1
9d00604c:   0f40180a    jal 9d006028 <dummy>
9d006050:   00000000    nop

你有进展吗?我现在正在尝试使用llvm和mips,但出现了“重定位目标截断以适应:R_MIPS_GOT16”和“重定位目标截断以适应:R_MIPS_CALL16”的问题,因此我需要让llvm不使用gp或者用ld链接它(使用llvm生成汇编代码,然后使用binutils将其转换为二进制文件)。 - old_timer
啊,已经解决了——-relocation-model=static - old_timer

-1

在x86上,LLVM通常比GCC更好,但我还没有找到关于MIPS的任何基准。因为您正在问这个问题,所以我假设您可以访问MIPS机器,那么为什么不使用GCC和LLVM编译计算机语言基准游戏C代码并查看哪个更快呢? 我猜测GCC会更快,因为MIPS后端相对较新,但代码要干净得多,我期望LLVM最终会胜出。


3
在x86平台上性能更好是一个很大的假设,参见http://leonardo-m.livejournal.com/77877.html ,这并不那么明显。关于MIPS,我只有一台旧的PS2和PSP,无法进行比较,因为GCC后端支持使用其内部VFPUs进行SIMD操作,而LLVM尚未支持它们。 - Paulo Lopes
1
以上链接比较了GCC -O3和JITed LLVM。这并不是一个公平的比较。LLVM可以进行静态编译。 - nominolo
@nominolo,你确定“jited llvm”吗?它确实将自己链接到应用程序,但不会在运行时重新构建任何部分。例如,请尝试阅读这个使用LLVM JIT的斐波那契函数代码http://www.cliff.biffle.org/software/llvm/ifibonacci.cpp - osgx
3
对于我的国际象棋引擎而言,gcc生成的代码比LLVM表现更优异。因此,你的说法并不是普遍正确的,实际上我怀疑它是否有任何严肃的证据支持。 - Gunther Piez

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