1 | /* RTL simplification functions for GNU compiler. |
2 | Copyright (C) 1987-2024 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GCC. |
5 | |
6 | GCC is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free |
8 | Software Foundation; either version 3, or (at your option) any later |
9 | version. |
10 | |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ |
19 | |
20 | |
21 | #include "config.h" |
22 | #include "system.h" |
23 | #include "coretypes.h" |
24 | #include "backend.h" |
25 | #include "target.h" |
26 | #include "rtl.h" |
27 | #include "tree.h" |
28 | #include "predict.h" |
29 | #include "memmodel.h" |
30 | #include "optabs.h" |
31 | #include "emit-rtl.h" |
32 | #include "recog.h" |
33 | #include "diagnostic-core.h" |
34 | #include "varasm.h" |
35 | #include "flags.h" |
36 | #include "selftest.h" |
37 | #include "selftest-rtl.h" |
38 | #include "rtx-vector-builder.h" |
39 | #include "rtlanal.h" |
40 | |
41 | /* Simplification and canonicalization of RTL. */ |
42 | |
43 | /* Much code operates on (low, high) pairs; the low value is an |
44 | unsigned wide int, the high value a signed wide int. We |
45 | occasionally need to sign extend from low to high as if low were a |
46 | signed wide int. */ |
47 | #define HWI_SIGN_EXTEND(low) \ |
48 | ((((HOST_WIDE_INT) low) < 0) ? HOST_WIDE_INT_M1 : HOST_WIDE_INT_0) |
49 | |
50 | static bool plus_minus_operand_p (const_rtx); |
51 | |
52 | /* Negate I, which satisfies poly_int_rtx_p. MODE is the mode of I. */ |
53 | |
54 | static rtx |
55 | neg_poly_int_rtx (machine_mode mode, const_rtx i) |
56 | { |
57 | return immed_wide_int_const (-wi::to_poly_wide (x: i, mode), mode); |
58 | } |
59 | |
60 | /* Test whether expression, X, is an immediate constant that represents |
61 | the most significant bit of machine mode MODE. */ |
62 | |
63 | bool |
64 | mode_signbit_p (machine_mode mode, const_rtx x) |
65 | { |
66 | unsigned HOST_WIDE_INT val; |
67 | unsigned int width; |
68 | scalar_int_mode int_mode; |
69 | |
70 | if (!is_int_mode (mode, int_mode: &int_mode)) |
71 | return false; |
72 | |
73 | width = GET_MODE_PRECISION (mode: int_mode); |
74 | if (width == 0) |
75 | return false; |
76 | |
77 | if (width <= HOST_BITS_PER_WIDE_INT |
78 | && CONST_INT_P (x)) |
79 | val = INTVAL (x); |
80 | #if TARGET_SUPPORTS_WIDE_INT |
81 | else if (CONST_WIDE_INT_P (x)) |
82 | { |
83 | unsigned int i; |
84 | unsigned int elts = CONST_WIDE_INT_NUNITS (x); |
85 | if (elts != (width + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT) |
86 | return false; |
87 | for (i = 0; i < elts - 1; i++) |
88 | if (CONST_WIDE_INT_ELT (x, i) != 0) |
89 | return false; |
90 | val = CONST_WIDE_INT_ELT (x, elts - 1); |
91 | width %= HOST_BITS_PER_WIDE_INT; |
92 | if (width == 0) |
93 | width = HOST_BITS_PER_WIDE_INT; |
94 | } |
95 | #else |
96 | else if (width <= HOST_BITS_PER_DOUBLE_INT |
97 | && CONST_DOUBLE_AS_INT_P (x) |
98 | && CONST_DOUBLE_LOW (x) == 0) |
99 | { |
100 | val = CONST_DOUBLE_HIGH (x); |
101 | width -= HOST_BITS_PER_WIDE_INT; |
102 | } |
103 | #endif |
104 | else |
105 | /* X is not an integer constant. */ |
106 | return false; |
107 | |
108 | if (width < HOST_BITS_PER_WIDE_INT) |
109 | val &= (HOST_WIDE_INT_1U << width) - 1; |
110 | return val == (HOST_WIDE_INT_1U << (width - 1)); |
111 | } |
112 | |
113 | /* Test whether VAL is equal to the most significant bit of mode MODE |
114 | (after masking with the mode mask of MODE). Returns false if the |
115 | precision of MODE is too large to handle. */ |
116 | |
117 | bool |
118 | val_signbit_p (machine_mode mode, unsigned HOST_WIDE_INT val) |
119 | { |
120 | unsigned int width; |
121 | scalar_int_mode int_mode; |
122 | |
123 | if (!is_int_mode (mode, int_mode: &int_mode)) |
124 | return false; |
125 | |
126 | width = GET_MODE_PRECISION (mode: int_mode); |
127 | if (width == 0 || width > HOST_BITS_PER_WIDE_INT) |
128 | return false; |
129 | |
130 | val &= GET_MODE_MASK (int_mode); |
131 | return val == (HOST_WIDE_INT_1U << (width - 1)); |
132 | } |
133 | |
134 | /* Test whether the most significant bit of mode MODE is set in VAL. |
135 | Returns false if the precision of MODE is too large to handle. */ |
136 | bool |
137 | val_signbit_known_set_p (machine_mode mode, unsigned HOST_WIDE_INT val) |
138 | { |
139 | unsigned int width; |
140 | |
141 | scalar_int_mode int_mode; |
142 | if (!is_int_mode (mode, int_mode: &int_mode)) |
143 | return false; |
144 | |
145 | width = GET_MODE_PRECISION (mode: int_mode); |
146 | if (width == 0 || width > HOST_BITS_PER_WIDE_INT) |
147 | return false; |
148 | |
149 | val &= HOST_WIDE_INT_1U << (width - 1); |
150 | return val != 0; |
151 | } |
152 | |
153 | /* Test whether the most significant bit of mode MODE is clear in VAL. |
154 | Returns false if the precision of MODE is too large to handle. */ |
155 | bool |
156 | val_signbit_known_clear_p (machine_mode mode, unsigned HOST_WIDE_INT val) |
157 | { |
158 | unsigned int width; |
159 | |
160 | scalar_int_mode int_mode; |
161 | if (!is_int_mode (mode, int_mode: &int_mode)) |
162 | return false; |
163 | |
164 | width = GET_MODE_PRECISION (mode: int_mode); |
165 | if (width == 0 || width > HOST_BITS_PER_WIDE_INT) |
166 | return false; |
167 | |
168 | val &= HOST_WIDE_INT_1U << (width - 1); |
169 | return val == 0; |
170 | } |
171 | |
172 | /* Make a binary operation by properly ordering the operands and |
173 | seeing if the expression folds. */ |
174 | |
175 | rtx |
176 | simplify_context::simplify_gen_binary (rtx_code code, machine_mode mode, |
177 | rtx op0, rtx op1) |
178 | { |
179 | rtx tem; |
180 | |
181 | /* If this simplifies, do it. */ |
182 | tem = simplify_binary_operation (code, mode, op0, op1); |
183 | if (tem) |
184 | return tem; |
185 | |
186 | /* Put complex operands first and constants second if commutative. */ |
187 | if (GET_RTX_CLASS (code) == RTX_COMM_ARITH |
188 | && swap_commutative_operands_p (op0, op1)) |
189 | std::swap (a&: op0, b&: op1); |
190 | |
191 | return gen_rtx_fmt_ee (code, mode, op0, op1); |
192 | } |
193 | |
194 | /* If X is a MEM referencing the constant pool, return the real value. |
195 | Otherwise return X. */ |
196 | rtx |
197 | avoid_constant_pool_reference (rtx x) |
198 | { |
199 | rtx c, tmp, addr; |
200 | machine_mode cmode; |
201 | poly_int64 offset = 0; |
202 | |
203 | switch (GET_CODE (x)) |
204 | { |
205 | case MEM: |
206 | break; |
207 | |
208 | case FLOAT_EXTEND: |
209 | /* Handle float extensions of constant pool references. */ |
210 | tmp = XEXP (x, 0); |
211 | c = avoid_constant_pool_reference (x: tmp); |
212 | if (c != tmp && CONST_DOUBLE_AS_FLOAT_P (c)) |
213 | return const_double_from_real_value (*CONST_DOUBLE_REAL_VALUE (c), |
214 | GET_MODE (x)); |
215 | return x; |
216 | |
217 | default: |
218 | return x; |
219 | } |
220 | |
221 | if (GET_MODE (x) == BLKmode) |
222 | return x; |
223 | |
224 | addr = XEXP (x, 0); |
225 | |
226 | /* Call target hook to avoid the effects of -fpic etc.... */ |
227 | addr = targetm.delegitimize_address (addr); |
228 | |
229 | /* Split the address into a base and integer offset. */ |
230 | addr = strip_offset (addr, &offset); |
231 | |
232 | if (GET_CODE (addr) == LO_SUM) |
233 | addr = XEXP (addr, 1); |
234 | |
235 | /* If this is a constant pool reference, we can turn it into its |
236 | constant and hope that simplifications happen. */ |
237 | if (GET_CODE (addr) == SYMBOL_REF |
238 | && CONSTANT_POOL_ADDRESS_P (addr)) |
239 | { |
240 | c = get_pool_constant (addr); |
241 | cmode = get_pool_mode (addr); |
242 | |
243 | /* If we're accessing the constant in a different mode than it was |
244 | originally stored, attempt to fix that up via subreg simplifications. |
245 | If that fails we have no choice but to return the original memory. */ |
246 | if (known_eq (offset, 0) && cmode == GET_MODE (x)) |
247 | return c; |
248 | else if (known_in_range_p (val: offset, pos: 0, size: GET_MODE_SIZE (mode: cmode))) |
249 | { |
250 | rtx tem = simplify_subreg (GET_MODE (x), op: c, innermode: cmode, byte: offset); |
251 | if (tem && CONSTANT_P (tem)) |
252 | return tem; |
253 | } |
254 | } |
255 | |
256 | return x; |
257 | } |
258 | |
259 | /* Simplify a MEM based on its attributes. This is the default |
260 | delegitimize_address target hook, and it's recommended that every |
261 | overrider call it. */ |
262 | |
263 | rtx |
264 | delegitimize_mem_from_attrs (rtx x) |
265 | { |
266 | /* MEMs without MEM_OFFSETs may have been offset, so we can't just |
267 | use their base addresses as equivalent. */ |
268 | if (MEM_P (x) |
269 | && MEM_EXPR (x) |
270 | && MEM_OFFSET_KNOWN_P (x)) |
271 | { |
272 | tree decl = MEM_EXPR (x); |
273 | machine_mode mode = GET_MODE (x); |
274 | poly_int64 offset = 0; |
275 | |
276 | switch (TREE_CODE (decl)) |
277 | { |
278 | default: |
279 | decl = NULL; |
280 | break; |
281 | |
282 | case VAR_DECL: |
283 | break; |
284 | |
285 | case ARRAY_REF: |
286 | case ARRAY_RANGE_REF: |
287 | case COMPONENT_REF: |
288 | case BIT_FIELD_REF: |
289 | case REALPART_EXPR: |
290 | case IMAGPART_EXPR: |
291 | case VIEW_CONVERT_EXPR: |
292 | { |
293 | poly_int64 bitsize, bitpos, bytepos, toffset_val = 0; |
294 | tree toffset; |
295 | int unsignedp, reversep, volatilep = 0; |
296 | |
297 | decl |
298 | = get_inner_reference (decl, &bitsize, &bitpos, &toffset, &mode, |
299 | &unsignedp, &reversep, &volatilep); |
300 | if (maybe_ne (a: bitsize, b: GET_MODE_BITSIZE (mode)) |
301 | || !multiple_p (a: bitpos, BITS_PER_UNIT, multiple: &bytepos) |
302 | || (toffset && !poly_int_tree_p (t: toffset, value: &toffset_val))) |
303 | decl = NULL; |
304 | else |
305 | offset += bytepos + toffset_val; |
306 | break; |
307 | } |
308 | } |
309 | |
310 | if (decl |
311 | && mode == GET_MODE (x) |
312 | && VAR_P (decl) |
313 | && (TREE_STATIC (decl) |
314 | || DECL_THREAD_LOCAL_P (decl)) |
315 | && DECL_RTL_SET_P (decl) |
316 | && MEM_P (DECL_RTL (decl))) |
317 | { |
318 | rtx newx; |
319 | |
320 | offset += MEM_OFFSET (x); |
321 | |
322 | newx = DECL_RTL (decl); |
323 | |
324 | if (MEM_P (newx)) |
325 | { |
326 | rtx n = XEXP (newx, 0), o = XEXP (x, 0); |
327 | poly_int64 n_offset, o_offset; |
328 | |
329 | /* Avoid creating a new MEM needlessly if we already had |
330 | the same address. We do if there's no OFFSET and the |
331 | old address X is identical to NEWX, or if X is of the |
332 | form (plus NEWX OFFSET), or the NEWX is of the form |
333 | (plus Y (const_int Z)) and X is that with the offset |
334 | added: (plus Y (const_int Z+OFFSET)). */ |
335 | n = strip_offset (n, &n_offset); |
336 | o = strip_offset (o, &o_offset); |
337 | if (!(known_eq (o_offset, n_offset + offset) |
338 | && rtx_equal_p (o, n))) |
339 | x = adjust_address_nv (newx, mode, offset); |
340 | } |
341 | else if (GET_MODE (x) == GET_MODE (newx) |
342 | && known_eq (offset, 0)) |
343 | x = newx; |
344 | } |
345 | } |
346 | |
347 | return x; |
348 | } |
349 | |
350 | /* Make a unary operation by first seeing if it folds and otherwise making |
351 | the specified operation. */ |
352 | |
353 | rtx |
354 | simplify_context::simplify_gen_unary (rtx_code code, machine_mode mode, rtx op, |
355 | machine_mode op_mode) |
356 | { |
357 | rtx tem; |
358 | |
359 | /* If this simplifies, use it. */ |
360 | if ((tem = simplify_unary_operation (code, mode, op, op_mode)) != 0) |
361 | return tem; |
362 | |
363 | return gen_rtx_fmt_e (code, mode, op); |
364 | } |
365 | |
366 | /* Likewise for ternary operations. */ |
367 | |
368 | rtx |
369 | simplify_context::simplify_gen_ternary (rtx_code code, machine_mode mode, |
370 | machine_mode op0_mode, |
371 | rtx op0, rtx op1, rtx op2) |
372 | { |
373 | rtx tem; |
374 | |
375 | /* If this simplifies, use it. */ |
376 | if ((tem = simplify_ternary_operation (code, mode, op0_mode, |
377 | op0, op1, op2)) != 0) |
378 | return tem; |
379 | |
380 | return gen_rtx_fmt_eee (code, mode, op0, op1, op2); |
381 | } |
382 | |
383 | /* Likewise, for relational operations. |
384 | CMP_MODE specifies mode comparison is done in. */ |
385 | |
386 | rtx |
387 | simplify_context::simplify_gen_relational (rtx_code code, machine_mode mode, |
388 | machine_mode cmp_mode, |
389 | rtx op0, rtx op1) |
390 | { |
391 | rtx tem; |
392 | |
393 | if ((tem = simplify_relational_operation (code, mode, cmp_mode, |
394 | op0, op1)) != 0) |
395 | return tem; |
396 | |
397 | return gen_rtx_fmt_ee (code, mode, op0, op1); |
398 | } |
399 | |
400 | /* If FN is NULL, replace all occurrences of OLD_RTX in X with copy_rtx (DATA) |
401 | and simplify the result. If FN is non-NULL, call this callback on each |
402 | X, if it returns non-NULL, replace X with its return value and simplify the |
403 | result. */ |
404 | |
405 | rtx |
406 | simplify_replace_fn_rtx (rtx x, const_rtx old_rtx, |
407 | rtx (*fn) (rtx, const_rtx, void *), void *data) |
408 | { |
409 | enum rtx_code code = GET_CODE (x); |
410 | machine_mode mode = GET_MODE (x); |
411 | machine_mode op_mode; |
412 | const char *fmt; |
413 | rtx op0, op1, op2, newx, op; |
414 | rtvec vec, newvec; |
415 | int i, j; |
416 | |
417 | if (UNLIKELY (fn != NULL)) |
418 | { |
419 | newx = fn (x, old_rtx, data); |
420 | if (newx) |
421 | return newx; |
422 | } |
423 | else if (rtx_equal_p (x, old_rtx)) |
424 | return copy_rtx ((rtx) data); |
425 | |
426 | switch (GET_RTX_CLASS (code)) |
427 | { |
428 | case RTX_UNARY: |
429 | op0 = XEXP (x, 0); |
430 | op_mode = GET_MODE (op0); |
431 | op0 = simplify_replace_fn_rtx (x: op0, old_rtx, fn, data); |
432 | if (op0 == XEXP (x, 0)) |
433 | return x; |
434 | return simplify_gen_unary (code, mode, op: op0, op_mode); |
435 | |
436 | case RTX_BIN_ARITH: |
437 | case RTX_COMM_ARITH: |
438 | op0 = simplify_replace_fn_rtx (XEXP (x, 0), old_rtx, fn, data); |
439 | op1 = simplify_replace_fn_rtx (XEXP (x, 1), old_rtx, fn, data); |
440 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) |
441 | return x; |
442 | return simplify_gen_binary (code, mode, op0, op1); |
443 | |
444 | case RTX_COMPARE: |
445 | case RTX_COMM_COMPARE: |
446 | op0 = XEXP (x, 0); |
447 | op1 = XEXP (x, 1); |
448 | op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1); |
449 | op0 = simplify_replace_fn_rtx (x: op0, old_rtx, fn, data); |
450 | op1 = simplify_replace_fn_rtx (x: op1, old_rtx, fn, data); |
451 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) |
452 | return x; |
453 | return simplify_gen_relational (code, mode, op_mode, op0, op1); |
454 | |
455 | case RTX_TERNARY: |
456 | case RTX_BITFIELD_OPS: |
457 | op0 = XEXP (x, 0); |
458 | op_mode = GET_MODE (op0); |
459 | op0 = simplify_replace_fn_rtx (x: op0, old_rtx, fn, data); |
460 | op1 = simplify_replace_fn_rtx (XEXP (x, 1), old_rtx, fn, data); |
461 | op2 = simplify_replace_fn_rtx (XEXP (x, 2), old_rtx, fn, data); |
462 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2)) |
463 | return x; |
464 | if (op_mode == VOIDmode) |
465 | op_mode = GET_MODE (op0); |
466 | return simplify_gen_ternary (code, mode, op0_mode: op_mode, op0, op1, op2); |
467 | |
468 | case RTX_EXTRA: |
469 | if (code == SUBREG) |
470 | { |
471 | op0 = simplify_replace_fn_rtx (SUBREG_REG (x), old_rtx, fn, data); |
472 | if (op0 == SUBREG_REG (x)) |
473 | return x; |
474 | op0 = simplify_gen_subreg (GET_MODE (x), op: op0, |
475 | GET_MODE (SUBREG_REG (x)), |
476 | SUBREG_BYTE (x)); |
477 | return op0 ? op0 : x; |
478 | } |
479 | break; |
480 | |
481 | case RTX_OBJ: |
482 | if (code == MEM) |
483 | { |
484 | op0 = simplify_replace_fn_rtx (XEXP (x, 0), old_rtx, fn, data); |
485 | if (op0 == XEXP (x, 0)) |
486 | return x; |
487 | return replace_equiv_address_nv (x, op0); |
488 | } |
489 | else if (code == LO_SUM) |
490 | { |
491 | op0 = simplify_replace_fn_rtx (XEXP (x, 0), old_rtx, fn, data); |
492 | op1 = simplify_replace_fn_rtx (XEXP (x, 1), old_rtx, fn, data); |
493 | |
494 | /* (lo_sum (high x) y) -> y where x and y have the same base. */ |
495 | if (GET_CODE (op0) == HIGH) |
496 | { |
497 | rtx base0, base1, offset0, offset1; |
498 | split_const (XEXP (op0, 0), &base0, &offset0); |
499 | split_const (op1, &base1, &offset1); |
500 | if (rtx_equal_p (base0, base1)) |
501 | return op1; |
502 | } |
503 | |
504 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) |
505 | return x; |
506 | return gen_rtx_LO_SUM (mode, op0, op1); |
507 | } |
508 | break; |
509 | |
510 | default: |
511 | break; |
512 | } |
513 | |
514 | newx = x; |
515 | fmt = GET_RTX_FORMAT (code); |
516 | for (i = 0; fmt[i]; i++) |
517 | switch (fmt[i]) |
518 | { |
519 | case 'E': |
520 | vec = XVEC (x, i); |
521 | newvec = XVEC (newx, i); |
522 | for (j = 0; j < GET_NUM_ELEM (vec); j++) |
523 | { |
524 | op = simplify_replace_fn_rtx (RTVEC_ELT (vec, j), |
525 | old_rtx, fn, data); |
526 | if (op != RTVEC_ELT (vec, j)) |
527 | { |
528 | if (newvec == vec) |
529 | { |
530 | newvec = shallow_copy_rtvec (vec); |
531 | if (x == newx) |
532 | newx = shallow_copy_rtx (x); |
533 | XVEC (newx, i) = newvec; |
534 | } |
535 | RTVEC_ELT (newvec, j) = op; |
536 | } |
537 | } |
538 | break; |
539 | |
540 | case 'e': |
541 | if (XEXP (x, i)) |
542 | { |
543 | op = simplify_replace_fn_rtx (XEXP (x, i), old_rtx, fn, data); |
544 | if (op != XEXP (x, i)) |
545 | { |
546 | if (x == newx) |
547 | newx = shallow_copy_rtx (x); |
548 | XEXP (newx, i) = op; |
549 | } |
550 | } |
551 | break; |
552 | } |
553 | return newx; |
554 | } |
555 | |
556 | /* Replace all occurrences of OLD_RTX in X with NEW_RTX and try to simplify the |
557 | resulting RTX. Return a new RTX which is as simplified as possible. */ |
558 | |
559 | rtx |
560 | simplify_replace_rtx (rtx x, const_rtx old_rtx, rtx new_rtx) |
561 | { |
562 | return simplify_replace_fn_rtx (x, old_rtx, fn: 0, data: new_rtx); |
563 | } |
564 | |
565 | /* Try to simplify a MODE truncation of OP, which has OP_MODE. |
566 | Only handle cases where the truncated value is inherently an rvalue. |
567 | |
568 | RTL provides two ways of truncating a value: |
569 | |
570 | 1. a lowpart subreg. This form is only a truncation when both |
571 | the outer and inner modes (here MODE and OP_MODE respectively) |
572 | are scalar integers, and only then when the subreg is used as |
573 | an rvalue. |
574 | |
575 | It is only valid to form such truncating subregs if the |
576 | truncation requires no action by the target. The onus for |
577 | proving this is on the creator of the subreg -- e.g. the |
578 | caller to simplify_subreg or simplify_gen_subreg -- and typically |
579 | involves either TRULY_NOOP_TRUNCATION_MODES_P or truncated_to_mode. |
580 | |
581 | 2. a TRUNCATE. This form handles both scalar and compound integers. |
582 | |
583 | The first form is preferred where valid. However, the TRUNCATE |
584 | handling in simplify_unary_operation turns the second form into the |
585 | first form when TRULY_NOOP_TRUNCATION_MODES_P or truncated_to_mode allow, |
586 | so it is generally safe to form rvalue truncations using: |
587 | |
588 | simplify_gen_unary (TRUNCATE, ...) |
589 | |
590 | and leave simplify_unary_operation to work out which representation |
591 | should be used. |
592 | |
593 | Because of the proof requirements on (1), simplify_truncation must |
594 | also use simplify_gen_unary (TRUNCATE, ...) to truncate parts of OP, |
595 | regardless of whether the outer truncation came from a SUBREG or a |
596 | TRUNCATE. For example, if the caller has proven that an SImode |
597 | truncation of: |
598 | |
599 | (and:DI X Y) |
600 | |
601 | is a no-op and can be represented as a subreg, it does not follow |
602 | that SImode truncations of X and Y are also no-ops. On a target |
603 | like 64-bit MIPS that requires SImode values to be stored in |
604 | sign-extended form, an SImode truncation of: |
605 | |
606 | (and:DI (reg:DI X) (const_int 63)) |
607 | |
608 | is trivially a no-op because only the lower 6 bits can be set. |
609 | However, X is still an arbitrary 64-bit number and so we cannot |
610 | assume that truncating it too is a no-op. */ |
611 | |
612 | rtx |
613 | simplify_context::simplify_truncation (machine_mode mode, rtx op, |
614 | machine_mode op_mode) |
615 | { |
616 | unsigned int precision = GET_MODE_UNIT_PRECISION (mode); |
617 | unsigned int op_precision = GET_MODE_UNIT_PRECISION (op_mode); |
618 | scalar_int_mode int_mode, int_op_mode, subreg_mode; |
619 | |
620 | gcc_assert (precision <= op_precision); |
621 | |
622 | /* Optimize truncations of zero and sign extended values. */ |
623 | if (GET_CODE (op) == ZERO_EXTEND |
624 | || GET_CODE (op) == SIGN_EXTEND) |
625 | { |
626 | /* There are three possibilities. If MODE is the same as the |
627 | origmode, we can omit both the extension and the subreg. |
628 | If MODE is not larger than the origmode, we can apply the |
629 | truncation without the extension. Finally, if the outermode |
630 | is larger than the origmode, we can just extend to the appropriate |
631 | mode. */ |
632 | machine_mode origmode = GET_MODE (XEXP (op, 0)); |
633 | if (mode == origmode) |
634 | return XEXP (op, 0); |
635 | else if (precision <= GET_MODE_UNIT_PRECISION (origmode)) |
636 | return simplify_gen_unary (code: TRUNCATE, mode, |
637 | XEXP (op, 0), op_mode: origmode); |
638 | else |
639 | return simplify_gen_unary (GET_CODE (op), mode, |
640 | XEXP (op, 0), op_mode: origmode); |
641 | } |
642 | |
643 | /* If the machine can perform operations in the truncated mode, distribute |
644 | the truncation, i.e. simplify (truncate:QI (op:SI (x:SI) (y:SI))) into |
645 | (op:QI (truncate:QI (x:SI)) (truncate:QI (y:SI))). */ |
646 | if (1 |
647 | && (!WORD_REGISTER_OPERATIONS || precision >= BITS_PER_WORD) |
648 | && (GET_CODE (op) == PLUS |
649 | || GET_CODE (op) == MINUS |
650 | || GET_CODE (op) == MULT)) |
651 | { |
652 | rtx op0 = simplify_gen_unary (code: TRUNCATE, mode, XEXP (op, 0), op_mode); |
653 | if (op0) |
654 | { |
655 | rtx op1 = simplify_gen_unary (code: TRUNCATE, mode, XEXP (op, 1), op_mode); |
656 | if (op1) |
657 | return simplify_gen_binary (GET_CODE (op), mode, op0, op1); |
658 | } |
659 | } |
660 | |
661 | /* Simplify (truncate:QI (lshiftrt:SI (sign_extend:SI (x:QI)) C)) into |
662 | to (ashiftrt:QI (x:QI) C), where C is a suitable small constant and |
663 | the outer subreg is effectively a truncation to the original mode. */ |
664 | if ((GET_CODE (op) == LSHIFTRT |
665 | || GET_CODE (op) == ASHIFTRT) |
666 | /* Ensure that OP_MODE is at least twice as wide as MODE |
667 | to avoid the possibility that an outer LSHIFTRT shifts by more |
668 | than the sign extension's sign_bit_copies and introduces zeros |
669 | into the high bits of the result. */ |
670 | && 2 * precision <= op_precision |
671 | && CONST_INT_P (XEXP (op, 1)) |
672 | && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND |
673 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode |
674 | && UINTVAL (XEXP (op, 1)) < precision) |
675 | return simplify_gen_binary (code: ASHIFTRT, mode, |
676 | XEXP (XEXP (op, 0), 0), XEXP (op, 1)); |
677 | |
678 | /* Likewise (truncate:QI (lshiftrt:SI (zero_extend:SI (x:QI)) C)) into |
679 | to (lshiftrt:QI (x:QI) C), where C is a suitable small constant and |
680 | the outer subreg is effectively a truncation to the original mode. */ |
681 | if ((GET_CODE (op) == LSHIFTRT |
682 | || GET_CODE (op) == ASHIFTRT) |
683 | && CONST_INT_P (XEXP (op, 1)) |
684 | && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND |
685 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode |
686 | && UINTVAL (XEXP (op, 1)) < precision) |
687 | return simplify_gen_binary (code: LSHIFTRT, mode, |
688 | XEXP (XEXP (op, 0), 0), XEXP (op, 1)); |
689 | |
690 | /* Likewise (truncate:QI (ashift:SI (zero_extend:SI (x:QI)) C)) into |
691 | to (ashift:QI (x:QI) C), where C is a suitable small constant and |
692 | the outer subreg is effectively a truncation to the original mode. */ |
693 | if (GET_CODE (op) == ASHIFT |
694 | && CONST_INT_P (XEXP (op, 1)) |
695 | && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND |
696 | || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND) |
697 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode |
698 | && UINTVAL (XEXP (op, 1)) < precision) |
699 | return simplify_gen_binary (code: ASHIFT, mode, |
700 | XEXP (XEXP (op, 0), 0), XEXP (op, 1)); |
701 | |
702 | /* Likewise (truncate:QI (and:SI (lshiftrt:SI (x:SI) C) C2)) into |
703 | (and:QI (lshiftrt:QI (truncate:QI (x:SI)) C) C2) for suitable C |
704 | and C2. */ |
705 | if (GET_CODE (op) == AND |
706 | && (GET_CODE (XEXP (op, 0)) == LSHIFTRT |
707 | || GET_CODE (XEXP (op, 0)) == ASHIFTRT) |
708 | && CONST_INT_P (XEXP (XEXP (op, 0), 1)) |
709 | && CONST_INT_P (XEXP (op, 1))) |
710 | { |
711 | rtx op0 = (XEXP (XEXP (op, 0), 0)); |
712 | rtx shift_op = XEXP (XEXP (op, 0), 1); |
713 | rtx mask_op = XEXP (op, 1); |
714 | unsigned HOST_WIDE_INT shift = UINTVAL (shift_op); |
715 | unsigned HOST_WIDE_INT mask = UINTVAL (mask_op); |
716 | |
717 | if (shift < precision |
718 | /* If doing this transform works for an X with all bits set, |
719 | it works for any X. */ |
720 | && ((GET_MODE_MASK (mode) >> shift) & mask) |
721 | == ((GET_MODE_MASK (op_mode) >> shift) & mask) |
722 | && (op0 = simplify_gen_unary (code: TRUNCATE, mode, op: op0, op_mode)) |
723 | && (op0 = simplify_gen_binary (code: LSHIFTRT, mode, op0, op1: shift_op))) |
724 | { |
725 | mask_op = GEN_INT (trunc_int_for_mode (mask, mode)); |
726 | return simplify_gen_binary (code: AND, mode, op0, op1: mask_op); |
727 | } |
728 | } |
729 | |
730 | /* Turn (truncate:M1 (*_extract:M2 (reg:M2) (len) (pos))) into |
731 | (*_extract:M1 (truncate:M1 (reg:M2)) (len) (pos')) if possible without |
732 | changing len. */ |
733 | if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT) |
734 | && REG_P (XEXP (op, 0)) |
735 | && GET_MODE (XEXP (op, 0)) == GET_MODE (op) |
736 | && CONST_INT_P (XEXP (op, 1)) |
737 | && CONST_INT_P (XEXP (op, 2))) |
738 | { |
739 | rtx op0 = XEXP (op, 0); |
740 | unsigned HOST_WIDE_INT len = UINTVAL (XEXP (op, 1)); |
741 | unsigned HOST_WIDE_INT pos = UINTVAL (XEXP (op, 2)); |
742 | if (BITS_BIG_ENDIAN && pos >= op_precision - precision) |
743 | { |
744 | op0 = simplify_gen_unary (code: TRUNCATE, mode, op: op0, GET_MODE (op0)); |
745 | if (op0) |
746 | { |
747 | pos -= op_precision - precision; |
748 | return simplify_gen_ternary (GET_CODE (op), mode, op0_mode: mode, op0, |
749 | XEXP (op, 1), GEN_INT (pos)); |
750 | } |
751 | } |
752 | else if (!BITS_BIG_ENDIAN && precision >= len + pos) |
753 | { |
754 | op0 = simplify_gen_unary (code: TRUNCATE, mode, op: op0, GET_MODE (op0)); |
755 | if (op0) |
756 | return simplify_gen_ternary (GET_CODE (op), mode, op0_mode: mode, op0, |
757 | XEXP (op, 1), XEXP (op, 2)); |
758 | } |
759 | } |
760 | |
761 | /* Recognize a word extraction from a multi-word subreg. */ |
762 | if ((GET_CODE (op) == LSHIFTRT |
763 | || GET_CODE (op) == ASHIFTRT) |
764 | && SCALAR_INT_MODE_P (mode) |
765 | && SCALAR_INT_MODE_P (op_mode) |
766 | && precision >= BITS_PER_WORD |
767 | && 2 * precision <= op_precision |
768 | && CONST_INT_P (XEXP (op, 1)) |
769 | && (INTVAL (XEXP (op, 1)) & (precision - 1)) == 0 |
770 | && UINTVAL (XEXP (op, 1)) < op_precision) |
771 | { |
772 | poly_int64 byte = subreg_lowpart_offset (outermode: mode, innermode: op_mode); |
773 | int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; |
774 | return simplify_gen_subreg (mode, XEXP (op, 0), op_mode, |
775 | (WORDS_BIG_ENDIAN |
776 | ? byte - shifted_bytes |
777 | : byte + shifted_bytes)); |
778 | } |
779 | |
780 | /* If we have a TRUNCATE of a right shift of MEM, make a new MEM |
781 | and try replacing the TRUNCATE and shift with it. Don't do this |
782 | if the MEM has a mode-dependent address. */ |
783 | if ((GET_CODE (op) == LSHIFTRT |
784 | || GET_CODE (op) == ASHIFTRT) |
785 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
786 | && is_a <scalar_int_mode> (m: op_mode, result: &int_op_mode) |
787 | && MEM_P (XEXP (op, 0)) |
788 | && CONST_INT_P (XEXP (op, 1)) |
789 | && INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (mode: int_mode) == 0 |
790 | && INTVAL (XEXP (op, 1)) > 0 |
791 | && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (mode: int_op_mode) |
792 | && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0), |
793 | MEM_ADDR_SPACE (XEXP (op, 0))) |
794 | && ! MEM_VOLATILE_P (XEXP (op, 0)) |
795 | && (GET_MODE_SIZE (mode: int_mode) >= UNITS_PER_WORD |
796 | || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN)) |
797 | { |
798 | poly_int64 byte = subreg_lowpart_offset (outermode: int_mode, innermode: int_op_mode); |
799 | int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; |
800 | return adjust_address_nv (XEXP (op, 0), int_mode, |
801 | (WORDS_BIG_ENDIAN |
802 | ? byte - shifted_bytes |
803 | : byte + shifted_bytes)); |
804 | } |
805 | |
806 | /* (truncate:SI (OP:DI ({sign,zero}_extend:DI foo:SI))) is |
807 | (OP:SI foo:SI) if OP is NEG or ABS. */ |
808 | if ((GET_CODE (op) == ABS |
809 | || GET_CODE (op) == NEG) |
810 | && (GET_CODE (XEXP (op, 0)) == SIGN_EXTEND |
811 | || GET_CODE (XEXP (op, 0)) == ZERO_EXTEND) |
812 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) |
813 | return simplify_gen_unary (GET_CODE (op), mode, |
814 | XEXP (XEXP (op, 0), 0), op_mode: mode); |
815 | |
816 | /* Simplifications of (truncate:A (subreg:B X 0)). */ |
817 | if (GET_CODE (op) == SUBREG |
818 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
819 | && SCALAR_INT_MODE_P (op_mode) |
820 | && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), result: &subreg_mode) |
821 | && subreg_lowpart_p (op)) |
822 | { |
823 | /* (truncate:A (subreg:B (truncate:C X) 0)) is (truncate:A X). */ |
824 | if (GET_CODE (SUBREG_REG (op)) == TRUNCATE) |
825 | { |
826 | rtx inner = XEXP (SUBREG_REG (op), 0); |
827 | if (GET_MODE_PRECISION (mode: int_mode) |
828 | <= GET_MODE_PRECISION (mode: subreg_mode)) |
829 | return simplify_gen_unary (code: TRUNCATE, mode: int_mode, op: inner, |
830 | GET_MODE (inner)); |
831 | else |
832 | /* If subreg above is paradoxical and C is narrower |
833 | than A, return (subreg:A (truncate:C X) 0). */ |
834 | return simplify_gen_subreg (int_mode, SUBREG_REG (op), |
835 | subreg_mode, 0); |
836 | } |
837 | |
838 | /* Simplifications of (truncate:A (subreg:B X:C 0)) with |
839 | paradoxical subregs (B is wider than C). */ |
840 | if (is_a <scalar_int_mode> (m: op_mode, result: &int_op_mode)) |
841 | { |
842 | unsigned int int_op_prec = GET_MODE_PRECISION (mode: int_op_mode); |
843 | unsigned int subreg_prec = GET_MODE_PRECISION (mode: subreg_mode); |
844 | if (int_op_prec > subreg_prec) |
845 | { |
846 | if (int_mode == subreg_mode) |
847 | return SUBREG_REG (op); |
848 | if (GET_MODE_PRECISION (mode: int_mode) < subreg_prec) |
849 | return simplify_gen_unary (code: TRUNCATE, mode: int_mode, |
850 | SUBREG_REG (op), op_mode: subreg_mode); |
851 | } |
852 | /* Simplification of (truncate:A (subreg:B X:C 0)) where |
853 | A is narrower than B and B is narrower than C. */ |
854 | else if (int_op_prec < subreg_prec |
855 | && GET_MODE_PRECISION (mode: int_mode) < int_op_prec) |
856 | return simplify_gen_unary (code: TRUNCATE, mode: int_mode, |
857 | SUBREG_REG (op), op_mode: subreg_mode); |
858 | } |
859 | } |
860 | |
861 | /* (truncate:A (truncate:B X)) is (truncate:A X). */ |
862 | if (GET_CODE (op) == TRUNCATE) |
863 | return simplify_gen_unary (code: TRUNCATE, mode, XEXP (op, 0), |
864 | GET_MODE (XEXP (op, 0))); |
865 | |
866 | /* (truncate:A (ior X C)) is (const_int -1) if C is equal to that already, |
867 | in mode A. */ |
868 | if (GET_CODE (op) == IOR |
869 | && SCALAR_INT_MODE_P (mode) |
870 | && SCALAR_INT_MODE_P (op_mode) |
871 | && CONST_INT_P (XEXP (op, 1)) |
872 | && trunc_int_for_mode (INTVAL (XEXP (op, 1)), mode) == -1) |
873 | return constm1_rtx; |
874 | |
875 | return NULL_RTX; |
876 | } |
877 | |
878 | /* Try to simplify a unary operation CODE whose output mode is to be |
879 | MODE with input operand OP whose mode was originally OP_MODE. |
880 | Return zero if no simplification can be made. */ |
881 | rtx |
882 | simplify_context::simplify_unary_operation (rtx_code code, machine_mode mode, |
883 | rtx op, machine_mode op_mode) |
884 | { |
885 | rtx trueop, tem; |
886 | |
887 | trueop = avoid_constant_pool_reference (x: op); |
888 | |
889 | tem = simplify_const_unary_operation (code, mode, trueop, op_mode); |
890 | if (tem) |
891 | return tem; |
892 | |
893 | return simplify_unary_operation_1 (code, mode, op); |
894 | } |
895 | |
896 | /* Return true if FLOAT or UNSIGNED_FLOAT operation OP is known |
897 | to be exact. */ |
898 | |
899 | static bool |
900 | exact_int_to_float_conversion_p (const_rtx op) |
901 | { |
902 | machine_mode op0_mode = GET_MODE (XEXP (op, 0)); |
903 | /* Constants can reach here with -frounding-math, if they do then |
904 | the conversion isn't exact. */ |
905 | if (op0_mode == VOIDmode) |
906 | return false; |
907 | int out_bits = significand_size (GET_MODE_INNER (GET_MODE (op))); |
908 | int in_prec = GET_MODE_UNIT_PRECISION (op0_mode); |
909 | int in_bits = in_prec; |
910 | if (HWI_COMPUTABLE_MODE_P (mode: op0_mode)) |
911 | { |
912 | unsigned HOST_WIDE_INT nonzero = nonzero_bits (XEXP (op, 0), op0_mode); |
913 | if (GET_CODE (op) == FLOAT) |
914 | in_bits -= num_sign_bit_copies (XEXP (op, 0), op0_mode); |
915 | else if (GET_CODE (op) == UNSIGNED_FLOAT) |
916 | in_bits = wi::min_precision (x: wi::uhwi (val: nonzero, precision: in_prec), sgn: UNSIGNED); |
917 | else |
918 | gcc_unreachable (); |
919 | in_bits -= wi::ctz (wi::uhwi (val: nonzero, precision: in_prec)); |
920 | } |
921 | return in_bits <= out_bits; |
922 | } |
923 | |
924 | /* Perform some simplifications we can do even if the operands |
925 | aren't constant. */ |
926 | rtx |
927 | simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, |
928 | rtx op) |
929 | { |
930 | enum rtx_code reversed; |
931 | rtx temp, elt, base, step; |
932 | scalar_int_mode inner, int_mode, op_mode, op0_mode; |
933 | |
934 | switch (code) |
935 | { |
936 | case NOT: |
937 | /* (not (not X)) == X. */ |
938 | if (GET_CODE (op) == NOT) |
939 | return XEXP (op, 0); |
940 | |
941 | /* (not (eq X Y)) == (ne X Y), etc. if BImode or the result of the |
942 | comparison is all ones. */ |
943 | if (COMPARISON_P (op) |
944 | && (mode == BImode || STORE_FLAG_VALUE == -1) |
945 | && ((reversed = reversed_comparison_code (op, NULL)) != UNKNOWN)) |
946 | return simplify_gen_relational (code: reversed, mode, VOIDmode, |
947 | XEXP (op, 0), XEXP (op, 1)); |
948 | |
949 | /* (not (plus X -1)) can become (neg X). */ |
950 | if (GET_CODE (op) == PLUS |
951 | && XEXP (op, 1) == constm1_rtx) |
952 | return simplify_gen_unary (code: NEG, mode, XEXP (op, 0), op_mode: mode); |
953 | |
954 | /* Similarly, (not (neg X)) is (plus X -1). Only do this for |
955 | modes that have CONSTM1_RTX, i.e. MODE_INT, MODE_PARTIAL_INT |
956 | and MODE_VECTOR_INT. */ |
957 | if (GET_CODE (op) == NEG && CONSTM1_RTX (mode)) |
958 | return simplify_gen_binary (code: PLUS, mode, XEXP (op, 0), |
959 | CONSTM1_RTX (mode)); |
960 | |
961 | /* (not (xor X C)) for C constant is (xor X D) with D = ~C. */ |
962 | if (GET_CODE (op) == XOR |
963 | && CONST_INT_P (XEXP (op, 1)) |
964 | && (temp = simplify_unary_operation (code: NOT, mode, |
965 | XEXP (op, 1), op_mode: mode)) != 0) |
966 | return simplify_gen_binary (code: XOR, mode, XEXP (op, 0), op1: temp); |
967 | |
968 | /* (not (plus X C)) for signbit C is (xor X D) with D = ~C. */ |
969 | if (GET_CODE (op) == PLUS |
970 | && CONST_INT_P (XEXP (op, 1)) |
971 | && mode_signbit_p (mode, XEXP (op, 1)) |
972 | && (temp = simplify_unary_operation (code: NOT, mode, |
973 | XEXP (op, 1), op_mode: mode)) != 0) |
974 | return simplify_gen_binary (code: XOR, mode, XEXP (op, 0), op1: temp); |
975 | |
976 | |
977 | /* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for |
978 | operands other than 1, but that is not valid. We could do a |
979 | similar simplification for (not (lshiftrt C X)) where C is |
980 | just the sign bit, but this doesn't seem common enough to |
981 | bother with. */ |
982 | if (GET_CODE (op) == ASHIFT |
983 | && XEXP (op, 0) == const1_rtx) |
984 | { |
985 | temp = simplify_gen_unary (code: NOT, mode, const1_rtx, op_mode: mode); |
986 | return simplify_gen_binary (code: ROTATE, mode, op0: temp, XEXP (op, 1)); |
987 | } |
988 | |
989 | /* (not (ashiftrt foo C)) where C is the number of bits in FOO |
990 | minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, |
991 | so we can perform the above simplification. */ |
992 | if (STORE_FLAG_VALUE == -1 |
993 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
994 | && GET_CODE (op) == ASHIFTRT |
995 | && CONST_INT_P (XEXP (op, 1)) |
996 | && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode: int_mode) - 1) |
997 | return simplify_gen_relational (code: GE, mode: int_mode, VOIDmode, |
998 | XEXP (op, 0), const0_rtx); |
999 | |
1000 | |
1001 | if (partial_subreg_p (x: op) |
1002 | && subreg_lowpart_p (op) |
1003 | && GET_CODE (SUBREG_REG (op)) == ASHIFT |
1004 | && XEXP (SUBREG_REG (op), 0) == const1_rtx) |
1005 | { |
1006 | machine_mode inner_mode = GET_MODE (SUBREG_REG (op)); |
1007 | rtx x; |
1008 | |
1009 | x = gen_rtx_ROTATE (inner_mode, |
1010 | simplify_gen_unary (NOT, inner_mode, const1_rtx, |
1011 | inner_mode), |
1012 | XEXP (SUBREG_REG (op), 1)); |
1013 | temp = rtl_hooks.gen_lowpart_no_emit (mode, x); |
1014 | if (temp) |
1015 | return temp; |
1016 | } |
1017 | |
1018 | /* Apply De Morgan's laws to reduce number of patterns for machines |
1019 | with negating logical insns (and-not, nand, etc.). If result has |
1020 | only one NOT, put it first, since that is how the patterns are |
1021 | coded. */ |
1022 | if (GET_CODE (op) == IOR || GET_CODE (op) == AND) |
1023 | { |
1024 | rtx in1 = XEXP (op, 0), in2 = XEXP (op, 1); |
1025 | machine_mode op_mode; |
1026 | |
1027 | op_mode = GET_MODE (in1); |
1028 | in1 = simplify_gen_unary (code: NOT, mode: op_mode, op: in1, op_mode); |
1029 | |
1030 | op_mode = GET_MODE (in2); |
1031 | if (op_mode == VOIDmode) |
1032 | op_mode = mode; |
1033 | in2 = simplify_gen_unary (code: NOT, mode: op_mode, op: in2, op_mode); |
1034 | |
1035 | if (GET_CODE (in2) == NOT && GET_CODE (in1) != NOT) |
1036 | std::swap (a&: in1, b&: in2); |
1037 | |
1038 | return gen_rtx_fmt_ee (GET_CODE (op) == IOR ? AND : IOR, |
1039 | mode, in1, in2); |
1040 | } |
1041 | |
1042 | /* (not (bswap x)) -> (bswap (not x)). */ |
1043 | if (GET_CODE (op) == BSWAP || GET_CODE (op) == BITREVERSE) |
1044 | { |
1045 | rtx x = simplify_gen_unary (code: NOT, mode, XEXP (op, 0), op_mode: mode); |
1046 | return simplify_gen_unary (GET_CODE (op), mode, op: x, op_mode: mode); |
1047 | } |
1048 | break; |
1049 | |
1050 | case NEG: |
1051 | /* (neg (neg X)) == X. */ |
1052 | if (GET_CODE (op) == NEG) |
1053 | return XEXP (op, 0); |
1054 | |
1055 | /* (neg (x ? (neg y) : y)) == !x ? (neg y) : y. |
1056 | If comparison is not reversible use |
1057 | x ? y : (neg y). */ |
1058 | if (GET_CODE (op) == IF_THEN_ELSE) |
1059 | { |
1060 | rtx cond = XEXP (op, 0); |
1061 | rtx true_rtx = XEXP (op, 1); |
1062 | rtx false_rtx = XEXP (op, 2); |
1063 | |
1064 | if ((GET_CODE (true_rtx) == NEG |
1065 | && rtx_equal_p (XEXP (true_rtx, 0), false_rtx)) |
1066 | || (GET_CODE (false_rtx) == NEG |
1067 | && rtx_equal_p (XEXP (false_rtx, 0), true_rtx))) |
1068 | { |
1069 | if (reversed_comparison_code (cond, NULL) != UNKNOWN) |
1070 | temp = reversed_comparison (cond, mode); |
1071 | else |
1072 | { |
1073 | temp = cond; |
1074 | std::swap (a&: true_rtx, b&: false_rtx); |
1075 | } |
1076 | return simplify_gen_ternary (code: IF_THEN_ELSE, mode, |
1077 | op0_mode: mode, op0: temp, op1: true_rtx, op2: false_rtx); |
1078 | } |
1079 | } |
1080 | |
1081 | /* (neg (plus X 1)) can become (not X). */ |
1082 | if (GET_CODE (op) == PLUS |
1083 | && XEXP (op, 1) == const1_rtx) |
1084 | return simplify_gen_unary (code: NOT, mode, XEXP (op, 0), op_mode: mode); |
1085 | |
1086 | /* Similarly, (neg (not X)) is (plus X 1). */ |
1087 | if (GET_CODE (op) == NOT) |
1088 | return simplify_gen_binary (code: PLUS, mode, XEXP (op, 0), |
1089 | CONST1_RTX (mode)); |
1090 | |
1091 | /* (neg (minus X Y)) can become (minus Y X). This transformation |
1092 | isn't safe for modes with signed zeros, since if X and Y are |
1093 | both +0, (minus Y X) is the same as (minus X Y). If the |
1094 | rounding mode is towards +infinity (or -infinity) then the two |
1095 | expressions will be rounded differently. */ |
1096 | if (GET_CODE (op) == MINUS |
1097 | && !HONOR_SIGNED_ZEROS (mode) |
1098 | && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) |
1099 | return simplify_gen_binary (code: MINUS, mode, XEXP (op, 1), XEXP (op, 0)); |
1100 | |
1101 | if (GET_CODE (op) == PLUS |
1102 | && !HONOR_SIGNED_ZEROS (mode) |
1103 | && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) |
1104 | { |
1105 | /* (neg (plus A C)) is simplified to (minus -C A). */ |
1106 | if (CONST_SCALAR_INT_P (XEXP (op, 1)) |
1107 | || CONST_DOUBLE_AS_FLOAT_P (XEXP (op, 1))) |
1108 | { |
1109 | temp = simplify_unary_operation (code: NEG, mode, XEXP (op, 1), op_mode: mode); |
1110 | if (temp) |
1111 | return simplify_gen_binary (code: MINUS, mode, op0: temp, XEXP (op, 0)); |
1112 | } |
1113 | |
1114 | /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */ |
1115 | temp = simplify_gen_unary (code: NEG, mode, XEXP (op, 0), op_mode: mode); |
1116 | return simplify_gen_binary (code: MINUS, mode, op0: temp, XEXP (op, 1)); |
1117 | } |
1118 | |
1119 | /* (neg (mult A B)) becomes (mult A (neg B)). |
1120 | This works even for floating-point values. */ |
1121 | if (GET_CODE (op) == MULT |
1122 | && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) |
1123 | { |
1124 | temp = simplify_gen_unary (code: NEG, mode, XEXP (op, 1), op_mode: mode); |
1125 | return simplify_gen_binary (code: MULT, mode, XEXP (op, 0), op1: temp); |
1126 | } |
1127 | |
1128 | /* NEG commutes with ASHIFT since it is multiplication. Only do |
1129 | this if we can then eliminate the NEG (e.g., if the operand |
1130 | is a constant). */ |
1131 | if (GET_CODE (op) == ASHIFT) |
1132 | { |
1133 | temp = simplify_unary_operation (code: NEG, mode, XEXP (op, 0), op_mode: mode); |
1134 | if (temp) |
1135 | return simplify_gen_binary (code: ASHIFT, mode, op0: temp, XEXP (op, 1)); |
1136 | } |
1137 | |
1138 | /* (neg (ashiftrt X C)) can be replaced by (lshiftrt X C) when |
1139 | C is equal to the width of MODE minus 1. */ |
1140 | if (GET_CODE (op) == ASHIFTRT |
1141 | && CONST_INT_P (XEXP (op, 1)) |
1142 | && INTVAL (XEXP (op, 1)) == GET_MODE_UNIT_PRECISION (mode) - 1) |
1143 | return simplify_gen_binary (code: LSHIFTRT, mode, |
1144 | XEXP (op, 0), XEXP (op, 1)); |
1145 | |
1146 | /* (neg (lshiftrt X C)) can be replaced by (ashiftrt X C) when |
1147 | C is equal to the width of MODE minus 1. */ |
1148 | if (GET_CODE (op) == LSHIFTRT |
1149 | && CONST_INT_P (XEXP (op, 1)) |
1150 | && INTVAL (XEXP (op, 1)) == GET_MODE_UNIT_PRECISION (mode) - 1) |
1151 | return simplify_gen_binary (code: ASHIFTRT, mode, |
1152 | XEXP (op, 0), XEXP (op, 1)); |
1153 | |
1154 | /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */ |
1155 | if (GET_CODE (op) == XOR |
1156 | && XEXP (op, 1) == const1_rtx |
1157 | && nonzero_bits (XEXP (op, 0), mode) == 1) |
1158 | return plus_constant (mode, XEXP (op, 0), -1); |
1159 | |
1160 | /* (neg (lt x 0)) is (ashiftrt X C) if STORE_FLAG_VALUE is 1. */ |
1161 | /* (neg (lt x 0)) is (lshiftrt X C) if STORE_FLAG_VALUE is -1. */ |
1162 | if (GET_CODE (op) == LT |
1163 | && XEXP (op, 1) == const0_rtx |
1164 | && is_a <scalar_int_mode> (GET_MODE (XEXP (op, 0)), result: &inner)) |
1165 | { |
1166 | int_mode = as_a <scalar_int_mode> (m: mode); |
1167 | int isize = GET_MODE_PRECISION (mode: inner); |
1168 | if (STORE_FLAG_VALUE == 1) |
1169 | { |
1170 | temp = simplify_gen_binary (code: ASHIFTRT, mode: inner, XEXP (op, 0), |
1171 | op1: gen_int_shift_amount (inner, |
1172 | isize - 1)); |
1173 | if (int_mode == inner) |
1174 | return temp; |
1175 | if (GET_MODE_PRECISION (mode: int_mode) > isize) |
1176 | return simplify_gen_unary (code: SIGN_EXTEND, mode: int_mode, op: temp, op_mode: inner); |
1177 | return simplify_gen_unary (code: TRUNCATE, mode: int_mode, op: temp, op_mode: inner); |
1178 | } |
1179 | else if (STORE_FLAG_VALUE == -1) |
1180 | { |
1181 | temp = simplify_gen_binary (code: LSHIFTRT, mode: inner, XEXP (op, 0), |
1182 | op1: gen_int_shift_amount (inner, |
1183 | isize - 1)); |
1184 | if (int_mode == inner) |
1185 | return temp; |
1186 | if (GET_MODE_PRECISION (mode: int_mode) > isize) |
1187 | return simplify_gen_unary (code: ZERO_EXTEND, mode: int_mode, op: temp, op_mode: inner); |
1188 | return simplify_gen_unary (code: TRUNCATE, mode: int_mode, op: temp, op_mode: inner); |
1189 | } |
1190 | } |
1191 | |
1192 | if (vec_series_p (x: op, base_out: &base, step_out: &step)) |
1193 | { |
1194 | /* Only create a new series if we can simplify both parts. In other |
1195 | cases this isn't really a simplification, and it's not necessarily |
1196 | a win to replace a vector operation with a scalar operation. */ |
1197 | scalar_mode inner_mode = GET_MODE_INNER (mode); |
1198 | base = simplify_unary_operation (code: NEG, mode: inner_mode, op: base, op_mode: inner_mode); |
1199 | if (base) |
1200 | { |
1201 | step = simplify_unary_operation (code: NEG, mode: inner_mode, |
1202 | op: step, op_mode: inner_mode); |
1203 | if (step) |
1204 | return gen_vec_series (mode, base, step); |
1205 | } |
1206 | } |
1207 | break; |
1208 | |
1209 | case TRUNCATE: |
1210 | /* Don't optimize (lshiftrt (mult ...)) as it would interfere |
1211 | with the umulXi3_highpart patterns. */ |
1212 | if (GET_CODE (op) == LSHIFTRT |
1213 | && GET_CODE (XEXP (op, 0)) == MULT) |
1214 | break; |
1215 | |
1216 | if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) |
1217 | { |
1218 | if (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op))) |
1219 | { |
1220 | temp = rtl_hooks.gen_lowpart_no_emit (mode, op); |
1221 | if (temp) |
1222 | return temp; |
1223 | } |
1224 | /* We can't handle truncation to a partial integer mode here |
1225 | because we don't know the real bitsize of the partial |
1226 | integer mode. */ |
1227 | break; |
1228 | } |
1229 | |
1230 | if (GET_MODE (op) != VOIDmode) |
1231 | { |
1232 | temp = simplify_truncation (mode, op, GET_MODE (op)); |
1233 | if (temp) |
1234 | return temp; |
1235 | } |
1236 | |
1237 | /* If we know that the value is already truncated, we can |
1238 | replace the TRUNCATE with a SUBREG. */ |
1239 | if (known_eq (GET_MODE_NUNITS (mode), 1) |
1240 | && (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)) |
1241 | || truncated_to_mode (mode, op))) |
1242 | { |
1243 | temp = rtl_hooks.gen_lowpart_no_emit (mode, op); |
1244 | if (temp) |
1245 | return temp; |
1246 | } |
1247 | |
1248 | /* A truncate of a comparison can be replaced with a subreg if |
1249 | STORE_FLAG_VALUE permits. This is like the previous test, |
1250 | but it works even if the comparison is done in a mode larger |
1251 | than HOST_BITS_PER_WIDE_INT. */ |
1252 | if (HWI_COMPUTABLE_MODE_P (mode) |
1253 | && COMPARISON_P (op) |
1254 | && (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0 |
1255 | && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op))) |
1256 | { |
1257 | temp = rtl_hooks.gen_lowpart_no_emit (mode, op); |
1258 | if (temp) |
1259 | return temp; |
1260 | } |
1261 | |
1262 | /* A truncate of a memory is just loading the low part of the memory |
1263 | if we are not changing the meaning of the address. */ |
1264 | if (GET_CODE (op) == MEM |
1265 | && !VECTOR_MODE_P (mode) |
1266 | && !MEM_VOLATILE_P (op) |
1267 | && !mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op))) |
1268 | { |
1269 | temp = rtl_hooks.gen_lowpart_no_emit (mode, op); |
1270 | if (temp) |
1271 | return temp; |
1272 | } |
1273 | |
1274 | /* Check for useless truncation. */ |
1275 | if (GET_MODE (op) == mode) |
1276 | return op; |
1277 | break; |
1278 | |
1279 | case FLOAT_TRUNCATE: |
1280 | /* Check for useless truncation. */ |
1281 | if (GET_MODE (op) == mode) |
1282 | return op; |
1283 | |
1284 | if (DECIMAL_FLOAT_MODE_P (mode)) |
1285 | break; |
1286 | |
1287 | /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF. */ |
1288 | if (GET_CODE (op) == FLOAT_EXTEND |
1289 | && GET_MODE (XEXP (op, 0)) == mode) |
1290 | return XEXP (op, 0); |
1291 | |
1292 | /* (float_truncate:SF (float_truncate:DF foo:XF)) |
1293 | = (float_truncate:SF foo:XF). |
1294 | This may eliminate double rounding, so it is unsafe. |
1295 | |
1296 | (float_truncate:SF (float_extend:XF foo:DF)) |
1297 | = (float_truncate:SF foo:DF). |
1298 | |
1299 | (float_truncate:DF (float_extend:XF foo:SF)) |
1300 | = (float_extend:DF foo:SF). */ |
1301 | if ((GET_CODE (op) == FLOAT_TRUNCATE |
1302 | && flag_unsafe_math_optimizations) |
1303 | || GET_CODE (op) == FLOAT_EXTEND) |
1304 | return simplify_gen_unary (GET_MODE_UNIT_SIZE (GET_MODE (XEXP (op, 0))) |
1305 | > GET_MODE_UNIT_SIZE (mode) |
1306 | ? FLOAT_TRUNCATE : FLOAT_EXTEND, |
1307 | mode, |
1308 | XEXP (op, 0), GET_MODE (XEXP (op, 0))); |
1309 | |
1310 | /* (float_truncate (float x)) is (float x) */ |
1311 | if ((GET_CODE (op) == FLOAT || GET_CODE (op) == UNSIGNED_FLOAT) |
1312 | && (flag_unsafe_math_optimizations |
1313 | || exact_int_to_float_conversion_p (op))) |
1314 | return simplify_gen_unary (GET_CODE (op), mode, |
1315 | XEXP (op, 0), |
1316 | GET_MODE (XEXP (op, 0))); |
1317 | |
1318 | /* (float_truncate:SF (OP:DF (float_extend:DF foo:sf))) is |
1319 | (OP:SF foo:SF) if OP is NEG or ABS. */ |
1320 | if ((GET_CODE (op) == ABS |
1321 | || GET_CODE (op) == NEG) |
1322 | && GET_CODE (XEXP (op, 0)) == FLOAT_EXTEND |
1323 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) |
1324 | return simplify_gen_unary (GET_CODE (op), mode, |
1325 | XEXP (XEXP (op, 0), 0), op_mode: mode); |
1326 | |
1327 | /* (float_truncate:SF (subreg:DF (float_truncate:SF X) 0)) |
1328 | is (float_truncate:SF x). */ |
1329 | if (GET_CODE (op) == SUBREG |
1330 | && subreg_lowpart_p (op) |
1331 | && GET_CODE (SUBREG_REG (op)) == FLOAT_TRUNCATE) |
1332 | return SUBREG_REG (op); |
1333 | break; |
1334 | |
1335 | case FLOAT_EXTEND: |
1336 | /* Check for useless extension. */ |
1337 | if (GET_MODE (op) == mode) |
1338 | return op; |
1339 | |
1340 | if (DECIMAL_FLOAT_MODE_P (mode)) |
1341 | break; |
1342 | |
1343 | /* (float_extend (float_extend x)) is (float_extend x) |
1344 | |
1345 | (float_extend (float x)) is (float x) assuming that double |
1346 | rounding can't happen. |
1347 | */ |
1348 | if (GET_CODE (op) == FLOAT_EXTEND |
1349 | || ((GET_CODE (op) == FLOAT || GET_CODE (op) == UNSIGNED_FLOAT) |
1350 | && exact_int_to_float_conversion_p (op))) |
1351 | return simplify_gen_unary (GET_CODE (op), mode, |
1352 | XEXP (op, 0), |
1353 | GET_MODE (XEXP (op, 0))); |
1354 | |
1355 | break; |
1356 | |
1357 | case ABS: |
1358 | /* (abs (neg <foo>)) -> (abs <foo>) */ |
1359 | if (GET_CODE (op) == NEG) |
1360 | return simplify_gen_unary (code: ABS, mode, XEXP (op, 0), |
1361 | GET_MODE (XEXP (op, 0))); |
1362 | |
1363 | /* If the mode of the operand is VOIDmode (i.e. if it is ASM_OPERANDS), |
1364 | do nothing. */ |
1365 | if (GET_MODE (op) == VOIDmode) |
1366 | break; |
1367 | |
1368 | /* If operand is something known to be positive, ignore the ABS. */ |
1369 | if (val_signbit_known_clear_p (GET_MODE (op), |
1370 | val: nonzero_bits (op, GET_MODE (op)))) |
1371 | return op; |
1372 | |
1373 | /* Using nonzero_bits doesn't (currently) work for modes wider than |
1374 | HOST_WIDE_INT, so the following transformations help simplify |
1375 | ABS for TImode and wider. */ |
1376 | switch (GET_CODE (op)) |
1377 | { |
1378 | case ABS: |
1379 | case CLRSB: |
1380 | case FFS: |
1381 | case PARITY: |
1382 | case POPCOUNT: |
1383 | case SS_ABS: |
1384 | return op; |
1385 | |
1386 | case LSHIFTRT: |
1387 | if (CONST_INT_P (XEXP (op, 1)) |
1388 | && INTVAL (XEXP (op, 1)) > 0 |
1389 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
1390 | && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (mode: int_mode)) |
1391 | return op; |
1392 | break; |
1393 | |
1394 | default: |
1395 | break; |
1396 | } |
1397 | |
1398 | /* If operand is known to be only -1 or 0, convert ABS to NEG. */ |
1399 | if (is_a <scalar_int_mode> (m: mode, result: &int_mode) |
1400 | && (num_sign_bit_copies (op, int_mode) |
1401 | == GET_MODE_PRECISION (mode: int_mode))) |
1402 | return gen_rtx_NEG (int_mode, op); |
1403 | |
1404 | break; |
1405 | |
1406 | case FFS: |
1407 | /* (ffs (*_extend <X>)) = (*_extend (ffs <X>)). */ |
1408 | if (GET_CODE (op) == SIGN_EXTEND |
1409 | || GET_CODE (op) == ZERO_EXTEND) |
1410 | { |
1411 | temp = simplify_gen_unary (code: FFS, GET_MODE (XEXP (op, 0)), |
1412 | XEXP (op, 0), GET_MODE (XEXP (op, 0))); |
1413 | return simplify_gen_unary (GET_CODE (op), mode, op: temp, |
1414 | GET_MODE (temp)); |
1415 | } |
1416 | break; |
1417 | |
1418 | case POPCOUNT: |
1419 | switch (GET_CODE (op)) |
1420 | { |
1421 | case BSWAP: |
1422 | case BITREVERSE: |
1423 | /* (popcount (bswap <X>)) = (popcount <X>). */ |
1424 | return simplify_gen_unary (code: POPCOUNT, mode, XEXP (op, 0), |
1425 | GET_MODE (XEXP (op, 0))); |
1426 | |
1427 | case ZERO_EXTEND: |
1428 | /* (popcount (zero_extend <X>)) = (zero_extend (popcount <X>)). */ |
1429 | temp = simplify_gen_unary (code: POPCOUNT, GET_MODE (XEXP (op, 0)), |
1430 | XEXP (op, 0), GET_MODE (XEXP (op, 0))); |
1431 | return simplify_gen_unary (code: ZERO_EXTEND, mode, op: temp, |
1432 | GET_MODE (temp)); |
1433 | |
1434 | case ROTATE: |
1435 | case ROTATERT: |
1436 | /* Rotations don't affect popcount. */ |
1437 | if (!side_effects_p (XEXP (op, 1))) |
1438 | return simplify_gen_unary (code: POPCOUNT, mode, XEXP (op, 0), |
1439 | GET_MODE (XEXP (op, 0))); |
1440 | break; |
1441 | |
1442 | default: |
1443 | break; |
1444 | } |
1445 | break; |
1446 | |
1447 | case PARITY: |
1448 | switch (GET_CODE (op)) |
1449 | { |
1450 | case NOT: |
1451 | case BSWAP: |
1452 | case BITREVERSE: |
1453 | return simplify_gen_unary (code: PARITY, mode, XEXP (op, 0), |
1454 | GET_MODE (XEXP (op, 0))); |
1455 | |
1456 | case ZERO_EXTEND: |
1457 | case SIGN_EXTEND: |
1458 | temp = simplify_gen_unary (code: PARITY, GET_MODE (XEXP (op, 0)), |
1459 | XEXP (op, 0), GET_MODE (XEXP (op, 0))); |
1460 | return simplify_gen_unary (GET_CODE (op), mode, op: temp, |
1461 | GET_MODE (temp)); |
1462 | |
1463 | case ROTATE: |
1464 | case ROTATERT: |
1465 | /* Rotations don't affect parity. */ |
1466 | if (!side_effects_p (XEXP (op, 1))) |
1467 | return simplify_gen_unary (code: PARITY, mode, XEXP (op, 0), |
1468 | GET_MODE (XEXP (op, 0))); |
1469 | break; |
1470 | |
1471 | case PARITY: |
1472 | /* (parity (parity x)) -> parity (x). */ |
1473 | return op; |
1474 | |
1475 | default: |
1476 | break; |
1477 | } |
1478 | break; |
1479 | |
1480 | case BSWAP: |
1481 | /* (bswap (bswap x)) -> x. */ |
1482 | if (GET_CODE (op) == BSWAP) |
1483 | return XEXP (op, 0); |
1484 | break; |
1485 | |
1486 | case BITREVERSE: |
1487 | /* (bitreverse (bitreverse x)) -> x. */ |
1488 | if (GET_CODE (op) == BITREVERSE) |
1489 | return XEXP (op, 0); |
1490 | break; |
1491 | |
1492 | case FLOAT: |
1493 | /* (float (sign_extend <X>)) = (float <X>). */ |
1494 | if (GET_CODE (op) == SIGN_EXTEND) |
1495 | return simplify_gen_unary (code: FLOAT, mode, XEXP (op, 0), |
1496 | GET_MODE (XEXP (op, 0))); |
1497 | break; |
1498 | |
1499 | case SIGN_EXTEND: |
1500 | /* Check for useless extension. */ |
1501 | if (GET_MODE (op) == mode) |
1502 | return op; |
1503 | |
1504 | /* (sign_extend (truncate (minus (label_ref L1) (label_ref L2)))) |
1505 | becomes just the MINUS if its mode is MODE. This allows |
1506 | folding switch statements on machines using casesi (such as |
1507 | the VAX). */ |
1508 | if (GET_CODE (op) == TRUNCATE |
1509 | && GET_MODE (XEXP (op, 0)) == mode |
1510 | && GET_CODE (XEXP (op, 0)) == MINUS |
1511 | && GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF |
1512 | && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF) |
1513 | return XEXP (op, 0); |
1514 | |
1515 | /* Extending a widening multiplication should be canonicalized to |
1516 | a wider widening multiplication. */ |
1517 | if (GET_CODE (op) == MULT) |
1518 | { |
1519 | rtx lhs = XEXP (op, 0); |
1520 | rtx rhs = XEXP (op, 1); |
1521 | enum rtx_code lcode = GET_CODE (lhs); |
1522 | enum rtx_code rcode = GET_CODE (rhs); |
1523 | |
1524 | /* Widening multiplies usually extend both operands, but sometimes |
1525 | they use a shift to extract a portion of a register. */ |
1526 | if ((lcode == SIGN_EXTEND |
1527 | || (lcode == ASHIFTRT && CONST_INT_P (XEXP (lhs, 1)))) |
1528 | && (rcode == SIGN_EXTEND |
1529 | || (rcode == ASHIFTRT && CONST_INT_P (XEXP (rhs, 1))))) |
1530 | { |
1531 | machine_mode lmode = GET_MODE (lhs); |
1532 | machine_mode rmode = GET_MODE (rhs); |
1533 | int bits; |
1534 | |
1535 | if (lcode == ASHIFTRT) |
1536 | /* Number of bits not shifted off the end. */ |
1537 | bits = (GET_MODE_UNIT_PRECISION (lmode) |
1538 | - INTVAL (XEXP (lhs, 1))); |
1539 | else /* lcode == SIGN_EXTEND */ |
1540 | /* Size of inner mode. */ |
1541 | bits = GET_MODE_UNIT_PRECISION (GET_MODE (XEXP (lhs, 0))); |
1542 | |
1543 | if (rcode == ASHIFTRT) |
1544 | bits += (GET_MODE_UNIT_PRECISION (rmode) |
1545 | - INTVAL (XEXP (rhs, 1))); |
1546 | else /* rcode == SIGN_EXTEND */ |
1547 | bits += GET_MODE_UNIT_PRECISION (GET_MODE (XEXP (rhs, 0))); |
1548 | |
1549 | /* We can only widen multiplies if the result is mathematiclly |
1550 | equivalent. I.e. if overflow was impossible. */ |
1551 | if (bits <= GET_MODE_UNIT_PRECISION (GET_MODE (op))) |
1552 | return simplify_gen_binary |
1553 | (code: MULT, mode, |
1554 | op0: simplify_gen_unary (code: SIGN_EXTEND, mode, op: lhs, op_mode: lmode), |
1555 | op1: simplify_gen_unary (code: SIGN_EXTEND, mode, op: rhs, op_mode: rmode)); |
1556 | } |
1557 | } |
1558 | |
1559 | /* Check for a sign extension of a subreg of a promoted |
1560 | variable, where the promotion is sign-extended, and the |
1561 | target mode is the same as the variable's promotion. */ |
1562 | if (GET_CODE (op) == SUBREG |
1563 | && SUBREG_PROMOTED_VAR_P (op) |
1564 | && SUBREG_PROMOTED_SIGNED_P (op)) |
1565 | { |
1566 | rtx subreg = SUBREG_REG (op); |
1567 | machine_mode subreg_mode = GET_MODE (subreg); |
1568 | if (!paradoxical_subreg_p (outermode: mode, innermode: subreg_mode)) |
1569 | { |
1570 | temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg); |
1571 | if (temp) |
1572 | { |
1573 | /* Preserve SUBREG_PROMOTED_VAR_P. */ |
1574 | if (partial_subreg_p (x: temp)) |
1575 | { |
1576 | SUBREG_PROMOTED_VAR_P (temp) = 1; |
1577 | SUBREG_PROMOTED_SET (temp, SRP_SIGNED); |
1578 | } |
1579 | return temp; |
1580 | } |
1581 | } |
1582 | else |
1583 | /* Sign-extending a sign-extended subreg. */ |
1584 | return simplify_gen_unary (code: SIGN_EXTEND, mode, |
1585 | op: subreg, op_mode: subreg_mode); |
1586 | } |
1587 | |
1588 | /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>). |
1589 | (sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>). */ |
1590 | if (GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND) |
1591 | { |
1592 | gcc_assert (GET_MODE_UNIT_PRECISION (mode) |
1593 | > GET_MODE_UNIT_PRECISION (GET_MODE (op))); |
1594 | return simplify_gen_unary (GET_CODE (op), mode, XEXP (op, 0), |
1595 | GET_MODE (XEXP (op, 0))); |
1596 | } |
1597 | |
1598 | /* (sign_extend:M (ashiftrt:N (ashift <X> (const_int I)) (const_int I))) |
1599 | is (sign_extend:M (subreg:O <X>)) if there is mode with |
1600 | GET_MODE_BITSIZE (N) - I bits. |
1601 | (sign_extend:M (lshiftrt:N (ashift <X> (const_int I)) (const_int I))) |
1602 | is similarly (zero_extend:M (subreg:O <X>)). */ |
1603 | if ((GET_CODE (op) == ASHIFTRT || GET_CODE (op) == LSHIFTRT) |
1604 | && GET_CODE (XEXP (op, 0)) == ASHIFT |
1605 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
1606 | && CONST_INT_P (XEXP (op, 1)) |
1607 | && XEXP (XEXP (op, 0), 1) == XEXP (op, 1) |
1608 | && (op_mode = as_a <scalar_int_mode> (GET_MODE (op)), |
1609 | GET_MODE_PRECISION (mode: op_mode) > INTVAL (XEXP (op, 1)))) |
1610 | { |
1611 | scalar_int_mode tmode; |
1612 | gcc_assert (GET_MODE_PRECISION (int_mode) |
1613 | > GET_MODE_PRECISION (op_mode)); |
1614 | if (int_mode_for_size (size: GET_MODE_PRECISION (mode: op_mode) |
1615 | - INTVAL (XEXP (op, 1)), limit: 1).exists (mode: &tmode)) |
1616 | { |
1617 | rtx inner = |
1618 | rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); |
1619 | if (inner) |
1620 | return simplify_gen_unary (GET_CODE (op) == ASHIFTRT |
1621 | ? SIGN_EXTEND : ZERO_EXTEND, |
1622 | mode: int_mode, op: inner, op_mode: tmode); |
1623 | } |
1624 | } |
1625 | |
1626 | /* (sign_extend:M (lshiftrt:N <X> (const_int I))) is better as |
1627 | (zero_extend:M (lshiftrt:N <X> (const_int I))) if I is not 0. */ |
1628 | if (GET_CODE (op) == LSHIFTRT |
1629 | && CONST_INT_P (XEXP (op, 1)) |
1630 | && XEXP (op, 1) != const0_rtx) |
1631 | return simplify_gen_unary (code: ZERO_EXTEND, mode, op, GET_MODE (op)); |
1632 | |
1633 | /* (sign_extend:M (truncate:N (lshiftrt:O <X> (const_int I)))) where |
1634 | I is GET_MODE_PRECISION(O) - GET_MODE_PRECISION(N), simplifies to |
1635 | (ashiftrt:M <X> (const_int I)) if modes M and O are the same, and |
1636 | (truncate:M (ashiftrt:O <X> (const_int I))) if M is narrower than |
1637 | O, and (sign_extend:M (ashiftrt:O <X> (const_int I))) if M is |
1638 | wider than O. */ |
1639 | if (GET_CODE (op) == TRUNCATE |
1640 | && GET_CODE (XEXP (op, 0)) == LSHIFTRT |
1641 | && CONST_INT_P (XEXP (XEXP (op, 0), 1))) |
1642 | { |
1643 | scalar_int_mode m_mode, n_mode, o_mode; |
1644 | rtx old_shift = XEXP (op, 0); |
1645 | if (is_a <scalar_int_mode> (m: mode, result: &m_mode) |
1646 | && is_a <scalar_int_mode> (GET_MODE (op), result: &n_mode) |
1647 | && is_a <scalar_int_mode> (GET_MODE (old_shift), result: &o_mode) |
1648 | && GET_MODE_PRECISION (mode: o_mode) - GET_MODE_PRECISION (mode: n_mode) |
1649 | == INTVAL (XEXP (old_shift, 1))) |
1650 | { |
1651 | rtx new_shift = simplify_gen_binary (code: ASHIFTRT, |
1652 | GET_MODE (old_shift), |
1653 | XEXP (old_shift, 0), |
1654 | XEXP (old_shift, 1)); |
1655 | if (GET_MODE_PRECISION (mode: m_mode) > GET_MODE_PRECISION (mode: o_mode)) |
1656 | return simplify_gen_unary (code: SIGN_EXTEND, mode, op: new_shift, |
1657 | GET_MODE (new_shift)); |
1658 | if (mode != GET_MODE (new_shift)) |
1659 | return simplify_gen_unary (code: TRUNCATE, mode, op: new_shift, |
1660 | GET_MODE (new_shift)); |
1661 | return new_shift; |
1662 | } |
1663 | } |
1664 | |
1665 | /* We can canonicalize SIGN_EXTEND (op) as ZERO_EXTEND (op) when |
1666 | we know the sign bit of OP must be clear. */ |
1667 | if (val_signbit_known_clear_p (GET_MODE (op), |
1668 | val: nonzero_bits (op, GET_MODE (op)))) |
1669 | return simplify_gen_unary (code: ZERO_EXTEND, mode, op, GET_MODE (op)); |
1670 | |
1671 | /* (sign_extend:DI (subreg:SI (ctz:DI ...))) is (ctz:DI ...). */ |
1672 | if (GET_CODE (op) == SUBREG |
1673 | && subreg_lowpart_p (op) |
1674 | && GET_MODE (SUBREG_REG (op)) == mode |
1675 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
1676 | && is_a <scalar_int_mode> (GET_MODE (op), result: &op_mode) |
1677 | && GET_MODE_PRECISION (mode: int_mode) <= HOST_BITS_PER_WIDE_INT |
1678 | && GET_MODE_PRECISION (mode: op_mode) < GET_MODE_PRECISION (mode: int_mode) |
1679 | && (nonzero_bits (SUBREG_REG (op), mode) |
1680 | & ~(GET_MODE_MASK (op_mode) >> 1)) == 0) |
1681 | return SUBREG_REG (op); |
1682 | |
1683 | #if defined(POINTERS_EXTEND_UNSIGNED) |
1684 | /* As we do not know which address space the pointer is referring to, |
1685 | we can do this only if the target does not support different pointer |
1686 | or address modes depending on the address space. */ |
1687 | if (target_default_pointer_address_modes_p () |
1688 | && ! POINTERS_EXTEND_UNSIGNED |
1689 | && mode == Pmode && GET_MODE (op) == ptr_mode |
1690 | && (CONSTANT_P (op) |
1691 | || (GET_CODE (op) == SUBREG |
1692 | && REG_P (SUBREG_REG (op)) |
1693 | && REG_POINTER (SUBREG_REG (op)) |
1694 | && GET_MODE (SUBREG_REG (op)) == Pmode)) |
1695 | && !targetm.have_ptr_extend ()) |
1696 | { |
1697 | temp |
1698 | = convert_memory_address_addr_space_1 (Pmode, op, |
1699 | ADDR_SPACE_GENERIC, false, |
1700 | true); |
1701 | if (temp) |
1702 | return temp; |
1703 | } |
1704 | #endif |
1705 | break; |
1706 | |
1707 | case ZERO_EXTEND: |
1708 | /* Check for useless extension. */ |
1709 | if (GET_MODE (op) == mode) |
1710 | return op; |
1711 | |
1712 | /* Check for a zero extension of a subreg of a promoted |
1713 | variable, where the promotion is zero-extended, and the |
1714 | target mode is the same as the variable's promotion. */ |
1715 | if (GET_CODE (op) == SUBREG |
1716 | && SUBREG_PROMOTED_VAR_P (op) |
1717 | && SUBREG_PROMOTED_UNSIGNED_P (op)) |
1718 | { |
1719 | rtx subreg = SUBREG_REG (op); |
1720 | machine_mode subreg_mode = GET_MODE (subreg); |
1721 | if (!paradoxical_subreg_p (outermode: mode, innermode: subreg_mode)) |
1722 | { |
1723 | temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg); |
1724 | if (temp) |
1725 | { |
1726 | /* Preserve SUBREG_PROMOTED_VAR_P. */ |
1727 | if (partial_subreg_p (x: temp)) |
1728 | { |
1729 | SUBREG_PROMOTED_VAR_P (temp) = 1; |
1730 | SUBREG_PROMOTED_SET (temp, SRP_UNSIGNED); |
1731 | } |
1732 | return temp; |
1733 | } |
1734 | } |
1735 | else |
1736 | /* Zero-extending a zero-extended subreg. */ |
1737 | return simplify_gen_unary (code: ZERO_EXTEND, mode, |
1738 | op: subreg, op_mode: subreg_mode); |
1739 | } |
1740 | |
1741 | /* Extending a widening multiplication should be canonicalized to |
1742 | a wider widening multiplication. */ |
1743 | if (GET_CODE (op) == MULT) |
1744 | { |
1745 | rtx lhs = XEXP (op, 0); |
1746 | rtx rhs = XEXP (op, 1); |
1747 | enum rtx_code lcode = GET_CODE (lhs); |
1748 | enum rtx_code rcode = GET_CODE (rhs); |
1749 | |
1750 | /* Widening multiplies usually extend both operands, but sometimes |
1751 | they use a shift to extract a portion of a register. */ |
1752 | if ((lcode == ZERO_EXTEND |
1753 | || (lcode == LSHIFTRT && CONST_INT_P (XEXP (lhs, 1)))) |
1754 | && (rcode == ZERO_EXTEND |
1755 | || (rcode == LSHIFTRT && CONST_INT_P (XEXP (rhs, 1))))) |
1756 | { |
1757 | machine_mode lmode = GET_MODE (lhs); |
1758 | machine_mode rmode = GET_MODE (rhs); |
1759 | int bits; |
1760 | |
1761 | if (lcode == LSHIFTRT) |
1762 | /* Number of bits not shifted off the end. */ |
1763 | bits = (GET_MODE_UNIT_PRECISION (lmode) |
1764 | - INTVAL (XEXP (lhs, 1))); |
1765 | else /* lcode == ZERO_EXTEND */ |
1766 | /* Size of inner mode. */ |
1767 | bits = GET_MODE_UNIT_PRECISION (GET_MODE (XEXP (lhs, 0))); |
1768 | |
1769 | if (rcode == LSHIFTRT) |
1770 | bits += (GET_MODE_UNIT_PRECISION (rmode) |
1771 | - INTVAL (XEXP (rhs, 1))); |
1772 | else /* rcode == ZERO_EXTEND */ |
1773 | bits += GET_MODE_UNIT_PRECISION (GET_MODE (XEXP (rhs, 0))); |
1774 | |
1775 | /* We can only widen multiplies if the result is mathematiclly |
1776 | equivalent. I.e. if overflow was impossible. */ |
1777 | if (bits <= GET_MODE_UNIT_PRECISION (GET_MODE (op))) |
1778 | return simplify_gen_binary |
1779 | (code: MULT, mode, |
1780 | op0: simplify_gen_unary (code: ZERO_EXTEND, mode, op: lhs, op_mode: lmode), |
1781 | op1: simplify_gen_unary (code: ZERO_EXTEND, mode, op: rhs, op_mode: rmode)); |
1782 | } |
1783 | } |
1784 | |
1785 | /* (zero_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>). */ |
1786 | if (GET_CODE (op) == ZERO_EXTEND) |
1787 | return simplify_gen_unary (code: ZERO_EXTEND, mode, XEXP (op, 0), |
1788 | GET_MODE (XEXP (op, 0))); |
1789 | |
1790 | /* (zero_extend:M (lshiftrt:N (ashift <X> (const_int I)) (const_int I))) |
1791 | is (zero_extend:M (subreg:O <X>)) if there is mode with |
1792 | GET_MODE_PRECISION (N) - I bits. */ |
1793 | if (GET_CODE (op) == LSHIFTRT |
1794 | && GET_CODE (XEXP (op, 0)) == ASHIFT |
1795 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
1796 | && CONST_INT_P (XEXP (op, 1)) |
1797 | && XEXP (XEXP (op, 0), 1) == XEXP (op, 1) |
1798 | && (op_mode = as_a <scalar_int_mode> (GET_MODE (op)), |
1799 | GET_MODE_PRECISION (mode: op_mode) > INTVAL (XEXP (op, 1)))) |
1800 | { |
1801 | scalar_int_mode tmode; |
1802 | if (int_mode_for_size (size: GET_MODE_PRECISION (mode: op_mode) |
1803 | - INTVAL (XEXP (op, 1)), limit: 1).exists (mode: &tmode)) |
1804 | { |
1805 | rtx inner = |
1806 | rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); |
1807 | if (inner) |
1808 | return simplify_gen_unary (code: ZERO_EXTEND, mode: int_mode, |
1809 | op: inner, op_mode: tmode); |
1810 | } |
1811 | } |
1812 | |
1813 | /* (zero_extend:M (subreg:N <X:O>)) is <X:O> (for M == O) or |
1814 | (zero_extend:M <X:O>), if X doesn't have any non-zero bits outside |
1815 | of mode N. E.g. |
1816 | (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)) is |
1817 | (and:SI (reg:SI) (const_int 63)). */ |
1818 | if (partial_subreg_p (x: op) |
1819 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
1820 | && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), result: &op0_mode) |
1821 | && GET_MODE_PRECISION (mode: op0_mode) <= HOST_BITS_PER_WIDE_INT |
1822 | && GET_MODE_PRECISION (mode: int_mode) >= GET_MODE_PRECISION (mode: op0_mode) |
1823 | && subreg_lowpart_p (op) |
1824 | && (nonzero_bits (SUBREG_REG (op), op0_mode) |
1825 | & ~GET_MODE_MASK (GET_MODE (op))) == 0) |
1826 | { |
1827 | if (GET_MODE_PRECISION (mode: int_mode) == GET_MODE_PRECISION (mode: op0_mode)) |
1828 | return SUBREG_REG (op); |
1829 | return simplify_gen_unary (code: ZERO_EXTEND, mode: int_mode, SUBREG_REG (op), |
1830 | op_mode: op0_mode); |
1831 | } |
1832 | |
1833 | /* (zero_extend:DI (subreg:SI (ctz:DI ...))) is (ctz:DI ...). */ |
1834 | if (GET_CODE (op) == SUBREG |
1835 | && subreg_lowpart_p (op) |
1836 | && GET_MODE (SUBREG_REG (op)) == mode |
1837 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
1838 | && is_a <scalar_int_mode> (GET_MODE (op), result: &op_mode) |
1839 | && GET_MODE_PRECISION (mode: int_mode) <= HOST_BITS_PER_WIDE_INT |
1840 | && GET_MODE_PRECISION (mode: op_mode) < GET_MODE_PRECISION (mode: int_mode) |
1841 | && (nonzero_bits (SUBREG_REG (op), mode) |
1842 | & ~GET_MODE_MASK (op_mode)) == 0) |
1843 | return SUBREG_REG (op); |
1844 | |
1845 | #if defined(POINTERS_EXTEND_UNSIGNED) |
1846 | /* As we do not know which address space the pointer is referring to, |
1847 | we can do this only if the target does not support different pointer |
1848 | or address modes depending on the address space. */ |
1849 | if (target_default_pointer_address_modes_p () |
1850 | && POINTERS_EXTEND_UNSIGNED > 0 |
1851 | && mode == Pmode && GET_MODE (op) == ptr_mode |
1852 | && (CONSTANT_P (op) |
1853 | || (GET_CODE (op) == SUBREG |
1854 | && REG_P (SUBREG_REG (op)) |
1855 | && REG_POINTER (SUBREG_REG (op)) |
1856 | && GET_MODE (SUBREG_REG (op)) == Pmode)) |
1857 | && !targetm.have_ptr_extend ()) |
1858 | { |
1859 | temp |
1860 | = convert_memory_address_addr_space_1 (Pmode, op, |
1861 | ADDR_SPACE_GENERIC, false, |
1862 | true); |
1863 | if (temp) |
1864 | return temp; |
1865 | } |
1866 | #endif |
1867 | break; |
1868 | |
1869 | default: |
1870 | break; |
1871 | } |
1872 | |
1873 | if (VECTOR_MODE_P (mode) |
1874 | && vec_duplicate_p (x: op, elt: &elt) |
1875 | && code != VEC_DUPLICATE) |
1876 | { |
1877 | if (code == SIGN_EXTEND || code == ZERO_EXTEND) |
1878 | /* Enforce a canonical order of VEC_DUPLICATE wrt other unary |
1879 | operations by promoting VEC_DUPLICATE to the root of the expression |
1880 | (as far as possible). */ |
1881 | temp = simplify_gen_unary (code, GET_MODE_INNER (mode), |
1882 | op: elt, GET_MODE_INNER (GET_MODE (op))); |
1883 | else |
1884 | /* Try applying the operator to ELT and see if that simplifies. |
1885 | We can duplicate the result if so. |
1886 | |
1887 | The reason we traditionally haven't used simplify_gen_unary |
1888 | for these codes is that it didn't necessarily seem to be a |
1889 | win to convert things like: |
1890 | |
1891 | (neg:V (vec_duplicate:V (reg:S R))) |
1892 | |
1893 | to: |
1894 | |
1895 | (vec_duplicate:V (neg:S (reg:S R))) |
1896 | |
1897 | The first might be done entirely in vector registers while the |
1898 | second might need a move between register files. |
1899 | |
1900 | However, there also cases where promoting the vec_duplicate is |
1901 | more efficient, and there is definite value in having a canonical |
1902 | form when matching instruction patterns. We should consider |
1903 | extending the simplify_gen_unary code above to more cases. */ |
1904 | temp = simplify_unary_operation (code, GET_MODE_INNER (mode), |
1905 | op: elt, GET_MODE_INNER (GET_MODE (op))); |
1906 | if (temp) |
1907 | return gen_vec_duplicate (mode, temp); |
1908 | } |
1909 | |
1910 | return 0; |
1911 | } |
1912 | |
1913 | /* Try to compute the value of a unary operation CODE whose output mode is to |
1914 | be MODE with input operand OP whose mode was originally OP_MODE. |
1915 | Return zero if the value cannot be computed. */ |
1916 | rtx |
1917 | simplify_const_unary_operation (enum rtx_code code, machine_mode mode, |
1918 | rtx op, machine_mode op_mode) |
1919 | { |
1920 | scalar_int_mode result_mode; |
1921 | |
1922 | if (code == VEC_DUPLICATE) |
1923 | { |
1924 | gcc_assert (VECTOR_MODE_P (mode)); |
1925 | if (GET_MODE (op) != VOIDmode) |
1926 | { |
1927 | if (!VECTOR_MODE_P (GET_MODE (op))) |
1928 | gcc_assert (GET_MODE_INNER (mode) == GET_MODE (op)); |
1929 | else |
1930 | gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER |
1931 | (GET_MODE (op))); |
1932 | } |
1933 | if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op)) |
1934 | return gen_const_vec_duplicate (mode, op); |
1935 | if (GET_CODE (op) == CONST_VECTOR |
1936 | && (CONST_VECTOR_DUPLICATE_P (op) |
1937 | || CONST_VECTOR_NUNITS (op).is_constant ())) |
1938 | { |
1939 | unsigned int npatterns = (CONST_VECTOR_DUPLICATE_P (op) |
1940 | ? CONST_VECTOR_NPATTERNS (op) |
1941 | : CONST_VECTOR_NUNITS (op).to_constant ()); |
1942 | gcc_assert (multiple_p (GET_MODE_NUNITS (mode), npatterns)); |
1943 | rtx_vector_builder builder (mode, npatterns, 1); |
1944 | for (unsigned i = 0; i < npatterns; i++) |
1945 | builder.quick_push (CONST_VECTOR_ELT (op, i)); |
1946 | return builder.build (); |
1947 | } |
1948 | } |
1949 | |
1950 | if (VECTOR_MODE_P (mode) |
1951 | && GET_CODE (op) == CONST_VECTOR |
1952 | && known_eq (GET_MODE_NUNITS (mode), CONST_VECTOR_NUNITS (op))) |
1953 | { |
1954 | gcc_assert (GET_MODE (op) == op_mode); |
1955 | |
1956 | rtx_vector_builder builder; |
1957 | if (!builder.new_unary_operation (shape: mode, vec: op, allow_stepped_p: false)) |
1958 | return 0; |
1959 | |
1960 | unsigned int count = builder.encoded_nelts (); |
1961 | for (unsigned int i = 0; i < count; i++) |
1962 | { |
1963 | rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode), |
1964 | CONST_VECTOR_ELT (op, i), |
1965 | GET_MODE_INNER (op_mode)); |
1966 | if (!x || !valid_for_const_vector_p (mode, x)) |
1967 | return 0; |
1968 | builder.quick_push (obj: x); |
1969 | } |
1970 | return builder.build (); |
1971 | } |
1972 | |
1973 | /* The order of these tests is critical so that, for example, we don't |
1974 | check the wrong mode (input vs. output) for a conversion operation, |
1975 | such as FIX. At some point, this should be simplified. */ |
1976 | |
1977 | if (code == FLOAT && CONST_SCALAR_INT_P (op)) |
1978 | { |
1979 | REAL_VALUE_TYPE d; |
1980 | |
1981 | if (op_mode == VOIDmode) |
1982 | { |
1983 | /* CONST_INT have VOIDmode as the mode. We assume that all |
1984 | the bits of the constant are significant, though, this is |
1985 | a dangerous assumption as many times CONST_INTs are |
1986 | created and used with garbage in the bits outside of the |
1987 | precision of the implied mode of the const_int. */ |
1988 | op_mode = MAX_MODE_INT; |
1989 | } |
1990 | |
1991 | real_from_integer (&d, mode, rtx_mode_t (op, op_mode), SIGNED); |
1992 | |
1993 | /* Avoid the folding if flag_signaling_nans is on and |
1994 | operand is a signaling NaN. */ |
1995 | if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) |
1996 | return 0; |
1997 | |
1998 | d = real_value_truncate (mode, d); |
1999 | |
2000 | /* Avoid the folding if flag_rounding_math is on and the |
2001 | conversion is not exact. */ |
2002 | if (HONOR_SIGN_DEPENDENT_ROUNDING (mode)) |
2003 | { |
2004 | bool fail = false; |
2005 | wide_int w = real_to_integer (&d, &fail, |
2006 | GET_MODE_PRECISION |
2007 | (mode: as_a <scalar_int_mode> (m: op_mode))); |
2008 | if (fail || wi::ne_p (x: w, y: wide_int (rtx_mode_t (op, op_mode)))) |
2009 | return 0; |
2010 | } |
2011 | |
2012 | return const_double_from_real_value (d, mode); |
2013 | } |
2014 | else if (code == UNSIGNED_FLOAT && CONST_SCALAR_INT_P (op)) |
2015 | { |
2016 | REAL_VALUE_TYPE d; |
2017 | |
2018 | if (op_mode == VOIDmode) |
2019 | { |
2020 | /* CONST_INT have VOIDmode as the mode. We assume that all |
2021 | the bits of the constant are significant, though, this is |
2022 | a dangerous assumption as many times CONST_INTs are |
2023 | created and used with garbage in the bits outside of the |
2024 | precision of the implied mode of the const_int. */ |
2025 | op_mode = MAX_MODE_INT; |
2026 | } |
2027 | |
2028 | real_from_integer (&d, mode, rtx_mode_t (op, op_mode), UNSIGNED); |
2029 | |
2030 | /* Avoid the folding if flag_signaling_nans is on and |
2031 | operand is a signaling NaN. */ |
2032 | if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) |
2033 | return 0; |
2034 | |
2035 | d = real_value_truncate (mode, d); |
2036 | |
2037 | /* Avoid the folding if flag_rounding_math is on and the |
2038 | conversion is not exact. */ |
2039 | if (HONOR_SIGN_DEPENDENT_ROUNDING (mode)) |
2040 | { |
2041 | bool fail = false; |
2042 | wide_int w = real_to_integer (&d, &fail, |
2043 | GET_MODE_PRECISION |
2044 | (mode: as_a <scalar_int_mode> (m: op_mode))); |
2045 | if (fail || wi::ne_p (x: w, y: wide_int (rtx_mode_t (op, op_mode)))) |
2046 | return 0; |
2047 | } |
2048 | |
2049 | return const_double_from_real_value (d, mode); |
2050 | } |
2051 | |
2052 | if (CONST_SCALAR_INT_P (op) && is_a <scalar_int_mode> (m: mode, result: &result_mode)) |
2053 | { |
2054 | unsigned int width = GET_MODE_PRECISION (mode: result_mode); |
2055 | if (width > MAX_BITSIZE_MODE_ANY_INT) |
2056 | return 0; |
2057 | |
2058 | wide_int result; |
2059 | scalar_int_mode imode = (op_mode == VOIDmode |
2060 | ? result_mode |
2061 | : as_a <scalar_int_mode> (m: op_mode)); |
2062 | rtx_mode_t op0 = rtx_mode_t (op, imode); |
2063 | int int_value; |
2064 | |
2065 | #if TARGET_SUPPORTS_WIDE_INT == 0 |
2066 | /* This assert keeps the simplification from producing a result |
2067 | that cannot be represented in a CONST_DOUBLE but a lot of |
2068 | upstream callers expect that this function never fails to |
2069 | simplify something and so you if you added this to the test |
2070 | above the code would die later anyway. If this assert |
2071 | happens, you just need to make the port support wide int. */ |
2072 | gcc_assert (width <= HOST_BITS_PER_DOUBLE_INT); |
2073 | #endif |
2074 | |
2075 | switch (code) |
2076 | { |
2077 | case NOT: |
2078 | result = wi::bit_not (x: op0); |
2079 | break; |
2080 | |
2081 | case NEG: |
2082 | result = wi::neg (x: op0); |
2083 | break; |
2084 | |
2085 | case ABS: |
2086 | result = wi::abs (x: op0); |
2087 | break; |
2088 | |
2089 | case FFS: |
2090 | result = wi::shwi (val: wi::ffs (op0), mode: result_mode); |
2091 | break; |
2092 | |
2093 | case CLZ: |
2094 | if (wi::ne_p (x: op0, y: 0)) |
2095 | int_value = wi::clz (op0); |
2096 | else if (! CLZ_DEFINED_VALUE_AT_ZERO (imode, int_value)) |
2097 | return NULL_RTX; |
2098 | result = wi::shwi (val: int_value, mode: result_mode); |
2099 | break; |
2100 | |
2101 | case CLRSB: |
2102 | result = wi::shwi (val: wi::clrsb (op0), mode: result_mode); |
2103 | break; |
2104 | |
2105 | case CTZ: |
2106 | if (wi::ne_p (x: op0, y: 0)) |
2107 | int_value = wi::ctz (op0); |
2108 | else if (! CTZ_DEFINED_VALUE_AT_ZERO (imode, int_value)) |
2109 | return NULL_RTX; |
2110 | result = wi::shwi (val: int_value, mode: result_mode); |
2111 | break; |
2112 | |
2113 | case POPCOUNT: |
2114 | result = wi::shwi (val: wi::popcount (op0), mode: result_mode); |
2115 | break; |
2116 | |
2117 | case PARITY: |
2118 | result = wi::shwi (val: wi::parity (x: op0), mode: result_mode); |
2119 | break; |
2120 | |
2121 | case BSWAP: |
2122 | result = wi::bswap (x: op0); |
2123 | break; |
2124 | |
2125 | case BITREVERSE: |
2126 | result = wi::bitreverse (x: op0); |
2127 | break; |
2128 | |
2129 | case TRUNCATE: |
2130 | case ZERO_EXTEND: |
2131 | result = wide_int::from (x: op0, precision: width, sgn: UNSIGNED); |
2132 | break; |
2133 | |
2134 | case US_TRUNCATE: |
2135 | case SS_TRUNCATE: |
2136 | { |
2137 | signop sgn = code == US_TRUNCATE ? UNSIGNED : SIGNED; |
2138 | wide_int nmax |
2139 | = wide_int::from (x: wi::max_value (width, sgn), |
2140 | precision: GET_MODE_PRECISION (mode: imode), sgn); |
2141 | wide_int nmin |
2142 | = wide_int::from (x: wi::min_value (width, sgn), |
2143 | precision: GET_MODE_PRECISION (mode: imode), sgn); |
2144 | result = wi::min (x: wi::max (x: op0, y: nmin, sgn), y: nmax, sgn); |
2145 | result = wide_int::from (x: result, precision: width, sgn); |
2146 | break; |
2147 | } |
2148 | case SIGN_EXTEND: |
2149 | result = wide_int::from (x: op0, precision: width, sgn: SIGNED); |
2150 | break; |
2151 | |
2152 | case SS_NEG: |
2153 | if (wi::only_sign_bit_p (op0)) |
2154 | result = wi::max_value (GET_MODE_PRECISION (mode: imode), SIGNED); |
2155 | else |
2156 | result = wi::neg (x: op0); |
2157 | break; |
2158 | |
2159 | case SS_ABS: |
2160 | if (wi::only_sign_bit_p (op0)) |
2161 | result = wi::max_value (GET_MODE_PRECISION (mode: imode), SIGNED); |
2162 | else |
2163 | result = wi::abs (x: op0); |
2164 | break; |
2165 | |
2166 | case SQRT: |
2167 | default: |
2168 | return 0; |
2169 | } |
2170 | |
2171 | return immed_wide_int_const (result, result_mode); |
2172 | } |
2173 | |
2174 | else if (CONST_DOUBLE_AS_FLOAT_P (op) |
2175 | && SCALAR_FLOAT_MODE_P (mode) |
2176 | && SCALAR_FLOAT_MODE_P (GET_MODE (op))) |
2177 | { |
2178 | REAL_VALUE_TYPE d = *CONST_DOUBLE_REAL_VALUE (op); |
2179 | switch (code) |
2180 | { |
2181 | case SQRT: |
2182 | return 0; |
2183 | case ABS: |
2184 | d = real_value_abs (&d); |
2185 | break; |
2186 | case NEG: |
2187 | d = real_value_negate (&d); |
2188 | break; |
2189 | case FLOAT_TRUNCATE: |
2190 | /* Don't perform the operation if flag_signaling_nans is on |
2191 | and the operand is a signaling NaN. */ |
2192 | if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) |
2193 | return NULL_RTX; |
2194 | /* Or if flag_rounding_math is on and the truncation is not |
2195 | exact. */ |
2196 | if (HONOR_SIGN_DEPENDENT_ROUNDING (mode) |
2197 | && !exact_real_truncate (mode, &d)) |
2198 | return NULL_RTX; |
2199 | d = real_value_truncate (mode, d); |
2200 | break; |
2201 | case FLOAT_EXTEND: |
2202 | /* Don't perform the operation if flag_signaling_nans is on |
2203 | and the operand is a signaling NaN. */ |
2204 | if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) |
2205 | return NULL_RTX; |
2206 | /* All this does is change the mode, unless changing |
2207 | mode class. */ |
2208 | if (GET_MODE_CLASS (mode) != GET_MODE_CLASS (GET_MODE (op))) |
2209 | real_convert (&d, mode, &d); |
2210 | break; |
2211 | case FIX: |
2212 | /* Don't perform the operation if flag_signaling_nans is on |
2213 | and the operand is a signaling NaN. */ |
2214 | if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) |
2215 | return NULL_RTX; |
2216 | real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); |
2217 | break; |
2218 | case NOT: |
2219 | { |
2220 | long tmp[4]; |
2221 | int i; |
2222 | |
2223 | real_to_target (tmp, &d, GET_MODE (op)); |
2224 | for (i = 0; i < 4; i++) |
2225 | tmp[i] = ~tmp[i]; |
2226 | real_from_target (&d, tmp, mode); |
2227 | break; |
2228 | } |
2229 | default: |
2230 | gcc_unreachable (); |
2231 | } |
2232 | return const_double_from_real_value (d, mode); |
2233 | } |
2234 | else if (CONST_DOUBLE_AS_FLOAT_P (op) |
2235 | && SCALAR_FLOAT_MODE_P (GET_MODE (op)) |
2236 | && is_int_mode (mode, int_mode: &result_mode)) |
2237 | { |
2238 | unsigned int width = GET_MODE_PRECISION (mode: result_mode); |
2239 | if (width > MAX_BITSIZE_MODE_ANY_INT) |
2240 | return 0; |
2241 | |
2242 | /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX |
2243 | operators are intentionally left unspecified (to ease implementation |
2244 | by target backends), for consistency, this routine implements the |
2245 | same semantics for constant folding as used by the middle-end. */ |
2246 | |
2247 | /* This was formerly used only for non-IEEE float. |
2248 | eggert@twinsun.com says it is safe for IEEE also. */ |
2249 | REAL_VALUE_TYPE t; |
2250 | const REAL_VALUE_TYPE *x = CONST_DOUBLE_REAL_VALUE (op); |
2251 | wide_int wmax, wmin; |
2252 | /* This is part of the abi to real_to_integer, but we check |
2253 | things before making this call. */ |
2254 | bool fail; |
2255 | |
2256 | switch (code) |
2257 | { |
2258 | case FIX: |
2259 | if (REAL_VALUE_ISNAN (*x)) |
2260 | return const0_rtx; |
2261 | |
2262 | /* Test against the signed upper bound. */ |
2263 | wmax = wi::max_value (width, SIGNED); |
2264 | real_from_integer (&t, VOIDmode, wmax, SIGNED); |
2265 | if (real_less (&t, x)) |
2266 | return immed_wide_int_const (wmax, mode); |
2267 | |
2268 | /* Test against the signed lower bound. */ |
2269 | wmin = wi::min_value (width, SIGNED); |
2270 | real_from_integer (&t, VOIDmode, wmin, SIGNED); |
2271 | if (real_less (x, &t)) |
2272 | return immed_wide_int_const (wmin, mode); |
2273 | |
2274 | return immed_wide_int_const (real_to_integer (x, &fail, width), |
2275 | mode); |
2276 | |
2277 | case UNSIGNED_FIX: |
2278 | if (REAL_VALUE_ISNAN (*x) || REAL_VALUE_NEGATIVE (*x)) |
2279 | return const0_rtx; |
2280 | |
2281 | /* Test against the unsigned upper bound. */ |
2282 | wmax = wi::max_value (width, UNSIGNED); |
2283 | real_from_integer (&t, VOIDmode, wmax, UNSIGNED); |
2284 | if (real_less (&t, x)) |
2285 | return immed_wide_int_const (wmax, mode); |
2286 | |
2287 | return immed_wide_int_const (real_to_integer (x, &fail, width), |
2288 | mode); |
2289 | |
2290 | default: |
2291 | gcc_unreachable (); |
2292 | } |
2293 | } |
2294 | |
2295 | /* Handle polynomial integers. */ |
2296 | else if (CONST_POLY_INT_P (op)) |
2297 | { |
2298 | poly_wide_int result; |
2299 | switch (code) |
2300 | { |
2301 | case NEG: |
2302 | result = -const_poly_int_value (x: op); |
2303 | break; |
2304 | |
2305 | case NOT: |
2306 | result = ~const_poly_int_value (x: op); |
2307 | break; |
2308 | |
2309 | default: |
2310 | return NULL_RTX; |
2311 | } |
2312 | return immed_wide_int_const (result, mode); |
2313 | } |
2314 | |
2315 | return NULL_RTX; |
2316 | } |
2317 | |
2318 | /* Subroutine of simplify_binary_operation to simplify a binary operation |
2319 | CODE that can commute with byte swapping, with result mode MODE and |
2320 | operating on OP0 and OP1. CODE is currently one of AND, IOR or XOR. |
2321 | Return zero if no simplification or canonicalization is possible. */ |
2322 | |
2323 | rtx |
2324 | simplify_context::simplify_byte_swapping_operation (rtx_code code, |
2325 | machine_mode mode, |
2326 | rtx op0, rtx op1) |
2327 | { |
2328 | rtx tem; |
2329 | |
2330 | /* (op (bswap x) C1)) -> (bswap (op x C2)) with C2 swapped. */ |
2331 | if (GET_CODE (op0) == BSWAP && CONST_SCALAR_INT_P (op1)) |
2332 | { |
2333 | tem = simplify_gen_binary (code, mode, XEXP (op0, 0), |
2334 | op1: simplify_gen_unary (code: BSWAP, mode, op: op1, op_mode: mode)); |
2335 | return simplify_gen_unary (code: BSWAP, mode, op: tem, op_mode: mode); |
2336 | } |
2337 | |
2338 | /* (op (bswap x) (bswap y)) -> (bswap (op x y)). */ |
2339 | if (GET_CODE (op0) == BSWAP && GET_CODE (op1) == BSWAP) |
2340 | { |
2341 | tem = simplify_gen_binary (code, mode, XEXP (op0, 0), XEXP (op1, 0)); |
2342 | return simplify_gen_unary (code: BSWAP, mode, op: tem, op_mode: mode); |
2343 | } |
2344 | |
2345 | return NULL_RTX; |
2346 | } |
2347 | |
2348 | /* Subroutine of simplify_binary_operation to simplify a commutative, |
2349 | associative binary operation CODE with result mode MODE, operating |
2350 | on OP0 and OP1. CODE is currently one of PLUS, MULT, AND, IOR, XOR, |
2351 | SMIN, SMAX, UMIN or UMAX. Return zero if no simplification or |
2352 | canonicalization is possible. */ |
2353 | |
2354 | rtx |
2355 | simplify_context::simplify_associative_operation (rtx_code code, |
2356 | machine_mode mode, |
2357 | rtx op0, rtx op1) |
2358 | { |
2359 | rtx tem; |
2360 | |
2361 | /* Normally expressions simplified by simplify-rtx.cc are combined |
2362 | at most from a few machine instructions and therefore the |
2363 | expressions should be fairly small. During var-tracking |
2364 | we can see arbitrarily large expressions though and reassociating |
2365 | those can be quadratic, so punt after encountering max_assoc_count |
2366 | simplify_associative_operation calls during outermost simplify_* |
2367 | call. */ |
2368 | if (++assoc_count >= max_assoc_count) |
2369 | return NULL_RTX; |
2370 | |
2371 | /* Linearize the operator to the left. */ |
2372 | if (GET_CODE (op1) == code) |
2373 | { |
2374 | /* "(a op b) op (c op d)" becomes "((a op b) op c) op d)". */ |
2375 | if (GET_CODE (op0) == code) |
2376 | { |
2377 | tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0)); |
2378 | return simplify_gen_binary (code, mode, op0: tem, XEXP (op1, 1)); |
2379 | } |
2380 | |
2381 | /* "a op (b op c)" becomes "(b op c) op a". */ |
2382 | if (! swap_commutative_operands_p (op1, op0)) |
2383 | return simplify_gen_binary (code, mode, op0: op1, op1: op0); |
2384 | |
2385 | std::swap (a&: op0, b&: op1); |
2386 | } |
2387 | |
2388 | if (GET_CODE (op0) == code) |
2389 | { |
2390 | /* Canonicalize "(x op c) op y" as "(x op y) op c". */ |
2391 | if (swap_commutative_operands_p (XEXP (op0, 1), op1)) |
2392 | { |
2393 | tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1); |
2394 | return simplify_gen_binary (code, mode, op0: tem, XEXP (op0, 1)); |
2395 | } |
2396 | |
2397 | /* Attempt to simplify "(a op b) op c" as "a op (b op c)". */ |
2398 | tem = simplify_binary_operation (code, mode, XEXP (op0, 1), op1); |
2399 | if (tem != 0) |
2400 | return simplify_gen_binary (code, mode, XEXP (op0, 0), op1: tem); |
2401 | |
2402 | /* Attempt to simplify "(a op b) op c" as "(a op c) op b". */ |
2403 | tem = simplify_binary_operation (code, mode, XEXP (op0, 0), op1); |
2404 | if (tem != 0) |
2405 | return simplify_gen_binary (code, mode, op0: tem, XEXP (op0, 1)); |
2406 | } |
2407 | |
2408 | return 0; |
2409 | } |
2410 | |
2411 | /* Return a mask describing the COMPARISON. */ |
2412 | static int |
2413 | comparison_to_mask (enum rtx_code comparison) |
2414 | { |
2415 | switch (comparison) |
2416 | { |
2417 | case LT: |
2418 | return 8; |
2419 | case GT: |
2420 | return 4; |
2421 | case EQ: |
2422 | return 2; |
2423 | case UNORDERED: |
2424 | return 1; |
2425 | |
2426 | case LTGT: |
2427 | return 12; |
2428 | case LE: |
2429 | return 10; |
2430 | case GE: |
2431 | return 6; |
2432 | case UNLT: |
2433 | return 9; |
2434 | case UNGT: |
2435 | return 5; |
2436 | case UNEQ: |
2437 | return 3; |
2438 | |
2439 | case ORDERED: |
2440 | return 14; |
2441 | case NE: |
2442 | return 13; |
2443 | case UNLE: |
2444 | return 11; |
2445 | case UNGE: |
2446 | return 7; |
2447 | |
2448 | default: |
2449 | gcc_unreachable (); |
2450 | } |
2451 | } |
2452 | |
2453 | /* Return a comparison corresponding to the MASK. */ |
2454 | static enum rtx_code |
2455 | mask_to_comparison (int mask) |
2456 | { |
2457 | switch (mask) |
2458 | { |
2459 | case 8: |
2460 | return LT; |
2461 | case 4: |
2462 | return GT; |
2463 | case 2: |
2464 | return EQ; |
2465 | case 1: |
2466 | return UNORDERED; |
2467 | |
2468 | case 12: |
2469 | return LTGT; |
2470 | case 10: |
2471 | return LE; |
2472 | case 6: |
2473 | return GE; |
2474 | case 9: |
2475 | return UNLT; |
2476 | case 5: |
2477 | return UNGT; |
2478 | case 3: |
2479 | return UNEQ; |
2480 | |
2481 | case 14: |
2482 | return ORDERED; |
2483 | case 13: |
2484 | return NE; |
2485 | case 11: |
2486 | return UNLE; |
2487 | case 7: |
2488 | return UNGE; |
2489 | |
2490 | default: |
2491 | gcc_unreachable (); |
2492 | } |
2493 | } |
2494 | |
2495 | /* Return true if CODE is valid for comparisons of mode MODE, false |
2496 | otherwise. |
2497 | |
2498 | It is always safe to return false, even if the code was valid for the |
2499 | given mode as that will merely suppress optimizations. */ |
2500 | |
2501 | static bool |
2502 | comparison_code_valid_for_mode (enum rtx_code code, enum machine_mode mode) |
2503 | { |
2504 | switch (code) |
2505 | { |
2506 | /* These are valid for integral, floating and vector modes. */ |
2507 | case NE: |
2508 | case EQ: |
2509 | case GE: |
2510 | case GT: |
2511 | case LE: |
2512 | case LT: |
2513 | return (INTEGRAL_MODE_P (mode) |
2514 | || FLOAT_MODE_P (mode) |
2515 | || VECTOR_MODE_P (mode)); |
2516 | |
2517 | /* These are valid for floating point modes. */ |
2518 | case LTGT: |
2519 | case UNORDERED: |
2520 | case ORDERED: |
2521 | case UNEQ: |
2522 | case UNGE: |
2523 | case UNGT: |
2524 | case UNLE: |
2525 | case UNLT: |
2526 | return FLOAT_MODE_P (mode); |
2527 | |
2528 | /* These are filtered out in simplify_logical_operation, but |
2529 | we check for them too as a matter of safety. They are valid |
2530 | for integral and vector modes. */ |
2531 | case GEU: |
2532 | case GTU: |
2533 | case LEU: |
2534 | case LTU: |
2535 | return INTEGRAL_MODE_P (mode) || VECTOR_MODE_P (mode); |
2536 | |
2537 | default: |
2538 | gcc_unreachable (); |
2539 | } |
2540 | } |
2541 | |
2542 | /* Canonicalize RES, a scalar const0_rtx/const_true_rtx to the right |
2543 | false/true value of comparison with MODE where comparison operands |
2544 | have CMP_MODE. */ |
2545 | |
2546 | static rtx |
2547 | relational_result (machine_mode mode, machine_mode cmp_mode, rtx res) |
2548 | { |
2549 | if (SCALAR_FLOAT_MODE_P (mode)) |
2550 | { |
2551 | if (res == const0_rtx) |
2552 | return CONST0_RTX (mode); |
2553 | #ifdef FLOAT_STORE_FLAG_VALUE |
2554 | REAL_VALUE_TYPE val = FLOAT_STORE_FLAG_VALUE (mode); |
2555 | return const_double_from_real_value (val, mode); |
2556 | #else |
2557 | return NULL_RTX; |
2558 | #endif |
2559 | } |
2560 | if (VECTOR_MODE_P (mode)) |
2561 | { |
2562 | if (res == const0_rtx) |
2563 | return CONST0_RTX (mode); |
2564 | #ifdef VECTOR_STORE_FLAG_VALUE |
2565 | rtx val = VECTOR_STORE_FLAG_VALUE (mode); |
2566 | if (val == NULL_RTX) |
2567 | return NULL_RTX; |
2568 | if (val == const1_rtx) |
2569 | return CONST1_RTX (mode); |
2570 | |
2571 | return gen_const_vec_duplicate (mode, val); |
2572 | #else |
2573 | return NULL_RTX; |
2574 | #endif |
2575 | } |
2576 | /* For vector comparison with scalar int result, it is unknown |
2577 | if the target means here a comparison into an integral bitmask, |
2578 | or comparison where all comparisons true mean const_true_rtx |
2579 | whole result, or where any comparisons true mean const_true_rtx |
2580 | whole result. For const0_rtx all the cases are the same. */ |
2581 | if (VECTOR_MODE_P (cmp_mode) |
2582 | && SCALAR_INT_MODE_P (mode) |
2583 | && res == const_true_rtx) |
2584 | return NULL_RTX; |
2585 | |
2586 | return res; |
2587 | } |
2588 | |
2589 | /* Simplify a logical operation CODE with result mode MODE, operating on OP0 |
2590 | and OP1, which should be both relational operations. Return 0 if no such |
2591 | simplification is possible. */ |
2592 | rtx |
2593 | simplify_context::simplify_logical_relational_operation (rtx_code code, |
2594 | machine_mode mode, |
2595 | rtx op0, rtx op1) |
2596 | { |
2597 | /* We only handle IOR of two relational operations. */ |
2598 | if (code != IOR) |
2599 | return 0; |
2600 | |
2601 | if (!(COMPARISON_P (op0) && COMPARISON_P (op1))) |
2602 | return 0; |
2603 | |
2604 | if (!(rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) |
2605 | && rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1)))) |
2606 | return 0; |
2607 | |
2608 | enum rtx_code code0 = GET_CODE (op0); |
2609 | enum rtx_code code1 = GET_CODE (op1); |
2610 | |
2611 | /* We don't handle unsigned comparisons currently. */ |
2612 | if (code0 == LTU || code0 == GTU || code0 == LEU || code0 == GEU) |
2613 | return 0; |
2614 | if (code1 == LTU || code1 == GTU || code1 == LEU || code1 == GEU) |
2615 | return 0; |
2616 | |
2617 | int mask0 = comparison_to_mask (comparison: code0); |
2618 | int mask1 = comparison_to_mask (comparison: code1); |
2619 | |
2620 | int mask = mask0 | mask1; |
2621 | |
2622 | if (mask == 15) |
2623 | return relational_result (mode, GET_MODE (op0), res: const_true_rtx); |
2624 | |
2625 | code = mask_to_comparison (mask); |
2626 | |
2627 | /* Many comparison codes are only valid for certain mode classes. */ |
2628 | if (!comparison_code_valid_for_mode (code, mode)) |
2629 | return 0; |
2630 | |
2631 | op0 = XEXP (op1, 0); |
2632 | op1 = XEXP (op1, 1); |
2633 | |
2634 | return simplify_gen_relational (code, mode, VOIDmode, op0, op1); |
2635 | } |
2636 | |
2637 | /* Simplify a binary operation CODE with result mode MODE, operating on OP0 |
2638 | and OP1. Return 0 if no simplification is possible. |
2639 | |
2640 | Don't use this for relational operations such as EQ or LT. |
2641 | Use simplify_relational_operation instead. */ |
2642 | rtx |
2643 | simplify_context::simplify_binary_operation (rtx_code code, machine_mode mode, |
2644 | rtx op0, rtx op1) |
2645 | { |
2646 | rtx trueop0, trueop1; |
2647 | rtx tem; |
2648 | |
2649 | /* Relational operations don't work here. We must know the mode |
2650 | of the operands in order to do the comparison correctly. |
2651 | Assuming a full word can give incorrect results. |
2652 | Consider comparing 128 with -128 in QImode. */ |
2653 | gcc_assert (GET_RTX_CLASS (code) != RTX_COMPARE); |
2654 | gcc_assert (GET_RTX_CLASS (code) != RTX_COMM_COMPARE); |
2655 | |
2656 | /* Make sure the constant is second. */ |
2657 | if (GET_RTX_CLASS (code) == RTX_COMM_ARITH |
2658 | && swap_commutative_operands_p (op0, op1)) |
2659 | std::swap (a&: op0, b&: op1); |
2660 | |
2661 | trueop0 = avoid_constant_pool_reference (x: op0); |
2662 | trueop1 = avoid_constant_pool_reference (x: op1); |
2663 | |
2664 | tem = simplify_const_binary_operation (code, mode, trueop0, trueop1); |
2665 | if (tem) |
2666 | return tem; |
2667 | tem = simplify_binary_operation_1 (code, mode, op0, op1, trueop0, trueop1); |
2668 | |
2669 | if (tem) |
2670 | return tem; |
2671 | |
2672 | /* If the above steps did not result in a simplification and op0 or op1 |
2673 | were constant pool references, use the referenced constants directly. */ |
2674 | if (trueop0 != op0 || trueop1 != op1) |
2675 | return simplify_gen_binary (code, mode, op0: trueop0, op1: trueop1); |
2676 | |
2677 | return NULL_RTX; |
2678 | } |
2679 | |
2680 | /* Subroutine of simplify_binary_operation_1 that looks for cases in |
2681 | which OP0 and OP1 are both vector series or vector duplicates |
2682 | (which are really just series with a step of 0). If so, try to |
2683 | form a new series by applying CODE to the bases and to the steps. |
2684 | Return null if no simplification is possible. |
2685 | |
2686 | MODE is the mode of the operation and is known to be a vector |
2687 | integer mode. */ |
2688 | |
2689 | rtx |
2690 | simplify_context::simplify_binary_operation_series (rtx_code code, |
2691 | machine_mode mode, |
2692 | rtx op0, rtx op1) |
2693 | { |
2694 | rtx base0, step0; |
2695 | if (vec_duplicate_p (x: op0, elt: &base0)) |
2696 | step0 = const0_rtx; |
2697 | else if (!vec_series_p (x: op0, base_out: &base0, step_out: &step0)) |
2698 | return NULL_RTX; |
2699 | |
2700 | rtx base1, step1; |
2701 | if (vec_duplicate_p (x: op1, elt: &base1)) |
2702 | step1 = const0_rtx; |
2703 | else if (!vec_series_p (x: op1, base_out: &base1, step_out: &step1)) |
2704 | return NULL_RTX; |
2705 | |
2706 | /* Only create a new series if we can simplify both parts. In other |
2707 | cases this isn't really a simplification, and it's not necessarily |
2708 | a win to replace a vector operation with a scalar operation. */ |
2709 | scalar_mode inner_mode = GET_MODE_INNER (mode); |
2710 | rtx new_base = simplify_binary_operation (code, mode: inner_mode, op0: base0, op1: base1); |
2711 | if (!new_base) |
2712 | return NULL_RTX; |
2713 | |
2714 | rtx new_step = simplify_binary_operation (code, mode: inner_mode, op0: step0, op1: step1); |
2715 | if (!new_step) |
2716 | return NULL_RTX; |
2717 | |
2718 | return gen_vec_series (mode, new_base, new_step); |
2719 | } |
2720 | |
2721 | /* Subroutine of simplify_binary_operation_1. Un-distribute a binary |
2722 | operation CODE with result mode MODE, operating on OP0 and OP1. |
2723 | e.g. simplify (xor (and A C) (and (B C)) to (and (xor (A B) C). |
2724 | Returns NULL_RTX if no simplification is possible. */ |
2725 | |
2726 | rtx |
2727 | simplify_context::simplify_distributive_operation (rtx_code code, |
2728 | machine_mode mode, |
2729 | rtx op0, rtx op1) |
2730 | { |
2731 | enum rtx_code op = GET_CODE (op0); |
2732 | gcc_assert (GET_CODE (op1) == op); |
2733 | |
2734 | if (rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1)) |
2735 | && ! side_effects_p (XEXP (op0, 1))) |
2736 | return simplify_gen_binary (code: op, mode, |
2737 | op0: simplify_gen_binary (code, mode, |
2738 | XEXP (op0, 0), |
2739 | XEXP (op1, 0)), |
2740 | XEXP (op0, 1)); |
2741 | |
2742 | if (GET_RTX_CLASS (op) == RTX_COMM_ARITH) |
2743 | { |
2744 | if (rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) |
2745 | && ! side_effects_p (XEXP (op0, 0))) |
2746 | return simplify_gen_binary (code: op, mode, |
2747 | op0: simplify_gen_binary (code, mode, |
2748 | XEXP (op0, 1), |
2749 | XEXP (op1, 1)), |
2750 | XEXP (op0, 0)); |
2751 | if (rtx_equal_p (XEXP (op0, 0), XEXP (op1, 1)) |
2752 | && ! side_effects_p (XEXP (op0, 0))) |
2753 | return simplify_gen_binary (code: op, mode, |
2754 | op0: simplify_gen_binary (code, mode, |
2755 | XEXP (op0, 1), |
2756 | XEXP (op1, 0)), |
2757 | XEXP (op0, 0)); |
2758 | if (rtx_equal_p (XEXP (op0, 1), XEXP (op1, 0)) |
2759 | && ! side_effects_p (XEXP (op0, 1))) |
2760 | return simplify_gen_binary (code: op, mode, |
2761 | op0: simplify_gen_binary (code, mode, |
2762 | XEXP (op0, 0), |
2763 | XEXP (op1, 1)), |
2764 | XEXP (op0, 1)); |
2765 | } |
2766 | |
2767 | return NULL_RTX; |
2768 | } |
2769 | |
2770 | /* Return TRUE if a rotate in mode MODE with a constant count in OP1 |
2771 | should be reversed. |
2772 | |
2773 | If the rotate should not be reversed, return FALSE. |
2774 | |
2775 | LEFT indicates if this is a rotate left or a rotate right. */ |
2776 | |
2777 | bool |
2778 | reverse_rotate_by_imm_p (machine_mode mode, unsigned int left, rtx op1) |
2779 | { |
2780 | if (!CONST_INT_P (op1)) |
2781 | return false; |
2782 | |
2783 | /* Some targets may only be able to rotate by a constant |
2784 | in one direction. So we need to query the optab interface |
2785 | to see what is possible. */ |
2786 | optab binoptab = left ? rotl_optab : rotr_optab; |
2787 | optab re_binoptab = left ? rotr_optab : rotl_optab; |
2788 | enum insn_code icode = optab_handler (op: binoptab, mode); |
2789 | enum insn_code re_icode = optab_handler (op: re_binoptab, mode); |
2790 | |
2791 | /* If the target can not support the reversed optab, then there |
2792 | is nothing to do. */ |
2793 | if (re_icode == CODE_FOR_nothing) |
2794 | return false; |
2795 | |
2796 | /* If the target does not support the requested rotate-by-immediate, |
2797 | then we want to try reversing the rotate. We also want to try |
2798 | reversing to minimize the count. */ |
2799 | if ((icode == CODE_FOR_nothing) |
2800 | || (!insn_operand_matches (icode, opno: 2, operand: op1)) |
2801 | || (IN_RANGE (INTVAL (op1), |
2802 | GET_MODE_UNIT_PRECISION (mode) / 2 + left, |
2803 | GET_MODE_UNIT_PRECISION (mode) - 1))) |
2804 | return (insn_operand_matches (icode: re_icode, opno: 2, operand: op1)); |
2805 | return false; |
2806 | } |
2807 | |
2808 | /* Subroutine of simplify_binary_operation. Simplify a binary operation |
2809 | CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or |
2810 | OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the |
2811 | actual constants. */ |
2812 | |
2813 | rtx |
2814 | simplify_context::simplify_binary_operation_1 (rtx_code code, |
2815 | machine_mode mode, |
2816 | rtx op0, rtx op1, |
2817 | rtx trueop0, rtx trueop1) |
2818 | { |
2819 | rtx tem, reversed, opleft, opright, elt0, elt1; |
2820 | HOST_WIDE_INT val; |
2821 | scalar_int_mode int_mode, inner_mode; |
2822 | poly_int64 offset; |
2823 | |
2824 | /* Even if we can't compute a constant result, |
2825 | there are some cases worth simplifying. */ |
2826 | |
2827 | switch (code) |
2828 | { |
2829 | case PLUS: |
2830 | /* Maybe simplify x + 0 to x. The two expressions are equivalent |
2831 | when x is NaN, infinite, or finite and nonzero. They aren't |
2832 | when x is -0 and the rounding mode is not towards -infinity, |
2833 | since (-0) + 0 is then 0. */ |
2834 | if (!HONOR_SIGNED_ZEROS (mode) && !HONOR_SNANS (mode) |
2835 | && trueop1 == CONST0_RTX (mode)) |
2836 | return op0; |
2837 | |
2838 | /* ((-a) + b) -> (b - a) and similarly for (a + (-b)). These |
2839 | transformations are safe even for IEEE. */ |
2840 | if (GET_CODE (op0) == NEG) |
2841 | return simplify_gen_binary (code: MINUS, mode, op0: op1, XEXP (op0, 0)); |
2842 | else if (GET_CODE (op1) == NEG) |
2843 | return simplify_gen_binary (code: MINUS, mode, op0, XEXP (op1, 0)); |
2844 | |
2845 | /* (~a) + 1 -> -a */ |
2846 | if (INTEGRAL_MODE_P (mode) |
2847 | && GET_CODE (op0) == NOT |
2848 | && trueop1 == const1_rtx) |
2849 | return simplify_gen_unary (code: NEG, mode, XEXP (op0, 0), op_mode: mode); |
2850 | |
2851 | /* Handle both-operands-constant cases. We can only add |
2852 | CONST_INTs to constants since the sum of relocatable symbols |
2853 | can't be handled by most assemblers. Don't add CONST_INT |
2854 | to CONST_INT since overflow won't be computed properly if wider |
2855 | than HOST_BITS_PER_WIDE_INT. */ |
2856 | |
2857 | if ((GET_CODE (op0) == CONST |
2858 | || GET_CODE (op0) == SYMBOL_REF |
2859 | || GET_CODE (op0) == LABEL_REF) |
2860 | && poly_int_rtx_p (x: op1, res: &offset)) |
2861 | return plus_constant (mode, op0, offset); |
2862 | else if ((GET_CODE (op1) == CONST |
2863 | || GET_CODE (op1) == SYMBOL_REF |
2864 | || GET_CODE (op1) == LABEL_REF) |
2865 | && poly_int_rtx_p (x: op0, res: &offset)) |
2866 | return plus_constant (mode, op1, offset); |
2867 | |
2868 | /* See if this is something like X * C - X or vice versa or |
2869 | if the multiplication is written as a shift. If so, we can |
2870 | distribute and make a new multiply, shift, or maybe just |
2871 | have X (if C is 2 in the example above). But don't make |
2872 | something more expensive than we had before. */ |
2873 | |
2874 | if (is_a <scalar_int_mode> (m: mode, result: &int_mode)) |
2875 | { |
2876 | rtx lhs = op0, rhs = op1; |
2877 | |
2878 | wide_int coeff0 = wi::one (precision: GET_MODE_PRECISION (mode: int_mode)); |
2879 | wide_int coeff1 = wi::one (precision: GET_MODE_PRECISION (mode: int_mode)); |
2880 | |
2881 | if (GET_CODE (lhs) == NEG) |
2882 | { |
2883 | coeff0 = wi::minus_one (precision: GET_MODE_PRECISION (mode: int_mode)); |
2884 | lhs = XEXP (lhs, 0); |
2885 | } |
2886 | else if (GET_CODE (lhs) == MULT |
2887 | && CONST_SCALAR_INT_P (XEXP (lhs, 1))) |
2888 | { |
2889 | coeff0 = rtx_mode_t (XEXP (lhs, 1), int_mode); |
2890 | lhs = XEXP (lhs, 0); |
2891 | } |
2892 | else if (GET_CODE (lhs) == ASHIFT |
2893 | && CONST_INT_P (XEXP (lhs, 1)) |
2894 | && INTVAL (XEXP (lhs, 1)) >= 0 |
2895 | && INTVAL (XEXP (lhs, 1)) < GET_MODE_PRECISION (mode: int_mode)) |
2896 | { |
2897 | coeff0 = wi::set_bit_in_zero (INTVAL (XEXP (lhs, 1)), |
2898 | precision: GET_MODE_PRECISION (mode: int_mode)); |
2899 | lhs = XEXP (lhs, 0); |
2900 | } |
2901 | |
2902 | if (GET_CODE (rhs) == NEG) |
2903 | { |
2904 | coeff1 = wi::minus_one (precision: GET_MODE_PRECISION (mode: int_mode)); |
2905 | rhs = XEXP (rhs, 0); |
2906 | } |
2907 | else if (GET_CODE (rhs) == MULT |
2908 | && CONST_INT_P (XEXP (rhs, 1))) |
2909 | { |
2910 | coeff1 = rtx_mode_t (XEXP (rhs, 1), int_mode); |
2911 | rhs = XEXP (rhs, 0); |
2912 | } |
2913 | else if (GET_CODE (rhs) == ASHIFT |
2914 | && CONST_INT_P (XEXP (rhs, 1)) |
2915 | && INTVAL (XEXP (rhs, 1)) >= 0 |
2916 | && INTVAL (XEXP (rhs, 1)) < GET_MODE_PRECISION (mode: int_mode)) |
2917 | { |
2918 | coeff1 = wi::set_bit_in_zero (INTVAL (XEXP (rhs, 1)), |
2919 | precision: GET_MODE_PRECISION (mode: int_mode)); |
2920 | rhs = XEXP (rhs, 0); |
2921 | } |
2922 | |
2923 | if (rtx_equal_p (lhs, rhs)) |
2924 | { |
2925 | rtx orig = gen_rtx_PLUS (int_mode, op0, op1); |
2926 | rtx coeff; |
2927 | bool speed = optimize_function_for_speed_p (cfun); |
2928 | |
2929 | coeff = immed_wide_int_const (coeff0 + coeff1, int_mode); |
2930 | |
2931 | tem = simplify_gen_binary (code: MULT, mode: int_mode, op0: lhs, op1: coeff); |
2932 | return (set_src_cost (x: tem, mode: int_mode, speed_p: speed) |
2933 | <= set_src_cost (x: orig, mode: int_mode, speed_p: speed) ? tem : 0); |
2934 | } |
2935 | |
2936 | /* Optimize (X - 1) * Y + Y to X * Y. */ |
2937 | lhs = op0; |
2938 | rhs = op1; |
2939 | if (GET_CODE (op0) == MULT) |
2940 | { |
2941 | if (((GET_CODE (XEXP (op0, 0)) == PLUS |
2942 | && XEXP (XEXP (op0, 0), 1) == constm1_rtx) |
2943 | || (GET_CODE (XEXP (op0, 0)) == MINUS |
2944 | && XEXP (XEXP (op0, 0), 1) == const1_rtx)) |
2945 | && rtx_equal_p (XEXP (op0, 1), op1)) |
2946 | lhs = XEXP (XEXP (op0, 0), 0); |
2947 | else if (((GET_CODE (XEXP (op0, 1)) == PLUS |
2948 | && XEXP (XEXP (op0, 1), 1) == constm1_rtx) |
2949 | || (GET_CODE (XEXP (op0, 1)) == MINUS |
2950 | && XEXP (XEXP (op0, 1), 1) == const1_rtx)) |
2951 | && rtx_equal_p (XEXP (op0, 0), op1)) |
2952 | lhs = XEXP (XEXP (op0, 1), 0); |
2953 | } |
2954 | else if (GET_CODE (op1) == MULT) |
2955 | { |
2956 | if (((GET_CODE (XEXP (op1, 0)) == PLUS |
2957 | && XEXP (XEXP (op1, 0), 1) == constm1_rtx) |
2958 | || (GET_CODE (XEXP (op1, 0)) == MINUS |
2959 | && XEXP (XEXP (op1, 0), 1) == const1_rtx)) |
2960 | && rtx_equal_p (XEXP (op1, 1), op0)) |
2961 | rhs = XEXP (XEXP (op1, 0), 0); |
2962 | else if (((GET_CODE (XEXP (op1, 1)) == PLUS |
2963 | && XEXP (XEXP (op1, 1), 1) == constm1_rtx) |
2964 | || (GET_CODE (XEXP (op1, 1)) == MINUS |
2965 | && XEXP (XEXP (op1, 1), 1) == const1_rtx)) |
2966 | && rtx_equal_p (XEXP (op1, 0), op0)) |
2967 | rhs = XEXP (XEXP (op1, 1), 0); |
2968 | } |
2969 | if (lhs != op0 || rhs != op1) |
2970 | return simplify_gen_binary (code: MULT, mode: int_mode, op0: lhs, op1: rhs); |
2971 | } |
2972 | |
2973 | /* (plus (xor X C1) C2) is (xor X (C1^C2)) if C2 is signbit. */ |
2974 | if (CONST_SCALAR_INT_P (op1) |
2975 | && GET_CODE (op0) == XOR |
2976 | && CONST_SCALAR_INT_P (XEXP (op0, 1)) |
2977 | && mode_signbit_p (mode, x: op1)) |
2978 | return simplify_gen_binary (code: XOR, mode, XEXP (op0, 0), |
2979 | op1: simplify_gen_binary (code: XOR, mode, op0: op1, |
2980 | XEXP (op0, 1))); |
2981 | |
2982 | /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)). */ |
2983 | if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode) |
2984 | && GET_CODE (op0) == MULT |
2985 | && GET_CODE (XEXP (op0, 0)) == NEG) |
2986 | { |
2987 | rtx in1, in2; |
2988 | |
2989 | in1 = XEXP (XEXP (op0, 0), 0); |
2990 | in2 = XEXP (op0, 1); |
2991 | return simplify_gen_binary (code: MINUS, mode, op0: op1, |
2992 | op1: simplify_gen_binary (code: MULT, mode, |
2993 | op0: in1, op1: in2)); |
2994 | } |
2995 | |
2996 | /* (plus (comparison A B) C) can become (neg (rev-comp A B)) if |
2997 | C is 1 and STORE_FLAG_VALUE is -1 or if C is -1 and STORE_FLAG_VALUE |
2998 | is 1. */ |
2999 | if (COMPARISON_P (op0) |
3000 | && ((STORE_FLAG_VALUE == -1 && trueop1 == const1_rtx) |
3001 | || (STORE_FLAG_VALUE == 1 && trueop1 == constm1_rtx)) |
3002 | && (reversed = reversed_comparison (op0, mode))) |
3003 | return |
3004 | simplify_gen_unary (code: NEG, mode, op: reversed, op_mode: mode); |
3005 | |
3006 | /* If one of the operands is a PLUS or a MINUS, see if we can |
3007 | simplify this by the associative law. |
3008 | Don't use the associative law for floating point. |
3009 | The inaccuracy makes it nonassociative, |
3010 | and subtle programs can break if operations are associated. */ |
3011 | |
3012 | if (INTEGRAL_MODE_P (mode) |
3013 | && (plus_minus_operand_p (op0) |
3014 | || plus_minus_operand_p (op1)) |
3015 | && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) |
3016 | return tem; |
3017 | |
3018 | /* Reassociate floating point addition only when the user |
3019 | specifies associative math operations. */ |
3020 | if (FLOAT_MODE_P (mode) |
3021 | && flag_associative_math) |
3022 | { |
3023 | tem = simplify_associative_operation (code, mode, op0, op1); |
3024 | if (tem) |
3025 | return tem; |
3026 | } |
3027 | |
3028 | /* Handle vector series. */ |
3029 | if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) |
3030 | { |
3031 | tem = simplify_binary_operation_series (code, mode, op0, op1); |
3032 | if (tem) |
3033 | return tem; |
3034 | } |
3035 | break; |
3036 | |
3037 | case COMPARE: |
3038 | /* Convert (compare (gt (flags) 0) (lt (flags) 0)) to (flags). */ |
3039 | if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT) |
3040 | || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU)) |
3041 | && XEXP (op0, 1) == const0_rtx && XEXP (op1, 1) == const0_rtx) |
3042 | { |
3043 | rtx xop00 = XEXP (op0, 0); |
3044 | rtx xop10 = XEXP (op1, 0); |
3045 | |
3046 | if (REG_P (xop00) && REG_P (xop10) |
3047 | && REGNO (xop00) == REGNO (xop10) |
3048 | && GET_MODE (xop00) == mode |
3049 | && GET_MODE (xop10) == mode |
3050 | && GET_MODE_CLASS (mode) == MODE_CC) |
3051 | return xop00; |
3052 | } |
3053 | break; |
3054 | |
3055 | case MINUS: |
3056 | /* We can't assume x-x is 0 even with non-IEEE floating point, |
3057 | but since it is zero except in very strange circumstances, we |
3058 | will treat it as zero with -ffinite-math-only. */ |
3059 | if (rtx_equal_p (trueop0, trueop1) |
3060 | && ! side_effects_p (op0) |
3061 | && (!FLOAT_MODE_P (mode) || !HONOR_NANS (mode))) |
3062 | return CONST0_RTX (mode); |
3063 | |
3064 | /* Change subtraction from zero into negation. (0 - x) is the |
3065 | same as -x when x is NaN, infinite, or finite and nonzero. |
3066 | But if the mode has signed zeros, and does not round towards |
3067 | -infinity, then 0 - 0 is 0, not -0. */ |
3068 | if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode)) |
3069 | return simplify_gen_unary (code: NEG, mode, op: op1, op_mode: mode); |
3070 | |
3071 | /* (-1 - a) is ~a, unless the expression contains symbolic |
3072 | constants, in which case not retaining additions and |
3073 | subtractions could cause invalid assembly to be produced. */ |
3074 | if (trueop0 == CONSTM1_RTX (mode) |
3075 | && !contains_symbolic_reference_p (op1)) |
3076 | return simplify_gen_unary (code: NOT, mode, op: op1, op_mode: mode); |
3077 | |
3078 | /* Subtracting 0 has no effect unless the mode has signalling NaNs, |
3079 | or has signed zeros and supports rounding towards -infinity. |
3080 | In such a case, 0 - 0 is -0. */ |
3081 | if (!(HONOR_SIGNED_ZEROS (mode) |
3082 | && HONOR_SIGN_DEPENDENT_ROUNDING (mode)) |
3083 | && !HONOR_SNANS (mode) |
3084 | && trueop1 == CONST0_RTX (mode)) |
3085 | return op0; |
3086 | |
3087 | /* See if this is something like X * C - X or vice versa or |
3088 | if the multiplication is written as a shift. If so, we can |
3089 | distribute and make a new multiply, shift, or maybe just |
3090 | have X (if C is 2 in the example above). But don't make |
3091 | something more expensive than we had before. */ |
3092 | |
3093 | if (is_a <scalar_int_mode> (m: mode, result: &int_mode)) |
3094 | { |
3095 | rtx lhs = op0, rhs = op1; |
3096 | |
3097 | wide_int coeff0 = wi::one (precision: GET_MODE_PRECISION (mode: int_mode)); |
3098 | wide_int negcoeff1 = wi::minus_one (precision: GET_MODE_PRECISION (mode: int_mode)); |
3099 | |
3100 | if (GET_CODE (lhs) == NEG) |
3101 | { |
3102 | coeff0 = wi::minus_one (precision: GET_MODE_PRECISION (mode: int_mode)); |
3103 | lhs = XEXP (lhs, 0); |
3104 | } |
3105 | else if (GET_CODE (lhs) == MULT |
3106 | && CONST_SCALAR_INT_P (XEXP (lhs, 1))) |
3107 | { |
3108 | coeff0 = rtx_mode_t (XEXP (lhs, 1), int_mode); |
3109 | lhs = XEXP (lhs, 0); |
3110 | } |
3111 | else if (GET_CODE (lhs) == ASHIFT |
3112 | && CONST_INT_P (XEXP (lhs, 1)) |
3113 | && INTVAL (XEXP (lhs, 1)) >= 0 |
3114 | && INTVAL (XEXP (lhs, 1)) < GET_MODE_PRECISION (mode: int_mode)) |
3115 | { |
3116 | coeff0 = wi::set_bit_in_zero (INTVAL (XEXP (lhs, 1)), |
3117 | precision: GET_MODE_PRECISION (mode: int_mode)); |
3118 | lhs = XEXP (lhs, 0); |
3119 | } |
3120 | |
3121 | if (GET_CODE (rhs) == NEG) |
3122 | { |
3123 | negcoeff1 = wi::one (precision: GET_MODE_PRECISION (mode: int_mode)); |
3124 | rhs = XEXP (rhs, 0); |
3125 | } |
3126 | else if (GET_CODE (rhs) == MULT |
3127 | && CONST_INT_P (XEXP (rhs, 1))) |
3128 | { |
3129 | negcoeff1 = wi::neg (x: rtx_mode_t (XEXP (rhs, 1), int_mode)); |
3130 | rhs = XEXP (rhs, 0); |
3131 | } |
3132 | else if (GET_CODE (rhs) == ASHIFT |
3133 | && CONST_INT_P (XEXP (rhs, 1)) |
3134 | && INTVAL (XEXP (rhs, 1)) >= 0 |
3135 | && INTVAL (XEXP (rhs, 1)) < GET_MODE_PRECISION (mode: int_mode)) |
3136 | { |
3137 | negcoeff1 = wi::set_bit_in_zero (INTVAL (XEXP (rhs, 1)), |
3138 | precision: GET_MODE_PRECISION (mode: int_mode)); |
3139 | negcoeff1 = -negcoeff1; |
3140 | rhs = XEXP (rhs, 0); |
3141 | } |
3142 | |
3143 | if (rtx_equal_p (lhs, rhs)) |
3144 | { |
3145 | rtx orig = gen_rtx_MINUS (int_mode, op0, op1); |
3146 | rtx coeff; |
3147 | bool speed = optimize_function_for_speed_p (cfun); |
3148 | |
3149 | coeff = immed_wide_int_const (coeff0 + negcoeff1, int_mode); |
3150 | |
3151 | tem = simplify_gen_binary (code: MULT, mode: int_mode, op0: lhs, op1: coeff); |
3152 | return (set_src_cost (x: tem, mode: int_mode, speed_p: speed) |
3153 | <= set_src_cost (x: orig, mode: int_mode, speed_p: speed) ? tem : 0); |
3154 | } |
3155 | |
3156 | /* Optimize (X + 1) * Y - Y to X * Y. */ |
3157 | lhs = op0; |
3158 | if (GET_CODE (op0) == MULT) |
3159 | { |
3160 | if (((GET_CODE (XEXP (op0, 0)) == PLUS |
3161 | && XEXP (XEXP (op0, 0), 1) == const1_rtx) |
3162 | || (GET_CODE (XEXP (op0, 0)) == MINUS |
3163 | && XEXP (XEXP (op0, 0), 1) == constm1_rtx)) |
3164 | && rtx_equal_p (XEXP (op0, 1), op1)) |
3165 | lhs = XEXP (XEXP (op0, 0), 0); |
3166 | else if (((GET_CODE (XEXP (op0, 1)) == PLUS |
3167 | && XEXP (XEXP (op0, 1), 1) == const1_rtx) |
3168 | || (GET_CODE (XEXP (op0, 1)) == MINUS |
3169 | && XEXP (XEXP (op0, 1), 1) == constm1_rtx)) |
3170 | && rtx_equal_p (XEXP (op0, 0), op1)) |
3171 | lhs = XEXP (XEXP (op0, 1), 0); |
3172 | } |
3173 | if (lhs != op0) |
3174 | return simplify_gen_binary (code: MULT, mode: int_mode, op0: lhs, op1); |
3175 | } |
3176 | |
3177 | /* (a - (-b)) -> (a + b). True even for IEEE. */ |
3178 | if (GET_CODE (op1) == NEG) |
3179 | return simplify_gen_binary (code: PLUS, mode, op0, XEXP (op1, 0)); |
3180 | |
3181 | /* (-x - c) may be simplified as (-c - x). */ |
3182 | if (GET_CODE (op0) == NEG |
3183 | && (CONST_SCALAR_INT_P (op1) || CONST_DOUBLE_AS_FLOAT_P (op1))) |
3184 | { |
3185 | tem = simplify_unary_operation (code: NEG, mode, op: op1, op_mode: mode); |
3186 | if (tem) |
3187 | return simplify_gen_binary (code: MINUS, mode, op0: tem, XEXP (op0, 0)); |
3188 | } |
3189 | |
3190 | if ((GET_CODE (op0) == CONST |
3191 | || GET_CODE (op0) == SYMBOL_REF |
3192 | || GET_CODE (op0) == LABEL_REF) |
3193 | && poly_int_rtx_p (x: op1, res: &offset)) |
3194 | return plus_constant (mode, op0, trunc_int_for_mode (-offset, mode)); |
3195 | |
3196 | /* Don't let a relocatable value get a negative coeff. */ |
3197 | if (poly_int_rtx_p (x: op1) && GET_MODE (op0) != VOIDmode) |
3198 | return simplify_gen_binary (code: PLUS, mode, |
3199 | op0, |
3200 | op1: neg_poly_int_rtx (mode, i: op1)); |
3201 | |
3202 | /* (x - (x & y)) -> (x & ~y) */ |
3203 | if (INTEGRAL_MODE_P (mode) && GET_CODE (op1) == AND) |
3204 | { |
3205 | if (rtx_equal_p (op0, XEXP (op1, 0))) |
3206 | { |
3207 | tem = simplify_gen_unary (code: NOT, mode, XEXP (op1, 1), |
3208 | GET_MODE (XEXP (op1, 1))); |
3209 | return simplify_gen_binary (code: AND, mode, op0, op1: tem); |
3210 | } |
3211 | if (rtx_equal_p (op0, XEXP (op1, 1))) |
3212 | { |
3213 | tem = simplify_gen_unary (code: NOT, mode, XEXP (op1, 0), |
3214 | GET_MODE (XEXP (op1, 0))); |
3215 | return simplify_gen_binary (code: AND, mode, op0, op1: tem); |
3216 | } |
3217 | } |
3218 | |
3219 | /* If STORE_FLAG_VALUE is 1, (minus 1 (comparison foo bar)) can be done |
3220 | by reversing the comparison code if valid. */ |
3221 | if (STORE_FLAG_VALUE == 1 |
3222 | && trueop0 == const1_rtx |
3223 | && COMPARISON_P (op1) |
3224 | && (reversed = reversed_comparison (op1, mode))) |
3225 | return reversed; |
3226 | |
3227 | /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A). */ |
3228 | if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode) |
3229 | && GET_CODE (op1) == MULT |
3230 | && GET_CODE (XEXP (op1, 0)) == NEG) |
3231 | { |
3232 | rtx in1, in2; |
3233 | |
3234 | in1 = XEXP (XEXP (op1, 0), 0); |
3235 | in2 = XEXP (op1, 1); |
3236 | return simplify_gen_binary (code: PLUS, mode, |
3237 | op0: simplify_gen_binary (code: MULT, mode, |
3238 | op0: in1, op1: in2), |
3239 | op1: op0); |
3240 | } |
3241 | |
3242 | /* Canonicalize (minus (neg A) (mult B C)) to |
3243 | (minus (mult (neg B) C) A). */ |
3244 | if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode) |
3245 | && GET_CODE (op1) == MULT |
3246 | && GET_CODE (op0) == NEG) |
3247 | { |
3248 | rtx in1, in2; |
3249 | |
3250 | in1 = simplify_gen_unary (code: NEG, mode, XEXP (op1, 0), op_mode: mode); |
3251 | in2 = XEXP (op1, 1); |
3252 | return simplify_gen_binary (code: MINUS, mode, |
3253 | op0: simplify_gen_binary (code: MULT, mode, |
3254 | op0: in1, op1: in2), |
3255 | XEXP (op0, 0)); |
3256 | } |
3257 | |
3258 | /* If one of the operands is a PLUS or a MINUS, see if we can |
3259 | simplify this by the associative law. This will, for example, |
3260 | canonicalize (minus A (plus B C)) to (minus (minus A B) C). |
3261 | Don't use the associative law for floating point. |
3262 | The inaccuracy makes it nonassociative, |
3263 | and subtle programs can break if operations are associated. */ |
3264 | |
3265 | if (INTEGRAL_MODE_P (mode) |
3266 | && (plus_minus_operand_p (op0) |
3267 | || plus_minus_operand_p (op1)) |
3268 | && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) |
3269 | return tem; |
3270 | |
3271 | /* Handle vector series. */ |
3272 | if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) |
3273 | { |
3274 | tem = simplify_binary_operation_series (code, mode, op0, op1); |
3275 | if (tem) |
3276 | return tem; |
3277 | } |
3278 | break; |
3279 | |
3280 | case MULT: |
3281 | if (trueop1 == constm1_rtx) |
3282 | return simplify_gen_unary (code: NEG, mode, op: op0, op_mode: mode); |
3283 | |
3284 | if (GET_CODE (op0) == NEG) |
3285 | { |
3286 | rtx temp = simplify_unary_operation (code: NEG, mode, op: op1, op_mode: mode); |
3287 | /* If op1 is a MULT as well and simplify_unary_operation |
3288 | just moved the NEG to the second operand, simplify_gen_binary |
3289 | below could through simplify_associative_operation move |
3290 | the NEG around again and recurse endlessly. */ |
3291 | if (temp |
3292 | && GET_CODE (op1) == MULT |
3293 | && GET_CODE (temp) == MULT |
3294 | && XEXP (op1, 0) == XEXP (temp, 0) |
3295 | && GET_CODE (XEXP (temp, 1)) == NEG |
3296 | && XEXP (op1, 1) == XEXP (XEXP (temp, 1), 0)) |
3297 | temp = NULL_RTX; |
3298 | if (temp) |
3299 | return simplify_gen_binary (code: MULT, mode, XEXP (op0, 0), op1: temp); |
3300 | } |
3301 | if (GET_CODE (op1) == NEG) |
3302 | { |
3303 | rtx temp = simplify_unary_operation (code: NEG, mode, op: op0, op_mode: mode); |
3304 | /* If op0 is a MULT as well and simplify_unary_operation |
3305 | just moved the NEG to the second operand, simplify_gen_binary |
3306 | below could through simplify_associative_operation move |
3307 | the NEG around again and recurse endlessly. */ |
3308 | if (temp |
3309 | && GET_CODE (op0) == MULT |
3310 | && GET_CODE (temp) == MULT |
3311 | && XEXP (op0, 0) == XEXP (temp, 0) |
3312 | && GET_CODE (XEXP (temp, 1)) == NEG |
3313 | && XEXP (op0, 1) == XEXP (XEXP (temp, 1), 0)) |
3314 | temp = NULL_RTX; |
3315 | if (temp) |
3316 | return simplify_gen_binary (code: MULT, mode, op0: temp, XEXP (op1, 0)); |
3317 | } |
3318 | |
3319 | /* Maybe simplify x * 0 to 0. The reduction is not valid if |
3320 | x is NaN, since x * 0 is then also NaN. Nor is it valid |
3321 | when the mode has signed zeros, since multiplying a negative |
3322 | number by 0 will give -0, not 0. */ |
3323 | if (!HONOR_NANS (mode) |
3324 | && !HONOR_SIGNED_ZEROS (mode) |
3325 | && trueop1 == CONST0_RTX (mode) |
3326 | && ! side_effects_p (op0)) |
3327 | return op1; |
3328 | |
3329 | /* In IEEE floating point, x*1 is not equivalent to x for |
3330 | signalling NaNs. */ |
3331 | if (!HONOR_SNANS (mode) |
3332 | && trueop1 == CONST1_RTX (mode)) |
3333 | return op0; |
3334 | |
3335 | /* Convert multiply by constant power of two into shift. */ |
3336 | if (mem_depth == 0 && CONST_SCALAR_INT_P (trueop1)) |
3337 | { |
3338 | val = wi::exact_log2 (rtx_mode_t (trueop1, mode)); |
3339 | if (val >= 0) |
3340 | return simplify_gen_binary (code: ASHIFT, mode, op0, |
3341 | op1: gen_int_shift_amount (mode, val)); |
3342 | } |
3343 | |
3344 | /* x*2 is x+x and x*(-1) is -x */ |
3345 | if (CONST_DOUBLE_AS_FLOAT_P (trueop1) |
3346 | && SCALAR_FLOAT_MODE_P (GET_MODE (trueop1)) |
3347 | && !DECIMAL_FLOAT_MODE_P (GET_MODE (trueop1)) |
3348 | && GET_MODE (op0) == mode) |
3349 | { |
3350 | const REAL_VALUE_TYPE *d1 = CONST_DOUBLE_REAL_VALUE (trueop1); |
3351 | |
3352 | if (real_equal (d1, &dconst2)) |
3353 | return simplify_gen_binary (code: PLUS, mode, op0, op1: copy_rtx (op0)); |
3354 | |
3355 | if (!HONOR_SNANS (mode) |
3356 | && real_equal (d1, &dconstm1)) |
3357 | return simplify_gen_unary (code: NEG, mode, op: op0, op_mode: mode); |
3358 | } |
3359 | |
3360 | /* Optimize -x * -x as x * x. */ |
3361 | if (FLOAT_MODE_P (mode) |
3362 | && GET_CODE (op0) == NEG |
3363 | && GET_CODE (op1) == NEG |
3364 | && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) |
3365 | && !side_effects_p (XEXP (op0, 0))) |
3366 | return simplify_gen_binary (code: MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); |
3367 | |
3368 | /* Likewise, optimize abs(x) * abs(x) as x * x. */ |
3369 | if (SCALAR_FLOAT_MODE_P (mode) |
3370 | && GET_CODE (op0) == ABS |
3371 | && GET_CODE (op1) == ABS |
3372 | && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) |
3373 | && !side_effects_p (XEXP (op0, 0))) |
3374 | return simplify_gen_binary (code: MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); |
3375 | |
3376 | /* Reassociate multiplication, but for floating point MULTs |
3377 | only when the user specifies unsafe math optimizations. */ |
3378 | if (! FLOAT_MODE_P (mode) |
3379 | || flag_unsafe_math_optimizations) |
3380 | { |
3381 | tem = simplify_associative_operation (code, mode, op0, op1); |
3382 | if (tem) |
3383 | return tem; |
3384 | } |
3385 | break; |
3386 | |
3387 | case IOR: |
3388 | if (trueop1 == CONST0_RTX (mode)) |
3389 | return op0; |
3390 | if (INTEGRAL_MODE_P (mode) |
3391 | && trueop1 == CONSTM1_RTX (mode) |
3392 | && !side_effects_p (op0)) |
3393 | return op1; |
3394 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) |
3395 | return op0; |
3396 | /* A | (~A) -> -1 */ |
3397 | if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) |
3398 | || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) |
3399 | && ! side_effects_p (op0) |
3400 | && GET_MODE_CLASS (mode) != MODE_CC) |
3401 | return CONSTM1_RTX (mode); |
3402 | |
3403 | /* (ior A C) is C if all bits of A that might be nonzero are on in C. */ |
3404 | if (CONST_INT_P (op1) |
3405 | && HWI_COMPUTABLE_MODE_P (mode) |
3406 | && (nonzero_bits (op0, mode) & ~UINTVAL (op1)) == 0 |
3407 | && !side_effects_p (op0)) |
3408 | return op1; |
3409 | |
3410 | /* Canonicalize (X & C1) | C2. */ |
3411 | if (GET_CODE (op0) == AND |
3412 | && CONST_INT_P (trueop1) |
3413 | && CONST_INT_P (XEXP (op0, 1))) |
3414 | { |
3415 | HOST_WIDE_INT mask = GET_MODE_MASK (mode); |
3416 | HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1)); |
3417 | HOST_WIDE_INT c2 = INTVAL (trueop1); |
3418 | |
3419 | /* If (C1&C2) == C1, then (X&C1)|C2 becomes C2. */ |
3420 | if ((c1 & c2) == c1 |
3421 | && !side_effects_p (XEXP (op0, 0))) |
3422 | return trueop1; |
3423 | |
3424 | /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */ |
3425 | if (((c1|c2) & mask) == mask) |
3426 | return simplify_gen_binary (code: IOR, mode, XEXP (op0, 0), op1); |
3427 | } |
3428 | |
3429 | /* Convert (A & B) | A to A. */ |
3430 | if (GET_CODE (op0) == AND |
3431 | && (rtx_equal_p (XEXP (op0, 0), op1) |
3432 | || rtx_equal_p (XEXP (op0, 1), op1)) |
3433 | && ! side_effects_p (XEXP (op0, 0)) |
3434 | && ! side_effects_p (XEXP (op0, 1))) |
3435 | return op1; |
3436 | |
3437 | /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the |
3438 | mode size to (rotate A CX). */ |
3439 | |
3440 | if (GET_CODE (op1) == ASHIFT |
3441 | || GET_CODE (op1) == SUBREG) |
3442 | { |
3443 | opleft = op1; |
3444 | opright = op0; |
3445 | } |
3446 | else |
3447 | { |
3448 | opright = op1; |
3449 | opleft = op0; |
3450 | } |
3451 | |
3452 | if (GET_CODE (opleft) == ASHIFT && GET_CODE (opright) == LSHIFTRT |
3453 | && rtx_equal_p (XEXP (opleft, 0), XEXP (opright, 0)) |
3454 | && CONST_INT_P (XEXP (opleft, 1)) |
3455 | && CONST_INT_P (XEXP (opright, 1)) |
3456 | && (INTVAL (XEXP (opleft, 1)) + INTVAL (XEXP (opright, 1)) |
3457 | == GET_MODE_UNIT_PRECISION (mode))) |
3458 | return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1)); |
3459 | |
3460 | /* Same, but for ashift that has been "simplified" to a wider mode |
3461 | by simplify_shift_const. */ |
3462 | |
3463 | if (GET_CODE (opleft) == SUBREG |
3464 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
3465 | && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (opleft)), |
3466 | result: &inner_mode) |
3467 | && GET_CODE (SUBREG_REG (opleft)) == ASHIFT |
3468 | && GET_CODE (opright) == LSHIFTRT |
3469 | && GET_CODE (XEXP (opright, 0)) == SUBREG |
3470 | && known_eq (SUBREG_BYTE (opleft), SUBREG_BYTE (XEXP (opright, 0))) |
3471 | && GET_MODE_SIZE (mode: int_mode) < GET_MODE_SIZE (mode: inner_mode) |
3472 | && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), |
3473 | SUBREG_REG (XEXP (opright, 0))) |
3474 | && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1)) |
3475 | && CONST_INT_P (XEXP (opright, 1)) |
3476 | && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) |
3477 | + INTVAL (XEXP (opright, 1)) |
3478 | == GET_MODE_PRECISION (mode: int_mode))) |
3479 | return gen_rtx_ROTATE (int_mode, XEXP (opright, 0), |
3480 | XEXP (SUBREG_REG (opleft), 1)); |
3481 | |
3482 | /* If OP0 is (ashiftrt (plus ...) C), it might actually be |
3483 | a (sign_extend (plus ...)). Then check if OP1 is a CONST_INT and |
3484 | the PLUS does not affect any of the bits in OP1: then we can do |
3485 | the IOR as a PLUS and we can associate. This is valid if OP1 |
3486 | can be safely shifted left C bits. */ |
3487 | if (CONST_INT_P (trueop1) && GET_CODE (op0) == ASHIFTRT |
3488 | && GET_CODE (XEXP (op0, 0)) == PLUS |
3489 | && CONST_INT_P (XEXP (XEXP (op0, 0), 1)) |
3490 | && CONST_INT_P (XEXP (op0, 1)) |
3491 | && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT) |
3492 | { |
3493 | int count = INTVAL (XEXP (op0, 1)); |
3494 | HOST_WIDE_INT mask = UINTVAL (trueop1) << count; |
3495 | |
3496 | if (mask >> count == INTVAL (trueop1) |
3497 | && trunc_int_for_mode (mask, mode) == mask |
3498 | && (mask & nonzero_bits (XEXP (op0, 0), mode)) == 0) |
3499 | return simplify_gen_binary (code: ASHIFTRT, mode, |
3500 | op0: plus_constant (mode, XEXP (op0, 0), |
3501 | mask), |
3502 | XEXP (op0, 1)); |
3503 | } |
3504 | |
3505 | /* The following happens with bitfield merging. |
3506 | (X & C) | ((X | Y) & ~C) -> X | (Y & ~C) */ |
3507 | if (GET_CODE (op0) == AND |
3508 | && GET_CODE (op1) == AND |
3509 | && CONST_INT_P (XEXP (op0, 1)) |
3510 | && CONST_INT_P (XEXP (op1, 1)) |
3511 | && (INTVAL (XEXP (op0, 1)) |
3512 | == ~INTVAL (XEXP (op1, 1)))) |
3513 | { |
3514 | /* The IOR may be on both sides. */ |
3515 | rtx top0 = NULL_RTX, top1 = NULL_RTX; |
3516 | if (GET_CODE (XEXP (op1, 0)) == IOR) |
3517 | top0 = op0, top1 = op1; |
3518 | else if (GET_CODE (XEXP (op0, 0)) == IOR) |
3519 | top0 = op1, top1 = op0; |
3520 | if (top0 && top1) |
3521 | { |
3522 | /* X may be on either side of the inner IOR. */ |
3523 | rtx tem = NULL_RTX; |
3524 | if (rtx_equal_p (XEXP (top0, 0), |
3525 | XEXP (XEXP (top1, 0), 0))) |
3526 | tem = XEXP (XEXP (top1, 0), 1); |
3527 | else if (rtx_equal_p (XEXP (top0, 0), |
3528 | XEXP (XEXP (top1, 0), 1))) |
3529 | tem = XEXP (XEXP (top1, 0), 0); |
3530 | if (tem) |
3531 | return simplify_gen_binary (code: IOR, mode, XEXP (top0, 0), |
3532 | op1: simplify_gen_binary |
3533 | (code: AND, mode, op0: tem, XEXP (top1, 1))); |
3534 | } |
3535 | } |
3536 | |
3537 | /* Convert (ior (and A C) (and B C)) into (and (ior A B) C). */ |
3538 | if (GET_CODE (op0) == GET_CODE (op1) |
3539 | && (GET_CODE (op0) == AND |
3540 | || GET_CODE (op0) == IOR |
3541 | || GET_CODE (op0) == LSHIFTRT |
3542 | || GET_CODE (op0) == ASHIFTRT |
3543 | || GET_CODE (op0) == ASHIFT |
3544 | || GET_CODE (op0) == ROTATE |
3545 | || GET_CODE (op0) == ROTATERT)) |
3546 | { |
3547 | tem = simplify_distributive_operation (code, mode, op0, op1); |
3548 | if (tem) |
3549 | return tem; |
3550 | } |
3551 | |
3552 | tem = simplify_byte_swapping_operation (code, mode, op0, op1); |
3553 | if (tem) |
3554 | return tem; |
3555 | |
3556 | tem = simplify_associative_operation (code, mode, op0, op1); |
3557 | if (tem) |
3558 | return tem; |
3559 | |
3560 | tem = simplify_logical_relational_operation (code, mode, op0, op1); |
3561 | if (tem) |
3562 | return tem; |
3563 | break; |
3564 | |
3565 | case XOR: |
3566 | if (trueop1 == CONST0_RTX (mode)) |
3567 | return op0; |
3568 | if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode)) |
3569 | return simplify_gen_unary (code: NOT, mode, op: op0, op_mode: mode); |
3570 | if (rtx_equal_p (trueop0, trueop1) |
3571 | && ! side_effects_p (op0) |
3572 | && GET_MODE_CLASS (mode) != MODE_CC) |
3573 | return CONST0_RTX (mode); |
3574 | |
3575 | /* Canonicalize XOR of the most significant bit to PLUS. */ |
3576 | if (CONST_SCALAR_INT_P (op1) |
3577 | && mode_signbit_p (mode, x: op1)) |
3578 | return simplify_gen_binary (code: PLUS, mode, op0, op1); |
3579 | /* (xor (plus X C1) C2) is (xor X (C1^C2)) if C1 is signbit. */ |
3580 | if (CONST_SCALAR_INT_P (op1) |
3581 | && GET_CODE (op0) == PLUS |
3582 | && CONST_SCALAR_INT_P (XEXP (op0, 1)) |
3583 | && mode_signbit_p (mode, XEXP (op0, 1))) |
3584 | return simplify_gen_binary (code: XOR, mode, XEXP (op0, 0), |
3585 | op1: simplify_gen_binary (code: XOR, mode, op0: op1, |
3586 | XEXP (op0, 1))); |
3587 | |
3588 | /* If we are XORing two things that have no bits in common, |
3589 | convert them into an IOR. This helps to detect rotation encoded |
3590 | using those methods and possibly other simplifications. */ |
3591 | |
3592 | if (HWI_COMPUTABLE_MODE_P (mode) |
3593 | && (nonzero_bits (op0, mode) |
3594 | & nonzero_bits (op1, mode)) == 0) |
3595 | return (simplify_gen_binary (code: IOR, mode, op0, op1)); |
3596 | |
3597 | /* Convert (XOR (NOT x) (NOT y)) to (XOR x y). |
3598 | Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for |
3599 | (NOT y). */ |
3600 | { |
3601 | int num_negated = 0; |
3602 | |
3603 | if (GET_CODE (op0) == NOT) |
3604 | num_negated++, op0 = XEXP (op0, 0); |
3605 | if (GET_CODE (op1) == NOT) |
3606 | num_negated++, op1 = XEXP (op1, 0); |
3607 | |
3608 | if (num_negated == 2) |
3609 | return simplify_gen_binary (code: XOR, mode, op0, op1); |
3610 | else if (num_negated == 1) |
3611 | return simplify_gen_unary (code: NOT, mode, |
3612 | op: simplify_gen_binary (code: XOR, mode, op0, op1), |
3613 | op_mode: mode); |
3614 | } |
3615 | |
3616 | /* Convert (xor (and A B) B) to (and (not A) B). The latter may |
3617 | correspond to a machine insn or result in further simplifications |
3618 | if B is a constant. */ |
3619 | |
3620 | if (GET_CODE (op0) == AND |
3621 | && rtx_equal_p (XEXP (op0, 1), op1) |
3622 | && ! side_effects_p (op1)) |
3623 | return simplify_gen_binary (code: AND, mode, |
3624 | op0: simplify_gen_unary (code: NOT, mode, |
3625 | XEXP (op0, 0), op_mode: mode), |
3626 | op1); |
3627 | |
3628 | else if (GET_CODE (op0) == AND |
3629 | && rtx_equal_p (XEXP (op0, 0), op1) |
3630 | && ! side_effects_p (op1)) |
3631 | return simplify_gen_binary (code: AND, mode, |
3632 | op0: simplify_gen_unary (code: NOT, mode, |
3633 | XEXP (op0, 1), op_mode: mode), |
3634 | op1); |
3635 | |
3636 | /* Given (xor (ior (xor A B) C) D), where B, C and D are |
3637 | constants, simplify to (xor (ior A C) (B&~C)^D), canceling |
3638 | out bits inverted twice and not set by C. Similarly, given |
3639 | (xor (and (xor A B) C) D), simplify without inverting C in |
3640 | the xor operand: (xor (and A C) (B&C)^D). |
3641 | */ |
3642 | else if ((GET_CODE (op0) == IOR || GET_CODE (op0) == AND) |
3643 | && GET_CODE (XEXP (op0, 0)) == XOR |
3644 | && CONST_INT_P (op1) |
3645 | && CONST_INT_P (XEXP (op0, 1)) |
3646 | && CONST_INT_P (XEXP (XEXP (op0, 0), 1))) |
3647 | { |
3648 | enum rtx_code op = GET_CODE (op0); |
3649 | rtx a = XEXP (XEXP (op0, 0), 0); |
3650 | rtx b = XEXP (XEXP (op0, 0), 1); |
3651 | rtx c = XEXP (op0, 1); |
3652 | rtx d = op1; |
3653 | HOST_WIDE_INT bval = INTVAL (b); |
3654 | HOST_WIDE_INT cval = INTVAL (c); |
3655 | HOST_WIDE_INT dval = INTVAL (d); |
3656 | HOST_WIDE_INT xcval; |
3657 | |
3658 | if (op == IOR) |
3659 | xcval = ~cval; |
3660 | else |
3661 | xcval = cval; |
3662 | |
3663 | return simplify_gen_binary (code: XOR, mode, |
3664 | op0: simplify_gen_binary (code: op, mode, op0: a, op1: c), |
3665 | op1: gen_int_mode ((bval & xcval) ^ dval, |
3666 | mode)); |
3667 | } |
3668 | |
3669 | /* Given (xor (and A B) C), using P^Q == (~P&Q) | (~Q&P), |
3670 | we can transform like this: |
3671 | (A&B)^C == ~(A&B)&C | ~C&(A&B) |
3672 | == (~A|~B)&C | ~C&(A&B) * DeMorgan's Law |
3673 | == ~A&C | ~B&C | A&(~C&B) * Distribute and re-order |
3674 | Attempt a few simplifications when B and C are both constants. */ |
3675 | if (GET_CODE (op0) == AND |
3676 | && CONST_INT_P (op1) |
3677 | && CONST_INT_P (XEXP (op0, 1))) |
3678 | { |
3679 | rtx a = XEXP (op0, 0); |
3680 | rtx b = XEXP (op0, 1); |
3681 | rtx c = op1; |
3682 | HOST_WIDE_INT bval = INTVAL (b); |
3683 | HOST_WIDE_INT cval = INTVAL (c); |
3684 | |
3685 | /* Instead of computing ~A&C, we compute its negated value, |
3686 | ~(A|~C). If it yields -1, ~A&C is zero, so we can |
3687 | optimize for sure. If it does not simplify, we still try |
3688 | to compute ~A&C below, but since that always allocates |
3689 | RTL, we don't try that before committing to returning a |
3690 | simplified expression. */ |
3691 | rtx n_na_c = simplify_binary_operation (code: IOR, mode, op0: a, |
3692 | GEN_INT (~cval)); |
3693 | |
3694 | if ((~cval & bval) == 0) |
3695 | { |
3696 | rtx na_c = NULL_RTX; |
3697 | if (n_na_c) |
3698 | na_c = simplify_gen_unary (code: NOT, mode, op: n_na_c, op_mode: mode); |
3699 | else |
3700 | { |
3701 | /* If ~A does not simplify, don't bother: we don't |
3702 | want to simplify 2 operations into 3, and if na_c |
3703 | were to simplify with na, n_na_c would have |
3704 | simplified as well. */ |
3705 | rtx na = simplify_unary_operation (code: NOT, mode, op: a, op_mode: mode); |
3706 | if (na) |
3707 | na_c = simplify_gen_binary (code: AND, mode, op0: na, op1: c); |
3708 | } |
3709 | |
3710 | /* Try to simplify ~A&C | ~B&C. */ |
3711 | if (na_c != NULL_RTX) |
3712 | return simplify_gen_binary (code: IOR, mode, op0: na_c, |
3713 | op1: gen_int_mode (~bval & cval, mode)); |
3714 | } |
3715 | else |
3716 | { |
3717 | /* If ~A&C is zero, simplify A&(~C&B) | ~B&C. */ |
3718 | if (n_na_c == CONSTM1_RTX (mode)) |
3719 | { |
3720 | rtx a_nc_b = simplify_gen_binary (code: AND, mode, op0: a, |
3721 | op1: gen_int_mode (~cval & bval, |
3722 | mode)); |
3723 | return simplify_gen_binary (code: IOR, mode, op0: a_nc_b, |
3724 | op1: gen_int_mode (~bval & cval, |
3725 | mode)); |
3726 | } |
3727 | } |
3728 | } |
3729 | |
3730 | /* If we have (xor (and (xor A B) C) A) with C a constant we can instead |
3731 | do (ior (and A ~C) (and B C)) which is a machine instruction on some |
3732 | machines, and also has shorter instruction path length. */ |
3733 | if (GET_CODE (op0) == AND |
3734 | && GET_CODE (XEXP (op0, 0)) == XOR |
3735 | && CONST_INT_P (XEXP (op0, 1)) |
3736 | && rtx_equal_p (XEXP (XEXP (op0, 0), 0), trueop1)) |
3737 | { |
3738 | rtx a = trueop1; |
3739 | rtx b = XEXP (XEXP (op0, 0), 1); |
3740 | rtx c = XEXP (op0, 1); |
3741 | rtx nc = simplify_gen_unary (code: NOT, mode, op: c, op_mode: mode); |
3742 | rtx a_nc = simplify_gen_binary (code: AND, mode, op0: a, op1: nc); |
3743 | rtx bc = simplify_gen_binary (code: AND, mode, op0: b, op1: c); |
3744 | return simplify_gen_binary (code: IOR, mode, op0: a_nc, op1: bc); |
3745 | } |
3746 | /* Similarly, (xor (and (xor A B) C) B) as (ior (and A C) (and B ~C)) */ |
3747 | else if (GET_CODE (op0) == AND |
3748 | && GET_CODE (XEXP (op0, 0)) == XOR |
3749 | && CONST_INT_P (XEXP (op0, 1)) |
3750 | && rtx_equal_p (XEXP (XEXP (op0, 0), 1), trueop1)) |
3751 | { |
3752 | rtx a = XEXP (XEXP (op0, 0), 0); |
3753 | rtx b = trueop1; |
3754 | rtx c = XEXP (op0, 1); |
3755 | rtx nc = simplify_gen_unary (code: NOT, mode, op: c, op_mode: mode); |
3756 | rtx b_nc = simplify_gen_binary (code: AND, mode, op0: b, op1: nc); |
3757 | rtx ac = simplify_gen_binary (code: AND, mode, op0: a, op1: c); |
3758 | return simplify_gen_binary (code: IOR, mode, op0: ac, op1: b_nc); |
3759 | } |
3760 | |
3761 | /* (xor (comparison foo bar) (const_int 1)) can become the reversed |
3762 | comparison if STORE_FLAG_VALUE is 1. */ |
3763 | if (STORE_FLAG_VALUE == 1 |
3764 | && trueop1 == const1_rtx |
3765 | && COMPARISON_P (op0) |
3766 | && (reversed = reversed_comparison (op0, mode))) |
3767 | return reversed; |
3768 | |
3769 | /* (lshiftrt foo C) where C is the number of bits in FOO minus 1 |
3770 | is (lt foo (const_int 0)), so we can perform the above |
3771 | simplification if STORE_FLAG_VALUE is 1. */ |
3772 | |
3773 | if (is_a <scalar_int_mode> (m: mode, result: &int_mode) |
3774 | && STORE_FLAG_VALUE == 1 |
3775 | && trueop1 == const1_rtx |
3776 | && GET_CODE (op0) == LSHIFTRT |
3777 | && CONST_INT_P (XEXP (op0, 1)) |
3778 | && INTVAL (XEXP (op0, 1)) == GET_MODE_PRECISION (mode: int_mode) - 1) |
3779 | return gen_rtx_GE (int_mode, XEXP (op0, 0), const0_rtx); |
3780 | |
3781 | /* (xor (comparison foo bar) (const_int sign-bit)) |
3782 | when STORE_FLAG_VALUE is the sign bit. */ |
3783 | if (is_a <scalar_int_mode> (m: mode, result: &int_mode) |
3784 | && val_signbit_p (mode: int_mode, STORE_FLAG_VALUE) |
3785 | && trueop1 == const_true_rtx |
3786 | && COMPARISON_P (op0) |
3787 | && (reversed = reversed_comparison (op0, int_mode))) |
3788 | return reversed; |
3789 | |
3790 | /* Convert (xor (and A C) (and B C)) into (and (xor A B) C). */ |
3791 | if (GET_CODE (op0) == GET_CODE (op1) |
3792 | && (GET_CODE (op0) == AND |
3793 | || GET_CODE (op0) == LSHIFTRT |
3794 | || GET_CODE (op0) == ASHIFTRT |
3795 | || GET_CODE (op0) == ASHIFT |
3796 | || GET_CODE (op0) == ROTATE |
3797 | || GET_CODE (op0) == ROTATERT)) |
3798 | { |
3799 | tem = simplify_distributive_operation (code, mode, op0, op1); |
3800 | if (tem) |
3801 | return tem; |
3802 | } |
3803 | |
3804 | tem = simplify_byte_swapping_operation (code, mode, op0, op1); |
3805 | if (tem) |
3806 | return tem; |
3807 | |
3808 | tem = simplify_associative_operation (code, mode, op0, op1); |
3809 | if (tem) |
3810 | return tem; |
3811 | break; |
3812 | |
3813 | case AND: |
3814 | if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) |
3815 | return trueop1; |
3816 | if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode)) |
3817 | return op0; |
3818 | if (HWI_COMPUTABLE_MODE_P (mode)) |
3819 | { |
3820 | /* When WORD_REGISTER_OPERATIONS is true, we need to know the |
3821 | nonzero bits in WORD_MODE rather than MODE. */ |
3822 | scalar_int_mode tmode = as_a <scalar_int_mode> (m: mode); |
3823 | if (WORD_REGISTER_OPERATIONS |
3824 | && GET_MODE_BITSIZE (mode: tmode) < BITS_PER_WORD) |
3825 | tmode = word_mode; |
3826 | HOST_WIDE_INT nzop0 = nonzero_bits (trueop0, tmode); |
3827 | HOST_WIDE_INT nzop1; |
3828 | if (CONST_INT_P (trueop1)) |
3829 | { |
3830 | HOST_WIDE_INT val1 = INTVAL (trueop1); |
3831 | /* If we are turning off bits already known off in OP0, we need |
3832 | not do an AND. */ |
3833 | if ((nzop0 & ~val1) == 0) |
3834 | return op0; |
3835 | } |
3836 | nzop1 = nonzero_bits (trueop1, mode); |
3837 | /* If we are clearing all the nonzero bits, the result is zero. */ |
3838 | if ((nzop1 & nzop0) == 0 |
3839 | && !side_effects_p (op0) && !side_effects_p (op1)) |
3840 | return CONST0_RTX (mode); |
3841 | } |
3842 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0) |
3843 | && GET_MODE_CLASS (mode) != MODE_CC) |
3844 | return op0; |
3845 | /* A & (~A) -> 0 */ |
3846 | if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) |
3847 | || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) |
3848 | && ! side_effects_p (op0) |
3849 | && GET_MODE_CLASS (mode) != MODE_CC) |
3850 | return CONST0_RTX (mode); |
3851 | |
3852 | /* Transform (and (extend X) C) into (zero_extend (and X C)) if |
3853 | there are no nonzero bits of C outside of X's mode. */ |
3854 | if ((GET_CODE (op0) == SIGN_EXTEND |
3855 | || GET_CODE (op0) == ZERO_EXTEND) |
3856 | && CONST_SCALAR_INT_P (trueop1) |
3857 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
3858 | && is_a <scalar_int_mode> (GET_MODE (XEXP (op0, 0)), result: &inner_mode) |
3859 | && (wi::mask (width: GET_MODE_PRECISION (mode: inner_mode), negate_p: true, |
3860 | precision: GET_MODE_PRECISION (mode: int_mode)) |
3861 | & rtx_mode_t (trueop1, mode)) == 0) |
3862 | { |
3863 | machine_mode imode = GET_MODE (XEXP (op0, 0)); |
3864 | tem = immed_wide_int_const (rtx_mode_t (trueop1, mode), imode); |
3865 | tem = simplify_gen_binary (code: AND, mode: imode, XEXP (op0, 0), op1: tem); |
3866 | return simplify_gen_unary (code: ZERO_EXTEND, mode, op: tem, op_mode: imode); |
3867 | } |
3868 | |
3869 | /* Transform (and (truncate X) C) into (truncate (and X C)). This way |
3870 | we might be able to further simplify the AND with X and potentially |
3871 | remove the truncation altogether. */ |
3872 | if (GET_CODE (op0) == TRUNCATE && CONST_INT_P (trueop1)) |
3873 | { |
3874 | rtx x = XEXP (op0, 0); |
3875 | machine_mode xmode = GET_MODE (x); |
3876 | tem = simplify_gen_binary (code: AND, mode: xmode, op0: x, |
3877 | op1: gen_int_mode (INTVAL (trueop1), xmode)); |
3878 | return simplify_gen_unary (code: TRUNCATE, mode, op: tem, op_mode: xmode); |
3879 | } |
3880 | |
3881 | /* Canonicalize (A | C1) & C2 as (A & C2) | (C1 & C2). */ |
3882 | if (GET_CODE (op0) == IOR |
3883 | && CONST_INT_P (trueop1) |
3884 | && CONST_INT_P (XEXP (op0, 1))) |
3885 | { |
3886 | HOST_WIDE_INT tmp = INTVAL (trueop1) & INTVAL (XEXP (op0, 1)); |
3887 | return simplify_gen_binary (code: IOR, mode, |
3888 | op0: simplify_gen_binary (code: AND, mode, |
3889 | XEXP (op0, 0), op1), |
3890 | op1: gen_int_mode (tmp, mode)); |
3891 | } |
3892 | |
3893 | /* Convert (A ^ B) & A to A & (~B) since the latter is often a single |
3894 | insn (and may simplify more). */ |
3895 | if (GET_CODE (op0) == XOR |
3896 | && rtx_equal_p (XEXP (op0, 0), op1) |
3897 | && ! side_effects_p (op1)) |
3898 | return simplify_gen_binary (code: AND, mode, |
3899 | op0: simplify_gen_unary (code: NOT, mode, |
3900 | XEXP (op0, 1), op_mode: mode), |
3901 | op1); |
3902 | |
3903 | if (GET_CODE (op0) == XOR |
3904 | && rtx_equal_p (XEXP (op0, 1), op1) |
3905 | && ! side_effects_p (op1)) |
3906 | return simplify_gen_binary (code: AND, mode, |
3907 | op0: simplify_gen_unary (code: NOT, mode, |
3908 | XEXP (op0, 0), op_mode: mode), |
3909 | op1); |
3910 | |
3911 | /* Similarly for (~(A ^ B)) & A. */ |
3912 | if (GET_CODE (op0) == NOT |
3913 | && GET_CODE (XEXP (op0, 0)) == XOR |
3914 | && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1) |
3915 | && ! side_effects_p (op1)) |
3916 | return simplify_gen_binary (code: AND, mode, XEXP (XEXP (op0, 0), 1), op1); |
3917 | |
3918 | if (GET_CODE (op0) == NOT |
3919 | && GET_CODE (XEXP (op0, 0)) == XOR |
3920 | && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1) |
3921 | && ! side_effects_p (op1)) |
3922 | return simplify_gen_binary (code: AND, mode, XEXP (XEXP (op0, 0), 0), op1); |
3923 | |
3924 | /* Convert (A | B) & A to A. */ |
3925 | if (GET_CODE (op0) == IOR |
3926 | && (rtx_equal_p (XEXP (op0, 0), op1) |
3927 | || rtx_equal_p (XEXP (op0, 1), op1)) |
3928 | && ! side_effects_p (XEXP (op0, 0)) |
3929 | && ! side_effects_p (XEXP (op0, 1))) |
3930 | return op1; |
3931 | |
3932 | /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M, |
3933 | ((A & N) + B) & M -> (A + B) & M |
3934 | Similarly if (N & M) == 0, |
3935 | ((A | N) + B) & M -> (A + B) & M |
3936 | and for - instead of + and/or ^ instead of |. |
3937 | Also, if (N & M) == 0, then |
3938 | (A +- N) & M -> A & M. */ |
3939 | if (CONST_INT_P (trueop1) |
3940 | && HWI_COMPUTABLE_MODE_P (mode) |
3941 | && ~UINTVAL (trueop1) |
3942 | && (UINTVAL (trueop1) & (UINTVAL (trueop1) + 1)) == 0 |
3943 | && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS)) |
3944 | { |
3945 | rtx pmop[2]; |
3946 | int which; |
3947 | |
3948 | pmop[0] = XEXP (op0, 0); |
3949 | pmop[1] = XEXP (op0, 1); |
3950 | |
3951 | if (CONST_INT_P (pmop[1]) |
3952 | && (UINTVAL (pmop[1]) & UINTVAL (trueop1)) == 0) |
3953 | return simplify_gen_binary (code: AND, mode, op0: pmop[0], op1); |
3954 | |
3955 | for (which = 0; which < 2; which++) |
3956 | { |
3957 | tem = pmop[which]; |
3958 | switch (GET_CODE (tem)) |
3959 | { |
3960 | case AND: |
3961 | if (CONST_INT_P (XEXP (tem, 1)) |
3962 | && (UINTVAL (XEXP (tem, 1)) & UINTVAL (trueop1)) |
3963 | == UINTVAL (trueop1)) |
3964 | pmop[which] = XEXP (tem, 0); |
3965 | break; |
3966 | case IOR: |
3967 | case XOR: |
3968 | if (CONST_INT_P (XEXP (tem, 1)) |
3969 | && (UINTVAL (XEXP (tem, 1)) & UINTVAL (trueop1)) == 0) |
3970 | pmop[which] = XEXP (tem, 0); |
3971 | break; |
3972 | default: |
3973 | break; |
3974 | } |
3975 | } |
3976 | |
3977 | if (pmop[0] != XEXP (op0, 0) || pmop[1] != XEXP (op0, 1)) |
3978 | { |
3979 | tem = simplify_gen_binary (GET_CODE (op0), mode, |
3980 | op0: pmop[0], op1: pmop[1]); |
3981 | return simplify_gen_binary (code, mode, op0: tem, op1); |
3982 | } |
3983 | } |
3984 | |
3985 | /* (and X (ior (not X) Y) -> (and X Y) */ |
3986 | if (GET_CODE (op1) == IOR |
3987 | && GET_CODE (XEXP (op1, 0)) == NOT |
3988 | && rtx_equal_p (op0, XEXP (XEXP (op1, 0), 0))) |
3989 | return simplify_gen_binary (code: AND, mode, op0, XEXP (op1, 1)); |
3990 | |
3991 | /* (and (ior (not X) Y) X) -> (and X Y) */ |
3992 | if (GET_CODE (op0) == IOR |
3993 | && GET_CODE (XEXP (op0, 0)) == NOT |
3994 | && rtx_equal_p (op1, XEXP (XEXP (op0, 0), 0))) |
3995 | return simplify_gen_binary (code: AND, mode, op0: op1, XEXP (op0, 1)); |
3996 | |
3997 | /* (and X (ior Y (not X)) -> (and X Y) */ |
3998 | if (GET_CODE (op1) == IOR |
3999 | && GET_CODE (XEXP (op1, 1)) == NOT |
4000 | && rtx_equal_p (op0, XEXP (XEXP (op1, 1), 0))) |
4001 | return simplify_gen_binary (code: AND, mode, op0, XEXP (op1, 0)); |
4002 | |
4003 | /* (and (ior Y (not X)) X) -> (and X Y) */ |
4004 | if (GET_CODE (op0) == IOR |
4005 | && GET_CODE (XEXP (op0, 1)) == NOT |
4006 | && rtx_equal_p (op1, XEXP (XEXP (op0, 1), 0))) |
4007 | return simplify_gen_binary (code: AND, mode, op0: op1, XEXP (op0, 0)); |
4008 | |
4009 | /* Convert (and (ior A C) (ior B C)) into (ior (and A B) C). */ |
4010 | if (GET_CODE (op0) == GET_CODE (op1) |
4011 | && (GET_CODE (op0) == AND |
4012 | || GET_CODE (op0) == IOR |
4013 | || GET_CODE (op0) == LSHIFTRT |
4014 | || GET_CODE (op0) == ASHIFTRT |
4015 | || GET_CODE (op0) == ASHIFT |
4016 | || GET_CODE (op0) == ROTATE |
4017 | || GET_CODE (op0) == ROTATERT)) |
4018 | { |
4019 | tem = simplify_distributive_operation (code, mode, op0, op1); |
4020 | if (tem) |
4021 | return tem; |
4022 | } |
4023 | |
4024 | tem = simplify_byte_swapping_operation (code, mode, op0, op1); |
4025 | if (tem) |
4026 | return tem; |
4027 | |
4028 | tem = simplify_associative_operation (code, mode, op0, op1); |
4029 | if (tem) |
4030 | return tem; |
4031 | break; |
4032 | |
4033 | case UDIV: |
4034 | /* 0/x is 0 (or x&0 if x has side-effects). */ |
4035 | if (trueop0 == CONST0_RTX (mode) |
4036 | && !cfun->can_throw_non_call_exceptions) |
4037 | { |
4038 | if (side_effects_p (op1)) |
4039 | return simplify_gen_binary (code: AND, mode, op0: op1, op1: trueop0); |
4040 | return trueop0; |
4041 | } |
4042 | /* x/1 is x. */ |
4043 | if (trueop1 == CONST1_RTX (mode)) |
4044 | { |
4045 | tem = rtl_hooks.gen_lowpart_no_emit (mode, op0); |
4046 | if (tem) |
4047 | return tem; |
4048 | } |
4049 | /* Convert divide by power of two into shift. */ |
4050 | if (CONST_INT_P (trueop1) |
4051 | && (val = exact_log2 (UINTVAL (trueop1))) > 0) |
4052 | return simplify_gen_binary (code: LSHIFTRT, mode, op0, |
4053 | op1: gen_int_shift_amount (mode, val)); |
4054 | break; |
4055 | |
4056 | case DIV: |
4057 | /* Handle floating point and integers separately. */ |
4058 | if (SCALAR_FLOAT_MODE_P (mode)) |
4059 | { |
4060 | /* Maybe change 0.0 / x to 0.0. This transformation isn't |
4061 | safe for modes with NaNs, since 0.0 / 0.0 will then be |
4062 | NaN rather than 0.0. Nor is it safe for modes with signed |
4063 | zeros, since dividing 0 by a negative number gives -0.0 */ |
4064 | if (trueop0 == CONST0_RTX (mode) |
4065 | && !HONOR_NANS (mode) |
4066 | && !HONOR_SIGNED_ZEROS (mode) |
4067 | && ! side_effects_p (op1)) |
4068 | return op0; |
4069 | /* x/1.0 is x. */ |
4070 | if (trueop1 == CONST1_RTX (mode) |
4071 | && !HONOR_SNANS (mode)) |
4072 | return op0; |
4073 | |
4074 | if (CONST_DOUBLE_AS_FLOAT_P (trueop1) |
4075 | && trueop1 != CONST0_RTX (mode)) |
4076 | { |
4077 | const REAL_VALUE_TYPE *d1 = CONST_DOUBLE_REAL_VALUE (trueop1); |
4078 | |
4079 | /* x/-1.0 is -x. */ |
4080 | if (real_equal (d1, &dconstm1) |
4081 | && !HONOR_SNANS (mode)) |
4082 | return simplify_gen_unary (code: NEG, mode, op: op0, op_mode: mode); |
4083 | |
4084 | /* Change FP division by a constant into multiplication. |
4085 | Only do this with -freciprocal-math. */ |
4086 | if (flag_reciprocal_math |
4087 | && !real_equal (d1, &dconst0)) |
4088 | { |
4089 | REAL_VALUE_TYPE d; |
4090 | real_arithmetic (&d, RDIV_EXPR, &dconst1, d1); |
4091 | tem = const_double_from_real_value (d, mode); |
4092 | return simplify_gen_binary (code: MULT, mode, op0, op1: tem); |
4093 | } |
4094 | } |
4095 | } |
4096 | else if (SCALAR_INT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_VECTOR_INT) |
4097 | { |
4098 | /* 0/x is 0 (or x&0 if x has side-effects). */ |
4099 | if (trueop0 == CONST0_RTX (mode) |
4100 | && !cfun->can_throw_non_call_exceptions) |
4101 | { |
4102 | if (side_effects_p (op1)) |
4103 | return simplify_gen_binary (code: AND, mode, op0: op1, op1: trueop0); |
4104 | return trueop0; |
4105 | } |
4106 | /* x/1 is x. */ |
4107 | if (trueop1 == CONST1_RTX (mode)) |
4108 | { |
4109 | tem = rtl_hooks.gen_lowpart_no_emit (mode, op0); |
4110 | if (tem) |
4111 | return tem; |
4112 | } |
4113 | /* x/-1 is -x. */ |
4114 | if (trueop1 == CONSTM1_RTX (mode)) |
4115 | { |
4116 | rtx x = rtl_hooks.gen_lowpart_no_emit (mode, op0); |
4117 | if (x) |
4118 | return simplify_gen_unary (code: NEG, mode, op: x, op_mode: mode); |
4119 | } |
4120 | } |
4121 | break; |
4122 | |
4123 | case UMOD: |
4124 | /* 0%x is 0 (or x&0 if x has side-effects). */ |
4125 | if (trueop0 == CONST0_RTX (mode)) |
4126 | { |
4127 | if (side_effects_p (op1)) |
4128 | return simplify_gen_binary (code: AND, mode, op0: op1, op1: trueop0); |
4129 | return trueop0; |
4130 | } |
4131 | /* x%1 is 0 (of x&0 if x has side-effects). */ |
4132 | if (trueop1 == CONST1_RTX (mode)) |
4133 | { |
4134 | if (side_effects_p (op0)) |
4135 | return simplify_gen_binary (code: AND, mode, op0, CONST0_RTX (mode)); |
4136 | return CONST0_RTX (mode); |
4137 | } |
4138 | /* Implement modulus by power of two as AND. */ |
4139 | if (CONST_INT_P (trueop1) |
4140 | && exact_log2 (UINTVAL (trueop1)) > 0) |
4141 | return simplify_gen_binary (code: AND, mode, op0, |
4142 | op1: gen_int_mode (UINTVAL (trueop1) - 1, |
4143 | mode)); |
4144 | break; |
4145 | |
4146 | case MOD: |
4147 | /* 0%x is 0 (or x&0 if x has side-effects). */ |
4148 | if (trueop0 == CONST0_RTX (mode)) |
4149 | { |
4150 | if (side_effects_p (op1)) |
4151 | return simplify_gen_binary (code: AND, mode, op0: op1, op1: trueop0); |
4152 | return trueop0; |
4153 | } |
4154 | /* x%1 and x%-1 is 0 (or x&0 if x has side-effects). */ |
4155 | if (trueop1 == CONST1_RTX (mode) || trueop1 == constm1_rtx) |
4156 | { |
4157 | if (side_effects_p (op0)) |
4158 | return simplify_gen_binary (code: AND, mode, op0, CONST0_RTX (mode)); |
4159 | return CONST0_RTX (mode); |
4160 | } |
4161 | break; |
4162 | |
4163 | case ROTATERT: |
4164 | case ROTATE: |
4165 | if (trueop1 == CONST0_RTX (mode)) |
4166 | return op0; |
4167 | /* Canonicalize rotates by constant amount. If the condition of |
4168 | reversing direction is met, then reverse the direction. */ |
4169 | #if defined(HAVE_rotate) && defined(HAVE_rotatert) |
4170 | if (reverse_rotate_by_imm_p (mode, left: (code == ROTATE), op1: trueop1)) |
4171 | { |
4172 | int new_amount = GET_MODE_UNIT_PRECISION (mode) - INTVAL (trueop1); |
4173 | rtx new_amount_rtx = gen_int_shift_amount (mode, new_amount); |
4174 | return simplify_gen_binary (code: code == ROTATE ? ROTATERT : ROTATE, |
4175 | mode, op0, op1: new_amount_rtx); |
4176 | } |
4177 | #endif |
4178 | /* FALLTHRU */ |
4179 | case ASHIFTRT: |
4180 | if (trueop1 == CONST0_RTX (mode)) |
4181 | return op0; |
4182 | if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) |
4183 | return op0; |
4184 | /* Rotating ~0 always results in ~0. */ |
4185 | if (CONST_INT_P (trueop0) |
4186 | && HWI_COMPUTABLE_MODE_P (mode) |
4187 | && UINTVAL (trueop0) == GET_MODE_MASK (mode) |
4188 | && ! side_effects_p (op1)) |
4189 | return op0; |
4190 | |
4191 | canonicalize_shift: |
4192 | /* Given: |
4193 | scalar modes M1, M2 |
4194 | scalar constants c1, c2 |
4195 | size (M2) > size (M1) |
4196 | c1 == size (M2) - size (M1) |
4197 | optimize: |
4198 | ([a|l]shiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) (const_int <c1>)) |
4199 | <low_part>) |
4200 | (const_int <c2>)) |
4201 | to: |
4202 | (subreg:M1 ([a|l]shiftrt:M2 (reg:M2) (const_int <c1 + c2>)) |
4203 | <low_part>). */ |
4204 | if ((code == ASHIFTRT || code == LSHIFTRT) |
4205 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
4206 | && SUBREG_P (op0) |
4207 | && CONST_INT_P (op1) |
4208 | && GET_CODE (SUBREG_REG (op0)) == LSHIFTRT |
4209 | && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op0)), |
4210 | result: &inner_mode) |
4211 | && CONST_INT_P (XEXP (SUBREG_REG (op0), 1)) |
4212 | && GET_MODE_BITSIZE (mode: inner_mode) > GET_MODE_BITSIZE (mode: int_mode) |
4213 | && (INTVAL (XEXP (SUBREG_REG (op0), 1)) |
4214 | == GET_MODE_BITSIZE (mode: inner_mode) - GET_MODE_BITSIZE (mode: int_mode)) |
4215 | && subreg_lowpart_p (op0)) |
4216 | { |
4217 | rtx tmp = gen_int_shift_amount |
4218 | (inner_mode, INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (op1)); |
4219 | |
4220 | /* Combine would usually zero out the value when combining two |
4221 | local shifts and the range becomes larger or equal to the mode. |
4222 | However since we fold away one of the shifts here combine won't |
4223 | see it so we should immediately zero the result if it's out of |
4224 | range. */ |
4225 | if (code == LSHIFTRT |
4226 | && INTVAL (tmp) >= GET_MODE_BITSIZE (mode: inner_mode)) |
4227 | tmp = const0_rtx; |
4228 | else |
4229 | tmp = simplify_gen_binary (code, |
4230 | mode: inner_mode, |
4231 | XEXP (SUBREG_REG (op0), 0), |
4232 | op1: tmp); |
4233 | |
4234 | return lowpart_subreg (int_mode, tmp, inner_mode); |
4235 | } |
4236 | |
4237 | if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1)) |
4238 | { |
4239 | val = INTVAL (op1) & (GET_MODE_UNIT_PRECISION (mode) - 1); |
4240 | if (val != INTVAL (op1)) |
4241 | return simplify_gen_binary (code, mode, op0, |
4242 | op1: gen_int_shift_amount (mode, val)); |
4243 | } |
4244 | break; |
4245 | |
4246 | case SS_ASHIFT: |
4247 | if (CONST_INT_P (trueop0) |
4248 | && HWI_COMPUTABLE_MODE_P (mode) |
4249 | && (UINTVAL (trueop0) == (GET_MODE_MASK (mode) >> 1) |
4250 | || mode_signbit_p (mode, x: trueop0)) |
4251 | && ! side_effects_p (op1)) |
4252 | return op0; |
4253 | goto simplify_ashift; |
4254 | |
4255 | case US_ASHIFT: |
4256 | if (CONST_INT_P (trueop0) |
4257 | && HWI_COMPUTABLE_MODE_P (mode) |
4258 | && UINTVAL (trueop0) == GET_MODE_MASK (mode) |
4259 | && ! side_effects_p (op1)) |
4260 | return op0; |
4261 | /* FALLTHRU */ |
4262 | |
4263 | case ASHIFT: |
4264 | simplify_ashift: |
4265 | if (trueop1 == CONST0_RTX (mode)) |
4266 | return op0; |
4267 | if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) |
4268 | return op0; |
4269 | if (mem_depth |
4270 | && code == ASHIFT |
4271 | && CONST_INT_P (trueop1) |
4272 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
4273 | && IN_RANGE (UINTVAL (trueop1), |
4274 | 1, GET_MODE_PRECISION (int_mode) - 1)) |
4275 | { |
4276 | auto c = (wi::one (precision: GET_MODE_PRECISION (mode: int_mode)) |
4277 | << UINTVAL (trueop1)); |
4278 | rtx new_op1 = immed_wide_int_const (c, int_mode); |
4279 | return simplify_gen_binary (code: MULT, mode: int_mode, op0, op1: new_op1); |
4280 | } |
4281 | goto canonicalize_shift; |
4282 | |
4283 | case LSHIFTRT: |
4284 | if (trueop1 == CONST0_RTX (mode)) |
4285 | return op0; |
4286 | if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) |
4287 | return op0; |
4288 | /* Optimize (lshiftrt (clz X) C) as (eq X 0). */ |
4289 | if (GET_CODE (op0) == CLZ |
4290 | && is_a <scalar_int_mode> (GET_MODE (XEXP (op0, 0)), result: &inner_mode) |
4291 | && CONST_INT_P (trueop1) |
4292 | && STORE_FLAG_VALUE == 1 |
4293 | && INTVAL (trueop1) < GET_MODE_UNIT_PRECISION (mode)) |
4294 | { |
4295 | unsigned HOST_WIDE_INT zero_val = 0; |
4296 | |
4297 | if (CLZ_DEFINED_VALUE_AT_ZERO (inner_mode, zero_val) |
4298 | && zero_val == GET_MODE_PRECISION (mode: inner_mode) |
4299 | && INTVAL (trueop1) == exact_log2 (x: zero_val)) |
4300 | return simplify_gen_relational (code: EQ, mode, cmp_mode: inner_mode, |
4301 | XEXP (op0, 0), const0_rtx); |
4302 | } |
4303 | goto canonicalize_shift; |
4304 | |
4305 | case SMIN: |
4306 | if (HWI_COMPUTABLE_MODE_P (mode) |
4307 | && mode_signbit_p (mode, x: trueop1) |
4308 | && ! side_effects_p (op0)) |
4309 | return op1; |
4310 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) |
4311 | return op0; |
4312 | tem = simplify_associative_operation (code, mode, op0, op1); |
4313 | if (tem) |
4314 | return tem; |
4315 | break; |
4316 | |
4317 | case SMAX: |
4318 | if (HWI_COMPUTABLE_MODE_P (mode) |
4319 | && CONST_INT_P (trueop1) |
4320 | && (UINTVAL (trueop1) == GET_MODE_MASK (mode) >> 1) |
4321 | && ! side_effects_p (op0)) |
4322 | return op1; |
4323 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) |
4324 | return op0; |
4325 | tem = simplify_associative_operation (code, mode, op0, op1); |
4326 | if (tem) |
4327 | return tem; |
4328 | break; |
4329 | |
4330 | case UMIN: |
4331 | if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) |
4332 | return op1; |
4333 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) |
4334 | return op0; |
4335 | tem = simplify_associative_operation (code, mode, op0, op1); |
4336 | if (tem) |
4337 | return tem; |
4338 | break; |
4339 | |
4340 | case UMAX: |
4341 | if (trueop1 == constm1_rtx && ! side_effects_p (op0)) |
4342 | return op1; |
4343 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) |
4344 | return op0; |
4345 | tem = simplify_associative_operation (code, mode, op0, op1); |
4346 | if (tem) |
4347 | return tem; |
4348 | break; |
4349 | |
4350 | case SS_PLUS: |
4351 | case US_PLUS: |
4352 | case SS_MINUS: |
4353 | case US_MINUS: |
4354 | /* Simplify x +/- 0 to x, if possible. */ |
4355 | if (trueop1 == CONST0_RTX (mode)) |
4356 | return op0; |
4357 | return 0; |
4358 | |
4359 | case SS_MULT: |
4360 | case US_MULT: |
4361 | /* Simplify x * 0 to 0, if possible. */ |
4362 | if (trueop1 == CONST0_RTX (mode) |
4363 | && !side_effects_p (op0)) |
4364 | return op1; |
4365 | |
4366 | /* Simplify x * 1 to x, if possible. */ |
4367 | if (trueop1 == CONST1_RTX (mode)) |
4368 | return op0; |
4369 | return 0; |
4370 | |
4371 | case SMUL_HIGHPART: |
4372 | case UMUL_HIGHPART: |
4373 | /* Simplify x * 0 to 0, if possible. */ |
4374 | if (trueop1 == CONST0_RTX (mode) |
4375 | && !side_effects_p (op0)) |
4376 | return op1; |
4377 | return 0; |
4378 | |
4379 | case SS_DIV: |
4380 | case US_DIV: |
4381 | /* Simplify x / 1 to x, if possible. */ |
4382 | if (trueop1 == CONST1_RTX (mode)) |
4383 | return op0; |
4384 | return 0; |
4385 | |
4386 | case COPYSIGN: |
4387 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) |
4388 | return op0; |
4389 | if (CONST_DOUBLE_AS_FLOAT_P (trueop1)) |
4390 | { |
4391 | REAL_VALUE_TYPE f1; |
4392 | real_convert (&f1, mode, CONST_DOUBLE_REAL_VALUE (trueop1)); |
4393 | rtx tmp = simplify_gen_unary (code: ABS, mode, op: op0, op_mode: mode); |
4394 | if (REAL_VALUE_NEGATIVE (f1)) |
4395 | tmp = simplify_unary_operation (code: NEG, mode, op: tmp, op_mode: mode); |
4396 | return tmp; |
4397 | } |
4398 | if (GET_CODE (op0) == NEG || GET_CODE (op0) == ABS) |
4399 | return simplify_gen_binary (code: COPYSIGN, mode, XEXP (op0, 0), op1); |
4400 | if (GET_CODE (op1) == ABS |
4401 | && ! side_effects_p (op1)) |
4402 | return simplify_gen_unary (code: ABS, mode, op: op0, op_mode: mode); |
4403 | if (GET_CODE (op0) == COPYSIGN |
4404 | && ! side_effects_p (XEXP (op0, 1))) |
4405 | return simplify_gen_binary (code: COPYSIGN, mode, XEXP (op0, 0), op1); |
4406 | if (GET_CODE (op1) == COPYSIGN |
4407 | && ! side_effects_p (XEXP (op1, 0))) |
4408 | return simplify_gen_binary (code: COPYSIGN, mode, op0, XEXP (op1, 1)); |
4409 | return 0; |
4410 | |
4411 | case VEC_SERIES: |
4412 | if (op1 == CONST0_RTX (GET_MODE_INNER (mode))) |
4413 | return gen_vec_duplicate (mode, op0); |
4414 | if (valid_for_const_vector_p (mode, op0) |
4415 | && valid_for_const_vector_p (mode, op1)) |
4416 | return gen_const_vec_series (mode, op0, op1); |
4417 | return 0; |
4418 | |
4419 | case VEC_SELECT: |
4420 | if (!VECTOR_MODE_P (mode)) |
4421 | { |
4422 | gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); |
4423 | gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0))); |
4424 | gcc_assert (GET_CODE (trueop1) == PARALLEL); |
4425 | gcc_assert (XVECLEN (trueop1, 0) == 1); |
4426 | |
4427 | /* We can't reason about selections made at runtime. */ |
4428 | if (!CONST_INT_P (XVECEXP (trueop1, 0, 0))) |
4429 | return 0; |
4430 | |
4431 | if (vec_duplicate_p (x: trueop0, elt: &elt0)) |
4432 | return elt0; |
4433 | |
4434 | if (GET_CODE (trueop0) == CONST_VECTOR) |
4435 | return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP |
4436 | (trueop1, 0, 0))); |
4437 | |
4438 | /* Extract a scalar element from a nested VEC_SELECT expression |
4439 | (with optional nested VEC_CONCAT expression). Some targets |
4440 | (i386) extract scalar element from a vector using chain of |
4441 | nested VEC_SELECT expressions. When input operand is a memory |
4442 | operand, this operation can be simplified to a simple scalar |
4443 | load from an offseted memory address. */ |
4444 | int n_elts; |
4445 | if (GET_CODE (trueop0) == VEC_SELECT |
4446 | && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 0))) |
4447 | .is_constant (const_value: &n_elts))) |
4448 | { |
4449 | rtx op0 = XEXP (trueop0, 0); |
4450 | rtx op1 = XEXP (trueop0, 1); |
4451 | |
4452 | int i = INTVAL (XVECEXP (trueop1, 0, 0)); |
4453 | int elem; |
4454 | |
4455 | rtvec vec; |
4456 | rtx tmp_op, tmp; |
4457 | |
4458 | gcc_assert (GET_CODE (op1) == PARALLEL); |
4459 | gcc_assert (i < n_elts); |
4460 | |
4461 | /* Select element, pointed by nested selector. */ |
4462 | elem = INTVAL (XVECEXP (op1, 0, i)); |
4463 | |
4464 | /* Handle the case when nested VEC_SELECT wraps VEC_CONCAT. */ |
4465 | if (GET_CODE (op0) == VEC_CONCAT) |
4466 | { |
4467 | rtx op00 = XEXP (op0, 0); |
4468 | rtx op01 = XEXP (op0, 1); |
4469 | |
4470 | machine_mode mode00, mode01; |
4471 | int n_elts00, n_elts01; |
4472 | |
4473 | mode00 = GET_MODE (op00); |
4474 | mode01 = GET_MODE (op01); |
4475 | |
4476 | /* Find out the number of elements of each operand. |
4477 | Since the concatenated result has a constant number |
4478 | of elements, the operands must too. */ |
4479 | n_elts00 = GET_MODE_NUNITS (mode: mode00).to_constant (); |
4480 | n_elts01 = GET_MODE_NUNITS (mode: mode01).to_constant (); |
4481 | |
4482 | gcc_assert (n_elts == n_elts00 + n_elts01); |
4483 | |
4484 | /* Select correct operand of VEC_CONCAT |
4485 | and adjust selector. */ |
4486 | if (elem < n_elts01) |
4487 | tmp_op = op00; |
4488 | else |
4489 | { |
4490 | tmp_op = op01; |
4491 | elem -= n_elts00; |
4492 | } |
4493 | } |
4494 | else |
4495 | tmp_op = op0; |
4496 | |
4497 | vec = rtvec_alloc (1); |
4498 | RTVEC_ELT (vec, 0) = GEN_INT (elem); |
4499 | |
4500 | tmp = gen_rtx_fmt_ee (code, mode, |
4501 | tmp_op, gen_rtx_PARALLEL (VOIDmode, vec)); |
4502 | return tmp; |
4503 | } |
4504 | } |
4505 | else |
4506 | { |
4507 | gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); |
4508 | gcc_assert (GET_MODE_INNER (mode) |
4509 | == GET_MODE_INNER (GET_MODE (trueop0))); |
4510 | gcc_assert (GET_CODE (trueop1) == PARALLEL); |
4511 | |
4512 | if (vec_duplicate_p (x: trueop0, elt: &elt0)) |
4513 | /* It doesn't matter which elements are selected by trueop1, |
4514 | because they are all the same. */ |
4515 | return gen_vec_duplicate (mode, elt0); |
4516 | |
4517 | if (GET_CODE (trueop0) == CONST_VECTOR) |
4518 | { |
4519 | unsigned n_elts = XVECLEN (trueop1, 0); |
4520 | rtvec v = rtvec_alloc (n_elts); |
4521 | unsigned int i; |
4522 | |
4523 | gcc_assert (known_eq (n_elts, GET_MODE_NUNITS (mode))); |
4524 | for (i = 0; i < n_elts; i++) |
4525 | { |
4526 | rtx x = XVECEXP (trueop1, 0, i); |
4527 | |
4528 | if (!CONST_INT_P (x)) |
4529 | return 0; |
4530 | |
4531 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, |
4532 | INTVAL (x)); |
4533 | } |
4534 | |
4535 | return gen_rtx_CONST_VECTOR (mode, v); |
4536 | } |
4537 | |
4538 | /* Recognize the identity. */ |
4539 | if (GET_MODE (trueop0) == mode) |
4540 | { |
4541 | bool maybe_ident = true; |
4542 | for (int i = 0; i < XVECLEN (trueop1, 0); i++) |
4543 | { |
4544 | rtx j = XVECEXP (trueop1, 0, i); |
4545 | if (!CONST_INT_P (j) || INTVAL (j) != i) |
4546 | { |
4547 | maybe_ident = false; |
4548 | break; |
4549 | } |
4550 | } |
4551 | if (maybe_ident) |
4552 | return trueop0; |
4553 | } |
4554 | |
4555 | /* If we select a low-part subreg, return that. */ |
4556 | if (vec_series_lowpart_p (result_mode: mode, GET_MODE (trueop0), sel: trueop1)) |
4557 | { |
4558 | rtx new_rtx = lowpart_subreg (mode, trueop0, |
4559 | GET_MODE (trueop0)); |
4560 | if (new_rtx != NULL_RTX) |
4561 | return new_rtx; |
4562 | } |
4563 | |
4564 | /* If we build {a,b} then permute it, build the result directly. */ |
4565 | if (XVECLEN (trueop1, 0) == 2 |
4566 | && CONST_INT_P (XVECEXP (trueop1, 0, 0)) |
4567 | && CONST_INT_P (XVECEXP (trueop1, 0, 1)) |
4568 | && GET_CODE (trueop0) == VEC_CONCAT |
4569 | && GET_CODE (XEXP (trueop0, 0)) == VEC_CONCAT |
4570 | && GET_MODE (XEXP (trueop0, 0)) == mode |
4571 | && GET_CODE (XEXP (trueop0, 1)) == VEC_CONCAT |
4572 | && GET_MODE (XEXP (trueop0, 1)) == mode) |
4573 | { |
4574 | unsigned int i0 = INTVAL (XVECEXP (trueop1, 0, 0)); |
4575 | unsigned int i1 = INTVAL (XVECEXP (trueop1, 0, 1)); |
4576 | rtx subop0, subop1; |
4577 | |
4578 | gcc_assert (i0 < 4 && i1 < 4); |
4579 | subop0 = XEXP (XEXP (trueop0, i0 / 2), i0 % 2); |
4580 | subop1 = XEXP (XEXP (trueop0, i1 / 2), i1 % 2); |
4581 | |
4582 | return simplify_gen_binary (code: VEC_CONCAT, mode, op0: subop0, op1: subop1); |
4583 | } |
4584 | |
4585 | if (XVECLEN (trueop1, 0) == 2 |
4586 | && CONST_INT_P (XVECEXP (trueop1, 0, 0)) |
4587 | && CONST_INT_P (XVECEXP (trueop1, 0, 1)) |
4588 | && GET_CODE (trueop0) == VEC_CONCAT |
4589 | && GET_MODE (trueop0) == mode) |
4590 | { |
4591 | unsigned int i0 = INTVAL (XVECEXP (trueop1, 0, 0)); |
4592 | unsigned int i1 = INTVAL (XVECEXP (trueop1, 0, 1)); |
4593 | rtx subop0, subop1; |
4594 | |
4595 | gcc_assert (i0 < 2 && i1 < 2); |
4596 | subop0 = XEXP (trueop0, i0); |
4597 | subop1 = XEXP (trueop0, i1); |
4598 | |
4599 | return simplify_gen_binary (code: VEC_CONCAT, mode, op0: subop0, op1: subop1); |
4600 | } |
4601 | |
4602 | /* If we select one half of a vec_concat, return that. */ |
4603 | int l0, l1; |
4604 | if (GET_CODE (trueop0) == VEC_CONCAT |
4605 | && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 0))) |
4606 | .is_constant (const_value: &l0)) |
4607 | && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 1))) |
4608 | .is_constant (const_value: &l1)) |
4609 | && CONST_INT_P (XVECEXP (trueop1, 0, 0))) |
4610 | { |
4611 | rtx subop0 = XEXP (trueop0, 0); |
4612 | rtx subop1 = XEXP (trueop0, 1); |
4613 | machine_mode mode0 = GET_MODE (subop0); |
4614 | machine_mode mode1 = GET_MODE (subop1); |
4615 | int i0 = INTVAL (XVECEXP (trueop1, 0, 0)); |
4616 | if (i0 == 0 && !side_effects_p (op1) && mode == mode0) |
4617 | { |
4618 | bool success = true; |
4619 | for (int i = 1; i < l0; ++i) |
4620 | { |
4621 | rtx j = XVECEXP (trueop1, 0, i); |
4622 | if (!CONST_INT_P (j) || INTVAL (j) != i) |
4623 | { |
4624 | success = false; |
4625 | break; |
4626 | } |
4627 | } |
4628 | if (success) |
4629 | return subop0; |
4630 | } |
4631 | if (i0 == l0 && !side_effects_p (op0) && mode == mode1) |
4632 | { |
4633 | bool success = true; |
4634 | for (int i = 1; i < l1; ++i) |
4635 | { |
4636 | rtx j = XVECEXP (trueop1, 0, i); |
4637 | if (!CONST_INT_P (j) || INTVAL (j) != i0 + i) |
4638 | { |
4639 | success = false; |
4640 | break; |
4641 | } |
4642 | } |
4643 | if (success) |
4644 | return subop1; |
4645 | } |
4646 | } |
4647 | |
4648 | /* Simplify vec_select of a subreg of X to just a vec_select of X |
4649 | when X has same component mode as vec_select. */ |
4650 | unsigned HOST_WIDE_INT subreg_offset = 0; |
4651 | if (GET_CODE (trueop0) == SUBREG |
4652 | && GET_MODE_INNER (mode) |
4653 | == GET_MODE_INNER (GET_MODE (SUBREG_REG (trueop0))) |
4654 | && GET_MODE_NUNITS (mode).is_constant (const_value: &l1) |
4655 | && constant_multiple_p (a: subreg_memory_offset (trueop0), |
4656 | GET_MODE_UNIT_BITSIZE (mode), |
4657 | multiple: &subreg_offset)) |
4658 | { |
4659 | poly_uint64 nunits |
4660 | = GET_MODE_NUNITS (GET_MODE (SUBREG_REG (trueop0))); |
4661 | bool success = true; |
4662 | for (int i = 0; i != l1; i++) |
4663 | { |
4664 | rtx idx = XVECEXP (trueop1, 0, i); |
4665 | if (!CONST_INT_P (idx) |
4666 | || maybe_ge (UINTVAL (idx) + subreg_offset, nunits)) |
4667 | { |
4668 | success = false; |
4669 | break; |
4670 | } |
4671 | } |
4672 | |
4673 | if (success) |
4674 | { |
4675 | rtx par = trueop1; |
4676 | if (subreg_offset) |
4677 | { |
4678 | rtvec vec = rtvec_alloc (l1); |
4679 | for (int i = 0; i < l1; i++) |
4680 | RTVEC_ELT (vec, i) |
4681 | = GEN_INT (INTVAL (XVECEXP (trueop1, 0, i)) |
4682 | + subreg_offset); |
4683 | par = gen_rtx_PARALLEL (VOIDmode, vec); |
4684 | } |
4685 | return gen_rtx_VEC_SELECT (mode, SUBREG_REG (trueop0), par); |
4686 | } |
4687 | } |
4688 | } |
4689 | |
4690 | if (XVECLEN (trueop1, 0) == 1 |
4691 | && CONST_INT_P (XVECEXP (trueop1, 0, 0)) |
4692 | && GET_CODE (trueop0) == VEC_CONCAT) |
4693 | { |
4694 | rtx vec = trueop0; |
4695 | offset = INTVAL (XVECEXP (trueop1, 0, 0)) * GET_MODE_SIZE (mode); |
4696 | |
4697 | /* Try to find the element in the VEC_CONCAT. */ |
4698 | while (GET_MODE (vec) != mode |
4699 | && GET_CODE (vec) == VEC_CONCAT) |
4700 | { |
4701 | poly_int64 vec_size; |
4702 | |
4703 | if (CONST_INT_P (XEXP (vec, 0))) |
4704 | { |
4705 | /* vec_concat of two const_ints doesn't make sense with |
4706 | respect to modes. */ |
4707 | if (CONST_INT_P (XEXP (vec, 1))) |
4708 | return 0; |
4709 | |
4710 | vec_size = GET_MODE_SIZE (GET_MODE (trueop0)) |
4711 | - GET_MODE_SIZE (GET_MODE (XEXP (vec, 1))); |
4712 | } |
4713 | else |
4714 | vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0))); |
4715 | |
4716 | if (known_lt (offset, vec_size)) |
4717 | vec = XEXP (vec, 0); |
4718 | else if (known_ge (offset, vec_size)) |
4719 | { |
4720 | offset -= vec_size; |
4721 | vec = XEXP (vec, 1); |
4722 | } |
4723 | else |
4724 | break; |
4725 | vec = avoid_constant_pool_reference (x: vec); |
4726 | } |
4727 | |
4728 | if (GET_MODE (vec) == mode) |
4729 | return vec; |
4730 | } |
4731 | |
4732 | /* If we select elements in a vec_merge that all come from the same |
4733 | operand, select from that operand directly. */ |
4734 | if (GET_CODE (op0) == VEC_MERGE) |
4735 | { |
4736 | rtx trueop02 = avoid_constant_pool_reference (XEXP (op0, 2)); |
4737 | if (CONST_INT_P (trueop02)) |
4738 | { |
4739 | unsigned HOST_WIDE_INT sel = UINTVAL (trueop02); |
4740 | bool all_operand0 = true; |
4741 | bool all_operand1 = true; |
4742 | for (int i = 0; i < XVECLEN (trueop1, 0); i++) |
4743 | { |
4744 | rtx j = XVECEXP (trueop1, 0, i); |
4745 | if (sel & (HOST_WIDE_INT_1U << UINTVAL (j))) |
4746 | all_operand1 = false; |
4747 | else |
4748 | all_operand0 = false; |
4749 | } |
4750 | if (all_operand0 && !side_effects_p (XEXP (op0, 1))) |
4751 | return simplify_gen_binary (code: VEC_SELECT, mode, XEXP (op0, 0), op1); |
4752 | if (all_operand1 && !side_effects_p (XEXP (op0, 0))) |
4753 | return simplify_gen_binary (code: VEC_SELECT, mode, XEXP (op0, 1), op1); |
4754 | } |
4755 | } |
4756 | |
4757 | /* If we have two nested selects that are inverses of each |
4758 | other, replace them with the source operand. */ |
4759 | if (GET_CODE (trueop0) == VEC_SELECT |
4760 | && GET_MODE (XEXP (trueop0, 0)) == mode) |
4761 | { |
4762 | rtx op0_subop1 = XEXP (trueop0, 1); |
4763 | gcc_assert (GET_CODE (op0_subop1) == PARALLEL); |
4764 | gcc_assert (known_eq (XVECLEN (trueop1, 0), GET_MODE_NUNITS (mode))); |
4765 | |
4766 | /* Apply the outer ordering vector to the inner one. (The inner |
4767 | ordering vector is expressly permitted to be of a different |
4768 | length than the outer one.) If the result is { 0, 1, ..., n-1 } |
4769 | then the two VEC_SELECTs cancel. */ |
4770 | for (int i = 0; i < XVECLEN (trueop1, 0); ++i) |
4771 | { |
4772 | rtx x = XVECEXP (trueop1, 0, i); |
4773 | if (!CONST_INT_P (x)) |
4774 | return 0; |
4775 | rtx y = XVECEXP (op0_subop1, 0, INTVAL (x)); |
4776 | if (!CONST_INT_P (y) || i != INTVAL (y)) |
4777 | return 0; |
4778 | } |
4779 | return XEXP (trueop0, 0); |
4780 | } |
4781 | |
4782 | return 0; |
4783 | case VEC_CONCAT: |
4784 | { |
4785 | machine_mode op0_mode = (GET_MODE (trueop0) != VOIDmode |
4786 | ? GET_MODE (trueop0) |
4787 | : GET_MODE_INNER (mode)); |
4788 | machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode |
4789 | ? GET_MODE (trueop1) |
4790 | : GET_MODE_INNER (mode)); |
4791 | |
4792 | gcc_assert (VECTOR_MODE_P (mode)); |
4793 | gcc_assert (known_eq (GET_MODE_SIZE (op0_mode) |
4794 | + GET_MODE_SIZE (op1_mode), |
4795 | GET_MODE_SIZE (mode))); |
4796 | |
4797 | if (VECTOR_MODE_P (op0_mode)) |
4798 | gcc_assert (GET_MODE_INNER (mode) |
4799 | == GET_MODE_INNER (op0_mode)); |
4800 | else |
4801 | gcc_assert (GET_MODE_INNER (mode) == op0_mode); |
4802 | |
4803 | if (VECTOR_MODE_P (op1_mode)) |
4804 | gcc_assert (GET_MODE_INNER (mode) |
4805 | == GET_MODE_INNER (op1_mode)); |
4806 | else |
4807 | gcc_assert (GET_MODE_INNER (mode) == op1_mode); |
4808 | |
4809 | unsigned int n_elts, in_n_elts; |
4810 | if ((GET_CODE (trueop0) == CONST_VECTOR |
4811 | || CONST_SCALAR_INT_P (trueop0) |
4812 | || CONST_DOUBLE_AS_FLOAT_P (trueop0)) |
4813 | && (GET_CODE (trueop1) == CONST_VECTOR |
4814 | || CONST_SCALAR_INT_P (trueop1) |
4815 | || CONST_DOUBLE_AS_FLOAT_P (trueop1)) |
4816 | && GET_MODE_NUNITS (mode).is_constant (const_value: &n_elts) |
4817 | && GET_MODE_NUNITS (mode: op0_mode).is_constant (const_value: &in_n_elts)) |
4818 | { |
4819 | rtvec v = rtvec_alloc (n_elts); |
4820 | unsigned int i; |
4821 | for (i = 0; i < n_elts; i++) |
4822 | { |
4823 | if (i < in_n_elts) |
4824 | { |
4825 | if (!VECTOR_MODE_P (op0_mode)) |
4826 | RTVEC_ELT (v, i) = trueop0; |
4827 | else |
4828 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, i); |
4829 | } |
4830 | else |
4831 | { |
4832 | if (!VECTOR_MODE_P (op1_mode)) |
4833 | RTVEC_ELT (v, i) = trueop1; |
4834 | else |
4835 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop1, |
4836 | i - in_n_elts); |
4837 | } |
4838 | } |
4839 | |
4840 | return gen_rtx_CONST_VECTOR (mode, v); |
4841 | } |
4842 | |
4843 | /* Try to merge two VEC_SELECTs from the same vector into a single one. |
4844 | Restrict the transformation to avoid generating a VEC_SELECT with a |
4845 | mode unrelated to its operand. */ |
4846 | if (GET_CODE (trueop0) == VEC_SELECT |
4847 | && GET_CODE (trueop1) == VEC_SELECT |
4848 | && rtx_equal_p (XEXP (trueop0, 0), XEXP (trueop1, 0)) |
4849 | && GET_MODE_INNER (GET_MODE (XEXP (trueop0, 0))) |
4850 | == GET_MODE_INNER(mode)) |
4851 | { |
4852 | rtx par0 = XEXP (trueop0, 1); |
4853 | rtx par1 = XEXP (trueop1, 1); |
4854 | int len0 = XVECLEN (par0, 0); |
4855 | int len1 = XVECLEN (par1, 0); |
4856 | rtvec vec = rtvec_alloc (len0 + len1); |
4857 | for (int i = 0; i < len0; i++) |
4858 | RTVEC_ELT (vec, i) = XVECEXP (par0, 0, i); |
4859 | for (int i = 0; i < len1; i++) |
4860 | RTVEC_ELT (vec, len0 + i) = XVECEXP (par1, 0, i); |
4861 | return simplify_gen_binary (code: VEC_SELECT, mode, XEXP (trueop0, 0), |
4862 | gen_rtx_PARALLEL (VOIDmode, vec)); |
4863 | } |
4864 | /* (vec_concat: |
4865 | (subreg_lowpart:N OP) |
4866 | (vec_select:N OP P)) --> OP when P selects the high half |
4867 | of the OP. */ |
4868 | if (GET_CODE (trueop0) == SUBREG |
4869 | && subreg_lowpart_p (trueop0) |
4870 | && GET_CODE (trueop1) == VEC_SELECT |
4871 | && SUBREG_REG (trueop0) == XEXP (trueop1, 0) |
4872 | && !side_effects_p (XEXP (trueop1, 0)) |
4873 | && vec_series_highpart_p (result_mode: op1_mode, op_mode: mode, XEXP (trueop1, 1))) |
4874 | return XEXP (trueop1, 0); |
4875 | } |
4876 | return 0; |
4877 | |
4878 | default: |
4879 | gcc_unreachable (); |
4880 | } |
4881 | |
4882 | if (mode == GET_MODE (op0) |
4883 | && mode == GET_MODE (op1) |
4884 | && vec_duplicate_p (x: op0, elt: &elt0) |
4885 | && vec_duplicate_p (x: op1, elt: &elt1)) |
4886 | { |
4887 | /* Try applying the operator to ELT and see if that simplifies. |
4888 | We can duplicate the result if so. |
4889 | |
4890 | The reason we don't use simplify_gen_binary is that it isn't |
4891 | necessarily a win to convert things like: |
4892 | |
4893 | (plus:V (vec_duplicate:V (reg:S R1)) |
4894 | (vec_duplicate:V (reg:S R2))) |
4895 | |
4896 | to: |
4897 | |
4898 | (vec_duplicate:V (plus:S (reg:S R1) (reg:S R2))) |
4899 | |
4900 | The first might be done entirely in vector registers while the |
4901 | second might need a move between register files. */ |
4902 | tem = simplify_binary_operation (code, GET_MODE_INNER (mode), |
4903 | op0: elt0, op1: elt1); |
4904 | if (tem) |
4905 | return gen_vec_duplicate (mode, tem); |
4906 | } |
4907 | |
4908 | return 0; |
4909 | } |
4910 | |
4911 | /* Return true if binary operation OP distributes over addition in operand |
4912 | OPNO, with the other operand being held constant. OPNO counts from 1. */ |
4913 | |
4914 | static bool |
4915 | distributes_over_addition_p (rtx_code op, int opno) |
4916 | { |
4917 | switch (op) |
4918 | { |
4919 | case PLUS: |
4920 | case MINUS: |
4921 | case MULT: |
4922 | return true; |
4923 | |
4924 | case ASHIFT: |
4925 | return opno == 1; |
4926 | |
4927 | default: |
4928 | return false; |
4929 | } |
4930 | } |
4931 | |
4932 | rtx |
4933 | simplify_const_binary_operation (enum rtx_code code, machine_mode mode, |
4934 | rtx op0, rtx op1) |
4935 | { |
4936 | if (VECTOR_MODE_P (mode) |
4937 | && code != VEC_CONCAT |
4938 | && GET_CODE (op0) == CONST_VECTOR |
4939 | && GET_CODE (op1) == CONST_VECTOR) |
4940 | { |
4941 | bool step_ok_p; |
4942 | if (CONST_VECTOR_STEPPED_P (op0) |
4943 | && CONST_VECTOR_STEPPED_P (op1)) |
4944 | /* We can operate directly on the encoding if: |
4945 | |
4946 | a3 - a2 == a2 - a1 && b3 - b2 == b2 - b1 |
4947 | implies |
4948 | (a3 op b3) - (a2 op b2) == (a2 op b2) - (a1 op b1) |
4949 | |
4950 | Addition and subtraction are the supported operators |
4951 | for which this is true. */ |
4952 | step_ok_p = (code == PLUS || code == MINUS); |
4953 | else if (CONST_VECTOR_STEPPED_P (op0)) |
4954 | /* We can operate directly on stepped encodings if: |
4955 | |
4956 | a3 - a2 == a2 - a1 |
4957 | implies: |
4958 | (a3 op c) - (a2 op c) == (a2 op c) - (a1 op c) |
4959 | |
4960 | which is true if (x -> x op c) distributes over addition. */ |
4961 | step_ok_p = distributes_over_addition_p (op: code, opno: 1); |
4962 | else |
4963 | /* Similarly in reverse. */ |
4964 | step_ok_p = distributes_over_addition_p (op: code, opno: 2); |
4965 | rtx_vector_builder builder; |
4966 | if (!builder.new_binary_operation (shape: mode, vec1: op0, vec2: op1, allow_stepped_p: step_ok_p)) |
4967 | return 0; |
4968 | |
4969 | unsigned int count = builder.encoded_nelts (); |
4970 | for (unsigned int i = 0; i < count; i++) |
4971 | { |
4972 | rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), |
4973 | CONST_VECTOR_ELT (op0, i), |
4974 | CONST_VECTOR_ELT (op1, i)); |
4975 | if (!x || !valid_for_const_vector_p (mode, x)) |
4976 | return 0; |
4977 | builder.quick_push (obj: x); |
4978 | } |
4979 | return builder.build (); |
4980 | } |
4981 | |
4982 | if (VECTOR_MODE_P (mode) |
4983 | && code == VEC_CONCAT |
4984 | && (CONST_SCALAR_INT_P (op0) |
4985 | || CONST_FIXED_P (op0) |
4986 | || CONST_DOUBLE_AS_FLOAT_P (op0)) |
4987 | && (CONST_SCALAR_INT_P (op1) |
4988 | || CONST_DOUBLE_AS_FLOAT_P (op1) |
4989 | || CONST_FIXED_P (op1))) |
4990 | { |
4991 | /* Both inputs have a constant number of elements, so the result |
4992 | must too. */ |
4993 | unsigned n_elts = GET_MODE_NUNITS (mode).to_constant (); |
4994 | rtvec v = rtvec_alloc (n_elts); |
4995 | |
4996 | gcc_assert (n_elts >= 2); |
4997 | if (n_elts == 2) |
4998 | { |
4999 | gcc_assert (GET_CODE (op0) != CONST_VECTOR); |
5000 | gcc_assert (GET_CODE (op1) != CONST_VECTOR); |
5001 | |
5002 | RTVEC_ELT (v, 0) = op0; |
5003 | RTVEC_ELT (v, 1) = op1; |
5004 | } |
5005 | else |
5006 | { |
5007 | unsigned op0_n_elts = GET_MODE_NUNITS (GET_MODE (op0)).to_constant (); |
5008 | unsigned op1_n_elts = GET_MODE_NUNITS (GET_MODE (op1)).to_constant (); |
5009 | unsigned i; |
5010 | |
5011 | gcc_assert (GET_CODE (op0) == CONST_VECTOR); |
5012 | gcc_assert (GET_CODE (op1) == CONST_VECTOR); |
5013 | gcc_assert (op0_n_elts + op1_n_elts == n_elts); |
5014 | |
5015 | for (i = 0; i < op0_n_elts; ++i) |
5016 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op0, i); |
5017 | for (i = 0; i < op1_n_elts; ++i) |
5018 | RTVEC_ELT (v, op0_n_elts+i) = CONST_VECTOR_ELT (op1, i); |
5019 | } |
5020 | |
5021 | return gen_rtx_CONST_VECTOR (mode, v); |
5022 | } |
5023 | |
5024 | if (SCALAR_FLOAT_MODE_P (mode) |
5025 | && CONST_DOUBLE_AS_FLOAT_P (op0) |
5026 | && CONST_DOUBLE_AS_FLOAT_P (op1) |
5027 | && mode == GET_MODE (op0) && mode == GET_MODE (op1)) |
5028 | { |
5029 | if (code == AND |
5030 | || code == IOR |
5031 | || code == XOR) |
5032 | { |
5033 | long tmp0[4]; |
5034 | long tmp1[4]; |
5035 | REAL_VALUE_TYPE r; |
5036 | int i; |
5037 | |
5038 | real_to_target (tmp0, CONST_DOUBLE_REAL_VALUE (op0), |
5039 | GET_MODE (op0)); |
5040 | real_to_target (tmp1, CONST_DOUBLE_REAL_VALUE (op1), |
5041 | GET_MODE (op1)); |
5042 | for (i = 0; i < 4; i++) |
5043 | { |
5044 | switch (code) |
5045 | { |
5046 | case AND: |
5047 | tmp0[i] &= tmp1[i]; |
5048 | break; |
5049 | case IOR: |
5050 | tmp0[i] |= tmp1[i]; |
5051 | break; |
5052 | case XOR: |
5053 | tmp0[i] ^= tmp1[i]; |
5054 | break; |
5055 | default: |
5056 | gcc_unreachable (); |
5057 | } |
5058 | } |
5059 | real_from_target (&r, tmp0, mode); |
5060 | return const_double_from_real_value (r, mode); |
5061 | } |
5062 | else if (code == COPYSIGN) |
5063 | { |
5064 | REAL_VALUE_TYPE f0, f1; |
5065 | real_convert (&f0, mode, CONST_DOUBLE_REAL_VALUE (op0)); |
5066 | real_convert (&f1, mode, CONST_DOUBLE_REAL_VALUE (op1)); |
5067 | real_copysign (&f0, &f1); |
5068 | return const_double_from_real_value (f0, mode); |
5069 | } |
5070 | else |
5071 | { |
5072 | REAL_VALUE_TYPE f0, f1, value, result; |
5073 | const REAL_VALUE_TYPE *opr0, *opr1; |
5074 | bool inexact; |
5075 | |
5076 | opr0 = CONST_DOUBLE_REAL_VALUE (op0); |
5077 | opr1 = CONST_DOUBLE_REAL_VALUE (op1); |
5078 | |
5079 | if (HONOR_SNANS (mode) |
5080 | && (REAL_VALUE_ISSIGNALING_NAN (*opr0) |
5081 | || REAL_VALUE_ISSIGNALING_NAN (*opr1))) |
5082 | return 0; |
5083 | |
5084 | real_convert (&f0, mode, opr0); |
5085 | real_convert (&f1, mode, opr1); |
5086 | |
5087 | if (code == DIV |
5088 | && real_equal (&f1, &dconst0) |
5089 | && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) |
5090 | return 0; |
5091 | |
5092 | if (MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) |
5093 | && flag_trapping_math |
5094 | && REAL_VALUE_ISINF (f0) && REAL_VALUE_ISINF (f1)) |
5095 | { |
5096 | int s0 = REAL_VALUE_NEGATIVE (f0); |
5097 | int s1 = REAL_VALUE_NEGATIVE (f1); |
5098 | |
5099 | switch (code) |
5100 | { |
5101 | case PLUS: |
5102 | /* Inf + -Inf = NaN plus exception. */ |
5103 | if (s0 != s1) |
5104 | return 0; |
5105 | break; |
5106 | case MINUS: |
5107 | /* Inf - Inf = NaN plus exception. */ |
5108 | if (s0 == s1) |
5109 | return 0; |
5110 | break; |
5111 | case DIV: |
5112 | /* Inf / Inf = NaN plus exception. */ |
5113 | return 0; |
5114 | default: |
5115 | break; |
5116 | } |
5117 | } |
5118 | |
5119 | if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) |
5120 | && flag_trapping_math |
5121 | && ((REAL_VALUE_ISINF (f0) && real_equal (&f1, &dconst0)) |
5122 | || (REAL_VALUE_ISINF (f1) |
5123 | && real_equal (&f0, &dconst0)))) |
5124 | /* Inf * 0 = NaN plus exception. */ |
5125 | return 0; |
5126 | |
5127 | inexact = real_arithmetic (&value, rtx_to_tree_code (code), |
5128 | &f0, &f1); |
5129 | real_convert (&result, mode, &value); |
5130 | |
5131 | /* Don't constant fold this floating point operation if |
5132 | the result has overflowed and flag_trapping_math. */ |
5133 | |
5134 | if (flag_trapping_math |
5135 | && MODE_HAS_INFINITIES (mode) |
5136 | && REAL_VALUE_ISINF (result) |
5137 | && !REAL_VALUE_ISINF (f0) |
5138 | && !REAL_VALUE_ISINF (f1)) |
5139 | /* Overflow plus exception. */ |
5140 | return 0; |
5141 | |
5142 | /* Don't constant fold this floating point operation if the |
5143 | result may dependent upon the run-time rounding mode and |
5144 | flag_rounding_math is set, or if GCC's software emulation |
5145 | is unable to accurately represent the result. */ |
5146 | |
5147 | if ((flag_rounding_math |
5148 | || (MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations)) |
5149 | && (inexact || !real_identical (&result, &value))) |
5150 | return NULL_RTX; |
5151 | |
5152 | return const_double_from_real_value (result, mode); |
5153 | } |
5154 | } |
5155 | |
5156 | /* We can fold some multi-word operations. */ |
5157 | scalar_int_mode int_mode; |
5158 | if (is_a <scalar_int_mode> (m: mode, result: &int_mode) |
5159 | && CONST_SCALAR_INT_P (op0) |
5160 | && CONST_SCALAR_INT_P (op1) |
5161 | && GET_MODE_PRECISION (mode: int_mode) <= MAX_BITSIZE_MODE_ANY_INT) |
5162 | { |
5163 | wide_int result; |
5164 | wi::overflow_type overflow; |
5165 | rtx_mode_t pop0 = rtx_mode_t (op0, int_mode); |
5166 | rtx_mode_t pop1 = rtx_mode_t (op1, int_mode); |
5167 | |
5168 | #if TARGET_SUPPORTS_WIDE_INT == 0 |
5169 | /* This assert keeps the simplification from producing a result |
5170 | that cannot be represented in a CONST_DOUBLE but a lot of |
5171 | upstream callers expect that this function never fails to |
5172 | simplify something and so you if you added this to the test |
5173 | above the code would die later anyway. If this assert |
5174 | happens, you just need to make the port support wide int. */ |
5175 | gcc_assert (GET_MODE_PRECISION (int_mode) <= HOST_BITS_PER_DOUBLE_INT); |
5176 | #endif |
5177 | switch (code) |
5178 | { |
5179 | case MINUS: |
5180 | result = wi::sub (x: pop0, y: pop1); |
5181 | break; |
5182 | |
5183 | case PLUS: |
5184 | result = wi::add (x: pop0, y: pop1); |
5185 | break; |
5186 | |
5187 | case MULT: |
5188 | result = wi::mul (x: pop0, y: pop1); |
5189 | break; |
5190 | |
5191 | case DIV: |
5192 | result = wi::div_trunc (x: pop0, y: pop1, sgn: SIGNED, overflow: &overflow); |
5193 | if (overflow) |
5194 | return NULL_RTX; |
5195 | break; |
5196 | |
5197 | case MOD: |
5198 | result = wi::mod_trunc (x: pop0, y: pop1, sgn: SIGNED, overflow: &overflow); |
5199 | if (overflow) |
5200 | return NULL_RTX; |
5201 | break; |
5202 | |
5203 | case UDIV: |
5204 | result = wi::div_trunc (x: pop0, y: pop1, sgn: UNSIGNED, overflow: &overflow); |
5205 | if (overflow) |
5206 | return NULL_RTX; |
5207 | break; |
5208 | |
5209 | case UMOD: |
5210 | result = wi::mod_trunc (x: pop0, y: pop1, sgn: UNSIGNED, overflow: &overflow); |
5211 | if (overflow) |
5212 | return NULL_RTX; |
5213 | break; |
5214 | |
5215 | case AND: |
5216 | result = wi::bit_and (x: pop0, y: pop1); |
5217 | break; |
5218 | |
5219 | case IOR: |
5220 | result = wi::bit_or (x: pop0, y: pop1); |
5221 | break; |
5222 | |
5223 | case XOR: |
5224 | result = wi::bit_xor (x: pop0, y: pop1); |
5225 | break; |
5226 | |
5227 | case SMIN: |
5228 | result = wi::smin (x: pop0, y: pop1); |
5229 | break; |
5230 | |
5231 | case SMAX: |
5232 | result = wi::smax (x: pop0, y: pop1); |
5233 | break; |
5234 | |
5235 | case UMIN: |
5236 | result = wi::umin (x: pop0, y: pop1); |
5237 | break; |
5238 | |
5239 | case UMAX: |
5240 | result = wi::umax (x: pop0, y: pop1); |
5241 | break; |
5242 | |
5243 | case LSHIFTRT: |
5244 | case ASHIFTRT: |
5245 | case ASHIFT: |
5246 | case SS_ASHIFT: |
5247 | case US_ASHIFT: |
5248 | { |
5249 | /* The shift count might be in SImode while int_mode might |
5250 | be narrower. On IA-64 it is even DImode. If the shift |
5251 | count is too large and doesn't fit into int_mode, we'd |
5252 | ICE. So, if int_mode is narrower than word, use |
5253 | word_mode for the shift count. */ |
5254 | if (GET_MODE (op1) == VOIDmode |
5255 | && GET_MODE_PRECISION (mode: int_mode) < BITS_PER_WORD) |
5256 | pop1 = rtx_mode_t (op1, word_mode); |
5257 | |
5258 | wide_int wop1 = pop1; |
5259 | if (SHIFT_COUNT_TRUNCATED) |
5260 | wop1 = wi::umod_trunc (x: wop1, y: GET_MODE_PRECISION (mode: int_mode)); |
5261 | else if (wi::geu_p (x: wop1, y: GET_MODE_PRECISION (mode: int_mode))) |
5262 | return NULL_RTX; |
5263 | |
5264 | switch (code) |
5265 | { |
5266 | case LSHIFTRT: |
5267 | result = wi::lrshift (x: pop0, y: wop1); |
5268 | break; |
5269 | |
5270 | case ASHIFTRT: |
5271 | result = wi::arshift (x: pop0, y: wop1); |
5272 | break; |
5273 | |
5274 | case ASHIFT: |
5275 | result = wi::lshift (x: pop0, y: wop1); |
5276 | break; |
5277 | |
5278 | case SS_ASHIFT: |
5279 | if (wi::leu_p (x: wop1, y: wi::clrsb (pop0))) |
5280 | result = wi::lshift (x: pop0, y: wop1); |
5281 | else if (wi::neg_p (x: pop0)) |
5282 | result = wi::min_value (mode: int_mode, sgn: SIGNED); |
5283 | else |
5284 | result = wi::max_value (mode: int_mode, sgn: SIGNED); |
5285 | break; |
5286 | |
5287 | case US_ASHIFT: |
5288 | if (wi::eq_p (x: pop0, y: 0)) |
5289 | result = pop0; |
5290 | else if (wi::leu_p (x: wop1, y: wi::clz (pop0))) |
5291 | result = wi::lshift (x: pop0, y: wop1); |
5292 | else |
5293 | result = wi::max_value (mode: int_mode, sgn: UNSIGNED); |
5294 | break; |
5295 | |
5296 | default: |
5297 | gcc_unreachable (); |
5298 | } |
5299 | break; |
5300 | } |
5301 | case ROTATE: |
5302 | case ROTATERT: |
5303 | { |
5304 | /* The rotate count might be in SImode while int_mode might |
5305 | be narrower. On IA-64 it is even DImode. If the shift |
5306 | count is too large and doesn't fit into int_mode, we'd |
5307 | ICE. So, if int_mode is narrower than word, use |
5308 | word_mode for the shift count. */ |
5309 | if (GET_MODE (op1) == VOIDmode |
5310 | && GET_MODE_PRECISION (mode: int_mode) < BITS_PER_WORD) |
5311 | pop1 = rtx_mode_t (op1, word_mode); |
5312 | |
5313 | if (wi::neg_p (x: pop1)) |
5314 | return NULL_RTX; |
5315 | |
5316 | switch (code) |
5317 | { |
5318 | case ROTATE: |
5319 | result = wi::lrotate (x: pop0, y: pop1); |
5320 | break; |
5321 | |
5322 | case ROTATERT: |
5323 | result = wi::rrotate (x: pop0, y: pop1); |
5324 | break; |
5325 | |
5326 | default: |
5327 | gcc_unreachable (); |
5328 | } |
5329 | break; |
5330 | } |
5331 | |
5332 | case SS_PLUS: |
5333 | result = wi::add (x: pop0, y: pop1, sgn: SIGNED, overflow: &overflow); |
5334 | clamp_signed_saturation: |
5335 | if (overflow == wi::OVF_OVERFLOW) |
5336 | result = wi::max_value (GET_MODE_PRECISION (mode: int_mode), SIGNED); |
5337 | else if (overflow == wi::OVF_UNDERFLOW) |
5338 | result = wi::min_value (GET_MODE_PRECISION (mode: int_mode), SIGNED); |
5339 | else if (overflow != wi::OVF_NONE) |
5340 | return NULL_RTX; |
5341 | break; |
5342 | |
5343 | case US_PLUS: |
5344 | result = wi::add (x: pop0, y: pop1, sgn: UNSIGNED, overflow: &overflow); |
5345 | clamp_unsigned_saturation: |
5346 | if (overflow != wi::OVF_NONE) |
5347 | result = wi::max_value (GET_MODE_PRECISION (mode: int_mode), UNSIGNED); |
5348 | break; |
5349 | |
5350 | case SS_MINUS: |
5351 | result = wi::sub (x: pop0, y: pop1, sgn: SIGNED, overflow: &overflow); |
5352 | goto clamp_signed_saturation; |
5353 | |
5354 | case US_MINUS: |
5355 | result = wi::sub (x: pop0, y: pop1, sgn: UNSIGNED, overflow: &overflow); |
5356 | if (overflow != wi::OVF_NONE) |
5357 | result = wi::min_value (GET_MODE_PRECISION (mode: int_mode), UNSIGNED); |
5358 | break; |
5359 | |
5360 | case SS_MULT: |
5361 | result = wi::mul (x: pop0, y: pop1, sgn: SIGNED, overflow: &overflow); |
5362 | goto clamp_signed_saturation; |
5363 | |
5364 | case US_MULT: |
5365 | result = wi::mul (x: pop0, y: pop1, sgn: UNSIGNED, overflow: &overflow); |
5366 | goto clamp_unsigned_saturation; |
5367 | |
5368 | case SMUL_HIGHPART: |
5369 | result = wi::mul_high (x: pop0, y: pop1, sgn: SIGNED); |
5370 | break; |
5371 | |
5372 | case UMUL_HIGHPART: |
5373 | result = wi::mul_high (x: pop0, y: pop1, sgn: UNSIGNED); |
5374 | break; |
5375 | |
5376 | default: |
5377 | return NULL_RTX; |
5378 | } |
5379 | return immed_wide_int_const (result, int_mode); |
5380 | } |
5381 | |
5382 | /* Handle polynomial integers. */ |
5383 | if (NUM_POLY_INT_COEFFS > 1 |
5384 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
5385 | && poly_int_rtx_p (x: op0) |
5386 | && poly_int_rtx_p (x: op1)) |
5387 | { |
5388 | poly_wide_int result; |
5389 | switch (code) |
5390 | { |
5391 | case PLUS: |
5392 | result = wi::to_poly_wide (x: op0, mode) + wi::to_poly_wide (x: op1, mode); |
5393 | break; |
5394 | |
5395 | case MINUS: |
5396 | result = wi::to_poly_wide (x: op0, mode) - wi::to_poly_wide (x: op1, mode); |
5397 | break; |
5398 | |
5399 | case MULT: |
5400 | if (CONST_SCALAR_INT_P (op1)) |
5401 | result = wi::to_poly_wide (x: op0, mode) * rtx_mode_t (op1, mode); |
5402 | else |
5403 | return NULL_RTX; |
5404 | break; |
5405 | |
5406 | case ASHIFT: |
5407 | if (CONST_SCALAR_INT_P (op1)) |
5408 | { |
5409 | wide_int shift |
5410 | = rtx_mode_t (op1, |
5411 | GET_MODE (op1) == VOIDmode |
5412 | && GET_MODE_PRECISION (mode: int_mode) < BITS_PER_WORD |
5413 | ? word_mode : mode); |
5414 | if (SHIFT_COUNT_TRUNCATED) |
5415 | shift = wi::umod_trunc (x: shift, y: GET_MODE_PRECISION (mode: int_mode)); |
5416 | else if (wi::geu_p (x: shift, y: GET_MODE_PRECISION (mode: int_mode))) |
5417 | return NULL_RTX; |
5418 | result = wi::to_poly_wide (x: op0, mode) << shift; |
5419 | } |
5420 | else |
5421 | return NULL_RTX; |
5422 | break; |
5423 | |
5424 | case IOR: |
5425 | if (!CONST_SCALAR_INT_P (op1) |
5426 | || !can_ior_p (a: wi::to_poly_wide (x: op0, mode), |
5427 | b: rtx_mode_t (op1, mode), result: &result)) |
5428 | return NULL_RTX; |
5429 | break; |
5430 | |
5431 | default: |
5432 | return NULL_RTX; |
5433 | } |
5434 | return immed_wide_int_const (result, int_mode); |
5435 | } |
5436 | |
5437 | return NULL_RTX; |
5438 | } |
5439 | |
5440 | |
5441 | |
5442 | /* Return a positive integer if X should sort after Y. The value |
5443 | returned is 1 if and only if X and Y are both regs. */ |
5444 | |
5445 | static int |
5446 | simplify_plus_minus_op_data_cmp (rtx x, rtx y) |
5447 | { |
5448 | int result; |
5449 | |
5450 | result = (commutative_operand_precedence (y) |
5451 | - commutative_operand_precedence (x)); |
5452 | if (result) |
5453 | return result + result; |
5454 | |
5455 | /* Group together equal REGs to do more simplification. */ |
5456 | if (REG_P (x) && REG_P (y)) |
5457 | return REGNO (x) > REGNO (y); |
5458 | |
5459 | return 0; |
5460 | } |
5461 | |
5462 | /* Simplify and canonicalize a PLUS or MINUS, at least one of whose |
5463 | operands may be another PLUS or MINUS. |
5464 | |
5465 | Rather than test for specific case, we do this by a brute-force method |
5466 | and do all possible simplifications until no more changes occur. Then |
5467 | we rebuild the operation. |
5468 | |
5469 | May return NULL_RTX when no changes were made. */ |
5470 | |
5471 | rtx |
5472 | simplify_context::simplify_plus_minus (rtx_code code, machine_mode mode, |
5473 | rtx op0, rtx op1) |
5474 | { |
5475 | struct simplify_plus_minus_op_data |
5476 | { |
5477 | rtx op; |
5478 | short neg; |
5479 | } ops[16]; |
5480 | rtx result, tem; |
5481 | int n_ops = 2; |
5482 | int changed, n_constants, canonicalized = 0; |
5483 | int i, j; |
5484 | |
5485 | memset (s: ops, c: 0, n: sizeof ops); |
5486 | |
5487 | /* Set up the two operands and then expand them until nothing has been |
5488 | changed. If we run out of room in our array, give up; this should |
5489 | almost never happen. */ |
5490 | |
5491 | ops[0].op = op0; |
5492 | ops[0].neg = 0; |
5493 | ops[1].op = op1; |
5494 | ops[1].neg = (code == MINUS); |
5495 | |
5496 | do |
5497 | { |
5498 | changed = 0; |
5499 | n_constants = 0; |
5500 | |
5501 | for (i = 0; i < n_ops; i++) |
5502 | { |
5503 | rtx this_op = ops[i].op; |
5504 | int this_neg = ops[i].neg; |
5505 | enum rtx_code this_code = GET_CODE (this_op); |
5506 | |
5507 | switch (this_code) |
5508 | { |
5509 | case PLUS: |
5510 | case MINUS: |
5511 | if (n_ops == ARRAY_SIZE (ops)) |
5512 | return NULL_RTX; |
5513 | |
5514 | ops[n_ops].op = XEXP (this_op, 1); |
5515 | ops[n_ops].neg = (this_code == MINUS) ^ this_neg; |
5516 | n_ops++; |
5517 | |
5518 | ops[i].op = XEXP (this_op, 0); |
5519 | changed = 1; |
5520 | /* If this operand was negated then we will potentially |
5521 | canonicalize the expression. Similarly if we don't |
5522 | place the operands adjacent we're re-ordering the |
5523 | expression and thus might be performing a |
5524 | canonicalization. Ignore register re-ordering. |
5525 | ??? It might be better to shuffle the ops array here, |
5526 | but then (plus (plus (A, B), plus (C, D))) wouldn't |
5527 | be seen as non-canonical. */ |
5528 | if (this_neg |
5529 | || (i != n_ops - 2 |
5530 | && !(REG_P (ops[i].op) && REG_P (ops[n_ops - 1].op)))) |
5531 | canonicalized = 1; |
5532 | break; |
5533 | |
5534 | case NEG: |
5535 | ops[i].op = XEXP (this_op, 0); |
5536 | ops[i].neg = ! this_neg; |
5537 | changed = 1; |
5538 | canonicalized = 1; |
5539 | break; |
5540 | |
5541 | case CONST: |
5542 | if (n_ops != ARRAY_SIZE (ops) |
5543 | && GET_CODE (XEXP (this_op, 0)) == PLUS |
5544 | && CONSTANT_P (XEXP (XEXP (this_op, 0), 0)) |
5545 | && CONSTANT_P (XEXP (XEXP (this_op, 0), 1))) |
5546 | { |
5547 | ops[i].op = XEXP (XEXP (this_op, 0), 0); |
5548 | ops[n_ops].op = XEXP (XEXP (this_op, 0), 1); |
5549 | ops[n_ops].neg = this_neg; |
5550 | n_ops++; |
5551 | changed = 1; |
5552 | canonicalized = 1; |
5553 | } |
5554 | break; |
5555 | |
5556 | case NOT: |
5557 | /* ~a -> (-a - 1) */ |
5558 | if (n_ops != ARRAY_SIZE (ops)) |
5559 | { |
5560 | ops[n_ops].op = CONSTM1_RTX (mode); |
5561 | ops[n_ops++].neg = this_neg; |
5562 | ops[i].op = XEXP (this_op, 0); |
5563 | ops[i].neg = !this_neg; |
5564 | changed = 1; |
5565 | canonicalized = 1; |
5566 | } |
5567 | break; |
5568 | |
5569 | CASE_CONST_SCALAR_INT: |
5570 | case CONST_POLY_INT: |
5571 | n_constants++; |
5572 | if (this_neg) |
5573 | { |
5574 | ops[i].op = neg_poly_int_rtx (mode, i: this_op); |
5575 | ops[i].neg = 0; |
5576 | changed = 1; |
5577 | canonicalized = 1; |
5578 | } |
5579 | break; |
5580 | |
5581 | default: |
5582 | break; |
5583 | } |
5584 | } |
5585 | } |
5586 | while (changed); |
5587 | |
5588 | if (n_constants > 1) |
5589 | canonicalized = 1; |
5590 | |
5591 | gcc_assert (n_ops >= 2); |
5592 | |
5593 | /* If we only have two operands, we can avoid the loops. */ |
5594 | if (n_ops == 2) |
5595 | { |
5596 | enum rtx_code code = ops[0].neg || ops[1].neg ? MINUS : PLUS; |
5597 | rtx lhs, rhs; |
5598 | |
5599 | /* Get the two operands. Be careful with the order, especially for |
5600 | the cases where code == MINUS. */ |
5601 | if (ops[0].neg && ops[1].neg) |
5602 | { |
5603 | lhs = gen_rtx_NEG (mode, ops[0].op); |
5604 | rhs = ops[1].op; |
5605 | } |
5606 | else if (ops[0].neg) |
5607 | { |
5608 | lhs = ops[1].op; |
5609 | rhs = ops[0].op; |
5610 | } |
5611 | else |
5612 | { |
5613 | lhs = ops[0].op; |
5614 | rhs = ops[1].op; |
5615 | } |
5616 | |
5617 | return simplify_const_binary_operation (code, mode, op0: lhs, op1: rhs); |
5618 | } |
5619 | |
5620 | /* Now simplify each pair of operands until nothing changes. */ |
5621 | while (1) |
5622 | { |
5623 | /* Insertion sort is good enough for a small array. */ |
5624 | for (i = 1; i < n_ops; i++) |
5625 | { |
5626 | struct simplify_plus_minus_op_data save; |
5627 | int cmp; |
5628 | |
5629 | j = i - 1; |
5630 | cmp = simplify_plus_minus_op_data_cmp (x: ops[j].op, y: ops[i].op); |
5631 | if (cmp <= 0) |
5632 | continue; |
5633 | /* Just swapping registers doesn't count as canonicalization. */ |
5634 | if (cmp != 1) |
5635 | canonicalized = 1; |
5636 | |
5637 | save = ops[i]; |
5638 | do |
5639 | ops[j + 1] = ops[j]; |
5640 | while (j-- |
5641 | && simplify_plus_minus_op_data_cmp (x: ops[j].op, y: save.op) > 0); |
5642 | ops[j + 1] = save; |
5643 | } |
5644 | |
5645 | changed = 0; |
5646 | for (i = n_ops - 1; i > 0; i--) |
5647 | for (j = i - 1; j >= 0; j--) |
5648 | { |
5649 | rtx lhs = ops[j].op, rhs = ops[i].op; |
5650 | int lneg = ops[j].neg, rneg = ops[i].neg; |
5651 | |
5652 | if (lhs != 0 && rhs != 0) |
5653 | { |
5654 | enum rtx_code ncode = PLUS; |
5655 | |
5656 | if (lneg != rneg) |
5657 | { |
5658 | ncode = MINUS; |
5659 | if (lneg) |
5660 | std::swap (a&: lhs, b&: rhs); |
5661 | } |
5662 | else if (swap_commutative_operands_p (lhs, rhs)) |
5663 | std::swap (a&: lhs, b&: rhs); |
5664 | |
5665 | if ((GET_CODE (lhs) == CONST || CONST_INT_P (lhs)) |
5666 | && (GET_CODE (rhs) == CONST || CONST_INT_P (rhs))) |
5667 | { |
5668 | rtx tem_lhs, tem_rhs; |
5669 | |
5670 | tem_lhs = GET_CODE (lhs) == CONST ? XEXP (lhs, 0) : lhs; |
5671 | tem_rhs = GET_CODE (rhs) == CONST ? XEXP (rhs, 0) : rhs; |
5672 | tem = simplify_binary_operation (code: ncode, mode, op0: tem_lhs, |
5673 | op1: tem_rhs); |
5674 | |
5675 | if (tem && !CONSTANT_P (tem)) |
5676 | tem = gen_rtx_CONST (GET_MODE (tem), tem); |
5677 | } |
5678 | else |
5679 | tem = simplify_binary_operation (code: ncode, mode, op0: lhs, op1: rhs); |
5680 | |
5681 | if (tem) |
5682 | { |
5683 | /* Reject "simplifications" that just wrap the two |
5684 | arguments in a CONST. Failure to do so can result |
5685 | in infinite recursion with simplify_binary_operation |
5686 | when it calls us to simplify CONST operations. |
5687 | Also, if we find such a simplification, don't try |
5688 | any more combinations with this rhs: We must have |
5689 | something like symbol+offset, ie. one of the |
5690 | trivial CONST expressions we handle later. */ |
5691 | if (GET_CODE (tem) == CONST |
5692 | && GET_CODE (XEXP (tem, 0)) == ncode |
5693 | && XEXP (XEXP (tem, 0), 0) == lhs |
5694 | && XEXP (XEXP (tem, 0), 1) == rhs) |
5695 | break; |
5696 | lneg &= rneg; |
5697 | if (GET_CODE (tem) == NEG) |
5698 | tem = XEXP (tem, 0), lneg = !lneg; |
5699 | if (poly_int_rtx_p (x: tem) && lneg) |
5700 | tem = neg_poly_int_rtx (mode, i: tem), lneg = 0; |
5701 | |
5702 | ops[i].op = tem; |
5703 | ops[i].neg = lneg; |
5704 | ops[j].op = NULL_RTX; |
5705 | changed = 1; |
5706 | canonicalized = 1; |
5707 | } |
5708 | } |
5709 | } |
5710 | |
5711 | if (!changed) |
5712 | break; |
5713 | |
5714 | /* Pack all the operands to the lower-numbered entries. */ |
5715 | for (i = 0, j = 0; j < n_ops; j++) |
5716 | if (ops[j].op) |
5717 | { |
5718 | ops[i] = ops[j]; |
5719 | i++; |
5720 | } |
5721 | n_ops = i; |
5722 | } |
5723 | |
5724 | /* If nothing changed, check that rematerialization of rtl instructions |
5725 | is still required. */ |
5726 | if (!canonicalized) |
5727 | { |
5728 | /* Perform rematerialization if only all operands are registers and |
5729 | all operations are PLUS. */ |
5730 | /* ??? Also disallow (non-global, non-frame) fixed registers to work |
5731 | around rs6000 and how it uses the CA register. See PR67145. */ |
5732 | for (i = 0; i < n_ops; i++) |
5733 | if (ops[i].neg |
5734 | || !REG_P (ops[i].op) |
5735 | || (REGNO (ops[i].op) < FIRST_PSEUDO_REGISTER |
5736 | && fixed_regs[REGNO (ops[i].op)] |
5737 | && !global_regs[REGNO (ops[i].op)] |
5738 | && ops[i].op != frame_pointer_rtx |
5739 | && ops[i].op != arg_pointer_rtx |
5740 | && ops[i].op != stack_pointer_rtx)) |
5741 | return NULL_RTX; |
5742 | goto gen_result; |
5743 | } |
5744 | |
5745 | /* Create (minus -C X) instead of (neg (const (plus X C))). */ |
5746 | if (n_ops == 2 |
5747 | && CONST_INT_P (ops[1].op) |
5748 | && CONSTANT_P (ops[0].op) |
5749 | && ops[0].neg) |
5750 | return gen_rtx_fmt_ee (MINUS, mode, ops[1].op, ops[0].op); |
5751 | |
5752 | /* We suppressed creation of trivial CONST expressions in the |
5753 | combination loop to avoid recursion. Create one manually now. |
5754 | The combination loop should have ensured that there is exactly |
5755 | one CONST_INT, and the sort will have ensured that it is last |
5756 | in the array and that any other constant will be next-to-last. */ |
5757 | |
5758 | if (n_ops > 1 |
5759 | && poly_int_rtx_p (x: ops[n_ops - 1].op) |
5760 | && CONSTANT_P (ops[n_ops - 2].op)) |
5761 | { |
5762 | rtx value = ops[n_ops - 1].op; |
5763 | if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg) |
5764 | value = neg_poly_int_rtx (mode, i: value); |
5765 | if (CONST_INT_P (value)) |
5766 | { |
5767 | ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op, |
5768 | INTVAL (value)); |
5769 | n_ops--; |
5770 | } |
5771 | } |
5772 | |
5773 | /* Put a non-negated operand first, if possible. */ |
5774 | |
5775 | for (i = 0; i < n_ops && ops[i].neg; i++) |
5776 | continue; |
5777 | if (i == n_ops) |
5778 | ops[0].op = gen_rtx_NEG (mode, ops[0].op); |
5779 | else if (i != 0) |
5780 | { |
5781 | tem = ops[0].op; |
5782 | ops[0] = ops[i]; |
5783 | ops[i].op = tem; |
5784 | ops[i].neg = 1; |
5785 | } |
5786 | |
5787 | /* Now make the result by performing the requested operations. */ |
5788 | gen_result: |
5789 | result = ops[0].op; |
5790 | for (i = 1; i < n_ops; i++) |
5791 | result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS, |
5792 | mode, result, ops[i].op); |
5793 | |
5794 | return result; |
5795 | } |
5796 | |
5797 | /* Check whether an operand is suitable for calling simplify_plus_minus. */ |
5798 | static bool |
5799 | plus_minus_operand_p (const_rtx x) |
5800 | { |
5801 | return GET_CODE (x) == PLUS |
5802 | || GET_CODE (x) == MINUS |
5803 | || (GET_CODE (x) == CONST |
5804 | && GET_CODE (XEXP (x, 0)) == PLUS |
5805 | && CONSTANT_P (XEXP (XEXP (x, 0), 0)) |
5806 | && CONSTANT_P (XEXP (XEXP (x, 0), 1))); |
5807 | } |
5808 | |
5809 | /* Like simplify_binary_operation except used for relational operators. |
5810 | MODE is the mode of the result. If MODE is VOIDmode, both operands must |
5811 | not also be VOIDmode. |
5812 | |
5813 | CMP_MODE specifies in which mode the comparison is done in, so it is |
5814 | the mode of the operands. If CMP_MODE is VOIDmode, it is taken from |
5815 | the operands or, if both are VOIDmode, the operands are compared in |
5816 | "infinite precision". */ |
5817 | rtx |
5818 | simplify_context::simplify_relational_operation (rtx_code code, |
5819 | machine_mode mode, |
5820 | machine_mode cmp_mode, |
5821 | rtx op0, rtx op1) |
5822 | { |
5823 | rtx tem, trueop0, trueop1; |
5824 | |
5825 | if (cmp_mode == VOIDmode) |
5826 | cmp_mode = GET_MODE (op0); |
5827 | if (cmp_mode == VOIDmode) |
5828 | cmp_mode = GET_MODE (op1); |
5829 | |
5830 | tem = simplify_const_relational_operation (code, cmp_mode, op0, op1); |
5831 | if (tem) |
5832 | return relational_result (mode, cmp_mode, res: tem); |
5833 | |
5834 | /* For the following tests, ensure const0_rtx is op1. */ |
5835 | if (swap_commutative_operands_p (op0, op1) |
5836 | || (op0 == const0_rtx && op1 != const0_rtx)) |
5837 | std::swap (a&: op0, b&: op1), code = swap_condition (code); |
5838 | |
5839 | /* If op0 is a compare, extract the comparison arguments from it. */ |
5840 | if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) |
5841 | return simplify_gen_relational (code, mode, VOIDmode, |
5842 | XEXP (op0, 0), XEXP (op0, 1)); |
5843 | |
5844 | if (GET_MODE_CLASS (cmp_mode) == MODE_CC) |
5845 | return NULL_RTX; |
5846 | |
5847 | trueop0 = avoid_constant_pool_reference (x: op0); |
5848 | trueop1 = avoid_constant_pool_reference (x: op1); |
5849 | return simplify_relational_operation_1 (code, mode, cmp_mode, |
5850 | trueop0, trueop1); |
5851 | } |
5852 | |
5853 | /* This part of simplify_relational_operation is only used when CMP_MODE |
5854 | is not in class MODE_CC (i.e. it is a real comparison). |
5855 | |
5856 | MODE is the mode of the result, while CMP_MODE specifies in which |
5857 | mode the comparison is done in, so it is the mode of the operands. */ |
5858 | |
5859 | rtx |
5860 | simplify_context::simplify_relational_operation_1 (rtx_code code, |
5861 | machine_mode mode, |
5862 | machine_mode cmp_mode, |
5863 | rtx op0, rtx op1) |
5864 | { |
5865 | enum rtx_code op0code = GET_CODE (op0); |
5866 | |
5867 | if (op1 == const0_rtx && COMPARISON_P (op0)) |
5868 | { |
5869 | /* If op0 is a comparison, extract the comparison arguments |
5870 | from it. */ |
5871 | if (code == NE) |
5872 | { |
5873 | if (GET_MODE (op0) == mode) |
5874 | return simplify_rtx (op0); |
5875 | else |
5876 | return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode, |
5877 | XEXP (op0, 0), XEXP (op0, 1)); |
5878 | } |
5879 | else if (code == EQ) |
5880 | { |
5881 | enum rtx_code new_code = reversed_comparison_code (op0, NULL); |
5882 | if (new_code != UNKNOWN) |
5883 | return simplify_gen_relational (code: new_code, mode, VOIDmode, |
5884 | XEXP (op0, 0), XEXP (op0, 1)); |
5885 | } |
5886 | } |
5887 | |
5888 | /* (LTU/GEU (PLUS a C) C), where C is constant, can be simplified to |
5889 | (GEU/LTU a -C). Likewise for (LTU/GEU (PLUS a C) a). */ |
5890 | if ((code == LTU || code == GEU) |
5891 | && GET_CODE (op0) == PLUS |
5892 | && CONST_INT_P (XEXP (op0, 1)) |
5893 | && (rtx_equal_p (op1, XEXP (op0, 0)) |
5894 | || rtx_equal_p (op1, XEXP (op0, 1))) |
5895 | /* (LTU/GEU (PLUS a 0) 0) is not the same as (GEU/LTU a 0). */ |
5896 | && XEXP (op0, 1) != const0_rtx) |
5897 | { |
5898 | rtx new_cmp |
5899 | = simplify_gen_unary (code: NEG, mode: cmp_mode, XEXP (op0, 1), op_mode: cmp_mode); |
5900 | return simplify_gen_relational (code: (code == LTU ? GEU : LTU), mode, |
5901 | cmp_mode, XEXP (op0, 0), op1: new_cmp); |
5902 | } |
5903 | |
5904 | /* (GTU (PLUS a C) (C - 1)) where C is a non-zero constant can be |
5905 | transformed into (LTU a -C). */ |
5906 | if (code == GTU && GET_CODE (op0) == PLUS && CONST_INT_P (op1) |
5907 | && CONST_INT_P (XEXP (op0, 1)) |
5908 | && (UINTVAL (op1) == UINTVAL (XEXP (op0, 1)) - 1) |
5909 | && XEXP (op0, 1) != const0_rtx) |
5910 | { |
5911 | rtx new_cmp |
5912 | = simplify_gen_unary (code: NEG, mode: cmp_mode, XEXP (op0, 1), op_mode: cmp_mode); |
5913 | return simplify_gen_relational (code: LTU, mode, cmp_mode, |
5914 | XEXP (op0, 0), op1: new_cmp); |
5915 | } |
5916 | |
5917 | /* Canonicalize (LTU/GEU (PLUS a b) b) as (LTU/GEU (PLUS a b) a). */ |
5918 | if ((code == LTU || code == GEU) |
5919 | && GET_CODE (op0) == PLUS |
5920 | && rtx_equal_p (op1, XEXP (op0, 1)) |
5921 | /* Don't recurse "infinitely" for (LTU/GEU (PLUS b b) b). */ |
5922 | && !rtx_equal_p (op1, XEXP (op0, 0))) |
5923 | return simplify_gen_relational (code, mode, cmp_mode, op0, |
5924 | op1: copy_rtx (XEXP (op0, 0))); |
5925 | |
5926 | if (op1 == const0_rtx) |
5927 | { |
5928 | /* Canonicalize (GTU x 0) as (NE x 0). */ |
5929 | if (code == GTU) |
5930 | return simplify_gen_relational (code: NE, mode, cmp_mode, op0, op1); |
5931 | /* Canonicalize (LEU x 0) as (EQ x 0). */ |
5932 | if (code == LEU) |
5933 | return simplify_gen_relational (code: EQ, mode, cmp_mode, op0, op1); |
5934 | } |
5935 | else if (op1 == const1_rtx) |
5936 | { |
5937 | switch (code) |
5938 | { |
5939 | case GE: |
5940 | /* Canonicalize (GE x 1) as (GT x 0). */ |
5941 | return simplify_gen_relational (code: GT, mode, cmp_mode, |
5942 | op0, const0_rtx); |
5943 | case GEU: |
5944 | /* Canonicalize (GEU x 1) as (NE x 0). */ |
5945 | return simplify_gen_relational (code: NE, mode, cmp_mode, |
5946 | op0, const0_rtx); |
5947 | case LT: |
5948 | /* Canonicalize (LT x 1) as (LE x 0). */ |
5949 | return simplify_gen_relational (code: LE, mode, cmp_mode, |
5950 | op0, const0_rtx); |
5951 | case LTU: |
5952 | /* Canonicalize (LTU x 1) as (EQ x 0). */ |
5953 | return simplify_gen_relational (code: EQ, mode, cmp_mode, |
5954 | op0, const0_rtx); |
5955 | default: |
5956 | break; |
5957 | } |
5958 | } |
5959 | else if (op1 == constm1_rtx) |
5960 | { |
5961 | /* Canonicalize (LE x -1) as (LT x 0). */ |
5962 | if (code == LE) |
5963 | return simplify_gen_relational (code: LT, mode, cmp_mode, op0, const0_rtx); |
5964 | /* Canonicalize (GT x -1) as (GE x 0). */ |
5965 | if (code == GT) |
5966 | return simplify_gen_relational (code: GE, mode, cmp_mode, op0, const0_rtx); |
5967 | } |
5968 | |
5969 | /* (eq/ne (plus x cst1) cst2) simplifies to (eq/ne x (cst2 - cst1)) */ |
5970 | if ((code == EQ || code == NE) |
5971 | && (op0code == PLUS || op0code == MINUS) |
5972 | && CONSTANT_P (op1) |
5973 | && CONSTANT_P (XEXP (op0, 1)) |
5974 | && (INTEGRAL_MODE_P (cmp_mode) || flag_unsafe_math_optimizations)) |
5975 | { |
5976 | rtx x = XEXP (op0, 0); |
5977 | rtx c = XEXP (op0, 1); |
5978 | enum rtx_code invcode = op0code == PLUS ? MINUS : PLUS; |
5979 | rtx tem = simplify_gen_binary (code: invcode, mode: cmp_mode, op0: op1, op1: c); |
5980 | |
5981 | /* Detect an infinite recursive condition, where we oscillate at this |
5982 | simplification case between: |
5983 | A + B == C <---> C - B == A, |
5984 | where A, B, and C are all constants with non-simplifiable expressions, |
5985 | usually SYMBOL_REFs. */ |
5986 | if (GET_CODE (tem) == invcode |
5987 | && CONSTANT_P (x) |
5988 | && rtx_equal_p (c, XEXP (tem, 1))) |
5989 | return NULL_RTX; |
5990 | |
5991 | return simplify_gen_relational (code, mode, cmp_mode, op0: x, op1: tem); |
5992 | } |
5993 | |
5994 | /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is |
5995 | the same as (zero_extract:SI FOO (const_int 1) BAR). */ |
5996 | scalar_int_mode int_mode, int_cmp_mode; |
5997 | if (code == NE |
5998 | && op1 == const0_rtx |
5999 | && is_int_mode (mode, int_mode: &int_mode) |
6000 | && is_a <scalar_int_mode> (m: cmp_mode, result: &int_cmp_mode) |
6001 | /* ??? Work-around BImode bugs in the ia64 backend. */ |
6002 | && int_mode != BImode |
6003 | && int_cmp_mode != BImode |
6004 | && nonzero_bits (op0, int_cmp_mode) == 1 |
6005 | && STORE_FLAG_VALUE == 1) |
6006 | return GET_MODE_SIZE (mode: int_mode) > GET_MODE_SIZE (mode: int_cmp_mode) |
6007 | ? simplify_gen_unary (code: ZERO_EXTEND, mode: int_mode, op: op0, op_mode: int_cmp_mode) |
6008 | : lowpart_subreg (int_mode, op0, int_cmp_mode); |
6009 | |
6010 | /* (eq/ne (xor x y) 0) simplifies to (eq/ne x y). */ |
6011 | if ((code == EQ || code == NE) |
6012 | && op1 == const0_rtx |
6013 | && op0code == XOR) |
6014 | return simplify_gen_relational (code, mode, cmp_mode, |
6015 | XEXP (op0, 0), XEXP (op0, 1)); |
6016 | |
6017 | /* (eq/ne (xor x y) x) simplifies to (eq/ne y 0). */ |
6018 | if ((code == EQ || code == NE) |
6019 | && op0code == XOR |
6020 | && rtx_equal_p (XEXP (op0, 0), op1) |
6021 | && !side_effects_p (XEXP (op0, 0))) |
6022 | return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 1), |
6023 | CONST0_RTX (mode)); |
6024 | |
6025 | /* Likewise (eq/ne (xor x y) y) simplifies to (eq/ne x 0). */ |
6026 | if ((code == EQ || code == NE) |
6027 | && op0code == XOR |
6028 | && rtx_equal_p (XEXP (op0, 1), op1) |
6029 | && !side_effects_p (XEXP (op0, 1))) |
6030 | return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), |
6031 | CONST0_RTX (mode)); |
6032 | |
6033 | /* (eq/ne (xor x C1) C2) simplifies to (eq/ne x (C1^C2)). */ |
6034 | if ((code == EQ || code == NE) |
6035 | && op0code == XOR |
6036 | && CONST_SCALAR_INT_P (op1) |
6037 | && CONST_SCALAR_INT_P (XEXP (op0, 1))) |
6038 | return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), |
6039 | op1: simplify_gen_binary (code: XOR, mode: cmp_mode, |
6040 | XEXP (op0, 1), op1)); |
6041 | |
6042 | /* Simplify eq/ne (and/ior x y) x/y) for targets with a BICS instruction or |
6043 | constant folding if x/y is a constant. */ |
6044 | if ((code == EQ || code == NE) |
6045 | && (op0code == AND || op0code == IOR) |
6046 | && !side_effects_p (op1) |
6047 | && op1 != CONST0_RTX (cmp_mode)) |
6048 | { |
6049 | /* Both (eq/ne (and x y) x) and (eq/ne (ior x y) y) simplify to |
6050 | (eq/ne (and (not y) x) 0). */ |
6051 | if ((op0code == AND && rtx_equal_p (XEXP (op0, 0), op1)) |
6052 | || (op0code == IOR && rtx_equal_p (XEXP (op0, 1), op1))) |
6053 | { |
6054 | rtx not_y = simplify_gen_unary (code: NOT, mode: cmp_mode, XEXP (op0, 1), |
6055 | op_mode: cmp_mode); |
6056 | rtx lhs = simplify_gen_binary (code: AND, mode: cmp_mode, op0: not_y, XEXP (op0, 0)); |
6057 | |
6058 | return simplify_gen_relational (code, mode, cmp_mode, op0: lhs, |
6059 | CONST0_RTX (cmp_mode)); |
6060 | } |
6061 | |
6062 | /* Both (eq/ne (and x y) y) and (eq/ne (ior x y) x) simplify to |
6063 | (eq/ne (and (not x) y) 0). */ |
6064 | if ((op0code == AND && rtx_equal_p (XEXP (op0, 1), op1)) |
6065 | || (op0code == IOR && rtx_equal_p (XEXP (op0, 0), op1))) |
6066 | { |
6067 | rtx not_x = simplify_gen_unary (code: NOT, mode: cmp_mode, XEXP (op0, 0), |
6068 | op_mode: cmp_mode); |
6069 | rtx lhs = simplify_gen_binary (code: AND, mode: cmp_mode, op0: not_x, XEXP (op0, 1)); |
6070 | |
6071 | return simplify_gen_relational (code, mode, cmp_mode, op0: lhs, |
6072 | CONST0_RTX (cmp_mode)); |
6073 | } |
6074 | } |
6075 | |
6076 | /* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped. */ |
6077 | if ((code == EQ || code == NE) |
6078 | && GET_CODE (op0) == BSWAP |
6079 | && CONST_SCALAR_INT_P (op1)) |
6080 | return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), |
6081 | op1: simplify_gen_unary (code: BSWAP, mode: cmp_mode, |
6082 | op: op1, op_mode: cmp_mode)); |
6083 | |
6084 | /* (eq/ne (bswap x) (bswap y)) simplifies to (eq/ne x y). */ |
6085 | if ((code == EQ || code == NE) |
6086 | && GET_CODE (op0) == BSWAP |
6087 | && GET_CODE (op1) == BSWAP) |
6088 | return simplify_gen_relational (code, mode, cmp_mode, |
6089 | XEXP (op0, 0), XEXP (op1, 0)); |
6090 | |
6091 | if (op0code == POPCOUNT && op1 == const0_rtx) |
6092 | switch (code) |
6093 | { |
6094 | case EQ: |
6095 | case LE: |
6096 | case LEU: |
6097 | /* (eq (popcount x) (const_int 0)) -> (eq x (const_int 0)). */ |
6098 | return simplify_gen_relational (code: EQ, mode, GET_MODE (XEXP (op0, 0)), |
6099 | XEXP (op0, 0), const0_rtx); |
6100 | |
6101 | case NE: |
6102 | case GT: |
6103 | case GTU: |
6104 | /* (ne (popcount x) (const_int 0)) -> (ne x (const_int 0)). */ |
6105 | return simplify_gen_relational (code: NE, mode, GET_MODE (XEXP (op0, 0)), |
6106 | XEXP (op0, 0), const0_rtx); |
6107 | |
6108 | default: |
6109 | break; |
6110 | } |
6111 | |
6112 | /* (ne:SI (subreg:QI (ashift:SI x 7) 0) 0) -> (and:SI x 1). */ |
6113 | if (code == NE |
6114 | && op1 == const0_rtx |
6115 | && (op0code == TRUNCATE |
6116 | || (partial_subreg_p (x: op0) |
6117 | && subreg_lowpart_p (op0))) |
6118 | && SCALAR_INT_MODE_P (mode) |
6119 | && STORE_FLAG_VALUE == 1) |
6120 | { |
6121 | rtx tmp = XEXP (op0, 0); |
6122 | if (GET_CODE (tmp) == ASHIFT |
6123 | && GET_MODE (tmp) == mode |
6124 | && CONST_INT_P (XEXP (tmp, 1)) |
6125 | && is_int_mode (GET_MODE (op0), int_mode: &int_mode) |
6126 | && INTVAL (XEXP (tmp, 1)) == GET_MODE_PRECISION (mode: int_mode) - 1) |
6127 | return simplify_gen_binary (code: AND, mode, XEXP (tmp, 0), const1_rtx); |
6128 | } |
6129 | return NULL_RTX; |
6130 | } |
6131 | |
6132 | enum |
6133 | { |
6134 | CMP_EQ = 1, |
6135 | CMP_LT = 2, |
6136 | CMP_GT = 4, |
6137 | CMP_LTU = 8, |
6138 | CMP_GTU = 16 |
6139 | }; |
6140 | |
6141 | |
6142 | /* Convert the known results for EQ, LT, GT, LTU, GTU contained in |
6143 | KNOWN_RESULT to a CONST_INT, based on the requested comparison CODE |
6144 | For KNOWN_RESULT to make sense it should be either CMP_EQ, or the |
6145 | logical OR of one of (CMP_LT, CMP_GT) and one of (CMP_LTU, CMP_GTU). |
6146 | For floating-point comparisons, assume that the operands were ordered. */ |
6147 | |
6148 | static rtx |
6149 | comparison_result (enum rtx_code code, int known_results) |
6150 | { |
6151 | switch (code) |
6152 | { |
6153 | case EQ: |
6154 | case UNEQ: |
6155 | return (known_results & CMP_EQ) ? const_true_rtx : const0_rtx; |
6156 | case NE: |
6157 | case LTGT: |
6158 | return (known_results & CMP_EQ) ? const0_rtx : const_true_rtx; |
6159 | |
6160 | case LT: |
6161 | case UNLT: |
6162 | return (known_results & CMP_LT) ? const_true_rtx : const0_rtx; |
6163 | case GE: |
6164 | case UNGE: |
6165 | return (known_results & CMP_LT) ? const0_rtx : const_true_rtx; |
6166 | |
6167 | case GT: |
6168 | case UNGT: |
6169 | return (known_results & CMP_GT) ? const_true_rtx : const0_rtx; |
6170 | case LE: |
6171 | case UNLE: |
6172 | return (known_results & CMP_GT) ? const0_rtx : const_true_rtx; |
6173 | |
6174 | case LTU: |
6175 | return (known_results & CMP_LTU) ? const_true_rtx : const0_rtx; |
6176 | case GEU: |
6177 | return (known_results & CMP_LTU) ? const0_rtx : const_true_rtx; |
6178 | |
6179 | case GTU: |
6180 | return (known_results & CMP_GTU) ? const_true_rtx : const0_rtx; |
6181 | case LEU: |
6182 | return (known_results & CMP_GTU) ? const0_rtx : const_true_rtx; |
6183 | |
6184 | case ORDERED: |
6185 | return const_true_rtx; |
6186 | case UNORDERED: |
6187 | return const0_rtx; |
6188 | default: |
6189 | gcc_unreachable (); |
6190 | } |
6191 | } |
6192 | |
6193 | /* Check if the given comparison (done in the given MODE) is actually |
6194 | a tautology or a contradiction. If the mode is VOIDmode, the |
6195 | comparison is done in "infinite precision". If no simplification |
6196 | is possible, this function returns zero. Otherwise, it returns |
6197 | either const_true_rtx or const0_rtx. */ |
6198 | |
6199 | rtx |
6200 | simplify_const_relational_operation (enum rtx_code code, |
6201 | machine_mode mode, |
6202 | rtx op0, rtx op1) |
6203 | { |
6204 | rtx tem; |
6205 | rtx trueop0; |
6206 | rtx trueop1; |
6207 | |
6208 | gcc_assert (mode != VOIDmode |
6209 | || (GET_MODE (op0) == VOIDmode |
6210 | && GET_MODE (op1) == VOIDmode)); |
6211 | |
6212 | /* We only handle MODE_CC comparisons that are COMPARE against zero. */ |
6213 | if (GET_MODE_CLASS (mode) == MODE_CC |
6214 | && (op1 != const0_rtx |
6215 | || GET_CODE (op0) != COMPARE)) |
6216 | return NULL_RTX; |
6217 | |
6218 | /* If op0 is a compare, extract the comparison arguments from it. */ |
6219 | if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) |
6220 | { |
6221 | op1 = XEXP (op0, 1); |
6222 | op0 = XEXP (op0, 0); |
6223 | |
6224 | if (GET_MODE (op0) != VOIDmode) |
6225 | mode = GET_MODE (op0); |
6226 | else if (GET_MODE (op1) != VOIDmode) |
6227 | mode = GET_MODE (op1); |
6228 | else |
6229 | return 0; |
6230 | } |
6231 | |
6232 | /* We can't simplify MODE_CC values since we don't know what the |
6233 | actual comparison is. */ |
6234 | if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) |
6235 | return 0; |
6236 | |
6237 | /* Make sure the constant is second. */ |
6238 | if (swap_commutative_operands_p (op0, op1)) |
6239 | { |
6240 | std::swap (a&: op0, b&: op1); |
6241 | code = swap_condition (code); |
6242 | } |
6243 | |
6244 | trueop0 = avoid_constant_pool_reference (x: op0); |
6245 | trueop1 = avoid_constant_pool_reference (x: op1); |
6246 | |
6247 | /* For integer comparisons of A and B maybe we can simplify A - B and can |
6248 | then simplify a comparison of that with zero. If A and B are both either |
6249 | a register or a CONST_INT, this can't help; testing for these cases will |
6250 | prevent infinite recursion here and speed things up. |
6251 | |
6252 | We can only do this for EQ and NE comparisons as otherwise we may |
6253 | lose or introduce overflow which we cannot disregard as undefined as |
6254 | we do not know the signedness of the operation on either the left or |
6255 | the right hand side of the comparison. */ |
6256 | |
6257 | if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx |
6258 | && (code == EQ || code == NE) |
6259 | && ! ((REG_P (op0) || CONST_INT_P (trueop0)) |
6260 | && (REG_P (op1) || CONST_INT_P (trueop1))) |
6261 | && (tem = simplify_binary_operation (code: MINUS, mode, op0, op1)) != 0 |
6262 | /* We cannot do this if tem is a nonzero address. */ |
6263 | && ! nonzero_address_p (tem)) |
6264 | return simplify_const_relational_operation (code: signed_condition (code), |
6265 | mode, op0: tem, const0_rtx); |
6266 | |
6267 | if (! HONOR_NANS (mode) && code == ORDERED) |
6268 | return const_true_rtx; |
6269 | |
6270 | if (! HONOR_NANS (mode) && code == UNORDERED) |
6271 | return const0_rtx; |
6272 | |
6273 | /* For modes without NaNs, if the two operands are equal, we know the |
6274 | result except if they have side-effects. Even with NaNs we know |
6275 | the result of unordered comparisons and, if signaling NaNs are |
6276 | irrelevant, also the result of LT/GT/LTGT. */ |
6277 | if ((! HONOR_NANS (trueop0) |
6278 | || code == UNEQ || code == UNLE || code == UNGE |
6279 | || ((code == LT || code == GT || code == LTGT) |
6280 | && ! HONOR_SNANS (trueop0))) |
6281 | && rtx_equal_p (trueop0, trueop1) |
6282 | && ! side_effects_p (trueop0)) |
6283 | return comparison_result (code, known_results: CMP_EQ); |
6284 | |
6285 | /* If the operands are floating-point constants, see if we can fold |
6286 | the result. */ |
6287 | if (CONST_DOUBLE_AS_FLOAT_P (trueop0) |
6288 | && CONST_DOUBLE_AS_FLOAT_P (trueop1) |
6289 | && SCALAR_FLOAT_MODE_P (GET_MODE (trueop0))) |
6290 | { |
6291 | const REAL_VALUE_TYPE *d0 = CONST_DOUBLE_REAL_VALUE (trueop0); |
6292 | const REAL_VALUE_TYPE *d1 = CONST_DOUBLE_REAL_VALUE (trueop1); |
6293 | |
6294 | /* Comparisons are unordered iff at least one of the values is NaN. */ |
6295 | if (REAL_VALUE_ISNAN (*d0) || REAL_VALUE_ISNAN (*d1)) |
6296 | switch (code) |
6297 | { |
6298 | case UNEQ: |
6299 | case UNLT: |
6300 | case UNGT: |
6301 | case UNLE: |
6302 | case UNGE: |
6303 | case NE: |
6304 | case UNORDERED: |
6305 | return const_true_rtx; |
6306 | case EQ: |
6307 | case LT: |
6308 | case GT: |
6309 | case LE: |
6310 | case GE: |
6311 | case LTGT: |
6312 | case ORDERED: |
6313 | return const0_rtx; |
6314 | default: |
6315 | return 0; |
6316 | } |
6317 | |
6318 | return comparison_result (code, |
6319 | known_results: (real_equal (d0, d1) ? CMP_EQ : |
6320 | real_less (d0, d1) ? CMP_LT : CMP_GT)); |
6321 | } |
6322 | |
6323 | /* Otherwise, see if the operands are both integers. */ |
6324 | if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode) |
6325 | && CONST_SCALAR_INT_P (trueop0) && CONST_SCALAR_INT_P (trueop1)) |
6326 | { |
6327 | /* It would be nice if we really had a mode here. However, the |
6328 | largest int representable on the target is as good as |
6329 | infinite. */ |
6330 | machine_mode cmode = (mode == VOIDmode) ? MAX_MODE_INT : mode; |
6331 | rtx_mode_t ptrueop0 = rtx_mode_t (trueop0, cmode); |
6332 | rtx_mode_t ptrueop1 = rtx_mode_t (trueop1, cmode); |
6333 | |
6334 | if (wi::eq_p (x: ptrueop0, y: ptrueop1)) |
6335 | return comparison_result (code, known_results: CMP_EQ); |
6336 | else |
6337 | { |
6338 | int cr = wi::lts_p (x: ptrueop0, y: ptrueop1) ? CMP_LT : CMP_GT; |
6339 | cr |= wi::ltu_p (x: ptrueop0, y: ptrueop1) ? CMP_LTU : CMP_GTU; |
6340 | return comparison_result (code, known_results: cr); |
6341 | } |
6342 | } |
6343 | |
6344 | /* Optimize comparisons with upper and lower bounds. */ |
6345 | scalar_int_mode int_mode; |
6346 | if (CONST_INT_P (trueop1) |
6347 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
6348 | && HWI_COMPUTABLE_MODE_P (mode: int_mode) |
6349 | && !side_effects_p (trueop0)) |
6350 | { |
6351 | int sign; |
6352 | unsigned HOST_WIDE_INT nonzero = nonzero_bits (trueop0, int_mode); |
6353 | HOST_WIDE_INT val = INTVAL (trueop1); |
6354 | HOST_WIDE_INT mmin, mmax; |
6355 | |
6356 | if (code == GEU |
6357 | || code == LEU |
6358 | || code == GTU |
6359 | || code == LTU) |
6360 | sign = 0; |
6361 | else |
6362 | sign = 1; |
6363 | |
6364 | /* Get a reduced range if the sign bit is zero. */ |
6365 | if (nonzero <= (GET_MODE_MASK (int_mode) >> 1)) |
6366 | { |
6367 | mmin = 0; |
6368 | mmax = nonzero; |
6369 | } |
6370 | else |
6371 | { |
6372 | rtx mmin_rtx, mmax_rtx; |
6373 | get_mode_bounds (int_mode, sign, int_mode, &mmin_rtx, &mmax_rtx); |
6374 | |
6375 | mmin = INTVAL (mmin_rtx); |
6376 | mmax = INTVAL (mmax_rtx); |
6377 | if (sign) |
6378 | { |
6379 | unsigned int sign_copies |
6380 | = num_sign_bit_copies (trueop0, int_mode); |
6381 | |
6382 | mmin >>= (sign_copies - 1); |
6383 | mmax >>= (sign_copies - 1); |
6384 | } |
6385 | } |
6386 | |
6387 | switch (code) |
6388 | { |
6389 | /* x >= y is always true for y <= mmin, always false for y > mmax. */ |
6390 | case GEU: |
6391 | if ((unsigned HOST_WIDE_INT) val <= (unsigned HOST_WIDE_INT) mmin) |
6392 | return const_true_rtx; |
6393 | if ((unsigned HOST_WIDE_INT) val > (unsigned HOST_WIDE_INT) mmax) |
6394 | return const0_rtx; |
6395 | break; |
6396 | case GE: |
6397 | if (val <= mmin) |
6398 | return const_true_rtx; |
6399 | if (val > mmax) |
6400 | return const0_rtx; |
6401 | break; |
6402 | |
6403 | /* x <= y is always true for y >= mmax, always false for y < mmin. */ |
6404 | case LEU: |
6405 | if ((unsigned HOST_WIDE_INT) val >= (unsigned HOST_WIDE_INT) mmax) |
6406 | return const_true_rtx; |
6407 | if ((unsigned HOST_WIDE_INT) val < (unsigned HOST_WIDE_INT) mmin) |
6408 | return const0_rtx; |
6409 | break; |
6410 | case LE: |
6411 | if (val >= mmax) |
6412 | return const_true_rtx; |
6413 | if (val < mmin) |
6414 | return const0_rtx; |
6415 | break; |
6416 | |
6417 | case EQ: |
6418 | /* x == y is always false for y out of range. */ |
6419 | if (val < mmin || val > mmax) |
6420 | return const0_rtx; |
6421 | break; |
6422 | |
6423 | /* x > y is always false for y >= mmax, always true for y < mmin. */ |
6424 | case GTU: |
6425 | if ((unsigned HOST_WIDE_INT) val >= (unsigned HOST_WIDE_INT) mmax) |
6426 | return const0_rtx; |
6427 | if ((unsigned HOST_WIDE_INT) val < (unsigned HOST_WIDE_INT) mmin) |
6428 | return const_true_rtx; |
6429 | break; |
6430 | case GT: |
6431 | if (val >= mmax) |
6432 | return const0_rtx; |
6433 | if (val < mmin) |
6434 | return const_true_rtx; |
6435 | break; |
6436 | |
6437 | /* x < y is always false for y <= mmin, always true for y > mmax. */ |
6438 | case LTU: |
6439 | if ((unsigned HOST_WIDE_INT) val <= (unsigned HOST_WIDE_INT) mmin) |
6440 | return const0_rtx; |
6441 | if ((unsigned HOST_WIDE_INT) val > (unsigned HOST_WIDE_INT) mmax) |
6442 | return const_true_rtx; |
6443 | break; |
6444 | case LT: |
6445 | if (val <= mmin) |
6446 | return const0_rtx; |
6447 | if (val > mmax) |
6448 | return const_true_rtx; |
6449 | break; |
6450 | |
6451 | case NE: |
6452 | /* x != y is always true for y out of range. */ |
6453 | if (val < mmin || val > mmax) |
6454 | return const_true_rtx; |
6455 | break; |
6456 | |
6457 | default: |
6458 | break; |
6459 | } |
6460 | } |
6461 | |
6462 | /* Optimize integer comparisons with zero. */ |
6463 | if (is_a <scalar_int_mode> (m: mode, result: &int_mode) |
6464 | && trueop1 == const0_rtx |
6465 | && !side_effects_p (trueop0)) |
6466 | { |
6467 | /* Some addresses are known to be nonzero. We don't know |
6468 | their sign, but equality comparisons are known. */ |
6469 | if (nonzero_address_p (trueop0)) |
6470 | { |
6471 | if (code == EQ || code == LEU) |
6472 | return const0_rtx; |
6473 | if (code == NE || code == GTU) |
6474 | return const_true_rtx; |
6475 | } |
6476 | |
6477 | /* See if the first operand is an IOR with a constant. If so, we |
6478 | may be able to determine the result of this comparison. */ |
6479 | if (GET_CODE (op0) == IOR) |
6480 | { |
6481 | rtx inner_const = avoid_constant_pool_reference (XEXP (op0, 1)); |
6482 | if (CONST_INT_P (inner_const) && inner_const != const0_rtx) |
6483 | { |
6484 | int sign_bitnum = GET_MODE_PRECISION (mode: int_mode) - 1; |
6485 | int has_sign = (HOST_BITS_PER_WIDE_INT >= sign_bitnum |
6486 | && (UINTVAL (inner_const) |
6487 | & (HOST_WIDE_INT_1U |
6488 | << sign_bitnum))); |
6489 | |
6490 | switch (code) |
6491 | { |
6492 | case EQ: |
6493 | case LEU: |
6494 | return const0_rtx; |
6495 | case NE: |
6496 | case GTU: |
6497 | return const_true_rtx; |
6498 | case LT: |
6499 | case LE: |
6500 | if (has_sign) |
6501 | return const_true_rtx; |
6502 | break; |
6503 | case GT: |
6504 | case GE: |
6505 | if (has_sign) |
6506 | return const0_rtx; |
6507 | break; |
6508 | default: |
6509 | break; |
6510 | } |
6511 | } |
6512 | } |
6513 | } |
6514 | |
6515 | /* Optimize comparison of ABS with zero. */ |
6516 | if (trueop1 == CONST0_RTX (mode) && !side_effects_p (trueop0) |
6517 | && (GET_CODE (trueop0) == ABS |
6518 | || (GET_CODE (trueop0) == FLOAT_EXTEND |
6519 | && GET_CODE (XEXP (trueop0, 0)) == ABS))) |
6520 | { |
6521 | switch (code) |
6522 | { |
6523 | case LT: |
6524 | /* Optimize abs(x) < 0.0. */ |
6525 | if (!INTEGRAL_MODE_P (mode) && !HONOR_SNANS (mode)) |
6526 | return const0_rtx; |
6527 | break; |
6528 | |
6529 | case GE: |
6530 | /* Optimize abs(x) >= 0.0. */ |
6531 | if (!INTEGRAL_MODE_P (mode) && !HONOR_NANS (mode)) |
6532 | return const_true_rtx; |
6533 | break; |
6534 | |
6535 | case UNGE: |
6536 | /* Optimize ! (abs(x) < 0.0). */ |
6537 | return const_true_rtx; |
6538 | |
6539 | default: |
6540 | break; |
6541 | } |
6542 | } |
6543 | |
6544 | return 0; |
6545 | } |
6546 | |
6547 | /* Recognize expressions of the form (X CMP 0) ? VAL : OP (X) |
6548 | where OP is CLZ or CTZ and VAL is the value from CLZ_DEFINED_VALUE_AT_ZERO |
6549 | or CTZ_DEFINED_VALUE_AT_ZERO respectively and return OP (X) if the expression |
6550 | can be simplified to that or NULL_RTX if not. |
6551 | Assume X is compared against zero with CMP_CODE and the true |
6552 | arm is TRUE_VAL and the false arm is FALSE_VAL. */ |
6553 | |
6554 | rtx |
6555 | simplify_context::simplify_cond_clz_ctz (rtx x, rtx_code cmp_code, |
6556 | rtx true_val, rtx false_val) |
6557 | { |
6558 | if (cmp_code != EQ && cmp_code != NE) |
6559 | return NULL_RTX; |
6560 | |
6561 | /* Result on X == 0 and X !=0 respectively. */ |
6562 | rtx on_zero, on_nonzero; |
6563 | if (cmp_code == EQ) |
6564 | { |
6565 | on_zero = true_val; |
6566 | on_nonzero = false_val; |
6567 | } |
6568 | else |
6569 | { |
6570 | on_zero = false_val; |
6571 | on_nonzero = true_val; |
6572 | } |
6573 | |
6574 | rtx_code op_code = GET_CODE (on_nonzero); |
6575 | if ((op_code != CLZ && op_code != CTZ) |
6576 | || !rtx_equal_p (XEXP (on_nonzero, 0), x) |
6577 | || !CONST_INT_P (on_zero)) |
6578 | return NULL_RTX; |
6579 | |
6580 | HOST_WIDE_INT op_val; |
6581 | scalar_int_mode mode ATTRIBUTE_UNUSED |
6582 | = as_a <scalar_int_mode> (GET_MODE (XEXP (on_nonzero, 0))); |
6583 | if (((op_code == CLZ && CLZ_DEFINED_VALUE_AT_ZERO (mode, op_val)) |
6584 | || (op_code == CTZ && CTZ_DEFINED_VALUE_AT_ZERO (mode, op_val))) |
6585 | && op_val == INTVAL (on_zero)) |
6586 | return on_nonzero; |
6587 | |
6588 | return NULL_RTX; |
6589 | } |
6590 | |
6591 | /* Try to simplify X given that it appears within operand OP of a |
6592 | VEC_MERGE operation whose mask is MASK. X need not use the same |
6593 | vector mode as the VEC_MERGE, but it must have the same number of |
6594 | elements. |
6595 | |
6596 | Return the simplified X on success, otherwise return NULL_RTX. */ |
6597 | |
6598 | rtx |
6599 | simplify_context::simplify_merge_mask (rtx x, rtx mask, int op) |
6600 | { |
6601 | gcc_assert (VECTOR_MODE_P (GET_MODE (x))); |
6602 | poly_uint64 nunits = GET_MODE_NUNITS (GET_MODE (x)); |
6603 | if (GET_CODE (x) == VEC_MERGE && rtx_equal_p (XEXP (x, 2), mask)) |
6604 | { |
6605 | if (side_effects_p (XEXP (x, 1 - op))) |
6606 | return NULL_RTX; |
6607 | |
6608 | return XEXP (x, op); |
6609 | } |
6610 | if (UNARY_P (x) |
6611 | && VECTOR_MODE_P (GET_MODE (XEXP (x, 0))) |
6612 | && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits)) |
6613 | { |
6614 | rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op); |
6615 | if (top0) |
6616 | return simplify_gen_unary (GET_CODE (x), GET_MODE (x), op: top0, |
6617 | GET_MODE (XEXP (x, 0))); |
6618 | } |
6619 | if (BINARY_P (x) |
6620 | && VECTOR_MODE_P (GET_MODE (XEXP (x, 0))) |
6621 | && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits) |
6622 | && VECTOR_MODE_P (GET_MODE (XEXP (x, 1))) |
6623 | && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 1))), nunits)) |
6624 | { |
6625 | rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op); |
6626 | rtx top1 = simplify_merge_mask (XEXP (x, 1), mask, op); |
6627 | if (top0 || top1) |
6628 | { |
6629 | if (COMPARISON_P (x)) |
6630 | return simplify_gen_relational (GET_CODE (x), GET_MODE (x), |
6631 | GET_MODE (XEXP (x, 0)) != VOIDmode |
6632 | ? GET_MODE (XEXP (x, 0)) |
6633 | : GET_MODE (XEXP (x, 1)), |
6634 | op0: top0 ? top0 : XEXP (x, 0), |
6635 | op1: top1 ? top1 : XEXP (x, 1)); |
6636 | else |
6637 | return simplify_gen_binary (GET_CODE (x), GET_MODE (x), |
6638 | op0: top0 ? top0 : XEXP (x, 0), |
6639 | op1: top1 ? top1 : XEXP (x, 1)); |
6640 | } |
6641 | } |
6642 | if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY |
6643 | && VECTOR_MODE_P (GET_MODE (XEXP (x, 0))) |
6644 | && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits) |
6645 | && VECTOR_MODE_P (GET_MODE (XEXP (x, 1))) |
6646 | && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 1))), nunits) |
6647 | && VECTOR_MODE_P (GET_MODE (XEXP (x, 2))) |
6648 | && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 2))), nunits)) |
6649 | { |
6650 | rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op); |
6651 | rtx top1 = simplify_merge_mask (XEXP (x, 1), mask, op); |
6652 | rtx top2 = simplify_merge_mask (XEXP (x, 2), mask, op); |
6653 | if (top0 || top1 || top2) |
6654 | return simplify_gen_ternary (GET_CODE (x), GET_MODE (x), |
6655 | GET_MODE (XEXP (x, 0)), |
6656 | op0: top0 ? top0 : XEXP (x, 0), |
6657 | op1: top1 ? top1 : XEXP (x, 1), |
6658 | op2: top2 ? top2 : XEXP (x, 2)); |
6659 | } |
6660 | return NULL_RTX; |
6661 | } |
6662 | |
6663 | |
6664 | /* Simplify CODE, an operation with result mode MODE and three operands, |
6665 | OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became |
6666 | a constant. Return 0 if no simplifications is possible. */ |
6667 | |
6668 | rtx |
6669 | simplify_context::simplify_ternary_operation (rtx_code code, machine_mode mode, |
6670 | machine_mode op0_mode, |
6671 | rtx op0, rtx op1, rtx op2) |
6672 | { |
6673 | bool any_change = false; |
6674 | rtx tem, trueop2; |
6675 | scalar_int_mode int_mode, int_op0_mode; |
6676 | unsigned int n_elts; |
6677 | |
6678 | switch (code) |
6679 | { |
6680 | case FMA: |
6681 | /* Simplify negations around the multiplication. */ |
6682 | /* -a * -b + c => a * b + c. */ |
6683 | if (GET_CODE (op0) == NEG) |
6684 | { |
6685 | tem = simplify_unary_operation (code: NEG, mode, op: op1, op_mode: mode); |
6686 | if (tem) |
6687 | op1 = tem, op0 = XEXP (op0, 0), any_change = true; |
6688 | } |
6689 | else if (GET_CODE (op1) == NEG) |
6690 | { |
6691 | tem = simplify_unary_operation (code: NEG, mode, op: op0, op_mode: mode); |
6692 | if (tem) |
6693 | op0 = tem, op1 = XEXP (op1, 0), any_change = true; |
6694 | } |
6695 | |
6696 | /* Canonicalize the two multiplication operands. */ |
6697 | /* a * -b + c => -b * a + c. */ |
6698 | if (swap_commutative_operands_p (op0, op1)) |
6699 | std::swap (a&: op0, b&: op1), any_change = true; |
6700 | |
6701 | if (any_change) |
6702 | return gen_rtx_FMA (mode, op0, op1, op2); |
6703 | return NULL_RTX; |
6704 | |
6705 | case SIGN_EXTRACT: |
6706 | case ZERO_EXTRACT: |
6707 | if (CONST_INT_P (op0) |
6708 | && CONST_INT_P (op1) |
6709 | && CONST_INT_P (op2) |
6710 | && is_a <scalar_int_mode> (m: mode, result: &int_mode) |
6711 | && INTVAL (op1) + INTVAL (op2) <= GET_MODE_PRECISION (mode: int_mode) |
6712 | && HWI_COMPUTABLE_MODE_P (mode: int_mode)) |
6713 | { |
6714 | /* Extracting a bit-field from a constant */ |
6715 | unsigned HOST_WIDE_INT val = UINTVAL (op0); |
6716 | HOST_WIDE_INT op1val = INTVAL (op1); |
6717 | HOST_WIDE_INT op2val = INTVAL (op2); |
6718 | if (!BITS_BIG_ENDIAN) |
6719 | val >>= op2val; |
6720 | else if (is_a <scalar_int_mode> (m: op0_mode, result: &int_op0_mode)) |
6721 | val >>= GET_MODE_PRECISION (mode: int_op0_mode) - op2val - op1val; |
6722 | else |
6723 | /* Not enough information to calculate the bit position. */ |
6724 | break; |
6725 | |
6726 | if (HOST_BITS_PER_WIDE_INT != op1val) |
6727 | { |
6728 | /* First zero-extend. */ |
6729 | val &= (HOST_WIDE_INT_1U << op1val) - 1; |
6730 | /* If desired, propagate sign bit. */ |
6731 | if (code == SIGN_EXTRACT |
6732 | && (val & (HOST_WIDE_INT_1U << (op1val - 1))) |
6733 | != 0) |
6734 | val |= ~ ((HOST_WIDE_INT_1U << op1val) - 1); |
6735 | } |
6736 | |
6737 | return gen_int_mode (val, int_mode); |
6738 | } |
6739 | break; |
6740 | |
6741 | case IF_THEN_ELSE: |
6742 | if (CONST_INT_P (op0)) |
6743 | return op0 != const0_rtx ? op1 : op2; |
6744 | |
6745 | /* Convert c ? a : a into "a". */ |
6746 | if (rtx_equal_p (op1, op2) && ! side_effects_p (op0)) |
6747 | return op1; |
6748 | |
6749 | /* Convert a != b ? a : b into "a". */ |
6750 | if (GET_CODE (op0) == NE |
6751 | && ! side_effects_p (op0) |
6752 | && ! HONOR_NANS (mode) |
6753 | && ! HONOR_SIGNED_ZEROS (mode) |
6754 | && ((rtx_equal_p (XEXP (op0, 0), op1) |
6755 | && rtx_equal_p (XEXP (op0, 1), op2)) |
6756 | || (rtx_equal_p (XEXP (op0, 0), op2) |
6757 | && rtx_equal_p (XEXP (op0, 1), op1)))) |
6758 | return op1; |
6759 | |
6760 | /* Convert a == b ? a : b into "b". */ |
6761 | if (GET_CODE (op0) == EQ |
6762 | && ! side_effects_p (op0) |
6763 | && ! HONOR_NANS (mode) |
6764 | && ! HONOR_SIGNED_ZEROS (mode) |
6765 | && ((rtx_equal_p (XEXP (op0, 0), op1) |
6766 | && rtx_equal_p (XEXP (op0, 1), op2)) |
6767 | || (rtx_equal_p (XEXP (op0, 0), op2) |
6768 | && rtx_equal_p (XEXP (op0, 1), op1)))) |
6769 | return op2; |
6770 | |
6771 | /* Convert (!c) != {0,...,0} ? a : b into |
6772 | c != {0,...,0} ? b : a for vector modes. */ |
6773 | if (VECTOR_MODE_P (GET_MODE (op1)) |
6774 | && GET_CODE (op0) == NE |
6775 | && GET_CODE (XEXP (op0, 0)) == NOT |
6776 | && GET_CODE (XEXP (op0, 1)) == CONST_VECTOR) |
6777 | { |
6778 | rtx cv = XEXP (op0, 1); |
6779 | int nunits; |
6780 | bool ok = true; |
6781 | if (!CONST_VECTOR_NUNITS (cv).is_constant (const_value: &nunits)) |
6782 | ok = false; |
6783 | else |
6784 | for (int i = 0; i < nunits; ++i) |
6785 | if (CONST_VECTOR_ELT (cv, i) != const0_rtx) |
6786 | { |
6787 | ok = false; |
6788 | break; |
6789 | } |
6790 | if (ok) |
6791 | { |
6792 | rtx new_op0 = gen_rtx_NE (GET_MODE (op0), |
6793 | XEXP (XEXP (op0, 0), 0), |
6794 | XEXP (op0, 1)); |
6795 | rtx retval = gen_rtx_IF_THEN_ELSE (mode, new_op0, op2, op1); |
6796 | return retval; |
6797 | } |
6798 | } |
6799 | |
6800 | /* Convert x == 0 ? N : clz (x) into clz (x) when |
6801 | CLZ_DEFINED_VALUE_AT_ZERO is defined to N for the mode of x. |
6802 | Similarly for ctz (x). */ |
6803 | if (COMPARISON_P (op0) && !side_effects_p (op0) |
6804 | && XEXP (op0, 1) == const0_rtx) |
6805 | { |
6806 | rtx simplified |
6807 | = simplify_cond_clz_ctz (XEXP (op0, 0), GET_CODE (op0), |
6808 | true_val: op1, false_val: op2); |
6809 | if (simplified) |
6810 | return simplified; |
6811 | } |
6812 | |
6813 | if (COMPARISON_P (op0) && ! side_effects_p (op0)) |
6814 | { |
6815 | machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode |
6816 | ? GET_MODE (XEXP (op0, 1)) |
6817 | : GET_MODE (XEXP (op0, 0))); |
6818 | rtx temp; |
6819 | |
6820 | /* Look for happy constants in op1 and op2. */ |
6821 | if (CONST_INT_P (op1) && CONST_INT_P (op2)) |
6822 | { |
6823 | HOST_WIDE_INT t = INTVAL (op1); |
6824 | HOST_WIDE_INT f = INTVAL (op2); |
6825 | |
6826 | if (t == STORE_FLAG_VALUE && f == 0) |
6827 | code = GET_CODE (op0); |
6828 | else if (t == 0 && f == STORE_FLAG_VALUE) |
6829 | { |
6830 | enum rtx_code tmp; |
6831 | tmp = reversed_comparison_code (op0, NULL); |
6832 | if (tmp == UNKNOWN) |
6833 | break; |
6834 | code = tmp; |
6835 | } |
6836 | else |
6837 | break; |
6838 | |
6839 | return simplify_gen_relational (code, mode, cmp_mode, |
6840 | XEXP (op0, 0), XEXP (op0, 1)); |
6841 | } |
6842 | |
6843 | temp = simplify_relational_operation (GET_CODE (op0), mode: op0_mode, |
6844 | cmp_mode, XEXP (op0, 0), |
6845 | XEXP (op0, 1)); |
6846 | |
6847 | /* See if any simplifications were possible. */ |
6848 | if (temp) |
6849 | { |
6850 | if (CONST_INT_P (temp)) |
6851 | return temp == const0_rtx ? op2 : op1; |
6852 | else if (temp) |
6853 | return gen_rtx_IF_THEN_ELSE (mode, temp, op1, op2); |
6854 | } |
6855 | } |
6856 | break; |
6857 | |
6858 | case VEC_MERGE: |
6859 | gcc_assert (GET_MODE (op0) == mode); |
6860 | gcc_assert (GET_MODE (op1) == mode); |
6861 | gcc_assert (VECTOR_MODE_P (mode)); |
6862 | trueop2 = avoid_constant_pool_reference (x: op2); |
6863 | if (CONST_INT_P (trueop2) |
6864 | && GET_MODE_NUNITS (mode).is_constant (const_value: &n_elts)) |
6865 | { |
6866 | unsigned HOST_WIDE_INT sel = UINTVAL (trueop2); |
6867 | unsigned HOST_WIDE_INT mask; |
6868 | if (n_elts == HOST_BITS_PER_WIDE_INT) |
6869 | mask = -1; |
6870 | else |
6871 | mask = (HOST_WIDE_INT_1U << n_elts) - 1; |
6872 | |
6873 | if (!(sel & mask) && !side_effects_p (op0)) |
6874 | return op1; |
6875 | if ((sel & mask) == mask && !side_effects_p (op1)) |
6876 | return op0; |
6877 | |
6878 | rtx trueop0 = avoid_constant_pool_reference (x: op0); |
6879 | rtx trueop1 = avoid_constant_pool_reference (x: op1); |
6880 | if (GET_CODE (trueop0) == CONST_VECTOR |
6881 | && GET_CODE (trueop1) == CONST_VECTOR) |
6882 | { |
6883 | rtvec v = rtvec_alloc (n_elts); |
6884 | unsigned int i; |
6885 | |
6886 | for (i = 0; i < n_elts; i++) |
6887 | RTVEC_ELT (v, i) = ((sel & (HOST_WIDE_INT_1U << i)) |
6888 | ? CONST_VECTOR_ELT (trueop0, i) |
6889 | : CONST_VECTOR_ELT (trueop1, i)); |
6890 | return gen_rtx_CONST_VECTOR (mode, v); |
6891 | } |
6892 | |
6893 | /* Replace (vec_merge (vec_merge a b m) c n) with (vec_merge b c n) |
6894 | if no element from a appears in the result. */ |
6895 | if (GET_CODE (op0) == VEC_MERGE) |
6896 | { |
6897 | tem = avoid_constant_pool_reference (XEXP (op0, 2)); |
6898 | if (CONST_INT_P (tem)) |
6899 | { |
6900 | unsigned HOST_WIDE_INT sel0 = UINTVAL (tem); |
6901 | if (!(sel & sel0 & mask) && !side_effects_p (XEXP (op0, 0))) |
6902 | return simplify_gen_ternary (code, mode, op0_mode: mode, |
6903 | XEXP (op0, 1), op1, op2); |
6904 | if (!(sel & ~sel0 & mask) && !side_effects_p (XEXP (op0, 1))) |
6905 | return simplify_gen_ternary (code, mode, op0_mode: mode, |
6906 | XEXP (op0, 0), op1, op2); |
6907 | } |
6908 | } |
6909 | if (GET_CODE (op1) == VEC_MERGE) |
6910 | { |
6911 | tem = avoid_constant_pool_reference (XEXP (op1, 2)); |
6912 | if (CONST_INT_P (tem)) |
6913 | { |
6914 | unsigned HOST_WIDE_INT sel1 = UINTVAL (tem); |
6915 | if (!(~sel & sel1 & mask) && !side_effects_p (XEXP (op1, 0))) |
6916 | return simplify_gen_ternary (code, mode, op0_mode: mode, |
6917 | op0, XEXP (op1, 1), op2); |
6918 | if (!(~sel & ~sel1 & mask) && !side_effects_p (XEXP (op1, 1))) |
6919 | return simplify_gen_ternary (code, mode, op0_mode: mode, |
6920 | op0, XEXP (op1, 0), op2); |
6921 | } |
6922 | } |
6923 | |
6924 | /* Replace (vec_merge (vec_duplicate (vec_select a parallel (i))) a 1 << i) |
6925 | with a. */ |
6926 | if (GET_CODE (op0) == VEC_DUPLICATE |
6927 | && GET_CODE (XEXP (op0, 0)) == VEC_SELECT |
6928 | && GET_CODE (XEXP (XEXP (op0, 0), 1)) == PARALLEL |
6929 | && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (op0, 0))), 1)) |
6930 | { |
6931 | tem = XVECEXP ((XEXP (XEXP (op0, 0), 1)), 0, 0); |
6932 | if (CONST_INT_P (tem) && CONST_INT_P (op2)) |
6933 | { |
6934 | if (XEXP (XEXP (op0, 0), 0) == op1 |
6935 | && UINTVAL (op2) == HOST_WIDE_INT_1U << UINTVAL (tem)) |
6936 | return op1; |
6937 | } |
6938 | } |
6939 | /* Replace (vec_merge (vec_duplicate (X)) (const_vector [A, B]) |
6940 | (const_int N)) |
6941 | with (vec_concat (X) (B)) if N == 1 or |
6942 | (vec_concat (A) (X)) if N == 2. */ |
6943 | if (GET_CODE (op0) == VEC_DUPLICATE |
6944 | && GET_CODE (op1) == CONST_VECTOR |
6945 | && known_eq (CONST_VECTOR_NUNITS (op1), 2) |
6946 | && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2) |
6947 | && IN_RANGE (sel, 1, 2)) |
6948 | { |
6949 | rtx newop0 = XEXP (op0, 0); |
6950 | rtx newop1 = CONST_VECTOR_ELT (op1, 2 - sel); |
6951 | if (sel == 2) |
6952 | std::swap (a&: newop0, b&: newop1); |
6953 | return simplify_gen_binary (code: VEC_CONCAT, mode, op0: newop0, op1: newop1); |
6954 | } |
6955 | /* Replace (vec_merge (vec_duplicate x) (vec_concat (y) (z)) (const_int N)) |
6956 | with (vec_concat x z) if N == 1, or (vec_concat y x) if N == 2. |
6957 | Only applies for vectors of two elements. */ |
6958 | if (GET_CODE (op0) == VEC_DUPLICATE |
6959 | && GET_CODE (op1) == VEC_CONCAT |
6960 | && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2) |
6961 | && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2) |
6962 | && IN_RANGE (sel, 1, 2)) |
6963 | { |
6964 | rtx newop0 = XEXP (op0, 0); |
6965 | rtx newop1 = XEXP (op1, 2 - sel); |
6966 | rtx otherop = XEXP (op1, sel - 1); |
6967 | if (sel == 2) |
6968 | std::swap (a&: newop0, b&: newop1); |
6969 | /* Don't want to throw away the other part of the vec_concat if |
6970 | it has side-effects. */ |
6971 | if (!side_effects_p (otherop)) |
6972 | return simplify_gen_binary (code: VEC_CONCAT, mode, op0: newop0, op1: newop1); |
6973 | } |
6974 | |
6975 | /* Replace: |
6976 | |
6977 | (vec_merge:outer (vec_duplicate:outer x:inner) |
6978 | (subreg:outer y:inner 0) |
6979 | (const_int N)) |
6980 | |
6981 | with (vec_concat:outer x:inner y:inner) if N == 1, |
6982 | or (vec_concat:outer y:inner x:inner) if N == 2. |
6983 | |
6984 | Implicitly, this means we have a paradoxical subreg, but such |
6985 | a check is cheap, so make it anyway. |
6986 | |
6987 | Only applies for vectors of two elements. */ |
6988 | if (GET_CODE (op0) == VEC_DUPLICATE |
6989 | && GET_CODE (op1) == SUBREG |
6990 | && GET_MODE (op1) == GET_MODE (op0) |
6991 | && GET_MODE (SUBREG_REG (op1)) == GET_MODE (XEXP (op0, 0)) |
6992 | && paradoxical_subreg_p (x: op1) |
6993 | && subreg_lowpart_p (op1) |
6994 | && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2) |
6995 | && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2) |
6996 | && IN_RANGE (sel, 1, 2)) |
6997 | { |
6998 | rtx newop0 = XEXP (op0, 0); |
6999 | rtx newop1 = SUBREG_REG (op1); |
7000 | if (sel == 2) |
7001 | std::swap (a&: newop0, b&: newop1); |
7002 | return simplify_gen_binary (code: VEC_CONCAT, mode, op0: newop0, op1: newop1); |
7003 | } |
7004 | |
7005 | /* Same as above but with switched operands: |
7006 | Replace (vec_merge:outer (subreg:outer x:inner 0) |
7007 | (vec_duplicate:outer y:inner) |
7008 | (const_int N)) |
7009 | |
7010 | with (vec_concat:outer x:inner y:inner) if N == 1, |
7011 | or (vec_concat:outer y:inner x:inner) if N == 2. */ |
7012 | if (GET_CODE (op1) == VEC_DUPLICATE |
7013 | && GET_CODE (op0) == SUBREG |
7014 | && GET_MODE (op0) == GET_MODE (op1) |
7015 | && GET_MODE (SUBREG_REG (op0)) == GET_MODE (XEXP (op1, 0)) |
7016 | && paradoxical_subreg_p (x: op0) |
7017 | && subreg_lowpart_p (op0) |
7018 | && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2) |
7019 | && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2) |
7020 | && IN_RANGE (sel, 1, 2)) |
7021 | { |
7022 | rtx newop0 = SUBREG_REG (op0); |
7023 | rtx newop1 = XEXP (op1, 0); |
7024 | if (sel == 2) |
7025 | std::swap (a&: newop0, b&: newop1); |
7026 | return simplify_gen_binary (code: VEC_CONCAT, mode, op0: newop0, op1: newop1); |
7027 | } |
7028 | |
7029 | /* Replace (vec_merge (vec_duplicate x) (vec_duplicate y) |
7030 | (const_int n)) |
7031 | with (vec_concat x y) or (vec_concat y x) depending on value |
7032 | of N. */ |
7033 | if (GET_CODE (op0) == VEC_DUPLICATE |
7034 | && GET_CODE (op1) == VEC_DUPLICATE |
7035 | && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2) |
7036 | && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2) |
7037 | && IN_RANGE (sel, 1, 2)) |
7038 | { |
7039 | rtx newop0 = XEXP (op0, 0); |
7040 | rtx newop1 = XEXP (op1, 0); |
7041 | if (sel == 2) |
7042 | std::swap (a&: newop0, b&: newop1); |
7043 | |
7044 | return simplify_gen_binary (code: VEC_CONCAT, mode, op0: newop0, op1: newop1); |
7045 | } |
7046 | } |
7047 | |
7048 | if (rtx_equal_p (op0, op1) |
7049 | && !side_effects_p (op2) && !side_effects_p (op1)) |
7050 | return op0; |
7051 | |
7052 | if (!side_effects_p (op2)) |
7053 | { |
7054 | rtx top0 |
7055 | = may_trap_p (op0) ? NULL_RTX : simplify_merge_mask (x: op0, mask: op2, op: 0); |
7056 | rtx top1 |
7057 | = may_trap_p (op1) ? NULL_RTX : simplify_merge_mask (x: op1, mask: op2, op: 1); |
7058 | if (top0 || top1) |
7059 | return simplify_gen_ternary (code, mode, op0_mode: mode, |
7060 | op0: top0 ? top0 : op0, |
7061 | op1: top1 ? top1 : op1, op2); |
7062 | } |
7063 | |
7064 | break; |
7065 | |
7066 | default: |
7067 | gcc_unreachable (); |
7068 | } |
7069 | |
7070 | return 0; |
7071 | } |
7072 | |
7073 | /* Try to calculate NUM_BYTES bytes of the target memory image of X, |
7074 | starting at byte FIRST_BYTE. Return true on success and add the |
7075 | bytes to BYTES, such that each byte has BITS_PER_UNIT bits and such |
7076 | that the bytes follow target memory order. Leave BYTES unmodified |
7077 | on failure. |
7078 | |
7079 | MODE is the mode of X. The caller must reserve NUM_BYTES bytes in |
7080 | BYTES before calling this function. */ |
7081 | |
7082 | bool |
7083 | native_encode_rtx (machine_mode mode, rtx x, vec<target_unit> &bytes, |
7084 | unsigned int first_byte, unsigned int num_bytes) |
7085 | { |
7086 | /* Check the mode is sensible. */ |
7087 | gcc_assert (GET_MODE (x) == VOIDmode |
7088 | ? is_a <scalar_int_mode> (mode) |
7089 | : mode == GET_MODE (x)); |
7090 | |
7091 | if (GET_CODE (x) == CONST_VECTOR) |
7092 | { |
7093 | /* CONST_VECTOR_ELT follows target memory order, so no shuffling |
7094 | is necessary. The only complication is that MODE_VECTOR_BOOL |
7095 | vectors can have several elements per byte. */ |
7096 | unsigned int elt_bits = vector_element_size (GET_MODE_PRECISION (mode), |
7097 | GET_MODE_NUNITS (mode)); |
7098 | unsigned int elt = first_byte * BITS_PER_UNIT / elt_bits; |
7099 | if (elt_bits < BITS_PER_UNIT) |
7100 | { |
7101 | /* This is the only case in which elements can be smaller than |
7102 | a byte. */ |
7103 | gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL); |
7104 | auto mask = GET_MODE_MASK (GET_MODE_INNER (mode)); |
7105 | for (unsigned int i = 0; i < num_bytes; ++i) |
7106 | { |
7107 | target_unit value = 0; |
7108 | for (unsigned int j = 0; j < BITS_PER_UNIT; j += elt_bits) |
7109 | { |
7110 | value |= (INTVAL (CONST_VECTOR_ELT (x, elt)) & mask) << j; |
7111 | elt += 1; |
7112 | } |
7113 | bytes.quick_push (obj: value); |
7114 | } |
7115 | return true; |
7116 | } |
7117 | |
7118 | unsigned int start = bytes.length (); |
7119 | unsigned int elt_bytes = GET_MODE_UNIT_SIZE (mode); |
7120 | /* Make FIRST_BYTE relative to ELT. */ |
7121 | first_byte %= elt_bytes; |
7122 | while (num_bytes > 0) |
7123 | { |
7124 | /* Work out how many bytes we want from element ELT. */ |
7125 | unsigned int chunk_bytes = MIN (num_bytes, elt_bytes - first_byte); |
7126 | if (!native_encode_rtx (GET_MODE_INNER (mode), |
7127 | CONST_VECTOR_ELT (x, elt), bytes, |
7128 | first_byte, num_bytes: chunk_bytes)) |
7129 | { |
7130 | bytes.truncate (size: start); |
7131 | return false; |
7132 | } |
7133 | elt += 1; |
7134 | first_byte = 0; |
7135 | num_bytes -= chunk_bytes; |
7136 | } |
7137 | return true; |
7138 | } |
7139 | |
7140 | /* All subsequent cases are limited to scalars. */ |
7141 | scalar_mode smode; |
7142 | if (!is_a <scalar_mode> (m: mode, result: &smode)) |
7143 | return false; |
7144 | |
7145 | /* Make sure that the region is in range. */ |
7146 | unsigned int end_byte = first_byte + num_bytes; |
7147 | unsigned int mode_bytes = GET_MODE_SIZE (mode: smode); |
7148 | gcc_assert (end_byte <= mode_bytes); |
7149 | |
7150 | if (CONST_SCALAR_INT_P (x)) |
7151 | { |
7152 | /* The target memory layout is affected by both BYTES_BIG_ENDIAN |
7153 | and WORDS_BIG_ENDIAN. Use the subreg machinery to get the lsb |
7154 | position of each byte. */ |
7155 | rtx_mode_t value (x, smode); |
7156 | wide_int_ref value_wi (value); |
7157 | for (unsigned int byte = first_byte; byte < end_byte; ++byte) |
7158 | { |
7159 | /* Always constant because the inputs are. */ |
7160 | unsigned int lsb |
7161 | = subreg_size_lsb (1, mode_bytes, byte).to_constant (); |
7162 | /* Operate directly on the encoding rather than using |
7163 | wi::extract_uhwi, so that we preserve the sign or zero |
7164 | extension for modes that are not a whole number of bits in |
7165 | size. (Zero extension is only used for the combination of |
7166 | innermode == BImode && STORE_FLAG_VALUE == 1). */ |
7167 | unsigned int elt = lsb / HOST_BITS_PER_WIDE_INT; |
7168 | unsigned int shift = lsb % HOST_BITS_PER_WIDE_INT; |
7169 | unsigned HOST_WIDE_INT uhwi = value_wi.elt (i: elt); |
7170 | bytes.quick_push (obj: uhwi >> shift); |
7171 | } |
7172 | return true; |
7173 | } |
7174 | |
7175 | if (CONST_DOUBLE_P (x)) |
7176 | { |
7177 | /* real_to_target produces an array of integers in target memory order. |
7178 | All integers before the last one have 32 bits; the last one may |
7179 | have 32 bits or fewer, depending on whether the mode bitsize |
7180 | is divisible by 32. Each of these integers is then laid out |
7181 | in target memory as any other integer would be. */ |
7182 | long el32[MAX_BITSIZE_MODE_ANY_MODE / 32]; |
7183 | real_to_target (el32, CONST_DOUBLE_REAL_VALUE (x), smode); |
7184 | |
7185 | /* The (maximum) number of target bytes per element of el32. */ |
7186 | unsigned int bytes_per_el32 = 32 / BITS_PER_UNIT; |
7187 | gcc_assert (bytes_per_el32 != 0); |
7188 | |
7189 | /* Build up the integers in a similar way to the CONST_SCALAR_INT_P |
7190 | handling above. */ |
7191 | for (unsigned int byte = first_byte; byte < end_byte; ++byte) |
7192 | { |
7193 | unsigned int index = byte / bytes_per_el32; |
7194 | unsigned int subbyte = byte % bytes_per_el32; |
7195 | unsigned int int_bytes = MIN (bytes_per_el32, |
7196 | mode_bytes - index * bytes_per_el32); |
7197 | /* Always constant because the inputs are. */ |
7198 | unsigned int lsb |
7199 | = subreg_size_lsb (1, int_bytes, subbyte).to_constant (); |
7200 | bytes.quick_push (obj: (unsigned long) el32[index] >> lsb); |
7201 | } |
7202 | return true; |
7203 | } |
7204 | |
7205 | if (GET_CODE (x) == CONST_FIXED) |
7206 | { |
7207 | for (unsigned int byte = first_byte; byte < end_byte; ++byte) |
7208 | { |
7209 | /* Always constant because the inputs are. */ |
7210 | unsigned int lsb |
7211 | = subreg_size_lsb (1, mode_bytes, byte).to_constant (); |
7212 | unsigned HOST_WIDE_INT piece = CONST_FIXED_VALUE_LOW (x); |
7213 | if (lsb >= HOST_BITS_PER_WIDE_INT) |
7214 | { |
7215 | lsb -= HOST_BITS_PER_WIDE_INT; |
7216 | piece = CONST_FIXED_VALUE_HIGH (x); |
7217 | } |
7218 | bytes.quick_push (obj: piece >> lsb); |
7219 | } |
7220 | return true; |
7221 | } |
7222 | |
7223 | return false; |
7224 | } |
7225 | |
7226 | /* Read a vector of mode MODE from the target memory image given by BYTES, |
7227 | starting at byte FIRST_BYTE. The vector is known to be encodable using |
7228 | NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements each, |
7229 | and BYTES is known to have enough bytes to supply NPATTERNS * |
7230 | NELTS_PER_PATTERN vector elements. Each element of BYTES contains |
7231 | BITS_PER_UNIT bits and the bytes are in target memory order. |
7232 | |
7233 | Return the vector on success, otherwise return NULL_RTX. */ |
7234 | |
7235 | rtx |
7236 | native_decode_vector_rtx (machine_mode mode, const vec<target_unit> &bytes, |
7237 | unsigned int first_byte, unsigned int npatterns, |
7238 | unsigned int nelts_per_pattern) |
7239 | { |
7240 | rtx_vector_builder builder (mode, npatterns, nelts_per_pattern); |
7241 | |
7242 | unsigned int elt_bits = vector_element_size (GET_MODE_PRECISION (mode), |
7243 | GET_MODE_NUNITS (mode)); |
7244 | if (elt_bits < BITS_PER_UNIT) |
7245 | { |
7246 | /* This is the only case in which elements can be smaller than a byte. |
7247 | Element 0 is always in the lsb of the containing byte. */ |
7248 | gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL); |
7249 | for (unsigned int i = 0; i < builder.encoded_nelts (); ++i) |
7250 | { |
7251 | unsigned int bit_index = first_byte * BITS_PER_UNIT + i * elt_bits; |
7252 | unsigned int byte_index = bit_index / BITS_PER_UNIT; |
7253 | unsigned int lsb = bit_index % BITS_PER_UNIT; |
7254 | unsigned int value = bytes[byte_index] >> lsb; |
7255 | builder.quick_push (obj: gen_int_mode (value, GET_MODE_INNER (mode))); |
7256 | } |
7257 | } |
7258 | else |
7259 | { |
7260 | for (unsigned int i = 0; i < builder.encoded_nelts (); ++i) |
7261 | { |
7262 | rtx x = native_decode_rtx (GET_MODE_INNER (mode), bytes, first_byte); |
7263 | if (!x) |
7264 | return NULL_RTX; |
7265 | builder.quick_push (obj: x); |
7266 | first_byte += elt_bits / BITS_PER_UNIT; |
7267 | } |
7268 | } |
7269 | return builder.build (); |
7270 | } |
7271 | |
7272 | /* Read an rtx of mode MODE from the target memory image given by BYTES, |
7273 | starting at byte FIRST_BYTE. Each element of BYTES contains BITS_PER_UNIT |
7274 | bits and the bytes are in target memory order. The image has enough |
7275 | values to specify all bytes of MODE. |
7276 | |
7277 | Return the rtx on success, otherwise return NULL_RTX. */ |
7278 | |
7279 | rtx |
7280 | native_decode_rtx (machine_mode mode, const vec<target_unit> &bytes, |
7281 | unsigned int first_byte) |
7282 | { |
7283 | if (VECTOR_MODE_P (mode)) |
7284 | { |
7285 | /* If we know at compile time how many elements there are, |
7286 | pull each element directly from BYTES. */ |
7287 | unsigned int nelts; |
7288 | if (GET_MODE_NUNITS (mode).is_constant (const_value: &nelts)) |
7289 | return native_decode_vector_rtx (mode, bytes, first_byte, npatterns: nelts, nelts_per_pattern: 1); |
7290 | return NULL_RTX; |
7291 | } |
7292 | |
7293 | scalar_int_mode imode; |
7294 | if (is_a <scalar_int_mode> (m: mode, result: &imode) |
7295 | && GET_MODE_PRECISION (mode: imode) <= MAX_BITSIZE_MODE_ANY_INT) |
7296 | { |
7297 | /* Pull the bytes msb first, so that we can use simple |
7298 | shift-and-insert wide_int operations. */ |
7299 | unsigned int size = GET_MODE_SIZE (mode: imode); |
7300 | wide_int result (wi::zero (precision: GET_MODE_PRECISION (mode: imode))); |
7301 | for (unsigned int i = 0; i < size; ++i) |
7302 | { |
7303 | unsigned int lsb = (size - i - 1) * BITS_PER_UNIT; |
7304 | /* Always constant because the inputs are. */ |
7305 | unsigned int subbyte |
7306 | = subreg_size_offset_from_lsb (1, size, lsb).to_constant (); |
7307 | result <<= BITS_PER_UNIT; |
7308 | result |= bytes[first_byte + subbyte]; |
7309 | } |
7310 | return immed_wide_int_const (result, imode); |
7311 | } |
7312 | |
7313 | scalar_float_mode fmode; |
7314 | if (is_a <scalar_float_mode> (m: mode, result: &fmode)) |
7315 | { |
7316 | /* We need to build an array of integers in target memory order. |
7317 | All integers before the last one have 32 bits; the last one may |
7318 | have 32 bits or fewer, depending on whether the mode bitsize |
7319 | is divisible by 32. */ |
7320 | long el32[MAX_BITSIZE_MODE_ANY_MODE / 32]; |
7321 | unsigned int num_el32 = CEIL (GET_MODE_BITSIZE (fmode), 32); |
7322 | memset (s: el32, c: 0, n: num_el32 * sizeof (long)); |
7323 | |
7324 | /* The (maximum) number of target bytes per element of el32. */ |
7325 | unsigned int bytes_per_el32 = 32 / BITS_PER_UNIT; |
7326 | gcc_assert (bytes_per_el32 != 0); |
7327 | |
7328 | unsigned int mode_bytes = GET_MODE_SIZE (mode: fmode); |
7329 | for (unsigned int byte = 0; byte < mode_bytes; ++byte) |
7330 | { |
7331 | unsigned int index = byte / bytes_per_el32; |
7332 | unsigned int subbyte = byte % bytes_per_el32; |
7333 | unsigned int int_bytes = MIN (bytes_per_el32, |
7334 | mode_bytes - index * bytes_per_el32); |
7335 | /* Always constant because the inputs are. */ |
7336 | unsigned int lsb |
7337 | = subreg_size_lsb (1, int_bytes, subbyte).to_constant (); |
7338 | el32[index] |= (unsigned long) bytes[first_byte + byte] << lsb; |
7339 | } |
7340 | REAL_VALUE_TYPE r; |
7341 | real_from_target (&r, el32, fmode); |
7342 | return const_double_from_real_value (r, fmode); |
7343 | } |
7344 | |
7345 | if (ALL_SCALAR_FIXED_POINT_MODE_P (mode)) |
7346 | { |
7347 | scalar_mode smode = as_a <scalar_mode> (m: mode); |
7348 | FIXED_VALUE_TYPE f; |
7349 | f.data.low = 0; |
7350 | f.data.high = 0; |
7351 | f.mode = smode; |
7352 | |
7353 | unsigned int mode_bytes = GET_MODE_SIZE (mode: smode); |
7354 | for (unsigned int byte = 0; byte < mode_bytes; ++byte) |
7355 | { |
7356 | /* Always constant because the inputs are. */ |
7357 | unsigned int lsb |
7358 | = subreg_size_lsb (1, mode_bytes, byte).to_constant (); |
7359 | unsigned HOST_WIDE_INT unit = bytes[first_byte + byte]; |
7360 | if (lsb >= HOST_BITS_PER_WIDE_INT) |
7361 | f.data.high |= unit << (lsb - HOST_BITS_PER_WIDE_INT); |
7362 | else |
7363 | f.data.low |= unit << lsb; |
7364 | } |
7365 | return CONST_FIXED_FROM_FIXED_VALUE (f, mode); |
7366 | } |
7367 | |
7368 | return NULL_RTX; |
7369 | } |
7370 | |
7371 | /* Simplify a byte offset BYTE into CONST_VECTOR X. The main purpose |
7372 | is to convert a runtime BYTE value into a constant one. */ |
7373 | |
7374 | static poly_uint64 |
7375 | simplify_const_vector_byte_offset (rtx x, poly_uint64 byte) |
7376 | { |
7377 | /* Cope with MODE_VECTOR_BOOL by operating on bits rather than bytes. */ |
7378 | machine_mode mode = GET_MODE (x); |
7379 | unsigned int elt_bits = vector_element_size (GET_MODE_PRECISION (mode), |
7380 | GET_MODE_NUNITS (mode)); |
7381 | /* The number of bits needed to encode one element from each pattern. */ |
7382 | unsigned int sequence_bits = CONST_VECTOR_NPATTERNS (x) * elt_bits; |
7383 | |
7384 | /* Identify the start point in terms of a sequence number and a byte offset |
7385 | within that sequence. */ |
7386 | poly_uint64 first_sequence; |
7387 | unsigned HOST_WIDE_INT subbit; |
7388 | if (can_div_trunc_p (a: byte * BITS_PER_UNIT, b: sequence_bits, |
7389 | quotient: &first_sequence, remainder: &subbit)) |
7390 | { |
7391 | unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (x); |
7392 | if (nelts_per_pattern == 1) |
7393 | /* This is a duplicated vector, so the value of FIRST_SEQUENCE |
7394 | doesn't matter. */ |
7395 | byte = subbit / BITS_PER_UNIT; |
7396 | else if (nelts_per_pattern == 2 && known_gt (first_sequence, 0U)) |
7397 | { |
7398 | /* The subreg drops the first element from each pattern and |
7399 | only uses the second element. Find the first sequence |
7400 | that starts on a byte boundary. */ |
7401 | subbit += least_common_multiple (sequence_bits, BITS_PER_UNIT); |
7402 | byte = subbit / BITS_PER_UNIT; |
7403 | } |
7404 | } |
7405 | return byte; |
7406 | } |
7407 | |
7408 | /* Subroutine of simplify_subreg in which: |
7409 | |
7410 | - X is known to be a CONST_VECTOR |
7411 | - OUTERMODE is known to be a vector mode |
7412 | |
7413 | Try to handle the subreg by operating on the CONST_VECTOR encoding |
7414 | rather than on each individual element of the CONST_VECTOR. |
7415 | |
7416 | Return the simplified subreg on success, otherwise return NULL_RTX. */ |
7417 | |
7418 | static rtx |
7419 | simplify_const_vector_subreg (machine_mode outermode, rtx x, |
7420 | machine_mode innermode, unsigned int first_byte) |
7421 | { |
7422 | /* Paradoxical subregs of vectors have dubious semantics. */ |
7423 | if (paradoxical_subreg_p (outermode, innermode)) |
7424 | return NULL_RTX; |
7425 | |
7426 | /* We can only preserve the semantics of a stepped pattern if the new |
7427 | vector element is the same as the original one. */ |
7428 | if (CONST_VECTOR_STEPPED_P (x) |
7429 | && GET_MODE_INNER (outermode) != GET_MODE_INNER (innermode)) |
7430 | return NULL_RTX; |
7431 | |
7432 | /* Cope with MODE_VECTOR_BOOL by operating on bits rather than bytes. */ |
7433 | unsigned int x_elt_bits |
7434 | = vector_element_size (GET_MODE_PRECISION (innermode), |
7435 | GET_MODE_NUNITS (innermode)); |
7436 | unsigned int out_elt_bits |
7437 | = vector_element_size (GET_MODE_PRECISION (outermode), |
7438 | GET_MODE_NUNITS (outermode)); |
7439 | |
7440 | /* The number of bits needed to encode one element from every pattern |
7441 | of the original vector. */ |
7442 | unsigned int x_sequence_bits = CONST_VECTOR_NPATTERNS (x) * x_elt_bits; |
7443 | |
7444 | /* The number of bits needed to encode one element from every pattern |
7445 | of the result. */ |
7446 | unsigned int out_sequence_bits |
7447 | = least_common_multiple (x_sequence_bits, out_elt_bits); |
7448 | |
7449 | /* Work out the number of interleaved patterns in the output vector |
7450 | and the number of encoded elements per pattern. */ |
7451 | unsigned int out_npatterns = out_sequence_bits / out_elt_bits; |
7452 | unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (x); |
7453 | |
7454 | /* The encoding scheme requires the number of elements to be a multiple |
7455 | of the number of patterns, so that each pattern appears at least once |
7456 | and so that the same number of elements appear from each pattern. */ |
7457 | bool ok_p = multiple_p (a: GET_MODE_NUNITS (mode: outermode), b: out_npatterns); |
7458 | unsigned int const_nunits; |
7459 | if (GET_MODE_NUNITS (mode: outermode).is_constant (const_value: &const_nunits) |
7460 | && (!ok_p || out_npatterns * nelts_per_pattern > const_nunits)) |
7461 | { |
7462 | /* Either the encoding is invalid, or applying it would give us |
7463 | more elements than we need. Just encode each element directly. */ |
7464 | out_npatterns = const_nunits; |
7465 | nelts_per_pattern = 1; |
7466 | } |
7467 | else if (!ok_p) |
7468 | return NULL_RTX; |
7469 | |
7470 | /* Get enough bytes of X to form the new encoding. */ |
7471 | unsigned int buffer_bits = out_npatterns * nelts_per_pattern * out_elt_bits; |
7472 | unsigned int buffer_bytes = CEIL (buffer_bits, BITS_PER_UNIT); |
7473 | auto_vec<target_unit, 128> buffer (buffer_bytes); |
7474 | if (!native_encode_rtx (mode: innermode, x, bytes&: buffer, first_byte, num_bytes: buffer_bytes)) |
7475 | return NULL_RTX; |
7476 | |
7477 | /* Reencode the bytes as OUTERMODE. */ |
7478 | return native_decode_vector_rtx (mode: outermode, bytes: buffer, first_byte: 0, npatterns: out_npatterns, |
7479 | nelts_per_pattern); |
7480 | } |
7481 | |
7482 | /* Try to simplify a subreg of a constant by encoding the subreg region |
7483 | as a sequence of target bytes and reading them back in the new mode. |
7484 | Return the new value on success, otherwise return null. |
7485 | |
7486 | The subreg has outer mode OUTERMODE, inner mode INNERMODE, inner value X |
7487 | and byte offset FIRST_BYTE. */ |
7488 | |
7489 | static rtx |
7490 | simplify_immed_subreg (fixed_size_mode outermode, rtx x, |
7491 | machine_mode innermode, unsigned int first_byte) |
7492 | { |
7493 | unsigned int buffer_bytes = GET_MODE_SIZE (mode: outermode); |
7494 | auto_vec<target_unit, 128> buffer (buffer_bytes); |
7495 | |
7496 | /* Some ports misuse CCmode. */ |
7497 | if (GET_MODE_CLASS (outermode) == MODE_CC && CONST_INT_P (x)) |
7498 | return x; |
7499 | |
7500 | /* Paradoxical subregs read undefined values for bytes outside of the |
7501 | inner value. However, we have traditionally always sign-extended |
7502 | integer constants and zero-extended others. */ |
7503 | unsigned int inner_bytes = buffer_bytes; |
7504 | if (paradoxical_subreg_p (outermode, innermode)) |
7505 | { |
7506 | if (!GET_MODE_SIZE (mode: innermode).is_constant (const_value: &inner_bytes)) |
7507 | return NULL_RTX; |
7508 | |
7509 | target_unit filler = 0; |
7510 | if (CONST_SCALAR_INT_P (x) && wi::neg_p (x: rtx_mode_t (x, innermode))) |
7511 | filler = -1; |
7512 | |
7513 | /* Add any leading bytes due to big-endian layout. The number of |
7514 | bytes must be constant because both modes have constant size. */ |
7515 | unsigned int leading_bytes |
7516 | = -byte_lowpart_offset (outermode, innermode).to_constant (); |
7517 | for (unsigned int i = 0; i < leading_bytes; ++i) |
7518 | buffer.quick_push (obj: filler); |
7519 | |
7520 | if (!native_encode_rtx (mode: innermode, x, bytes&: buffer, first_byte, num_bytes: inner_bytes)) |
7521 | return NULL_RTX; |
7522 | |
7523 | /* Add any trailing bytes due to little-endian layout. */ |
7524 | while (buffer.length () < buffer_bytes) |
7525 | buffer.quick_push (obj: filler); |
7526 | } |
7527 | else if (!native_encode_rtx (mode: innermode, x, bytes&: buffer, first_byte, num_bytes: inner_bytes)) |
7528 | return NULL_RTX; |
7529 | rtx ret = native_decode_rtx (mode: outermode, bytes: buffer, first_byte: 0); |
7530 | if (ret && FLOAT_MODE_P (outermode)) |
7531 | { |
7532 | auto_vec<target_unit, 128> buffer2 (buffer_bytes); |
7533 | if (!native_encode_rtx (mode: outermode, x: ret, bytes&: buffer2, first_byte: 0, num_bytes: buffer_bytes)) |
7534 | return NULL_RTX; |
7535 | for (unsigned int i = 0; i < buffer_bytes; ++i) |
7536 | if (buffer[i] != buffer2[i]) |
7537 | return NULL_RTX; |
7538 | } |
7539 | return ret; |
7540 | } |
7541 | |
7542 | /* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE) |
7543 | Return 0 if no simplifications are possible. */ |
7544 | rtx |
7545 | simplify_context::simplify_subreg (machine_mode outermode, rtx op, |
7546 | machine_mode innermode, poly_uint64 byte) |
7547 | { |
7548 | /* Little bit of sanity checking. */ |
7549 | gcc_assert (innermode != VOIDmode); |
7550 | gcc_assert (outermode != VOIDmode); |
7551 | gcc_assert (innermode != BLKmode); |
7552 | gcc_assert (outermode != BLKmode); |
7553 | |
7554 | gcc_assert (GET_MODE (op) == innermode |
7555 | || GET_MODE (op) == VOIDmode); |
7556 | |
7557 | poly_uint64 outersize = GET_MODE_SIZE (mode: outermode); |
7558 | if (!multiple_p (a: byte, b: outersize)) |
7559 | return NULL_RTX; |
7560 | |
7561 | poly_uint64 innersize = GET_MODE_SIZE (mode: innermode); |
7562 | if (maybe_ge (byte, innersize)) |
7563 | return NULL_RTX; |
7564 | |
7565 | if (outermode == innermode && known_eq (byte, 0U)) |
7566 | return op; |
7567 | |
7568 | if (GET_CODE (op) == CONST_VECTOR) |
7569 | byte = simplify_const_vector_byte_offset (x: op, byte); |
7570 | |
7571 | if (multiple_p (a: byte, GET_MODE_UNIT_SIZE (innermode))) |
7572 | { |
7573 | rtx elt; |
7574 | |
7575 | if (VECTOR_MODE_P (outermode) |
7576 | && GET_MODE_INNER (outermode) == GET_MODE_INNER (innermode) |
7577 | && vec_duplicate_p (x: op, elt: &elt)) |
7578 | return gen_vec_duplicate (outermode, elt); |
7579 | |
7580 | if (outermode == GET_MODE_INNER (innermode) |
7581 | && vec_duplicate_p (x: op, elt: &elt)) |
7582 | return elt; |
7583 | } |
7584 | |
7585 | if (CONST_SCALAR_INT_P (op) |
7586 | || CONST_DOUBLE_AS_FLOAT_P (op) |
7587 | || CONST_FIXED_P (op) |
7588 | || GET_CODE (op) == CONST_VECTOR) |
7589 | { |
7590 | unsigned HOST_WIDE_INT cbyte; |
7591 | if (byte.is_constant (const_value: &cbyte)) |
7592 | { |
7593 | if (GET_CODE (op) == CONST_VECTOR && VECTOR_MODE_P (outermode)) |
7594 | { |
7595 | rtx tmp = simplify_const_vector_subreg (outermode, x: op, |
7596 | innermode, first_byte: cbyte); |
7597 | if (tmp) |
7598 | return tmp; |
7599 | } |
7600 | |
7601 | fixed_size_mode fs_outermode; |
7602 | if (is_a <fixed_size_mode> (m: outermode, result: &fs_outermode)) |
7603 | return simplify_immed_subreg (outermode: fs_outermode, x: op, innermode, first_byte: cbyte); |
7604 | } |
7605 | } |
7606 | |
7607 | /* Changing mode twice with SUBREG => just change it once, |
7608 | or not at all if changing back op starting mode. */ |
7609 | if (GET_CODE (op) == SUBREG) |
7610 | { |
7611 | machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); |
7612 | poly_uint64 innermostsize = GET_MODE_SIZE (mode: innermostmode); |
7613 | rtx newx; |
7614 | |
7615 | if (outermode == innermostmode |
7616 | && known_eq (byte, 0U) |
7617 | && known_eq (SUBREG_BYTE (op), 0)) |
7618 | return SUBREG_REG (op); |
7619 | |
7620 | /* Work out the memory offset of the final OUTERMODE value relative |
7621 | to the inner value of OP. */ |
7622 | poly_int64 mem_offset = subreg_memory_offset (outermode, |
7623 | innermode, byte); |
7624 | poly_int64 op_mem_offset = subreg_memory_offset (op); |
7625 | poly_int64 final_offset = mem_offset + op_mem_offset; |
7626 | |
7627 | /* See whether resulting subreg will be paradoxical. */ |
7628 | if (!paradoxical_subreg_p (outermode, innermode: innermostmode)) |
7629 | { |
7630 | /* Bail out in case resulting subreg would be incorrect. */ |
7631 | if (maybe_lt (a: final_offset, b: 0) |
7632 | || maybe_ge (poly_uint64 (final_offset), innermostsize) |
7633 | || !multiple_p (a: final_offset, b: outersize)) |
7634 | return NULL_RTX; |
7635 | } |
7636 | else |
7637 | { |
7638 | poly_int64 required_offset = subreg_memory_offset (outermode, |
7639 | innermostmode, 0); |
7640 | if (maybe_ne (a: final_offset, b: required_offset)) |
7641 | return NULL_RTX; |
7642 | /* Paradoxical subregs always have byte offset 0. */ |
7643 | final_offset = 0; |
7644 | } |
7645 | |
7646 | /* Recurse for further possible simplifications. */ |
7647 | newx = simplify_subreg (outermode, SUBREG_REG (op), innermode: innermostmode, |
7648 | byte: final_offset); |
7649 | if (newx) |
7650 | return newx; |
7651 | if (validate_subreg (outermode, innermostmode, |
7652 | SUBREG_REG (op), final_offset)) |
7653 | { |
7654 | newx = gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset); |
7655 | if (SUBREG_PROMOTED_VAR_P (op) |
7656 | && SUBREG_PROMOTED_SIGN (op) >= 0 |
7657 | && GET_MODE_CLASS (outermode) == MODE_INT |
7658 | && known_ge (outersize, innersize) |
7659 | && known_le (outersize, innermostsize) |
7660 | && subreg_lowpart_p (newx)) |
7661 | { |
7662 | SUBREG_PROMOTED_VAR_P (newx) = 1; |
7663 | SUBREG_PROMOTED_SET (newx, SUBREG_PROMOTED_GET (op)); |
7664 | } |
7665 | return newx; |
7666 | } |
7667 | return NULL_RTX; |
7668 | } |
7669 | |
7670 | /* SUBREG of a hard register => just change the register number |
7671 | and/or mode. If the hard register is not valid in that mode, |
7672 | suppress this simplification. If the hard register is the stack, |
7673 | frame, or argument pointer, leave this as a SUBREG. */ |
7674 | |
7675 | if (REG_P (op) && HARD_REGISTER_P (op)) |
7676 | { |
7677 | unsigned int regno, final_regno; |
7678 | |
7679 | regno = REGNO (op); |
7680 | final_regno = simplify_subreg_regno (regno, innermode, byte, outermode); |
7681 | if (HARD_REGISTER_NUM_P (final_regno)) |
7682 | { |
7683 | rtx x = gen_rtx_REG_offset (op, outermode, final_regno, |
7684 | subreg_memory_offset (outermode, |
7685 | innermode, byte)); |
7686 | |
7687 | /* Propagate original regno. We don't have any way to specify |
7688 | the offset inside original regno, so do so only for lowpart. |
7689 | The information is used only by alias analysis that cannot |
7690 | grog partial register anyway. */ |
7691 | |
7692 | if (known_eq (subreg_lowpart_offset (outermode, innermode), byte)) |
7693 | ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op); |
7694 | return x; |
7695 | } |
7696 | } |
7697 | |
7698 | /* If we have a SUBREG of a register that we are replacing and we are |
7699 | replacing it with a MEM, make a new MEM and try replacing the |
7700 | SUBREG with it. Don't do this if the MEM has a mode-dependent address |
7701 | or if we would be widening it. */ |
7702 | |
7703 | if (MEM_P (op) |
7704 | && ! mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op)) |
7705 | /* Allow splitting of volatile memory references in case we don't |
7706 | have instruction to move the whole thing. */ |
7707 | && (! MEM_VOLATILE_P (op) |
7708 | || ! have_insn_for (SET, innermode)) |
7709 | && !(STRICT_ALIGNMENT && MEM_ALIGN (op) < GET_MODE_ALIGNMENT (outermode)) |
7710 | && known_le (outersize, innersize)) |
7711 | return adjust_address_nv (op, outermode, byte); |
7712 | |
7713 | /* Handle complex or vector values represented as CONCAT or VEC_CONCAT |
7714 | of two parts. */ |
7715 | if (GET_CODE (op) == CONCAT |
7716 | || GET_CODE (op) == VEC_CONCAT) |
7717 | { |
7718 | poly_uint64 final_offset; |
7719 | rtx part, res; |
7720 | |
7721 | machine_mode part_mode = GET_MODE (XEXP (op, 0)); |
7722 | if (part_mode == VOIDmode) |
7723 | part_mode = GET_MODE_INNER (GET_MODE (op)); |
7724 | poly_uint64 part_size = GET_MODE_SIZE (mode: part_mode); |
7725 | if (known_lt (byte, part_size)) |
7726 | { |
7727 | part = XEXP (op, 0); |
7728 | final_offset = byte; |
7729 | } |
7730 | else if (known_ge (byte, part_size)) |
7731 | { |
7732 | part = XEXP (op, 1); |
7733 | final_offset = byte - part_size; |
7734 | } |
7735 | else |
7736 | return NULL_RTX; |
7737 | |
7738 | if (maybe_gt (final_offset + outersize, part_size)) |
7739 | return NULL_RTX; |
7740 | |
7741 | part_mode = GET_MODE (part); |
7742 | if (part_mode == VOIDmode) |
7743 | part_mode = GET_MODE_INNER (GET_MODE (op)); |
7744 | res = simplify_subreg (outermode, op: part, innermode: part_mode, byte: final_offset); |
7745 | if (res) |
7746 | return res; |
7747 | if (validate_subreg (outermode, part_mode, part, final_offset)) |
7748 | return gen_rtx_SUBREG (outermode, part, final_offset); |
7749 | return NULL_RTX; |
7750 | } |
7751 | |
7752 | /* Simplify |
7753 | (subreg (vec_merge (X) |
7754 | (vector) |
7755 | (const_int ((1 << N) | M))) |
7756 | (N * sizeof (outermode))) |
7757 | to |
7758 | (subreg (X) (N * sizeof (outermode))) |
7759 | */ |
7760 | unsigned int idx; |
7761 | if (constant_multiple_p (a: byte, b: GET_MODE_SIZE (mode: outermode), multiple: &idx) |
7762 | && idx < HOST_BITS_PER_WIDE_INT |
7763 | && GET_CODE (op) == VEC_MERGE |
7764 | && GET_MODE_INNER (innermode) == outermode |
7765 | && CONST_INT_P (XEXP (op, 2)) |
7766 | && (UINTVAL (XEXP (op, 2)) & (HOST_WIDE_INT_1U << idx)) != 0) |
7767 | return simplify_gen_subreg (outermode, XEXP (op, 0), innermode, byte); |
7768 | |
7769 | /* A SUBREG resulting from a zero extension may fold to zero if |
7770 | it extracts higher bits that the ZERO_EXTEND's source bits. */ |
7771 | if (GET_CODE (op) == ZERO_EXTEND && SCALAR_INT_MODE_P (innermode)) |
7772 | { |
7773 | poly_uint64 bitpos = subreg_lsb_1 (outer_mode: outermode, inner_mode: innermode, subreg_byte: byte); |
7774 | if (known_ge (bitpos, GET_MODE_PRECISION (GET_MODE (XEXP (op, 0))))) |
7775 | return CONST0_RTX (outermode); |
7776 | } |
7777 | |
7778 | /* Optimize SUBREGS of scalar integral ASHIFT by a valid constant. */ |
7779 | if (GET_CODE (op) == ASHIFT |
7780 | && SCALAR_INT_MODE_P (innermode) |
7781 | && CONST_INT_P (XEXP (op, 1)) |
7782 | && INTVAL (XEXP (op, 1)) > 0 |
7783 | && known_gt (GET_MODE_BITSIZE (innermode), INTVAL (XEXP (op, 1)))) |
7784 | { |
7785 | HOST_WIDE_INT val = INTVAL (XEXP (op, 1)); |
7786 | /* A lowpart SUBREG of a ASHIFT by a constant may fold to zero. */ |
7787 | if (known_eq (subreg_lowpart_offset (outermode, innermode), byte) |
7788 | && known_le (GET_MODE_BITSIZE (outermode), val)) |
7789 | return CONST0_RTX (outermode); |
7790 | /* Optimize the highpart SUBREG of a suitable ASHIFT (ZERO_EXTEND). */ |
7791 | if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND |
7792 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode |
7793 | && known_eq (GET_MODE_BITSIZE (outermode), val) |
7794 | && known_eq (GET_MODE_BITSIZE (innermode), 2 * val) |
7795 | && known_eq (subreg_highpart_offset (outermode, innermode), byte)) |
7796 | return XEXP (XEXP (op, 0), 0); |
7797 | } |
7798 | |
7799 | /* Attempt to simplify WORD_MODE SUBREGs of bitwise expressions. */ |
7800 | if (outermode == word_mode |
7801 | && (GET_CODE (op) == IOR || GET_CODE (op) == XOR || GET_CODE (op) == AND) |
7802 | && SCALAR_INT_MODE_P (innermode)) |
7803 | { |
7804 | rtx op0 = simplify_subreg (outermode, XEXP (op, 0), innermode, byte); |
7805 | rtx op1 = simplify_subreg (outermode, XEXP (op, 1), innermode, byte); |
7806 | if (op0 && op1) |
7807 | return simplify_gen_binary (GET_CODE (op), mode: outermode, op0, op1); |
7808 | } |
7809 | |
7810 | scalar_int_mode int_outermode, int_innermode; |
7811 | if (is_a <scalar_int_mode> (m: outermode, result: &int_outermode) |
7812 | && is_a <scalar_int_mode> (m: innermode, result: &int_innermode) |
7813 | && known_eq (byte, subreg_lowpart_offset (int_outermode, int_innermode))) |
7814 | { |
7815 | /* Handle polynomial integers. The upper bits of a paradoxical |
7816 | subreg are undefined, so this is safe regardless of whether |
7817 | we're truncating or extending. */ |
7818 | if (CONST_POLY_INT_P (op)) |
7819 | { |
7820 | poly_wide_int val |
7821 | = poly_wide_int::from (a: const_poly_int_value (x: op), |
7822 | bitsize: GET_MODE_PRECISION (mode: int_outermode), |
7823 | sgn: SIGNED); |
7824 | return immed_wide_int_const (val, int_outermode); |
7825 | } |
7826 | |
7827 | if (GET_MODE_PRECISION (mode: int_outermode) |
7828 | < GET_MODE_PRECISION (mode: int_innermode)) |
7829 | { |
7830 | rtx tem = simplify_truncation (mode: int_outermode, op, op_mode: int_innermode); |
7831 | if (tem) |
7832 | return tem; |
7833 | } |
7834 | } |
7835 | |
7836 | /* If the outer mode is not integral, try taking a subreg with the equivalent |
7837 | integer outer mode and then bitcasting the result. |
7838 | Other simplifications rely on integer to integer subregs and we'd |
7839 | potentially miss out on optimizations otherwise. */ |
7840 | if (known_gt (GET_MODE_SIZE (innermode), |
7841 | GET_MODE_SIZE (outermode)) |
7842 | && SCALAR_INT_MODE_P (innermode) |
7843 | && !SCALAR_INT_MODE_P (outermode) |
7844 | && int_mode_for_size (size: GET_MODE_BITSIZE (mode: outermode), |
7845 | limit: 0).exists (mode: &int_outermode)) |
7846 | { |
7847 | rtx tem = simplify_subreg (outermode: int_outermode, op, innermode, byte); |
7848 | if (tem) |
7849 | return lowpart_subreg (outermode, tem, int_outermode); |
7850 | } |
7851 | |
7852 | /* If OP is a vector comparison and the subreg is not changing the |
7853 | number of elements or the size of the elements, change the result |
7854 | of the comparison to the new mode. */ |
7855 | if (COMPARISON_P (op) |
7856 | && VECTOR_MODE_P (outermode) |
7857 | && VECTOR_MODE_P (innermode) |
7858 | && known_eq (GET_MODE_NUNITS (outermode), GET_MODE_NUNITS (innermode)) |
7859 | && known_eq (GET_MODE_UNIT_SIZE (outermode), |
7860 | GET_MODE_UNIT_SIZE (innermode))) |
7861 | return simplify_gen_relational (GET_CODE (op), mode: outermode, cmp_mode: innermode, |
7862 | XEXP (op, 0), XEXP (op, 1)); |
7863 | return NULL_RTX; |
7864 | } |
7865 | |
7866 | /* Make a SUBREG operation or equivalent if it folds. */ |
7867 | |
7868 | rtx |
7869 | simplify_context::simplify_gen_subreg (machine_mode outermode, rtx op, |
7870 | machine_mode innermode, |
7871 | poly_uint64 byte) |
7872 | { |
7873 | rtx newx; |
7874 | |
7875 | newx = simplify_subreg (outermode, op, innermode, byte); |
7876 | if (newx) |
7877 | return newx; |
7878 | |
7879 | if (GET_CODE (op) == SUBREG |
7880 | || GET_CODE (op) == CONCAT |
7881 | || GET_MODE (op) == VOIDmode) |
7882 | return NULL_RTX; |
7883 | |
7884 | if (MODE_COMPOSITE_P (outermode) |
7885 | && (CONST_SCALAR_INT_P (op) |
7886 | || CONST_DOUBLE_AS_FLOAT_P (op) |
7887 | || CONST_FIXED_P (op) |
7888 | || GET_CODE (op) == CONST_VECTOR)) |
7889 | return NULL_RTX; |
7890 | |
7891 | if (validate_subreg (outermode, innermode, op, byte)) |
7892 | return gen_rtx_SUBREG (outermode, op, byte); |
7893 | |
7894 | return NULL_RTX; |
7895 | } |
7896 | |
7897 | /* Generates a subreg to get the least significant part of EXPR (in mode |
7898 | INNER_MODE) to OUTER_MODE. */ |
7899 | |
7900 | rtx |
7901 | simplify_context::lowpart_subreg (machine_mode outer_mode, rtx expr, |
7902 | machine_mode inner_mode) |
7903 | { |
7904 | return simplify_gen_subreg (outermode: outer_mode, op: expr, innermode: inner_mode, |
7905 | byte: subreg_lowpart_offset (outermode: outer_mode, innermode: inner_mode)); |
7906 | } |
7907 | |
7908 | /* Generate RTX to select element at INDEX out of vector OP. */ |
7909 | |
7910 | rtx |
7911 | simplify_context::simplify_gen_vec_select (rtx op, unsigned int index) |
7912 | { |
7913 | gcc_assert (VECTOR_MODE_P (GET_MODE (op))); |
7914 | |
7915 | scalar_mode imode = GET_MODE_INNER (GET_MODE (op)); |
7916 | |
7917 | if (known_eq (index * GET_MODE_SIZE (imode), |
7918 | subreg_lowpart_offset (imode, GET_MODE (op)))) |
7919 | { |
7920 | rtx res = lowpart_subreg (outer_mode: imode, expr: op, GET_MODE (op)); |
7921 | if (res) |
7922 | return res; |
7923 | } |
7924 | |
7925 | rtx tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (index))); |
7926 | return gen_rtx_VEC_SELECT (imode, op, tmp); |
7927 | } |
7928 | |
7929 | |
7930 | /* Simplify X, an rtx expression. |
7931 | |
7932 | Return the simplified expression or NULL if no simplifications |
7933 | were possible. |
7934 | |
7935 | This is the preferred entry point into the simplification routines; |
7936 | however, we still allow passes to call the more specific routines. |
7937 | |
7938 | Right now GCC has three (yes, three) major bodies of RTL simplification |
7939 | code that need to be unified. |
7940 | |
7941 | 1. fold_rtx in cse.cc. This code uses various CSE specific |
7942 | information to aid in RTL simplification. |
7943 | |
7944 | 2. simplify_rtx in combine.cc. Similar to fold_rtx, except that |
7945 | it uses combine specific information to aid in RTL |
7946 | simplification. |
7947 | |
7948 | 3. The routines in this file. |
7949 | |
7950 | |
7951 | Long term we want to only have one body of simplification code; to |
7952 | get to that state I recommend the following steps: |
7953 | |
7954 | 1. Pour over fold_rtx & simplify_rtx and move any simplifications |
7955 | which are not pass dependent state into these routines. |
7956 | |
7957 | 2. As code is moved by #1, change fold_rtx & simplify_rtx to |
7958 | use this routine whenever possible. |
7959 | |
7960 | 3. Allow for pass dependent state to be provided to these |
7961 | routines and add simplifications based on the pass dependent |
7962 | state. Remove code from cse.cc & combine.cc that becomes |
7963 | redundant/dead. |
7964 | |
7965 | It will take time, but ultimately the compiler will be easier to |
7966 | maintain and improve. It's totally silly that when we add a |
7967 | simplification that it needs to be added to 4 places (3 for RTL |
7968 | simplification and 1 for tree simplification. */ |
7969 | |
7970 | rtx |
7971 | simplify_rtx (const_rtx x) |
7972 | { |
7973 | const enum rtx_code code = GET_CODE (x); |
7974 | const machine_mode mode = GET_MODE (x); |
7975 | |
7976 | switch (GET_RTX_CLASS (code)) |
7977 | { |
7978 | case RTX_UNARY: |
7979 | return simplify_unary_operation (code, mode, |
7980 | XEXP (x, 0), GET_MODE (XEXP (x, 0))); |
7981 | case RTX_COMM_ARITH: |
7982 | if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1))) |
7983 | return simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0)); |
7984 | |
7985 | /* Fall through. */ |
7986 | |
7987 | case RTX_BIN_ARITH: |
7988 | return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1)); |
7989 | |
7990 | case RTX_TERNARY: |
7991 | case RTX_BITFIELD_OPS: |
7992 | return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)), |
7993 | XEXP (x, 0), XEXP (x, 1), |
7994 | XEXP (x, 2)); |
7995 | |
7996 | case RTX_COMPARE: |
7997 | case RTX_COMM_COMPARE: |
7998 | return simplify_relational_operation (code, mode, |
7999 | op_mode: ((GET_MODE (XEXP (x, 0)) |
8000 | != VOIDmode) |
8001 | ? GET_MODE (XEXP (x, 0)) |
8002 | : GET_MODE (XEXP (x, 1))), |
8003 | XEXP (x, 0), |
8004 | XEXP (x, 1)); |
8005 | |
8006 | case RTX_EXTRA: |
8007 | if (code == SUBREG) |
8008 | return simplify_subreg (outermode: mode, SUBREG_REG (x), |
8009 | GET_MODE (SUBREG_REG (x)), |
8010 | SUBREG_BYTE (x)); |
8011 | break; |
8012 | |
8013 | case RTX_OBJ: |
8014 | if (code == LO_SUM) |
8015 | { |
8016 | /* Convert (lo_sum (high FOO) FOO) to FOO. */ |
8017 | if (GET_CODE (XEXP (x, 0)) == HIGH |
8018 | && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1))) |
8019 | return XEXP (x, 1); |
8020 | } |
8021 | break; |
8022 | |
8023 | default: |
8024 | break; |
8025 | } |
8026 | return NULL; |
8027 | } |
8028 | |
8029 | #if CHECKING_P |
8030 | |
8031 | namespace selftest { |
8032 | |
8033 | /* Make a unique pseudo REG of mode MODE for use by selftests. */ |
8034 | |
8035 | static rtx |
8036 | make_test_reg (machine_mode mode) |
8037 | { |
8038 | static int test_reg_num = LAST_VIRTUAL_REGISTER + 1; |
8039 | |
8040 | return gen_rtx_REG (mode, test_reg_num++); |
8041 | } |
8042 | |
8043 | static void |
8044 | test_scalar_int_ops (machine_mode mode) |
8045 | { |
8046 | rtx op0 = make_test_reg (mode); |
8047 | rtx op1 = make_test_reg (mode); |
8048 | rtx six = GEN_INT (6); |
8049 | |
8050 | rtx neg_op0 = simplify_gen_unary (code: NEG, mode, op: op0, op_mode: mode); |
8051 | rtx not_op0 = simplify_gen_unary (code: NOT, mode, op: op0, op_mode: mode); |
8052 | rtx bswap_op0 = simplify_gen_unary (code: BSWAP, mode, op: op0, op_mode: mode); |
8053 | |
8054 | rtx and_op0_op1 = simplify_gen_binary (code: AND, mode, op0, op1); |
8055 | rtx ior_op0_op1 = simplify_gen_binary (code: IOR, mode, op0, op1); |
8056 | rtx xor_op0_op1 = simplify_gen_binary (code: XOR, mode, op0, op1); |
8057 | |
8058 | rtx and_op0_6 = simplify_gen_binary (code: AND, mode, op0, op1: six); |
8059 | rtx and_op1_6 = simplify_gen_binary (code: AND, mode, op0: op1, op1: six); |
8060 | |
8061 | /* Test some binary identities. */ |
8062 | ASSERT_RTX_EQ (op0, simplify_gen_binary (PLUS, mode, op0, const0_rtx)); |
8063 | ASSERT_RTX_EQ (op0, simplify_gen_binary (PLUS, mode, const0_rtx, op0)); |
8064 | ASSERT_RTX_EQ (op0, simplify_gen_binary (MINUS, mode, op0, const0_rtx)); |
8065 | ASSERT_RTX_EQ (op0, simplify_gen_binary (MULT, mode, op0, const1_rtx)); |
8066 | ASSERT_RTX_EQ (op0, simplify_gen_binary (MULT, mode, const1_rtx, op0)); |
8067 | ASSERT_RTX_EQ (op0, simplify_gen_binary (DIV, mode, op0, const1_rtx)); |
8068 | ASSERT_RTX_EQ (op0, simplify_gen_binary (AND, mode, op0, constm1_rtx)); |
8069 | ASSERT_RTX_EQ (op0, simplify_gen_binary (AND, mode, constm1_rtx, op0)); |
8070 | ASSERT_RTX_EQ (op0, simplify_gen_binary (IOR, mode, op0, const0_rtx)); |
8071 | ASSERT_RTX_EQ (op0, simplify_gen_binary (IOR, mode, const0_rtx, op0)); |
8072 | ASSERT_RTX_EQ (op0, simplify_gen_binary (XOR, mode, op0, const0_rtx)); |
8073 | ASSERT_RTX_EQ (op0, simplify_gen_binary (XOR, mode, const0_rtx, op0)); |
8074 | ASSERT_RTX_EQ (op0, simplify_gen_binary (ASHIFT, mode, op0, const0_rtx)); |
8075 | ASSERT_RTX_EQ (op0, simplify_gen_binary (ROTATE, mode, op0, const0_rtx)); |
8076 | ASSERT_RTX_EQ (op0, simplify_gen_binary (ASHIFTRT, mode, op0, const0_rtx)); |
8077 | ASSERT_RTX_EQ (op0, simplify_gen_binary (LSHIFTRT, mode, op0, const0_rtx)); |
8078 | ASSERT_RTX_EQ (op0, simplify_gen_binary (ROTATERT, mode, op0, const0_rtx)); |
8079 | |
8080 | /* Test some self-inverse operations. */ |
8081 | ASSERT_RTX_EQ (op0, simplify_gen_unary (NEG, mode, neg_op0, mode)); |
8082 | ASSERT_RTX_EQ (op0, simplify_gen_unary (NOT, mode, not_op0, mode)); |
8083 | ASSERT_RTX_EQ (op0, simplify_gen_unary (BSWAP, mode, bswap_op0, mode)); |
8084 | |
8085 | /* Test some reflexive operations. */ |
8086 | ASSERT_RTX_EQ (op0, simplify_gen_binary (AND, mode, op0, op0)); |
8087 | ASSERT_RTX_EQ (op0, simplify_gen_binary (IOR, mode, op0, op0)); |
8088 | ASSERT_RTX_EQ (op0, simplify_gen_binary (SMIN, mode, op0, op0)); |
8089 | ASSERT_RTX_EQ (op0, simplify_gen_binary (SMAX, mode, op0, op0)); |
8090 | ASSERT_RTX_EQ (op0, simplify_gen_binary (UMIN, mode, op0, op0)); |
8091 | ASSERT_RTX_EQ (op0, simplify_gen_binary (UMAX, mode, op0, op0)); |
8092 | |
8093 | ASSERT_RTX_EQ (const0_rtx, simplify_gen_binary (MINUS, mode, op0, op0)); |
8094 | ASSERT_RTX_EQ (const0_rtx, simplify_gen_binary (XOR, mode, op0, op0)); |
8095 | |
8096 | /* Test simplify_distributive_operation. */ |
8097 | ASSERT_RTX_EQ (simplify_gen_binary (AND, mode, xor_op0_op1, six), |
8098 | simplify_gen_binary (XOR, mode, and_op0_6, and_op1_6)); |
8099 | ASSERT_RTX_EQ (simplify_gen_binary (AND, mode, ior_op0_op1, six), |
8100 | simplify_gen_binary (IOR, mode, and_op0_6, and_op1_6)); |
8101 | ASSERT_RTX_EQ (simplify_gen_binary (AND, mode, and_op0_op1, six), |
8102 | simplify_gen_binary (AND, mode, and_op0_6, and_op1_6)); |
8103 | |
8104 | /* Test useless extensions are eliminated. */ |
8105 | ASSERT_RTX_EQ (op0, simplify_gen_unary (TRUNCATE, mode, op0, mode)); |
8106 | ASSERT_RTX_EQ (op0, simplify_gen_unary (ZERO_EXTEND, mode, op0, mode)); |
8107 | ASSERT_RTX_EQ (op0, simplify_gen_unary (SIGN_EXTEND, mode, op0, mode)); |
8108 | ASSERT_RTX_EQ (op0, lowpart_subreg (mode, op0, mode)); |
8109 | } |
8110 | |
8111 | /* Verify some simplifications of integer extension/truncation. |
8112 | Machine mode BMODE is the guaranteed wider than SMODE. */ |
8113 | |
8114 | static void |
8115 | test_scalar_int_ext_ops (machine_mode bmode, machine_mode smode) |
8116 | { |
8117 | rtx sreg = make_test_reg (mode: smode); |
8118 | |
8119 | /* Check truncation of extension. */ |
8120 | ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, |
8121 | simplify_gen_unary (ZERO_EXTEND, bmode, |
8122 | sreg, smode), |
8123 | bmode), |
8124 | sreg); |
8125 | ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, |
8126 | simplify_gen_unary (SIGN_EXTEND, bmode, |
8127 | sreg, smode), |
8128 | bmode), |
8129 | sreg); |
8130 | ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, |
8131 | lowpart_subreg (bmode, sreg, smode), |
8132 | bmode), |
8133 | sreg); |
8134 | } |
8135 | |
8136 | /* Verify more simplifications of integer extension/truncation. |
8137 | BMODE is wider than MMODE which is wider than SMODE. */ |
8138 | |
8139 | static void |
8140 | test_scalar_int_ext_ops2 (machine_mode bmode, machine_mode mmode, |
8141 | machine_mode smode) |
8142 | { |
8143 | rtx breg = make_test_reg (mode: bmode); |
8144 | rtx mreg = make_test_reg (mode: mmode); |
8145 | rtx sreg = make_test_reg (mode: smode); |
8146 | |
8147 | /* Check truncate of truncate. */ |
8148 | ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, |
8149 | simplify_gen_unary (TRUNCATE, mmode, |
8150 | breg, bmode), |
8151 | mmode), |
8152 | simplify_gen_unary (TRUNCATE, smode, breg, bmode)); |
8153 | |
8154 | /* Check extension of extension. */ |
8155 | ASSERT_RTX_EQ (simplify_gen_unary (ZERO_EXTEND, bmode, |
8156 | simplify_gen_unary (ZERO_EXTEND, mmode, |
8157 | sreg, smode), |
8158 | mmode), |
8159 | simplify_gen_unary (ZERO_EXTEND, bmode, sreg, smode)); |
8160 | ASSERT_RTX_EQ (simplify_gen_unary (SIGN_EXTEND, bmode, |
8161 | simplify_gen_unary (SIGN_EXTEND, mmode, |
8162 | sreg, smode), |
8163 | mmode), |
8164 | simplify_gen_unary (SIGN_EXTEND, bmode, sreg, smode)); |
8165 | ASSERT_RTX_EQ (simplify_gen_unary (SIGN_EXTEND, bmode, |
8166 | simplify_gen_unary (ZERO_EXTEND, mmode, |
8167 | sreg, smode), |
8168 | mmode), |
8169 | simplify_gen_unary (ZERO_EXTEND, bmode, sreg, smode)); |
8170 | |
8171 | /* Check truncation of extension. */ |
8172 | ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, |
8173 | simplify_gen_unary (ZERO_EXTEND, bmode, |
8174 | mreg, mmode), |
8175 | bmode), |
8176 | simplify_gen_unary (TRUNCATE, smode, mreg, mmode)); |
8177 | ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, |
8178 | simplify_gen_unary (SIGN_EXTEND, bmode, |
8179 | mreg, mmode), |
8180 | bmode), |
8181 | simplify_gen_unary (TRUNCATE, smode, mreg, mmode)); |
8182 | ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, |
8183 | lowpart_subreg (bmode, mreg, mmode), |
8184 | bmode), |
8185 | simplify_gen_unary (TRUNCATE, smode, mreg, mmode)); |
8186 | } |
8187 | |
8188 | |
8189 | /* Verify some simplifications involving scalar expressions. */ |
8190 | |
8191 | static void |
8192 | test_scalar_ops () |
8193 | { |
8194 | for (unsigned int i = 0; i < NUM_MACHINE_MODES; ++i) |
8195 | { |
8196 | machine_mode mode = (machine_mode) i; |
8197 | if (SCALAR_INT_MODE_P (mode) && mode != BImode) |
8198 | test_scalar_int_ops (mode); |
8199 | } |
8200 | |
8201 | test_scalar_int_ext_ops (HImode, QImode); |
8202 | test_scalar_int_ext_ops (SImode, QImode); |
8203 | test_scalar_int_ext_ops (SImode, HImode); |
8204 | test_scalar_int_ext_ops (DImode, QImode); |
8205 | test_scalar_int_ext_ops (DImode, HImode); |
8206 | test_scalar_int_ext_ops (DImode, SImode); |
8207 | |
8208 | test_scalar_int_ext_ops2 (SImode, HImode, QImode); |
8209 | test_scalar_int_ext_ops2 (DImode, HImode, QImode); |
8210 | test_scalar_int_ext_ops2 (DImode, SImode, QImode); |
8211 | test_scalar_int_ext_ops2 (DImode, SImode, HImode); |
8212 | } |
8213 | |
8214 | /* Test vector simplifications involving VEC_DUPLICATE in which the |
8215 | operands and result have vector mode MODE. SCALAR_REG is a pseudo |
8216 | register that holds one element of MODE. */ |
8217 | |
8218 | static void |
8219 | test_vector_ops_duplicate (machine_mode mode, rtx scalar_reg) |
8220 | { |
8221 | scalar_mode inner_mode = GET_MODE_INNER (mode); |
8222 | rtx duplicate = gen_rtx_VEC_DUPLICATE (mode, scalar_reg); |
8223 | poly_uint64 nunits = GET_MODE_NUNITS (mode); |
8224 | if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) |
8225 | { |
8226 | /* Test some simple unary cases with VEC_DUPLICATE arguments. */ |
8227 | rtx not_scalar_reg = gen_rtx_NOT (inner_mode, scalar_reg); |
8228 | rtx duplicate_not = gen_rtx_VEC_DUPLICATE (mode, not_scalar_reg); |
8229 | ASSERT_RTX_EQ (duplicate, |
8230 | simplify_unary_operation (NOT, mode, |
8231 | duplicate_not, mode)); |
8232 | |
8233 | rtx neg_scalar_reg = gen_rtx_NEG (inner_mode, scalar_reg); |
8234 | rtx duplicate_neg = gen_rtx_VEC_DUPLICATE (mode, neg_scalar_reg); |
8235 | ASSERT_RTX_EQ (duplicate, |
8236 | simplify_unary_operation (NEG, mode, |
8237 | duplicate_neg, mode)); |
8238 | |
8239 | /* Test some simple binary cases with VEC_DUPLICATE arguments. */ |
8240 | ASSERT_RTX_EQ (duplicate, |
8241 | simplify_binary_operation (PLUS, mode, duplicate, |
8242 | CONST0_RTX (mode))); |
8243 | |
8244 | ASSERT_RTX_EQ (duplicate, |
8245 | simplify_binary_operation (MINUS, mode, duplicate, |
8246 | CONST0_RTX (mode))); |
8247 | |
8248 | ASSERT_RTX_PTR_EQ (CONST0_RTX (mode), |
8249 | simplify_binary_operation (MINUS, mode, duplicate, |
8250 | duplicate)); |
8251 | } |
8252 | |
8253 | /* Test a scalar VEC_SELECT of a VEC_DUPLICATE. */ |
8254 | rtx zero_par = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx)); |
8255 | ASSERT_RTX_PTR_EQ (scalar_reg, |
8256 | simplify_binary_operation (VEC_SELECT, inner_mode, |
8257 | duplicate, zero_par)); |
8258 | |
8259 | unsigned HOST_WIDE_INT const_nunits; |
8260 | if (nunits.is_constant (const_value: &const_nunits)) |
8261 | { |
8262 | /* And again with the final element. */ |
8263 | rtx last_index = gen_int_mode (const_nunits - 1, word_mode); |
8264 | rtx last_par = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, last_index)); |
8265 | ASSERT_RTX_PTR_EQ (scalar_reg, |
8266 | simplify_binary_operation (VEC_SELECT, inner_mode, |
8267 | duplicate, last_par)); |
8268 | |
8269 | /* Test a scalar subreg of a VEC_MERGE of a VEC_DUPLICATE. */ |
8270 | /* Skip this test for vectors of booleans, because offset is in bytes, |
8271 | while vec_merge indices are in elements (usually bits). */ |
8272 | if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL) |
8273 | { |
8274 | rtx vector_reg = make_test_reg (mode); |
8275 | for (unsigned HOST_WIDE_INT i = 0; i < const_nunits; i++) |
8276 | { |
8277 | if (i >= HOST_BITS_PER_WIDE_INT) |
8278 | break; |
8279 | rtx mask = GEN_INT ((HOST_WIDE_INT_1U << i) | (i + 1)); |
8280 | rtx vm = gen_rtx_VEC_MERGE (mode, duplicate, vector_reg, mask); |
8281 | poly_uint64 offset = i * GET_MODE_SIZE (mode: inner_mode); |
8282 | |
8283 | ASSERT_RTX_EQ (scalar_reg, |
8284 | simplify_gen_subreg (inner_mode, vm, |
8285 | mode, offset)); |
8286 | } |
8287 | } |
8288 | } |
8289 | |
8290 | /* Test a scalar subreg of a VEC_DUPLICATE. */ |
8291 | poly_uint64 offset = subreg_lowpart_offset (outermode: inner_mode, innermode: mode); |
8292 | ASSERT_RTX_EQ (scalar_reg, |
8293 | simplify_gen_subreg (inner_mode, duplicate, |
8294 | mode, offset)); |
8295 | |
8296 | machine_mode narrower_mode; |
8297 | if (maybe_ne (a: nunits, b: 2U) |
8298 | && multiple_p (a: nunits, b: 2) |
8299 | && mode_for_vector (inner_mode, 2).exists (mode: &narrower_mode) |
8300 | && VECTOR_MODE_P (narrower_mode)) |
8301 | { |
8302 | /* Test VEC_DUPLICATE of a vector. */ |
8303 | rtx_vector_builder nbuilder (narrower_mode, 2, 1); |
8304 | nbuilder.quick_push (const0_rtx); |
8305 | nbuilder.quick_push (const1_rtx); |
8306 | rtx_vector_builder builder (mode, 2, 1); |
8307 | builder.quick_push (const0_rtx); |
8308 | builder.quick_push (const1_rtx); |
8309 | ASSERT_RTX_EQ (builder.build (), |
8310 | simplify_unary_operation (VEC_DUPLICATE, mode, |
8311 | nbuilder.build (), |
8312 | narrower_mode)); |
8313 | |
8314 | /* Test VEC_SELECT of a vector. */ |
8315 | rtx vec_par |
8316 | = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, const1_rtx, const0_rtx)); |
8317 | rtx narrower_duplicate |
8318 | = gen_rtx_VEC_DUPLICATE (narrower_mode, scalar_reg); |
8319 | ASSERT_RTX_EQ (narrower_duplicate, |
8320 | simplify_binary_operation (VEC_SELECT, narrower_mode, |
8321 | duplicate, vec_par)); |
8322 | |
8323 | /* Test a vector subreg of a VEC_DUPLICATE. */ |
8324 | poly_uint64 offset = subreg_lowpart_offset (outermode: narrower_mode, innermode: mode); |
8325 | ASSERT_RTX_EQ (narrower_duplicate, |
8326 | simplify_gen_subreg (narrower_mode, duplicate, |
8327 | mode, offset)); |
8328 | } |
8329 | } |
8330 | |
8331 | /* Test vector simplifications involving VEC_SERIES in which the |
8332 | operands and result have vector mode MODE. SCALAR_REG is a pseudo |
8333 | register that holds one element of MODE. */ |
8334 | |
8335 | static void |
8336 | test_vector_ops_series (machine_mode mode, rtx scalar_reg) |
8337 | { |
8338 | /* Test unary cases with VEC_SERIES arguments. */ |
8339 | scalar_mode inner_mode = GET_MODE_INNER (mode); |
8340 | rtx duplicate = gen_rtx_VEC_DUPLICATE (mode, scalar_reg); |
8341 | rtx neg_scalar_reg = gen_rtx_NEG (inner_mode, scalar_reg); |
8342 | rtx series_0_r = gen_rtx_VEC_SERIES (mode, const0_rtx, scalar_reg); |
8343 | rtx series_0_nr = gen_rtx_VEC_SERIES (mode, const0_rtx, neg_scalar_reg); |
8344 | rtx series_nr_1 = gen_rtx_VEC_SERIES (mode, neg_scalar_reg, const1_rtx); |
8345 | rtx series_r_m1 = gen_rtx_VEC_SERIES (mode, scalar_reg, constm1_rtx); |
8346 | rtx series_r_r = gen_rtx_VEC_SERIES (mode, scalar_reg, scalar_reg); |
8347 | rtx series_nr_nr = gen_rtx_VEC_SERIES (mode, neg_scalar_reg, |
8348 | neg_scalar_reg); |
8349 | ASSERT_RTX_EQ (series_0_r, |
8350 | simplify_unary_operation (NEG, mode, series_0_nr, mode)); |
8351 | ASSERT_RTX_EQ (series_r_m1, |
8352 | simplify_unary_operation (NEG, mode, series_nr_1, mode)); |
8353 | ASSERT_RTX_EQ (series_r_r, |
8354 | simplify_unary_operation (NEG, mode, series_nr_nr, mode)); |
8355 | |
8356 | /* Test that a VEC_SERIES with a zero step is simplified away. */ |
8357 | ASSERT_RTX_EQ (duplicate, |
8358 | simplify_binary_operation (VEC_SERIES, mode, |
8359 | scalar_reg, const0_rtx)); |
8360 | |
8361 | /* Test PLUS and MINUS with VEC_SERIES. */ |
8362 | rtx series_0_1 = gen_const_vec_series (mode, const0_rtx, const1_rtx); |
8363 | rtx series_0_m1 = gen_const_vec_series (mode, const0_rtx, constm1_rtx); |
8364 | rtx series_r_1 = gen_rtx_VEC_SERIES (mode, scalar_reg, const1_rtx); |
8365 | ASSERT_RTX_EQ (series_r_r, |
8366 | simplify_binary_operation (PLUS, mode, series_0_r, |
8367 | duplicate)); |
8368 | ASSERT_RTX_EQ (series_r_1, |
8369 | simplify_binary_operation (PLUS, mode, duplicate, |
8370 | series_0_1)); |
8371 | ASSERT_RTX_EQ (series_r_m1, |
8372 | simplify_binary_operation (PLUS, mode, duplicate, |
8373 | series_0_m1)); |
8374 | ASSERT_RTX_EQ (series_0_r, |
8375 | simplify_binary_operation (MINUS, mode, series_r_r, |
8376 | duplicate)); |
8377 | ASSERT_RTX_EQ (series_r_m1, |
8378 | simplify_binary_operation (MINUS, mode, duplicate, |
8379 | series_0_1)); |
8380 | ASSERT_RTX_EQ (series_r_1, |
8381 | simplify_binary_operation (MINUS, mode, duplicate, |
8382 | series_0_m1)); |
8383 | ASSERT_RTX_EQ (series_0_m1, |
8384 | simplify_binary_operation (VEC_SERIES, mode, const0_rtx, |
8385 | constm1_rtx)); |
8386 | |
8387 | /* Test NEG on constant vector series. */ |
8388 | ASSERT_RTX_EQ (series_0_m1, |
8389 | simplify_unary_operation (NEG, mode, series_0_1, mode)); |
8390 | ASSERT_RTX_EQ (series_0_1, |
8391 | simplify_unary_operation (NEG, mode, series_0_m1, mode)); |
8392 | |
8393 | /* Test PLUS and MINUS on constant vector series. */ |
8394 | rtx scalar2 = gen_int_mode (2, inner_mode); |
8395 | rtx scalar3 = gen_int_mode (3, inner_mode); |
8396 | rtx series_1_1 = gen_const_vec_series (mode, const1_rtx, const1_rtx); |
8397 | rtx series_0_2 = gen_const_vec_series (mode, const0_rtx, scalar2); |
8398 | rtx series_1_3 = gen_const_vec_series (mode, const1_rtx, scalar3); |
8399 | ASSERT_RTX_EQ (series_1_1, |
8400 | simplify_binary_operation (PLUS, mode, series_0_1, |
8401 | CONST1_RTX (mode))); |
8402 | ASSERT_RTX_EQ (series_0_m1, |
8403 | simplify_binary_operation (PLUS, mode, CONST0_RTX (mode), |
8404 | series_0_m1)); |
8405 | ASSERT_RTX_EQ (series_1_3, |
8406 | simplify_binary_operation (PLUS, mode, series_1_1, |
8407 | series_0_2)); |
8408 | ASSERT_RTX_EQ (series_0_1, |
8409 | simplify_binary_operation (MINUS, mode, series_1_1, |
8410 | CONST1_RTX (mode))); |
8411 | ASSERT_RTX_EQ (series_1_1, |
8412 | simplify_binary_operation (MINUS, mode, CONST1_RTX (mode), |
8413 | series_0_m1)); |
8414 | ASSERT_RTX_EQ (series_1_1, |
8415 | simplify_binary_operation (MINUS, mode, series_1_3, |
8416 | series_0_2)); |
8417 | |
8418 | /* Test MULT between constant vectors. */ |
8419 | rtx vec2 = gen_const_vec_duplicate (mode, scalar2); |
8420 | rtx vec3 = gen_const_vec_duplicate (mode, scalar3); |
8421 | rtx scalar9 = gen_int_mode (9, inner_mode); |
8422 | rtx series_3_9 = gen_const_vec_series (mode, scalar3, scalar9); |
8423 | ASSERT_RTX_EQ (series_0_2, |
8424 | simplify_binary_operation (MULT, mode, series_0_1, vec2)); |
8425 | ASSERT_RTX_EQ (series_3_9, |
8426 | simplify_binary_operation (MULT, mode, vec3, series_1_3)); |
8427 | if (!GET_MODE_NUNITS (mode).is_constant ()) |
8428 | ASSERT_FALSE (simplify_binary_operation (MULT, mode, series_0_1, |
8429 | series_0_1)); |
8430 | |
8431 | /* Test ASHIFT between constant vectors. */ |
8432 | ASSERT_RTX_EQ (series_0_2, |
8433 | simplify_binary_operation (ASHIFT, mode, series_0_1, |
8434 | CONST1_RTX (mode))); |
8435 | if (!GET_MODE_NUNITS (mode).is_constant ()) |
8436 | ASSERT_FALSE (simplify_binary_operation (ASHIFT, mode, CONST1_RTX (mode), |
8437 | series_0_1)); |
8438 | } |
8439 | |
8440 | static rtx |
8441 | simplify_merge_mask (rtx x, rtx mask, int op) |
8442 | { |
8443 | return simplify_context ().simplify_merge_mask (x, mask, op); |
8444 | } |
8445 | |
8446 | /* Verify simplify_merge_mask works correctly. */ |
8447 | |
8448 | static void |
8449 | test_vec_merge (machine_mode mode) |
8450 | { |
8451 | rtx op0 = make_test_reg (mode); |
8452 | rtx op1 = make_test_reg (mode); |
8453 | rtx op2 = make_test_reg (mode); |
8454 | rtx op3 = make_test_reg (mode); |
8455 | rtx op4 = make_test_reg (mode); |
8456 | rtx op5 = make_test_reg (mode); |
8457 | rtx mask1 = make_test_reg (SImode); |
8458 | rtx mask2 = make_test_reg (SImode); |
8459 | rtx vm1 = gen_rtx_VEC_MERGE (mode, op0, op1, mask1); |
8460 | rtx vm2 = gen_rtx_VEC_MERGE (mode, op2, op3, mask1); |
8461 | rtx vm3 = gen_rtx_VEC_MERGE (mode, op4, op5, mask1); |
8462 | |
8463 | /* Simple vec_merge. */ |
8464 | ASSERT_EQ (op0, simplify_merge_mask (vm1, mask1, 0)); |
8465 | ASSERT_EQ (op1, simplify_merge_mask (vm1, mask1, 1)); |
8466 | ASSERT_EQ (NULL_RTX, simplify_merge_mask (vm1, mask2, 0)); |
8467 | ASSERT_EQ (NULL_RTX, simplify_merge_mask (vm1, mask2, 1)); |
8468 | |
8469 | /* Nested vec_merge. |
8470 | It's tempting to make this simplify right down to opN, but we don't |
8471 | because all the simplify_* functions assume that the operands have |
8472 | already been simplified. */ |
8473 | rtx nvm = gen_rtx_VEC_MERGE (mode, vm1, vm2, mask1); |
8474 | ASSERT_EQ (vm1, simplify_merge_mask (nvm, mask1, 0)); |
8475 | ASSERT_EQ (vm2, simplify_merge_mask (nvm, mask1, 1)); |
8476 | |
8477 | /* Intermediate unary op. */ |
8478 | rtx unop = gen_rtx_NOT (mode, vm1); |
8479 | ASSERT_RTX_EQ (gen_rtx_NOT (mode, op0), |
8480 | simplify_merge_mask (unop, mask1, 0)); |
8481 | ASSERT_RTX_EQ (gen_rtx_NOT (mode, op1), |
8482 | simplify_merge_mask (unop, mask1, 1)); |
8483 | |
8484 | /* Intermediate binary op. */ |
8485 | rtx binop = gen_rtx_PLUS (mode, vm1, vm2); |
8486 | ASSERT_RTX_EQ (gen_rtx_PLUS (mode, op0, op2), |
8487 | simplify_merge_mask (binop, mask1, 0)); |
8488 | ASSERT_RTX_EQ (gen_rtx_PLUS (mode, op1, op3), |
8489 | simplify_merge_mask (binop, mask1, 1)); |
8490 | |
8491 | /* Intermediate ternary op. */ |
8492 | rtx tenop = gen_rtx_FMA (mode, vm1, vm2, vm3); |
8493 | ASSERT_RTX_EQ (gen_rtx_FMA (mode, op0, op2, op4), |
8494 | simplify_merge_mask (tenop, mask1, 0)); |
8495 | ASSERT_RTX_EQ (gen_rtx_FMA (mode, op1, op3, op5), |
8496 | simplify_merge_mask (tenop, mask1, 1)); |
8497 | |
8498 | /* Side effects. */ |
8499 | rtx badop0 = gen_rtx_PRE_INC (mode, op0); |
8500 | rtx badvm = gen_rtx_VEC_MERGE (mode, badop0, op1, mask1); |
8501 | ASSERT_EQ (badop0, simplify_merge_mask (badvm, mask1, 0)); |
8502 | ASSERT_EQ (NULL_RTX, simplify_merge_mask (badvm, mask1, 1)); |
8503 | |
8504 | /* Called indirectly. */ |
8505 | ASSERT_RTX_EQ (gen_rtx_VEC_MERGE (mode, op0, op3, mask1), |
8506 | simplify_rtx (nvm)); |
8507 | } |
8508 | |
8509 | /* Test subregs of integer vector constant X, trying elements in |
8510 | the range [ELT_BIAS, ELT_BIAS + constant_lower_bound (NELTS)), |
8511 | where NELTS is the number of elements in X. Subregs involving |
8512 | elements [ELT_BIAS, ELT_BIAS + FIRST_VALID) are expected to fail. */ |
8513 | |
8514 | static void |
8515 | test_vector_subregs_modes (rtx x, poly_uint64 elt_bias = 0, |
8516 | unsigned int first_valid = 0) |
8517 | { |
8518 | machine_mode inner_mode = GET_MODE (x); |
8519 | scalar_mode int_mode = GET_MODE_INNER (inner_mode); |
8520 | |
8521 | for (unsigned int modei = 0; modei < NUM_MACHINE_MODES; ++modei) |
8522 | { |
8523 | machine_mode outer_mode = (machine_mode) modei; |
8524 | if (!VECTOR_MODE_P (outer_mode)) |
8525 | continue; |
8526 | |
8527 | unsigned int outer_nunits; |
8528 | if (GET_MODE_INNER (outer_mode) == int_mode |
8529 | && GET_MODE_NUNITS (mode: outer_mode).is_constant (const_value: &outer_nunits) |
8530 | && multiple_p (a: GET_MODE_NUNITS (mode: inner_mode), b: outer_nunits)) |
8531 | { |
8532 | /* Test subregs in which the outer mode is a smaller, |
8533 | constant-sized vector of the same element type. */ |
8534 | unsigned int limit |
8535 | = constant_lower_bound (a: GET_MODE_NUNITS (mode: inner_mode)); |
8536 | for (unsigned int elt = 0; elt < limit; elt += outer_nunits) |
8537 | { |
8538 | rtx expected = NULL_RTX; |
8539 | if (elt >= first_valid) |
8540 | { |
8541 | rtx_vector_builder builder (outer_mode, outer_nunits, 1); |
8542 | for (unsigned int i = 0; i < outer_nunits; ++i) |
8543 | builder.quick_push (CONST_VECTOR_ELT (x, elt + i)); |
8544 | expected = builder.build (); |
8545 | } |
8546 | poly_uint64 byte = (elt_bias + elt) * GET_MODE_SIZE (mode: int_mode); |
8547 | ASSERT_RTX_EQ (expected, |
8548 | simplify_subreg (outer_mode, x, |
8549 | inner_mode, byte)); |
8550 | } |
8551 | } |
8552 | else if (known_eq (GET_MODE_SIZE (outer_mode), |
8553 | GET_MODE_SIZE (inner_mode)) |
8554 | && known_eq (elt_bias, 0U) |
8555 | && (GET_MODE_CLASS (outer_mode) != MODE_VECTOR_BOOL |
8556 | || known_eq (GET_MODE_BITSIZE (outer_mode), |
8557 | GET_MODE_NUNITS (outer_mode))) |
8558 | && (!FLOAT_MODE_P (outer_mode) |
8559 | || (FLOAT_MODE_FORMAT (outer_mode)->ieee_bits |
8560 | == GET_MODE_UNIT_PRECISION (outer_mode))) |
8561 | && (GET_MODE_SIZE (mode: inner_mode).is_constant () |
8562 | || !CONST_VECTOR_STEPPED_P (x))) |
8563 | { |
8564 | /* Try converting to OUTER_MODE and back. */ |
8565 | rtx outer_x = simplify_subreg (outermode: outer_mode, op: x, innermode: inner_mode, byte: 0); |
8566 | ASSERT_TRUE (outer_x != NULL_RTX); |
8567 | ASSERT_RTX_EQ (x, simplify_subreg (inner_mode, outer_x, |
8568 | outer_mode, 0)); |
8569 | } |
8570 | } |
8571 | |
8572 | if (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN) |
8573 | { |
8574 | /* Test each byte in the element range. */ |
8575 | unsigned int limit |
8576 | = constant_lower_bound (a: GET_MODE_SIZE (mode: inner_mode)); |
8577 | for (unsigned int i = 0; i < limit; ++i) |
8578 | { |
8579 | unsigned int elt = i / GET_MODE_SIZE (mode: int_mode); |
8580 | rtx expected = NULL_RTX; |
8581 | if (elt >= first_valid) |
8582 | { |
8583 | unsigned int byte_shift = i % GET_MODE_SIZE (mode: int_mode); |
8584 | if (BYTES_BIG_ENDIAN) |
8585 | byte_shift = GET_MODE_SIZE (mode: int_mode) - byte_shift - 1; |
8586 | rtx_mode_t vec_elt (CONST_VECTOR_ELT (x, elt), int_mode); |
8587 | wide_int shifted_elt |
8588 | = wi::lrshift (x: vec_elt, y: byte_shift * BITS_PER_UNIT); |
8589 | expected = immed_wide_int_const (shifted_elt, QImode); |
8590 | } |
8591 | poly_uint64 byte = elt_bias * GET_MODE_SIZE (mode: int_mode) + i; |
8592 | ASSERT_RTX_EQ (expected, |
8593 | simplify_subreg (QImode, x, inner_mode, byte)); |
8594 | } |
8595 | } |
8596 | } |
8597 | |
8598 | /* Test constant subregs of integer vector mode INNER_MODE, using 1 |
8599 | element per pattern. */ |
8600 | |
8601 | static void |
8602 | test_vector_subregs_repeating (machine_mode inner_mode) |
8603 | { |
8604 | poly_uint64 nunits = GET_MODE_NUNITS (mode: inner_mode); |
8605 | unsigned int min_nunits = constant_lower_bound (a: nunits); |
8606 | scalar_mode int_mode = GET_MODE_INNER (inner_mode); |
8607 | unsigned int count = gcd (min_nunits, 8); |
8608 | |
8609 | rtx_vector_builder builder (inner_mode, count, 1); |
8610 | for (unsigned int i = 0; i < count; ++i) |
8611 | builder.quick_push (obj: gen_int_mode (8 - i, int_mode)); |
8612 | rtx x = builder.build (); |
8613 | |
8614 | test_vector_subregs_modes (x); |
8615 | if (!nunits.is_constant ()) |
8616 | test_vector_subregs_modes (x, elt_bias: nunits - min_nunits); |
8617 | } |
8618 | |
8619 | /* Test constant subregs of integer vector mode INNER_MODE, using 2 |
8620 | elements per pattern. */ |
8621 | |
8622 | static void |
8623 | test_vector_subregs_fore_back (machine_mode inner_mode) |
8624 | { |
8625 | poly_uint64 nunits = GET_MODE_NUNITS (mode: inner_mode); |
8626 | unsigned int min_nunits = constant_lower_bound (a: nunits); |
8627 | scalar_mode int_mode = GET_MODE_INNER (inner_mode); |
8628 | unsigned int count = gcd (min_nunits, 4); |
8629 | |
8630 | rtx_vector_builder builder (inner_mode, count, 2); |
8631 | for (unsigned int i = 0; i < count; ++i) |
8632 | builder.quick_push (obj: gen_int_mode (i, int_mode)); |
8633 | for (unsigned int i = 0; i < count; ++i) |
8634 | builder.quick_push (obj: gen_int_mode (-1 - (int) i, int_mode)); |
8635 | rtx x = builder.build (); |
8636 | |
8637 | test_vector_subregs_modes (x); |
8638 | if (!nunits.is_constant ()) |
8639 | test_vector_subregs_modes (x, elt_bias: nunits - min_nunits, first_valid: count); |
8640 | } |
8641 | |
8642 | /* Test constant subregs of integer vector mode INNER_MODE, using 3 |
8643 | elements per pattern. */ |
8644 | |
8645 | static void |
8646 | test_vector_subregs_stepped (machine_mode inner_mode) |
8647 | { |
8648 | /* Build { 0, 1, 2, 3, ... }. */ |
8649 | scalar_mode int_mode = GET_MODE_INNER (inner_mode); |
8650 | rtx_vector_builder builder (inner_mode, 1, 3); |
8651 | for (unsigned int i = 0; i < 3; ++i) |
8652 | builder.quick_push (obj: gen_int_mode (i, int_mode)); |
8653 | rtx x = builder.build (); |
8654 | |
8655 | test_vector_subregs_modes (x); |
8656 | } |
8657 | |
8658 | /* Test constant subregs of integer vector mode INNER_MODE. */ |
8659 | |
8660 | static void |
8661 | test_vector_subregs (machine_mode inner_mode) |
8662 | { |
8663 | test_vector_subregs_repeating (inner_mode); |
8664 | test_vector_subregs_fore_back (inner_mode); |
8665 | test_vector_subregs_stepped (inner_mode); |
8666 | } |
8667 | |
8668 | /* Verify some simplifications involving vectors. */ |
8669 | |
8670 | static void |
8671 | test_vector_ops () |
8672 | { |
8673 | for (unsigned int i = 0; i < NUM_MACHINE_MODES; ++i) |
8674 | { |
8675 | machine_mode mode = (machine_mode) i; |
8676 | if (VECTOR_MODE_P (mode)) |
8677 | { |
8678 | rtx scalar_reg = make_test_reg (GET_MODE_INNER (mode)); |
8679 | test_vector_ops_duplicate (mode, scalar_reg); |
8680 | if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT |
8681 | && maybe_gt (GET_MODE_NUNITS (mode), 2)) |
8682 | { |
8683 | test_vector_ops_series (mode, scalar_reg); |
8684 | test_vector_subregs (inner_mode: mode); |
8685 | } |
8686 | test_vec_merge (mode); |
8687 | } |
8688 | } |
8689 | } |
8690 | |
8691 | template<unsigned int N> |
8692 | struct simplify_const_poly_int_tests |
8693 | { |
8694 | static void run (); |
8695 | }; |
8696 | |
8697 | template<> |
8698 | struct simplify_const_poly_int_tests<1> |
8699 | { |
8700 | static void run () {} |
8701 | }; |
8702 | |
8703 | /* Test various CONST_POLY_INT properties. */ |
8704 | |
8705 | template<unsigned int N> |
8706 | void |
8707 | simplify_const_poly_int_tests<N>::run () |
8708 | { |
8709 | using poly_int64 = poly_int<N, HOST_WIDE_INT>; |
8710 | rtx x1 = gen_int_mode (poly_int64 (1, 1), QImode); |
8711 | rtx x2 = gen_int_mode (poly_int64 (-80, 127), QImode); |
8712 | rtx x3 = gen_int_mode (poly_int64 (-79, -128), QImode); |
8713 | rtx x4 = gen_int_mode (poly_int64 (5, 4), QImode); |
8714 | rtx x5 = gen_int_mode (poly_int64 (30, 24), QImode); |
8715 | rtx x6 = gen_int_mode (poly_int64 (20, 16), QImode); |
8716 | rtx x7 = gen_int_mode (poly_int64 (7, 4), QImode); |
8717 | rtx x8 = gen_int_mode (poly_int64 (30, 24), HImode); |
8718 | rtx x9 = gen_int_mode (poly_int64 (-30, -24), HImode); |
8719 | rtx x10 = gen_int_mode (poly_int64 (-31, -24), HImode); |
8720 | rtx two = GEN_INT (2); |
8721 | rtx six = GEN_INT (6); |
8722 | poly_uint64 offset = subreg_lowpart_offset (QImode, HImode); |
8723 | |
8724 | /* These tests only try limited operation combinations. Fuller arithmetic |
8725 | testing is done directly on poly_ints. */ |
8726 | ASSERT_EQ (simplify_unary_operation (NEG, HImode, x8, HImode), x9); |
8727 | ASSERT_EQ (simplify_unary_operation (NOT, HImode, x8, HImode), x10); |
8728 | ASSERT_EQ (simplify_unary_operation (TRUNCATE, QImode, x8, HImode), x5); |
8729 | ASSERT_EQ (simplify_binary_operation (PLUS, QImode, x1, x2), x3); |
8730 | ASSERT_EQ (simplify_binary_operation (MINUS, QImode, x3, x1), x2); |
8731 | ASSERT_EQ (simplify_binary_operation (MULT, QImode, x4, six), x5); |
8732 | ASSERT_EQ (simplify_binary_operation (MULT, QImode, six, x4), x5); |
8733 | ASSERT_EQ (simplify_binary_operation (ASHIFT, QImode, x4, two), x6); |
8734 | ASSERT_EQ (simplify_binary_operation (IOR, QImode, x4, two), x7); |
8735 | ASSERT_EQ (simplify_subreg (HImode, x5, QImode, 0), x8); |
8736 | ASSERT_EQ (simplify_subreg (QImode, x8, HImode, offset), x5); |
8737 | } |
8738 | |
8739 | /* Run all of the selftests within this file. */ |
8740 | |
8741 | void |
8742 | simplify_rtx_cc_tests () |
8743 | { |
8744 | test_scalar_ops (); |
8745 | test_vector_ops (); |
8746 | simplify_const_poly_int_tests<NUM_POLY_INT_COEFFS>::run (); |
8747 | } |
8748 | |
8749 | } // namespace selftest |
8750 | |
8751 | #endif /* CHECKING_P */ |
8752 | |