diff gcc/config/nds32/nds32-predicates.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/config/nds32/nds32-predicates.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/config/nds32/nds32-predicates.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Predicate functions of Andes NDS32 cpu for GNU compiler
-   Copyright (C) 2012-2017 Free Software Foundation, Inc.
+   Copyright (C) 2012-2018 Free Software Foundation, Inc.
    Contributed by Andes Technology Corporation.
 
    This file is part of GCC.
@@ -20,6 +20,8 @@
 
 /* ------------------------------------------------------------------------ */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -33,6 +35,7 @@
 #include "emit-rtl.h"
 #include "recog.h"
 #include "tm-constrs.h"
+#include "insn-attr.h"
 
 /* ------------------------------------------------------------------------ */
 
@@ -99,21 +102,33 @@
    We have to extract reg and mem of every element and
    check if the information is valid for multiple load/store operation.  */
 bool
-nds32_valid_multiple_load_store (rtx op, bool load_p)
+nds32_valid_multiple_load_store_p (rtx op, bool load_p, bool bim_p)
 {
   int count;
   int first_elt_regno;
+  int update_base_elt_idx;
+  int offset;
   rtx elt;
+  rtx update_base;
 
-  /* Get the counts of elements in the parallel rtx.  */
-  count = XVECLEN (op, 0);
-  /* Pick up the first element.  */
-  elt = XVECEXP (op, 0, 0);
+  /* Get the counts of elements in the parallel rtx.
+     Last one is update base register if bim_p.
+     and pick up the first element.  */
+  if (bim_p)
+    {
+      count = XVECLEN (op, 0) - 1;
+      elt = XVECEXP (op, 0, 1);
+    }
+  else
+    {
+      count = XVECLEN (op, 0);
+      elt = XVECEXP (op, 0, 0);
+    }
 
   /* Perform some quick check for the first element in the parallel rtx.  */
   if (GET_CODE (elt) != SET
       || count <= 1
-      || count > 8)
+      || count > 25)
     return false;
 
   /* Pick up regno of first element for further detail checking.
@@ -139,11 +154,29 @@
      Refer to nds32-multiple.md for more information
      about following checking.
      The starting element of parallel rtx is index 0.  */
-  if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
+  if (!nds32_consecutive_registers_load_store_p (op, load_p, bim_p ? 1 : 0,
 						 first_elt_regno,
 						 count))
     return false;
 
+  if (bim_p)
+    {
+      update_base_elt_idx = 0;
+      update_base = XVECEXP (op, 0, update_base_elt_idx);
+      if (!REG_P (SET_DEST (update_base)))
+	return false;
+      if (GET_CODE (SET_SRC (update_base)) != PLUS)
+	return false;
+      else
+	{
+	  offset = count * UNITS_PER_WORD;
+	  elt = XEXP (SET_SRC (update_base), 1);
+	  if (GET_CODE (elt) != CONST_INT
+	      || (INTVAL (elt) != offset))
+	    return false;
+	}
+    }
+
   /* Pass all test, this is a valid rtx.  */
   return true;
 }
@@ -323,54 +356,57 @@
 }
 
 /* Function to check if 'bclr' instruction can be used with IVAL.  */
-int
-nds32_can_use_bclr_p (int ival)
+bool
+nds32_can_use_bclr_p (HOST_WIDE_INT ival)
 {
   int one_bit_count;
+  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
 
   /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
      it means the original ival has only one 0-bit,
      So it is ok to perform 'bclr' operation.  */
 
-  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
+  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival) & mask);
 
   /* 'bclr' is a performance extension instruction.  */
-  return (TARGET_PERF_EXT && (one_bit_count == 1));
+  return (TARGET_EXT_PERF && (one_bit_count == 1));
 }
 
 /* Function to check if 'bset' instruction can be used with IVAL.  */
-int
-nds32_can_use_bset_p (int ival)
+bool
+nds32_can_use_bset_p (HOST_WIDE_INT ival)
 {
   int one_bit_count;
+  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
 
   /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
      it is ok to perform 'bset' operation.  */
 
-  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
+  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
 
   /* 'bset' is a performance extension instruction.  */
-  return (TARGET_PERF_EXT && (one_bit_count == 1));
+  return (TARGET_EXT_PERF && (one_bit_count == 1));
 }
 
 /* Function to check if 'btgl' instruction can be used with IVAL.  */
-int
-nds32_can_use_btgl_p (int ival)
+bool
+nds32_can_use_btgl_p (HOST_WIDE_INT ival)
 {
   int one_bit_count;
+  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
 
   /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
      it is ok to perform 'btgl' operation.  */
 
-  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
+  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
 
   /* 'btgl' is a performance extension instruction.  */
-  return (TARGET_PERF_EXT && (one_bit_count == 1));
+  return (TARGET_EXT_PERF && (one_bit_count == 1));
 }
 
 /* Function to check if 'bitci' instruction can be used with IVAL.  */
-int
-nds32_can_use_bitci_p (int ival)
+bool
+nds32_can_use_bitci_p (HOST_WIDE_INT ival)
 {
   /* If we are using V3 ISA, we have 'bitci' instruction.
      Try to see if we can present 'andi' semantic with
@@ -382,4 +418,217 @@
 	  && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
 }
 
+/* Return true if is load/store with SYMBOL_REF addressing mode
+   and memory mode is SImode.  */
+bool
+nds32_symbol_load_store_p (rtx_insn *insn)
+{
+  rtx mem_src = NULL_RTX;
+
+  switch (get_attr_type (insn))
+    {
+    case TYPE_LOAD:
+      mem_src = SET_SRC (PATTERN (insn));
+      break;
+    case TYPE_STORE:
+      mem_src = SET_DEST (PATTERN (insn));
+      break;
+    default:
+      break;
+    }
+
+  /* Find load/store insn with addressing mode is SYMBOL_REF.  */
+  if (mem_src != NULL_RTX)
+    {
+      if ((GET_CODE (mem_src) == ZERO_EXTEND)
+	  || (GET_CODE (mem_src) == SIGN_EXTEND))
+	mem_src = XEXP (mem_src, 0);
+
+      if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF)
+	   || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM))
+	return true;
+    }
+
+  return false;
+}
+
+/* Vaild memory operand for floating-point loads and stores */
+bool
+nds32_float_mem_operand_p (rtx op)
+{
+  machine_mode mode = GET_MODE (op);
+  rtx addr = XEXP (op, 0);
+
+  /* Not support [symbol] [const] memory */
+  if (GET_CODE (addr) == SYMBOL_REF
+      || GET_CODE (addr) == CONST
+      || GET_CODE (addr) == LO_SUM)
+    return false;
+
+  if (GET_CODE (addr) == PLUS)
+    {
+      if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
+	return false;
+
+      /* Restrict const range: (imm12s << 2) */
+      if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+	{
+	  if ((mode == SImode || mode == SFmode)
+	      && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
+	      && !satisfies_constraint_Is14 ( XEXP(addr, 1)))
+	    return false;
+
+	  if ((mode == DImode || mode == DFmode)
+	      && NDS32_DOUBLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
+	      && !satisfies_constraint_Is14 (XEXP (addr, 1)))
+	    return false;
+	}
+    }
+
+  return true;
+}
+
+int
+nds32_cond_move_p (rtx cmp_rtx)
+{
+  machine_mode cmp0_mode = GET_MODE (XEXP (cmp_rtx, 0));
+  machine_mode cmp1_mode = GET_MODE (XEXP (cmp_rtx, 1));
+  enum rtx_code cond = GET_CODE (cmp_rtx);
+
+  if ((cmp0_mode == DFmode || cmp0_mode == SFmode)
+      && (cmp1_mode == DFmode || cmp1_mode == SFmode)
+      && (cond == ORDERED || cond == UNORDERED))
+    return true;
+  return false;
+}
+
+bool
+nds32_const_double_range_ok_p (rtx op, machine_mode mode,
+			       HOST_WIDE_INT lower, HOST_WIDE_INT upper)
+{
+  if (GET_CODE (op) != CONST_DOUBLE
+      || GET_MODE (op) != mode)
+    return false;
+
+  const REAL_VALUE_TYPE *rv;
+  long val;
+
+  rv = CONST_DOUBLE_REAL_VALUE (op);
+  REAL_VALUE_TO_TARGET_SINGLE (*rv, val);
+
+  return val >= lower && val < upper;
+}
+
+bool
+nds32_const_unspec_p (rtx x)
+{
+  if (GET_CODE (x) == CONST)
+    {
+      x = XEXP (x, 0);
+
+      if (GET_CODE (x) == PLUS)
+	x = XEXP (x, 0);
+
+      if (GET_CODE (x) == UNSPEC)
+	{
+	  switch (XINT (x, 1))
+	    {
+	    case UNSPEC_GOTINIT:
+	    case UNSPEC_GOT:
+	    case UNSPEC_GOTOFF:
+	    case UNSPEC_PLT:
+	    case UNSPEC_TLSGD:
+	    case UNSPEC_TLSLD:
+	    case UNSPEC_TLSIE:
+	    case UNSPEC_TLSLE:
+	      return false;
+	    default:
+	      return true;
+	    }
+	}
+    }
+
+  if (GET_CODE (x) == SYMBOL_REF
+      && SYMBOL_REF_TLS_MODEL (x))
+    return false;
+
+  return true;
+}
+
+HOST_WIDE_INT
+const_vector_to_hwint (rtx op)
+{
+  HOST_WIDE_INT hwint = 0;
+  HOST_WIDE_INT mask;
+  int i;
+  int shift_adv;
+  int shift = 0;
+  int nelem;
+
+  switch (GET_MODE (op))
+    {
+      case E_V2HImode:
+	mask = 0xffff;
+	shift_adv = 16;
+	nelem = 2;
+	break;
+      case E_V4QImode:
+	mask = 0xff;
+	shift_adv = 8;
+	nelem = 4;
+	break;
+      default:
+	gcc_unreachable ();
+    }
+
+  if (TARGET_BIG_ENDIAN)
+    {
+      for (i = 0; i < nelem; ++i)
+	{
+	  HOST_WIDE_INT val = XINT (XVECEXP (op, 0, nelem - i - 1), 0);
+	  hwint |= (val & mask) << shift;
+	  shift = shift + shift_adv;
+	}
+    }
+  else
+    {
+      for (i = 0; i < nelem; ++i)
+	{
+	  HOST_WIDE_INT val = XINT (XVECEXP (op, 0, i), 0);
+	  hwint |= (val & mask) << shift;
+	  shift = shift + shift_adv;
+	}
+    }
+
+  return hwint;
+}
+
+bool
+nds32_valid_CVp5_p (rtx op)
+{
+  HOST_WIDE_INT ival = const_vector_to_hwint (op);
+  return (ival < ((1 << 5) + 16)) && (ival >= (0 + 16));
+}
+
+bool
+nds32_valid_CVs5_p (rtx op)
+{
+  HOST_WIDE_INT ival = const_vector_to_hwint (op);
+  return (ival < (1 << 4)) && (ival >= -(1 << 4));
+}
+
+bool
+nds32_valid_CVs2_p (rtx op)
+{
+  HOST_WIDE_INT ival = const_vector_to_hwint (op);
+  return (ival < (1 << 19)) && (ival >= -(1 << 19));
+}
+
+bool
+nds32_valid_CVhi_p (rtx op)
+{
+  HOST_WIDE_INT ival = const_vector_to_hwint (op);
+  return (ival != 0) && ((ival & 0xfff) == 0);
+}
+
 /* ------------------------------------------------------------------------ */