1. A method of optimizing an intermediate representation of source code, comprising: generating a graph from the intermediate representation, wherein the graph comprises a plurality of nodes; initializing a ready list; adding a start node in the plurality of nodes to the ready list; selecting a node in the ready list; incrementing a visitation counter of the selected node; determining whether the selected node has been visited more than twice; determining whether to apply a forwards optimization on the selected node in response to determining that the selected node has not been visited more than twice; applying the forwards optimization on the selected node in response to determining to apply the forwards optimization on the selected node; recognizing a bounded subgraph based on the selected node; initializing a successor list; adding all successors of the selected node in the bounded subgraph to the successor list; choosing a successor node from the successor list; incrementing a visitation counter of the chosen successor node; determining whether the chosen successor node has been visited more than twice; determining whether to apply the forwards optimization on the chosen successor node in response to determining that the chosen successor node has not been visited twice; applying the forwards optimization on the chosen successor node in response to determining to apply the forwards optimization; determining whether the chosen successor node is an exit node; adding successors of the chosen successor node to the successor list unless it is determined that the chosen successor node is an exit node or it is determined not to apply the forwards optimization on the chosen successor node; and removing the chosen successor node from the successor list.