跳转到内容

GNU C 编译器内部/风格技巧 4 1

来自维基教科书,为开放世界而开放的书籍

这些练习来自 http://gcc.gnu.org/projects/beginner.html

拆分庞大的源代码文件

[编辑 | 编辑源代码]

并不难。注意文件范围内的全局变量。建议的目标

大文件
文件大小 文件名
494K java/parse.y
413K combine.c
408K dwarf2out.c
375K cp/pt.c
367K fold-const.c
356K loop.c

还有几个其他文件的大小在这个范围内,我没有列出来,因为修改它们是不可取的(例如,reload,Fortran 前端)。你可以尝试,但我对由此可能造成的任何理智损伤概不负责。

拆分庞大的函数

[编辑 | 编辑源代码]

这与上面的拆分文件类似,但难度更大,因为你需要注意不要改变任何语义。一般来说,你需要将独立的代码块提取到它们自己的函数中。任何头部有半打局部变量声明的内部代码块都是一个不错的候选者。但是,要注意那些局部变量在外部循环迭代之间传递信息的地方!

更谨慎地,你可能能够找到一些地方,整个代码块在大型函数之间重复(可能略有不同),并将它们分解出来。

拆分庞大的条件语句

[编辑 | 编辑源代码]

难度更大,因为你可能无法确定条件测试,更不可能知道它是否应该测试。但如果你能做到,绝对值得付出努力。一个我们想要改变的示例

if (mode1 == VOIDmode
    || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
    || (modifier != EXPAND_CONST_ADDRESS
        && modifier != EXPAND_INITIALIZER
        && ((mode1 != BLKmode && ! direct_load[(int) mode1]
             && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
             && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
            /* If the field isn't aligned enough to fetch as a memref,
               fetch it as a bit field.  */
            || (mode1 != BLKmode  
                && SLOW_UNALIGNED_ACCESS (mode1, alignment)
                && ((TYPE_ALIGN (TREE_TYPE (tem))
                     < GET_MODE_ALIGNMENT (mode))
                    || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
            /* If the type and the field are a constant size and the
               size of the type isn't the same size as the bitfield,
               we must use bitfield operations.  */
            || ((bitsize >= 0
                 && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
                     == INTEGER_CST)
                 && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
                                           bitsize[check spelling])))))
    || (modifier != EXPAND_CONST_ADDRESS
        && modifier != EXPAND_INITIALIZER
        && mode == BLKmode
        && SLOW_UNALIGNED_ACCESS (mode, alignment)
        && (TYPE_ALIGN (type) > alignment
            || bitpos % TYPE_ALIGN (type) != 0)))
  {

删除垃圾代码

[编辑 | 编辑源代码]

多年来一直存在的 #if 0 代码块、未使用的函数、未使用的整个文件、失效的配置、失效的 Makefile 逻辑、失效的 RTL 和树形式,等等等等。根据它的具体情况,可能不清楚它是否是垃圾代码。先从容易的部分开始。

对 RTL 对象使用谓词

[编辑 | 编辑源代码]

GCC 有简单的谓词,用来判断给定的 rtx 是否属于某个特定类。这些谓词只查看给定 RTL 对象的 rtx_code,如果谓词为真则返回非零值。例如,如果 rtx 表示一个寄存器,那么 REG_P (rtx) 为非零值。

不幸的是,中间端和后端的很多代码都没有使用这些谓词,而是直接比较 rtx_code:(GET_CODE (rtx) == REG)。找到所有可以用谓词替换这种比较的地方。此外,对于许多常见的比较,还没有谓词。看看哪些值得添加谓词,并添加它们。你可以在邮件列表存档中找到许多建议。

华夏公益教科书