Dear all,
I was just playing around with a toy example when I noticed an oddity in
the code generated by clang-5.0.0 (and also in clang-5.0.1) regarding
constexpr.
Given the code:
> int fib(int i) { if (i <= 0) return i; else return (fib(i - 1) + fib(i - 2))
> % 100; }
> int main()
> {
> int ret = 0;
> for (int i = 0; i < 10; ++i)
> ret += fib(39);
> return ret;
> }
Compile it with clang++ -O3 and what you get is (gdb disassembly of "main"):
> 7 {
> 8 int ret = 0;
> 9 for (int i = 0; i < 10; ++i)
> 10 ret += fib(39);
>0x004004e0 <+0>: push rax
>0x004004e1 <+1>: movedi,0x27
>0x004004e6 <+6>: call 0x400490
>
> 9 for (int i = 0; i < 10; ++i)
>0x004004eb <+11>:addeax,eax
>0x004004ed <+13>:leaeax,[rax+rax*4]
>
> 11 return ret;
>0x004004f0 <+16>:poprcx
>0x004004f1 <+17>:ret
A call to fib(39) once followed by a multiplication with 10.
Now, if you make "fib" constexpr, i.e.:
> constexpr int fib(int i) { if (i <= 0) return i; else return (fib(i - 1) +
> fib(i - 2)) % 100; }
And, again, compile it with -O3 and disassemble "main":
> 7 {
> 8 int ret = 0;
> 9 for (int i = 0; i < 10; ++i)
> 10 ret += fib(39);
>0x00400490 <+0>: push rbp
>0x00400491 <+1>: push rbx
>0x00400492 <+2>: push rax
>0x00400493 <+3>: movedi,0x27
>0x00400498 <+8>: call 0x400530
>0x0040049d <+13>:movebx,eax
>0x0040049f <+15>:movedi,0x27
>0x004004a4 <+20>:call 0x400530
>0x004004a9 <+25>:movebp,eax
>0x004004ab <+27>:addebp,ebx
>0x004004ad <+29>:movedi,0x27
>0x004004b2 <+34>:call 0x400530
>0x004004b7 <+39>:movebx,eax
>0x004004b9 <+41>:addebx,ebp
>0x004004bb <+43>:movedi,0x27
>0x004004c0 <+48>:call 0x400530
>0x004004c5 <+53>:movebp,eax
>0x004004c7 <+55>:addebp,ebx
>0x004004c9 <+57>:movedi,0x27
>0x004004ce <+62>:call 0x400530
>0x004004d3 <+67>:movebx,eax
>0x004004d5 <+69>:addebx,ebp
>0x004004d7 <+71>:movedi,0x27
>0x004004dc <+76>:call 0x400530
>0x004004e1 <+81>:movebp,eax
>0x004004e3 <+83>:addebp,ebx
>0x004004e5 <+85>:movedi,0x27
>0x004004ea <+90>:call 0x400530
>0x004004ef <+95>:movebx,eax
>0x004004f1 <+97>:addebx,ebp
>0x004004f3 <+99>:movedi,0x27
>0x004004f8 <+104>: call 0x400530
>0x004004fd <+109>: movebp,eax
>0x004004ff <+111>: addebp,ebx
>0x00400501 <+113>: movedi,0x27
>0x00400506 <+118>: call 0x400530
>0x0040050b <+123>: movebx,eax
>0x0040050d <+125>: addebx,ebp
>0x0040050f <+127>: movedi,0x27
>0x00400514 <+132>: call 0x400530
>0x00400519 <+137>: addeax,ebx
>
> 11 return ret;
>0x0040051b <+139>: addrsp,0x8
>0x0040051f <+143>: poprbx
>0x00400520 <+144>: poprbp
>0x00400521 <+145>: ret
That's 10 calls to function "fib" (for which the assembly is essentially
the same as in the example above).
Regardless of whether the function is evaluated at compile time or not,
it seems odd to me that using constexpr here prohibits clang from
emitting the very same code as in the non-constexpr example. Note
however, that if you declare "fib" to be "static constexpr" clang,
again, emits the multiplication code.
Is there something keeping clang from producing the multiplication code
for a non-static constexpr example that I don't see? And why is the
optimization possible again if one makes "fib" static?
Greetings,
Steffen
___
cfe-users mailing list
cfe-users@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users