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