The DAG combiner previously would not produce a pre-indexed store if the base pointer was a predecessor of the value being stored, so to prevent a cycle in the DAG. However, we could produce a pre-inc store if the store is final use of base pointer.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
lib/CodeGen/SelectionDAG/DAGCombiner.cpp | ||
---|---|---|
12644 ↗ | (On Diff #181777) | This needs a better comment explaining exactly what cases this is rejecting, and which cases it is accepting. (I'm not sure I follow the logic here. What cases need to be rejected for correctness? Are there cases which could be transformed, but shouldn't be transformed to avoid register copies?) I'm a bit concerned about performance here. isPredecessorOf is expensive. |
Hi Eli,
I've added more tests and a few comments.
Yes, predecessor checks are expensive, how about adding an upper limit of uses and/or performing this check under a target flag?
hasPredecessorHelper supports a limit, that would be fine, probably. (The check is probably fast enough in practice in common cases, so it should be fine as long as it doesn't explode quadratically in extreme cases.)
lib/CodeGen/SelectionDAG/DAGCombiner.cpp | ||
---|---|---|
12664 ↗ | (On Diff #182029) | Could you clarify what "last use" means? It's not obvious when you're dealing with a DAG. I guess it means the store must be scheduled after every other use of BasePtr? |
12666 ↗ | (On Diff #182029) | I think this could still use a bit more clarification... There are two different uses of ReplaceAllUsesOfValueWith which could cause a cycle related to stored value: the replacement of Ptr with the pre-indexed result, and the rewritten arithmetic relative to BasePtr in OtherUses. Are you trying to prevent both those cycles? Could we be more aggressive if we separated those checks? |
12669 ↗ | (On Diff #182029) | The equality check here seems suspect; what if Val is a use of one of the direct users of BasePtr? |
lib/CodeGen/SelectionDAG/DAGCombiner.cpp | ||
---|---|---|
12664 ↗ | (On Diff #182029) | Yes, scheduled last is what I mean. |
12666 ↗ | (On Diff #182029) | So yes, I am trying to make sure that Ptr can be replaced legally and I have assumed that by allowing the last scheduled user to be a pre-indexed store, we don't have to worry about OtherUses. Though I am now confused after re-reading statement (3) from above which appears to directly contradict my thoughts. |
12669 ↗ | (On Diff #182029) | Hmm. Would it be valid to create an ADD/SUB node and check whether it becomes a predecessor of Val...? |
I just did a very brief experiment, and just checking if (Val == BasePtr || Val == Ptr || Ptr->isPredecessorOf(Val.getNode())) seems to do the right thing without any additional checks. Is all this extra code really necessary?
lib/CodeGen/SelectionDAG/DAGCombiner.cpp | ||
---|---|---|
12666 ↗ | (On Diff #182029) | There's a hasPredecessorHelper call later; I think that handles cases like (3). |
12669 ↗ | (On Diff #182029) | ADD/SUB of what, exactly? More generally, we want to avoid performing predecessor checking more than once, since it's expensive. |
I just did a very brief experiment, and just checking if (Val == BasePtr || Val == Ptr || Ptr->isPredecessorOf(Val.getNode())) seems to do the right thing without any additional checks.
Err, nevermind, that doesn't do anything; please ignore.
Hmm... actually, I'm just confusing myself. My suggestion appears to fix your pre_inc_str_multi without causing any regressions (although I haven't run anything outside the regression tests). I'm assuming that's the primary case you're interested in?