]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/aarch-common.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / arm / aarch-common.c
1 /* Dependency checks for instruction scheduling, shared between ARM and
2 AARCH64.
3
4 Copyright (C) 1991-2020 Free Software Foundation, Inc.
5 Contributed by ARM Ltd.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 3, or (at your
12 option) any later version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23
24 #define IN_TARGET_CODE 1
25
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
29 #include "insn-modes.h"
30 #include "tm.h"
31 #include "rtl.h"
32 #include "rtl-iter.h"
33 #include "memmodel.h"
34 #include "diagnostic.h"
35 #include "tree.h"
36 #include "expr.h"
37 #include "function.h"
38 #include "emit-rtl.h"
39
40 /* Return TRUE if X is either an arithmetic shift left, or
41 is a multiplication by a power of two. */
42 bool
43 arm_rtx_shift_left_p (rtx x)
44 {
45 enum rtx_code code = GET_CODE (x);
46
47 if (code == MULT && CONST_INT_P (XEXP (x, 1))
48 && exact_log2 (INTVAL (XEXP (x, 1))) > 0)
49 return true;
50
51 if (code == ASHIFT)
52 return true;
53
54 return false;
55 }
56
57 static rtx_code shift_rtx_codes[] =
58 { ASHIFT, ROTATE, ASHIFTRT, LSHIFTRT,
59 ROTATERT, ZERO_EXTEND, SIGN_EXTEND };
60
61 /* Traverse PATTERN looking for a sub-rtx with RTX_CODE CODE.
62 If FIND_ANY_SHIFT then we are interested in anything which can
63 reasonably be described as a SHIFT RTX. */
64 static rtx
65 arm_find_sub_rtx_with_code (rtx pattern, rtx_code code, bool find_any_shift)
66 {
67 subrtx_var_iterator::array_type array;
68 FOR_EACH_SUBRTX_VAR (iter, array, pattern, NONCONST)
69 {
70 rtx x = *iter;
71 if (find_any_shift)
72 {
73 /* Left shifts might have been canonicalized to a MULT of some
74 power of two. Make sure we catch them. */
75 if (arm_rtx_shift_left_p (x))
76 return x;
77 else
78 for (unsigned int i = 0; i < ARRAY_SIZE (shift_rtx_codes); i++)
79 if (GET_CODE (x) == shift_rtx_codes[i])
80 return x;
81 }
82
83 if (GET_CODE (x) == code)
84 return x;
85 }
86 return NULL_RTX;
87 }
88
89 /* Traverse PATTERN looking for any sub-rtx which looks like a shift. */
90 static rtx
91 arm_find_shift_sub_rtx (rtx pattern)
92 {
93 return arm_find_sub_rtx_with_code (pattern, ASHIFT, true);
94 }
95
96 /* PRODUCER and CONSUMER are two potentially dependant RTX. PRODUCER
97 (possibly) contains a SET which will provide a result we can access
98 using the SET_DEST macro. We will place the RTX which would be
99 written by PRODUCER in SET_SOURCE.
100 Similarly, CONSUMER (possibly) contains a SET which has an operand
101 we can access using SET_SRC. We place this operand in
102 SET_DESTINATION.
103
104 Return nonzero if we found the SET RTX we expected. */
105 static int
106 arm_get_set_operands (rtx producer, rtx consumer,
107 rtx *set_source, rtx *set_destination)
108 {
109 rtx set_producer = arm_find_sub_rtx_with_code (PATTERN (producer),
110 SET, false);
111 rtx set_consumer = arm_find_sub_rtx_with_code (PATTERN (consumer),
112 SET, false);
113
114 if (set_producer && set_consumer)
115 {
116 *set_source = SET_DEST (set_producer);
117 *set_destination = SET_SRC (set_consumer);
118 return 1;
119 }
120 return 0;
121 }
122
123 bool
124 aarch_rev16_shright_mask_imm_p (rtx val, machine_mode mode)
125 {
126 return CONST_INT_P (val)
127 && INTVAL (val)
128 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff),
129 mode);
130 }
131
132 bool
133 aarch_rev16_shleft_mask_imm_p (rtx val, machine_mode mode)
134 {
135 return CONST_INT_P (val)
136 && INTVAL (val)
137 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff00),
138 mode);
139 }
140
141
142 static bool
143 aarch_rev16_p_1 (rtx lhs, rtx rhs, machine_mode mode)
144 {
145 if (GET_CODE (lhs) == AND
146 && GET_CODE (XEXP (lhs, 0)) == ASHIFT
147 && CONST_INT_P (XEXP (XEXP (lhs, 0), 1))
148 && INTVAL (XEXP (XEXP (lhs, 0), 1)) == 8
149 && REG_P (XEXP (XEXP (lhs, 0), 0))
150 && CONST_INT_P (XEXP (lhs, 1))
151 && GET_CODE (rhs) == AND
152 && GET_CODE (XEXP (rhs, 0)) == LSHIFTRT
153 && REG_P (XEXP (XEXP (rhs, 0), 0))
154 && CONST_INT_P (XEXP (XEXP (rhs, 0), 1))
155 && INTVAL (XEXP (XEXP (rhs, 0), 1)) == 8
156 && CONST_INT_P (XEXP (rhs, 1))
157 && REGNO (XEXP (XEXP (rhs, 0), 0)) == REGNO (XEXP (XEXP (lhs, 0), 0)))
158
159 {
160 rtx lhs_mask = XEXP (lhs, 1);
161 rtx rhs_mask = XEXP (rhs, 1);
162
163 return aarch_rev16_shright_mask_imm_p (rhs_mask, mode)
164 && aarch_rev16_shleft_mask_imm_p (lhs_mask, mode);
165 }
166
167 return false;
168 }
169
170 /* Recognise a sequence of bitwise operations corresponding to a rev16 operation.
171 These will be of the form:
172 ((x >> 8) & 0x00ff00ff)
173 | ((x << 8) & 0xff00ff00)
174 for SImode and with similar but wider bitmasks for DImode.
175 The two sub-expressions of the IOR can appear on either side so check both
176 permutations with the help of aarch_rev16_p_1 above. */
177
178 bool
179 aarch_rev16_p (rtx x)
180 {
181 rtx left_sub_rtx, right_sub_rtx;
182 bool is_rev = false;
183
184 if (GET_CODE (x) != IOR)
185 return false;
186
187 left_sub_rtx = XEXP (x, 0);
188 right_sub_rtx = XEXP (x, 1);
189
190 /* There are no canonicalisation rules for the position of the two shifts
191 involved in a rev, so try both permutations. */
192 is_rev = aarch_rev16_p_1 (left_sub_rtx, right_sub_rtx, GET_MODE (x));
193
194 if (!is_rev)
195 is_rev = aarch_rev16_p_1 (right_sub_rtx, left_sub_rtx, GET_MODE (x));
196
197 return is_rev;
198 }
199
200 /* Return non-zero if the RTX representing a memory model is a memory model
201 that needs acquire semantics. */
202 bool
203 aarch_mm_needs_acquire (rtx const_int)
204 {
205 enum memmodel model = memmodel_from_int (INTVAL (const_int));
206 return !(is_mm_relaxed (model)
207 || is_mm_consume (model)
208 || is_mm_release (model));
209 }
210
211 /* Return non-zero if the RTX representing a memory model is a memory model
212 that needs release semantics. */
213 bool
214 aarch_mm_needs_release (rtx const_int)
215 {
216 enum memmodel model = memmodel_from_int (INTVAL (const_int));
217 return !(is_mm_relaxed (model)
218 || is_mm_consume (model)
219 || is_mm_acquire (model));
220 }
221
222 /* Return nonzero if the CONSUMER instruction (a load) does need
223 PRODUCER's value to calculate the address. */
224 int
225 arm_early_load_addr_dep (rtx producer, rtx consumer)
226 {
227 rtx value, addr;
228
229 if (!arm_get_set_operands (producer, consumer, &value, &addr))
230 return 0;
231
232 return reg_overlap_mentioned_p (value, addr);
233 }
234
235 /* Return nonzero if the CONSUMER instruction (a load) does need
236 a Pmode PRODUCER's value to calculate the address. */
237
238 int
239 arm_early_load_addr_dep_ptr (rtx producer, rtx consumer)
240 {
241 rtx value = arm_find_sub_rtx_with_code (PATTERN (producer), SET, false);
242 rtx addr = arm_find_sub_rtx_with_code (PATTERN (consumer), SET, false);
243
244 if (!value || !addr || !MEM_P (SET_SRC (value)))
245 return 0;
246
247 value = SET_DEST (value);
248 addr = SET_SRC (addr);
249
250 return GET_MODE (value) == Pmode && reg_overlap_mentioned_p (value, addr);
251 }
252
253 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
254 have an early register shift value or amount dependency on the
255 result of PRODUCER. */
256 int
257 arm_no_early_alu_shift_dep (rtx producer, rtx consumer)
258 {
259 rtx value, op;
260 rtx early_op;
261
262 if (!arm_get_set_operands (producer, consumer, &value, &op))
263 return 0;
264
265 if ((early_op = arm_find_shift_sub_rtx (op)))
266 return !reg_overlap_mentioned_p (value, early_op);
267
268 return 0;
269 }
270
271 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
272 have an early register shift value dependency on the result of
273 PRODUCER. */
274 int
275 arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer)
276 {
277 rtx value, op;
278 rtx early_op;
279
280 if (!arm_get_set_operands (producer, consumer, &value, &op))
281 return 0;
282
283 if ((early_op = arm_find_shift_sub_rtx (op)))
284 /* We want to check the value being shifted. */
285 if (!reg_overlap_mentioned_p (value, XEXP (early_op, 0)))
286 return 1;
287
288 return 0;
289 }
290
291 /* Return nonzero if the CONSUMER (a mul or mac op) does not
292 have an early register mult dependency on the result of
293 PRODUCER. */
294 int
295 arm_no_early_mul_dep (rtx producer, rtx consumer)
296 {
297 rtx value, op;
298
299 if (!arm_get_set_operands (producer, consumer, &value, &op))
300 return 0;
301
302 if (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
303 {
304 if (GET_CODE (XEXP (op, 0)) == MULT)
305 return !reg_overlap_mentioned_p (value, XEXP (op, 0));
306 else
307 return !reg_overlap_mentioned_p (value, XEXP (op, 1));
308 }
309
310 return 0;
311 }
312
313 /* Return nonzero if the CONSUMER instruction (a store) does not need
314 PRODUCER's value to calculate the address. */
315
316 int
317 arm_no_early_store_addr_dep (rtx producer, rtx consumer)
318 {
319 rtx value = arm_find_sub_rtx_with_code (PATTERN (producer), SET, false);
320 rtx addr = arm_find_sub_rtx_with_code (PATTERN (consumer), SET, false);
321
322 if (value)
323 value = SET_DEST (value);
324
325 if (addr)
326 addr = SET_DEST (addr);
327
328 if (!value || !addr)
329 return 0;
330
331 return !reg_overlap_mentioned_p (value, addr);
332 }
333
334 /* Return nonzero if the CONSUMER instruction (a store) does need
335 PRODUCER's value to calculate the address. */
336
337 int
338 arm_early_store_addr_dep (rtx producer, rtx consumer)
339 {
340 return !arm_no_early_store_addr_dep (producer, consumer);
341 }
342
343 /* Return nonzero if the CONSUMER instruction (a store) does need
344 a Pmode PRODUCER's value to calculate the address. */
345
346 int
347 arm_early_store_addr_dep_ptr (rtx producer, rtx consumer)
348 {
349 rtx value = arm_find_sub_rtx_with_code (PATTERN (producer), SET, false);
350 rtx addr = arm_find_sub_rtx_with_code (PATTERN (consumer), SET, false);
351
352 if (!value || !addr || !MEM_P (SET_SRC (value)))
353 return 0;
354
355 value = SET_DEST (value);
356 addr = SET_DEST (addr);
357
358 return GET_MODE (value) == Pmode && reg_overlap_mentioned_p (value, addr);
359 }
360
361 /* Return non-zero iff the consumer (a multiply-accumulate or a
362 multiple-subtract instruction) has an accumulator dependency on the
363 result of the producer and no other dependency on that result. It
364 does not check if the producer is multiply-accumulate instruction. */
365 int
366 arm_mac_accumulator_is_result (rtx producer, rtx consumer)
367 {
368 rtx result;
369 rtx op0, op1, acc;
370
371 producer = PATTERN (producer);
372 consumer = PATTERN (consumer);
373
374 if (GET_CODE (producer) == COND_EXEC)
375 producer = COND_EXEC_CODE (producer);
376 if (GET_CODE (consumer) == COND_EXEC)
377 consumer = COND_EXEC_CODE (consumer);
378
379 if (GET_CODE (producer) != SET)
380 return 0;
381
382 result = XEXP (producer, 0);
383
384 if (GET_CODE (consumer) != SET)
385 return 0;
386
387 /* Check that the consumer is of the form
388 (set (...) (plus (mult ...) (...)))
389 or
390 (set (...) (minus (...) (mult ...))). */
391 if (GET_CODE (XEXP (consumer, 1)) == PLUS)
392 {
393 if (GET_CODE (XEXP (XEXP (consumer, 1), 0)) != MULT)
394 return 0;
395
396 op0 = XEXP (XEXP (XEXP (consumer, 1), 0), 0);
397 op1 = XEXP (XEXP (XEXP (consumer, 1), 0), 1);
398 acc = XEXP (XEXP (consumer, 1), 1);
399 }
400 else if (GET_CODE (XEXP (consumer, 1)) == MINUS)
401 {
402 if (GET_CODE (XEXP (XEXP (consumer, 1), 1)) != MULT)
403 return 0;
404
405 op0 = XEXP (XEXP (XEXP (consumer, 1), 1), 0);
406 op1 = XEXP (XEXP (XEXP (consumer, 1), 1), 1);
407 acc = XEXP (XEXP (consumer, 1), 0);
408 }
409 else
410 return 0;
411
412 return (reg_overlap_mentioned_p (result, acc)
413 && !reg_overlap_mentioned_p (result, op0)
414 && !reg_overlap_mentioned_p (result, op1));
415 }
416
417 /* Return non-zero if the destination of PRODUCER feeds the accumulator
418 operand of an MLA-like operation. */
419
420 int
421 aarch_accumulator_forwarding (rtx_insn *producer, rtx_insn *consumer)
422 {
423 rtx producer_set = single_set (producer);
424 rtx consumer_set = single_set (consumer);
425
426 /* We are looking for a SET feeding a SET. */
427 if (!producer_set || !consumer_set)
428 return 0;
429
430 rtx dest = SET_DEST (producer_set);
431 rtx mla = SET_SRC (consumer_set);
432
433 /* We're looking for a register SET. */
434 if (!REG_P (dest))
435 return 0;
436
437 rtx accumulator;
438
439 /* Strip a zero_extend. */
440 if (GET_CODE (mla) == ZERO_EXTEND)
441 mla = XEXP (mla, 0);
442
443 switch (GET_CODE (mla))
444 {
445 case PLUS:
446 /* Possibly an MADD. */
447 if (GET_CODE (XEXP (mla, 0)) == MULT)
448 accumulator = XEXP (mla, 1);
449 else
450 return 0;
451 break;
452 case MINUS:
453 /* Possibly an MSUB. */
454 if (GET_CODE (XEXP (mla, 1)) == MULT)
455 accumulator = XEXP (mla, 0);
456 else
457 return 0;
458 break;
459 case FMA:
460 {
461 /* Possibly an FMADD/FMSUB/FNMADD/FNMSUB. */
462 if (REG_P (XEXP (mla, 1))
463 && REG_P (XEXP (mla, 2))
464 && (REG_P (XEXP (mla, 0))
465 || GET_CODE (XEXP (mla, 0)) == NEG))
466
467 {
468 /* FMADD/FMSUB. */
469 accumulator = XEXP (mla, 2);
470 }
471 else if (REG_P (XEXP (mla, 1))
472 && GET_CODE (XEXP (mla, 2)) == NEG
473 && (REG_P (XEXP (mla, 0))
474 || GET_CODE (XEXP (mla, 0)) == NEG))
475 {
476 /* FNMADD/FNMSUB. */
477 accumulator = XEXP (XEXP (mla, 2), 0);
478 }
479 else
480 return 0;
481 break;
482 }
483 default:
484 /* Not an MLA-like operation. */
485 return 0;
486 }
487
488 if (GET_CODE (accumulator) == SUBREG)
489 accumulator = SUBREG_REG (accumulator);
490
491 if (!REG_P (accumulator))
492 return 0;
493
494 return (REGNO (dest) == REGNO (accumulator));
495 }
496
497 /* Return non-zero if the consumer (a multiply-accumulate instruction)
498 has an accumulator dependency on the result of the producer (a
499 multiplication instruction) and no other dependency on that result. */
500 int
501 arm_mac_accumulator_is_mul_result (rtx producer, rtx consumer)
502 {
503 rtx mul = PATTERN (producer);
504 rtx mac = PATTERN (consumer);
505 rtx mul_result;
506 rtx mac_op0, mac_op1, mac_acc;
507
508 if (GET_CODE (mul) == COND_EXEC)
509 mul = COND_EXEC_CODE (mul);
510 if (GET_CODE (mac) == COND_EXEC)
511 mac = COND_EXEC_CODE (mac);
512
513 /* Check that mul is of the form (set (...) (mult ...))
514 and mla is of the form (set (...) (plus (mult ...) (...))). */
515 if ((GET_CODE (mul) != SET || GET_CODE (XEXP (mul, 1)) != MULT)
516 || (GET_CODE (mac) != SET || GET_CODE (XEXP (mac, 1)) != PLUS
517 || GET_CODE (XEXP (XEXP (mac, 1), 0)) != MULT))
518 return 0;
519
520 mul_result = XEXP (mul, 0);
521 mac_op0 = XEXP (XEXP (XEXP (mac, 1), 0), 0);
522 mac_op1 = XEXP (XEXP (XEXP (mac, 1), 0), 1);
523 mac_acc = XEXP (XEXP (mac, 1), 1);
524
525 return (reg_overlap_mentioned_p (mul_result, mac_acc)
526 && !reg_overlap_mentioned_p (mul_result, mac_op0)
527 && !reg_overlap_mentioned_p (mul_result, mac_op1));
528 }
529
530 /* Worker function for TARGET_MD_ASM_ADJUST.
531 We implement asm flag outputs. */
532
533 rtx_insn *
534 arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
535 vec<const char *> &constraints,
536 vec<rtx> &/*clobbers*/, HARD_REG_SET &/*clobbered_regs*/)
537 {
538 bool saw_asm_flag = false;
539
540 start_sequence ();
541 for (unsigned i = 0, n = outputs.length (); i < n; ++i)
542 {
543 const char *con = constraints[i];
544 if (strncmp (con, "=@cc", 4) != 0)
545 continue;
546 con += 4;
547 if (strchr (con, ',') != NULL)
548 {
549 error ("alternatives not allowed in %<asm%> flag output");
550 continue;
551 }
552
553 machine_mode mode;
554 rtx_code code;
555 int con01 = 0;
556
557 #define C(X, Y) (unsigned char)(X) * 256 + (unsigned char)(Y)
558
559 /* All of the condition codes are two characters. */
560 if (con[0] != 0 && con[1] != 0 && con[2] == 0)
561 con01 = C(con[0], con[1]);
562
563 switch (con01)
564 {
565 case C('c', 'c'):
566 case C('l', 'o'):
567 mode = CC_Cmode, code = GEU;
568 break;
569 case C('c', 's'):
570 case C('h', 's'):
571 mode = CC_Cmode, code = LTU;
572 break;
573 case C('e', 'q'):
574 mode = CC_NZmode, code = EQ;
575 break;
576 case C('g', 'e'):
577 mode = CCmode, code = GE;
578 break;
579 case C('g', 't'):
580 mode = CCmode, code = GT;
581 break;
582 case C('h', 'i'):
583 mode = CCmode, code = GTU;
584 break;
585 case C('l', 'e'):
586 mode = CCmode, code = LE;
587 break;
588 case C('l', 's'):
589 mode = CCmode, code = LEU;
590 break;
591 case C('l', 't'):
592 mode = CCmode, code = LT;
593 break;
594 case C('m', 'i'):
595 mode = CC_NZmode, code = LT;
596 break;
597 case C('n', 'e'):
598 mode = CC_NZmode, code = NE;
599 break;
600 case C('p', 'l'):
601 mode = CC_NZmode, code = GE;
602 break;
603 case C('v', 'c'):
604 mode = CC_Vmode, code = EQ;
605 break;
606 case C('v', 's'):
607 mode = CC_Vmode, code = NE;
608 break;
609 default:
610 error ("unknown %<asm%> flag output %qs", constraints[i]);
611 continue;
612 }
613
614 #undef C
615
616 rtx dest = outputs[i];
617 machine_mode dest_mode = GET_MODE (dest);
618 if (!SCALAR_INT_MODE_P (dest_mode))
619 {
620 error ("invalid type for %<asm%> flag output");
621 continue;
622 }
623
624 if (!saw_asm_flag)
625 {
626 /* This is the first asm flag output. Here we put the flags
627 register in as the real output and adjust the condition to
628 allow it. */
629 constraints[i] = "=c";
630 outputs[i] = gen_rtx_REG (CCmode, CC_REGNUM);
631 saw_asm_flag = true;
632 }
633 else
634 {
635 /* We don't need the flags register as output twice. */
636 constraints[i] = "=X";
637 outputs[i] = gen_rtx_SCRATCH (word_mode);
638 }
639
640 rtx x = gen_rtx_REG (mode, CC_REGNUM);
641 x = gen_rtx_fmt_ee (code, word_mode, x, const0_rtx);
642
643 if (dest_mode == word_mode)
644 emit_insn (gen_rtx_SET (dest, x));
645 else
646 {
647 rtx tmp = gen_reg_rtx (word_mode);
648 emit_insn (gen_rtx_SET (tmp, x));
649
650 tmp = convert_modes (dest_mode, word_mode, tmp, true);
651 emit_move_insn (dest, tmp);
652 }
653 }
654 rtx_insn *seq = get_insns ();
655 end_sequence ();
656
657 return saw_asm_flag ? seq : NULL;
658 }