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")