diff options
author | Chung-Ju Wu <jasonwucj@gmail.com> | 2014-07-04 07:30:04 +0000 |
---|---|---|
committer | Chung-Ju Wu <jasonwucj@gcc.gnu.org> | 2014-07-04 07:30:04 +0000 |
commit | 6a2a98b1a658893ecb790c90614900d7bf8bd022 (patch) | |
tree | a53035313feca19b44de973887d95dc9c58a04e1 /gcc | |
parent | aaa44d2d0bb56f15efc400c66415dce03a8f2da2 (diff) | |
download | gcc-6a2a98b1a658893ecb790c90614900d7bf8bd022.zip gcc-6a2a98b1a658893ecb790c90614900d7bf8bd022.tar.gz gcc-6a2a98b1a658893ecb790c90614900d7bf8bd022.tar.bz2 |
Move some helper functions of predicates and constraints to nds32-predicates.c module.
gcc/
* config/nds32/nds32.c
(nds32_consecutive_registers_load_store_p): Move to ...
(nds32_valid_multiple_load_store): Move to ...
(nds32_valid_stack_push_pop): Move to ...
(nds32_can_use_bclr_p): Move to ...
(nds32_can_use_bset_p): Move to ...
(nds32_can_use_btgl_p): Move to ...
(nds32_can_use_bitci_p): Move to ...
* config/nds32/nds32-predicates.c: ... here.
Co-Authored-By: Kito Cheng <kito@0xlab.org>
Co-Authored-By: Monk Chiang <sh.chiang04@gmail.com>
From-SVN: r212283
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/nds32/nds32-predicates.c | 379 | ||||
-rw-r--r-- | gcc/config/nds32/nds32.c | 341 |
3 files changed, 393 insertions, 341 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 61899bf..1d08a69 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -3,6 +3,20 @@ Monk Chiang <sh.chiang04@gmail.com> * config/nds32/nds32.c + (nds32_consecutive_registers_load_store_p): Move to ... + (nds32_valid_multiple_load_store): Move to ... + (nds32_valid_stack_push_pop): Move to ... + (nds32_can_use_bclr_p): Move to ... + (nds32_can_use_bset_p): Move to ... + (nds32_can_use_btgl_p): Move to ... + (nds32_can_use_bitci_p): Move to ... + * config/nds32/nds32-predicates.c: ... here. + +2014-07-04 Chung-Ju Wu <jasonwucj@gmail.com> + Kito Cheng <kito@0xlab.org> + Monk Chiang <sh.chiang04@gmail.com> + + * config/nds32/nds32.c (nds32_expand_builtin_null_ftype_reg): Move to ... (nds32_expand_builtin_reg_ftype_imm): Move to ... (nds32_expand_builtin_null_ftype_reg_imm): Move to ... diff --git a/gcc/config/nds32/nds32-predicates.c b/gcc/config/nds32/nds32-predicates.c index 2c0ac0b..72cd739 100644 --- a/gcc/config/nds32/nds32-predicates.c +++ b/gcc/config/nds32/nds32-predicates.c @@ -17,3 +17,382 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ + +/* ------------------------------------------------------------------------ */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "stor-layout.h" +#include "varasm.h" +#include "calls.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "insn-config.h" /* Required by recog.h. */ +#include "conditions.h" +#include "output.h" +#include "insn-attr.h" /* For DFA state_t. */ +#include "insn-codes.h" /* For CODE_FOR_xxx. */ +#include "reload.h" /* For push_reload(). */ +#include "flags.h" +#include "function.h" +#include "expr.h" +#include "recog.h" +#include "diagnostic-core.h" +#include "df.h" +#include "tm_p.h" +#include "tm-constrs.h" +#include "optabs.h" /* For GEN_FCN. */ +#include "target.h" +#include "target-def.h" +#include "langhooks.h" /* For add_builtin_function(). */ +#include "ggc.h" +#include "builtins.h" + +/* ------------------------------------------------------------------------ */ + +/* A subroutine that checks multiple load and store + using consecutive registers. + OP is a parallel rtx we would like to check. + LOAD_P indicates whether we are checking load operation. + PAR_INDEX is starting element of parallel rtx. + FIRST_ELT_REGNO is used to tell starting register number. + COUNT helps us to check consecutive register numbers. */ +static bool +nds32_consecutive_registers_load_store_p (rtx op, + bool load_p, + int par_index, + int first_elt_regno, + int count) +{ + int i; + int check_regno; + rtx elt; + rtx elt_reg; + rtx elt_mem; + + for (i = 0; i < count; i++) + { + /* Pick up each element from parallel rtx. */ + elt = XVECEXP (op, 0, i + par_index); + + /* If this element is not a 'set' rtx, return false immediately. */ + if (GET_CODE (elt) != SET) + return false; + + /* Pick up reg and mem of this element. */ + elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt); + elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt); + + /* If elt_reg is not a expected reg rtx, return false. */ + if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode) + return false; + /* If elt_mem is not a expected mem rtx, return false. */ + if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode) + return false; + + /* The consecutive registers should be in (Rb,Rb+1...Re) order. */ + check_regno = first_elt_regno + i; + + /* If the register number is not continuous, return false. */ + if (REGNO (elt_reg) != (unsigned int) check_regno) + return false; + } + + return true; +} + +/* Function to check whether the OP is a valid load/store operation. + This is a helper function for the predicates: + 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation' + in predicates.md file. + + The OP is supposed to be a parallel rtx. + For each element within this parallel rtx: + (set (reg) (mem addr)) is the form for load operation. + (set (mem addr) (reg)) is the form for store operation. + 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) +{ + int count; + int first_elt_regno; + rtx elt; + + /* Get the counts of elements in the parallel rtx. */ + count = XVECLEN (op, 0); + /* Pick up the first element. */ + 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) + return false; + + /* Pick up regno of first element for further detail checking. + Note that the form is different between load and store operation. */ + if (load_p) + { + if (GET_CODE (SET_DEST (elt)) != REG + || GET_CODE (SET_SRC (elt)) != MEM) + return false; + + first_elt_regno = REGNO (SET_DEST (elt)); + } + else + { + if (GET_CODE (SET_SRC (elt)) != REG + || GET_CODE (SET_DEST (elt)) != MEM) + return false; + + first_elt_regno = REGNO (SET_SRC (elt)); + } + + /* Perform detail check for each element. + 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, + first_elt_regno, + count)) + return false; + + /* Pass all test, this is a valid rtx. */ + return true; +} + +/* Function to check whether the OP is a valid stack push/pop operation. + For a valid stack operation, it must satisfy following conditions: + 1. Consecutive registers push/pop operations. + 2. Valid $fp/$gp/$lp push/pop operations. + 3. The last element must be stack adjustment rtx. + See the prologue/epilogue implementation for details. */ +bool +nds32_valid_stack_push_pop (rtx op, bool push_p) +{ + int index; + int total_count; + int rest_count; + int first_regno; + rtx elt; + rtx elt_reg; + rtx elt_mem; + rtx elt_plus; + + /* Get the counts of elements in the parallel rtx. */ + total_count = XVECLEN (op, 0); + + /* Perform some quick check for that every element should be 'set'. */ + for (index = 0; index < total_count; index++) + { + elt = XVECEXP (op, 0, index); + if (GET_CODE (elt) != SET) + return false; + } + + /* For push operation, the parallel rtx looks like: + (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) + (reg:SI Rb)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) + (reg:SI Rb+1)) + ... + (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) + (reg:SI Re)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) + (reg:SI FP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) + (reg:SI GP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) + (reg:SI LP_REGNUM)) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int -32)))]) + + For pop operation, the parallel rtx looks like: + (parallel [(set (reg:SI Rb) + (mem (reg:SI SP_REGNUM))) + (set (reg:SI Rb+1) + (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) + ... + (set (reg:SI Re) + (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) + (set (reg:SI FP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) + (set (reg:SI GP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) + (set (reg:SI LP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ + + /* 1. Consecutive registers push/pop operations. + We need to calculate how many registers should be consecutive. + The $sp adjustment rtx, $fp push rtx, $gp push rtx, + and $lp push rtx are excluded. */ + + /* Exclude last $sp adjustment rtx. */ + rest_count = total_count - 1; + /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */ + if (cfun->machine->fp_size) + rest_count--; + if (cfun->machine->gp_size) + rest_count--; + if (cfun->machine->lp_size) + rest_count--; + + if (rest_count > 0) + { + elt = XVECEXP (op, 0, 0); + /* Pick up register element. */ + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + first_regno = REGNO (elt_reg); + + /* The 'push' operation is a kind of store operation. + The 'pop' operation is a kind of load operation. + Pass corresponding false/true as second argument (bool load_p). + The par_index is supposed to start with index 0. */ + if (!nds32_consecutive_registers_load_store_p (op, + !push_p ? true : false, + 0, + first_regno, + rest_count)) + return false; + } + + /* 2. Valid $fp/$gp/$lp push/pop operations. + Remember to set start index for checking them. */ + + /* The rest_count is the start index for checking $fp/$gp/$lp. */ + index = rest_count; + /* If index < 0, this parallel rtx is definitely + not a valid stack push/pop operation. */ + if (index < 0) + return false; + + /* Check $fp/$gp/$lp one by one. + We use 'push_p' to pick up reg rtx and mem rtx. */ + if (cfun->machine->fp_size) + { + elt = XVECEXP (op, 0, index); + elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + index++; + + if (GET_CODE (elt_mem) != MEM + || GET_CODE (elt_reg) != REG + || REGNO (elt_reg) != FP_REGNUM) + return false; + } + if (cfun->machine->gp_size) + { + elt = XVECEXP (op, 0, index); + elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + index++; + + if (GET_CODE (elt_mem) != MEM + || GET_CODE (elt_reg) != REG + || REGNO (elt_reg) != GP_REGNUM) + return false; + } + if (cfun->machine->lp_size) + { + elt = XVECEXP (op, 0, index); + elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + index++; + + if (GET_CODE (elt_mem) != MEM + || GET_CODE (elt_reg) != REG + || REGNO (elt_reg) != LP_REGNUM) + return false; + } + + /* 3. The last element must be stack adjustment rtx. + Its form of rtx should be: + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int X))) + The X could be positive or negative value. */ + + /* Pick up the last element. */ + elt = XVECEXP (op, 0, total_count - 1); + + /* Extract its destination and source rtx. */ + elt_reg = SET_DEST (elt); + elt_plus = SET_SRC (elt); + + /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */ + if (GET_CODE (elt_reg) != REG + || GET_CODE (elt_plus) != PLUS + || REGNO (elt_reg) != SP_REGNUM) + return false; + + /* Pass all test, this is a valid rtx. */ + return true; +} + +/* Function to check if 'bclr' instruction can be used with IVAL. */ +int +nds32_can_use_bclr_p (int ival) +{ + int one_bit_count; + + /* 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)); + + /* 'bclr' is a performance extension instruction. */ + return (TARGET_PERF_EXT && (one_bit_count == 1)); +} + +/* Function to check if 'bset' instruction can be used with IVAL. */ +int +nds32_can_use_bset_p (int ival) +{ + int one_bit_count; + + /* 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)); + + /* 'bset' is a performance extension instruction. */ + return (TARGET_PERF_EXT && (one_bit_count == 1)); +} + +/* Function to check if 'btgl' instruction can be used with IVAL. */ +int +nds32_can_use_btgl_p (int ival) +{ + int one_bit_count; + + /* 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)); + + /* 'btgl' is a performance extension instruction. */ + return (TARGET_PERF_EXT && (one_bit_count == 1)); +} + +/* Function to check if 'bitci' instruction can be used with IVAL. */ +int +nds32_can_use_bitci_p (int ival) +{ + /* If we are using V3 ISA, we have 'bitci' instruction. + Try to see if we can present 'andi' semantic with + such 'bit-clear-immediate' operation. + For example, 'andi $r0,$r0,0xfffffffc' can be + presented with 'bitci $r0,$r0,3'. */ + return (TARGET_ISA_V3 + && (ival < 0) + && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode))); +} + +/* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index e4dd770..922d9e4 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -849,57 +849,6 @@ nds32_gen_stack_v3pop (rtx Rb, return parallel_insn; } -/* A subroutine that checks multiple load and store - using consecutive registers. - OP is a parallel rtx we would like to check. - LOAD_P indicates whether we are checking load operation. - PAR_INDEX is starting element of parallel rtx. - FIRST_ELT_REGNO is used to tell starting register number. - COUNT helps us to check consecutive register numbers. */ -static bool -nds32_consecutive_registers_load_store_p (rtx op, - bool load_p, - int par_index, - int first_elt_regno, - int count) -{ - int i; - int check_regno; - rtx elt; - rtx elt_reg; - rtx elt_mem; - - for (i = 0; i < count; i++) - { - /* Pick up each element from parallel rtx. */ - elt = XVECEXP (op, 0, i + par_index); - - /* If this element is not a 'set' rtx, return false immediately. */ - if (GET_CODE (elt) != SET) - return false; - - /* Pick up reg and mem of this element. */ - elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt); - elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt); - - /* If elt_reg is not a expected reg rtx, return false. */ - if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode) - return false; - /* If elt_mem is not a expected mem rtx, return false. */ - if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode) - return false; - - /* The consecutive registers should be in (Rb,Rb+1...Re) order. */ - check_regno = first_elt_regno + i; - - /* If the register number is not continuous, return false. */ - if (REGNO (elt_reg) != (unsigned int) check_regno) - return false; - } - - return true; -} - /* Function that may creates more instructions for large value on adjusting stack pointer. @@ -3499,236 +3448,6 @@ nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment) return 1; } -/* Function to check whether the OP is a valid load/store operation. - This is a helper function for the predicates: - 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation' - in predicates.md file. - - The OP is supposed to be a parallel rtx. - For each element within this parallel rtx: - (set (reg) (mem addr)) is the form for load operation. - (set (mem addr) (reg)) is the form for store operation. - 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) -{ - int count; - int first_elt_regno; - rtx elt; - - /* Get the counts of elements in the parallel rtx. */ - count = XVECLEN (op, 0); - /* Pick up the first element. */ - 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) - return false; - - /* Pick up regno of first element for further detail checking. - Note that the form is different between load and store operation. */ - if (load_p) - { - if (GET_CODE (SET_DEST (elt)) != REG - || GET_CODE (SET_SRC (elt)) != MEM) - return false; - - first_elt_regno = REGNO (SET_DEST (elt)); - } - else - { - if (GET_CODE (SET_SRC (elt)) != REG - || GET_CODE (SET_DEST (elt)) != MEM) - return false; - - first_elt_regno = REGNO (SET_SRC (elt)); - } - - /* Perform detail check for each element. - 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, - first_elt_regno, - count)) - return false; - - /* Pass all test, this is a valid rtx. */ - return true; -} - -/* Function to check whether the OP is a valid stack push/pop operation. - For a valid stack operation, it must satisfy following conditions: - 1. Consecutive registers push/pop operations. - 2. Valid $fp/$gp/$lp push/pop operations. - 3. The last element must be stack adjustment rtx. - See the prologue/epilogue implementation for details. */ -bool -nds32_valid_stack_push_pop (rtx op, bool push_p) -{ - int index; - int total_count; - int rest_count; - int first_regno; - rtx elt; - rtx elt_reg; - rtx elt_mem; - rtx elt_plus; - - /* Get the counts of elements in the parallel rtx. */ - total_count = XVECLEN (op, 0); - - /* Perform some quick check for that every element should be 'set'. */ - for (index = 0; index < total_count; index++) - { - elt = XVECEXP (op, 0, index); - if (GET_CODE (elt) != SET) - return false; - } - - /* For push operation, the parallel rtx looks like: - (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) - (reg:SI Rb)) - (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) - (reg:SI Rb+1)) - ... - (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) - (reg:SI Re)) - (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) - (reg:SI FP_REGNUM)) - (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) - (reg:SI GP_REGNUM)) - (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) - (reg:SI LP_REGNUM)) - (set (reg:SI SP_REGNUM) - (plus (reg:SI SP_REGNUM) (const_int -32)))]) - - For pop operation, the parallel rtx looks like: - (parallel [(set (reg:SI Rb) - (mem (reg:SI SP_REGNUM))) - (set (reg:SI Rb+1) - (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) - ... - (set (reg:SI Re) - (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) - (set (reg:SI FP_REGNUM) - (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) - (set (reg:SI GP_REGNUM) - (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) - (set (reg:SI LP_REGNUM) - (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) - (set (reg:SI SP_REGNUM) - (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ - - /* 1. Consecutive registers push/pop operations. - We need to calculate how many registers should be consecutive. - The $sp adjustment rtx, $fp push rtx, $gp push rtx, - and $lp push rtx are excluded. */ - - /* Exclude last $sp adjustment rtx. */ - rest_count = total_count - 1; - /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */ - if (cfun->machine->fp_size) - rest_count--; - if (cfun->machine->gp_size) - rest_count--; - if (cfun->machine->lp_size) - rest_count--; - - if (rest_count > 0) - { - elt = XVECEXP (op, 0, 0); - /* Pick up register element. */ - elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); - first_regno = REGNO (elt_reg); - - /* The 'push' operation is a kind of store operation. - The 'pop' operation is a kind of load operation. - Pass corresponding false/true as second argument (bool load_p). - The par_index is supposed to start with index 0. */ - if (!nds32_consecutive_registers_load_store_p (op, - !push_p ? true : false, - 0, - first_regno, - rest_count)) - return false; - } - - /* 2. Valid $fp/$gp/$lp push/pop operations. - Remember to set start index for checking them. */ - - /* The rest_count is the start index for checking $fp/$gp/$lp. */ - index = rest_count; - /* If index < 0, this parallel rtx is definitely - not a valid stack push/pop operation. */ - if (index < 0) - return false; - - /* Check $fp/$gp/$lp one by one. - We use 'push_p' to pick up reg rtx and mem rtx. */ - if (cfun->machine->fp_size) - { - elt = XVECEXP (op, 0, index); - elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); - elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); - index++; - - if (GET_CODE (elt_mem) != MEM - || GET_CODE (elt_reg) != REG - || REGNO (elt_reg) != FP_REGNUM) - return false; - } - if (cfun->machine->gp_size) - { - elt = XVECEXP (op, 0, index); - elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); - elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); - index++; - - if (GET_CODE (elt_mem) != MEM - || GET_CODE (elt_reg) != REG - || REGNO (elt_reg) != GP_REGNUM) - return false; - } - if (cfun->machine->lp_size) - { - elt = XVECEXP (op, 0, index); - elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); - elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); - index++; - - if (GET_CODE (elt_mem) != MEM - || GET_CODE (elt_reg) != REG - || REGNO (elt_reg) != LP_REGNUM) - return false; - } - - /* 3. The last element must be stack adjustment rtx. - Its form of rtx should be: - (set (reg:SI SP_REGNUM) - (plus (reg:SI SP_REGNUM) (const_int X))) - The X could be positive or negative value. */ - - /* Pick up the last element. */ - elt = XVECEXP (op, 0, total_count - 1); - - /* Extract its destination and source rtx. */ - elt_reg = SET_DEST (elt); - elt_plus = SET_SRC (elt); - - /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */ - if (GET_CODE (elt_reg) != REG - || GET_CODE (elt_plus) != PLUS - || REGNO (elt_reg) != SP_REGNUM) - return false; - - /* Pass all test, this is a valid rtx. */ - return true; -} - /* Computing the Length of an Insn. Modifies the length assigned to instruction INSN. LEN is the initially computed length of the insn. */ @@ -3760,66 +3479,6 @@ nds32_adjust_insn_length (rtx insn, int length) } -/* Function to check if 'bclr' instruction can be used with IVAL. */ -int -nds32_can_use_bclr_p (int ival) -{ - int one_bit_count; - - /* 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)); - - /* 'bclr' is a performance extension instruction. */ - return (TARGET_PERF_EXT && (one_bit_count == 1)); -} - -/* Function to check if 'bset' instruction can be used with IVAL. */ -int -nds32_can_use_bset_p (int ival) -{ - int one_bit_count; - - /* 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)); - - /* 'bset' is a performance extension instruction. */ - return (TARGET_PERF_EXT && (one_bit_count == 1)); -} - -/* Function to check if 'btgl' instruction can be used with IVAL. */ -int -nds32_can_use_btgl_p (int ival) -{ - int one_bit_count; - - /* 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)); - - /* 'btgl' is a performance extension instruction. */ - return (TARGET_PERF_EXT && (one_bit_count == 1)); -} - -/* Function to check if 'bitci' instruction can be used with IVAL. */ -int -nds32_can_use_bitci_p (int ival) -{ - /* If we are using V3 ISA, we have 'bitci' instruction. - Try to see if we can present 'andi' semantic with - such 'bit-clear-immediate' operation. - For example, 'andi $r0,$r0,0xfffffffc' can be - presented with 'bitci $r0,$r0,3'. */ - return (TARGET_ISA_V3 - && (ival < 0) - && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode))); -} - /* Return true if is load/store with SYMBOL_REF addressing mode and memory mode is SImode. */ |