summaryrefslogtreecommitdiff
path: root/0151-Backport-SME-Allow-targets-to-add-USEs-to-asms.patch
blob: cb0675161f01a8f02f7ea68208187125df861095 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
From 8684458c3faf358e5a15dfb73b4ef632341ddf0a Mon Sep 17 00:00:00 2001
From: Richard Sandiford <richard.sandiford@arm.com>
Date: Tue, 5 Dec 2023 09:52:41 +0000
Subject: [PATCH 052/157] [Backport][SME] Allow targets to add USEs to asms

Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=414d795d8a365b6e72a84257caa36cb3bed7e0ba

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 4691355aa..5401a4ebd 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -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)
 	{
diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index ae0465159..3b525c174 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -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);
 
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index 04a53d750..365cfc140 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -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;
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index b700c23b8..c72e9c0b0 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -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.  */
@@ -34209,7 +34209,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)
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 4ed390e4c..1b5a95410 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -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*/)
 {
diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc
index f0017d630..3a1c85481 100644
--- a/gcc/config/cris/cris.cc
+++ b/gcc/config/cris/cris.cc
@@ -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.
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 593185fa6..83a0d8abb 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -22252,8 +22252,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;
 
diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc
index 2a58dd925..2ca2c769c 100644
--- a/gcc/config/mn10300/mn10300.cc
+++ b/gcc/config/mn10300/mn10300.cc
@@ -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));
diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
index 71fe9e8bc..27530495f 100644
--- a/gcc/config/nds32/nds32.cc
+++ b/gcc/config/nds32/nds32.cc
@@ -4199,8 +4199,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)
     {
diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
index 380223439..25cf62cbc 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<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));
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 0b75861bb..55d4ce751 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -3443,7 +3443,8 @@ rs6000_builtin_mask_calculate (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));
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index ae0cf9ef5..f1599a5c5 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -16994,7 +16994,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)
diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
index 28c1af59a..7673a1428 100644
--- a/gcc/config/vax/vax.cc
+++ b/gcc/config/vax/vax.cc
@@ -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*/)
 {
diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
index 03c1a33e1..35b46ced9 100644
--- a/gcc/config/visium/visium.cc
+++ b/gcc/config/visium/visium.cc
@@ -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));
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 357c29a4d..4f93facf7 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -11626,10 +11626,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<rtx>& @var{outputs}, vec<rtx>& @var{inputs}, vec<machine_mode>& @var{input_modes}, vec<const char *>& @var{constraints}, vec<rtx>& @var{clobbers}, HARD_REG_SET& @var{clobbered_regs}, location_t @var{loc})
+@deftypefn {Target Hook} {rtx_insn *} TARGET_MD_ASM_ADJUST (vec<rtx>& @var{outputs}, vec<rtx>& @var{inputs}, vec<machine_mode>& @var{input_modes}, vec<const char *>& @var{constraints}, vec<rtx>& @var{usess}, vec<rtx>& @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 cd2410ab2..5b81d5e21 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -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)
diff --git a/gcc/target.def b/gcc/target.def
index a57e51b0d..60096c60c 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4309,7 +4309,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\
@@ -4320,7 +4321,7 @@ changes to @var{inputs} must be accompanied by the corresponding changes\n\
 to @var{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)
 
-- 
2.33.0