https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115217

            Bug ID: 115217
           Summary: Register pairs can't be encoded in RISC-V inline asm
                    blocks
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: palmer at gcc dot gnu.org
  Target Milestone: ---

Alex is trying to do the amocas.q support in Linux, which operates on paired X
registers by providing only the even register in the instruction encoding.  As
far as I can tell we don't have a way to encode this in inline assembly
constraints: we can just force a pair of registers via the asm/register
variable type tricks, but we don't have a constraint for allocating them.

IIUC just doing something like the following isn't sufficient, as we'd need to
also read/clobber the paired register and I'm not sure how to plumb that into
inline assembly.

It's not super clear if that's a real performance problem as there's not going
to be a ton of 128-bit CAS instances in code, but I figured it's worth filing a
bug just in case anyone's looking or there's some inline asm trick I don't know
about.  Both x86_64 and aarch64 look like they're using explicit register
numbers in their 128-bit cmpxchg code in Linux, so maybe that's a sign this
isn't worth doing?

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index a9ee346af6f..c372c5f8853 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -141,6 +141,10 @@ (define_constraint "T"
   (and (match_operand 0 "move_operand")
        (match_test "CONSTANT_P (op)")))

+(define_constraint "re"
+  "The even part of an X register pair, not including the x0-x0 pair"
+  (match_test "even_x_register_pair (op)"))
+
 ;; Zfa constraints.

 (define_constraint "zfli"
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 0fb5729fdcf..70ba741ab54 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -201,6 +201,11 @@ (define_predicate "zcmp_mv_sreg_operand"
                     : IN_RANGE (REGNO (op), S0_REGNUM, S1_REGNUM)
                     || IN_RANGE (REGNO (op), S2_REGNUM, S7_REGNUM)")))

+;; Some operations (like amocas.q) operate on X register pairs.
+(define_predicate "even_x_register_pair"
+  (and (match_code "reg")
+       (match_test "GP_REG_P (REGNO (op)) && (REGNO (op) % 2 == 0)")))
+
 ;; Only use branch-on-bit sequences when the mask is not an ANDI immediate.
 (define_predicate "branch_on_bit_operand"
   (and (match_code "const_int")

Reply via email to