]>
Commit | Line | Data |
---|---|---|
e53b6e56 | 1 | /* Target-dependent costs for expmed.cc. |
a945c346 | 2 | Copyright (C) 1987-2024 Free Software Foundation, Inc. |
462f85ce RS |
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 | |
ee7d63ab | 8 | Software Foundation; either version 3, or (at your option) any later |
462f85ce RS |
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 | ||
2d52a3a1 ZC |
23 | #include "insn-codes.h" |
24 | ||
c371bb73 RS |
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 | ||
ec573d17 KT |
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 | ||
c371bb73 RS |
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. */ | |
ef4bddc2 | 115 | machine_mode mode; |
c371bb73 RS |
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 | ||
91f8035e RH |
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) | |
2a261cd3 NF |
138 | |
139 | struct expmed_op_cheap { | |
91f8035e | 140 | bool cheap[2][NUM_MODE_IPV_INT]; |
2a261cd3 NF |
141 | }; |
142 | ||
143 | struct expmed_op_costs { | |
91f8035e | 144 | int cost[2][NUM_MODE_IPV_INT]; |
2a261cd3 | 145 | }; |
6dd8f4bb | 146 | |
462f85ce RS |
147 | /* Target-dependent globals. */ |
148 | struct target_expmed { | |
c371bb73 RS |
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 | ||
462f85ce RS |
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. */ | |
2a261cd3 NF |
161 | struct expmed_op_cheap x_sdiv_pow2_cheap; |
162 | struct expmed_op_cheap x_smod_pow2_cheap; | |
462f85ce | 163 | |
1fe9bef9 | 164 | /* Cost of various pieces of RTL. */ |
462f85ce | 165 | int x_zero_cost[2]; |
2a261cd3 NF |
166 | struct expmed_op_costs x_add_cost; |
167 | struct expmed_op_costs x_neg_cost; | |
1fe9bef9 VG |
168 | int x_shift_cost[2][NUM_MODE_IPV_INT][MAX_BITS_PER_WORD]; |
169 | int x_shiftadd_cost[2][NUM_MODE_IPV_INT][MAX_BITS_PER_WORD]; | |
170 | int x_shiftsub0_cost[2][NUM_MODE_IPV_INT][MAX_BITS_PER_WORD]; | |
171 | int x_shiftsub1_cost[2][NUM_MODE_IPV_INT][MAX_BITS_PER_WORD]; | |
2a261cd3 NF |
172 | struct expmed_op_costs x_mul_cost; |
173 | struct expmed_op_costs x_sdiv_cost; | |
174 | struct expmed_op_costs x_udiv_cost; | |
175 | int x_mul_widen_cost[2][NUM_MODE_INT]; | |
176 | int x_mul_highpart_cost[2][NUM_MODE_INT]; | |
6dd8f4bb BS |
177 | |
178 | /* Conversion costs are only defined between two scalar integer modes | |
179 | of different sizes. The first machine mode is the destination mode, | |
180 | and the second is the source mode. */ | |
91f8035e | 181 | int x_convert_cost[2][NUM_MODE_IP_INT][NUM_MODE_IP_INT]; |
462f85ce RS |
182 | }; |
183 | ||
184 | extern struct target_expmed default_target_expmed; | |
185 | #if SWITCHABLE_TARGET | |
186 | extern struct target_expmed *this_target_expmed; | |
187 | #else | |
188 | #define this_target_expmed (&default_target_expmed) | |
189 | #endif | |
190 | ||
5322d07e | 191 | /* Return a pointer to the alg_hash_entry at IDX. */ |
462f85ce | 192 | |
cb3e0eac | 193 | inline struct alg_hash_entry * |
5322d07e NF |
194 | alg_hash_entry_ptr (int idx) |
195 | { | |
196 | return &this_target_expmed->x_alg_hash[idx]; | |
197 | } | |
198 | ||
199 | /* Return true if the x_alg_hash field might have been used. */ | |
200 | ||
cb3e0eac | 201 | inline bool |
5322d07e NF |
202 | alg_hash_used_p (void) |
203 | { | |
204 | return this_target_expmed->x_alg_hash_used_p; | |
205 | } | |
206 | ||
207 | /* Set whether the x_alg_hash field might have been used. */ | |
208 | ||
cb3e0eac | 209 | inline void |
5322d07e NF |
210 | set_alg_hash_used_p (bool usedp) |
211 | { | |
212 | this_target_expmed->x_alg_hash_used_p = usedp; | |
213 | } | |
214 | ||
91f8035e RH |
215 | /* Compute an index into the cost arrays by mode class. */ |
216 | ||
cb3e0eac | 217 | inline int |
ef4bddc2 | 218 | expmed_mode_index (machine_mode mode) |
91f8035e RH |
219 | { |
220 | switch (GET_MODE_CLASS (mode)) | |
221 | { | |
222 | case MODE_INT: | |
223 | return mode - MIN_MODE_INT; | |
224 | case MODE_PARTIAL_INT: | |
904e5ccd JJ |
225 | /* If there are no partial integer modes, help the compiler |
226 | to figure out this will never happen. See PR59934. */ | |
227 | if (MIN_MODE_PARTIAL_INT != VOIDmode) | |
228 | return mode - MIN_MODE_PARTIAL_INT + NUM_MODE_INT; | |
229 | break; | |
91f8035e | 230 | case MODE_VECTOR_INT: |
904e5ccd JJ |
231 | /* If there are no vector integer modes, help the compiler |
232 | to figure out this will never happen. See PR59934. */ | |
233 | if (MIN_MODE_VECTOR_INT != VOIDmode) | |
234 | return mode - MIN_MODE_VECTOR_INT + NUM_MODE_IP_INT; | |
235 | break; | |
91f8035e | 236 | default: |
904e5ccd | 237 | break; |
91f8035e | 238 | } |
904e5ccd | 239 | gcc_unreachable (); |
91f8035e RH |
240 | } |
241 | ||
2a261cd3 NF |
242 | /* Return a pointer to a boolean contained in EOC indicating whether |
243 | a particular operation performed in MODE is cheap when optimizing | |
244 | for SPEED. */ | |
245 | ||
cb3e0eac | 246 | inline bool * |
2a261cd3 | 247 | expmed_op_cheap_ptr (struct expmed_op_cheap *eoc, bool speed, |
ef4bddc2 | 248 | machine_mode mode) |
2a261cd3 | 249 | { |
91f8035e RH |
250 | int idx = expmed_mode_index (mode); |
251 | return &eoc->cheap[speed][idx]; | |
2a261cd3 NF |
252 | } |
253 | ||
254 | /* Return a pointer to a cost contained in COSTS when a particular | |
255 | operation is performed in MODE when optimizing for SPEED. */ | |
256 | ||
cb3e0eac | 257 | inline int * |
2a261cd3 | 258 | expmed_op_cost_ptr (struct expmed_op_costs *costs, bool speed, |
ef4bddc2 | 259 | machine_mode mode) |
2a261cd3 | 260 | { |
91f8035e RH |
261 | int idx = expmed_mode_index (mode); |
262 | return &costs->cost[speed][idx]; | |
2a261cd3 NF |
263 | } |
264 | ||
5322d07e NF |
265 | /* Subroutine of {set_,}sdiv_pow2_cheap. Not to be used otherwise. */ |
266 | ||
cb3e0eac | 267 | inline bool * |
ef4bddc2 | 268 | sdiv_pow2_cheap_ptr (bool speed, machine_mode mode) |
5322d07e | 269 | { |
2a261cd3 NF |
270 | return expmed_op_cheap_ptr (&this_target_expmed->x_sdiv_pow2_cheap, |
271 | speed, mode); | |
5322d07e NF |
272 | } |
273 | ||
274 | /* Set whether a signed division by a power of 2 is cheap in MODE | |
275 | when optimizing for SPEED. */ | |
276 | ||
cb3e0eac | 277 | inline void |
ef4bddc2 | 278 | set_sdiv_pow2_cheap (bool speed, machine_mode mode, bool cheap_p) |
5322d07e NF |
279 | { |
280 | *sdiv_pow2_cheap_ptr (speed, mode) = cheap_p; | |
281 | } | |
282 | ||
283 | /* Return whether a signed division by a power of 2 is cheap in MODE | |
284 | when optimizing for SPEED. */ | |
285 | ||
cb3e0eac | 286 | inline bool |
ef4bddc2 | 287 | sdiv_pow2_cheap (bool speed, machine_mode mode) |
5322d07e NF |
288 | { |
289 | return *sdiv_pow2_cheap_ptr (speed, mode); | |
290 | } | |
291 | ||
292 | /* Subroutine of {set_,}smod_pow2_cheap. Not to be used otherwise. */ | |
293 | ||
cb3e0eac | 294 | inline bool * |
ef4bddc2 | 295 | smod_pow2_cheap_ptr (bool speed, machine_mode mode) |
5322d07e | 296 | { |
2a261cd3 NF |
297 | return expmed_op_cheap_ptr (&this_target_expmed->x_smod_pow2_cheap, |
298 | speed, mode); | |
5322d07e NF |
299 | } |
300 | ||
301 | /* Set whether a signed modulo by a power of 2 is CHEAP in MODE when | |
302 | optimizing for SPEED. */ | |
303 | ||
cb3e0eac | 304 | inline void |
ef4bddc2 | 305 | set_smod_pow2_cheap (bool speed, machine_mode mode, bool cheap) |
5322d07e NF |
306 | { |
307 | *smod_pow2_cheap_ptr (speed, mode) = cheap; | |
308 | } | |
309 | ||
310 | /* Return whether a signed modulo by a power of 2 is cheap in MODE | |
311 | when optimizing for SPEED. */ | |
312 | ||
cb3e0eac | 313 | inline bool |
ef4bddc2 | 314 | smod_pow2_cheap (bool speed, machine_mode mode) |
5322d07e NF |
315 | { |
316 | return *smod_pow2_cheap_ptr (speed, mode); | |
317 | } | |
318 | ||
319 | /* Subroutine of {set_,}zero_cost. Not to be used otherwise. */ | |
320 | ||
cb3e0eac | 321 | inline int * |
5322d07e NF |
322 | zero_cost_ptr (bool speed) |
323 | { | |
324 | return &this_target_expmed->x_zero_cost[speed]; | |
325 | } | |
326 | ||
327 | /* Set the COST of loading zero when optimizing for SPEED. */ | |
328 | ||
cb3e0eac | 329 | inline void |
5322d07e NF |
330 | set_zero_cost (bool speed, int cost) |
331 | { | |
332 | *zero_cost_ptr (speed) = cost; | |
333 | } | |
334 | ||
335 | /* Return the COST of loading zero when optimizing for SPEED. */ | |
336 | ||
cb3e0eac | 337 | inline int |
5322d07e NF |
338 | zero_cost (bool speed) |
339 | { | |
340 | return *zero_cost_ptr (speed); | |
341 | } | |
342 | ||
343 | /* Subroutine of {set_,}add_cost. Not to be used otherwise. */ | |
344 | ||
cb3e0eac | 345 | inline int * |
ef4bddc2 | 346 | add_cost_ptr (bool speed, machine_mode mode) |
5322d07e | 347 | { |
2a261cd3 | 348 | return expmed_op_cost_ptr (&this_target_expmed->x_add_cost, speed, mode); |
5322d07e NF |
349 | } |
350 | ||
351 | /* Set the COST of computing an add in MODE when optimizing for SPEED. */ | |
352 | ||
cb3e0eac | 353 | inline void |
ef4bddc2 | 354 | set_add_cost (bool speed, machine_mode mode, int cost) |
5322d07e NF |
355 | { |
356 | *add_cost_ptr (speed, mode) = cost; | |
357 | } | |
358 | ||
359 | /* Return the cost of computing an add in MODE when optimizing for SPEED. */ | |
360 | ||
cb3e0eac | 361 | inline int |
ef4bddc2 | 362 | add_cost (bool speed, machine_mode mode) |
5322d07e NF |
363 | { |
364 | return *add_cost_ptr (speed, mode); | |
365 | } | |
366 | ||
367 | /* Subroutine of {set_,}neg_cost. Not to be used otherwise. */ | |
368 | ||
cb3e0eac | 369 | inline int * |
ef4bddc2 | 370 | neg_cost_ptr (bool speed, machine_mode mode) |
5322d07e | 371 | { |
2a261cd3 | 372 | return expmed_op_cost_ptr (&this_target_expmed->x_neg_cost, speed, mode); |
5322d07e NF |
373 | } |
374 | ||
375 | /* Set the COST of computing a negation in MODE when optimizing for SPEED. */ | |
376 | ||
cb3e0eac | 377 | inline void |
ef4bddc2 | 378 | set_neg_cost (bool speed, machine_mode mode, int cost) |
5322d07e NF |
379 | { |
380 | *neg_cost_ptr (speed, mode) = cost; | |
381 | } | |
382 | ||
383 | /* Return the cost of computing a negation in MODE when optimizing for | |
384 | SPEED. */ | |
385 | ||
cb3e0eac | 386 | inline int |
ef4bddc2 | 387 | neg_cost (bool speed, machine_mode mode) |
5322d07e NF |
388 | { |
389 | return *neg_cost_ptr (speed, mode); | |
390 | } | |
391 | ||
392 | /* Subroutine of {set_,}shift_cost. Not to be used otherwise. */ | |
393 | ||
cb3e0eac | 394 | inline int * |
ef4bddc2 | 395 | shift_cost_ptr (bool speed, machine_mode mode, int bits) |
5322d07e | 396 | { |
1fe9bef9 VG |
397 | int midx = expmed_mode_index (mode); |
398 | return &this_target_expmed->x_shift_cost[speed][midx][bits]; | |
5322d07e NF |
399 | } |
400 | ||
401 | /* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED. */ | |
402 | ||
cb3e0eac | 403 | inline void |
ef4bddc2 | 404 | set_shift_cost (bool speed, machine_mode mode, int bits, int cost) |
5322d07e NF |
405 | { |
406 | *shift_cost_ptr (speed, mode, bits) = cost; | |
407 | } | |
408 | ||
409 | /* Return the cost of doing a shift in MODE by BITS when optimizing for | |
410 | SPEED. */ | |
411 | ||
cb3e0eac | 412 | inline int |
ef4bddc2 | 413 | shift_cost (bool speed, machine_mode mode, int bits) |
5322d07e NF |
414 | { |
415 | return *shift_cost_ptr (speed, mode, bits); | |
416 | } | |
417 | ||
418 | /* Subroutine of {set_,}shiftadd_cost. Not to be used otherwise. */ | |
419 | ||
cb3e0eac | 420 | inline int * |
ef4bddc2 | 421 | shiftadd_cost_ptr (bool speed, machine_mode mode, int bits) |
5322d07e | 422 | { |
1fe9bef9 VG |
423 | int midx = expmed_mode_index (mode); |
424 | return &this_target_expmed->x_shiftadd_cost[speed][midx][bits]; | |
5322d07e NF |
425 | } |
426 | ||
427 | /* Set the COST of doing a shift in MODE by BITS followed by an add when | |
428 | optimizing for SPEED. */ | |
429 | ||
cb3e0eac | 430 | inline void |
ef4bddc2 | 431 | set_shiftadd_cost (bool speed, machine_mode mode, int bits, int cost) |
5322d07e NF |
432 | { |
433 | *shiftadd_cost_ptr (speed, mode, bits) = cost; | |
434 | } | |
435 | ||
436 | /* Return the cost of doing a shift in MODE by BITS followed by an add | |
437 | when optimizing for SPEED. */ | |
438 | ||
cb3e0eac | 439 | inline int |
ef4bddc2 | 440 | shiftadd_cost (bool speed, machine_mode mode, int bits) |
5322d07e NF |
441 | { |
442 | return *shiftadd_cost_ptr (speed, mode, bits); | |
443 | } | |
444 | ||
445 | /* Subroutine of {set_,}shiftsub0_cost. Not to be used otherwise. */ | |
446 | ||
cb3e0eac | 447 | inline int * |
ef4bddc2 | 448 | shiftsub0_cost_ptr (bool speed, machine_mode mode, int bits) |
5322d07e | 449 | { |
1fe9bef9 VG |
450 | int midx = expmed_mode_index (mode); |
451 | return &this_target_expmed->x_shiftsub0_cost[speed][midx][bits]; | |
5322d07e NF |
452 | } |
453 | ||
454 | /* Set the COST of doing a shift in MODE by BITS and then subtracting a | |
455 | value when optimizing for SPEED. */ | |
456 | ||
cb3e0eac | 457 | inline void |
ef4bddc2 | 458 | set_shiftsub0_cost (bool speed, machine_mode mode, int bits, int cost) |
5322d07e NF |
459 | { |
460 | *shiftsub0_cost_ptr (speed, mode, bits) = cost; | |
461 | } | |
462 | ||
463 | /* Return the cost of doing a shift in MODE by BITS and then subtracting | |
464 | a value when optimizing for SPEED. */ | |
465 | ||
cb3e0eac | 466 | inline int |
ef4bddc2 | 467 | shiftsub0_cost (bool speed, machine_mode mode, int bits) |
5322d07e NF |
468 | { |
469 | return *shiftsub0_cost_ptr (speed, mode, bits); | |
470 | } | |
471 | ||
472 | /* Subroutine of {set_,}shiftsub1_cost. Not to be used otherwise. */ | |
473 | ||
cb3e0eac | 474 | inline int * |
ef4bddc2 | 475 | shiftsub1_cost_ptr (bool speed, machine_mode mode, int bits) |
5322d07e | 476 | { |
1fe9bef9 VG |
477 | int midx = expmed_mode_index (mode); |
478 | return &this_target_expmed->x_shiftsub1_cost[speed][midx][bits]; | |
5322d07e NF |
479 | } |
480 | ||
481 | /* Set the COST of subtracting a shift in MODE by BITS from a value when | |
482 | optimizing for SPEED. */ | |
483 | ||
cb3e0eac | 484 | inline void |
ef4bddc2 | 485 | set_shiftsub1_cost (bool speed, machine_mode mode, int bits, int cost) |
5322d07e NF |
486 | { |
487 | *shiftsub1_cost_ptr (speed, mode, bits) = cost; | |
488 | } | |
489 | ||
490 | /* Return the cost of subtracting a shift in MODE by BITS from a value | |
491 | when optimizing for SPEED. */ | |
492 | ||
cb3e0eac | 493 | inline int |
ef4bddc2 | 494 | shiftsub1_cost (bool speed, machine_mode mode, int bits) |
5322d07e NF |
495 | { |
496 | return *shiftsub1_cost_ptr (speed, mode, bits); | |
497 | } | |
498 | ||
499 | /* Subroutine of {set_,}mul_cost. Not to be used otherwise. */ | |
500 | ||
cb3e0eac | 501 | inline int * |
ef4bddc2 | 502 | mul_cost_ptr (bool speed, machine_mode mode) |
5322d07e | 503 | { |
2a261cd3 | 504 | return expmed_op_cost_ptr (&this_target_expmed->x_mul_cost, speed, mode); |
5322d07e NF |
505 | } |
506 | ||
507 | /* Set the COST of doing a multiplication in MODE when optimizing for | |
508 | SPEED. */ | |
509 | ||
cb3e0eac | 510 | inline void |
ef4bddc2 | 511 | set_mul_cost (bool speed, machine_mode mode, int cost) |
5322d07e NF |
512 | { |
513 | *mul_cost_ptr (speed, mode) = cost; | |
514 | } | |
515 | ||
516 | /* Return the cost of doing a multiplication in MODE when optimizing | |
517 | for SPEED. */ | |
518 | ||
cb3e0eac | 519 | inline int |
ef4bddc2 | 520 | mul_cost (bool speed, machine_mode mode) |
5322d07e NF |
521 | { |
522 | return *mul_cost_ptr (speed, mode); | |
523 | } | |
524 | ||
525 | /* Subroutine of {set_,}sdiv_cost. Not to be used otherwise. */ | |
526 | ||
cb3e0eac | 527 | inline int * |
ef4bddc2 | 528 | sdiv_cost_ptr (bool speed, machine_mode mode) |
5322d07e | 529 | { |
2a261cd3 | 530 | return expmed_op_cost_ptr (&this_target_expmed->x_sdiv_cost, speed, mode); |
5322d07e NF |
531 | } |
532 | ||
533 | /* Set the COST of doing a signed division in MODE when optimizing | |
6dd8f4bb BS |
534 | for SPEED. */ |
535 | ||
cb3e0eac | 536 | inline void |
ef4bddc2 | 537 | set_sdiv_cost (bool speed, machine_mode mode, int cost) |
5322d07e NF |
538 | { |
539 | *sdiv_cost_ptr (speed, mode) = cost; | |
540 | } | |
541 | ||
542 | /* Return the cost of doing a signed division in MODE when optimizing | |
543 | for SPEED. */ | |
544 | ||
cb3e0eac | 545 | inline int |
ef4bddc2 | 546 | sdiv_cost (bool speed, machine_mode mode) |
5322d07e NF |
547 | { |
548 | return *sdiv_cost_ptr (speed, mode); | |
549 | } | |
550 | ||
551 | /* Subroutine of {set_,}udiv_cost. Not to be used otherwise. */ | |
552 | ||
cb3e0eac | 553 | inline int * |
ef4bddc2 | 554 | udiv_cost_ptr (bool speed, machine_mode mode) |
5322d07e | 555 | { |
2a261cd3 | 556 | return expmed_op_cost_ptr (&this_target_expmed->x_udiv_cost, speed, mode); |
5322d07e NF |
557 | } |
558 | ||
559 | /* Set the COST of doing an unsigned division in MODE when optimizing | |
560 | for SPEED. */ | |
561 | ||
cb3e0eac | 562 | inline void |
ef4bddc2 | 563 | set_udiv_cost (bool speed, machine_mode mode, int cost) |
5322d07e NF |
564 | { |
565 | *udiv_cost_ptr (speed, mode) = cost; | |
566 | } | |
567 | ||
568 | /* Return the cost of doing an unsigned division in MODE when | |
569 | optimizing for SPEED. */ | |
570 | ||
cb3e0eac | 571 | inline int |
ef4bddc2 | 572 | udiv_cost (bool speed, machine_mode mode) |
5322d07e NF |
573 | { |
574 | return *udiv_cost_ptr (speed, mode); | |
575 | } | |
576 | ||
577 | /* Subroutine of {set_,}mul_widen_cost. Not to be used otherwise. */ | |
578 | ||
cb3e0eac | 579 | inline int * |
ef4bddc2 | 580 | mul_widen_cost_ptr (bool speed, machine_mode mode) |
5322d07e | 581 | { |
2a261cd3 NF |
582 | gcc_assert (GET_MODE_CLASS (mode) == MODE_INT); |
583 | ||
584 | return &this_target_expmed->x_mul_widen_cost[speed][mode - MIN_MODE_INT]; | |
5322d07e NF |
585 | } |
586 | ||
587 | /* Set the COST for computing a widening multiplication in MODE when | |
588 | optimizing for SPEED. */ | |
589 | ||
cb3e0eac | 590 | inline void |
ef4bddc2 | 591 | set_mul_widen_cost (bool speed, machine_mode mode, int cost) |
5322d07e NF |
592 | { |
593 | *mul_widen_cost_ptr (speed, mode) = cost; | |
594 | } | |
595 | ||
596 | /* Return the cost for computing a widening multiplication in MODE when | |
597 | optimizing for SPEED. */ | |
598 | ||
cb3e0eac | 599 | inline int |
ef4bddc2 | 600 | mul_widen_cost (bool speed, machine_mode mode) |
5322d07e NF |
601 | { |
602 | return *mul_widen_cost_ptr (speed, mode); | |
603 | } | |
604 | ||
605 | /* Subroutine of {set_,}mul_highpart_cost. Not to be used otherwise. */ | |
606 | ||
cb3e0eac | 607 | inline int * |
ef4bddc2 | 608 | mul_highpart_cost_ptr (bool speed, machine_mode mode) |
5322d07e | 609 | { |
2a261cd3 | 610 | gcc_assert (GET_MODE_CLASS (mode) == MODE_INT); |
ac2a97db ML |
611 | int m = mode - MIN_MODE_INT; |
612 | gcc_assert (m < NUM_MODE_INT); | |
2a261cd3 | 613 | |
ac2a97db | 614 | return &this_target_expmed->x_mul_highpart_cost[speed][m]; |
5322d07e NF |
615 | } |
616 | ||
617 | /* Set the COST for computing the high part of a multiplication in MODE | |
618 | when optimizing for SPEED. */ | |
619 | ||
cb3e0eac | 620 | inline void |
ef4bddc2 | 621 | set_mul_highpart_cost (bool speed, machine_mode mode, int cost) |
5322d07e NF |
622 | { |
623 | *mul_highpart_cost_ptr (speed, mode) = cost; | |
624 | } | |
625 | ||
626 | /* Return the cost for computing the high part of a multiplication in MODE | |
627 | when optimizing for SPEED. */ | |
628 | ||
cb3e0eac | 629 | inline int |
ef4bddc2 | 630 | mul_highpart_cost (bool speed, machine_mode mode) |
5322d07e NF |
631 | { |
632 | return *mul_highpart_cost_ptr (speed, mode); | |
633 | } | |
634 | ||
635 | /* Subroutine of {set_,}convert_cost. Not to be used otherwise. */ | |
636 | ||
cb3e0eac | 637 | inline int * |
ef4bddc2 | 638 | convert_cost_ptr (machine_mode to_mode, machine_mode from_mode, |
5322d07e | 639 | bool speed) |
6dd8f4bb | 640 | { |
91f8035e RH |
641 | int to_idx = expmed_mode_index (to_mode); |
642 | int from_idx = expmed_mode_index (from_mode); | |
6dd8f4bb | 643 | |
91f8035e RH |
644 | gcc_assert (IN_RANGE (to_idx, 0, NUM_MODE_IP_INT - 1)); |
645 | gcc_assert (IN_RANGE (from_idx, 0, NUM_MODE_IP_INT - 1)); | |
6dd8f4bb | 646 | |
5322d07e NF |
647 | return &this_target_expmed->x_convert_cost[speed][to_idx][from_idx]; |
648 | } | |
649 | ||
650 | /* Set the COST for converting from FROM_MODE to TO_MODE when optimizing | |
651 | for SPEED. */ | |
652 | ||
cb3e0eac | 653 | inline void |
ef4bddc2 | 654 | set_convert_cost (machine_mode to_mode, machine_mode from_mode, |
5322d07e NF |
655 | bool speed, int cost) |
656 | { | |
657 | *convert_cost_ptr (to_mode, from_mode, speed) = cost; | |
6dd8f4bb BS |
658 | } |
659 | ||
660 | /* Return the cost for converting from FROM_MODE to TO_MODE when optimizing | |
661 | for SPEED. */ | |
662 | ||
cb3e0eac | 663 | inline int |
ef4bddc2 | 664 | convert_cost (machine_mode to_mode, machine_mode from_mode, |
6dd8f4bb BS |
665 | bool speed) |
666 | { | |
5322d07e | 667 | return *convert_cost_ptr (to_mode, from_mode, speed); |
6dd8f4bb BS |
668 | } |
669 | ||
ef4bddc2 | 670 | extern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool); |
2d52a3a1 | 671 | extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code, |
b8506a8a | 672 | machine_mode mode, machine_mode compare_mode, |
2d52a3a1 | 673 | int unsignedp, rtx x, rtx y, int normalizep, |
b8506a8a | 674 | machine_mode target_mode); |
36566b39 PK |
675 | |
676 | /* Arguments MODE, RTX: return an rtx for the negation of that value. | |
677 | May emit insns. */ | |
678 | extern rtx negate_rtx (machine_mode, rtx); | |
679 | ||
ee45a32d EB |
680 | /* Arguments MODE, RTX: return an rtx for the flipping of that value. |
681 | May emit insns. */ | |
b8506a8a | 682 | extern rtx flip_storage_order (machine_mode, rtx); |
ee45a32d | 683 | |
36566b39 PK |
684 | /* Expand a logical AND operation. */ |
685 | extern rtx expand_and (machine_mode, rtx, rtx, rtx); | |
686 | ||
687 | /* Emit a store-flag operation. */ | |
688 | extern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, machine_mode, | |
689 | int, int); | |
690 | ||
691 | /* Like emit_store_flag, but always succeeds. */ | |
692 | extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx, | |
693 | machine_mode, int, int); | |
694 | ||
ec18e48e VL |
695 | extern void canonicalize_comparison (machine_mode, enum rtx_code *, rtx *); |
696 | ||
10e34aa5 EB |
697 | /* Choose a minimal N + 1 bit approximation to 2**K / D that can be used to |
698 | replace division by D, put the least significant N bits of the result in | |
699 | *MULTIPLIER_PTR, the value K - N in *POST_SHIFT_PTR, and return the most | |
700 | significant bit. */ | |
36566b39 PK |
701 | extern unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int, |
702 | int, unsigned HOST_WIDE_INT *, | |
10e34aa5 | 703 | int *); |
36566b39 PK |
704 | |
705 | #ifdef TREE_CODE | |
706 | extern rtx expand_variable_shift (enum tree_code, machine_mode, | |
707 | rtx, tree, rtx, int); | |
0c12fc9b RS |
708 | extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx, |
709 | int); | |
c2565a31 JJ |
710 | extern rtx maybe_expand_shift (enum tree_code, machine_mode, rtx, int, rtx, |
711 | int); | |
e34153b0 | 712 | #ifdef GCC_OPTABS_H |
2246d576 TC |
713 | extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx, |
714 | rtx, int, enum optab_methods = OPTAB_LIB_WIDEN); | |
e34153b0 | 715 | #endif |
462f85ce | 716 | #endif |
36566b39 | 717 | |
2d7b38df | 718 | extern void store_bit_field (rtx, poly_uint64, poly_uint64, |
8c59e5e7 | 719 | poly_uint64, poly_uint64, |
13f44099 | 720 | machine_mode, rtx, bool, bool); |
fc60a416 | 721 | extern rtx extract_bit_field (rtx, poly_uint64, poly_uint64, int, rtx, |
f96bf49a | 722 | machine_mode, machine_mode, bool, rtx *); |
5b4f3384 | 723 | extern rtx extract_low_bits (machine_mode, machine_mode, rtx); |
0b99f253 | 724 | extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int, bool = false); |
095a2d76 RS |
725 | extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx, |
726 | rtx, int); | |
5b4f3384 | 727 | |
36566b39 | 728 | #endif // EXPMED_H |