Volatile and optimization

Asked

Viewed 62 times

2

I’m studying about the type qualifier volatile in C language, and I took a test.

In the attached image we have the comparison of two programs written in C. The one on the left has a variable without volatile and the one on the right is the same program but with a volatile variable.

Below each program, we have the respective Assembly code.

As I don’t know much about Assembly, my question is: the logical test of while (valor == 666) has been optimized in the Assembly code on the left?

As the variable value valor is never changed in the code, I imagine the compiler can optimize the logical test by replacing valor == 666 for 1. That’s right?

códigos comparando

  • Which flags you used to compile this?

  • I didn’t understand your question; but to generate the Assembly code I used: gcc -S program. c

2 answers

1

volatile is not an optimization engine, and so when you used it nothing was optimized.

When you use this keyword you’re saying that this information can be changed at any time without your strict control, then what the compiler did was add an extra instruction, so it will be slower, and its function was to protect the data being used in comparison.

If what you’re saying is that there might be a change that you have no control over is just telling you not to optimize because the optimization could affect it erroneously.

If you want some optimization, then have it optimize, do it with the flag -O3 for maximum speed optimization. Nothing guarantees which optimizations will be made because the language does not require any of this, but is likely to be well simplified. The volatile prevent optimization.

Your GCC code using O3:

.LC0:
        .string "volatile"
main:
        sub     rsp, 8
.L2:
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        jmp     .L2

Behold in the Compiler Explorer.

No Clang:

main:                                   # @main
        push    RBP
        mov     RBP, RSP
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
        mov     EDI, .L.str
        xor     AL, AL
        call    printf
        jmp     .LBB0_1

.L.str:
        .asciz   "volatile"

Behold in the Compiler Explorer.

In MSVC the optimization is not done at the moment as far as I could observe.

On ARM using GCC:

main:
        stp     x29, x30, [sp, -32]!
        mov     x29, sp
        str     x19, [sp, 16]
        adrp    x19, .LC0
        add     x19, x19, :lo12:.LC0
.L2:
        mov     x0, x19
        bl      printf
        b       .L2
.LC0:
        .string "volatile"

Behold in the Compiler Explorer.

  • Right, but in the program on the left, the compiler changed the logical test (value == 999) to 1 (since the value of the variable never changes)? Or not? If not, why?

  • I don’t know what change you want me to make or what you’re talking about, there’s no change at all.

  • The question is: in the code on the left, could the compiler replace the logical test (for optimization purposes) simply with 1? Since the variable "value" does not have volatile and its value is never changed.

  • Could, depending on how you had it compiled, in case you didn’t.

  • Cool! How can I compile to optimize this code to disappear with the logical test? Should I use this flag?

  • Yes, but optimizations are not guaranteed, power is not duty to do.

  • Got it. When I go to compile by GCC I use: gcc -o <executable> <program>.c. You know if so it can already optimize?

  • Power can, but is less likely because it is not deliberately having optimized. You can use -o3 which is the maximum optimization and still not optimize. Theoretically if a compiler has a flag that has this optimization done specifically yet, unless it is documented by the compiler that he specifically ensures will do, he may or may not do.

  • I think it’s clearer now. Thank you very much for your attention!

Show 4 more comments

1

Editing your code a little to make optimization clearer.

#include <stdio.h>

int main(void) {
    int valor = 666;
    return (valor == 666) ? 1 : 0;
}

Compiling in GCC with the flag -O3.

main:
        mov     eax, 1
        ret

Now compiling the same program with volatile and -O3.

#include <stdio.h>

int main(void) {
    volatile int valor = 666;
    return (valor == 666) ? 1 : 0;
}
main:
        mov     DWORD PTR [rsp-4], 666
        mov     eax, DWORD PTR [rsp-4]
        cmp     eax, 666
        sete    al
        movzx   eax, al
        ret

Volatile is not an optimizer and does exactly the opposite, as it imposes constraints on the compiler.

  • Interesting. What I doubt is: in the code on the left, the compiler could replace the logical test (for optimization purposes) simply with 1? Since the variable "value" does not have volatile and its value is never changed.

  • 1

    Probably. It depends a lot on the compiler. For example, if this code was C++, MSVC would probably let this optimization pass beaten, while CLANG would almost certainly optimize. This type of optimization is not standard so it is not mandatory. A better way to signal to the compiler you want to have this optimization would be to mark variables as constants (C), or use constexpr to make this check only once during compilation (C++).

  • Got it. Thanks a lot for your attention!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.