Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the compiler write a member variable to memory for each iteration of this loop?

The first version does an optimisation by moving a value from memory to a local variable. The second version does not.

I was expecting the compiler might choose to do the localValue optimisation here anyway and not read and write the value from memory for each iteration of the loop. Why doesn't it?

class Example
{
    public:
        void processSamples(float * x, int num) 
        {
            float localValue = v1;

            for (int i = 0; i < num; ++i)
            {
                x[i] = x[i] + localValue;
                localValue = 0.5 * x[i];
            }

            v1 = localValue;
        }

        void processSamples2(float * x, int num)
        {

            for (int i = 0; i < num; ++i)
            {
                x[i] = x[i] + v1;
                v1 = 0.5 * x[i];
            }

        }

    float v1;
};

processSamples assembles to code like this:

.L4:
  addss xmm0, DWORD PTR [rax]
  movss DWORD PTR [rax], xmm0
  mulss xmm0, xmm1
  add rax, 4
  cmp rax, rcx
  jne .L4

processSamples2 to this:

.L5:
  movss xmm0, DWORD PTR [rax]
  addss xmm0, DWORD PTR example[rip]
  movss DWORD PTR [rax], xmm0
  mulss xmm0, xmm1
  movss DWORD PTR example[rip], xmm0
  add rax, 4
  cmp rax, rdx
  jne .L5

As the compiler doesn't have to worry about threads (v1 isn't atomic). Can't it just assume nothing else will be looking at this value and go ahead and keep it in a register while the loop is spinning?

See https://godbolt.org/g/RiF3B4 for the full assembly and a selection of compilers to choose from!

like image 862
JCx Avatar asked Oct 16 '17 12:10

JCx


People also ask

What happens to variable after for loop?

Yes, they are destroyed when they go out of scope. Note that this isn't specific to variables in the loop. This rule applies to all variables with automatic storage duration. Save this answer.

What happens when a variable value type data goes out of its scope?

Nothing physical happens. A typical implementation will allocate enough space in the program stack to store all variables at the deepest level of block nesting in the current function. This space is typically allocated in the stack in one shot at the function startup and released back at the function exit.


1 Answers

Because of aliasing: v1 is a member variable, and it could be that x points at it. Thus, one of the writes to the elements of x might change v1.

In C99, you can use the restrict keyword on a function argument of pointer type to inform the compiler that it doesn't alias anything else that is in the scope of the function. Some C++ compilers also support it, although it is not standard. (Copied from one of my comments.)

like image 98
Aasmund Eldhuset Avatar answered Sep 18 '22 13:09

Aasmund Eldhuset