认识 GCC 4

这几年,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 年开始这个项目,当时是希望构建一个免费的 C 编译器,这种编译器可以使用、修改和演变。GCC 起初在早期的 Sun 和 DEC VAX 系统上运行。

阅读 Tim 在 developerWorks 上的更多文章

它是一种开源的编译器(也就是说,源代码是免费提供的),所以其他人开始为新的语言和目标架构提供补丁和更新(后者更重要)。不久以后,它的 首字母缩写的意思变成了 GNU Compiler Collection ,因为它支持在大多数流行的(甚至罕见的)架构上运行的各种不同 的语言。


图 1. GCC 发行版的历史
GCC 发行版的历史

如今,GCC 是最流行的编译器工具链。可以使用相同的源代码库构建用于 Ada、Fortran、Java™ 语言、C 的变体(C++ 和 Objective-C )的编译器,并且它最大范围地覆盖了所有编译器的目 标处理器架构(支持 30 种处理器家族)。而且,源代码基是完全可移植的,可以在超过 60 种平台上运行。编译器是高度可调优的,有大量调整生成代码的选项。简言之,GCC 是编译器中的瑞士军刀,它重新定义了灵活性的含义。它也是最复杂的开源系统:目前,GCC 由多达 150 万行代码构成。

哇!说了这么多。您肯定以为我真的被 GCC 迷倒了吧。这么说吧,当我用 GCC 开发软件时,就算我妻子走进房间,我都觉得有点不舒服。

 




回页首


开始之前

编译器是以一种管道架构来构造的,这种架构由几个阶段(stage)组成,每个阶段处理不同格式的数据(见图 2)。编译器的前端是特定于语言的,它包括一个用于给定语言的解析器,这个解析器产生经过解析的树和中间表示(Register Transfer Language,RTL)。然后,后端负责使用这种独立于语言的表示,并产生用于特定的目标架构的指令。为此,优化器使用 RTL 创建快速的或紧凑的代码(或者两者兼顾)。然后,优化后的 RTL 被提供给代码生成器,后者产生目标代码。


图 2. 编译器不同阶段的简化视图
编译器不同阶段的简化视图




回页首


GCC 4 的核心变化

GCC 4 为标准的编译器套件带来了很多变化,最大的变化是为了支持优化而引入的树的 Static Single Assignment(SSA)形式。但是,通常情况下编译器在某些优化模式下会更快,并提供很多新的增强,包括新的目标支持。GCC 4 对于警告和错误的处理要彻底得多(实际上,在 GCC 4 中,某些警告显示为错误)。GCC 4 的一个缺点是,它与用 GCC 3 编译器构建的对象不是二进制兼容的(这意味着源代码必须用 GCC 4 来编译)— 这的确有点不幸,但这是为取得进步而付出的代价。

我们来看看新的 GCC 4 中引入的一些关键改进。

4.0 发行版系列

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 系列还引入了(除了很多 CC++ 变化外)一个新的 Fortran 前端,该前端支持 Fortran 90 和 95(而不是 GCC 3 中支持的更旧的 Fortran 77)。另外,GCC 4 还引入了新的 Ada 2005 特性,并支持更多目标架构上的 Ada 特性。

4.1 发行版系列

有了新的优化框架,4.1 发行版系列引入了大量的优化,例如改进的概要分析(profiling)支持和更准确的分支可能性估计。更有用的两个优化是更好的内联支持和利用指令缓存 局部性的能力。当需要内联函数时,编译器不再内联那些不常执行的函数。相反,热调用点(hot call site)更可能被内联,以使代码尽量短小,同时仍获得内联函数的优点。GCC 还可以帮助将函数划分到热区和冷区。与将冷函数填入缓存相比,将热函数(也就是那些更常用的函数)放在一起可以更好地利用指令缓存。

前端有很多的更新,包括对 Objective-C++ 的支持。还有很多用于 Java 核心库(libgc)的更新。后端则引入了对 IBM® System z™ 9-109 处理器的支持,包括 128 位 Institute of Electrical and Electronics Engineers(IEEE)浮点数和内建的原子内存访问。如果那还不够,后端现在还可以产生防止栈溢出(stack-smashing)攻击的代码 (即缓冲区溢出检测和重排,以防止指针泄漏)。有些内建的函数也已经被更新,以较小的开销防止缓冲区溢出。

4.2 发行版系列

4.2 发行版系列继续引入新的优化和增强,这些优化和增强同时涵盖了语言和处理器架构。后端被更新为包括对 Sun 的 UltraSPARC T1 处理器(代码名为 Niagara )和 Broadcom 的 SB-1A(每秒百万条指令,或 MIPS)核心的支持。

在 4.2 发行版中前端也有所变化。修改了 C++ 可见性处理和对 Fortran 2003 streaming input/output(I/O)扩展的支持。但是 4.2 发行版中最有趣的变化之一是增加了用于 CC++ 和 Fortran 编译器的 OpenMP。OpenMP 是一个多线程实现,它允许编译器为任务和数据并行生成代码。

OpenMP 的一种用法是,使用预处理程序指令注释其中应该发生并行的代码。该代码在执行块期间转换为一个多线程程序,当块中的每个线程完成时,各个线程再结合起来。

图 3 显示了这个过程。OpenMP 不仅提供一套 pragma (即预处理程序指令),还提供用于 CC++ 和 Fortran 的函数。在图 3 中,可以看到一个简单的程序,它将代码中的一些元素划分到多个线程中(将 for 块并行化)。图 3 中图形化地显示了其效果:传统的程序将连续地执行循环,而 OpenMP 实现则创建多个线程,从而并行地执行 for 块。在 参 考资料 中可以了解更多关于 OpenMP 的信息。


图 3. OpenMP 支持的简单例子
OpenMP 支持的简单例子

4.3 发行版系列

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.3 发行版之后

4.4 发行版系列方面的工作已经开始,其目标是一个通用发行版。在 4.4 版中,您将发现大量的 bug 修复和更通用的优化器改进。针对 CC++ 和 Fortran 的 3.0 版的 OpenMP 规范已经集成。

编译器现在还允许在函数级(而不是在之前默认的文件级)定义一个优化级别。这个功能是通过 optimize 属性提供的,该属性还允许指定优化器的一些选项。

最后,增加了对 Picochip 的处理器支持,它是一个 16 位的多核处理器。Picochip 比较有趣的地方是,可以为每个核单独编程,各个核之间在一个 mesh 中通信。

 




回页首


结束语

显然,GCC 的前景是光明的。工具链不断发展 —包括架构上的发展和增量式的发展— 以支持最新的处理器架构。GCC 很好地覆盖了各种语言。目前正在开发对很多不同语言的支持,例如 Mercury、GHDL(用于 VHDL 的 GCC 前端)以及 Unified Parallel C 语言(UPC)。

GCC 除了拥有光明的前景外,它的不断改善将使所有类型的软件受益,包括 Linux、Berkeley Software Distribution [BSD] 和 Apache 等软件。用 GCC 4 编译的软件通常更加紧凑和快速,这意味着软件行业的全面改善。


参考资料

学 习


获得产品和技术

  • 订购 SEK for Linux ,共含两张 DVD,包含来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的针对 Linux 的最新 IBM 试用软件。
  • 用可直接从 developerWorks 下载的 IBM 试用软件 构建您的下一个 Linux 开发项目。


讨论


关 于作者

M. Tim Jones

M. Tim Jones 是一名嵌入式软件工程师,他是 GNU/Linux Application Programming, AI Application Programming (第二版)以及 BSD Sockets Programming from a Multilanguage Perspective 等书的作者。他的工程背景包括地球同步航天器内核开发、嵌入式系统架构和网络协议开发等。Tim 也是科罗拉多州朗蒙特市 Emulex Corp. 的顾问软件工程师。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值