HighLife
HighLife

Reputation: 4344

GNU Compiler optimization

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

Answers (3)

James
James

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

Mysticial
Mysticial

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

Kerrek SB
Kerrek SB

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

Related Questions