My basic situation: I have an include file that has something like #define foo (Flag1 | Flags2 | Flag3)
, so it's a predefined combination of bit flags. For the sake of type-safety, I wanted to replace these #defines by static consts, i.e. static const int foo = (Flag1 | Flag2 | Flag3)
(or similar). This include file is included in dozens of places in the program.
Now when I'm doing a release build with all relevant optimisation options enabled (using the C++ compiler of VS2010), replacing the #defines seems to increase the executable by a few KiB, depending on how many constants I replaced.
Why does this happen? To my knowledge, integer constants are supposed to be "inlined" into the ASM code that is produced if possible, and I don't see how using a static const
vs #define
would make a difference here. Clearly, the variable isn't inlined as the disassembly shows:
#define:
01325041 or eax,0FFD87FE0h
static int:
011E5451 or eax,dword ptr [CMainFrame::s_TemplateModulePaths+38h (151F008h)]
So the final question is: How can I avoid #define
but still rely on the variable being inserted directly into the generated assembly?
There is no reason the compiler couldn't eliminate the static const variable. If you're compiling with optimizations turned on, I'm surprised that VC++ doesn't do that.
I tried compiling this code with gcc.
enum { FLAG1 = 1 << 0, FLAG2 = 1 << 1, FLAG3 = 1 << 2 };
static const int foo = (FLAG1 | FLAG2 | FLAG3);
int main(){
return foo;
}
With optimizations turned off, it inlined the value but still reserved storage space for the variable.
_main:
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
call ___main
movl $7, %eax ;value inlined
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
.section .rdata,"dr"
.align 4
__ZL3foo: ; storage space for foo
.long 7
At O2 it inlined the value and got rid of the storage space.
_main:
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
call ___main
movl $7, %eax ; value inlined
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
; no storage space for foo
My only thought other that incorrect compiler settings, or VC++ failing to make this optimization, is that the Flags variables might not be compile-time constants which would mean that the value of the expression has to be computed at program start-up, which would prevent inlining.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With