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