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