[PATCH] D118143: [GVN] Support loop load PRE through pointer select.

Florian Hahn via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 25 06:53:30 PST 2022


fhahn created this revision.
fhahn added reviewers: reames, spatel, lebedev.ri, mkazantsev.
Herald added a subscriber: hiraditya.
fhahn requested review of this revision.
Herald added a project: LLVM.

This patch extends GVN to support removing re-loads with pointer
phis from loops.

The transformation starts by looking for a load that uses a pointer phi,
which forms a select recurrence and where the other pointer in the
select is also loaded from before the select. Outside the loop, the
pointer is only used by a load that is guaranteed to execute when the
loop exits. See below for an illustration of the pattern.

  loop:
    %sel.phi = phi i32* [ %start, %ph ], [ %sel, %ph ]
    %l = load %ptr
    %l.sel = load %sel.phi
    %sel = select cond, %ptr, %sel.phi
    ...
  
  exit:
    %res = load %sel
    use(%res)

The load of the pointer phi can be replaced by a load of the start value
outside the loop and a new phi/select chain based on the loaded values,
as illustrated below

    %l.start = load %start
  loop:
    sel.phi.prom = phi i32 [ %l.start, %ph ], [ %sel.prom, %ph ]
    %l = load %ptr
    %sel.prom = select cond, %l, %sel.phi.prom
    ...
  exit:
    use(%sel.prom)

Together with a follow-up change that supports chains of (lcssa) phis
outside the loop, this allows vectorizing loops using common libc++
library functions, like std::min_element (https://clang.godbolt.org/z/6czGzzqbs)

  #include <vector>
  #include <algorithm>
  
  int foo(const std::vector<int> &V) {
      return *std::min_element(V.begin(), V.end());
  }

The initial version is intentionally kept relatively simple &
restrictive, only supporting read-only loops where all instructions
are guaranteed to execute and the loop contains only a single block.
Some of those restrictions could be lifted in the future if desired.

The requirement that the result pointer needs to have a load as only
real user outside the loop is not strictly necessary for correctness. On
some architectures/CPUs, replacing the load with a select is always
profitable, even if the pointer select remains. But it may not be
beneficial on all architectures, which is why the initial version is
limited to cases where the pointer select/phi can be removed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118143

Files:
  llvm/include/llvm/Transforms/Scalar/GVN.h
  llvm/lib/Transforms/Scalar/GVN.cpp
  llvm/test/Transforms/GVN/PRE/pre-loop-load-through-select.ll

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D118143.402896.patch
Type: text/x-patch
Size: 13592 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220125/7b7d0068/attachment.bin>


More information about the llvm-commits mailing list