File: | build/gcc/expmed.cc |
Warning: | line 1433, column 13 The result of the left shift is undefined due to shifting by '64', which is greater or equal to the width of type 'long' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Medium-level subroutines: convert bit-field store and extract | ||||
2 | and shifts, multiplies and divides to rtl instructions. | ||||
3 | Copyright (C) 1987-2023 Free Software Foundation, Inc. | ||||
4 | |||||
5 | This file is part of GCC. | ||||
6 | |||||
7 | GCC is free software; you can redistribute it and/or modify it under | ||||
8 | the terms of the GNU General Public License as published by the Free | ||||
9 | Software Foundation; either version 3, or (at your option) any later | ||||
10 | version. | ||||
11 | |||||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||||
15 | for more details. | ||||
16 | |||||
17 | You should have received a copy of the GNU General Public License | ||||
18 | along with GCC; see the file COPYING3. If not see | ||||
19 | <http://www.gnu.org/licenses/>. */ | ||||
20 | |||||
21 | /* Work around tree-optimization/91825. */ | ||||
22 | #pragma GCC diagnostic warning "-Wmaybe-uninitialized" | ||||
23 | |||||
24 | #include "config.h" | ||||
25 | #include "system.h" | ||||
26 | #include "coretypes.h" | ||||
27 | #include "backend.h" | ||||
28 | #include "target.h" | ||||
29 | #include "rtl.h" | ||||
30 | #include "tree.h" | ||||
31 | #include "predict.h" | ||||
32 | #include "memmodel.h" | ||||
33 | #include "tm_p.h" | ||||
34 | #include "optabs.h" | ||||
35 | #include "expmed.h" | ||||
36 | #include "regs.h" | ||||
37 | #include "emit-rtl.h" | ||||
38 | #include "diagnostic-core.h" | ||||
39 | #include "fold-const.h" | ||||
40 | #include "stor-layout.h" | ||||
41 | #include "dojump.h" | ||||
42 | #include "explow.h" | ||||
43 | #include "expr.h" | ||||
44 | #include "langhooks.h" | ||||
45 | #include "tree-vector-builder.h" | ||||
46 | |||||
47 | struct target_expmed default_target_expmed; | ||||
48 | #if SWITCHABLE_TARGET1 | ||||
49 | struct target_expmed *this_target_expmed = &default_target_expmed; | ||||
50 | #endif | ||||
51 | |||||
52 | static bool store_integral_bit_field (rtx, opt_scalar_int_mode, | ||||
53 | unsigned HOST_WIDE_INTlong, | ||||
54 | unsigned HOST_WIDE_INTlong, | ||||
55 | poly_uint64, poly_uint64, | ||||
56 | machine_mode, rtx, bool, bool); | ||||
57 | static void store_fixed_bit_field (rtx, opt_scalar_int_mode, | ||||
58 | unsigned HOST_WIDE_INTlong, | ||||
59 | unsigned HOST_WIDE_INTlong, | ||||
60 | poly_uint64, poly_uint64, | ||||
61 | rtx, scalar_int_mode, bool); | ||||
62 | static void store_fixed_bit_field_1 (rtx, scalar_int_mode, | ||||
63 | unsigned HOST_WIDE_INTlong, | ||||
64 | unsigned HOST_WIDE_INTlong, | ||||
65 | rtx, scalar_int_mode, bool); | ||||
66 | static void store_split_bit_field (rtx, opt_scalar_int_mode, | ||||
67 | unsigned HOST_WIDE_INTlong, | ||||
68 | unsigned HOST_WIDE_INTlong, | ||||
69 | poly_uint64, poly_uint64, | ||||
70 | rtx, scalar_int_mode, bool); | ||||
71 | static rtx extract_integral_bit_field (rtx, opt_scalar_int_mode, | ||||
72 | unsigned HOST_WIDE_INTlong, | ||||
73 | unsigned HOST_WIDE_INTlong, int, rtx, | ||||
74 | machine_mode, machine_mode, bool, bool); | ||||
75 | static rtx extract_fixed_bit_field (machine_mode, rtx, opt_scalar_int_mode, | ||||
76 | unsigned HOST_WIDE_INTlong, | ||||
77 | unsigned HOST_WIDE_INTlong, rtx, int, bool); | ||||
78 | static rtx extract_fixed_bit_field_1 (machine_mode, rtx, scalar_int_mode, | ||||
79 | unsigned HOST_WIDE_INTlong, | ||||
80 | unsigned HOST_WIDE_INTlong, rtx, int, bool); | ||||
81 | static rtx lshift_value (machine_mode, unsigned HOST_WIDE_INTlong, int); | ||||
82 | static rtx extract_split_bit_field (rtx, opt_scalar_int_mode, | ||||
83 | unsigned HOST_WIDE_INTlong, | ||||
84 | unsigned HOST_WIDE_INTlong, int, bool); | ||||
85 | static void do_cmp_and_jump (rtx, rtx, enum rtx_code, machine_mode, rtx_code_label *); | ||||
86 | static rtx expand_smod_pow2 (scalar_int_mode, rtx, HOST_WIDE_INTlong); | ||||
87 | static rtx expand_sdiv_pow2 (scalar_int_mode, rtx, HOST_WIDE_INTlong); | ||||
88 | |||||
89 | /* Return a constant integer mask value of mode MODE with BITSIZE ones | ||||
90 | followed by BITPOS zeros, or the complement of that if COMPLEMENT. | ||||
91 | The mask is truncated if necessary to the width of mode MODE. The | ||||
92 | mask is zero-extended if BITSIZE+BITPOS is too small for MODE. */ | ||||
93 | |||||
94 | static inline rtx | ||||
95 | mask_rtx (scalar_int_mode mode, int bitpos, int bitsize, bool complement) | ||||
96 | { | ||||
97 | return immed_wide_int_const | ||||
98 | (wi::shifted_mask (bitpos, bitsize, complement, | ||||
99 | GET_MODE_PRECISION (mode)), mode); | ||||
100 | } | ||||
101 | |||||
102 | /* Test whether a value is zero of a power of two. */ | ||||
103 | #define EXACT_POWER_OF_2_OR_ZERO_P(x)(((x) & ((x) - 1UL)) == 0) \ | ||||
104 | (((x) & ((x) - HOST_WIDE_INT_1U1UL)) == 0) | ||||
105 | |||||
106 | struct init_expmed_rtl | ||||
107 | { | ||||
108 | rtx reg; | ||||
109 | rtx plus; | ||||
110 | rtx neg; | ||||
111 | rtx mult; | ||||
112 | rtx sdiv; | ||||
113 | rtx udiv; | ||||
114 | rtx sdiv_32; | ||||
115 | rtx smod_32; | ||||
116 | rtx wide_mult; | ||||
117 | rtx wide_lshr; | ||||
118 | rtx wide_trunc; | ||||
119 | rtx shift; | ||||
120 | rtx shift_mult; | ||||
121 | rtx shift_add; | ||||
122 | rtx shift_sub0; | ||||
123 | rtx shift_sub1; | ||||
124 | rtx zext; | ||||
125 | rtx trunc; | ||||
126 | |||||
127 | rtx pow2[MAX_BITS_PER_WORD64]; | ||||
128 | rtx cint[MAX_BITS_PER_WORD64]; | ||||
129 | }; | ||||
130 | |||||
131 | static void | ||||
132 | init_expmed_one_conv (struct init_expmed_rtl *all, scalar_int_mode to_mode, | ||||
133 | scalar_int_mode from_mode, bool speed) | ||||
134 | { | ||||
135 | int to_size, from_size; | ||||
136 | rtx which; | ||||
137 | |||||
138 | to_size = GET_MODE_PRECISION (to_mode); | ||||
139 | from_size = GET_MODE_PRECISION (from_mode); | ||||
140 | |||||
141 | /* Most partial integers have a precision less than the "full" | ||||
142 | integer it requires for storage. In case one doesn't, for | ||||
143 | comparison purposes here, reduce the bit size by one in that | ||||
144 | case. */ | ||||
145 | if (GET_MODE_CLASS (to_mode)((enum mode_class) mode_class[to_mode]) == MODE_PARTIAL_INT | ||||
146 | && pow2p_hwi (to_size)) | ||||
147 | to_size --; | ||||
148 | if (GET_MODE_CLASS (from_mode)((enum mode_class) mode_class[from_mode]) == MODE_PARTIAL_INT | ||||
149 | && pow2p_hwi (from_size)) | ||||
150 | from_size --; | ||||
151 | |||||
152 | /* Assume cost of zero-extend and sign-extend is the same. */ | ||||
153 | which = (to_size < from_size ? all->trunc : all->zext); | ||||
154 | |||||
155 | PUT_MODE (all->reg, from_mode); | ||||
156 | set_convert_cost (to_mode, from_mode, speed, | ||||
157 | set_src_cost (which, to_mode, speed)); | ||||
158 | /* Restore all->reg's mode. */ | ||||
159 | PUT_MODE (all->reg, to_mode); | ||||
160 | } | ||||
161 | |||||
162 | static void | ||||
163 | init_expmed_one_mode (struct init_expmed_rtl *all, | ||||
164 | machine_mode mode, int speed) | ||||
165 | { | ||||
166 | int m, n, mode_bitsize; | ||||
167 | machine_mode mode_from; | ||||
168 | |||||
169 | mode_bitsize = GET_MODE_UNIT_BITSIZE (mode)((unsigned short) (mode_to_unit_size (mode) * (8))); | ||||
170 | |||||
171 | PUT_MODE (all->reg, mode); | ||||
172 | PUT_MODE (all->plus, mode); | ||||
173 | PUT_MODE (all->neg, mode); | ||||
174 | PUT_MODE (all->mult, mode); | ||||
175 | PUT_MODE (all->sdiv, mode); | ||||
176 | PUT_MODE (all->udiv, mode); | ||||
177 | PUT_MODE (all->sdiv_32, mode); | ||||
178 | PUT_MODE (all->smod_32, mode); | ||||
179 | PUT_MODE (all->wide_trunc, mode); | ||||
180 | PUT_MODE (all->shift, mode); | ||||
181 | PUT_MODE (all->shift_mult, mode); | ||||
182 | PUT_MODE (all->shift_add, mode); | ||||
183 | PUT_MODE (all->shift_sub0, mode); | ||||
184 | PUT_MODE (all->shift_sub1, mode); | ||||
185 | PUT_MODE (all->zext, mode); | ||||
186 | PUT_MODE (all->trunc, mode); | ||||
187 | |||||
188 | set_add_cost (speed, mode, set_src_cost (all->plus, mode, speed)); | ||||
189 | set_neg_cost (speed, mode, set_src_cost (all->neg, mode, speed)); | ||||
190 | set_mul_cost (speed, mode, set_src_cost (all->mult, mode, speed)); | ||||
191 | set_sdiv_cost (speed, mode, set_src_cost (all->sdiv, mode, speed)); | ||||
192 | set_udiv_cost (speed, mode, set_src_cost (all->udiv, mode, speed)); | ||||
193 | |||||
194 | set_sdiv_pow2_cheap (speed, mode, (set_src_cost (all->sdiv_32, mode, speed) | ||||
195 | <= 2 * add_cost (speed, mode))); | ||||
196 | set_smod_pow2_cheap (speed, mode, (set_src_cost (all->smod_32, mode, speed) | ||||
197 | <= 4 * add_cost (speed, mode))); | ||||
198 | |||||
199 | set_shift_cost (speed, mode, 0, 0); | ||||
200 | { | ||||
201 | int cost = add_cost (speed, mode); | ||||
202 | set_shiftadd_cost (speed, mode, 0, cost); | ||||
203 | set_shiftsub0_cost (speed, mode, 0, cost); | ||||
204 | set_shiftsub1_cost (speed, mode, 0, cost); | ||||
205 | } | ||||
206 | |||||
207 | n = MIN (MAX_BITS_PER_WORD, mode_bitsize)((64) < (mode_bitsize) ? (64) : (mode_bitsize)); | ||||
208 | for (m = 1; m < n; m++) | ||||
209 | { | ||||
210 | XEXP (all->shift, 1)(((all->shift)->u.fld[1]).rt_rtx) = all->cint[m]; | ||||
211 | XEXP (all->shift_mult, 1)(((all->shift_mult)->u.fld[1]).rt_rtx) = all->pow2[m]; | ||||
212 | |||||
213 | set_shift_cost (speed, mode, m, set_src_cost (all->shift, mode, speed)); | ||||
214 | set_shiftadd_cost (speed, mode, m, set_src_cost (all->shift_add, mode, | ||||
215 | speed)); | ||||
216 | set_shiftsub0_cost (speed, mode, m, set_src_cost (all->shift_sub0, mode, | ||||
217 | speed)); | ||||
218 | set_shiftsub1_cost (speed, mode, m, set_src_cost (all->shift_sub1, mode, | ||||
219 | speed)); | ||||
220 | } | ||||
221 | |||||
222 | scalar_int_mode int_mode_to; | ||||
223 | if (is_a <scalar_int_mode> (mode, &int_mode_to)) | ||||
224 | { | ||||
225 | for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT; | ||||
226 | mode_from = (machine_mode)(mode_from + 1)) | ||||
227 | init_expmed_one_conv (all, int_mode_to, | ||||
228 | as_a <scalar_int_mode> (mode_from), speed); | ||||
229 | |||||
230 | scalar_int_mode wider_mode; | ||||
231 | if (GET_MODE_CLASS (int_mode_to)((enum mode_class) mode_class[int_mode_to]) == MODE_INT | ||||
232 | && GET_MODE_WIDER_MODE (int_mode_to).exists (&wider_mode)) | ||||
233 | { | ||||
234 | PUT_MODE (all->reg, mode); | ||||
235 | PUT_MODE (all->zext, wider_mode); | ||||
236 | PUT_MODE (all->wide_mult, wider_mode); | ||||
237 | PUT_MODE (all->wide_lshr, wider_mode); | ||||
238 | XEXP (all->wide_lshr, 1)(((all->wide_lshr)->u.fld[1]).rt_rtx) | ||||
239 | = gen_int_shift_amount (wider_mode, mode_bitsize); | ||||
240 | |||||
241 | set_mul_widen_cost (speed, wider_mode, | ||||
242 | set_src_cost (all->wide_mult, wider_mode, speed)); | ||||
243 | set_mul_highpart_cost (speed, int_mode_to, | ||||
244 | set_src_cost (all->wide_trunc, | ||||
245 | int_mode_to, speed)); | ||||
246 | } | ||||
247 | } | ||||
248 | } | ||||
249 | |||||
250 | void | ||||
251 | init_expmed (void) | ||||
252 | { | ||||
253 | struct init_expmed_rtl all; | ||||
254 | machine_mode mode = QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)); | ||||
255 | int m, speed; | ||||
256 | |||||
257 | memset (&all, 0, sizeof all); | ||||
258 | for (m = 1; m < MAX_BITS_PER_WORD64; m++) | ||||
259 | { | ||||
260 | all.pow2[m] = GEN_INT (HOST_WIDE_INT_1 << m)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1L << m)); | ||||
261 | all.cint[m] = GEN_INT (m)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (m)); | ||||
262 | } | ||||
263 | |||||
264 | /* Avoid using hard regs in ways which may be unsupported. */ | ||||
265 | all.reg = gen_raw_REG (mode, LAST_VIRTUAL_REGISTER(((76)) + 5) + 1); | ||||
266 | all.plus = gen_rtx_PLUS (mode, all.reg, all.reg)gen_rtx_fmt_ee_stat ((PLUS), ((mode)), ((all.reg)), ((all.reg )) ); | ||||
267 | all.neg = gen_rtx_NEG (mode, all.reg)gen_rtx_fmt_e_stat ((NEG), ((mode)), ((all.reg)) ); | ||||
268 | all.mult = gen_rtx_MULT (mode, all.reg, all.reg)gen_rtx_fmt_ee_stat ((MULT), ((mode)), ((all.reg)), ((all.reg )) ); | ||||
269 | all.sdiv = gen_rtx_DIV (mode, all.reg, all.reg)gen_rtx_fmt_ee_stat ((DIV), ((mode)), ((all.reg)), ((all.reg) ) ); | ||||
270 | all.udiv = gen_rtx_UDIV (mode, all.reg, all.reg)gen_rtx_fmt_ee_stat ((UDIV), ((mode)), ((all.reg)), ((all.reg )) ); | ||||
271 | all.sdiv_32 = gen_rtx_DIV (mode, all.reg, all.pow2[5])gen_rtx_fmt_ee_stat ((DIV), ((mode)), ((all.reg)), ((all.pow2 [5])) ); | ||||
272 | all.smod_32 = gen_rtx_MOD (mode, all.reg, all.pow2[5])gen_rtx_fmt_ee_stat ((MOD), ((mode)), ((all.reg)), ((all.pow2 [5])) ); | ||||
273 | all.zext = gen_rtx_ZERO_EXTEND (mode, all.reg)gen_rtx_fmt_e_stat ((ZERO_EXTEND), ((mode)), ((all.reg)) ); | ||||
274 | all.wide_mult = gen_rtx_MULT (mode, all.zext, all.zext)gen_rtx_fmt_ee_stat ((MULT), ((mode)), ((all.zext)), ((all.zext )) ); | ||||
275 | all.wide_lshr = gen_rtx_LSHIFTRT (mode, all.wide_mult, all.reg)gen_rtx_fmt_ee_stat ((LSHIFTRT), ((mode)), ((all.wide_mult)), ((all.reg)) ); | ||||
276 | all.wide_trunc = gen_rtx_TRUNCATE (mode, all.wide_lshr)gen_rtx_fmt_e_stat ((TRUNCATE), ((mode)), ((all.wide_lshr)) ); | ||||
277 | all.shift = gen_rtx_ASHIFT (mode, all.reg, all.reg)gen_rtx_fmt_ee_stat ((ASHIFT), ((mode)), ((all.reg)), ((all.reg )) ); | ||||
278 | all.shift_mult = gen_rtx_MULT (mode, all.reg, all.reg)gen_rtx_fmt_ee_stat ((MULT), ((mode)), ((all.reg)), ((all.reg )) ); | ||||
279 | all.shift_add = gen_rtx_PLUS (mode, all.shift_mult, all.reg)gen_rtx_fmt_ee_stat ((PLUS), ((mode)), ((all.shift_mult)), (( all.reg)) ); | ||||
280 | all.shift_sub0 = gen_rtx_MINUS (mode, all.shift_mult, all.reg)gen_rtx_fmt_ee_stat ((MINUS), ((mode)), ((all.shift_mult)), ( (all.reg)) ); | ||||
281 | all.shift_sub1 = gen_rtx_MINUS (mode, all.reg, all.shift_mult)gen_rtx_fmt_ee_stat ((MINUS), ((mode)), ((all.reg)), ((all.shift_mult )) ); | ||||
282 | all.trunc = gen_rtx_TRUNCATE (mode, all.reg)gen_rtx_fmt_e_stat ((TRUNCATE), ((mode)), ((all.reg)) ); | ||||
283 | |||||
284 | for (speed = 0; speed < 2; speed++) | ||||
285 | { | ||||
286 | crtl(&x_rtl)->maybe_hot_insn_p = speed; | ||||
287 | set_zero_cost (speed, set_src_cost (const0_rtx(const_int_rtx[64]), mode, speed)); | ||||
288 | |||||
289 | for (mode = MIN_MODE_INT; mode <= MAX_MODE_INT; | ||||
290 | mode = (machine_mode)(mode + 1)) | ||||
291 | init_expmed_one_mode (&all, mode, speed); | ||||
292 | |||||
293 | if (MIN_MODE_PARTIAL_INT != VOIDmode((void) 0, E_VOIDmode)) | ||||
294 | for (mode = MIN_MODE_PARTIAL_INT; mode <= MAX_MODE_PARTIAL_INT; | ||||
295 | mode = (machine_mode)(mode + 1)) | ||||
296 | init_expmed_one_mode (&all, mode, speed); | ||||
297 | |||||
298 | if (MIN_MODE_VECTOR_INT != VOIDmode((void) 0, E_VOIDmode)) | ||||
299 | for (mode = MIN_MODE_VECTOR_INT; mode <= MAX_MODE_VECTOR_INT; | ||||
300 | mode = (machine_mode)(mode + 1)) | ||||
301 | init_expmed_one_mode (&all, mode, speed); | ||||
302 | } | ||||
303 | |||||
304 | if (alg_hash_used_p ()) | ||||
305 | { | ||||
306 | struct alg_hash_entry *p = alg_hash_entry_ptr (0); | ||||
307 | memset (p, 0, sizeof (*p) * NUM_ALG_HASH_ENTRIES1031); | ||||
308 | } | ||||
309 | else | ||||
310 | set_alg_hash_used_p (true); | ||||
311 | default_rtl_profile (); | ||||
312 | |||||
313 | ggc_free (all.trunc); | ||||
314 | ggc_free (all.shift_sub1); | ||||
315 | ggc_free (all.shift_sub0); | ||||
316 | ggc_free (all.shift_add); | ||||
317 | ggc_free (all.shift_mult); | ||||
318 | ggc_free (all.shift); | ||||
319 | ggc_free (all.wide_trunc); | ||||
320 | ggc_free (all.wide_lshr); | ||||
321 | ggc_free (all.wide_mult); | ||||
322 | ggc_free (all.zext); | ||||
323 | ggc_free (all.smod_32); | ||||
324 | ggc_free (all.sdiv_32); | ||||
325 | ggc_free (all.udiv); | ||||
326 | ggc_free (all.sdiv); | ||||
327 | ggc_free (all.mult); | ||||
328 | ggc_free (all.neg); | ||||
329 | ggc_free (all.plus); | ||||
330 | ggc_free (all.reg); | ||||
331 | } | ||||
332 | |||||
333 | /* Return an rtx representing minus the value of X. | ||||
334 | MODE is the intended mode of the result, | ||||
335 | useful if X is a CONST_INT. */ | ||||
336 | |||||
337 | rtx | ||||
338 | negate_rtx (machine_mode mode, rtx x) | ||||
339 | { | ||||
340 | rtx result = simplify_unary_operation (NEG, mode, x, mode); | ||||
341 | |||||
342 | if (result == 0) | ||||
343 | result = expand_unop (mode, neg_optab, x, NULL_RTX(rtx) 0, 0); | ||||
344 | |||||
345 | return result; | ||||
346 | } | ||||
347 | |||||
348 | /* Whether reverse storage order is supported on the target. */ | ||||
349 | static int reverse_storage_order_supported = -1; | ||||
350 | |||||
351 | /* Check whether reverse storage order is supported on the target. */ | ||||
352 | |||||
353 | static void | ||||
354 | check_reverse_storage_order_support (void) | ||||
355 | { | ||||
356 | if (BYTES_BIG_ENDIAN0 != WORDS_BIG_ENDIAN0) | ||||
357 | { | ||||
358 | reverse_storage_order_supported = 0; | ||||
359 | sorry ("reverse scalar storage order"); | ||||
360 | } | ||||
361 | else | ||||
362 | reverse_storage_order_supported = 1; | ||||
363 | } | ||||
364 | |||||
365 | /* Whether reverse FP storage order is supported on the target. */ | ||||
366 | static int reverse_float_storage_order_supported = -1; | ||||
367 | |||||
368 | /* Check whether reverse FP storage order is supported on the target. */ | ||||
369 | |||||
370 | static void | ||||
371 | check_reverse_float_storage_order_support (void) | ||||
372 | { | ||||
373 | if (FLOAT_WORDS_BIG_ENDIAN0 != WORDS_BIG_ENDIAN0) | ||||
374 | { | ||||
375 | reverse_float_storage_order_supported = 0; | ||||
376 | sorry ("reverse floating-point scalar storage order"); | ||||
377 | } | ||||
378 | else | ||||
379 | reverse_float_storage_order_supported = 1; | ||||
380 | } | ||||
381 | |||||
382 | /* Return an rtx representing value of X with reverse storage order. | ||||
383 | MODE is the intended mode of the result, | ||||
384 | useful if X is a CONST_INT. */ | ||||
385 | |||||
386 | rtx | ||||
387 | flip_storage_order (machine_mode mode, rtx x) | ||||
388 | { | ||||
389 | scalar_int_mode int_mode; | ||||
390 | rtx result; | ||||
391 | |||||
392 | if (mode == QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode))) | ||||
393 | return x; | ||||
394 | |||||
395 | if (COMPLEX_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_COMPLEX_INT || ( (enum mode_class) mode_class[mode]) == MODE_COMPLEX_FLOAT)) | ||||
396 | { | ||||
397 | rtx real = read_complex_part (x, false); | ||||
398 | rtx imag = read_complex_part (x, true); | ||||
399 | |||||
400 | real = flip_storage_order (GET_MODE_INNER (mode)(mode_to_inner (mode)), real); | ||||
401 | imag = flip_storage_order (GET_MODE_INNER (mode)(mode_to_inner (mode)), imag); | ||||
402 | |||||
403 | return gen_rtx_CONCAT (mode, real, imag)gen_rtx_fmt_ee_stat ((CONCAT), ((mode)), ((real)), ((imag)) ); | ||||
404 | } | ||||
405 | |||||
406 | if (UNLIKELY (reverse_storage_order_supported < 0)(__builtin_expect ((reverse_storage_order_supported < 0), 0 ))) | ||||
407 | check_reverse_storage_order_support (); | ||||
408 | |||||
409 | if (!is_a <scalar_int_mode> (mode, &int_mode)) | ||||
410 | { | ||||
411 | if (FLOAT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT) | ||||
412 | && UNLIKELY (reverse_float_storage_order_supported < 0)(__builtin_expect ((reverse_float_storage_order_supported < 0), 0))) | ||||
413 | check_reverse_float_storage_order_support (); | ||||
414 | |||||
415 | if (!int_mode_for_size (GET_MODE_PRECISION (mode), 0).exists (&int_mode) | ||||
416 | || !targetm.scalar_mode_supported_p (int_mode)) | ||||
417 | { | ||||
418 | sorry ("reverse storage order for %smode", GET_MODE_NAME (mode)mode_name[mode]); | ||||
419 | return x; | ||||
420 | } | ||||
421 | x = gen_lowpartrtl_hooks.gen_lowpart (int_mode, x); | ||||
422 | } | ||||
423 | |||||
424 | result = simplify_unary_operation (BSWAP, int_mode, x, int_mode); | ||||
425 | if (result == 0) | ||||
426 | result = expand_unop (int_mode, bswap_optab, x, NULL_RTX(rtx) 0, 1); | ||||
427 | |||||
428 | if (int_mode != mode) | ||||
429 | result = gen_lowpartrtl_hooks.gen_lowpart (mode, result); | ||||
430 | |||||
431 | return result; | ||||
432 | } | ||||
433 | |||||
434 | /* If MODE is set, adjust bitfield memory MEM so that it points to the | ||||
435 | first unit of mode MODE that contains a bitfield of size BITSIZE at | ||||
436 | bit position BITNUM. If MODE is not set, return a BLKmode reference | ||||
437 | to every byte in the bitfield. Set *NEW_BITNUM to the bit position | ||||
438 | of the field within the new memory. */ | ||||
439 | |||||
440 | static rtx | ||||
441 | narrow_bit_field_mem (rtx mem, opt_scalar_int_mode mode, | ||||
442 | unsigned HOST_WIDE_INTlong bitsize, | ||||
443 | unsigned HOST_WIDE_INTlong bitnum, | ||||
444 | unsigned HOST_WIDE_INTlong *new_bitnum) | ||||
445 | { | ||||
446 | scalar_int_mode imode; | ||||
447 | if (mode.exists (&imode)) | ||||
448 | { | ||||
449 | unsigned int unit = GET_MODE_BITSIZE (imode); | ||||
450 | *new_bitnum = bitnum % unit; | ||||
451 | HOST_WIDE_INTlong offset = (bitnum - *new_bitnum) / BITS_PER_UNIT(8); | ||||
452 | return adjust_bitfield_address (mem, imode, offset)adjust_address_1 (mem, imode, offset, 1, 1, 1, 0); | ||||
453 | } | ||||
454 | else | ||||
455 | { | ||||
456 | *new_bitnum = bitnum % BITS_PER_UNIT(8); | ||||
457 | HOST_WIDE_INTlong offset = bitnum / BITS_PER_UNIT(8); | ||||
458 | HOST_WIDE_INTlong size = ((*new_bitnum + bitsize + BITS_PER_UNIT(8) - 1) | ||||
459 | / BITS_PER_UNIT(8)); | ||||
460 | return adjust_bitfield_address_size (mem, BLKmode, offset, size)adjust_address_1 (mem, ((void) 0, E_BLKmode), offset, 1, 1, 1 , size); | ||||
461 | } | ||||
462 | } | ||||
463 | |||||
464 | /* The caller wants to perform insertion or extraction PATTERN on a | ||||
465 | bitfield of size BITSIZE at BITNUM bits into memory operand OP0. | ||||
466 | BITREGION_START and BITREGION_END are as for store_bit_field | ||||
467 | and FIELDMODE is the natural mode of the field. | ||||
468 | |||||
469 | Search for a mode that is compatible with the memory access | ||||
470 | restrictions and (where applicable) with a register insertion or | ||||
471 | extraction. Return the new memory on success, storing the adjusted | ||||
472 | bit position in *NEW_BITNUM. Return null otherwise. */ | ||||
473 | |||||
474 | static rtx | ||||
475 | adjust_bit_field_mem_for_reg (enum extraction_pattern pattern, | ||||
476 | rtx op0, HOST_WIDE_INTlong bitsize, | ||||
477 | HOST_WIDE_INTlong bitnum, | ||||
478 | poly_uint64 bitregion_start, | ||||
479 | poly_uint64 bitregion_end, | ||||
480 | machine_mode fieldmode, | ||||
481 | unsigned HOST_WIDE_INTlong *new_bitnum) | ||||
482 | { | ||||
483 | bit_field_mode_iterator iter (bitsize, bitnum, bitregion_start, | ||||
484 | bitregion_end, MEM_ALIGN (op0)(get_mem_attrs (op0)->align), | ||||
485 | MEM_VOLATILE_P (op0)(__extension__ ({ __typeof ((op0)) const _rtx = ((op0)); if ( ((enum rtx_code) (_rtx)->code) != MEM && ((enum rtx_code ) (_rtx)->code) != ASM_OPERANDS && ((enum rtx_code ) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 485, __FUNCTION__); _rtx; })->volatil)); | ||||
486 | scalar_int_mode best_mode; | ||||
487 | if (iter.next_mode (&best_mode)) | ||||
488 | { | ||||
489 | /* We can use a memory in BEST_MODE. See whether this is true for | ||||
490 | any wider modes. All other things being equal, we prefer to | ||||
491 | use the widest mode possible because it tends to expose more | ||||
492 | CSE opportunities. */ | ||||
493 | if (!iter.prefer_smaller_modes ()) | ||||
494 | { | ||||
495 | /* Limit the search to the mode required by the corresponding | ||||
496 | register insertion or extraction instruction, if any. */ | ||||
497 | scalar_int_mode limit_mode = word_mode; | ||||
498 | extraction_insn insn; | ||||
499 | if (get_best_reg_extraction_insn (&insn, pattern, | ||||
500 | GET_MODE_BITSIZE (best_mode), | ||||
501 | fieldmode)) | ||||
502 | limit_mode = insn.field_mode; | ||||
503 | |||||
504 | scalar_int_mode wider_mode; | ||||
505 | while (iter.next_mode (&wider_mode) | ||||
506 | && GET_MODE_SIZE (wider_mode) <= GET_MODE_SIZE (limit_mode)) | ||||
507 | best_mode = wider_mode; | ||||
508 | } | ||||
509 | return narrow_bit_field_mem (op0, best_mode, bitsize, bitnum, | ||||
510 | new_bitnum); | ||||
511 | } | ||||
512 | return NULL_RTX(rtx) 0; | ||||
513 | } | ||||
514 | |||||
515 | /* Return true if a bitfield of size BITSIZE at bit number BITNUM within | ||||
516 | a structure of mode STRUCT_MODE represents a lowpart subreg. The subreg | ||||
517 | offset is then BITNUM / BITS_PER_UNIT. */ | ||||
518 | |||||
519 | static bool | ||||
520 | lowpart_bit_field_p (poly_uint64 bitnum, poly_uint64 bitsize, | ||||
521 | machine_mode struct_mode) | ||||
522 | { | ||||
523 | poly_uint64 regsize = REGMODE_NATURAL_SIZE (struct_mode)ix86_regmode_natural_size (struct_mode); | ||||
524 | if (BYTES_BIG_ENDIAN0) | ||||
525 | return (multiple_p (bitnum, BITS_PER_UNIT(8)) | ||||
526 | && (known_eq (bitnum + bitsize, GET_MODE_BITSIZE (struct_mode))(!maybe_ne (bitnum + bitsize, GET_MODE_BITSIZE (struct_mode)) ) | ||||
527 | || multiple_p (bitnum + bitsize, | ||||
528 | regsize * BITS_PER_UNIT(8)))); | ||||
529 | else | ||||
530 | return multiple_p (bitnum, regsize * BITS_PER_UNIT(8)); | ||||
531 | } | ||||
532 | |||||
533 | /* Return true if -fstrict-volatile-bitfields applies to an access of OP0 | ||||
534 | containing BITSIZE bits starting at BITNUM, with field mode FIELDMODE. | ||||
535 | Return false if the access would touch memory outside the range | ||||
536 | BITREGION_START to BITREGION_END for conformance to the C++ memory | ||||
537 | model. */ | ||||
538 | |||||
539 | static bool | ||||
540 | strict_volatile_bitfield_p (rtx op0, unsigned HOST_WIDE_INTlong bitsize, | ||||
541 | unsigned HOST_WIDE_INTlong bitnum, | ||||
542 | scalar_int_mode fieldmode, | ||||
543 | poly_uint64 bitregion_start, | ||||
544 | poly_uint64 bitregion_end) | ||||
545 | { | ||||
546 | unsigned HOST_WIDE_INTlong modesize = GET_MODE_BITSIZE (fieldmode); | ||||
547 | |||||
548 | /* -fstrict-volatile-bitfields must be enabled and we must have a | ||||
549 | volatile MEM. */ | ||||
550 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
551 | || !MEM_VOLATILE_P (op0)(__extension__ ({ __typeof ((op0)) const _rtx = ((op0)); if ( ((enum rtx_code) (_rtx)->code) != MEM && ((enum rtx_code ) (_rtx)->code) != ASM_OPERANDS && ((enum rtx_code ) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 551, __FUNCTION__); _rtx; })->volatil) | ||||
552 | || flag_strict_volatile_bitfieldsglobal_options.x_flag_strict_volatile_bitfields <= 0) | ||||
553 | return false; | ||||
554 | |||||
555 | /* The bit size must not be larger than the field mode, and | ||||
556 | the field mode must not be larger than a word. */ | ||||
557 | if (bitsize > modesize || modesize > BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
558 | return false; | ||||
559 | |||||
560 | /* Check for cases of unaligned fields that must be split. */ | ||||
561 | if (bitnum % modesize + bitsize > modesize) | ||||
562 | return false; | ||||
563 | |||||
564 | /* The memory must be sufficiently aligned for a MODESIZE access. | ||||
565 | This condition guarantees, that the memory access will not | ||||
566 | touch anything after the end of the structure. */ | ||||
567 | if (MEM_ALIGN (op0)(get_mem_attrs (op0)->align) < modesize) | ||||
568 | return false; | ||||
569 | |||||
570 | /* Check for cases where the C++ memory model applies. */ | ||||
571 | if (maybe_ne (bitregion_end, 0U) | ||||
572 | && (maybe_lt (bitnum - bitnum % modesize, bitregion_start) | ||||
573 | || maybe_gt (bitnum - bitnum % modesize + modesize - 1,maybe_lt (bitregion_end, bitnum - bitnum % modesize + modesize - 1) | ||||
574 | bitregion_end)maybe_lt (bitregion_end, bitnum - bitnum % modesize + modesize - 1))) | ||||
575 | return false; | ||||
576 | |||||
577 | return true; | ||||
578 | } | ||||
579 | |||||
580 | /* Return true if OP is a memory and if a bitfield of size BITSIZE at | ||||
581 | bit number BITNUM can be treated as a simple value of mode MODE. | ||||
582 | Store the byte offset in *BYTENUM if so. */ | ||||
583 | |||||
584 | static bool | ||||
585 | simple_mem_bitfield_p (rtx op0, poly_uint64 bitsize, poly_uint64 bitnum, | ||||
586 | machine_mode mode, poly_uint64 *bytenum) | ||||
587 | { | ||||
588 | return (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
589 | && multiple_p (bitnum, BITS_PER_UNIT(8), bytenum) | ||||
590 | && known_eq (bitsize, GET_MODE_BITSIZE (mode))(!maybe_ne (bitsize, GET_MODE_BITSIZE (mode))) | ||||
591 | && (!targetm.slow_unaligned_access (mode, MEM_ALIGN (op0)(get_mem_attrs (op0)->align)) | ||||
592 | || (multiple_p (bitnum, GET_MODE_ALIGNMENT (mode)get_mode_alignment (mode)) | ||||
593 | && MEM_ALIGN (op0)(get_mem_attrs (op0)->align) >= GET_MODE_ALIGNMENT (mode)get_mode_alignment (mode)))); | ||||
594 | } | ||||
595 | |||||
596 | /* Try to use instruction INSV to store VALUE into a field of OP0. | ||||
597 | If OP0_MODE is defined, it is the mode of OP0, otherwise OP0 is a | ||||
598 | BLKmode MEM. VALUE_MODE is the mode of VALUE. BITSIZE and BITNUM | ||||
599 | are as for store_bit_field. */ | ||||
600 | |||||
601 | static bool | ||||
602 | store_bit_field_using_insv (const extraction_insn *insv, rtx op0, | ||||
603 | opt_scalar_int_mode op0_mode, | ||||
604 | unsigned HOST_WIDE_INTlong bitsize, | ||||
605 | unsigned HOST_WIDE_INTlong bitnum, | ||||
606 | rtx value, scalar_int_mode value_mode) | ||||
607 | { | ||||
608 | class expand_operand ops[4]; | ||||
609 | rtx value1; | ||||
610 | rtx xop0 = op0; | ||||
611 | rtx_insn *last = get_last_insn (); | ||||
612 | bool copy_back = false; | ||||
613 | |||||
614 | scalar_int_mode op_mode = insv->field_mode; | ||||
615 | unsigned int unit = GET_MODE_BITSIZE (op_mode); | ||||
616 | if (bitsize == 0 || bitsize > unit) | ||||
617 | return false; | ||||
618 | |||||
619 | if (MEM_P (xop0)(((enum rtx_code) (xop0)->code) == MEM)) | ||||
620 | /* Get a reference to the first byte of the field. */ | ||||
621 | xop0 = narrow_bit_field_mem (xop0, insv->struct_mode, bitsize, bitnum, | ||||
622 | &bitnum); | ||||
623 | else | ||||
624 | { | ||||
625 | /* Convert from counting within OP0 to counting in OP_MODE. */ | ||||
626 | if (BYTES_BIG_ENDIAN0) | ||||
627 | bitnum += unit - GET_MODE_BITSIZE (op0_mode.require ()); | ||||
628 | |||||
629 | /* If xop0 is a register, we need it in OP_MODE | ||||
630 | to make it acceptable to the format of insv. */ | ||||
631 | if (GET_CODE (xop0)((enum rtx_code) (xop0)->code) == SUBREG) | ||||
632 | { | ||||
633 | /* If such a SUBREG can't be created, give up. */ | ||||
634 | if (!validate_subreg (op_mode, GET_MODE (SUBREG_REG (xop0))((machine_mode) ((((xop0)->u.fld[0]).rt_rtx))->mode), | ||||
635 | SUBREG_REG (xop0)(((xop0)->u.fld[0]).rt_rtx), SUBREG_BYTE (xop0)(((xop0)->u.fld[1]).rt_subreg))) | ||||
636 | return false; | ||||
637 | /* We can't just change the mode, because this might clobber op0, | ||||
638 | and we will need the original value of op0 if insv fails. */ | ||||
639 | xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0)(((xop0)->u.fld[0]).rt_rtx), | ||||
640 | SUBREG_BYTE (xop0)(((xop0)->u.fld[1]).rt_subreg)); | ||||
641 | } | ||||
642 | if (REG_P (xop0)(((enum rtx_code) (xop0)->code) == REG) && GET_MODE (xop0)((machine_mode) (xop0)->mode) != op_mode) | ||||
643 | xop0 = gen_lowpart_SUBREG (op_mode, xop0); | ||||
644 | } | ||||
645 | |||||
646 | /* If the destination is a paradoxical subreg such that we need a | ||||
647 | truncate to the inner mode, perform the insertion on a temporary and | ||||
648 | truncate the result to the original destination. Note that we can't | ||||
649 | just truncate the paradoxical subreg as (truncate:N (subreg:W (reg:N | ||||
650 | X) 0)) is (reg:N X). */ | ||||
651 | if (GET_CODE (xop0)((enum rtx_code) (xop0)->code) == SUBREG | ||||
652 | && REG_P (SUBREG_REG (xop0))(((enum rtx_code) ((((xop0)->u.fld[0]).rt_rtx))->code) == REG) | ||||
653 | && !TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (SUBREG_REG (xop0)),(targetm.truly_noop_truncation (GET_MODE_PRECISION (((machine_mode ) ((((xop0)->u.fld[0]).rt_rtx))->mode)), GET_MODE_PRECISION (op_mode))) | ||||
654 | op_mode)(targetm.truly_noop_truncation (GET_MODE_PRECISION (((machine_mode ) ((((xop0)->u.fld[0]).rt_rtx))->mode)), GET_MODE_PRECISION (op_mode)))) | ||||
655 | { | ||||
656 | rtx tem = gen_reg_rtx (op_mode); | ||||
657 | emit_move_insn (tem, xop0); | ||||
658 | xop0 = tem; | ||||
659 | copy_back = true; | ||||
660 | } | ||||
661 | |||||
662 | /* There are similar overflow check at the start of store_bit_field_1, | ||||
663 | but that only check the situation where the field lies completely | ||||
664 | outside the register, while there do have situation where the field | ||||
665 | lies partialy in the register, we need to adjust bitsize for this | ||||
666 | partial overflow situation. Without this fix, pr48335-2.c on big-endian | ||||
667 | will broken on those arch support bit insert instruction, like arm, aarch64 | ||||
668 | etc. */ | ||||
669 | if (bitsize + bitnum > unit && bitnum < unit) | ||||
670 | { | ||||
671 | warning (OPT_Wextra, "write of %wu-bit data outside the bound of " | ||||
672 | "destination object, data truncated into %wu-bit", | ||||
673 | bitsize, unit - bitnum); | ||||
674 | bitsize = unit - bitnum; | ||||
675 | } | ||||
676 | |||||
677 | /* If BITS_BIG_ENDIAN is zero on a BYTES_BIG_ENDIAN machine, we count | ||||
678 | "backwards" from the size of the unit we are inserting into. | ||||
679 | Otherwise, we count bits from the most significant on a | ||||
680 | BYTES/BITS_BIG_ENDIAN machine. */ | ||||
681 | |||||
682 | if (BITS_BIG_ENDIAN0 != BYTES_BIG_ENDIAN0) | ||||
683 | bitnum = unit - bitsize - bitnum; | ||||
684 | |||||
685 | /* Convert VALUE to op_mode (which insv insn wants) in VALUE1. */ | ||||
686 | value1 = value; | ||||
687 | if (value_mode != op_mode) | ||||
688 | { | ||||
689 | if (GET_MODE_BITSIZE (value_mode) >= bitsize) | ||||
690 | { | ||||
691 | rtx tmp; | ||||
692 | /* Optimization: Don't bother really extending VALUE | ||||
693 | if it has all the bits we will actually use. However, | ||||
694 | if we must narrow it, be sure we do it correctly. */ | ||||
695 | |||||
696 | if (GET_MODE_SIZE (value_mode) < GET_MODE_SIZE (op_mode)) | ||||
697 | { | ||||
698 | tmp = simplify_subreg (op_mode, value1, value_mode, 0); | ||||
699 | if (! tmp) | ||||
700 | tmp = simplify_gen_subreg (op_mode, | ||||
701 | force_reg (value_mode, value1), | ||||
702 | value_mode, 0); | ||||
703 | } | ||||
704 | else | ||||
705 | { | ||||
706 | tmp = gen_lowpart_if_possible (op_mode, value1); | ||||
707 | if (! tmp) | ||||
708 | tmp = gen_lowpartrtl_hooks.gen_lowpart (op_mode, force_reg (value_mode, value1)); | ||||
709 | } | ||||
710 | value1 = tmp; | ||||
711 | } | ||||
712 | else if (CONST_INT_P (value)(((enum rtx_code) (value)->code) == CONST_INT)) | ||||
713 | value1 = gen_int_mode (INTVAL (value)((value)->u.hwint[0]), op_mode); | ||||
714 | else | ||||
715 | /* Parse phase is supposed to make VALUE's data type | ||||
716 | match that of the component reference, which is a type | ||||
717 | at least as wide as the field; so VALUE should have | ||||
718 | a mode that corresponds to that type. */ | ||||
719 | gcc_assert (CONSTANT_P (value))((void)(!(((rtx_class[(int) (((enum rtx_code) (value)->code ))]) == RTX_CONST_OBJ)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 719, __FUNCTION__), 0 : 0)); | ||||
720 | } | ||||
721 | |||||
722 | create_fixed_operand (&ops[0], xop0); | ||||
723 | create_integer_operand (&ops[1], bitsize); | ||||
724 | create_integer_operand (&ops[2], bitnum); | ||||
725 | create_input_operand (&ops[3], value1, op_mode); | ||||
726 | if (maybe_expand_insn (insv->icode, 4, ops)) | ||||
727 | { | ||||
728 | if (copy_back) | ||||
729 | convert_move (op0, xop0, true); | ||||
730 | return true; | ||||
731 | } | ||||
732 | delete_insns_since (last); | ||||
733 | return false; | ||||
734 | } | ||||
735 | |||||
736 | /* A subroutine of store_bit_field, with the same arguments. Return true | ||||
737 | if the operation could be implemented. | ||||
738 | |||||
739 | If FALLBACK_P is true, fall back to store_fixed_bit_field if we have | ||||
740 | no other way of implementing the operation. If FALLBACK_P is false, | ||||
741 | return false instead. | ||||
742 | |||||
743 | if UNDEFINED_P is true then STR_RTX is undefined and may be set using | ||||
744 | a subreg instead. */ | ||||
745 | |||||
746 | static bool | ||||
747 | store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, | ||||
748 | poly_uint64 bitregion_start, poly_uint64 bitregion_end, | ||||
749 | machine_mode fieldmode, | ||||
750 | rtx value, bool reverse, bool fallback_p, bool undefined_p) | ||||
751 | { | ||||
752 | rtx op0 = str_rtx; | ||||
753 | |||||
754 | while (GET_CODE (op0)((enum rtx_code) (op0)->code) == SUBREG) | ||||
755 | { | ||||
756 | bitnum += subreg_memory_offset (op0) * BITS_PER_UNIT(8); | ||||
757 | op0 = SUBREG_REG (op0)(((op0)->u.fld[0]).rt_rtx); | ||||
758 | } | ||||
759 | |||||
760 | /* No action is needed if the target is a register and if the field | ||||
761 | lies completely outside that register. This can occur if the source | ||||
762 | code contains an out-of-bounds access to a small array. */ | ||||
763 | if (REG_P (op0)(((enum rtx_code) (op0)->code) == REG) && known_ge (bitnum, GET_MODE_BITSIZE (GET_MODE (op0)))(!maybe_lt (bitnum, GET_MODE_BITSIZE (((machine_mode) (op0)-> mode))))) | ||||
764 | return true; | ||||
765 | |||||
766 | /* Use vec_set patterns for inserting parts of vectors whenever | ||||
767 | available. */ | ||||
768 | machine_mode outermode = GET_MODE (op0)((machine_mode) (op0)->mode); | ||||
769 | scalar_mode innermode = GET_MODE_INNER (outermode)(mode_to_inner (outermode)); | ||||
770 | poly_uint64 pos; | ||||
771 | if (VECTOR_MODE_P (outermode)(((enum mode_class) mode_class[outermode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_UACCUM ) | ||||
772 | && !MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
773 | && optab_handler (vec_set_optab, outermode) != CODE_FOR_nothing | ||||
774 | && fieldmode == innermode | ||||
775 | && known_eq (bitsize, GET_MODE_BITSIZE (innermode))(!maybe_ne (bitsize, GET_MODE_BITSIZE (innermode))) | ||||
776 | && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos)) | ||||
777 | { | ||||
778 | class expand_operand ops[3]; | ||||
779 | enum insn_code icode = optab_handler (vec_set_optab, outermode); | ||||
780 | |||||
781 | create_fixed_operand (&ops[0], op0); | ||||
782 | create_input_operand (&ops[1], value, innermode); | ||||
783 | create_integer_operand (&ops[2], pos); | ||||
784 | if (maybe_expand_insn (icode, 3, ops)) | ||||
785 | return true; | ||||
786 | } | ||||
787 | |||||
788 | /* If the target is a register, overwriting the entire object, or storing | ||||
789 | a full-word or multi-word field can be done with just a SUBREG. */ | ||||
790 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
791 | && known_eq (bitsize, GET_MODE_BITSIZE (fieldmode))(!maybe_ne (bitsize, GET_MODE_BITSIZE (fieldmode)))) | ||||
792 | { | ||||
793 | /* Use the subreg machinery either to narrow OP0 to the required | ||||
794 | words or to cope with mode punning between equal-sized modes. | ||||
795 | In the latter case, use subreg on the rhs side, not lhs. */ | ||||
796 | rtx sub; | ||||
797 | poly_uint64 bytenum; | ||||
798 | poly_uint64 regsize = REGMODE_NATURAL_SIZE (GET_MODE (op0))ix86_regmode_natural_size (((machine_mode) (op0)->mode)); | ||||
799 | if (known_eq (bitnum, 0U)(!maybe_ne (bitnum, 0U)) | ||||
800 | && known_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0)))(!maybe_ne (bitsize, GET_MODE_BITSIZE (((machine_mode) (op0)-> mode))))) | ||||
801 | { | ||||
802 | sub = simplify_gen_subreg (GET_MODE (op0)((machine_mode) (op0)->mode), value, fieldmode, 0); | ||||
803 | if (sub) | ||||
804 | { | ||||
805 | if (reverse) | ||||
806 | sub = flip_storage_order (GET_MODE (op0)((machine_mode) (op0)->mode), sub); | ||||
807 | emit_move_insn (op0, sub); | ||||
808 | return true; | ||||
809 | } | ||||
810 | } | ||||
811 | else if (multiple_p (bitnum, BITS_PER_UNIT(8), &bytenum) | ||||
812 | && (undefined_p | ||||
813 | || (multiple_p (bitnum, regsize * BITS_PER_UNIT(8)) | ||||
814 | && multiple_p (bitsize, regsize * BITS_PER_UNIT(8)))) | ||||
815 | && known_ge (GET_MODE_BITSIZE (GET_MODE (op0)), bitsize)(!maybe_lt (GET_MODE_BITSIZE (((machine_mode) (op0)->mode) ), bitsize))) | ||||
816 | { | ||||
817 | sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0)((machine_mode) (op0)->mode), bytenum); | ||||
818 | if (sub) | ||||
819 | { | ||||
820 | if (reverse) | ||||
821 | value = flip_storage_order (fieldmode, value); | ||||
822 | emit_move_insn (sub, value); | ||||
823 | return true; | ||||
824 | } | ||||
825 | } | ||||
826 | } | ||||
827 | |||||
828 | /* If the target is memory, storing any naturally aligned field can be | ||||
829 | done with a simple store. For targets that support fast unaligned | ||||
830 | memory, any naturally sized, unit aligned field can be done directly. */ | ||||
831 | poly_uint64 bytenum; | ||||
832 | if (simple_mem_bitfield_p (op0, bitsize, bitnum, fieldmode, &bytenum)) | ||||
833 | { | ||||
834 | op0 = adjust_bitfield_address (op0, fieldmode, bytenum)adjust_address_1 (op0, fieldmode, bytenum, 1, 1, 1, 0); | ||||
835 | if (reverse) | ||||
836 | value = flip_storage_order (fieldmode, value); | ||||
837 | emit_move_insn (op0, value); | ||||
838 | return true; | ||||
839 | } | ||||
840 | |||||
841 | /* It's possible we'll need to handle other cases here for | ||||
842 | polynomial bitnum and bitsize. */ | ||||
843 | |||||
844 | /* From here on we need to be looking at a fixed-size insertion. */ | ||||
845 | unsigned HOST_WIDE_INTlong ibitsize = bitsize.to_constant (); | ||||
846 | unsigned HOST_WIDE_INTlong ibitnum = bitnum.to_constant (); | ||||
847 | |||||
848 | /* Make sure we are playing with integral modes. Pun with subregs | ||||
849 | if we aren't. This must come after the entire register case above, | ||||
850 | since that case is valid for any mode. The following cases are only | ||||
851 | valid for integral modes. */ | ||||
852 | opt_scalar_int_mode op0_mode = int_mode_for_mode (GET_MODE (op0)((machine_mode) (op0)->mode)); | ||||
853 | scalar_int_mode imode; | ||||
854 | if (!op0_mode.exists (&imode) || imode != GET_MODE (op0)((machine_mode) (op0)->mode)) | ||||
855 | { | ||||
856 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | ||||
857 | op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),adjust_address_1 (op0, op0_mode.else_blk (), 0, 1, 1, 1, (get_mem_attrs (op0)->size)) | ||||
858 | 0, MEM_SIZE (op0))adjust_address_1 (op0, op0_mode.else_blk (), 0, 1, 1, 1, (get_mem_attrs (op0)->size)); | ||||
859 | else if (!op0_mode.exists ()) | ||||
860 | { | ||||
861 | if (ibitnum == 0 | ||||
862 | && known_eq (ibitsize, GET_MODE_BITSIZE (GET_MODE (op0)))(!maybe_ne (ibitsize, GET_MODE_BITSIZE (((machine_mode) (op0) ->mode)))) | ||||
863 | && MEM_P (value)(((enum rtx_code) (value)->code) == MEM) | ||||
864 | && !reverse) | ||||
865 | { | ||||
866 | value = adjust_address (value, GET_MODE (op0), 0)adjust_address_1 (value, ((machine_mode) (op0)->mode), 0, 1 , 1, 0, 0); | ||||
867 | emit_move_insn (op0, value); | ||||
868 | return true; | ||||
869 | } | ||||
870 | if (!fallback_p) | ||||
871 | return false; | ||||
872 | rtx temp = assign_stack_temp (GET_MODE (op0)((machine_mode) (op0)->mode), | ||||
873 | GET_MODE_SIZE (GET_MODE (op0)((machine_mode) (op0)->mode))); | ||||
874 | emit_move_insn (temp, op0); | ||||
875 | store_bit_field_1 (temp, bitsize, bitnum, 0, 0, fieldmode, value, | ||||
876 | reverse, fallback_p, undefined_p); | ||||
877 | emit_move_insn (op0, temp); | ||||
878 | return true; | ||||
879 | } | ||||
880 | else | ||||
881 | op0 = gen_lowpartrtl_hooks.gen_lowpart (op0_mode.require (), op0); | ||||
882 | } | ||||
883 | |||||
884 | return store_integral_bit_field (op0, op0_mode, ibitsize, ibitnum, | ||||
885 | bitregion_start, bitregion_end, | ||||
886 | fieldmode, value, reverse, fallback_p); | ||||
887 | } | ||||
888 | |||||
889 | /* Subroutine of store_bit_field_1, with the same arguments, except | ||||
890 | that BITSIZE and BITNUM are constant. Handle cases specific to | ||||
891 | integral modes. If OP0_MODE is defined, it is the mode of OP0, | ||||
892 | otherwise OP0 is a BLKmode MEM. */ | ||||
893 | |||||
894 | static bool | ||||
895 | store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, | ||||
896 | unsigned HOST_WIDE_INTlong bitsize, | ||||
897 | unsigned HOST_WIDE_INTlong bitnum, | ||||
898 | poly_uint64 bitregion_start, | ||||
899 | poly_uint64 bitregion_end, | ||||
900 | machine_mode fieldmode, | ||||
901 | rtx value, bool reverse, bool fallback_p) | ||||
902 | { | ||||
903 | /* Storing an lsb-aligned field in a register | ||||
904 | can be done with a movstrict instruction. */ | ||||
905 | |||||
906 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
| |||||
907 | && !reverse | ||||
908 | && lowpart_bit_field_p (bitnum, bitsize, op0_mode.require ()) | ||||
909 | && known_eq (bitsize, GET_MODE_BITSIZE (fieldmode))(!maybe_ne (bitsize, GET_MODE_BITSIZE (fieldmode))) | ||||
910 | && optab_handler (movstrict_optab, fieldmode) != CODE_FOR_nothing) | ||||
911 | { | ||||
912 | class expand_operand ops[2]; | ||||
913 | enum insn_code icode = optab_handler (movstrict_optab, fieldmode); | ||||
914 | rtx arg0 = op0; | ||||
915 | unsigned HOST_WIDE_INTlong subreg_off; | ||||
916 | |||||
917 | if (GET_CODE (arg0)((enum rtx_code) (arg0)->code) == SUBREG) | ||||
918 | { | ||||
919 | /* Else we've got some float mode source being extracted into | ||||
920 | a different float mode destination -- this combination of | ||||
921 | subregs results in Severe Tire Damage. */ | ||||
922 | gcc_assert (GET_MODE (SUBREG_REG (arg0)) == fieldmode((void)(!(((machine_mode) ((((arg0)->u.fld[0]).rt_rtx))-> mode) == fieldmode || ((enum mode_class) mode_class[fieldmode ]) == MODE_INT || ((enum mode_class) mode_class[fieldmode]) == MODE_PARTIAL_INT) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 924, __FUNCTION__), 0 : 0)) | ||||
923 | || GET_MODE_CLASS (fieldmode) == MODE_INT((void)(!(((machine_mode) ((((arg0)->u.fld[0]).rt_rtx))-> mode) == fieldmode || ((enum mode_class) mode_class[fieldmode ]) == MODE_INT || ((enum mode_class) mode_class[fieldmode]) == MODE_PARTIAL_INT) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 924, __FUNCTION__), 0 : 0)) | ||||
924 | || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)((void)(!(((machine_mode) ((((arg0)->u.fld[0]).rt_rtx))-> mode) == fieldmode || ((enum mode_class) mode_class[fieldmode ]) == MODE_INT || ((enum mode_class) mode_class[fieldmode]) == MODE_PARTIAL_INT) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 924, __FUNCTION__), 0 : 0)); | ||||
925 | arg0 = SUBREG_REG (arg0)(((arg0)->u.fld[0]).rt_rtx); | ||||
926 | } | ||||
927 | |||||
928 | subreg_off = bitnum / BITS_PER_UNIT(8); | ||||
929 | if (validate_subreg (fieldmode, GET_MODE (arg0)((machine_mode) (arg0)->mode), arg0, subreg_off) | ||||
930 | /* STRICT_LOW_PART must have a non-paradoxical subreg as | ||||
931 | operand. */ | ||||
932 | && !paradoxical_subreg_p (fieldmode, GET_MODE (arg0)((machine_mode) (arg0)->mode))) | ||||
933 | { | ||||
934 | arg0 = gen_rtx_SUBREG (fieldmode, arg0, subreg_off); | ||||
935 | |||||
936 | create_fixed_operand (&ops[0], arg0); | ||||
937 | /* Shrink the source operand to FIELDMODE. */ | ||||
938 | create_convert_operand_to (&ops[1], value, fieldmode, false); | ||||
939 | if (maybe_expand_insn (icode, 2, ops)) | ||||
940 | return true; | ||||
941 | } | ||||
942 | } | ||||
943 | |||||
944 | /* Handle fields bigger than a word. */ | ||||
945 | |||||
946 | if (bitsize > BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
947 | { | ||||
948 | /* Here we transfer the words of the field | ||||
949 | in the order least significant first. | ||||
950 | This is because the most significant word is the one which may | ||||
951 | be less than full. | ||||
952 | However, only do that if the value is not BLKmode. */ | ||||
953 | |||||
954 | const bool backwards = WORDS_BIG_ENDIAN0 && fieldmode != BLKmode((void) 0, E_BLKmode); | ||||
955 | const int nwords = (bitsize + (BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) - 1)) / BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
956 | rtx_insn *last; | ||||
957 | |||||
958 | /* This is the mode we must force value to, so that there will be enough | ||||
959 | subwords to extract. Note that fieldmode will often (always?) be | ||||
960 | VOIDmode, because that is what store_field uses to indicate that this | ||||
961 | is a bit field, but passing VOIDmode to operand_subword_force | ||||
962 | is not allowed. | ||||
963 | |||||
964 | The mode must be fixed-size, since insertions into variable-sized | ||||
965 | objects are meant to be handled before calling this function. */ | ||||
966 | fixed_size_mode value_mode = as_a <fixed_size_mode> (GET_MODE (value)((machine_mode) (value)->mode)); | ||||
967 | if (value_mode == VOIDmode((void) 0, E_VOIDmode)) | ||||
968 | value_mode = smallest_int_mode_for_size (nwords * BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))); | ||||
969 | |||||
970 | last = get_last_insn (); | ||||
971 | for (int i = 0; i < nwords; i++) | ||||
972 | { | ||||
973 | /* Number of bits to be stored in this iteration, i.e. BITS_PER_WORD | ||||
974 | except maybe for the last iteration. */ | ||||
975 | const unsigned HOST_WIDE_INTlong new_bitsize | ||||
976 | = MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD)((((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) < (bitsize - i * ((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) ? ( ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) : (bitsize - i * ((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)))); | ||||
977 | /* Bit offset from the starting bit number in the target. */ | ||||
978 | const unsigned int bit_offset | ||||
979 | = backwards ^ reverse | ||||
980 | ? MAX ((int) bitsize - (i + 1) * BITS_PER_WORD, 0)(((int) bitsize - (i + 1) * ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) > (0) ? ((int) bitsize - (i + 1) * ((8) * (((global_options.x_ix86_isa_flags & ( 1UL << 1)) != 0) ? 8 : 4))) : (0)) | ||||
981 | : i * BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
982 | /* Starting word number in the value. */ | ||||
983 | const unsigned int wordnum | ||||
984 | = backwards | ||||
985 | ? GET_MODE_SIZE (value_mode) / UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4) - (i + 1) | ||||
986 | : i; | ||||
987 | /* The chunk of the value in word_mode. We use bit-field extraction | ||||
988 | in BLKmode to handle unaligned memory references and to shift the | ||||
989 | last chunk right on big-endian machines if need be. */ | ||||
990 | rtx value_word | ||||
991 | = fieldmode == BLKmode((void) 0, E_BLKmode) | ||||
992 | ? extract_bit_field (value, new_bitsize, wordnum * BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)), | ||||
993 | 1, NULL_RTX(rtx) 0, word_mode, word_mode, false, | ||||
994 | NULLnullptr) | ||||
995 | : operand_subword_force (value, wordnum, value_mode); | ||||
996 | |||||
997 | if (!store_bit_field_1 (op0, new_bitsize, | ||||
998 | bitnum + bit_offset, | ||||
999 | bitregion_start, bitregion_end, | ||||
1000 | word_mode, | ||||
1001 | value_word, reverse, fallback_p, false)) | ||||
1002 | { | ||||
1003 | delete_insns_since (last); | ||||
1004 | return false; | ||||
1005 | } | ||||
1006 | } | ||||
1007 | return true; | ||||
1008 | } | ||||
1009 | |||||
1010 | /* If VALUE has a floating-point or complex mode, access it as an | ||||
1011 | integer of the corresponding size. This can occur on a machine | ||||
1012 | with 64 bit registers that uses SFmode for float. It can also | ||||
1013 | occur for unaligned float or complex fields. */ | ||||
1014 | rtx orig_value = value; | ||||
1015 | scalar_int_mode value_mode; | ||||
1016 | if (GET_MODE (value)((machine_mode) (value)->mode) == VOIDmode((void) 0, E_VOIDmode)) | ||||
1017 | /* By this point we've dealt with values that are bigger than a word, | ||||
1018 | so word_mode is a conservatively correct choice. */ | ||||
1019 | value_mode = word_mode; | ||||
1020 | else if (!is_a <scalar_int_mode> (GET_MODE (value)((machine_mode) (value)->mode), &value_mode)) | ||||
1021 | { | ||||
1022 | value_mode = int_mode_for_mode (GET_MODE (value)((machine_mode) (value)->mode)).require (); | ||||
1023 | value = gen_reg_rtx (value_mode); | ||||
1024 | emit_move_insn (gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (orig_value)((machine_mode) (orig_value)->mode), value), orig_value); | ||||
1025 | } | ||||
1026 | |||||
1027 | /* If OP0 is a multi-word register, narrow it to the affected word. | ||||
1028 | If the region spans two words, defer to store_split_bit_field. | ||||
1029 | Don't do this if op0 is a single hard register wider than word | ||||
1030 | such as a float or vector register. */ | ||||
1031 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
1032 | && GET_MODE_SIZE (op0_mode.require ()) > UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4) | ||||
1033 | && (!REG_P (op0)(((enum rtx_code) (op0)->code) == REG) | ||||
1034 | || !HARD_REGISTER_P (op0)((((rhs_regno(op0))) < 76)) | ||||
1035 | || hard_regno_nregs (REGNO (op0)(rhs_regno(op0)), op0_mode.require ()) != 1)) | ||||
1036 | { | ||||
1037 | if (bitnum % BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) + bitsize > BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
1038 | { | ||||
1039 | if (!fallback_p) | ||||
1040 | return false; | ||||
1041 | |||||
1042 | store_split_bit_field (op0, op0_mode, bitsize, bitnum, | ||||
1043 | bitregion_start, bitregion_end, | ||||
1044 | value, value_mode, reverse); | ||||
1045 | return true; | ||||
1046 | } | ||||
1047 | op0 = simplify_gen_subreg (word_mode, op0, op0_mode.require (), | ||||
1048 | bitnum / BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) * UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
1049 | gcc_assert (op0)((void)(!(op0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1049, __FUNCTION__), 0 : 0)); | ||||
1050 | op0_mode = word_mode; | ||||
1051 | bitnum %= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
1052 | } | ||||
1053 | |||||
1054 | /* From here on we can assume that the field to be stored in fits | ||||
1055 | within a word. If the destination is a register, it too fits | ||||
1056 | in a word. */ | ||||
1057 | |||||
1058 | extraction_insn insv; | ||||
1059 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
1060 | && !reverse | ||||
1061 | && get_best_reg_extraction_insn (&insv, EP_insv, | ||||
1062 | GET_MODE_BITSIZE (op0_mode.require ()), | ||||
1063 | fieldmode) | ||||
1064 | && store_bit_field_using_insv (&insv, op0, op0_mode, | ||||
1065 | bitsize, bitnum, value, value_mode)) | ||||
1066 | return true; | ||||
1067 | |||||
1068 | /* If OP0 is a memory, try copying it to a register and seeing if a | ||||
1069 | cheap register alternative is available. */ | ||||
1070 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && !reverse) | ||||
1071 | { | ||||
1072 | if (get_best_mem_extraction_insn (&insv, EP_insv, bitsize, bitnum, | ||||
1073 | fieldmode) | ||||
1074 | && store_bit_field_using_insv (&insv, op0, op0_mode, | ||||
1075 | bitsize, bitnum, value, value_mode)) | ||||
1076 | return true; | ||||
1077 | |||||
1078 | rtx_insn *last = get_last_insn (); | ||||
1079 | |||||
1080 | /* Try loading part of OP0 into a register, inserting the bitfield | ||||
1081 | into that, and then copying the result back to OP0. */ | ||||
1082 | unsigned HOST_WIDE_INTlong bitpos; | ||||
1083 | rtx xop0 = adjust_bit_field_mem_for_reg (EP_insv, op0, bitsize, bitnum, | ||||
1084 | bitregion_start, bitregion_end, | ||||
1085 | fieldmode, &bitpos); | ||||
1086 | if (xop0) | ||||
1087 | { | ||||
1088 | rtx tempreg = copy_to_reg (xop0); | ||||
1089 | if (store_bit_field_1 (tempreg, bitsize, bitpos, | ||||
1090 | bitregion_start, bitregion_end, | ||||
1091 | fieldmode, orig_value, reverse, false, false)) | ||||
1092 | { | ||||
1093 | emit_move_insn (xop0, tempreg); | ||||
1094 | return true; | ||||
1095 | } | ||||
1096 | delete_insns_since (last); | ||||
1097 | } | ||||
1098 | } | ||||
1099 | |||||
1100 | if (!fallback_p) | ||||
1101 | return false; | ||||
1102 | |||||
1103 | store_fixed_bit_field (op0, op0_mode, bitsize, bitnum, bitregion_start, | ||||
1104 | bitregion_end, value, value_mode, reverse); | ||||
1105 | return true; | ||||
1106 | } | ||||
1107 | |||||
1108 | /* Generate code to store value from rtx VALUE | ||||
1109 | into a bit-field within structure STR_RTX | ||||
1110 | containing BITSIZE bits starting at bit BITNUM. | ||||
1111 | |||||
1112 | BITREGION_START is bitpos of the first bitfield in this region. | ||||
1113 | BITREGION_END is the bitpos of the ending bitfield in this region. | ||||
1114 | These two fields are 0, if the C++ memory model does not apply, | ||||
1115 | or we are not interested in keeping track of bitfield regions. | ||||
1116 | |||||
1117 | FIELDMODE is the machine-mode of the FIELD_DECL node for this field. | ||||
1118 | |||||
1119 | If REVERSE is true, the store is to be done in reverse order. | ||||
1120 | |||||
1121 | If UNDEFINED_P is true then STR_RTX is currently undefined. */ | ||||
1122 | |||||
1123 | void | ||||
1124 | store_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, | ||||
1125 | poly_uint64 bitregion_start, poly_uint64 bitregion_end, | ||||
1126 | machine_mode fieldmode, | ||||
1127 | rtx value, bool reverse, bool undefined_p) | ||||
1128 | { | ||||
1129 | /* Handle -fstrict-volatile-bitfields in the cases where it applies. */ | ||||
1130 | unsigned HOST_WIDE_INTlong ibitsize = 0, ibitnum = 0; | ||||
1131 | scalar_int_mode int_mode; | ||||
1132 | if (bitsize.is_constant (&ibitsize) | ||||
1133 | && bitnum.is_constant (&ibitnum) | ||||
1134 | && is_a <scalar_int_mode> (fieldmode, &int_mode) | ||||
1135 | && strict_volatile_bitfield_p (str_rtx, ibitsize, ibitnum, int_mode, | ||||
1136 | bitregion_start, bitregion_end)) | ||||
1137 | { | ||||
1138 | /* Storing of a full word can be done with a simple store. | ||||
1139 | We know here that the field can be accessed with one single | ||||
1140 | instruction. For targets that support unaligned memory, | ||||
1141 | an unaligned access may be necessary. */ | ||||
1142 | if (ibitsize == GET_MODE_BITSIZE (int_mode)) | ||||
1143 | { | ||||
1144 | str_rtx = adjust_bitfield_address (str_rtx, int_mode,adjust_address_1 (str_rtx, int_mode, ibitnum / (8), 1, 1, 1, 0 ) | ||||
1145 | ibitnum / BITS_PER_UNIT)adjust_address_1 (str_rtx, int_mode, ibitnum / (8), 1, 1, 1, 0 ); | ||||
1146 | if (reverse) | ||||
1147 | value = flip_storage_order (int_mode, value); | ||||
1148 | gcc_assert (ibitnum % BITS_PER_UNIT == 0)((void)(!(ibitnum % (8) == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1148, __FUNCTION__), 0 : 0)); | ||||
1149 | emit_move_insn (str_rtx, value); | ||||
1150 | } | ||||
1151 | else | ||||
1152 | { | ||||
1153 | rtx temp; | ||||
1154 | |||||
1155 | str_rtx = narrow_bit_field_mem (str_rtx, int_mode, ibitsize, | ||||
1156 | ibitnum, &ibitnum); | ||||
1157 | gcc_assert (ibitnum + ibitsize <= GET_MODE_BITSIZE (int_mode))((void)(!(ibitnum + ibitsize <= GET_MODE_BITSIZE (int_mode )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1157, __FUNCTION__), 0 : 0)); | ||||
1158 | temp = copy_to_reg (str_rtx); | ||||
1159 | if (!store_bit_field_1 (temp, ibitsize, ibitnum, 0, 0, | ||||
1160 | int_mode, value, reverse, true, undefined_p)) | ||||
1161 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1161, __FUNCTION__)); | ||||
1162 | |||||
1163 | emit_move_insn (str_rtx, temp); | ||||
1164 | } | ||||
1165 | |||||
1166 | return; | ||||
1167 | } | ||||
1168 | |||||
1169 | /* Under the C++0x memory model, we must not touch bits outside the | ||||
1170 | bit region. Adjust the address to start at the beginning of the | ||||
1171 | bit region. */ | ||||
1172 | if (MEM_P (str_rtx)(((enum rtx_code) (str_rtx)->code) == MEM) && maybe_ne (bitregion_start, 0U)) | ||||
1173 | { | ||||
1174 | scalar_int_mode best_mode; | ||||
1175 | machine_mode addr_mode = VOIDmode((void) 0, E_VOIDmode); | ||||
1176 | |||||
1177 | poly_uint64 offset = exact_div (bitregion_start, BITS_PER_UNIT(8)); | ||||
1178 | bitnum -= bitregion_start; | ||||
1179 | poly_int64 size = bits_to_bytes_round_up (bitnum + bitsize)force_align_up_and_div (bitnum + bitsize, (8)); | ||||
1180 | bitregion_end -= bitregion_start; | ||||
1181 | bitregion_start = 0; | ||||
1182 | if (bitsize.is_constant (&ibitsize) | ||||
1183 | && bitnum.is_constant (&ibitnum) | ||||
1184 | && get_best_mode (ibitsize, ibitnum, | ||||
1185 | bitregion_start, bitregion_end, | ||||
1186 | MEM_ALIGN (str_rtx)(get_mem_attrs (str_rtx)->align), INT_MAX2147483647, | ||||
1187 | MEM_VOLATILE_P (str_rtx)(__extension__ ({ __typeof ((str_rtx)) const _rtx = ((str_rtx )); if (((enum rtx_code) (_rtx)->code) != MEM && ( (enum rtx_code) (_rtx)->code) != ASM_OPERANDS && ( (enum rtx_code) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1187, __FUNCTION__); _rtx; })->volatil), &best_mode)) | ||||
1188 | addr_mode = best_mode; | ||||
1189 | str_rtx = adjust_bitfield_address_size (str_rtx, addr_mode,adjust_address_1 (str_rtx, addr_mode, offset, 1, 1, 1, size) | ||||
1190 | offset, size)adjust_address_1 (str_rtx, addr_mode, offset, 1, 1, 1, size); | ||||
1191 | } | ||||
1192 | |||||
1193 | if (!store_bit_field_1 (str_rtx, bitsize, bitnum, | ||||
1194 | bitregion_start, bitregion_end, | ||||
1195 | fieldmode, value, reverse, true, undefined_p)) | ||||
1196 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1196, __FUNCTION__)); | ||||
1197 | } | ||||
1198 | |||||
1199 | /* Use shifts and boolean operations to store VALUE into a bit field of | ||||
1200 | width BITSIZE in OP0, starting at bit BITNUM. If OP0_MODE is defined, | ||||
1201 | it is the mode of OP0, otherwise OP0 is a BLKmode MEM. VALUE_MODE is | ||||
1202 | the mode of VALUE. | ||||
1203 | |||||
1204 | If REVERSE is true, the store is to be done in reverse order. */ | ||||
1205 | |||||
1206 | static void | ||||
1207 | store_fixed_bit_field (rtx op0, opt_scalar_int_mode op0_mode, | ||||
1208 | unsigned HOST_WIDE_INTlong bitsize, | ||||
1209 | unsigned HOST_WIDE_INTlong bitnum, | ||||
1210 | poly_uint64 bitregion_start, poly_uint64 bitregion_end, | ||||
1211 | rtx value, scalar_int_mode value_mode, bool reverse) | ||||
1212 | { | ||||
1213 | /* There is a case not handled here: | ||||
1214 | a structure with a known alignment of just a halfword | ||||
1215 | and a field split across two aligned halfwords within the structure. | ||||
1216 | Or likewise a structure with a known alignment of just a byte | ||||
1217 | and a field split across two bytes. | ||||
1218 | Such cases are not supposed to be able to occur. */ | ||||
1219 | |||||
1220 | scalar_int_mode best_mode; | ||||
1221 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | ||||
1222 | { | ||||
1223 | unsigned int max_bitsize = BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
1224 | scalar_int_mode imode; | ||||
1225 | if (op0_mode.exists (&imode) && GET_MODE_BITSIZE (imode) < max_bitsize) | ||||
1226 | max_bitsize = GET_MODE_BITSIZE (imode); | ||||
1227 | |||||
1228 | if (!get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end, | ||||
1229 | MEM_ALIGN (op0)(get_mem_attrs (op0)->align), max_bitsize, MEM_VOLATILE_P (op0)(__extension__ ({ __typeof ((op0)) const _rtx = ((op0)); if ( ((enum rtx_code) (_rtx)->code) != MEM && ((enum rtx_code ) (_rtx)->code) != ASM_OPERANDS && ((enum rtx_code ) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1229, __FUNCTION__); _rtx; })->volatil), | ||||
1230 | &best_mode)) | ||||
1231 | { | ||||
1232 | /* The only way this should occur is if the field spans word | ||||
1233 | boundaries. */ | ||||
1234 | store_split_bit_field (op0, op0_mode, bitsize, bitnum, | ||||
1235 | bitregion_start, bitregion_end, | ||||
1236 | value, value_mode, reverse); | ||||
1237 | return; | ||||
1238 | } | ||||
1239 | |||||
1240 | op0 = narrow_bit_field_mem (op0, best_mode, bitsize, bitnum, &bitnum); | ||||
1241 | } | ||||
1242 | else | ||||
1243 | best_mode = op0_mode.require (); | ||||
1244 | |||||
1245 | store_fixed_bit_field_1 (op0, best_mode, bitsize, bitnum, | ||||
1246 | value, value_mode, reverse); | ||||
1247 | } | ||||
1248 | |||||
1249 | /* Helper function for store_fixed_bit_field, stores | ||||
1250 | the bit field always using MODE, which is the mode of OP0. The other | ||||
1251 | arguments are as for store_fixed_bit_field. */ | ||||
1252 | |||||
1253 | static void | ||||
1254 | store_fixed_bit_field_1 (rtx op0, scalar_int_mode mode, | ||||
1255 | unsigned HOST_WIDE_INTlong bitsize, | ||||
1256 | unsigned HOST_WIDE_INTlong bitnum, | ||||
1257 | rtx value, scalar_int_mode value_mode, bool reverse) | ||||
1258 | { | ||||
1259 | rtx temp; | ||||
1260 | int all_zero = 0; | ||||
1261 | int all_one = 0; | ||||
1262 | |||||
1263 | /* Note that bitsize + bitnum can be greater than GET_MODE_BITSIZE (mode) | ||||
1264 | for invalid input, such as f5 from gcc.dg/pr48335-2.c. */ | ||||
1265 | |||||
1266 | if (reverse ? !BYTES_BIG_ENDIAN0 : BYTES_BIG_ENDIAN0) | ||||
1267 | /* BITNUM is the distance between our msb | ||||
1268 | and that of the containing datum. | ||||
1269 | Convert it to the distance from the lsb. */ | ||||
1270 | bitnum = GET_MODE_BITSIZE (mode) - bitsize - bitnum; | ||||
1271 | |||||
1272 | /* Now BITNUM is always the distance between our lsb | ||||
1273 | and that of OP0. */ | ||||
1274 | |||||
1275 | /* Shift VALUE left by BITNUM bits. If VALUE is not constant, | ||||
1276 | we must first convert its mode to MODE. */ | ||||
1277 | |||||
1278 | if (CONST_INT_P (value)(((enum rtx_code) (value)->code) == CONST_INT)) | ||||
1279 | { | ||||
1280 | unsigned HOST_WIDE_INTlong v = UINTVAL (value)((unsigned long) ((value)->u.hwint[0])); | ||||
1281 | |||||
1282 | if (bitsize < HOST_BITS_PER_WIDE_INT64) | ||||
1283 | v &= (HOST_WIDE_INT_1U1UL << bitsize) - 1; | ||||
1284 | |||||
1285 | if (v == 0) | ||||
1286 | all_zero = 1; | ||||
1287 | else if ((bitsize < HOST_BITS_PER_WIDE_INT64 | ||||
1288 | && v == (HOST_WIDE_INT_1U1UL << bitsize) - 1) | ||||
1289 | || (bitsize == HOST_BITS_PER_WIDE_INT64 | ||||
1290 | && v == HOST_WIDE_INT_M1U-1UL)) | ||||
1291 | all_one = 1; | ||||
1292 | |||||
1293 | value = lshift_value (mode, v, bitnum); | ||||
1294 | } | ||||
1295 | else | ||||
1296 | { | ||||
1297 | int must_and = (GET_MODE_BITSIZE (value_mode) != bitsize | ||||
1298 | && bitnum + bitsize != GET_MODE_BITSIZE (mode)); | ||||
1299 | |||||
1300 | if (value_mode != mode) | ||||
1301 | value = convert_to_mode (mode, value, 1); | ||||
1302 | |||||
1303 | if (must_and) | ||||
1304 | value = expand_binop (mode, and_optab, value, | ||||
1305 | mask_rtx (mode, 0, bitsize, 0), | ||||
1306 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
1307 | if (bitnum > 0) | ||||
1308 | value = expand_shift (LSHIFT_EXPR, mode, value, | ||||
1309 | bitnum, NULL_RTX(rtx) 0, 1); | ||||
1310 | } | ||||
1311 | |||||
1312 | if (reverse) | ||||
1313 | value = flip_storage_order (mode, value); | ||||
1314 | |||||
1315 | /* Now clear the chosen bits in OP0, | ||||
1316 | except that if VALUE is -1 we need not bother. */ | ||||
1317 | /* We keep the intermediates in registers to allow CSE to combine | ||||
1318 | consecutive bitfield assignments. */ | ||||
1319 | |||||
1320 | temp = force_reg (mode, op0); | ||||
1321 | |||||
1322 | if (! all_one) | ||||
1323 | { | ||||
1324 | rtx mask = mask_rtx (mode, bitnum, bitsize, 1); | ||||
1325 | if (reverse) | ||||
1326 | mask = flip_storage_order (mode, mask); | ||||
1327 | temp = expand_binop (mode, and_optab, temp, mask, | ||||
1328 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
1329 | temp = force_reg (mode, temp); | ||||
1330 | } | ||||
1331 | |||||
1332 | /* Now logical-or VALUE into OP0, unless it is zero. */ | ||||
1333 | |||||
1334 | if (! all_zero) | ||||
1335 | { | ||||
1336 | temp = expand_binop (mode, ior_optab, temp, value, | ||||
1337 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
1338 | temp = force_reg (mode, temp); | ||||
1339 | } | ||||
1340 | |||||
1341 | if (op0 != temp) | ||||
1342 | { | ||||
1343 | op0 = copy_rtx (op0); | ||||
1344 | emit_move_insn (op0, temp); | ||||
1345 | } | ||||
1346 | } | ||||
1347 | |||||
1348 | /* Store a bit field that is split across multiple accessible memory objects. | ||||
1349 | |||||
1350 | OP0 is the REG, SUBREG or MEM rtx for the first of the objects. | ||||
1351 | BITSIZE is the field width; BITPOS the position of its first bit | ||||
1352 | (within the word). | ||||
1353 | VALUE is the value to store, which has mode VALUE_MODE. | ||||
1354 | If OP0_MODE is defined, it is the mode of OP0, otherwise OP0 is | ||||
1355 | a BLKmode MEM. | ||||
1356 | |||||
1357 | If REVERSE is true, the store is to be done in reverse order. | ||||
1358 | |||||
1359 | This does not yet handle fields wider than BITS_PER_WORD. */ | ||||
1360 | |||||
1361 | static void | ||||
1362 | store_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, | ||||
1363 | unsigned HOST_WIDE_INTlong bitsize, | ||||
1364 | unsigned HOST_WIDE_INTlong bitpos, | ||||
1365 | poly_uint64 bitregion_start, poly_uint64 bitregion_end, | ||||
1366 | rtx value, scalar_int_mode value_mode, bool reverse) | ||||
1367 | { | ||||
1368 | unsigned int unit, total_bits, bitsdone = 0; | ||||
1369 | |||||
1370 | /* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that | ||||
1371 | much at a time. */ | ||||
1372 | if (REG_P (op0)(((enum rtx_code) (op0)->code) == REG) || GET_CODE (op0)((enum rtx_code) (op0)->code) == SUBREG) | ||||
1373 | unit = BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
1374 | else | ||||
1375 | unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD)(((get_mem_attrs (op0)->align)) < (((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) ? ( (get_mem_attrs (op0)->align)) : (((8) * (((global_options. x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)))); | ||||
1376 | |||||
1377 | /* If OP0 is a memory with a mode, then UNIT must not be larger than | ||||
1378 | OP0's mode as well. Otherwise, store_fixed_bit_field will call us | ||||
1379 | again, and we will mutually recurse forever. */ | ||||
1380 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && op0_mode.exists ()) | ||||
1381 | unit = MIN (unit, GET_MODE_BITSIZE (op0_mode.require ()))((unit) < (GET_MODE_BITSIZE (op0_mode.require ())) ? (unit ) : (GET_MODE_BITSIZE (op0_mode.require ()))); | ||||
1382 | |||||
1383 | /* If VALUE is a constant other than a CONST_INT, get it into a register in | ||||
1384 | WORD_MODE. If we can do this using gen_lowpart_common, do so. Note | ||||
1385 | that VALUE might be a floating-point constant. */ | ||||
1386 | if (CONSTANT_P (value)((rtx_class[(int) (((enum rtx_code) (value)->code))]) == RTX_CONST_OBJ ) && !CONST_INT_P (value)(((enum rtx_code) (value)->code) == CONST_INT)) | ||||
1387 | { | ||||
1388 | rtx word = gen_lowpart_common (word_mode, value); | ||||
1389 | |||||
1390 | if (word && (value != word)) | ||||
1391 | value = word; | ||||
1392 | else | ||||
1393 | value = gen_lowpart_common (word_mode, force_reg (value_mode, value)); | ||||
1394 | value_mode = word_mode; | ||||
1395 | } | ||||
1396 | |||||
1397 | total_bits = GET_MODE_BITSIZE (value_mode); | ||||
1398 | |||||
1399 | while (bitsdone < bitsize) | ||||
1400 | { | ||||
1401 | unsigned HOST_WIDE_INTlong thissize; | ||||
1402 | unsigned HOST_WIDE_INTlong thispos; | ||||
1403 | unsigned HOST_WIDE_INTlong offset; | ||||
1404 | rtx part; | ||||
1405 | |||||
1406 | offset = (bitpos + bitsdone) / unit; | ||||
1407 | thispos = (bitpos + bitsdone) % unit; | ||||
1408 | |||||
1409 | /* When region of bytes we can touch is restricted, decrease | ||||
1410 | UNIT close to the end of the region as needed. If op0 is a REG | ||||
1411 | or SUBREG of REG, don't do this, as there can't be data races | ||||
1412 | on a register and we can expand shorter code in some cases. */ | ||||
1413 | if (maybe_ne (bitregion_end, 0U) | ||||
1414 | && unit > BITS_PER_UNIT(8) | ||||
1415 | && maybe_gt (bitpos + bitsdone - thispos + unit, bitregion_end + 1)maybe_lt (bitregion_end + 1, bitpos + bitsdone - thispos + unit ) | ||||
1416 | && !REG_P (op0)(((enum rtx_code) (op0)->code) == REG) | ||||
1417 | && (GET_CODE (op0)((enum rtx_code) (op0)->code) != SUBREG || !REG_P (SUBREG_REG (op0))(((enum rtx_code) ((((op0)->u.fld[0]).rt_rtx))->code) == REG))) | ||||
1418 | { | ||||
1419 | unit = unit / 2; | ||||
1420 | continue; | ||||
1421 | } | ||||
1422 | |||||
1423 | /* THISSIZE must not overrun a word boundary. Otherwise, | ||||
1424 | store_fixed_bit_field will call us again, and we will mutually | ||||
1425 | recurse forever. */ | ||||
1426 | thissize = MIN (bitsize - bitsdone, BITS_PER_WORD)((bitsize - bitsdone) < (((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) ? (bitsize - bitsdone ) : (((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)))); | ||||
1427 | thissize = MIN (thissize, unit - thispos)((thissize) < (unit - thispos) ? (thissize) : (unit - thispos )); | ||||
1428 | |||||
1429 | if (reverse
| ||||
1430 | { | ||||
1431 | /* Fetch successively less significant portions. */ | ||||
1432 | if (CONST_INT_P (value)(((enum rtx_code) (value)->code) == CONST_INT)) | ||||
1433 | part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (((unsigned long) ( ((value)->u.hwint[0])) >> (bitsize - bitsdone - thissize )) & ((1L << thissize) - 1))) | ||||
| |||||
1434 | >> (bitsize - bitsdone - thissize))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (((unsigned long) ( ((value)->u.hwint[0])) >> (bitsize - bitsdone - thissize )) & ((1L << thissize) - 1))) | ||||
1435 | & ((HOST_WIDE_INT_1 << thissize) - 1))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (((unsigned long) ( ((value)->u.hwint[0])) >> (bitsize - bitsdone - thissize )) & ((1L << thissize) - 1))); | ||||
1436 | /* Likewise, but the source is little-endian. */ | ||||
1437 | else if (reverse) | ||||
1438 | part = extract_fixed_bit_field (word_mode, value, value_mode, | ||||
1439 | thissize, | ||||
1440 | bitsize - bitsdone - thissize, | ||||
1441 | NULL_RTX(rtx) 0, 1, false); | ||||
1442 | else | ||||
1443 | /* The args are chosen so that the last part includes the | ||||
1444 | lsb. Give extract_bit_field the value it needs (with | ||||
1445 | endianness compensation) to fetch the piece we want. */ | ||||
1446 | part = extract_fixed_bit_field (word_mode, value, value_mode, | ||||
1447 | thissize, | ||||
1448 | total_bits - bitsize + bitsdone, | ||||
1449 | NULL_RTX(rtx) 0, 1, false); | ||||
1450 | } | ||||
1451 | else | ||||
1452 | { | ||||
1453 | /* Fetch successively more significant portions. */ | ||||
1454 | if (CONST_INT_P (value)(((enum rtx_code) (value)->code) == CONST_INT)) | ||||
1455 | part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (((unsigned long) ( ((value)->u.hwint[0])) >> bitsdone) & ((1L << thissize) - 1))) | ||||
1456 | >> bitsdone)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (((unsigned long) ( ((value)->u.hwint[0])) >> bitsdone) & ((1L << thissize) - 1))) | ||||
1457 | & ((HOST_WIDE_INT_1 << thissize) - 1))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (((unsigned long) ( ((value)->u.hwint[0])) >> bitsdone) & ((1L << thissize) - 1))); | ||||
1458 | /* Likewise, but the source is big-endian. */ | ||||
1459 | else if (reverse) | ||||
1460 | part = extract_fixed_bit_field (word_mode, value, value_mode, | ||||
1461 | thissize, | ||||
1462 | total_bits - bitsdone - thissize, | ||||
1463 | NULL_RTX(rtx) 0, 1, false); | ||||
1464 | else | ||||
1465 | part = extract_fixed_bit_field (word_mode, value, value_mode, | ||||
1466 | thissize, bitsdone, NULL_RTX(rtx) 0, | ||||
1467 | 1, false); | ||||
1468 | } | ||||
1469 | |||||
1470 | /* If OP0 is a register, then handle OFFSET here. */ | ||||
1471 | rtx op0_piece = op0; | ||||
1472 | opt_scalar_int_mode op0_piece_mode = op0_mode; | ||||
1473 | if (SUBREG_P (op0)(((enum rtx_code) (op0)->code) == SUBREG) || REG_P (op0)(((enum rtx_code) (op0)->code) == REG)) | ||||
1474 | { | ||||
1475 | scalar_int_mode imode; | ||||
1476 | if (op0_mode.exists (&imode) | ||||
1477 | && GET_MODE_SIZE (imode) < UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
1478 | { | ||||
1479 | if (offset) | ||||
1480 | op0_piece = const0_rtx(const_int_rtx[64]); | ||||
1481 | } | ||||
1482 | else | ||||
1483 | { | ||||
1484 | op0_piece = operand_subword_force (op0, | ||||
1485 | offset * unit / BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)), | ||||
1486 | GET_MODE (op0)((machine_mode) (op0)->mode)); | ||||
1487 | op0_piece_mode = word_mode; | ||||
1488 | } | ||||
1489 | offset &= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) / unit - 1; | ||||
1490 | } | ||||
1491 | |||||
1492 | /* OFFSET is in UNITs, and UNIT is in bits. If WORD is const0_rtx, | ||||
1493 | it is just an out-of-bounds access. Ignore it. */ | ||||
1494 | if (op0_piece != const0_rtx(const_int_rtx[64])) | ||||
1495 | store_fixed_bit_field (op0_piece, op0_piece_mode, thissize, | ||||
1496 | offset * unit + thispos, bitregion_start, | ||||
1497 | bitregion_end, part, word_mode, reverse); | ||||
1498 | bitsdone += thissize; | ||||
1499 | } | ||||
1500 | } | ||||
1501 | |||||
1502 | /* A subroutine of extract_bit_field_1 that converts return value X | ||||
1503 | to either MODE or TMODE. MODE, TMODE and UNSIGNEDP are arguments | ||||
1504 | to extract_bit_field. */ | ||||
1505 | |||||
1506 | static rtx | ||||
1507 | convert_extracted_bit_field (rtx x, machine_mode mode, | ||||
1508 | machine_mode tmode, bool unsignedp) | ||||
1509 | { | ||||
1510 | if (GET_MODE (x)((machine_mode) (x)->mode) == tmode || GET_MODE (x)((machine_mode) (x)->mode) == mode) | ||||
1511 | return x; | ||||
1512 | |||||
1513 | /* If the x mode is not a scalar integral, first convert to the | ||||
1514 | integer mode of that size and then access it as a floating-point | ||||
1515 | value via a SUBREG. */ | ||||
1516 | if (!SCALAR_INT_MODE_P (tmode)(((enum mode_class) mode_class[tmode]) == MODE_INT || ((enum mode_class ) mode_class[tmode]) == MODE_PARTIAL_INT)) | ||||
1517 | { | ||||
1518 | scalar_int_mode int_mode = int_mode_for_mode (tmode).require (); | ||||
1519 | x = convert_to_mode (int_mode, x, unsignedp); | ||||
1520 | x = force_reg (int_mode, x); | ||||
1521 | return gen_lowpartrtl_hooks.gen_lowpart (tmode, x); | ||||
1522 | } | ||||
1523 | |||||
1524 | return convert_to_mode (tmode, x, unsignedp); | ||||
1525 | } | ||||
1526 | |||||
1527 | /* Try to use an ext(z)v pattern to extract a field from OP0. | ||||
1528 | Return the extracted value on success, otherwise return null. | ||||
1529 | EXTV describes the extraction instruction to use. If OP0_MODE | ||||
1530 | is defined, it is the mode of OP0, otherwise OP0 is a BLKmode MEM. | ||||
1531 | The other arguments are as for extract_bit_field. */ | ||||
1532 | |||||
1533 | static rtx | ||||
1534 | extract_bit_field_using_extv (const extraction_insn *extv, rtx op0, | ||||
1535 | opt_scalar_int_mode op0_mode, | ||||
1536 | unsigned HOST_WIDE_INTlong bitsize, | ||||
1537 | unsigned HOST_WIDE_INTlong bitnum, | ||||
1538 | int unsignedp, rtx target, | ||||
1539 | machine_mode mode, machine_mode tmode) | ||||
1540 | { | ||||
1541 | class expand_operand ops[4]; | ||||
1542 | rtx spec_target = target; | ||||
1543 | rtx spec_target_subreg = 0; | ||||
1544 | scalar_int_mode ext_mode = extv->field_mode; | ||||
1545 | unsigned unit = GET_MODE_BITSIZE (ext_mode); | ||||
1546 | |||||
1547 | if (bitsize == 0 || unit < bitsize) | ||||
1548 | return NULL_RTX(rtx) 0; | ||||
1549 | |||||
1550 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | ||||
1551 | /* Get a reference to the first byte of the field. */ | ||||
1552 | op0 = narrow_bit_field_mem (op0, extv->struct_mode, bitsize, bitnum, | ||||
1553 | &bitnum); | ||||
1554 | else | ||||
1555 | { | ||||
1556 | /* Convert from counting within OP0 to counting in EXT_MODE. */ | ||||
1557 | if (BYTES_BIG_ENDIAN0) | ||||
1558 | bitnum += unit - GET_MODE_BITSIZE (op0_mode.require ()); | ||||
1559 | |||||
1560 | /* If op0 is a register, we need it in EXT_MODE to make it | ||||
1561 | acceptable to the format of ext(z)v. */ | ||||
1562 | if (GET_CODE (op0)((enum rtx_code) (op0)->code) == SUBREG && op0_mode.require () != ext_mode) | ||||
1563 | return NULL_RTX(rtx) 0; | ||||
1564 | if (REG_P (op0)(((enum rtx_code) (op0)->code) == REG) && op0_mode.require () != ext_mode) | ||||
1565 | op0 = gen_lowpart_SUBREG (ext_mode, op0); | ||||
1566 | } | ||||
1567 | |||||
1568 | /* If BITS_BIG_ENDIAN is zero on a BYTES_BIG_ENDIAN machine, we count | ||||
1569 | "backwards" from the size of the unit we are extracting from. | ||||
1570 | Otherwise, we count bits from the most significant on a | ||||
1571 | BYTES/BITS_BIG_ENDIAN machine. */ | ||||
1572 | |||||
1573 | if (BITS_BIG_ENDIAN0 != BYTES_BIG_ENDIAN0) | ||||
1574 | bitnum = unit - bitsize - bitnum; | ||||
1575 | |||||
1576 | if (target == 0) | ||||
1577 | target = spec_target = gen_reg_rtx (tmode); | ||||
1578 | |||||
1579 | if (GET_MODE (target)((machine_mode) (target)->mode) != ext_mode) | ||||
1580 | { | ||||
1581 | rtx temp; | ||||
1582 | /* Don't use LHS paradoxical subreg if explicit truncation is needed | ||||
1583 | between the mode of the extraction (word_mode) and the target | ||||
1584 | mode. Instead, create a temporary and use convert_move to set | ||||
1585 | the target. */ | ||||
1586 | if (REG_P (target)(((enum rtx_code) (target)->code) == REG) | ||||
1587 | && TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (target), ext_mode)(targetm.truly_noop_truncation (GET_MODE_PRECISION (((machine_mode ) (target)->mode)), GET_MODE_PRECISION (ext_mode))) | ||||
1588 | && (temp = gen_lowpart_if_possible (ext_mode, target))) | ||||
1589 | { | ||||
1590 | target = temp; | ||||
1591 | if (partial_subreg_p (GET_MODE (spec_target)((machine_mode) (spec_target)->mode), ext_mode)) | ||||
1592 | spec_target_subreg = target; | ||||
1593 | } | ||||
1594 | else | ||||
1595 | target = gen_reg_rtx (ext_mode); | ||||
1596 | } | ||||
1597 | |||||
1598 | create_output_operand (&ops[0], target, ext_mode); | ||||
1599 | create_fixed_operand (&ops[1], op0); | ||||
1600 | create_integer_operand (&ops[2], bitsize); | ||||
1601 | create_integer_operand (&ops[3], bitnum); | ||||
1602 | if (maybe_expand_insn (extv->icode, 4, ops)) | ||||
1603 | { | ||||
1604 | target = ops[0].value; | ||||
1605 | if (target == spec_target) | ||||
1606 | return target; | ||||
1607 | if (target == spec_target_subreg) | ||||
1608 | return spec_target; | ||||
1609 | return convert_extracted_bit_field (target, mode, tmode, unsignedp); | ||||
1610 | } | ||||
1611 | return NULL_RTX(rtx) 0; | ||||
1612 | } | ||||
1613 | |||||
1614 | /* See whether it would be valid to extract the part of OP0 with | ||||
1615 | mode OP0_MODE described by BITNUM and BITSIZE into a value of | ||||
1616 | mode MODE using a subreg operation. | ||||
1617 | Return the subreg if so, otherwise return null. */ | ||||
1618 | |||||
1619 | static rtx | ||||
1620 | extract_bit_field_as_subreg (machine_mode mode, rtx op0, | ||||
1621 | machine_mode op0_mode, | ||||
1622 | poly_uint64 bitsize, poly_uint64 bitnum) | ||||
1623 | { | ||||
1624 | poly_uint64 bytenum; | ||||
1625 | if (multiple_p (bitnum, BITS_PER_UNIT(8), &bytenum) | ||||
1626 | && known_eq (bitsize, GET_MODE_BITSIZE (mode))(!maybe_ne (bitsize, GET_MODE_BITSIZE (mode))) | ||||
1627 | && lowpart_bit_field_p (bitnum, bitsize, op0_mode) | ||||
1628 | && TRULY_NOOP_TRUNCATION_MODES_P (mode, op0_mode)(targetm.truly_noop_truncation (GET_MODE_PRECISION (mode), GET_MODE_PRECISION (op0_mode)))) | ||||
1629 | return simplify_gen_subreg (mode, op0, op0_mode, bytenum); | ||||
1630 | return NULL_RTX(rtx) 0; | ||||
1631 | } | ||||
1632 | |||||
1633 | /* A subroutine of extract_bit_field, with the same arguments. | ||||
1634 | If FALLBACK_P is true, fall back to extract_fixed_bit_field | ||||
1635 | if we can find no other means of implementing the operation. | ||||
1636 | if FALLBACK_P is false, return NULL instead. */ | ||||
1637 | |||||
1638 | static rtx | ||||
1639 | extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, | ||||
1640 | int unsignedp, rtx target, machine_mode mode, | ||||
1641 | machine_mode tmode, bool reverse, bool fallback_p, | ||||
1642 | rtx *alt_rtl) | ||||
1643 | { | ||||
1644 | rtx op0 = str_rtx; | ||||
1645 | machine_mode mode1; | ||||
1646 | |||||
1647 | if (tmode == VOIDmode((void) 0, E_VOIDmode)) | ||||
1648 | tmode = mode; | ||||
1649 | |||||
1650 | while (GET_CODE (op0)((enum rtx_code) (op0)->code) == SUBREG) | ||||
1651 | { | ||||
1652 | bitnum += SUBREG_BYTE (op0)(((op0)->u.fld[1]).rt_subreg) * BITS_PER_UNIT(8); | ||||
1653 | op0 = SUBREG_REG (op0)(((op0)->u.fld[0]).rt_rtx); | ||||
1654 | } | ||||
1655 | |||||
1656 | /* If we have an out-of-bounds access to a register, just return an | ||||
1657 | uninitialized register of the required mode. This can occur if the | ||||
1658 | source code contains an out-of-bounds access to a small array. */ | ||||
1659 | if (REG_P (op0)(((enum rtx_code) (op0)->code) == REG) && known_ge (bitnum, GET_MODE_BITSIZE (GET_MODE (op0)))(!maybe_lt (bitnum, GET_MODE_BITSIZE (((machine_mode) (op0)-> mode))))) | ||||
1660 | return gen_reg_rtx (tmode); | ||||
1661 | |||||
1662 | if (REG_P (op0)(((enum rtx_code) (op0)->code) == REG) | ||||
1663 | && mode == GET_MODE (op0)((machine_mode) (op0)->mode) | ||||
1664 | && known_eq (bitnum, 0U)(!maybe_ne (bitnum, 0U)) | ||||
1665 | && known_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0)))(!maybe_ne (bitsize, GET_MODE_BITSIZE (((machine_mode) (op0)-> mode))))) | ||||
1666 | { | ||||
1667 | if (reverse) | ||||
1668 | op0 = flip_storage_order (mode, op0); | ||||
1669 | /* We're trying to extract a full register from itself. */ | ||||
1670 | return op0; | ||||
1671 | } | ||||
1672 | |||||
1673 | /* First try to check for vector from vector extractions. */ | ||||
1674 | if (VECTOR_MODE_P (GET_MODE (op0))(((enum mode_class) mode_class[((machine_mode) (op0)->mode )]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[((machine_mode ) (op0)->mode)]) == MODE_VECTOR_INT || ((enum mode_class) mode_class [((machine_mode) (op0)->mode)]) == MODE_VECTOR_FLOAT || (( enum mode_class) mode_class[((machine_mode) (op0)->mode)]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[((machine_mode ) (op0)->mode)]) == MODE_VECTOR_UFRACT || ((enum mode_class ) mode_class[((machine_mode) (op0)->mode)]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[((machine_mode) (op0)->mode )]) == MODE_VECTOR_UACCUM) | ||||
1675 | && !MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
1676 | && VECTOR_MODE_P (tmode)(((enum mode_class) mode_class[tmode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[tmode]) == MODE_VECTOR_INT || ( (enum mode_class) mode_class[tmode]) == MODE_VECTOR_FLOAT || ( (enum mode_class) mode_class[tmode]) == MODE_VECTOR_FRACT || ( (enum mode_class) mode_class[tmode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[tmode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[tmode]) == MODE_VECTOR_UACCUM) | ||||
1677 | && known_eq (bitsize, GET_MODE_BITSIZE (tmode))(!maybe_ne (bitsize, GET_MODE_BITSIZE (tmode))) | ||||
1678 | && maybe_gt (GET_MODE_SIZE (GET_MODE (op0)), GET_MODE_SIZE (tmode))maybe_lt (GET_MODE_SIZE (tmode), GET_MODE_SIZE (((machine_mode ) (op0)->mode)))) | ||||
1679 | { | ||||
1680 | machine_mode new_mode = GET_MODE (op0)((machine_mode) (op0)->mode); | ||||
1681 | if (GET_MODE_INNER (new_mode)(mode_to_inner (new_mode)) != GET_MODE_INNER (tmode)(mode_to_inner (tmode))) | ||||
1682 | { | ||||
1683 | scalar_mode inner_mode = GET_MODE_INNER (tmode)(mode_to_inner (tmode)); | ||||
1684 | poly_uint64 nunits; | ||||
1685 | if (!multiple_p (GET_MODE_BITSIZE (GET_MODE (op0)((machine_mode) (op0)->mode)), | ||||
1686 | GET_MODE_UNIT_BITSIZE (tmode)((unsigned short) (mode_to_unit_size (tmode) * (8))), &nunits) | ||||
1687 | || !related_vector_mode (tmode, inner_mode, | ||||
1688 | nunits).exists (&new_mode) | ||||
1689 | || maybe_ne (GET_MODE_SIZE (new_mode), | ||||
1690 | GET_MODE_SIZE (GET_MODE (op0)((machine_mode) (op0)->mode)))) | ||||
1691 | new_mode = VOIDmode((void) 0, E_VOIDmode); | ||||
1692 | } | ||||
1693 | poly_uint64 pos; | ||||
1694 | if (new_mode != VOIDmode((void) 0, E_VOIDmode) | ||||
1695 | && (convert_optab_handler (vec_extract_optab, new_mode, tmode) | ||||
1696 | != CODE_FOR_nothing) | ||||
1697 | && multiple_p (bitnum, GET_MODE_BITSIZE (tmode), &pos)) | ||||
1698 | { | ||||
1699 | class expand_operand ops[3]; | ||||
1700 | machine_mode outermode = new_mode; | ||||
1701 | machine_mode innermode = tmode; | ||||
1702 | enum insn_code icode | ||||
1703 | = convert_optab_handler (vec_extract_optab, outermode, innermode); | ||||
1704 | |||||
1705 | if (new_mode != GET_MODE (op0)((machine_mode) (op0)->mode)) | ||||
1706 | op0 = gen_lowpartrtl_hooks.gen_lowpart (new_mode, op0); | ||||
1707 | create_output_operand (&ops[0], target, innermode); | ||||
1708 | ops[0].target = 1; | ||||
1709 | create_input_operand (&ops[1], op0, outermode); | ||||
1710 | create_integer_operand (&ops[2], pos); | ||||
1711 | if (maybe_expand_insn (icode, 3, ops)) | ||||
1712 | { | ||||
1713 | if (alt_rtl && ops[0].target) | ||||
1714 | *alt_rtl = target; | ||||
1715 | target = ops[0].value; | ||||
1716 | if (GET_MODE (target)((machine_mode) (target)->mode) != mode) | ||||
1717 | return gen_lowpartrtl_hooks.gen_lowpart (tmode, target); | ||||
1718 | return target; | ||||
1719 | } | ||||
1720 | } | ||||
1721 | } | ||||
1722 | |||||
1723 | /* See if we can get a better vector mode before extracting. */ | ||||
1724 | if (VECTOR_MODE_P (GET_MODE (op0))(((enum mode_class) mode_class[((machine_mode) (op0)->mode )]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[((machine_mode ) (op0)->mode)]) == MODE_VECTOR_INT || ((enum mode_class) mode_class [((machine_mode) (op0)->mode)]) == MODE_VECTOR_FLOAT || (( enum mode_class) mode_class[((machine_mode) (op0)->mode)]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[((machine_mode ) (op0)->mode)]) == MODE_VECTOR_UFRACT || ((enum mode_class ) mode_class[((machine_mode) (op0)->mode)]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[((machine_mode) (op0)->mode )]) == MODE_VECTOR_UACCUM) | ||||
1725 | && !MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
1726 | && GET_MODE_INNER (GET_MODE (op0))(mode_to_inner (((machine_mode) (op0)->mode))) != tmode) | ||||
1727 | { | ||||
1728 | machine_mode new_mode; | ||||
1729 | |||||
1730 | if (GET_MODE_CLASS (tmode)((enum mode_class) mode_class[tmode]) == MODE_FLOAT) | ||||
1731 | new_mode = MIN_MODE_VECTOR_FLOAT; | ||||
1732 | else if (GET_MODE_CLASS (tmode)((enum mode_class) mode_class[tmode]) == MODE_FRACT) | ||||
1733 | new_mode = MIN_MODE_VECTOR_FRACT; | ||||
1734 | else if (GET_MODE_CLASS (tmode)((enum mode_class) mode_class[tmode]) == MODE_UFRACT) | ||||
1735 | new_mode = MIN_MODE_VECTOR_UFRACT; | ||||
1736 | else if (GET_MODE_CLASS (tmode)((enum mode_class) mode_class[tmode]) == MODE_ACCUM) | ||||
1737 | new_mode = MIN_MODE_VECTOR_ACCUM; | ||||
1738 | else if (GET_MODE_CLASS (tmode)((enum mode_class) mode_class[tmode]) == MODE_UACCUM) | ||||
1739 | new_mode = MIN_MODE_VECTOR_UACCUM; | ||||
1740 | else | ||||
1741 | new_mode = MIN_MODE_VECTOR_INT; | ||||
1742 | |||||
1743 | FOR_EACH_MODE_FROM (new_mode, new_mode)for ((new_mode) = (new_mode); mode_iterator::iterate_p (& (new_mode)); mode_iterator::get_next (&(new_mode))) | ||||
1744 | if (known_eq (GET_MODE_SIZE (new_mode), GET_MODE_SIZE (GET_MODE (op0)))(!maybe_ne (GET_MODE_SIZE (new_mode), GET_MODE_SIZE (((machine_mode ) (op0)->mode)))) | ||||
1745 | && known_eq (GET_MODE_UNIT_SIZE (new_mode), GET_MODE_SIZE (tmode))(!maybe_ne (mode_to_unit_size (new_mode), GET_MODE_SIZE (tmode ))) | ||||
1746 | && targetm.vector_mode_supported_p (new_mode) | ||||
1747 | && targetm.modes_tieable_p (GET_MODE (op0)((machine_mode) (op0)->mode), new_mode)) | ||||
1748 | break; | ||||
1749 | if (new_mode != VOIDmode((void) 0, E_VOIDmode)) | ||||
1750 | op0 = gen_lowpartrtl_hooks.gen_lowpart (new_mode, op0); | ||||
1751 | } | ||||
1752 | |||||
1753 | /* Use vec_extract patterns for extracting parts of vectors whenever | ||||
1754 | available. If that fails, see whether the current modes and bitregion | ||||
1755 | give a natural subreg. */ | ||||
1756 | machine_mode outermode = GET_MODE (op0)((machine_mode) (op0)->mode); | ||||
1757 | if (VECTOR_MODE_P (outermode)(((enum mode_class) mode_class[outermode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[outermode]) == MODE_VECTOR_UACCUM ) && !MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | ||||
1758 | { | ||||
1759 | scalar_mode innermode = GET_MODE_INNER (outermode)(mode_to_inner (outermode)); | ||||
1760 | enum insn_code icode | ||||
1761 | = convert_optab_handler (vec_extract_optab, outermode, innermode); | ||||
1762 | poly_uint64 pos; | ||||
1763 | if (icode != CODE_FOR_nothing | ||||
1764 | && known_eq (bitsize, GET_MODE_BITSIZE (innermode))(!maybe_ne (bitsize, GET_MODE_BITSIZE (innermode))) | ||||
1765 | && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos)) | ||||
1766 | { | ||||
1767 | class expand_operand ops[3]; | ||||
1768 | |||||
1769 | create_output_operand (&ops[0], target, innermode); | ||||
1770 | ops[0].target = 1; | ||||
1771 | create_input_operand (&ops[1], op0, outermode); | ||||
1772 | create_integer_operand (&ops[2], pos); | ||||
1773 | if (maybe_expand_insn (icode, 3, ops)) | ||||
1774 | { | ||||
1775 | if (alt_rtl && ops[0].target) | ||||
1776 | *alt_rtl = target; | ||||
1777 | target = ops[0].value; | ||||
1778 | if (GET_MODE (target)((machine_mode) (target)->mode) != mode) | ||||
1779 | return gen_lowpartrtl_hooks.gen_lowpart (tmode, target); | ||||
1780 | return target; | ||||
1781 | } | ||||
1782 | } | ||||
1783 | /* Using subregs is useful if we're extracting one register vector | ||||
1784 | from a multi-register vector. extract_bit_field_as_subreg checks | ||||
1785 | for valid bitsize and bitnum, so we don't need to do that here. */ | ||||
1786 | if (VECTOR_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_VECTOR_BOOL || ( (enum mode_class) mode_class[mode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UACCUM)) | ||||
1787 | { | ||||
1788 | rtx sub = extract_bit_field_as_subreg (mode, op0, outermode, | ||||
1789 | bitsize, bitnum); | ||||
1790 | if (sub) | ||||
1791 | return sub; | ||||
1792 | } | ||||
1793 | } | ||||
1794 | |||||
1795 | /* Make sure we are playing with integral modes. Pun with subregs | ||||
1796 | if we aren't. */ | ||||
1797 | opt_scalar_int_mode op0_mode = int_mode_for_mode (GET_MODE (op0)((machine_mode) (op0)->mode)); | ||||
1798 | scalar_int_mode imode; | ||||
1799 | if (!op0_mode.exists (&imode) || imode != GET_MODE (op0)((machine_mode) (op0)->mode)) | ||||
1800 | { | ||||
1801 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | ||||
1802 | op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),adjust_address_1 (op0, op0_mode.else_blk (), 0, 1, 1, 1, (get_mem_attrs (op0)->size)) | ||||
1803 | 0, MEM_SIZE (op0))adjust_address_1 (op0, op0_mode.else_blk (), 0, 1, 1, 1, (get_mem_attrs (op0)->size)); | ||||
1804 | else if (op0_mode.exists (&imode)) | ||||
1805 | { | ||||
1806 | op0 = gen_lowpartrtl_hooks.gen_lowpart (imode, op0); | ||||
1807 | |||||
1808 | /* If we got a SUBREG, force it into a register since we | ||||
1809 | aren't going to be able to do another SUBREG on it. */ | ||||
1810 | if (GET_CODE (op0)((enum rtx_code) (op0)->code) == SUBREG) | ||||
1811 | op0 = force_reg (imode, op0); | ||||
1812 | } | ||||
1813 | else | ||||
1814 | { | ||||
1815 | poly_int64 size = GET_MODE_SIZE (GET_MODE (op0)((machine_mode) (op0)->mode)); | ||||
1816 | rtx mem = assign_stack_temp (GET_MODE (op0)((machine_mode) (op0)->mode), size); | ||||
1817 | emit_move_insn (mem, op0); | ||||
1818 | op0 = adjust_bitfield_address_size (mem, BLKmode, 0, size)adjust_address_1 (mem, ((void) 0, E_BLKmode), 0, 1, 1, 1, size ); | ||||
1819 | } | ||||
1820 | } | ||||
1821 | |||||
1822 | /* ??? We currently assume TARGET is at least as big as BITSIZE. | ||||
1823 | If that's wrong, the solution is to test for it and set TARGET to 0 | ||||
1824 | if needed. */ | ||||
1825 | |||||
1826 | /* Get the mode of the field to use for atomic access or subreg | ||||
1827 | conversion. */ | ||||
1828 | if (!SCALAR_INT_MODE_P (tmode)(((enum mode_class) mode_class[tmode]) == MODE_INT || ((enum mode_class ) mode_class[tmode]) == MODE_PARTIAL_INT) | ||||
1829 | || !mode_for_size (bitsize, GET_MODE_CLASS (tmode)((enum mode_class) mode_class[tmode]), 0).exists (&mode1)) | ||||
1830 | mode1 = mode; | ||||
1831 | gcc_assert (mode1 != BLKmode)((void)(!(mode1 != ((void) 0, E_BLKmode)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1831, __FUNCTION__), 0 : 0)); | ||||
1832 | |||||
1833 | /* Extraction of a full MODE1 value can be done with a subreg as long | ||||
1834 | as the least significant bit of the value is the least significant | ||||
1835 | bit of either OP0 or a word of OP0. */ | ||||
1836 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && !reverse && op0_mode.exists (&imode)) | ||||
1837 | { | ||||
1838 | rtx sub = extract_bit_field_as_subreg (mode1, op0, imode, | ||||
1839 | bitsize, bitnum); | ||||
1840 | if (sub) | ||||
1841 | return convert_extracted_bit_field (sub, mode, tmode, unsignedp); | ||||
1842 | } | ||||
1843 | |||||
1844 | /* Extraction of a full MODE1 value can be done with a load as long as | ||||
1845 | the field is on a byte boundary and is sufficiently aligned. */ | ||||
1846 | poly_uint64 bytenum; | ||||
1847 | if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1, &bytenum)) | ||||
1848 | { | ||||
1849 | op0 = adjust_bitfield_address (op0, mode1, bytenum)adjust_address_1 (op0, mode1, bytenum, 1, 1, 1, 0); | ||||
1850 | if (reverse) | ||||
1851 | op0 = flip_storage_order (mode1, op0); | ||||
1852 | return convert_extracted_bit_field (op0, mode, tmode, unsignedp); | ||||
1853 | } | ||||
1854 | |||||
1855 | /* If we have a memory source and a non-constant bit offset, restrict | ||||
1856 | the memory to the referenced bytes. This is a worst-case fallback | ||||
1857 | but is useful for things like vector booleans. */ | ||||
1858 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && !bitnum.is_constant ()) | ||||
1859 | { | ||||
1860 | bytenum = bits_to_bytes_round_down (bitnum)force_align_down_and_div (bitnum, (8)); | ||||
1861 | bitnum = num_trailing_bits (bitnum)force_get_misalignment (bitnum, (8)); | ||||
1862 | poly_uint64 bytesize = bits_to_bytes_round_up (bitnum + bitsize)force_align_up_and_div (bitnum + bitsize, (8)); | ||||
1863 | op0 = adjust_bitfield_address_size (op0, BLKmode, bytenum, bytesize)adjust_address_1 (op0, ((void) 0, E_BLKmode), bytenum, 1, 1, 1 , bytesize); | ||||
1864 | op0_mode = opt_scalar_int_mode (); | ||||
1865 | } | ||||
1866 | |||||
1867 | /* It's possible we'll need to handle other cases here for | ||||
1868 | polynomial bitnum and bitsize. */ | ||||
1869 | |||||
1870 | /* From here on we need to be looking at a fixed-size insertion. */ | ||||
1871 | return extract_integral_bit_field (op0, op0_mode, bitsize.to_constant (), | ||||
1872 | bitnum.to_constant (), unsignedp, | ||||
1873 | target, mode, tmode, reverse, fallback_p); | ||||
1874 | } | ||||
1875 | |||||
1876 | /* Subroutine of extract_bit_field_1, with the same arguments, except | ||||
1877 | that BITSIZE and BITNUM are constant. Handle cases specific to | ||||
1878 | integral modes. If OP0_MODE is defined, it is the mode of OP0, | ||||
1879 | otherwise OP0 is a BLKmode MEM. */ | ||||
1880 | |||||
1881 | static rtx | ||||
1882 | extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, | ||||
1883 | unsigned HOST_WIDE_INTlong bitsize, | ||||
1884 | unsigned HOST_WIDE_INTlong bitnum, int unsignedp, | ||||
1885 | rtx target, machine_mode mode, machine_mode tmode, | ||||
1886 | bool reverse, bool fallback_p) | ||||
1887 | { | ||||
1888 | /* Handle fields bigger than a word. */ | ||||
1889 | |||||
1890 | if (bitsize > BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
1891 | { | ||||
1892 | /* Here we transfer the words of the field | ||||
1893 | in the order least significant first. | ||||
1894 | This is because the most significant word is the one which may | ||||
1895 | be less than full. */ | ||||
1896 | |||||
1897 | const bool backwards = WORDS_BIG_ENDIAN0; | ||||
1898 | unsigned int nwords = (bitsize + (BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) - 1)) / BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
1899 | unsigned int i; | ||||
1900 | rtx_insn *last; | ||||
1901 | |||||
1902 | if (target == 0 || !REG_P (target)(((enum rtx_code) (target)->code) == REG) || !valid_multiword_target_p (target)) | ||||
1903 | target = gen_reg_rtx (mode); | ||||
1904 | |||||
1905 | /* In case we're about to clobber a base register or something | ||||
1906 | (see gcc.c-torture/execute/20040625-1.c). */ | ||||
1907 | if (reg_mentioned_p (target, op0)) | ||||
1908 | target = gen_reg_rtx (mode); | ||||
1909 | |||||
1910 | /* Indicate for flow that the entire target reg is being set. */ | ||||
1911 | emit_clobber (target); | ||||
1912 | |||||
1913 | /* The mode must be fixed-size, since extract_bit_field_1 handles | ||||
1914 | extractions from variable-sized objects before calling this | ||||
1915 | function. */ | ||||
1916 | unsigned int target_size | ||||
1917 | = GET_MODE_SIZE (GET_MODE (target)((machine_mode) (target)->mode)).to_constant (); | ||||
1918 | last = get_last_insn (); | ||||
1919 | for (i = 0; i < nwords; i++) | ||||
1920 | { | ||||
1921 | /* If I is 0, use the low-order word in both field and target; | ||||
1922 | if I is 1, use the next to lowest word; and so on. */ | ||||
1923 | /* Word number in TARGET to use. */ | ||||
1924 | unsigned int wordnum | ||||
1925 | = (backwards ? target_size / UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4) - i - 1 : i); | ||||
1926 | /* Offset from start of field in OP0. */ | ||||
1927 | unsigned int bit_offset = (backwards ^ reverse | ||||
1928 | ? MAX ((int) bitsize - ((int) i + 1)(((int) bitsize - ((int) i + 1) * ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) > (0) ? ((int) bitsize - ((int) i + 1) * ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) : (0)) | ||||
1929 | * BITS_PER_WORD,(((int) bitsize - ((int) i + 1) * ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) > (0) ? ((int) bitsize - ((int) i + 1) * ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) : (0)) | ||||
1930 | 0)(((int) bitsize - ((int) i + 1) * ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) > (0) ? ((int) bitsize - ((int) i + 1) * ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) : (0)) | ||||
1931 | : (int) i * BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))); | ||||
1932 | rtx target_part = operand_subword (target, wordnum, 1, VOIDmode((void) 0, E_VOIDmode)); | ||||
1933 | rtx result_part | ||||
1934 | = extract_bit_field_1 (op0, MIN (BITS_PER_WORD,((((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) < (bitsize - i * ((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) ? ( ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) : (bitsize - i * ((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)))) | ||||
1935 | bitsize - i * BITS_PER_WORD)((((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) < (bitsize - i * ((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) ? ( ((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) : (bitsize - i * ((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)))), | ||||
1936 | bitnum + bit_offset, 1, target_part, | ||||
1937 | mode, word_mode, reverse, fallback_p, NULLnullptr); | ||||
1938 | |||||
1939 | gcc_assert (target_part)((void)(!(target_part) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 1939, __FUNCTION__), 0 : 0)); | ||||
1940 | if (!result_part) | ||||
1941 | { | ||||
1942 | delete_insns_since (last); | ||||
1943 | return NULLnullptr; | ||||
1944 | } | ||||
1945 | |||||
1946 | if (result_part != target_part) | ||||
1947 | emit_move_insn (target_part, result_part); | ||||
1948 | } | ||||
1949 | |||||
1950 | if (unsignedp) | ||||
1951 | { | ||||
1952 | /* Unless we've filled TARGET, the upper regs in a multi-reg value | ||||
1953 | need to be zero'd out. */ | ||||
1954 | if (target_size > nwords * UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
1955 | { | ||||
1956 | unsigned int i, total_words; | ||||
1957 | |||||
1958 | total_words = target_size / UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4); | ||||
1959 | for (i = nwords; i < total_words; i++) | ||||
1960 | emit_move_insn | ||||
1961 | (operand_subword (target, | ||||
1962 | backwards ? total_words - i - 1 : i, | ||||
1963 | 1, VOIDmode((void) 0, E_VOIDmode)), | ||||
1964 | const0_rtx(const_int_rtx[64])); | ||||
1965 | } | ||||
1966 | return target; | ||||
1967 | } | ||||
1968 | |||||
1969 | /* Signed bit field: sign-extend with two arithmetic shifts. */ | ||||
1970 | target = expand_shift (LSHIFT_EXPR, mode, target, | ||||
1971 | GET_MODE_BITSIZE (mode) - bitsize, NULL_RTX(rtx) 0, 0); | ||||
1972 | return expand_shift (RSHIFT_EXPR, mode, target, | ||||
1973 | GET_MODE_BITSIZE (mode) - bitsize, NULL_RTX(rtx) 0, 0); | ||||
1974 | } | ||||
1975 | |||||
1976 | /* If OP0 is a multi-word register, narrow it to the affected word. | ||||
1977 | If the region spans two words, defer to extract_split_bit_field. */ | ||||
1978 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && GET_MODE_SIZE (op0_mode.require ()) > UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
1979 | { | ||||
1980 | if (bitnum % BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) + bitsize > BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
1981 | { | ||||
1982 | if (!fallback_p) | ||||
1983 | return NULL_RTX(rtx) 0; | ||||
1984 | target = extract_split_bit_field (op0, op0_mode, bitsize, bitnum, | ||||
1985 | unsignedp, reverse); | ||||
1986 | return convert_extracted_bit_field (target, mode, tmode, unsignedp); | ||||
1987 | } | ||||
1988 | /* If OP0 is a hard register, copy it to a pseudo before calling | ||||
1989 | simplify_gen_subreg. */ | ||||
1990 | if (REG_P (op0)(((enum rtx_code) (op0)->code) == REG) && HARD_REGISTER_P (op0)((((rhs_regno(op0))) < 76))) | ||||
1991 | op0 = copy_to_reg (op0); | ||||
1992 | op0 = simplify_gen_subreg (word_mode, op0, op0_mode.require (), | ||||
1993 | bitnum / BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) * UNITS_PER_WORD(((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
1994 | op0_mode = word_mode; | ||||
1995 | bitnum %= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
1996 | } | ||||
1997 | |||||
1998 | /* From here on we know the desired field is smaller than a word. | ||||
1999 | If OP0 is a register, it too fits within a word. */ | ||||
2000 | enum extraction_pattern pattern = unsignedp ? EP_extzv : EP_extv; | ||||
2001 | extraction_insn extv; | ||||
2002 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | ||||
2003 | && !reverse | ||||
2004 | /* ??? We could limit the structure size to the part of OP0 that | ||||
2005 | contains the field, with appropriate checks for endianness | ||||
2006 | and TARGET_TRULY_NOOP_TRUNCATION. */ | ||||
2007 | && get_best_reg_extraction_insn (&extv, pattern, | ||||
2008 | GET_MODE_BITSIZE (op0_mode.require ()), | ||||
2009 | tmode)) | ||||
2010 | { | ||||
2011 | rtx result = extract_bit_field_using_extv (&extv, op0, op0_mode, | ||||
2012 | bitsize, bitnum, | ||||
2013 | unsignedp, target, mode, | ||||
2014 | tmode); | ||||
2015 | if (result) | ||||
2016 | return result; | ||||
2017 | } | ||||
2018 | |||||
2019 | /* If OP0 is a memory, try copying it to a register and seeing if a | ||||
2020 | cheap register alternative is available. */ | ||||
2021 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) & !reverse) | ||||
2022 | { | ||||
2023 | if (get_best_mem_extraction_insn (&extv, pattern, bitsize, bitnum, | ||||
2024 | tmode)) | ||||
2025 | { | ||||
2026 | rtx result = extract_bit_field_using_extv (&extv, op0, op0_mode, | ||||
2027 | bitsize, bitnum, | ||||
2028 | unsignedp, target, mode, | ||||
2029 | tmode); | ||||
2030 | if (result) | ||||
2031 | return result; | ||||
2032 | } | ||||
2033 | |||||
2034 | rtx_insn *last = get_last_insn (); | ||||
2035 | |||||
2036 | /* Try loading part of OP0 into a register and extracting the | ||||
2037 | bitfield from that. */ | ||||
2038 | unsigned HOST_WIDE_INTlong bitpos; | ||||
2039 | rtx xop0 = adjust_bit_field_mem_for_reg (pattern, op0, bitsize, bitnum, | ||||
2040 | 0, 0, tmode, &bitpos); | ||||
2041 | if (xop0) | ||||
2042 | { | ||||
2043 | xop0 = copy_to_reg (xop0); | ||||
2044 | rtx result = extract_bit_field_1 (xop0, bitsize, bitpos, | ||||
2045 | unsignedp, target, | ||||
2046 | mode, tmode, reverse, false, NULLnullptr); | ||||
2047 | if (result) | ||||
2048 | return result; | ||||
2049 | delete_insns_since (last); | ||||
2050 | } | ||||
2051 | } | ||||
2052 | |||||
2053 | if (!fallback_p) | ||||
2054 | return NULLnullptr; | ||||
2055 | |||||
2056 | /* Find a correspondingly-sized integer field, so we can apply | ||||
2057 | shifts and masks to it. */ | ||||
2058 | scalar_int_mode int_mode; | ||||
2059 | if (!int_mode_for_mode (tmode).exists (&int_mode)) | ||||
2060 | /* If this fails, we should probably push op0 out to memory and then | ||||
2061 | do a load. */ | ||||
2062 | int_mode = int_mode_for_mode (mode).require (); | ||||
2063 | |||||
2064 | target = extract_fixed_bit_field (int_mode, op0, op0_mode, bitsize, | ||||
2065 | bitnum, target, unsignedp, reverse); | ||||
2066 | |||||
2067 | /* Complex values must be reversed piecewise, so we need to undo the global | ||||
2068 | reversal, convert to the complex mode and reverse again. */ | ||||
2069 | if (reverse && COMPLEX_MODE_P (tmode)(((enum mode_class) mode_class[tmode]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class[tmode]) == MODE_COMPLEX_FLOAT)) | ||||
2070 | { | ||||
2071 | target = flip_storage_order (int_mode, target); | ||||
2072 | target = convert_extracted_bit_field (target, mode, tmode, unsignedp); | ||||
2073 | target = flip_storage_order (tmode, target); | ||||
2074 | } | ||||
2075 | else | ||||
2076 | target = convert_extracted_bit_field (target, mode, tmode, unsignedp); | ||||
2077 | |||||
2078 | return target; | ||||
2079 | } | ||||
2080 | |||||
2081 | /* Generate code to extract a byte-field from STR_RTX | ||||
2082 | containing BITSIZE bits, starting at BITNUM, | ||||
2083 | and put it in TARGET if possible (if TARGET is nonzero). | ||||
2084 | Regardless of TARGET, we return the rtx for where the value is placed. | ||||
2085 | |||||
2086 | STR_RTX is the structure containing the byte (a REG or MEM). | ||||
2087 | UNSIGNEDP is nonzero if this is an unsigned bit field. | ||||
2088 | MODE is the natural mode of the field value once extracted. | ||||
2089 | TMODE is the mode the caller would like the value to have; | ||||
2090 | but the value may be returned with type MODE instead. | ||||
2091 | |||||
2092 | If REVERSE is true, the extraction is to be done in reverse order. | ||||
2093 | |||||
2094 | If a TARGET is specified and we can store in it at no extra cost, | ||||
2095 | we do so, and return TARGET. | ||||
2096 | Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred | ||||
2097 | if they are equally easy. | ||||
2098 | |||||
2099 | If the result can be stored at TARGET, and ALT_RTL is non-NULL, | ||||
2100 | then *ALT_RTL is set to TARGET (before legitimziation). */ | ||||
2101 | |||||
2102 | rtx | ||||
2103 | extract_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, | ||||
2104 | int unsignedp, rtx target, machine_mode mode, | ||||
2105 | machine_mode tmode, bool reverse, rtx *alt_rtl) | ||||
2106 | { | ||||
2107 | machine_mode mode1; | ||||
2108 | |||||
2109 | /* Handle -fstrict-volatile-bitfields in the cases where it applies. */ | ||||
2110 | if (maybe_ne (GET_MODE_BITSIZE (GET_MODE (str_rtx)((machine_mode) (str_rtx)->mode)), 0)) | ||||
2111 | mode1 = GET_MODE (str_rtx)((machine_mode) (str_rtx)->mode); | ||||
2112 | else if (target && maybe_ne (GET_MODE_BITSIZE (GET_MODE (target)((machine_mode) (target)->mode)), 0)) | ||||
2113 | mode1 = GET_MODE (target)((machine_mode) (target)->mode); | ||||
2114 | else | ||||
2115 | mode1 = tmode; | ||||
2116 | |||||
2117 | unsigned HOST_WIDE_INTlong ibitsize, ibitnum; | ||||
2118 | scalar_int_mode int_mode; | ||||
2119 | if (bitsize.is_constant (&ibitsize) | ||||
2120 | && bitnum.is_constant (&ibitnum) | ||||
2121 | && is_a <scalar_int_mode> (mode1, &int_mode) | ||||
2122 | && strict_volatile_bitfield_p (str_rtx, ibitsize, ibitnum, | ||||
2123 | int_mode, 0, 0)) | ||||
2124 | { | ||||
2125 | /* Extraction of a full INT_MODE value can be done with a simple load. | ||||
2126 | We know here that the field can be accessed with one single | ||||
2127 | instruction. For targets that support unaligned memory, | ||||
2128 | an unaligned access may be necessary. */ | ||||
2129 | if (ibitsize == GET_MODE_BITSIZE (int_mode)) | ||||
2130 | { | ||||
2131 | rtx result = adjust_bitfield_address (str_rtx, int_mode,adjust_address_1 (str_rtx, int_mode, ibitnum / (8), 1, 1, 1, 0 ) | ||||
2132 | ibitnum / BITS_PER_UNIT)adjust_address_1 (str_rtx, int_mode, ibitnum / (8), 1, 1, 1, 0 ); | ||||
2133 | if (reverse) | ||||
2134 | result = flip_storage_order (int_mode, result); | ||||
2135 | gcc_assert (ibitnum % BITS_PER_UNIT == 0)((void)(!(ibitnum % (8) == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 2135, __FUNCTION__), 0 : 0)); | ||||
2136 | return convert_extracted_bit_field (result, mode, tmode, unsignedp); | ||||
2137 | } | ||||
2138 | |||||
2139 | str_rtx = narrow_bit_field_mem (str_rtx, int_mode, ibitsize, ibitnum, | ||||
2140 | &ibitnum); | ||||
2141 | gcc_assert (ibitnum + ibitsize <= GET_MODE_BITSIZE (int_mode))((void)(!(ibitnum + ibitsize <= GET_MODE_BITSIZE (int_mode )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 2141, __FUNCTION__), 0 : 0)); | ||||
2142 | str_rtx = copy_to_reg (str_rtx); | ||||
2143 | return extract_bit_field_1 (str_rtx, ibitsize, ibitnum, unsignedp, | ||||
2144 | target, mode, tmode, reverse, true, alt_rtl); | ||||
2145 | } | ||||
2146 | |||||
2147 | return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp, | ||||
2148 | target, mode, tmode, reverse, true, alt_rtl); | ||||
2149 | } | ||||
2150 | |||||
2151 | /* Use shifts and boolean operations to extract a field of BITSIZE bits | ||||
2152 | from bit BITNUM of OP0. If OP0_MODE is defined, it is the mode of OP0, | ||||
2153 | otherwise OP0 is a BLKmode MEM. | ||||
2154 | |||||
2155 | UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value). | ||||
2156 | If REVERSE is true, the extraction is to be done in reverse order. | ||||
2157 | |||||
2158 | If TARGET is nonzero, attempts to store the value there | ||||
2159 | and return TARGET, but this is not guaranteed. | ||||
2160 | If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */ | ||||
2161 | |||||
2162 | static rtx | ||||
2163 | extract_fixed_bit_field (machine_mode tmode, rtx op0, | ||||
2164 | opt_scalar_int_mode op0_mode, | ||||
2165 | unsigned HOST_WIDE_INTlong bitsize, | ||||
2166 | unsigned HOST_WIDE_INTlong bitnum, rtx target, | ||||
2167 | int unsignedp, bool reverse) | ||||
2168 | { | ||||
2169 | scalar_int_mode mode; | ||||
2170 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | ||||
2171 | { | ||||
2172 | if (!get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0)(get_mem_attrs (op0)->align), | ||||
2173 | BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)), MEM_VOLATILE_P (op0)(__extension__ ({ __typeof ((op0)) const _rtx = ((op0)); if ( ((enum rtx_code) (_rtx)->code) != MEM && ((enum rtx_code ) (_rtx)->code) != ASM_OPERANDS && ((enum rtx_code ) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 2173, __FUNCTION__); _rtx; })->volatil), &mode)) | ||||
2174 | /* The only way this should occur is if the field spans word | ||||
2175 | boundaries. */ | ||||
2176 | return extract_split_bit_field (op0, op0_mode, bitsize, bitnum, | ||||
2177 | unsignedp, reverse); | ||||
2178 | |||||
2179 | op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum); | ||||
2180 | } | ||||
2181 | else | ||||
2182 | mode = op0_mode.require (); | ||||
2183 | |||||
2184 | return extract_fixed_bit_field_1 (tmode, op0, mode, bitsize, bitnum, | ||||
2185 | target, unsignedp, reverse); | ||||
2186 | } | ||||
2187 | |||||
2188 | /* Helper function for extract_fixed_bit_field, extracts | ||||
2189 | the bit field always using MODE, which is the mode of OP0. | ||||
2190 | The other arguments are as for extract_fixed_bit_field. */ | ||||
2191 | |||||
2192 | static rtx | ||||
2193 | extract_fixed_bit_field_1 (machine_mode tmode, rtx op0, scalar_int_mode mode, | ||||
2194 | unsigned HOST_WIDE_INTlong bitsize, | ||||
2195 | unsigned HOST_WIDE_INTlong bitnum, rtx target, | ||||
2196 | int unsignedp, bool reverse) | ||||
2197 | { | ||||
2198 | /* Note that bitsize + bitnum can be greater than GET_MODE_BITSIZE (mode) | ||||
2199 | for invalid input, such as extract equivalent of f5 from | ||||
2200 | gcc.dg/pr48335-2.c. */ | ||||
2201 | |||||
2202 | if (reverse ? !BYTES_BIG_ENDIAN0 : BYTES_BIG_ENDIAN0) | ||||
2203 | /* BITNUM is the distance between our msb and that of OP0. | ||||
2204 | Convert it to the distance from the lsb. */ | ||||
2205 | bitnum = GET_MODE_BITSIZE (mode) - bitsize - bitnum; | ||||
2206 | |||||
2207 | /* Now BITNUM is always the distance between the field's lsb and that of OP0. | ||||
2208 | We have reduced the big-endian case to the little-endian case. */ | ||||
2209 | if (reverse) | ||||
2210 | op0 = flip_storage_order (mode, op0); | ||||
2211 | |||||
2212 | if (unsignedp) | ||||
2213 | { | ||||
2214 | if (bitnum) | ||||
2215 | { | ||||
2216 | /* If the field does not already start at the lsb, | ||||
2217 | shift it so it does. */ | ||||
2218 | /* Maybe propagate the target for the shift. */ | ||||
2219 | rtx subtarget = (target != 0 && REG_P (target)(((enum rtx_code) (target)->code) == REG) ? target : 0); | ||||
2220 | if (tmode != mode) | ||||
2221 | subtarget = 0; | ||||
2222 | op0 = expand_shift (RSHIFT_EXPR, mode, op0, bitnum, subtarget, 1); | ||||
2223 | } | ||||
2224 | /* Convert the value to the desired mode. TMODE must also be a | ||||
2225 | scalar integer for this conversion to make sense, since we | ||||
2226 | shouldn't reinterpret the bits. */ | ||||
2227 | scalar_int_mode new_mode = as_a <scalar_int_mode> (tmode); | ||||
2228 | if (mode != new_mode) | ||||
2229 | op0 = convert_to_mode (new_mode, op0, 1); | ||||
2230 | |||||
2231 | /* Unless the msb of the field used to be the msb when we shifted, | ||||
2232 | mask out the upper bits. */ | ||||
2233 | |||||
2234 | if (GET_MODE_BITSIZE (mode) != bitnum + bitsize) | ||||
2235 | return expand_binop (new_mode, and_optab, op0, | ||||
2236 | mask_rtx (new_mode, 0, bitsize, 0), | ||||
2237 | target, 1, OPTAB_LIB_WIDEN); | ||||
2238 | return op0; | ||||
2239 | } | ||||
2240 | |||||
2241 | /* To extract a signed bit-field, first shift its msb to the msb of the word, | ||||
2242 | then arithmetic-shift its lsb to the lsb of the word. */ | ||||
2243 | op0 = force_reg (mode, op0); | ||||
2244 | |||||
2245 | /* Find the narrowest integer mode that contains the field. */ | ||||
2246 | |||||
2247 | opt_scalar_int_mode mode_iter; | ||||
2248 | FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)for (mode_iterator::start (&(mode_iter), MODE_INT); mode_iterator ::iterate_p (&(mode_iter)); mode_iterator::get_next (& (mode_iter))) | ||||
2249 | if (GET_MODE_BITSIZE (mode_iter.require ()) >= bitsize + bitnum) | ||||
2250 | break; | ||||
2251 | |||||
2252 | mode = mode_iter.require (); | ||||
2253 | op0 = convert_to_mode (mode, op0, 0); | ||||
2254 | |||||
2255 | if (mode != tmode) | ||||
2256 | target = 0; | ||||
2257 | |||||
2258 | if (GET_MODE_BITSIZE (mode) != (bitsize + bitnum)) | ||||
2259 | { | ||||
2260 | int amount = GET_MODE_BITSIZE (mode) - (bitsize + bitnum); | ||||
2261 | /* Maybe propagate the target for the shift. */ | ||||
2262 | rtx subtarget = (target != 0 && REG_P (target)(((enum rtx_code) (target)->code) == REG) ? target : 0); | ||||
2263 | op0 = expand_shift (LSHIFT_EXPR, mode, op0, amount, subtarget, 1); | ||||
2264 | } | ||||
2265 | |||||
2266 | return expand_shift (RSHIFT_EXPR, mode, op0, | ||||
2267 | GET_MODE_BITSIZE (mode) - bitsize, target, 0); | ||||
2268 | } | ||||
2269 | |||||
2270 | /* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value | ||||
2271 | VALUE << BITPOS. */ | ||||
2272 | |||||
2273 | static rtx | ||||
2274 | lshift_value (machine_mode mode, unsigned HOST_WIDE_INTlong value, | ||||
2275 | int bitpos) | ||||
2276 | { | ||||
2277 | return immed_wide_int_const (wi::lshift (value, bitpos), mode); | ||||
2278 | } | ||||
2279 | |||||
2280 | /* Extract a bit field that is split across two words | ||||
2281 | and return an RTX for the result. | ||||
2282 | |||||
2283 | OP0 is the REG, SUBREG or MEM rtx for the first of the two words. | ||||
2284 | BITSIZE is the field width; BITPOS, position of its first bit, in the word. | ||||
2285 | UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. | ||||
2286 | If OP0_MODE is defined, it is the mode of OP0, otherwise OP0 is | ||||
2287 | a BLKmode MEM. | ||||
2288 | |||||
2289 | If REVERSE is true, the extraction is to be done in reverse order. */ | ||||
2290 | |||||
2291 | static rtx | ||||
2292 | extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, | ||||
2293 | unsigned HOST_WIDE_INTlong bitsize, | ||||
2294 | unsigned HOST_WIDE_INTlong bitpos, int unsignedp, | ||||
2295 | bool reverse) | ||||
2296 | { | ||||
2297 | unsigned int unit; | ||||
2298 | unsigned int bitsdone = 0; | ||||
2299 | rtx result = NULL_RTX(rtx) 0; | ||||
2300 | int first = 1; | ||||
2301 | |||||
2302 | /* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that | ||||
2303 | much at a time. */ | ||||
2304 | if (REG_P (op0)(((enum rtx_code) (op0)->code) == REG) || GET_CODE (op0)((enum rtx_code) (op0)->code) == SUBREG) | ||||
2305 | unit = BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)); | ||||
2306 | else | ||||
2307 | unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD)(((get_mem_attrs (op0)->align)) < (((8) * (((global_options .x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) ? ( (get_mem_attrs (op0)->align)) : (((8) * (((global_options. x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)))); | ||||
2308 | |||||
2309 | while (bitsdone < bitsize) | ||||
2310 | { | ||||
2311 | unsigned HOST_WIDE_INTlong thissize; | ||||
2312 | rtx part; | ||||
2313 | unsigned HOST_WIDE_INTlong thispos; | ||||
2314 | unsigned HOST_WIDE_INTlong offset; | ||||
2315 | |||||
2316 | offset = (bitpos + bitsdone) / unit; | ||||
2317 | thispos = (bitpos + bitsdone) % unit; | ||||
2318 | |||||
2319 | /* THISSIZE must not overrun a word boundary. Otherwise, | ||||
2320 | extract_fixed_bit_field will call us again, and we will mutually | ||||
2321 | recurse forever. */ | ||||
2322 | thissize = MIN (bitsize - bitsdone, BITS_PER_WORD)((bitsize - bitsdone) < (((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) ? (bitsize - bitsdone ) : (((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)))); | ||||
2323 | thissize = MIN (thissize, unit - thispos)((thissize) < (unit - thispos) ? (thissize) : (unit - thispos )); | ||||
2324 | |||||
2325 | /* If OP0 is a register, then handle OFFSET here. */ | ||||
2326 | rtx op0_piece = op0; | ||||
2327 | opt_scalar_int_mode op0_piece_mode = op0_mode; | ||||
2328 | if (SUBREG_P (op0)(((enum rtx_code) (op0)->code) == SUBREG) || REG_P (op0)(((enum rtx_code) (op0)->code) == REG)) | ||||
2329 | { | ||||
2330 | op0_piece = operand_subword_force (op0, offset, op0_mode.require ()); | ||||
2331 | op0_piece_mode = word_mode; | ||||
2332 | offset = 0; | ||||
2333 | } | ||||
2334 | |||||
2335 | /* Extract the parts in bit-counting order, | ||||
2336 | whose meaning is determined by BYTES_PER_UNIT. | ||||
2337 | OFFSET is in UNITs, and UNIT is in bits. */ | ||||
2338 | part = extract_fixed_bit_field (word_mode, op0_piece, op0_piece_mode, | ||||
2339 | thissize, offset * unit + thispos, | ||||
2340 | 0, 1, reverse); | ||||
2341 | bitsdone += thissize; | ||||
2342 | |||||
2343 | /* Shift this part into place for the result. */ | ||||
2344 | if (reverse ? !BYTES_BIG_ENDIAN0 : BYTES_BIG_ENDIAN0) | ||||
2345 | { | ||||
2346 | if (bitsize != bitsdone) | ||||
2347 | part = expand_shift (LSHIFT_EXPR, word_mode, part, | ||||
2348 | bitsize - bitsdone, 0, 1); | ||||
2349 | } | ||||
2350 | else | ||||
2351 | { | ||||
2352 | if (bitsdone != thissize) | ||||
2353 | part = expand_shift (LSHIFT_EXPR, word_mode, part, | ||||
2354 | bitsdone - thissize, 0, 1); | ||||
2355 | } | ||||
2356 | |||||
2357 | if (first) | ||||
2358 | result = part; | ||||
2359 | else | ||||
2360 | /* Combine the parts with bitwise or. This works | ||||
2361 | because we extracted each part as an unsigned bit field. */ | ||||
2362 | result = expand_binop (word_mode, ior_optab, part, result, NULL_RTX(rtx) 0, 1, | ||||
2363 | OPTAB_LIB_WIDEN); | ||||
2364 | |||||
2365 | first = 0; | ||||
2366 | } | ||||
2367 | |||||
2368 | /* Unsigned bit field: we are done. */ | ||||
2369 | if (unsignedp) | ||||
2370 | return result; | ||||
2371 | /* Signed bit field: sign-extend with two arithmetic shifts. */ | ||||
2372 | result = expand_shift (LSHIFT_EXPR, word_mode, result, | ||||
2373 | BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) - bitsize, NULL_RTX(rtx) 0, 0); | ||||
2374 | return expand_shift (RSHIFT_EXPR, word_mode, result, | ||||
2375 | BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) - bitsize, NULL_RTX(rtx) 0, 0); | ||||
2376 | } | ||||
2377 | |||||
2378 | /* Try to read the low bits of SRC as an rvalue of mode MODE, preserving | ||||
2379 | the bit pattern. SRC_MODE is the mode of SRC; if this is smaller than | ||||
2380 | MODE, fill the upper bits with zeros. Fail if the layout of either | ||||
2381 | mode is unknown (as for CC modes) or if the extraction would involve | ||||
2382 | unprofitable mode punning. Return the value on success, otherwise | ||||
2383 | return null. | ||||
2384 | |||||
2385 | This is different from gen_lowpart* in these respects: | ||||
2386 | |||||
2387 | - the returned value must always be considered an rvalue | ||||
2388 | |||||
2389 | - when MODE is wider than SRC_MODE, the extraction involves | ||||
2390 | a zero extension | ||||
2391 | |||||
2392 | - when MODE is smaller than SRC_MODE, the extraction involves | ||||
2393 | a truncation (and is thus subject to TARGET_TRULY_NOOP_TRUNCATION). | ||||
2394 | |||||
2395 | In other words, this routine performs a computation, whereas the | ||||
2396 | gen_lowpart* routines are conceptually lvalue or rvalue subreg | ||||
2397 | operations. */ | ||||
2398 | |||||
2399 | rtx | ||||
2400 | extract_low_bits (machine_mode mode, machine_mode src_mode, rtx src) | ||||
2401 | { | ||||
2402 | scalar_int_mode int_mode, src_int_mode; | ||||
2403 | |||||
2404 | if (mode == src_mode) | ||||
2405 | return src; | ||||
2406 | |||||
2407 | if (CONSTANT_P (src)((rtx_class[(int) (((enum rtx_code) (src)->code))]) == RTX_CONST_OBJ )) | ||||
2408 | { | ||||
2409 | /* simplify_gen_subreg can't be used here, as if simplify_subreg | ||||
2410 | fails, it will happily create (subreg (symbol_ref)) or similar | ||||
2411 | invalid SUBREGs. */ | ||||
2412 | poly_uint64 byte = subreg_lowpart_offset (mode, src_mode); | ||||
2413 | rtx ret = simplify_subreg (mode, src, src_mode, byte); | ||||
2414 | if (ret) | ||||
2415 | return ret; | ||||
2416 | |||||
2417 | if (GET_MODE (src)((machine_mode) (src)->mode) == VOIDmode((void) 0, E_VOIDmode) | ||||
2418 | || !validate_subreg (mode, src_mode, src, byte)) | ||||
2419 | return NULL_RTX(rtx) 0; | ||||
2420 | |||||
2421 | src = force_reg (GET_MODE (src)((machine_mode) (src)->mode), src); | ||||
2422 | return gen_rtx_SUBREG (mode, src, byte); | ||||
2423 | } | ||||
2424 | |||||
2425 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_CC || GET_MODE_CLASS (src_mode)((enum mode_class) mode_class[src_mode]) == MODE_CC) | ||||
2426 | return NULL_RTX(rtx) 0; | ||||
2427 | |||||
2428 | if (known_eq (GET_MODE_BITSIZE (mode), GET_MODE_BITSIZE (src_mode))(!maybe_ne (GET_MODE_BITSIZE (mode), GET_MODE_BITSIZE (src_mode ))) | ||||
2429 | && targetm.modes_tieable_p (mode, src_mode)) | ||||
2430 | { | ||||
2431 | rtx x = gen_lowpart_common (mode, src); | ||||
2432 | if (x) | ||||
2433 | return x; | ||||
2434 | } | ||||
2435 | |||||
2436 | if (!int_mode_for_mode (src_mode).exists (&src_int_mode) | ||||
2437 | || !int_mode_for_mode (mode).exists (&int_mode)) | ||||
2438 | return NULL_RTX(rtx) 0; | ||||
2439 | |||||
2440 | if (!targetm.modes_tieable_p (src_int_mode, src_mode)) | ||||
2441 | return NULL_RTX(rtx) 0; | ||||
2442 | if (!targetm.modes_tieable_p (int_mode, mode)) | ||||
2443 | return NULL_RTX(rtx) 0; | ||||
2444 | |||||
2445 | src = gen_lowpartrtl_hooks.gen_lowpart (src_int_mode, src); | ||||
2446 | if (!validate_subreg (int_mode, src_int_mode, src, | ||||
2447 | subreg_lowpart_offset (int_mode, src_int_mode))) | ||||
2448 | return NULL_RTX(rtx) 0; | ||||
2449 | |||||
2450 | src = convert_modes (int_mode, src_int_mode, src, true); | ||||
2451 | src = gen_lowpartrtl_hooks.gen_lowpart (mode, src); | ||||
2452 | return src; | ||||
2453 | } | ||||
2454 | |||||
2455 | /* Add INC into TARGET. */ | ||||
2456 | |||||
2457 | void | ||||
2458 | expand_inc (rtx target, rtx inc) | ||||
2459 | { | ||||
2460 | rtx value = expand_binop (GET_MODE (target)((machine_mode) (target)->mode), add_optab, | ||||
2461 | target, inc, | ||||
2462 | target, 0, OPTAB_LIB_WIDEN); | ||||
2463 | if (value != target) | ||||
2464 | emit_move_insn (target, value); | ||||
2465 | } | ||||
2466 | |||||
2467 | /* Subtract DEC from TARGET. */ | ||||
2468 | |||||
2469 | void | ||||
2470 | expand_dec (rtx target, rtx dec) | ||||
2471 | { | ||||
2472 | rtx value = expand_binop (GET_MODE (target)((machine_mode) (target)->mode), sub_optab, | ||||
2473 | target, dec, | ||||
2474 | target, 0, OPTAB_LIB_WIDEN); | ||||
2475 | if (value != target) | ||||
2476 | emit_move_insn (target, value); | ||||
2477 | } | ||||
2478 | |||||
2479 | /* Output a shift instruction for expression code CODE, | ||||
2480 | with SHIFTED being the rtx for the value to shift, | ||||
2481 | and AMOUNT the rtx for the amount to shift by. | ||||
2482 | Store the result in the rtx TARGET, if that is convenient. | ||||
2483 | If UNSIGNEDP is nonzero, do a logical shift; otherwise, arithmetic. | ||||
2484 | Return the rtx for where the value is. | ||||
2485 | If that cannot be done, abort the compilation unless MAY_FAIL is true, | ||||
2486 | in which case 0 is returned. */ | ||||
2487 | |||||
2488 | static rtx | ||||
2489 | expand_shift_1 (enum tree_code code, machine_mode mode, rtx shifted, | ||||
2490 | rtx amount, rtx target, int unsignedp, bool may_fail = false) | ||||
2491 | { | ||||
2492 | rtx op1, temp = 0; | ||||
2493 | int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR); | ||||
2494 | int rotate = (code == LROTATE_EXPR || code == RROTATE_EXPR); | ||||
2495 | optab lshift_optab = ashl_optab; | ||||
2496 | optab rshift_arith_optab = ashr_optab; | ||||
2497 | optab rshift_uns_optab = lshr_optab; | ||||
2498 | optab lrotate_optab = rotl_optab; | ||||
2499 | optab rrotate_optab = rotr_optab; | ||||
2500 | machine_mode op1_mode; | ||||
2501 | scalar_mode scalar_mode = GET_MODE_INNER (mode)(mode_to_inner (mode)); | ||||
2502 | int attempt; | ||||
2503 | bool speed = optimize_insn_for_speed_p (); | ||||
2504 | |||||
2505 | op1 = amount; | ||||
2506 | op1_mode = GET_MODE (op1)((machine_mode) (op1)->mode); | ||||
2507 | |||||
2508 | /* Determine whether the shift/rotate amount is a vector, or scalar. If the | ||||
2509 | shift amount is a vector, use the vector/vector shift patterns. */ | ||||
2510 | if (VECTOR_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_VECTOR_BOOL || ( (enum mode_class) mode_class[mode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UACCUM) && VECTOR_MODE_P (op1_mode)(((enum mode_class) mode_class[op1_mode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[op1_mode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[op1_mode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[op1_mode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[op1_mode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[op1_mode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[op1_mode]) == MODE_VECTOR_UACCUM )) | ||||
2511 | { | ||||
2512 | lshift_optab = vashl_optab; | ||||
2513 | rshift_arith_optab = vashr_optab; | ||||
2514 | rshift_uns_optab = vlshr_optab; | ||||
2515 | lrotate_optab = vrotl_optab; | ||||
2516 | rrotate_optab = vrotr_optab; | ||||
2517 | } | ||||
2518 | |||||
2519 | /* Previously detected shift-counts computed by NEGATE_EXPR | ||||
2520 | and shifted in the other direction; but that does not work | ||||
2521 | on all machines. */ | ||||
2522 | |||||
2523 | if (SHIFT_COUNT_TRUNCATED0) | ||||
2524 | { | ||||
2525 | if (CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT) | ||||
2526 | && ((unsigned HOST_WIDE_INTlong) INTVAL (op1)((op1)->u.hwint[0]) >= | ||||
2527 | (unsigned HOST_WIDE_INTlong) GET_MODE_BITSIZE (scalar_mode))) | ||||
2528 | op1 = gen_int_shift_amount (mode, | ||||
2529 | (unsigned HOST_WIDE_INTlong) INTVAL (op1)((op1)->u.hwint[0]) | ||||
2530 | % GET_MODE_BITSIZE (scalar_mode)); | ||||
2531 | else if (GET_CODE (op1)((enum rtx_code) (op1)->code) == SUBREG | ||||
2532 | && subreg_lowpart_p (op1) | ||||
2533 | && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op1)))(((enum mode_class) mode_class[((machine_mode) ((((op1)->u .fld[0]).rt_rtx))->mode)]) == MODE_INT || ((enum mode_class ) mode_class[((machine_mode) ((((op1)->u.fld[0]).rt_rtx))-> mode)]) == MODE_PARTIAL_INT) | ||||
2534 | && SCALAR_INT_MODE_P (GET_MODE (op1))(((enum mode_class) mode_class[((machine_mode) (op1)->mode )]) == MODE_INT || ((enum mode_class) mode_class[((machine_mode ) (op1)->mode)]) == MODE_PARTIAL_INT)) | ||||
2535 | op1 = SUBREG_REG (op1)(((op1)->u.fld[0]).rt_rtx); | ||||
2536 | } | ||||
2537 | |||||
2538 | /* Canonicalize rotates by constant amount. If op1 is bitsize / 2, | ||||
2539 | prefer left rotation, if op1 is from bitsize / 2 + 1 to | ||||
2540 | bitsize - 1, use other direction of rotate with 1 .. bitsize / 2 - 1 | ||||
2541 | amount instead. */ | ||||
2542 | if (rotate | ||||
2543 | && CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT) | ||||
2544 | && IN_RANGE (INTVAL (op1), GET_MODE_BITSIZE (scalar_mode) / 2 + left,((unsigned long) (((op1)->u.hwint[0])) - (unsigned long) ( GET_MODE_BITSIZE (scalar_mode) / 2 + left) <= (unsigned long ) (GET_MODE_BITSIZE (scalar_mode) - 1) - (unsigned long) (GET_MODE_BITSIZE (scalar_mode) / 2 + left)) | ||||
2545 | GET_MODE_BITSIZE (scalar_mode) - 1)((unsigned long) (((op1)->u.hwint[0])) - (unsigned long) ( GET_MODE_BITSIZE (scalar_mode) / 2 + left) <= (unsigned long ) (GET_MODE_BITSIZE (scalar_mode) - 1) - (unsigned long) (GET_MODE_BITSIZE (scalar_mode) / 2 + left))) | ||||
2546 | { | ||||
2547 | op1 = gen_int_shift_amount (mode, (GET_MODE_BITSIZE (scalar_mode) | ||||
2548 | - INTVAL (op1)((op1)->u.hwint[0]))); | ||||
2549 | left = !left; | ||||
2550 | code = left ? LROTATE_EXPR : RROTATE_EXPR; | ||||
2551 | } | ||||
2552 | |||||
2553 | /* Rotation of 16bit values by 8 bits is effectively equivalent to a bswaphi. | ||||
2554 | Note that this is not the case for bigger values. For instance a rotation | ||||
2555 | of 0x01020304 by 16 bits gives 0x03040102 which is different from | ||||
2556 | 0x04030201 (bswapsi). */ | ||||
2557 | if (rotate | ||||
2558 | && CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT) | ||||
2559 | && INTVAL (op1)((op1)->u.hwint[0]) == BITS_PER_UNIT(8) | ||||
2560 | && GET_MODE_SIZE (scalar_mode) == 2 | ||||
2561 | && optab_handler (bswap_optab, mode) != CODE_FOR_nothing) | ||||
2562 | return expand_unop (mode, bswap_optab, shifted, NULL_RTX(rtx) 0, unsignedp); | ||||
2563 | |||||
2564 | if (op1 == const0_rtx(const_int_rtx[64])) | ||||
2565 | return shifted; | ||||
2566 | |||||
2567 | /* Check whether its cheaper to implement a left shift by a constant | ||||
2568 | bit count by a sequence of additions. */ | ||||
2569 | if (code == LSHIFT_EXPR | ||||
2570 | && CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT) | ||||
2571 | && INTVAL (op1)((op1)->u.hwint[0]) > 0 | ||||
2572 | && INTVAL (op1)((op1)->u.hwint[0]) < GET_MODE_PRECISION (scalar_mode) | ||||
2573 | && INTVAL (op1)((op1)->u.hwint[0]) < MAX_BITS_PER_WORD64 | ||||
2574 | && (shift_cost (speed, mode, INTVAL (op1)((op1)->u.hwint[0])) | ||||
2575 | > INTVAL (op1)((op1)->u.hwint[0]) * add_cost (speed, mode)) | ||||
2576 | && shift_cost (speed, mode, INTVAL (op1)((op1)->u.hwint[0])) != MAX_COST2147483647) | ||||
2577 | { | ||||
2578 | int i; | ||||
2579 | for (i = 0; i < INTVAL (op1)((op1)->u.hwint[0]); i++) | ||||
2580 | { | ||||
2581 | temp = force_reg (mode, shifted); | ||||
2582 | shifted = expand_binop (mode, add_optab, temp, temp, NULL_RTX(rtx) 0, | ||||
2583 | unsignedp, OPTAB_LIB_WIDEN); | ||||
2584 | } | ||||
2585 | return shifted; | ||||
2586 | } | ||||
2587 | |||||
2588 | for (attempt = 0; temp == 0 && attempt < 3; attempt++) | ||||
2589 | { | ||||
2590 | enum optab_methods methods; | ||||
2591 | |||||
2592 | if (attempt == 0) | ||||
2593 | methods = OPTAB_DIRECT; | ||||
2594 | else if (attempt == 1) | ||||
2595 | methods = OPTAB_WIDEN; | ||||
2596 | else | ||||
2597 | methods = OPTAB_LIB_WIDEN; | ||||
2598 | |||||
2599 | if (rotate) | ||||
2600 | { | ||||
2601 | /* Widening does not work for rotation. */ | ||||
2602 | if (methods == OPTAB_WIDEN) | ||||
2603 | continue; | ||||
2604 | else if (methods == OPTAB_LIB_WIDEN) | ||||
2605 | { | ||||
2606 | /* If we have been unable to open-code this by a rotation, | ||||
2607 | do it as the IOR of two shifts. I.e., to rotate A | ||||
2608 | by N bits, compute | ||||
2609 | (A << N) | ((unsigned) A >> ((-N) & (C - 1))) | ||||
2610 | where C is the bitsize of A. | ||||
2611 | |||||
2612 | It is theoretically possible that the target machine might | ||||
2613 | not be able to perform either shift and hence we would | ||||
2614 | be making two libcalls rather than just the one for the | ||||
2615 | shift (similarly if IOR could not be done). We will allow | ||||
2616 | this extremely unlikely lossage to avoid complicating the | ||||
2617 | code below. */ | ||||
2618 | |||||
2619 | rtx subtarget = target == shifted ? 0 : target; | ||||
2620 | rtx new_amount, other_amount; | ||||
2621 | rtx temp1; | ||||
2622 | |||||
2623 | new_amount = op1; | ||||
2624 | if (op1 == const0_rtx(const_int_rtx[64])) | ||||
2625 | return shifted; | ||||
2626 | else if (CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT)) | ||||
2627 | other_amount = gen_int_shift_amount | ||||
2628 | (mode, GET_MODE_BITSIZE (scalar_mode) - INTVAL (op1)((op1)->u.hwint[0])); | ||||
2629 | else | ||||
2630 | { | ||||
2631 | other_amount | ||||
2632 | = simplify_gen_unary (NEG, GET_MODE (op1)((machine_mode) (op1)->mode), | ||||
2633 | op1, GET_MODE (op1)((machine_mode) (op1)->mode)); | ||||
2634 | HOST_WIDE_INTlong mask = GET_MODE_PRECISION (scalar_mode) - 1; | ||||
2635 | other_amount | ||||
2636 | = simplify_gen_binary (AND, GET_MODE (op1)((machine_mode) (op1)->mode), other_amount, | ||||
2637 | gen_int_mode (mask, GET_MODE (op1)((machine_mode) (op1)->mode))); | ||||
2638 | } | ||||
2639 | |||||
2640 | shifted = force_reg (mode, shifted); | ||||
2641 | |||||
2642 | temp = expand_shift_1 (left ? LSHIFT_EXPR : RSHIFT_EXPR, | ||||
2643 | mode, shifted, new_amount, 0, 1); | ||||
2644 | temp1 = expand_shift_1 (left ? RSHIFT_EXPR : LSHIFT_EXPR, | ||||
2645 | mode, shifted, other_amount, | ||||
2646 | subtarget, 1); | ||||
2647 | return expand_binop (mode, ior_optab, temp, temp1, target, | ||||
2648 | unsignedp, methods); | ||||
2649 | } | ||||
2650 | |||||
2651 | temp = expand_binop (mode, | ||||
2652 | left ? lrotate_optab : rrotate_optab, | ||||
2653 | shifted, op1, target, unsignedp, methods); | ||||
2654 | } | ||||
2655 | else if (unsignedp) | ||||
2656 | temp = expand_binop (mode, | ||||
2657 | left ? lshift_optab : rshift_uns_optab, | ||||
2658 | shifted, op1, target, unsignedp, methods); | ||||
2659 | |||||
2660 | /* Do arithmetic shifts. | ||||
2661 | Also, if we are going to widen the operand, we can just as well | ||||
2662 | use an arithmetic right-shift instead of a logical one. */ | ||||
2663 | if (temp == 0 && ! rotate | ||||
2664 | && (! unsignedp || (! left && methods == OPTAB_WIDEN))) | ||||
2665 | { | ||||
2666 | enum optab_methods methods1 = methods; | ||||
2667 | |||||
2668 | /* If trying to widen a log shift to an arithmetic shift, | ||||
2669 | don't accept an arithmetic shift of the same size. */ | ||||
2670 | if (unsignedp) | ||||
2671 | methods1 = OPTAB_MUST_WIDEN; | ||||
2672 | |||||
2673 | /* Arithmetic shift */ | ||||
2674 | |||||
2675 | temp = expand_binop (mode, | ||||
2676 | left ? lshift_optab : rshift_arith_optab, | ||||
2677 | shifted, op1, target, unsignedp, methods1); | ||||
2678 | } | ||||
2679 | |||||
2680 | /* We used to try extzv here for logical right shifts, but that was | ||||
2681 | only useful for one machine, the VAX, and caused poor code | ||||
2682 | generation there for lshrdi3, so the code was deleted and a | ||||
2683 | define_expand for lshrsi3 was added to vax.md. */ | ||||
2684 | } | ||||
2685 | |||||
2686 | gcc_assert (temp != NULL_RTX || may_fail)((void)(!(temp != (rtx) 0 || may_fail) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 2686, __FUNCTION__), 0 : 0)); | ||||
2687 | return temp; | ||||
2688 | } | ||||
2689 | |||||
2690 | /* Output a shift instruction for expression code CODE, | ||||
2691 | with SHIFTED being the rtx for the value to shift, | ||||
2692 | and AMOUNT the amount to shift by. | ||||
2693 | Store the result in the rtx TARGET, if that is convenient. | ||||
2694 | If UNSIGNEDP is nonzero, do a logical shift; otherwise, arithmetic. | ||||
2695 | Return the rtx for where the value is. */ | ||||
2696 | |||||
2697 | rtx | ||||
2698 | expand_shift (enum tree_code code, machine_mode mode, rtx shifted, | ||||
2699 | poly_int64 amount, rtx target, int unsignedp) | ||||
2700 | { | ||||
2701 | return expand_shift_1 (code, mode, shifted, | ||||
2702 | gen_int_shift_amount (mode, amount), | ||||
2703 | target, unsignedp); | ||||
2704 | } | ||||
2705 | |||||
2706 | /* Likewise, but return 0 if that cannot be done. */ | ||||
2707 | |||||
2708 | rtx | ||||
2709 | maybe_expand_shift (enum tree_code code, machine_mode mode, rtx shifted, | ||||
2710 | int amount, rtx target, int unsignedp) | ||||
2711 | { | ||||
2712 | return expand_shift_1 (code, mode, | ||||
2713 | shifted, GEN_INT (amount)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (amount)), target, unsignedp, true); | ||||
2714 | } | ||||
2715 | |||||
2716 | /* Output a shift instruction for expression code CODE, | ||||
2717 | with SHIFTED being the rtx for the value to shift, | ||||
2718 | and AMOUNT the tree for the amount to shift by. | ||||
2719 | Store the result in the rtx TARGET, if that is convenient. | ||||
2720 | If UNSIGNEDP is nonzero, do a logical shift; otherwise, arithmetic. | ||||
2721 | Return the rtx for where the value is. */ | ||||
2722 | |||||
2723 | rtx | ||||
2724 | expand_variable_shift (enum tree_code code, machine_mode mode, rtx shifted, | ||||
2725 | tree amount, rtx target, int unsignedp) | ||||
2726 | { | ||||
2727 | return expand_shift_1 (code, mode, | ||||
2728 | shifted, expand_normal (amount), target, unsignedp); | ||||
2729 | } | ||||
2730 | |||||
2731 | |||||
2732 | static void synth_mult (struct algorithm *, unsigned HOST_WIDE_INTlong, | ||||
2733 | const struct mult_cost *, machine_mode mode); | ||||
2734 | static rtx expand_mult_const (machine_mode, rtx, HOST_WIDE_INTlong, rtx, | ||||
2735 | const struct algorithm *, enum mult_variant); | ||||
2736 | static unsigned HOST_WIDE_INTlong invert_mod2n (unsigned HOST_WIDE_INTlong, int); | ||||
2737 | static rtx extract_high_half (scalar_int_mode, rtx); | ||||
2738 | static rtx expmed_mult_highpart (scalar_int_mode, rtx, rtx, rtx, int, int); | ||||
2739 | static rtx expmed_mult_highpart_optab (scalar_int_mode, rtx, rtx, rtx, | ||||
2740 | int, int); | ||||
2741 | /* Compute and return the best algorithm for multiplying by T. | ||||
2742 | The algorithm must cost less than cost_limit | ||||
2743 | If retval.cost >= COST_LIMIT, no algorithm was found and all | ||||
2744 | other field of the returned struct are undefined. | ||||
2745 | MODE is the machine mode of the multiplication. */ | ||||
2746 | |||||
2747 | static void | ||||
2748 | synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INTlong t, | ||||
2749 | const struct mult_cost *cost_limit, machine_mode mode) | ||||
2750 | { | ||||
2751 | int m; | ||||
2752 | struct algorithm *alg_in, *best_alg; | ||||
2753 | struct mult_cost best_cost; | ||||
2754 | struct mult_cost new_limit; | ||||
2755 | int op_cost, op_latency; | ||||
2756 | unsigned HOST_WIDE_INTlong orig_t = t; | ||||
2757 | unsigned HOST_WIDE_INTlong q; | ||||
2758 | int maxm, hash_index; | ||||
2759 | bool cache_hit = false; | ||||
2760 | enum alg_code cache_alg = alg_zero; | ||||
2761 | bool speed = optimize_insn_for_speed_p (); | ||||
2762 | scalar_int_mode imode; | ||||
2763 | struct alg_hash_entry *entry_ptr; | ||||
2764 | |||||
2765 | /* Indicate that no algorithm is yet found. If no algorithm | ||||
2766 | is found, this value will be returned and indicate failure. */ | ||||
2767 | alg_out->cost.cost = cost_limit->cost + 1; | ||||
2768 | alg_out->cost.latency = cost_limit->latency + 1; | ||||
2769 | |||||
2770 | if (cost_limit->cost < 0 | ||||
2771 | || (cost_limit->cost == 0 && cost_limit->latency <= 0)) | ||||
2772 | return; | ||||
2773 | |||||
2774 | /* Be prepared for vector modes. */ | ||||
2775 | imode = as_a <scalar_int_mode> (GET_MODE_INNER (mode)(mode_to_inner (mode))); | ||||
2776 | |||||
2777 | maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (imode))((((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) < (GET_MODE_BITSIZE (imode)) ? (((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) : (GET_MODE_BITSIZE (imode))); | ||||
2778 | |||||
2779 | /* Restrict the bits of "t" to the multiplication's mode. */ | ||||
2780 | t &= GET_MODE_MASK (imode)mode_mask_array[imode]; | ||||
2781 | |||||
2782 | /* t == 1 can be done in zero cost. */ | ||||
2783 | if (t == 1) | ||||
2784 | { | ||||
2785 | alg_out->ops = 1; | ||||
2786 | alg_out->cost.cost = 0; | ||||
2787 | alg_out->cost.latency = 0; | ||||
2788 | alg_out->op[0] = alg_m; | ||||
2789 | return; | ||||
2790 | } | ||||
2791 | |||||
2792 | /* t == 0 sometimes has a cost. If it does and it exceeds our limit, | ||||
2793 | fail now. */ | ||||
2794 | if (t == 0) | ||||
2795 | { | ||||
2796 | if (MULT_COST_LESS (cost_limit, zero_cost (speed))((cost_limit)->cost < (zero_cost (speed)) || ((cost_limit )->cost == (zero_cost (speed)) && (cost_limit)-> latency < (zero_cost (speed))))) | ||||
2797 | return; | ||||
2798 | else | ||||
2799 | { | ||||
2800 | alg_out->ops = 1; | ||||
2801 | alg_out->cost.cost = zero_cost (speed); | ||||
2802 | alg_out->cost.latency = zero_cost (speed); | ||||
2803 | alg_out->op[0] = alg_zero; | ||||
2804 | return; | ||||
2805 | } | ||||
2806 | } | ||||
2807 | |||||
2808 | /* We'll be needing a couple extra algorithm structures now. */ | ||||
2809 | |||||
2810 | alg_in = XALLOCA (struct algorithm)((struct algorithm *) __builtin_alloca(sizeof (struct algorithm ))); | ||||
2811 | best_alg = XALLOCA (struct algorithm)((struct algorithm *) __builtin_alloca(sizeof (struct algorithm ))); | ||||
2812 | best_cost = *cost_limit; | ||||
2813 | |||||
2814 | /* Compute the hash index. */ | ||||
2815 | hash_index = (t ^ (unsigned int) mode ^ (speed * 256)) % NUM_ALG_HASH_ENTRIES1031; | ||||
2816 | |||||
2817 | /* See if we already know what to do for T. */ | ||||
2818 | entry_ptr = alg_hash_entry_ptr (hash_index); | ||||
2819 | if (entry_ptr->t == t | ||||
2820 | && entry_ptr->mode == mode | ||||
2821 | && entry_ptr->speed == speed | ||||
2822 | && entry_ptr->alg != alg_unknown) | ||||
2823 | { | ||||
2824 | cache_alg = entry_ptr->alg; | ||||
2825 | |||||
2826 | if (cache_alg == alg_impossible) | ||||
2827 | { | ||||
2828 | /* The cache tells us that it's impossible to synthesize | ||||
2829 | multiplication by T within entry_ptr->cost. */ | ||||
2830 | if (!CHEAPER_MULT_COST (&entry_ptr->cost, cost_limit)((&entry_ptr->cost)->cost < (cost_limit)->cost || ((&entry_ptr->cost)->cost == (cost_limit)->cost && (&entry_ptr->cost)->latency < (cost_limit )->latency))) | ||||
2831 | /* COST_LIMIT is at least as restrictive as the one | ||||
2832 | recorded in the hash table, in which case we have no | ||||
2833 | hope of synthesizing a multiplication. Just | ||||
2834 | return. */ | ||||
2835 | return; | ||||
2836 | |||||
2837 | /* If we get here, COST_LIMIT is less restrictive than the | ||||
2838 | one recorded in the hash table, so we may be able to | ||||
2839 | synthesize a multiplication. Proceed as if we didn't | ||||
2840 | have the cache entry. */ | ||||
2841 | } | ||||
2842 | else | ||||
2843 | { | ||||
2844 | if (CHEAPER_MULT_COST (cost_limit, &entry_ptr->cost)((cost_limit)->cost < (&entry_ptr->cost)->cost || ((cost_limit)->cost == (&entry_ptr->cost)->cost && (cost_limit)->latency < (&entry_ptr-> cost)->latency))) | ||||
2845 | /* The cached algorithm shows that this multiplication | ||||
2846 | requires more cost than COST_LIMIT. Just return. This | ||||
2847 | way, we don't clobber this cache entry with | ||||
2848 | alg_impossible but retain useful information. */ | ||||
2849 | return; | ||||
2850 | |||||
2851 | cache_hit = true; | ||||
2852 | |||||
2853 | switch (cache_alg) | ||||
2854 | { | ||||
2855 | case alg_shift: | ||||
2856 | goto do_alg_shift; | ||||
2857 | |||||
2858 | case alg_add_t_m2: | ||||
2859 | case alg_sub_t_m2: | ||||
2860 | goto do_alg_addsub_t_m2; | ||||
2861 | |||||
2862 | case alg_add_factor: | ||||
2863 | case alg_sub_factor: | ||||
2864 | goto do_alg_addsub_factor; | ||||
2865 | |||||
2866 | case alg_add_t2_m: | ||||
2867 | goto do_alg_add_t2_m; | ||||
2868 | |||||
2869 | case alg_sub_t2_m: | ||||
2870 | goto do_alg_sub_t2_m; | ||||
2871 | |||||
2872 | default: | ||||
2873 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 2873, __FUNCTION__)); | ||||
2874 | } | ||||
2875 | } | ||||
2876 | } | ||||
2877 | |||||
2878 | /* If we have a group of zero bits at the low-order part of T, try | ||||
2879 | multiplying by the remaining bits and then doing a shift. */ | ||||
2880 | |||||
2881 | if ((t & 1) == 0) | ||||
2882 | { | ||||
2883 | do_alg_shift: | ||||
2884 | m = ctz_or_zero (t); /* m = number of low zero bits */ | ||||
2885 | if (m < maxm) | ||||
2886 | { | ||||
2887 | q = t >> m; | ||||
2888 | /* The function expand_shift will choose between a shift and | ||||
2889 | a sequence of additions, so the observed cost is given as | ||||
2890 | MIN (m * add_cost(speed, mode), shift_cost(speed, mode, m)). */ | ||||
2891 | op_cost = m * add_cost (speed, mode); | ||||
2892 | if (shift_cost (speed, mode, m) < op_cost) | ||||
2893 | op_cost = shift_cost (speed, mode, m); | ||||
2894 | new_limit.cost = best_cost.cost - op_cost; | ||||
2895 | new_limit.latency = best_cost.latency - op_cost; | ||||
2896 | synth_mult (alg_in, q, &new_limit, mode); | ||||
2897 | |||||
2898 | alg_in->cost.cost += op_cost; | ||||
2899 | alg_in->cost.latency += op_cost; | ||||
2900 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
2901 | { | ||||
2902 | best_cost = alg_in->cost; | ||||
2903 | std::swap (alg_in, best_alg); | ||||
2904 | best_alg->log[best_alg->ops] = m; | ||||
2905 | best_alg->op[best_alg->ops] = alg_shift; | ||||
2906 | } | ||||
2907 | |||||
2908 | /* See if treating ORIG_T as a signed number yields a better | ||||
2909 | sequence. Try this sequence only for a negative ORIG_T | ||||
2910 | as it would be useless for a non-negative ORIG_T. */ | ||||
2911 | if ((HOST_WIDE_INTlong) orig_t < 0) | ||||
2912 | { | ||||
2913 | /* Shift ORIG_T as follows because a right shift of a | ||||
2914 | negative-valued signed type is implementation | ||||
2915 | defined. */ | ||||
2916 | q = ~(~orig_t >> m); | ||||
2917 | /* The function expand_shift will choose between a shift | ||||
2918 | and a sequence of additions, so the observed cost is | ||||
2919 | given as MIN (m * add_cost(speed, mode), | ||||
2920 | shift_cost(speed, mode, m)). */ | ||||
2921 | op_cost = m * add_cost (speed, mode); | ||||
2922 | if (shift_cost (speed, mode, m) < op_cost) | ||||
2923 | op_cost = shift_cost (speed, mode, m); | ||||
2924 | new_limit.cost = best_cost.cost - op_cost; | ||||
2925 | new_limit.latency = best_cost.latency - op_cost; | ||||
2926 | synth_mult (alg_in, q, &new_limit, mode); | ||||
2927 | |||||
2928 | alg_in->cost.cost += op_cost; | ||||
2929 | alg_in->cost.latency += op_cost; | ||||
2930 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
2931 | { | ||||
2932 | best_cost = alg_in->cost; | ||||
2933 | std::swap (alg_in, best_alg); | ||||
2934 | best_alg->log[best_alg->ops] = m; | ||||
2935 | best_alg->op[best_alg->ops] = alg_shift; | ||||
2936 | } | ||||
2937 | } | ||||
2938 | } | ||||
2939 | if (cache_hit) | ||||
2940 | goto done; | ||||
2941 | } | ||||
2942 | |||||
2943 | /* If we have an odd number, add or subtract one. */ | ||||
2944 | if ((t & 1) != 0) | ||||
2945 | { | ||||
2946 | unsigned HOST_WIDE_INTlong w; | ||||
2947 | |||||
2948 | do_alg_addsub_t_m2: | ||||
2949 | for (w = 1; (w & t) != 0; w <<= 1) | ||||
2950 | ; | ||||
2951 | /* If T was -1, then W will be zero after the loop. This is another | ||||
2952 | case where T ends with ...111. Handling this with (T + 1) and | ||||
2953 | subtract 1 produces slightly better code and results in algorithm | ||||
2954 | selection much faster than treating it like the ...0111 case | ||||
2955 | below. */ | ||||
2956 | if (w == 0 | ||||
2957 | || (w > 2 | ||||
2958 | /* Reject the case where t is 3. | ||||
2959 | Thus we prefer addition in that case. */ | ||||
2960 | && t != 3)) | ||||
2961 | { | ||||
2962 | /* T ends with ...111. Multiply by (T + 1) and subtract T. */ | ||||
2963 | |||||
2964 | op_cost = add_cost (speed, mode); | ||||
2965 | new_limit.cost = best_cost.cost - op_cost; | ||||
2966 | new_limit.latency = best_cost.latency - op_cost; | ||||
2967 | synth_mult (alg_in, t + 1, &new_limit, mode); | ||||
2968 | |||||
2969 | alg_in->cost.cost += op_cost; | ||||
2970 | alg_in->cost.latency += op_cost; | ||||
2971 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
2972 | { | ||||
2973 | best_cost = alg_in->cost; | ||||
2974 | std::swap (alg_in, best_alg); | ||||
2975 | best_alg->log[best_alg->ops] = 0; | ||||
2976 | best_alg->op[best_alg->ops] = alg_sub_t_m2; | ||||
2977 | } | ||||
2978 | } | ||||
2979 | else | ||||
2980 | { | ||||
2981 | /* T ends with ...01 or ...011. Multiply by (T - 1) and add T. */ | ||||
2982 | |||||
2983 | op_cost = add_cost (speed, mode); | ||||
2984 | new_limit.cost = best_cost.cost - op_cost; | ||||
2985 | new_limit.latency = best_cost.latency - op_cost; | ||||
2986 | synth_mult (alg_in, t - 1, &new_limit, mode); | ||||
2987 | |||||
2988 | alg_in->cost.cost += op_cost; | ||||
2989 | alg_in->cost.latency += op_cost; | ||||
2990 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
2991 | { | ||||
2992 | best_cost = alg_in->cost; | ||||
2993 | std::swap (alg_in, best_alg); | ||||
2994 | best_alg->log[best_alg->ops] = 0; | ||||
2995 | best_alg->op[best_alg->ops] = alg_add_t_m2; | ||||
2996 | } | ||||
2997 | } | ||||
2998 | |||||
2999 | /* We may be able to calculate a * -7, a * -15, a * -31, etc | ||||
3000 | quickly with a - a * n for some appropriate constant n. */ | ||||
3001 | m = exact_log2 (-orig_t + 1); | ||||
3002 | if (m >= 0 && m < maxm) | ||||
3003 | { | ||||
3004 | op_cost = add_cost (speed, mode) + shift_cost (speed, mode, m); | ||||
3005 | /* If the target has a cheap shift-and-subtract insn use | ||||
3006 | that in preference to a shift insn followed by a sub insn. | ||||
3007 | Assume that the shift-and-sub is "atomic" with a latency | ||||
3008 | equal to it's cost, otherwise assume that on superscalar | ||||
3009 | hardware the shift may be executed concurrently with the | ||||
3010 | earlier steps in the algorithm. */ | ||||
3011 | if (shiftsub1_cost (speed, mode, m) <= op_cost) | ||||
3012 | { | ||||
3013 | op_cost = shiftsub1_cost (speed, mode, m); | ||||
3014 | op_latency = op_cost; | ||||
3015 | } | ||||
3016 | else | ||||
3017 | op_latency = add_cost (speed, mode); | ||||
3018 | |||||
3019 | new_limit.cost = best_cost.cost - op_cost; | ||||
3020 | new_limit.latency = best_cost.latency - op_latency; | ||||
3021 | synth_mult (alg_in, (unsigned HOST_WIDE_INTlong) (-orig_t + 1) >> m, | ||||
3022 | &new_limit, mode); | ||||
3023 | |||||
3024 | alg_in->cost.cost += op_cost; | ||||
3025 | alg_in->cost.latency += op_latency; | ||||
3026 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
3027 | { | ||||
3028 | best_cost = alg_in->cost; | ||||
3029 | std::swap (alg_in, best_alg); | ||||
3030 | best_alg->log[best_alg->ops] = m; | ||||
3031 | best_alg->op[best_alg->ops] = alg_sub_t_m2; | ||||
3032 | } | ||||
3033 | } | ||||
3034 | |||||
3035 | if (cache_hit) | ||||
3036 | goto done; | ||||
3037 | } | ||||
3038 | |||||
3039 | /* Look for factors of t of the form | ||||
3040 | t = q(2**m +- 1), 2 <= m <= floor(log2(t - 1)). | ||||
3041 | If we find such a factor, we can multiply by t using an algorithm that | ||||
3042 | multiplies by q, shift the result by m and add/subtract it to itself. | ||||
3043 | |||||
3044 | We search for large factors first and loop down, even if large factors | ||||
3045 | are less probable than small; if we find a large factor we will find a | ||||
3046 | good sequence quickly, and therefore be able to prune (by decreasing | ||||
3047 | COST_LIMIT) the search. */ | ||||
3048 | |||||
3049 | do_alg_addsub_factor: | ||||
3050 | for (m = floor_log2 (t - 1); m >= 2; m--) | ||||
3051 | { | ||||
3052 | unsigned HOST_WIDE_INTlong d; | ||||
3053 | |||||
3054 | d = (HOST_WIDE_INT_1U1UL << m) + 1; | ||||
3055 | if (t % d == 0 && t > d && m < maxm | ||||
3056 | && (!cache_hit || cache_alg == alg_add_factor)) | ||||
3057 | { | ||||
3058 | op_cost = add_cost (speed, mode) + shift_cost (speed, mode, m); | ||||
3059 | if (shiftadd_cost (speed, mode, m) <= op_cost) | ||||
3060 | op_cost = shiftadd_cost (speed, mode, m); | ||||
3061 | |||||
3062 | op_latency = op_cost; | ||||
3063 | |||||
3064 | |||||
3065 | new_limit.cost = best_cost.cost - op_cost; | ||||
3066 | new_limit.latency = best_cost.latency - op_latency; | ||||
3067 | synth_mult (alg_in, t / d, &new_limit, mode); | ||||
3068 | |||||
3069 | alg_in->cost.cost += op_cost; | ||||
3070 | alg_in->cost.latency += op_latency; | ||||
3071 | if (alg_in->cost.latency < op_cost) | ||||
3072 | alg_in->cost.latency = op_cost; | ||||
3073 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
3074 | { | ||||
3075 | best_cost = alg_in->cost; | ||||
3076 | std::swap (alg_in, best_alg); | ||||
3077 | best_alg->log[best_alg->ops] = m; | ||||
3078 | best_alg->op[best_alg->ops] = alg_add_factor; | ||||
3079 | } | ||||
3080 | /* Other factors will have been taken care of in the recursion. */ | ||||
3081 | break; | ||||
3082 | } | ||||
3083 | |||||
3084 | d = (HOST_WIDE_INT_1U1UL << m) - 1; | ||||
3085 | if (t % d == 0 && t > d && m < maxm | ||||
3086 | && (!cache_hit || cache_alg == alg_sub_factor)) | ||||
3087 | { | ||||
3088 | op_cost = add_cost (speed, mode) + shift_cost (speed, mode, m); | ||||
3089 | if (shiftsub0_cost (speed, mode, m) <= op_cost) | ||||
3090 | op_cost = shiftsub0_cost (speed, mode, m); | ||||
3091 | |||||
3092 | op_latency = op_cost; | ||||
3093 | |||||
3094 | new_limit.cost = best_cost.cost - op_cost; | ||||
3095 | new_limit.latency = best_cost.latency - op_latency; | ||||
3096 | synth_mult (alg_in, t / d, &new_limit, mode); | ||||
3097 | |||||
3098 | alg_in->cost.cost += op_cost; | ||||
3099 | alg_in->cost.latency += op_latency; | ||||
3100 | if (alg_in->cost.latency < op_cost) | ||||
3101 | alg_in->cost.latency = op_cost; | ||||
3102 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
3103 | { | ||||
3104 | best_cost = alg_in->cost; | ||||
3105 | std::swap (alg_in, best_alg); | ||||
3106 | best_alg->log[best_alg->ops] = m; | ||||
3107 | best_alg->op[best_alg->ops] = alg_sub_factor; | ||||
3108 | } | ||||
3109 | break; | ||||
3110 | } | ||||
3111 | } | ||||
3112 | if (cache_hit) | ||||
3113 | goto done; | ||||
3114 | |||||
3115 | /* Try shift-and-add (load effective address) instructions, | ||||
3116 | i.e. do a*3, a*5, a*9. */ | ||||
3117 | if ((t & 1) != 0) | ||||
3118 | { | ||||
3119 | do_alg_add_t2_m: | ||||
3120 | q = t - 1; | ||||
3121 | m = ctz_hwi (q); | ||||
3122 | if (q && m < maxm) | ||||
3123 | { | ||||
3124 | op_cost = shiftadd_cost (speed, mode, m); | ||||
3125 | new_limit.cost = best_cost.cost - op_cost; | ||||
3126 | new_limit.latency = best_cost.latency - op_cost; | ||||
3127 | synth_mult (alg_in, (t - 1) >> m, &new_limit, mode); | ||||
3128 | |||||
3129 | alg_in->cost.cost += op_cost; | ||||
3130 | alg_in->cost.latency += op_cost; | ||||
3131 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
3132 | { | ||||
3133 | best_cost = alg_in->cost; | ||||
3134 | std::swap (alg_in, best_alg); | ||||
3135 | best_alg->log[best_alg->ops] = m; | ||||
3136 | best_alg->op[best_alg->ops] = alg_add_t2_m; | ||||
3137 | } | ||||
3138 | } | ||||
3139 | if (cache_hit) | ||||
3140 | goto done; | ||||
3141 | |||||
3142 | do_alg_sub_t2_m: | ||||
3143 | q = t + 1; | ||||
3144 | m = ctz_hwi (q); | ||||
3145 | if (q && m < maxm) | ||||
3146 | { | ||||
3147 | op_cost = shiftsub0_cost (speed, mode, m); | ||||
3148 | new_limit.cost = best_cost.cost - op_cost; | ||||
3149 | new_limit.latency = best_cost.latency - op_cost; | ||||
3150 | synth_mult (alg_in, (t + 1) >> m, &new_limit, mode); | ||||
3151 | |||||
3152 | alg_in->cost.cost += op_cost; | ||||
3153 | alg_in->cost.latency += op_cost; | ||||
3154 | if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost)((&alg_in->cost)->cost < (&best_cost)->cost || ((&alg_in->cost)->cost == (&best_cost)-> cost && (&alg_in->cost)->latency < (& best_cost)->latency))) | ||||
3155 | { | ||||
3156 | best_cost = alg_in->cost; | ||||
3157 | std::swap (alg_in, best_alg); | ||||
3158 | best_alg->log[best_alg->ops] = m; | ||||
3159 | best_alg->op[best_alg->ops] = alg_sub_t2_m; | ||||
3160 | } | ||||
3161 | } | ||||
3162 | if (cache_hit) | ||||
3163 | goto done; | ||||
3164 | } | ||||
3165 | |||||
3166 | done: | ||||
3167 | /* If best_cost has not decreased, we have not found any algorithm. */ | ||||
3168 | if (!CHEAPER_MULT_COST (&best_cost, cost_limit)((&best_cost)->cost < (cost_limit)->cost || ((& best_cost)->cost == (cost_limit)->cost && (& best_cost)->latency < (cost_limit)->latency))) | ||||
3169 | { | ||||
3170 | /* We failed to find an algorithm. Record alg_impossible for | ||||
3171 | this case (that is, <T, MODE, COST_LIMIT>) so that next time | ||||
3172 | we are asked to find an algorithm for T within the same or | ||||
3173 | lower COST_LIMIT, we can immediately return to the | ||||
3174 | caller. */ | ||||
3175 | entry_ptr->t = t; | ||||
3176 | entry_ptr->mode = mode; | ||||
3177 | entry_ptr->speed = speed; | ||||
3178 | entry_ptr->alg = alg_impossible; | ||||
3179 | entry_ptr->cost = *cost_limit; | ||||
3180 | return; | ||||
3181 | } | ||||
3182 | |||||
3183 | /* Cache the result. */ | ||||
3184 | if (!cache_hit) | ||||
3185 | { | ||||
3186 | entry_ptr->t = t; | ||||
3187 | entry_ptr->mode = mode; | ||||
3188 | entry_ptr->speed = speed; | ||||
3189 | entry_ptr->alg = best_alg->op[best_alg->ops]; | ||||
3190 | entry_ptr->cost.cost = best_cost.cost; | ||||
3191 | entry_ptr->cost.latency = best_cost.latency; | ||||
3192 | } | ||||
3193 | |||||
3194 | /* If we are getting a too long sequence for `struct algorithm' | ||||
3195 | to record, make this search fail. */ | ||||
3196 | if (best_alg->ops == MAX_BITS_PER_WORD64) | ||||
3197 | return; | ||||
3198 | |||||
3199 | /* Copy the algorithm from temporary space to the space at alg_out. | ||||
3200 | We avoid using structure assignment because the majority of | ||||
3201 | best_alg is normally undefined, and this is a critical function. */ | ||||
3202 | alg_out->ops = best_alg->ops + 1; | ||||
3203 | alg_out->cost = best_cost; | ||||
3204 | memcpy (alg_out->op, best_alg->op, | ||||
3205 | alg_out->ops * sizeof *alg_out->op); | ||||
3206 | memcpy (alg_out->log, best_alg->log, | ||||
3207 | alg_out->ops * sizeof *alg_out->log); | ||||
3208 | } | ||||
3209 | |||||
3210 | /* Find the cheapest way of multiplying a value of mode MODE by VAL. | ||||
3211 | Try three variations: | ||||
3212 | |||||
3213 | - a shift/add sequence based on VAL itself | ||||
3214 | - a shift/add sequence based on -VAL, followed by a negation | ||||
3215 | - a shift/add sequence based on VAL - 1, followed by an addition. | ||||
3216 | |||||
3217 | Return true if the cheapest of these cost less than MULT_COST, | ||||
3218 | describing the algorithm in *ALG and final fixup in *VARIANT. */ | ||||
3219 | |||||
3220 | bool | ||||
3221 | choose_mult_variant (machine_mode mode, HOST_WIDE_INTlong val, | ||||
3222 | struct algorithm *alg, enum mult_variant *variant, | ||||
3223 | int mult_cost) | ||||
3224 | { | ||||
3225 | struct algorithm alg2; | ||||
3226 | struct mult_cost limit; | ||||
3227 | int op_cost; | ||||
3228 | bool speed = optimize_insn_for_speed_p (); | ||||
3229 | |||||
3230 | /* Fail quickly for impossible bounds. */ | ||||
3231 | if (mult_cost < 0) | ||||
3232 | return false; | ||||
3233 | |||||
3234 | /* Ensure that mult_cost provides a reasonable upper bound. | ||||
3235 | Any constant multiplication can be performed with less | ||||
3236 | than 2 * bits additions. */ | ||||
3237 | op_cost = 2 * GET_MODE_UNIT_BITSIZE (mode)((unsigned short) (mode_to_unit_size (mode) * (8))) * add_cost (speed, mode); | ||||
3238 | if (mult_cost > op_cost) | ||||
3239 | mult_cost = op_cost; | ||||
3240 | |||||
3241 | *variant = basic_variant; | ||||
3242 | limit.cost = mult_cost; | ||||
3243 | limit.latency = mult_cost; | ||||
3244 | synth_mult (alg, val, &limit, mode); | ||||
3245 | |||||
3246 | /* This works only if the inverted value actually fits in an | ||||
3247 | `unsigned int' */ | ||||
3248 | if (HOST_BITS_PER_INT(8 * 4) >= GET_MODE_UNIT_BITSIZE (mode)((unsigned short) (mode_to_unit_size (mode) * (8)))) | ||||
3249 | { | ||||
3250 | op_cost = neg_cost (speed, mode); | ||||
3251 | if (MULT_COST_LESS (&alg->cost, mult_cost)((&alg->cost)->cost < (mult_cost) || ((&alg-> cost)->cost == (mult_cost) && (&alg->cost)-> latency < (mult_cost)))) | ||||
3252 | { | ||||
3253 | limit.cost = alg->cost.cost - op_cost; | ||||
3254 | limit.latency = alg->cost.latency - op_cost; | ||||
3255 | } | ||||
3256 | else | ||||
3257 | { | ||||
3258 | limit.cost = mult_cost - op_cost; | ||||
3259 | limit.latency = mult_cost - op_cost; | ||||
3260 | } | ||||
3261 | |||||
3262 | synth_mult (&alg2, -val, &limit, mode); | ||||
3263 | alg2.cost.cost += op_cost; | ||||
3264 | alg2.cost.latency += op_cost; | ||||
3265 | if (CHEAPER_MULT_COST (&alg2.cost, &alg->cost)((&alg2.cost)->cost < (&alg->cost)->cost || ((&alg2.cost)->cost == (&alg->cost)->cost && (&alg2.cost)->latency < (&alg->cost)->latency ))) | ||||
3266 | *alg = alg2, *variant = negate_variant; | ||||
3267 | } | ||||
3268 | |||||
3269 | /* This proves very useful for division-by-constant. */ | ||||
3270 | op_cost = add_cost (speed, mode); | ||||
3271 | if (MULT_COST_LESS (&alg->cost, mult_cost)((&alg->cost)->cost < (mult_cost) || ((&alg-> cost)->cost == (mult_cost) && (&alg->cost)-> latency < (mult_cost)))) | ||||
3272 | { | ||||
3273 | limit.cost = alg->cost.cost - op_cost; | ||||
3274 | limit.latency = alg->cost.latency - op_cost; | ||||
3275 | } | ||||
3276 | else | ||||
3277 | { | ||||
3278 | limit.cost = mult_cost - op_cost; | ||||
3279 | limit.latency = mult_cost - op_cost; | ||||
3280 | } | ||||
3281 | |||||
3282 | synth_mult (&alg2, val - 1, &limit, mode); | ||||
3283 | alg2.cost.cost += op_cost; | ||||
3284 | alg2.cost.latency += op_cost; | ||||
3285 | if (CHEAPER_MULT_COST (&alg2.cost, &alg->cost)((&alg2.cost)->cost < (&alg->cost)->cost || ((&alg2.cost)->cost == (&alg->cost)->cost && (&alg2.cost)->latency < (&alg->cost)->latency ))) | ||||
3286 | *alg = alg2, *variant = add_variant; | ||||
3287 | |||||
3288 | return MULT_COST_LESS (&alg->cost, mult_cost)((&alg->cost)->cost < (mult_cost) || ((&alg-> cost)->cost == (mult_cost) && (&alg->cost)-> latency < (mult_cost))); | ||||
3289 | } | ||||
3290 | |||||
3291 | /* A subroutine of expand_mult, used for constant multiplications. | ||||
3292 | Multiply OP0 by VAL in mode MODE, storing the result in TARGET if | ||||
3293 | convenient. Use the shift/add sequence described by ALG and apply | ||||
3294 | the final fixup specified by VARIANT. */ | ||||
3295 | |||||
3296 | static rtx | ||||
3297 | expand_mult_const (machine_mode mode, rtx op0, HOST_WIDE_INTlong val, | ||||
3298 | rtx target, const struct algorithm *alg, | ||||
3299 | enum mult_variant variant) | ||||
3300 | { | ||||
3301 | unsigned HOST_WIDE_INTlong val_so_far; | ||||
3302 | rtx_insn *insn; | ||||
3303 | rtx accum, tem; | ||||
3304 | int opno; | ||||
3305 | machine_mode nmode; | ||||
3306 | |||||
3307 | /* Avoid referencing memory over and over and invalid sharing | ||||
3308 | on SUBREGs. */ | ||||
3309 | op0 = force_reg (mode, op0); | ||||
3310 | |||||
3311 | /* ACCUM starts out either as OP0 or as a zero, depending on | ||||
3312 | the first operation. */ | ||||
3313 | |||||
3314 | if (alg->op[0] == alg_zero) | ||||
3315 | { | ||||
3316 | accum = copy_to_mode_reg (mode, CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)])); | ||||
3317 | val_so_far = 0; | ||||
3318 | } | ||||
3319 | else if (alg->op[0] == alg_m) | ||||
3320 | { | ||||
3321 | accum = copy_to_mode_reg (mode, op0); | ||||
3322 | val_so_far = 1; | ||||
3323 | } | ||||
3324 | else | ||||
3325 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 3325, __FUNCTION__)); | ||||
3326 | |||||
3327 | for (opno = 1; opno < alg->ops; opno++) | ||||
3328 | { | ||||
3329 | int log = alg->log[opno]; | ||||
3330 | rtx shift_subtarget = optimizeglobal_options.x_optimize ? 0 : accum; | ||||
3331 | rtx add_target | ||||
3332 | = (opno == alg->ops - 1 && target != 0 && variant != add_variant | ||||
3333 | && !optimizeglobal_options.x_optimize) | ||||
3334 | ? target : 0; | ||||
3335 | rtx accum_target = optimizeglobal_options.x_optimize ? 0 : accum; | ||||
3336 | rtx accum_inner; | ||||
3337 | |||||
3338 | switch (alg->op[opno]) | ||||
3339 | { | ||||
3340 | case alg_shift: | ||||
3341 | tem = expand_shift (LSHIFT_EXPR, mode, accum, log, NULL_RTX(rtx) 0, 0); | ||||
3342 | /* REG_EQUAL note will be attached to the following insn. */ | ||||
3343 | emit_move_insn (accum, tem); | ||||
3344 | val_so_far <<= log; | ||||
3345 | break; | ||||
3346 | |||||
3347 | case alg_add_t_m2: | ||||
3348 | tem = expand_shift (LSHIFT_EXPR, mode, op0, log, NULL_RTX(rtx) 0, 0); | ||||
3349 | accum = force_operand (gen_rtx_PLUS (mode, accum, tem)gen_rtx_fmt_ee_stat ((PLUS), ((mode)), ((accum)), ((tem)) ), | ||||
3350 | add_target ? add_target : accum_target); | ||||
3351 | val_so_far += HOST_WIDE_INT_1U1UL << log; | ||||
3352 | break; | ||||
3353 | |||||
3354 | case alg_sub_t_m2: | ||||
3355 | tem = expand_shift (LSHIFT_EXPR, mode, op0, log, NULL_RTX(rtx) 0, 0); | ||||
3356 | accum = force_operand (gen_rtx_MINUS (mode, accum, tem)gen_rtx_fmt_ee_stat ((MINUS), ((mode)), ((accum)), ((tem)) ), | ||||
3357 | add_target ? add_target : accum_target); | ||||
3358 | val_so_far -= HOST_WIDE_INT_1U1UL << log; | ||||
3359 | break; | ||||
3360 | |||||
3361 | case alg_add_t2_m: | ||||
3362 | accum = expand_shift (LSHIFT_EXPR, mode, accum, | ||||
3363 | log, shift_subtarget, 0); | ||||
3364 | accum = force_operand (gen_rtx_PLUS (mode, accum, op0)gen_rtx_fmt_ee_stat ((PLUS), ((mode)), ((accum)), ((op0)) ), | ||||
3365 | add_target ? add_target : accum_target); | ||||
3366 | val_so_far = (val_so_far << log) + 1; | ||||
3367 | break; | ||||
3368 | |||||
3369 | case alg_sub_t2_m: | ||||
3370 | accum = expand_shift (LSHIFT_EXPR, mode, accum, | ||||
3371 | log, shift_subtarget, 0); | ||||
3372 | accum = force_operand (gen_rtx_MINUS (mode, accum, op0)gen_rtx_fmt_ee_stat ((MINUS), ((mode)), ((accum)), ((op0)) ), | ||||
3373 | add_target ? add_target : accum_target); | ||||
3374 | val_so_far = (val_so_far << log) - 1; | ||||
3375 | break; | ||||
3376 | |||||
3377 | case alg_add_factor: | ||||
3378 | tem = expand_shift (LSHIFT_EXPR, mode, accum, log, NULL_RTX(rtx) 0, 0); | ||||
3379 | accum = force_operand (gen_rtx_PLUS (mode, accum, tem)gen_rtx_fmt_ee_stat ((PLUS), ((mode)), ((accum)), ((tem)) ), | ||||
3380 | add_target ? add_target : accum_target); | ||||
3381 | val_so_far += val_so_far << log; | ||||
3382 | break; | ||||
3383 | |||||
3384 | case alg_sub_factor: | ||||
3385 | tem = expand_shift (LSHIFT_EXPR, mode, accum, log, NULL_RTX(rtx) 0, 0); | ||||
3386 | accum = force_operand (gen_rtx_MINUS (mode, tem, accum)gen_rtx_fmt_ee_stat ((MINUS), ((mode)), ((tem)), ((accum)) ), | ||||
3387 | (add_target | ||||
3388 | ? add_target : (optimizeglobal_options.x_optimize ? 0 : tem))); | ||||
3389 | val_so_far = (val_so_far << log) - val_so_far; | ||||
3390 | break; | ||||
3391 | |||||
3392 | default: | ||||
3393 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 3393, __FUNCTION__)); | ||||
3394 | } | ||||
3395 | |||||
3396 | if (SCALAR_INT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_INT || ((enum mode_class ) mode_class[mode]) == MODE_PARTIAL_INT)) | ||||
3397 | { | ||||
3398 | /* Write a REG_EQUAL note on the last insn so that we can cse | ||||
3399 | multiplication sequences. Note that if ACCUM is a SUBREG, | ||||
3400 | we've set the inner register and must properly indicate that. */ | ||||
3401 | tem = op0, nmode = mode; | ||||
3402 | accum_inner = accum; | ||||
3403 | if (GET_CODE (accum)((enum rtx_code) (accum)->code) == SUBREG) | ||||
3404 | { | ||||
3405 | accum_inner = SUBREG_REG (accum)(((accum)->u.fld[0]).rt_rtx); | ||||
3406 | nmode = GET_MODE (accum_inner)((machine_mode) (accum_inner)->mode); | ||||
3407 | tem = gen_lowpartrtl_hooks.gen_lowpart (nmode, op0); | ||||
3408 | } | ||||
3409 | |||||
3410 | /* Don't add a REG_EQUAL note if tem is a paradoxical SUBREG. | ||||
3411 | In that case, only the low bits of accum would be guaranteed to | ||||
3412 | be equal to the content of the REG_EQUAL note, the upper bits | ||||
3413 | can be anything. */ | ||||
3414 | if (!paradoxical_subreg_p (tem)) | ||||
3415 | { | ||||
3416 | insn = get_last_insn (); | ||||
3417 | wide_int wval_so_far | ||||
3418 | = wi::uhwi (val_so_far, | ||||
3419 | GET_MODE_PRECISION (as_a <scalar_mode> (nmode))); | ||||
3420 | rtx c = immed_wide_int_const (wval_so_far, nmode); | ||||
3421 | set_dst_reg_note (insn, REG_EQUAL, gen_rtx_MULT (nmode, tem, c)gen_rtx_fmt_ee_stat ((MULT), ((nmode)), ((tem)), ((c)) ), | ||||
3422 | accum_inner); | ||||
3423 | } | ||||
3424 | } | ||||
3425 | } | ||||
3426 | |||||
3427 | if (variant == negate_variant) | ||||
3428 | { | ||||
3429 | val_so_far = -val_so_far; | ||||
3430 | accum = expand_unop (mode, neg_optab, accum, target, 0); | ||||
3431 | } | ||||
3432 | else if (variant == add_variant) | ||||
3433 | { | ||||
3434 | val_so_far = val_so_far + 1; | ||||
3435 | accum = force_operand (gen_rtx_PLUS (mode, accum, op0)gen_rtx_fmt_ee_stat ((PLUS), ((mode)), ((accum)), ((op0)) ), target); | ||||
3436 | } | ||||
3437 | |||||
3438 | /* Compare only the bits of val and val_so_far that are significant | ||||
3439 | in the result mode, to avoid sign-/zero-extension confusion. */ | ||||
3440 | nmode = GET_MODE_INNER (mode)(mode_to_inner (mode)); | ||||
3441 | val &= GET_MODE_MASK (nmode)mode_mask_array[nmode]; | ||||
3442 | val_so_far &= GET_MODE_MASK (nmode)mode_mask_array[nmode]; | ||||
3443 | gcc_assert (val == (HOST_WIDE_INT) val_so_far)((void)(!(val == (long) val_so_far) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 3443, __FUNCTION__), 0 : 0)); | ||||
3444 | |||||
3445 | return accum; | ||||
3446 | } | ||||
3447 | |||||
3448 | /* Perform a multiplication and return an rtx for the result. | ||||
3449 | MODE is mode of value; OP0 and OP1 are what to multiply (rtx's); | ||||
3450 | TARGET is a suggestion for where to store the result (an rtx). | ||||
3451 | |||||
3452 | We check specially for a constant integer as OP1. | ||||
3453 | If you want this check for OP0 as well, then before calling | ||||
3454 | you should swap the two operands if OP0 would be constant. */ | ||||
3455 | |||||
3456 | rtx | ||||
3457 | expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target, | ||||
3458 | int unsignedp, bool no_libcall) | ||||
3459 | { | ||||
3460 | enum mult_variant variant; | ||||
3461 | struct algorithm algorithm; | ||||
3462 | rtx scalar_op1; | ||||
3463 | int max_cost; | ||||
3464 | bool speed = optimize_insn_for_speed_p (); | ||||
3465 | bool do_trapv = flag_trapvglobal_options.x_flag_trapv && SCALAR_INT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_INT || ((enum mode_class ) mode_class[mode]) == MODE_PARTIAL_INT) && !unsignedp; | ||||
3466 | |||||
3467 | if (CONSTANT_P (op0)((rtx_class[(int) (((enum rtx_code) (op0)->code))]) == RTX_CONST_OBJ )) | ||||
3468 | std::swap (op0, op1); | ||||
3469 | |||||
3470 | /* For vectors, there are several simplifications that can be made if | ||||
3471 | all elements of the vector constant are identical. */ | ||||
3472 | scalar_op1 = unwrap_const_vec_duplicate (op1); | ||||
3473 | |||||
3474 | if (INTEGRAL_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_INT || ((enum mode_class ) mode_class[mode]) == MODE_PARTIAL_INT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class [mode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[ mode]) == MODE_VECTOR_INT)) | ||||
3475 | { | ||||
3476 | rtx fake_reg; | ||||
3477 | HOST_WIDE_INTlong coeff; | ||||
3478 | bool is_neg; | ||||
3479 | int mode_bitsize; | ||||
3480 | |||||
3481 | if (op1 == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)])) | ||||
3482 | return op1; | ||||
3483 | if (op1 == CONST1_RTX (mode)(const_tiny_rtx[1][(int) (mode)])) | ||||
3484 | return op0; | ||||
3485 | if (op1 == CONSTM1_RTX (mode)(const_tiny_rtx[3][(int) (mode)])) | ||||
3486 | return expand_unop (mode, do_trapv ? negv_optab : neg_optab, | ||||
3487 | op0, target, 0); | ||||
3488 | |||||
3489 | if (do_trapv) | ||||
3490 | goto skip_synth; | ||||
3491 | |||||
3492 | /* If mode is integer vector mode, check if the backend supports | ||||
3493 | vector lshift (by scalar or vector) at all. If not, we can't use | ||||
3494 | synthetized multiply. */ | ||||
3495 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_VECTOR_INT | ||||
3496 | && optab_handler (vashl_optab, mode) == CODE_FOR_nothing | ||||
3497 | && optab_handler (ashl_optab, mode) == CODE_FOR_nothing) | ||||
3498 | goto skip_synth; | ||||
3499 | |||||
3500 | /* These are the operations that are potentially turned into | ||||
3501 | a sequence of shifts and additions. */ | ||||
3502 | mode_bitsize = GET_MODE_UNIT_BITSIZE (mode)((unsigned short) (mode_to_unit_size (mode) * (8))); | ||||
3503 | |||||
3504 | /* synth_mult does an `unsigned int' multiply. As long as the mode is | ||||
3505 | less than or equal in size to `unsigned int' this doesn't matter. | ||||
3506 | If the mode is larger than `unsigned int', then synth_mult works | ||||
3507 | only if the constant value exactly fits in an `unsigned int' without | ||||
3508 | any truncation. This means that multiplying by negative values does | ||||
3509 | not work; results are off by 2^32 on a 32 bit machine. */ | ||||
3510 | if (CONST_INT_P (scalar_op1)(((enum rtx_code) (scalar_op1)->code) == CONST_INT)) | ||||
3511 | { | ||||
3512 | coeff = INTVAL (scalar_op1)((scalar_op1)->u.hwint[0]); | ||||
3513 | is_neg = coeff < 0; | ||||
3514 | } | ||||
3515 | #if TARGET_SUPPORTS_WIDE_INT1 | ||||
3516 | else if (CONST_WIDE_INT_P (scalar_op1)(((enum rtx_code) (scalar_op1)->code) == CONST_WIDE_INT)) | ||||
3517 | #else | ||||
3518 | else if (CONST_DOUBLE_AS_INT_P (scalar_op1)(((enum rtx_code) (scalar_op1)->code) == CONST_DOUBLE && ((machine_mode) (scalar_op1)->mode) == ((void) 0, E_VOIDmode ))) | ||||
3519 | #endif | ||||
3520 | { | ||||
3521 | int shift = wi::exact_log2 (rtx_mode_t (scalar_op1, mode)); | ||||
3522 | /* Perfect power of 2 (other than 1, which is handled above). */ | ||||
3523 | if (shift > 0) | ||||
3524 | return expand_shift (LSHIFT_EXPR, mode, op0, | ||||
3525 | shift, target, unsignedp); | ||||
3526 | else | ||||
3527 | goto skip_synth; | ||||
3528 | } | ||||
3529 | else | ||||
3530 | goto skip_synth; | ||||
3531 | |||||
3532 | /* We used to test optimize here, on the grounds that it's better to | ||||
3533 | produce a smaller program when -O is not used. But this causes | ||||
3534 | such a terrible slowdown sometimes that it seems better to always | ||||
3535 | use synth_mult. */ | ||||
3536 | |||||
3537 | /* Special case powers of two. */ | ||||
3538 | if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)(((coeff) & ((coeff) - 1UL)) == 0) | ||||
3539 | && !(is_neg && mode_bitsize > HOST_BITS_PER_WIDE_INT64)) | ||||
3540 | return expand_shift (LSHIFT_EXPR, mode, op0, | ||||
3541 | floor_log2 (coeff), target, unsignedp); | ||||
3542 | |||||
3543 | fake_reg = gen_raw_REG (mode, LAST_VIRTUAL_REGISTER(((76)) + 5) + 1); | ||||
3544 | |||||
3545 | /* Attempt to handle multiplication of DImode values by negative | ||||
3546 | coefficients, by performing the multiplication by a positive | ||||
3547 | multiplier and then inverting the result. */ | ||||
3548 | if (is_neg && mode_bitsize > HOST_BITS_PER_WIDE_INT64) | ||||
3549 | { | ||||
3550 | /* Its safe to use -coeff even for INT_MIN, as the | ||||
3551 | result is interpreted as an unsigned coefficient. | ||||
3552 | Exclude cost of op0 from max_cost to match the cost | ||||
3553 | calculation of the synth_mult. */ | ||||
3554 | coeff = -(unsigned HOST_WIDE_INTlong) coeff; | ||||
3555 | max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1)gen_rtx_fmt_ee_stat ((MULT), ((mode)), ((fake_reg)), ((op1)) ), | ||||
3556 | mode, speed) | ||||
3557 | - neg_cost (speed, mode)); | ||||
3558 | if (max_cost <= 0) | ||||
3559 | goto skip_synth; | ||||
3560 | |||||
3561 | /* Special case powers of two. */ | ||||
3562 | if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)(((coeff) & ((coeff) - 1UL)) == 0)) | ||||
3563 | { | ||||
3564 | rtx temp = expand_shift (LSHIFT_EXPR, mode, op0, | ||||
3565 | floor_log2 (coeff), target, unsignedp); | ||||
3566 | return expand_unop (mode, neg_optab, temp, target, 0); | ||||
3567 | } | ||||
3568 | |||||
3569 | if (choose_mult_variant (mode, coeff, &algorithm, &variant, | ||||
3570 | max_cost)) | ||||
3571 | { | ||||
3572 | rtx temp = expand_mult_const (mode, op0, coeff, NULL_RTX(rtx) 0, | ||||
3573 | &algorithm, variant); | ||||
3574 | return expand_unop (mode, neg_optab, temp, target, 0); | ||||
3575 | } | ||||
3576 | goto skip_synth; | ||||
3577 | } | ||||
3578 | |||||
3579 | /* Exclude cost of op0 from max_cost to match the cost | ||||
3580 | calculation of the synth_mult. */ | ||||
3581 | max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, op1)gen_rtx_fmt_ee_stat ((MULT), ((mode)), ((fake_reg)), ((op1)) ), mode, speed); | ||||
3582 | if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost)) | ||||
3583 | return expand_mult_const (mode, op0, coeff, target, | ||||
3584 | &algorithm, variant); | ||||
3585 | } | ||||
3586 | skip_synth: | ||||
3587 | |||||
3588 | /* Expand x*2.0 as x+x. */ | ||||
3589 | if (CONST_DOUBLE_AS_FLOAT_P (scalar_op1)(((enum rtx_code) (scalar_op1)->code) == CONST_DOUBLE && ((machine_mode) (scalar_op1)->mode) != ((void) 0, E_VOIDmode )) | ||||
3590 | && real_equal (CONST_DOUBLE_REAL_VALUE (scalar_op1)((const struct real_value *) (&(scalar_op1)->u.rv)), &dconst2)) | ||||
3591 | { | ||||
3592 | op0 = force_reg (GET_MODE (op0)((machine_mode) (op0)->mode), op0); | ||||
3593 | return expand_binop (mode, add_optab, op0, op0, | ||||
3594 | target, unsignedp, | ||||
3595 | no_libcall ? OPTAB_WIDEN : OPTAB_LIB_WIDEN); | ||||
3596 | } | ||||
3597 | |||||
3598 | /* This used to use umul_optab if unsigned, but for non-widening multiply | ||||
3599 | there is no difference between signed and unsigned. */ | ||||
3600 | op0 = expand_binop (mode, do_trapv ? smulv_optab : smul_optab, | ||||
3601 | op0, op1, target, unsignedp, | ||||
3602 | no_libcall ? OPTAB_WIDEN : OPTAB_LIB_WIDEN); | ||||
3603 | gcc_assert (op0 || no_libcall)((void)(!(op0 || no_libcall) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 3603, __FUNCTION__), 0 : 0)); | ||||
3604 | return op0; | ||||
3605 | } | ||||
3606 | |||||
3607 | /* Return a cost estimate for multiplying a register by the given | ||||
3608 | COEFFicient in the given MODE and SPEED. */ | ||||
3609 | |||||
3610 | int | ||||
3611 | mult_by_coeff_cost (HOST_WIDE_INTlong coeff, machine_mode mode, bool speed) | ||||
3612 | { | ||||
3613 | int max_cost; | ||||
3614 | struct algorithm algorithm; | ||||
3615 | enum mult_variant variant; | ||||
3616 | |||||
3617 | rtx fake_reg = gen_raw_REG (mode, LAST_VIRTUAL_REGISTER(((76)) + 5) + 1); | ||||
3618 | max_cost = set_src_cost (gen_rtx_MULT (mode, fake_reg, fake_reg)gen_rtx_fmt_ee_stat ((MULT), ((mode)), ((fake_reg)), ((fake_reg )) ), | ||||
3619 | mode, speed); | ||||
3620 | if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost)) | ||||
3621 | return algorithm.cost.cost; | ||||
3622 | else | ||||
3623 | return max_cost; | ||||
3624 | } | ||||
3625 | |||||
3626 | /* Perform a widening multiplication and return an rtx for the result. | ||||
3627 | MODE is mode of value; OP0 and OP1 are what to multiply (rtx's); | ||||
3628 | TARGET is a suggestion for where to store the result (an rtx). | ||||
3629 | THIS_OPTAB is the optab we should use, it must be either umul_widen_optab | ||||
3630 | or smul_widen_optab. | ||||
3631 | |||||
3632 | We check specially for a constant integer as OP1, comparing the | ||||
3633 | cost of a widening multiply against the cost of a sequence of shifts | ||||
3634 | and adds. */ | ||||
3635 | |||||
3636 | rtx | ||||
3637 | expand_widening_mult (machine_mode mode, rtx op0, rtx op1, rtx target, | ||||
3638 | int unsignedp, optab this_optab) | ||||
3639 | { | ||||
3640 | bool speed = optimize_insn_for_speed_p (); | ||||
3641 | rtx cop1; | ||||
3642 | |||||
3643 | if (CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT) | ||||
3644 | && GET_MODE (op0)((machine_mode) (op0)->mode) != VOIDmode((void) 0, E_VOIDmode) | ||||
3645 | && (cop1 = convert_modes (mode, GET_MODE (op0)((machine_mode) (op0)->mode), op1, | ||||
3646 | this_optab == umul_widen_optab)) | ||||
3647 | && CONST_INT_P (cop1)(((enum rtx_code) (cop1)->code) == CONST_INT) | ||||
3648 | && (INTVAL (cop1)((cop1)->u.hwint[0]) >= 0 | ||||
3649 | || HWI_COMPUTABLE_MODE_P (mode))) | ||||
3650 | { | ||||
3651 | HOST_WIDE_INTlong coeff = INTVAL (cop1)((cop1)->u.hwint[0]); | ||||
3652 | int max_cost; | ||||
3653 | enum mult_variant variant; | ||||
3654 | struct algorithm algorithm; | ||||
3655 | |||||
3656 | if (coeff == 0) | ||||
3657 | return CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)]); | ||||
3658 | |||||
3659 | /* Special case powers of two. */ | ||||
3660 | if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)(((coeff) & ((coeff) - 1UL)) == 0)) | ||||
3661 | { | ||||
3662 | op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); | ||||
3663 | return expand_shift (LSHIFT_EXPR, mode, op0, | ||||
3664 | floor_log2 (coeff), target, unsignedp); | ||||
3665 | } | ||||
3666 | |||||
3667 | /* Exclude cost of op0 from max_cost to match the cost | ||||
3668 | calculation of the synth_mult. */ | ||||
3669 | max_cost = mul_widen_cost (speed, mode); | ||||
3670 | if (choose_mult_variant (mode, coeff, &algorithm, &variant, | ||||
3671 | max_cost)) | ||||
3672 | { | ||||
3673 | op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); | ||||
3674 | return expand_mult_const (mode, op0, coeff, target, | ||||
3675 | &algorithm, variant); | ||||
3676 | } | ||||
3677 | } | ||||
3678 | return expand_binop (mode, this_optab, op0, op1, target, | ||||
3679 | unsignedp, OPTAB_LIB_WIDEN); | ||||
3680 | } | ||||
3681 | |||||
3682 | /* Choose a minimal N + 1 bit approximation to 1/D that can be used to | ||||
3683 | replace division by D, and put the least significant N bits of the result | ||||
3684 | in *MULTIPLIER_PTR and return the most significant bit. | ||||
3685 | |||||
3686 | The width of operations is N (should be <= HOST_BITS_PER_WIDE_INT), the | ||||
3687 | needed precision is in PRECISION (should be <= N). | ||||
3688 | |||||
3689 | PRECISION should be as small as possible so this function can choose | ||||
3690 | multiplier more freely. | ||||
3691 | |||||
3692 | The rounded-up logarithm of D is placed in *lgup_ptr. A shift count that | ||||
3693 | is to be used for a final right shift is placed in *POST_SHIFT_PTR. | ||||
3694 | |||||
3695 | Using this function, x/D will be equal to (x * m) >> (*POST_SHIFT_PTR), | ||||
3696 | where m is the full HOST_BITS_PER_WIDE_INT + 1 bit multiplier. */ | ||||
3697 | |||||
3698 | unsigned HOST_WIDE_INTlong | ||||
3699 | choose_multiplier (unsigned HOST_WIDE_INTlong d, int n, int precision, | ||||
3700 | unsigned HOST_WIDE_INTlong *multiplier_ptr, | ||||
3701 | int *post_shift_ptr, int *lgup_ptr) | ||||
3702 | { | ||||
3703 | int lgup, post_shift; | ||||
3704 | int pow, pow2; | ||||
3705 | |||||
3706 | /* lgup = ceil(log2(divisor)); */ | ||||
3707 | lgup = ceil_log2 (d); | ||||
3708 | |||||
3709 | gcc_assert (lgup <= n)((void)(!(lgup <= n) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 3709, __FUNCTION__), 0 : 0)); | ||||
3710 | |||||
3711 | pow = n + lgup; | ||||
3712 | pow2 = n + lgup - precision; | ||||
3713 | |||||
3714 | /* mlow = 2^(N + lgup)/d */ | ||||
3715 | wide_int val = wi::set_bit_in_zero (pow, HOST_BITS_PER_DOUBLE_INT(2 * 64)); | ||||
3716 | wide_int mlow = wi::udiv_trunc (val, d); | ||||
3717 | |||||
3718 | /* mhigh = (2^(N + lgup) + 2^(N + lgup - precision))/d */ | ||||
3719 | val |= wi::set_bit_in_zero (pow2, HOST_BITS_PER_DOUBLE_INT(2 * 64)); | ||||
3720 | wide_int mhigh = wi::udiv_trunc (val, d); | ||||
3721 | |||||
3722 | /* If precision == N, then mlow, mhigh exceed 2^N | ||||
3723 | (but they do not exceed 2^(N+1)). */ | ||||
3724 | |||||
3725 | /* Reduce to lowest terms. */ | ||||
3726 | for (post_shift = lgup; post_shift > 0; post_shift--) | ||||
3727 | { | ||||
3728 | unsigned HOST_WIDE_INTlong ml_lo = wi::extract_uhwi (mlow, 1, | ||||
3729 | HOST_BITS_PER_WIDE_INT64); | ||||
3730 | unsigned HOST_WIDE_INTlong mh_lo = wi::extract_uhwi (mhigh, 1, | ||||
3731 | HOST_BITS_PER_WIDE_INT64); | ||||
3732 | if (ml_lo >= mh_lo) | ||||
3733 | break; | ||||
3734 | |||||
3735 | mlow = wi::uhwi (ml_lo, HOST_BITS_PER_DOUBLE_INT(2 * 64)); | ||||
3736 | mhigh = wi::uhwi (mh_lo, HOST_BITS_PER_DOUBLE_INT(2 * 64)); | ||||
3737 | } | ||||
3738 | |||||
3739 | *post_shift_ptr = post_shift; | ||||
3740 | *lgup_ptr = lgup; | ||||
3741 | if (n < HOST_BITS_PER_WIDE_INT64) | ||||
3742 | { | ||||
3743 | unsigned HOST_WIDE_INTlong mask = (HOST_WIDE_INT_1U1UL << n) - 1; | ||||
3744 | *multiplier_ptr = mhigh.to_uhwi () & mask; | ||||
3745 | return mhigh.to_uhwi () > mask; | ||||
3746 | } | ||||
3747 | else | ||||
3748 | { | ||||
3749 | *multiplier_ptr = mhigh.to_uhwi (); | ||||
3750 | return wi::extract_uhwi (mhigh, HOST_BITS_PER_WIDE_INT64, 1); | ||||
3751 | } | ||||
3752 | } | ||||
3753 | |||||
3754 | /* Compute the inverse of X mod 2**n, i.e., find Y such that X * Y is | ||||
3755 | congruent to 1 (mod 2**N). */ | ||||
3756 | |||||
3757 | static unsigned HOST_WIDE_INTlong | ||||
3758 | invert_mod2n (unsigned HOST_WIDE_INTlong x, int n) | ||||
3759 | { | ||||
3760 | /* Solve x*y == 1 (mod 2^n), where x is odd. Return y. */ | ||||
3761 | |||||
3762 | /* The algorithm notes that the choice y = x satisfies | ||||
3763 | x*y == 1 mod 2^3, since x is assumed odd. | ||||
3764 | Each iteration doubles the number of bits of significance in y. */ | ||||
3765 | |||||
3766 | unsigned HOST_WIDE_INTlong mask; | ||||
3767 | unsigned HOST_WIDE_INTlong y = x; | ||||
3768 | int nbit = 3; | ||||
3769 | |||||
3770 | mask = (n == HOST_BITS_PER_WIDE_INT64 | ||||
3771 | ? HOST_WIDE_INT_M1U-1UL | ||||
3772 | : (HOST_WIDE_INT_1U1UL << n) - 1); | ||||
3773 | |||||
3774 | while (nbit < n) | ||||
3775 | { | ||||
3776 | y = y * (2 - x*y) & mask; /* Modulo 2^N */ | ||||
3777 | nbit *= 2; | ||||
3778 | } | ||||
3779 | return y; | ||||
3780 | } | ||||
3781 | |||||
3782 | /* Emit code to adjust ADJ_OPERAND after multiplication of wrong signedness | ||||
3783 | flavor of OP0 and OP1. ADJ_OPERAND is already the high half of the | ||||
3784 | product OP0 x OP1. If UNSIGNEDP is nonzero, adjust the signed product | ||||
3785 | to become unsigned, if UNSIGNEDP is zero, adjust the unsigned product to | ||||
3786 | become signed. | ||||
3787 | |||||
3788 | The result is put in TARGET if that is convenient. | ||||
3789 | |||||
3790 | MODE is the mode of operation. */ | ||||
3791 | |||||
3792 | rtx | ||||
3793 | expand_mult_highpart_adjust (scalar_int_mode mode, rtx adj_operand, rtx op0, | ||||
3794 | rtx op1, rtx target, int unsignedp) | ||||
3795 | { | ||||
3796 | rtx tem; | ||||
3797 | enum rtx_code adj_code = unsignedp ? PLUS : MINUS; | ||||
3798 | |||||
3799 | tem = expand_shift (RSHIFT_EXPR, mode, op0, | ||||
3800 | GET_MODE_BITSIZE (mode) - 1, NULL_RTX(rtx) 0, 0); | ||||
3801 | tem = expand_and (mode, tem, op1, NULL_RTX(rtx) 0); | ||||
3802 | adj_operand | ||||
3803 | = force_operand (gen_rtx_fmt_ee (adj_code, mode, adj_operand, tem)gen_rtx_fmt_ee_stat ((adj_code), (mode), (adj_operand), (tem) ), | ||||
3804 | adj_operand); | ||||
3805 | |||||
3806 | tem = expand_shift (RSHIFT_EXPR, mode, op1, | ||||
3807 | GET_MODE_BITSIZE (mode) - 1, NULL_RTX(rtx) 0, 0); | ||||
3808 | tem = expand_and (mode, tem, op0, NULL_RTX(rtx) 0); | ||||
3809 | target = force_operand (gen_rtx_fmt_ee (adj_code, mode, adj_operand, tem)gen_rtx_fmt_ee_stat ((adj_code), (mode), (adj_operand), (tem) ), | ||||
3810 | target); | ||||
3811 | |||||
3812 | return target; | ||||
3813 | } | ||||
3814 | |||||
3815 | /* Subroutine of expmed_mult_highpart. Return the MODE high part of OP. */ | ||||
3816 | |||||
3817 | static rtx | ||||
3818 | extract_high_half (scalar_int_mode mode, rtx op) | ||||
3819 | { | ||||
3820 | if (mode == word_mode) | ||||
3821 | return gen_highpart (mode, op); | ||||
3822 | |||||
3823 | scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); | ||||
3824 | |||||
3825 | op = expand_shift (RSHIFT_EXPR, wider_mode, op, | ||||
3826 | GET_MODE_BITSIZE (mode), 0, 1); | ||||
3827 | return convert_modes (mode, wider_mode, op, 0); | ||||
3828 | } | ||||
3829 | |||||
3830 | /* Like expmed_mult_highpart, but only consider using a multiplication | ||||
3831 | optab. OP1 is an rtx for the constant operand. */ | ||||
3832 | |||||
3833 | static rtx | ||||
3834 | expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1, | ||||
3835 | rtx target, int unsignedp, int max_cost) | ||||
3836 | { | ||||
3837 | rtx narrow_op1 = gen_int_mode (INTVAL (op1)((op1)->u.hwint[0]), mode); | ||||
3838 | optab moptab; | ||||
3839 | rtx tem; | ||||
3840 | int size; | ||||
3841 | bool speed = optimize_insn_for_speed_p (); | ||||
3842 | |||||
3843 | scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); | ||||
3844 | |||||
3845 | size = GET_MODE_BITSIZE (mode); | ||||
3846 | |||||
3847 | /* Firstly, try using a multiplication insn that only generates the needed | ||||
3848 | high part of the product, and in the sign flavor of unsignedp. */ | ||||
3849 | if (mul_highpart_cost (speed, mode) < max_cost) | ||||
3850 | { | ||||
3851 | moptab = unsignedp ? umul_highpart_optab : smul_highpart_optab; | ||||
3852 | tem = expand_binop (mode, moptab, op0, narrow_op1, target, | ||||
3853 | unsignedp, OPTAB_DIRECT); | ||||
3854 | if (tem) | ||||
3855 | return tem; | ||||
3856 | } | ||||
3857 | |||||
3858 | /* Secondly, same as above, but use sign flavor opposite of unsignedp. | ||||
3859 | Need to adjust the result after the multiplication. */ | ||||
3860 | if (size - 1 < BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
3861 | && (mul_highpart_cost (speed, mode) | ||||
3862 | + 2 * shift_cost (speed, mode, size-1) | ||||
3863 | + 4 * add_cost (speed, mode) < max_cost)) | ||||
3864 | { | ||||
3865 | moptab = unsignedp ? smul_highpart_optab : umul_highpart_optab; | ||||
3866 | tem = expand_binop (mode, moptab, op0, narrow_op1, target, | ||||
3867 | unsignedp, OPTAB_DIRECT); | ||||
3868 | if (tem) | ||||
3869 | /* We used the wrong signedness. Adjust the result. */ | ||||
3870 | return expand_mult_highpart_adjust (mode, tem, op0, narrow_op1, | ||||
3871 | tem, unsignedp); | ||||
3872 | } | ||||
3873 | |||||
3874 | /* Try widening multiplication. */ | ||||
3875 | moptab = unsignedp ? umul_widen_optab : smul_widen_optab; | ||||
3876 | if (convert_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing | ||||
3877 | && mul_widen_cost (speed, wider_mode) < max_cost) | ||||
3878 | { | ||||
3879 | tem = expand_binop (wider_mode, moptab, op0, narrow_op1, 0, | ||||
3880 | unsignedp, OPTAB_WIDEN); | ||||
3881 | if (tem) | ||||
3882 | return extract_high_half (mode, tem); | ||||
3883 | } | ||||
3884 | |||||
3885 | /* Try widening the mode and perform a non-widening multiplication. */ | ||||
3886 | if (optab_handler (smul_optab, wider_mode) != CODE_FOR_nothing | ||||
3887 | && size - 1 < BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
3888 | && (mul_cost (speed, wider_mode) + shift_cost (speed, mode, size-1) | ||||
3889 | < max_cost)) | ||||
3890 | { | ||||
3891 | rtx_insn *insns; | ||||
3892 | rtx wop0, wop1; | ||||
3893 | |||||
3894 | /* We need to widen the operands, for example to ensure the | ||||
3895 | constant multiplier is correctly sign or zero extended. | ||||
3896 | Use a sequence to clean-up any instructions emitted by | ||||
3897 | the conversions if things don't work out. */ | ||||
3898 | start_sequence (); | ||||
3899 | wop0 = convert_modes (wider_mode, mode, op0, unsignedp); | ||||
3900 | wop1 = convert_modes (wider_mode, mode, op1, unsignedp); | ||||
3901 | tem = expand_binop (wider_mode, smul_optab, wop0, wop1, 0, | ||||
3902 | unsignedp, OPTAB_WIDEN); | ||||
3903 | insns = get_insns (); | ||||
3904 | end_sequence (); | ||||
3905 | |||||
3906 | if (tem) | ||||
3907 | { | ||||
3908 | emit_insn (insns); | ||||
3909 | return extract_high_half (mode, tem); | ||||
3910 | } | ||||
3911 | } | ||||
3912 | |||||
3913 | /* Try widening multiplication of opposite signedness, and adjust. */ | ||||
3914 | moptab = unsignedp ? smul_widen_optab : umul_widen_optab; | ||||
3915 | if (convert_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing | ||||
3916 | && size - 1 < BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
3917 | && (mul_widen_cost (speed, wider_mode) | ||||
3918 | + 2 * shift_cost (speed, mode, size-1) | ||||
3919 | + 4 * add_cost (speed, mode) < max_cost)) | ||||
3920 | { | ||||
3921 | tem = expand_binop (wider_mode, moptab, op0, narrow_op1, | ||||
3922 | NULL_RTX(rtx) 0, ! unsignedp, OPTAB_WIDEN); | ||||
3923 | if (tem != 0) | ||||
3924 | { | ||||
3925 | tem = extract_high_half (mode, tem); | ||||
3926 | /* We used the wrong signedness. Adjust the result. */ | ||||
3927 | return expand_mult_highpart_adjust (mode, tem, op0, narrow_op1, | ||||
3928 | target, unsignedp); | ||||
3929 | } | ||||
3930 | } | ||||
3931 | |||||
3932 | return 0; | ||||
3933 | } | ||||
3934 | |||||
3935 | /* Emit code to multiply OP0 and OP1 (where OP1 is an integer constant), | ||||
3936 | putting the high half of the result in TARGET if that is convenient, | ||||
3937 | and return where the result is. If the operation cannot be performed, | ||||
3938 | 0 is returned. | ||||
3939 | |||||
3940 | MODE is the mode of operation and result. | ||||
3941 | |||||
3942 | UNSIGNEDP nonzero means unsigned multiply. | ||||
3943 | |||||
3944 | MAX_COST is the total allowed cost for the expanded RTL. */ | ||||
3945 | |||||
3946 | static rtx | ||||
3947 | expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1, | ||||
3948 | rtx target, int unsignedp, int max_cost) | ||||
3949 | { | ||||
3950 | unsigned HOST_WIDE_INTlong cnst1; | ||||
3951 | int extra_cost; | ||||
3952 | bool sign_adjust = false; | ||||
3953 | enum mult_variant variant; | ||||
3954 | struct algorithm alg; | ||||
3955 | rtx tem; | ||||
3956 | bool speed = optimize_insn_for_speed_p (); | ||||
3957 | |||||
3958 | /* We can't support modes wider than HOST_BITS_PER_INT. */ | ||||
3959 | gcc_assert (HWI_COMPUTABLE_MODE_P (mode))((void)(!(HWI_COMPUTABLE_MODE_P (mode)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 3959, __FUNCTION__), 0 : 0)); | ||||
3960 | |||||
3961 | cnst1 = INTVAL (op1)((op1)->u.hwint[0]) & GET_MODE_MASK (mode)mode_mask_array[mode]; | ||||
3962 | |||||
3963 | /* We can't optimize modes wider than BITS_PER_WORD. | ||||
3964 | ??? We might be able to perform double-word arithmetic if | ||||
3965 | mode == word_mode, however all the cost calculations in | ||||
3966 | synth_mult etc. assume single-word operations. */ | ||||
3967 | scalar_int_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); | ||||
3968 | if (GET_MODE_BITSIZE (wider_mode) > BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
3969 | return expmed_mult_highpart_optab (mode, op0, op1, target, | ||||
3970 | unsignedp, max_cost); | ||||
3971 | |||||
3972 | extra_cost = shift_cost (speed, mode, GET_MODE_BITSIZE (mode) - 1); | ||||
3973 | |||||
3974 | /* Check whether we try to multiply by a negative constant. */ | ||||
3975 | if (!unsignedp && ((cnst1 >> (GET_MODE_BITSIZE (mode) - 1)) & 1)) | ||||
3976 | { | ||||
3977 | sign_adjust = true; | ||||
3978 | extra_cost += add_cost (speed, mode); | ||||
3979 | } | ||||
3980 | |||||
3981 | /* See whether shift/add multiplication is cheap enough. */ | ||||
3982 | if (choose_mult_variant (wider_mode, cnst1, &alg, &variant, | ||||
3983 | max_cost - extra_cost)) | ||||
3984 | { | ||||
3985 | /* See whether the specialized multiplication optabs are | ||||
3986 | cheaper than the shift/add version. */ | ||||
3987 | tem = expmed_mult_highpart_optab (mode, op0, op1, target, unsignedp, | ||||
3988 | alg.cost.cost + extra_cost); | ||||
3989 | if (tem) | ||||
3990 | return tem; | ||||
3991 | |||||
3992 | tem = convert_to_mode (wider_mode, op0, unsignedp); | ||||
3993 | tem = expand_mult_const (wider_mode, tem, cnst1, 0, &alg, variant); | ||||
3994 | tem = extract_high_half (mode, tem); | ||||
3995 | |||||
3996 | /* Adjust result for signedness. */ | ||||
3997 | if (sign_adjust) | ||||
3998 | tem = force_operand (gen_rtx_MINUS (mode, tem, op0)gen_rtx_fmt_ee_stat ((MINUS), ((mode)), ((tem)), ((op0)) ), tem); | ||||
3999 | |||||
4000 | return tem; | ||||
4001 | } | ||||
4002 | return expmed_mult_highpart_optab (mode, op0, op1, target, | ||||
4003 | unsignedp, max_cost); | ||||
4004 | } | ||||
4005 | |||||
4006 | |||||
4007 | /* Expand signed modulus of OP0 by a power of two D in mode MODE. */ | ||||
4008 | |||||
4009 | static rtx | ||||
4010 | expand_smod_pow2 (scalar_int_mode mode, rtx op0, HOST_WIDE_INTlong d) | ||||
4011 | { | ||||
4012 | rtx result, temp, shift; | ||||
4013 | rtx_code_label *label; | ||||
4014 | int logd; | ||||
4015 | int prec = GET_MODE_PRECISION (mode); | ||||
4016 | |||||
4017 | logd = floor_log2 (d); | ||||
4018 | result = gen_reg_rtx (mode); | ||||
4019 | |||||
4020 | /* Avoid conditional branches when they're expensive. */ | ||||
4021 | if (BRANCH_COST (optimize_insn_for_speed_p (), false)(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) >= 2 | ||||
4022 | && optimize_insn_for_speed_p ()) | ||||
4023 | { | ||||
4024 | rtx signmask = emit_store_flag (result, LT, op0, const0_rtx(const_int_rtx[64]), | ||||
4025 | mode, 0, -1); | ||||
4026 | if (signmask) | ||||
4027 | { | ||||
4028 | HOST_WIDE_INTlong masklow = (HOST_WIDE_INT_11L << logd) - 1; | ||||
4029 | signmask = force_reg (mode, signmask); | ||||
4030 | shift = gen_int_shift_amount (mode, GET_MODE_BITSIZE (mode) - logd); | ||||
4031 | |||||
4032 | /* Use the rtx_cost of a LSHIFTRT instruction to determine | ||||
4033 | which instruction sequence to use. If logical right shifts | ||||
4034 | are expensive the use 2 XORs, 2 SUBs and an AND, otherwise | ||||
4035 | use a LSHIFTRT, 1 ADD, 1 SUB and an AND. */ | ||||
4036 | |||||
4037 | temp = gen_rtx_LSHIFTRT (mode, result, shift)gen_rtx_fmt_ee_stat ((LSHIFTRT), ((mode)), ((result)), ((shift )) ); | ||||
4038 | if (optab_handler (lshr_optab, mode) == CODE_FOR_nothing | ||||
4039 | || (set_src_cost (temp, mode, optimize_insn_for_speed_p ()) | ||||
4040 | > COSTS_N_INSNS (2)((2) * 4))) | ||||
4041 | { | ||||
4042 | temp = expand_binop (mode, xor_optab, op0, signmask, | ||||
4043 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4044 | temp = expand_binop (mode, sub_optab, temp, signmask, | ||||
4045 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4046 | temp = expand_binop (mode, and_optab, temp, | ||||
4047 | gen_int_mode (masklow, mode), | ||||
4048 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4049 | temp = expand_binop (mode, xor_optab, temp, signmask, | ||||
4050 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4051 | temp = expand_binop (mode, sub_optab, temp, signmask, | ||||
4052 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4053 | } | ||||
4054 | else | ||||
4055 | { | ||||
4056 | signmask = expand_binop (mode, lshr_optab, signmask, shift, | ||||
4057 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4058 | signmask = force_reg (mode, signmask); | ||||
4059 | |||||
4060 | temp = expand_binop (mode, add_optab, op0, signmask, | ||||
4061 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4062 | temp = expand_binop (mode, and_optab, temp, | ||||
4063 | gen_int_mode (masklow, mode), | ||||
4064 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4065 | temp = expand_binop (mode, sub_optab, temp, signmask, | ||||
4066 | NULL_RTX(rtx) 0, 1, OPTAB_LIB_WIDEN); | ||||
4067 | } | ||||
4068 | return temp; | ||||
4069 | } | ||||
4070 | } | ||||
4071 | |||||
4072 | /* Mask contains the mode's signbit and the significant bits of the | ||||
4073 | modulus. By including the signbit in the operation, many targets | ||||
4074 | can avoid an explicit compare operation in the following comparison | ||||
4075 | against zero. */ | ||||
4076 | wide_int mask = wi::mask (logd, false, prec); | ||||
4077 | mask = wi::set_bit (mask, prec - 1); | ||||
4078 | |||||
4079 | temp = expand_binop (mode, and_optab, op0, | ||||
4080 | immed_wide_int_const (mask, mode), | ||||
4081 | result, 1, OPTAB_LIB_WIDEN); | ||||
4082 | if (temp != result) | ||||
4083 | emit_move_insn (result, temp); | ||||
4084 | |||||
4085 | label = gen_label_rtx (); | ||||
4086 | do_cmp_and_jump (result, const0_rtx(const_int_rtx[64]), GE, mode, label); | ||||
4087 | |||||
4088 | temp = expand_binop (mode, sub_optab, result, const1_rtx(const_int_rtx[64 +1]), result, | ||||
4089 | 0, OPTAB_LIB_WIDEN); | ||||
4090 | |||||
4091 | mask = wi::mask (logd, true, prec); | ||||
4092 | temp = expand_binop (mode, ior_optab, temp, | ||||
4093 | immed_wide_int_const (mask, mode), | ||||
4094 | result, 1, OPTAB_LIB_WIDEN); | ||||
4095 | temp = expand_binop (mode, add_optab, temp, const1_rtx(const_int_rtx[64 +1]), result, | ||||
4096 | 0, OPTAB_LIB_WIDEN); | ||||
4097 | if (temp != result) | ||||
4098 | emit_move_insn (result, temp); | ||||
4099 | emit_label (label); | ||||
4100 | return result; | ||||
4101 | } | ||||
4102 | |||||
4103 | /* Expand signed division of OP0 by a power of two D in mode MODE. | ||||
4104 | This routine is only called for positive values of D. */ | ||||
4105 | |||||
4106 | static rtx | ||||
4107 | expand_sdiv_pow2 (scalar_int_mode mode, rtx op0, HOST_WIDE_INTlong d) | ||||
4108 | { | ||||
4109 | rtx temp; | ||||
4110 | rtx_code_label *label; | ||||
4111 | int logd; | ||||
4112 | |||||
4113 | logd = floor_log2 (d); | ||||
4114 | |||||
4115 | if (d == 2 | ||||
4116 | && BRANCH_COST (optimize_insn_for_speed_p (),(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) | ||||
4117 | false)(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) >= 1) | ||||
4118 | { | ||||
4119 | temp = gen_reg_rtx (mode); | ||||
4120 | temp = emit_store_flag (temp, LT, op0, const0_rtx(const_int_rtx[64]), mode, 0, 1); | ||||
4121 | if (temp != NULL_RTX(rtx) 0) | ||||
4122 | { | ||||
4123 | temp = expand_binop (mode, add_optab, temp, op0, NULL_RTX(rtx) 0, | ||||
4124 | 0, OPTAB_LIB_WIDEN); | ||||
4125 | return expand_shift (RSHIFT_EXPR, mode, temp, logd, NULL_RTX(rtx) 0, 0); | ||||
4126 | } | ||||
4127 | } | ||||
4128 | |||||
4129 | if (HAVE_conditional_move1 | ||||
4130 | && BRANCH_COST (optimize_insn_for_speed_p (), false)(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) >= 2) | ||||
4131 | { | ||||
4132 | rtx temp2; | ||||
4133 | |||||
4134 | start_sequence (); | ||||
4135 | temp2 = copy_to_mode_reg (mode, op0); | ||||
4136 | temp = expand_binop (mode, add_optab, temp2, gen_int_mode (d - 1, mode), | ||||
4137 | NULL_RTX(rtx) 0, 0, OPTAB_LIB_WIDEN); | ||||
4138 | temp = force_reg (mode, temp); | ||||
4139 | |||||
4140 | /* Construct "temp2 = (temp2 < 0) ? temp : temp2". */ | ||||
4141 | temp2 = emit_conditional_move (temp2, { LT, temp2, const0_rtx(const_int_rtx[64]), mode }, | ||||
4142 | temp, temp2, mode, 0); | ||||
4143 | if (temp2) | ||||
4144 | { | ||||
4145 | rtx_insn *seq = get_insns (); | ||||
4146 | end_sequence (); | ||||
4147 | emit_insn (seq); | ||||
4148 | return expand_shift (RSHIFT_EXPR, mode, temp2, logd, NULL_RTX(rtx) 0, 0); | ||||
4149 | } | ||||
4150 | end_sequence (); | ||||
4151 | } | ||||
4152 | |||||
4153 | if (BRANCH_COST (optimize_insn_for_speed_p (),(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) | ||||
4154 | false)(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) >= 2) | ||||
4155 | { | ||||
4156 | int ushift = GET_MODE_BITSIZE (mode) - logd; | ||||
4157 | |||||
4158 | temp = gen_reg_rtx (mode); | ||||
4159 | temp = emit_store_flag (temp, LT, op0, const0_rtx(const_int_rtx[64]), mode, 0, -1); | ||||
4160 | if (temp != NULL_RTX(rtx) 0) | ||||
4161 | { | ||||
4162 | if (GET_MODE_BITSIZE (mode) >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
4163 | || shift_cost (optimize_insn_for_speed_p (), mode, ushift) | ||||
4164 | > COSTS_N_INSNS (1)((1) * 4)) | ||||
4165 | temp = expand_binop (mode, and_optab, temp, | ||||
4166 | gen_int_mode (d - 1, mode), | ||||
4167 | NULL_RTX(rtx) 0, 0, OPTAB_LIB_WIDEN); | ||||
4168 | else | ||||
4169 | temp = expand_shift (RSHIFT_EXPR, mode, temp, | ||||
4170 | ushift, NULL_RTX(rtx) 0, 1); | ||||
4171 | temp = expand_binop (mode, add_optab, temp, op0, NULL_RTX(rtx) 0, | ||||
4172 | 0, OPTAB_LIB_WIDEN); | ||||
4173 | return expand_shift (RSHIFT_EXPR, mode, temp, logd, NULL_RTX(rtx) 0, 0); | ||||
4174 | } | ||||
4175 | } | ||||
4176 | |||||
4177 | label = gen_label_rtx (); | ||||
4178 | temp = copy_to_mode_reg (mode, op0); | ||||
4179 | do_cmp_and_jump (temp, const0_rtx(const_int_rtx[64]), GE, mode, label); | ||||
4180 | expand_inc (temp, gen_int_mode (d - 1, mode)); | ||||
4181 | emit_label (label); | ||||
4182 | return expand_shift (RSHIFT_EXPR, mode, temp, logd, NULL_RTX(rtx) 0, 0); | ||||
4183 | } | ||||
4184 | |||||
4185 | /* Emit the code to divide OP0 by OP1, putting the result in TARGET | ||||
4186 | if that is convenient, and returning where the result is. | ||||
4187 | You may request either the quotient or the remainder as the result; | ||||
4188 | specify REM_FLAG nonzero to get the remainder. | ||||
4189 | |||||
4190 | CODE is the expression code for which kind of division this is; | ||||
4191 | it controls how rounding is done. MODE is the machine mode to use. | ||||
4192 | UNSIGNEDP nonzero means do unsigned division. */ | ||||
4193 | |||||
4194 | /* ??? For CEIL_MOD_EXPR, can compute incorrect remainder with ANDI | ||||
4195 | and then correct it by or'ing in missing high bits | ||||
4196 | if result of ANDI is nonzero. | ||||
4197 | For ROUND_MOD_EXPR, can use ANDI and then sign-extend the result. | ||||
4198 | This could optimize to a bfexts instruction. | ||||
4199 | But C doesn't use these operations, so their optimizations are | ||||
4200 | left for later. */ | ||||
4201 | /* ??? For modulo, we don't actually need the highpart of the first product, | ||||
4202 | the low part will do nicely. And for small divisors, the second multiply | ||||
4203 | can also be a low-part only multiply or even be completely left out. | ||||
4204 | E.g. to calculate the remainder of a division by 3 with a 32 bit | ||||
4205 | multiply, multiply with 0x55555556 and extract the upper two bits; | ||||
4206 | the result is exact for inputs up to 0x1fffffff. | ||||
4207 | The input range can be reduced by using cross-sum rules. | ||||
4208 | For odd divisors >= 3, the following table gives right shift counts | ||||
4209 | so that if a number is shifted by an integer multiple of the given | ||||
4210 | amount, the remainder stays the same: | ||||
4211 | 2, 4, 3, 6, 10, 12, 4, 8, 18, 6, 11, 20, 18, 0, 5, 10, 12, 0, 12, 20, | ||||
4212 | 14, 12, 23, 21, 8, 0, 20, 18, 0, 0, 6, 12, 0, 22, 0, 18, 20, 30, 0, 0, | ||||
4213 | 0, 8, 0, 11, 12, 10, 36, 0, 30, 0, 0, 12, 0, 0, 0, 0, 44, 12, 24, 0, | ||||
4214 | 20, 0, 7, 14, 0, 18, 36, 0, 0, 46, 60, 0, 42, 0, 15, 24, 20, 0, 0, 33, | ||||
4215 | 0, 20, 0, 0, 18, 0, 60, 0, 0, 0, 0, 0, 40, 18, 0, 0, 12 | ||||
4216 | |||||
4217 | Cross-sum rules for even numbers can be derived by leaving as many bits | ||||
4218 | to the right alone as the divisor has zeros to the right. | ||||
4219 | E.g. if x is an unsigned 32 bit number: | ||||
4220 | (x mod 12) == (((x & 1023) + ((x >> 8) & ~3)) * 0x15555558 >> 2 * 3) >> 28 | ||||
4221 | */ | ||||
4222 | |||||
4223 | rtx | ||||
4224 | expand_divmod (int rem_flag, enum tree_code code, machine_mode mode, | ||||
4225 | rtx op0, rtx op1, rtx target, int unsignedp, | ||||
4226 | enum optab_methods methods) | ||||
4227 | { | ||||
4228 | machine_mode compute_mode; | ||||
4229 | rtx tquotient; | ||||
4230 | rtx quotient = 0, remainder = 0; | ||||
4231 | rtx_insn *last; | ||||
4232 | rtx_insn *insn; | ||||
4233 | optab optab1, optab2; | ||||
4234 | int op1_is_constant, op1_is_pow2 = 0; | ||||
4235 | int max_cost, extra_cost; | ||||
4236 | static HOST_WIDE_INTlong last_div_const = 0; | ||||
4237 | bool speed = optimize_insn_for_speed_p (); | ||||
4238 | |||||
4239 | op1_is_constant = CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT); | ||||
4240 | if (op1_is_constant) | ||||
4241 | { | ||||
4242 | wide_int ext_op1 = rtx_mode_t (op1, mode); | ||||
4243 | op1_is_pow2 = (wi::popcount (ext_op1) == 1 | ||||
4244 | || (! unsignedp | ||||
4245 | && wi::popcount (wi::neg (ext_op1)) == 1)); | ||||
4246 | } | ||||
4247 | |||||
4248 | /* | ||||
4249 | This is the structure of expand_divmod: | ||||
4250 | |||||
4251 | First comes code to fix up the operands so we can perform the operations | ||||
4252 | correctly and efficiently. | ||||
4253 | |||||
4254 | Second comes a switch statement with code specific for each rounding mode. | ||||
4255 | For some special operands this code emits all RTL for the desired | ||||
4256 | operation, for other cases, it generates only a quotient and stores it in | ||||
4257 | QUOTIENT. The case for trunc division/remainder might leave quotient = 0, | ||||
4258 | to indicate that it has not done anything. | ||||
4259 | |||||
4260 | Last comes code that finishes the operation. If QUOTIENT is set and | ||||
4261 | REM_FLAG is set, the remainder is computed as OP0 - QUOTIENT * OP1. If | ||||
4262 | QUOTIENT is not set, it is computed using trunc rounding. | ||||
4263 | |||||
4264 | We try to generate special code for division and remainder when OP1 is a | ||||
4265 | constant. If |OP1| = 2**n we can use shifts and some other fast | ||||
4266 | operations. For other values of OP1, we compute a carefully selected | ||||
4267 | fixed-point approximation m = 1/OP1, and generate code that multiplies OP0 | ||||
4268 | by m. | ||||
4269 | |||||
4270 | In all cases but EXACT_DIV_EXPR, this multiplication requires the upper | ||||
4271 | half of the product. Different strategies for generating the product are | ||||
4272 | implemented in expmed_mult_highpart. | ||||
4273 | |||||
4274 | If what we actually want is the remainder, we generate that by another | ||||
4275 | by-constant multiplication and a subtraction. */ | ||||
4276 | |||||
4277 | /* We shouldn't be called with OP1 == const1_rtx, but some of the | ||||
4278 | code below will malfunction if we are, so check here and handle | ||||
4279 | the special case if so. */ | ||||
4280 | if (op1 == const1_rtx(const_int_rtx[64 +1])) | ||||
4281 | return rem_flag ? const0_rtx(const_int_rtx[64]) : op0; | ||||
4282 | |||||
4283 | /* When dividing by -1, we could get an overflow. | ||||
4284 | negv_optab can handle overflows. */ | ||||
4285 | if (! unsignedp && op1 == constm1_rtx(const_int_rtx[64 -1])) | ||||
4286 | { | ||||
4287 | if (rem_flag) | ||||
4288 | return const0_rtx(const_int_rtx[64]); | ||||
4289 | return expand_unop (mode, flag_trapvglobal_options.x_flag_trapv && GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_INT | ||||
4290 | ? negv_optab : neg_optab, op0, target, 0); | ||||
4291 | } | ||||
4292 | |||||
4293 | if (target | ||||
4294 | /* Don't use the function value register as a target | ||||
4295 | since we have to read it as well as write it, | ||||
4296 | and function-inlining gets confused by this. */ | ||||
4297 | && ((REG_P (target)(((enum rtx_code) (target)->code) == REG) && REG_FUNCTION_VALUE_P (target)(__extension__ ({ __typeof ((target)) const _rtx = ((target)) ; if (((enum rtx_code) (_rtx)->code) != REG && ((enum rtx_code) (_rtx)->code) != PARALLEL) rtl_check_failed_flag ("REG_FUNCTION_VALUE_P",_rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 4297, __FUNCTION__); _rtx; })->return_val)) | ||||
4298 | /* Don't clobber an operand while doing a multi-step calculation. */ | ||||
4299 | || ((rem_flag || op1_is_constant) | ||||
4300 | && (reg_mentioned_p (target, op0) | ||||
4301 | || (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && MEM_P (target)(((enum rtx_code) (target)->code) == MEM)))) | ||||
4302 | || reg_mentioned_p (target, op1) | ||||
4303 | || (MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM) && MEM_P (target)(((enum rtx_code) (target)->code) == MEM)))) | ||||
4304 | target = 0; | ||||
4305 | |||||
4306 | /* Get the mode in which to perform this computation. Normally it will | ||||
4307 | be MODE, but sometimes we can't do the desired operation in MODE. | ||||
4308 | If so, pick a wider mode in which we can do the operation. Convert | ||||
4309 | to that mode at the start to avoid repeated conversions. | ||||
4310 | |||||
4311 | First see what operations we need. These depend on the expression | ||||
4312 | we are evaluating. (We assume that divxx3 insns exist under the | ||||
4313 | same conditions that modxx3 insns and that these insns don't normally | ||||
4314 | fail. If these assumptions are not correct, we may generate less | ||||
4315 | efficient code in some cases.) | ||||
4316 | |||||
4317 | Then see if we find a mode in which we can open-code that operation | ||||
4318 | (either a division, modulus, or shift). Finally, check for the smallest | ||||
4319 | mode for which we can do the operation with a library call. */ | ||||
4320 | |||||
4321 | /* We might want to refine this now that we have division-by-constant | ||||
4322 | optimization. Since expmed_mult_highpart tries so many variants, it is | ||||
4323 | not straightforward to generalize this. Maybe we should make an array | ||||
4324 | of possible modes in init_expmed? Save this for GCC 2.7. */ | ||||
4325 | |||||
4326 | optab1 = (op1_is_pow2 | ||||
4327 | ? (unsignedp ? lshr_optab : ashr_optab) | ||||
4328 | : (unsignedp ? udiv_optab : sdiv_optab)); | ||||
4329 | optab2 = (op1_is_pow2 ? optab1 | ||||
4330 | : (unsignedp ? udivmod_optab : sdivmod_optab)); | ||||
4331 | |||||
4332 | if (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN) | ||||
4333 | { | ||||
4334 | FOR_EACH_MODE_FROM (compute_mode, mode)for ((compute_mode) = (mode); mode_iterator::iterate_p (& (compute_mode)); mode_iterator::get_next (&(compute_mode) )) | ||||
4335 | if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing | ||||
4336 | || optab_handler (optab2, compute_mode) != CODE_FOR_nothing) | ||||
4337 | break; | ||||
4338 | |||||
4339 | if (compute_mode == VOIDmode((void) 0, E_VOIDmode) && methods == OPTAB_LIB_WIDEN) | ||||
4340 | FOR_EACH_MODE_FROM (compute_mode, mode)for ((compute_mode) = (mode); mode_iterator::iterate_p (& (compute_mode)); mode_iterator::get_next (&(compute_mode) )) | ||||
4341 | if (optab_libfunc (optab1, compute_mode) | ||||
4342 | || optab_libfunc (optab2, compute_mode)) | ||||
4343 | break; | ||||
4344 | } | ||||
4345 | else | ||||
4346 | compute_mode = mode; | ||||
4347 | |||||
4348 | /* If we still couldn't find a mode, use MODE, but expand_binop will | ||||
4349 | probably die. */ | ||||
4350 | if (compute_mode == VOIDmode((void) 0, E_VOIDmode)) | ||||
4351 | compute_mode = mode; | ||||
4352 | |||||
4353 | if (target && GET_MODE (target)((machine_mode) (target)->mode) == compute_mode) | ||||
4354 | tquotient = target; | ||||
4355 | else | ||||
4356 | tquotient = gen_reg_rtx (compute_mode); | ||||
4357 | |||||
4358 | #if 0 | ||||
4359 | /* It should be possible to restrict the precision to GET_MODE_BITSIZE | ||||
4360 | (mode), and thereby get better code when OP1 is a constant. Do that | ||||
4361 | later. It will require going over all usages of SIZE below. */ | ||||
4362 | size = GET_MODE_BITSIZE (mode); | ||||
4363 | #endif | ||||
4364 | |||||
4365 | /* Only deduct something for a REM if the last divide done was | ||||
4366 | for a different constant. Then set the constant of the last | ||||
4367 | divide. */ | ||||
4368 | max_cost = (unsignedp | ||||
4369 | ? udiv_cost (speed, compute_mode) | ||||
4370 | : sdiv_cost (speed, compute_mode)); | ||||
4371 | if (rem_flag && ! (last_div_const != 0 && op1_is_constant | ||||
4372 | && INTVAL (op1)((op1)->u.hwint[0]) == last_div_const)) | ||||
4373 | max_cost -= (mul_cost (speed, compute_mode) | ||||
4374 | + add_cost (speed, compute_mode)); | ||||
4375 | |||||
4376 | last_div_const = ! rem_flag && op1_is_constant ? INTVAL (op1)((op1)->u.hwint[0]) : 0; | ||||
4377 | |||||
4378 | /* Now convert to the best mode to use. */ | ||||
4379 | if (compute_mode != mode) | ||||
4380 | { | ||||
4381 | op0 = convert_modes (compute_mode, mode, op0, unsignedp); | ||||
4382 | op1 = convert_modes (compute_mode, mode, op1, unsignedp); | ||||
4383 | |||||
4384 | /* convert_modes may have placed op1 into a register, so we | ||||
4385 | must recompute the following. */ | ||||
4386 | op1_is_constant = CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT); | ||||
4387 | if (op1_is_constant) | ||||
4388 | { | ||||
4389 | wide_int ext_op1 = rtx_mode_t (op1, compute_mode); | ||||
4390 | op1_is_pow2 = (wi::popcount (ext_op1) == 1 | ||||
4391 | || (! unsignedp | ||||
4392 | && wi::popcount (wi::neg (ext_op1)) == 1)); | ||||
4393 | } | ||||
4394 | else | ||||
4395 | op1_is_pow2 = 0; | ||||
4396 | } | ||||
4397 | |||||
4398 | /* If one of the operands is a volatile MEM, copy it into a register. */ | ||||
4399 | |||||
4400 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && MEM_VOLATILE_P (op0)(__extension__ ({ __typeof ((op0)) const _rtx = ((op0)); if ( ((enum rtx_code) (_rtx)->code) != MEM && ((enum rtx_code ) (_rtx)->code) != ASM_OPERANDS && ((enum rtx_code ) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 4400, __FUNCTION__); _rtx; })->volatil)) | ||||
4401 | op0 = force_reg (compute_mode, op0); | ||||
4402 | if (MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM) && MEM_VOLATILE_P (op1)(__extension__ ({ __typeof ((op1)) const _rtx = ((op1)); if ( ((enum rtx_code) (_rtx)->code) != MEM && ((enum rtx_code ) (_rtx)->code) != ASM_OPERANDS && ((enum rtx_code ) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 4402, __FUNCTION__); _rtx; })->volatil)) | ||||
4403 | op1 = force_reg (compute_mode, op1); | ||||
4404 | |||||
4405 | /* If we need the remainder or if OP1 is constant, we need to | ||||
4406 | put OP0 in a register in case it has any queued subexpressions. */ | ||||
4407 | if (rem_flag || op1_is_constant) | ||||
4408 | op0 = force_reg (compute_mode, op0); | ||||
4409 | |||||
4410 | last = get_last_insn (); | ||||
4411 | |||||
4412 | /* Promote floor rounding to trunc rounding for unsigned operations. */ | ||||
4413 | if (unsignedp) | ||||
4414 | { | ||||
4415 | if (code == FLOOR_DIV_EXPR) | ||||
4416 | code = TRUNC_DIV_EXPR; | ||||
4417 | if (code == FLOOR_MOD_EXPR) | ||||
4418 | code = TRUNC_MOD_EXPR; | ||||
4419 | if (code == EXACT_DIV_EXPR && op1_is_pow2) | ||||
4420 | code = TRUNC_DIV_EXPR; | ||||
4421 | } | ||||
4422 | |||||
4423 | if (op1 != const0_rtx(const_int_rtx[64])) | ||||
4424 | switch (code) | ||||
4425 | { | ||||
4426 | case TRUNC_MOD_EXPR: | ||||
4427 | case TRUNC_DIV_EXPR: | ||||
4428 | if (op1_is_constant) | ||||
4429 | { | ||||
4430 | scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode); | ||||
4431 | int size = GET_MODE_BITSIZE (int_mode); | ||||
4432 | if (unsignedp) | ||||
4433 | { | ||||
4434 | unsigned HOST_WIDE_INTlong mh, ml; | ||||
4435 | int pre_shift, post_shift; | ||||
4436 | int dummy; | ||||
4437 | wide_int wd = rtx_mode_t (op1, int_mode); | ||||
4438 | unsigned HOST_WIDE_INTlong d = wd.to_uhwi (); | ||||
4439 | |||||
4440 | if (wi::popcount (wd) == 1) | ||||
4441 | { | ||||
4442 | pre_shift = floor_log2 (d); | ||||
4443 | if (rem_flag) | ||||
4444 | { | ||||
4445 | unsigned HOST_WIDE_INTlong mask | ||||
4446 | = (HOST_WIDE_INT_1U1UL << pre_shift) - 1; | ||||
4447 | remainder | ||||
4448 | = expand_binop (int_mode, and_optab, op0, | ||||
4449 | gen_int_mode (mask, int_mode), | ||||
4450 | remainder, 1, methods); | ||||
4451 | if (remainder) | ||||
4452 | return gen_lowpartrtl_hooks.gen_lowpart (mode, remainder); | ||||
4453 | } | ||||
4454 | quotient = expand_shift (RSHIFT_EXPR, int_mode, op0, | ||||
4455 | pre_shift, tquotient, 1); | ||||
4456 | } | ||||
4457 | else if (size <= HOST_BITS_PER_WIDE_INT64) | ||||
4458 | { | ||||
4459 | if (d >= (HOST_WIDE_INT_1U1UL << (size - 1))) | ||||
4460 | { | ||||
4461 | /* Most significant bit of divisor is set; emit an scc | ||||
4462 | insn. */ | ||||
4463 | quotient = emit_store_flag_force (tquotient, GEU, op0, op1, | ||||
4464 | int_mode, 1, 1); | ||||
4465 | } | ||||
4466 | else | ||||
4467 | { | ||||
4468 | /* Find a suitable multiplier and right shift count | ||||
4469 | instead of multiplying with D. */ | ||||
4470 | |||||
4471 | mh = choose_multiplier (d, size, size, | ||||
4472 | &ml, &post_shift, &dummy); | ||||
4473 | |||||
4474 | /* If the suggested multiplier is more than SIZE bits, | ||||
4475 | we can do better for even divisors, using an | ||||
4476 | initial right shift. */ | ||||
4477 | if (mh != 0 && (d & 1) == 0) | ||||
4478 | { | ||||
4479 | pre_shift = ctz_or_zero (d); | ||||
4480 | mh = choose_multiplier (d >> pre_shift, size, | ||||
4481 | size - pre_shift, | ||||
4482 | &ml, &post_shift, &dummy); | ||||
4483 | gcc_assert (!mh)((void)(!(!mh) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 4483, __FUNCTION__), 0 : 0)); | ||||
4484 | } | ||||
4485 | else | ||||
4486 | pre_shift = 0; | ||||
4487 | |||||
4488 | if (mh != 0) | ||||
4489 | { | ||||
4490 | rtx t1, t2, t3, t4; | ||||
4491 | |||||
4492 | if (post_shift - 1 >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
4493 | goto fail1; | ||||
4494 | |||||
4495 | extra_cost | ||||
4496 | = (shift_cost (speed, int_mode, post_shift - 1) | ||||
4497 | + shift_cost (speed, int_mode, 1) | ||||
4498 | + 2 * add_cost (speed, int_mode)); | ||||
4499 | t1 = expmed_mult_highpart | ||||
4500 | (int_mode, op0, gen_int_mode (ml, int_mode), | ||||
4501 | NULL_RTX(rtx) 0, 1, max_cost - extra_cost); | ||||
4502 | if (t1 == 0) | ||||
4503 | goto fail1; | ||||
4504 | t2 = force_operand (gen_rtx_MINUS (int_mode,gen_rtx_fmt_ee_stat ((MINUS), ((int_mode)), ((op0)), ((t1)) ) | ||||
4505 | op0, t1)gen_rtx_fmt_ee_stat ((MINUS), ((int_mode)), ((op0)), ((t1)) ), | ||||
4506 | NULL_RTX(rtx) 0); | ||||
4507 | t3 = expand_shift (RSHIFT_EXPR, int_mode, | ||||
4508 | t2, 1, NULL_RTX(rtx) 0, 1); | ||||
4509 | t4 = force_operand (gen_rtx_PLUS (int_mode,gen_rtx_fmt_ee_stat ((PLUS), ((int_mode)), ((t1)), ((t3)) ) | ||||
4510 | t1, t3)gen_rtx_fmt_ee_stat ((PLUS), ((int_mode)), ((t1)), ((t3)) ), | ||||
4511 | NULL_RTX(rtx) 0); | ||||
4512 | quotient = expand_shift | ||||
4513 | (RSHIFT_EXPR, int_mode, t4, | ||||
4514 | post_shift - 1, tquotient, 1); | ||||
4515 | } | ||||
4516 | else | ||||
4517 | { | ||||
4518 | rtx t1, t2; | ||||
4519 | |||||
4520 | if (pre_shift >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
4521 | || post_shift >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
4522 | goto fail1; | ||||
4523 | |||||
4524 | t1 = expand_shift | ||||
4525 | (RSHIFT_EXPR, int_mode, op0, | ||||
4526 | pre_shift, NULL_RTX(rtx) 0, 1); | ||||
4527 | extra_cost | ||||
4528 | = (shift_cost (speed, int_mode, pre_shift) | ||||
4529 | + shift_cost (speed, int_mode, post_shift)); | ||||
4530 | t2 = expmed_mult_highpart | ||||
4531 | (int_mode, t1, | ||||
4532 | gen_int_mode (ml, int_mode), | ||||
4533 | NULL_RTX(rtx) 0, 1, max_cost - extra_cost); | ||||
4534 | if (t2 == 0) | ||||
4535 | goto fail1; | ||||
4536 | quotient = expand_shift | ||||
4537 | (RSHIFT_EXPR, int_mode, t2, | ||||
4538 | post_shift, tquotient, 1); | ||||
4539 | } | ||||
4540 | } | ||||
4541 | } | ||||
4542 | else /* Too wide mode to use tricky code */ | ||||
4543 | break; | ||||
4544 | |||||
4545 | insn = get_last_insn (); | ||||
4546 | if (insn != last) | ||||
4547 | set_dst_reg_note (insn, REG_EQUAL, | ||||
4548 | gen_rtx_UDIV (int_mode, op0, op1)gen_rtx_fmt_ee_stat ((UDIV), ((int_mode)), ((op0)), ((op1)) ), | ||||
4549 | quotient); | ||||
4550 | } | ||||
4551 | else /* TRUNC_DIV, signed */ | ||||
4552 | { | ||||
4553 | unsigned HOST_WIDE_INTlong ml; | ||||
4554 | int lgup, post_shift; | ||||
4555 | rtx mlr; | ||||
4556 | HOST_WIDE_INTlong d = INTVAL (op1)((op1)->u.hwint[0]); | ||||
4557 | unsigned HOST_WIDE_INTlong abs_d; | ||||
4558 | |||||
4559 | /* Not prepared to handle division/remainder by | ||||
4560 | 0xffffffffffffffff8000000000000000 etc. */ | ||||
4561 | if (d == HOST_WIDE_INT_MIN(long) (1UL << (64 - 1)) && size > HOST_BITS_PER_WIDE_INT64) | ||||
4562 | break; | ||||
4563 | |||||
4564 | /* Since d might be INT_MIN, we have to cast to | ||||
4565 | unsigned HOST_WIDE_INT before negating to avoid | ||||
4566 | undefined signed overflow. */ | ||||
4567 | abs_d = (d >= 0 | ||||
4568 | ? (unsigned HOST_WIDE_INTlong) d | ||||
4569 | : - (unsigned HOST_WIDE_INTlong) d); | ||||
4570 | |||||
4571 | /* n rem d = n rem -d */ | ||||
4572 | if (rem_flag && d < 0) | ||||
4573 | { | ||||
4574 | d = abs_d; | ||||
4575 | op1 = gen_int_mode (abs_d, int_mode); | ||||
4576 | } | ||||
4577 | |||||
4578 | if (d == 1) | ||||
4579 | quotient = op0; | ||||
4580 | else if (d == -1) | ||||
4581 | quotient = expand_unop (int_mode, neg_optab, op0, | ||||
4582 | tquotient, 0); | ||||
4583 | else if (size <= HOST_BITS_PER_WIDE_INT64 | ||||
4584 | && abs_d == HOST_WIDE_INT_1U1UL << (size - 1)) | ||||
4585 | { | ||||
4586 | /* This case is not handled correctly below. */ | ||||
4587 | quotient = emit_store_flag (tquotient, EQ, op0, op1, | ||||
4588 | int_mode, 1, 1); | ||||
4589 | if (quotient == 0) | ||||
4590 | goto fail1; | ||||
4591 | } | ||||
4592 | else if (EXACT_POWER_OF_2_OR_ZERO_P (d)(((d) & ((d) - 1UL)) == 0) | ||||
4593 | && (size <= HOST_BITS_PER_WIDE_INT64 || d >= 0) | ||||
4594 | && (rem_flag | ||||
4595 | ? smod_pow2_cheap (speed, int_mode) | ||||
4596 | : sdiv_pow2_cheap (speed, int_mode)) | ||||
4597 | /* We assume that cheap metric is true if the | ||||
4598 | optab has an expander for this mode. */ | ||||
4599 | && ((optab_handler ((rem_flag ? smod_optab | ||||
4600 | : sdiv_optab), | ||||
4601 | int_mode) | ||||
4602 | != CODE_FOR_nothing) | ||||
4603 | || (optab_handler (sdivmod_optab, int_mode) | ||||
4604 | != CODE_FOR_nothing))) | ||||
4605 | ; | ||||
4606 | else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d)(((abs_d) & ((abs_d) - 1UL)) == 0)) | ||||
4607 | { | ||||
4608 | if (rem_flag) | ||||
4609 | { | ||||
4610 | remainder = expand_smod_pow2 (int_mode, op0, d); | ||||
4611 | if (remainder) | ||||
4612 | return gen_lowpartrtl_hooks.gen_lowpart (mode, remainder); | ||||
4613 | } | ||||
4614 | |||||
4615 | if (sdiv_pow2_cheap (speed, int_mode) | ||||
4616 | && ((optab_handler (sdiv_optab, int_mode) | ||||
4617 | != CODE_FOR_nothing) | ||||
4618 | || (optab_handler (sdivmod_optab, int_mode) | ||||
4619 | != CODE_FOR_nothing))) | ||||
4620 | quotient = expand_divmod (0, TRUNC_DIV_EXPR, | ||||
4621 | int_mode, op0, | ||||
4622 | gen_int_mode (abs_d, | ||||
4623 | int_mode), | ||||
4624 | NULL_RTX(rtx) 0, 0); | ||||
4625 | else | ||||
4626 | quotient = expand_sdiv_pow2 (int_mode, op0, abs_d); | ||||
4627 | |||||
4628 | /* We have computed OP0 / abs(OP1). If OP1 is negative, | ||||
4629 | negate the quotient. */ | ||||
4630 | if (d < 0) | ||||
4631 | { | ||||
4632 | insn = get_last_insn (); | ||||
4633 | if (insn != last | ||||
4634 | && abs_d < (HOST_WIDE_INT_1U1UL | ||||
4635 | << (HOST_BITS_PER_WIDE_INT64 - 1))) | ||||
4636 | set_dst_reg_note (insn, REG_EQUAL, | ||||
4637 | gen_rtx_DIV (int_mode, op0,gen_rtx_fmt_ee_stat ((DIV), ((int_mode)), ((op0)), ((gen_int_mode (abs_d, int_mode))) ) | ||||
4638 | gen_int_modegen_rtx_fmt_ee_stat ((DIV), ((int_mode)), ((op0)), ((gen_int_mode (abs_d, int_mode))) ) | ||||
4639 | (abs_d,gen_rtx_fmt_ee_stat ((DIV), ((int_mode)), ((op0)), ((gen_int_mode (abs_d, int_mode))) ) | ||||
4640 | int_mode))gen_rtx_fmt_ee_stat ((DIV), ((int_mode)), ((op0)), ((gen_int_mode (abs_d, int_mode))) ), | ||||
4641 | quotient); | ||||
4642 | |||||
4643 | quotient = expand_unop (int_mode, neg_optab, | ||||
4644 | quotient, quotient, 0); | ||||
4645 | } | ||||
4646 | } | ||||
4647 | else if (size <= HOST_BITS_PER_WIDE_INT64) | ||||
4648 | { | ||||
4649 | choose_multiplier (abs_d, size, size - 1, | ||||
4650 | &ml, &post_shift, &lgup); | ||||
4651 | if (ml < HOST_WIDE_INT_1U1UL << (size - 1)) | ||||
4652 | { | ||||
4653 | rtx t1, t2, t3; | ||||
4654 | |||||
4655 | if (post_shift >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
4656 | || size - 1 >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
4657 | goto fail1; | ||||
4658 | |||||
4659 | extra_cost = (shift_cost (speed, int_mode, post_shift) | ||||
4660 | + shift_cost (speed, int_mode, size - 1) | ||||
4661 | + add_cost (speed, int_mode)); | ||||
4662 | t1 = expmed_mult_highpart | ||||
4663 | (int_mode, op0, gen_int_mode (ml, int_mode), | ||||
4664 | NULL_RTX(rtx) 0, 0, max_cost - extra_cost); | ||||
4665 | if (t1 == 0) | ||||
4666 | goto fail1; | ||||
4667 | t2 = expand_shift | ||||
4668 | (RSHIFT_EXPR, int_mode, t1, | ||||
4669 | post_shift, NULL_RTX(rtx) 0, 0); | ||||
4670 | t3 = expand_shift | ||||
4671 | (RSHIFT_EXPR, int_mode, op0, | ||||
4672 | size - 1, NULL_RTX(rtx) 0, 0); | ||||
4673 | if (d < 0) | ||||
4674 | quotient | ||||
4675 | = force_operand (gen_rtx_MINUS (int_mode, t3, t2)gen_rtx_fmt_ee_stat ((MINUS), ((int_mode)), ((t3)), ((t2)) ), | ||||
4676 | tquotient); | ||||
4677 | else | ||||
4678 | quotient | ||||
4679 | = force_operand (gen_rtx_MINUS (int_mode, t2, t3)gen_rtx_fmt_ee_stat ((MINUS), ((int_mode)), ((t2)), ((t3)) ), | ||||
4680 | tquotient); | ||||
4681 | } | ||||
4682 | else | ||||
4683 | { | ||||
4684 | rtx t1, t2, t3, t4; | ||||
4685 | |||||
4686 | if (post_shift >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
4687 | || size - 1 >= BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
4688 | goto fail1; | ||||
4689 | |||||
4690 | ml |= HOST_WIDE_INT_M1U-1UL << (size - 1); | ||||
4691 | mlr = gen_int_mode (ml, int_mode); | ||||
4692 | extra_cost = (shift_cost (speed, int_mode, post_shift) | ||||
4693 | + shift_cost (speed, int_mode, size - 1) | ||||
4694 | + 2 * add_cost (speed, int_mode)); | ||||
4695 | t1 = expmed_mult_highpart (int_mode, op0, mlr, | ||||
4696 | NULL_RTX(rtx) 0, 0, | ||||
4697 | max_cost - extra_cost); | ||||
4698 | if (t1 == 0) | ||||
4699 | goto fail1; | ||||
4700 | t2 = force_operand (gen_rtx_PLUS (int_mode, t1, op0)gen_rtx_fmt_ee_stat ((PLUS), ((int_mode)), ((t1)), ((op0)) ), | ||||
4701 | NULL_RTX(rtx) 0); | ||||
4702 | t3 = expand_shift | ||||
4703 | (RSHIFT_EXPR, int_mode, t2, | ||||
4704 | post_shift, NULL_RTX(rtx) 0, 0); | ||||
4705 | t4 = expand_shift | ||||
4706 | (RSHIFT_EXPR, int_mode, op0, | ||||
4707 | size - 1, NULL_RTX(rtx) 0, 0); | ||||
4708 | if (d < 0) | ||||
4709 | quotient | ||||
4710 | = force_operand (gen_rtx_MINUS (int_mode, t4, t3)gen_rtx_fmt_ee_stat ((MINUS), ((int_mode)), ((t4)), ((t3)) ), | ||||
4711 | tquotient); | ||||
4712 | else | ||||
4713 | quotient | ||||
4714 | = force_operand (gen_rtx_MINUS (int_mode, t3, t4)gen_rtx_fmt_ee_stat ((MINUS), ((int_mode)), ((t3)), ((t4)) ), | ||||
4715 | tquotient); | ||||
4716 | } | ||||
4717 | } | ||||
4718 | else /* Too wide mode to use tricky code */ | ||||
4719 | break; | ||||
4720 | |||||
4721 | insn = get_last_insn (); | ||||
4722 | if (insn != last) | ||||
4723 | set_dst_reg_note (insn, REG_EQUAL, | ||||
4724 | gen_rtx_DIV (int_mode, op0, op1)gen_rtx_fmt_ee_stat ((DIV), ((int_mode)), ((op0)), ((op1)) ), | ||||
4725 | quotient); | ||||
4726 | } | ||||
4727 | break; | ||||
4728 | } | ||||
4729 | fail1: | ||||
4730 | delete_insns_since (last); | ||||
4731 | break; | ||||
4732 | |||||
4733 | case FLOOR_DIV_EXPR: | ||||
4734 | case FLOOR_MOD_EXPR: | ||||
4735 | /* We will come here only for signed operations. */ | ||||
4736 | if (op1_is_constant && HWI_COMPUTABLE_MODE_P (compute_mode)) | ||||
4737 | { | ||||
4738 | scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode); | ||||
4739 | int size = GET_MODE_BITSIZE (int_mode); | ||||
4740 | unsigned HOST_WIDE_INTlong mh, ml; | ||||
4741 | int pre_shift, lgup, post_shift; | ||||
4742 | HOST_WIDE_INTlong d = INTVAL (op1)((op1)->u.hwint[0]); | ||||
4743 | |||||
4744 | if (d > 0) | ||||
4745 | { | ||||
4746 | /* We could just as easily deal with negative constants here, | ||||
4747 | but it does not seem worth the trouble for GCC 2.6. */ | ||||
4748 | if (EXACT_POWER_OF_2_OR_ZERO_P (d)(((d) & ((d) - 1UL)) == 0)) | ||||
4749 | { | ||||
4750 | pre_shift = floor_log2 (d); | ||||
4751 | if (rem_flag) | ||||
4752 | { | ||||
4753 | unsigned HOST_WIDE_INTlong mask | ||||
4754 | = (HOST_WIDE_INT_1U1UL << pre_shift) - 1; | ||||
4755 | remainder = expand_binop | ||||
4756 | (int_mode, and_optab, op0, | ||||
4757 | gen_int_mode (mask, int_mode), | ||||
4758 | remainder, 0, methods); | ||||
4759 | if (remainder) | ||||
4760 | return gen_lowpartrtl_hooks.gen_lowpart (mode, remainder); | ||||
4761 | } | ||||
4762 | quotient = expand_shift | ||||
4763 | (RSHIFT_EXPR, int_mode, op0, | ||||
4764 | pre_shift, tquotient, 0); | ||||
4765 | } | ||||
4766 | else | ||||
4767 | { | ||||
4768 | rtx t1, t2, t3, t4; | ||||
4769 | |||||
4770 | mh = choose_multiplier (d, size, size - 1, | ||||
4771 | &ml, &post_shift, &lgup); | ||||
4772 | gcc_assert (!mh)((void)(!(!mh) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 4772, __FUNCTION__), 0 : 0)); | ||||
4773 | |||||
4774 | if (post_shift < BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) | ||||
4775 | && size - 1 < BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))) | ||||
4776 | { | ||||
4777 | t1 = expand_shift | ||||
4778 | (RSHIFT_EXPR, int_mode, op0, | ||||
4779 | size - 1, NULL_RTX(rtx) 0, 0); | ||||
4780 | t2 = expand_binop (int_mode, xor_optab, op0, t1, | ||||
4781 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
4782 | extra_cost = (shift_cost (speed, int_mode, post_shift) | ||||
4783 | + shift_cost (speed, int_mode, size - 1) | ||||
4784 | + 2 * add_cost (speed, int_mode)); | ||||
4785 | t3 = expmed_mult_highpart | ||||
4786 | (int_mode, t2, gen_int_mode (ml, int_mode), | ||||
4787 | NULL_RTX(rtx) 0, 1, max_cost - extra_cost); | ||||
4788 | if (t3 != 0) | ||||
4789 | { | ||||
4790 | t4 = expand_shift | ||||
4791 | (RSHIFT_EXPR, int_mode, t3, | ||||
4792 | post_shift, NULL_RTX(rtx) 0, 1); | ||||
4793 | quotient = expand_binop (int_mode, xor_optab, | ||||
4794 | t4, t1, tquotient, 0, | ||||
4795 | OPTAB_WIDEN); | ||||
4796 | } | ||||
4797 | } | ||||
4798 | } | ||||
4799 | } | ||||
4800 | else | ||||
4801 | { | ||||
4802 | rtx nsign, t1, t2, t3, t4; | ||||
4803 | t1 = force_operand (gen_rtx_PLUS (int_mode,gen_rtx_fmt_ee_stat ((PLUS), ((int_mode)), ((op0)), (((const_int_rtx [64 -1]))) ) | ||||
4804 | op0, constm1_rtx)gen_rtx_fmt_ee_stat ((PLUS), ((int_mode)), ((op0)), (((const_int_rtx [64 -1]))) ), NULL_RTX(rtx) 0); | ||||
4805 | t2 = expand_binop (int_mode, ior_optab, op0, t1, NULL_RTX(rtx) 0, | ||||
4806 | 0, OPTAB_WIDEN); | ||||
4807 | nsign = expand_shift (RSHIFT_EXPR, int_mode, t2, | ||||
4808 | size - 1, NULL_RTX(rtx) 0, 0); | ||||
4809 | t3 = force_operand (gen_rtx_MINUS (int_mode, t1, nsign)gen_rtx_fmt_ee_stat ((MINUS), ((int_mode)), ((t1)), ((nsign)) ), | ||||
4810 | NULL_RTX(rtx) 0); | ||||
4811 | t4 = expand_divmod (0, TRUNC_DIV_EXPR, int_mode, t3, op1, | ||||
4812 | NULL_RTX(rtx) 0, 0); | ||||
4813 | if (t4) | ||||
4814 | { | ||||
4815 | rtx t5; | ||||
4816 | t5 = expand_unop (int_mode, one_cmpl_optab, nsign, | ||||
4817 | NULL_RTX(rtx) 0, 0); | ||||
4818 | quotient = force_operand (gen_rtx_PLUS (int_mode, t4, t5)gen_rtx_fmt_ee_stat ((PLUS), ((int_mode)), ((t4)), ((t5)) ), | ||||
4819 | tquotient); | ||||
4820 | } | ||||
4821 | } | ||||
4822 | } | ||||
4823 | |||||
4824 | if (quotient != 0) | ||||
4825 | break; | ||||
4826 | delete_insns_since (last); | ||||
4827 | |||||
4828 | /* Try using an instruction that produces both the quotient and | ||||
4829 | remainder, using truncation. We can easily compensate the quotient | ||||
4830 | or remainder to get floor rounding, once we have the remainder. | ||||
4831 | Notice that we compute also the final remainder value here, | ||||
4832 | and return the result right away. */ | ||||
4833 | if (target == 0 || GET_MODE (target)((machine_mode) (target)->mode) != compute_mode) | ||||
4834 | target = gen_reg_rtx (compute_mode); | ||||
4835 | |||||
4836 | if (rem_flag) | ||||
4837 | { | ||||
4838 | remainder | ||||
4839 | = REG_P (target)(((enum rtx_code) (target)->code) == REG) ? target : gen_reg_rtx (compute_mode); | ||||
4840 | quotient = gen_reg_rtx (compute_mode); | ||||
4841 | } | ||||
4842 | else | ||||
4843 | { | ||||
4844 | quotient | ||||
4845 | = REG_P (target)(((enum rtx_code) (target)->code) == REG) ? target : gen_reg_rtx (compute_mode); | ||||
4846 | remainder = gen_reg_rtx (compute_mode); | ||||
4847 | } | ||||
4848 | |||||
4849 | if (expand_twoval_binop (sdivmod_optab, op0, op1, | ||||
4850 | quotient, remainder, 0)) | ||||
4851 | { | ||||
4852 | /* This could be computed with a branch-less sequence. | ||||
4853 | Save that for later. */ | ||||
4854 | rtx tem; | ||||
4855 | rtx_code_label *label = gen_label_rtx (); | ||||
4856 | do_cmp_and_jump (remainder, const0_rtx(const_int_rtx[64]), EQ, compute_mode, label); | ||||
4857 | tem = expand_binop (compute_mode, xor_optab, op0, op1, | ||||
4858 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
4859 | do_cmp_and_jump (tem, const0_rtx(const_int_rtx[64]), GE, compute_mode, label); | ||||
4860 | expand_dec (quotient, const1_rtx(const_int_rtx[64 +1])); | ||||
4861 | expand_inc (remainder, op1); | ||||
4862 | emit_label (label); | ||||
4863 | return gen_lowpartrtl_hooks.gen_lowpart (mode, rem_flag ? remainder : quotient); | ||||
4864 | } | ||||
4865 | |||||
4866 | /* No luck with division elimination or divmod. Have to do it | ||||
4867 | by conditionally adjusting op0 *and* the result. */ | ||||
4868 | { | ||||
4869 | rtx_code_label *label1, *label2, *label3, *label4, *label5; | ||||
4870 | rtx adjusted_op0; | ||||
4871 | rtx tem; | ||||
4872 | |||||
4873 | quotient = gen_reg_rtx (compute_mode); | ||||
4874 | adjusted_op0 = copy_to_mode_reg (compute_mode, op0); | ||||
4875 | label1 = gen_label_rtx (); | ||||
4876 | label2 = gen_label_rtx (); | ||||
4877 | label3 = gen_label_rtx (); | ||||
4878 | label4 = gen_label_rtx (); | ||||
4879 | label5 = gen_label_rtx (); | ||||
4880 | do_cmp_and_jump (op1, const0_rtx(const_int_rtx[64]), LT, compute_mode, label2); | ||||
4881 | do_cmp_and_jump (adjusted_op0, const0_rtx(const_int_rtx[64]), LT, compute_mode, label1); | ||||
4882 | tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1, | ||||
4883 | quotient, 0, methods); | ||||
4884 | if (tem != quotient) | ||||
4885 | emit_move_insn (quotient, tem); | ||||
4886 | emit_jump_insn (targetm.gen_jump (label5)); | ||||
4887 | emit_barrier (); | ||||
4888 | emit_label (label1); | ||||
4889 | expand_inc (adjusted_op0, const1_rtx(const_int_rtx[64 +1])); | ||||
4890 | emit_jump_insn (targetm.gen_jump (label4)); | ||||
4891 | emit_barrier (); | ||||
4892 | emit_label (label2); | ||||
4893 | do_cmp_and_jump (adjusted_op0, const0_rtx(const_int_rtx[64]), GT, compute_mode, label3); | ||||
4894 | tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1, | ||||
4895 | quotient, 0, methods); | ||||
4896 | if (tem != quotient) | ||||
4897 | emit_move_insn (quotient, tem); | ||||
4898 | emit_jump_insn (targetm.gen_jump (label5)); | ||||
4899 | emit_barrier (); | ||||
4900 | emit_label (label3); | ||||
4901 | expand_dec (adjusted_op0, const1_rtx(const_int_rtx[64 +1])); | ||||
4902 | emit_label (label4); | ||||
4903 | tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1, | ||||
4904 | quotient, 0, methods); | ||||
4905 | if (tem != quotient) | ||||
4906 | emit_move_insn (quotient, tem); | ||||
4907 | expand_dec (quotient, const1_rtx(const_int_rtx[64 +1])); | ||||
4908 | emit_label (label5); | ||||
4909 | } | ||||
4910 | break; | ||||
4911 | |||||
4912 | case CEIL_DIV_EXPR: | ||||
4913 | case CEIL_MOD_EXPR: | ||||
4914 | if (unsignedp) | ||||
4915 | { | ||||
4916 | if (op1_is_constant | ||||
4917 | && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))(((((op1)->u.hwint[0])) & ((((op1)->u.hwint[0])) - 1UL )) == 0) | ||||
4918 | && (HWI_COMPUTABLE_MODE_P (compute_mode) | ||||
4919 | || INTVAL (op1)((op1)->u.hwint[0]) >= 0)) | ||||
4920 | { | ||||
4921 | scalar_int_mode int_mode | ||||
4922 | = as_a <scalar_int_mode> (compute_mode); | ||||
4923 | rtx t1, t2, t3; | ||||
4924 | unsigned HOST_WIDE_INTlong d = INTVAL (op1)((op1)->u.hwint[0]); | ||||
4925 | t1 = expand_shift (RSHIFT_EXPR, int_mode, op0, | ||||
4926 | floor_log2 (d), tquotient, 1); | ||||
4927 | t2 = expand_binop (int_mode, and_optab, op0, | ||||
4928 | gen_int_mode (d - 1, int_mode), | ||||
4929 | NULL_RTX(rtx) 0, 1, methods); | ||||
4930 | t3 = gen_reg_rtx (int_mode); | ||||
4931 | t3 = emit_store_flag (t3, NE, t2, const0_rtx(const_int_rtx[64]), int_mode, 1, 1); | ||||
4932 | if (t3 == 0) | ||||
4933 | { | ||||
4934 | rtx_code_label *lab; | ||||
4935 | lab = gen_label_rtx (); | ||||
4936 | do_cmp_and_jump (t2, const0_rtx(const_int_rtx[64]), EQ, int_mode, lab); | ||||
4937 | expand_inc (t1, const1_rtx(const_int_rtx[64 +1])); | ||||
4938 | emit_label (lab); | ||||
4939 | quotient = t1; | ||||
4940 | } | ||||
4941 | else | ||||
4942 | quotient = force_operand (gen_rtx_PLUS (int_mode, t1, t3)gen_rtx_fmt_ee_stat ((PLUS), ((int_mode)), ((t1)), ((t3)) ), | ||||
4943 | tquotient); | ||||
4944 | break; | ||||
4945 | } | ||||
4946 | |||||
4947 | /* Try using an instruction that produces both the quotient and | ||||
4948 | remainder, using truncation. We can easily compensate the | ||||
4949 | quotient or remainder to get ceiling rounding, once we have the | ||||
4950 | remainder. Notice that we compute also the final remainder | ||||
4951 | value here, and return the result right away. */ | ||||
4952 | if (target == 0 || GET_MODE (target)((machine_mode) (target)->mode) != compute_mode) | ||||
4953 | target = gen_reg_rtx (compute_mode); | ||||
4954 | |||||
4955 | if (rem_flag) | ||||
4956 | { | ||||
4957 | remainder = (REG_P (target)(((enum rtx_code) (target)->code) == REG) | ||||
4958 | ? target : gen_reg_rtx (compute_mode)); | ||||
4959 | quotient = gen_reg_rtx (compute_mode); | ||||
4960 | } | ||||
4961 | else | ||||
4962 | { | ||||
4963 | quotient = (REG_P (target)(((enum rtx_code) (target)->code) == REG) | ||||
4964 | ? target : gen_reg_rtx (compute_mode)); | ||||
4965 | remainder = gen_reg_rtx (compute_mode); | ||||
4966 | } | ||||
4967 | |||||
4968 | if (expand_twoval_binop (udivmod_optab, op0, op1, quotient, | ||||
4969 | remainder, 1)) | ||||
4970 | { | ||||
4971 | /* This could be computed with a branch-less sequence. | ||||
4972 | Save that for later. */ | ||||
4973 | rtx_code_label *label = gen_label_rtx (); | ||||
4974 | do_cmp_and_jump (remainder, const0_rtx(const_int_rtx[64]), EQ, | ||||
4975 | compute_mode, label); | ||||
4976 | expand_inc (quotient, const1_rtx(const_int_rtx[64 +1])); | ||||
4977 | expand_dec (remainder, op1); | ||||
4978 | emit_label (label); | ||||
4979 | return gen_lowpartrtl_hooks.gen_lowpart (mode, rem_flag ? remainder : quotient); | ||||
4980 | } | ||||
4981 | |||||
4982 | /* No luck with division elimination or divmod. Have to do it | ||||
4983 | by conditionally adjusting op0 *and* the result. */ | ||||
4984 | { | ||||
4985 | rtx_code_label *label1, *label2; | ||||
4986 | rtx adjusted_op0, tem; | ||||
4987 | |||||
4988 | quotient = gen_reg_rtx (compute_mode); | ||||
4989 | adjusted_op0 = copy_to_mode_reg (compute_mode, op0); | ||||
4990 | label1 = gen_label_rtx (); | ||||
4991 | label2 = gen_label_rtx (); | ||||
4992 | do_cmp_and_jump (adjusted_op0, const0_rtx(const_int_rtx[64]), NE, | ||||
4993 | compute_mode, label1); | ||||
4994 | emit_move_insn (quotient, const0_rtx(const_int_rtx[64])); | ||||
4995 | emit_jump_insn (targetm.gen_jump (label2)); | ||||
4996 | emit_barrier (); | ||||
4997 | emit_label (label1); | ||||
4998 | expand_dec (adjusted_op0, const1_rtx(const_int_rtx[64 +1])); | ||||
4999 | tem = expand_binop (compute_mode, udiv_optab, adjusted_op0, op1, | ||||
5000 | quotient, 1, methods); | ||||
5001 | if (tem != quotient) | ||||
5002 | emit_move_insn (quotient, tem); | ||||
5003 | expand_inc (quotient, const1_rtx(const_int_rtx[64 +1])); | ||||
5004 | emit_label (label2); | ||||
5005 | } | ||||
5006 | } | ||||
5007 | else /* signed */ | ||||
5008 | { | ||||
5009 | if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))(((((op1)->u.hwint[0])) & ((((op1)->u.hwint[0])) - 1UL )) == 0) | ||||
5010 | && INTVAL (op1)((op1)->u.hwint[0]) >= 0) | ||||
5011 | { | ||||
5012 | /* This is extremely similar to the code for the unsigned case | ||||
5013 | above. For 2.7 we should merge these variants, but for | ||||
5014 | 2.6.1 I don't want to touch the code for unsigned since that | ||||
5015 | get used in C. The signed case will only be used by other | ||||
5016 | languages (Ada). */ | ||||
5017 | |||||
5018 | rtx t1, t2, t3; | ||||
5019 | unsigned HOST_WIDE_INTlong d = INTVAL (op1)((op1)->u.hwint[0]); | ||||
5020 | t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0, | ||||
5021 | floor_log2 (d), tquotient, 0); | ||||
5022 | t2 = expand_binop (compute_mode, and_optab, op0, | ||||
5023 | gen_int_mode (d - 1, compute_mode), | ||||
5024 | NULL_RTX(rtx) 0, 1, methods); | ||||
5025 | t3 = gen_reg_rtx (compute_mode); | ||||
5026 | t3 = emit_store_flag (t3, NE, t2, const0_rtx(const_int_rtx[64]), | ||||
5027 | compute_mode, 1, 1); | ||||
5028 | if (t3 == 0) | ||||
5029 | { | ||||
5030 | rtx_code_label *lab; | ||||
5031 | lab = gen_label_rtx (); | ||||
5032 | do_cmp_and_jump (t2, const0_rtx(const_int_rtx[64]), EQ, compute_mode, lab); | ||||
5033 | expand_inc (t1, const1_rtx(const_int_rtx[64 +1])); | ||||
5034 | emit_label (lab); | ||||
5035 | quotient = t1; | ||||
5036 | } | ||||
5037 | else | ||||
5038 | quotient = force_operand (gen_rtx_PLUS (compute_mode,gen_rtx_fmt_ee_stat ((PLUS), ((compute_mode)), ((t1)), ((t3)) ) | ||||
5039 | t1, t3)gen_rtx_fmt_ee_stat ((PLUS), ((compute_mode)), ((t1)), ((t3)) ), | ||||
5040 | tquotient); | ||||
5041 | break; | ||||
5042 | } | ||||
5043 | |||||
5044 | /* Try using an instruction that produces both the quotient and | ||||
5045 | remainder, using truncation. We can easily compensate the | ||||
5046 | quotient or remainder to get ceiling rounding, once we have the | ||||
5047 | remainder. Notice that we compute also the final remainder | ||||
5048 | value here, and return the result right away. */ | ||||
5049 | if (target == 0 || GET_MODE (target)((machine_mode) (target)->mode) != compute_mode) | ||||
5050 | target = gen_reg_rtx (compute_mode); | ||||
5051 | if (rem_flag) | ||||
5052 | { | ||||
5053 | remainder= (REG_P (target)(((enum rtx_code) (target)->code) == REG) | ||||
5054 | ? target : gen_reg_rtx (compute_mode)); | ||||
5055 | quotient = gen_reg_rtx (compute_mode); | ||||
5056 | } | ||||
5057 | else | ||||
5058 | { | ||||
5059 | quotient = (REG_P (target)(((enum rtx_code) (target)->code) == REG) | ||||
5060 | ? target : gen_reg_rtx (compute_mode)); | ||||
5061 | remainder = gen_reg_rtx (compute_mode); | ||||
5062 | } | ||||
5063 | |||||
5064 | if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient, | ||||
5065 | remainder, 0)) | ||||
5066 | { | ||||
5067 | /* This could be computed with a branch-less sequence. | ||||
5068 | Save that for later. */ | ||||
5069 | rtx tem; | ||||
5070 | rtx_code_label *label = gen_label_rtx (); | ||||
5071 | do_cmp_and_jump (remainder, const0_rtx(const_int_rtx[64]), EQ, | ||||
5072 | compute_mode, label); | ||||
5073 | tem = expand_binop (compute_mode, xor_optab, op0, op1, | ||||
5074 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
5075 | do_cmp_and_jump (tem, const0_rtx(const_int_rtx[64]), LT, compute_mode, label); | ||||
5076 | expand_inc (quotient, const1_rtx(const_int_rtx[64 +1])); | ||||
5077 | expand_dec (remainder, op1); | ||||
5078 | emit_label (label); | ||||
5079 | return gen_lowpartrtl_hooks.gen_lowpart (mode, rem_flag ? remainder : quotient); | ||||
5080 | } | ||||
5081 | |||||
5082 | /* No luck with division elimination or divmod. Have to do it | ||||
5083 | by conditionally adjusting op0 *and* the result. */ | ||||
5084 | { | ||||
5085 | rtx_code_label *label1, *label2, *label3, *label4, *label5; | ||||
5086 | rtx adjusted_op0; | ||||
5087 | rtx tem; | ||||
5088 | |||||
5089 | quotient = gen_reg_rtx (compute_mode); | ||||
5090 | adjusted_op0 = copy_to_mode_reg (compute_mode, op0); | ||||
5091 | label1 = gen_label_rtx (); | ||||
5092 | label2 = gen_label_rtx (); | ||||
5093 | label3 = gen_label_rtx (); | ||||
5094 | label4 = gen_label_rtx (); | ||||
5095 | label5 = gen_label_rtx (); | ||||
5096 | do_cmp_and_jump (op1, const0_rtx(const_int_rtx[64]), LT, compute_mode, label2); | ||||
5097 | do_cmp_and_jump (adjusted_op0, const0_rtx(const_int_rtx[64]), GT, | ||||
5098 | compute_mode, label1); | ||||
5099 | tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1, | ||||
5100 | quotient, 0, methods); | ||||
5101 | if (tem != quotient) | ||||
5102 | emit_move_insn (quotient, tem); | ||||
5103 | emit_jump_insn (targetm.gen_jump (label5)); | ||||
5104 | emit_barrier (); | ||||
5105 | emit_label (label1); | ||||
5106 | expand_dec (adjusted_op0, const1_rtx(const_int_rtx[64 +1])); | ||||
5107 | emit_jump_insn (targetm.gen_jump (label4)); | ||||
5108 | emit_barrier (); | ||||
5109 | emit_label (label2); | ||||
5110 | do_cmp_and_jump (adjusted_op0, const0_rtx(const_int_rtx[64]), LT, | ||||
5111 | compute_mode, label3); | ||||
5112 | tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1, | ||||
5113 | quotient, 0, methods); | ||||
5114 | if (tem != quotient) | ||||
5115 | emit_move_insn (quotient, tem); | ||||
5116 | emit_jump_insn (targetm.gen_jump (label5)); | ||||
5117 | emit_barrier (); | ||||
5118 | emit_label (label3); | ||||
5119 | expand_inc (adjusted_op0, const1_rtx(const_int_rtx[64 +1])); | ||||
5120 | emit_label (label4); | ||||
5121 | tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1, | ||||
5122 | quotient, 0, methods); | ||||
5123 | if (tem != quotient) | ||||
5124 | emit_move_insn (quotient, tem); | ||||
5125 | expand_inc (quotient, const1_rtx(const_int_rtx[64 +1])); | ||||
5126 | emit_label (label5); | ||||
5127 | } | ||||
5128 | } | ||||
5129 | break; | ||||
5130 | |||||
5131 | case EXACT_DIV_EXPR: | ||||
5132 | if (op1_is_constant && HWI_COMPUTABLE_MODE_P (compute_mode)) | ||||
5133 | { | ||||
5134 | scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode); | ||||
5135 | int size = GET_MODE_BITSIZE (int_mode); | ||||
5136 | HOST_WIDE_INTlong d = INTVAL (op1)((op1)->u.hwint[0]); | ||||
5137 | unsigned HOST_WIDE_INTlong ml; | ||||
5138 | int pre_shift; | ||||
5139 | rtx t1; | ||||
5140 | |||||
5141 | pre_shift = ctz_or_zero (d); | ||||
5142 | ml = invert_mod2n (d >> pre_shift, size); | ||||
5143 | t1 = expand_shift (RSHIFT_EXPR, int_mode, op0, | ||||
5144 | pre_shift, NULL_RTX(rtx) 0, unsignedp); | ||||
5145 | quotient = expand_mult (int_mode, t1, gen_int_mode (ml, int_mode), | ||||
5146 | NULL_RTX(rtx) 0, 1); | ||||
5147 | |||||
5148 | insn = get_last_insn (); | ||||
5149 | set_dst_reg_note (insn, REG_EQUAL, | ||||
5150 | gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,gen_rtx_fmt_ee_stat ((unsignedp ? UDIV : DIV), (int_mode), (op0 ), (op1) ) | ||||
5151 | int_mode, op0, op1)gen_rtx_fmt_ee_stat ((unsignedp ? UDIV : DIV), (int_mode), (op0 ), (op1) ), | ||||
5152 | quotient); | ||||
5153 | } | ||||
5154 | break; | ||||
5155 | |||||
5156 | case ROUND_DIV_EXPR: | ||||
5157 | case ROUND_MOD_EXPR: | ||||
5158 | if (unsignedp) | ||||
5159 | { | ||||
5160 | scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode); | ||||
5161 | rtx tem; | ||||
5162 | rtx_code_label *label; | ||||
5163 | label = gen_label_rtx (); | ||||
5164 | quotient = gen_reg_rtx (int_mode); | ||||
5165 | remainder = gen_reg_rtx (int_mode); | ||||
5166 | if (expand_twoval_binop (udivmod_optab, op0, op1, quotient, remainder, 1) == 0) | ||||
5167 | { | ||||
5168 | rtx tem; | ||||
5169 | quotient = expand_binop (int_mode, udiv_optab, op0, op1, | ||||
5170 | quotient, 1, methods); | ||||
5171 | tem = expand_mult (int_mode, quotient, op1, NULL_RTX(rtx) 0, 1); | ||||
5172 | remainder = expand_binop (int_mode, sub_optab, op0, tem, | ||||
5173 | remainder, 1, methods); | ||||
5174 | } | ||||
5175 | tem = plus_constant (int_mode, op1, -1); | ||||
5176 | tem = expand_shift (RSHIFT_EXPR, int_mode, tem, 1, NULL_RTX(rtx) 0, 1); | ||||
5177 | do_cmp_and_jump (remainder, tem, LEU, int_mode, label); | ||||
5178 | expand_inc (quotient, const1_rtx(const_int_rtx[64 +1])); | ||||
5179 | expand_dec (remainder, op1); | ||||
5180 | emit_label (label); | ||||
5181 | } | ||||
5182 | else | ||||
5183 | { | ||||
5184 | scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode); | ||||
5185 | int size = GET_MODE_BITSIZE (int_mode); | ||||
5186 | rtx abs_rem, abs_op1, tem, mask; | ||||
5187 | rtx_code_label *label; | ||||
5188 | label = gen_label_rtx (); | ||||
5189 | quotient = gen_reg_rtx (int_mode); | ||||
5190 | remainder = gen_reg_rtx (int_mode); | ||||
5191 | if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient, remainder, 0) == 0) | ||||
5192 | { | ||||
5193 | rtx tem; | ||||
5194 | quotient = expand_binop (int_mode, sdiv_optab, op0, op1, | ||||
5195 | quotient, 0, methods); | ||||
5196 | tem = expand_mult (int_mode, quotient, op1, NULL_RTX(rtx) 0, 0); | ||||
5197 | remainder = expand_binop (int_mode, sub_optab, op0, tem, | ||||
5198 | remainder, 0, methods); | ||||
5199 | } | ||||
5200 | abs_rem = expand_abs (int_mode, remainder, NULL_RTX(rtx) 0, 1, 0); | ||||
5201 | abs_op1 = expand_abs (int_mode, op1, NULL_RTX(rtx) 0, 1, 0); | ||||
5202 | tem = expand_shift (LSHIFT_EXPR, int_mode, abs_rem, | ||||
5203 | 1, NULL_RTX(rtx) 0, 1); | ||||
5204 | do_cmp_and_jump (tem, abs_op1, LTU, int_mode, label); | ||||
5205 | tem = expand_binop (int_mode, xor_optab, op0, op1, | ||||
5206 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
5207 | mask = expand_shift (RSHIFT_EXPR, int_mode, tem, | ||||
5208 | size - 1, NULL_RTX(rtx) 0, 0); | ||||
5209 | tem = expand_binop (int_mode, xor_optab, mask, const1_rtx(const_int_rtx[64 +1]), | ||||
5210 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
5211 | tem = expand_binop (int_mode, sub_optab, tem, mask, | ||||
5212 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
5213 | expand_inc (quotient, tem); | ||||
5214 | tem = expand_binop (int_mode, xor_optab, mask, op1, | ||||
5215 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
5216 | tem = expand_binop (int_mode, sub_optab, tem, mask, | ||||
5217 | NULL_RTX(rtx) 0, 0, OPTAB_WIDEN); | ||||
5218 | expand_dec (remainder, tem); | ||||
5219 | emit_label (label); | ||||
5220 | } | ||||
5221 | return gen_lowpartrtl_hooks.gen_lowpart (mode, rem_flag ? remainder : quotient); | ||||
5222 | |||||
5223 | default: | ||||
5224 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5224, __FUNCTION__)); | ||||
5225 | } | ||||
5226 | |||||
5227 | if (quotient == 0) | ||||
5228 | { | ||||
5229 | if (target && GET_MODE (target)((machine_mode) (target)->mode) != compute_mode) | ||||
5230 | target = 0; | ||||
5231 | |||||
5232 | if (rem_flag) | ||||
5233 | { | ||||
5234 | /* Try to produce the remainder without producing the quotient. | ||||
5235 | If we seem to have a divmod pattern that does not require widening, | ||||
5236 | don't try widening here. We should really have a WIDEN argument | ||||
5237 | to expand_twoval_binop, since what we'd really like to do here is | ||||
5238 | 1) try a mod insn in compute_mode | ||||
5239 | 2) try a divmod insn in compute_mode | ||||
5240 | 3) try a div insn in compute_mode and multiply-subtract to get | ||||
5241 | remainder | ||||
5242 | 4) try the same things with widening allowed. */ | ||||
5243 | remainder | ||||
5244 | = sign_expand_binop (compute_mode, umod_optab, smod_optab, | ||||
5245 | op0, op1, target, | ||||
5246 | unsignedp, | ||||
5247 | ((optab_handler (optab2, compute_mode) | ||||
5248 | != CODE_FOR_nothing) | ||||
5249 | ? OPTAB_DIRECT : OPTAB_WIDEN)); | ||||
5250 | if (remainder == 0) | ||||
5251 | { | ||||
5252 | /* No luck there. Can we do remainder and divide at once | ||||
5253 | without a library call? */ | ||||
5254 | remainder = gen_reg_rtx (compute_mode); | ||||
5255 | if (! expand_twoval_binop ((unsignedp | ||||
5256 | ? udivmod_optab | ||||
5257 | : sdivmod_optab), | ||||
5258 | op0, op1, | ||||
5259 | NULL_RTX(rtx) 0, remainder, unsignedp)) | ||||
5260 | remainder = 0; | ||||
5261 | } | ||||
5262 | |||||
5263 | if (remainder) | ||||
5264 | return gen_lowpartrtl_hooks.gen_lowpart (mode, remainder); | ||||
5265 | } | ||||
5266 | |||||
5267 | /* Produce the quotient. Try a quotient insn, but not a library call. | ||||
5268 | If we have a divmod in this mode, use it in preference to widening | ||||
5269 | the div (for this test we assume it will not fail). Note that optab2 | ||||
5270 | is set to the one of the two optabs that the call below will use. */ | ||||
5271 | quotient | ||||
5272 | = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, | ||||
5273 | op0, op1, rem_flag ? NULL_RTX(rtx) 0 : target, | ||||
5274 | unsignedp, | ||||
5275 | ((optab_handler (optab2, compute_mode) | ||||
5276 | != CODE_FOR_nothing) | ||||
5277 | ? OPTAB_DIRECT : OPTAB_WIDEN)); | ||||
5278 | |||||
5279 | if (quotient == 0) | ||||
5280 | { | ||||
5281 | /* No luck there. Try a quotient-and-remainder insn, | ||||
5282 | keeping the quotient alone. */ | ||||
5283 | quotient = gen_reg_rtx (compute_mode); | ||||
5284 | if (! expand_twoval_binop (unsignedp ? udivmod_optab : sdivmod_optab, | ||||
5285 | op0, op1, | ||||
5286 | quotient, NULL_RTX(rtx) 0, unsignedp)) | ||||
5287 | { | ||||
5288 | quotient = 0; | ||||
5289 | if (! rem_flag) | ||||
5290 | /* Still no luck. If we are not computing the remainder, | ||||
5291 | use a library call for the quotient. */ | ||||
5292 | quotient = sign_expand_binop (compute_mode, | ||||
5293 | udiv_optab, sdiv_optab, | ||||
5294 | op0, op1, target, | ||||
5295 | unsignedp, methods); | ||||
5296 | } | ||||
5297 | } | ||||
5298 | } | ||||
5299 | |||||
5300 | if (rem_flag) | ||||
5301 | { | ||||
5302 | if (target && GET_MODE (target)((machine_mode) (target)->mode) != compute_mode) | ||||
5303 | target = 0; | ||||
5304 | |||||
5305 | if (quotient == 0) | ||||
5306 | { | ||||
5307 | /* No divide instruction either. Use library for remainder. */ | ||||
5308 | remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab, | ||||
5309 | op0, op1, target, | ||||
5310 | unsignedp, methods); | ||||
5311 | /* No remainder function. Try a quotient-and-remainder | ||||
5312 | function, keeping the remainder. */ | ||||
5313 | if (!remainder | ||||
5314 | && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN)) | ||||
5315 | { | ||||
5316 | remainder = gen_reg_rtx (compute_mode); | ||||
5317 | if (!expand_twoval_binop_libfunc | ||||
5318 | (unsignedp ? udivmod_optab : sdivmod_optab, | ||||
5319 | op0, op1, | ||||
5320 | NULL_RTX(rtx) 0, remainder, | ||||
5321 | unsignedp ? UMOD : MOD)) | ||||
5322 | remainder = NULL_RTX(rtx) 0; | ||||
5323 | } | ||||
5324 | } | ||||
5325 | else | ||||
5326 | { | ||||
5327 | /* We divided. Now finish doing X - Y * (X / Y). */ | ||||
5328 | remainder = expand_mult (compute_mode, quotient, op1, | ||||
5329 | NULL_RTX(rtx) 0, unsignedp); | ||||
5330 | remainder = expand_binop (compute_mode, sub_optab, op0, | ||||
5331 | remainder, target, unsignedp, | ||||
5332 | methods); | ||||
5333 | } | ||||
5334 | } | ||||
5335 | |||||
5336 | if (methods != OPTAB_LIB_WIDEN | ||||
5337 | && (rem_flag ? remainder : quotient) == NULL_RTX(rtx) 0) | ||||
5338 | return NULL_RTX(rtx) 0; | ||||
5339 | |||||
5340 | return gen_lowpartrtl_hooks.gen_lowpart (mode, rem_flag ? remainder : quotient); | ||||
5341 | } | ||||
5342 | |||||
5343 | /* Return a tree node with data type TYPE, describing the value of X. | ||||
5344 | Usually this is an VAR_DECL, if there is no obvious better choice. | ||||
5345 | X may be an expression, however we only support those expressions | ||||
5346 | generated by loop.c. */ | ||||
5347 | |||||
5348 | tree | ||||
5349 | make_tree (tree type, rtx x) | ||||
5350 | { | ||||
5351 | tree t; | ||||
5352 | |||||
5353 | switch (GET_CODE (x)((enum rtx_code) (x)->code)) | ||||
5354 | { | ||||
5355 | case CONST_INT: | ||||
5356 | case CONST_WIDE_INT: | ||||
5357 | t = wide_int_to_tree (type, rtx_mode_t (x, TYPE_MODE (type)((((enum tree_code) ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5357, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (type) : (type)->type_common.mode))); | ||||
5358 | return t; | ||||
5359 | |||||
5360 | case CONST_DOUBLE: | ||||
5361 | STATIC_ASSERT (HOST_BITS_PER_WIDE_INT * 2 <= MAX_BITSIZE_MODE_ANY_INT)static_assert ((64 * 2 <= (64*(8))), "HOST_BITS_PER_WIDE_INT * 2 <= MAX_BITSIZE_MODE_ANY_INT" ); | ||||
5362 | if (TARGET_SUPPORTS_WIDE_INT1 == 0 && GET_MODE (x)((machine_mode) (x)->mode) == VOIDmode((void) 0, E_VOIDmode)) | ||||
5363 | t = wide_int_to_tree (type, | ||||
5364 | wide_int::from_array (&CONST_DOUBLE_LOW (x)((x)->u.hwint[0]), 2, | ||||
5365 | HOST_BITS_PER_WIDE_INT64 * 2)); | ||||
5366 | else | ||||
5367 | t = build_real (type, *CONST_DOUBLE_REAL_VALUE (x)((const struct real_value *) (&(x)->u.rv))); | ||||
5368 | |||||
5369 | return t; | ||||
5370 | |||||
5371 | case CONST_VECTOR: | ||||
5372 | { | ||||
5373 | unsigned int npatterns = CONST_VECTOR_NPATTERNS (x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum rtx_code) (_rtx)->code) != CONST_VECTOR) rtl_check_failed_flag ("CONST_VECTOR_NPATTERNS", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5373, __FUNCTION__); _rtx; }) ->u2.const_vector.npatterns ); | ||||
5374 | unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum rtx_code) (_rtx)->code) != CONST_VECTOR) rtl_check_failed_flag ("CONST_VECTOR_NELTS_PER_PATTERN", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5374, __FUNCTION__); _rtx; }) ->u2.const_vector.nelts_per_pattern ); | ||||
5375 | tree itype = TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5375, __FUNCTION__))->typed.type); | ||||
5376 | |||||
5377 | /* Build a tree with vector elements. */ | ||||
5378 | tree_vector_builder elts (type, npatterns, nelts_per_pattern); | ||||
5379 | unsigned int count = elts.encoded_nelts (); | ||||
5380 | for (unsigned int i = 0; i < count; ++i) | ||||
5381 | { | ||||
5382 | rtx elt = CONST_VECTOR_ELT (x, i)const_vector_elt (x, i); | ||||
5383 | elts.quick_push (make_tree (itype, elt)); | ||||
5384 | } | ||||
5385 | |||||
5386 | return elts.build (); | ||||
5387 | } | ||||
5388 | |||||
5389 | case PLUS: | ||||
5390 | return fold_build2 (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)),fold_build2_loc (((location_t) 0), PLUS_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ) | ||||
5391 | make_tree (type, XEXP (x, 1)))fold_build2_loc (((location_t) 0), PLUS_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ); | ||||
5392 | |||||
5393 | case MINUS: | ||||
5394 | return fold_build2 (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)),fold_build2_loc (((location_t) 0), MINUS_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ) | ||||
5395 | make_tree (type, XEXP (x, 1)))fold_build2_loc (((location_t) 0), MINUS_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ); | ||||
5396 | |||||
5397 | case NEG: | ||||
5398 | return fold_build1 (NEGATE_EXPR, type, make_tree (type, XEXP (x, 0)))fold_build1_loc (((location_t) 0), NEGATE_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)) ); | ||||
5399 | |||||
5400 | case MULT: | ||||
5401 | return fold_build2 (MULT_EXPR, type, make_tree (type, XEXP (x, 0)),fold_build2_loc (((location_t) 0), MULT_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ) | ||||
5402 | make_tree (type, XEXP (x, 1)))fold_build2_loc (((location_t) 0), MULT_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ); | ||||
5403 | |||||
5404 | case ASHIFT: | ||||
5405 | return fold_build2 (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)),fold_build2_loc (((location_t) 0), LSHIFT_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ) | ||||
5406 | make_tree (type, XEXP (x, 1)))fold_build2_loc (((location_t) 0), LSHIFT_EXPR, type, make_tree (type, (((x)->u.fld[0]).rt_rtx)), make_tree (type, (((x)-> u.fld[1]).rt_rtx)) ); | ||||
5407 | |||||
5408 | case LSHIFTRT: | ||||
5409 | t = unsigned_type_for (type); | ||||
5410 | return fold_convert (type, build2 (RSHIFT_EXPR, t,fold_convert_loc (((location_t) 0), type, build2 (RSHIFT_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (type , (((x)->u.fld[1]).rt_rtx)))) | ||||
5411 | make_tree (t, XEXP (x, 0)),fold_convert_loc (((location_t) 0), type, build2 (RSHIFT_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (type , (((x)->u.fld[1]).rt_rtx)))) | ||||
5412 | make_tree (type, XEXP (x, 1))))fold_convert_loc (((location_t) 0), type, build2 (RSHIFT_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (type , (((x)->u.fld[1]).rt_rtx)))); | ||||
5413 | |||||
5414 | case ASHIFTRT: | ||||
5415 | t = signed_type_for (type); | ||||
5416 | return fold_convert (type, build2 (RSHIFT_EXPR, t,fold_convert_loc (((location_t) 0), type, build2 (RSHIFT_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (type , (((x)->u.fld[1]).rt_rtx)))) | ||||
5417 | make_tree (t, XEXP (x, 0)),fold_convert_loc (((location_t) 0), type, build2 (RSHIFT_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (type , (((x)->u.fld[1]).rt_rtx)))) | ||||
5418 | make_tree (type, XEXP (x, 1))))fold_convert_loc (((location_t) 0), type, build2 (RSHIFT_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (type , (((x)->u.fld[1]).rt_rtx)))); | ||||
5419 | |||||
5420 | case DIV: | ||||
5421 | if (TREE_CODE (type)((enum tree_code) (type)->base.code) != REAL_TYPE) | ||||
5422 | t = signed_type_for (type); | ||||
5423 | else | ||||
5424 | t = type; | ||||
5425 | |||||
5426 | return fold_convert (type, build2 (TRUNC_DIV_EXPR, t,fold_convert_loc (((location_t) 0), type, build2 (TRUNC_DIV_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (t , (((x)->u.fld[1]).rt_rtx)))) | ||||
5427 | make_tree (t, XEXP (x, 0)),fold_convert_loc (((location_t) 0), type, build2 (TRUNC_DIV_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (t , (((x)->u.fld[1]).rt_rtx)))) | ||||
5428 | make_tree (t, XEXP (x, 1))))fold_convert_loc (((location_t) 0), type, build2 (TRUNC_DIV_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (t , (((x)->u.fld[1]).rt_rtx)))); | ||||
5429 | case UDIV: | ||||
5430 | t = unsigned_type_for (type); | ||||
5431 | return fold_convert (type, build2 (TRUNC_DIV_EXPR, t,fold_convert_loc (((location_t) 0), type, build2 (TRUNC_DIV_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (t , (((x)->u.fld[1]).rt_rtx)))) | ||||
5432 | make_tree (t, XEXP (x, 0)),fold_convert_loc (((location_t) 0), type, build2 (TRUNC_DIV_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (t , (((x)->u.fld[1]).rt_rtx)))) | ||||
5433 | make_tree (t, XEXP (x, 1))))fold_convert_loc (((location_t) 0), type, build2 (TRUNC_DIV_EXPR , t, make_tree (t, (((x)->u.fld[0]).rt_rtx)), make_tree (t , (((x)->u.fld[1]).rt_rtx)))); | ||||
5434 | |||||
5435 | case SIGN_EXTEND: | ||||
5436 | case ZERO_EXTEND: | ||||
5437 | t = lang_hooks.types.type_for_mode (GET_MODE (XEXP (x, 0))((machine_mode) ((((x)->u.fld[0]).rt_rtx))->mode), | ||||
5438 | GET_CODE (x)((enum rtx_code) (x)->code) == ZERO_EXTEND); | ||||
5439 | return fold_convert (type, make_tree (t, XEXP (x, 0)))fold_convert_loc (((location_t) 0), type, make_tree (t, (((x) ->u.fld[0]).rt_rtx))); | ||||
5440 | |||||
5441 | case CONST: | ||||
5442 | return make_tree (type, XEXP (x, 0)(((x)->u.fld[0]).rt_rtx)); | ||||
5443 | |||||
5444 | case SYMBOL_REF: | ||||
5445 | t = SYMBOL_REF_DECL (x)((__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum rtx_code) (_rtx)->code) != SYMBOL_REF) rtl_check_failed_flag ("CONSTANT_POOL_ADDRESS_P", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5445, __FUNCTION__); _rtx; })->unchanging) ? nullptr : ( (((x))->u.fld[1]).rt_tree)); | ||||
5446 | if (t) | ||||
5447 | return fold_convert (type, build_fold_addr_expr (t))fold_convert_loc (((location_t) 0), type, build_fold_addr_expr_loc (((location_t) 0), (t))); | ||||
5448 | /* fall through. */ | ||||
5449 | |||||
5450 | default: | ||||
5451 | if (CONST_POLY_INT_P (x)(1 > 1 && ((enum rtx_code) (x)->code) == CONST_POLY_INT )) | ||||
5452 | return wide_int_to_tree (t, const_poly_int_value (x)); | ||||
5453 | |||||
5454 | t = build_decl (RTL_LOCATION (x)((((((enum rtx_code) (x)->code) == INSN) || (((enum rtx_code ) (x)->code) == JUMP_INSN) || (((enum rtx_code) (x)->code ) == CALL_INSN)) || (((enum rtx_code) (x)->code) == DEBUG_INSN )) ? INSN_LOCATION (as_a <rtx_insn *> (x)) : ((location_t ) 0)), VAR_DECL, NULL_TREE(tree) nullptr, type); | ||||
5455 | |||||
5456 | /* If TYPE is a POINTER_TYPE, we might need to convert X from | ||||
5457 | address mode to pointer mode. */ | ||||
5458 | if (POINTER_TYPE_P (type)(((enum tree_code) (type)->base.code) == POINTER_TYPE || ( (enum tree_code) (type)->base.code) == REFERENCE_TYPE)) | ||||
5459 | x = convert_memory_address_addr_space | ||||
5460 | (SCALAR_INT_TYPE_MODE (type)(as_a <scalar_int_mode> ((tree_class_check ((type), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5460, __FUNCTION__))->type_common.mode)), x, TYPE_ADDR_SPACE (TREE_TYPE (type))((tree_class_check ((((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5460, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5460, __FUNCTION__))->base.u.bits.address_space)); | ||||
5461 | |||||
5462 | /* Note that we do *not* use SET_DECL_RTL here, because we do not | ||||
5463 | want set_decl_rtl to go adjusting REG_ATTRS for this temporary. */ | ||||
5464 | t->decl_with_rtl.rtl = x; | ||||
5465 | |||||
5466 | return t; | ||||
5467 | } | ||||
5468 | } | ||||
5469 | |||||
5470 | /* Compute the logical-and of OP0 and OP1, storing it in TARGET | ||||
5471 | and returning TARGET. | ||||
5472 | |||||
5473 | If TARGET is 0, a pseudo-register or constant is returned. */ | ||||
5474 | |||||
5475 | rtx | ||||
5476 | expand_and (machine_mode mode, rtx op0, rtx op1, rtx target) | ||||
5477 | { | ||||
5478 | rtx tem = 0; | ||||
5479 | |||||
5480 | if (GET_MODE (op0)((machine_mode) (op0)->mode) == VOIDmode((void) 0, E_VOIDmode) && GET_MODE (op1)((machine_mode) (op1)->mode) == VOIDmode((void) 0, E_VOIDmode)) | ||||
5481 | tem = simplify_binary_operation (AND, mode, op0, op1); | ||||
5482 | if (tem == 0) | ||||
5483 | tem = expand_binop (mode, and_optab, op0, op1, target, 0, OPTAB_LIB_WIDEN); | ||||
5484 | |||||
5485 | if (target == 0) | ||||
5486 | target = tem; | ||||
5487 | else if (tem != target) | ||||
5488 | emit_move_insn (target, tem); | ||||
5489 | return target; | ||||
5490 | } | ||||
5491 | |||||
5492 | /* Helper function for emit_store_flag. */ | ||||
5493 | rtx | ||||
5494 | emit_cstore (rtx target, enum insn_code icode, enum rtx_code code, | ||||
5495 | machine_mode mode, machine_mode compare_mode, | ||||
5496 | int unsignedp, rtx x, rtx y, int normalizep, | ||||
5497 | machine_mode target_mode) | ||||
5498 | { | ||||
5499 | class expand_operand ops[4]; | ||||
5500 | rtx op0, comparison, subtarget; | ||||
5501 | rtx_insn *last; | ||||
5502 | scalar_int_mode result_mode = targetm.cstore_mode (icode); | ||||
5503 | scalar_int_mode int_target_mode; | ||||
5504 | |||||
5505 | last = get_last_insn (); | ||||
5506 | x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp); | ||||
5507 | y = prepare_operand (icode, y, 3, mode, compare_mode, unsignedp); | ||||
5508 | if (!x || !y) | ||||
5509 | { | ||||
5510 | delete_insns_since (last); | ||||
5511 | return NULL_RTX(rtx) 0; | ||||
5512 | } | ||||
5513 | |||||
5514 | if (target_mode == VOIDmode((void) 0, E_VOIDmode)) | ||||
5515 | int_target_mode = result_mode; | ||||
5516 | else | ||||
5517 | int_target_mode = as_a <scalar_int_mode> (target_mode); | ||||
5518 | if (!target) | ||||
5519 | target = gen_reg_rtx (int_target_mode); | ||||
5520 | |||||
5521 | comparison = gen_rtx_fmt_ee (code, result_mode, x, y)gen_rtx_fmt_ee_stat ((code), (result_mode), (x), (y) ); | ||||
5522 | |||||
5523 | create_output_operand (&ops[0], optimizeglobal_options.x_optimize ? NULL_RTX(rtx) 0 : target, result_mode); | ||||
5524 | create_fixed_operand (&ops[1], comparison); | ||||
5525 | create_fixed_operand (&ops[2], x); | ||||
5526 | create_fixed_operand (&ops[3], y); | ||||
5527 | if (!maybe_expand_insn (icode, 4, ops)) | ||||
5528 | { | ||||
5529 | delete_insns_since (last); | ||||
5530 | return NULL_RTX(rtx) 0; | ||||
5531 | } | ||||
5532 | subtarget = ops[0].value; | ||||
5533 | |||||
5534 | /* If we are converting to a wider mode, first convert to | ||||
5535 | INT_TARGET_MODE, then normalize. This produces better combining | ||||
5536 | opportunities on machines that have a SIGN_EXTRACT when we are | ||||
5537 | testing a single bit. This mostly benefits the 68k. | ||||
5538 | |||||
5539 | If STORE_FLAG_VALUE does not have the sign bit set when | ||||
5540 | interpreted in MODE, we can do this conversion as unsigned, which | ||||
5541 | is usually more efficient. */ | ||||
5542 | if (GET_MODE_PRECISION (int_target_mode) > GET_MODE_PRECISION (result_mode)) | ||||
5543 | { | ||||
5544 | gcc_assert (GET_MODE_PRECISION (result_mode) != 1((void)(!(GET_MODE_PRECISION (result_mode) != 1 || 1 == 1 || 1 == -1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5545, __FUNCTION__), 0 : 0)) | ||||
5545 | || STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)((void)(!(GET_MODE_PRECISION (result_mode) != 1 || 1 == 1 || 1 == -1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5545, __FUNCTION__), 0 : 0)); | ||||
5546 | |||||
5547 | bool unsignedp = (STORE_FLAG_VALUE1 >= 0); | ||||
5548 | convert_move (target, subtarget, unsignedp); | ||||
5549 | |||||
5550 | op0 = target; | ||||
5551 | result_mode = int_target_mode; | ||||
5552 | } | ||||
5553 | else | ||||
5554 | op0 = subtarget; | ||||
5555 | |||||
5556 | /* If we want to keep subexpressions around, don't reuse our last | ||||
5557 | target. */ | ||||
5558 | if (optimizeglobal_options.x_optimize) | ||||
5559 | subtarget = 0; | ||||
5560 | |||||
5561 | /* Now normalize to the proper value in MODE. Sometimes we don't | ||||
5562 | have to do anything. */ | ||||
5563 | if (normalizep == 0 || normalizep == STORE_FLAG_VALUE1) | ||||
5564 | ; | ||||
5565 | /* STORE_FLAG_VALUE might be the most negative number, so write | ||||
5566 | the comparison this way to avoid a compiler-time warning. */ | ||||
5567 | else if (- normalizep == STORE_FLAG_VALUE1) | ||||
5568 | op0 = expand_unop (result_mode, neg_optab, op0, subtarget, 0); | ||||
5569 | |||||
5570 | /* We don't want to use STORE_FLAG_VALUE < 0 below since this makes | ||||
5571 | it hard to use a value of just the sign bit due to ANSI integer | ||||
5572 | constant typing rules. */ | ||||
5573 | else if (val_signbit_known_set_p (result_mode, STORE_FLAG_VALUE1)) | ||||
5574 | op0 = expand_shift (RSHIFT_EXPR, result_mode, op0, | ||||
5575 | GET_MODE_BITSIZE (result_mode) - 1, subtarget, | ||||
5576 | normalizep == 1); | ||||
5577 | else | ||||
5578 | { | ||||
5579 | gcc_assert (STORE_FLAG_VALUE & 1)((void)(!(1 & 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/expmed.cc" , 5579, __FUNCTION__), 0 : 0)); | ||||
5580 | |||||
5581 | op0 = expand_and (result_mode, op0, const1_rtx(const_int_rtx[64 +1]), subtarget); | ||||
5582 | if (normalizep == -1) | ||||
5583 | op0 = expand_unop (result_mode, neg_optab, op0, op0, 0); | ||||
5584 | } | ||||
5585 | |||||
5586 | /* If we were converting to a smaller mode, do the conversion now. */ | ||||
5587 | if (int_target_mode != result_mode) | ||||
5588 | { | ||||
5589 | convert_move (target, op0, 0); | ||||
5590 | return target; | ||||
5591 | } | ||||
5592 | else | ||||
5593 | return op0; | ||||
5594 | } | ||||
5595 | |||||
5596 | |||||
5597 | /* A subroutine of emit_store_flag only including "tricks" that do not | ||||
5598 | need a recursive call. These are kept separate to avoid infinite | ||||
5599 | loops. */ | ||||
5600 | |||||
5601 | static rtx | ||||
5602 | emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1, | ||||
5603 | machine_mode mode, int unsignedp, int normalizep, | ||||
5604 | machine_mode target_mode) | ||||
5605 | { | ||||
5606 | rtx subtarget; | ||||
5607 | enum insn_code icode; | ||||
5608 | machine_mode compare_mode; | ||||
5609 | enum mode_class mclass; | ||||
5610 | enum rtx_code scode; | ||||
5611 | |||||
5612 | if (unsignedp) | ||||
5613 | code = unsigned_condition (code); | ||||
5614 | scode = swap_condition (code); | ||||
5615 | |||||
5616 | /* If one operand is constant, make it the second one. Only do this | ||||
5617 | if the other operand is not constant as well. */ | ||||
5618 | |||||
5619 | if (swap_commutative_operands_p (op0, op1)) | ||||
5620 | { | ||||
5621 | std::swap (op0, op1); | ||||
5622 | code = swap_condition (code); | ||||
5623 | } | ||||
5624 | |||||
5625 | if (mode == VOIDmode((void) 0, E_VOIDmode)) | ||||
5626 | mode = GET_MODE (op0)((machine_mode) (op0)->mode); | ||||
5627 | |||||