Optimization

The IR-code generated by the front-end can be optimized in many ways. The compiler does not have the best way to optimize code, but instead has a bag of tricks it can use.

Abstract base classes

The optimization passes all subclass one of the following base classes.

class ppci.opt.transform.ModulePass

Base class of all optimizing passes.

Subclass this class to implement your own optimization pass.

run(ir_module)

Run this pass over a module

class ppci.opt.transform.FunctionPass

Base pass that loops over all functions in a module

on_function(function: ppci.ir.SubRoutine)

Override this virtual method

run(ir_module: ppci.ir.Module)

Main entry point for the pass

class ppci.opt.transform.BlockPass

Base pass that loops over all blocks

on_block(block: ppci.ir.Block)

Override this virtual method

on_function(function)

Loops over each block in the function

class ppci.opt.transform.InstructionPass

Base pass that loops over all instructions

on_block(block)

Loops over each instruction in the block

on_instruction(instruction)

Override this virtual method

Optimization passes

class ppci.opt.Mem2RegPromotor

Tries to find alloc instructions only used by load and store instructions and replace them with values and phi nodes

class ppci.opt.LoadAfterStorePass

Remove load after store to the same location.

[x] = a
b = [x]
c = b + 2

transforms into:

[x] = a
c = a + 2
class ppci.opt.DeleteUnusedInstructionsPass

Remove unused variables from a block

class ppci.opt.RemoveAddZeroPass

Replace additions with zero with the value itself. Replace multiplication by 1 with value itself.

class ppci.opt.CommonSubexpressionEliminationPass

Replace common sub expressions (cse) with the previously defined one.

class ppci.opt.cjmp.CJumpPass

Uml

digraph "classes_foo" {
charset="utf-8"
rankdir=BT
"0" [label="{BlockPass|\l|on_block(block)\lon_function(function)\l}", shape="record"];
"1" [label="{CJumpPass|\l|on_instruction(instruction)\l}", shape="record"];
"2" [label="{CleanPass|\l|find_empty_blocks(function)\lfind_single_predecessor_block(function)\lglue_blocks(block1, block2)\lon_function(function)\lremove_empty_blocks(function)\lremove_one_preds(function)\l}", shape="record"];
"3" [label="{CommonSubexpressionEliminationPass|\l|on_block(block)\l}", shape="record"];
"4" [label="{ConstantFolder|ops : dict\l|eval_const(value)\lis_const(value)\lon_block(block)\l}", shape="record"];
"5" [label="{DeleteUnusedInstructionsPass|\l|on_block(block)\l}", shape="record"];
"6" [label="{FunctionPass|debug_db : NoneType\l|on_function(function)\lrun(ir_module)\l}", shape="record"];
"7" [label="{InstructionPass|\l|on_block(block)\lon_instruction(instruction)\l}", shape="record"];
"8" [label="{LoadAfterStorePass|\l|find_store_backwards(i, ty, stop_on)\lon_block(block)\lremove_redundant_stores(block)\lreplace_load_after_store(block)\l}", shape="record"];
"9" [label="{Mem2RegPromotor|\l|on_function(function)\lplace_phi_nodes(stores, phi_ty, name, cfg_info)\lpromote(alloc, cfg_info)\lrename(initial_value, phis, loads, stores, cfg_info)\l}", shape="record"];
"10" [label="{ModulePass|logger : RootLogger, NoneType\l|prepare()\lrun(ir_module)\l}", shape="record"];
"11" [label="{RemoveAddZeroPass|\l|on_instruction(instruction)\l}", shape="record"];
"12" [label="{TailCallOptimization|\l|on_function(function)\lrewrite_tailcalls(function, tail_calls)\l}", shape="record"];
"0" -> "6" [arrowhead="empty", arrowtail="none"];
"1" -> "7" [arrowhead="empty", arrowtail="none"];
"2" -> "6" [arrowhead="empty", arrowtail="none"];
"3" -> "0" [arrowhead="empty", arrowtail="none"];
"4" -> "0" [arrowhead="empty", arrowtail="none"];
"5" -> "0" [arrowhead="empty", arrowtail="none"];
"6" -> "10" [arrowhead="empty", arrowtail="none"];
"7" -> "0" [arrowhead="empty", arrowtail="none"];
"8" -> "0" [arrowhead="empty", arrowtail="none"];
"9" -> "6" [arrowhead="empty", arrowtail="none"];
"11" -> "7" [arrowhead="empty", arrowtail="none"];
"12" -> "6" [arrowhead="empty", arrowtail="none"];
}