Working with existing passes¶
GCC organizes the optimization work it does as “passes”, and these form trees: passes can have both successors and child passes.
There are actually five “roots” to this tree:
gcc.Passholding all “lowering” passes, invoked per function within the callgraph, to turn high-level GIMPLE into lower-level forms (this wraps all_lowering_passes within gcc/passes.c).
gcc.Passholding all “small IPA” passes, working on the whole callgraph (IPA is “Interprocedural Analysis”; all_small_ipa_passes within gcc/passes.c)
gcc.Passholding all regular IPA passes (all_regular_ipa_passes within gcc/passes.c)
gcc.Passholding those passes relating to link-time-optimization (all_lto_gen_passes within gcc/passes.c)
- The “all other passes” gcc.Pass catchall, holding the majority of the passes. These are called on each function within the call graph (all_passes within gcc/passes.c)
Returns a 5-tuple of
gcc.Passinstances, giving the 5 top-level passes within GCC’s tree of passes, in the order described above.
gcc.Passinstance for the pass with the given name, raising ValueError if it isn’t found
This wraps one of GCC’s struct opt_pass * instances.
Beware: “pass” is a reserved word in Python, so use e.g. ps as a variable name for an instance of
The name of the pass, as a string
The first child pass of this pass (if any)
The next sibling pass of this pass (if any)
Currently these are int bitfields, expressing the flow of data betweeen the various passes.
They can be accessed using bitwise arithmetic:
if ps.properties_provided & gcc.PROP_cfg: print(fn.cfg)
Here are the bitfield flags:
Mask Meaning Which pass sets this up? Which pass clears this? gcc.PROP_gimple_any Is the full GIMPLE grammar allowed? (the frontend) “expand” gcc.PROP_gimple_lcf Has control flow been lowered? “lower” “expand” gcc.PROP_gimple_leh Has exception-handling been lowered? “eh” “expand” gcc.PROP_cfg Does the gcc.Function have a non-None “cfg”? “cfg” “*free_cfg” gcc.PROP_referenced_vars Do we have data on which functions reference which variables? (Dataflow analysis, aka DFA). This flag was removed in GCC 4.8 “*referenced_vars” (none) gcc.PROP_ssa Is the GIMPLE in SSA form? “ssa” “expand” gcc.PROP_no_crit_edges Have all critical edges within the CFG been split? “crited” (none) gcc.PROP_rtl Is the function now in RTL form? (rather than GIMPLE-SSA) “expand” “*clean_state” gcc.PROP_gimple_lomp Have OpenMP directives been lowered into explicit calls to the runtime library (libgomp) “omplower” “expand” gcc.PROP_cfglayout Are we reorganizing the CFG into a more efficient order? “into_cfglayout” “outof_cfglayout” gcc.PROP_gimple_lcx Have operations on complex numbers been lowered to scalar operations? “cplxlower” “cplxlower0”
(int) The number of this pass, used as a fragment of the dump file name. This is assigned automatically for custom passes.
(boolean) Is dumping enabled for this pass? Set this attribute to True to enable dumping. Not available from GCC 4.8 onwards
There are four subclasses of
gcc.Pass, signifying a pass called per-function on the GIMPLE representation of that function.
gcc.Pass, signifying a pass called per-function on the RTL representation of that function.
Creating new optimization passes¶
You can create new optimization passes. This involves three steps:
Here’s an example:
# Here's the (trivial) implementation of our new pass: class MyPass(gcc.GimplePass): # This is optional. # If present, it should return a bool, specifying whether or not # to execute this pass (and any child passes) def gate(self, fun): print('gate() called for %r' % fun) return True def execute(self, fun): print('execute() called for %r' % fun) # We now create an instance of the class: my_pass = MyPass(name='my-pass') # ...and wire it up, after the "cfg" pass: my_pass.register_after('cfg')
where fun is a
Unfortunately it doesn’t appear to be possible to implement gate() for gcc.IpaPass yet; for now, the gate() method on such passes will not be called. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54959
If an unhandled exception is raised within gate or execute