Visual Studio 2010 (Express) does, in the simple cases I've tested at least. Anyone to test gcc?
I've tested the following:
1. Passing only i
:
int vars[] = {1,2,3,12,3,23,1,213,231,1,21,12,213,21321,213,123213,213123};
int ok1(const int i){
return sqrtl(vars[i]);
}
int ok2(const int & i){
return sqrtl(vars[i]);
}
void main() {
int i;
std::cin >> i;
//i = ok1(i);
i = ok2(i);
std::cout << i;
}
The ASM:
i = ok1(i);
000D1014 mov ecx,dword ptr [i]
000D1017 fild dword ptr vars (0D3018h)[ecx*4]
000D101E call _CIsqrt (0D1830h)
000D1023 call _ftol2_sse (0D1840h)
i = ok2(i);
013A1014 mov ecx,dword ptr [i]
013A1017 fild dword ptr vars (13A3018h)[ecx*4]
013A101E call _CIsqrt (13A1830h)
013A1023 call _ftol2_sse (13A1840h)
Well, the ASMs are identical, no doubt the optimization was performed.
2. Passing i
and &i
:
Let's consider @newacct 's anser here.
int vars[] = {1,2,3,12,3,23,1,213,231,1,21,12,213,21321,213,123213,213123};
int ok1(const int i, int * pi) {
*pi = 2;
return sqrtl(vars[i]);
}
int ok2(const int & i, int * pi) {
*pi = 2;
return sqrtl(vars[i]);
}
void main() {
int i;
int * pi = &i;
std::cin >> i;
i = ok1(i, pi);
//i = ok2(i, pi);
std::cout << i;
}
The ASM:
i = ok1(i, pi);
00891014 mov ecx,dword ptr [i]
00891017 fild dword ptr vars (893018h)[ecx*4] // access vars[i]
0089101E call _CIsqrt (891830h)
00891023 call _ftol2_sse (891840h)
i = ok2(i, pi);
011B1014 fild dword ptr [vars+8 (11B3020h)] // access vars[2]
011B101A call _CIsqrt (11B1830h)
011B101F call _ftol2_sse (11B1840h)
In ok1
I can't see it writing 2 into pi
. Probably it understands that the memory location will be overwritten by the result of the function anyway, so the writing is useless.
With ok2
, the compiler is as smart-ass as I expected. It understands that i
and pi
point to the same place, so it uses a hardcoded 2
directly.
Notes:
- I've compiled twice for both test, once uncommenting only
ok1
, once uncommenting only ok2
. Compiling both at the same time leads to more complex optimizations between the two functions, which end up all inlined and mixed up
- I've added a lookup in the array
vars
because simple calls to sqrtl
were simplified into basic ADD- and MUL-like operations without the actual call
- Compiled in Release
- Yielded the expected results, of course