GCC(/Clang):合并具有相同指令的函数(COMDAT折叠)

31
只是好奇,GCC或Clang工具集目前是否实现了MSVC的相同COMDAT折叠(ICF)的等效版本?如果没有,是否有任何计划?我似乎找不到任何关于此主题的最新权威链接,除了旧的GCC邮件列表消息。
如果没有,这是否意味着在结果二进制文件中,对不同类型进行模板实例化的函数始终是不同的函数(在它们没有完全内联的情况下),即使它们是二进制兼容的,或者是否有其他机制来在其他级别上处理这个问题?
此外,有人发现ICF在实践中大大减小了生成的可执行文件的大小吗?我手头没有任何大型MSVC项目来测试它。(我猜想,它只有在您恰好对许多不同的vtable-layout兼容类型进行模板实例化时才真正有帮助。)
最后,两个指向不同函数的函数指针在运行时比较相等是否符合C++11标准?此链接似乎暗示着它不符合,但它是针对C99的。编辑:在此主题上找到先前的问题

1
发现一篇来自微软的 Larry Osterman 的引用语:“而这个特性[ICF]是使C ++模板成为应用程序可行解决方案的原因...否则,模板将导致代码大小的大幅增长,以至于它们在生产软件中几乎无法使用。”... 如果GCC / Clang不这样做,那就很好奇。 - Stephen Lin
3
他们确实能够正常使用,许多软件使用标准库中的模板,因此很明显,"几乎无法使用"的说法是不正确的。 - Jonathan Wakely
@JonathanWakely 哈哈,我喜欢GCC,那只是他的话 :) - Stephen Lin
3
在 ELF 和 PE 平台上,GNU ld 会按名称 COMDAT 折叠(即折叠具有相同类型签名的不同翻译单元中的实例),但不会按节内容折叠(这就是 MSVC /OPT:ICF 的作用方式——它合并具有不同修饰符名称/签名但内容相同的 COMDAT)。 因此,在这种情况下,Larry 制作了飞镖靶的外环,但没有制作靶心。 - LThode
1个回答

20
GCC和Clang都不是链接器,ICF需要由链接器完成,或者至少与链接器合作完成。编辑:它们不执行ICF,因此,独立的实例会产生不同的代码。 GNU gold链接器支持使用--icf选项进行ICF,需要使用GCC选项-ffunction-sections
不同的函数必须具有不同的地址...我不记得是否禁用了对其地址取地址的任何函数的ICF,但如果没有,应该可以在组合函数之前放置大量的无操作指令,并使每个不同的实例始于不同的指令,从而具有不同的地址。编辑:gold的--icf=safe选项仅为可以证明未获取其地址的函数启用ICF,因此依赖于不同地址的代码仍将正常工作。
ICF是一种不错的优化方式,但并非必要。通过花费一些精力将与依赖无关的代码提取到非模板或参数更少的模板中,可以减少可执行文件中重复代码的数量。我曾在几年前做过Diet Templates的演讲,幻灯片中有更多相关信息。

1
那个链接器通常被称为“GNU ld”或GNU链接器,整个工具集通常被称为GNU工具链(意味着GCC、GNU as、GNU ld,有时包括GNU libc)。链接器通常是操作系统的一部分,例如Solaris有自己的链接器,但GNU链接器是跨平台的,支持许多可执行格式并在许多不同的操作系统上运行,因此例如在Solaris上的GCC可以配置为使用本地Solaris链接器或GNU链接器。 - Jonathan Wakely
在GNU/Linux上,是的...我不确定Mac OS X是否有自己的链接器或使用GNU ld。此外,请注意,GNU binutils项目包含两个链接器,GNU ld和更新(速度更快)的gold链接器,它仅适用于ELF。 - Jonathan Wakely
谢谢,这绝对有助于更好地理解工具链...不管怎样,你知道gcc/ld是否有计划开展类似ICF的工作吗?只是好奇,我意识到GCC没有它也可以“过得去” :D(抱歉措辞可能不太好) - Stephen Lin
2
顺便提一下,似乎互联网上没有其他人提到过你的安全ICF的无操作想法。我找到的所有来源(例如http://research.google.com/pubs/pub36912.html)都坚持避免折叠那些地址被占用的函数。也许你是第一个想到这个想法的人,或者有一些技术限制阻止它发挥作用? - Stephen Lin
1
"只要付出一些努力,您就可以提取出非依赖代码"。您是指编译器编写者还是程序员需要付出努力? - pmr
显示剩余5条评论

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