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

            Bug ID: 122734
           Summary: Hoist loop invariant in presence of exception handling
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: fxue at os dot amperecomputing.com
  Target Milestone: ---

Different from vector::operator[](), vector::at() has an extra out-of-bound
check over index when extracting element, and needs to calculate size of the
vector from its start and end addresses, which seem to be loop invariant.

int foo(const std::vector<int> &array, const std::vector<int> &index)
{
    int sum = 0;
    for (size_t i = 0; i < index.size(); i++)
        sum += array.at(index[i]);
    return sum;
}

The call to no-return exception handling function does have side effect, but it
might be still legal to hoist these two addresses outside of the loop. Or there
is special point I missed?

int foo (const struct vector & array, const struct vector & index)
{
  ptrdiff_t __dif;
  ptrdiff_t __dif;
  size_t i;
  int sum;
  int _1;
  long unsigned int _2;
  int * _7;
  int * _8;
  value_type _10;
  long int _13;
  long unsigned int _15;
  long unsigned int _16;
  const value_type & _17;
  long unsigned int _24;
  int * _26;
  int * _29;
  long int _30;

  <bb 2> [local count: 40126338]:
  _26 = index_6(D)->D.25633._M_impl.D.24944._M_finish;
  _29 = index_6(D)->D.25633._M_impl.D.24944._M_start;
  _30 = _26 - _29;
  __dif_31 = _30 /[ex] 4;
  _24 = (long unsigned int) __dif_31;
  goto <bb 6>; [100.00%]

  <bb 3> [local count: 1034029095]:
  _7 = array_9(D)->D.25633._M_impl.D.24944._M_finish;  // Could be hoisted?
  _8 = array_9(D)->D.25633._M_impl.D.24944._M_start;   // Could be hoisted?
  _13 = _7 - _8;
  _1 = MEM[(const value_type &)_29 + i_33 * 4];
  _2 = (long unsigned int) _1;
  __dif_14 = _13 /[ex] 4;
  _15 = (long unsigned int) __dif_14;
  if (_2 >= _15)
    goto <bb 4>; [0.00%]
  else
    goto <bb 5>; [100.00%]

  <bb 4> [count: 0]:
  std::__throw_out_of_range_fmt ("vector::_M_range_check: __n (which is %zu) >=
this->size() (which is %zu)", _2, _15);

  <bb 5> [local count: 1033615486]:
  _16 = _1 w* 4;
  _17 = _8 + _16;
  _10 = *_17;
  sum_11 = _10 + sum_32;
  i_12 = i_33 + 1;

  <bb 6> [local count: 1073312328]:
  # sum_32 = PHI <sum_11(5), 0(2)>
  # i_33 = PHI <i_12(5), 0(2)>
  if (_24 != i_33)
    goto <bb 3>; [96.34%]
  else
    goto <bb 7>; [3.66%]

  <bb 7> [local count: 39283232]:
  return sum_32;

}

Reply via email to