1275963Srpaulo/* Target-dependent costs for expmed.c.
2275963Srpaulo   Copyright (C) 1987-2015 Free Software Foundation, Inc.
3275963Srpaulo
4275963SrpauloThis file is part of GCC.
5275963Srpaulo
6275963SrpauloGCC is free software; you can redistribute it and/or modify it under
7275963Srpaulothe terms of the GNU General Public License as published by the Free
8275963SrpauloSoftware Foundation; either version 3, or (at your option; any later
9275963Srpauloversion.
10275963Srpaulo
11275963SrpauloGCC is distributed in the hope that it will be useful, but WITHOUT ANY
12275963SrpauloWARRANTY; without even the implied warranty of MERCHANTABILITY or
13275963SrpauloFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14275963Srpaulofor more details.
15275963Srpaulo
16275963SrpauloYou should have received a copy of the GNU General Public License
17275963Srpauloalong with GCC; see the file COPYING3.  If not see
18275963Srpaulo<http://www.gnu.org/licenses/>.  */
19275963Srpaulo
20275963Srpaulo#ifndef EXPMED_H
21275963Srpaulo#define EXPMED_H 1
22275963Srpaulo
23275963Srpaulo#include "insn-codes.h"
24275963Srpaulo
25275963Srpauloenum alg_code {
26275963Srpaulo  alg_unknown,
27275963Srpaulo  alg_zero,
28275963Srpaulo  alg_m, alg_shift,
29275963Srpaulo  alg_add_t_m2,
30275963Srpaulo  alg_sub_t_m2,
31275963Srpaulo  alg_add_factor,
32275963Srpaulo  alg_sub_factor,
33275963Srpaulo  alg_add_t2_m,
34275963Srpaulo  alg_sub_t2_m,
35275963Srpaulo  alg_impossible
36275963Srpaulo};
37275963Srpaulo
38275963Srpaulo/* This structure holds the "cost" of a multiply sequence.  The
39275963Srpaulo   "cost" field holds the total rtx_cost of every operator in the
40275963Srpaulo   synthetic multiplication sequence, hence cost(a op b) is defined
41275963Srpaulo   as rtx_cost(op) + cost(a) + cost(b), where cost(leaf) is zero.
42275963Srpaulo   The "latency" field holds the minimum possible latency of the
43275963Srpaulo   synthetic multiply, on a hypothetical infinitely parallel CPU.
44275963Srpaulo   This is the critical path, or the maximum height, of the expression
45275963Srpaulo   tree which is the sum of rtx_costs on the most expensive path from
46275963Srpaulo   any leaf to the root.  Hence latency(a op b) is defined as zero for
47322724Smarius   leaves and rtx_cost(op) + max(latency(a), latency(b)) otherwise.  */
48322724Smarius
49322724Smariusstruct mult_cost {
50322724Smarius  short cost;     /* Total rtx_cost of the multiplication sequence.  */
51322724Smarius  short latency;  /* The latency of the multiplication sequence.  */
52275963Srpaulo};
53275963Srpaulo
54275963Srpaulo/* This macro is used to compare a pointer to a mult_cost against an
55275963Srpaulo   single integer "rtx_cost" value.  This is equivalent to the macro
56275963Srpaulo   CHEAPER_MULT_COST(X,Z) where Z = {Y,Y}.  */
57275963Srpaulo#define MULT_COST_LESS(X,Y) ((X)->cost < (Y)	\
58275963Srpaulo			     || ((X)->cost == (Y) && (X)->latency < (Y)))
59275963Srpaulo
60275963Srpaulo/* This macro is used to compare two pointers to mult_costs against
61275963Srpaulo   each other.  The macro returns true if X is cheaper than Y.
62275963Srpaulo   Currently, the cheaper of two mult_costs is the one with the
63275963Srpaulo   lower "cost".  If "cost"s are tied, the lower latency is cheaper.  */
64275963Srpaulo#define CHEAPER_MULT_COST(X,Y)  ((X)->cost < (Y)->cost		\
65275963Srpaulo				 || ((X)->cost == (Y)->cost	\
66275963Srpaulo				     && (X)->latency < (Y)->latency))
67275963Srpaulo
68275963Srpaulo/* This structure records a sequence of operations.
69275963Srpaulo   `ops' is the number of operations recorded.
70275963Srpaulo   `cost' is their total cost.
71275963Srpaulo   The operations are stored in `op' and the corresponding
72275963Srpaulo   logarithms of the integer coefficients in `log'.
73275963Srpaulo
74275963Srpaulo   These are the operations:
75275963Srpaulo   alg_zero		total := 0;
76275963Srpaulo   alg_m		total := multiplicand;
77275963Srpaulo   alg_shift		total := total * coeff
78275963Srpaulo   alg_add_t_m2		total := total + multiplicand * coeff;
79275963Srpaulo   alg_sub_t_m2		total := total - multiplicand * coeff;
80275963Srpaulo   alg_add_factor	total := total * coeff + total;
81275963Srpaulo   alg_sub_factor	total := total * coeff - total;
82275963Srpaulo   alg_add_t2_m		total := total * coeff + multiplicand;
83278768Sloos   alg_sub_t2_m		total := total * coeff - multiplicand;
84275963Srpaulo
85275963Srpaulo   The first operand must be either alg_zero or alg_m.  */
86275963Srpaulo
87275963Srpaulostruct algorithm
88275963Srpaulo{
89275963Srpaulo  struct mult_cost cost;
90275963Srpaulo  short ops;
91275963Srpaulo  /* The size of the OP and LOG fields are not directly related to the
92275963Srpaulo     word size, but the worst-case algorithms will be if we have few
93275963Srpaulo     consecutive ones or zeros, i.e., a multiplicand like 10101010101...
94275963Srpaulo     In that case we will generate shift-by-2, add, shift-by-2, add,...,
95275963Srpaulo     in total wordsize operations.  */
96275963Srpaulo  enum alg_code op[MAX_BITS_PER_WORD];
97275963Srpaulo  char log[MAX_BITS_PER_WORD];
98275963Srpaulo};
99275963Srpaulo
100275963Srpaulo/* The entry for our multiplication cache/hash table.  */
101275963Srpaulostruct alg_hash_entry {
102275963Srpaulo  /* The number we are multiplying by.  */
103275963Srpaulo  unsigned HOST_WIDE_INT t;
104275963Srpaulo
105275963Srpaulo  /* The mode in which we are multiplying something by T.  */
106275963Srpaulo  machine_mode mode;
107275963Srpaulo
108275963Srpaulo  /* The best multiplication algorithm for t.  */
109275963Srpaulo  enum alg_code alg;
110275963Srpaulo
111275963Srpaulo  /* The cost of multiplication if ALG_CODE is not alg_impossible.
112275963Srpaulo     Otherwise, the cost within which multiplication by T is
113275963Srpaulo     impossible.  */
114275963Srpaulo  struct mult_cost cost;
115275963Srpaulo
116275963Srpaulo  /* Optimized for speed? */
117275963Srpaulo  bool speed;
118275963Srpaulo};
119275963Srpaulo
120322724Smarius/* The number of cache/hash entries.  */
121322724Smarius#if HOST_BITS_PER_WIDE_INT == 64
122322724Smarius#define NUM_ALG_HASH_ENTRIES 1031
123322724Smarius#else
124322724Smarius#define NUM_ALG_HASH_ENTRIES 307
125322724Smarius#endif
126322724Smarius
127275963Srpaulo#define NUM_MODE_INT \
128275963Srpaulo  (MAX_MODE_INT - MIN_MODE_INT + 1)
129275963Srpaulo#define NUM_MODE_PARTIAL_INT \
130275963Srpaulo  (MIN_MODE_PARTIAL_INT == VOIDmode ? 0 \
131275963Srpaulo   : MAX_MODE_PARTIAL_INT - MIN_MODE_PARTIAL_INT + 1)
132278768Sloos#define NUM_MODE_VECTOR_INT \
133275963Srpaulo  (MIN_MODE_VECTOR_INT == VOIDmode ? 0 \
134275963Srpaulo   : MAX_MODE_VECTOR_INT - MIN_MODE_VECTOR_INT + 1)
135275963Srpaulo
136275963Srpaulo#define NUM_MODE_IP_INT (NUM_MODE_INT + NUM_MODE_PARTIAL_INT)
137275963Srpaulo#define NUM_MODE_IPV_INT (NUM_MODE_IP_INT + NUM_MODE_VECTOR_INT)
138275963Srpaulo
139275963Srpaulostruct expmed_op_cheap {
140275963Srpaulo  bool cheap[2][NUM_MODE_IPV_INT];
141275963Srpaulo};
142275963Srpaulo
143275963Srpaulostruct expmed_op_costs {
144275963Srpaulo  int cost[2][NUM_MODE_IPV_INT];
145275963Srpaulo};
146275963Srpaulo
147275963Srpaulo/* Target-dependent globals.  */
148275963Srpaulostruct target_expmed {
149275963Srpaulo  /* Each entry of ALG_HASH caches alg_code for some integer.  This is
150275963Srpaulo     actually a hash table.  If we have a collision, that the older
151275963Srpaulo     entry is kicked out.  */
152275963Srpaulo  struct alg_hash_entry x_alg_hash[NUM_ALG_HASH_ENTRIES];
153275963Srpaulo
154275963Srpaulo  /* True if x_alg_hash might already have been used.  */
155322724Smarius  bool x_alg_hash_used_p;
156275963Srpaulo
157275963Srpaulo  /* Nonzero means divides or modulus operations are relatively cheap for
158275963Srpaulo     powers of two, so don't use branches; emit the operation instead.
159275963Srpaulo     Usually, this will mean that the MD file will emit non-branch
160275963Srpaulo     sequences.  */
161275963Srpaulo  struct expmed_op_cheap x_sdiv_pow2_cheap;
162275963Srpaulo  struct expmed_op_cheap x_smod_pow2_cheap;
163275963Srpaulo
164275963Srpaulo  /* Cost of various pieces of RTL.  Note that some of these are indexed by
165275963Srpaulo     shift count and some by mode.  */
166275963Srpaulo  int x_zero_cost[2];
167275963Srpaulo  struct expmed_op_costs x_add_cost;
168275963Srpaulo  struct expmed_op_costs x_neg_cost;
169275963Srpaulo  struct expmed_op_costs x_shift_cost[MAX_BITS_PER_WORD];
170275963Srpaulo  struct expmed_op_costs x_shiftadd_cost[MAX_BITS_PER_WORD];
171275963Srpaulo  struct expmed_op_costs x_shiftsub0_cost[MAX_BITS_PER_WORD];
172275963Srpaulo  struct expmed_op_costs x_shiftsub1_cost[MAX_BITS_PER_WORD];
173275963Srpaulo  struct expmed_op_costs x_mul_cost;
174322724Smarius  struct expmed_op_costs x_sdiv_cost;
175322724Smarius  struct expmed_op_costs x_udiv_cost;
176322724Smarius  int x_mul_widen_cost[2][NUM_MODE_INT];
177322724Smarius  int x_mul_highpart_cost[2][NUM_MODE_INT];
178322724Smarius
179322724Smarius  /* Conversion costs are only defined between two scalar integer modes
180322724Smarius     of different sizes.  The first machine mode is the destination mode,
181322724Smarius     and the second is the source mode.  */
182275963Srpaulo  int x_convert_cost[2][NUM_MODE_IP_INT][NUM_MODE_IP_INT];
183275963Srpaulo};
184322724Smarius
185275963Srpauloextern struct target_expmed default_target_expmed;
186275963Srpaulo#if SWITCHABLE_TARGET
187275963Srpauloextern struct target_expmed *this_target_expmed;
188275963Srpaulo#else
189275963Srpaulo#define this_target_expmed (&default_target_expmed)
190275963Srpaulo#endif
191275963Srpaulo
192322724Smarius/* Return a pointer to the alg_hash_entry at IDX.  */
193275963Srpaulo
194275963Srpaulostatic inline struct alg_hash_entry *
195275963Srpauloalg_hash_entry_ptr (int idx)
196275963Srpaulo{
197275963Srpaulo  return &this_target_expmed->x_alg_hash[idx];
198275963Srpaulo}
199275963Srpaulo
200275963Srpaulo/* Return true if the x_alg_hash field might have been used.  */
201322724Smarius
202275963Srpaulostatic inline bool
203275963Srpauloalg_hash_used_p (void)
204275963Srpaulo{
205275963Srpaulo  return this_target_expmed->x_alg_hash_used_p;
206275963Srpaulo}
207275963Srpaulo
208275963Srpaulo/* Set whether the x_alg_hash field might have been used.  */
209275963Srpaulo
210275963Srpaulostatic inline void
211275963Srpauloset_alg_hash_used_p (bool usedp)
212275963Srpaulo{
213275963Srpaulo  this_target_expmed->x_alg_hash_used_p = usedp;
214275963Srpaulo}
215275963Srpaulo
216275963Srpaulo/* Compute an index into the cost arrays by mode class.  */
217275963Srpaulo
218275963Srpaulostatic inline int
219275963Srpauloexpmed_mode_index (machine_mode mode)
220322724Smarius{
221322724Smarius  switch (GET_MODE_CLASS (mode))
222322724Smarius    {
223322724Smarius    case MODE_INT:
224322724Smarius      return mode - MIN_MODE_INT;
225322724Smarius    case MODE_PARTIAL_INT:
226322724Smarius      /* If there are no partial integer modes, help the compiler
227322724Smarius	 to figure out this will never happen.  See PR59934.  */
228275963Srpaulo      if (MIN_MODE_PARTIAL_INT != VOIDmode)
229275963Srpaulo	return mode - MIN_MODE_PARTIAL_INT + NUM_MODE_INT;
230322724Smarius      break;
231275963Srpaulo    case MODE_VECTOR_INT:
232275963Srpaulo      /* If there are no vector integer modes, help the compiler
233275963Srpaulo	 to figure out this will never happen.  See PR59934.  */
234275963Srpaulo      if (MIN_MODE_VECTOR_INT != VOIDmode)
235275963Srpaulo	return mode - MIN_MODE_VECTOR_INT + NUM_MODE_IP_INT;
236275963Srpaulo      break;
237275963Srpaulo    default:
238322724Smarius      break;
239275963Srpaulo    }
240275963Srpaulo  gcc_unreachable ();
241275963Srpaulo}
242275963Srpaulo
243275963Srpaulo/* Return a pointer to a boolean contained in EOC indicating whether
244275963Srpaulo   a particular operation performed in MODE is cheap when optimizing
245275963Srpaulo   for SPEED.  */
246275963Srpaulo
247322724Smariusstatic inline bool *
248275963Srpauloexpmed_op_cheap_ptr (struct expmed_op_cheap *eoc, bool speed,
249275963Srpaulo		     machine_mode mode)
250275963Srpaulo{
251275963Srpaulo  int idx = expmed_mode_index (mode);
252275963Srpaulo  return &eoc->cheap[speed][idx];
253275963Srpaulo}
254275963Srpaulo
255275963Srpaulo/* Return a pointer to a cost contained in COSTS when a particular
256275963Srpaulo   operation is performed in MODE when optimizing for SPEED.  */
257275963Srpaulo
258275963Srpaulostatic inline int *
259275963Srpauloexpmed_op_cost_ptr (struct expmed_op_costs *costs, bool speed,
260275963Srpaulo		    machine_mode mode)
261275963Srpaulo{
262275963Srpaulo  int idx = expmed_mode_index (mode);
263275963Srpaulo  return &costs->cost[speed][idx];
264275963Srpaulo}
265275963Srpaulo
266322724Smarius/* Subroutine of {set_,}sdiv_pow2_cheap.  Not to be used otherwise.  */
267322724Smarius
268322724Smariusstatic inline bool *
269322724Smariussdiv_pow2_cheap_ptr (bool speed, machine_mode mode)
270322724Smarius{
271322724Smarius  return expmed_op_cheap_ptr (&this_target_expmed->x_sdiv_pow2_cheap,
272322724Smarius			      speed, mode);
273322724Smarius}
274275963Srpaulo
275275963Srpaulo/* Set whether a signed division by a power of 2 is cheap in MODE
276322724Smarius   when optimizing for SPEED.  */
277275963Srpaulo
278275963Srpaulostatic inline void
279275963Srpauloset_sdiv_pow2_cheap (bool speed, machine_mode mode, bool cheap_p)
280275963Srpaulo{
281275963Srpaulo  *sdiv_pow2_cheap_ptr (speed, mode) = cheap_p;
282275963Srpaulo}
283275963Srpaulo
284322724Smarius/* Return whether a signed division by a power of 2 is cheap in MODE
285275963Srpaulo   when optimizing for SPEED.  */
286275963Srpaulo
287275963Srpaulostatic inline bool
288275963Srpaulosdiv_pow2_cheap (bool speed, machine_mode mode)
289275963Srpaulo{
290275963Srpaulo  return *sdiv_pow2_cheap_ptr (speed, mode);
291275963Srpaulo}
292275963Srpaulo
293322724Smarius/* Subroutine of {set_,}smod_pow2_cheap.  Not to be used otherwise.  */
294275963Srpaulo
295275963Srpaulostatic inline bool *
296275963Srpaulosmod_pow2_cheap_ptr (bool speed, machine_mode mode)
297275963Srpaulo{
298275963Srpaulo  return expmed_op_cheap_ptr (&this_target_expmed->x_smod_pow2_cheap,
299275963Srpaulo			      speed, mode);
300275963Srpaulo}
301275963Srpaulo
302275963Srpaulo/* Set whether a signed modulo by a power of 2 is CHEAP in MODE when
303275963Srpaulo   optimizing for SPEED.  */
304275963Srpaulo
305275963Srpaulostatic inline void
306275963Srpauloset_smod_pow2_cheap (bool speed, machine_mode mode, bool cheap)
307275963Srpaulo{
308275963Srpaulo  *smod_pow2_cheap_ptr (speed, mode) = cheap;
309275963Srpaulo}
310275963Srpaulo
311275963Srpaulo/* Return whether a signed modulo by a power of 2 is cheap in MODE
312275963Srpaulo   when optimizing for SPEED.  */
313322724Smarius
314322724Smariusstatic inline bool
315322724Smariussmod_pow2_cheap (bool speed, machine_mode mode)
316322724Smarius{
317322724Smarius  return *smod_pow2_cheap_ptr (speed, mode);
318322724Smarius}
319322724Smarius
320322724Smarius/* Subroutine of {set_,}zero_cost.  Not to be used otherwise.  */
321322724Smarius
322275963Srpaulostatic inline int *
323275963Srpaulozero_cost_ptr (bool speed)
324322724Smarius{
325275963Srpaulo  return &this_target_expmed->x_zero_cost[speed];
326275963Srpaulo}
327275963Srpaulo
328275963Srpaulo/* Set the COST of loading zero when optimizing for SPEED.  */
329275963Srpaulo
330275963Srpaulostatic inline void
331275963Srpauloset_zero_cost (bool speed, int cost)
332275963Srpaulo{
333275963Srpaulo  *zero_cost_ptr (speed) = cost;
334275963Srpaulo}
335275963Srpaulo
336275963Srpaulo/* Return the COST of loading zero when optimizing for SPEED.  */
337275963Srpaulo
338275963Srpaulostatic inline int
339275963Srpaulozero_cost (bool speed)
340275963Srpaulo{
341275963Srpaulo  return *zero_cost_ptr (speed);
342322724Smarius}
343322724Smarius
344322724Smarius/* Subroutine of {set_,}add_cost.  Not to be used otherwise.  */
345322724Smarius
346322724Smariusstatic inline int *
347322724Smariusadd_cost_ptr (bool speed, machine_mode mode)
348322724Smarius{
349322724Smarius  return expmed_op_cost_ptr (&this_target_expmed->x_add_cost, speed, mode);
350322724Smarius}
351275963Srpaulo
352275963Srpaulo/* Set the COST of computing an add in MODE when optimizing for SPEED.  */
353322724Smarius
354275963Srpaulostatic inline void
355275963Srpauloset_add_cost (bool speed, machine_mode mode, int cost)
356275963Srpaulo{
357275963Srpaulo  *add_cost_ptr (speed, mode) = cost;
358275963Srpaulo}
359275963Srpaulo
360275963Srpaulo/* Return the cost of computing an add in MODE when optimizing for SPEED.  */
361275963Srpaulo
362322724Smariusstatic inline int
363275963Srpauloadd_cost (bool speed, machine_mode mode)
364275963Srpaulo{
365275963Srpaulo  return *add_cost_ptr (speed, mode);
366275963Srpaulo}
367275963Srpaulo
368275963Srpaulo/* Subroutine of {set_,}neg_cost.  Not to be used otherwise.  */
369275963Srpaulo
370322724Smariusstatic inline int *
371275963Srpauloneg_cost_ptr (bool speed, machine_mode mode)
372275963Srpaulo{
373275963Srpaulo  return expmed_op_cost_ptr (&this_target_expmed->x_neg_cost, speed, mode);
374275963Srpaulo}
375275963Srpaulo
376275963Srpaulo/* Set the COST of computing a negation in MODE when optimizing for SPEED.  */
377275963Srpaulo
378275963Srpaulostatic inline void
379275963Srpauloset_neg_cost (bool speed, machine_mode mode, int cost)
380275963Srpaulo{
381275963Srpaulo  *neg_cost_ptr (speed, mode) = cost;
382275963Srpaulo}
383275963Srpaulo
384275963Srpaulo/* Return the cost of computing a negation in MODE when optimizing for
385275963Srpaulo   SPEED.  */
386275963Srpaulo
387275963Srpaulostatic inline int
388275963Srpauloneg_cost (bool speed, machine_mode mode)
389322724Smarius{
390322724Smarius  return *neg_cost_ptr (speed, mode);
391322724Smarius}
392322724Smarius
393322724Smarius/* Subroutine of {set_,}shift_cost.  Not to be used otherwise.  */
394322724Smarius
395322724Smariusstatic inline int *
396322724Smariusshift_cost_ptr (bool speed, machine_mode mode, int bits)
397275963Srpaulo{
398275963Srpaulo  return expmed_op_cost_ptr (&this_target_expmed->x_shift_cost[bits],
399322724Smarius			     speed, mode);
400275963Srpaulo}
401275963Srpaulo
402275963Srpaulo/* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED.  */
403275963Srpaulo
404275963Srpaulostatic inline void
405275963Srpauloset_shift_cost (bool speed, machine_mode mode, int bits, int cost)
406322724Smarius{
407275963Srpaulo  *shift_cost_ptr (speed, mode, bits) = cost;
408275963Srpaulo}
409275963Srpaulo
410275963Srpaulo/* Return the cost of doing a shift in MODE by BITS when optimizing for
411275963Srpaulo   SPEED.  */
412275963Srpaulo
413275963Srpaulostatic inline int
414322724Smariusshift_cost (bool speed, machine_mode mode, int bits)
415275963Srpaulo{
416275963Srpaulo  return *shift_cost_ptr (speed, mode, bits);
417275963Srpaulo}
418275963Srpaulo
419275963Srpaulo/* Subroutine of {set_,}shiftadd_cost.  Not to be used otherwise.  */
420275963Srpaulo
421275963Srpaulostatic inline int *
422275963Srpauloshiftadd_cost_ptr (bool speed, machine_mode mode, int bits)
423275963Srpaulo{
424275963Srpaulo  return expmed_op_cost_ptr (&this_target_expmed->x_shiftadd_cost[bits],
425275963Srpaulo			     speed, mode);
426275963Srpaulo}
427275963Srpaulo
428275963Srpaulo/* Set the COST of doing a shift in MODE by BITS followed by an add when
429275963Srpaulo   optimizing for SPEED.  */
430275963Srpaulo
431275963Srpaulostatic inline void
432275963Srpauloset_shiftadd_cost (bool speed, machine_mode mode, int bits, int cost)
433275963Srpaulo{
434275963Srpaulo  *shiftadd_cost_ptr (speed, mode, bits) = cost;
435275963Srpaulo}
436275963Srpaulo
437275963Srpaulo/* Return the cost of doing a shift in MODE by BITS followed by an add
438322724Smarius   when optimizing for SPEED.  */
439322724Smarius
440322724Smariusstatic inline int
441322724Smariusshiftadd_cost (bool speed, machine_mode mode, int bits)
442322724Smarius{
443322724Smarius  return *shiftadd_cost_ptr (speed, mode, bits);
444322724Smarius}
445322724Smarius
446322724Smarius/* Subroutine of {set_,}shiftsub0_cost.  Not to be used otherwise.  */
447275963Srpaulo
448275963Srpaulostatic inline int *
449322724Smariusshiftsub0_cost_ptr (bool speed, machine_mode mode, int bits)
450275963Srpaulo{
451275963Srpaulo  return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub0_cost[bits],
452275963Srpaulo			     speed, mode);
453275963Srpaulo}
454275963Srpaulo
455275963Srpaulo/* Set the COST of doing a shift in MODE by BITS and then subtracting a
456322724Smarius   value when optimizing for SPEED.  */
457275963Srpaulo
458275963Srpaulostatic inline void
459275963Srpauloset_shiftsub0_cost (bool speed, machine_mode mode, int bits, int cost)
460275963Srpaulo{
461275963Srpaulo  *shiftsub0_cost_ptr (speed, mode, bits) = cost;
462275963Srpaulo}
463275963Srpaulo
464275963Srpaulo/* Return the cost of doing a shift in MODE by BITS and then subtracting
465322724Smarius   a value when optimizing for SPEED.  */
466275963Srpaulo
467275963Srpaulostatic inline int
468275963Srpauloshiftsub0_cost (bool speed, machine_mode mode, int bits)
469275963Srpaulo{
470275963Srpaulo  return *shiftsub0_cost_ptr (speed, mode, bits);
471275963Srpaulo}
472275963Srpaulo
473275963Srpaulo/* Subroutine of {set_,}shiftsub1_cost.  Not to be used otherwise.  */
474275963Srpaulo
475275963Srpaulostatic inline int *
476275963Srpauloshiftsub1_cost_ptr (bool speed, machine_mode mode, int bits)
477275963Srpaulo{
478275963Srpaulo  return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub1_cost[bits],
479275963Srpaulo			     speed, mode);
480275963Srpaulo}
481275963Srpaulo
482275963Srpaulo/* Set the COST of subtracting a shift in MODE by BITS from a value when
483275963Srpaulo   optimizing for SPEED.  */
484322724Smarius
485322724Smariusstatic inline void
486322724Smariusset_shiftsub1_cost (bool speed, machine_mode mode, int bits, int cost)
487322724Smarius{
488322724Smarius  *shiftsub1_cost_ptr (speed, mode, bits) = cost;
489322724Smarius}
490322724Smarius
491322724Smarius/* Return the cost of subtracting a shift in MODE by BITS from a value
492275963Srpaulo   when optimizing for SPEED.  */
493275963Srpaulo
494322724Smariusstatic inline int
495275963Srpauloshiftsub1_cost (bool speed, machine_mode mode, int bits)
496275963Srpaulo{
497275963Srpaulo  return *shiftsub1_cost_ptr (speed, mode, bits);
498275963Srpaulo}
499275963Srpaulo
500275963Srpaulo/* Subroutine of {set_,}mul_cost.  Not to be used otherwise.  */
501322724Smarius
502275963Srpaulostatic inline int *
503275963Srpaulomul_cost_ptr (bool speed, machine_mode mode)
504275963Srpaulo{
505275963Srpaulo  return expmed_op_cost_ptr (&this_target_expmed->x_mul_cost, speed, mode);
506275963Srpaulo}
507275963Srpaulo
508275963Srpaulo/* Set the COST of doing a multiplication in MODE when optimizing for
509275963Srpaulo   SPEED.  */
510322724Smarius
511275963Srpaulostatic inline void
512275963Srpauloset_mul_cost (bool speed, machine_mode mode, int cost)
513275963Srpaulo{
514275963Srpaulo  *mul_cost_ptr (speed, mode) = cost;
515275963Srpaulo}
516275963Srpaulo
517275963Srpaulo/* Return the cost of doing a multiplication in MODE when optimizing
518275963Srpaulo   for SPEED.  */
519275963Srpaulo
520275963Srpaulostatic inline int
521275963Srpaulomul_cost (bool speed, machine_mode mode)
522275963Srpaulo{
523275963Srpaulo  return *mul_cost_ptr (speed, mode);
524275963Srpaulo}
525275963Srpaulo
526275963Srpaulo/* Subroutine of {set_,}sdiv_cost.  Not to be used otherwise.  */
527275963Srpaulo
528275963Srpaulostatic inline int *
529322724Smariussdiv_cost_ptr (bool speed, machine_mode mode)
530322724Smarius{
531322724Smarius  return expmed_op_cost_ptr (&this_target_expmed->x_sdiv_cost, speed, mode);
532322724Smarius}
533322724Smarius
534322724Smarius/* Set the COST of doing a signed division in MODE when optimizing
535322724Smarius   for SPEED.  */
536322724Smarius
537275963Srpaulostatic inline void
538275963Srpauloset_sdiv_cost (bool speed, machine_mode mode, int cost)
539322724Smarius{
540275963Srpaulo  *sdiv_cost_ptr (speed, mode) = cost;
541275963Srpaulo}
542275963Srpaulo
543275963Srpaulo/* Return the cost of doing a signed division in MODE when optimizing
544275963Srpaulo   for SPEED.  */
545275963Srpaulo
546322724Smariusstatic inline int
547275963Srpaulosdiv_cost (bool speed, machine_mode mode)
548275963Srpaulo{
549275963Srpaulo  return *sdiv_cost_ptr (speed, mode);
550275963Srpaulo}
551275963Srpaulo
552275963Srpaulo/* Subroutine of {set_,}udiv_cost.  Not to be used otherwise.  */
553275963Srpaulo
554322724Smariusstatic inline int *
555275963Srpauloudiv_cost_ptr (bool speed, machine_mode mode)
556275963Srpaulo{
557275963Srpaulo  return expmed_op_cost_ptr (&this_target_expmed->x_udiv_cost, speed, mode);
558275963Srpaulo}
559275963Srpaulo
560275963Srpaulo/* Set the COST of doing an unsigned division in MODE when optimizing
561275963Srpaulo   for SPEED.  */
562275963Srpaulo
563275963Srpaulostatic inline void
564275963Srpauloset_udiv_cost (bool speed, machine_mode mode, int cost)
565275963Srpaulo{
566275963Srpaulo  *udiv_cost_ptr (speed, mode) = cost;
567275963Srpaulo}
568275963Srpaulo
569275963Srpaulo/* Return the cost of doing an unsigned division in MODE when
570275963Srpaulo   optimizing for SPEED.  */
571275963Srpaulo
572275963Srpaulostatic inline int
573322724Smariusudiv_cost (bool speed, machine_mode mode)
574322724Smarius{
575322724Smarius  return *udiv_cost_ptr (speed, mode);
576322724Smarius}
577322724Smarius
578322724Smarius/* Subroutine of {set_,}mul_widen_cost.  Not to be used otherwise.  */
579322724Smarius
580322724Smariusstatic inline int *
581275963Srpaulomul_widen_cost_ptr (bool speed, machine_mode mode)
582275963Srpaulo{
583322724Smarius  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
584275963Srpaulo
585275963Srpaulo  return &this_target_expmed->x_mul_widen_cost[speed][mode - MIN_MODE_INT];
586275963Srpaulo}
587275963Srpaulo
588275963Srpaulo/* Set the COST for computing a widening multiplication in MODE when
589275963Srpaulo   optimizing for SPEED.  */
590322724Smarius
591275963Srpaulostatic inline void
592275963Srpauloset_mul_widen_cost (bool speed, machine_mode mode, int cost)
593275963Srpaulo{
594275963Srpaulo  *mul_widen_cost_ptr (speed, mode) = cost;
595275963Srpaulo}
596275963Srpaulo
597275963Srpaulo/* Return the cost for computing a widening multiplication in MODE when
598275963Srpaulo   optimizing for SPEED.  */
599322724Smarius
600275963Srpaulostatic inline int
601275963Srpaulomul_widen_cost (bool speed, machine_mode mode)
602275963Srpaulo{
603275963Srpaulo  return *mul_widen_cost_ptr (speed, mode);
604275963Srpaulo}
605275963Srpaulo
606275963Srpaulo/* Subroutine of {set_,}mul_highpart_cost.  Not to be used otherwise.  */
607275963Srpaulo
608275963Srpaulostatic inline int *
609275963Srpaulomul_highpart_cost_ptr (bool speed, machine_mode mode)
610275963Srpaulo{
611275963Srpaulo  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
612275963Srpaulo
613275963Srpaulo  return &this_target_expmed->x_mul_highpart_cost[speed][mode - MIN_MODE_INT];
614275963Srpaulo}
615275963Srpaulo
616275963Srpaulo/* Set the COST for computing the high part of a multiplication in MODE
617275963Srpaulo   when optimizing for SPEED.  */
618275963Srpaulo
619275963Srpaulostatic inline void
620275963Srpauloset_mul_highpart_cost (bool speed, machine_mode mode, int cost)
621275963Srpaulo{
622275963Srpaulo  *mul_highpart_cost_ptr (speed, mode) = cost;
623275963Srpaulo}
624275963Srpaulo
625275963Srpaulo/* Return the cost for computing the high part of a multiplication in MODE
626275963Srpaulo   when optimizing for SPEED.  */
627275963Srpaulo
628275963Srpaulostatic inline int
629322724Smariusmul_highpart_cost (bool speed, machine_mode mode)
630322724Smarius{
631322724Smarius  return *mul_highpart_cost_ptr (speed, mode);
632322724Smarius}
633322724Smarius
634322724Smarius/* Subroutine of {set_,}convert_cost.  Not to be used otherwise.  */
635322724Smarius
636322724Smariusstatic inline int *
637322724Smariusconvert_cost_ptr (machine_mode to_mode, machine_mode from_mode,
638275963Srpaulo		  bool speed)
639275963Srpaulo{
640322724Smarius  int to_idx = expmed_mode_index (to_mode);
641275963Srpaulo  int from_idx = expmed_mode_index (from_mode);
642275963Srpaulo
643275963Srpaulo  gcc_assert (IN_RANGE (to_idx, 0, NUM_MODE_IP_INT - 1));
644275963Srpaulo  gcc_assert (IN_RANGE (from_idx, 0, NUM_MODE_IP_INT - 1));
645275963Srpaulo
646275963Srpaulo  return &this_target_expmed->x_convert_cost[speed][to_idx][from_idx];
647322724Smarius}
648275963Srpaulo
649275963Srpaulo/* Set the COST for converting from FROM_MODE to TO_MODE when optimizing
650275963Srpaulo   for SPEED.  */
651275963Srpaulo
652275963Srpaulostatic inline void
653275963Srpauloset_convert_cost (machine_mode to_mode, machine_mode from_mode,
654275963Srpaulo		  bool speed, int cost)
655322724Smarius{
656275963Srpaulo  *convert_cost_ptr (to_mode, from_mode, speed) = cost;
657275963Srpaulo}
658275963Srpaulo
659275963Srpaulo/* Return the cost for converting from FROM_MODE to TO_MODE when optimizing
660275963Srpaulo   for SPEED.  */
661275963Srpaulo
662275963Srpaulostatic inline int
663275963Srpauloconvert_cost (machine_mode to_mode, machine_mode from_mode,
664275963Srpaulo	      bool speed)
665275963Srpaulo{
666275963Srpaulo  return *convert_cost_ptr (to_mode, from_mode, speed);
667275963Srpaulo}
668275963Srpaulo
669275963Srpauloextern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool);
670275963Srpauloextern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
671275963Srpaulo			enum machine_mode mode, enum machine_mode compare_mode,
672275963Srpaulo			int unsignedp, rtx x, rtx y, int normalizep,
673275963Srpaulo			enum machine_mode target_mode);
674322724Smarius
675322724Smarius/* Arguments MODE, RTX: return an rtx for the negation of that value.
676322724Smarius   May emit insns.  */
677322724Smariusextern rtx negate_rtx (machine_mode, rtx);
678322724Smarius
679322724Smarius/* Expand a logical AND operation.  */
680322724Smariusextern rtx expand_and (machine_mode, rtx, rtx, rtx);
681322724Smarius
682275963Srpaulo/* Emit a store-flag operation.  */
683275963Srpauloextern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, machine_mode,
684322724Smarius			    int, int);
685275963Srpaulo
686275963Srpaulo/* Like emit_store_flag, but always succeeds.  */
687275963Srpauloextern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx,
688275963Srpaulo				  machine_mode, int, int);
689275963Srpaulo
690275963Srpaulo/* Choose a minimal N + 1 bit approximation to 1/D that can be used to
691322724Smarius   replace division by D, and put the least significant N bits of the result
692275963Srpaulo   in *MULTIPLIER_PTR and return the most significant bit.  */
693275963Srpauloextern unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int,
694275963Srpaulo						 int, unsigned HOST_WIDE_INT *,
695275963Srpaulo						 int *, int *);
696275963Srpaulo
697275963Srpaulo#ifdef TREE_CODE
698275963Srpauloextern rtx expand_variable_shift (enum tree_code, machine_mode,
699275963Srpaulo				  rtx, tree, rtx, int);
700275963Srpauloextern rtx expand_shift (enum tree_code, machine_mode, rtx, int, rtx,
701275963Srpaulo			     int);
702275963Srpauloextern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
703275963Srpaulo			  rtx, int);
704275963Srpaulo#endif
705275963Srpaulo
706275963Srpauloextern void store_bit_field (rtx, unsigned HOST_WIDE_INT,
707275963Srpaulo			     unsigned HOST_WIDE_INT,
708275963Srpaulo			     unsigned HOST_WIDE_INT,
709275963Srpaulo			     unsigned HOST_WIDE_INT,
710275963Srpaulo			     machine_mode, rtx);
711275963Srpauloextern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
712275963Srpaulo			      unsigned HOST_WIDE_INT, int, rtx,
713275963Srpaulo			      machine_mode, machine_mode);
714275963Srpauloextern rtx extract_low_bits (machine_mode, machine_mode, rtx);
715275963Srpauloextern rtx expand_mult (machine_mode, rtx, rtx, rtx, int);
716275963Srpauloextern rtx expand_mult_highpart_adjust (machine_mode, rtx, rtx, rtx, rtx, int);
717275963Srpaulo
718275963Srpaulo#endif  // EXPMED_H
719275963Srpaulo