why didn't gcc decide inline-or-not for me for this function?

Viewed 424

From some words on net I know that GCC is smart enough to decide whether to inline a function or not. The inline key word is just a hint:
GCC may inline a common function, and may not inline an inline function.

But for this function in my project:

struct vb_pos{
    union{
        struct{
            int offset;
            int l;
        };
        unsigned long long g_offset;    
    };
};
static inline void vi_write_vtail_smart(struct vi *vi){
    struct vb_pos *vhead, *vtail, *cursor;
    vhead = &vi->v_head;                    
    vtail = &vi->v_tail;
    cursor = &vi->cursor;

    int curoff = vi->curr - vi->lines[vi->currl].buf;
    cursor->offset = curoff;    

    if(cursor->g_offset >= vhead->g_offset){
        *vtail = *cursor;
    }
    else{
        *vtail = *vhead;
        *vhead = *cursor;
    }
}

compiled with -O2.
I checked the assembly code, and knew this function was inlined as expected.
However, when I deleted its inline modifier, and recompiled, I found it was no loner inlined. Its function body appeared in final binary file:

0000000000000000 <vi_write_vtail_smart>:
       0:       48 63 47 14             movslq 0x14(%rdi),%rax
       4:       48 8b 17                mov    (%rdi),%rdx
       7:       48 8d 04 40             lea    (%rax,%rax,2),%rax
       b:       48 8d 04 c2             lea    (%rdx,%rax,8),%rax
       f:       48 8b 57 18             mov    0x18(%rdi),%rdx
      13:       48 2b 10                sub    (%rax),%rdx
      16:       89 57 10                mov    %edx,0x10(%rdi)
      19:       48 8b 47 10             mov    0x10(%rdi),%rax
      1d:       48 3b 47 38             cmp    0x38(%rdi),%rax
      21:       73 0d                   jae    30 <vi_write_vtail_smart+0x30>
      23:       48 8b 57 38             mov    0x38(%rdi),%rdx
      27:       48 89 47 38             mov    %rax,0x38(%rdi)
      2b:       48 89 57 40             mov    %rdx,0x40(%rdi)
      2f:       c3                      retq   
      30:       48 89 47 40             mov    %rax,0x40(%rdi)
      34:       c3                      retq

I want to know, since GCC is smart enough, why didn't it has its own decision? Why it performed inline when I specified, and no when I not?

Because he didn't find enough clue to make a strong decision? or, because he already got a decision, and his decision is: there is no much difference to inline or not, and since you ask me, i inline for you; otherwise, i leave it as a common function.

I want to know the real reason.
If it's the first case, i think we may need reconsider the viewpoint(very popular on the net) in this post beginning————At least, GCC is not as smart as they said, and the inline key word is not as useless as they said.

In the article end, I want to add more description for the context of the code snippet above:

1, I originally want vi_write_vtail_smart() to be inlined into function A() and B(), which are exported as library APIs and both will be often invoked by users.

2, A() and B() are within the same file with vi_write_vtail_smart().

3, vi_write_vtail_smart() is only used in A() and B(), no where else.

4, the function body size of A() is about 450 bytes, B() is similar.

5, A() and B() are basically plain machine code, no big loop or heavy computations involved, and only one subfunction is invoked, except vi_write_vtail_smart(). That subfunction is in another file.

6, I did a small test, I added one line return; before if(cursor->g_offset >= vhead->g_offset){, (I wanted to see what happened when this function is small enough), namely:

...
int curoff = vi->curr - vi->lines[vi->currl].buf;
cursor->offset = curoff;    

return;
if(cursor->g_offset >= vhead->g_offset){
...

And compiled without inline modifier, and checked the assembly code————this time GCC inlined it and its function definition disappeared from final binary file.

7, My develop enviroment:
ubuntu-16.04 /64bit
gcc version 5.4.0 20160609
architecture: intel X86 Ivybridge Mobile

9,Compile flag( have to write here again, some people miss it when read) -O2 -std=gnu99

1 Answers
Related