PR target/84064
[official-gcc.git] / gcc / config / nds32 / nds32-predicates.c
blob341f8b6f1cd11a45a1197942bb842c39364eadc7
1 /* Predicate functions of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2018 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 #define IN_TARGET_CODE 1
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "memmodel.h"
33 #include "tm_p.h"
34 #include "optabs.h" /* For GEN_FCN. */
35 #include "emit-rtl.h"
36 #include "recog.h"
37 #include "tm-constrs.h"
39 /* ------------------------------------------------------------------------ */
41 /* A subroutine that checks multiple load and store
42 using consecutive registers.
43 OP is a parallel rtx we would like to check.
44 LOAD_P indicates whether we are checking load operation.
45 PAR_INDEX is starting element of parallel rtx.
46 FIRST_ELT_REGNO is used to tell starting register number.
47 COUNT helps us to check consecutive register numbers. */
48 static bool
49 nds32_consecutive_registers_load_store_p (rtx op,
50 bool load_p,
51 int par_index,
52 int first_elt_regno,
53 int count)
55 int i;
56 int check_regno;
57 rtx elt;
58 rtx elt_reg;
59 rtx elt_mem;
61 for (i = 0; i < count; i++)
63 /* Pick up each element from parallel rtx. */
64 elt = XVECEXP (op, 0, i + par_index);
66 /* If this element is not a 'set' rtx, return false immediately. */
67 if (GET_CODE (elt) != SET)
68 return false;
70 /* Pick up reg and mem of this element. */
71 elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
72 elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
74 /* If elt_reg is not a expected reg rtx, return false. */
75 if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
76 return false;
77 /* If elt_mem is not a expected mem rtx, return false. */
78 if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
79 return false;
81 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
82 check_regno = first_elt_regno + i;
84 /* If the register number is not continuous, return false. */
85 if (REGNO (elt_reg) != (unsigned int) check_regno)
86 return false;
89 return true;
92 /* Function to check whether the OP is a valid load/store operation.
93 This is a helper function for the predicates:
94 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
95 in predicates.md file.
97 The OP is supposed to be a parallel rtx.
98 For each element within this parallel rtx:
99 (set (reg) (mem addr)) is the form for load operation.
100 (set (mem addr) (reg)) is the form for store operation.
101 We have to extract reg and mem of every element and
102 check if the information is valid for multiple load/store operation. */
103 bool
104 nds32_valid_multiple_load_store (rtx op, bool load_p)
106 int count;
107 int first_elt_regno;
108 rtx elt;
110 /* Get the counts of elements in the parallel rtx. */
111 count = XVECLEN (op, 0);
112 /* Pick up the first element. */
113 elt = XVECEXP (op, 0, 0);
115 /* Perform some quick check for the first element in the parallel rtx. */
116 if (GET_CODE (elt) != SET
117 || count <= 1
118 || count > 8)
119 return false;
121 /* Pick up regno of first element for further detail checking.
122 Note that the form is different between load and store operation. */
123 if (load_p)
125 if (GET_CODE (SET_DEST (elt)) != REG
126 || GET_CODE (SET_SRC (elt)) != MEM)
127 return false;
129 first_elt_regno = REGNO (SET_DEST (elt));
131 else
133 if (GET_CODE (SET_SRC (elt)) != REG
134 || GET_CODE (SET_DEST (elt)) != MEM)
135 return false;
137 first_elt_regno = REGNO (SET_SRC (elt));
140 /* Perform detail check for each element.
141 Refer to nds32-multiple.md for more information
142 about following checking.
143 The starting element of parallel rtx is index 0. */
144 if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
145 first_elt_regno,
146 count))
147 return false;
149 /* Pass all test, this is a valid rtx. */
150 return true;
153 /* Function to check whether the OP is a valid stack push/pop operation.
154 For a valid stack operation, it must satisfy following conditions:
155 1. Consecutive registers push/pop operations.
156 2. Valid $fp/$gp/$lp push/pop operations.
157 3. The last element must be stack adjustment rtx.
158 See the prologue/epilogue implementation for details. */
159 bool
160 nds32_valid_stack_push_pop_p (rtx op, bool push_p)
162 int index;
163 int total_count;
164 int rest_count;
165 int first_regno;
166 int save_fp, save_gp, save_lp;
167 rtx elt;
168 rtx elt_reg;
169 rtx elt_mem;
170 rtx elt_plus;
172 /* Get the counts of elements in the parallel rtx. */
173 total_count = XVECLEN (op, 0);
175 /* Perform some quick check for that every element should be 'set'. */
176 for (index = 0; index < total_count; index++)
178 elt = XVECEXP (op, 0, index);
179 if (GET_CODE (elt) != SET)
180 return false;
183 /* For push operation, the parallel rtx looks like:
184 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
185 (reg:SI Rb))
186 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
187 (reg:SI Rb+1))
189 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
190 (reg:SI Re))
191 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
192 (reg:SI FP_REGNUM))
193 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
194 (reg:SI GP_REGNUM))
195 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
196 (reg:SI LP_REGNUM))
197 (set (reg:SI SP_REGNUM)
198 (plus (reg:SI SP_REGNUM) (const_int -32)))])
200 For pop operation, the parallel rtx looks like:
201 (parallel [(set (reg:SI Rb)
202 (mem (reg:SI SP_REGNUM)))
203 (set (reg:SI Rb+1)
204 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
206 (set (reg:SI Re)
207 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
208 (set (reg:SI FP_REGNUM)
209 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
210 (set (reg:SI GP_REGNUM)
211 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
212 (set (reg:SI LP_REGNUM)
213 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
214 (set (reg:SI SP_REGNUM)
215 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
217 /* 1. Consecutive registers push/pop operations.
218 We need to calculate how many registers should be consecutive.
219 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
220 and $lp push rtx are excluded. */
222 /* Detect whether we have $fp, $gp, or $lp in the parallel rtx. */
223 save_fp = reg_mentioned_p (gen_rtx_REG (SImode, FP_REGNUM), op);
224 save_gp = reg_mentioned_p (gen_rtx_REG (SImode, GP_REGNUM), op);
225 save_lp = reg_mentioned_p (gen_rtx_REG (SImode, LP_REGNUM), op);
226 /* Exclude last $sp adjustment rtx. */
227 rest_count = total_count - 1;
228 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
229 if (save_fp)
230 rest_count--;
231 if (save_gp)
232 rest_count--;
233 if (save_lp)
234 rest_count--;
236 if (rest_count > 0)
238 elt = XVECEXP (op, 0, 0);
239 /* Pick up register element. */
240 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
241 first_regno = REGNO (elt_reg);
243 /* The 'push' operation is a kind of store operation.
244 The 'pop' operation is a kind of load operation.
245 Pass corresponding false/true as second argument (bool load_p).
246 The par_index is supposed to start with index 0. */
247 if (!nds32_consecutive_registers_load_store_p (op,
248 !push_p ? true : false,
250 first_regno,
251 rest_count))
252 return false;
255 /* 2. Valid $fp/$gp/$lp push/pop operations.
256 Remember to set start index for checking them. */
258 /* The rest_count is the start index for checking $fp/$gp/$lp. */
259 index = rest_count;
260 /* If index < 0, this parallel rtx is definitely
261 not a valid stack push/pop operation. */
262 if (index < 0)
263 return false;
265 /* Check $fp/$gp/$lp one by one.
266 We use 'push_p' to pick up reg rtx and mem rtx. */
267 if (save_fp)
269 elt = XVECEXP (op, 0, index);
270 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
271 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
272 index++;
274 if (GET_CODE (elt_mem) != MEM
275 || GET_CODE (elt_reg) != REG
276 || REGNO (elt_reg) != FP_REGNUM)
277 return false;
279 if (save_gp)
281 elt = XVECEXP (op, 0, index);
282 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
283 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
284 index++;
286 if (GET_CODE (elt_mem) != MEM
287 || GET_CODE (elt_reg) != REG
288 || REGNO (elt_reg) != GP_REGNUM)
289 return false;
291 if (save_lp)
293 elt = XVECEXP (op, 0, index);
294 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
295 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
296 index++;
298 if (GET_CODE (elt_mem) != MEM
299 || GET_CODE (elt_reg) != REG
300 || REGNO (elt_reg) != LP_REGNUM)
301 return false;
304 /* 3. The last element must be stack adjustment rtx.
305 Its form of rtx should be:
306 (set (reg:SI SP_REGNUM)
307 (plus (reg:SI SP_REGNUM) (const_int X)))
308 The X could be positive or negative value. */
310 /* Pick up the last element. */
311 elt = XVECEXP (op, 0, total_count - 1);
313 /* Extract its destination and source rtx. */
314 elt_reg = SET_DEST (elt);
315 elt_plus = SET_SRC (elt);
317 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
318 if (GET_CODE (elt_reg) != REG
319 || GET_CODE (elt_plus) != PLUS
320 || REGNO (elt_reg) != SP_REGNUM)
321 return false;
323 /* Pass all test, this is a valid rtx. */
324 return true;
327 /* Function to check if 'bclr' instruction can be used with IVAL. */
329 nds32_can_use_bclr_p (int ival)
331 int one_bit_count;
333 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
334 it means the original ival has only one 0-bit,
335 So it is ok to perform 'bclr' operation. */
337 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
339 /* 'bclr' is a performance extension instruction. */
340 return (TARGET_EXT_PERF && (one_bit_count == 1));
343 /* Function to check if 'bset' instruction can be used with IVAL. */
345 nds32_can_use_bset_p (int ival)
347 int one_bit_count;
349 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
350 it is ok to perform 'bset' operation. */
352 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
354 /* 'bset' is a performance extension instruction. */
355 return (TARGET_EXT_PERF && (one_bit_count == 1));
358 /* Function to check if 'btgl' instruction can be used with IVAL. */
360 nds32_can_use_btgl_p (int ival)
362 int one_bit_count;
364 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
365 it is ok to perform 'btgl' operation. */
367 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
369 /* 'btgl' is a performance extension instruction. */
370 return (TARGET_EXT_PERF && (one_bit_count == 1));
373 /* Function to check if 'bitci' instruction can be used with IVAL. */
375 nds32_can_use_bitci_p (int ival)
377 /* If we are using V3 ISA, we have 'bitci' instruction.
378 Try to see if we can present 'andi' semantic with
379 such 'bit-clear-immediate' operation.
380 For example, 'andi $r0,$r0,0xfffffffc' can be
381 presented with 'bitci $r0,$r0,3'. */
382 return (TARGET_ISA_V3
383 && (ival < 0)
384 && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
387 /* ------------------------------------------------------------------------ */