I use SCEVExpander and IRBuilder to generate some code and I frequently end-up breaking dominance because the SCEVExpander insertion point and the IRBuilder insertion point do not advance in synchrony.
Ideally, I could build a SCEVExpander based on an existing IRBuilder (so that they move each other). Or even better, SCEVExpander inherit from IRBuilder and basically extend it with SCEV expander capabilities (then I don’t need to use a separate IRBuilder).
Or maybe I am using them wrong? What is the intended way to use those?
Sorry I missed this -- I was on vacation when you sent this.
SCEVExpander already has an IRBuilder in it but AFAICT it isn't
exposed as a public interface. I'd be fine if you wanted to expose a
public `GetIRBuilder()` accessor that let a SCEVExpander client use
the same IRBuilder as SCEVExpander.
exposing the internal IRBuilder to users of SCEVExpander violates information hiding, and encourages the tight coupling that makes code bases such as Polly so hard to maintain. SCEVExpander::expandCodeFor returns a Value that (if it’s an instruction) can be used to update the insert point of the client’s IRBuilder. Is that not enough?
No hidden state, no hidden state transitions, so it’s locally clear to a reader how the IRBuilder moves.
Alternatively, expose a SCEVExpander::getInsertPoint? This would proxy the underlying IRbuilder, with no real state sharing, other than the current insert point.
This will be less ugly than recieving the expanded SCEV value, casting to an instruction, and feeding this to the IRBuilder.
SCEVExpander::expandCodeFor takes the insert point as an argument, so that’s entirely client-controlled. That insert point also never changes. So there is no need to ever query it from the expander.
On the other hand, if you wanted to pass around an expander object to expand multiple SCEVs, I think it’s much clearer to pass the insert point instead. Again, no hidden state!