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