Reputation: 4344
Say I had code that looked like this:
string foo = "bar";
for(int i = 0; i < foo.length(); i++){
//some code that does not modify the length of foo
}
Would the GNU compiler be smart enough to realize that the length of foo
does not change over the course of this loop and replace the foo.length()
call with the proper value? Or would foo.length()
be called for every i
comparison?
Upvotes: 3
Views: 618
Reputation: 2413
Since both Mysticial and Kerrek rightfully suggest peeking at the generated assembly, here's an example:
#include <string>
using namespace std;
int does_clang_love_me(string foo) {
int j = 0;
for (int i = 0; i < foo.length(); i++) {
j++;
}
return j;
}
I saved the above code in test.cpp and compiled it like this:
$ clang++ -o test.o -Os -c test.cpp
The -Os switch tells clang to try to optimize for the smallest code size. GCC has a corresponding switch you can use. To see the assembly, I hit the resulting object file with otool, as I happen to be using a mac at the moment. Other platforms have similar tools.
$ otool -tv test.o
test.o:
(__TEXT,__text) section
__Z16does_clang_love_meSs:
0000000000000000 pushq %rbp
0000000000000001 movq %rsp,%rbp
0000000000000004 movq (%rdi),%rax
0000000000000007 movq 0xe8(%rax),%rcx
000000000000000b xorl %eax,%eax
000000000000000d testq %rcx,%rcx
0000000000000010 je 0x0000001e
0000000000000012 cmpq $0x01,%rcx
0000000000000016 movl $0x00000001,%eax
000000000000001b cmoval %ecx,%eax
000000000000001e popq %rbp
000000000000001f ret
It's like Mysticial said; it's just a variable access.
Upvotes: 7
Reputation: 471209
The only way to know for sure is to try it and take a look at the assembly.
My guess is that if the call to length()
is inlined, then Loop Invariant Code Motion will hoist the internals of length()
out of the loop and replace it with a single variable.
As a second thought, this might even be moot. The size of a string is probably just a simple field in the string
class - which is on the stack. So just inlining the call to length()
will already have the effect of reducing the call to a simple variable access.
EDIT :
In this latter case, it doesn't even matter whether or not the length of foo
is modified inside the loop. Getting the length of a string is already just a variable access.
Upvotes: 6
Reputation: 476920
The compiler has to guarantee that the program behaves as if length()
was called in every round. It can only hoist the call out of the loop if it can prove that there are no side effects and that the result is indeed constant.
What happens in a real example needs to be analyzed case-by-case. Just look at the assembly if you're curious.
The typical way to enforce the hoisting is to just do it manually:
for (unsigned int i = 0, end = s.length(); i != end; ++i)
Perhaps you'd also like to consider the modern for (char & c : s)
as an alternative.
Upvotes: 2