认识 GCC 4GNU Compiler Collection 发行版系列中的新特性 ![]() | ![]() |
![]() | 级别: 中级 M. Tim Jones, 顾问工程师, Emulex Corp. 2008 年 11 月 24 日 这 几年,GNU Compiler Collection(GCC)经历了从 GCC 3 到 GCC 4 的巨大转变。GCC 4 引入了一个新的优化框架(以及新的中间代码表示法)、新的目标和语言支持以及多种新的属性和选项。认识 GCC 4 的主要新特性及其优点。 无论是开源开发还是闭源开 发,GCC 都是开发的基础。它是架构和操作系统的启用程序(enabler)。当一种新的处理器出现时,它的成功取决于支持它的 GCC 版本(可以为它生成代码的后端)。GCC 也是 Linux® 的启用程序。Linux 作为操作系统取得了巨大的成功,因为它可以在众多不同的架构上运行。将 GCC 移植到目标环境后,便可以将 Linux 移植到该环境,并在其中运行 Linux。坦白地说,GCC 为 Linux 和嵌入式开发铺平了道路。 但是,GCC 不能止步不前。新的处理器架构不断涌现,新的研究发现优化和生成代码的更好方式。所以 GCC 需要继续前进,现在已成长到它的第 4 个主发行版。本文探索 GCC 第 4 版中的重要变化,展示为什么 — 如果您还使用 GCC 的话 — 现在应该使用这个编译器标准。 当 Richard Stallman 于 1987 年首次发行 GCC 时,它最初表示 GNU C Compiler。(图 1 显示了 GCC 的历史时期)。Richard 在 1984 年开始这个项目,当时是希望构建一个免费的 它是一种开源的编译器(也就是说,源代码是免费提供的),所以其他人开始为新的语言和目标架构提供补丁和更新(后者更重要)。不久以后,它的首字母缩写的意思变成了 GNU Compiler Collection,因为它支持在大多数流行的(甚至罕见的)架构上运行的各种不同的语言。 图 1. GCC 发行版的历史 ![]() 如今,GCC 是最流行的编译器工具链。可以使用相同的源代码库构建用于 Ada、Fortran、Java™ 语言、 哇!说了这么多。您肯定以为我真的被 GCC 迷倒了吧。这么说吧,当我用 GCC 开发软件时,就算我妻子走进房间,我都觉得有点不舒服。
编 译器是以一种管道架构来构造的,这种架构由几个阶段(stage)组成,每个阶段处理不同格式的数据(见图 2)。编译器的前端是特定于语言的,它包括一个用于给定语言的解析器,这个解析器产生经过解析的树和中间表示(Register Transfer Language,RTL)。然后,后端负责使用这种独立于语言的表示,并产生用于特定的目标架构的指令。为此,优化器使用 RTL 创建快速的或紧凑的代码(或者两者兼顾)。然后,优化后的 RTL 被提供给代码生成器,后者产生目标代码。 图 2. 编译器不同阶段的简化视图 ![]()
GCC 4 为标准的编译器套件带来了很多变化,最大的变化是为了支持优化而引入的树的 Static Single Assignment(SSA)形式。但是,通常情况下编译器在某些优化模式下会更快,并提供很多新的增强,包括新的目标支持。GCC 4 对于警告和错误的处理要彻底得多(实际上,在 GCC 4 中,某些警告显示为错误)。GCC 4 的一个缺点是,它与用 GCC 3 编译器构建的对象不是二进制兼容的(这意味着源代码必须用 GCC 4 来编译)— 这的确有点不幸,但这是为取得进步而付出的代价。 我们来看看新的 GCC 4 中引入的一些关键改进。 4.0 发行版(最新的版本是 4.0.4)是迈入 GCC 4 的第一步。就这一点而言,除非它到了一个稳定的版本,否则不建议将它用于生产开发。这个发行版包含很多变化 — 其中两个特别的变化是引入了新的优化框架(Tree SSA)和支持自动向量化(autovectorization)。 在 GCC 4 之前,中间表示曾被称作 Register Transfer Language(RTL)。 RTL 是非常接近于汇编语言的一种低级的表示(受 LISP S 表达式的影响)。RTL 的问题是,它支持的优化是接近于目标的。需要关于程序的高级信息的优化可能无法实现,因为无法用 RTL 表达它们。Tree SSA 被设计为既独立于语言又独立于目标,同时还支持更先进的分析和更丰富的优化。 Tree SSA 引入了 2 种新的中间表示法。第一种是 GENERIC, 它是一种通用的树表示法,由语言前端树构成。GENERIC 树被转换成 GIMPLE 形式,进而转换成控制流图,以支持基于 SSA 的优化。最后,SSA 树被转换成 RTL,后者被后端用于目标生成代码。这是一个过度简化的描述,但是其结果是一种新的中间形式,这种形式更适合于高级和低级优化。(要了解关于这个过程的 更多信息,请参阅 参考资料)。 由于这些变化实际上表示一种新的框架,所以可以定义新的优化。到目前为止,已经实现了一些新的优化,但是显然还有更多的工作要做,以确保 GCC 生成尽可能紧凑、有效的代码。 GCC 4 的另一个有趣的变化是增加了一个循环向量器(基于 Tree SSA 框架)。Autovectorization 这个特性允许编译器在受益于目标处理器的向量指令的代码中识别标量处理循环。另一种基于循环的优化是 Swing Modulo Scheduling(SMS),这种优化用于构造指令管道,其目的是通过利用指令级并行减少处理器周期。要了解更多关于这些新方法的信息,请参阅 参考资料。 最后,4.0 系列还引入了(除了很多 有 了新的优化框架,4.1 发行版系列引入了大量的优化,例如改进的概要分析(profiling)支持和更准确的分支可能性估计。更有用的两个优化是更好的内联支持和利用指令缓存 局部性的能力。当需要内联函数时,编译器不再内联那些不常执行的函数。相反,热调用点(hot call site)更可能被内联,以使代码尽量短小,同时仍获得内联函数的优点。GCC 还可以帮助将函数划分到热区和冷区。与将冷函数填入缓存相比,将热函数(也就是那些更常用的函数)放在一起可以更好地利用指令缓存。 前端有很多的更新,包括对 Objective- 4.2 发行版系列继续引入新的优化和增强,这些优化和增强同时涵盖了语言和处理器架构。后端被更新为包括对 Sun 的 UltraSPARC T1 处理器(代码名为 Niagara)和 Broadcom 的 SB-1A(每秒百万条指令,或 MIPS)核心的支持。 在 4.2 发行版中前端也有所变化。修改了 OpenMP 的一种用法是,使用预处理程序指令注释其中应该发生并行的代码。该代码在执行块期间转换为一个多线程程序,当块中的每个线程完成时,各个线程再结合起来。 图 3 显示了这个过程。OpenMP 不仅提供一套 图 3. OpenMP 支持的简单例子 ![]() GCC 4 当前的发行版系列是 4.3。这个发行版系列在特性和支持的架构(以及不支持的架构,因为很多过时的架构和端口已被移除)方面有了很大的进步。4.3 为 Fortran 2003 增加了新的语言支持,以及大量通用的优化器改进。 这 个发行版中支持的新的处理器包括 Coldfire 处理器家族中的一些处理器、IBM System z9 EC/BC 处理器、Cell 宽带引擎架构的 Synergistic Processor Unit(SPU),并且支持 SmartMIPS 等。此外,它还支持 Thumb2(压缩的 ARM 指令)和 ARMv7 架构的编译器和库,支持对 Core2 处理器和 Geode 处理器家族进行调优。 在编译器的前端,GIMPLE 的内部表示被重新定义,这意味着编译器将消耗更少的内存。 4.4 发行版系列方面的工作已经开始,其目标是一个通用发行版。在 4.4 版中,您将发现大量的 bug 修复和更通用的优化器改进。针对 编译器现在还允许在函数级(而不是在之前默认的文件级)定义一个优化级别。这个功能是通过 最后,增加了对 Picochip 的处理器支持,它是一个 16 位的多核处理器。Picochip 比较有趣的地方是,可以为每个核单独编程,各个核之间在一个 mesh 中通信。
显 然,GCC 的前景是光明的。工具链不断发展 —包括架构上的发展和增量式的发展— 以支持最新的处理器架构。GCC 很好地覆盖了各种语言。目前正在开发对很多不同语言的支持,例如 Mercury、GHDL(用于 VHDL 的 GCC 前端)以及 Unified Parallel GCC 除了拥有光明的前景外,它的不断改善将使所有类型的软件受益,包括 Linux、Berkeley Software Distribution [BSD] 和 Apache 等软件。用 GCC 4 编译的软件通常更加紧凑和快速,这意味着软件行业的全面改善。 学习
获得产品和技术
讨论
|
From: http://www.ibm.com/developerworks/cn/linux/l-gcc4/index.html