]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/aarch-common.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / arm / aarch-common.c
CommitLineData
015adf41 1/* Dependency checks for instruction scheduling, shared between ARM and
2 AARCH64.
3
fbd26352 4 Copyright (C) 1991-2019 Free Software Foundation, Inc.
015adf41 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
785790dc 24#define IN_TARGET_CODE 1
25
015adf41 26#include "config.h"
27#include "system.h"
28#include "coretypes.h"
29#include "tm.h"
015adf41 30#include "rtl.h"
fad99894 31#include "rtl-iter.h"
50bfed1c 32#include "memmodel.h"
015adf41 33
98d7984b 34/* In ARMv8-A there's a general expectation that AESE/AESMC
35 and AESD/AESIMC sequences of the form:
36
37 AESE Vn, _
38 AESMC Vn, Vn
39
40 will issue both instructions in a single cycle on super-scalar
41 implementations. This function identifies such pairs. */
42
43int
50fc2d35 44aarch_crypto_can_dual_issue (rtx_insn *producer_insn, rtx_insn *consumer_insn)
98d7984b 45{
50fc2d35 46 rtx producer_set, consumer_set;
98d7984b 47 rtx producer_src, consumer_src;
48
50fc2d35 49 producer_set = single_set (producer_insn);
50 consumer_set = single_set (consumer_insn);
98d7984b 51
50fc2d35 52 producer_src = producer_set ? SET_SRC (producer_set) : NULL;
53 consumer_src = consumer_set ? SET_SRC (consumer_set) : NULL;
98d7984b 54
55 if (producer_src && consumer_src
56 && GET_CODE (producer_src) == UNSPEC && GET_CODE (consumer_src) == UNSPEC
57 && ((XINT (producer_src, 1) == UNSPEC_AESE
58 && XINT (consumer_src, 1) == UNSPEC_AESMC)
59 || (XINT (producer_src, 1) == UNSPEC_AESD
60 && XINT (consumer_src, 1) == UNSPEC_AESIMC)))
61 {
50fc2d35 62 unsigned int regno = REGNO (SET_DEST (producer_set));
98d7984b 63
f367ec4c 64 /* Before reload the registers are virtual, so the destination of
65 consumer_set doesn't need to match. */
66
67 return (REGNO (SET_DEST (consumer_set)) == regno || !reload_completed)
68 && REGNO (XVECEXP (consumer_src, 0, 0)) == regno;
98d7984b 69 }
70
71 return 0;
72}
73
4c849ae7 74/* Return TRUE if X is either an arithmetic shift left, or
75 is a multiplication by a power of two. */
daac2ec8 76bool
4c849ae7 77arm_rtx_shift_left_p (rtx x)
78{
79 enum rtx_code code = GET_CODE (x);
dff74f11 80
4c849ae7 81 if (code == MULT && CONST_INT_P (XEXP (x, 1))
82 && exact_log2 (INTVAL (XEXP (x, 1))) > 0)
83 return true;
84
85 if (code == ASHIFT)
86 return true;
87
88 return false;
89}
90
91static rtx_code shift_rtx_codes[] =
92 { ASHIFT, ROTATE, ASHIFTRT, LSHIFTRT,
93 ROTATERT, ZERO_EXTEND, SIGN_EXTEND };
94
fad99894 95/* Traverse PATTERN looking for a sub-rtx with RTX_CODE CODE.
96 If FIND_ANY_SHIFT then we are interested in anything which can
97 reasonably be described as a SHIFT RTX. */
4c849ae7 98static rtx
99arm_find_sub_rtx_with_code (rtx pattern, rtx_code code, bool find_any_shift)
100{
fad99894 101 subrtx_var_iterator::array_type array;
102 FOR_EACH_SUBRTX_VAR (iter, array, pattern, NONCONST)
103 {
104 rtx x = *iter;
105 if (find_any_shift)
106 {
107 /* Left shifts might have been canonicalized to a MULT of some
108 power of two. Make sure we catch them. */
109 if (arm_rtx_shift_left_p (x))
110 return x;
111 else
112 for (unsigned int i = 0; i < ARRAY_SIZE (shift_rtx_codes); i++)
113 if (GET_CODE (x) == shift_rtx_codes[i])
114 return x;
115 }
116
117 if (GET_CODE (x) == code)
118 return x;
119 }
120 return NULL_RTX;
4c849ae7 121}
122
123/* Traverse PATTERN looking for any sub-rtx which looks like a shift. */
124static rtx
125arm_find_shift_sub_rtx (rtx pattern)
126{
127 return arm_find_sub_rtx_with_code (pattern, ASHIFT, true);
128}
129
130/* PRODUCER and CONSUMER are two potentially dependant RTX. PRODUCER
131 (possibly) contains a SET which will provide a result we can access
132 using the SET_DEST macro. We will place the RTX which would be
133 written by PRODUCER in SET_SOURCE.
134 Similarly, CONSUMER (possibly) contains a SET which has an operand
135 we can access using SET_SRC. We place this operand in
136 SET_DESTINATION.
137
138 Return nonzero if we found the SET RTX we expected. */
139static int
140arm_get_set_operands (rtx producer, rtx consumer,
141 rtx *set_source, rtx *set_destination)
142{
fad99894 143 rtx set_producer = arm_find_sub_rtx_with_code (PATTERN (producer),
144 SET, false);
145 rtx set_consumer = arm_find_sub_rtx_with_code (PATTERN (consumer),
146 SET, false);
4c849ae7 147
148 if (set_producer && set_consumer)
149 {
150 *set_source = SET_DEST (set_producer);
151 *set_destination = SET_SRC (set_consumer);
152 return 1;
153 }
154 return 0;
155}
156
d049924d 157bool
3754d046 158aarch_rev16_shright_mask_imm_p (rtx val, machine_mode mode)
d049924d 159{
160 return CONST_INT_P (val)
4ea1b263 161 && INTVAL (val)
162 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff),
163 mode);
d049924d 164}
165
166bool
3754d046 167aarch_rev16_shleft_mask_imm_p (rtx val, machine_mode mode)
d049924d 168{
169 return CONST_INT_P (val)
4ea1b263 170 && INTVAL (val)
171 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff00),
172 mode);
d049924d 173}
174
175
176static bool
3754d046 177aarch_rev16_p_1 (rtx lhs, rtx rhs, machine_mode mode)
d049924d 178{
179 if (GET_CODE (lhs) == AND
180 && GET_CODE (XEXP (lhs, 0)) == ASHIFT
181 && CONST_INT_P (XEXP (XEXP (lhs, 0), 1))
182 && INTVAL (XEXP (XEXP (lhs, 0), 1)) == 8
183 && REG_P (XEXP (XEXP (lhs, 0), 0))
184 && CONST_INT_P (XEXP (lhs, 1))
185 && GET_CODE (rhs) == AND
186 && GET_CODE (XEXP (rhs, 0)) == LSHIFTRT
187 && REG_P (XEXP (XEXP (rhs, 0), 0))
188 && CONST_INT_P (XEXP (XEXP (rhs, 0), 1))
189 && INTVAL (XEXP (XEXP (rhs, 0), 1)) == 8
190 && CONST_INT_P (XEXP (rhs, 1))
191 && REGNO (XEXP (XEXP (rhs, 0), 0)) == REGNO (XEXP (XEXP (lhs, 0), 0)))
192
193 {
194 rtx lhs_mask = XEXP (lhs, 1);
195 rtx rhs_mask = XEXP (rhs, 1);
196
197 return aarch_rev16_shright_mask_imm_p (rhs_mask, mode)
198 && aarch_rev16_shleft_mask_imm_p (lhs_mask, mode);
199 }
200
201 return false;
202}
203
204/* Recognise a sequence of bitwise operations corresponding to a rev16 operation.
205 These will be of the form:
206 ((x >> 8) & 0x00ff00ff)
207 | ((x << 8) & 0xff00ff00)
208 for SImode and with similar but wider bitmasks for DImode.
209 The two sub-expressions of the IOR can appear on either side so check both
210 permutations with the help of aarch_rev16_p_1 above. */
211
212bool
213aarch_rev16_p (rtx x)
214{
215 rtx left_sub_rtx, right_sub_rtx;
216 bool is_rev = false;
217
218 if (GET_CODE (x) != IOR)
219 return false;
220
221 left_sub_rtx = XEXP (x, 0);
222 right_sub_rtx = XEXP (x, 1);
223
224 /* There are no canonicalisation rules for the position of the two shifts
225 involved in a rev, so try both permutations. */
226 is_rev = aarch_rev16_p_1 (left_sub_rtx, right_sub_rtx, GET_MODE (x));
227
228 if (!is_rev)
229 is_rev = aarch_rev16_p_1 (right_sub_rtx, left_sub_rtx, GET_MODE (x));
230
231 return is_rev;
232}
233
50bfed1c 234/* Return non-zero if the RTX representing a memory model is a memory model
235 that needs acquire semantics. */
236bool
237aarch_mm_needs_acquire (rtx const_int)
238{
239 enum memmodel model = memmodel_from_int (INTVAL (const_int));
240 return !(is_mm_relaxed (model)
241 || is_mm_consume (model)
242 || is_mm_release (model));
243}
244
245/* Return non-zero if the RTX representing a memory model is a memory model
246 that needs release semantics. */
247bool
248aarch_mm_needs_release (rtx const_int)
249{
250 enum memmodel model = memmodel_from_int (INTVAL (const_int));
251 return !(is_mm_relaxed (model)
252 || is_mm_consume (model)
253 || is_mm_acquire (model));
254}
255
4c849ae7 256/* Return nonzero if the CONSUMER instruction (a load) does need
257 PRODUCER's value to calculate the address. */
258int
259arm_early_load_addr_dep (rtx producer, rtx consumer)
260{
261 rtx value, addr;
262
263 if (!arm_get_set_operands (producer, consumer, &value, &addr))
264 return 0;
015adf41 265
266 return reg_overlap_mentioned_p (value, addr);
267}
268
441e8134 269/* Return nonzero if the CONSUMER instruction (a load) does need
270 a Pmode PRODUCER's value to calculate the address. */
271
272int
273arm_early_load_addr_dep_ptr (rtx producer, rtx consumer)
274{
275 rtx value = arm_find_sub_rtx_with_code (PATTERN (producer), SET, false);
276 rtx addr = arm_find_sub_rtx_with_code (PATTERN (consumer), SET, false);
277
278 if (!value || !addr || !MEM_P (SET_SRC (value)))
279 return 0;
280
281 value = SET_DEST (value);
282 addr = SET_SRC (addr);
283
284 return GET_MODE (value) == Pmode && reg_overlap_mentioned_p (value, addr);
285}
286
015adf41 287/* Return nonzero if the CONSUMER instruction (an ALU op) does not
288 have an early register shift value or amount dependency on the
289 result of PRODUCER. */
015adf41 290int
291arm_no_early_alu_shift_dep (rtx producer, rtx consumer)
292{
4c849ae7 293 rtx value, op;
015adf41 294 rtx early_op;
295
4c849ae7 296 if (!arm_get_set_operands (producer, consumer, &value, &op))
297 return 0;
298
299 if ((early_op = arm_find_shift_sub_rtx (op)))
5f43aafa 300 return !reg_overlap_mentioned_p (value, early_op);
4c849ae7 301
302 return 0;
015adf41 303}
304
305/* Return nonzero if the CONSUMER instruction (an ALU op) does not
306 have an early register shift value dependency on the result of
307 PRODUCER. */
015adf41 308int
309arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer)
310{
4c849ae7 311 rtx value, op;
015adf41 312 rtx early_op;
313
4c849ae7 314 if (!arm_get_set_operands (producer, consumer, &value, &op))
315 return 0;
316
317 if ((early_op = arm_find_shift_sub_rtx (op)))
318 /* We want to check the value being shifted. */
319 if (!reg_overlap_mentioned_p (value, XEXP (early_op, 0)))
320 return 1;
321
322 return 0;
015adf41 323}
324
325/* Return nonzero if the CONSUMER (a mul or mac op) does not
326 have an early register mult dependency on the result of
327 PRODUCER. */
015adf41 328int
329arm_no_early_mul_dep (rtx producer, rtx consumer)
330{
4c849ae7 331 rtx value, op;
332
333 if (!arm_get_set_operands (producer, consumer, &value, &op))
334 return 0;
015adf41 335
336 if (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
337 {
338 if (GET_CODE (XEXP (op, 0)) == MULT)
339 return !reg_overlap_mentioned_p (value, XEXP (op, 0));
340 else
341 return !reg_overlap_mentioned_p (value, XEXP (op, 1));
342 }
343
344 return 0;
345}
346
347/* Return nonzero if the CONSUMER instruction (a store) does not need
348 PRODUCER's value to calculate the address. */
349
350int
351arm_no_early_store_addr_dep (rtx producer, rtx consumer)
352{
fad99894 353 rtx value = arm_find_sub_rtx_with_code (PATTERN (producer), SET, false);
354 rtx addr = arm_find_sub_rtx_with_code (PATTERN (consumer), SET, false);
4c849ae7 355
356 if (value)
357 value = SET_DEST (value);
358
359 if (addr)
360 addr = SET_DEST (addr);
361
362 if (!value || !addr)
363 return 0;
015adf41 364
365 return !reg_overlap_mentioned_p (value, addr);
366}
367
368/* Return nonzero if the CONSUMER instruction (a store) does need
369 PRODUCER's value to calculate the address. */
370
371int
372arm_early_store_addr_dep (rtx producer, rtx consumer)
373{
374 return !arm_no_early_store_addr_dep (producer, consumer);
375}
376
441e8134 377/* Return nonzero if the CONSUMER instruction (a store) does need
378 a Pmode PRODUCER's value to calculate the address. */
379
380int
381arm_early_store_addr_dep_ptr (rtx producer, rtx consumer)
382{
383 rtx value = arm_find_sub_rtx_with_code (PATTERN (producer), SET, false);
384 rtx addr = arm_find_sub_rtx_with_code (PATTERN (consumer), SET, false);
385
386 if (!value || !addr || !MEM_P (SET_SRC (value)))
387 return 0;
388
389 value = SET_DEST (value);
390 addr = SET_DEST (addr);
391
392 return GET_MODE (value) == Pmode && reg_overlap_mentioned_p (value, addr);
393}
394
015adf41 395/* Return non-zero iff the consumer (a multiply-accumulate or a
396 multiple-subtract instruction) has an accumulator dependency on the
397 result of the producer and no other dependency on that result. It
398 does not check if the producer is multiply-accumulate instruction. */
399int
400arm_mac_accumulator_is_result (rtx producer, rtx consumer)
401{
402 rtx result;
403 rtx op0, op1, acc;
404
405 producer = PATTERN (producer);
406 consumer = PATTERN (consumer);
407
408 if (GET_CODE (producer) == COND_EXEC)
409 producer = COND_EXEC_CODE (producer);
410 if (GET_CODE (consumer) == COND_EXEC)
411 consumer = COND_EXEC_CODE (consumer);
412
413 if (GET_CODE (producer) != SET)
414 return 0;
415
416 result = XEXP (producer, 0);
417
418 if (GET_CODE (consumer) != SET)
419 return 0;
420
421 /* Check that the consumer is of the form
422 (set (...) (plus (mult ...) (...)))
423 or
424 (set (...) (minus (...) (mult ...))). */
425 if (GET_CODE (XEXP (consumer, 1)) == PLUS)
426 {
427 if (GET_CODE (XEXP (XEXP (consumer, 1), 0)) != MULT)
428 return 0;
429
430 op0 = XEXP (XEXP (XEXP (consumer, 1), 0), 0);
431 op1 = XEXP (XEXP (XEXP (consumer, 1), 0), 1);
432 acc = XEXP (XEXP (consumer, 1), 1);
433 }
434 else if (GET_CODE (XEXP (consumer, 1)) == MINUS)
435 {
436 if (GET_CODE (XEXP (XEXP (consumer, 1), 1)) != MULT)
437 return 0;
438
439 op0 = XEXP (XEXP (XEXP (consumer, 1), 1), 0);
440 op1 = XEXP (XEXP (XEXP (consumer, 1), 1), 1);
441 acc = XEXP (XEXP (consumer, 1), 0);
442 }
443 else
444 return 0;
445
446 return (reg_overlap_mentioned_p (result, acc)
447 && !reg_overlap_mentioned_p (result, op0)
448 && !reg_overlap_mentioned_p (result, op1));
449}
450
08993ad1 451/* Return non-zero if the destination of PRODUCER feeds the accumulator
452 operand of an MLA-like operation. */
453
454int
455aarch_accumulator_forwarding (rtx_insn *producer, rtx_insn *consumer)
456{
457 rtx producer_set = single_set (producer);
458 rtx consumer_set = single_set (consumer);
459
460 /* We are looking for a SET feeding a SET. */
461 if (!producer_set || !consumer_set)
462 return 0;
463
464 rtx dest = SET_DEST (producer_set);
465 rtx mla = SET_SRC (consumer_set);
466
467 /* We're looking for a register SET. */
468 if (!REG_P (dest))
469 return 0;
470
471 rtx accumulator;
472
473 /* Strip a zero_extend. */
474 if (GET_CODE (mla) == ZERO_EXTEND)
475 mla = XEXP (mla, 0);
476
477 switch (GET_CODE (mla))
478 {
479 case PLUS:
480 /* Possibly an MADD. */
481 if (GET_CODE (XEXP (mla, 0)) == MULT)
482 accumulator = XEXP (mla, 1);
483 else
484 return 0;
485 break;
486 case MINUS:
487 /* Possibly an MSUB. */
488 if (GET_CODE (XEXP (mla, 1)) == MULT)
489 accumulator = XEXP (mla, 0);
490 else
491 return 0;
492 break;
493 case FMA:
494 {
495 /* Possibly an FMADD/FMSUB/FNMADD/FNMSUB. */
496 if (REG_P (XEXP (mla, 1))
497 && REG_P (XEXP (mla, 2))
498 && (REG_P (XEXP (mla, 0))
499 || GET_CODE (XEXP (mla, 0)) == NEG))
500
501 {
502 /* FMADD/FMSUB. */
503 accumulator = XEXP (mla, 2);
504 }
505 else if (REG_P (XEXP (mla, 1))
506 && GET_CODE (XEXP (mla, 2)) == NEG
507 && (REG_P (XEXP (mla, 0))
508 || GET_CODE (XEXP (mla, 0)) == NEG))
509 {
510 /* FNMADD/FNMSUB. */
511 accumulator = XEXP (XEXP (mla, 2), 0);
512 }
513 else
514 return 0;
515 break;
516 }
517 default:
518 /* Not an MLA-like operation. */
519 return 0;
520 }
521
74905ec3 522 if (GET_CODE (accumulator) == SUBREG)
523 accumulator = SUBREG_REG (accumulator);
524
525 if (!REG_P (accumulator))
526 return 0;
527
08993ad1 528 return (REGNO (dest) == REGNO (accumulator));
529}
530
015adf41 531/* Return non-zero if the consumer (a multiply-accumulate instruction)
532 has an accumulator dependency on the result of the producer (a
533 multiplication instruction) and no other dependency on that result. */
534int
535arm_mac_accumulator_is_mul_result (rtx producer, rtx consumer)
536{
537 rtx mul = PATTERN (producer);
538 rtx mac = PATTERN (consumer);
539 rtx mul_result;
540 rtx mac_op0, mac_op1, mac_acc;
541
542 if (GET_CODE (mul) == COND_EXEC)
543 mul = COND_EXEC_CODE (mul);
544 if (GET_CODE (mac) == COND_EXEC)
545 mac = COND_EXEC_CODE (mac);
546
547 /* Check that mul is of the form (set (...) (mult ...))
548 and mla is of the form (set (...) (plus (mult ...) (...))). */
549 if ((GET_CODE (mul) != SET || GET_CODE (XEXP (mul, 1)) != MULT)
550 || (GET_CODE (mac) != SET || GET_CODE (XEXP (mac, 1)) != PLUS
551 || GET_CODE (XEXP (XEXP (mac, 1), 0)) != MULT))
552 return 0;
553
554 mul_result = XEXP (mul, 0);
555 mac_op0 = XEXP (XEXP (XEXP (mac, 1), 0), 0);
556 mac_op1 = XEXP (XEXP (XEXP (mac, 1), 0), 1);
557 mac_acc = XEXP (XEXP (mac, 1), 1);
558
559 return (reg_overlap_mentioned_p (mul_result, mac_acc)
560 && !reg_overlap_mentioned_p (mul_result, mac_op0)
561 && !reg_overlap_mentioned_p (mul_result, mac_op1));
562}