Inline functiion in GCC

Venkatachala Upadhya venkatu@samsung.com
Fri Aug 6 11:25:00 GMT 2004


Hello GCC people,

I am working on audio Codecs. I am using Linux 2.4.20 kernel on 
ARM926EJS processor. The tool chain used is GCC 3.3.1 and the binutils 
2.14. The codec code is optimised for ARMEJS priocessor using ADS suite 
version 1.2. This optimised code is having C inline functions with 
inline assembly statements. I have given here one inline C function with 
inline assembly code for reference.

__inline Word16 add(Word16, Word16);


__inline Word16 add(Word16 x, Word16 y)
{
    Word32 xs, ys;
    Word16 rs;
    __asm{
        mov     xs, x, lsl #16
        mov     ys, y, lsl #16
        qadd    xs, xs, ys
        mov     rs, xs, asr #16
    }
    return (rs);

}


I have ported the same code to GNU tool chain. I have used the 
C-Language extention with Extended inline assembly feature, available in 
GNU tool chain. The GNU port code is also reproduced here for reference.


__inline__ static int add(int, int) __attribute__ ((always_inline));

__inline__ static int add(int x, int y)
{
    int xs, ys;
    __asm__  __volatile__
    (
         "mov     %3, %0, lsl #16 \n;"
         "mov     %4, %2, lsl #16 \n;"
         "qadd    %3, %3, %4 \n;"
         "mov     %0, %3, asr #16 \n;"
         : "=r" (x)
         : "0" (x), "r" (y), "r" (xs), "r" (ys)
    ) ;
    return (x);
}


I have used this piece of code in the following example to study how the 
inline is happening and the effectiveness of the inline.


#include <stdio.h>
#include <stdlib.h>


__inline__ static int add(int, int) __attribute__ ((always_inline));

__inline__ static int add(int x, int y)
{
    int xs, ys;
    __asm__  __volatile__
    (
         "mov     %3, %0, lsl #16 \n;"
         "mov     %4, %2, lsl #16 \n;"
         "qadd    %3, %3, %4 \n;"
         "mov     %0, %3, asr #16 \n;"
         : "=r" (x)
         : "0" (x), "r" (y), "r" (xs), "r" (ys)
    ) ;
    return (x);
}


int main (void)
{

  int x=10, y=20, z=30;
  int sum1, sum2, sum3;

  sum1 = add (x, y);
  sum2 = add (y, z);
  sum3 = add (sum1, sum2);

  printf("sum1 = %d  sum2 = %d  sum3 = %d\n", sum1, sum2, sum3);

}


Compilation option used is

arm_v4t_le-gcc  -march=armv5te -msoft-float -finline-functions -Winline 
-I. inline_test.c  -o  inline_out

I have generated the executable and got the object dump of this 
executable with dis-assembly option (option -D). object dump command is


arm_v4t_le-objdump -D inline_out > inline_out_objdump

Using this inline_out_objdump file, I could see that the function main 
has 285 ARM instructions. See the attached file inline_out_objdump.



Now I have converted this inline assembly to ARM assembly file as shown 
below.


        .global add
        .code 32
        .text

add:
   mov     r0, r0, lsl #16
   mov     r1, r1, lsl #16
   qadd    r0, r0, r1
   mov     r0, r0, asr #16
   bx lr

  .end

Now I wrote a test program as shown below.


#include <stdio.h>
#include <stdlib.h>


int main (void)
{

  int x=10, y=20, z=30;
  int sum1, sum2, sum3;

  sum1 = add (x, y);
  sum2 = add (y, z);
  sum3 = add (sum1, sum2);

  printf("sum1 = %d  sum2 = %d  sum3 = %d\n", sum1, sum2, sum3);

}

Compilation option used is

arm_v4t_le-gcc  -march=armv5te -msoft-float -finline-functions -Winline 
inline_add.s inline_test.c  -o  inline_out_as

I have got the object dump of this executable with dis-assembly option 
(option -D). object dump command is

arm_v4t_le-objdump -D inline_out_as > as_objdump



I could see that the function main has 33 ARM instructions and add 
function has 5 instructions. Since add is called three times in the 
main, total number of instructions are 33+(3*5) = 48 instructions. See 
the attached file as_objdump.


Now I find that there is a big increase in the number of ARM 
instructions in the inline option compared to function call option. Also 
I could notice that compiler has not used the set of registers available 
(like r4, r5, ... r10) in the inline option, though it is free to use 
it. Moreover, though we have 2 arguments in add, registers r2, r3 are 
set to some value before entering the inline function. In case of 
function call option. I guess,  the compiler has used the registers 
correctly. Is this the expected behaviour of GCC? I could not find the 
advantage of using the inline in this case. In case of inline case, it 
can also be seen that a number of un-necessary instructions are 
generated, which can be avoided.

For this experiment, I have compared the GNU output with ADS suite 1.2, 
for the same program. ADS output is much better compared to GNU.


Does any one have any comment on this? I am hoping that some one would 
work on this to make the GCC better.


Please note that, I have added the number of instructions under the 
label main and add to count the number of instructions in each case.

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: as_objdump
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20040806/ab3ffa6d/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: inline_out_objdump
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20040806/ab3ffa6d/attachment-0001.ksh>


More information about the Gcc mailing list