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: [email protected]
ReportedBy: [email protected]
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.