]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nds32/nds32-predicates.c
1 /* Predicate functions of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* ------------------------------------------------------------------------ */
25 #include "coretypes.h"
30 #include "stor-layout.h"
35 #include "hard-reg-set.h"
36 #include "insn-config.h" /* Required by recog.h. */
37 #include "conditions.h"
39 #include "insn-attr.h" /* For DFA state_t. */
40 #include "insn-codes.h" /* For CODE_FOR_xxx. */
41 #include "reload.h" /* For push_reload(). */
44 #include "insn-config.h"
52 #include "diagnostic-core.h"
53 #include "dominance.h"
59 #include "cfgcleanup.h"
61 #include "basic-block.h"
64 #include "tm-constrs.h"
65 #include "optabs.h" /* For GEN_FCN. */
67 #include "target-def.h"
68 #include "langhooks.h" /* For add_builtin_function(). */
71 /* ------------------------------------------------------------------------ */
73 /* A subroutine that checks multiple load and store
74 using consecutive registers.
75 OP is a parallel rtx we would like to check.
76 LOAD_P indicates whether we are checking load operation.
77 PAR_INDEX is starting element of parallel rtx.
78 FIRST_ELT_REGNO is used to tell starting register number.
79 COUNT helps us to check consecutive register numbers. */
81 nds32_consecutive_registers_load_store_p (rtx op
,
93 for (i
= 0; i
< count
; i
++)
95 /* Pick up each element from parallel rtx. */
96 elt
= XVECEXP (op
, 0, i
+ par_index
);
98 /* If this element is not a 'set' rtx, return false immediately. */
99 if (GET_CODE (elt
) != SET
)
102 /* Pick up reg and mem of this element. */
103 elt_reg
= load_p
? SET_DEST (elt
) : SET_SRC (elt
);
104 elt_mem
= load_p
? SET_SRC (elt
) : SET_DEST (elt
);
106 /* If elt_reg is not a expected reg rtx, return false. */
107 if (GET_CODE (elt_reg
) != REG
|| GET_MODE (elt_reg
) != SImode
)
109 /* If elt_mem is not a expected mem rtx, return false. */
110 if (GET_CODE (elt_mem
) != MEM
|| GET_MODE (elt_mem
) != SImode
)
113 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
114 check_regno
= first_elt_regno
+ i
;
116 /* If the register number is not continuous, return false. */
117 if (REGNO (elt_reg
) != (unsigned int) check_regno
)
124 /* Function to check whether the OP is a valid load/store operation.
125 This is a helper function for the predicates:
126 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
127 in predicates.md file.
129 The OP is supposed to be a parallel rtx.
130 For each element within this parallel rtx:
131 (set (reg) (mem addr)) is the form for load operation.
132 (set (mem addr) (reg)) is the form for store operation.
133 We have to extract reg and mem of every element and
134 check if the information is valid for multiple load/store operation. */
136 nds32_valid_multiple_load_store (rtx op
, bool load_p
)
142 /* Get the counts of elements in the parallel rtx. */
143 count
= XVECLEN (op
, 0);
144 /* Pick up the first element. */
145 elt
= XVECEXP (op
, 0, 0);
147 /* Perform some quick check for the first element in the parallel rtx. */
148 if (GET_CODE (elt
) != SET
153 /* Pick up regno of first element for further detail checking.
154 Note that the form is different between load and store operation. */
157 if (GET_CODE (SET_DEST (elt
)) != REG
158 || GET_CODE (SET_SRC (elt
)) != MEM
)
161 first_elt_regno
= REGNO (SET_DEST (elt
));
165 if (GET_CODE (SET_SRC (elt
)) != REG
166 || GET_CODE (SET_DEST (elt
)) != MEM
)
169 first_elt_regno
= REGNO (SET_SRC (elt
));
172 /* Perform detail check for each element.
173 Refer to nds32-multiple.md for more information
174 about following checking.
175 The starting element of parallel rtx is index 0. */
176 if (!nds32_consecutive_registers_load_store_p (op
, load_p
, 0,
181 /* Pass all test, this is a valid rtx. */
185 /* Function to check whether the OP is a valid stack push/pop operation.
186 For a valid stack operation, it must satisfy following conditions:
187 1. Consecutive registers push/pop operations.
188 2. Valid $fp/$gp/$lp push/pop operations.
189 3. The last element must be stack adjustment rtx.
190 See the prologue/epilogue implementation for details. */
192 nds32_valid_stack_push_pop_p (rtx op
, bool push_p
)
198 int save_fp
, save_gp
, save_lp
;
204 /* Get the counts of elements in the parallel rtx. */
205 total_count
= XVECLEN (op
, 0);
207 /* Perform some quick check for that every element should be 'set'. */
208 for (index
= 0; index
< total_count
; index
++)
210 elt
= XVECEXP (op
, 0, index
);
211 if (GET_CODE (elt
) != SET
)
215 /* For push operation, the parallel rtx looks like:
216 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
218 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
221 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
223 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
225 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
227 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
229 (set (reg:SI SP_REGNUM)
230 (plus (reg:SI SP_REGNUM) (const_int -32)))])
232 For pop operation, the parallel rtx looks like:
233 (parallel [(set (reg:SI Rb)
234 (mem (reg:SI SP_REGNUM)))
236 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
239 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
240 (set (reg:SI FP_REGNUM)
241 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
242 (set (reg:SI GP_REGNUM)
243 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
244 (set (reg:SI LP_REGNUM)
245 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
246 (set (reg:SI SP_REGNUM)
247 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
249 /* 1. Consecutive registers push/pop operations.
250 We need to calculate how many registers should be consecutive.
251 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
252 and $lp push rtx are excluded. */
254 /* Detect whether we have $fp, $gp, or $lp in the parallel rtx. */
255 save_fp
= reg_mentioned_p (gen_rtx_REG (SImode
, FP_REGNUM
), op
);
256 save_gp
= reg_mentioned_p (gen_rtx_REG (SImode
, GP_REGNUM
), op
);
257 save_lp
= reg_mentioned_p (gen_rtx_REG (SImode
, LP_REGNUM
), op
);
258 /* Exclude last $sp adjustment rtx. */
259 rest_count
= total_count
- 1;
260 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
270 elt
= XVECEXP (op
, 0, 0);
271 /* Pick up register element. */
272 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
273 first_regno
= REGNO (elt_reg
);
275 /* The 'push' operation is a kind of store operation.
276 The 'pop' operation is a kind of load operation.
277 Pass corresponding false/true as second argument (bool load_p).
278 The par_index is supposed to start with index 0. */
279 if (!nds32_consecutive_registers_load_store_p (op
,
280 !push_p
? true : false,
287 /* 2. Valid $fp/$gp/$lp push/pop operations.
288 Remember to set start index for checking them. */
290 /* The rest_count is the start index for checking $fp/$gp/$lp. */
292 /* If index < 0, this parallel rtx is definitely
293 not a valid stack push/pop operation. */
297 /* Check $fp/$gp/$lp one by one.
298 We use 'push_p' to pick up reg rtx and mem rtx. */
301 elt
= XVECEXP (op
, 0, index
);
302 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
303 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
306 if (GET_CODE (elt_mem
) != MEM
307 || GET_CODE (elt_reg
) != REG
308 || REGNO (elt_reg
) != FP_REGNUM
)
313 elt
= XVECEXP (op
, 0, index
);
314 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
315 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
318 if (GET_CODE (elt_mem
) != MEM
319 || GET_CODE (elt_reg
) != REG
320 || REGNO (elt_reg
) != GP_REGNUM
)
325 elt
= XVECEXP (op
, 0, index
);
326 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
327 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
330 if (GET_CODE (elt_mem
) != MEM
331 || GET_CODE (elt_reg
) != REG
332 || REGNO (elt_reg
) != LP_REGNUM
)
336 /* 3. The last element must be stack adjustment rtx.
337 Its form of rtx should be:
338 (set (reg:SI SP_REGNUM)
339 (plus (reg:SI SP_REGNUM) (const_int X)))
340 The X could be positive or negative value. */
342 /* Pick up the last element. */
343 elt
= XVECEXP (op
, 0, total_count
- 1);
345 /* Extract its destination and source rtx. */
346 elt_reg
= SET_DEST (elt
);
347 elt_plus
= SET_SRC (elt
);
349 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
350 if (GET_CODE (elt_reg
) != REG
351 || GET_CODE (elt_plus
) != PLUS
352 || REGNO (elt_reg
) != SP_REGNUM
)
355 /* Pass all test, this is a valid rtx. */
359 /* Function to check if 'bclr' instruction can be used with IVAL. */
361 nds32_can_use_bclr_p (int ival
)
365 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
366 it means the original ival has only one 0-bit,
367 So it is ok to perform 'bclr' operation. */
369 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (~ival
));
371 /* 'bclr' is a performance extension instruction. */
372 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
375 /* Function to check if 'bset' instruction can be used with IVAL. */
377 nds32_can_use_bset_p (int ival
)
381 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
382 it is ok to perform 'bset' operation. */
384 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
386 /* 'bset' is a performance extension instruction. */
387 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
390 /* Function to check if 'btgl' instruction can be used with IVAL. */
392 nds32_can_use_btgl_p (int ival
)
396 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
397 it is ok to perform 'btgl' operation. */
399 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
401 /* 'btgl' is a performance extension instruction. */
402 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
405 /* Function to check if 'bitci' instruction can be used with IVAL. */
407 nds32_can_use_bitci_p (int ival
)
409 /* If we are using V3 ISA, we have 'bitci' instruction.
410 Try to see if we can present 'andi' semantic with
411 such 'bit-clear-immediate' operation.
412 For example, 'andi $r0,$r0,0xfffffffc' can be
413 presented with 'bitci $r0,$r0,3'. */
414 return (TARGET_ISA_V3
416 && satisfies_constraint_Iu15 (gen_int_mode (~ival
, SImode
)));
419 /* ------------------------------------------------------------------------ */