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