From 414d795d8a365b6e72a84257caa36cb3bed7e0ba Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 5 Dec 2023 09:52:41 +0000 Subject: [PATCH] Allow targets to add USEs to asms Arm's SME has an array called ZA that for inline asm purposes is effectively a form of special-purpose memory. It doesn't have an associated storage type and so can't be passed and returned in normal C/C++ objects. We'd therefore like "za" in a clobber list to mean that an inline asm can read from and write to ZA. (Just reading or writing individually is unlikely to be useful, but we could add syntax for that too if necessary.) There is currently a TARGET_MD_ASM_ADJUST target hook that allows targets to add clobbers to an asm instruction. This patch extends that to allow targets to add USEs as well. gcc/ * target.def (md_asm_adjust): Add a uses parameter. * doc/tm.texi: Regenerate. * cfgexpand.cc (expand_asm_loc): Update call to md_asm_adjust. Handle any USEs created by the target. (expand_asm_stmt): Likewise. * recog.cc (asm_noperands): Handle asms with USEs. (decode_asm_operands): Likewise. * config/arm/aarch-common-protos.h (arm_md_asm_adjust): Add uses parameter. * config/arm/aarch-common.cc (arm_md_asm_adjust): Likewise. * config/arm/arm.cc (thumb1_md_asm_adjust): Likewise. * config/avr/avr.cc (avr_md_asm_adjust): Likewise. * config/cris/cris.cc (cris_md_asm_adjust): Likewise. * config/i386/i386.cc (ix86_md_asm_adjust): Likewise. * config/mn10300/mn10300.cc (mn10300_md_asm_adjust): Likewise. * config/nds32/nds32.cc (nds32_md_asm_adjust): Likewise. * config/pdp11/pdp11.cc (pdp11_md_asm_adjust): Likewise. * config/rs6000/rs6000.cc (rs6000_md_asm_adjust): Likewise. * config/s390/s390.cc (s390_md_asm_adjust): Likewise. * config/vax/vax.cc (vax_md_asm_adjust): Likewise. * config/visium/visium.cc (visium_md_asm_adjust): Likewise. --- gcc/cfgexpand.cc | 37 +++++++++++++++++++--------- gcc/config/arm/aarch-common-protos.h | 2 +- gcc/config/arm/aarch-common.cc | 3 ++- gcc/config/arm/arm.cc | 5 ++-- gcc/config/avr/avr.cc | 1 + gcc/config/cris/cris.cc | 6 +++-- gcc/config/i386/i386.cc | 5 ++-- gcc/config/mn10300/mn10300.cc | 3 ++- gcc/config/nds32/nds32.cc | 4 +-- gcc/config/pdp11/pdp11.cc | 6 +++-- gcc/config/rs6000/rs6000.cc | 3 ++- gcc/config/s390/s390.cc | 3 ++- gcc/config/vax/vax.cc | 4 ++- gcc/config/visium/visium.cc | 5 ++-- gcc/doc/tm.texi | 5 ++-- gcc/recog.cc | 20 ++++++++++----- gcc/target.def | 5 ++-- 17 files changed, 77 insertions(+), 40 deletions(-) diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc index 3fee2569680..b860be8bb77 100644 --- a/gcc/cfgexpand.cc +++ b/gcc/cfgexpand.cc @@ -2874,6 +2874,7 @@ expand_asm_loc (tree string, int vol, location_t locus) auto_vec input_rvec, output_rvec; auto_vec input_mode; auto_vec constraints; + auto_vec use_rvec; auto_vec clobber_rvec; HARD_REG_SET clobbered_regs; CLEAR_HARD_REG_SET (clobbered_regs); @@ -2883,16 +2884,20 @@ expand_asm_loc (tree string, int vol, location_t locus) if (targetm.md_asm_adjust) targetm.md_asm_adjust (output_rvec, input_rvec, input_mode, - constraints, clobber_rvec, clobbered_regs, - locus); + constraints, use_rvec, clobber_rvec, + clobbered_regs, locus); asm_op = body; nclobbers = clobber_rvec.length (); - body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (1 + nclobbers)); + auto nuses = use_rvec.length (); + body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (1 + nuses + nclobbers)); - XVECEXP (body, 0, 0) = asm_op; - for (i = 0; i < nclobbers; i++) - XVECEXP (body, 0, i + 1) = gen_rtx_CLOBBER (VOIDmode, clobber_rvec[i]); + i = 0; + XVECEXP (body, 0, i++) = asm_op; + for (rtx use : use_rvec) + XVECEXP (body, 0, i++) = gen_rtx_USE (VOIDmode, use); + for (rtx clobber : clobber_rvec) + XVECEXP (body, 0, i++) = gen_rtx_CLOBBER (VOIDmode, clobber); } emit_insn (body); @@ -3444,11 +3449,12 @@ expand_asm_stmt (gasm *stmt) maintaining source-level compatibility means automatically clobbering the flags register. */ rtx_insn *after_md_seq = NULL; + auto_vec use_rvec; if (targetm.md_asm_adjust) after_md_seq = targetm.md_asm_adjust (output_rvec, input_rvec, input_mode, - constraints, clobber_rvec, clobbered_regs, - locus); + constraints, use_rvec, clobber_rvec, + clobbered_regs, locus); /* Do not allow the hook to change the output and input count, lest it mess up the operand numbering. */ @@ -3456,7 +3462,8 @@ expand_asm_stmt (gasm *stmt) gcc_assert (input_rvec.length() == ninputs); gcc_assert (constraints.length() == noutputs + ninputs); - /* But it certainly can adjust the clobbers. */ + /* But it certainly can adjust the uses and clobbers. */ + unsigned nuses = use_rvec.length (); unsigned nclobbers = clobber_rvec.length (); /* Third pass checks for easy conflicts. */ @@ -3528,7 +3535,7 @@ expand_asm_stmt (gasm *stmt) ARGVEC CONSTRAINTS OPNAMES)) If there is more than one, put them inside a PARALLEL. */ - if (noutputs == 0 && nclobbers == 0) + if (noutputs == 0 && nuses == 0 && nclobbers == 0) { /* No output operands: put in a raw ASM_OPERANDS rtx. */ if (nlabels > 0) @@ -3536,7 +3543,7 @@ expand_asm_stmt (gasm *stmt) else emit_insn (body); } - else if (noutputs == 1 && nclobbers == 0) + else if (noutputs == 1 && nuses == 0 && nclobbers == 0) { ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = constraints[0]; if (nlabels > 0) @@ -3552,7 +3559,8 @@ expand_asm_stmt (gasm *stmt) if (num == 0) num = 1; - body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num + nclobbers)); + body = gen_rtx_PARALLEL (VOIDmode, + rtvec_alloc (num + nuses + nclobbers)); /* For each output operand, store a SET. */ for (i = 0; i < noutputs; ++i) @@ -3579,6 +3587,11 @@ expand_asm_stmt (gasm *stmt) if (i == 0) XVECEXP (body, 0, i++) = obody; + /* Add the uses specified by the target hook. No checking should + be needed since this doesn't come directly from user code. */ + for (rtx use : use_rvec) + XVECEXP (body, 0, i++) = gen_rtx_USE (VOIDmode, use); + /* Store (clobber REG) for each clobbered register specified. */ for (unsigned j = 0; j < nclobbers; ++j) { diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h index f8cb6562096..6e44d29b433 100644 --- a/gcc/config/arm/aarch-common-protos.h +++ b/gcc/config/arm/aarch-common-protos.h @@ -155,7 +155,7 @@ struct cpu_cost_table rtx_insn *arm_md_asm_adjust (vec &outputs, vec & /*inputs*/, vec & /*input_modes*/, - vec &constraints, + vec &constraints, vec &, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t loc); diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc index 5b96ff4c2e8..d68b7047c9b 100644 --- a/gcc/config/arm/aarch-common.cc +++ b/gcc/config/arm/aarch-common.cc @@ -534,7 +534,8 @@ arm_mac_accumulator_is_mul_result (rtx producer, rtx consumer) rtx_insn * arm_md_asm_adjust (vec &outputs, vec & /*inputs*/, vec & /*input_modes*/, - vec &constraints, vec & /*clobbers*/, + vec &constraints, + vec & /*uses*/, vec & /*clobbers*/, HARD_REG_SET & /*clobbered_regs*/, location_t loc) { bool saw_asm_flag = false; diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 5cb35e8d061..5ac67c1e28b 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -328,7 +328,7 @@ static HOST_WIDE_INT arm_constant_alignment (const_tree, HOST_WIDE_INT); static rtx_insn *thumb1_md_asm_adjust (vec &, vec &, vec &, vec &, vec &, - HARD_REG_SET &, location_t); + vec &, HARD_REG_SET &, location_t); static const char *arm_identify_fpu_from_isa (sbitmap); /* Table of machine attributes. */ @@ -34646,7 +34646,8 @@ arm_stack_protect_guard (void) rtx_insn * thumb1_md_asm_adjust (vec &outputs, vec & /*inputs*/, vec & /*input_modes*/, - vec &constraints, vec & /*clobbers*/, + vec &constraints, + vec &, vec & /*clobbers*/, HARD_REG_SET & /*clobbered_regs*/, location_t /*loc*/) { for (unsigned i = 0, n = outputs.length (); i < n; ++i) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 3af9ca8d17f..c5e9ccf9663 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -15085,6 +15085,7 @@ static rtx_insn * avr_md_asm_adjust (vec &/*outputs*/, vec &/*inputs*/, vec & /*input_modes*/, vec &/*constraints*/, + vec &/*uses*/, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t /*loc*/) { diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc index 8b0f82e9810..7705c25ed6c 100644 --- a/gcc/config/cris/cris.cc +++ b/gcc/config/cris/cris.cc @@ -152,7 +152,8 @@ static void cris_function_arg_advance (cumulative_args_t, const function_arg_info &); static rtx_insn *cris_md_asm_adjust (vec &, vec &, vec &, vec &, - vec &, HARD_REG_SET &, location_t); + vec &, vec &, + HARD_REG_SET &, location_t); static void cris_option_override (void); @@ -3646,7 +3647,8 @@ cris_function_arg_advance (cumulative_args_t ca_v, static rtx_insn * cris_md_asm_adjust (vec &outputs, vec &inputs, vec & /*input_modes*/, - vec &constraints, vec &clobbers, + vec &constraints, + vec &/*uses*/, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t /*loc*/) { /* For the time being, all asms clobber condition codes. diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 6ab3f61a8cc..7c5cab4e2c6 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -23681,8 +23681,9 @@ static void map_egpr_constraints (vec &constraints) static rtx_insn * ix86_md_asm_adjust (vec &outputs, vec & /*inputs*/, vec & /*input_modes*/, - vec &constraints, vec &clobbers, - HARD_REG_SET &clobbered_regs, location_t loc) + vec &constraints, vec &/*uses*/, + vec &clobbers, HARD_REG_SET &clobbered_regs, + location_t loc) { bool saw_asm_flag = false; diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc index cd1de1b2d83..d56247afc08 100644 --- a/gcc/config/mn10300/mn10300.cc +++ b/gcc/config/mn10300/mn10300.cc @@ -2850,7 +2850,8 @@ mn10300_conditional_register_usage (void) static rtx_insn * mn10300_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/, vec & /*input_modes*/, - vec & /*constraints*/, vec &clobbers, + vec & /*constraints*/, + vec &/*uses*/, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t /*loc*/) { clobbers.safe_push (gen_rtx_REG (CCmode, CC_REG)); diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc index e0a73985b66..921102df51b 100644 --- a/gcc/config/nds32/nds32.cc +++ b/gcc/config/nds32/nds32.cc @@ -4200,8 +4200,8 @@ nds32_md_asm_adjust (vec &outputs ATTRIBUTE_UNUSED, vec &inputs ATTRIBUTE_UNUSED, vec &input_modes ATTRIBUTE_UNUSED, vec &constraints ATTRIBUTE_UNUSED, - vec &clobbers, HARD_REG_SET &clobbered_regs, - location_t /*loc*/) + vec &/*uses*/, vec &clobbers, + HARD_REG_SET &clobbered_regs, location_t /*loc*/) { if (!flag_inline_asm_r15) { diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc index 78c1927f143..478297e4a58 100644 --- a/gcc/config/pdp11/pdp11.cc +++ b/gcc/config/pdp11/pdp11.cc @@ -155,7 +155,8 @@ static int pdp11_addr_cost (rtx, machine_mode, addr_space_t, bool); static int pdp11_insn_cost (rtx_insn *insn, bool speed); static rtx_insn *pdp11_md_asm_adjust (vec &, vec &, vec &, vec &, - vec &, HARD_REG_SET &, location_t); + vec &, vec &, + HARD_REG_SET &, location_t); static bool pdp11_return_in_memory (const_tree, const_tree); static rtx pdp11_function_value (const_tree, const_tree, bool); static rtx pdp11_libcall_value (machine_mode, const_rtx); @@ -2137,7 +2138,8 @@ pdp11_cmp_length (rtx *operands, int words) static rtx_insn * pdp11_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/, vec & /*input_modes*/, - vec & /*constraints*/, vec &clobbers, + vec & /*constraints*/, + vec &/*uses*/, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t /*loc*/) { clobbers.safe_push (gen_rtx_REG (CCmode, CC_REGNUM)); diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 5386470f6f8..bff06f73bcf 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -3387,7 +3387,8 @@ darwin_rs6000_override_options (void) static rtx_insn * rs6000_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/, vec & /*input_modes*/, - vec & /*constraints*/, vec &clobbers, + vec & /*constraints*/, + vec &/*uses*/, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t /*loc*/) { clobbers.safe_push (gen_rtx_REG (SImode, CA_REGNO)); diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index 384fdb93df5..044de874590 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -17513,7 +17513,8 @@ s390_hard_fp_reg_p (rtx x) static rtx_insn * s390_md_asm_adjust (vec &outputs, vec &inputs, vec &input_modes, - vec &constraints, vec & /*clobbers*/, + vec &constraints, + vec &/*uses*/, vec &/*clobbers*/, HARD_REG_SET &clobbered_regs, location_t loc) { diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc index 032de712946..ccaf14b27d2 100644 --- a/gcc/config/vax/vax.cc +++ b/gcc/config/vax/vax.cc @@ -58,7 +58,8 @@ static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool); static machine_mode vax_cc_modes_compatible (machine_mode, machine_mode); static rtx_insn *vax_md_asm_adjust (vec &, vec &, vec &, vec &, - vec &, HARD_REG_SET &, location_t); + vec &, vec &, HARD_REG_SET &, + location_t); static rtx vax_function_arg (cumulative_args_t, const function_arg_info &); static void vax_function_arg_advance (cumulative_args_t, const function_arg_info &); @@ -1180,6 +1181,7 @@ vax_md_asm_adjust (vec &outputs ATTRIBUTE_UNUSED, vec &inputs ATTRIBUTE_UNUSED, vec &input_modes ATTRIBUTE_UNUSED, vec &constraints ATTRIBUTE_UNUSED, + vec &/*uses*/, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t /*loc*/) { diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc index 4a1877c2ac1..0691ea2ad13 100644 --- a/gcc/config/visium/visium.cc +++ b/gcc/config/visium/visium.cc @@ -189,7 +189,7 @@ static tree visium_build_builtin_va_list (void); static rtx_insn *visium_md_asm_adjust (vec &, vec &, vec &, vec &, vec &, - HARD_REG_SET &, location_t); + vec &, HARD_REG_SET &, location_t); static bool visium_legitimate_constant_p (machine_mode, rtx); @@ -794,7 +794,8 @@ visium_conditional_register_usage (void) static rtx_insn * visium_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/, vec & /*input_modes*/, - vec & /*constraints*/, vec &clobbers, + vec & /*constraints*/, + vec &/*uses*/, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t /*loc*/) { clobbers.safe_push (gen_rtx_REG (CCmode, FLAGS_REGNUM)); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 1246ed12ca5..a2801ca5987 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11821,10 +11821,11 @@ from shared libraries (DLLs). You need not define this macro if it would always evaluate to zero. @end defmac -@deftypefn {Target Hook} {rtx_insn *} TARGET_MD_ASM_ADJUST (vec& @var{outputs}, vec& @var{inputs}, vec& @var{input_modes}, vec& @var{constraints}, vec& @var{clobbers}, HARD_REG_SET& @var{clobbered_regs}, location_t @var{loc}) +@deftypefn {Target Hook} {rtx_insn *} TARGET_MD_ASM_ADJUST (vec& @var{outputs}, vec& @var{inputs}, vec& @var{input_modes}, vec& @var{constraints}, vec& @var{usess}, vec& @var{clobbers}, HARD_REG_SET& @var{clobbered_regs}, location_t @var{loc}) This target hook may add @dfn{clobbers} to @var{clobbers} and @var{clobbered_regs} for any hard regs the port wishes to automatically -clobber for an asm. The @var{outputs} and @var{inputs} may be inspected +clobber for an asm. It can also add hard registers that are used by the +asm to @var{uses}. The @var{outputs} and @var{inputs} may be inspected to avoid clobbering a register that is already used by the asm. @var{loc} is the source location of the asm. diff --git a/gcc/recog.cc b/gcc/recog.cc index eaab79c25d7..ed084fa8808 100644 --- a/gcc/recog.cc +++ b/gcc/recog.cc @@ -1990,13 +1990,17 @@ asm_noperands (const_rtx body) { /* Multiple output operands, or 1 output plus some clobbers: body is - [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */ - /* Count backwards through CLOBBERs to determine number of SETs. */ + [(set OUTPUT (asm_operands ...))... + (use (reg ...))... + (clobber (reg ...))...]. */ + /* Count backwards through USEs and CLOBBERs to determine + number of SETs. */ for (i = XVECLEN (body, 0); i > 0; i--) { if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET) break; - if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER) + if (GET_CODE (XVECEXP (body, 0, i - 1)) != USE + && GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER) return -1; } @@ -2023,10 +2027,13 @@ asm_noperands (const_rtx body) else { /* 0 outputs, but some clobbers: - body is [(asm_operands ...) (clobber (reg ...))...]. */ + body is [(asm_operands ...) + (use (reg ...))... + (clobber (reg ...))...]. */ /* Make sure all the other parallel things really are clobbers. */ for (i = XVECLEN (body, 0) - 1; i > 0; i--) - if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER) + if (GET_CODE (XVECEXP (body, 0, i)) != USE + && GET_CODE (XVECEXP (body, 0, i)) != CLOBBER) return -1; } } @@ -2093,7 +2100,8 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs, the SETs. Their constraints are in the ASM_OPERANDS itself. */ for (i = 0; i < nparallel; i++) { - if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) + if (GET_CODE (XVECEXP (body, 0, i)) == USE + || GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) break; /* Past last SET */ gcc_assert (GET_CODE (XVECEXP (body, 0, i)) == SET); if (operands) diff --git a/gcc/target.def b/gcc/target.def index 4addee1ab03..b51939a4f85 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4342,7 +4342,8 @@ DEFHOOK (md_asm_adjust, "This target hook may add @dfn{clobbers} to @var{clobbers} and\n\ @var{clobbered_regs} for any hard regs the port wishes to automatically\n\ -clobber for an asm. The @var{outputs} and @var{inputs} may be inspected\n\ +clobber for an asm. It can also add hard registers that are used by the\n\ +asm to @var{uses}. The @var{outputs} and @var{inputs} may be inspected\n\ to avoid clobbering a register that is already used by the asm. @var{loc}\n\ is the source location of the asm.\n\ \n\ @@ -4353,7 +4354,7 @@ changes to @var{inputs} must be accompanied by the corresponding changes\n\ to @var{input_modes}.", rtx_insn *, (vec& outputs, vec& inputs, vec& input_modes, - vec& constraints, vec& clobbers, + vec& constraints, vec& usess, vec& clobbers, HARD_REG_SET& clobbered_regs, location_t loc), NULL)