LLVM 每周 - 第 29 期,2014 年 7 月 21 日
欢迎来到 LLVM 每周的第 29 期,这是一份每周发布(每周一发布)的时事通讯,涵盖 LLVM、Clang 和相关项目的进展。LLVM 每周由 Alex Bradbury 为您带来。在 http://llvmweekly.org 订阅未来期,并将其转发给您认为可能感兴趣的任何人。请将任何提示或反馈发送到 [email protected],或在 Twitter 上 @llvmweekly 或 @asbradbury。
这是一个特殊的扩展期,我选择将其副标题为“LLVM 每周访问 GNU Tools Cauldron”。活动 在周末举行,有许多有趣的演讲。您可以在本期时事通讯的末尾找到我的笔记。演讲已录制,视频将在未来一两个月内发布。
本期时事通讯的规范主页可以在 llvmweekly.org 找到.
来自网络的新闻和文章
第八届年度 LLVM 开发者大会已宣布,将于 10 月 28 日和 29 日在美国加州圣何塞举行。正在寻求赞助商和演讲/海报提交。
LLVM 博客发布了一篇新博客文章,详细介绍了 FTL:WebKit 基于 LLVM 的 JIT.
已经发布了LLVM/Clang 3.5 版本的暂定时间表.
Botond Ballo 发表了一篇2014 年 6 月 C++ 标准委员会会议总结.
邮件列表上的内容
Hal Finkel 发表了一篇关于在 LLVM 中添加 IR 级别的内在函数以表示不变量的 RFC。这些是不变的条件,优化器可以假设这些条件在程序执行期间有效。该帖子还附带了一套完整的补丁来实现该概念。Philip Reames 提出一个问题,即通过将不变量表示为 IR 指令,这可能会影响优化过程中的盈利能力启发式方法。Chandler Carruth 在随后的一篇帖子中 清晰地描述了权衡取舍,大多数人似乎都同意这一点。
Yuri Gribov 重新打开了一个之前讨论过的议题,即LLVM 和 GCC 在 ARM 上将帧指针设置为指向不同的堆栈槽。Renato Golin 回应了,解释了 GCC 如何最终以不同的方式完成操作。AddressSanitizer 团队更希望将两者统一起来,这样他们就可以利用布局的知识来执行解开操作,而无需使用表(一项速度优化)。不过,似乎 LLVM 或 GCC 都不太可能改变。
Diego Novillo 正在征求关于将他的 autofdo 工具集成到 LLVM 中的反馈。AutoFDO 是一种工具,可以将从 Linux perf 收集的数据转换为 LLVM 可以使用的格式。
Philip Reames 询问是否有人为在 IR 中询问 SSA 值的生存期问题实现了一个框架。缺乏直接的答案表明他们还没有,尽管 Andrew Trick 指出了计算 SSA 形式程序的生存集,而 Dibyendu Das 指出了使用合并集和 DJ 图进行高效的生存期计算,它与前者类似。
Tim Northover 编写了一份 RFC,建议应该删除 llvm.convert.to.fp16 和相关的内在函数。相反,可以使用 'half' 类型与 fpext/fptrunc 结合使用。
Chandler Carruth 编写了一份关于合法化操作和合法化后 DAG 结合 的 RFC。它刚刚发布,因此还没有收到反馈。
Andrew Kaylor 提议 让 Lang Hames 接替他成为 MCJIT、RuntimeDyld 和 JIT 事件监听器的代码所有者。这已经达成一致,并且
CODE_OWNERS.txt
已被相应更新。
LLVM 提交
添加了一个可解引用的属性。这表明参数或返回值指针是可解引用的(即可以从推测中加载,而不会有陷阱的风险)。这与 nonnull 属性略有不同,nonnull 属性并不一定意味着可解引用性(例如,您可能有一个指向数组末尾之后一个元素的指针)。r213385.
添加了一个 MergedLoadStoreMotion 传递。 r213396.
RegionInfo 已被模板化,以便它适用于 MachineBasicBlocks。 r213456.
来自 Nvidia 的一个大型补丁在 NVPTX 后端添加了一堆表面/纹理内在函数。 r213256.
添加了对发出警告的支持,如果强制向量化并且失败。 r213110.
对 FastISel 的改进继续进行,其中包括为 X86 实现 FastLowerCall 钩子。这实际上复制了 X86 中已经完成的操作,但是针对目标独立的调用降低进行了重构。 r213049.
ARM dmb、dsb 和 isb 内在函数已为 AARch64 实现。 r213247.
Clang 提交
Clang 的重写引擎现在是核心功能(即它无法在配置时禁用)。 r213171.
改进了程序员将
::
误写为:
时的错误恢复。 r213120.已经实现了 AARch64 Clang CLI 接口针对
-march
的提案。有关详细信息,请参阅提交消息。 r213353.OpenMP 工作仍在继续,包括针对
final
、untied
和其他子句以及master
指令添加初始解析和语义分析。 r213232、r213257、r213237,以及更多。
其他项目提交
- lldb 现在支持 'Kalimba' 平台(可能指的是 CSR 处理器)。 r213158.
LLVM 每周在 GNU Tools Cauldron 上
有关会议的详细信息以及我总结的演讲的详细信息,请参阅GNU Tools Cauldron 2014 网页。对于任何不准确之处,请务必与我联系,如果您发现任何我可能记错的地方。LLVM 追随者可能特别感兴趣 Renato Golin 关于 GCC 和 LLVM 社区之间合作的演讲。
Glibc BoF
- 2.20 处于“半冻结”模式。还有什么遗漏?fmemopen、fd 锁定、一些
-Wundef
工作 - 有人计划为 2.21 签入大型内容吗?
- Mentor Graphics 计划签入 NIOS II 移植。它们将在 Linux 内核补丁进入内核发行版之前被接受。
- 希望将 AArch64 ILP32 ABI 加入其中。内核补丁目前正在审查中,编译器工作已准备就绪。
- OpenRISC
- NaCl (nptl)
- 对 glibc 进行基准测试?是否有人知道好的方法?有一种预加载库方法(请参阅 Ondrej 演讲中的笔记)。
- Glibc 已使用 AddressSanitizer 构建,需要帮助将其集成到构建系统中。有人评论说这将是很好地将其添加到发行版中的功能。
- Red Hat 正在努力支持替代的 libm 实现,包括低精度和高精度实现。英特尔正在努力添加适用于小型向量的数学函数。
Abigail:走向 ABI 驯服
- 希望确定对共享库的更改是否会破坏用户的应用程序,以及用户希望了解更新的库是否与其代码保持兼容。bidiff 工具会告诉你两个目标文件作为输入的 ABI 方面的差异。
- libabi 包含诸如 DWARF 阅读器、比较引擎之类的模块。bidiff 等工具基于此 API 构建。
- libabigail 的下一步是什么?
- bicompat 将帮助应用程序作者通过检查 A 由 L 解决的未定义符号来确定他们的应用程序 A 是否仍与给定库 L 的更新版本兼容。
- 更便于自动化(例如集成到构建系统中)
- 支持未实例化的模板。这将需要在 DWARF 中表示未实例化的模板的声明。
- 第一个正式发布版(尽管源代码可在 https://sourceware.org/libabigail/ 获取)
在 Java 中编写虚拟机并在 GDB 中调试它们
- 甲骨文实验室一直在努力在 Java 中实现各种动态语言(例如 Ruby、Python、R、JS 等)。
- FastR 是 R 在 Java 中的重新实现,它具有一个解释器(Truffle)和一个动态编译器(Graal)。
- Truffle 和 Graal 从 AST 解释器开始。第一次评估节点时,它会专门化到在运行时看到的类型。之后,使用部分评估来编译树。
- 它可以部署在标准 HotSpot(没有编译)、GraalVM 或 SubstrateVM(SVM)上,SubstrateVM 使用 Graal 来提前编译语言实现。调试 SVM 很困难,因为 Java 调试工具不可用。解决方案是在 SVM 的输出中生成 DWARF 信息。
- Truffle 和 Graal 是开源的,SubstrateVM 不是(尚未?)。
GCC 和 LLVM 合作
- 好消息:许可证问题、个人恩怨和性能都不在讨论范围之内。
- 用户应该受到保护,不受任何发生的分歧的影响。在未来,我们应该在各种问题上进行更积极的讨论,而不是对例如事后才发现任意不同的编译器标志进行被动式的讨论。
- Renato 列出了我们可以合作的常见项目:binutils、glibc、sanitizers。Sanitizers 是一个合作成功的故事。
- 我们是否可以就一个(新的?)通用用户界面达成一致?
- 考虑到我们身处一个由编译器开发人员组成的房间,对于
-march
、-mtune
和-mcpu
存在令人惊讶的混淆。听起来,对重新设计编译器标志集的支持并不多,因为潜在的收益并不被认为足够大。 - 我们是否可以就属性、C/C++ 扩展、内置函数、ASM、链接器 API 达成标准化?
- GCC 文档刚刚重写,因此一些关于挖掘文档多么困难的批评不再有效。
机器引导的节能编译
- 2012 年的初步调查发现,编译器标志可以对能耗产生有意义的影响。这引发了一个问题,即如何确定使用哪些标志。
- MAGEEC 将最初同时针对 GCC 和 LLVM。它被实现为一个编译器插件,执行特征提取,并允许机器学习算法的输出更改运行的传递顺序。使用分数阶乘设计来减少要探索的优化空间。
- 随意开启或关闭编译器优化选项可能会导致内部编译器错误。机器学习算法应该学习这些选项,还是 GCC 应该更好地记录优化选项的依赖关系?
- 如果 (当前内部的) 插件 API 可以稳定下来,这对 MAGEEC 会非常有用。他们目前还必须使用一个经过修改的 Clang,因为它没有提供插件钩子。
- 该项目已经开发了一个低成本的能量测量板,以及他们自己的基准测试套件 (Bristol/Embecosm 嵌入式基准测试套件,或 BEEBS)。BEEBS 2.0 计划在 2014 年 8 月 31 日发布,其中包含更广泛的基准测试 (目前为 93 个)。Jeremy 展示了一个令人愉快的现场演示,您可以在微控制器开发板上运行基准测试,并立即找到运行它所消耗的毫焦耳数。
- 该项目目前的状况是它还没有达到比 GCC O2 更好的结果,但预计这种情况将在未来几个月内改变。
使用 GCC 进行即时编译
- libgccjit.so 是 GCC 的一个实验性分支,它允许您将 GCC 构建为共享库并将其嵌入到其他程序中,以允许在运行时进行进程内代码生成。
- 专用的 JIT API 将提供更好的稳定性保证。它提供了一个为易用性而设计的高级 API。
- 该 API 没有提供针对类型推断、逃逸分析、拆箱、内联缓存等的解决方案。
- 它有一个 C++ API,其中包括一些巧妙的操作符重载,可以大幅减少冗长代码,以及一个 Python API。
- David Malcolm 编写了 Coconut,一个使用 libgccjit.so 的 Python JIT 编译器。它尚未完善,并且处于实验阶段。
- 缺点:目前必须将 .s 文件写入文件并调用 gcc 进行编译。
有些人可能会对将编译器架构为库的好处发表俏皮的评论,但我当然不敢。好消息是演讲者正在积极研究将 GAS 和 GNU ld 作为库使用所需的内容。
新的 Intel SIMD ISA 简介及其对 GCC 的影响
- AVX-512 每周期提供 64 个单精度或 32 个双精度浮点运算。它还具有 8 个 64 位掩码寄存器。
- 可以在每个指令进程中设置舍入模式。
- GCC 4.9.x 提供基本支持。
来自 Sanitizers 的新闻
- MemorySanitizer 检测未初始化内存的使用。将 CPU 提高约 2.5 倍,将 RAM 提高 2 倍。于 2013 年在 LLVM 中发布。目前仅限于 Linux/x86-64。
- 通过限制历史记录深度和每个堆栈跟踪的新历史记录节点数来限制历史记录增长。
- MSan 已经在 Google 内部代码、Chromium、LLVM 等中发现了数百个错误。由于需要重新构建大量系统库,因此这对 Chromium 来说更具挑战性。
- AddressSanitizer 注释允许您检测对例如
std::vector<>
区域的访问,该区域已作为其容量的一部分分配,但尚未使用 (即将在下一个push_back
中开始使用)。接下来是对std::string
和std::deque
做同样的事情。 - Glibc 使用 GNU-C 而不是 ANSI C,目前无法用 Clang 编译 (尤其是嵌套函数有问题)。但是,它可以用 GCC 构建 ASan。
- Evgeniy 评论说,Clang 和 GCC 之间在诸如
__has_feature(address_sanitizer)
与__SANITIZE_ADDRESS__
之类的事物上的标准化缺乏是令人恼火的。这正是 Renato 昨天谈论的内容。
glibc 性能调优
- 以 memset 为例。查看 3 种变体。
- 编写有用的基准测试比您想象的要困难。当使用相同的内存位置时,在循环中多次运行
memset
并不是一个好的基准测试,因为处理器会进行负载存储转发。即使解决了这个问题,分支预测器也可能比在实际场景中使用 memset 时表现得更好,并导致结果不准确。 - 为了超越微基准测试,Ondrej 一直在使用
LD_PRELOAD
来链接到记录时间消耗详细信息的函数的已检测版本。 - 参见 此处 获取 memset 基准测试,并参见 此处 获取更多背景信息。
- 在 Ondrej 的测试中 (运行 Firefox 时),strcmp 是调用频率最高的 glibc 函数。
GCC 中的去虚拟化
- 这是间接调用移除的一种特殊情况,虽然讨论是在 C++ 的背景下进行的,但这些技术也适用于其他语言。一些基本情况在前端得到处理,甚至由语言标准指定。
- 它是跨聚合体的常量传播的一种特殊情况,这已经由全局值编号和过程间常量传播完成。但这些传递只捕获了极少数可能的情况。
- 前端和中间端之间信息的丢失可能会使某些情况几乎不可能。中间语言可以使用显式表示基本类型、虚拟表指针的位置和 vtable 进行扩展。还可以注释多态调用,指定实例和多态调用类型,以及用于表示构造函数/析构函数的标志。
- 我无法比幻灯片更好地总结 GCC 去虚拟化实现的细节。希望它们会在线提供。
- 一个特别的挑战是匹配不同编译单元之间的类型。使用 C++ 单一定义规则。
- 它可以用来加强不可到达函数移除。
- 在 GCC 4.9 中,反馈导向的去虚拟化扩展到与 LTO 进行模块间操作。