summaryrefslogtreecommitdiff
path: root/gcc/config/nds32/nds32-cost.c
blob: cd215241441a8033aa9d89665781e3a4a1f8626e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/* Subroutines used for calculate rtx costs of Andes NDS32 cpu for GNU compiler
   Copyright (C) 2012-2015 Free Software Foundation, Inc.
   Contributed by Andes Technology Corporation.

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published
   by the Free Software Foundation; either version 3, or (at your
   option) any later version.

   GCC is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.

   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 "hashtab.h"
#include "hash-set.h"
#include "vec.h"
#include "machmode.h"
#include "input.h"
#include "function.h"
#include "expr.h"
#include "recog.h"
#include "diagnostic-core.h"
#include "dominance.h"
#include "cfg.h"
#include "cfgrtl.h"
#include "cfganal.h"
#include "lcm.h"
#include "cfgbuild.h"
#include "cfgcleanup.h"
#include "predict.h"
#include "basic-block.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"

/* ------------------------------------------------------------------------ */

bool
nds32_rtx_costs_impl (rtx x,
		      int code,
		      int outer_code,
		      int opno ATTRIBUTE_UNUSED,
		      int *total,
		      bool speed)
{
  /* According to 'speed', goto suitable cost model section.  */
  if (speed)
    goto performance_cost;
  else
    goto size_cost;


performance_cost:
  /* This is section for performance cost model.  */

  /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
     We treat it as 4-cycle cost for each instruction
     under performance consideration.  */
  switch (code)
    {
    case SET:
      /* For 'SET' rtx, we need to return false
         so that it can recursively calculate costs.  */
      return false;

    case USE:
      /* Used in combine.c as a marker.  */
      *total = 0;
      break;

    case MULT:
      *total = COSTS_N_INSNS (1);
      break;

    case DIV:
    case UDIV:
    case MOD:
    case UMOD:
      *total = COSTS_N_INSNS (7);
      break;

    default:
      *total = COSTS_N_INSNS (1);
      break;
    }

  return true;


size_cost:
  /* This is section for size cost model.  */

  /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
     We treat it as 4-byte cost for each instruction
     under code size consideration.  */
  switch (code)
    {
    case SET:
      /* For 'SET' rtx, we need to return false
         so that it can recursively calculate costs.  */
      return false;

    case USE:
      /* Used in combine.c as a marker.  */
      *total = 0;
      break;

    case CONST_INT:
      /* All instructions involving constant operation
         need to be considered for cost evaluation.  */
      if (outer_code == SET)
	{
	  /* (set X imm5s), use movi55, 2-byte cost.
	     (set X imm20s), use movi, 4-byte cost.
	     (set X BIG_INT), use sethi/ori, 8-byte cost.  */
	  if (satisfies_constraint_Is05 (x))
	    *total = COSTS_N_INSNS (1) - 2;
	  else if (satisfies_constraint_Is20 (x))
	    *total = COSTS_N_INSNS (1);
	  else
	    *total = COSTS_N_INSNS (2);
	}
      else if (outer_code == PLUS || outer_code == MINUS)
	{
	  /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
	     General case, cost 1 instruction with 4-byte.  */
	  if (satisfies_constraint_Iu05 (x))
	    *total = COSTS_N_INSNS (1) - 2;
	  else
	    *total = COSTS_N_INSNS (1);
	}
      else if (outer_code == ASHIFT)
	{
	  /* Possible slli333, 2-byte cost.
	     General case, cost 1 instruction with 4-byte.  */
	  if (satisfies_constraint_Iu03 (x))
	    *total = COSTS_N_INSNS (1) - 2;
	  else
	    *total = COSTS_N_INSNS (1);
	}
      else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
	{
	  /* Possible srai45 or srli45, 2-byte cost.
	     General case, cost 1 instruction with 4-byte.  */
	  if (satisfies_constraint_Iu05 (x))
	    *total = COSTS_N_INSNS (1) - 2;
	  else
	    *total = COSTS_N_INSNS (1);
	}
      else
	{
	  /* For other cases, simply set it 4-byte cost.  */
	  *total = COSTS_N_INSNS (1);
	}
      break;

    case CONST_DOUBLE:
      /* It requires high part and low part processing, set it 8-byte cost.  */
      *total = COSTS_N_INSNS (2);
      break;

    default:
      /* For other cases, generally we set it 4-byte cost
         and stop resurively traversing.  */
      *total = COSTS_N_INSNS (1);
      break;
    }

  return true;
}

int
nds32_address_cost_impl (rtx address,
			 machine_mode mode ATTRIBUTE_UNUSED,
			 addr_space_t as ATTRIBUTE_UNUSED,
			 bool speed)
{
  rtx plus0, plus1;
  enum rtx_code code;

  code = GET_CODE (address);

  /* According to 'speed', goto suitable cost model section.  */
  if (speed)
    goto performance_cost;
  else
    goto size_cost;

performance_cost:
  /* This is section for performance cost model.  */

  /* FALLTHRU, currently we use same cost model as size_cost.  */

size_cost:
  /* This is section for size cost model.  */

  switch (code)
    {
    case POST_MODIFY:
    case POST_INC:
    case POST_DEC:
      /* We encourage that rtx contains
         POST_MODIFY/POST_INC/POST_DEC behavior.  */
      return 0;

    case SYMBOL_REF:
      /* We can have gp-relative load/store for symbol_ref.
         Have it 4-byte cost.  */
      return COSTS_N_INSNS (1);

    case CONST:
      /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
         Have it 4-byte cost.  */
      return COSTS_N_INSNS (1);

    case REG:
      /* Simply return 4-byte costs.  */
      return COSTS_N_INSNS (1);

    case PLUS:
      /* We do not need to check if the address is a legitimate address,
         because this hook is never called with an invalid address.
         But we better check the range of
         const_int value for cost, if it exists.  */
      plus0 = XEXP (address, 0);
      plus1 = XEXP (address, 1);

      if (REG_P (plus0) && CONST_INT_P (plus1))
        {
	  /* If it is possible to be lwi333/swi333 form,
	     make it 2-byte cost.  */
	  if (satisfies_constraint_Iu05 (plus1))
	    return (COSTS_N_INSNS (1) - 2);
	  else
	    return COSTS_N_INSNS (1);
	}

      /* For other 'plus' situation, make it cost 4-byte.  */
      return COSTS_N_INSNS (1);

    default:
      break;
    }

  return COSTS_N_INSNS (4);
}

/* ------------------------------------------------------------------------ */