nds32-predicates.c revision 1.4
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.
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#define IN_TARGET_CODE 1
24
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"
38#include "insn-attr.h"
39
40/* ------------------------------------------------------------------------ */
41
42/* A subroutine that checks multiple load and store
43   using consecutive registers.
44     OP is a parallel rtx we would like to check.
45     LOAD_P indicates whether we are checking load operation.
46     PAR_INDEX is starting element of parallel rtx.
47     FIRST_ELT_REGNO is used to tell starting register number.
48     COUNT helps us to check consecutive register numbers.  */
49static bool
50nds32_consecutive_registers_load_store_p (rtx op,
51					  bool load_p,
52					  int par_index,
53					  int first_elt_regno,
54					  int count)
55{
56  int i;
57  int check_regno;
58  rtx elt;
59  rtx elt_reg;
60  rtx elt_mem;
61
62  for (i = 0; i < count; i++)
63    {
64      /* Pick up each element from parallel rtx.  */
65      elt = XVECEXP (op, 0, i + par_index);
66
67      /* If this element is not a 'set' rtx, return false immediately.  */
68      if (GET_CODE (elt) != SET)
69	return false;
70
71      /* Pick up reg and mem of this element.  */
72      elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
73      elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
74
75      /* If elt_reg is not a expected reg rtx, return false.  */
76      if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
77	return false;
78      /* If elt_mem is not a expected mem rtx, return false.  */
79      if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
80	return false;
81
82      /* The consecutive registers should be in (Rb,Rb+1...Re) order.  */
83      check_regno = first_elt_regno + i;
84
85      /* If the register number is not continuous, return false.  */
86      if (REGNO (elt_reg) != (unsigned int) check_regno)
87	return false;
88    }
89
90  return true;
91}
92
93/* Function to check whether the OP is a valid load/store operation.
94   This is a helper function for the predicates:
95   'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
96   in predicates.md file.
97
98   The OP is supposed to be a parallel rtx.
99   For each element within this parallel rtx:
100     (set (reg) (mem addr)) is the form for load operation.
101     (set (mem addr) (reg)) is the form for store operation.
102   We have to extract reg and mem of every element and
103   check if the information is valid for multiple load/store operation.  */
104bool
105nds32_valid_multiple_load_store_p (rtx op, bool load_p, bool bim_p)
106{
107  int count;
108  int first_elt_regno;
109  int update_base_elt_idx;
110  int offset;
111  rtx elt;
112  rtx update_base;
113
114  /* Get the counts of elements in the parallel rtx.
115     Last one is update base register if bim_p.
116     and pick up the first element.  */
117  if (bim_p)
118    {
119      count = XVECLEN (op, 0) - 1;
120      elt = XVECEXP (op, 0, 1);
121    }
122  else
123    {
124      count = XVECLEN (op, 0);
125      elt = XVECEXP (op, 0, 0);
126    }
127
128  /* Perform some quick check for the first element in the parallel rtx.  */
129  if (GET_CODE (elt) != SET
130      || count <= 1
131      || count > 25)
132    return false;
133
134  /* Pick up regno of first element for further detail checking.
135     Note that the form is different between load and store operation.  */
136  if (load_p)
137    {
138      if (GET_CODE (SET_DEST (elt)) != REG
139	  || GET_CODE (SET_SRC (elt)) != MEM)
140	return false;
141
142      first_elt_regno = REGNO (SET_DEST (elt));
143    }
144  else
145    {
146      if (GET_CODE (SET_SRC (elt)) != REG
147	  || GET_CODE (SET_DEST (elt)) != MEM)
148	return false;
149
150      first_elt_regno = REGNO (SET_SRC (elt));
151    }
152
153  /* Perform detail check for each element.
154     Refer to nds32-multiple.md for more information
155     about following checking.
156     The starting element of parallel rtx is index 0.  */
157  if (!nds32_consecutive_registers_load_store_p (op, load_p, bim_p ? 1 : 0,
158						 first_elt_regno,
159						 count))
160    return false;
161
162  if (bim_p)
163    {
164      update_base_elt_idx = 0;
165      update_base = XVECEXP (op, 0, update_base_elt_idx);
166      if (!REG_P (SET_DEST (update_base)))
167	return false;
168      if (GET_CODE (SET_SRC (update_base)) != PLUS)
169	return false;
170      else
171	{
172	  offset = count * UNITS_PER_WORD;
173	  elt = XEXP (SET_SRC (update_base), 1);
174	  if (GET_CODE (elt) != CONST_INT
175	      || (INTVAL (elt) != offset))
176	    return false;
177	}
178    }
179
180  /* Pass all test, this is a valid rtx.  */
181  return true;
182}
183
184/* Function to check whether the OP is a valid stack push/pop operation.
185   For a valid stack operation, it must satisfy following conditions:
186     1. Consecutive registers push/pop operations.
187     2. Valid $fp/$gp/$lp push/pop operations.
188     3. The last element must be stack adjustment rtx.
189   See the prologue/epilogue implementation for details.  */
190bool
191nds32_valid_stack_push_pop_p (rtx op, bool push_p)
192{
193  int index;
194  int total_count;
195  int rest_count;
196  int first_regno;
197  int save_fp, save_gp, save_lp;
198  rtx elt;
199  rtx elt_reg;
200  rtx elt_mem;
201  rtx elt_plus;
202
203  /* Get the counts of elements in the parallel rtx.  */
204  total_count = XVECLEN (op, 0);
205
206  /* Perform some quick check for that every element should be 'set'.  */
207  for (index = 0; index < total_count; index++)
208    {
209      elt = XVECEXP (op, 0, index);
210      if (GET_CODE (elt) != SET)
211	return false;
212    }
213
214  /* For push operation, the parallel rtx looks like:
215     (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
216		     (reg:SI Rb))
217		(set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
218		     (reg:SI Rb+1))
219		...
220		(set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
221		     (reg:SI Re))
222		(set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
223		     (reg:SI FP_REGNUM))
224		(set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
225		     (reg:SI GP_REGNUM))
226		(set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
227		     (reg:SI LP_REGNUM))
228		(set (reg:SI SP_REGNUM)
229		     (plus (reg:SI SP_REGNUM) (const_int -32)))])
230
231     For pop operation, the parallel rtx looks like:
232     (parallel [(set (reg:SI Rb)
233		     (mem (reg:SI SP_REGNUM)))
234		(set (reg:SI Rb+1)
235		     (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
236		...
237		(set (reg:SI Re)
238		     (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
239		(set (reg:SI FP_REGNUM)
240		     (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
241		(set (reg:SI GP_REGNUM)
242		     (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
243		(set (reg:SI LP_REGNUM)
244		     (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
245		(set (reg:SI SP_REGNUM)
246		     (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
247
248  /* 1. Consecutive registers push/pop operations.
249	We need to calculate how many registers should be consecutive.
250	The $sp adjustment rtx, $fp push rtx, $gp push rtx,
251	and $lp push rtx are excluded.  */
252
253  /* Detect whether we have $fp, $gp, or $lp in the parallel rtx.  */
254  save_fp = reg_mentioned_p (gen_rtx_REG (SImode, FP_REGNUM), op);
255  save_gp = reg_mentioned_p (gen_rtx_REG (SImode, GP_REGNUM), op);
256  save_lp = reg_mentioned_p (gen_rtx_REG (SImode, LP_REGNUM), op);
257  /* Exclude last $sp adjustment rtx.  */
258  rest_count = total_count - 1;
259  /* Exclude $fp, $gp, and $lp if they are in the parallel rtx.  */
260  if (save_fp)
261    rest_count--;
262  if (save_gp)
263    rest_count--;
264  if (save_lp)
265    rest_count--;
266
267  if (rest_count > 0)
268    {
269      elt = XVECEXP (op, 0, 0);
270      /* Pick up register element.  */
271      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
272      first_regno = REGNO (elt_reg);
273
274      /* The 'push' operation is a kind of store operation.
275	 The 'pop' operation is a kind of load operation.
276	 Pass corresponding false/true as second argument (bool load_p).
277	 The par_index is supposed to start with index 0.  */
278      if (!nds32_consecutive_registers_load_store_p (op,
279						     !push_p ? true : false,
280						     0,
281						     first_regno,
282						     rest_count))
283	return false;
284    }
285
286  /* 2. Valid $fp/$gp/$lp push/pop operations.
287	Remember to set start index for checking them.  */
288
289  /* The rest_count is the start index for checking $fp/$gp/$lp.  */
290  index = rest_count;
291  /* If index < 0, this parallel rtx is definitely
292     not a valid stack push/pop operation.  */
293  if (index < 0)
294    return false;
295
296  /* Check $fp/$gp/$lp one by one.
297     We use 'push_p' to pick up reg rtx and mem rtx.  */
298  if (save_fp)
299    {
300      elt = XVECEXP (op, 0, index);
301      elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
302      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
303      index++;
304
305      if (GET_CODE (elt_mem) != MEM
306	  || GET_CODE (elt_reg) != REG
307	  || REGNO (elt_reg) != FP_REGNUM)
308	return false;
309    }
310  if (save_gp)
311    {
312      elt = XVECEXP (op, 0, index);
313      elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
314      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
315      index++;
316
317      if (GET_CODE (elt_mem) != MEM
318	  || GET_CODE (elt_reg) != REG
319	  || REGNO (elt_reg) != GP_REGNUM)
320	return false;
321    }
322  if (save_lp)
323    {
324      elt = XVECEXP (op, 0, index);
325      elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
326      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
327      index++;
328
329      if (GET_CODE (elt_mem) != MEM
330	  || GET_CODE (elt_reg) != REG
331	  || REGNO (elt_reg) != LP_REGNUM)
332	return false;
333    }
334
335  /* 3. The last element must be stack adjustment rtx.
336	Its form of rtx should be:
337	  (set (reg:SI SP_REGNUM)
338	       (plus (reg:SI SP_REGNUM) (const_int X)))
339	The X could be positive or negative value.  */
340
341  /* Pick up the last element.  */
342  elt = XVECEXP (op, 0, total_count - 1);
343
344  /* Extract its destination and source rtx.  */
345  elt_reg  = SET_DEST (elt);
346  elt_plus = SET_SRC (elt);
347
348  /* Check this is (set (stack_reg) (plus stack_reg const)) pattern.  */
349  if (GET_CODE (elt_reg) != REG
350      || GET_CODE (elt_plus) != PLUS
351      || REGNO (elt_reg) != SP_REGNUM)
352    return false;
353
354  /* Pass all test, this is a valid rtx.  */
355  return true;
356}
357
358/* Function to check if 'bclr' instruction can be used with IVAL.  */
359int
360nds32_can_use_bclr_p (int ival)
361{
362  int one_bit_count;
363  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
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) & mask);
370
371  /* 'bclr' is a performance extension instruction.  */
372  return (TARGET_EXT_PERF && (one_bit_count == 1));
373}
374
375/* Function to check if 'bset' instruction can be used with IVAL.  */
376int
377nds32_can_use_bset_p (int ival)
378{
379  int one_bit_count;
380  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
381
382  /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
383     it is ok to perform 'bset' operation.  */
384
385  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
386
387  /* 'bset' is a performance extension instruction.  */
388  return (TARGET_EXT_PERF && (one_bit_count == 1));
389}
390
391/* Function to check if 'btgl' instruction can be used with IVAL.  */
392int
393nds32_can_use_btgl_p (int ival)
394{
395  int one_bit_count;
396  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
397
398  /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
399     it is ok to perform 'btgl' operation.  */
400
401  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
402
403  /* 'btgl' is a performance extension instruction.  */
404  return (TARGET_EXT_PERF && (one_bit_count == 1));
405}
406
407/* Function to check if 'bitci' instruction can be used with IVAL.  */
408int
409nds32_can_use_bitci_p (int ival)
410{
411  /* If we are using V3 ISA, we have 'bitci' instruction.
412     Try to see if we can present 'andi' semantic with
413     such 'bit-clear-immediate' operation.
414     For example, 'andi $r0,$r0,0xfffffffc' can be
415     presented with 'bitci $r0,$r0,3'.  */
416  return (TARGET_ISA_V3
417	  && (ival < 0)
418	  && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
419}
420
421/* Return true if is load/store with SYMBOL_REF addressing mode
422   and memory mode is SImode.  */
423bool
424nds32_symbol_load_store_p (rtx_insn *insn)
425{
426  rtx mem_src = NULL_RTX;
427
428  switch (get_attr_type (insn))
429    {
430    case TYPE_LOAD:
431      mem_src = SET_SRC (PATTERN (insn));
432      break;
433    case TYPE_STORE:
434      mem_src = SET_DEST (PATTERN (insn));
435      break;
436    default:
437      break;
438    }
439
440  /* Find load/store insn with addressing mode is SYMBOL_REF.  */
441  if (mem_src != NULL_RTX)
442    {
443      if ((GET_CODE (mem_src) == ZERO_EXTEND)
444	  || (GET_CODE (mem_src) == SIGN_EXTEND))
445	mem_src = XEXP (mem_src, 0);
446
447      if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF)
448	   || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM))
449	return true;
450    }
451
452  return false;
453}
454
455/* Vaild memory operand for floating-point loads and stores */
456bool
457nds32_float_mem_operand_p (rtx op)
458{
459  machine_mode mode = GET_MODE (op);
460  rtx addr = XEXP (op, 0);
461
462  /* Not support [symbol] [const] memory */
463  if (GET_CODE (addr) == SYMBOL_REF
464      || GET_CODE (addr) == CONST
465      || GET_CODE (addr) == LO_SUM)
466    return false;
467
468  if (GET_CODE (addr) == PLUS)
469    {
470      if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
471	return false;
472
473      /* Restrict const range: (imm12s << 2) */
474      if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
475	{
476	  if ((mode == SImode || mode == SFmode)
477	      && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
478	      && !satisfies_constraint_Is14 ( XEXP(addr, 1)))
479	    return false;
480
481	  if ((mode == DImode || mode == DFmode)
482	      && NDS32_DOUBLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
483	      && !satisfies_constraint_Is14 (XEXP (addr, 1)))
484	    return false;
485	}
486    }
487
488  return true;
489}
490
491int
492nds32_cond_move_p (rtx cmp_rtx)
493{
494  machine_mode cmp0_mode = GET_MODE (XEXP (cmp_rtx, 0));
495  machine_mode cmp1_mode = GET_MODE (XEXP (cmp_rtx, 1));
496  enum rtx_code cond = GET_CODE (cmp_rtx);
497
498  if ((cmp0_mode == DFmode || cmp0_mode == SFmode)
499      && (cmp1_mode == DFmode || cmp1_mode == SFmode)
500      && (cond == ORDERED || cond == UNORDERED))
501    return true;
502  return false;
503}
504
505bool
506nds32_const_double_range_ok_p (rtx op, machine_mode mode,
507			       HOST_WIDE_INT lower, HOST_WIDE_INT upper)
508{
509  if (GET_CODE (op) != CONST_DOUBLE
510      || GET_MODE (op) != mode)
511    return false;
512
513  const REAL_VALUE_TYPE *rv;
514  long val;
515
516  rv = CONST_DOUBLE_REAL_VALUE (op);
517  REAL_VALUE_TO_TARGET_SINGLE (*rv, val);
518
519  return val >= lower && val < upper;
520}
521/* ------------------------------------------------------------------------ */
522