Description
Bugzilla Link | 13622 |
Resolution | FIXED |
Resolved on | Feb 21, 2014 05:20 |
Version | trunk |
OS | All |
Blocks | llvm/llvm-bugzilla-archive#18926 |
Attachments | test case |
Reporter | LLVM Bugzilla Contributor |
CC | @asl,@efriedma-quic,@rengolin,@tinti |
Extended Description
on ARM, for the following C code:
typedef unsigned long long u64;
void i64_write(u64 *p, u64 val)
{
u64 tmp;
__asm__ __volatile__(
"1: ldrexd %0, %H0, [%2]\n"
" strexd %0, %3, %H3, [%2]\n"
" teq %0, #0\n"
" bne 1b"
: "=&r" (tmp), "=Qo" (*p)
: "r" (p), "r" (val)
: "cc");
}
It gives error like:
/tmp/write-D5hDGg.s: Assembler messages:
/tmp/write-D5hDGg.s:14: Error: even register required -- `ldrexd r1,r1,[r0]'
Here is the asm it generates:
i64_write:
@app
1: ldrexd r1, r1, [r0]
strexd r1, r2, r3, [r0]
teq r1, #0
bne 1b
@NO_APP
bx lr
This is because it assigns r1 to %0 (tmp). However, for 64-bit data, it should allocate even/odd reg pair.
One workaround is to hard code register pairs for i64 types. This is the similar way that ARM deals with ldrexd/strexd intrinsics. (In ARMISelDAGToDAG.cpp, ldrexd/strexd get hard coded registers: R0,R1, before register allocation pass)