死虚函数消除

时间:2015-04-09 20:00:20

标签: c++ clang llvm virtual-functions dead-code

问题

(我可以使用LLVM附带的clang或者其他一些优化工具来识别C ++程序中未使用的虚函数,标记它们是否可以消除死代码?我猜不是。)

如果LLVM没有附带此类功能,那么如何实现这样的功能呢?实现这一目标的最合适的层是什么,我在哪里可以找到可以构建它的示例?

思想

我的第一个想法是使用LLVM bitcode或IR的优化器。毕竟,为该表示编写了许多优化器。简单的死代码消除很容易:任何既不被调用也没有将其地址采集并存储在某处的函数都是死代码,可以从最终的二进制文件中省略。但是虚函数的地址被采用并存储在相应类的虚函数表中。为了确定该函数是否有可能被调用,优化器不仅必须识别所有虚函数调用,还要识别类型层次结构以将这些虚函数调用映射到所有可能的实现。

这使得在bitcode级别上解决问题变得非常困难。在更接近前端的某个地方,在可获得更多类型信息的阶段处理这一点可能更好,并且对虚拟功能的调用可能更容易与这些功能的实现相关联。也许VirtualCallChecker可以作为起点。

一个问题可能是这样的事实:尽管可以将多个对象的bitcode组合成一个单元以进行链接时间优化,但是很难将中等大小项目的所有源代码编译为单个翻译单元。因此,虚拟函数调用和实现之间的关联可能必须以某种方式保持到该阶段。我不知道LLVM是否可以使用任何类型的自定义注释;我在language specification中没有看到这一点。

但无论如何我在语言规范方面遇到了一些麻烦。 virtualvirtuality的{​​{1}}和virtualIndex属性唯一引用-fvtable-gc,但到目前为止,我找不到有关其语义的信息。 LLVM源代码中没有文档,也没有任何有用的地方。我可能正在查看用例的错误文档。

交叉引用

MDSubprogram在GCC的背景下问了几乎相同的事情,但我特意在这里寻找一个LLVM解决方案。曾经有一个struct foo { virtual ~foo() { } virtual int a() { return 12345001; } virtual int b() { return 12345002; } }; struct bar : public foo { virtual ~bar() { } virtual int a() { return 12345003; } virtual int b() { return 12345004; } }; int main(int argc, char** argv) { foo* p = (argc & 1 ? new foo() : new bar()); int res = p->a(); delete p; return res; }; 切换到海湾合作委员会,但显然它太过马车并受到了惩罚,而且铿锵也不支持它。

实施例

foo::b()

如何编写工具来自动删除生成的代码中的bar::b()clang++ -fuse-ld=gold -O3 -flto? 使用clang 3.5.1的objdump -d -C是不够的,因为生成的可执行文件的{{1}}显示了。

问题重点已更改

最初我一直在询问如何使用clang或LLVM来实现这种效果,但是如果clang和LLVM无法完成任务,可能会使用第三方工具来实现相同目的。但是,要求工具的问题在这里是不受欢迎的,所以到目前为止,重点已经从寻找工具转向编写工具。我想在任何情况下找到一个的机会都很渺茫,因为网络搜索没有显示出那个方向的提示。

0 个答案:

没有答案