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 */ }