On Fri, Jun 20, 2025 at 10:17:20AM -0400, Vladimir Makarov wrote: > > On 5/20/25 3:22 AM, Stefan Schulze Frielinghaus wrote: > > Implement hard register constraints of the form {regname} where regname > > must be a valid register name for the target. Such constraints may be > > used in asm statements as a replacement for register asm and in machine > > descriptions. > > > > --- > > gcc/config/cris/cris.cc | 6 +- > > gcc/config/i386/i386.cc | 6 + > > gcc/config/s390/s390.cc | 6 +- > > gcc/doc/extend.texi | 178 ++++++++++++++++++ > > gcc/doc/md.texi | 6 + > > gcc/function.cc | 116 ++++++++++++ > > gcc/genoutput.cc | 14 ++ > > gcc/genpreds.cc | 4 +- > > gcc/ira.cc | 79 +++++++- > > gcc/lra-constraints.cc | 13 ++ > > gcc/recog.cc | 11 +- > > gcc/stmt.cc | 39 ++++ > > gcc/stmt.h | 1 + > > gcc/testsuite/gcc.dg/asm-hard-reg-1.c | 85 +++++++++ > > gcc/testsuite/gcc.dg/asm-hard-reg-2.c | 33 ++++ > > gcc/testsuite/gcc.dg/asm-hard-reg-3.c | 25 +++ > > gcc/testsuite/gcc.dg/asm-hard-reg-4.c | 50 +++++ > > gcc/testsuite/gcc.dg/asm-hard-reg-5.c | 36 ++++ > > gcc/testsuite/gcc.dg/asm-hard-reg-6.c | 60 ++++++ > > gcc/testsuite/gcc.dg/asm-hard-reg-7.c | 41 ++++ > > gcc/testsuite/gcc.dg/asm-hard-reg-8.c | 49 +++++ > > .../gcc.target/aarch64/asm-hard-reg-1.c | 55 ++++++ > > .../gcc.target/i386/asm-hard-reg-1.c | 115 +++++++++++ > > .../gcc.target/s390/asm-hard-reg-1.c | 103 ++++++++++ > > .../gcc.target/s390/asm-hard-reg-2.c | 43 +++++ > > .../gcc.target/s390/asm-hard-reg-3.c | 42 +++++ > > .../gcc.target/s390/asm-hard-reg-4.c | 6 + > > .../gcc.target/s390/asm-hard-reg-5.c | 6 + > > .../gcc.target/s390/asm-hard-reg-6.c | 152 +++++++++++++++ > > .../gcc.target/s390/asm-hard-reg-longdouble.h | 18 ++ > > 30 files changed, 1391 insertions(+), 7 deletions(-) > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-1.c > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-2.c > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-3.c > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-4.c > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-5.c > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-6.c > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-7.c > > create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-8.c > > create mode 100644 gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c > > create mode 100644 gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c > > create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c > > create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c > > create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c > > create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c > > create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c > > create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c > > create mode 100644 gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h > > diff --git a/gcc/ira.cc b/gcc/ira.cc > > index 885239d1b43..c32d4ceab88 100644 > > --- a/gcc/ira.cc > > +++ b/gcc/ira.cc > > @@ -2113,6 +2113,82 @@ ira_get_dup_out_num (int op_num, alternative_mask > > alts, > > > > +/* Return true if a replacement of SRC by DEST does not lead to > > unsatisfiable > > + asm. Thus, a replacement is valid if and only if SRC and DEST are not > > + constrained in asm inputs of a single asm statement. See > > + match_asm_constraints_2() for more details. TODO: As in > > + match_asm_constraints_2() consider alternatives more precisely. */ > > + > > +static bool > > +valid_replacement_for_asm_input_p_1 (const_rtx asmops, const_rtx src, > > const_rtx dest) > > +{ > > + int ninputs = ASM_OPERANDS_INPUT_LENGTH (asmops); > > + rtvec inputs = ASM_OPERANDS_INPUT_VEC (asmops); > > + for (int i = 0; i < ninputs; ++i) > > + { > > + rtx input_src = RTVEC_ELT (inputs, i); > > + const char *constraint_src > > + = ASM_OPERANDS_INPUT_CONSTRAINT (asmops, i); > > + if (rtx_equal_p (input_src, src) > > + && strchr (constraint_src, '{') != nullptr) > > + for (int j = 0; j < ninputs; ++j) > > + { > > + rtx input_dest = RTVEC_ELT (inputs, j); > > + const char *constraint_dest > > + = ASM_OPERANDS_INPUT_CONSTRAINT (asmops, j); > > + if (rtx_equal_p (input_dest, dest) > > + && strchr (constraint_dest, '{') != nullptr) > > + return false; > > + } > > + } > > + return true; > > +} > > + > > +static bool > > +valid_replacement_for_asm_input_p (const_rtx src, const_rtx dest) > > +{ > > + /* Bail out early if there is no asm statement. */ > > + if (!crtl->has_asm_statement) > > + return true; > > + for (df_ref use = DF_REG_USE_CHAIN (REGNO (src)); > > + use; > > + use = DF_REF_NEXT_REG (use)) > > + { > > + struct df_insn_info *use_info = DF_REF_INSN_INFO (use); > > + /* Only check real uses, not artificial ones. */ > > + if (use_info) > > + { > > + rtx_insn *insn = DF_REF_INSN (use); > > + rtx pat = PATTERN (insn); > > + if (asm_noperands (pat) <= 0) > > + continue; > > + if (GET_CODE (pat) == SET) > > + { > > + if (!valid_replacement_for_asm_input_p_1 (SET_SRC (pat), src, > > dest)) > > + return false; > > + } > > + else if (GET_CODE (pat) == PARALLEL) > > + for (int i = 0, len = XVECLEN (pat, 0); i < len; ++i) > > + { > > + rtx asmops = XVECEXP (pat, 0, i); > > + if (GET_CODE (asmops) == SET) > > + asmops = SET_SRC (asmops); > > + if (GET_CODE (asmops) == ASM_OPERANDS > > + && !valid_replacement_for_asm_input_p_1 (asmops, src, dest)) > > + return false; > > + } > > + else if (GET_CODE (pat) == ASM_OPERANDS) > > + { > > + if (!valid_replacement_for_asm_input_p_1 (pat, src, dest)) > > + return false; > > + } > > + else > > + gcc_unreachable (); > > + } > > + } > > + return true; > > +} > > + > > /* Search forward to see if the source register of a copy insn dies > > before either it or the destination register is modified, but don't > > scan past the end of the basic block. If so, we can replace the > > @@ -2162,7 +2238,8 @@ decrease_live_ranges_number (void) > > auto-inc memory reference, so we must disallow this > > optimization on them. */ > > || sregno == STACK_POINTER_REGNUM > > - || dregno == STACK_POINTER_REGNUM) > > + || dregno == STACK_POINTER_REGNUM > > + || !valid_replacement_for_asm_input_p (src, dest)) > > continue; > > dest_death = NULL_RTX; > > diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc > > index 7dbc7fe1e00..689a12b2c71 100644 > > --- a/gcc/lra-constraints.cc > > +++ b/gcc/lra-constraints.cc > > @@ -114,6 +114,7 @@ > > #include "target.h" > > #include "rtl.h" > > #include "tree.h" > > +#include "stmt.h" > > #include "predict.h" > > #include "df.h" > > #include "memmodel.h" > > @@ -2175,6 +2176,7 @@ process_alt_operands (int only_alternative) > > bool costly_p; > > enum reg_class cl; > > const HARD_REG_SET *cl_filter; > > + HARD_REG_SET hard_reg_constraint; > > /* Calculate some data common for all alternatives to speed up the > > function. */ > > @@ -2551,6 +2553,17 @@ process_alt_operands (int only_alternative) > > cl_filter = nullptr; > > goto reg; > > + case '{': > > + { > > + int regno = decode_hard_reg_constraint (p); > > + gcc_assert (regno >= 0); > > + cl = REGNO_REG_CLASS (regno); > > + CLEAR_HARD_REG_SET (hard_reg_constraint); > > + SET_HARD_REG_BIT (hard_reg_constraint, regno); > > + cl_filter = &hard_reg_constraint; > > + goto reg; > > + } > > + > > default: > > cn = lookup_constraint (p); > > switch (get_constraint_type (cn)) > > > The RA part of the patch is OK for me. The changes are pretty obvious. It > would be nice to add a short comment to valid_replacement_for_asm_input_p > mentioning valid_replacement_for_asm_input_p_1 but it is not obligatory. > > Thank you for your work on this new GCC feature.
Thanks for the review. Very much appreciated! I added a comment to valid_replacement_for_asm_input_p(). Out of curiosity, do you have any idea how to tackle fixed registers? This is the last remaining piece for a full fledged solution. Certainly not required for this patch but something I would like to look into in the future. Cheers, Stefan