GNU C Compiler Internals/Style Hacks 4 1

From Wikibooks, open books for an open world
Jump to: navigation, search

These exercises are from http://gcc.gnu.org/projects/beginner.html

Break up enormous source files[edit]

Not terribly hard. Watch out for file-scope globals. Suggested targets:

Big Files
File Size File Name
494K java/parse.y
413K combine.c
408K dwarf2out.c
375K cp/pt.c
367K fold-const.c
356K loop.c

There are several other files in this size range, which I have left out because touching them at all is unwise (reload, the Fortran front end). You can try, but I am not responsible for any damage to your sanity which may result.

Break up enormous functions[edit]

This is in the same vein as the above, but significantly harder, because you must take care not to change any semantics. The general idea is to extract independent chunks of code to their own functions. Any inner block that has a half dozen local variable declarations at its head is a good candidate. However, watch out for places where those local variables communicate information between iterations of the outer loop!

With even greater caution, you may be able to find places where entire blocks of code are duplicated between large functions (probably with slight differences) and factor them out.

Break up enormous conditionals[edit]

Harder still, because it's unlikely that you can tell what the conditional tests, and even less likely that you can tell if that's what it's supposed to test. It is definitely worth the effort if you can hack it, though. An example of the sort of thing we want changed:

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)))))
    || (modifier != EXPAND_CONST_ADDRESS
        && modifier != EXPAND_INITIALIZER
        && mode == BLKmode
        && SLOW_UNALIGNED_ACCESS (mode, alignment)
        && (TYPE_ALIGN (type) > alignment
            || bitpos % TYPE_ALIGN (type) != 0)))
  {

Delete garbage[edit]

#if 0 blocks that have been there for years, unused functions, unused entire files, dead configurations, dead Makefile logic, dead RTL and tree forms, and on and on and on. Depending on what it is, it may not be obvious if it's garbage or not. Go for the easy ones first.

Use predicates for RTL objects[edit]

GCC has simple predicates to see if a given rtx is of some specific class. These predicates simply look at the rtx_code of the given RTL object and return nonzero if the predicate is true. For example, if an rtx represents a register, then REG_P (rtx) is nonzero.

Unfortunately, lots of code in the middle end and in the back ends does not use these predicates and instead compare the rtx_code in place: (GET_CODE (rtx) == REG). Find all the places where such comparisons can be replaced with a predicate. Also, for many common comparisons there is no predicate yet. See which ones are worth having a predicate for, and add them. You can find a number of suggestions in the mailing list archives.