@@ -2873,6 +2873,7 @@ expand_asm_loc (tree string, int vol, location_t locus)
auto_vec<rtx> input_rvec, output_rvec;
auto_vec<machine_mode> input_mode;
auto_vec<const char *> constraints;
+ auto_vec<rtx> use_rvec;
auto_vec<rtx> clobber_rvec;
HARD_REG_SET clobbered_regs;
CLEAR_HARD_REG_SET (clobbered_regs);
@@ -2882,16 +2883,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);
@@ -3443,11 +3448,12 @@ expand_asm_stmt (gasm *stmt)
maintaining source-level compatibility means automatically clobbering
the flags register. */
rtx_insn *after_md_seq = NULL;
+ auto_vec<rtx> 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. */
@@ -3455,7 +3461,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. */
@@ -3527,7 +3534,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)
@@ -3535,7 +3542,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)
@@ -3551,7 +3558,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)
@@ -3578,6 +3586,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)
{
@@ -149,7 +149,7 @@ struct cpu_cost_table
rtx_insn *arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> &constraints,
+ vec<const char *> &constraints, vec<rtx> &,
vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
location_t loc);
@@ -533,7 +533,8 @@ arm_mac_accumulator_is_mul_result (rtx producer, rtx consumer)
rtx_insn *
arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> &constraints, vec<rtx> & /*clobbers*/,
+ vec<const char *> &constraints,
+ vec<rtx> & /*uses*/, vec<rtx> & /*clobbers*/,
HARD_REG_SET & /*clobbered_regs*/, location_t loc)
{
bool saw_asm_flag = false;
@@ -325,7 +325,7 @@ static HOST_WIDE_INT arm_constant_alignment (const_tree, HOST_WIDE_INT);
static rtx_insn *thumb1_md_asm_adjust (vec<rtx> &, vec<rtx> &,
vec<machine_mode> &,
vec<const char *> &, vec<rtx> &,
- HARD_REG_SET &, location_t);
+ vec<rtx> &, HARD_REG_SET &, location_t);
static const char *arm_identify_fpu_from_isa (sbitmap);
/* Table of machine attributes. */
@@ -34290,7 +34290,8 @@ arm_stack_protect_guard (void)
rtx_insn *
thumb1_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> &constraints, vec<rtx> & /*clobbers*/,
+ vec<const char *> &constraints,
+ vec<rtx> &, vec<rtx> & /*clobbers*/,
HARD_REG_SET & /*clobbered_regs*/, location_t /*loc*/)
{
for (unsigned i = 0, n = outputs.length (); i < n; ++i)
@@ -14497,6 +14497,7 @@ static rtx_insn *
avr_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
vec<machine_mode> & /*input_modes*/,
vec<const char *> &/*constraints*/,
+ vec<rtx> &/*uses*/,
vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
location_t /*loc*/)
{
@@ -151,7 +151,8 @@ static void cris_function_arg_advance (cumulative_args_t,
const function_arg_info &);
static rtx_insn *cris_md_asm_adjust (vec<rtx> &, vec<rtx> &,
vec<machine_mode> &, vec<const char *> &,
- vec<rtx> &, HARD_REG_SET &, location_t);
+ vec<rtx> &, vec<rtx> &,
+ HARD_REG_SET &, location_t);
static void cris_option_override (void);
@@ -3506,7 +3507,8 @@ cris_function_arg_advance (cumulative_args_t ca_v,
static rtx_insn *
cris_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &inputs,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> &constraints, vec<rtx> &clobbers,
+ vec<const char *> &constraints,
+ vec<rtx> &/*uses*/, vec<rtx> &clobbers,
HARD_REG_SET &clobbered_regs, location_t /*loc*/)
{
/* For the time being, all asms clobber condition codes.
@@ -22488,8 +22488,9 @@ ix86_c_mode_for_suffix (char suffix)
static rtx_insn *
ix86_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> &constraints, vec<rtx> &clobbers,
- HARD_REG_SET &clobbered_regs, location_t loc)
+ vec<const char *> &constraints, vec<rtx> &/*uses*/,
+ vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
+ location_t loc)
{
bool saw_asm_flag = false;
@@ -2849,7 +2849,8 @@ mn10300_conditional_register_usage (void)
static rtx_insn *
mn10300_md_asm_adjust (vec<rtx> & /*outputs*/, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> & /*constraints*/, vec<rtx> &clobbers,
+ vec<const char *> & /*constraints*/,
+ vec<rtx> &/*uses*/, vec<rtx> &clobbers,
HARD_REG_SET &clobbered_regs, location_t /*loc*/)
{
clobbers.safe_push (gen_rtx_REG (CCmode, CC_REG));
@@ -4202,8 +4202,8 @@ nds32_md_asm_adjust (vec<rtx> &outputs ATTRIBUTE_UNUSED,
vec<rtx> &inputs ATTRIBUTE_UNUSED,
vec<machine_mode> &input_modes ATTRIBUTE_UNUSED,
vec<const char *> &constraints ATTRIBUTE_UNUSED,
- vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
- location_t /*loc*/)
+ vec<rtx> &/*uses*/, vec<rtx> &clobbers,
+ HARD_REG_SET &clobbered_regs, location_t /*loc*/)
{
if (!flag_inline_asm_r15)
{
@@ -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<rtx> &, vec<rtx> &,
vec<machine_mode> &, vec<const char *> &,
- vec<rtx> &, HARD_REG_SET &, location_t);
+ vec<rtx> &, vec<rtx> &,
+ 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<rtx> & /*outputs*/, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> & /*constraints*/, vec<rtx> &clobbers,
+ vec<const char *> & /*constraints*/,
+ vec<rtx> &/*uses*/, vec<rtx> &clobbers,
HARD_REG_SET &clobbered_regs, location_t /*loc*/)
{
clobbers.safe_push (gen_rtx_REG (CCmode, CC_REGNUM));
@@ -3373,7 +3373,8 @@ darwin_rs6000_override_options (void)
static rtx_insn *
rs6000_md_asm_adjust (vec<rtx> & /*outputs*/, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> & /*constraints*/, vec<rtx> &clobbers,
+ vec<const char *> & /*constraints*/,
+ vec<rtx> &/*uses*/, vec<rtx> &clobbers,
HARD_REG_SET &clobbered_regs, location_t /*loc*/)
{
clobbers.safe_push (gen_rtx_REG (SImode, CA_REGNO));
@@ -17081,7 +17081,8 @@ s390_hard_fp_reg_p (rtx x)
static rtx_insn *
s390_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &inputs,
vec<machine_mode> &input_modes,
- vec<const char *> &constraints, vec<rtx> & /*clobbers*/,
+ vec<const char *> &constraints,
+ vec<rtx> &/*uses*/, vec<rtx> & /*clobbers*/,
HARD_REG_SET & /*clobbered_regs*/, location_t /*loc*/)
{
if (!TARGET_VXE)
@@ -57,7 +57,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<rtx> &, vec<rtx> &,
vec<machine_mode> &, vec<const char *> &,
- vec<rtx> &, HARD_REG_SET &, location_t);
+ vec<rtx> &, vec<rtx> &, 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 &);
@@ -1179,6 +1180,7 @@ vax_md_asm_adjust (vec<rtx> &outputs ATTRIBUTE_UNUSED,
vec<rtx> &inputs ATTRIBUTE_UNUSED,
vec<machine_mode> &input_modes ATTRIBUTE_UNUSED,
vec<const char *> &constraints ATTRIBUTE_UNUSED,
+ vec<rtx> &/*uses*/,
vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
location_t /*loc*/)
{
@@ -190,7 +190,7 @@ static tree visium_build_builtin_va_list (void);
static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
vec<machine_mode> &,
vec<const char *> &, vec<rtx> &,
- HARD_REG_SET &, location_t);
+ vec<rtx> &, 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<rtx> & /*outputs*/, vec<rtx> & /*inputs*/,
vec<machine_mode> & /*input_modes*/,
- vec<const char *> & /*constraints*/, vec<rtx> &clobbers,
+ vec<const char *> & /*constraints*/,
+ vec<rtx> &/*uses*/, vec<rtx> &clobbers,
HARD_REG_SET &clobbered_regs, location_t /*loc*/)
{
clobbers.safe_push (gen_rtx_REG (CCmode, FLAGS_REGNUM));
@@ -3877,13 +3877,14 @@
[TARGET_BUILTIN_SETJMP_FRAME_VALUE]
[TARGET_MD_ASM_ADJUST]
-.. function:: rtx_insn * TARGET_MD_ASM_ADJUST (vec<rtx>& outputs, vec<rtx>& inputs, vec<machine_mode>& input_modes, vec<const char *>& constraints, vec<rtx>& clobbers, HARD_REG_SET& clobbered_regs, location_t loc)
+.. function:: rtx_insn * TARGET_MD_ASM_ADJUST (vec<rtx>& outputs, vec<rtx>& inputs, vec<machine_mode>& input_modes, vec<const char *>& constraints, vec<rtx>& usess, vec<rtx>& clobbers, HARD_REG_SET& clobbered_regs, location_t loc)
This target hook may add :dfn:`clobbers` to :samp:`{clobbers}` and
:samp:`{clobbered_regs}` for any hard regs the port wishes to automatically
- clobber for an asm. The :samp:`{outputs}` and :samp:`{inputs}` may be inspected
- to avoid clobbering a register that is already used by the asm. :samp:`{loc}`
- is the source location of the asm.
+ clobber for an asm. It can also add hard registers that are used by the
+ asm to :samp:`uses`. The :samp:`{outputs}` and :samp:`{inputs}` may be
+ inspected to avoid clobbering a register that is already used by the asm.
+ :samp:`{loc}` is the source location of the asm.
It may modify the :samp:`{outputs}`, :samp:`{inputs}`, :samp:`{input_modes}`, and
:samp:`{constraints}` as necessary for other pre-processing. In this case the
@@ -1977,13 +1977,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;
}
@@ -2010,10 +2014,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;
}
}
@@ -2080,7 +2087,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)
@@ -4251,9 +4251,10 @@ DEFHOOK
(md_asm_adjust,
"This target hook may add :dfn:`clobbers` to :samp:`{clobbers}` and\n\
:samp:`{clobbered_regs}` for any hard regs the port wishes to automatically\n\
-clobber for an asm. The :samp:`{outputs}` and :samp:`{inputs}` may be inspected\n\
-to avoid clobbering a register that is already used by the asm. :samp:`{loc}`\n\
-is the source location of the asm.\n\
+clobber for an asm. It can also add hard registers that are used by the\n\
+asm to :samp:`uses`. The :samp:`{outputs}` and :samp:`{inputs}` may be\n\
+inspected to avoid clobbering a register that is already used by the asm.\n\
+:samp:`{loc}` is the source location of the asm.\n\
\n\
It may modify the :samp:`{outputs}`, :samp:`{inputs}`, :samp:`{input_modes}`, and\n\
:samp:`{constraints}` as necessary for other pre-processing. In this case the\n\
@@ -4262,7 +4263,7 @@ changes to :samp:`{inputs}` must be accompanied by the corresponding changes\n\
to :samp:`{input_modes}`.",
rtx_insn *,
(vec<rtx>& outputs, vec<rtx>& inputs, vec<machine_mode>& input_modes,
- vec<const char *>& constraints, vec<rtx>& clobbers,
+ vec<const char *>& constraints, vec<rtx>& usess, vec<rtx>& clobbers,
HARD_REG_SET& clobbered_regs, location_t loc),
NULL)