111
|
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.
|
|
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 "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"
|
|
36
|
|
37 /* ------------------------------------------------------------------------ */
|
|
38
|
|
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)
|
|
52 {
|
|
53 int i;
|
|
54 int check_regno;
|
|
55 rtx elt;
|
|
56 rtx elt_reg;
|
|
57 rtx elt_mem;
|
|
58
|
|
59 for (i = 0; i < count; i++)
|
|
60 {
|
|
61 /* Pick up each element from parallel rtx. */
|
|
62 elt = XVECEXP (op, 0, i + par_index);
|
|
63
|
|
64 /* If this element is not a 'set' rtx, return false immediately. */
|
|
65 if (GET_CODE (elt) != SET)
|
|
66 return false;
|
|
67
|
|
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);
|
|
71
|
|
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;
|
|
78
|
|
79 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
|
|
80 check_regno = first_elt_regno + i;
|
|
81
|
|
82 /* If the register number is not continuous, return false. */
|
|
83 if (REGNO (elt_reg) != (unsigned int) check_regno)
|
|
84 return false;
|
|
85 }
|
|
86
|
|
87 return true;
|
|
88 }
|
|
89
|
|
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.
|
|
94
|
|
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)
|
|
103 {
|
|
104 int count;
|
|
105 int first_elt_regno;
|
|
106 rtx elt;
|
|
107
|
|
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);
|
|
112
|
|
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;
|
|
118
|
|
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)
|
|
122 {
|
|
123 if (GET_CODE (SET_DEST (elt)) != REG
|
|
124 || GET_CODE (SET_SRC (elt)) != MEM)
|
|
125 return false;
|
|
126
|
|
127 first_elt_regno = REGNO (SET_DEST (elt));
|
|
128 }
|
|
129 else
|
|
130 {
|
|
131 if (GET_CODE (SET_SRC (elt)) != REG
|
|
132 || GET_CODE (SET_DEST (elt)) != MEM)
|
|
133 return false;
|
|
134
|
|
135 first_elt_regno = REGNO (SET_SRC (elt));
|
|
136 }
|
|
137
|
|
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;
|
|
146
|
|
147 /* Pass all test, this is a valid rtx. */
|
|
148 return true;
|
|
149 }
|
|
150
|
|
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)
|
|
159 {
|
|
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;
|
|
169
|
|
170 /* Get the counts of elements in the parallel rtx. */
|
|
171 total_count = XVECLEN (op, 0);
|
|
172
|
|
173 /* Perform some quick check for that every element should be 'set'. */
|
|
174 for (index = 0; index < total_count; index++)
|
|
175 {
|
|
176 elt = XVECEXP (op, 0, index);
|
|
177 if (GET_CODE (elt) != SET)
|
|
178 return false;
|
|
179 }
|
|
180
|
|
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))
|
|
186 ...
|
|
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)))])
|
|
197
|
|
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))))
|
|
203 ...
|
|
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)))]) */
|
|
214
|
|
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. */
|
|
219
|
|
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--;
|
|
233
|
|
234 if (rest_count > 0)
|
|
235 {
|
|
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);
|
|
240
|
|
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,
|
|
247 0,
|
|
248 first_regno,
|
|
249 rest_count))
|
|
250 return false;
|
|
251 }
|
|
252
|
|
253 /* 2. Valid $fp/$gp/$lp push/pop operations.
|
|
254 Remember to set start index for checking them. */
|
|
255
|
|
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;
|
|
262
|
|
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)
|
|
266 {
|
|
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++;
|
|
271
|
|
272 if (GET_CODE (elt_mem) != MEM
|
|
273 || GET_CODE (elt_reg) != REG
|
|
274 || REGNO (elt_reg) != FP_REGNUM)
|
|
275 return false;
|
|
276 }
|
|
277 if (save_gp)
|
|
278 {
|
|
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++;
|
|
283
|
|
284 if (GET_CODE (elt_mem) != MEM
|
|
285 || GET_CODE (elt_reg) != REG
|
|
286 || REGNO (elt_reg) != GP_REGNUM)
|
|
287 return false;
|
|
288 }
|
|
289 if (save_lp)
|
|
290 {
|
|
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++;
|
|
295
|
|
296 if (GET_CODE (elt_mem) != MEM
|
|
297 || GET_CODE (elt_reg) != REG
|
|
298 || REGNO (elt_reg) != LP_REGNUM)
|
|
299 return false;
|
|
300 }
|
|
301
|
|
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. */
|
|
307
|
|
308 /* Pick up the last element. */
|
|
309 elt = XVECEXP (op, 0, total_count - 1);
|
|
310
|
|
311 /* Extract its destination and source rtx. */
|
|
312 elt_reg = SET_DEST (elt);
|
|
313 elt_plus = SET_SRC (elt);
|
|
314
|
|
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;
|
|
320
|
|
321 /* Pass all test, this is a valid rtx. */
|
|
322 return true;
|
|
323 }
|
|
324
|
|
325 /* Function to check if 'bclr' instruction can be used with IVAL. */
|
|
326 int
|
|
327 nds32_can_use_bclr_p (int ival)
|
|
328 {
|
|
329 int one_bit_count;
|
|
330
|
|
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. */
|
|
334
|
|
335 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
|
|
336
|
|
337 /* 'bclr' is a performance extension instruction. */
|
|
338 return (TARGET_PERF_EXT && (one_bit_count == 1));
|
|
339 }
|
|
340
|
|
341 /* Function to check if 'bset' instruction can be used with IVAL. */
|
|
342 int
|
|
343 nds32_can_use_bset_p (int ival)
|
|
344 {
|
|
345 int one_bit_count;
|
|
346
|
|
347 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
|
|
348 it is ok to perform 'bset' operation. */
|
|
349
|
|
350 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
|
|
351
|
|
352 /* 'bset' is a performance extension instruction. */
|
|
353 return (TARGET_PERF_EXT && (one_bit_count == 1));
|
|
354 }
|
|
355
|
|
356 /* Function to check if 'btgl' instruction can be used with IVAL. */
|
|
357 int
|
|
358 nds32_can_use_btgl_p (int ival)
|
|
359 {
|
|
360 int one_bit_count;
|
|
361
|
|
362 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
|
|
363 it is ok to perform 'btgl' operation. */
|
|
364
|
|
365 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
|
|
366
|
|
367 /* 'btgl' is a performance extension instruction. */
|
|
368 return (TARGET_PERF_EXT && (one_bit_count == 1));
|
|
369 }
|
|
370
|
|
371 /* Function to check if 'bitci' instruction can be used with IVAL. */
|
|
372 int
|
|
373 nds32_can_use_bitci_p (int ival)
|
|
374 {
|
|
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)));
|
|
383 }
|
|
384
|
|
385 /* ------------------------------------------------------------------------ */
|