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_r | 0.74% |
502.gcc_r | 0.26% |
505.mcf_r | 0.82% |
520.omnetpp_r | -0.29% |
523.xalancbmk_r | 0.86% |
525.x264_r | 8.33% |
531.deepsjeng_r | 0.00% |
541.leela_r | -0.71% |
548.exchange2_r | 0.00% |
557.xz_r | 0.75% |