HomePhabricator

Revert D71539 "Recommit "[SCEV] Look through single value PHIs.""

Authored by MaskRay on Mon, Sep 21, 5:18 PM.

Description

Revert D71539 "Recommit "[SCEV] Look through single value PHIs.""

This reverts commit 11dccf8d3aa5d55210f8b886fb21926c7a8353ca.

A bootstrapped clang crashes (due to ArrayRef::front called on an empty
ArrayRef) when compiling some files. Very strangely, this only reproduces with
modules.

13 0x0000564d3349e968 llvm::ArrayRef<llvm::BasicBlock*>::front() const /proc/self/cwd/llvm/include/llvm/ADT/ArrayRef.h:160:7
14 0x0000564d3349e896 llvm::LoopBase<llvm::BasicBlock, llvm::Loop>::getHeader() const /proc/self/cwd/llvm/include/llvm/Analysis/LoopInfo.h:104:50
15 0x0000564d3349fd9d llvm::LoopBase<llvm::BasicBlock, llvm::Loop>::getLoopLatch() const /proc/self/cwd/llvm/include/llvm/Analysis/LoopInfoImpl.h:210:11
16 0x0000564d33593c8a llvm::ScalarEvolution::computeBackedgeTakenCount(llvm::Loop const*, bool) /proc/self/cwd/llvm/lib/Analysis/ScalarEvolution.cpp:6933:15
17 0x0000564d33592ebc llvm::ScalarEvolution::getBackedgeTakenInfo(llvm::Loop const*) /proc/self/cwd/llvm/lib/Analysis/ScalarEvolution.cpp:0:30
18 0x0000564d33593a54 llvm::ScalarEvolution::getBackedgeTakenCount(llvm::Loop const*, llvm::ScalarEvolution::ExitCountKind) /proc/self/cwd/llvm/lib/Analysis/ScalarEvolution.cpp:6487:36
19 0x0000564d32be2402 llvm::ScalarEvolution::getConstantMaxBackedgeTakenCount(llvm::Loop const*) /proc/self/cwd/llvm/include/llvm/Analysis/ScalarEvolution.h:768:5
20 0x0000564d33590807 llvm::ScalarEvolution::getRangeRef(llvm::SCEV const*, llvm::ScalarEvolution::RangeSignHint) /proc/self/cwd/llvm/lib/Analysis/ScalarEvolution.cpp:5495:19
21 0x0000564d320abab7 llvm::ScalarEvolution::getSignedRange(llvm::SCEV const*) /proc/self/cwd/llvm/include/llvm/Analysis/ScalarEvolution.h:840:12
22 0x0000564d335a03aa llvm::ScalarEvolution::isKnownPredicateViaConstantRanges(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*) /proc/self/cwd/llvm/lib/Analysis/ScalarEvolution.cpp:9239:60
23 0x0000564d33586a80 llvm::ScalarEvolution::isKnownViaNonRecursiveReasoning(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*) /proc/self/cwd/llvm/lib/Analysis/ScalarEvolution.cpp:10284:60

Event Timeline

fhahn added a subscriber: fhahn.Tue, Sep 22, 6:22 AM

It would be great if you could share more details about how to reproduce the failure. I tried to reproduce with a stage-2 build with -DLLVM_ENABLE_MODULES=On, but check-clang passed. Could you share the file/IR causing the crash?

It would be great if you could share more details about how to reproduce the failure. I tried to reproduce with a stage-2 build with -DLLVM_ENABLE_MODULES=On, but check-clang passed. Could you share the file/IR causing the crash?

It took me many hours to identify the commit. I (or a colleague)'d like to provide a reproduce, but we may be slow.

The issue is with the new pass manager.

$ clang -O2 -std=c++17 -fexperimental-new-pass-manager -c repro.cc
clang: /home/rupprecht/src/llvm-project/llvm/include/llvm/ADT/ArrayRef.h:160: const T &llvm::ArrayRef<llvm::BasicBlock *>::front() const [T = llvm::BasicBlock *]: Assertion `!empty()' failed.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /home/rupprecht/dev/clang -O2 -std=c++17 -fexperimental-new-pass-manager -c repro.cc
1.      <eof> parser at end of file
2.      Optimizer
 #0 0x0000000008e6992a llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/rupprecht/src/llvm-project/llvm/lib/Support/Unix/Signals.inc:563:11
...
#12 0x00000000078b242f llvm::ArrayRef<llvm::BasicBlock*>::front() const /home/rupprecht/src/llvm-project/llvm/include/llvm/ADT/ArrayRef.h:0:7
#13 0x00000000078b2346 llvm::LoopBase<llvm::BasicBlock, llvm::Loop>::getHeader() const /home/rupprecht/src/llvm-project/llvm/include/llvm/Analysis/LoopInfo.h:104:50
#14 0x00000000078b3b80 llvm::LoopBase<llvm::BasicBlock, llvm::Loop>::getLoopLatch() const /home/rupprecht/src/llvm-project/llvm/include/llvm/Analysis/LoopInfoImpl.h:210:11
#15 0x00000000079e093a llvm::ScalarEvolution::computeBackedgeTakenCount(llvm::Loop const*, bool) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:6949:15
#16 0x00000000079dfafc llvm::ScalarEvolution::getBackedgeTakenInfo(llvm::Loop const*) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:0:30
#17 0x00000000079e0704 llvm::ScalarEvolution::getBackedgeTakenCount(llvm::Loop const*, llvm::ScalarEvolution::ExitCountKind) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:6503:36
#18 0x0000000007a0f8d2 llvm::ScalarEvolution::getConstantMaxBackedgeTakenCount(llvm::Loop const*) /home/rupprecht/src/llvm-project/llvm/include/llvm/Analysis/ScalarEvolution.h:768:5
#19 0x00000000079dd367 llvm::ScalarEvolution::getRangeRef(llvm::SCEV const*, llvm::ScalarEvolution::RangeSignHint) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:5491:19
#20 0x0000000007a0fcd7 llvm::ScalarEvolution::getSignedRange(llvm::SCEV const*) /home/rupprecht/src/llvm-project/llvm/include/llvm/Analysis/ScalarEvolution.h:840:12
#21 0x00000000079ed3fa llvm::ScalarEvolution::isKnownPredicateViaConstantRanges(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:9255:60
#22 0x00000000079d3190 llvm::ScalarEvolution::isKnownViaNonRecursiveReasoning(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:10300:60
#23 0x00000000079efa94 llvm::ScalarEvolution::isImpliedViaMerge(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, unsigned int)::$_27::operator()(llvm::SCEV const*, llvm::SCEV const*) const /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:9968:58
#24 0x00000000079ef99e llvm::ScalarEvolution::isImpliedViaMerge(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, unsigned int) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:10013:11
#25 0x00000000079f0762 llvm::ScalarEvolution::isImpliedViaOperations(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, unsigned int) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:10258:7
#26 0x00000000079f0002 llvm::ScalarEvolution::isImpliedCondOperandsHelper(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:10345:7
#27 0x00000000079ee8f6 llvm::ScalarEvolution::isImpliedCondOperands(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*, llvm::SCEV const*) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:10031:58
#28 0x00000000079ee4eb llvm::ScalarEvolution::isImpliedCond(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*, llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:9754:11
#29 0x00000000079edca7 llvm::ScalarEvolution::isImpliedCond(llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*, llvm::Value const*, bool) /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:9615:3
#30 0x00000000079ee6bc llvm::ScalarEvolution::isLoopEntryGuardedByCond(llvm::Loop const*, llvm::CmpInst::Predicate, llvm::SCEV const*, llvm::SCEV const*)::$_24::operator()(llvm::Value const*, bool) const /home/rupprecht/src/llvm-project/llvm/lib/Analysis/ScalarEvolution.cpp:9528:9
...
$ cat repro.cc
template <typename>
struct f;
template <typename>
struct g;
template <typename, int h, int i, int = 0, int = h, int = i>
class j;
template <typename>
class k;
template <typename>
class l;
template <typename, typename, int = 2>
class m;
struct o {
  typedef j<double, 0, 1, 2, 2, -1> p;
};
template <typename q>
struct r {
  typedef k<q> p;
};
struct s {
  typedef r<l<m<int, int> > >::p p;
};
template <typename>
struct t {};
template <typename q>
class ab : public g<q> {
 public:
  enum { ac };
  typedef q u;
};
template <typename q>
class k : public ab<q> {
 public:
  typedef typename f<q>::v v;
  l<q> ad();
};
template <typename q>
struct g {
  q ae();
};
template <int>
class w;
template <typename y, typename z, int af>
struct f<m<y, z, af> > {
  typedef typename y ::v v;
};
template <typename ag, typename ah, int af>
class m : public w<af> {
 public:
  ag ai();
  ah aj();
};
template <int af>
class ak : public r<m<j<double, -1, -1, 2>, j<double, -1, -1, 2>, af> >::p {};
template <int af>
class w : public ak<af> {};
template <typename, typename, typename>
struct al;
template <typename am, typename an, typename ao>
void ap(am aq, an ar, ao as) {
  al<am, an, ao>::at(aq, ar, as);
}
template <typename, typename, typename, int, int, typename, int, bool = false,
          bool = false>
struct au;
template <typename, int, typename, int>
struct av;
class aw {
 public:
  aw(double *, int);
};
template <typename q>
class ax : public r<q>::p {
 public:
  template <typename ay>
  ax(ay az) {
    ap(this->ae(), az, t<typename ay::v>());
  }
};
template <typename ba, int h, int i, int bb, int bc, int bd>
struct f<j<ba, h, i, bb, bc, bd> > {
  typedef ba v;
};
template <typename ba, int h, int i, int bb, int bc, int bd>
class j : public ax<j<ba, h, i, bb, bc, bd> > {
 public:
  template <typename ay>
  j(ay az) : ax<j>(az.ae()) {}
};
template <typename>
class bk;
template <typename bl>
struct f<l<bl> > : f<typename bl::u> {};
template <typename bl>
class l : public bk<bl> {
 public:
  bl bm();
};
template <typename>
class bk : public s::p {};
template <typename v, typename bq, typename br, int bs, int bt, typename bu,
          bool bv, bool bw>
struct au<v, bq, br, bs, bt, bu, 1, bv, bw> {
  void operator()(v *, const br &, bq, bq, bq = 0, bq = 0);
};
template <typename v, typename bq, typename br, int bs, int bt, typename bu,
          bool bv, bool bw>
void au<v, bq, br, bs, bt, bu, 1, bv, bw>::operator()(v *bx, const br &, bq by,
                                                      bq, bq, bq) {
  bq ca;
  int cb = bs;
  while (cb) {
    for (; 0 < by;) {
      for (; cb - 3;) {
        v d(0);
        bx[ca++] = d;
      }
      for (; 4 < cb;) bx[ca++] = 0;
    }
    cb -= 2;
  }
}
template <int, typename cd>
void ce(cd as, long, bool) {
  as(0, 2);
}
template <typename, typename, int = 3>
struct cf;
template <typename cg, typename y, typename z, int ch, typename v>
struct al<cg, m<y, z, ch>, t<v> > {
  static void at(cg aq, m<y, z> ar, t<v>) {
    cf<y, z>::ci(aq, ar.ai(), ar.aj());
  }
};
long cj, ck;
template <typename cl, int cx, typename cm>
struct av<cl, cx, cm, 0> {
  static void at() {
    cl cn, bx;
    aw ai(&cn, 0);
    au<cl, long, aw, 5, 6, double, cx> co;
    co(&bx, ai, ck, cj);
  }
};
template <typename cp>
struct cq {
  cq(j<double, -1, -1, 2>, j<double, -1, -1, 2>, j<double, 0, 1, 2, 2, -1>,
     double, cp);
  void operator()(int, int) { av<double, 1, double, 0>::at(); }
};
template <typename y, typename z>
struct cf<y, z> {
  template <typename am>
  static void ci(am aq, y ai, z aj) {
    cr(aq, ai, aj);
  }
  template <typename cs>
  static void cr(cs aq, y ct, z cu) {
    y ai(ct), aj(cu);
    typename m<y, z>::v cv;
    void xy();
    ce<0>(cq(ai, aj, aq, cv, xy), 0, cs::ac);
  }
};
template <typename cg, typename bl>
struct al<cg, l<bl>, t<typename bl::v> > {
  static void at(cg, l<bl> ar, t<typename bl::v>) { o::p(ar.bm()); }
};
void cw() { j<double, 1, 1> x = x.ad(); }

The issue is with the new pass manager.

Ah that was probably why I didn't manage to reproduce it. Thank you very much for the reproducer below!

mafft regressed quite a lot (compile time) so it would be good to handle possibly weird cases well - some limit/threshold/bailout?