简体   繁体   中英

Compiler optimization of static constexpr

Given the following C++ code:

#include <stdio.h>

static constexpr int x = 1;

void testfn() {
    if (x == 2)
        printf("This is test.\n");
}

int main() {
    for (int a = 0; a < 10; a++)
        testfn();
    return 0;
}

Visual Studio 2019 produces the following Debug build assembly (viewed using Approach 1 of accepted answer at: How to view the assembly behind the code using Visual C++? )

int main() {
00EC1870  push        ebp  
00EC1871  mov         ebp,esp  
00EC1873  sub         esp,0CCh  
00EC1879  push        ebx  
00EC187A  push        esi  
00EC187B  push        edi  
00EC187C  lea         edi,[ebp-0CCh]  
00EC1882  mov         ecx,33h  
00EC1887  mov         eax,0CCCCCCCCh  
00EC188C  rep stos    dword ptr es:[edi]  
00EC188E  mov         ecx,offset _6D4A0457_how_compiler_treats_staticconstexpr@cpp (0ECC003h)  
00EC1893  call        @__CheckForDebuggerJustMyCode@4 (0EC120Dh)  
    for (int a = 0; a < 10; a++)
00EC1898  mov         dword ptr [ebp-8],0  
00EC189F  jmp         main+3Ah (0EC18AAh)  
00EC18A1  mov         eax,dword ptr [ebp-8]  
00EC18A4  add         eax,1  
00EC18A7  mov         dword ptr [ebp-8],eax  
00EC18AA  cmp         dword ptr [ebp-8],0Ah  
00EC18AE  jge         main+47h (0EC18B7h)  
        testfn();
00EC18B0  call        testfn (0EC135Ch)  
00EC18B5  jmp         main+31h (0EC18A1h)  
    return 0;
00EC18B7  xor         eax,eax  
}

As can be seen in the assembly, possibly because this is a Debug build, there is pointless references to the for loop and testfn in main . I would have hoped that they should not find any mention in the assembly code at all given that the printf in testfn will never be hit since static constexpr int x=1 .

I have 2 questions:

(1)Perhaps in the Release build, the for loop is optimized away. How can I check this? Viewing the release build assembly code does not work for me even on using the Approach 2 specified at at: How to view the assembly behind the code using Visual C++? . The file with the assembly code is not produced at all.

(2)In using static constexpr int/double/char as opposed to #define 's, under what circumstances is one guaranteed that the former does not involve any unnecessary overhead (runtime computations/evaluations)? #define 's, though much maligned, seem to offer much greater guarantee than static constexpr 's in this regard.

The issue here is that you are compiling the code using a debug build. If you want sanity in the asm, compile as release instead. The problem is that a debugger is used to help confirm the logic of the underlying code. The logic in your underlying code is that it should call testfn() 10 times. As a result, you should be able to place a breakpoint on that method, and hit it at the correct point in the execution. In a release build, that breakpoint would never be hit (because it would have been optimised away).

In your case however, it's entirely incorrect to say that the constexpr is being ignored. You may notice that there are no calls to printf() in the generated asm, so the compiler has correctly identified that if (x == 2) can never be true, and has removed it. However, if the compiler removed the call to testfn() completely, your breakpoint would never be hit, and the debugger would basically be useless.

Don't look at the output of a debug build and imagine it tells you anything useful about the code or compiler. You should expect the code to be deliberately de-optimised.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM