[PATCH] D142292: [SCEV] Introduce `SCEVSelectExpr`

Roman Lebedev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 21 16:53:52 PST 2023


lebedev.ri created this revision.
lebedev.ri added reviewers: fhahn, mkazantsev, efriedma, reames, nikic.
lebedev.ri added a project: LLVM.
Herald added a reviewer: bollu.
Herald added subscribers: nlopes, jeroen.dobbelaere, StephenFan, javed.absar, kosarev, hiraditya.
Herald added a project: All.
lebedev.ri requested review of this revision.
Herald added a subscriber: pcwang-thead.

I believe, the time has come.

First, let's look at an example:

  #include <algorithm>
  
  void foo(int* data, int width, short*LUT) {
      for(int i = 0; i != width; ++i) {
          int& val = data[i];
          val = LUT[std::min(std::max(val, 0), 255)];
      }
  }

It's obvious to vectorize, and indeed that does happen: https://godbolt.org/z/91eKoaM5T

But what if we change the element type of `LUT`?

  #include <algorithm>
  
  void foo(int* data, int width, int*LUT) {
      for(int i = 0; i != width; ++i) {
          int& val = data[i];
          val = LUT[std::min(std::max(val, 0), 255)];
      }
  }

https://godbolt.org/z/GeGKh3nz4 <- oops.

The original example vectorized because of TBAA.
Indeed, we don't do a great job of modelling the `select`'s,
so no wonder we failed.

LoopVectorizer has this interesting logic:

  // Walk back through the IR for a pointer, looking for a select like the
  // following:
  //
  //  %offset = select i1 %cmp, i64 %a, i64 %b
  //  %addr = getelementptr double, double* %base, i64 %offset
  //  %ld = load double, double* %addr, align 8
  //
  // We won't be able to form a single SCEVAddRecExpr from this since the
  // address for each loop iteration depends on %cmp. We could potentially
  // produce multiple valid SCEVAddRecExprs, though, and check all of them for
  // memory safety/aliasing if needed.
  //
  // If we encounter some IR we don't yet handle, or something obviously fine
  // like a constant, then we just add the SCEV for that term to the list passed
  // in by the caller. If we have a node that may potentially yield a valid
  // SCEVAddRecExpr then we decompose it into parts and build the SCEV terms
  // ourselves before adding to the list.
  static void findForkedSCEVs(
      ScalarEvolution *SE, const Loop *L, Value *Ptr,
      SmallVectorImpl<PointerIntPair<const SCEV *, 1, bool>> &ScevList,
      unsigned Depth) 

... that tries to deal with exactly this case, but it does so
by effectively inventing it's own representation, 
which forces it to re-implement handling for everything that SCEV already handles,
and it is incomplete.
(We have something similar in SCEV already, `getRangeViaFactoring()`)

I would like to teach SCEV about `select`'s, and then replace that code
with a straight-forward, complete, SCEV-based implementation.

The (only?) regression i see in the diffs is the fact that i didn't add recursive predicate reasoning for selects.

(I'm going to peel off some more changes from here to the diff even smaller.)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142292

Files:
  llvm/include/llvm/Analysis/ScalarEvolution.h
  llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
  llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
  llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
  llvm/lib/Analysis/ScalarEvolution.cpp
  llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
  llvm/test/Analysis/ScalarEvolution/becount-invalidation.ll
  llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
  llvm/test/Analysis/ScalarEvolution/exit-count-select.ll
  llvm/test/Analysis/ScalarEvolution/ext_min_max.ll
  llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
  llvm/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll
  llvm/test/Analysis/ScalarEvolution/logical-operations.ll
  llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll
  llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
  llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
  llvm/test/Analysis/ScalarEvolution/nsw.ll
  llvm/test/Analysis/ScalarEvolution/pointer-rounding.ll
  llvm/test/Analysis/ScalarEvolution/pointer-select.ll
  llvm/test/Analysis/ScalarEvolution/sext-to-zext.ll
  llvm/test/Analysis/ScalarEvolution/shift-recurrences.ll
  llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll
  llvm/test/Analysis/ScalarEvolution/trip-count-minmax.ll
  llvm/test/Analysis/ScalarEvolution/trivial-phis.ll
  llvm/test/Analysis/StackSafetyAnalysis/local.ll
  llvm/test/Analysis/StackSafetyAnalysis/memintrin.ll
  llvm/test/Transforms/IRCE/decrementing-loop.ll
  llvm/test/Transforms/IndVarSimplify/lftr-pr20680.ll
  llvm/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll
  llvm/test/Transforms/LoopVectorize/single-value-blend-phis.ll
  llvm/test/Transforms/SimpleLoopUnswitch/update-scev.ll
  llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
  polly/include/polly/Support/SCEVAffinator.h
  polly/lib/Support/SCEVAffinator.cpp
  polly/lib/Support/SCEVValidator.cpp
  polly/lib/Support/ScopHelper.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D142292.491109.patch
Type: text/x-patch
Size: 163681 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230122/fcd1b79a/attachment-0001.bin>


More information about the llvm-commits mailing list