xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/nds32/nds32-predicates.c (revision 1580a27b92f58fcdcb23fdfbc04a7c2b54a0b7c8)
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.
4 
5    This file is part of GCC.
6 
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.
11 
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.
16 
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/>.  */
20 
21 /* ------------------------------------------------------------------------ */
22 
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "hash-set.h"
28 #include "machmode.h"
29 #include "vec.h"
30 #include "double-int.h"
31 #include "input.h"
32 #include "alias.h"
33 #include "symtab.h"
34 #include "wide-int.h"
35 #include "inchash.h"
36 #include "tree.h"
37 #include "stor-layout.h"
38 #include "varasm.h"
39 #include "calls.h"
40 #include "rtl.h"
41 #include "regs.h"
42 #include "hard-reg-set.h"
43 #include "insn-config.h"	/* Required by recog.h.  */
44 #include "conditions.h"
45 #include "output.h"
46 #include "insn-attr.h"		/* For DFA state_t.  */
47 #include "insn-codes.h"		/* For CODE_FOR_xxx.  */
48 #include "reload.h"		/* For push_reload().  */
49 #include "flags.h"
50 #include "function.h"
51 #include "hashtab.h"
52 #include "statistics.h"
53 #include "real.h"
54 #include "fixed-value.h"
55 #include "insn-config.h"
56 #include "expmed.h"
57 #include "dojump.h"
58 #include "explow.h"
59 #include "emit-rtl.h"
60 #include "stmt.h"
61 #include "expr.h"
62 #include "recog.h"
63 #include "diagnostic-core.h"
64 #include "dominance.h"
65 #include "cfg.h"
66 #include "cfgrtl.h"
67 #include "cfganal.h"
68 #include "lcm.h"
69 #include "cfgbuild.h"
70 #include "cfgcleanup.h"
71 #include "predict.h"
72 #include "basic-block.h"
73 #include "df.h"
74 #include "tm_p.h"
75 #include "tm-constrs.h"
76 #include "optabs.h"		/* For GEN_FCN.  */
77 #include "target.h"
78 #include "target-def.h"
79 #include "langhooks.h"		/* For add_builtin_function().  */
80 #include "ggc.h"
81 #include "builtins.h"
82 
83 /* ------------------------------------------------------------------------ */
84 
85 /* A subroutine that checks multiple load and store
86    using consecutive registers.
87      OP is a parallel rtx we would like to check.
88      LOAD_P indicates whether we are checking load operation.
89      PAR_INDEX is starting element of parallel rtx.
90      FIRST_ELT_REGNO is used to tell starting register number.
91      COUNT helps us to check consecutive register numbers.  */
92 static bool
93 nds32_consecutive_registers_load_store_p (rtx op,
94 					  bool load_p,
95 					  int par_index,
96 					  int first_elt_regno,
97 					  int count)
98 {
99   int i;
100   int check_regno;
101   rtx elt;
102   rtx elt_reg;
103   rtx elt_mem;
104 
105   for (i = 0; i < count; i++)
106     {
107       /* Pick up each element from parallel rtx.  */
108       elt = XVECEXP (op, 0, i + par_index);
109 
110       /* If this element is not a 'set' rtx, return false immediately.  */
111       if (GET_CODE (elt) != SET)
112 	return false;
113 
114       /* Pick up reg and mem of this element.  */
115       elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
116       elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
117 
118       /* If elt_reg is not a expected reg rtx, return false.  */
119       if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
120 	return false;
121       /* If elt_mem is not a expected mem rtx, return false.  */
122       if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
123 	return false;
124 
125       /* The consecutive registers should be in (Rb,Rb+1...Re) order.  */
126       check_regno = first_elt_regno + i;
127 
128       /* If the register number is not continuous, return false.  */
129       if (REGNO (elt_reg) != (unsigned int) check_regno)
130 	return false;
131     }
132 
133   return true;
134 }
135 
136 /* Function to check whether the OP is a valid load/store operation.
137    This is a helper function for the predicates:
138    'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
139    in predicates.md file.
140 
141    The OP is supposed to be a parallel rtx.
142    For each element within this parallel rtx:
143      (set (reg) (mem addr)) is the form for load operation.
144      (set (mem addr) (reg)) is the form for store operation.
145    We have to extract reg and mem of every element and
146    check if the information is valid for multiple load/store operation.  */
147 bool
148 nds32_valid_multiple_load_store (rtx op, bool load_p)
149 {
150   int count;
151   int first_elt_regno;
152   rtx elt;
153 
154   /* Get the counts of elements in the parallel rtx.  */
155   count = XVECLEN (op, 0);
156   /* Pick up the first element.  */
157   elt = XVECEXP (op, 0, 0);
158 
159   /* Perform some quick check for the first element in the parallel rtx.  */
160   if (GET_CODE (elt) != SET
161       || count <= 1
162       || count > 8)
163     return false;
164 
165   /* Pick up regno of first element for further detail checking.
166      Note that the form is different between load and store operation.  */
167   if (load_p)
168     {
169       if (GET_CODE (SET_DEST (elt)) != REG
170 	  || GET_CODE (SET_SRC (elt)) != MEM)
171 	return false;
172 
173       first_elt_regno = REGNO (SET_DEST (elt));
174     }
175   else
176     {
177       if (GET_CODE (SET_SRC (elt)) != REG
178 	  || GET_CODE (SET_DEST (elt)) != MEM)
179 	return false;
180 
181       first_elt_regno = REGNO (SET_SRC (elt));
182     }
183 
184   /* Perform detail check for each element.
185      Refer to nds32-multiple.md for more information
186      about following checking.
187      The starting element of parallel rtx is index 0.  */
188   if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
189 						 first_elt_regno,
190 						 count))
191     return false;
192 
193   /* Pass all test, this is a valid rtx.  */
194   return true;
195 }
196 
197 /* Function to check whether the OP is a valid stack push/pop operation.
198    For a valid stack operation, it must satisfy following conditions:
199      1. Consecutive registers push/pop operations.
200      2. Valid $fp/$gp/$lp push/pop operations.
201      3. The last element must be stack adjustment rtx.
202    See the prologue/epilogue implementation for details.  */
203 bool
204 nds32_valid_stack_push_pop_p (rtx op, bool push_p)
205 {
206   int index;
207   int total_count;
208   int rest_count;
209   int first_regno;
210   int save_fp, save_gp, save_lp;
211   rtx elt;
212   rtx elt_reg;
213   rtx elt_mem;
214   rtx elt_plus;
215 
216   /* Get the counts of elements in the parallel rtx.  */
217   total_count = XVECLEN (op, 0);
218 
219   /* Perform some quick check for that every element should be 'set'.  */
220   for (index = 0; index < total_count; index++)
221     {
222       elt = XVECEXP (op, 0, index);
223       if (GET_CODE (elt) != SET)
224         return false;
225     }
226 
227   /* For push operation, the parallel rtx looks like:
228      (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
229                      (reg:SI Rb))
230                 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
231                      (reg:SI Rb+1))
232                 ...
233                 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
234                      (reg:SI Re))
235                 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
236                      (reg:SI FP_REGNUM))
237                 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
238                      (reg:SI GP_REGNUM))
239                 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
240                      (reg:SI LP_REGNUM))
241                 (set (reg:SI SP_REGNUM)
242                      (plus (reg:SI SP_REGNUM) (const_int -32)))])
243 
244      For pop operation, the parallel rtx looks like:
245      (parallel [(set (reg:SI Rb)
246                      (mem (reg:SI SP_REGNUM)))
247                 (set (reg:SI Rb+1)
248                      (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
249                 ...
250                 (set (reg:SI Re)
251                      (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
252                 (set (reg:SI FP_REGNUM)
253                      (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
254                 (set (reg:SI GP_REGNUM)
255                      (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
256                 (set (reg:SI LP_REGNUM)
257                      (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
258                 (set (reg:SI SP_REGNUM)
259                      (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
260 
261   /* 1. Consecutive registers push/pop operations.
262         We need to calculate how many registers should be consecutive.
263         The $sp adjustment rtx, $fp push rtx, $gp push rtx,
264         and $lp push rtx are excluded.  */
265 
266   /* Detect whether we have $fp, $gp, or $lp in the parallel rtx.  */
267   save_fp = reg_mentioned_p (gen_rtx_REG (SImode, FP_REGNUM), op);
268   save_gp = reg_mentioned_p (gen_rtx_REG (SImode, GP_REGNUM), op);
269   save_lp = reg_mentioned_p (gen_rtx_REG (SImode, LP_REGNUM), op);
270   /* Exclude last $sp adjustment rtx.  */
271   rest_count = total_count - 1;
272   /* Exclude $fp, $gp, and $lp if they are in the parallel rtx.  */
273   if (save_fp)
274     rest_count--;
275   if (save_gp)
276     rest_count--;
277   if (save_lp)
278     rest_count--;
279 
280   if (rest_count > 0)
281     {
282       elt = XVECEXP (op, 0, 0);
283       /* Pick up register element.  */
284       elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
285       first_regno = REGNO (elt_reg);
286 
287       /* The 'push' operation is a kind of store operation.
288          The 'pop' operation is a kind of load operation.
289          Pass corresponding false/true as second argument (bool load_p).
290          The par_index is supposed to start with index 0.  */
291       if (!nds32_consecutive_registers_load_store_p (op,
292 						     !push_p ? true : false,
293 						     0,
294 						     first_regno,
295 						     rest_count))
296         return false;
297     }
298 
299   /* 2. Valid $fp/$gp/$lp push/pop operations.
300         Remember to set start index for checking them.  */
301 
302   /* The rest_count is the start index for checking $fp/$gp/$lp.  */
303   index = rest_count;
304   /* If index < 0, this parallel rtx is definitely
305      not a valid stack push/pop operation.  */
306   if (index < 0)
307     return false;
308 
309   /* Check $fp/$gp/$lp one by one.
310      We use 'push_p' to pick up reg rtx and mem rtx.  */
311   if (save_fp)
312     {
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);
316       index++;
317 
318       if (GET_CODE (elt_mem) != MEM
319           || GET_CODE (elt_reg) != REG
320           || REGNO (elt_reg) != FP_REGNUM)
321         return false;
322     }
323   if (save_gp)
324     {
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);
328       index++;
329 
330       if (GET_CODE (elt_mem) != MEM
331           || GET_CODE (elt_reg) != REG
332           || REGNO (elt_reg) != GP_REGNUM)
333         return false;
334     }
335   if (save_lp)
336     {
337       elt = XVECEXP (op, 0, index);
338       elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
339       elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
340       index++;
341 
342       if (GET_CODE (elt_mem) != MEM
343           || GET_CODE (elt_reg) != REG
344           || REGNO (elt_reg) != LP_REGNUM)
345         return false;
346     }
347 
348   /* 3. The last element must be stack adjustment rtx.
349         Its form of rtx should be:
350           (set (reg:SI SP_REGNUM)
351                (plus (reg:SI SP_REGNUM) (const_int X)))
352         The X could be positive or negative value.  */
353 
354   /* Pick up the last element.  */
355   elt = XVECEXP (op, 0, total_count - 1);
356 
357   /* Extract its destination and source rtx.  */
358   elt_reg  = SET_DEST (elt);
359   elt_plus = SET_SRC (elt);
360 
361   /* Check this is (set (stack_reg) (plus stack_reg const)) pattern.  */
362   if (GET_CODE (elt_reg) != REG
363       || GET_CODE (elt_plus) != PLUS
364       || REGNO (elt_reg) != SP_REGNUM)
365     return false;
366 
367   /* Pass all test, this is a valid rtx.  */
368   return true;
369 }
370 
371 /* Function to check if 'bclr' instruction can be used with IVAL.  */
372 int
373 nds32_can_use_bclr_p (int ival)
374 {
375   int one_bit_count;
376 
377   /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
378      it means the original ival has only one 0-bit,
379      So it is ok to perform 'bclr' operation.  */
380 
381   one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
382 
383   /* 'bclr' is a performance extension instruction.  */
384   return (TARGET_PERF_EXT && (one_bit_count == 1));
385 }
386 
387 /* Function to check if 'bset' instruction can be used with IVAL.  */
388 int
389 nds32_can_use_bset_p (int ival)
390 {
391   int one_bit_count;
392 
393   /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
394      it is ok to perform 'bset' operation.  */
395 
396   one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
397 
398   /* 'bset' is a performance extension instruction.  */
399   return (TARGET_PERF_EXT && (one_bit_count == 1));
400 }
401 
402 /* Function to check if 'btgl' instruction can be used with IVAL.  */
403 int
404 nds32_can_use_btgl_p (int ival)
405 {
406   int one_bit_count;
407 
408   /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
409      it is ok to perform 'btgl' operation.  */
410 
411   one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
412 
413   /* 'btgl' is a performance extension instruction.  */
414   return (TARGET_PERF_EXT && (one_bit_count == 1));
415 }
416 
417 /* Function to check if 'bitci' instruction can be used with IVAL.  */
418 int
419 nds32_can_use_bitci_p (int ival)
420 {
421   /* If we are using V3 ISA, we have 'bitci' instruction.
422      Try to see if we can present 'andi' semantic with
423      such 'bit-clear-immediate' operation.
424      For example, 'andi $r0,$r0,0xfffffffc' can be
425      presented with 'bitci $r0,$r0,3'.  */
426   return (TARGET_ISA_V3
427 	  && (ival < 0)
428 	  && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
429 }
430 
431 /* ------------------------------------------------------------------------ */
432