[Bug middle-end/86909] Missing common subexpression elimination for types other than int

2018-08-21 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86909

Richard Biener  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2018-08-21
 CC||rguenth at gcc dot gnu.org
 Ever confirmed|0   |1

--- Comment #2 from Richard Biener  ---
Similar "bad" code for using 'unsigned int'.  With 'int' the reassoc
pass combines the repetitive checks to

   [local count: 840525100]:
  _8 = (unsigned int) _9;
  _15 = _8 <= 7;
  if (_15 != 0)
goto ; [50.00%]
  else
goto ; [50.00%]

   [local count: 532808861]:
  iftmp.1_6 = &in_3(D)->a;

   [local count: 1073741824]:
  # _1 = PHI 
  return _1;

with char or unsigned int it fails to do that which is because we are
testing different vars:


   [local count: 840525100]:
  i_36 = (int) _9;
  if (i_36 == 0)
goto ; [50.00%]
  else
goto ; [50.00%]

   [local count: 420262550]:
  if (_9 == 0)
goto ; [71.00%]
  else
goto ; [29.00%]

   [local count: 532808861]:
  iftmp.1_6 = &in_3(D)->a;
  goto ; [100.00%]

   [local count: 303654184]:
  if (i_36 == 1)
goto ; [67.33%]
  else
goto ; [32.67%]

   [local count: 182536110]:
  if (_9 == 1)
goto ; [43.66%]
  else
goto ; [56.34%]

same for char.  We're somehow not seeing the equivalence

  _9 = MEM[(unsigned int *)in_3(D) + 4B];
  i_36 = (int) _9;

when we know either is of a specific value.  Jump threading and/or CSE
should do this job.  Btw, the initial code is quite convoluted and needs
lot of threading to get to the above "nice" state.  EVRP figures out
the equivalencies but is confused by the initial

   :
  _24 = MEM[(unsigned int *)in_5(D) + 4B];
  if (_24 != 4294967295)
goto ; [78.28%]
  else
goto ; [21.72%]

   :
  iftmp.0_20 = (long long unsigned int) _24;

   :
  # iftmp.0_18 = PHI <18446744073709551615(2), iftmp.0_20(3)>
  i_7 = (int) iftmp.0_18;

which has to be jump-threaded away first with later

   :
  if (_24 != 4294967295)
goto ; [78.28%]
  else
goto ; [21.72%]

   :
  if (_24 == 6)
goto ; [55.78%]
  else
goto ; [44.22%]

   :

or alternatively the initial sequence needs to be phi-opted earlier.

In the end it appears to be a pass-ordering issue.

[Bug middle-end/86909] Missing common subexpression elimination for types other than int

2018-08-10 Thread antoshkka at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86909

--- Comment #1 from Antony Polukhin  ---
Another std::variant related example where GCC fails to eliminate
subexpressions and generates 6 times bigger assembly:

using size_t = unsigned long long;

struct A {} a;
static const size_t variant_npos = -1;

struct variant {
using __index_type = unsigned char; //   O_O !!
__index_type _M_index;

size_t index() const noexcept {
return (_M_index == __index_type(variant_npos) ? variant_npos :
_M_index);
}
};

template
static A* get_if(variant* __ptr) noexcept {
return (__ptr->index() == _Np ? &a : nullptr);
}

A* foo(int i, variant& in) {
if (i==0) return get_if<0>(&in);
if (i==1) return get_if<1>(&in);
if (i==2) return get_if<2>(&in);
if (i==3) return get_if<3>(&in);
if (i==4) return get_if<4>(&in);
if (i==5) return get_if<5>(&in);
if (i==6) return get_if<6>(&in);

return get_if<7>(&in);
}