]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nds32/nds32-predicates.c
2015-06-17 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / 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.
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 "alias.h"
28 #include "symtab.h"
29 #include "tree.h"
30 #include "stor-layout.h"
31 #include "varasm.h"
32 #include "calls.h"
33 #include "rtl.h"
34 #include "regs.h"
35 #include "hard-reg-set.h"
36 #include "insn-config.h" /* Required by recog.h. */
37 #include "conditions.h"
38 #include "output.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(). */
42 #include "flags.h"
43 #include "function.h"
44 #include "insn-config.h"
45 #include "expmed.h"
46 #include "dojump.h"
47 #include "explow.h"
48 #include "emit-rtl.h"
49 #include "stmt.h"
50 #include "expr.h"
51 #include "recog.h"
52 #include "diagnostic-core.h"
53 #include "dominance.h"
54 #include "cfg.h"
55 #include "cfgrtl.h"
56 #include "cfganal.h"
57 #include "lcm.h"
58 #include "cfgbuild.h"
59 #include "cfgcleanup.h"
60 #include "predict.h"
61 #include "basic-block.h"
62 #include "df.h"
63 #include "tm_p.h"
64 #include "tm-constrs.h"
65 #include "optabs.h" /* For GEN_FCN. */
66 #include "target.h"
67 #include "target-def.h"
68 #include "langhooks.h" /* For add_builtin_function(). */
69 #include "builtins.h"
70
71 /* ------------------------------------------------------------------------ */
72
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. */
80 static bool
81 nds32_consecutive_registers_load_store_p (rtx op,
82 bool load_p,
83 int par_index,
84 int first_elt_regno,
85 int count)
86 {
87 int i;
88 int check_regno;
89 rtx elt;
90 rtx elt_reg;
91 rtx elt_mem;
92
93 for (i = 0; i < count; i++)
94 {
95 /* Pick up each element from parallel rtx. */
96 elt = XVECEXP (op, 0, i + par_index);
97
98 /* If this element is not a 'set' rtx, return false immediately. */
99 if (GET_CODE (elt) != SET)
100 return false;
101
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);
105
106 /* If elt_reg is not a expected reg rtx, return false. */
107 if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
108 return false;
109 /* If elt_mem is not a expected mem rtx, return false. */
110 if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
111 return false;
112
113 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
114 check_regno = first_elt_regno + i;
115
116 /* If the register number is not continuous, return false. */
117 if (REGNO (elt_reg) != (unsigned int) check_regno)
118 return false;
119 }
120
121 return true;
122 }
123
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.
128
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. */
135 bool
136 nds32_valid_multiple_load_store (rtx op, bool load_p)
137 {
138 int count;
139 int first_elt_regno;
140 rtx elt;
141
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);
146
147 /* Perform some quick check for the first element in the parallel rtx. */
148 if (GET_CODE (elt) != SET
149 || count <= 1
150 || count > 8)
151 return false;
152
153 /* Pick up regno of first element for further detail checking.
154 Note that the form is different between load and store operation. */
155 if (load_p)
156 {
157 if (GET_CODE (SET_DEST (elt)) != REG
158 || GET_CODE (SET_SRC (elt)) != MEM)
159 return false;
160
161 first_elt_regno = REGNO (SET_DEST (elt));
162 }
163 else
164 {
165 if (GET_CODE (SET_SRC (elt)) != REG
166 || GET_CODE (SET_DEST (elt)) != MEM)
167 return false;
168
169 first_elt_regno = REGNO (SET_SRC (elt));
170 }
171
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,
177 first_elt_regno,
178 count))
179 return false;
180
181 /* Pass all test, this is a valid rtx. */
182 return true;
183 }
184
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. */
191 bool
192 nds32_valid_stack_push_pop_p (rtx op, bool push_p)
193 {
194 int index;
195 int total_count;
196 int rest_count;
197 int first_regno;
198 int save_fp, save_gp, save_lp;
199 rtx elt;
200 rtx elt_reg;
201 rtx elt_mem;
202 rtx elt_plus;
203
204 /* Get the counts of elements in the parallel rtx. */
205 total_count = XVECLEN (op, 0);
206
207 /* Perform some quick check for that every element should be 'set'. */
208 for (index = 0; index < total_count; index++)
209 {
210 elt = XVECEXP (op, 0, index);
211 if (GET_CODE (elt) != SET)
212 return false;
213 }
214
215 /* For push operation, the parallel rtx looks like:
216 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
217 (reg:SI Rb))
218 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
219 (reg:SI Rb+1))
220 ...
221 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
222 (reg:SI Re))
223 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
224 (reg:SI FP_REGNUM))
225 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
226 (reg:SI GP_REGNUM))
227 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
228 (reg:SI LP_REGNUM))
229 (set (reg:SI SP_REGNUM)
230 (plus (reg:SI SP_REGNUM) (const_int -32)))])
231
232 For pop operation, the parallel rtx looks like:
233 (parallel [(set (reg:SI Rb)
234 (mem (reg:SI SP_REGNUM)))
235 (set (reg:SI Rb+1)
236 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
237 ...
238 (set (reg:SI Re)
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)))]) */
248
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. */
253
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. */
261 if (save_fp)
262 rest_count--;
263 if (save_gp)
264 rest_count--;
265 if (save_lp)
266 rest_count--;
267
268 if (rest_count > 0)
269 {
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);
274
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,
281 0,
282 first_regno,
283 rest_count))
284 return false;
285 }
286
287 /* 2. Valid $fp/$gp/$lp push/pop operations.
288 Remember to set start index for checking them. */
289
290 /* The rest_count is the start index for checking $fp/$gp/$lp. */
291 index = rest_count;
292 /* If index < 0, this parallel rtx is definitely
293 not a valid stack push/pop operation. */
294 if (index < 0)
295 return false;
296
297 /* Check $fp/$gp/$lp one by one.
298 We use 'push_p' to pick up reg rtx and mem rtx. */
299 if (save_fp)
300 {
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);
304 index++;
305
306 if (GET_CODE (elt_mem) != MEM
307 || GET_CODE (elt_reg) != REG
308 || REGNO (elt_reg) != FP_REGNUM)
309 return false;
310 }
311 if (save_gp)
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) != GP_REGNUM)
321 return false;
322 }
323 if (save_lp)
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) != LP_REGNUM)
333 return false;
334 }
335
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. */
341
342 /* Pick up the last element. */
343 elt = XVECEXP (op, 0, total_count - 1);
344
345 /* Extract its destination and source rtx. */
346 elt_reg = SET_DEST (elt);
347 elt_plus = SET_SRC (elt);
348
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)
353 return false;
354
355 /* Pass all test, this is a valid rtx. */
356 return true;
357 }
358
359 /* Function to check if 'bclr' instruction can be used with IVAL. */
360 int
361 nds32_can_use_bclr_p (int ival)
362 {
363 int one_bit_count;
364
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. */
368
369 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
370
371 /* 'bclr' is a performance extension instruction. */
372 return (TARGET_PERF_EXT && (one_bit_count == 1));
373 }
374
375 /* Function to check if 'bset' instruction can be used with IVAL. */
376 int
377 nds32_can_use_bset_p (int ival)
378 {
379 int one_bit_count;
380
381 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
382 it is ok to perform 'bset' operation. */
383
384 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
385
386 /* 'bset' is a performance extension instruction. */
387 return (TARGET_PERF_EXT && (one_bit_count == 1));
388 }
389
390 /* Function to check if 'btgl' instruction can be used with IVAL. */
391 int
392 nds32_can_use_btgl_p (int ival)
393 {
394 int one_bit_count;
395
396 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
397 it is ok to perform 'btgl' operation. */
398
399 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
400
401 /* 'btgl' is a performance extension instruction. */
402 return (TARGET_PERF_EXT && (one_bit_count == 1));
403 }
404
405 /* Function to check if 'bitci' instruction can be used with IVAL. */
406 int
407 nds32_can_use_bitci_p (int ival)
408 {
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
415 && (ival < 0)
416 && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
417 }
418
419 /* ------------------------------------------------------------------------ */