]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/aarch-common.c
1 /* Dependency checks for instruction scheduling, shared between ARM and
4 Copyright (C) 1991-2020 Free Software Foundation, Inc.
5 Contributed by ARM Ltd.
7 This file is part of GCC.
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.
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.
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/>. */
24 #define IN_TARGET_CODE 1
28 #include "coretypes.h"
29 #include "insn-modes.h"
34 #include "diagnostic.h"
40 /* Return TRUE if X is either an arithmetic shift left, or
41 is a multiplication by a power of two. */
43 arm_rtx_shift_left_p (rtx x
)
45 enum rtx_code code
= GET_CODE (x
);
47 if (code
== MULT
&& CONST_INT_P (XEXP (x
, 1))
48 && exact_log2 (INTVAL (XEXP (x
, 1))) > 0)
57 static rtx_code shift_rtx_codes
[] =
58 { ASHIFT
, ROTATE
, ASHIFTRT
, LSHIFTRT
,
59 ROTATERT
, ZERO_EXTEND
, SIGN_EXTEND
};
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. */
65 arm_find_sub_rtx_with_code (rtx pattern
, rtx_code code
, bool find_any_shift
)
67 subrtx_var_iterator::array_type array
;
68 FOR_EACH_SUBRTX_VAR (iter
, array
, pattern
, NONCONST
)
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
))
78 for (unsigned int i
= 0; i
< ARRAY_SIZE (shift_rtx_codes
); i
++)
79 if (GET_CODE (x
) == shift_rtx_codes
[i
])
83 if (GET_CODE (x
) == code
)
89 /* Traverse PATTERN looking for any sub-rtx which looks like a shift. */
91 arm_find_shift_sub_rtx (rtx pattern
)
93 return arm_find_sub_rtx_with_code (pattern
, ASHIFT
, true);
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
104 Return nonzero if we found the SET RTX we expected. */
106 arm_get_set_operands (rtx producer
, rtx consumer
,
107 rtx
*set_source
, rtx
*set_destination
)
109 rtx set_producer
= arm_find_sub_rtx_with_code (PATTERN (producer
),
111 rtx set_consumer
= arm_find_sub_rtx_with_code (PATTERN (consumer
),
114 if (set_producer
&& set_consumer
)
116 *set_source
= SET_DEST (set_producer
);
117 *set_destination
= SET_SRC (set_consumer
);
124 aarch_rev16_shright_mask_imm_p (rtx val
, machine_mode mode
)
126 return CONST_INT_P (val
)
128 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff),
133 aarch_rev16_shleft_mask_imm_p (rtx val
, machine_mode mode
)
135 return CONST_INT_P (val
)
137 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff00),
143 aarch_rev16_p_1 (rtx lhs
, rtx rhs
, machine_mode mode
)
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)))
160 rtx lhs_mask
= XEXP (lhs
, 1);
161 rtx rhs_mask
= XEXP (rhs
, 1);
163 return aarch_rev16_shright_mask_imm_p (rhs_mask
, mode
)
164 && aarch_rev16_shleft_mask_imm_p (lhs_mask
, mode
);
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. */
179 aarch_rev16_p (rtx x
)
181 rtx left_sub_rtx
, right_sub_rtx
;
184 if (GET_CODE (x
) != IOR
)
187 left_sub_rtx
= XEXP (x
, 0);
188 right_sub_rtx
= XEXP (x
, 1);
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
));
195 is_rev
= aarch_rev16_p_1 (right_sub_rtx
, left_sub_rtx
, GET_MODE (x
));
200 /* Return non-zero if the RTX representing a memory model is a memory model
201 that needs acquire semantics. */
203 aarch_mm_needs_acquire (rtx const_int
)
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
));
211 /* Return non-zero if the RTX representing a memory model is a memory model
212 that needs release semantics. */
214 aarch_mm_needs_release (rtx const_int
)
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
));
222 /* Return nonzero if the CONSUMER instruction (a load) does need
223 PRODUCER's value to calculate the address. */
225 arm_early_load_addr_dep (rtx producer
, rtx consumer
)
229 if (!arm_get_set_operands (producer
, consumer
, &value
, &addr
))
232 return reg_overlap_mentioned_p (value
, addr
);
235 /* Return nonzero if the CONSUMER instruction (a load) does need
236 a Pmode PRODUCER's value to calculate the address. */
239 arm_early_load_addr_dep_ptr (rtx producer
, rtx consumer
)
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);
244 if (!value
|| !addr
|| !MEM_P (SET_SRC (value
)))
247 value
= SET_DEST (value
);
248 addr
= SET_SRC (addr
);
250 return GET_MODE (value
) == Pmode
&& reg_overlap_mentioned_p (value
, addr
);
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. */
257 arm_no_early_alu_shift_dep (rtx producer
, rtx consumer
)
262 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
265 if ((early_op
= arm_find_shift_sub_rtx (op
)))
266 return !reg_overlap_mentioned_p (value
, early_op
);
271 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
272 have an early register shift value dependency on the result of
275 arm_no_early_alu_shift_value_dep (rtx producer
, rtx consumer
)
280 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
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)))
291 /* Return nonzero if the CONSUMER (a mul or mac op) does not
292 have an early register mult dependency on the result of
295 arm_no_early_mul_dep (rtx producer
, rtx consumer
)
299 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
302 if (GET_CODE (op
) == PLUS
|| GET_CODE (op
) == MINUS
)
304 if (GET_CODE (XEXP (op
, 0)) == MULT
)
305 return !reg_overlap_mentioned_p (value
, XEXP (op
, 0));
307 return !reg_overlap_mentioned_p (value
, XEXP (op
, 1));
313 /* Return nonzero if the CONSUMER instruction (a store) does not need
314 PRODUCER's value to calculate the address. */
317 arm_no_early_store_addr_dep (rtx producer
, rtx consumer
)
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);
323 value
= SET_DEST (value
);
326 addr
= SET_DEST (addr
);
331 return !reg_overlap_mentioned_p (value
, addr
);
334 /* Return nonzero if the CONSUMER instruction (a store) does need
335 PRODUCER's value to calculate the address. */
338 arm_early_store_addr_dep (rtx producer
, rtx consumer
)
340 return !arm_no_early_store_addr_dep (producer
, consumer
);
343 /* Return nonzero if the CONSUMER instruction (a store) does need
344 a Pmode PRODUCER's value to calculate the address. */
347 arm_early_store_addr_dep_ptr (rtx producer
, rtx consumer
)
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);
352 if (!value
|| !addr
|| !MEM_P (SET_SRC (value
)))
355 value
= SET_DEST (value
);
356 addr
= SET_DEST (addr
);
358 return GET_MODE (value
) == Pmode
&& reg_overlap_mentioned_p (value
, addr
);
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. */
366 arm_mac_accumulator_is_result (rtx producer
, rtx consumer
)
371 producer
= PATTERN (producer
);
372 consumer
= PATTERN (consumer
);
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
);
379 if (GET_CODE (producer
) != SET
)
382 result
= XEXP (producer
, 0);
384 if (GET_CODE (consumer
) != SET
)
387 /* Check that the consumer is of the form
388 (set (...) (plus (mult ...) (...)))
390 (set (...) (minus (...) (mult ...))). */
391 if (GET_CODE (XEXP (consumer
, 1)) == PLUS
)
393 if (GET_CODE (XEXP (XEXP (consumer
, 1), 0)) != MULT
)
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);
400 else if (GET_CODE (XEXP (consumer
, 1)) == MINUS
)
402 if (GET_CODE (XEXP (XEXP (consumer
, 1), 1)) != MULT
)
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);
412 return (reg_overlap_mentioned_p (result
, acc
)
413 && !reg_overlap_mentioned_p (result
, op0
)
414 && !reg_overlap_mentioned_p (result
, op1
));
417 /* Return non-zero if the destination of PRODUCER feeds the accumulator
418 operand of an MLA-like operation. */
421 aarch_accumulator_forwarding (rtx_insn
*producer
, rtx_insn
*consumer
)
423 rtx producer_set
= single_set (producer
);
424 rtx consumer_set
= single_set (consumer
);
426 /* We are looking for a SET feeding a SET. */
427 if (!producer_set
|| !consumer_set
)
430 rtx dest
= SET_DEST (producer_set
);
431 rtx mla
= SET_SRC (consumer_set
);
433 /* We're looking for a register SET. */
439 /* Strip a zero_extend. */
440 if (GET_CODE (mla
) == ZERO_EXTEND
)
443 switch (GET_CODE (mla
))
446 /* Possibly an MADD. */
447 if (GET_CODE (XEXP (mla
, 0)) == MULT
)
448 accumulator
= XEXP (mla
, 1);
453 /* Possibly an MSUB. */
454 if (GET_CODE (XEXP (mla
, 1)) == MULT
)
455 accumulator
= XEXP (mla
, 0);
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
))
469 accumulator
= XEXP (mla
, 2);
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
))
477 accumulator
= XEXP (XEXP (mla
, 2), 0);
484 /* Not an MLA-like operation. */
488 if (GET_CODE (accumulator
) == SUBREG
)
489 accumulator
= SUBREG_REG (accumulator
);
491 if (!REG_P (accumulator
))
494 return (REGNO (dest
) == REGNO (accumulator
));
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. */
501 arm_mac_accumulator_is_mul_result (rtx producer
, rtx consumer
)
503 rtx mul
= PATTERN (producer
);
504 rtx mac
= PATTERN (consumer
);
506 rtx mac_op0
, mac_op1
, mac_acc
;
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
);
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
))
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);
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
));
530 /* Worker function for TARGET_MD_ASM_ADJUST.
531 We implement asm flag outputs. */
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*/)
538 bool saw_asm_flag
= false;
541 for (unsigned i
= 0, n
= outputs
.length (); i
< n
; ++i
)
543 const char *con
= constraints
[i
];
544 if (strncmp (con
, "=@cc", 4) != 0)
547 if (strchr (con
, ',') != NULL
)
549 error ("alternatives not allowed in %<asm%> flag output");
557 #define C(X, Y) (unsigned char)(X) * 256 + (unsigned char)(Y)
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]);
567 mode
= CC_Cmode
, code
= GEU
;
571 mode
= CC_Cmode
, code
= LTU
;
574 mode
= CC_NZmode
, code
= EQ
;
577 mode
= CCmode
, code
= GE
;
580 mode
= CCmode
, code
= GT
;
583 mode
= CCmode
, code
= GTU
;
586 mode
= CCmode
, code
= LE
;
589 mode
= CCmode
, code
= LEU
;
592 mode
= CCmode
, code
= LT
;
595 mode
= CC_NZmode
, code
= LT
;
598 mode
= CC_NZmode
, code
= NE
;
601 mode
= CC_NZmode
, code
= GE
;
604 mode
= CC_Vmode
, code
= EQ
;
607 mode
= CC_Vmode
, code
= NE
;
610 error ("unknown %<asm%> flag output %qs", constraints
[i
]);
616 rtx dest
= outputs
[i
];
617 machine_mode dest_mode
= GET_MODE (dest
);
618 if (!SCALAR_INT_MODE_P (dest_mode
))
620 error ("invalid type for %<asm%> flag output");
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
629 constraints
[i
] = "=c";
630 outputs
[i
] = gen_rtx_REG (CCmode
, CC_REGNUM
);
635 /* We don't need the flags register as output twice. */
636 constraints
[i
] = "=X";
637 outputs
[i
] = gen_rtx_SCRATCH (word_mode
);
640 rtx x
= gen_rtx_REG (mode
, CC_REGNUM
);
641 x
= gen_rtx_fmt_ee (code
, word_mode
, x
, const0_rtx
);
643 if (dest_mode
== word_mode
)
644 emit_insn (gen_rtx_SET (dest
, x
));
647 rtx tmp
= gen_reg_rtx (word_mode
);
648 emit_insn (gen_rtx_SET (tmp
, x
));
650 tmp
= convert_modes (dest_mode
, word_mode
, tmp
, true);
651 emit_move_insn (dest
, tmp
);
654 rtx_insn
*seq
= get_insns ();
657 return saw_asm_flag
? seq
: NULL
;