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

            Bug ID: 86619
           Summary: Missed optimization opportunity with array aliasing
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mickey.veksler at gmail dot com
  Target Milestone: ---

// gcc version 9.0.0 20180720 (experimental) 
// Compiled with -O3

int f(std::array<int, 3> & a, std::array<int, 2> & b)
{
  a[0] = 1;
  b[0] = 2;
  return a[0];
}

Produces:
f(std::array<int, 3ul>&, std::array<int, 2ul>&):
  mov DWORD PTR [rdi], 1
  mov DWORD PTR [rsi], 2
  mov eax, DWORD PTR [rdi]
  ret

Instead of
  mov DWORD PTR [rdi], 1
  mov eax, 1
  mov DWORD PTR [rsi], 2
  ret

But this does not seem to be something that libstdc++ can do anything about.
Consider a simplified array implementation:

template <class T, size_t size>
struct ar
{
  T ar[size];
  T &operator[](size_t offset) { return ar[offset]; }
};

int f1(ar<int, 3> & a, ar<int, 2> & b)
{
  a.ar[0] = 1;
  b.ar[0] = 2;
  return a.ar[0];
// This is perfect:
/*
  mov DWORD PTR [rdi], 1
  mov eax, 1
  mov DWORD PTR [rsi], 2
  ret
*/
}

// BUT:
int f2(ar<int, 3> & a, ar<int, 2> & b)
{
  a[0] = 1;
  b[0] = 2;
  return a[0];
// Too conservative alias analysis 
/*
  mov DWORD PTR [rdi], 1
  mov DWORD PTR [rsi], 2
  mov eax, DWORD PTR [rdi]
*/
}

It seems that by returning a reference, operator[] makes the compiler lose the
fact that a and b can't alias.

I'm not a language lawyer, but the following also seems to be another lost
optimization opportunity for arrays. After all, a and b have different types:
int g(int (&a)[2], int (&b)[3])
{
   a[0] = 1;
   b[0] = 2;
   return a[0];
/*
  mov DWORD PTR [rdi], 1
  mov DWORD PTR [rsi], 2
  mov eax, DWORD PTR [rdi]
  ret
*/
}

Reply via email to