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

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
So we now (GCC 8+ at least) get

  <bb 2> :
  _1 = i_am_pure (5);
  a_8 = _1 * 2;
  i_am_pure (8);
  return a_8;

after early DCE.  This is because we now do FRE before the first DCE which
4.5 didn't have (4.8 has that already).

So fixed for the testcase, not exactly in general though.

__attribute__ ((noinline,noclone))
int
i_am_pure (int a)
{
  if (a>10)
    __builtin_abort();
}

int main()
{
  i_am_pure (8);
  i_am_pure (8);
  return 0;
}

is still not "CSE"d.  The question is whether that happens in practice?

We do actually detect the "redundancy" during propagation but fail to
do anything in elimination - also because we don't properly track
"availability" here.  As a first step one could handle the cases
where the call has the same VUSE, but that only helps for pure calls,
not const ones.

There's also the case of aggregate returns which makes the calls
receive vops:

struct S { int x; };

__attribute__ ((noinline,noclone))
struct S
i_am_pure (int a)
{
  if (a>10)
    __builtin_abort();
}

int main()
{
  struct S x;
  x = i_am_pure (8);
  x = i_am_pure (8);
  return 0;
}

which we do not optimize at all.

int main ()
{
  struct S x;

  <bb 2> [local count: 1073741824]:
  x = i_am_pure (8);
  x = i_am_pure (8);
  x ={v} {CLOBBER};
  return 0;

we could DSE the LHS of the calls it seems.

Reply via email to