15ef59e75Smrg /* Subroutines used for calculate rtx costs of Andes NDS32 cpu for GNU compiler
2*dd083157Smrg    Copyright (C) 2012-2020 Free Software Foundation, Inc.
35ef59e75Smrg    Contributed by Andes Technology Corporation.
45ef59e75Smrg 
55ef59e75Smrg    This file is part of GCC.
65ef59e75Smrg 
75ef59e75Smrg    GCC is free software; you can redistribute it and/or modify it
85ef59e75Smrg    under the terms of the GNU General Public License as published
95ef59e75Smrg    by the Free Software Foundation; either version 3, or (at your
105ef59e75Smrg    option) any later version.
115ef59e75Smrg 
125ef59e75Smrg    GCC is distributed in the hope that it will be useful, but WITHOUT
135ef59e75Smrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
145ef59e75Smrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
155ef59e75Smrg    License for more details.
165ef59e75Smrg 
175ef59e75Smrg    You should have received a copy of the GNU General Public License
185ef59e75Smrg    along with GCC; see the file COPYING3.  If not see
195ef59e75Smrg    <http://www.gnu.org/licenses/>.  */
205ef59e75Smrg 
215ef59e75Smrg /* ------------------------------------------------------------------------ */
225ef59e75Smrg 
233903d7f3Smrg #define IN_TARGET_CODE 1
243903d7f3Smrg 
255ef59e75Smrg #include "config.h"
265ef59e75Smrg #include "system.h"
275ef59e75Smrg #include "coretypes.h"
2863aace61Smrg #include "backend.h"
295ef59e75Smrg #include "target.h"
3063aace61Smrg #include "rtl.h"
3163aace61Smrg #include "tree.h"
326a5c9aabSmrg #include "memmodel.h"
3363aace61Smrg #include "tm_p.h"
3463aace61Smrg #include "optabs.h"		/* For GEN_FCN.  */
3563aace61Smrg #include "recog.h"
3663aace61Smrg #include "tm-constrs.h"
3781418a27Smrg #include "tree-pass.h"
385ef59e75Smrg 
395ef59e75Smrg /* ------------------------------------------------------------------------ */
405ef59e75Smrg 
4181418a27Smrg typedef bool (*rtx_cost_func) (rtx, int, int, int, int*);
4281418a27Smrg 
4381418a27Smrg struct rtx_cost_model_t {
4481418a27Smrg   rtx_cost_func speed_prefer;
4581418a27Smrg   rtx_cost_func size_prefer;
4681418a27Smrg };
4781418a27Smrg 
4881418a27Smrg static rtx_cost_model_t rtx_cost_model;
4981418a27Smrg 
5081418a27Smrg static int insn_size_16bit; /* Initial at nds32_init_rtx_costs.  */
5181418a27Smrg static const int insn_size_32bit = 4;
5281418a27Smrg 
5381418a27Smrg static bool
nds32_rtx_costs_speed_prefer(rtx x ATTRIBUTE_UNUSED,int code,int outer_code ATTRIBUTE_UNUSED,int opno ATTRIBUTE_UNUSED,int * total)5481418a27Smrg nds32_rtx_costs_speed_prefer (rtx x ATTRIBUTE_UNUSED,
5581418a27Smrg 			      int code,
5681418a27Smrg 			      int outer_code ATTRIBUTE_UNUSED,
575ef59e75Smrg 			      int opno ATTRIBUTE_UNUSED,
5881418a27Smrg 			      int *total)
595ef59e75Smrg {
6081418a27Smrg   rtx op0;
6181418a27Smrg   rtx op1;
6281418a27Smrg   machine_mode mode = GET_MODE (x);
6381418a27Smrg   /* Scale cost by mode size.  */
6481418a27Smrg   int cost = COSTS_N_INSNS (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode));
6563aace61Smrg 
665ef59e75Smrg   switch (code)
675ef59e75Smrg     {
685ef59e75Smrg     case USE:
695ef59e75Smrg       /* Used in combine.c as a marker.  */
705ef59e75Smrg       *total = 0;
7181418a27Smrg       return true;
7281418a27Smrg 
7381418a27Smrg     case CONST_INT:
7481418a27Smrg       /* When not optimizing for size, we care more about the cost
7581418a27Smrg 	 of hot code, and hot code is often in a loop.  If a constant
7681418a27Smrg 	 operand needs to be forced into a register, we will often be
7781418a27Smrg 	 able to hoist the constant load out of the loop, so the load
7881418a27Smrg 	 should not contribute to the cost.  */
7981418a27Smrg       if (outer_code == SET || outer_code == PLUS)
8081418a27Smrg 	*total = satisfies_constraint_Is20 (x) ? 0 : 4;
8181418a27Smrg       else if (outer_code == AND || outer_code == IOR || outer_code == XOR
8281418a27Smrg 	       || outer_code == MINUS)
8381418a27Smrg 	*total = satisfies_constraint_Iu15 (x) ? 0 : 4;
8481418a27Smrg       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
8581418a27Smrg 	       || outer_code == LSHIFTRT)
8681418a27Smrg 	*total = satisfies_constraint_Iu05 (x) ? 0 : 4;
8781418a27Smrg       else if (GET_RTX_CLASS (outer_code) == RTX_COMPARE
8881418a27Smrg 	       || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
8981418a27Smrg 	*total = satisfies_constraint_Is16 (x) ? 0 : 4;
9081418a27Smrg       else
9181418a27Smrg 	*total = COSTS_N_INSNS (1);
9281418a27Smrg       return true;
9381418a27Smrg 
9481418a27Smrg     case CONST:
9581418a27Smrg     case LO_SUM:
9681418a27Smrg     case HIGH:
9781418a27Smrg     case SYMBOL_REF:
9881418a27Smrg       *total = COSTS_N_INSNS (1);
9981418a27Smrg       return true;
10081418a27Smrg 
10181418a27Smrg     case MEM:
10281418a27Smrg       *total = COSTS_N_INSNS (1);
10381418a27Smrg       return true;
10481418a27Smrg 
10581418a27Smrg     case SET:
10681418a27Smrg       op0 = SET_DEST (x);
10781418a27Smrg       op1 = SET_SRC (x);
10881418a27Smrg       mode = GET_MODE (op0);
10981418a27Smrg       /* Scale cost by mode size.  */
11081418a27Smrg       cost = COSTS_N_INSNS (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode));
11181418a27Smrg 
11281418a27Smrg       switch (GET_CODE (op1))
11381418a27Smrg 	{
11481418a27Smrg 	case REG:
11581418a27Smrg 	case SUBREG:
11681418a27Smrg 	  /* Register move and Store instructions.  */
11781418a27Smrg 	  if ((REG_P (op0) || MEM_P (op0))
11881418a27Smrg 	      && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (DImode))
11981418a27Smrg 	    *total = COSTS_N_INSNS (1);
12081418a27Smrg 	  else
12181418a27Smrg 	    *total = cost;
12281418a27Smrg 	  return true;
12381418a27Smrg 
12481418a27Smrg 	case MEM:
12581418a27Smrg 	  /* Load instructions.  */
12681418a27Smrg 	  if (REG_P (op0) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (DImode))
12781418a27Smrg 	    *total = COSTS_N_INSNS (1);
12881418a27Smrg 	  else
12981418a27Smrg 	    *total = cost;
13081418a27Smrg 	  return true;
13181418a27Smrg 
13281418a27Smrg 	case CONST_INT:
13381418a27Smrg 	  /* movi instruction.  */
13481418a27Smrg 	  if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode))
13581418a27Smrg 	    {
13681418a27Smrg 	      if (satisfies_constraint_Is20 (op1))
13781418a27Smrg 		*total = COSTS_N_INSNS (1) - 1;
13881418a27Smrg 	      else
13981418a27Smrg 		*total = COSTS_N_INSNS (2);
14081418a27Smrg 	    }
14181418a27Smrg 	  else
14281418a27Smrg 	    *total = cost;
14381418a27Smrg 	  return true;
14481418a27Smrg 
14581418a27Smrg 	case CONST:
14681418a27Smrg 	case SYMBOL_REF:
14781418a27Smrg 	case LABEL_REF:
14881418a27Smrg 	  /* la instruction.  */
14981418a27Smrg 	  if (REG_P (op0) && GET_MODE_SIZE (mode) < GET_MODE_SIZE (DImode))
15081418a27Smrg 	    *total = COSTS_N_INSNS (1) - 1;
15181418a27Smrg 	  else
15281418a27Smrg 	    *total = cost;
15381418a27Smrg 	  return true;
15481418a27Smrg 	case VEC_SELECT:
15581418a27Smrg 	  *total = cost;
15681418a27Smrg 	  return true;
15781418a27Smrg 
15881418a27Smrg 	default:
15981418a27Smrg 	  *total = cost;
16081418a27Smrg 	  return true;
16181418a27Smrg 	}
16281418a27Smrg 
16381418a27Smrg     case PLUS:
16481418a27Smrg       op0 = XEXP (x, 0);
16581418a27Smrg       op1 = XEXP (x, 1);
16681418a27Smrg 
16781418a27Smrg       if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
16881418a27Smrg 	*total = cost;
16981418a27Smrg       else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT
17081418a27Smrg 	       || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT)
17181418a27Smrg 	/* ALU_SHIFT */
17281418a27Smrg 	*total = COSTS_N_INSNS (2);
17381418a27Smrg 
17481418a27Smrg       else if ((GET_CODE (op1) == CONST_INT
17581418a27Smrg 		&& satisfies_constraint_Is15 (op1))
17681418a27Smrg 		|| REG_P (op1))
17781418a27Smrg 	/* ADD instructions */
17881418a27Smrg 	*total = COSTS_N_INSNS (1);
17981418a27Smrg       else
18081418a27Smrg 	/* ADD instructions: IMM out of range.  */
18181418a27Smrg 	*total = COSTS_N_INSNS (2);
18281418a27Smrg       return true;
18381418a27Smrg 
18481418a27Smrg     case MINUS:
18581418a27Smrg       op0 = XEXP (x, 0);
18681418a27Smrg       op1 = XEXP (x, 1);
18781418a27Smrg 
18881418a27Smrg       if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
18981418a27Smrg 	*total = cost;
19081418a27Smrg       else if (GET_CODE (op0) == MULT || GET_CODE (op0) == LSHIFTRT
19181418a27Smrg 	       || GET_CODE (op1) == MULT || GET_CODE (op1) == LSHIFTRT)
19281418a27Smrg 	/* ALU_SHIFT */
19381418a27Smrg 	*total = COSTS_N_INSNS (2);
19481418a27Smrg       else if ((GET_CODE (op0) == CONST_INT
19581418a27Smrg 		&& satisfies_constraint_Is15 (op0))
19681418a27Smrg 		|| REG_P (op0))
19781418a27Smrg 	/* SUB instructions */
19881418a27Smrg 	*total = COSTS_N_INSNS (1);
19981418a27Smrg       else
20081418a27Smrg 	/* SUB instructions: IMM out of range.  */
20181418a27Smrg 	*total = COSTS_N_INSNS (2);
20281418a27Smrg       return true;
20381418a27Smrg 
20481418a27Smrg     case TRUNCATE:
20581418a27Smrg       /* TRUNCATE and AND behavior is same. */
20681418a27Smrg       *total = COSTS_N_INSNS (1);
20781418a27Smrg       return true;
20881418a27Smrg 
20981418a27Smrg     case AND:
21081418a27Smrg     case IOR:
21181418a27Smrg     case XOR:
21281418a27Smrg       op0 = XEXP (x, 0);
21381418a27Smrg       op1 = XEXP (x, 1);
21481418a27Smrg 
21581418a27Smrg       if (NDS32_EXT_DSP_P ())
21681418a27Smrg 	{
21781418a27Smrg 	  /* We prefer (and (ior) (ior)) than (ior (and) (and)) for
21881418a27Smrg 	     synthetize pk** and insb instruction.  */
21981418a27Smrg 	  if (code == AND && GET_CODE (op0) == IOR && GET_CODE (op1) == IOR)
22081418a27Smrg 	    return COSTS_N_INSNS (1);
22181418a27Smrg 
22281418a27Smrg 	  if (code == IOR && GET_CODE (op0) == AND && GET_CODE (op1) == AND)
22381418a27Smrg 	    return COSTS_N_INSNS (10);
22481418a27Smrg 	}
22581418a27Smrg 
22681418a27Smrg       if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
22781418a27Smrg 	*total = cost;
22881418a27Smrg       else if (GET_CODE (op0) == ASHIFT || GET_CODE (op0) == LSHIFTRT)
22981418a27Smrg 	*total = COSTS_N_INSNS (2);
23081418a27Smrg       else if ((GET_CODE (op1) == CONST_INT
23181418a27Smrg 	       && satisfies_constraint_Iu15 (op1))
23281418a27Smrg 	       || REG_P (op1))
23381418a27Smrg 	/* AND, OR, XOR instructions */
23481418a27Smrg 	*total = COSTS_N_INSNS (1);
23581418a27Smrg       else if (code == AND || GET_CODE (op0) == NOT)
23681418a27Smrg 	/* BITC instruction */
23781418a27Smrg 	*total = COSTS_N_INSNS (1);
23881418a27Smrg       else
23981418a27Smrg 	/* AND, OR, XOR instructions: IMM out of range.  */
24081418a27Smrg 	*total = COSTS_N_INSNS (2);
24181418a27Smrg       return true;
2425ef59e75Smrg 
2435ef59e75Smrg     case MULT:
24481418a27Smrg       if (GET_MODE (x) == DImode
24581418a27Smrg 	  || GET_CODE (XEXP (x, 1)) == SIGN_EXTEND
24681418a27Smrg 	  || GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
24781418a27Smrg 	/* MUL instructions */
2485ef59e75Smrg 	*total = COSTS_N_INSNS (1);
24981418a27Smrg       else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
25081418a27Smrg 	*total = cost;
25181418a27Smrg       else if (outer_code == PLUS || outer_code == MINUS)
25281418a27Smrg 	*total = COSTS_N_INSNS (2);
25381418a27Smrg       else if ((GET_CODE (XEXP (x, 1)) == CONST_INT
25481418a27Smrg 	       && satisfies_constraint_Iu05 (XEXP (x, 1)))
25581418a27Smrg 	       || REG_P (XEXP (x, 1)))
25681418a27Smrg 	/* MUL instructions */
25781418a27Smrg 	*total = COSTS_N_INSNS (1);
25881418a27Smrg       else
25981418a27Smrg 	/* MUL instructions: IMM out of range.  */
26081418a27Smrg 	*total = COSTS_N_INSNS (2);
26181418a27Smrg 
26281418a27Smrg       if (TARGET_MUL_SLOW)
26381418a27Smrg 	*total += COSTS_N_INSNS (4);
26481418a27Smrg 
26581418a27Smrg       return true;
26681418a27Smrg 
26781418a27Smrg     case LSHIFTRT:
26881418a27Smrg       if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
26981418a27Smrg 	*total = cost;
27081418a27Smrg       else if (outer_code == PLUS || outer_code == MINUS
27181418a27Smrg 	       || outer_code == AND || outer_code == IOR
27281418a27Smrg 	       || outer_code == XOR)
27381418a27Smrg 	*total = COSTS_N_INSNS (2);
27481418a27Smrg       else if ((GET_CODE (XEXP (x, 1)) == CONST_INT
27581418a27Smrg 	       && satisfies_constraint_Iu05 (XEXP (x, 1)))
27681418a27Smrg 	       || REG_P (XEXP (x, 1)))
27781418a27Smrg 	/* SRL instructions */
27881418a27Smrg 	*total = COSTS_N_INSNS (1);
27981418a27Smrg       else
28081418a27Smrg 	/* SRL instructions: IMM out of range.  */
28181418a27Smrg 	*total = COSTS_N_INSNS (2);
28281418a27Smrg       return true;
28381418a27Smrg 
28481418a27Smrg     case ASHIFT:
28581418a27Smrg       if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
28681418a27Smrg 	*total = cost;
28781418a27Smrg       else if (outer_code == AND || outer_code == IOR
28881418a27Smrg 	       || outer_code == XOR)
28981418a27Smrg 	*total = COSTS_N_INSNS (2);
29081418a27Smrg       else if ((GET_CODE (XEXP (x, 1)) == CONST_INT
29181418a27Smrg 	       && satisfies_constraint_Iu05 (XEXP (x, 1)))
29281418a27Smrg 	       || REG_P (XEXP (x, 1)))
29381418a27Smrg 	/* SLL instructions */
29481418a27Smrg 	*total = COSTS_N_INSNS (1);
29581418a27Smrg       else
29681418a27Smrg 	/* SLL instructions: IMM out of range.  */
29781418a27Smrg 	*total = COSTS_N_INSNS (2);
29881418a27Smrg       return true;
29981418a27Smrg 
30081418a27Smrg     case ASHIFTRT:
30181418a27Smrg     case ROTATERT:
30281418a27Smrg       if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (DImode))
30381418a27Smrg 	*total = cost;
30481418a27Smrg       else if ((GET_CODE (XEXP (x, 1)) == CONST_INT
30581418a27Smrg 	       && satisfies_constraint_Iu05 (XEXP (x, 1)))
30681418a27Smrg 	       || REG_P (XEXP (x, 1)))
30781418a27Smrg 	/* ROTR, SLL instructions */
30881418a27Smrg 	*total = COSTS_N_INSNS (1);
30981418a27Smrg       else
31081418a27Smrg 	/* ROTR, SLL instructions: IMM out of range.  */
31181418a27Smrg 	*total = COSTS_N_INSNS (2);
31281418a27Smrg       return true;
31381418a27Smrg 
31481418a27Smrg     case LT:
31581418a27Smrg     case LTU:
31681418a27Smrg       if (outer_code == SET)
31781418a27Smrg 	{
31881418a27Smrg 	  if ((GET_CODE (XEXP (x, 1)) == CONST_INT
31981418a27Smrg 	      && satisfies_constraint_Iu15 (XEXP (x, 1)))
32081418a27Smrg 	      || REG_P (XEXP (x, 1)))
32181418a27Smrg 	    /* SLT, SLTI instructions */
32281418a27Smrg 	    *total = COSTS_N_INSNS (1);
32381418a27Smrg 	  else
32481418a27Smrg 	    /* SLT, SLT instructions: IMM out of range.  */
32581418a27Smrg 	    *total = COSTS_N_INSNS (2);
32681418a27Smrg 	}
32781418a27Smrg       else
32881418a27Smrg 	/* branch */
32981418a27Smrg 	*total = COSTS_N_INSNS (2);
33081418a27Smrg       return true;
33181418a27Smrg 
33281418a27Smrg     case EQ:
33381418a27Smrg     case NE:
33481418a27Smrg     case GE:
33581418a27Smrg     case LE:
33681418a27Smrg     case GT:
33781418a27Smrg       /* branch */
33881418a27Smrg       *total = COSTS_N_INSNS (2);
33981418a27Smrg       return true;
34081418a27Smrg 
34181418a27Smrg     case IF_THEN_ELSE:
34281418a27Smrg       if (GET_CODE (XEXP (x, 1)) == LABEL_REF)
34381418a27Smrg 	/* branch */
34481418a27Smrg 	*total = COSTS_N_INSNS (2);
34581418a27Smrg       else
34681418a27Smrg 	/* cmovz, cmovn instructions */
34781418a27Smrg 	*total = COSTS_N_INSNS (1);
34881418a27Smrg       return true;
34981418a27Smrg 
35081418a27Smrg     case LABEL_REF:
35181418a27Smrg       if (outer_code == IF_THEN_ELSE)
35281418a27Smrg 	/* branch */
35381418a27Smrg 	*total = COSTS_N_INSNS (2);
35481418a27Smrg       else
35581418a27Smrg 	*total = COSTS_N_INSNS (1);
35681418a27Smrg       return true;
35781418a27Smrg 
35881418a27Smrg     case ZERO_EXTEND:
35981418a27Smrg     case SIGN_EXTEND:
36081418a27Smrg       if (MEM_P (XEXP (x, 0)))
36181418a27Smrg 	/* Using memory access. */
36281418a27Smrg 	*total = COSTS_N_INSNS (1);
36381418a27Smrg       else
36481418a27Smrg 	/* Zero extend and sign extend instructions.  */
36581418a27Smrg 	*total = COSTS_N_INSNS (1);
36681418a27Smrg       return true;
36781418a27Smrg 
36881418a27Smrg     case NEG:
36981418a27Smrg     case NOT:
37081418a27Smrg       *total = COSTS_N_INSNS (1);
37181418a27Smrg       return true;
3725ef59e75Smrg 
3735ef59e75Smrg     case DIV:
3745ef59e75Smrg     case UDIV:
3755ef59e75Smrg     case MOD:
3765ef59e75Smrg     case UMOD:
37781418a27Smrg       *total = COSTS_N_INSNS (20);
3785ef59e75Smrg       return true;
3795ef59e75Smrg 
38081418a27Smrg     case CALL:
38181418a27Smrg       *total = COSTS_N_INSNS (2);
38281418a27Smrg       return true;
3835ef59e75Smrg 
38481418a27Smrg     case CLZ:
38581418a27Smrg     case SMIN:
38681418a27Smrg     case SMAX:
38781418a27Smrg     case ZERO_EXTRACT:
38881418a27Smrg       if (TARGET_EXT_PERF)
38981418a27Smrg 	*total = COSTS_N_INSNS (1);
39081418a27Smrg       else
39181418a27Smrg 	*total = COSTS_N_INSNS (3);
39281418a27Smrg       return true;
39381418a27Smrg     case VEC_SELECT:
39481418a27Smrg       *total = COSTS_N_INSNS (1);
39581418a27Smrg       return true;
3965ef59e75Smrg 
39781418a27Smrg     default:
39881418a27Smrg       *total = COSTS_N_INSNS (3);
39981418a27Smrg       return true;
40081418a27Smrg     }
40181418a27Smrg }
40281418a27Smrg 
40381418a27Smrg static bool
nds32_rtx_costs_size_prefer(rtx x,int code,int outer_code,int opno ATTRIBUTE_UNUSED,int * total)40481418a27Smrg nds32_rtx_costs_size_prefer (rtx x,
40581418a27Smrg 			     int code,
40681418a27Smrg 			     int outer_code,
40781418a27Smrg 			     int opno ATTRIBUTE_UNUSED,
40881418a27Smrg 			     int *total)
40981418a27Smrg {
4105ef59e75Smrg   /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
4115ef59e75Smrg      We treat it as 4-byte cost for each instruction
4125ef59e75Smrg      under code size consideration.  */
4135ef59e75Smrg   switch (code)
4145ef59e75Smrg     {
4155ef59e75Smrg     case SET:
4165ef59e75Smrg       /* For 'SET' rtx, we need to return false
4175ef59e75Smrg 	 so that it can recursively calculate costs.  */
4185ef59e75Smrg       return false;
4195ef59e75Smrg 
4205ef59e75Smrg     case USE:
4215ef59e75Smrg       /* Used in combine.c as a marker.  */
4225ef59e75Smrg       *total = 0;
4235ef59e75Smrg       break;
4245ef59e75Smrg 
4255ef59e75Smrg     case CONST_INT:
4265ef59e75Smrg       /* All instructions involving constant operation
4275ef59e75Smrg 	 need to be considered for cost evaluation.  */
4285ef59e75Smrg       if (outer_code == SET)
4295ef59e75Smrg 	{
4305ef59e75Smrg 	  /* (set X imm5s), use movi55, 2-byte cost.
4315ef59e75Smrg 	     (set X imm20s), use movi, 4-byte cost.
4325ef59e75Smrg 	     (set X BIG_INT), use sethi/ori, 8-byte cost.  */
4335ef59e75Smrg 	  if (satisfies_constraint_Is05 (x))
43481418a27Smrg 	    *total = insn_size_16bit;
4355ef59e75Smrg 	  else if (satisfies_constraint_Is20 (x))
43681418a27Smrg 	    *total = insn_size_32bit;
4375ef59e75Smrg 	  else
43881418a27Smrg 	    *total = insn_size_32bit * 2;
4395ef59e75Smrg 	}
4405ef59e75Smrg       else if (outer_code == PLUS || outer_code == MINUS)
4415ef59e75Smrg 	{
4425ef59e75Smrg 	  /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
4435ef59e75Smrg 	     General case, cost 1 instruction with 4-byte.  */
4445ef59e75Smrg 	  if (satisfies_constraint_Iu05 (x))
44581418a27Smrg 	    *total = insn_size_16bit;
4465ef59e75Smrg 	  else
44781418a27Smrg 	    *total = insn_size_32bit;
4485ef59e75Smrg 	}
4495ef59e75Smrg       else if (outer_code == ASHIFT)
4505ef59e75Smrg 	{
4515ef59e75Smrg 	  /* Possible slli333, 2-byte cost.
4525ef59e75Smrg 	     General case, cost 1 instruction with 4-byte.  */
4535ef59e75Smrg 	  if (satisfies_constraint_Iu03 (x))
45481418a27Smrg 	    *total = insn_size_16bit;
4555ef59e75Smrg 	  else
45681418a27Smrg 	    *total = insn_size_32bit;
4575ef59e75Smrg 	}
4585ef59e75Smrg       else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
4595ef59e75Smrg 	{
4605ef59e75Smrg 	  /* Possible srai45 or srli45, 2-byte cost.
4615ef59e75Smrg 	     General case, cost 1 instruction with 4-byte.  */
4625ef59e75Smrg 	  if (satisfies_constraint_Iu05 (x))
46381418a27Smrg 	    *total = insn_size_16bit;
4645ef59e75Smrg 	  else
46581418a27Smrg 	    *total = insn_size_32bit;
4665ef59e75Smrg 	}
4675ef59e75Smrg       else
4685ef59e75Smrg 	{
4695ef59e75Smrg 	  /* For other cases, simply set it 4-byte cost.  */
47081418a27Smrg 	  *total = insn_size_32bit;
4715ef59e75Smrg 	}
4725ef59e75Smrg       break;
4735ef59e75Smrg 
4745ef59e75Smrg     case CONST_DOUBLE:
4755ef59e75Smrg       /* It requires high part and low part processing, set it 8-byte cost.  */
47681418a27Smrg       *total = insn_size_32bit * 2;
47781418a27Smrg       break;
47881418a27Smrg 
47981418a27Smrg     case CONST:
48081418a27Smrg     case SYMBOL_REF:
48181418a27Smrg       *total = insn_size_32bit * 2;
4825ef59e75Smrg       break;
4835ef59e75Smrg 
4845ef59e75Smrg     default:
4855ef59e75Smrg       /* For other cases, generally we set it 4-byte cost
4865ef59e75Smrg 	 and stop resurively traversing.  */
48781418a27Smrg       *total = insn_size_32bit;
4885ef59e75Smrg       break;
4895ef59e75Smrg     }
4905ef59e75Smrg 
4915ef59e75Smrg   return true;
4925ef59e75Smrg }
4935ef59e75Smrg 
49481418a27Smrg void
nds32_init_rtx_costs(void)49581418a27Smrg nds32_init_rtx_costs (void)
49681418a27Smrg {
49781418a27Smrg   rtx_cost_model.speed_prefer = nds32_rtx_costs_speed_prefer;
49881418a27Smrg   rtx_cost_model.size_prefer  = nds32_rtx_costs_size_prefer;
49981418a27Smrg 
50081418a27Smrg   if (TARGET_16_BIT)
50181418a27Smrg     insn_size_16bit = 2;
50281418a27Smrg   else
50381418a27Smrg     insn_size_16bit = 4;
50481418a27Smrg }
50581418a27Smrg 
50681418a27Smrg /* This target hook describes the relative costs of RTL expressions.
50781418a27Smrg    Return 'true' when all subexpressions of x have been processed.
50881418a27Smrg    Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
50981418a27Smrg    Refer to gcc/rtlanal.c for more information.  */
51081418a27Smrg bool
nds32_rtx_costs_impl(rtx x,machine_mode mode ATTRIBUTE_UNUSED,int outer_code,int opno,int * total,bool speed)51181418a27Smrg nds32_rtx_costs_impl (rtx x,
5125ef59e75Smrg 		      machine_mode mode ATTRIBUTE_UNUSED,
51381418a27Smrg 		      int outer_code,
51481418a27Smrg 		      int opno,
51581418a27Smrg 		      int *total,
5165ef59e75Smrg 		      bool speed)
5175ef59e75Smrg {
51881418a27Smrg   int code = GET_CODE (x);
51981418a27Smrg 
52081418a27Smrg   /* According to 'speed', use suitable cost model section.  */
52181418a27Smrg   if (speed)
52281418a27Smrg     return rtx_cost_model.speed_prefer(x, code, outer_code, opno, total);
52381418a27Smrg   else
52481418a27Smrg     return rtx_cost_model.size_prefer(x, code, outer_code, opno, total);
52581418a27Smrg }
52681418a27Smrg 
52781418a27Smrg 
nds32_address_cost_speed_prefer(rtx address)52881418a27Smrg int nds32_address_cost_speed_prefer (rtx address)
52981418a27Smrg {
5305ef59e75Smrg   rtx plus0, plus1;
5315ef59e75Smrg   enum rtx_code code;
5325ef59e75Smrg 
5335ef59e75Smrg   code = GET_CODE (address);
5345ef59e75Smrg 
53581418a27Smrg   switch (code)
53681418a27Smrg     {
53781418a27Smrg     case POST_MODIFY:
53881418a27Smrg     case POST_INC:
53981418a27Smrg     case POST_DEC:
54081418a27Smrg       /* We encourage that rtx contains
54181418a27Smrg 	 POST_MODIFY/POST_INC/POST_DEC behavior.  */
54281418a27Smrg       return COSTS_N_INSNS (1) - 2;
5435ef59e75Smrg 
54481418a27Smrg     case SYMBOL_REF:
54581418a27Smrg       /* We can have gp-relative load/store for symbol_ref.
54681418a27Smrg 	Have it 4-byte cost.  */
54781418a27Smrg       return COSTS_N_INSNS (2);
5485ef59e75Smrg 
54981418a27Smrg     case CONST:
55081418a27Smrg       /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
55181418a27Smrg 	 Have it 4-byte cost.  */
55281418a27Smrg       return COSTS_N_INSNS (2);
5535ef59e75Smrg 
55481418a27Smrg     case REG:
55581418a27Smrg       /* Simply return 4-byte costs.  */
55681418a27Smrg       return COSTS_N_INSNS (1) - 2;
55781418a27Smrg 
55881418a27Smrg     case PLUS:
55981418a27Smrg       /* We do not need to check if the address is a legitimate address,
56081418a27Smrg 	 because this hook is never called with an invalid address.
56181418a27Smrg 	 But we better check the range of
56281418a27Smrg 	 const_int value for cost, if it exists.  */
56381418a27Smrg       plus0 = XEXP (address, 0);
56481418a27Smrg       plus1 = XEXP (address, 1);
56581418a27Smrg 
56681418a27Smrg       if (REG_P (plus0) && CONST_INT_P (plus1))
56781418a27Smrg 	return COSTS_N_INSNS (1) - 2;
56881418a27Smrg       else if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1))
56981418a27Smrg 	return COSTS_N_INSNS (1) - 1;
57081418a27Smrg       else if (REG_P (plus0) && REG_P (plus1))
57181418a27Smrg 	return COSTS_N_INSNS (1);
57281418a27Smrg 
57381418a27Smrg       /* For other 'plus' situation, make it cost 4-byte.  */
57481418a27Smrg       return COSTS_N_INSNS (1);
57581418a27Smrg 
57681418a27Smrg     default:
57781418a27Smrg       break;
57881418a27Smrg     }
57981418a27Smrg 
58081418a27Smrg   return COSTS_N_INSNS (4);
58181418a27Smrg 
58281418a27Smrg }
58381418a27Smrg 
nds32_address_cost_speed_fwprop(rtx address)58481418a27Smrg int nds32_address_cost_speed_fwprop (rtx address)
58581418a27Smrg {
58681418a27Smrg   rtx plus0, plus1;
58781418a27Smrg   enum rtx_code code;
58881418a27Smrg 
58981418a27Smrg   code = GET_CODE (address);
5905ef59e75Smrg 
5915ef59e75Smrg   switch (code)
5925ef59e75Smrg     {
5935ef59e75Smrg     case POST_MODIFY:
5945ef59e75Smrg     case POST_INC:
5955ef59e75Smrg     case POST_DEC:
5965ef59e75Smrg       /* We encourage that rtx contains
5975ef59e75Smrg 	 POST_MODIFY/POST_INC/POST_DEC behavior.  */
5985ef59e75Smrg       return 0;
5995ef59e75Smrg 
6005ef59e75Smrg     case SYMBOL_REF:
6015ef59e75Smrg       /* We can have gp-relative load/store for symbol_ref.
6025ef59e75Smrg 	 Have it 4-byte cost.  */
60381418a27Smrg       return COSTS_N_INSNS (2);
6045ef59e75Smrg 
6055ef59e75Smrg     case CONST:
6065ef59e75Smrg       /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
6075ef59e75Smrg 	 Have it 4-byte cost.  */
60881418a27Smrg       return COSTS_N_INSNS (2);
6095ef59e75Smrg 
6105ef59e75Smrg     case REG:
6115ef59e75Smrg       /* Simply return 4-byte costs.  */
6125ef59e75Smrg       return COSTS_N_INSNS (1);
6135ef59e75Smrg 
6145ef59e75Smrg     case PLUS:
6155ef59e75Smrg       /* We do not need to check if the address is a legitimate address,
6165ef59e75Smrg 	 because this hook is never called with an invalid address.
6175ef59e75Smrg 	 But we better check the range of
6185ef59e75Smrg 	 const_int value for cost, if it exists.  */
6195ef59e75Smrg       plus0 = XEXP (address, 0);
6205ef59e75Smrg       plus1 = XEXP (address, 1);
6215ef59e75Smrg 
6225ef59e75Smrg       if (REG_P (plus0) && CONST_INT_P (plus1))
6235ef59e75Smrg 	{
6245ef59e75Smrg 	  /* If it is possible to be lwi333/swi333 form,
6255ef59e75Smrg 	     make it 2-byte cost.  */
62681418a27Smrg 	  if (satisfies_constraint_Iu03 (plus1))
6275ef59e75Smrg 	    return (COSTS_N_INSNS (1) - 2);
6285ef59e75Smrg 	  else
6295ef59e75Smrg 	    return COSTS_N_INSNS (1);
6305ef59e75Smrg 	}
63181418a27Smrg       if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1))
63281418a27Smrg 	return COSTS_N_INSNS (1) - 2;
63381418a27Smrg       else if (REG_P (plus0) && REG_P (plus1))
63481418a27Smrg 	return COSTS_N_INSNS (1);
6355ef59e75Smrg 
6365ef59e75Smrg       /* For other 'plus' situation, make it cost 4-byte.  */
6375ef59e75Smrg       return COSTS_N_INSNS (1);
6385ef59e75Smrg 
6395ef59e75Smrg     default:
6405ef59e75Smrg       break;
6415ef59e75Smrg     }
6425ef59e75Smrg 
6435ef59e75Smrg   return COSTS_N_INSNS (4);
6445ef59e75Smrg }
6455ef59e75Smrg 
64681418a27Smrg 
nds32_address_cost_size_prefer(rtx address)64781418a27Smrg int nds32_address_cost_size_prefer (rtx address)
64881418a27Smrg {
64981418a27Smrg   rtx plus0, plus1;
65081418a27Smrg   enum rtx_code code;
65181418a27Smrg 
65281418a27Smrg   code = GET_CODE (address);
65381418a27Smrg 
65481418a27Smrg   switch (code)
65581418a27Smrg     {
65681418a27Smrg     case POST_MODIFY:
65781418a27Smrg     case POST_INC:
65881418a27Smrg     case POST_DEC:
65981418a27Smrg       /* We encourage that rtx contains
66081418a27Smrg 	 POST_MODIFY/POST_INC/POST_DEC behavior.  */
66181418a27Smrg       return 0;
66281418a27Smrg 
66381418a27Smrg     case SYMBOL_REF:
66481418a27Smrg       /* We can have gp-relative load/store for symbol_ref.
66581418a27Smrg 	 Have it 4-byte cost.  */
66681418a27Smrg       return COSTS_N_INSNS (2);
66781418a27Smrg 
66881418a27Smrg     case CONST:
66981418a27Smrg       /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
67081418a27Smrg 	 Have it 4-byte cost.  */
67181418a27Smrg       return COSTS_N_INSNS (2);
67281418a27Smrg 
67381418a27Smrg     case REG:
67481418a27Smrg       /* Simply return 4-byte costs.  */
67581418a27Smrg       return COSTS_N_INSNS (1) - 1;
67681418a27Smrg 
67781418a27Smrg     case PLUS:
67881418a27Smrg       /* We do not need to check if the address is a legitimate address,
67981418a27Smrg 	 because this hook is never called with an invalid address.
68081418a27Smrg 	 But we better check the range of
68181418a27Smrg 	 const_int value for cost, if it exists.  */
68281418a27Smrg       plus0 = XEXP (address, 0);
68381418a27Smrg       plus1 = XEXP (address, 1);
68481418a27Smrg 
68581418a27Smrg       if (REG_P (plus0) && CONST_INT_P (plus1))
68681418a27Smrg 	{
68781418a27Smrg 	  /* If it is possible to be lwi333/swi333 form,
68881418a27Smrg 	     make it 2-byte cost.  */
68981418a27Smrg 	  if (satisfies_constraint_Iu03 (plus1))
69081418a27Smrg 	    return (COSTS_N_INSNS (1) - 2);
69181418a27Smrg 	  else
69281418a27Smrg 	    return COSTS_N_INSNS (1) - 1;
69381418a27Smrg 	}
69481418a27Smrg 
69581418a27Smrg       /* (plus (reg) (mult (reg) (const))) */
69681418a27Smrg       if (ARITHMETIC_P (plus0) || ARITHMETIC_P (plus1))
69781418a27Smrg 	return (COSTS_N_INSNS (1) - 1);
69881418a27Smrg 
69981418a27Smrg       /* For other 'plus' situation, make it cost 4-byte.  */
70081418a27Smrg       return COSTS_N_INSNS (1);
70181418a27Smrg 
70281418a27Smrg     default:
70381418a27Smrg       break;
70481418a27Smrg     }
70581418a27Smrg 
70681418a27Smrg   return COSTS_N_INSNS (4);
70781418a27Smrg 
70881418a27Smrg }
70981418a27Smrg 
nds32_address_cost_impl(rtx address,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed_p)71081418a27Smrg int nds32_address_cost_impl (rtx address,
71181418a27Smrg 			     machine_mode mode ATTRIBUTE_UNUSED,
71281418a27Smrg 			     addr_space_t as ATTRIBUTE_UNUSED,
71381418a27Smrg 			     bool speed_p)
71481418a27Smrg {
71581418a27Smrg   if (speed_p)
71681418a27Smrg     {
71781418a27Smrg       if (current_pass->tv_id == TV_FWPROP)
71881418a27Smrg 	return nds32_address_cost_speed_fwprop (address);
71981418a27Smrg       else
72081418a27Smrg 	return nds32_address_cost_speed_prefer (address);
72181418a27Smrg     }
72281418a27Smrg   else
72381418a27Smrg     return nds32_address_cost_size_prefer (address);
72481418a27Smrg }
72581418a27Smrg 
7265ef59e75Smrg /* ------------------------------------------------------------------------ */
727