LLVM使用自己的RTTI系统有几个原因。该系统简单而强大,并在
LLVM程序员手册的一节中进行了描述。正如另一个帖子所指出的,
编码标准提出了C++ RTTI的两个主要问题:1)空间成本和2)使用它的性能不佳。
RTTI的空间成本相当高:每个具有虚函数表(至少一个虚方法)的类都会获得RTTI信息,其中包括类的名称和其基类的信息。此信息用于实现
typeid运算符以及
dynamic_cast。由于这个成本是为每个具有虚函数表的类支付的(不,PGO和链接时优化无法帮助,因为虚函数表指向RTTI信息),因此LLVM使用-fno-rtti进行构建。根据经验,这可以节省可执行文件大小的5-10%,这非常重要。LLVM不需要等价于typeid的东西,因此保留每个类的名称(以及type_info中的其他内容)只是浪费空间。
如果你进行一些基准测试或查看简单操作生成的代码,就会很容易看出性能差。通常情况下,LLVM isa<>运算符会编译成一个加载和与常量的比较(尽管类控制着它们如何实现classof方法)。以下是一个微不足道的例子:
#include "llvm/Constants.h"
using namespace llvm;
bool isConstantInt(Value *V) { return isa<ConstantInt>(V); }
这将编译为:
$ clang t.cc -S -o - -O3 -I$HOME/llvm/include -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -mkernel -fomit-frame-pointer
...
__Z13isConstantIntPN4llvm5ValueE:
cmpb $9, 8(%rdi)
sete %al
movzbl %al, %eax
ret
如果你不会看汇编的话,这是一个加载和与常量比较的过程。相比之下,使用dynamic_cast的等效代码如下:
#include "llvm/Constants.h"
using namespace llvm;
bool isConstantInt(Value *V) { return dynamic_cast<ConstantInt*>(V) != 0; }
编译结果为:
clang t.cc -S -o - -O3 -I$HOME/llvm/include -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -mkernel -fomit-frame-pointer
...
__Z13isConstantIntPN4llvm5ValueE:
pushq %rax
xorb %al, %al
testq %rdi, %rdi
je LBB0_2
xorl %esi, %esi
movq $-1, %rcx
xorl %edx, %edx
callq ___dynamic_cast
testq %rax, %rax
setne %al
LBB0_2:
movzbl %al, %eax
popq %rdx
ret
这是更多的代码,但致命的是对__dynamic_cast的调用,它必须在RTTI数据结构中搜索并进行一次非常通用的动态计算遍历。 这比加载和比较慢几个数量级。
好吧,好吧,它速度慢,为什么要介绍? 这很重要,因为LLVM进行了大量类型检查。 许多优化器部分都是基于在代码中匹配特定结构并对其执行替换的模式匹配构建的。 例如,以下是用于匹配简单模式的代码(它已经知道Op0 / Op1是整数减法操作的左右手):
// (X*2) - X -> X
if (match(Op0, m_Mul(m_Specific(Op1), m_ConstantInt<2>())))
return Op1;
匹配运算符和m_*是模板元编程,其归结为一系列isa/dyn_cast调用,每个调用都需要进行类型检查。使用dynamic_cast进行这种细粒度的模式匹配将会非常缓慢。
最后,还有另一个点,那就是表现力。LLVM使用的不同的'rtti'运算符用于表示不同的内容:类型检查、dynamic_cast、强制(断言)转换、空处理等。C++的dynamic_cast没有(本地)提供任何这些功能。
最终,有两种看待这种情况的方式。消极的一面是,对于许多人想要的内容(完全反射),C++ RTTI定义过于狭窄,并且对于像LLVM这样简单的事情来说太慢了。积极的一面是,C++语言足够强大,我们可以将这样的抽象定义为库代码,并选择不使用语言特性。我最喜欢C++的一件事情就是它的库代码可以如此强大而优雅。RTTI甚至不在我最不喜欢的C++功能之列 :)!
-Chris
clang
而不是gcc
,考虑到它被别名为 clang 后端... https://dev59.com/wWIk5IYBdhLWcg3wJ7P4 - Cade Brown