This is an archive of the discontinued LLVM Phabricator instance.

[GVN] Simple GVN hoist - loads and stores
Needs RevisionPublic

Authored by chill on Sep 30 2021, 6:17 AM.

Details

Summary

This is the second part of the Simple GVNHoist, which deals with load and store
instructions (first part is https://reviews.llvm.org/D110817).

This part makes use of MemorySSA to incorporate the incoming memory state into
the value numbers for the load and store instructions as well as to determine
memory dependencies.

If MemorySSA is not available, the value numbers for loads and stores are
unique, as before.

If MemorySSA is available, additional numbers are added to varargs of the
GVN::Expression.

If the incoming memory state is:

  • LiveOnEntry, do nothing.
  • a MemoryPhi, add <0, ID> where ID is the unique identifier of the MemoryPhi.
  • a MemoryDef, add VN, where VN is the value number of the memory setting instruction.

Then the algorithm is essentially the same as for the scalars with a couple of
extra tweaks:

  • when we pair instructions, we don't pair (therefore won't hoist/merge) volatile with non-volatile instructions or instructions with different atomic ordering.
  • when hoisting, in addition of operands, for loads and store we try to hoist the memory dependencies too. Same principles as for operands apply - we only ever hoist pairs of instructions, starting from the memory dependencies of the then-instruction and just checking the memory dependencies of the else-instruction.

With both patches applied, the preliminary SPEC results look fairly decent (positive/higher is better, Neoverse N1, -O3 -flto):

500.perlbench_r0.74%
502.gcc_r0.26%
505.mcf_r0.82%
520.omnetpp_r-0.29%
523.xalancbmk_r0.86%
525.x264_r8.33%
531.deepsjeng_r0.00%
541.leela_r-0.71%
548.exchange2_r0.00%
557.xz_r0.75%

Diff Detail

Event Timeline

chill created this revision.Sep 30 2021, 6:17 AM
chill requested review of this revision.Sep 30 2021, 6:17 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 30 2021, 6:17 AM
fhahn added a subscriber: fhahn.Sep 30 2021, 10:12 AM
mkazantsev requested changes to this revision.Oct 7 2021, 10:24 PM

I'll mark it "request changes" until the underlyingpatch has merged just to reduce my review list. Feel free to request review again when it lands.

This revision now requires changes to proceed.Oct 7 2021, 10:24 PM
chill updated this revision to Diff 381934.Oct 25 2021, 4:25 AM

Passing-by +1 to this approach.
I would like to remove load/store special-handling from simplifycfg's,
because that would allow to implement a more powerful phi-to-select bb merging fold.

(Please don't mind -1 for me as it was just for sorting out review list purposes)

The general question I have - we are planning to transit from GVN to NewGVN, or at least so I heard. Is NewGVN already able to handle that? Is there a further plan to port these changes there?

(Please don't mind -1 for me as it was just for sorting out review list purposes)

The general question I have - we are planning to transit from GVN to NewGVN, or at least so I heard. Is NewGVN already able to handle that? Is there a further plan to port these changes there?

I believe transitioning to NewGVN is still not definitive, there are a lot of things it doesn't support yet and it has bugs.

asbirlea requested changes to this revision.Nov 8 2021, 2:07 PM

The request changes is for the use of getID() in MemorySSA(). Other optimizations should never rely on the value of the IDs assigned by MemorySSA.

I think the idea of implementing GVN Hoist is good, but there are other broader issues that concern me.
So, stepping back, I'd like to raise the question of how this change is going to be used if implemented. In the current default pipeline MemorySSA is not available where GVN is added. This is forcing the computation of MemorySSA before GVN.

Having MemorySSA computed before GVN may be good in the LTO pipeline (GVN already preserves the analysis), as the following passes require it (MemCpyOpt and DSE), but in the function simplification pipeline we'd end up with GVN computing, using and preserving two analysis (MemorySSA and MemDepAnalysis) with overlapping goals.

The status for switching to NewGVN is uncertain at this point, but porting GVN to switch over from MemDepAnalysis to MemorySSA may be an option, at least in the interim. This will lift the issue of having two analysis and also provide the availability of MemorySSA here. Is this something you'd be interested in exploring?

This revision now requires changes to proceed.Nov 8 2021, 2:07 PM
chill added a comment.Nov 8 2021, 3:57 PM

The request changes is for the use of getID() in MemorySSA(). Other optimizations should never rely on the value of the IDs assigned by MemorySSA.

The getID() was already a public method in derived classes and the ID is used according to its description "Guaranteed unique among MemoryAccesses".

How about value numbering the BasicBlock that corresponds to a MemoryPhi ? It's a little bit of overhead and not strictly necessary if we have an ID readily available, but, fair enough, I don't mind doing it this way.

The status for switching to NewGVN is uncertain at this point, but porting GVN to switch over from MemDepAnalysis to MemorySSA may be an option, at least in the interim. This will lift the issue of having two analysis and also provide the availability of MemorySSA here. Is this something you'd be interested in exploring?

It's certainly something we need to discuss first.

The request changes is for the use of getID() in MemorySSA(). Other optimizations should never rely on the value of the IDs assigned by MemorySSA.

The getID() was already a public method in derived classes and the ID is used according to its description "Guaranteed unique among MemoryAccesses".

How about value numbering the BasicBlock that corresponds to a MemoryPhi ? It's a little bit of overhead and not strictly necessary if we have an ID readily available, but, fair enough, I don't mind doing it this way.

The problem I have in mind is that the ID (and MemoryPhi ptr) may no longer exist during the transformation. The hoistPair is recursive, and it calls both the lookup (which adds the ID) and the moveToPlace in the MSSAUpdater; the moveToPlace can cleanup redundant MemoryPhis after a move and also add new phis; it's possible for a block to be revisited in GVN, and no longer have a MemoryPho; it's also possible it still has a MemoryPhi but with a different ID, if a move cleaned it up but then needed to readd it.
Relying on the BB ptr for example makes sense, that won't move from under your feet.

The status for switching to NewGVN is uncertain at this point, but porting GVN to switch over from MemDepAnalysis to MemorySSA may be an option, at least in the interim. This will lift the issue of having two analysis and also provide the availability of MemorySSA here. Is this something you'd be interested in exploring?

It's certainly something we need to discuss first.

Agreed, this is a big topic.

chill added a comment.Dec 6 2021, 8:25 AM

Relying on the BB ptr for example makes sense, that won't move from under your feet.

All right, I used the basic block in the draft https://reviews.llvm.org/D115160 . In time, I'm going to rebase all these patches on top of the MemorySSA-for-GVN conversion.