Turn SECONDARY_MEMORY_NEEDED_MODE into a target hook
[official-gcc.git] / gcc / config / nds32 / nds32-predicates.c
blob05e3f69988300bbf4ece7fca22cff3d2320eafa0
1 /* Predicate functions of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2017 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 /* ------------------------------------------------------------------------ */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "backend.h"
27 #include "target.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "memmodel.h"
31 #include "tm_p.h"
32 #include "optabs.h" /* For GEN_FCN. */
33 #include "emit-rtl.h"
34 #include "recog.h"
35 #include "tm-constrs.h"
37 /* ------------------------------------------------------------------------ */
39 /* A subroutine that checks multiple load and store
40 using consecutive registers.
41 OP is a parallel rtx we would like to check.
42 LOAD_P indicates whether we are checking load operation.
43 PAR_INDEX is starting element of parallel rtx.
44 FIRST_ELT_REGNO is used to tell starting register number.
45 COUNT helps us to check consecutive register numbers. */
46 static bool
47 nds32_consecutive_registers_load_store_p (rtx op,
48 bool load_p,
49 int par_index,
50 int first_elt_regno,
51 int count)
53 int i;
54 int check_regno;
55 rtx elt;
56 rtx elt_reg;
57 rtx elt_mem;
59 for (i = 0; i < count; i++)
61 /* Pick up each element from parallel rtx. */
62 elt = XVECEXP (op, 0, i + par_index);
64 /* If this element is not a 'set' rtx, return false immediately. */
65 if (GET_CODE (elt) != SET)
66 return false;
68 /* Pick up reg and mem of this element. */
69 elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
70 elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
72 /* If elt_reg is not a expected reg rtx, return false. */
73 if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
74 return false;
75 /* If elt_mem is not a expected mem rtx, return false. */
76 if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
77 return false;
79 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
80 check_regno = first_elt_regno + i;
82 /* If the register number is not continuous, return false. */
83 if (REGNO (elt_reg) != (unsigned int) check_regno)
84 return false;
87 return true;
90 /* Function to check whether the OP is a valid load/store operation.
91 This is a helper function for the predicates:
92 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
93 in predicates.md file.
95 The OP is supposed to be a parallel rtx.
96 For each element within this parallel rtx:
97 (set (reg) (mem addr)) is the form for load operation.
98 (set (mem addr) (reg)) is the form for store operation.
99 We have to extract reg and mem of every element and
100 check if the information is valid for multiple load/store operation. */
101 bool
102 nds32_valid_multiple_load_store (rtx op, bool load_p)
104 int count;
105 int first_elt_regno;
106 rtx elt;
108 /* Get the counts of elements in the parallel rtx. */
109 count = XVECLEN (op, 0);
110 /* Pick up the first element. */
111 elt = XVECEXP (op, 0, 0);
113 /* Perform some quick check for the first element in the parallel rtx. */
114 if (GET_CODE (elt) != SET
115 || count <= 1
116 || count > 8)
117 return false;
119 /* Pick up regno of first element for further detail checking.
120 Note that the form is different between load and store operation. */
121 if (load_p)
123 if (GET_CODE (SET_DEST (elt)) != REG
124 || GET_CODE (SET_SRC (elt)) != MEM)
125 return false;
127 first_elt_regno = REGNO (SET_DEST (elt));
129 else
131 if (GET_CODE (SET_SRC (elt)) != REG
132 || GET_CODE (SET_DEST (elt)) != MEM)
133 return false;
135 first_elt_regno = REGNO (SET_SRC (elt));
138 /* Perform detail check for each element.
139 Refer to nds32-multiple.md for more information
140 about following checking.
141 The starting element of parallel rtx is index 0. */
142 if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
143 first_elt_regno,
144 count))
145 return false;
147 /* Pass all test, this is a valid rtx. */
148 return true;
151 /* Function to check whether the OP is a valid stack push/pop operation.
152 For a valid stack operation, it must satisfy following conditions:
153 1. Consecutive registers push/pop operations.
154 2. Valid $fp/$gp/$lp push/pop operations.
155 3. The last element must be stack adjustment rtx.
156 See the prologue/epilogue implementation for details. */
157 bool
158 nds32_valid_stack_push_pop_p (rtx op, bool push_p)
160 int index;
161 int total_count;
162 int rest_count;
163 int first_regno;
164 int save_fp, save_gp, save_lp;
165 rtx elt;
166 rtx elt_reg;
167 rtx elt_mem;
168 rtx elt_plus;
170 /* Get the counts of elements in the parallel rtx. */
171 total_count = XVECLEN (op, 0);
173 /* Perform some quick check for that every element should be 'set'. */
174 for (index = 0; index < total_count; index++)
176 elt = XVECEXP (op, 0, index);
177 if (GET_CODE (elt) != SET)
178 return false;
181 /* For push operation, the parallel rtx looks like:
182 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
183 (reg:SI Rb))
184 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
185 (reg:SI Rb+1))
187 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
188 (reg:SI Re))
189 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
190 (reg:SI FP_REGNUM))
191 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
192 (reg:SI GP_REGNUM))
193 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
194 (reg:SI LP_REGNUM))
195 (set (reg:SI SP_REGNUM)
196 (plus (reg:SI SP_REGNUM) (const_int -32)))])
198 For pop operation, the parallel rtx looks like:
199 (parallel [(set (reg:SI Rb)
200 (mem (reg:SI SP_REGNUM)))
201 (set (reg:SI Rb+1)
202 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
204 (set (reg:SI Re)
205 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
206 (set (reg:SI FP_REGNUM)
207 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
208 (set (reg:SI GP_REGNUM)
209 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
210 (set (reg:SI LP_REGNUM)
211 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
212 (set (reg:SI SP_REGNUM)
213 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
215 /* 1. Consecutive registers push/pop operations.
216 We need to calculate how many registers should be consecutive.
217 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
218 and $lp push rtx are excluded. */
220 /* Detect whether we have $fp, $gp, or $lp in the parallel rtx. */
221 save_fp = reg_mentioned_p (gen_rtx_REG (SImode, FP_REGNUM), op);
222 save_gp = reg_mentioned_p (gen_rtx_REG (SImode, GP_REGNUM), op);
223 save_lp = reg_mentioned_p (gen_rtx_REG (SImode, LP_REGNUM), op);
224 /* Exclude last $sp adjustment rtx. */
225 rest_count = total_count - 1;
226 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
227 if (save_fp)
228 rest_count--;
229 if (save_gp)
230 rest_count--;
231 if (save_lp)
232 rest_count--;
234 if (rest_count > 0)
236 elt = XVECEXP (op, 0, 0);
237 /* Pick up register element. */
238 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
239 first_regno = REGNO (elt_reg);
241 /* The 'push' operation is a kind of store operation.
242 The 'pop' operation is a kind of load operation.
243 Pass corresponding false/true as second argument (bool load_p).
244 The par_index is supposed to start with index 0. */
245 if (!nds32_consecutive_registers_load_store_p (op,
246 !push_p ? true : false,
248 first_regno,
249 rest_count))
250 return false;
253 /* 2. Valid $fp/$gp/$lp push/pop operations.
254 Remember to set start index for checking them. */
256 /* The rest_count is the start index for checking $fp/$gp/$lp. */
257 index = rest_count;
258 /* If index < 0, this parallel rtx is definitely
259 not a valid stack push/pop operation. */
260 if (index < 0)
261 return false;
263 /* Check $fp/$gp/$lp one by one.
264 We use 'push_p' to pick up reg rtx and mem rtx. */
265 if (save_fp)
267 elt = XVECEXP (op, 0, index);
268 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
269 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
270 index++;
272 if (GET_CODE (elt_mem) != MEM
273 || GET_CODE (elt_reg) != REG
274 || REGNO (elt_reg) != FP_REGNUM)
275 return false;
277 if (save_gp)
279 elt = XVECEXP (op, 0, index);
280 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
281 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
282 index++;
284 if (GET_CODE (elt_mem) != MEM
285 || GET_CODE (elt_reg) != REG
286 || REGNO (elt_reg) != GP_REGNUM)
287 return false;
289 if (save_lp)
291 elt = XVECEXP (op, 0, index);
292 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
293 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
294 index++;
296 if (GET_CODE (elt_mem) != MEM
297 || GET_CODE (elt_reg) != REG
298 || REGNO (elt_reg) != LP_REGNUM)
299 return false;
302 /* 3. The last element must be stack adjustment rtx.
303 Its form of rtx should be:
304 (set (reg:SI SP_REGNUM)
305 (plus (reg:SI SP_REGNUM) (const_int X)))
306 The X could be positive or negative value. */
308 /* Pick up the last element. */
309 elt = XVECEXP (op, 0, total_count - 1);
311 /* Extract its destination and source rtx. */
312 elt_reg = SET_DEST (elt);
313 elt_plus = SET_SRC (elt);
315 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
316 if (GET_CODE (elt_reg) != REG
317 || GET_CODE (elt_plus) != PLUS
318 || REGNO (elt_reg) != SP_REGNUM)
319 return false;
321 /* Pass all test, this is a valid rtx. */
322 return true;
325 /* Function to check if 'bclr' instruction can be used with IVAL. */
327 nds32_can_use_bclr_p (int ival)
329 int one_bit_count;
331 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
332 it means the original ival has only one 0-bit,
333 So it is ok to perform 'bclr' operation. */
335 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
337 /* 'bclr' is a performance extension instruction. */
338 return (TARGET_PERF_EXT && (one_bit_count == 1));
341 /* Function to check if 'bset' instruction can be used with IVAL. */
343 nds32_can_use_bset_p (int ival)
345 int one_bit_count;
347 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
348 it is ok to perform 'bset' operation. */
350 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
352 /* 'bset' is a performance extension instruction. */
353 return (TARGET_PERF_EXT && (one_bit_count == 1));
356 /* Function to check if 'btgl' instruction can be used with IVAL. */
358 nds32_can_use_btgl_p (int ival)
360 int one_bit_count;
362 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
363 it is ok to perform 'btgl' operation. */
365 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
367 /* 'btgl' is a performance extension instruction. */
368 return (TARGET_PERF_EXT && (one_bit_count == 1));
371 /* Function to check if 'bitci' instruction can be used with IVAL. */
373 nds32_can_use_bitci_p (int ival)
375 /* If we are using V3 ISA, we have 'bitci' instruction.
376 Try to see if we can present 'andi' semantic with
377 such 'bit-clear-immediate' operation.
378 For example, 'andi $r0,$r0,0xfffffffc' can be
379 presented with 'bitci $r0,$r0,3'. */
380 return (TARGET_ISA_V3
381 && (ival < 0)
382 && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
385 /* ------------------------------------------------------------------------ */