(root)/
gcc-13.2.0/
gcc/
expmed.h
       1  /* Target-dependent costs for expmed.cc.
       2     Copyright (C) 1987-2023 Free Software Foundation, Inc.
       3  
       4  This file is part of GCC.
       5  
       6  GCC is free software; you can redistribute it and/or modify it under
       7  the terms of the GNU General Public License as published by the Free
       8  Software Foundation; either version 3, or (at your option) any later
       9  version.
      10  
      11  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  for more details.
      15  
      16  You should have received a copy of the GNU General Public License
      17  along with GCC; see the file COPYING3.  If not see
      18  <http://www.gnu.org/licenses/>.  */
      19  
      20  #ifndef EXPMED_H
      21  #define EXPMED_H 1
      22  
      23  #include "insn-codes.h"
      24  
      25  enum alg_code {
      26    alg_unknown,
      27    alg_zero,
      28    alg_m, alg_shift,
      29    alg_add_t_m2,
      30    alg_sub_t_m2,
      31    alg_add_factor,
      32    alg_sub_factor,
      33    alg_add_t2_m,
      34    alg_sub_t2_m,
      35    alg_impossible
      36  };
      37  
      38  /* Indicates the type of fixup needed after a constant multiplication.
      39     BASIC_VARIANT means no fixup is needed, NEGATE_VARIANT means that
      40     the result should be negated, and ADD_VARIANT means that the
      41     multiplicand should be added to the result.  */
      42  enum mult_variant {basic_variant, negate_variant, add_variant};
      43  
      44  bool choose_mult_variant (machine_mode, HOST_WIDE_INT,
      45  			  struct algorithm *, enum mult_variant *, int);
      46  
      47  /* This structure holds the "cost" of a multiply sequence.  The
      48     "cost" field holds the total rtx_cost of every operator in the
      49     synthetic multiplication sequence, hence cost(a op b) is defined
      50     as rtx_cost(op) + cost(a) + cost(b), where cost(leaf) is zero.
      51     The "latency" field holds the minimum possible latency of the
      52     synthetic multiply, on a hypothetical infinitely parallel CPU.
      53     This is the critical path, or the maximum height, of the expression
      54     tree which is the sum of rtx_costs on the most expensive path from
      55     any leaf to the root.  Hence latency(a op b) is defined as zero for
      56     leaves and rtx_cost(op) + max(latency(a), latency(b)) otherwise.  */
      57  
      58  struct mult_cost {
      59    short cost;     /* Total rtx_cost of the multiplication sequence.  */
      60    short latency;  /* The latency of the multiplication sequence.  */
      61  };
      62  
      63  /* This macro is used to compare a pointer to a mult_cost against an
      64     single integer "rtx_cost" value.  This is equivalent to the macro
      65     CHEAPER_MULT_COST(X,Z) where Z = {Y,Y}.  */
      66  #define MULT_COST_LESS(X,Y) ((X)->cost < (Y)	\
      67  			     || ((X)->cost == (Y) && (X)->latency < (Y)))
      68  
      69  /* This macro is used to compare two pointers to mult_costs against
      70     each other.  The macro returns true if X is cheaper than Y.
      71     Currently, the cheaper of two mult_costs is the one with the
      72     lower "cost".  If "cost"s are tied, the lower latency is cheaper.  */
      73  #define CHEAPER_MULT_COST(X,Y)  ((X)->cost < (Y)->cost		\
      74  				 || ((X)->cost == (Y)->cost	\
      75  				     && (X)->latency < (Y)->latency))
      76  
      77  /* This structure records a sequence of operations.
      78     `ops' is the number of operations recorded.
      79     `cost' is their total cost.
      80     The operations are stored in `op' and the corresponding
      81     logarithms of the integer coefficients in `log'.
      82  
      83     These are the operations:
      84     alg_zero		total := 0;
      85     alg_m		total := multiplicand;
      86     alg_shift		total := total * coeff
      87     alg_add_t_m2		total := total + multiplicand * coeff;
      88     alg_sub_t_m2		total := total - multiplicand * coeff;
      89     alg_add_factor	total := total * coeff + total;
      90     alg_sub_factor	total := total * coeff - total;
      91     alg_add_t2_m		total := total * coeff + multiplicand;
      92     alg_sub_t2_m		total := total * coeff - multiplicand;
      93  
      94     The first operand must be either alg_zero or alg_m.  */
      95  
      96  struct algorithm
      97  {
      98    struct mult_cost cost;
      99    short ops;
     100    /* The size of the OP and LOG fields are not directly related to the
     101       word size, but the worst-case algorithms will be if we have few
     102       consecutive ones or zeros, i.e., a multiplicand like 10101010101...
     103       In that case we will generate shift-by-2, add, shift-by-2, add,...,
     104       in total wordsize operations.  */
     105    enum alg_code op[MAX_BITS_PER_WORD];
     106    char log[MAX_BITS_PER_WORD];
     107  };
     108  
     109  /* The entry for our multiplication cache/hash table.  */
     110  struct alg_hash_entry {
     111    /* The number we are multiplying by.  */
     112    unsigned HOST_WIDE_INT t;
     113  
     114    /* The mode in which we are multiplying something by T.  */
     115    machine_mode mode;
     116  
     117    /* The best multiplication algorithm for t.  */
     118    enum alg_code alg;
     119  
     120    /* The cost of multiplication if ALG_CODE is not alg_impossible.
     121       Otherwise, the cost within which multiplication by T is
     122       impossible.  */
     123    struct mult_cost cost;
     124  
     125    /* Optimized for speed? */
     126    bool speed;
     127  };
     128  
     129  /* The number of cache/hash entries.  */
     130  #if HOST_BITS_PER_WIDE_INT == 64
     131  #define NUM_ALG_HASH_ENTRIES 1031
     132  #else
     133  #define NUM_ALG_HASH_ENTRIES 307
     134  #endif
     135  
     136  #define NUM_MODE_IP_INT (NUM_MODE_INT + NUM_MODE_PARTIAL_INT)
     137  #define NUM_MODE_IPV_INT (NUM_MODE_IP_INT + NUM_MODE_VECTOR_INT)
     138  
     139  struct expmed_op_cheap {
     140    bool cheap[2][NUM_MODE_IPV_INT];
     141  };
     142  
     143  struct expmed_op_costs {
     144    int cost[2][NUM_MODE_IPV_INT];
     145  };
     146  
     147  /* Target-dependent globals.  */
     148  struct target_expmed {
     149    /* Each entry of ALG_HASH caches alg_code for some integer.  This is
     150       actually a hash table.  If we have a collision, that the older
     151       entry is kicked out.  */
     152    struct alg_hash_entry x_alg_hash[NUM_ALG_HASH_ENTRIES];
     153  
     154    /* True if x_alg_hash might already have been used.  */
     155    bool x_alg_hash_used_p;
     156  
     157    /* Nonzero means divides or modulus operations are relatively cheap for
     158       powers of two, so don't use branches; emit the operation instead.
     159       Usually, this will mean that the MD file will emit non-branch
     160       sequences.  */
     161    struct expmed_op_cheap x_sdiv_pow2_cheap;
     162    struct expmed_op_cheap x_smod_pow2_cheap;
     163  
     164    /* Cost of various pieces of RTL.  Note that some of these are indexed by
     165       shift count and some by mode.  */
     166    int x_zero_cost[2];
     167    struct expmed_op_costs x_add_cost;
     168    struct expmed_op_costs x_neg_cost;
     169    struct expmed_op_costs x_shift_cost[MAX_BITS_PER_WORD];
     170    struct expmed_op_costs x_shiftadd_cost[MAX_BITS_PER_WORD];
     171    struct expmed_op_costs x_shiftsub0_cost[MAX_BITS_PER_WORD];
     172    struct expmed_op_costs x_shiftsub1_cost[MAX_BITS_PER_WORD];
     173    struct expmed_op_costs x_mul_cost;
     174    struct expmed_op_costs x_sdiv_cost;
     175    struct expmed_op_costs x_udiv_cost;
     176    int x_mul_widen_cost[2][NUM_MODE_INT];
     177    int x_mul_highpart_cost[2][NUM_MODE_INT];
     178  
     179    /* Conversion costs are only defined between two scalar integer modes
     180       of different sizes.  The first machine mode is the destination mode,
     181       and the second is the source mode.  */
     182    int x_convert_cost[2][NUM_MODE_IP_INT][NUM_MODE_IP_INT];
     183  };
     184  
     185  extern struct target_expmed default_target_expmed;
     186  #if SWITCHABLE_TARGET
     187  extern struct target_expmed *this_target_expmed;
     188  #else
     189  #define this_target_expmed (&default_target_expmed)
     190  #endif
     191  
     192  /* Return a pointer to the alg_hash_entry at IDX.  */
     193  
     194  inline struct alg_hash_entry *
     195  alg_hash_entry_ptr (int idx)
     196  {
     197    return &this_target_expmed->x_alg_hash[idx];
     198  }
     199  
     200  /* Return true if the x_alg_hash field might have been used.  */
     201  
     202  inline bool
     203  alg_hash_used_p (void)
     204  {
     205    return this_target_expmed->x_alg_hash_used_p;
     206  }
     207  
     208  /* Set whether the x_alg_hash field might have been used.  */
     209  
     210  inline void
     211  set_alg_hash_used_p (bool usedp)
     212  {
     213    this_target_expmed->x_alg_hash_used_p = usedp;
     214  }
     215  
     216  /* Compute an index into the cost arrays by mode class.  */
     217  
     218  inline int
     219  expmed_mode_index (machine_mode mode)
     220  {
     221    switch (GET_MODE_CLASS (mode))
     222      {
     223      case MODE_INT:
     224        return mode - MIN_MODE_INT;
     225      case MODE_PARTIAL_INT:
     226        /* If there are no partial integer modes, help the compiler
     227  	 to figure out this will never happen.  See PR59934.  */
     228        if (MIN_MODE_PARTIAL_INT != VOIDmode)
     229  	return mode - MIN_MODE_PARTIAL_INT + NUM_MODE_INT;
     230        break;
     231      case MODE_VECTOR_INT:
     232        /* If there are no vector integer modes, help the compiler
     233  	 to figure out this will never happen.  See PR59934.  */
     234        if (MIN_MODE_VECTOR_INT != VOIDmode)
     235  	return mode - MIN_MODE_VECTOR_INT + NUM_MODE_IP_INT;
     236        break;
     237      default:
     238        break;
     239      }
     240    gcc_unreachable ();
     241  }
     242  
     243  /* Return a pointer to a boolean contained in EOC indicating whether
     244     a particular operation performed in MODE is cheap when optimizing
     245     for SPEED.  */
     246  
     247  inline bool *
     248  expmed_op_cheap_ptr (struct expmed_op_cheap *eoc, bool speed,
     249  		     machine_mode mode)
     250  {
     251    int idx = expmed_mode_index (mode);
     252    return &eoc->cheap[speed][idx];
     253  }
     254  
     255  /* Return a pointer to a cost contained in COSTS when a particular
     256     operation is performed in MODE when optimizing for SPEED.  */
     257  
     258  inline int *
     259  expmed_op_cost_ptr (struct expmed_op_costs *costs, bool speed,
     260  		    machine_mode mode)
     261  {
     262    int idx = expmed_mode_index (mode);
     263    return &costs->cost[speed][idx];
     264  }
     265  
     266  /* Subroutine of {set_,}sdiv_pow2_cheap.  Not to be used otherwise.  */
     267  
     268  inline bool *
     269  sdiv_pow2_cheap_ptr (bool speed, machine_mode mode)
     270  {
     271    return expmed_op_cheap_ptr (&this_target_expmed->x_sdiv_pow2_cheap,
     272  			      speed, mode);
     273  }
     274  
     275  /* Set whether a signed division by a power of 2 is cheap in MODE
     276     when optimizing for SPEED.  */
     277  
     278  inline void
     279  set_sdiv_pow2_cheap (bool speed, machine_mode mode, bool cheap_p)
     280  {
     281    *sdiv_pow2_cheap_ptr (speed, mode) = cheap_p;
     282  }
     283  
     284  /* Return whether a signed division by a power of 2 is cheap in MODE
     285     when optimizing for SPEED.  */
     286  
     287  inline bool
     288  sdiv_pow2_cheap (bool speed, machine_mode mode)
     289  {
     290    return *sdiv_pow2_cheap_ptr (speed, mode);
     291  }
     292  
     293  /* Subroutine of {set_,}smod_pow2_cheap.  Not to be used otherwise.  */
     294  
     295  inline bool *
     296  smod_pow2_cheap_ptr (bool speed, machine_mode mode)
     297  {
     298    return expmed_op_cheap_ptr (&this_target_expmed->x_smod_pow2_cheap,
     299  			      speed, mode);
     300  }
     301  
     302  /* Set whether a signed modulo by a power of 2 is CHEAP in MODE when
     303     optimizing for SPEED.  */
     304  
     305  inline void
     306  set_smod_pow2_cheap (bool speed, machine_mode mode, bool cheap)
     307  {
     308    *smod_pow2_cheap_ptr (speed, mode) = cheap;
     309  }
     310  
     311  /* Return whether a signed modulo by a power of 2 is cheap in MODE
     312     when optimizing for SPEED.  */
     313  
     314  inline bool
     315  smod_pow2_cheap (bool speed, machine_mode mode)
     316  {
     317    return *smod_pow2_cheap_ptr (speed, mode);
     318  }
     319  
     320  /* Subroutine of {set_,}zero_cost.  Not to be used otherwise.  */
     321  
     322  inline int *
     323  zero_cost_ptr (bool speed)
     324  {
     325    return &this_target_expmed->x_zero_cost[speed];
     326  }
     327  
     328  /* Set the COST of loading zero when optimizing for SPEED.  */
     329  
     330  inline void
     331  set_zero_cost (bool speed, int cost)
     332  {
     333    *zero_cost_ptr (speed) = cost;
     334  }
     335  
     336  /* Return the COST of loading zero when optimizing for SPEED.  */
     337  
     338  inline int
     339  zero_cost (bool speed)
     340  {
     341    return *zero_cost_ptr (speed);
     342  }
     343  
     344  /* Subroutine of {set_,}add_cost.  Not to be used otherwise.  */
     345  
     346  inline int *
     347  add_cost_ptr (bool speed, machine_mode mode)
     348  {
     349    return expmed_op_cost_ptr (&this_target_expmed->x_add_cost, speed, mode);
     350  }
     351  
     352  /* Set the COST of computing an add in MODE when optimizing for SPEED.  */
     353  
     354  inline void
     355  set_add_cost (bool speed, machine_mode mode, int cost)
     356  {
     357    *add_cost_ptr (speed, mode) = cost;
     358  }
     359  
     360  /* Return the cost of computing an add in MODE when optimizing for SPEED.  */
     361  
     362  inline int
     363  add_cost (bool speed, machine_mode mode)
     364  {
     365    return *add_cost_ptr (speed, mode);
     366  }
     367  
     368  /* Subroutine of {set_,}neg_cost.  Not to be used otherwise.  */
     369  
     370  inline int *
     371  neg_cost_ptr (bool speed, machine_mode mode)
     372  {
     373    return expmed_op_cost_ptr (&this_target_expmed->x_neg_cost, speed, mode);
     374  }
     375  
     376  /* Set the COST of computing a negation in MODE when optimizing for SPEED.  */
     377  
     378  inline void
     379  set_neg_cost (bool speed, machine_mode mode, int cost)
     380  {
     381    *neg_cost_ptr (speed, mode) = cost;
     382  }
     383  
     384  /* Return the cost of computing a negation in MODE when optimizing for
     385     SPEED.  */
     386  
     387  inline int
     388  neg_cost (bool speed, machine_mode mode)
     389  {
     390    return *neg_cost_ptr (speed, mode);
     391  }
     392  
     393  /* Subroutine of {set_,}shift_cost.  Not to be used otherwise.  */
     394  
     395  inline int *
     396  shift_cost_ptr (bool speed, machine_mode mode, int bits)
     397  {
     398    return expmed_op_cost_ptr (&this_target_expmed->x_shift_cost[bits],
     399  			     speed, mode);
     400  }
     401  
     402  /* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED.  */
     403  
     404  inline void
     405  set_shift_cost (bool speed, machine_mode mode, int bits, int cost)
     406  {
     407    *shift_cost_ptr (speed, mode, bits) = cost;
     408  }
     409  
     410  /* Return the cost of doing a shift in MODE by BITS when optimizing for
     411     SPEED.  */
     412  
     413  inline int
     414  shift_cost (bool speed, machine_mode mode, int bits)
     415  {
     416    return *shift_cost_ptr (speed, mode, bits);
     417  }
     418  
     419  /* Subroutine of {set_,}shiftadd_cost.  Not to be used otherwise.  */
     420  
     421  inline int *
     422  shiftadd_cost_ptr (bool speed, machine_mode mode, int bits)
     423  {
     424    return expmed_op_cost_ptr (&this_target_expmed->x_shiftadd_cost[bits],
     425  			     speed, mode);
     426  }
     427  
     428  /* Set the COST of doing a shift in MODE by BITS followed by an add when
     429     optimizing for SPEED.  */
     430  
     431  inline void
     432  set_shiftadd_cost (bool speed, machine_mode mode, int bits, int cost)
     433  {
     434    *shiftadd_cost_ptr (speed, mode, bits) = cost;
     435  }
     436  
     437  /* Return the cost of doing a shift in MODE by BITS followed by an add
     438     when optimizing for SPEED.  */
     439  
     440  inline int
     441  shiftadd_cost (bool speed, machine_mode mode, int bits)
     442  {
     443    return *shiftadd_cost_ptr (speed, mode, bits);
     444  }
     445  
     446  /* Subroutine of {set_,}shiftsub0_cost.  Not to be used otherwise.  */
     447  
     448  inline int *
     449  shiftsub0_cost_ptr (bool speed, machine_mode mode, int bits)
     450  {
     451    return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub0_cost[bits],
     452  			     speed, mode);
     453  }
     454  
     455  /* Set the COST of doing a shift in MODE by BITS and then subtracting a
     456     value when optimizing for SPEED.  */
     457  
     458  inline void
     459  set_shiftsub0_cost (bool speed, machine_mode mode, int bits, int cost)
     460  {
     461    *shiftsub0_cost_ptr (speed, mode, bits) = cost;
     462  }
     463  
     464  /* Return the cost of doing a shift in MODE by BITS and then subtracting
     465     a value when optimizing for SPEED.  */
     466  
     467  inline int
     468  shiftsub0_cost (bool speed, machine_mode mode, int bits)
     469  {
     470    return *shiftsub0_cost_ptr (speed, mode, bits);
     471  }
     472  
     473  /* Subroutine of {set_,}shiftsub1_cost.  Not to be used otherwise.  */
     474  
     475  inline int *
     476  shiftsub1_cost_ptr (bool speed, machine_mode mode, int bits)
     477  {
     478    return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub1_cost[bits],
     479  			     speed, mode);
     480  }
     481  
     482  /* Set the COST of subtracting a shift in MODE by BITS from a value when
     483     optimizing for SPEED.  */
     484  
     485  inline void
     486  set_shiftsub1_cost (bool speed, machine_mode mode, int bits, int cost)
     487  {
     488    *shiftsub1_cost_ptr (speed, mode, bits) = cost;
     489  }
     490  
     491  /* Return the cost of subtracting a shift in MODE by BITS from a value
     492     when optimizing for SPEED.  */
     493  
     494  inline int
     495  shiftsub1_cost (bool speed, machine_mode mode, int bits)
     496  {
     497    return *shiftsub1_cost_ptr (speed, mode, bits);
     498  }
     499  
     500  /* Subroutine of {set_,}mul_cost.  Not to be used otherwise.  */
     501  
     502  inline int *
     503  mul_cost_ptr (bool speed, machine_mode mode)
     504  {
     505    return expmed_op_cost_ptr (&this_target_expmed->x_mul_cost, speed, mode);
     506  }
     507  
     508  /* Set the COST of doing a multiplication in MODE when optimizing for
     509     SPEED.  */
     510  
     511  inline void
     512  set_mul_cost (bool speed, machine_mode mode, int cost)
     513  {
     514    *mul_cost_ptr (speed, mode) = cost;
     515  }
     516  
     517  /* Return the cost of doing a multiplication in MODE when optimizing
     518     for SPEED.  */
     519  
     520  inline int
     521  mul_cost (bool speed, machine_mode mode)
     522  {
     523    return *mul_cost_ptr (speed, mode);
     524  }
     525  
     526  /* Subroutine of {set_,}sdiv_cost.  Not to be used otherwise.  */
     527  
     528  inline int *
     529  sdiv_cost_ptr (bool speed, machine_mode mode)
     530  {
     531    return expmed_op_cost_ptr (&this_target_expmed->x_sdiv_cost, speed, mode);
     532  }
     533  
     534  /* Set the COST of doing a signed division in MODE when optimizing
     535     for SPEED.  */
     536  
     537  inline void
     538  set_sdiv_cost (bool speed, machine_mode mode, int cost)
     539  {
     540    *sdiv_cost_ptr (speed, mode) = cost;
     541  }
     542  
     543  /* Return the cost of doing a signed division in MODE when optimizing
     544     for SPEED.  */
     545  
     546  inline int
     547  sdiv_cost (bool speed, machine_mode mode)
     548  {
     549    return *sdiv_cost_ptr (speed, mode);
     550  }
     551  
     552  /* Subroutine of {set_,}udiv_cost.  Not to be used otherwise.  */
     553  
     554  inline int *
     555  udiv_cost_ptr (bool speed, machine_mode mode)
     556  {
     557    return expmed_op_cost_ptr (&this_target_expmed->x_udiv_cost, speed, mode);
     558  }
     559  
     560  /* Set the COST of doing an unsigned division in MODE when optimizing
     561     for SPEED.  */
     562  
     563  inline void
     564  set_udiv_cost (bool speed, machine_mode mode, int cost)
     565  {
     566    *udiv_cost_ptr (speed, mode) = cost;
     567  }
     568  
     569  /* Return the cost of doing an unsigned division in MODE when
     570     optimizing for SPEED.  */
     571  
     572  inline int
     573  udiv_cost (bool speed, machine_mode mode)
     574  {
     575    return *udiv_cost_ptr (speed, mode);
     576  }
     577  
     578  /* Subroutine of {set_,}mul_widen_cost.  Not to be used otherwise.  */
     579  
     580  inline int *
     581  mul_widen_cost_ptr (bool speed, machine_mode mode)
     582  {
     583    gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
     584  
     585    return &this_target_expmed->x_mul_widen_cost[speed][mode - MIN_MODE_INT];
     586  }
     587  
     588  /* Set the COST for computing a widening multiplication in MODE when
     589     optimizing for SPEED.  */
     590  
     591  inline void
     592  set_mul_widen_cost (bool speed, machine_mode mode, int cost)
     593  {
     594    *mul_widen_cost_ptr (speed, mode) = cost;
     595  }
     596  
     597  /* Return the cost for computing a widening multiplication in MODE when
     598     optimizing for SPEED.  */
     599  
     600  inline int
     601  mul_widen_cost (bool speed, machine_mode mode)
     602  {
     603    return *mul_widen_cost_ptr (speed, mode);
     604  }
     605  
     606  /* Subroutine of {set_,}mul_highpart_cost.  Not to be used otherwise.  */
     607  
     608  inline int *
     609  mul_highpart_cost_ptr (bool speed, machine_mode mode)
     610  {
     611    gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
     612    int m = mode - MIN_MODE_INT;
     613    gcc_assert (m < NUM_MODE_INT);
     614  
     615    return &this_target_expmed->x_mul_highpart_cost[speed][m];
     616  }
     617  
     618  /* Set the COST for computing the high part of a multiplication in MODE
     619     when optimizing for SPEED.  */
     620  
     621  inline void
     622  set_mul_highpart_cost (bool speed, machine_mode mode, int cost)
     623  {
     624    *mul_highpart_cost_ptr (speed, mode) = cost;
     625  }
     626  
     627  /* Return the cost for computing the high part of a multiplication in MODE
     628     when optimizing for SPEED.  */
     629  
     630  inline int
     631  mul_highpart_cost (bool speed, machine_mode mode)
     632  {
     633    return *mul_highpart_cost_ptr (speed, mode);
     634  }
     635  
     636  /* Subroutine of {set_,}convert_cost.  Not to be used otherwise.  */
     637  
     638  inline int *
     639  convert_cost_ptr (machine_mode to_mode, machine_mode from_mode,
     640  		  bool speed)
     641  {
     642    int to_idx = expmed_mode_index (to_mode);
     643    int from_idx = expmed_mode_index (from_mode);
     644  
     645    gcc_assert (IN_RANGE (to_idx, 0, NUM_MODE_IP_INT - 1));
     646    gcc_assert (IN_RANGE (from_idx, 0, NUM_MODE_IP_INT - 1));
     647  
     648    return &this_target_expmed->x_convert_cost[speed][to_idx][from_idx];
     649  }
     650  
     651  /* Set the COST for converting from FROM_MODE to TO_MODE when optimizing
     652     for SPEED.  */
     653  
     654  inline void
     655  set_convert_cost (machine_mode to_mode, machine_mode from_mode,
     656  		  bool speed, int cost)
     657  {
     658    *convert_cost_ptr (to_mode, from_mode, speed) = cost;
     659  }
     660  
     661  /* Return the cost for converting from FROM_MODE to TO_MODE when optimizing
     662     for SPEED.  */
     663  
     664  inline int
     665  convert_cost (machine_mode to_mode, machine_mode from_mode,
     666  	      bool speed)
     667  {
     668    return *convert_cost_ptr (to_mode, from_mode, speed);
     669  }
     670  
     671  extern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool);
     672  extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
     673  			machine_mode mode, machine_mode compare_mode,
     674  			int unsignedp, rtx x, rtx y, int normalizep,
     675  			machine_mode target_mode);
     676  
     677  /* Arguments MODE, RTX: return an rtx for the negation of that value.
     678     May emit insns.  */
     679  extern rtx negate_rtx (machine_mode, rtx);
     680  
     681  /* Arguments MODE, RTX: return an rtx for the flipping of that value.
     682     May emit insns.  */
     683  extern rtx flip_storage_order (machine_mode, rtx);
     684  
     685  /* Expand a logical AND operation.  */
     686  extern rtx expand_and (machine_mode, rtx, rtx, rtx);
     687  
     688  /* Emit a store-flag operation.  */
     689  extern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, machine_mode,
     690  			    int, int);
     691  
     692  /* Like emit_store_flag, but always succeeds.  */
     693  extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx,
     694  				  machine_mode, int, int);
     695  
     696  extern void canonicalize_comparison (machine_mode, enum rtx_code *, rtx *);
     697  
     698  /* Choose a minimal N + 1 bit approximation to 1/D that can be used to
     699     replace division by D, and put the least significant N bits of the result
     700     in *MULTIPLIER_PTR and return the most significant bit.  */
     701  extern unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int,
     702  						 int, unsigned HOST_WIDE_INT *,
     703  						 int *, int *);
     704  
     705  #ifdef TREE_CODE
     706  extern rtx expand_variable_shift (enum tree_code, machine_mode,
     707  				  rtx, tree, rtx, int);
     708  extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
     709  			 int);
     710  extern rtx maybe_expand_shift (enum tree_code, machine_mode, rtx, int, rtx,
     711  			       int);
     712  #ifdef GCC_OPTABS_H
     713  extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
     714  			  rtx, int, enum optab_methods = OPTAB_LIB_WIDEN);
     715  #endif
     716  #endif
     717  
     718  extern void store_bit_field (rtx, poly_uint64, poly_uint64,
     719  			     poly_uint64, poly_uint64,
     720  			     machine_mode, rtx, bool, bool);
     721  extern rtx extract_bit_field (rtx, poly_uint64, poly_uint64, int, rtx,
     722  			      machine_mode, machine_mode, bool, rtx *);
     723  extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
     724  extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int, bool = false);
     725  extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx,
     726  					rtx, int);
     727  
     728  #endif  // EXPMED_H