[PATCH] D19338: New code hoisting pass based on GVN (optimistic approach)

Sebastian Pop via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 20 12:25:06 PDT 2016


sebpop created this revision.
sebpop added reviewers: dberlin, chandlerc.
sebpop added subscribers: llvm-commits, hiraditya, flyingforyou.
sebpop set the repository for this revision to rL LLVM.
Herald added a subscriber: joker.eph.

This pass hoists duplicated computations in the program. The primary goal of
gvn-hoist is to reduce the size of functions before inline heuristics to reduce
the total cost of function inlining. This implementation is the optimistic approach
that Danny asked us to implement: we start from the set of all known equivalent
computations, and we discard unsafe hoisting situations.

Here is the algorithm Danny asked us to work on last time:

  Make a multimap from VN to each expression with that VN (VNTable is not currently this) over the entire program.
  For each VN in the table:
   if (size (expressions with a given VN) > 1):
     For each block in domtree in DFS order:
         For each expression, if DFSin/DFSOut(expression->parent) within range of DFSin/DFSOut(block), push(possiblehoistlist (a list), expression (current expression), block (insertion point))
            If you have 2 or more things on possiblehoistlist, calculate availability of operands for each expression in block
                (you can cache the highest point you can move them to for later to checking again and again.
                 Since you are using dominance, you know they can only be hoisted to blocks dominated by the highest point you can hoist to).
            If 2 or more things are still available, hoist
  Note you can also likely skip any domtree block that does not have two or more children, i just haven't proven it to myself yet.

Because we "value number everything up front":
- we VN things that do not matter for hoisting,
- we VN all computations dependent on loads and that would forbid
  hoisting the whole dependence chain as each load gets a different VN (in the
  current GVN.cpp implementation.) The temporary solution is to hoist twice and
  invalidate the VN table in between.

The harder parts compared to the previous patch in http://reviews.llvm.org/D18798
are the detection of safety properties of hoisting:
- no side effects on all paths between insert point and the original location of
  all hoistable expressions: we use a traversal of the inverse CFG from the
  expression to be hoisted to the insertion point to gather all the BBs on the
  execution paths that we have to check for side-effects.
- to make hoisting efficient for scalars (and safe for hoisting load
  expressions) we need to prove that from the insertion point to the end of the
  function the expressions are needed on all paths.

There are still a few improvements to be implemented:
- using memory SSA as a minimal data dependence analysis
  to improve the accuracy of the side effects analysis in loops.
- computing hoisting subsets: for the moment we try to hoist all
  expressions with the same VN without checking whether
  a subset would be safe to hoist. 

Passes llvm regression test, test-suite, and SPEC Cpu2006.
Over the c/c++ SPEC 2006 benchmarks the GVN-hoisting pass removes 55012 instructions.
    - Without the patch:
    Number of call sites deleted, not inlined: 20394
    Number of functions deleted because all callers found: 70497
    Number of functions inlined: 182119
    Number of allocas merged together: 225
    Number of caller-callers analyzed: 200361
    Number of call sites analyzed: 445806
    
    - With the patch:
    Number of call sites deleted, not inlined: 20412
    Number of functions deleted because all callers found: 70495
    Number of functions inlined: 182122
    Number of allocas merged together: 225
    Number of caller-callers analyzed: 200360
    Number of call sites analyzed: 445624
    Number of hoisted instructions: 5435
    Number of instructions removed: 55012

Spec2006 results are quite noisy:
(positive is an increase of the spec score in percent)
    400.perlbench: 0
    401.bzip2: 0
    403.gcc: -2.00
    429.mcf: -4.00
    445.gobmk: 0
    456.hmmer: 0
    458.sjeng: 0
    462.libquantum: -2.00
    464.h264ref: 4.00
    471.omnetpp: -1.00
    473.astar: -1.00
    433.milc: 15.00
    444.namd: 0
    447.dealII: 0
    450.soplex: 0
    453.povray: 0
    470.lbm: 0
    482.sphinx3: 1.00

Pass written by:
    Sebastian Pop
    Aditya Kumar
    Xiaoyu Hu
    Brian Rzycki
    Daniel Berlin


Repository:
  rL LLVM

http://reviews.llvm.org/D19338

Files:
  llvm/include/llvm/InitializePasses.h
  llvm/include/llvm/LinkAllPasses.h
  llvm/include/llvm/Transforms/Scalar.h
  llvm/include/llvm/Transforms/Scalar/GVN.h
  llvm/lib/Passes/PassRegistry.def
  llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
  llvm/lib/Transforms/Scalar/CMakeLists.txt
  llvm/lib/Transforms/Scalar/GVNHoist.cpp
  llvm/lib/Transforms/Scalar/Scalar.cpp
  llvm/test/Transforms/GVN/hoist.ll

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D19338.54398.patch
Type: text/x-patch
Size: 41681 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160420/daf38a1b/attachment.bin>


More information about the llvm-commits mailing list