http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53933

             Bug #: 53933
           Summary: Register choosing error when inline assembly used at
                    inline function
    Classification: Unclassified
           Product: gcc
           Version: 4.6.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: nicejae...@gmail.com


Created attachment 27778
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=27778
gcc -v verbose output and itermediate(*.i) file

1) the system type: arm cortex-a8 / linux-montavista
2) the options given when GCC was configured/built: -O3
3) the complete command line that triggers the bug: execute w/ no param
4) the compiler output (error messages, warnings, etc.): attached

It seems GCC picks wrong registers
when inline assembly is used at inline function.

Below clip_int32 function is in-lined at main function by -O3 option,
and GCC picked same register 'movlt   ip, ip' 
(it should have picked different register as instructed 'movlt %0, %2 ')

*code

int clip_int32(int a, int amin, int amax)
{
#if 1
    asm volatile (
            "mov %0, %1     \n\t"
            "cmp %1, %2     \n\t"
            "movlt %0, %2   \n\t"
            "cmp %1, %3     \n\t"
            "movgt %0, %3   \n\t"
            : "=r"(a)
            : "r"(a), "r"(amin), "r"(amax)
            //: "r0", "r1", "r2"
            );

    return a;
#endif
#else
  if      (a < amin) return amin;
  else if (a > amax) return amax;
  else               return a;
#endif
}


int main()
{

    int ret[4];

    ret[0] = clip_int32( -5, -1, 1 );
    ret[1] = clip_int32( -5, -1, 1 );
    ret[2] = clip_int32( -5, -1, 1 );
    ret[3] = clip_int32( -5, -1, 1 );

    printf("%d %d %d %d\n", ret[0], ret[1], ret[2], ret[3]);

    return 0;
}

*disassembled executable

000082c8 <main>:
    82c8:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
    82cc:   e3e00004    mvn r0, #4
    82d0:   e24dd00c    sub sp, sp, #12
    82d4:   e3e0c000    mvn ip, #0
    82d8:   e3a0e001    mov lr, #1
    82dc:   e1a01000    mov r1, r0
    82e0:   e150000c    cmp r0, ip
    82e4:   b1a0100c    movlt   r1, ip
    82e8:   e150000e    cmp r0, lr
    82ec:   c1a0100e    movgt   r1, lr
    82f0:   e1a02000    mov r2, r0
    82f4:   e150000c    cmp r0, ip
    82f8:   b1a0200c    movlt   r2, ip
    82fc:   e150000e    cmp r0, lr
    8300:   c1a0200e    movgt   r2, lr
    8304:   e1a03000    mov r3, r0
    8308:   e150000c    cmp r0, ip
    830c:   b1a0300c    movlt   r3, ip
    8310:   e150000e    cmp r0, lr
    8314:   c1a0300e    movgt   r3, lr
    8318:   e1a0c000    mov ip, r0
    831c:   e150000c    cmp r0, ip
    8320:   b1a0c00c    movlt   ip, ip (these register should not be the same!)
    8324:   e150000e    cmp r0, lr
    8328:   c1a0c00e    movgt   ip, lr
    832c:   e3080480    movw    r0, #33920  ; 0x8480
    8330:   e58dc000    str ip, [sp]
    8334:   e3400000    movt    r0, #0
    8338:   ebffffd6    bl  8298 <_init+0x20>
    833c:   e3a00000    mov r0, #0
    8340:   e28dd00c    add sp, sp, #12
    8344:   e8bd8000    pop {pc}

the result was 
-1, -1, -1, -1(wrong) for -O3 option, and 
-1, -1, -1, -5(correct) for -O1 option.

Reply via email to