Strange inlining behaviour

John Colvin john.loughran.colvin at gmail.com
Tue Feb 2 20:42:38 UTC 2021


https://d.godbolt.org/z/r8Gj1b

Very odd results, or at least they seem odd to me. Lambdas being 
treated differently to nested functions, behaviour being 
different depending on whether there is a `pragma(inline, false)` 
function to forward to? Also, different behaviour depending on 
whether the `pragma(inline, false)` is inside or outside the 
function!

I ran in to this in a more significant chunk of code where a 
lambda wasn't being inlined as expected, what's here is a simple 
example case.

pragma(inline, false)
int foo1() {
     alias bar = (int s) => s;
     return bar(3);
}

version (TryThisToo) {} else
int foo5() {
     pragma(inline, false);
     alias bar = (int s) => s;
     return bar(3);
}

int foo2() {
     alias bar = (int s) => s;
     return bar(3);
}

pragma(inline, false)
int foo3() {
     int bar(int s) { return s; }
     return bar(3);
}

int foo4() {
     int bar(int s) { return s; }
     return bar(3);
}

All asm done with gdc 10.2 -O3

If we define TryThisToo we get

pure nothrow @nogc @safe int example.foo3().bar(int).constprop.0:
.LFB18:
.LVL0:
         mov     eax, 3
         ret
.LFE18:
pure nothrow @nogc @safe int example.foo1().__lambda1(int):
.LVL1:
.LFB1:
         mov     eax, edi
         ret
.LFE1:
int example.foo1():
.LFB0:
         mov     edi, 3
         call    pure nothrow @nogc @safe int 
example.foo1().__lambda1(int)
.LVL2:
         ret
.LFE0:
int example.foo2():
.LFB2:
         mov     eax, 3
         ret
.LFE2:
pure nothrow @nogc @safe int example.foo2().__lambda1(int):
.LFB15:
         jmp     pure nothrow @nogc @safe int 
example.foo1().__lambda1(int)
.LFE15:
int example.foo3():
.LFB4:
         call    pure nothrow @nogc @safe int 
example.foo3().bar(int).constprop.0
.LVL3:
         ret
.LFE4:
int example.foo4():
.LFB17:
         mov     eax, 3
         ret
.LFE17:


I we don't define it, we instead get:


pure nothrow @nogc @safe int example.foo3().bar(int).constprop.0:
.LFB24:
.LVL0:
         mov     eax, 3
         ret
.LFE24:
pure nothrow @nogc @safe int example.foo1().__lambda1(int):
.LVL1:
.LFB1:
         mov     eax, edi
         ret
.LFE1:
int example.foo1():
.LFB0:
         mov     edi, 3
         call    pure nothrow @nogc @safe int 
example.foo1().__lambda1(int)
.LVL2:
         ret
.LFE0:
int example.foo5():
.LFB2:
         mov     eax, 3
         ret
.LFE2:
pure nothrow @nogc @safe int example.foo5().__lambda1(int):
.LFB17:
         jmp     pure nothrow @nogc @safe int 
example.foo1().__lambda1(int)
.LFE17:
int example.foo2():
.LFB21:
         jmp     int example.foo5()
.LFE21:
pure nothrow @nogc @safe int example.foo2().__lambda1(int):
.LFB19:
         jmp     pure nothrow @nogc @safe int 
example.foo1().__lambda1(int)
.LFE19:
int example.foo3():
.LFB6:
         call    pure nothrow @nogc @safe int 
example.foo3().bar(int).constprop.0
.LVL3:
         ret
.LFE6:
int example.foo4():
.LFB23:
         jmp     int example.foo5()
.LFE23:


More information about the D.gnu mailing list