1 /* Dependency checks for instruction scheduling, shared between ARM and
4 Copyright (C) 1991-2014 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/>. */
26 #include "coretypes.h"
31 #include "c-family/c-common.h"
41 /* Return TRUE if X is either an arithmetic shift left, or
42 is a multiplication by a power of two. */
44 arm_rtx_shift_left_p (rtx x
)
46 enum rtx_code code
= GET_CODE (x
);
48 if (code
== MULT
&& CONST_INT_P (XEXP (x
, 1))
49 && exact_log2 (INTVAL (XEXP (x
, 1))) > 0)
58 static rtx_code shift_rtx_codes
[] =
59 { ASHIFT
, ROTATE
, ASHIFTRT
, LSHIFTRT
,
60 ROTATERT
, ZERO_EXTEND
, SIGN_EXTEND
};
62 /* Callback function for arm_find_sub_rtx_with_code.
63 DATA is safe to treat as a SEARCH_TERM, ST. This will
64 hold a SEARCH_CODE. PATTERN is checked to see if it is an
65 RTX with that code. If it is, write SEARCH_RESULT in ST
66 and return 1. Otherwise, or if we have been passed a NULL_RTX
67 return 0. If ST.FIND_ANY_SHIFT then we are interested in
68 anything which can reasonably be described as a SHIFT RTX. */
70 arm_find_sub_rtx_with_search_term (rtx
*pattern
, void *data
)
72 search_term
*st
= (search_term
*) data
;
73 rtx_code pattern_code
;
79 /* Poorly formed patterns can really ruin our day. */
80 if (*pattern
== NULL_RTX
)
83 pattern_code
= GET_CODE (*pattern
);
85 if (st
->find_any_shift
)
89 /* Left shifts might have been canonicalized to a MULT of some
90 power of two. Make sure we catch them. */
91 if (arm_rtx_shift_left_p (*pattern
))
94 for (i
= 0; i
< ARRAY_SIZE (shift_rtx_codes
); i
++)
95 if (pattern_code
== shift_rtx_codes
[i
])
99 if (pattern_code
== st
->search_code
)
103 st
->search_result
= *pattern
;
108 /* Traverse PATTERN looking for a sub-rtx with RTX_CODE CODE. */
110 arm_find_sub_rtx_with_code (rtx pattern
, rtx_code code
, bool find_any_shift
)
115 gcc_assert (pattern
!= NULL_RTX
);
116 st
.search_code
= code
;
117 st
.search_result
= NULL_RTX
;
118 st
.find_any_shift
= find_any_shift
;
119 result
= for_each_rtx (&pattern
, arm_find_sub_rtx_with_search_term
, &st
);
121 return st
.search_result
;
126 /* Traverse PATTERN looking for any sub-rtx which looks like a shift. */
128 arm_find_shift_sub_rtx (rtx pattern
)
130 return arm_find_sub_rtx_with_code (pattern
, ASHIFT
, true);
133 /* PRODUCER and CONSUMER are two potentially dependant RTX. PRODUCER
134 (possibly) contains a SET which will provide a result we can access
135 using the SET_DEST macro. We will place the RTX which would be
136 written by PRODUCER in SET_SOURCE.
137 Similarly, CONSUMER (possibly) contains a SET which has an operand
138 we can access using SET_SRC. We place this operand in
141 Return nonzero if we found the SET RTX we expected. */
143 arm_get_set_operands (rtx producer
, rtx consumer
,
144 rtx
*set_source
, rtx
*set_destination
)
146 rtx set_producer
= arm_find_sub_rtx_with_code (producer
, SET
, false);
147 rtx set_consumer
= arm_find_sub_rtx_with_code (consumer
, SET
, false);
149 if (set_producer
&& set_consumer
)
151 *set_source
= SET_DEST (set_producer
);
152 *set_destination
= SET_SRC (set_consumer
);
158 /* Return nonzero if the CONSUMER instruction (a load) does need
159 PRODUCER's value to calculate the address. */
161 arm_early_load_addr_dep (rtx producer
, rtx consumer
)
165 if (!arm_get_set_operands (producer
, consumer
, &value
, &addr
))
168 return reg_overlap_mentioned_p (value
, addr
);
171 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
172 have an early register shift value or amount dependency on the
173 result of PRODUCER. */
175 arm_no_early_alu_shift_dep (rtx producer
, rtx consumer
)
180 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
183 if ((early_op
= arm_find_shift_sub_rtx (op
)))
185 if (REG_P (early_op
))
188 return !reg_overlap_mentioned_p (value
, early_op
);
194 /* Return nonzero if the CONSUMER instruction (an ALU op) does not
195 have an early register shift value dependency on the result of
198 arm_no_early_alu_shift_value_dep (rtx producer
, rtx consumer
)
203 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
206 if ((early_op
= arm_find_shift_sub_rtx (op
)))
207 /* We want to check the value being shifted. */
208 if (!reg_overlap_mentioned_p (value
, XEXP (early_op
, 0)))
214 /* Return nonzero if the CONSUMER (a mul or mac op) does not
215 have an early register mult dependency on the result of
218 arm_no_early_mul_dep (rtx producer
, rtx consumer
)
222 if (!arm_get_set_operands (producer
, consumer
, &value
, &op
))
225 if (GET_CODE (op
) == PLUS
|| GET_CODE (op
) == MINUS
)
227 if (GET_CODE (XEXP (op
, 0)) == MULT
)
228 return !reg_overlap_mentioned_p (value
, XEXP (op
, 0));
230 return !reg_overlap_mentioned_p (value
, XEXP (op
, 1));
236 /* Return nonzero if the CONSUMER instruction (a store) does not need
237 PRODUCER's value to calculate the address. */
240 arm_no_early_store_addr_dep (rtx producer
, rtx consumer
)
242 rtx value
= arm_find_sub_rtx_with_code (producer
, SET
, false);
243 rtx addr
= arm_find_sub_rtx_with_code (consumer
, SET
, false);
246 value
= SET_DEST (value
);
249 addr
= SET_DEST (addr
);
254 return !reg_overlap_mentioned_p (value
, addr
);
257 /* Return nonzero if the CONSUMER instruction (a store) does need
258 PRODUCER's value to calculate the address. */
261 arm_early_store_addr_dep (rtx producer
, rtx consumer
)
263 return !arm_no_early_store_addr_dep (producer
, consumer
);
266 /* Return non-zero iff the consumer (a multiply-accumulate or a
267 multiple-subtract instruction) has an accumulator dependency on the
268 result of the producer and no other dependency on that result. It
269 does not check if the producer is multiply-accumulate instruction. */
271 arm_mac_accumulator_is_result (rtx producer
, rtx consumer
)
276 producer
= PATTERN (producer
);
277 consumer
= PATTERN (consumer
);
279 if (GET_CODE (producer
) == COND_EXEC
)
280 producer
= COND_EXEC_CODE (producer
);
281 if (GET_CODE (consumer
) == COND_EXEC
)
282 consumer
= COND_EXEC_CODE (consumer
);
284 if (GET_CODE (producer
) != SET
)
287 result
= XEXP (producer
, 0);
289 if (GET_CODE (consumer
) != SET
)
292 /* Check that the consumer is of the form
293 (set (...) (plus (mult ...) (...)))
295 (set (...) (minus (...) (mult ...))). */
296 if (GET_CODE (XEXP (consumer
, 1)) == PLUS
)
298 if (GET_CODE (XEXP (XEXP (consumer
, 1), 0)) != MULT
)
301 op0
= XEXP (XEXP (XEXP (consumer
, 1), 0), 0);
302 op1
= XEXP (XEXP (XEXP (consumer
, 1), 0), 1);
303 acc
= XEXP (XEXP (consumer
, 1), 1);
305 else if (GET_CODE (XEXP (consumer
, 1)) == MINUS
)
307 if (GET_CODE (XEXP (XEXP (consumer
, 1), 1)) != MULT
)
310 op0
= XEXP (XEXP (XEXP (consumer
, 1), 1), 0);
311 op1
= XEXP (XEXP (XEXP (consumer
, 1), 1), 1);
312 acc
= XEXP (XEXP (consumer
, 1), 0);
317 return (reg_overlap_mentioned_p (result
, acc
)
318 && !reg_overlap_mentioned_p (result
, op0
)
319 && !reg_overlap_mentioned_p (result
, op1
));
322 /* Return non-zero if the consumer (a multiply-accumulate instruction)
323 has an accumulator dependency on the result of the producer (a
324 multiplication instruction) and no other dependency on that result. */
326 arm_mac_accumulator_is_mul_result (rtx producer
, rtx consumer
)
328 rtx mul
= PATTERN (producer
);
329 rtx mac
= PATTERN (consumer
);
331 rtx mac_op0
, mac_op1
, mac_acc
;
333 if (GET_CODE (mul
) == COND_EXEC
)
334 mul
= COND_EXEC_CODE (mul
);
335 if (GET_CODE (mac
) == COND_EXEC
)
336 mac
= COND_EXEC_CODE (mac
);
338 /* Check that mul is of the form (set (...) (mult ...))
339 and mla is of the form (set (...) (plus (mult ...) (...))). */
340 if ((GET_CODE (mul
) != SET
|| GET_CODE (XEXP (mul
, 1)) != MULT
)
341 || (GET_CODE (mac
) != SET
|| GET_CODE (XEXP (mac
, 1)) != PLUS
342 || GET_CODE (XEXP (XEXP (mac
, 1), 0)) != MULT
))
345 mul_result
= XEXP (mul
, 0);
346 mac_op0
= XEXP (XEXP (XEXP (mac
, 1), 0), 0);
347 mac_op1
= XEXP (XEXP (XEXP (mac
, 1), 0), 1);
348 mac_acc
= XEXP (XEXP (mac
, 1), 1);
350 return (reg_overlap_mentioned_p (mul_result
, mac_acc
)
351 && !reg_overlap_mentioned_p (mul_result
, mac_op0
)
352 && !reg_overlap_mentioned_p (mul_result
, mac_op1
));