Skip to content

Unable to assign paired register for inline asm with 64-bit data on ARM #13994

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
llvmbot opened this issue Aug 16, 2012 · 9 comments
Closed
Labels
bugzilla Issues migrated from bugzilla

Comments

@llvmbot
Copy link
Member

llvmbot commented Aug 16, 2012

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)

@llvmbot
Copy link
Member Author

llvmbot commented Feb 13, 2013

Fixed by patches:
r175008, r173833, r168229, r168207, r166816

@llvmbot
Copy link
Member Author

llvmbot commented Mar 6, 2013

I'm still seeing this issue (on almost identical code) in llvm rev. 176491, clang rev. 176480.

Code in question is:

static inline void tf_write_reg64(void *comm_buffer, u64 value)
{
u64 tmp;

    __asm__ __volatile__("@ tf_write_reg64\n"
            "1:     ldrexd %0, [%2]\n"
            "       strexd %0, %1, [%2]\n"
            "       teq    %0, #​0\n"
            "       bne    1b"
            : "=&r" (tmp)
            : "r" (value), "r" (comm_buffer)
            : "cc"
    );

}

Generated code is:

.Ltmp7:
.loc 73 83 0
@​APP
@ tf_write_reg64
1: ldrexd r5, [r3]
strexd r5, r0, [r3]
teq r5, #​0
bne 1b
@​NO_APP

(Note the ldrexd r5, [r3] -- r5 is an odd register)

@llvmbot
Copy link
Member Author

llvmbot commented Mar 6, 2013

(changing platform to Other/All as the target is arm w/ any OS)

@llvmbot
Copy link
Member Author

llvmbot commented Mar 6, 2013

when you use
ldrexd %0, [%2]
strexd %0, %1, [%2]

it assumes %0, %1, %2 are independent regs.

Instead, you should use %n %Hn.
For you code, GCC also gives invalid asm:

@ tf_write_reg64

1: ldrexd r4, [r1]
strexd r4, r2, [r1]
teq r4, #​0
bne 1b

@berolinux
Copy link

Fix
This patch fixes it -- admittedly a little ugly, but the beginnings of just that workaround were already there before...

@tinti
Copy link
Contributor

tinti commented May 28, 2013

Bernhard's patch has fixed my issue in both runtime and compile time.

Also I know a commit of LLVM in which these problems do not happen: baabdec

Here the list of commits applied on the same file as Bernhard's patch after this commit.
ac6d9be Track IR ordering of SelectionDAG nodes 2/4.
c6af243 Replace Count{Leading,Trailing}Zeros_{32,64} with count{Leading,Trailing}Zeros.
2a8bea7 ArrayRefize getMachineNode(). No functionality change.
f793de7 Don't glue users to extract_subreg when selecting the llvm.arm.ldrexd intrinsic - it can cause impossible-to-schedule subgraphs to be introduced.
3853f74 ArrayRefize some code. No functionality change.
7248451 Re-apply r175088 for bug fix 13622: Add paired register support for inline asm with 64-bit data on ARM
c0c2816 temporarily revert the patch due to some conflicts
3019fbb Bug fix 13622: Add paired register support for inline asm with 64-bit data on ARM

@tinti
Copy link
Contributor

tinti commented Jun 10, 2013

In fact baabdec commit + Weiming Zhao patch solved the problem at that point. But in the current HEAD the problem is still happening.

@rengolin
Copy link
Member

Fixed in r188643

@rengolin
Copy link
Member

mentioned in issue llvm/llvm-bugzilla-archive#18926

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 3, 2021
djtodoro pushed a commit to djtodoro/llvm-project that referenced this issue Apr 24, 2025
$ cat test.s
// llvm-mc -triple=riscv32 -mattr=+Xsecure test.s -show-inst
// llvm-mc -triple=riscv32 -mattr=+Xsecure test.s -filetype=obj -o test.o
// llvm-objdump -d --mattr=+Xsecure test.o

        .text
        .globl _start
_start:
        # Test the new instructions:
        openstealth.rol   x5, x6, x7
        openstealth.ror   x5, x6, x7
        openstealth.rori  x5, x6, 13

        # Return or jump to an infinite loop to avoid crashing
        ret

$ llvm-mc -triple=riscv32 -mattr=+Xsecure test.s -show-inst

	.text
	.globl	_start
_start:
	openstealth.rol	t0, t1, t2                      # <MCInst llvm#13993 XSECURE_ROL
                                        #  <MCOperand Reg:48>
                                        #  <MCOperand Reg:49>
                                        #  <MCOperand Reg:50>>
	openstealth.ror	t0, t1, t2                      # <MCInst llvm#13994 XSECURE_ROR
                                        #  <MCOperand Reg:48>
                                        #  <MCOperand Reg:49>
                                        #  <MCOperand Reg:50>>
	openstealth.rori	t0, t1, 13                      # <MCInst llvm#13995 XSECURE_RORI
                                        #  <MCOperand Reg:48>
                                        #  <MCOperand Reg:49>
                                        #  <MCOperand Imm:13>>

	ret                                     # <MCInst llvm#12777 JALR
                                        #  <MCOperand Reg:43>
                                        #  <MCOperand Reg:44>
                                        #  <MCOperand Imm:0>>

$ llvm-objdump -d --mattr=+Xsecure test.o

test.o:	file format elf32-littleriscv

Disassembly of section .text:

00000000 <_start>:
       0: 607312b3     	openstealth.rol	t0, t1, t2
       4: 607352b3     	openstealth.ror	t0, t1, t2
       8: 60d35293     	openstealth.rori	t0, t1, 0xd
       c: 00008067     	ret
djtodoro pushed a commit to djtodoro/llvm-project that referenced this issue Apr 24, 2025
$ cat test.s
// llvm-mc -triple=riscv32 -mattr=+Xsecure test.s -show-inst
// llvm-mc -triple=riscv32 -mattr=+Xsecure test.s -filetype=obj -o test.o
// llvm-objdump -d --mattr=+Xsecure test.o

        .text
        .globl _start
_start:
        # Test the new instructions:
        openstealth.rol   x5, x6, x7
        openstealth.ror   x5, x6, x7
        openstealth.rori  x5, x6, 13

        # Return or jump to an infinite loop to avoid crashing
        ret

$ llvm-mc -triple=riscv32 -mattr=+Xsecure test.s -show-inst

	.text
	.globl	_start
_start:
	openstealth.rol	t0, t1, t2                      # <MCInst llvm#13993 XSECURE_ROL
                                        #  <MCOperand Reg:48>
                                        #  <MCOperand Reg:49>
                                        #  <MCOperand Reg:50>>
	openstealth.ror	t0, t1, t2                      # <MCInst llvm#13994 XSECURE_ROR
                                        #  <MCOperand Reg:48>
                                        #  <MCOperand Reg:49>
                                        #  <MCOperand Reg:50>>
	openstealth.rori	t0, t1, 13                      # <MCInst llvm#13995 XSECURE_RORI
                                        #  <MCOperand Reg:48>
                                        #  <MCOperand Reg:49>
                                        #  <MCOperand Imm:13>>

	ret                                     # <MCInst llvm#12777 JALR
                                        #  <MCOperand Reg:43>
                                        #  <MCOperand Reg:44>
                                        #  <MCOperand Imm:0>>

$ llvm-objdump -d --mattr=+Xsecure test.o

test.o:	file format elf32-littleriscv

Disassembly of section .text:

00000000 <_start>:
       0: 607312b3     	openstealth.rol	t0, t1, t2
       4: 607352b3     	openstealth.ror	t0, t1, t2
       8: 60d35293     	openstealth.rori	t0, t1, 0xd
       c: 00008067     	ret

$ clang --target=riscv32 -mcpu=attorv32 test.s -c
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla
Projects
None yet
Development

No branches or pull requests

4 participants