https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93891

--- Comment #1 from Marc Glisse <glisse at gcc dot gnu.org> ---
On the original code (I can attach it if needed, but it is large, it is
resizing a std::vector with reference-counted elements) FRE3 fails to simplify

  MEM[(struct Handle_for *)__cur_16] ={v} {CLOBBER};
  _17 = MEM[(const struct Handle_for &)__first_15].ptr_;
  MEM[(struct Handle_for *)__cur_16].ptr_ = _17;
  _18 = *_17.count;
  _19 = _18 + 1;
  *_17.count = _19;
  _20 = &__first_15->D.202020;
  _31 = MEM[(struct Handle_for *)__first_15].ptr_;

while FRE4 sees

  MEM[(struct Handle_for *)__cur_3] ={v} {CLOBBER};
  _17 = MEM[base: __first_20, offset: 0B];
  MEM[base: __cur_3, offset: 0B] = _17;
  _18 = *_17.count;
  _19 = _18 + 1;
  *_17.count = _19;
  _31 = MEM[base: __first_20, offset: 0B];

and replaces _31 with _17. That's confusing, since the main difference between
the 2 is removing a statement without VOP.

(optimizing in FRE4 is way too late in this case, I want the simplified version
before ldist, and it still requires at least DSE, some pass detecting a
self-assignment, and DCE before that)

Here is another simplified version of the testcase, but you need to compile it
with -fno-early-inlining to see the issue:

void g();
struct A {
  int*p;
  A(A const&a)noexcept:p(a.p){if(*p<=0)__builtin_unreachable();++*p;}
  ~A(){if(--*p==0)g();}
};

#include <vector>

void f(std::vector<A>&v){
  v.reserve(1<<20);
}

At the end of gimple, we still have

  _92 = *_91;
  *_91 = _92;

in the main loop, while I would want that gone before ldist.

Reply via email to