Mercurial > hg > CbC > CbC_gcc
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); +} + /* ------------------------------------------------------------------------ */