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