]>
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-2019 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"
34 /* Return TRUE if X is either an arithmetic shift left, or
35 is a multiplication by a power of two. */
37 arm_rtx_shift_left_p (rtx x
)
39 enum rtx_code code
= GET_CODE (x
);
41 if (code
== MULT
&& CONST_INT_P (XEXP (x
, 1))
42 && exact_log2 (INTVAL (XEXP (x
, 1))) > 0)
51 static rtx_code shift_rtx_codes
[] =
52 { ASHIFT
, ROTATE
, ASHIFTRT
, LSHIFTRT
,
53 ROTATERT
, ZERO_EXTEND
, SIGN_EXTEND
};
55 /* Traverse PATTERN looking for a sub-rtx with RTX_CODE CODE.
56 If FIND_ANY_SHIFT then we are interested in anything which can
57 reasonably be described as a SHIFT RTX. */
59 arm_find_sub_rtx_with_code (rtx pattern
, rtx_code code
, bool find_any_shift
)
61 subrtx_var_iterator::array_type array
;
62 FOR_EACH_SUBRTX_VAR (iter
, array
, pattern
, NONCONST
)
67 /* Left shifts might have been canonicalized to a MULT of some
68 power of two. Make sure we catch them. */
69 if (arm_rtx_shift_left_p (x
))
72 for (unsigned int i
= 0; i
< ARRAY_SIZE (shift_rtx_codes
); i
++)
73 if (GET_CODE (x
) == shift_rtx_codes
[i
])
77 if (GET_CODE (x
) == code
)
83 /* Traverse PATTERN looking for any sub-rtx which looks like a shift. */
85 arm_find_shift_sub_rtx (rtx pattern
)
87 return arm_find_sub_rtx_with_code (pattern
, ASHIFT
, true);
90 /* PRODUCER and CONSUMER are two potentially dependant RTX. PRODUCER
91 (possibly) contains a SET which will provide a result we can access
92 using the SET_DEST macro. We will place the RTX which would be
93 written by PRODUCER in SET_SOURCE.
94 Similarly, CONSUMER (possibly) contains a SET which has an operand
95 we can access using SET_SRC. We place this operand in
98 Return nonzero if we found the SET RTX we expected. */
100 arm_get_set_operands (rtx producer
, rtx consumer
,
101 rtx
*set_source
, rtx
*set_destination
)
103 rtx set_producer
= arm_find_sub_rtx_with_code (PATTERN (producer
),
105 rtx set_consumer
= arm_find_sub_rtx_with_code (PATTERN (consumer
),
108 if (set_producer
&& set_consumer
)
110 *set_source
= SET_DEST (set_producer
);
111 *set_destination
= SET_SRC (set_consumer
);
118 aarch_rev16_shright_mask_imm_p (rtx val
, machine_mode mode
)
120 return CONST_INT_P (val
)
122 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff),
127 aarch_rev16_shleft_mask_imm_p (rtx val
, machine_mode mode
)
129 return CONST_INT_P (val
)
131 == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff00),
137 aarch_rev16_p_1 (rtx lhs
, rtx rhs
, machine_mode mode
)
139 if (GET_CODE (lhs
) == AND
140 && GET_CODE (XEXP (lhs
, 0)) == ASHIFT
141 && CONST_INT_P (XEXP (XEXP (lhs
, 0), 1))
142 && INTVAL (XEXP (XEXP (lhs
, 0), 1)) == 8
143 && REG_P (XEXP (XEXP (lhs
, 0), 0))
144 && CONST_INT_P (XEXP (lhs
, 1))
145 && GET_CODE (rhs
) == AND
146 && GET_CODE (XEXP (rhs
, 0)) == LSHIFTRT
147 && REG_P (XEXP (XEXP (rhs
, 0), 0))
148 && CONST_INT_P (XEXP (XEXP (rhs
, 0), 1))
149 && INTVAL (XEXP (XEXP (rhs
, 0), 1)) == 8
150 && CONST_INT_P (XEXP (rhs
, 1))
151 && REGNO (XEXP (XEXP (rhs
, 0), 0)) == REGNO (XEXP (XEXP (lhs
, 0), 0)))
154 rtx lhs_mask
= XEXP (lhs
, 1);
155 rtx rhs_mask
= XEXP (rhs
, 1);
157 return aarch_rev16_shright_mask_imm_p (rhs_mask
, mode
)
158 && aarch_rev16_shleft_mask_imm_p (lhs_mask
, mode
);
164 /* Recognise a sequence of bitwise operations corresponding to a rev16 operation.
165 These will be of the form:
166 ((x >> 8) & 0x00ff00ff)
167 | ((x << 8) & 0xff00ff00)
168 for SImode and with similar but wider bitmasks for DImode.
169 The two sub-expressions of the IOR can appear on either side so check both
170 permutations with the help of aarch_rev16_p_1 above. */
173 aarch_rev16_p (rtx x
)
175 rtx left_sub_rtx
, right_sub_rtx
;
178 if (GET_CODE (x
) != IOR
)
181 left_sub_rtx
= XEXP (x
, 0);
182 right_sub_rtx
= XEXP (x
, 1);
184 /* There are no canonicalisation rules for the position of the two shifts
185 involved in a rev, so try both permutations. */
186 is_rev
= aarch_rev16_p_1 (left_sub_rtx
, right_sub_rtx
, GET_MODE (x
));
189 is_rev
= aarch_rev16_p_1 (right_sub_rtx
, left_sub_rtx
, GET_MODE (x
));
194 /* Return non-zero if the RTX representing a memory model is a memory model
195 that needs acquire semantics. */
197 aarch_mm_needs_acquire (rtx const_int
)
199 enum memmodel model
= memmodel_from_int (INTVAL (const_int
));
200 return !(is_mm_relaxed (model
)
201 || is_mm_consume (model
)
202 || is_mm_release (model
));
205 /* Return non-zero if the RTX representing a memory model is a memory model
206 that needs release semantics. */
208 aarch_mm_needs_release (rtx const_int
)
210 enum memmodel model
= memmodel_from_int (INTVAL (const_int
));
211 return !(is_mm_relaxed (model
)
212 || is_mm_consume (model
)
213 || is_mm_acquire (model
));
216 /* Return nonzero if the CONSUMER instruction (a load) does need
217 PRODUCER's value to calculate the address. */
219 arm_early_load_addr_dep (rtx producer
, rtx consumer
)
223 if (!arm_get_set_operands (producer
, consumer
, &value
, &addr
))
226 return reg_overlap_mentioned_p (value
, addr
);
229 /* Return nonzero if the CONSUMER instruction (a load) does need
230 a Pmode PRODUCER's value to calculate the address. */
233 arm_early_load_addr_dep_ptr (rtx producer
, rtx consumer
)
235 rtx value
= arm_find_sub_rtx_with_code (PATTERN (producer
), SET
, false);
236 rtx addr
= arm_find_sub_rtx_with_code (PATTERN (consumer
), SET
, false);
238 if (!value
|| !addr
|| !MEM_P (SET_SRC (value
)))
241 value
= SET_DEST (value
);
242 addr
= SET_SRC (addr
);
244 return GET_MODE (value
) == Pmode
&& reg_overlap_mentioned_p (value
, addr
);
247 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
248 have an early register shift value or amount dependency on the
249 result of PRODUCER. */
251 arm_no_early_alu_shift_dep (rtx producer
, rtx consumer
)
256 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
259 if ((early_op
= arm_find_shift_sub_rtx (op
)))
260 return !reg_overlap_mentioned_p (value
, early_op
);
265 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
266 have an early register shift value dependency on the result of
269 arm_no_early_alu_shift_value_dep (rtx producer
, rtx consumer
)
274 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
277 if ((early_op
= arm_find_shift_sub_rtx (op
)))
278 /* We want to check the value being shifted. */
279 if (!reg_overlap_mentioned_p (value
, XEXP (early_op
, 0)))
285 /* Return nonzero if the CONSUMER (a mul or mac op) does not
286 have an early register mult dependency on the result of
289 arm_no_early_mul_dep (rtx producer
, rtx consumer
)
293 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
296 if (GET_CODE (op
) == PLUS
|| GET_CODE (op
) == MINUS
)
298 if (GET_CODE (XEXP (op
, 0)) == MULT
)
299 return !reg_overlap_mentioned_p (value
, XEXP (op
, 0));
301 return !reg_overlap_mentioned_p (value
, XEXP (op
, 1));
307 /* Return nonzero if the CONSUMER instruction (a store) does not need
308 PRODUCER's value to calculate the address. */
311 arm_no_early_store_addr_dep (rtx producer
, rtx consumer
)
313 rtx value
= arm_find_sub_rtx_with_code (PATTERN (producer
), SET
, false);
314 rtx addr
= arm_find_sub_rtx_with_code (PATTERN (consumer
), SET
, false);
317 value
= SET_DEST (value
);
320 addr
= SET_DEST (addr
);
325 return !reg_overlap_mentioned_p (value
, addr
);
328 /* Return nonzero if the CONSUMER instruction (a store) does need
329 PRODUCER's value to calculate the address. */
332 arm_early_store_addr_dep (rtx producer
, rtx consumer
)
334 return !arm_no_early_store_addr_dep (producer
, consumer
);
337 /* Return nonzero if the CONSUMER instruction (a store) does need
338 a Pmode PRODUCER's value to calculate the address. */
341 arm_early_store_addr_dep_ptr (rtx producer
, rtx consumer
)
343 rtx value
= arm_find_sub_rtx_with_code (PATTERN (producer
), SET
, false);
344 rtx addr
= arm_find_sub_rtx_with_code (PATTERN (consumer
), SET
, false);
346 if (!value
|| !addr
|| !MEM_P (SET_SRC (value
)))
349 value
= SET_DEST (value
);
350 addr
= SET_DEST (addr
);
352 return GET_MODE (value
) == Pmode
&& reg_overlap_mentioned_p (value
, addr
);
355 /* Return non-zero iff the consumer (a multiply-accumulate or a
356 multiple-subtract instruction) has an accumulator dependency on the
357 result of the producer and no other dependency on that result. It
358 does not check if the producer is multiply-accumulate instruction. */
360 arm_mac_accumulator_is_result (rtx producer
, rtx consumer
)
365 producer
= PATTERN (producer
);
366 consumer
= PATTERN (consumer
);
368 if (GET_CODE (producer
) == COND_EXEC
)
369 producer
= COND_EXEC_CODE (producer
);
370 if (GET_CODE (consumer
) == COND_EXEC
)
371 consumer
= COND_EXEC_CODE (consumer
);
373 if (GET_CODE (producer
) != SET
)
376 result
= XEXP (producer
, 0);
378 if (GET_CODE (consumer
) != SET
)
381 /* Check that the consumer is of the form
382 (set (...) (plus (mult ...) (...)))
384 (set (...) (minus (...) (mult ...))). */
385 if (GET_CODE (XEXP (consumer
, 1)) == PLUS
)
387 if (GET_CODE (XEXP (XEXP (consumer
, 1), 0)) != MULT
)
390 op0
= XEXP (XEXP (XEXP (consumer
, 1), 0), 0);
391 op1
= XEXP (XEXP (XEXP (consumer
, 1), 0), 1);
392 acc
= XEXP (XEXP (consumer
, 1), 1);
394 else if (GET_CODE (XEXP (consumer
, 1)) == MINUS
)
396 if (GET_CODE (XEXP (XEXP (consumer
, 1), 1)) != MULT
)
399 op0
= XEXP (XEXP (XEXP (consumer
, 1), 1), 0);
400 op1
= XEXP (XEXP (XEXP (consumer
, 1), 1), 1);
401 acc
= XEXP (XEXP (consumer
, 1), 0);
406 return (reg_overlap_mentioned_p (result
, acc
)
407 && !reg_overlap_mentioned_p (result
, op0
)
408 && !reg_overlap_mentioned_p (result
, op1
));
411 /* Return non-zero if the destination of PRODUCER feeds the accumulator
412 operand of an MLA-like operation. */
415 aarch_accumulator_forwarding (rtx_insn
*producer
, rtx_insn
*consumer
)
417 rtx producer_set
= single_set (producer
);
418 rtx consumer_set
= single_set (consumer
);
420 /* We are looking for a SET feeding a SET. */
421 if (!producer_set
|| !consumer_set
)
424 rtx dest
= SET_DEST (producer_set
);
425 rtx mla
= SET_SRC (consumer_set
);
427 /* We're looking for a register SET. */
433 /* Strip a zero_extend. */
434 if (GET_CODE (mla
) == ZERO_EXTEND
)
437 switch (GET_CODE (mla
))
440 /* Possibly an MADD. */
441 if (GET_CODE (XEXP (mla
, 0)) == MULT
)
442 accumulator
= XEXP (mla
, 1);
447 /* Possibly an MSUB. */
448 if (GET_CODE (XEXP (mla
, 1)) == MULT
)
449 accumulator
= XEXP (mla
, 0);
455 /* Possibly an FMADD/FMSUB/FNMADD/FNMSUB. */
456 if (REG_P (XEXP (mla
, 1))
457 && REG_P (XEXP (mla
, 2))
458 && (REG_P (XEXP (mla
, 0))
459 || GET_CODE (XEXP (mla
, 0)) == NEG
))
463 accumulator
= XEXP (mla
, 2);
465 else if (REG_P (XEXP (mla
, 1))
466 && GET_CODE (XEXP (mla
, 2)) == NEG
467 && (REG_P (XEXP (mla
, 0))
468 || GET_CODE (XEXP (mla
, 0)) == NEG
))
471 accumulator
= XEXP (XEXP (mla
, 2), 0);
478 /* Not an MLA-like operation. */
482 if (GET_CODE (accumulator
) == SUBREG
)
483 accumulator
= SUBREG_REG (accumulator
);
485 if (!REG_P (accumulator
))
488 return (REGNO (dest
) == REGNO (accumulator
));
491 /* Return non-zero if the consumer (a multiply-accumulate instruction)
492 has an accumulator dependency on the result of the producer (a
493 multiplication instruction) and no other dependency on that result. */
495 arm_mac_accumulator_is_mul_result (rtx producer
, rtx consumer
)
497 rtx mul
= PATTERN (producer
);
498 rtx mac
= PATTERN (consumer
);
500 rtx mac_op0
, mac_op1
, mac_acc
;
502 if (GET_CODE (mul
) == COND_EXEC
)
503 mul
= COND_EXEC_CODE (mul
);
504 if (GET_CODE (mac
) == COND_EXEC
)
505 mac
= COND_EXEC_CODE (mac
);
507 /* Check that mul is of the form (set (...) (mult ...))
508 and mla is of the form (set (...) (plus (mult ...) (...))). */
509 if ((GET_CODE (mul
) != SET
|| GET_CODE (XEXP (mul
, 1)) != MULT
)
510 || (GET_CODE (mac
) != SET
|| GET_CODE (XEXP (mac
, 1)) != PLUS
511 || GET_CODE (XEXP (XEXP (mac
, 1), 0)) != MULT
))
514 mul_result
= XEXP (mul
, 0);
515 mac_op0
= XEXP (XEXP (XEXP (mac
, 1), 0), 0);
516 mac_op1
= XEXP (XEXP (XEXP (mac
, 1), 0), 1);
517 mac_acc
= XEXP (XEXP (mac
, 1), 1);
519 return (reg_overlap_mentioned_p (mul_result
, mac_acc
)
520 && !reg_overlap_mentioned_p (mul_result
, mac_op0
)
521 && !reg_overlap_mentioned_p (mul_result
, mac_op1
));