xref: /netbsd/external/gpl3/gcc.old/dist/gcc/expmed.h (revision ec02198a)
110d565efSmrg /* Target-dependent costs for expmed.c.
2*ec02198aSmrg    Copyright (C) 1987-2020 Free Software Foundation, Inc.
310d565efSmrg 
410d565efSmrg This file is part of GCC.
510d565efSmrg 
610d565efSmrg GCC is free software; you can redistribute it and/or modify it under
710d565efSmrg the terms of the GNU General Public License as published by the Free
810d565efSmrg Software Foundation; either version 3, or (at your option) any later
910d565efSmrg version.
1010d565efSmrg 
1110d565efSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1210d565efSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1310d565efSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1410d565efSmrg for more details.
1510d565efSmrg 
1610d565efSmrg You should have received a copy of the GNU General Public License
1710d565efSmrg along with GCC; see the file COPYING3.  If not see
1810d565efSmrg <http://www.gnu.org/licenses/>.  */
1910d565efSmrg 
2010d565efSmrg #ifndef EXPMED_H
2110d565efSmrg #define EXPMED_H 1
2210d565efSmrg 
2310d565efSmrg #include "insn-codes.h"
2410d565efSmrg 
2510d565efSmrg enum alg_code {
2610d565efSmrg   alg_unknown,
2710d565efSmrg   alg_zero,
2810d565efSmrg   alg_m, alg_shift,
2910d565efSmrg   alg_add_t_m2,
3010d565efSmrg   alg_sub_t_m2,
3110d565efSmrg   alg_add_factor,
3210d565efSmrg   alg_sub_factor,
3310d565efSmrg   alg_add_t2_m,
3410d565efSmrg   alg_sub_t2_m,
3510d565efSmrg   alg_impossible
3610d565efSmrg };
3710d565efSmrg 
3810d565efSmrg /* Indicates the type of fixup needed after a constant multiplication.
3910d565efSmrg    BASIC_VARIANT means no fixup is needed, NEGATE_VARIANT means that
4010d565efSmrg    the result should be negated, and ADD_VARIANT means that the
4110d565efSmrg    multiplicand should be added to the result.  */
4210d565efSmrg enum mult_variant {basic_variant, negate_variant, add_variant};
4310d565efSmrg 
4410d565efSmrg bool choose_mult_variant (machine_mode, HOST_WIDE_INT,
4510d565efSmrg 			  struct algorithm *, enum mult_variant *, int);
4610d565efSmrg 
4710d565efSmrg /* This structure holds the "cost" of a multiply sequence.  The
4810d565efSmrg    "cost" field holds the total rtx_cost of every operator in the
4910d565efSmrg    synthetic multiplication sequence, hence cost(a op b) is defined
5010d565efSmrg    as rtx_cost(op) + cost(a) + cost(b), where cost(leaf) is zero.
5110d565efSmrg    The "latency" field holds the minimum possible latency of the
5210d565efSmrg    synthetic multiply, on a hypothetical infinitely parallel CPU.
5310d565efSmrg    This is the critical path, or the maximum height, of the expression
5410d565efSmrg    tree which is the sum of rtx_costs on the most expensive path from
5510d565efSmrg    any leaf to the root.  Hence latency(a op b) is defined as zero for
5610d565efSmrg    leaves and rtx_cost(op) + max(latency(a), latency(b)) otherwise.  */
5710d565efSmrg 
5810d565efSmrg struct mult_cost {
5910d565efSmrg   short cost;     /* Total rtx_cost of the multiplication sequence.  */
6010d565efSmrg   short latency;  /* The latency of the multiplication sequence.  */
6110d565efSmrg };
6210d565efSmrg 
6310d565efSmrg /* This macro is used to compare a pointer to a mult_cost against an
6410d565efSmrg    single integer "rtx_cost" value.  This is equivalent to the macro
6510d565efSmrg    CHEAPER_MULT_COST(X,Z) where Z = {Y,Y}.  */
6610d565efSmrg #define MULT_COST_LESS(X,Y) ((X)->cost < (Y)	\
6710d565efSmrg 			     || ((X)->cost == (Y) && (X)->latency < (Y)))
6810d565efSmrg 
6910d565efSmrg /* This macro is used to compare two pointers to mult_costs against
7010d565efSmrg    each other.  The macro returns true if X is cheaper than Y.
7110d565efSmrg    Currently, the cheaper of two mult_costs is the one with the
7210d565efSmrg    lower "cost".  If "cost"s are tied, the lower latency is cheaper.  */
7310d565efSmrg #define CHEAPER_MULT_COST(X,Y)  ((X)->cost < (Y)->cost		\
7410d565efSmrg 				 || ((X)->cost == (Y)->cost	\
7510d565efSmrg 				     && (X)->latency < (Y)->latency))
7610d565efSmrg 
7710d565efSmrg /* This structure records a sequence of operations.
7810d565efSmrg    `ops' is the number of operations recorded.
7910d565efSmrg    `cost' is their total cost.
8010d565efSmrg    The operations are stored in `op' and the corresponding
8110d565efSmrg    logarithms of the integer coefficients in `log'.
8210d565efSmrg 
8310d565efSmrg    These are the operations:
8410d565efSmrg    alg_zero		total := 0;
8510d565efSmrg    alg_m		total := multiplicand;
8610d565efSmrg    alg_shift		total := total * coeff
8710d565efSmrg    alg_add_t_m2		total := total + multiplicand * coeff;
8810d565efSmrg    alg_sub_t_m2		total := total - multiplicand * coeff;
8910d565efSmrg    alg_add_factor	total := total * coeff + total;
9010d565efSmrg    alg_sub_factor	total := total * coeff - total;
9110d565efSmrg    alg_add_t2_m		total := total * coeff + multiplicand;
9210d565efSmrg    alg_sub_t2_m		total := total * coeff - multiplicand;
9310d565efSmrg 
9410d565efSmrg    The first operand must be either alg_zero or alg_m.  */
9510d565efSmrg 
9610d565efSmrg struct algorithm
9710d565efSmrg {
9810d565efSmrg   struct mult_cost cost;
9910d565efSmrg   short ops;
10010d565efSmrg   /* The size of the OP and LOG fields are not directly related to the
10110d565efSmrg      word size, but the worst-case algorithms will be if we have few
10210d565efSmrg      consecutive ones or zeros, i.e., a multiplicand like 10101010101...
10310d565efSmrg      In that case we will generate shift-by-2, add, shift-by-2, add,...,
10410d565efSmrg      in total wordsize operations.  */
10510d565efSmrg   enum alg_code op[MAX_BITS_PER_WORD];
10610d565efSmrg   char log[MAX_BITS_PER_WORD];
10710d565efSmrg };
10810d565efSmrg 
10910d565efSmrg /* The entry for our multiplication cache/hash table.  */
11010d565efSmrg struct alg_hash_entry {
11110d565efSmrg   /* The number we are multiplying by.  */
11210d565efSmrg   unsigned HOST_WIDE_INT t;
11310d565efSmrg 
11410d565efSmrg   /* The mode in which we are multiplying something by T.  */
11510d565efSmrg   machine_mode mode;
11610d565efSmrg 
11710d565efSmrg   /* The best multiplication algorithm for t.  */
11810d565efSmrg   enum alg_code alg;
11910d565efSmrg 
12010d565efSmrg   /* The cost of multiplication if ALG_CODE is not alg_impossible.
12110d565efSmrg      Otherwise, the cost within which multiplication by T is
12210d565efSmrg      impossible.  */
12310d565efSmrg   struct mult_cost cost;
12410d565efSmrg 
12510d565efSmrg   /* Optimized for speed? */
12610d565efSmrg   bool speed;
12710d565efSmrg };
12810d565efSmrg 
12910d565efSmrg /* The number of cache/hash entries.  */
13010d565efSmrg #if HOST_BITS_PER_WIDE_INT == 64
13110d565efSmrg #define NUM_ALG_HASH_ENTRIES 1031
13210d565efSmrg #else
13310d565efSmrg #define NUM_ALG_HASH_ENTRIES 307
13410d565efSmrg #endif
13510d565efSmrg 
13610d565efSmrg #define NUM_MODE_INT \
13710d565efSmrg   (MAX_MODE_INT - MIN_MODE_INT + 1)
13810d565efSmrg #define NUM_MODE_PARTIAL_INT \
139c7a68eb7Smrg   (MIN_MODE_PARTIAL_INT == E_VOIDmode ? 0 \
14010d565efSmrg    : MAX_MODE_PARTIAL_INT - MIN_MODE_PARTIAL_INT + 1)
14110d565efSmrg #define NUM_MODE_VECTOR_INT \
142c7a68eb7Smrg   (MIN_MODE_VECTOR_INT == E_VOIDmode ? 0 \
14310d565efSmrg    : MAX_MODE_VECTOR_INT - MIN_MODE_VECTOR_INT + 1)
14410d565efSmrg 
14510d565efSmrg #define NUM_MODE_IP_INT (NUM_MODE_INT + NUM_MODE_PARTIAL_INT)
14610d565efSmrg #define NUM_MODE_IPV_INT (NUM_MODE_IP_INT + NUM_MODE_VECTOR_INT)
14710d565efSmrg 
14810d565efSmrg struct expmed_op_cheap {
14910d565efSmrg   bool cheap[2][NUM_MODE_IPV_INT];
15010d565efSmrg };
15110d565efSmrg 
15210d565efSmrg struct expmed_op_costs {
15310d565efSmrg   int cost[2][NUM_MODE_IPV_INT];
15410d565efSmrg };
15510d565efSmrg 
15610d565efSmrg /* Target-dependent globals.  */
15710d565efSmrg struct target_expmed {
15810d565efSmrg   /* Each entry of ALG_HASH caches alg_code for some integer.  This is
15910d565efSmrg      actually a hash table.  If we have a collision, that the older
16010d565efSmrg      entry is kicked out.  */
16110d565efSmrg   struct alg_hash_entry x_alg_hash[NUM_ALG_HASH_ENTRIES];
16210d565efSmrg 
16310d565efSmrg   /* True if x_alg_hash might already have been used.  */
16410d565efSmrg   bool x_alg_hash_used_p;
16510d565efSmrg 
16610d565efSmrg   /* Nonzero means divides or modulus operations are relatively cheap for
16710d565efSmrg      powers of two, so don't use branches; emit the operation instead.
16810d565efSmrg      Usually, this will mean that the MD file will emit non-branch
16910d565efSmrg      sequences.  */
17010d565efSmrg   struct expmed_op_cheap x_sdiv_pow2_cheap;
17110d565efSmrg   struct expmed_op_cheap x_smod_pow2_cheap;
17210d565efSmrg 
17310d565efSmrg   /* Cost of various pieces of RTL.  Note that some of these are indexed by
17410d565efSmrg      shift count and some by mode.  */
17510d565efSmrg   int x_zero_cost[2];
17610d565efSmrg   struct expmed_op_costs x_add_cost;
17710d565efSmrg   struct expmed_op_costs x_neg_cost;
17810d565efSmrg   struct expmed_op_costs x_shift_cost[MAX_BITS_PER_WORD];
17910d565efSmrg   struct expmed_op_costs x_shiftadd_cost[MAX_BITS_PER_WORD];
18010d565efSmrg   struct expmed_op_costs x_shiftsub0_cost[MAX_BITS_PER_WORD];
18110d565efSmrg   struct expmed_op_costs x_shiftsub1_cost[MAX_BITS_PER_WORD];
18210d565efSmrg   struct expmed_op_costs x_mul_cost;
18310d565efSmrg   struct expmed_op_costs x_sdiv_cost;
18410d565efSmrg   struct expmed_op_costs x_udiv_cost;
18510d565efSmrg   int x_mul_widen_cost[2][NUM_MODE_INT];
18610d565efSmrg   int x_mul_highpart_cost[2][NUM_MODE_INT];
18710d565efSmrg 
18810d565efSmrg   /* Conversion costs are only defined between two scalar integer modes
18910d565efSmrg      of different sizes.  The first machine mode is the destination mode,
19010d565efSmrg      and the second is the source mode.  */
19110d565efSmrg   int x_convert_cost[2][NUM_MODE_IP_INT][NUM_MODE_IP_INT];
19210d565efSmrg };
19310d565efSmrg 
19410d565efSmrg extern struct target_expmed default_target_expmed;
19510d565efSmrg #if SWITCHABLE_TARGET
19610d565efSmrg extern struct target_expmed *this_target_expmed;
19710d565efSmrg #else
19810d565efSmrg #define this_target_expmed (&default_target_expmed)
19910d565efSmrg #endif
20010d565efSmrg 
20110d565efSmrg /* Return a pointer to the alg_hash_entry at IDX.  */
20210d565efSmrg 
20310d565efSmrg static inline struct alg_hash_entry *
alg_hash_entry_ptr(int idx)20410d565efSmrg alg_hash_entry_ptr (int idx)
20510d565efSmrg {
20610d565efSmrg   return &this_target_expmed->x_alg_hash[idx];
20710d565efSmrg }
20810d565efSmrg 
20910d565efSmrg /* Return true if the x_alg_hash field might have been used.  */
21010d565efSmrg 
21110d565efSmrg static inline bool
alg_hash_used_p(void)21210d565efSmrg alg_hash_used_p (void)
21310d565efSmrg {
21410d565efSmrg   return this_target_expmed->x_alg_hash_used_p;
21510d565efSmrg }
21610d565efSmrg 
21710d565efSmrg /* Set whether the x_alg_hash field might have been used.  */
21810d565efSmrg 
21910d565efSmrg static inline void
set_alg_hash_used_p(bool usedp)22010d565efSmrg set_alg_hash_used_p (bool usedp)
22110d565efSmrg {
22210d565efSmrg   this_target_expmed->x_alg_hash_used_p = usedp;
22310d565efSmrg }
22410d565efSmrg 
22510d565efSmrg /* Compute an index into the cost arrays by mode class.  */
22610d565efSmrg 
22710d565efSmrg static inline int
expmed_mode_index(machine_mode mode)22810d565efSmrg expmed_mode_index (machine_mode mode)
22910d565efSmrg {
23010d565efSmrg   switch (GET_MODE_CLASS (mode))
23110d565efSmrg     {
23210d565efSmrg     case MODE_INT:
23310d565efSmrg       return mode - MIN_MODE_INT;
23410d565efSmrg     case MODE_PARTIAL_INT:
23510d565efSmrg       /* If there are no partial integer modes, help the compiler
23610d565efSmrg 	 to figure out this will never happen.  See PR59934.  */
23710d565efSmrg       if (MIN_MODE_PARTIAL_INT != VOIDmode)
23810d565efSmrg 	return mode - MIN_MODE_PARTIAL_INT + NUM_MODE_INT;
23910d565efSmrg       break;
24010d565efSmrg     case MODE_VECTOR_INT:
24110d565efSmrg       /* If there are no vector integer modes, help the compiler
24210d565efSmrg 	 to figure out this will never happen.  See PR59934.  */
24310d565efSmrg       if (MIN_MODE_VECTOR_INT != VOIDmode)
24410d565efSmrg 	return mode - MIN_MODE_VECTOR_INT + NUM_MODE_IP_INT;
24510d565efSmrg       break;
24610d565efSmrg     default:
24710d565efSmrg       break;
24810d565efSmrg     }
24910d565efSmrg   gcc_unreachable ();
25010d565efSmrg }
25110d565efSmrg 
25210d565efSmrg /* Return a pointer to a boolean contained in EOC indicating whether
25310d565efSmrg    a particular operation performed in MODE is cheap when optimizing
25410d565efSmrg    for SPEED.  */
25510d565efSmrg 
25610d565efSmrg static inline bool *
expmed_op_cheap_ptr(struct expmed_op_cheap * eoc,bool speed,machine_mode mode)25710d565efSmrg expmed_op_cheap_ptr (struct expmed_op_cheap *eoc, bool speed,
25810d565efSmrg 		     machine_mode mode)
25910d565efSmrg {
26010d565efSmrg   int idx = expmed_mode_index (mode);
26110d565efSmrg   return &eoc->cheap[speed][idx];
26210d565efSmrg }
26310d565efSmrg 
26410d565efSmrg /* Return a pointer to a cost contained in COSTS when a particular
26510d565efSmrg    operation is performed in MODE when optimizing for SPEED.  */
26610d565efSmrg 
26710d565efSmrg static inline int *
expmed_op_cost_ptr(struct expmed_op_costs * costs,bool speed,machine_mode mode)26810d565efSmrg expmed_op_cost_ptr (struct expmed_op_costs *costs, bool speed,
26910d565efSmrg 		    machine_mode mode)
27010d565efSmrg {
27110d565efSmrg   int idx = expmed_mode_index (mode);
27210d565efSmrg   return &costs->cost[speed][idx];
27310d565efSmrg }
27410d565efSmrg 
27510d565efSmrg /* Subroutine of {set_,}sdiv_pow2_cheap.  Not to be used otherwise.  */
27610d565efSmrg 
27710d565efSmrg static inline bool *
sdiv_pow2_cheap_ptr(bool speed,machine_mode mode)27810d565efSmrg sdiv_pow2_cheap_ptr (bool speed, machine_mode mode)
27910d565efSmrg {
28010d565efSmrg   return expmed_op_cheap_ptr (&this_target_expmed->x_sdiv_pow2_cheap,
28110d565efSmrg 			      speed, mode);
28210d565efSmrg }
28310d565efSmrg 
28410d565efSmrg /* Set whether a signed division by a power of 2 is cheap in MODE
28510d565efSmrg    when optimizing for SPEED.  */
28610d565efSmrg 
28710d565efSmrg static inline void
set_sdiv_pow2_cheap(bool speed,machine_mode mode,bool cheap_p)28810d565efSmrg set_sdiv_pow2_cheap (bool speed, machine_mode mode, bool cheap_p)
28910d565efSmrg {
29010d565efSmrg   *sdiv_pow2_cheap_ptr (speed, mode) = cheap_p;
29110d565efSmrg }
29210d565efSmrg 
29310d565efSmrg /* Return whether a signed division by a power of 2 is cheap in MODE
29410d565efSmrg    when optimizing for SPEED.  */
29510d565efSmrg 
29610d565efSmrg static inline bool
sdiv_pow2_cheap(bool speed,machine_mode mode)29710d565efSmrg sdiv_pow2_cheap (bool speed, machine_mode mode)
29810d565efSmrg {
29910d565efSmrg   return *sdiv_pow2_cheap_ptr (speed, mode);
30010d565efSmrg }
30110d565efSmrg 
30210d565efSmrg /* Subroutine of {set_,}smod_pow2_cheap.  Not to be used otherwise.  */
30310d565efSmrg 
30410d565efSmrg static inline bool *
smod_pow2_cheap_ptr(bool speed,machine_mode mode)30510d565efSmrg smod_pow2_cheap_ptr (bool speed, machine_mode mode)
30610d565efSmrg {
30710d565efSmrg   return expmed_op_cheap_ptr (&this_target_expmed->x_smod_pow2_cheap,
30810d565efSmrg 			      speed, mode);
30910d565efSmrg }
31010d565efSmrg 
31110d565efSmrg /* Set whether a signed modulo by a power of 2 is CHEAP in MODE when
31210d565efSmrg    optimizing for SPEED.  */
31310d565efSmrg 
31410d565efSmrg static inline void
set_smod_pow2_cheap(bool speed,machine_mode mode,bool cheap)31510d565efSmrg set_smod_pow2_cheap (bool speed, machine_mode mode, bool cheap)
31610d565efSmrg {
31710d565efSmrg   *smod_pow2_cheap_ptr (speed, mode) = cheap;
31810d565efSmrg }
31910d565efSmrg 
32010d565efSmrg /* Return whether a signed modulo by a power of 2 is cheap in MODE
32110d565efSmrg    when optimizing for SPEED.  */
32210d565efSmrg 
32310d565efSmrg static inline bool
smod_pow2_cheap(bool speed,machine_mode mode)32410d565efSmrg smod_pow2_cheap (bool speed, machine_mode mode)
32510d565efSmrg {
32610d565efSmrg   return *smod_pow2_cheap_ptr (speed, mode);
32710d565efSmrg }
32810d565efSmrg 
32910d565efSmrg /* Subroutine of {set_,}zero_cost.  Not to be used otherwise.  */
33010d565efSmrg 
33110d565efSmrg static inline int *
zero_cost_ptr(bool speed)33210d565efSmrg zero_cost_ptr (bool speed)
33310d565efSmrg {
33410d565efSmrg   return &this_target_expmed->x_zero_cost[speed];
33510d565efSmrg }
33610d565efSmrg 
33710d565efSmrg /* Set the COST of loading zero when optimizing for SPEED.  */
33810d565efSmrg 
33910d565efSmrg static inline void
set_zero_cost(bool speed,int cost)34010d565efSmrg set_zero_cost (bool speed, int cost)
34110d565efSmrg {
34210d565efSmrg   *zero_cost_ptr (speed) = cost;
34310d565efSmrg }
34410d565efSmrg 
34510d565efSmrg /* Return the COST of loading zero when optimizing for SPEED.  */
34610d565efSmrg 
34710d565efSmrg static inline int
zero_cost(bool speed)34810d565efSmrg zero_cost (bool speed)
34910d565efSmrg {
35010d565efSmrg   return *zero_cost_ptr (speed);
35110d565efSmrg }
35210d565efSmrg 
35310d565efSmrg /* Subroutine of {set_,}add_cost.  Not to be used otherwise.  */
35410d565efSmrg 
35510d565efSmrg static inline int *
add_cost_ptr(bool speed,machine_mode mode)35610d565efSmrg add_cost_ptr (bool speed, machine_mode mode)
35710d565efSmrg {
35810d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_add_cost, speed, mode);
35910d565efSmrg }
36010d565efSmrg 
36110d565efSmrg /* Set the COST of computing an add in MODE when optimizing for SPEED.  */
36210d565efSmrg 
36310d565efSmrg static inline void
set_add_cost(bool speed,machine_mode mode,int cost)36410d565efSmrg set_add_cost (bool speed, machine_mode mode, int cost)
36510d565efSmrg {
36610d565efSmrg   *add_cost_ptr (speed, mode) = cost;
36710d565efSmrg }
36810d565efSmrg 
36910d565efSmrg /* Return the cost of computing an add in MODE when optimizing for SPEED.  */
37010d565efSmrg 
37110d565efSmrg static inline int
add_cost(bool speed,machine_mode mode)37210d565efSmrg add_cost (bool speed, machine_mode mode)
37310d565efSmrg {
37410d565efSmrg   return *add_cost_ptr (speed, mode);
37510d565efSmrg }
37610d565efSmrg 
37710d565efSmrg /* Subroutine of {set_,}neg_cost.  Not to be used otherwise.  */
37810d565efSmrg 
37910d565efSmrg static inline int *
neg_cost_ptr(bool speed,machine_mode mode)38010d565efSmrg neg_cost_ptr (bool speed, machine_mode mode)
38110d565efSmrg {
38210d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_neg_cost, speed, mode);
38310d565efSmrg }
38410d565efSmrg 
38510d565efSmrg /* Set the COST of computing a negation in MODE when optimizing for SPEED.  */
38610d565efSmrg 
38710d565efSmrg static inline void
set_neg_cost(bool speed,machine_mode mode,int cost)38810d565efSmrg set_neg_cost (bool speed, machine_mode mode, int cost)
38910d565efSmrg {
39010d565efSmrg   *neg_cost_ptr (speed, mode) = cost;
39110d565efSmrg }
39210d565efSmrg 
39310d565efSmrg /* Return the cost of computing a negation in MODE when optimizing for
39410d565efSmrg    SPEED.  */
39510d565efSmrg 
39610d565efSmrg static inline int
neg_cost(bool speed,machine_mode mode)39710d565efSmrg neg_cost (bool speed, machine_mode mode)
39810d565efSmrg {
39910d565efSmrg   return *neg_cost_ptr (speed, mode);
40010d565efSmrg }
40110d565efSmrg 
40210d565efSmrg /* Subroutine of {set_,}shift_cost.  Not to be used otherwise.  */
40310d565efSmrg 
40410d565efSmrg static inline int *
shift_cost_ptr(bool speed,machine_mode mode,int bits)40510d565efSmrg shift_cost_ptr (bool speed, machine_mode mode, int bits)
40610d565efSmrg {
40710d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_shift_cost[bits],
40810d565efSmrg 			     speed, mode);
40910d565efSmrg }
41010d565efSmrg 
41110d565efSmrg /* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED.  */
41210d565efSmrg 
41310d565efSmrg static inline void
set_shift_cost(bool speed,machine_mode mode,int bits,int cost)41410d565efSmrg set_shift_cost (bool speed, machine_mode mode, int bits, int cost)
41510d565efSmrg {
41610d565efSmrg   *shift_cost_ptr (speed, mode, bits) = cost;
41710d565efSmrg }
41810d565efSmrg 
41910d565efSmrg /* Return the cost of doing a shift in MODE by BITS when optimizing for
42010d565efSmrg    SPEED.  */
42110d565efSmrg 
42210d565efSmrg static inline int
shift_cost(bool speed,machine_mode mode,int bits)42310d565efSmrg shift_cost (bool speed, machine_mode mode, int bits)
42410d565efSmrg {
42510d565efSmrg   return *shift_cost_ptr (speed, mode, bits);
42610d565efSmrg }
42710d565efSmrg 
42810d565efSmrg /* Subroutine of {set_,}shiftadd_cost.  Not to be used otherwise.  */
42910d565efSmrg 
43010d565efSmrg static inline int *
shiftadd_cost_ptr(bool speed,machine_mode mode,int bits)43110d565efSmrg shiftadd_cost_ptr (bool speed, machine_mode mode, int bits)
43210d565efSmrg {
43310d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_shiftadd_cost[bits],
43410d565efSmrg 			     speed, mode);
43510d565efSmrg }
43610d565efSmrg 
43710d565efSmrg /* Set the COST of doing a shift in MODE by BITS followed by an add when
43810d565efSmrg    optimizing for SPEED.  */
43910d565efSmrg 
44010d565efSmrg static inline void
set_shiftadd_cost(bool speed,machine_mode mode,int bits,int cost)44110d565efSmrg set_shiftadd_cost (bool speed, machine_mode mode, int bits, int cost)
44210d565efSmrg {
44310d565efSmrg   *shiftadd_cost_ptr (speed, mode, bits) = cost;
44410d565efSmrg }
44510d565efSmrg 
44610d565efSmrg /* Return the cost of doing a shift in MODE by BITS followed by an add
44710d565efSmrg    when optimizing for SPEED.  */
44810d565efSmrg 
44910d565efSmrg static inline int
shiftadd_cost(bool speed,machine_mode mode,int bits)45010d565efSmrg shiftadd_cost (bool speed, machine_mode mode, int bits)
45110d565efSmrg {
45210d565efSmrg   return *shiftadd_cost_ptr (speed, mode, bits);
45310d565efSmrg }
45410d565efSmrg 
45510d565efSmrg /* Subroutine of {set_,}shiftsub0_cost.  Not to be used otherwise.  */
45610d565efSmrg 
45710d565efSmrg static inline int *
shiftsub0_cost_ptr(bool speed,machine_mode mode,int bits)45810d565efSmrg shiftsub0_cost_ptr (bool speed, machine_mode mode, int bits)
45910d565efSmrg {
46010d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub0_cost[bits],
46110d565efSmrg 			     speed, mode);
46210d565efSmrg }
46310d565efSmrg 
46410d565efSmrg /* Set the COST of doing a shift in MODE by BITS and then subtracting a
46510d565efSmrg    value when optimizing for SPEED.  */
46610d565efSmrg 
46710d565efSmrg static inline void
set_shiftsub0_cost(bool speed,machine_mode mode,int bits,int cost)46810d565efSmrg set_shiftsub0_cost (bool speed, machine_mode mode, int bits, int cost)
46910d565efSmrg {
47010d565efSmrg   *shiftsub0_cost_ptr (speed, mode, bits) = cost;
47110d565efSmrg }
47210d565efSmrg 
47310d565efSmrg /* Return the cost of doing a shift in MODE by BITS and then subtracting
47410d565efSmrg    a value when optimizing for SPEED.  */
47510d565efSmrg 
47610d565efSmrg static inline int
shiftsub0_cost(bool speed,machine_mode mode,int bits)47710d565efSmrg shiftsub0_cost (bool speed, machine_mode mode, int bits)
47810d565efSmrg {
47910d565efSmrg   return *shiftsub0_cost_ptr (speed, mode, bits);
48010d565efSmrg }
48110d565efSmrg 
48210d565efSmrg /* Subroutine of {set_,}shiftsub1_cost.  Not to be used otherwise.  */
48310d565efSmrg 
48410d565efSmrg static inline int *
shiftsub1_cost_ptr(bool speed,machine_mode mode,int bits)48510d565efSmrg shiftsub1_cost_ptr (bool speed, machine_mode mode, int bits)
48610d565efSmrg {
48710d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub1_cost[bits],
48810d565efSmrg 			     speed, mode);
48910d565efSmrg }
49010d565efSmrg 
49110d565efSmrg /* Set the COST of subtracting a shift in MODE by BITS from a value when
49210d565efSmrg    optimizing for SPEED.  */
49310d565efSmrg 
49410d565efSmrg static inline void
set_shiftsub1_cost(bool speed,machine_mode mode,int bits,int cost)49510d565efSmrg set_shiftsub1_cost (bool speed, machine_mode mode, int bits, int cost)
49610d565efSmrg {
49710d565efSmrg   *shiftsub1_cost_ptr (speed, mode, bits) = cost;
49810d565efSmrg }
49910d565efSmrg 
50010d565efSmrg /* Return the cost of subtracting a shift in MODE by BITS from a value
50110d565efSmrg    when optimizing for SPEED.  */
50210d565efSmrg 
50310d565efSmrg static inline int
shiftsub1_cost(bool speed,machine_mode mode,int bits)50410d565efSmrg shiftsub1_cost (bool speed, machine_mode mode, int bits)
50510d565efSmrg {
50610d565efSmrg   return *shiftsub1_cost_ptr (speed, mode, bits);
50710d565efSmrg }
50810d565efSmrg 
50910d565efSmrg /* Subroutine of {set_,}mul_cost.  Not to be used otherwise.  */
51010d565efSmrg 
51110d565efSmrg static inline int *
mul_cost_ptr(bool speed,machine_mode mode)51210d565efSmrg mul_cost_ptr (bool speed, machine_mode mode)
51310d565efSmrg {
51410d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_mul_cost, speed, mode);
51510d565efSmrg }
51610d565efSmrg 
51710d565efSmrg /* Set the COST of doing a multiplication in MODE when optimizing for
51810d565efSmrg    SPEED.  */
51910d565efSmrg 
52010d565efSmrg static inline void
set_mul_cost(bool speed,machine_mode mode,int cost)52110d565efSmrg set_mul_cost (bool speed, machine_mode mode, int cost)
52210d565efSmrg {
52310d565efSmrg   *mul_cost_ptr (speed, mode) = cost;
52410d565efSmrg }
52510d565efSmrg 
52610d565efSmrg /* Return the cost of doing a multiplication in MODE when optimizing
52710d565efSmrg    for SPEED.  */
52810d565efSmrg 
52910d565efSmrg static inline int
mul_cost(bool speed,machine_mode mode)53010d565efSmrg mul_cost (bool speed, machine_mode mode)
53110d565efSmrg {
53210d565efSmrg   return *mul_cost_ptr (speed, mode);
53310d565efSmrg }
53410d565efSmrg 
53510d565efSmrg /* Subroutine of {set_,}sdiv_cost.  Not to be used otherwise.  */
53610d565efSmrg 
53710d565efSmrg static inline int *
sdiv_cost_ptr(bool speed,machine_mode mode)53810d565efSmrg sdiv_cost_ptr (bool speed, machine_mode mode)
53910d565efSmrg {
54010d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_sdiv_cost, speed, mode);
54110d565efSmrg }
54210d565efSmrg 
54310d565efSmrg /* Set the COST of doing a signed division in MODE when optimizing
54410d565efSmrg    for SPEED.  */
54510d565efSmrg 
54610d565efSmrg static inline void
set_sdiv_cost(bool speed,machine_mode mode,int cost)54710d565efSmrg set_sdiv_cost (bool speed, machine_mode mode, int cost)
54810d565efSmrg {
54910d565efSmrg   *sdiv_cost_ptr (speed, mode) = cost;
55010d565efSmrg }
55110d565efSmrg 
55210d565efSmrg /* Return the cost of doing a signed division in MODE when optimizing
55310d565efSmrg    for SPEED.  */
55410d565efSmrg 
55510d565efSmrg static inline int
sdiv_cost(bool speed,machine_mode mode)55610d565efSmrg sdiv_cost (bool speed, machine_mode mode)
55710d565efSmrg {
55810d565efSmrg   return *sdiv_cost_ptr (speed, mode);
55910d565efSmrg }
56010d565efSmrg 
56110d565efSmrg /* Subroutine of {set_,}udiv_cost.  Not to be used otherwise.  */
56210d565efSmrg 
56310d565efSmrg static inline int *
udiv_cost_ptr(bool speed,machine_mode mode)56410d565efSmrg udiv_cost_ptr (bool speed, machine_mode mode)
56510d565efSmrg {
56610d565efSmrg   return expmed_op_cost_ptr (&this_target_expmed->x_udiv_cost, speed, mode);
56710d565efSmrg }
56810d565efSmrg 
56910d565efSmrg /* Set the COST of doing an unsigned division in MODE when optimizing
57010d565efSmrg    for SPEED.  */
57110d565efSmrg 
57210d565efSmrg static inline void
set_udiv_cost(bool speed,machine_mode mode,int cost)57310d565efSmrg set_udiv_cost (bool speed, machine_mode mode, int cost)
57410d565efSmrg {
57510d565efSmrg   *udiv_cost_ptr (speed, mode) = cost;
57610d565efSmrg }
57710d565efSmrg 
57810d565efSmrg /* Return the cost of doing an unsigned division in MODE when
57910d565efSmrg    optimizing for SPEED.  */
58010d565efSmrg 
58110d565efSmrg static inline int
udiv_cost(bool speed,machine_mode mode)58210d565efSmrg udiv_cost (bool speed, machine_mode mode)
58310d565efSmrg {
58410d565efSmrg   return *udiv_cost_ptr (speed, mode);
58510d565efSmrg }
58610d565efSmrg 
58710d565efSmrg /* Subroutine of {set_,}mul_widen_cost.  Not to be used otherwise.  */
58810d565efSmrg 
58910d565efSmrg static inline int *
mul_widen_cost_ptr(bool speed,machine_mode mode)59010d565efSmrg mul_widen_cost_ptr (bool speed, machine_mode mode)
59110d565efSmrg {
59210d565efSmrg   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
59310d565efSmrg 
59410d565efSmrg   return &this_target_expmed->x_mul_widen_cost[speed][mode - MIN_MODE_INT];
59510d565efSmrg }
59610d565efSmrg 
59710d565efSmrg /* Set the COST for computing a widening multiplication in MODE when
59810d565efSmrg    optimizing for SPEED.  */
59910d565efSmrg 
60010d565efSmrg static inline void
set_mul_widen_cost(bool speed,machine_mode mode,int cost)60110d565efSmrg set_mul_widen_cost (bool speed, machine_mode mode, int cost)
60210d565efSmrg {
60310d565efSmrg   *mul_widen_cost_ptr (speed, mode) = cost;
60410d565efSmrg }
60510d565efSmrg 
60610d565efSmrg /* Return the cost for computing a widening multiplication in MODE when
60710d565efSmrg    optimizing for SPEED.  */
60810d565efSmrg 
60910d565efSmrg static inline int
mul_widen_cost(bool speed,machine_mode mode)61010d565efSmrg mul_widen_cost (bool speed, machine_mode mode)
61110d565efSmrg {
61210d565efSmrg   return *mul_widen_cost_ptr (speed, mode);
61310d565efSmrg }
61410d565efSmrg 
61510d565efSmrg /* Subroutine of {set_,}mul_highpart_cost.  Not to be used otherwise.  */
61610d565efSmrg 
61710d565efSmrg static inline int *
mul_highpart_cost_ptr(bool speed,machine_mode mode)61810d565efSmrg mul_highpart_cost_ptr (bool speed, machine_mode mode)
61910d565efSmrg {
62010d565efSmrg   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
62110d565efSmrg   int m = mode - MIN_MODE_INT;
62210d565efSmrg   gcc_assert (m < NUM_MODE_INT);
62310d565efSmrg 
62410d565efSmrg   return &this_target_expmed->x_mul_highpart_cost[speed][m];
62510d565efSmrg }
62610d565efSmrg 
62710d565efSmrg /* Set the COST for computing the high part of a multiplication in MODE
62810d565efSmrg    when optimizing for SPEED.  */
62910d565efSmrg 
63010d565efSmrg static inline void
set_mul_highpart_cost(bool speed,machine_mode mode,int cost)63110d565efSmrg set_mul_highpart_cost (bool speed, machine_mode mode, int cost)
63210d565efSmrg {
63310d565efSmrg   *mul_highpart_cost_ptr (speed, mode) = cost;
63410d565efSmrg }
63510d565efSmrg 
63610d565efSmrg /* Return the cost for computing the high part of a multiplication in MODE
63710d565efSmrg    when optimizing for SPEED.  */
63810d565efSmrg 
63910d565efSmrg static inline int
mul_highpart_cost(bool speed,machine_mode mode)64010d565efSmrg mul_highpart_cost (bool speed, machine_mode mode)
64110d565efSmrg {
64210d565efSmrg   return *mul_highpart_cost_ptr (speed, mode);
64310d565efSmrg }
64410d565efSmrg 
64510d565efSmrg /* Subroutine of {set_,}convert_cost.  Not to be used otherwise.  */
64610d565efSmrg 
64710d565efSmrg static inline int *
convert_cost_ptr(machine_mode to_mode,machine_mode from_mode,bool speed)64810d565efSmrg convert_cost_ptr (machine_mode to_mode, machine_mode from_mode,
64910d565efSmrg 		  bool speed)
65010d565efSmrg {
65110d565efSmrg   int to_idx = expmed_mode_index (to_mode);
65210d565efSmrg   int from_idx = expmed_mode_index (from_mode);
65310d565efSmrg 
65410d565efSmrg   gcc_assert (IN_RANGE (to_idx, 0, NUM_MODE_IP_INT - 1));
65510d565efSmrg   gcc_assert (IN_RANGE (from_idx, 0, NUM_MODE_IP_INT - 1));
65610d565efSmrg 
65710d565efSmrg   return &this_target_expmed->x_convert_cost[speed][to_idx][from_idx];
65810d565efSmrg }
65910d565efSmrg 
66010d565efSmrg /* Set the COST for converting from FROM_MODE to TO_MODE when optimizing
66110d565efSmrg    for SPEED.  */
66210d565efSmrg 
66310d565efSmrg static inline void
set_convert_cost(machine_mode to_mode,machine_mode from_mode,bool speed,int cost)66410d565efSmrg set_convert_cost (machine_mode to_mode, machine_mode from_mode,
66510d565efSmrg 		  bool speed, int cost)
66610d565efSmrg {
66710d565efSmrg   *convert_cost_ptr (to_mode, from_mode, speed) = cost;
66810d565efSmrg }
66910d565efSmrg 
67010d565efSmrg /* Return the cost for converting from FROM_MODE to TO_MODE when optimizing
67110d565efSmrg    for SPEED.  */
67210d565efSmrg 
67310d565efSmrg static inline int
convert_cost(machine_mode to_mode,machine_mode from_mode,bool speed)67410d565efSmrg convert_cost (machine_mode to_mode, machine_mode from_mode,
67510d565efSmrg 	      bool speed)
67610d565efSmrg {
67710d565efSmrg   return *convert_cost_ptr (to_mode, from_mode, speed);
67810d565efSmrg }
67910d565efSmrg 
68010d565efSmrg extern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool);
68110d565efSmrg extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
682c7a68eb7Smrg 			machine_mode mode, machine_mode compare_mode,
68310d565efSmrg 			int unsignedp, rtx x, rtx y, int normalizep,
684c7a68eb7Smrg 			machine_mode target_mode);
68510d565efSmrg 
68610d565efSmrg /* Arguments MODE, RTX: return an rtx for the negation of that value.
68710d565efSmrg    May emit insns.  */
68810d565efSmrg extern rtx negate_rtx (machine_mode, rtx);
68910d565efSmrg 
69010d565efSmrg /* Arguments MODE, RTX: return an rtx for the flipping of that value.
69110d565efSmrg    May emit insns.  */
692c7a68eb7Smrg extern rtx flip_storage_order (machine_mode, rtx);
69310d565efSmrg 
69410d565efSmrg /* Expand a logical AND operation.  */
69510d565efSmrg extern rtx expand_and (machine_mode, rtx, rtx, rtx);
69610d565efSmrg 
69710d565efSmrg /* Emit a store-flag operation.  */
69810d565efSmrg extern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, machine_mode,
69910d565efSmrg 			    int, int);
70010d565efSmrg 
70110d565efSmrg /* Like emit_store_flag, but always succeeds.  */
70210d565efSmrg extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx,
70310d565efSmrg 				  machine_mode, int, int);
70410d565efSmrg 
7050fc04c29Smrg extern void canonicalize_comparison (machine_mode, enum rtx_code *, rtx *);
7060fc04c29Smrg 
70710d565efSmrg /* Choose a minimal N + 1 bit approximation to 1/D that can be used to
70810d565efSmrg    replace division by D, and put the least significant N bits of the result
70910d565efSmrg    in *MULTIPLIER_PTR and return the most significant bit.  */
71010d565efSmrg extern unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int,
71110d565efSmrg 						 int, unsigned HOST_WIDE_INT *,
71210d565efSmrg 						 int *, int *);
71310d565efSmrg 
71410d565efSmrg #ifdef TREE_CODE
71510d565efSmrg extern rtx expand_variable_shift (enum tree_code, machine_mode,
71610d565efSmrg 				  rtx, tree, rtx, int);
717c7a68eb7Smrg extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
71810d565efSmrg 			 int);
71910d565efSmrg extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
72010d565efSmrg 			  rtx, int);
72110d565efSmrg #endif
72210d565efSmrg 
723c7a68eb7Smrg extern void store_bit_field (rtx, poly_uint64, poly_uint64,
724c7a68eb7Smrg 			     poly_uint64, poly_uint64,
72510d565efSmrg 			     machine_mode, rtx, bool);
726c7a68eb7Smrg extern rtx extract_bit_field (rtx, poly_uint64, poly_uint64, int, rtx,
727c7a68eb7Smrg 			      machine_mode, machine_mode, bool, rtx *);
72810d565efSmrg extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
729c7a68eb7Smrg extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int, bool = false);
730c7a68eb7Smrg extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx,
731c7a68eb7Smrg 					rtx, int);
73210d565efSmrg 
73310d565efSmrg #endif  // EXPMED_H
734