Original Post
I'm trying to determine patterns for optimizing code (and by this, I mean that the code is optimizing its output). To give an example of my problem, let's consider a small code generator, which provides a simple interface for writing code. In particular, there is a "for loop generator", with interface:
public Statement GenerateForLoop(
Variable x, Statement inner, Expression min, Expression max) { ... }
Given a variable name x, a statement inner and two expressions min and max, generates the code: for(x = min; x < max; ++x) inner; Now, there is a large range of optimizations that are possible: - If I determine that min > max is always true before the loop starts, I can generate a { x = min; } instead of the loop.
- If I determine that inner contains no side-effects, I can generate an { x = max; } instead of the loop.
- If I determine that min + 1 == max, the loop becomes { x = min; inner; ++x; }
- If I determine that max has no side-effects but is a lengthy computation, the loop becomes int m = max; for(x = min; x < m; ++x) inner;
- I have a large number of optimization opportunities, both present and future, and I need to be able to add them in an elegant and efficient way when the time comes—I don't want to add them from the start just in case they aren't necessary.
- These optimizations rely on properties of the manipulated objects (side-effects, inequality and equaliy relationships, etc) that are not part of the user-side interface of my objects (they don't need it), but I need a way to transmit these properties simply from object to object, and also to add them when I start needing them.
- These optimizations should naturally cascade: in the above example, the loop could be collapsed to { x = max; }. Then, if x is not used anywhere outside the loop, there's no need for that, so the statement is collapsed to {}. But then, if max was a variable set as the sole side-effect of a loop right before that, then the entire loop loses its side-effect and becomes { x = max; } as well, and so on.