comparison gcc/simplify-rtx.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* RTL simplification functions for GNU compiler. 1 /* RTL simplification functions for GNU compiler.
2 Copyright (C) 1987-2017 Free Software Foundation, Inc. 2 Copyright (C) 1987-2018 Free Software Foundation, Inc.
3 3
4 This file is part of GCC. 4 This file is part of GCC.
5 5
6 GCC is free software; you can redistribute it and/or modify it under 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 7 the terms of the GNU General Public License as published by the Free
31 #include "emit-rtl.h" 31 #include "emit-rtl.h"
32 #include "recog.h" 32 #include "recog.h"
33 #include "diagnostic-core.h" 33 #include "diagnostic-core.h"
34 #include "varasm.h" 34 #include "varasm.h"
35 #include "flags.h" 35 #include "flags.h"
36 #include "selftest.h"
37 #include "selftest-rtl.h"
36 38
37 /* Simplification and canonicalization of RTL. */ 39 /* Simplification and canonicalization of RTL. */
38 40
39 /* Much code operates on (low, high) pairs; the low value is an 41 /* Much code operates on (low, high) pairs; the low value is an
40 unsigned wide int, the high value a signed wide int. We 42 unsigned wide int, the high value a signed wide int. We
44 ((((HOST_WIDE_INT) low) < 0) ? HOST_WIDE_INT_M1 : HOST_WIDE_INT_0) 46 ((((HOST_WIDE_INT) low) < 0) ? HOST_WIDE_INT_M1 : HOST_WIDE_INT_0)
45 47
46 static rtx neg_const_int (machine_mode, const_rtx); 48 static rtx neg_const_int (machine_mode, const_rtx);
47 static bool plus_minus_operand_p (const_rtx); 49 static bool plus_minus_operand_p (const_rtx);
48 static rtx simplify_plus_minus (enum rtx_code, machine_mode, rtx, rtx); 50 static rtx simplify_plus_minus (enum rtx_code, machine_mode, rtx, rtx);
49 static rtx simplify_immed_subreg (machine_mode, rtx, machine_mode,
50 unsigned int);
51 static rtx simplify_associative_operation (enum rtx_code, machine_mode, 51 static rtx simplify_associative_operation (enum rtx_code, machine_mode,
52 rtx, rtx); 52 rtx, rtx);
53 static rtx simplify_relational_operation_1 (enum rtx_code, machine_mode, 53 static rtx simplify_relational_operation_1 (enum rtx_code, machine_mode,
54 machine_mode, rtx, rtx); 54 machine_mode, rtx, rtx);
55 static rtx simplify_unary_operation_1 (enum rtx_code, machine_mode, rtx); 55 static rtx simplify_unary_operation_1 (enum rtx_code, machine_mode, rtx);
208 rtx 208 rtx
209 avoid_constant_pool_reference (rtx x) 209 avoid_constant_pool_reference (rtx x)
210 { 210 {
211 rtx c, tmp, addr; 211 rtx c, tmp, addr;
212 machine_mode cmode; 212 machine_mode cmode;
213 HOST_WIDE_INT offset = 0; 213 poly_int64 offset = 0;
214 214
215 switch (GET_CODE (x)) 215 switch (GET_CODE (x))
216 { 216 {
217 case MEM: 217 case MEM:
218 break; 218 break;
237 237
238 /* Call target hook to avoid the effects of -fpic etc.... */ 238 /* Call target hook to avoid the effects of -fpic etc.... */
239 addr = targetm.delegitimize_address (addr); 239 addr = targetm.delegitimize_address (addr);
240 240
241 /* Split the address into a base and integer offset. */ 241 /* Split the address into a base and integer offset. */
242 if (GET_CODE (addr) == CONST 242 addr = strip_offset (addr, &offset);
243 && GET_CODE (XEXP (addr, 0)) == PLUS
244 && CONST_INT_P (XEXP (XEXP (addr, 0), 1)))
245 {
246 offset = INTVAL (XEXP (XEXP (addr, 0), 1));
247 addr = XEXP (XEXP (addr, 0), 0);
248 }
249 243
250 if (GET_CODE (addr) == LO_SUM) 244 if (GET_CODE (addr) == LO_SUM)
251 addr = XEXP (addr, 1); 245 addr = XEXP (addr, 1);
252 246
253 /* If this is a constant pool reference, we can turn it into its 247 /* If this is a constant pool reference, we can turn it into its
259 cmode = get_pool_mode (addr); 253 cmode = get_pool_mode (addr);
260 254
261 /* If we're accessing the constant in a different mode than it was 255 /* If we're accessing the constant in a different mode than it was
262 originally stored, attempt to fix that up via subreg simplifications. 256 originally stored, attempt to fix that up via subreg simplifications.
263 If that fails we have no choice but to return the original memory. */ 257 If that fails we have no choice but to return the original memory. */
264 if (offset == 0 && cmode == GET_MODE (x)) 258 if (known_eq (offset, 0) && cmode == GET_MODE (x))
265 return c; 259 return c;
266 else if (offset >= 0 && offset < GET_MODE_SIZE (cmode)) 260 else if (known_in_range_p (offset, 0, GET_MODE_SIZE (cmode)))
267 { 261 {
268 rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset); 262 rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset);
269 if (tem && CONSTANT_P (tem)) 263 if (tem && CONSTANT_P (tem))
270 return tem; 264 return tem;
271 } 265 }
287 && MEM_EXPR (x) 281 && MEM_EXPR (x)
288 && MEM_OFFSET_KNOWN_P (x)) 282 && MEM_OFFSET_KNOWN_P (x))
289 { 283 {
290 tree decl = MEM_EXPR (x); 284 tree decl = MEM_EXPR (x);
291 machine_mode mode = GET_MODE (x); 285 machine_mode mode = GET_MODE (x);
292 HOST_WIDE_INT offset = 0; 286 poly_int64 offset = 0;
293 287
294 switch (TREE_CODE (decl)) 288 switch (TREE_CODE (decl))
295 { 289 {
296 default: 290 default:
297 decl = NULL; 291 decl = NULL;
306 case BIT_FIELD_REF: 300 case BIT_FIELD_REF:
307 case REALPART_EXPR: 301 case REALPART_EXPR:
308 case IMAGPART_EXPR: 302 case IMAGPART_EXPR:
309 case VIEW_CONVERT_EXPR: 303 case VIEW_CONVERT_EXPR:
310 { 304 {
311 HOST_WIDE_INT bitsize, bitpos; 305 poly_int64 bitsize, bitpos, bytepos, toffset_val = 0;
312 tree toffset; 306 tree toffset;
313 int unsignedp, reversep, volatilep = 0; 307 int unsignedp, reversep, volatilep = 0;
314 308
315 decl 309 decl
316 = get_inner_reference (decl, &bitsize, &bitpos, &toffset, &mode, 310 = get_inner_reference (decl, &bitsize, &bitpos, &toffset, &mode,
317 &unsignedp, &reversep, &volatilep); 311 &unsignedp, &reversep, &volatilep);
318 if (bitsize != GET_MODE_BITSIZE (mode) 312 if (maybe_ne (bitsize, GET_MODE_BITSIZE (mode))
319 || (bitpos % BITS_PER_UNIT) 313 || !multiple_p (bitpos, BITS_PER_UNIT, &bytepos)
320 || (toffset && !tree_fits_shwi_p (toffset))) 314 || (toffset && !poly_int_tree_p (toffset, &toffset_val)))
321 decl = NULL; 315 decl = NULL;
322 else 316 else
323 { 317 offset += bytepos + toffset_val;
324 offset += bitpos / BITS_PER_UNIT;
325 if (toffset)
326 offset += tree_to_shwi (toffset);
327 }
328 break; 318 break;
329 } 319 }
330 } 320 }
331 321
332 if (decl 322 if (decl
344 newx = DECL_RTL (decl); 334 newx = DECL_RTL (decl);
345 335
346 if (MEM_P (newx)) 336 if (MEM_P (newx))
347 { 337 {
348 rtx n = XEXP (newx, 0), o = XEXP (x, 0); 338 rtx n = XEXP (newx, 0), o = XEXP (x, 0);
339 poly_int64 n_offset, o_offset;
349 340
350 /* Avoid creating a new MEM needlessly if we already had 341 /* Avoid creating a new MEM needlessly if we already had
351 the same address. We do if there's no OFFSET and the 342 the same address. We do if there's no OFFSET and the
352 old address X is identical to NEWX, or if X is of the 343 old address X is identical to NEWX, or if X is of the
353 form (plus NEWX OFFSET), or the NEWX is of the form 344 form (plus NEWX OFFSET), or the NEWX is of the form
354 (plus Y (const_int Z)) and X is that with the offset 345 (plus Y (const_int Z)) and X is that with the offset
355 added: (plus Y (const_int Z+OFFSET)). */ 346 added: (plus Y (const_int Z+OFFSET)). */
356 if (!((offset == 0 347 n = strip_offset (n, &n_offset);
357 || (GET_CODE (o) == PLUS 348 o = strip_offset (o, &o_offset);
358 && GET_CODE (XEXP (o, 1)) == CONST_INT 349 if (!(known_eq (o_offset, n_offset + offset)
359 && (offset == INTVAL (XEXP (o, 1))
360 || (GET_CODE (n) == PLUS
361 && GET_CODE (XEXP (n, 1)) == CONST_INT
362 && (INTVAL (XEXP (n, 1)) + offset
363 == INTVAL (XEXP (o, 1)))
364 && (n = XEXP (n, 0))))
365 && (o = XEXP (o, 0))))
366 && rtx_equal_p (o, n))) 350 && rtx_equal_p (o, n)))
367 x = adjust_address_nv (newx, mode, offset); 351 x = adjust_address_nv (newx, mode, offset);
368 } 352 }
369 else if (GET_MODE (x) == GET_MODE (newx) 353 else if (GET_MODE (x) == GET_MODE (newx)
370 && offset == 0) 354 && known_eq (offset, 0))
371 x = newx; 355 x = newx;
372 } 356 }
373 } 357 }
374 358
375 return x; 359 return x;
398 machine_mode op0_mode, rtx op0, rtx op1, rtx op2) 382 machine_mode op0_mode, rtx op0, rtx op1, rtx op2)
399 { 383 {
400 rtx tem; 384 rtx tem;
401 385
402 /* If this simplifies, use it. */ 386 /* If this simplifies, use it. */
403 if (0 != (tem = simplify_ternary_operation (code, mode, op0_mode, 387 if ((tem = simplify_ternary_operation (code, mode, op0_mode,
404 op0, op1, op2))) 388 op0, op1, op2)) != 0)
405 return tem; 389 return tem;
406 390
407 return gen_rtx_fmt_eee (code, mode, op0, op1, op2); 391 return gen_rtx_fmt_eee (code, mode, op0, op1, op2);
408 } 392 }
409 393
414 simplify_gen_relational (enum rtx_code code, machine_mode mode, 398 simplify_gen_relational (enum rtx_code code, machine_mode mode,
415 machine_mode cmp_mode, rtx op0, rtx op1) 399 machine_mode cmp_mode, rtx op0, rtx op1)
416 { 400 {
417 rtx tem; 401 rtx tem;
418 402
419 if (0 != (tem = simplify_relational_operation (code, mode, cmp_mode, 403 if ((tem = simplify_relational_operation (code, mode, cmp_mode,
420 op0, op1))) 404 op0, op1)) != 0)
421 return tem; 405 return tem;
422 406
423 return gen_rtx_fmt_ee (code, mode, op0, op1); 407 return gen_rtx_fmt_ee (code, mode, op0, op1);
424 } 408 }
425 409
793 && 2 * precision <= op_precision 777 && 2 * precision <= op_precision
794 && CONST_INT_P (XEXP (op, 1)) 778 && CONST_INT_P (XEXP (op, 1))
795 && (INTVAL (XEXP (op, 1)) & (precision - 1)) == 0 779 && (INTVAL (XEXP (op, 1)) & (precision - 1)) == 0
796 && UINTVAL (XEXP (op, 1)) < op_precision) 780 && UINTVAL (XEXP (op, 1)) < op_precision)
797 { 781 {
798 int byte = subreg_lowpart_offset (mode, op_mode); 782 poly_int64 byte = subreg_lowpart_offset (mode, op_mode);
799 int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; 783 int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
800 return simplify_gen_subreg (mode, XEXP (op, 0), op_mode, 784 return simplify_gen_subreg (mode, XEXP (op, 0), op_mode,
801 (WORDS_BIG_ENDIAN 785 (WORDS_BIG_ENDIAN
802 ? byte - shifted_bytes 786 ? byte - shifted_bytes
803 : byte + shifted_bytes)); 787 : byte + shifted_bytes));
819 MEM_ADDR_SPACE (XEXP (op, 0))) 803 MEM_ADDR_SPACE (XEXP (op, 0)))
820 && ! MEM_VOLATILE_P (XEXP (op, 0)) 804 && ! MEM_VOLATILE_P (XEXP (op, 0))
821 && (GET_MODE_SIZE (int_mode) >= UNITS_PER_WORD 805 && (GET_MODE_SIZE (int_mode) >= UNITS_PER_WORD
822 || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN)) 806 || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN))
823 { 807 {
824 int byte = subreg_lowpart_offset (int_mode, int_op_mode); 808 poly_int64 byte = subreg_lowpart_offset (int_mode, int_op_mode);
825 int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; 809 int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
826 return adjust_address_nv (XEXP (op, 0), int_mode, 810 return adjust_address_nv (XEXP (op, 0), int_mode,
827 (WORDS_BIG_ENDIAN 811 (WORDS_BIG_ENDIAN
828 ? byte - shifted_bytes 812 ? byte - shifted_bytes
829 : byte + shifted_bytes)); 813 : byte + shifted_bytes));
923 aren't constant. */ 907 aren't constant. */
924 static rtx 908 static rtx
925 simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) 909 simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
926 { 910 {
927 enum rtx_code reversed; 911 enum rtx_code reversed;
928 rtx temp; 912 rtx temp, elt, base, step;
929 scalar_int_mode inner, int_mode, op_mode, op0_mode; 913 scalar_int_mode inner, int_mode, op_mode, op0_mode;
930 914
931 switch (code) 915 switch (code)
932 { 916 {
933 case NOT: 917 case NOT:
1163 int_mode = as_a <scalar_int_mode> (mode); 1147 int_mode = as_a <scalar_int_mode> (mode);
1164 int isize = GET_MODE_PRECISION (inner); 1148 int isize = GET_MODE_PRECISION (inner);
1165 if (STORE_FLAG_VALUE == 1) 1149 if (STORE_FLAG_VALUE == 1)
1166 { 1150 {
1167 temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0), 1151 temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0),
1168 GEN_INT (isize - 1)); 1152 gen_int_shift_amount (inner,
1153 isize - 1));
1169 if (int_mode == inner) 1154 if (int_mode == inner)
1170 return temp; 1155 return temp;
1171 if (GET_MODE_PRECISION (int_mode) > isize) 1156 if (GET_MODE_PRECISION (int_mode) > isize)
1172 return simplify_gen_unary (SIGN_EXTEND, int_mode, temp, inner); 1157 return simplify_gen_unary (SIGN_EXTEND, int_mode, temp, inner);
1173 return simplify_gen_unary (TRUNCATE, int_mode, temp, inner); 1158 return simplify_gen_unary (TRUNCATE, int_mode, temp, inner);
1174 } 1159 }
1175 else if (STORE_FLAG_VALUE == -1) 1160 else if (STORE_FLAG_VALUE == -1)
1176 { 1161 {
1177 temp = simplify_gen_binary (LSHIFTRT, inner, XEXP (op, 0), 1162 temp = simplify_gen_binary (LSHIFTRT, inner, XEXP (op, 0),
1178 GEN_INT (isize - 1)); 1163 gen_int_shift_amount (inner,
1164 isize - 1));
1179 if (int_mode == inner) 1165 if (int_mode == inner)
1180 return temp; 1166 return temp;
1181 if (GET_MODE_PRECISION (int_mode) > isize) 1167 if (GET_MODE_PRECISION (int_mode) > isize)
1182 return simplify_gen_unary (ZERO_EXTEND, int_mode, temp, inner); 1168 return simplify_gen_unary (ZERO_EXTEND, int_mode, temp, inner);
1183 return simplify_gen_unary (TRUNCATE, int_mode, temp, inner); 1169 return simplify_gen_unary (TRUNCATE, int_mode, temp, inner);
1170 }
1171 }
1172
1173 if (vec_series_p (op, &base, &step))
1174 {
1175 /* Only create a new series if we can simplify both parts. In other
1176 cases this isn't really a simplification, and it's not necessarily
1177 a win to replace a vector operation with a scalar operation. */
1178 scalar_mode inner_mode = GET_MODE_INNER (mode);
1179 base = simplify_unary_operation (NEG, inner_mode, base, inner_mode);
1180 if (base)
1181 {
1182 step = simplify_unary_operation (NEG, inner_mode,
1183 step, inner_mode);
1184 if (step)
1185 return gen_vec_series (mode, base, step);
1184 } 1186 }
1185 } 1187 }
1186 break; 1188 break;
1187 1189
1188 case TRUNCATE: 1190 case TRUNCATE:
1213 return temp; 1215 return temp;
1214 } 1216 }
1215 1217
1216 /* If we know that the value is already truncated, we can 1218 /* If we know that the value is already truncated, we can
1217 replace the TRUNCATE with a SUBREG. */ 1219 replace the TRUNCATE with a SUBREG. */
1218 if (GET_MODE_NUNITS (mode) == 1 1220 if (known_eq (GET_MODE_NUNITS (mode), 1)
1219 && (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)) 1221 && (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op))
1220 || truncated_to_mode (mode, op))) 1222 || truncated_to_mode (mode, op)))
1221 { 1223 {
1222 temp = rtl_hooks.gen_lowpart_no_emit (mode, op); 1224 temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
1223 if (temp) 1225 if (temp)
1474 if (GET_CODE (op) == SUBREG 1476 if (GET_CODE (op) == SUBREG
1475 && SUBREG_PROMOTED_VAR_P (op) 1477 && SUBREG_PROMOTED_VAR_P (op)
1476 && SUBREG_PROMOTED_SIGNED_P (op) 1478 && SUBREG_PROMOTED_SIGNED_P (op)
1477 && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op)))) 1479 && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
1478 { 1480 {
1479 temp = rtl_hooks.gen_lowpart_no_emit (mode, op); 1481 temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
1480 if (temp) 1482 if (temp)
1481 return temp; 1483 return temp;
1482 } 1484 }
1483 1485
1484 /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>). 1486 /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
1557 if (GET_CODE (op) == SUBREG 1559 if (GET_CODE (op) == SUBREG
1558 && SUBREG_PROMOTED_VAR_P (op) 1560 && SUBREG_PROMOTED_VAR_P (op)
1559 && SUBREG_PROMOTED_UNSIGNED_P (op) 1561 && SUBREG_PROMOTED_UNSIGNED_P (op)
1560 && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op)))) 1562 && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
1561 { 1563 {
1562 temp = rtl_hooks.gen_lowpart_no_emit (mode, op); 1564 temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
1563 if (temp) 1565 if (temp)
1564 return temp; 1566 return temp;
1565 } 1567 }
1566 1568
1567 /* Extending a widening multiplication should be canonicalized to 1569 /* Extending a widening multiplication should be canonicalized to
1682 1684
1683 default: 1685 default:
1684 break; 1686 break;
1685 } 1687 }
1686 1688
1689 if (VECTOR_MODE_P (mode)
1690 && vec_duplicate_p (op, &elt)
1691 && code != VEC_DUPLICATE)
1692 {
1693 /* Try applying the operator to ELT and see if that simplifies.
1694 We can duplicate the result if so.
1695
1696 The reason we don't use simplify_gen_unary is that it isn't
1697 necessarily a win to convert things like:
1698
1699 (neg:V (vec_duplicate:V (reg:S R)))
1700
1701 to:
1702
1703 (vec_duplicate:V (neg:S (reg:S R)))
1704
1705 The first might be done entirely in vector registers while the
1706 second might need a move between register files. */
1707 temp = simplify_unary_operation (code, GET_MODE_INNER (mode),
1708 elt, GET_MODE_INNER (GET_MODE (op)));
1709 if (temp)
1710 return gen_vec_duplicate (mode, temp);
1711 }
1712
1687 return 0; 1713 return 0;
1688 } 1714 }
1689 1715
1690 /* Try to compute the value of a unary operation CODE whose output mode is to 1716 /* Try to compute the value of a unary operation CODE whose output mode is to
1691 be MODE with input operand OP whose mode was originally OP_MODE. 1717 be MODE with input operand OP whose mode was originally OP_MODE.
1705 gcc_assert (GET_MODE_INNER (mode) == GET_MODE (op)); 1731 gcc_assert (GET_MODE_INNER (mode) == GET_MODE (op));
1706 else 1732 else
1707 gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER 1733 gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER
1708 (GET_MODE (op))); 1734 (GET_MODE (op)));
1709 } 1735 }
1710 if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op) 1736 if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op))
1711 || GET_CODE (op) == CONST_VECTOR) 1737 return gen_const_vec_duplicate (mode, op);
1712 { 1738 unsigned int n_elts;
1713 int elt_size = GET_MODE_UNIT_SIZE (mode); 1739 if (GET_CODE (op) == CONST_VECTOR
1714 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 1740 && GET_MODE_NUNITS (mode).is_constant (&n_elts))
1741 {
1742 /* This must be constant if we're duplicating it to a constant
1743 number of elements. */
1744 unsigned int in_n_elts = CONST_VECTOR_NUNITS (op).to_constant ();
1745 gcc_assert (in_n_elts < n_elts);
1746 gcc_assert ((n_elts % in_n_elts) == 0);
1715 rtvec v = rtvec_alloc (n_elts); 1747 rtvec v = rtvec_alloc (n_elts);
1716 unsigned int i; 1748 for (unsigned i = 0; i < n_elts; i++)
1717 1749 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts);
1718 if (GET_CODE (op) != CONST_VECTOR)
1719 for (i = 0; i < n_elts; i++)
1720 RTVEC_ELT (v, i) = op;
1721 else
1722 {
1723 machine_mode inmode = GET_MODE (op);
1724 int in_elt_size = GET_MODE_UNIT_SIZE (inmode);
1725 unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size);
1726
1727 gcc_assert (in_n_elts < n_elts);
1728 gcc_assert ((n_elts % in_n_elts) == 0);
1729 for (i = 0; i < n_elts; i++)
1730 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts);
1731 }
1732 return gen_rtx_CONST_VECTOR (mode, v); 1750 return gen_rtx_CONST_VECTOR (mode, v);
1733 } 1751 }
1734 } 1752 }
1735 1753
1736 if (VECTOR_MODE_P (mode) && GET_CODE (op) == CONST_VECTOR) 1754 if (VECTOR_MODE_P (mode) && GET_CODE (op) == CONST_VECTOR)
1737 { 1755 {
1738 int elt_size = GET_MODE_UNIT_SIZE (mode); 1756 unsigned int n_elts;
1739 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); 1757 if (!CONST_VECTOR_NUNITS (op).is_constant (&n_elts))
1758 return NULL_RTX;
1759
1740 machine_mode opmode = GET_MODE (op); 1760 machine_mode opmode = GET_MODE (op);
1741 int op_elt_size = GET_MODE_UNIT_SIZE (opmode); 1761 gcc_assert (known_eq (GET_MODE_NUNITS (mode), n_elts));
1742 unsigned op_n_elts = (GET_MODE_SIZE (opmode) / op_elt_size); 1762 gcc_assert (known_eq (GET_MODE_NUNITS (opmode), n_elts));
1763
1743 rtvec v = rtvec_alloc (n_elts); 1764 rtvec v = rtvec_alloc (n_elts);
1744 unsigned int i; 1765 unsigned int i;
1745 1766
1746 gcc_assert (op_n_elts == n_elts);
1747 for (i = 0; i < n_elts; i++) 1767 for (i = 0; i < n_elts; i++)
1748 { 1768 {
1749 rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode), 1769 rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode),
1750 CONST_VECTOR_ELT (op, i), 1770 CONST_VECTOR_ELT (op, i),
1751 GET_MODE_INNER (opmode)); 1771 GET_MODE_INNER (opmode));
1752 if (!x) 1772 if (!x || !valid_for_const_vector_p (mode, x))
1753 return 0; 1773 return 0;
1754 RTVEC_ELT (v, i) = x; 1774 RTVEC_ELT (v, i) = x;
1755 } 1775 }
1756 return gen_rtx_CONST_VECTOR (mode, v); 1776 return gen_rtx_CONST_VECTOR (mode, v);
1757 } 1777 }
1849 1869
1850 case CLZ: 1870 case CLZ:
1851 if (wi::ne_p (op0, 0)) 1871 if (wi::ne_p (op0, 0))
1852 int_value = wi::clz (op0); 1872 int_value = wi::clz (op0);
1853 else if (! CLZ_DEFINED_VALUE_AT_ZERO (imode, int_value)) 1873 else if (! CLZ_DEFINED_VALUE_AT_ZERO (imode, int_value))
1854 int_value = GET_MODE_PRECISION (imode); 1874 return NULL_RTX;
1855 result = wi::shwi (int_value, result_mode); 1875 result = wi::shwi (int_value, result_mode);
1856 break; 1876 break;
1857 1877
1858 case CLRSB: 1878 case CLRSB:
1859 result = wi::shwi (wi::clrsb (op0), result_mode); 1879 result = wi::shwi (wi::clrsb (op0), result_mode);
1861 1881
1862 case CTZ: 1882 case CTZ:
1863 if (wi::ne_p (op0, 0)) 1883 if (wi::ne_p (op0, 0))
1864 int_value = wi::ctz (op0); 1884 int_value = wi::ctz (op0);
1865 else if (! CTZ_DEFINED_VALUE_AT_ZERO (imode, int_value)) 1885 else if (! CTZ_DEFINED_VALUE_AT_ZERO (imode, int_value))
1866 int_value = GET_MODE_PRECISION (imode); 1886 return NULL_RTX;
1867 result = wi::shwi (int_value, result_mode); 1887 result = wi::shwi (int_value, result_mode);
1868 break; 1888 break;
1869 1889
1870 case POPCOUNT: 1890 case POPCOUNT:
1871 result = wi::shwi (wi::popcount (op0), result_mode); 1891 result = wi::shwi (wi::popcount (op0), result_mode);
2007 default: 2027 default:
2008 gcc_unreachable (); 2028 gcc_unreachable ();
2009 } 2029 }
2010 } 2030 }
2011 2031
2032 /* Handle polynomial integers. */
2033 else if (CONST_POLY_INT_P (op))
2034 {
2035 poly_wide_int result;
2036 switch (code)
2037 {
2038 case NEG:
2039 result = -const_poly_int_value (op);
2040 break;
2041
2042 case NOT:
2043 result = ~const_poly_int_value (op);
2044 break;
2045
2046 default:
2047 return NULL_RTX;
2048 }
2049 return immed_wide_int_const (result, mode);
2050 }
2051
2012 return NULL_RTX; 2052 return NULL_RTX;
2013 } 2053 }
2014 2054
2015 /* Subroutine of simplify_binary_operation to simplify a binary operation 2055 /* Subroutine of simplify_binary_operation to simplify a binary operation
2016 CODE that can commute with byte swapping, with result mode MODE and 2056 CODE that can commute with byte swapping, with result mode MODE and
2135 return simplify_gen_binary (code, mode, trueop0, trueop1); 2175 return simplify_gen_binary (code, mode, trueop0, trueop1);
2136 2176
2137 return NULL_RTX; 2177 return NULL_RTX;
2138 } 2178 }
2139 2179
2180 /* Subroutine of simplify_binary_operation_1 that looks for cases in
2181 which OP0 and OP1 are both vector series or vector duplicates
2182 (which are really just series with a step of 0). If so, try to
2183 form a new series by applying CODE to the bases and to the steps.
2184 Return null if no simplification is possible.
2185
2186 MODE is the mode of the operation and is known to be a vector
2187 integer mode. */
2188
2189 static rtx
2190 simplify_binary_operation_series (rtx_code code, machine_mode mode,
2191 rtx op0, rtx op1)
2192 {
2193 rtx base0, step0;
2194 if (vec_duplicate_p (op0, &base0))
2195 step0 = const0_rtx;
2196 else if (!vec_series_p (op0, &base0, &step0))
2197 return NULL_RTX;
2198
2199 rtx base1, step1;
2200 if (vec_duplicate_p (op1, &base1))
2201 step1 = const0_rtx;
2202 else if (!vec_series_p (op1, &base1, &step1))
2203 return NULL_RTX;
2204
2205 /* Only create a new series if we can simplify both parts. In other
2206 cases this isn't really a simplification, and it's not necessarily
2207 a win to replace a vector operation with a scalar operation. */
2208 scalar_mode inner_mode = GET_MODE_INNER (mode);
2209 rtx new_base = simplify_binary_operation (code, inner_mode, base0, base1);
2210 if (!new_base)
2211 return NULL_RTX;
2212
2213 rtx new_step = simplify_binary_operation (code, inner_mode, step0, step1);
2214 if (!new_step)
2215 return NULL_RTX;
2216
2217 return gen_vec_series (mode, new_base, new_step);
2218 }
2219
2140 /* Subroutine of simplify_binary_operation. Simplify a binary operation 2220 /* Subroutine of simplify_binary_operation. Simplify a binary operation
2141 CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or 2221 CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or
2142 OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the 2222 OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the
2143 actual constants. */ 2223 actual constants. */
2144 2224
2145 static rtx 2225 static rtx
2146 simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, 2226 simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
2147 rtx op0, rtx op1, rtx trueop0, rtx trueop1) 2227 rtx op0, rtx op1, rtx trueop0, rtx trueop1)
2148 { 2228 {
2149 rtx tem, reversed, opleft, opright; 2229 rtx tem, reversed, opleft, opright, elt0, elt1;
2150 HOST_WIDE_INT val; 2230 HOST_WIDE_INT val;
2151 scalar_int_mode int_mode, inner_mode; 2231 scalar_int_mode int_mode, inner_mode;
2232 poly_int64 offset;
2152 2233
2153 /* Even if we can't compute a constant result, 2234 /* Even if we can't compute a constant result,
2154 there are some cases worth simplifying. */ 2235 there are some cases worth simplifying. */
2155 2236
2156 switch (code) 2237 switch (code)
2183 than HOST_BITS_PER_WIDE_INT. */ 2264 than HOST_BITS_PER_WIDE_INT. */
2184 2265
2185 if ((GET_CODE (op0) == CONST 2266 if ((GET_CODE (op0) == CONST
2186 || GET_CODE (op0) == SYMBOL_REF 2267 || GET_CODE (op0) == SYMBOL_REF
2187 || GET_CODE (op0) == LABEL_REF) 2268 || GET_CODE (op0) == LABEL_REF)
2188 && CONST_INT_P (op1)) 2269 && poly_int_rtx_p (op1, &offset))
2189 return plus_constant (mode, op0, INTVAL (op1)); 2270 return plus_constant (mode, op0, offset);
2190 else if ((GET_CODE (op1) == CONST 2271 else if ((GET_CODE (op1) == CONST
2191 || GET_CODE (op1) == SYMBOL_REF 2272 || GET_CODE (op1) == SYMBOL_REF
2192 || GET_CODE (op1) == LABEL_REF) 2273 || GET_CODE (op1) == LABEL_REF)
2193 && CONST_INT_P (op0)) 2274 && poly_int_rtx_p (op0, &offset))
2194 return plus_constant (mode, op1, INTVAL (op0)); 2275 return plus_constant (mode, op1, offset);
2195 2276
2196 /* See if this is something like X * C - X or vice versa or 2277 /* See if this is something like X * C - X or vice versa or
2197 if the multiplication is written as a shift. If so, we can 2278 if the multiplication is written as a shift. If so, we can
2198 distribute and make a new multiply, shift, or maybe just 2279 distribute and make a new multiply, shift, or maybe just
2199 have X (if C is 2 in the example above). But don't make 2280 have X (if C is 2 in the example above). But don't make
2311 specifies associative math operations. */ 2392 specifies associative math operations. */
2312 if (FLOAT_MODE_P (mode) 2393 if (FLOAT_MODE_P (mode)
2313 && flag_associative_math) 2394 && flag_associative_math)
2314 { 2395 {
2315 tem = simplify_associative_operation (code, mode, op0, op1); 2396 tem = simplify_associative_operation (code, mode, op0, op1);
2397 if (tem)
2398 return tem;
2399 }
2400
2401 /* Handle vector series. */
2402 if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
2403 {
2404 tem = simplify_binary_operation_series (code, mode, op0, op1);
2316 if (tem) 2405 if (tem)
2317 return tem; 2406 return tem;
2318 } 2407 }
2319 break; 2408 break;
2320 2409
2451 tem = simplify_unary_operation (NEG, mode, op1, mode); 2540 tem = simplify_unary_operation (NEG, mode, op1, mode);
2452 if (tem) 2541 if (tem)
2453 return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0)); 2542 return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0));
2454 } 2543 }
2455 2544
2545 if ((GET_CODE (op0) == CONST
2546 || GET_CODE (op0) == SYMBOL_REF
2547 || GET_CODE (op0) == LABEL_REF)
2548 && poly_int_rtx_p (op1, &offset))
2549 return plus_constant (mode, op0, trunc_int_for_mode (-offset, mode));
2550
2456 /* Don't let a relocatable value get a negative coeff. */ 2551 /* Don't let a relocatable value get a negative coeff. */
2457 if (CONST_INT_P (op1) && GET_MODE (op0) != VOIDmode) 2552 if (CONST_INT_P (op1) && GET_MODE (op0) != VOIDmode)
2458 return simplify_gen_binary (PLUS, mode, 2553 return simplify_gen_binary (PLUS, mode,
2459 op0, 2554 op0,
2460 neg_const_int (mode, op1)); 2555 neg_const_int (mode, op1));
2525 if (INTEGRAL_MODE_P (mode) 2620 if (INTEGRAL_MODE_P (mode)
2526 && (plus_minus_operand_p (op0) 2621 && (plus_minus_operand_p (op0)
2527 || plus_minus_operand_p (op1)) 2622 || plus_minus_operand_p (op1))
2528 && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) 2623 && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
2529 return tem; 2624 return tem;
2625
2626 /* Handle vector series. */
2627 if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
2628 {
2629 tem = simplify_binary_operation_series (code, mode, op0, op1);
2630 if (tem)
2631 return tem;
2632 }
2530 break; 2633 break;
2531 2634
2532 case MULT: 2635 case MULT:
2533 if (trueop1 == constm1_rtx) 2636 if (trueop1 == constm1_rtx)
2534 return simplify_gen_unary (NEG, mode, op0, mode); 2637 return simplify_gen_unary (NEG, mode, op0, mode);
2587 /* Convert multiply by constant power of two into shift. */ 2690 /* Convert multiply by constant power of two into shift. */
2588 if (CONST_SCALAR_INT_P (trueop1)) 2691 if (CONST_SCALAR_INT_P (trueop1))
2589 { 2692 {
2590 val = wi::exact_log2 (rtx_mode_t (trueop1, mode)); 2693 val = wi::exact_log2 (rtx_mode_t (trueop1, mode));
2591 if (val >= 0) 2694 if (val >= 0)
2592 return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val)); 2695 return simplify_gen_binary (ASHIFT, mode, op0,
2696 gen_int_shift_amount (mode, val));
2593 } 2697 }
2594 2698
2595 /* x*2 is x+x and x*(-1) is -x */ 2699 /* x*2 is x+x and x*(-1) is -x */
2596 if (CONST_DOUBLE_AS_FLOAT_P (trueop1) 2700 if (CONST_DOUBLE_AS_FLOAT_P (trueop1)
2597 && SCALAR_FLOAT_MODE_P (GET_MODE (trueop1)) 2701 && SCALAR_FLOAT_MODE_P (GET_MODE (trueop1))
2716 && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (opleft)), 2820 && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (opleft)),
2717 &inner_mode) 2821 &inner_mode)
2718 && GET_CODE (SUBREG_REG (opleft)) == ASHIFT 2822 && GET_CODE (SUBREG_REG (opleft)) == ASHIFT
2719 && GET_CODE (opright) == LSHIFTRT 2823 && GET_CODE (opright) == LSHIFTRT
2720 && GET_CODE (XEXP (opright, 0)) == SUBREG 2824 && GET_CODE (XEXP (opright, 0)) == SUBREG
2721 && SUBREG_BYTE (opleft) == SUBREG_BYTE (XEXP (opright, 0)) 2825 && known_eq (SUBREG_BYTE (opleft), SUBREG_BYTE (XEXP (opright, 0)))
2722 && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode) 2826 && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode)
2723 && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), 2827 && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0),
2724 SUBREG_REG (XEXP (opright, 0))) 2828 SUBREG_REG (XEXP (opright, 0)))
2725 && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1)) 2829 && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1))
2726 && CONST_INT_P (XEXP (opright, 1)) 2830 && CONST_INT_P (XEXP (opright, 1))
3211 return tem; 3315 return tem;
3212 } 3316 }
3213 /* Convert divide by power of two into shift. */ 3317 /* Convert divide by power of two into shift. */
3214 if (CONST_INT_P (trueop1) 3318 if (CONST_INT_P (trueop1)
3215 && (val = exact_log2 (UINTVAL (trueop1))) > 0) 3319 && (val = exact_log2 (UINTVAL (trueop1))) > 0)
3216 return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val)); 3320 return simplify_gen_binary (LSHIFTRT, mode, op0,
3321 gen_int_shift_amount (mode, val));
3217 break; 3322 break;
3218 3323
3219 case DIV: 3324 case DIV:
3220 /* Handle floating point and integers separately. */ 3325 /* Handle floating point and integers separately. */
3221 if (SCALAR_FLOAT_MODE_P (mode)) 3326 if (SCALAR_FLOAT_MODE_P (mode))
3300 } 3405 }
3301 /* Implement modulus by power of two as AND. */ 3406 /* Implement modulus by power of two as AND. */
3302 if (CONST_INT_P (trueop1) 3407 if (CONST_INT_P (trueop1)
3303 && exact_log2 (UINTVAL (trueop1)) > 0) 3408 && exact_log2 (UINTVAL (trueop1)) > 0)
3304 return simplify_gen_binary (AND, mode, op0, 3409 return simplify_gen_binary (AND, mode, op0,
3305 gen_int_mode (INTVAL (op1) - 1, mode)); 3410 gen_int_mode (UINTVAL (trueop1) - 1,
3411 mode));
3306 break; 3412 break;
3307 3413
3308 case MOD: 3414 case MOD:
3309 /* 0%x is 0 (or x&0 if x has side-effects). */ 3415 /* 0%x is 0 (or x&0 if x has side-effects). */
3310 if (trueop0 == CONST0_RTX (mode)) 3416 if (trueop0 == CONST0_RTX (mode))
3331 #if defined(HAVE_rotate) && defined(HAVE_rotatert) 3437 #if defined(HAVE_rotate) && defined(HAVE_rotatert)
3332 if (CONST_INT_P (trueop1) 3438 if (CONST_INT_P (trueop1)
3333 && IN_RANGE (INTVAL (trueop1), 3439 && IN_RANGE (INTVAL (trueop1),
3334 GET_MODE_UNIT_PRECISION (mode) / 2 + (code == ROTATE), 3440 GET_MODE_UNIT_PRECISION (mode) / 2 + (code == ROTATE),
3335 GET_MODE_UNIT_PRECISION (mode) - 1)) 3441 GET_MODE_UNIT_PRECISION (mode) - 1))
3336 return simplify_gen_binary (code == ROTATE ? ROTATERT : ROTATE, 3442 {
3337 mode, op0, 3443 int new_amount = GET_MODE_UNIT_PRECISION (mode) - INTVAL (trueop1);
3338 GEN_INT (GET_MODE_UNIT_PRECISION (mode) 3444 rtx new_amount_rtx = gen_int_shift_amount (mode, new_amount);
3339 - INTVAL (trueop1))); 3445 return simplify_gen_binary (code == ROTATE ? ROTATERT : ROTATE,
3446 mode, op0, new_amount_rtx);
3447 }
3340 #endif 3448 #endif
3341 /* FALLTHRU */ 3449 /* FALLTHRU */
3342 case ASHIFTRT: 3450 case ASHIFTRT:
3343 if (trueop1 == CONST0_RTX (mode)) 3451 if (trueop1 == CONST0_RTX (mode))
3344 return op0; 3452 return op0;
3375 && GET_MODE_BITSIZE (inner_mode) > GET_MODE_BITSIZE (int_mode) 3483 && GET_MODE_BITSIZE (inner_mode) > GET_MODE_BITSIZE (int_mode)
3376 && (INTVAL (XEXP (SUBREG_REG (op0), 1)) 3484 && (INTVAL (XEXP (SUBREG_REG (op0), 1))
3377 == GET_MODE_BITSIZE (inner_mode) - GET_MODE_BITSIZE (int_mode)) 3485 == GET_MODE_BITSIZE (inner_mode) - GET_MODE_BITSIZE (int_mode))
3378 && subreg_lowpart_p (op0)) 3486 && subreg_lowpart_p (op0))
3379 { 3487 {
3380 rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1)) 3488 rtx tmp = gen_int_shift_amount
3381 + INTVAL (op1)); 3489 (inner_mode, INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (op1));
3382 tmp = simplify_gen_binary (code, inner_mode, 3490 tmp = simplify_gen_binary (code, inner_mode,
3383 XEXP (SUBREG_REG (op0), 0), 3491 XEXP (SUBREG_REG (op0), 0),
3384 tmp); 3492 tmp);
3385 return lowpart_subreg (int_mode, tmp, inner_mode); 3493 return lowpart_subreg (int_mode, tmp, inner_mode);
3386 } 3494 }
3387 3495
3388 if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1)) 3496 if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1))
3389 { 3497 {
3390 val = INTVAL (op1) & (GET_MODE_UNIT_PRECISION (mode) - 1); 3498 val = INTVAL (op1) & (GET_MODE_UNIT_PRECISION (mode) - 1);
3391 if (val != INTVAL (op1)) 3499 if (val != INTVAL (op1))
3392 return simplify_gen_binary (code, mode, op0, GEN_INT (val)); 3500 return simplify_gen_binary (code, mode, op0,
3501 gen_int_shift_amount (mode, val));
3393 } 3502 }
3394 break; 3503 break;
3395 3504
3396 case ASHIFT: 3505 case ASHIFT:
3397 case SS_ASHIFT: 3506 case SS_ASHIFT:
3478 case SS_DIV: 3587 case SS_DIV:
3479 case US_DIV: 3588 case US_DIV:
3480 /* ??? There are simplifications that can be done. */ 3589 /* ??? There are simplifications that can be done. */
3481 return 0; 3590 return 0;
3482 3591
3592 case VEC_SERIES:
3593 if (op1 == CONST0_RTX (GET_MODE_INNER (mode)))
3594 return gen_vec_duplicate (mode, op0);
3595 if (valid_for_const_vector_p (mode, op0)
3596 && valid_for_const_vector_p (mode, op1))
3597 return gen_const_vec_series (mode, op0, op1);
3598 return 0;
3599
3483 case VEC_SELECT: 3600 case VEC_SELECT:
3484 if (!VECTOR_MODE_P (mode)) 3601 if (!VECTOR_MODE_P (mode))
3485 { 3602 {
3486 gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); 3603 gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0)));
3487 gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0))); 3604 gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0)));
3488 gcc_assert (GET_CODE (trueop1) == PARALLEL); 3605 gcc_assert (GET_CODE (trueop1) == PARALLEL);
3489 gcc_assert (XVECLEN (trueop1, 0) == 1); 3606 gcc_assert (XVECLEN (trueop1, 0) == 1);
3490 gcc_assert (CONST_INT_P (XVECEXP (trueop1, 0, 0))); 3607
3608 /* We can't reason about selections made at runtime. */
3609 if (!CONST_INT_P (XVECEXP (trueop1, 0, 0)))
3610 return 0;
3611
3612 if (vec_duplicate_p (trueop0, &elt0))
3613 return elt0;
3491 3614
3492 if (GET_CODE (trueop0) == CONST_VECTOR) 3615 if (GET_CODE (trueop0) == CONST_VECTOR)
3493 return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP 3616 return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP
3494 (trueop1, 0, 0))); 3617 (trueop1, 0, 0)));
3495 3618
3497 (with optional nested VEC_CONCAT expression). Some targets 3620 (with optional nested VEC_CONCAT expression). Some targets
3498 (i386) extract scalar element from a vector using chain of 3621 (i386) extract scalar element from a vector using chain of
3499 nested VEC_SELECT expressions. When input operand is a memory 3622 nested VEC_SELECT expressions. When input operand is a memory
3500 operand, this operation can be simplified to a simple scalar 3623 operand, this operation can be simplified to a simple scalar
3501 load from an offseted memory address. */ 3624 load from an offseted memory address. */
3502 if (GET_CODE (trueop0) == VEC_SELECT) 3625 int n_elts;
3626 if (GET_CODE (trueop0) == VEC_SELECT
3627 && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 0)))
3628 .is_constant (&n_elts)))
3503 { 3629 {
3504 rtx op0 = XEXP (trueop0, 0); 3630 rtx op0 = XEXP (trueop0, 0);
3505 rtx op1 = XEXP (trueop0, 1); 3631 rtx op1 = XEXP (trueop0, 1);
3506
3507 machine_mode opmode = GET_MODE (op0);
3508 int elt_size = GET_MODE_UNIT_SIZE (opmode);
3509 int n_elts = GET_MODE_SIZE (opmode) / elt_size;
3510 3632
3511 int i = INTVAL (XVECEXP (trueop1, 0, 0)); 3633 int i = INTVAL (XVECEXP (trueop1, 0, 0));
3512 int elem; 3634 int elem;
3513 3635
3514 rtvec vec; 3636 rtvec vec;
3530 int n_elts00, n_elts01; 3652 int n_elts00, n_elts01;
3531 3653
3532 mode00 = GET_MODE (op00); 3654 mode00 = GET_MODE (op00);
3533 mode01 = GET_MODE (op01); 3655 mode01 = GET_MODE (op01);
3534 3656
3535 /* Find out number of elements of each operand. */ 3657 /* Find out the number of elements of each operand.
3536 if (VECTOR_MODE_P (mode00)) 3658 Since the concatenated result has a constant number
3537 { 3659 of elements, the operands must too. */
3538 elt_size = GET_MODE_UNIT_SIZE (mode00); 3660 n_elts00 = GET_MODE_NUNITS (mode00).to_constant ();
3539 n_elts00 = GET_MODE_SIZE (mode00) / elt_size; 3661 n_elts01 = GET_MODE_NUNITS (mode01).to_constant ();
3540 }
3541 else
3542 n_elts00 = 1;
3543
3544 if (VECTOR_MODE_P (mode01))
3545 {
3546 elt_size = GET_MODE_UNIT_SIZE (mode01);
3547 n_elts01 = GET_MODE_SIZE (mode01) / elt_size;
3548 }
3549 else
3550 n_elts01 = 1;
3551 3662
3552 gcc_assert (n_elts == n_elts00 + n_elts01); 3663 gcc_assert (n_elts == n_elts00 + n_elts01);
3553 3664
3554 /* Select correct operand of VEC_CONCAT 3665 /* Select correct operand of VEC_CONCAT
3555 and adjust selector. */ 3666 and adjust selector. */
3569 3680
3570 tmp = gen_rtx_fmt_ee (code, mode, 3681 tmp = gen_rtx_fmt_ee (code, mode,
3571 tmp_op, gen_rtx_PARALLEL (VOIDmode, vec)); 3682 tmp_op, gen_rtx_PARALLEL (VOIDmode, vec));
3572 return tmp; 3683 return tmp;
3573 } 3684 }
3574 if (GET_CODE (trueop0) == VEC_DUPLICATE
3575 && GET_MODE (XEXP (trueop0, 0)) == mode)
3576 return XEXP (trueop0, 0);
3577 } 3685 }
3578 else 3686 else
3579 { 3687 {
3580 gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); 3688 gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0)));
3581 gcc_assert (GET_MODE_INNER (mode) 3689 gcc_assert (GET_MODE_INNER (mode)
3582 == GET_MODE_INNER (GET_MODE (trueop0))); 3690 == GET_MODE_INNER (GET_MODE (trueop0)));
3583 gcc_assert (GET_CODE (trueop1) == PARALLEL); 3691 gcc_assert (GET_CODE (trueop1) == PARALLEL);
3584 3692
3693 if (vec_duplicate_p (trueop0, &elt0))
3694 /* It doesn't matter which elements are selected by trueop1,
3695 because they are all the same. */
3696 return gen_vec_duplicate (mode, elt0);
3697
3585 if (GET_CODE (trueop0) == CONST_VECTOR) 3698 if (GET_CODE (trueop0) == CONST_VECTOR)
3586 { 3699 {
3587 int elt_size = GET_MODE_UNIT_SIZE (mode); 3700 unsigned n_elts = XVECLEN (trueop1, 0);
3588 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
3589 rtvec v = rtvec_alloc (n_elts); 3701 rtvec v = rtvec_alloc (n_elts);
3590 unsigned int i; 3702 unsigned int i;
3591 3703
3592 gcc_assert (XVECLEN (trueop1, 0) == (int) n_elts); 3704 gcc_assert (known_eq (n_elts, GET_MODE_NUNITS (mode)));
3593 for (i = 0; i < n_elts; i++) 3705 for (i = 0; i < n_elts; i++)
3594 { 3706 {
3595 rtx x = XVECEXP (trueop1, 0, i); 3707 rtx x = XVECEXP (trueop1, 0, i);
3596 3708
3597 gcc_assert (CONST_INT_P (x)); 3709 if (!CONST_INT_P (x))
3710 return 0;
3711
3598 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, 3712 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0,
3599 INTVAL (x)); 3713 INTVAL (x));
3600 } 3714 }
3601 3715
3602 return gen_rtx_CONST_VECTOR (mode, v); 3716 return gen_rtx_CONST_VECTOR (mode, v);
3656 3770
3657 return simplify_gen_binary (VEC_CONCAT, mode, subop0, subop1); 3771 return simplify_gen_binary (VEC_CONCAT, mode, subop0, subop1);
3658 } 3772 }
3659 3773
3660 /* If we select one half of a vec_concat, return that. */ 3774 /* If we select one half of a vec_concat, return that. */
3775 int l0, l1;
3661 if (GET_CODE (trueop0) == VEC_CONCAT 3776 if (GET_CODE (trueop0) == VEC_CONCAT
3777 && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 0)))
3778 .is_constant (&l0))
3779 && (GET_MODE_NUNITS (GET_MODE (XEXP (trueop0, 1)))
3780 .is_constant (&l1))
3662 && CONST_INT_P (XVECEXP (trueop1, 0, 0))) 3781 && CONST_INT_P (XVECEXP (trueop1, 0, 0)))
3663 { 3782 {
3664 rtx subop0 = XEXP (trueop0, 0); 3783 rtx subop0 = XEXP (trueop0, 0);
3665 rtx subop1 = XEXP (trueop0, 1); 3784 rtx subop1 = XEXP (trueop0, 1);
3666 machine_mode mode0 = GET_MODE (subop0); 3785 machine_mode mode0 = GET_MODE (subop0);
3667 machine_mode mode1 = GET_MODE (subop1); 3786 machine_mode mode1 = GET_MODE (subop1);
3668 int li = GET_MODE_UNIT_SIZE (mode0);
3669 int l0 = GET_MODE_SIZE (mode0) / li;
3670 int l1 = GET_MODE_SIZE (mode1) / li;
3671 int i0 = INTVAL (XVECEXP (trueop1, 0, 0)); 3787 int i0 = INTVAL (XVECEXP (trueop1, 0, 0));
3672 if (i0 == 0 && !side_effects_p (op1) && mode == mode0) 3788 if (i0 == 0 && !side_effects_p (op1) && mode == mode0)
3673 { 3789 {
3674 bool success = true; 3790 bool success = true;
3675 for (int i = 1; i < l0; ++i) 3791 for (int i = 1; i < l0; ++i)
3705 if (XVECLEN (trueop1, 0) == 1 3821 if (XVECLEN (trueop1, 0) == 1
3706 && CONST_INT_P (XVECEXP (trueop1, 0, 0)) 3822 && CONST_INT_P (XVECEXP (trueop1, 0, 0))
3707 && GET_CODE (trueop0) == VEC_CONCAT) 3823 && GET_CODE (trueop0) == VEC_CONCAT)
3708 { 3824 {
3709 rtx vec = trueop0; 3825 rtx vec = trueop0;
3710 int offset = INTVAL (XVECEXP (trueop1, 0, 0)) * GET_MODE_SIZE (mode); 3826 offset = INTVAL (XVECEXP (trueop1, 0, 0)) * GET_MODE_SIZE (mode);
3711 3827
3712 /* Try to find the element in the VEC_CONCAT. */ 3828 /* Try to find the element in the VEC_CONCAT. */
3713 while (GET_MODE (vec) != mode 3829 while (GET_MODE (vec) != mode
3714 && GET_CODE (vec) == VEC_CONCAT) 3830 && GET_CODE (vec) == VEC_CONCAT)
3715 { 3831 {
3716 HOST_WIDE_INT vec_size; 3832 poly_int64 vec_size;
3717 3833
3718 if (CONST_INT_P (XEXP (vec, 0))) 3834 if (CONST_INT_P (XEXP (vec, 0)))
3719 { 3835 {
3720 /* vec_concat of two const_ints doesn't make sense with 3836 /* vec_concat of two const_ints doesn't make sense with
3721 respect to modes. */ 3837 respect to modes. */
3726 - GET_MODE_SIZE (GET_MODE (XEXP (vec, 1))); 3842 - GET_MODE_SIZE (GET_MODE (XEXP (vec, 1)));
3727 } 3843 }
3728 else 3844 else
3729 vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0))); 3845 vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0)));
3730 3846
3731 if (offset < vec_size) 3847 if (known_lt (offset, vec_size))
3732 vec = XEXP (vec, 0); 3848 vec = XEXP (vec, 0);
3733 else 3849 else if (known_ge (offset, vec_size))
3734 { 3850 {
3735 offset -= vec_size; 3851 offset -= vec_size;
3736 vec = XEXP (vec, 1); 3852 vec = XEXP (vec, 1);
3737 } 3853 }
3854 else
3855 break;
3738 vec = avoid_constant_pool_reference (vec); 3856 vec = avoid_constant_pool_reference (vec);
3739 } 3857 }
3740 3858
3741 if (GET_MODE (vec) == mode) 3859 if (GET_MODE (vec) == mode)
3742 return vec; 3860 return vec;
3772 if (GET_CODE (trueop0) == VEC_SELECT 3890 if (GET_CODE (trueop0) == VEC_SELECT
3773 && GET_MODE (XEXP (trueop0, 0)) == mode) 3891 && GET_MODE (XEXP (trueop0, 0)) == mode)
3774 { 3892 {
3775 rtx op0_subop1 = XEXP (trueop0, 1); 3893 rtx op0_subop1 = XEXP (trueop0, 1);
3776 gcc_assert (GET_CODE (op0_subop1) == PARALLEL); 3894 gcc_assert (GET_CODE (op0_subop1) == PARALLEL);
3777 gcc_assert (XVECLEN (trueop1, 0) == GET_MODE_NUNITS (mode)); 3895 gcc_assert (known_eq (XVECLEN (trueop1, 0), GET_MODE_NUNITS (mode)));
3778 3896
3779 /* Apply the outer ordering vector to the inner one. (The inner 3897 /* Apply the outer ordering vector to the inner one. (The inner
3780 ordering vector is expressly permitted to be of a different 3898 ordering vector is expressly permitted to be of a different
3781 length than the outer one.) If the result is { 0, 1, ..., n-1 } 3899 length than the outer one.) If the result is { 0, 1, ..., n-1 }
3782 then the two VEC_SELECTs cancel. */ 3900 then the two VEC_SELECTs cancel. */
3801 machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode 3919 machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode
3802 ? GET_MODE (trueop1) 3920 ? GET_MODE (trueop1)
3803 : GET_MODE_INNER (mode)); 3921 : GET_MODE_INNER (mode));
3804 3922
3805 gcc_assert (VECTOR_MODE_P (mode)); 3923 gcc_assert (VECTOR_MODE_P (mode));
3806 gcc_assert (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode) 3924 gcc_assert (known_eq (GET_MODE_SIZE (op0_mode)
3807 == GET_MODE_SIZE (mode)); 3925 + GET_MODE_SIZE (op1_mode),
3926 GET_MODE_SIZE (mode)));
3808 3927
3809 if (VECTOR_MODE_P (op0_mode)) 3928 if (VECTOR_MODE_P (op0_mode))
3810 gcc_assert (GET_MODE_INNER (mode) 3929 gcc_assert (GET_MODE_INNER (mode)
3811 == GET_MODE_INNER (op0_mode)); 3930 == GET_MODE_INNER (op0_mode));
3812 else 3931 else
3816 gcc_assert (GET_MODE_INNER (mode) 3935 gcc_assert (GET_MODE_INNER (mode)
3817 == GET_MODE_INNER (op1_mode)); 3936 == GET_MODE_INNER (op1_mode));
3818 else 3937 else
3819 gcc_assert (GET_MODE_INNER (mode) == op1_mode); 3938 gcc_assert (GET_MODE_INNER (mode) == op1_mode);
3820 3939
3940 unsigned int n_elts, in_n_elts;
3821 if ((GET_CODE (trueop0) == CONST_VECTOR 3941 if ((GET_CODE (trueop0) == CONST_VECTOR
3822 || CONST_SCALAR_INT_P (trueop0) 3942 || CONST_SCALAR_INT_P (trueop0)
3823 || CONST_DOUBLE_AS_FLOAT_P (trueop0)) 3943 || CONST_DOUBLE_AS_FLOAT_P (trueop0))
3824 && (GET_CODE (trueop1) == CONST_VECTOR 3944 && (GET_CODE (trueop1) == CONST_VECTOR
3825 || CONST_SCALAR_INT_P (trueop1) 3945 || CONST_SCALAR_INT_P (trueop1)
3826 || CONST_DOUBLE_AS_FLOAT_P (trueop1))) 3946 || CONST_DOUBLE_AS_FLOAT_P (trueop1))
3947 && GET_MODE_NUNITS (mode).is_constant (&n_elts)
3948 && GET_MODE_NUNITS (op0_mode).is_constant (&in_n_elts))
3827 { 3949 {
3828 int elt_size = GET_MODE_UNIT_SIZE (mode);
3829 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
3830 rtvec v = rtvec_alloc (n_elts); 3950 rtvec v = rtvec_alloc (n_elts);
3831 unsigned int i; 3951 unsigned int i;
3832 unsigned in_n_elts = 1;
3833
3834 if (VECTOR_MODE_P (op0_mode))
3835 in_n_elts = (GET_MODE_SIZE (op0_mode) / elt_size);
3836 for (i = 0; i < n_elts; i++) 3952 for (i = 0; i < n_elts; i++)
3837 { 3953 {
3838 if (i < in_n_elts) 3954 if (i < in_n_elts)
3839 { 3955 {
3840 if (!VECTOR_MODE_P (op0_mode)) 3956 if (!VECTOR_MODE_P (op0_mode))
3880 3996
3881 default: 3997 default:
3882 gcc_unreachable (); 3998 gcc_unreachable ();
3883 } 3999 }
3884 4000
4001 if (mode == GET_MODE (op0)
4002 && mode == GET_MODE (op1)
4003 && vec_duplicate_p (op0, &elt0)
4004 && vec_duplicate_p (op1, &elt1))
4005 {
4006 /* Try applying the operator to ELT and see if that simplifies.
4007 We can duplicate the result if so.
4008
4009 The reason we don't use simplify_gen_binary is that it isn't
4010 necessarily a win to convert things like:
4011
4012 (plus:V (vec_duplicate:V (reg:S R1))
4013 (vec_duplicate:V (reg:S R2)))
4014
4015 to:
4016
4017 (vec_duplicate:V (plus:S (reg:S R1) (reg:S R2)))
4018
4019 The first might be done entirely in vector registers while the
4020 second might need a move between register files. */
4021 tem = simplify_binary_operation (code, GET_MODE_INNER (mode),
4022 elt0, elt1);
4023 if (tem)
4024 return gen_vec_duplicate (mode, tem);
4025 }
4026
3885 return 0; 4027 return 0;
3886 } 4028 }
3887 4029
3888 rtx 4030 rtx
3889 simplify_const_binary_operation (enum rtx_code code, machine_mode mode, 4031 simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
3892 if (VECTOR_MODE_P (mode) 4034 if (VECTOR_MODE_P (mode)
3893 && code != VEC_CONCAT 4035 && code != VEC_CONCAT
3894 && GET_CODE (op0) == CONST_VECTOR 4036 && GET_CODE (op0) == CONST_VECTOR
3895 && GET_CODE (op1) == CONST_VECTOR) 4037 && GET_CODE (op1) == CONST_VECTOR)
3896 { 4038 {
3897 unsigned n_elts = GET_MODE_NUNITS (mode); 4039 unsigned int n_elts;
3898 machine_mode op0mode = GET_MODE (op0); 4040 if (!CONST_VECTOR_NUNITS (op0).is_constant (&n_elts))
3899 unsigned op0_n_elts = GET_MODE_NUNITS (op0mode); 4041 return NULL_RTX;
3900 machine_mode op1mode = GET_MODE (op1); 4042
3901 unsigned op1_n_elts = GET_MODE_NUNITS (op1mode); 4043 gcc_assert (known_eq (n_elts, CONST_VECTOR_NUNITS (op1)));
4044 gcc_assert (known_eq (n_elts, GET_MODE_NUNITS (mode)));
3902 rtvec v = rtvec_alloc (n_elts); 4045 rtvec v = rtvec_alloc (n_elts);
3903 unsigned int i; 4046 unsigned int i;
3904 4047
3905 gcc_assert (op0_n_elts == n_elts);
3906 gcc_assert (op1_n_elts == n_elts);
3907 for (i = 0; i < n_elts; i++) 4048 for (i = 0; i < n_elts; i++)
3908 { 4049 {
3909 rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), 4050 rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode),
3910 CONST_VECTOR_ELT (op0, i), 4051 CONST_VECTOR_ELT (op0, i),
3911 CONST_VECTOR_ELT (op1, i)); 4052 CONST_VECTOR_ELT (op1, i));
3912 if (!x) 4053 if (!x || !valid_for_const_vector_p (mode, x))
3913 return 0; 4054 return 0;
3914 RTVEC_ELT (v, i) = x; 4055 RTVEC_ELT (v, i) = x;
3915 } 4056 }
3916 4057
3917 return gen_rtx_CONST_VECTOR (mode, v); 4058 return gen_rtx_CONST_VECTOR (mode, v);
3918 } 4059 }
3919 4060
3920 if (VECTOR_MODE_P (mode) 4061 if (VECTOR_MODE_P (mode)
3921 && code == VEC_CONCAT 4062 && code == VEC_CONCAT
3922 && (CONST_SCALAR_INT_P (op0) 4063 && (CONST_SCALAR_INT_P (op0)
3923 || GET_CODE (op0) == CONST_FIXED 4064 || CONST_FIXED_P (op0)
3924 || CONST_DOUBLE_AS_FLOAT_P (op0)) 4065 || CONST_DOUBLE_AS_FLOAT_P (op0))
3925 && (CONST_SCALAR_INT_P (op1) 4066 && (CONST_SCALAR_INT_P (op1)
3926 || CONST_DOUBLE_AS_FLOAT_P (op1) 4067 || CONST_DOUBLE_AS_FLOAT_P (op1)
3927 || GET_CODE (op1) == CONST_FIXED)) 4068 || CONST_FIXED_P (op1)))
3928 { 4069 {
3929 unsigned n_elts = GET_MODE_NUNITS (mode); 4070 /* Both inputs have a constant number of elements, so the result
4071 must too. */
4072 unsigned n_elts = GET_MODE_NUNITS (mode).to_constant ();
3930 rtvec v = rtvec_alloc (n_elts); 4073 rtvec v = rtvec_alloc (n_elts);
3931 4074
3932 gcc_assert (n_elts >= 2); 4075 gcc_assert (n_elts >= 2);
3933 if (n_elts == 2) 4076 if (n_elts == 2)
3934 { 4077 {
3938 RTVEC_ELT (v, 0) = op0; 4081 RTVEC_ELT (v, 0) = op0;
3939 RTVEC_ELT (v, 1) = op1; 4082 RTVEC_ELT (v, 1) = op1;
3940 } 4083 }
3941 else 4084 else
3942 { 4085 {
3943 unsigned op0_n_elts = GET_MODE_NUNITS (GET_MODE (op0)); 4086 unsigned op0_n_elts = GET_MODE_NUNITS (GET_MODE (op0)).to_constant ();
3944 unsigned op1_n_elts = GET_MODE_NUNITS (GET_MODE (op1)); 4087 unsigned op1_n_elts = GET_MODE_NUNITS (GET_MODE (op1)).to_constant ();
3945 unsigned i; 4088 unsigned i;
3946 4089
3947 gcc_assert (GET_CODE (op0) == CONST_VECTOR); 4090 gcc_assert (GET_CODE (op0) == CONST_VECTOR);
3948 gcc_assert (GET_CODE (op1) == CONST_VECTOR); 4091 gcc_assert (GET_CODE (op1) == CONST_VECTOR);
3949 gcc_assert (op0_n_elts + op1_n_elts == n_elts); 4092 gcc_assert (op0_n_elts + op1_n_elts == n_elts);
3950 4093
3951 for (i = 0; i < op0_n_elts; ++i) 4094 for (i = 0; i < op0_n_elts; ++i)
3952 RTVEC_ELT (v, i) = XVECEXP (op0, 0, i); 4095 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op0, i);
3953 for (i = 0; i < op1_n_elts; ++i) 4096 for (i = 0; i < op1_n_elts; ++i)
3954 RTVEC_ELT (v, op0_n_elts+i) = XVECEXP (op1, 0, i); 4097 RTVEC_ELT (v, op0_n_elts+i) = CONST_VECTOR_ELT (op1, i);
3955 } 4098 }
3956 4099
3957 return gen_rtx_CONST_VECTOR (mode, v); 4100 return gen_rtx_CONST_VECTOR (mode, v);
3958 } 4101 }
3959 4102
4086 if (is_a <scalar_int_mode> (mode, &int_mode) 4229 if (is_a <scalar_int_mode> (mode, &int_mode)
4087 && CONST_SCALAR_INT_P (op0) 4230 && CONST_SCALAR_INT_P (op0)
4088 && CONST_SCALAR_INT_P (op1)) 4231 && CONST_SCALAR_INT_P (op1))
4089 { 4232 {
4090 wide_int result; 4233 wide_int result;
4091 bool overflow; 4234 wi::overflow_type overflow;
4092 rtx_mode_t pop0 = rtx_mode_t (op0, int_mode); 4235 rtx_mode_t pop0 = rtx_mode_t (op0, int_mode);
4093 rtx_mode_t pop1 = rtx_mode_t (op1, int_mode); 4236 rtx_mode_t pop1 = rtx_mode_t (op1, int_mode);
4094 4237
4095 #if TARGET_SUPPORTS_WIDE_INT == 0 4238 #if TARGET_SUPPORTS_WIDE_INT == 0
4096 /* This assert keeps the simplification from producing a result 4239 /* This assert keeps the simplification from producing a result
4215 default: 4358 default:
4216 gcc_unreachable (); 4359 gcc_unreachable ();
4217 } 4360 }
4218 break; 4361 break;
4219 } 4362 }
4363 default:
4364 return NULL_RTX;
4365 }
4366 return immed_wide_int_const (result, int_mode);
4367 }
4368
4369 /* Handle polynomial integers. */
4370 if (NUM_POLY_INT_COEFFS > 1
4371 && is_a <scalar_int_mode> (mode, &int_mode)
4372 && poly_int_rtx_p (op0)
4373 && poly_int_rtx_p (op1))
4374 {
4375 poly_wide_int result;
4376 switch (code)
4377 {
4378 case PLUS:
4379 result = wi::to_poly_wide (op0, mode) + wi::to_poly_wide (op1, mode);
4380 break;
4381
4382 case MINUS:
4383 result = wi::to_poly_wide (op0, mode) - wi::to_poly_wide (op1, mode);
4384 break;
4385
4386 case MULT:
4387 if (CONST_SCALAR_INT_P (op1))
4388 result = wi::to_poly_wide (op0, mode) * rtx_mode_t (op1, mode);
4389 else
4390 return NULL_RTX;
4391 break;
4392
4393 case ASHIFT:
4394 if (CONST_SCALAR_INT_P (op1))
4395 {
4396 wide_int shift = rtx_mode_t (op1, mode);
4397 if (SHIFT_COUNT_TRUNCATED)
4398 shift = wi::umod_trunc (shift, GET_MODE_PRECISION (int_mode));
4399 else if (wi::geu_p (shift, GET_MODE_PRECISION (int_mode)))
4400 return NULL_RTX;
4401 result = wi::to_poly_wide (op0, mode) << shift;
4402 }
4403 else
4404 return NULL_RTX;
4405 break;
4406
4407 case IOR:
4408 if (!CONST_SCALAR_INT_P (op1)
4409 || !can_ior_p (wi::to_poly_wide (op0, mode),
4410 rtx_mode_t (op1, mode), &result))
4411 return NULL_RTX;
4412 break;
4413
4220 default: 4414 default:
4221 return NULL_RTX; 4415 return NULL_RTX;
4222 } 4416 }
4223 return immed_wide_int_const (result, int_mode); 4417 return immed_wide_int_const (result, int_mode);
4224 } 4418 }
4634 { 4828 {
4635 if (tem == const0_rtx) 4829 if (tem == const0_rtx)
4636 return CONST0_RTX (mode); 4830 return CONST0_RTX (mode);
4637 #ifdef VECTOR_STORE_FLAG_VALUE 4831 #ifdef VECTOR_STORE_FLAG_VALUE
4638 { 4832 {
4639 int i, units;
4640 rtvec v;
4641
4642 rtx val = VECTOR_STORE_FLAG_VALUE (mode); 4833 rtx val = VECTOR_STORE_FLAG_VALUE (mode);
4643 if (val == NULL_RTX) 4834 if (val == NULL_RTX)
4644 return NULL_RTX; 4835 return NULL_RTX;
4645 if (val == const1_rtx) 4836 if (val == const1_rtx)
4646 return CONST1_RTX (mode); 4837 return CONST1_RTX (mode);
4647 4838
4648 units = GET_MODE_NUNITS (mode); 4839 return gen_const_vec_duplicate (mode, val);
4649 v = rtvec_alloc (units);
4650 for (i = 0; i < units; i++)
4651 RTVEC_ELT (v, i) = val;
4652 return gen_rtx_raw_CONST_VECTOR (mode, v);
4653 } 4840 }
4654 #else 4841 #else
4655 return NULL_RTX; 4842 return NULL_RTX;
4656 #endif 4843 #endif
4657 } 4844 }
4864 && CONST_SCALAR_INT_P (XEXP (op0, 1))) 5051 && CONST_SCALAR_INT_P (XEXP (op0, 1)))
4865 return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), 5052 return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0),
4866 simplify_gen_binary (XOR, cmp_mode, 5053 simplify_gen_binary (XOR, cmp_mode,
4867 XEXP (op0, 1), op1)); 5054 XEXP (op0, 1), op1));
4868 5055
4869 /* (eq/ne (and x y) x) simplifies to (eq/ne (and (not y) x) 0), which 5056 /* Simplify eq/ne (and/ior x y) x/y) for targets with a BICS instruction or
4870 can be implemented with a BICS instruction on some targets, or 5057 constant folding if x/y is a constant. */
4871 constant-folded if y is a constant. */
4872 if ((code == EQ || code == NE) 5058 if ((code == EQ || code == NE)
4873 && op0code == AND 5059 && (op0code == AND || op0code == IOR)
4874 && rtx_equal_p (XEXP (op0, 0), op1)
4875 && !side_effects_p (op1) 5060 && !side_effects_p (op1)
4876 && op1 != CONST0_RTX (cmp_mode)) 5061 && op1 != CONST0_RTX (cmp_mode))
4877 { 5062 {
4878 rtx not_y = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 1), cmp_mode); 5063 /* Both (eq/ne (and x y) x) and (eq/ne (ior x y) y) simplify to
4879 rtx lhs = simplify_gen_binary (AND, cmp_mode, not_y, XEXP (op0, 0)); 5064 (eq/ne (and (not y) x) 0). */
4880 5065 if ((op0code == AND && rtx_equal_p (XEXP (op0, 0), op1))
4881 return simplify_gen_relational (code, mode, cmp_mode, lhs, 5066 || (op0code == IOR && rtx_equal_p (XEXP (op0, 1), op1)))
4882 CONST0_RTX (cmp_mode)); 5067 {
4883 } 5068 rtx not_y = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 1),
4884 5069 cmp_mode);
4885 /* Likewise for (eq/ne (and x y) y). */ 5070 rtx lhs = simplify_gen_binary (AND, cmp_mode, not_y, XEXP (op0, 0));
4886 if ((code == EQ || code == NE) 5071
4887 && op0code == AND 5072 return simplify_gen_relational (code, mode, cmp_mode, lhs,
4888 && rtx_equal_p (XEXP (op0, 1), op1) 5073 CONST0_RTX (cmp_mode));
4889 && !side_effects_p (op1) 5074 }
4890 && op1 != CONST0_RTX (cmp_mode)) 5075
4891 { 5076 /* Both (eq/ne (and x y) y) and (eq/ne (ior x y) x) simplify to
4892 rtx not_x = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 0), cmp_mode); 5077 (eq/ne (and (not x) y) 0). */
4893 rtx lhs = simplify_gen_binary (AND, cmp_mode, not_x, XEXP (op0, 1)); 5078 if ((op0code == AND && rtx_equal_p (XEXP (op0, 1), op1))
4894 5079 || (op0code == IOR && rtx_equal_p (XEXP (op0, 0), op1)))
4895 return simplify_gen_relational (code, mode, cmp_mode, lhs, 5080 {
4896 CONST0_RTX (cmp_mode)); 5081 rtx not_x = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 0),
5082 cmp_mode);
5083 rtx lhs = simplify_gen_binary (AND, cmp_mode, not_x, XEXP (op0, 1));
5084
5085 return simplify_gen_relational (code, mode, cmp_mode, lhs,
5086 CONST0_RTX (cmp_mode));
5087 }
4897 } 5088 }
4898 5089
4899 /* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped. */ 5090 /* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped. */
4900 if ((code == EQ || code == NE) 5091 if ((code == EQ || code == NE)
4901 && GET_CODE (op0) == BSWAP 5092 && GET_CODE (op0) == BSWAP
5056 5247
5057 if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx 5248 if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
5058 && (code == EQ || code == NE) 5249 && (code == EQ || code == NE)
5059 && ! ((REG_P (op0) || CONST_INT_P (trueop0)) 5250 && ! ((REG_P (op0) || CONST_INT_P (trueop0))
5060 && (REG_P (op1) || CONST_INT_P (trueop1))) 5251 && (REG_P (op1) || CONST_INT_P (trueop1)))
5061 && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1)) 5252 && (tem = simplify_binary_operation (MINUS, mode, op0, op1)) != 0
5062 /* We cannot do this if tem is a nonzero address. */ 5253 /* We cannot do this if tem is a nonzero address. */
5063 && ! nonzero_address_p (tem)) 5254 && ! nonzero_address_p (tem))
5064 return simplify_const_relational_operation (signed_condition (code), 5255 return simplify_const_relational_operation (signed_condition (code),
5065 mode, tem, const0_rtx); 5256 mode, tem, const0_rtx);
5066 5257
5385 return on_nonzero; 5576 return on_nonzero;
5386 5577
5387 return NULL_RTX; 5578 return NULL_RTX;
5388 } 5579 }
5389 5580
5581 /* Try to simplify X given that it appears within operand OP of a
5582 VEC_MERGE operation whose mask is MASK. X need not use the same
5583 vector mode as the VEC_MERGE, but it must have the same number of
5584 elements.
5585
5586 Return the simplified X on success, otherwise return NULL_RTX. */
5587
5588 rtx
5589 simplify_merge_mask (rtx x, rtx mask, int op)
5590 {
5591 gcc_assert (VECTOR_MODE_P (GET_MODE (x)));
5592 poly_uint64 nunits = GET_MODE_NUNITS (GET_MODE (x));
5593 if (GET_CODE (x) == VEC_MERGE && rtx_equal_p (XEXP (x, 2), mask))
5594 {
5595 if (side_effects_p (XEXP (x, 1 - op)))
5596 return NULL_RTX;
5597
5598 return XEXP (x, op);
5599 }
5600 if (UNARY_P (x)
5601 && VECTOR_MODE_P (GET_MODE (XEXP (x, 0)))
5602 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits))
5603 {
5604 rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op);
5605 if (top0)
5606 return simplify_gen_unary (GET_CODE (x), GET_MODE (x), top0,
5607 GET_MODE (XEXP (x, 0)));
5608 }
5609 if (BINARY_P (x)
5610 && VECTOR_MODE_P (GET_MODE (XEXP (x, 0)))
5611 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits)
5612 && VECTOR_MODE_P (GET_MODE (XEXP (x, 1)))
5613 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 1))), nunits))
5614 {
5615 rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op);
5616 rtx top1 = simplify_merge_mask (XEXP (x, 1), mask, op);
5617 if (top0 || top1)
5618 return simplify_gen_binary (GET_CODE (x), GET_MODE (x),
5619 top0 ? top0 : XEXP (x, 0),
5620 top1 ? top1 : XEXP (x, 1));
5621 }
5622 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY
5623 && VECTOR_MODE_P (GET_MODE (XEXP (x, 0)))
5624 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits)
5625 && VECTOR_MODE_P (GET_MODE (XEXP (x, 1)))
5626 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 1))), nunits)
5627 && VECTOR_MODE_P (GET_MODE (XEXP (x, 2)))
5628 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 2))), nunits))
5629 {
5630 rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op);
5631 rtx top1 = simplify_merge_mask (XEXP (x, 1), mask, op);
5632 rtx top2 = simplify_merge_mask (XEXP (x, 2), mask, op);
5633 if (top0 || top1 || top2)
5634 return simplify_gen_ternary (GET_CODE (x), GET_MODE (x),
5635 GET_MODE (XEXP (x, 0)),
5636 top0 ? top0 : XEXP (x, 0),
5637 top1 ? top1 : XEXP (x, 1),
5638 top2 ? top2 : XEXP (x, 2));
5639 }
5640 return NULL_RTX;
5641 }
5642
5390 5643
5391 /* Simplify CODE, an operation with result mode MODE and three operands, 5644 /* Simplify CODE, an operation with result mode MODE and three operands,
5392 OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became 5645 OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became
5393 a constant. Return 0 if no simplifications is possible. */ 5646 a constant. Return 0 if no simplifications is possible. */
5394 5647
5398 rtx op2) 5651 rtx op2)
5399 { 5652 {
5400 bool any_change = false; 5653 bool any_change = false;
5401 rtx tem, trueop2; 5654 rtx tem, trueop2;
5402 scalar_int_mode int_mode, int_op0_mode; 5655 scalar_int_mode int_mode, int_op0_mode;
5656 unsigned int n_elts;
5403 5657
5404 switch (code) 5658 switch (code)
5405 { 5659 {
5406 case FMA: 5660 case FMA:
5407 /* Simplify negations around the multiplication. */ 5661 /* Simplify negations around the multiplication. */
5500 && GET_CODE (op0) == NE 5754 && GET_CODE (op0) == NE
5501 && GET_CODE (XEXP (op0, 0)) == NOT 5755 && GET_CODE (XEXP (op0, 0)) == NOT
5502 && GET_CODE (XEXP (op0, 1)) == CONST_VECTOR) 5756 && GET_CODE (XEXP (op0, 1)) == CONST_VECTOR)
5503 { 5757 {
5504 rtx cv = XEXP (op0, 1); 5758 rtx cv = XEXP (op0, 1);
5505 int nunits = CONST_VECTOR_NUNITS (cv); 5759 int nunits;
5506 bool ok = true; 5760 bool ok = true;
5507 for (int i = 0; i < nunits; ++i) 5761 if (!CONST_VECTOR_NUNITS (cv).is_constant (&nunits))
5508 if (CONST_VECTOR_ELT (cv, i) != const0_rtx) 5762 ok = false;
5509 { 5763 else
5510 ok = false; 5764 for (int i = 0; i < nunits; ++i)
5511 break; 5765 if (CONST_VECTOR_ELT (cv, i) != const0_rtx)
5512 } 5766 {
5767 ok = false;
5768 break;
5769 }
5513 if (ok) 5770 if (ok)
5514 { 5771 {
5515 rtx new_op0 = gen_rtx_NE (GET_MODE (op0), 5772 rtx new_op0 = gen_rtx_NE (GET_MODE (op0),
5516 XEXP (XEXP (op0, 0), 0), 5773 XEXP (XEXP (op0, 0), 0),
5517 XEXP (op0, 1)); 5774 XEXP (op0, 1));
5561 5818
5562 return simplify_gen_relational (code, mode, cmp_mode, 5819 return simplify_gen_relational (code, mode, cmp_mode,
5563 XEXP (op0, 0), XEXP (op0, 1)); 5820 XEXP (op0, 0), XEXP (op0, 1));
5564 } 5821 }
5565 5822
5566 if (cmp_mode == VOIDmode)
5567 cmp_mode = op0_mode;
5568 temp = simplify_relational_operation (GET_CODE (op0), op0_mode, 5823 temp = simplify_relational_operation (GET_CODE (op0), op0_mode,
5569 cmp_mode, XEXP (op0, 0), 5824 cmp_mode, XEXP (op0, 0),
5570 XEXP (op0, 1)); 5825 XEXP (op0, 1));
5571 5826
5572 /* See if any simplifications were possible. */ 5827 /* See if any simplifications were possible. */
5583 case VEC_MERGE: 5838 case VEC_MERGE:
5584 gcc_assert (GET_MODE (op0) == mode); 5839 gcc_assert (GET_MODE (op0) == mode);
5585 gcc_assert (GET_MODE (op1) == mode); 5840 gcc_assert (GET_MODE (op1) == mode);
5586 gcc_assert (VECTOR_MODE_P (mode)); 5841 gcc_assert (VECTOR_MODE_P (mode));
5587 trueop2 = avoid_constant_pool_reference (op2); 5842 trueop2 = avoid_constant_pool_reference (op2);
5588 if (CONST_INT_P (trueop2)) 5843 if (CONST_INT_P (trueop2)
5589 { 5844 && GET_MODE_NUNITS (mode).is_constant (&n_elts))
5590 int elt_size = GET_MODE_UNIT_SIZE (mode); 5845 {
5591 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
5592 unsigned HOST_WIDE_INT sel = UINTVAL (trueop2); 5846 unsigned HOST_WIDE_INT sel = UINTVAL (trueop2);
5593 unsigned HOST_WIDE_INT mask; 5847 unsigned HOST_WIDE_INT mask;
5594 if (n_elts == HOST_BITS_PER_WIDE_INT) 5848 if (n_elts == HOST_BITS_PER_WIDE_INT)
5595 mask = -1; 5849 mask = -1;
5596 else 5850 else
5650 /* Replace (vec_merge (vec_duplicate (vec_select a parallel (i))) a 1 << i) 5904 /* Replace (vec_merge (vec_duplicate (vec_select a parallel (i))) a 1 << i)
5651 with a. */ 5905 with a. */
5652 if (GET_CODE (op0) == VEC_DUPLICATE 5906 if (GET_CODE (op0) == VEC_DUPLICATE
5653 && GET_CODE (XEXP (op0, 0)) == VEC_SELECT 5907 && GET_CODE (XEXP (op0, 0)) == VEC_SELECT
5654 && GET_CODE (XEXP (XEXP (op0, 0), 1)) == PARALLEL 5908 && GET_CODE (XEXP (XEXP (op0, 0), 1)) == PARALLEL
5655 && mode_nunits[GET_MODE (XEXP (op0, 0))] == 1) 5909 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (op0, 0))), 1))
5656 { 5910 {
5657 tem = XVECEXP ((XEXP (XEXP (op0, 0), 1)), 0, 0); 5911 tem = XVECEXP ((XEXP (XEXP (op0, 0), 1)), 0, 0);
5658 if (CONST_INT_P (tem) && CONST_INT_P (op2)) 5912 if (CONST_INT_P (tem) && CONST_INT_P (op2))
5659 { 5913 {
5660 if (XEXP (XEXP (op0, 0), 0) == op1 5914 if (XEXP (XEXP (op0, 0), 0) == op1
5661 && UINTVAL (op2) == HOST_WIDE_INT_1U << UINTVAL (tem)) 5915 && UINTVAL (op2) == HOST_WIDE_INT_1U << UINTVAL (tem))
5662 return op1; 5916 return op1;
5663 } 5917 }
5664 } 5918 }
5919 /* Replace (vec_merge (vec_duplicate (X)) (const_vector [A, B])
5920 (const_int N))
5921 with (vec_concat (X) (B)) if N == 1 or
5922 (vec_concat (A) (X)) if N == 2. */
5923 if (GET_CODE (op0) == VEC_DUPLICATE
5924 && GET_CODE (op1) == CONST_VECTOR
5925 && known_eq (CONST_VECTOR_NUNITS (op1), 2)
5926 && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2)
5927 && IN_RANGE (sel, 1, 2))
5928 {
5929 rtx newop0 = XEXP (op0, 0);
5930 rtx newop1 = CONST_VECTOR_ELT (op1, 2 - sel);
5931 if (sel == 2)
5932 std::swap (newop0, newop1);
5933 return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1);
5934 }
5935 /* Replace (vec_merge (vec_duplicate x) (vec_concat (y) (z)) (const_int N))
5936 with (vec_concat x z) if N == 1, or (vec_concat y x) if N == 2.
5937 Only applies for vectors of two elements. */
5938 if (GET_CODE (op0) == VEC_DUPLICATE
5939 && GET_CODE (op1) == VEC_CONCAT
5940 && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2)
5941 && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2)
5942 && IN_RANGE (sel, 1, 2))
5943 {
5944 rtx newop0 = XEXP (op0, 0);
5945 rtx newop1 = XEXP (op1, 2 - sel);
5946 rtx otherop = XEXP (op1, sel - 1);
5947 if (sel == 2)
5948 std::swap (newop0, newop1);
5949 /* Don't want to throw away the other part of the vec_concat if
5950 it has side-effects. */
5951 if (!side_effects_p (otherop))
5952 return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1);
5953 }
5954
5955 /* Replace:
5956
5957 (vec_merge:outer (vec_duplicate:outer x:inner)
5958 (subreg:outer y:inner 0)
5959 (const_int N))
5960
5961 with (vec_concat:outer x:inner y:inner) if N == 1,
5962 or (vec_concat:outer y:inner x:inner) if N == 2.
5963
5964 Implicitly, this means we have a paradoxical subreg, but such
5965 a check is cheap, so make it anyway.
5966
5967 Only applies for vectors of two elements. */
5968 if (GET_CODE (op0) == VEC_DUPLICATE
5969 && GET_CODE (op1) == SUBREG
5970 && GET_MODE (op1) == GET_MODE (op0)
5971 && GET_MODE (SUBREG_REG (op1)) == GET_MODE (XEXP (op0, 0))
5972 && paradoxical_subreg_p (op1)
5973 && subreg_lowpart_p (op1)
5974 && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2)
5975 && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2)
5976 && IN_RANGE (sel, 1, 2))
5977 {
5978 rtx newop0 = XEXP (op0, 0);
5979 rtx newop1 = SUBREG_REG (op1);
5980 if (sel == 2)
5981 std::swap (newop0, newop1);
5982 return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1);
5983 }
5984
5985 /* Same as above but with switched operands:
5986 Replace (vec_merge:outer (subreg:outer x:inner 0)
5987 (vec_duplicate:outer y:inner)
5988 (const_int N))
5989
5990 with (vec_concat:outer x:inner y:inner) if N == 1,
5991 or (vec_concat:outer y:inner x:inner) if N == 2. */
5992 if (GET_CODE (op1) == VEC_DUPLICATE
5993 && GET_CODE (op0) == SUBREG
5994 && GET_MODE (op0) == GET_MODE (op1)
5995 && GET_MODE (SUBREG_REG (op0)) == GET_MODE (XEXP (op1, 0))
5996 && paradoxical_subreg_p (op0)
5997 && subreg_lowpart_p (op0)
5998 && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2)
5999 && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2)
6000 && IN_RANGE (sel, 1, 2))
6001 {
6002 rtx newop0 = SUBREG_REG (op0);
6003 rtx newop1 = XEXP (op1, 0);
6004 if (sel == 2)
6005 std::swap (newop0, newop1);
6006 return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1);
6007 }
6008
6009 /* Replace (vec_merge (vec_duplicate x) (vec_duplicate y)
6010 (const_int n))
6011 with (vec_concat x y) or (vec_concat y x) depending on value
6012 of N. */
6013 if (GET_CODE (op0) == VEC_DUPLICATE
6014 && GET_CODE (op1) == VEC_DUPLICATE
6015 && known_eq (GET_MODE_NUNITS (GET_MODE (op0)), 2)
6016 && known_eq (GET_MODE_NUNITS (GET_MODE (op1)), 2)
6017 && IN_RANGE (sel, 1, 2))
6018 {
6019 rtx newop0 = XEXP (op0, 0);
6020 rtx newop1 = XEXP (op1, 0);
6021 if (sel == 2)
6022 std::swap (newop0, newop1);
6023
6024 return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1);
6025 }
5665 } 6026 }
5666 6027
5667 if (rtx_equal_p (op0, op1) 6028 if (rtx_equal_p (op0, op1)
5668 && !side_effects_p (op2) && !side_effects_p (op1)) 6029 && !side_effects_p (op2) && !side_effects_p (op1))
5669 return op0; 6030 return op0;
5670 6031
6032 if (!side_effects_p (op2))
6033 {
6034 rtx top0 = simplify_merge_mask (op0, op2, 0);
6035 rtx top1 = simplify_merge_mask (op1, op2, 1);
6036 if (top0 || top1)
6037 return simplify_gen_ternary (code, mode, mode,
6038 top0 ? top0 : op0,
6039 top1 ? top1 : op1, op2);
6040 }
6041
5671 break; 6042 break;
5672 6043
5673 default: 6044 default:
5674 gcc_unreachable (); 6045 gcc_unreachable ();
5675 } 6046 }
5679 6050
5680 /* Evaluate a SUBREG of a CONST_INT or CONST_WIDE_INT or CONST_DOUBLE 6051 /* Evaluate a SUBREG of a CONST_INT or CONST_WIDE_INT or CONST_DOUBLE
5681 or CONST_FIXED or CONST_VECTOR, returning another CONST_INT or 6052 or CONST_FIXED or CONST_VECTOR, returning another CONST_INT or
5682 CONST_WIDE_INT or CONST_DOUBLE or CONST_FIXED or CONST_VECTOR. 6053 CONST_WIDE_INT or CONST_DOUBLE or CONST_FIXED or CONST_VECTOR.
5683 6054
5684 Works by unpacking OP into a collection of 8-bit values 6055 Works by unpacking INNER_BYTES bytes of OP into a collection of 8-bit values
5685 represented as a little-endian array of 'unsigned char', selecting by BYTE, 6056 represented as a little-endian array of 'unsigned char', selecting by BYTE,
5686 and then repacking them again for OUTERMODE. */ 6057 and then repacking them again for OUTERMODE. If OP is a CONST_VECTOR,
6058 FIRST_ELEM is the number of the first element to extract, otherwise
6059 FIRST_ELEM is ignored. */
5687 6060
5688 static rtx 6061 static rtx
5689 simplify_immed_subreg (machine_mode outermode, rtx op, 6062 simplify_immed_subreg (fixed_size_mode outermode, rtx op,
5690 machine_mode innermode, unsigned int byte) 6063 machine_mode innermode, unsigned int byte,
6064 unsigned int first_elem, unsigned int inner_bytes)
5691 { 6065 {
5692 enum { 6066 enum {
5693 value_bit = 8, 6067 value_bit = 8,
5694 value_mask = (1 << value_bit) - 1 6068 value_mask = (1 << value_bit) - 1
5695 }; 6069 };
5715 if (COMPLEX_MODE_P (outermode)) 6089 if (COMPLEX_MODE_P (outermode))
5716 return NULL_RTX; 6090 return NULL_RTX;
5717 6091
5718 /* We support any size mode. */ 6092 /* We support any size mode. */
5719 max_bitsize = MAX (GET_MODE_BITSIZE (outermode), 6093 max_bitsize = MAX (GET_MODE_BITSIZE (outermode),
5720 GET_MODE_BITSIZE (innermode)); 6094 inner_bytes * BITS_PER_UNIT);
5721 6095
5722 /* Unpack the value. */ 6096 /* Unpack the value. */
5723 6097
5724 if (GET_CODE (op) == CONST_VECTOR) 6098 if (GET_CODE (op) == CONST_VECTOR)
5725 { 6099 {
5726 num_elem = CONST_VECTOR_NUNITS (op); 6100 num_elem = CEIL (inner_bytes, GET_MODE_UNIT_SIZE (innermode));
5727 elems = &CONST_VECTOR_ELT (op, 0);
5728 elem_bitsize = GET_MODE_UNIT_BITSIZE (innermode); 6101 elem_bitsize = GET_MODE_UNIT_BITSIZE (innermode);
5729 } 6102 }
5730 else 6103 else
5731 { 6104 {
5732 num_elem = 1; 6105 num_elem = 1;
5733 elems = &op;
5734 elem_bitsize = max_bitsize; 6106 elem_bitsize = max_bitsize;
5735 } 6107 }
5736 /* If this asserts, it is too complicated; reducing value_bit may help. */ 6108 /* If this asserts, it is too complicated; reducing value_bit may help. */
5737 gcc_assert (BITS_PER_UNIT % value_bit == 0); 6109 gcc_assert (BITS_PER_UNIT % value_bit == 0);
5738 /* I don't know how to handle endianness of sub-units. */ 6110 /* I don't know how to handle endianness of sub-units. */
5739 gcc_assert (elem_bitsize % BITS_PER_UNIT == 0); 6111 gcc_assert (elem_bitsize % BITS_PER_UNIT == 0);
5740 6112
5741 for (elem = 0; elem < num_elem; elem++) 6113 for (elem = 0; elem < num_elem; elem++)
5742 { 6114 {
5743 unsigned char * vp; 6115 unsigned char * vp;
5744 rtx el = elems[elem]; 6116 rtx el = (GET_CODE (op) == CONST_VECTOR
6117 ? CONST_VECTOR_ELT (op, first_elem + elem)
6118 : op);
5745 6119
5746 /* Vectors are kept in target memory order. (This is probably 6120 /* Vectors are kept in target memory order. (This is probably
5747 a mistake.) */ 6121 a mistake.) */
5748 { 6122 {
5749 unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; 6123 unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT;
5865 6239
5866 /* Now, pick the right byte to start with. */ 6240 /* Now, pick the right byte to start with. */
5867 /* Renumber BYTE so that the least-significant byte is byte 0. A special 6241 /* Renumber BYTE so that the least-significant byte is byte 0. A special
5868 case is paradoxical SUBREGs, which shouldn't be adjusted since they 6242 case is paradoxical SUBREGs, which shouldn't be adjusted since they
5869 will already have offset 0. */ 6243 will already have offset 0. */
5870 if (GET_MODE_SIZE (innermode) >= GET_MODE_SIZE (outermode)) 6244 if (inner_bytes >= GET_MODE_SIZE (outermode))
5871 { 6245 {
5872 unsigned ibyte = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode) 6246 unsigned ibyte = inner_bytes - GET_MODE_SIZE (outermode) - byte;
5873 - byte);
5874 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; 6247 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte;
5875 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; 6248 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte;
5876 byte = (subword_byte % UNITS_PER_WORD 6249 byte = (subword_byte % UNITS_PER_WORD
5877 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); 6250 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD);
5878 } 6251 }
5879 6252
5880 /* BYTE should still be inside OP. (Note that BYTE is unsigned, 6253 /* BYTE should still be inside OP. (Note that BYTE is unsigned,
5881 so if it's become negative it will instead be very large.) */ 6254 so if it's become negative it will instead be very large.) */
5882 gcc_assert (byte < GET_MODE_SIZE (innermode)); 6255 gcc_assert (byte < inner_bytes);
5883 6256
5884 /* Convert from bytes to chunks of size value_bit. */ 6257 /* Convert from bytes to chunks of size value_bit. */
5885 value_start = byte * (BITS_PER_UNIT / value_bit); 6258 value_start = byte * (BITS_PER_UNIT / value_bit);
5886 6259
5887 /* Re-pack the value. */ 6260 /* Re-pack the value. */
6015 6388
6016 /* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE) 6389 /* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE)
6017 Return 0 if no simplifications are possible. */ 6390 Return 0 if no simplifications are possible. */
6018 rtx 6391 rtx
6019 simplify_subreg (machine_mode outermode, rtx op, 6392 simplify_subreg (machine_mode outermode, rtx op,
6020 machine_mode innermode, unsigned int byte) 6393 machine_mode innermode, poly_uint64 byte)
6021 { 6394 {
6022 /* Little bit of sanity checking. */ 6395 /* Little bit of sanity checking. */
6023 gcc_assert (innermode != VOIDmode); 6396 gcc_assert (innermode != VOIDmode);
6024 gcc_assert (outermode != VOIDmode); 6397 gcc_assert (outermode != VOIDmode);
6025 gcc_assert (innermode != BLKmode); 6398 gcc_assert (innermode != BLKmode);
6026 gcc_assert (outermode != BLKmode); 6399 gcc_assert (outermode != BLKmode);
6027 6400
6028 gcc_assert (GET_MODE (op) == innermode 6401 gcc_assert (GET_MODE (op) == innermode
6029 || GET_MODE (op) == VOIDmode); 6402 || GET_MODE (op) == VOIDmode);
6030 6403
6031 if ((byte % GET_MODE_SIZE (outermode)) != 0) 6404 poly_uint64 outersize = GET_MODE_SIZE (outermode);
6405 if (!multiple_p (byte, outersize))
6032 return NULL_RTX; 6406 return NULL_RTX;
6033 6407
6034 if (byte >= GET_MODE_SIZE (innermode)) 6408 poly_uint64 innersize = GET_MODE_SIZE (innermode);
6409 if (maybe_ge (byte, innersize))
6035 return NULL_RTX; 6410 return NULL_RTX;
6036 6411
6037 if (outermode == innermode && !byte) 6412 if (outermode == innermode && known_eq (byte, 0U))
6038 return op; 6413 return op;
6414
6415 if (multiple_p (byte, GET_MODE_UNIT_SIZE (innermode)))
6416 {
6417 rtx elt;
6418
6419 if (VECTOR_MODE_P (outermode)
6420 && GET_MODE_INNER (outermode) == GET_MODE_INNER (innermode)
6421 && vec_duplicate_p (op, &elt))
6422 return gen_vec_duplicate (outermode, elt);
6423
6424 if (outermode == GET_MODE_INNER (innermode)
6425 && vec_duplicate_p (op, &elt))
6426 return elt;
6427 }
6039 6428
6040 if (CONST_SCALAR_INT_P (op) 6429 if (CONST_SCALAR_INT_P (op)
6041 || CONST_DOUBLE_AS_FLOAT_P (op) 6430 || CONST_DOUBLE_AS_FLOAT_P (op)
6042 || GET_CODE (op) == CONST_FIXED 6431 || CONST_FIXED_P (op)
6043 || GET_CODE (op) == CONST_VECTOR) 6432 || GET_CODE (op) == CONST_VECTOR)
6044 return simplify_immed_subreg (outermode, op, innermode, byte); 6433 {
6434 /* simplify_immed_subreg deconstructs OP into bytes and constructs
6435 the result from bytes, so it only works if the sizes of the modes
6436 and the value of the offset are known at compile time. Cases that
6437 that apply to general modes and offsets should be handled here
6438 before calling simplify_immed_subreg. */
6439 fixed_size_mode fs_outermode, fs_innermode;
6440 unsigned HOST_WIDE_INT cbyte;
6441 if (is_a <fixed_size_mode> (outermode, &fs_outermode)
6442 && is_a <fixed_size_mode> (innermode, &fs_innermode)
6443 && byte.is_constant (&cbyte))
6444 return simplify_immed_subreg (fs_outermode, op, fs_innermode, cbyte,
6445 0, GET_MODE_SIZE (fs_innermode));
6446
6447 /* Handle constant-sized outer modes and variable-sized inner modes. */
6448 unsigned HOST_WIDE_INT first_elem;
6449 if (GET_CODE (op) == CONST_VECTOR
6450 && is_a <fixed_size_mode> (outermode, &fs_outermode)
6451 && constant_multiple_p (byte, GET_MODE_UNIT_SIZE (innermode),
6452 &first_elem))
6453 return simplify_immed_subreg (fs_outermode, op, innermode, 0,
6454 first_elem,
6455 GET_MODE_SIZE (fs_outermode));
6456
6457 return NULL_RTX;
6458 }
6045 6459
6046 /* Changing mode twice with SUBREG => just change it once, 6460 /* Changing mode twice with SUBREG => just change it once,
6047 or not at all if changing back op starting mode. */ 6461 or not at all if changing back op starting mode. */
6048 if (GET_CODE (op) == SUBREG) 6462 if (GET_CODE (op) == SUBREG)
6049 { 6463 {
6050 machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); 6464 machine_mode innermostmode = GET_MODE (SUBREG_REG (op));
6465 poly_uint64 innermostsize = GET_MODE_SIZE (innermostmode);
6051 rtx newx; 6466 rtx newx;
6052 6467
6053 if (outermode == innermostmode 6468 if (outermode == innermostmode
6054 && byte == 0 && SUBREG_BYTE (op) == 0) 6469 && known_eq (byte, 0U)
6470 && known_eq (SUBREG_BYTE (op), 0))
6055 return SUBREG_REG (op); 6471 return SUBREG_REG (op);
6056 6472
6057 /* Work out the memory offset of the final OUTERMODE value relative 6473 /* Work out the memory offset of the final OUTERMODE value relative
6058 to the inner value of OP. */ 6474 to the inner value of OP. */
6059 HOST_WIDE_INT mem_offset = subreg_memory_offset (outermode, 6475 poly_int64 mem_offset = subreg_memory_offset (outermode,
6060 innermode, byte); 6476 innermode, byte);
6061 HOST_WIDE_INT op_mem_offset = subreg_memory_offset (op); 6477 poly_int64 op_mem_offset = subreg_memory_offset (op);
6062 HOST_WIDE_INT final_offset = mem_offset + op_mem_offset; 6478 poly_int64 final_offset = mem_offset + op_mem_offset;
6063 6479
6064 /* See whether resulting subreg will be paradoxical. */ 6480 /* See whether resulting subreg will be paradoxical. */
6065 if (!paradoxical_subreg_p (outermode, innermostmode)) 6481 if (!paradoxical_subreg_p (outermode, innermostmode))
6066 { 6482 {
6067 /* In nonparadoxical subregs we can't handle negative offsets. */ 6483 /* Bail out in case resulting subreg would be incorrect. */
6068 if (final_offset < 0) 6484 if (maybe_lt (final_offset, 0)
6485 || maybe_ge (poly_uint64 (final_offset), innermostsize)
6486 || !multiple_p (final_offset, outersize))
6069 return NULL_RTX; 6487 return NULL_RTX;
6070 /* Bail out in case resulting subreg would be incorrect. */
6071 if (final_offset % GET_MODE_SIZE (outermode)
6072 || (unsigned) final_offset >= GET_MODE_SIZE (innermostmode))
6073 return NULL_RTX;
6074 } 6488 }
6075 else 6489 else
6076 { 6490 {
6077 HOST_WIDE_INT required_offset 6491 poly_int64 required_offset = subreg_memory_offset (outermode,
6078 = subreg_memory_offset (outermode, innermostmode, 0); 6492 innermostmode, 0);
6079 if (final_offset != required_offset) 6493 if (maybe_ne (final_offset, required_offset))
6080 return NULL_RTX; 6494 return NULL_RTX;
6081 /* Paradoxical subregs always have byte offset 0. */ 6495 /* Paradoxical subregs always have byte offset 0. */
6082 final_offset = 0; 6496 final_offset = 0;
6083 } 6497 }
6084 6498
6092 { 6506 {
6093 newx = gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset); 6507 newx = gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
6094 if (SUBREG_PROMOTED_VAR_P (op) 6508 if (SUBREG_PROMOTED_VAR_P (op)
6095 && SUBREG_PROMOTED_SIGN (op) >= 0 6509 && SUBREG_PROMOTED_SIGN (op) >= 0
6096 && GET_MODE_CLASS (outermode) == MODE_INT 6510 && GET_MODE_CLASS (outermode) == MODE_INT
6097 && IN_RANGE (GET_MODE_SIZE (outermode), 6511 && known_ge (outersize, innersize)
6098 GET_MODE_SIZE (innermode), 6512 && known_le (outersize, innermostsize)
6099 GET_MODE_SIZE (innermostmode))
6100 && subreg_lowpart_p (newx)) 6513 && subreg_lowpart_p (newx))
6101 { 6514 {
6102 SUBREG_PROMOTED_VAR_P (newx) = 1; 6515 SUBREG_PROMOTED_VAR_P (newx) = 1;
6103 SUBREG_PROMOTED_SET (newx, SUBREG_PROMOTED_GET (op)); 6516 SUBREG_PROMOTED_SET (newx, SUBREG_PROMOTED_GET (op));
6104 } 6517 }
6127 /* Propagate original regno. We don't have any way to specify 6540 /* Propagate original regno. We don't have any way to specify
6128 the offset inside original regno, so do so only for lowpart. 6541 the offset inside original regno, so do so only for lowpart.
6129 The information is used only by alias analysis that can not 6542 The information is used only by alias analysis that can not
6130 grog partial register anyway. */ 6543 grog partial register anyway. */
6131 6544
6132 if (subreg_lowpart_offset (outermode, innermode) == byte) 6545 if (known_eq (subreg_lowpart_offset (outermode, innermode), byte))
6133 ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op); 6546 ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op);
6134 return x; 6547 return x;
6135 } 6548 }
6136 } 6549 }
6137 6550
6144 && ! mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op)) 6557 && ! mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op))
6145 /* Allow splitting of volatile memory references in case we don't 6558 /* Allow splitting of volatile memory references in case we don't
6146 have instruction to move the whole thing. */ 6559 have instruction to move the whole thing. */
6147 && (! MEM_VOLATILE_P (op) 6560 && (! MEM_VOLATILE_P (op)
6148 || ! have_insn_for (SET, innermode)) 6561 || ! have_insn_for (SET, innermode))
6149 && GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op))) 6562 && known_le (outersize, innersize))
6150 return adjust_address_nv (op, outermode, byte); 6563 return adjust_address_nv (op, outermode, byte);
6151 6564
6152 /* Handle complex or vector values represented as CONCAT or VEC_CONCAT 6565 /* Handle complex or vector values represented as CONCAT or VEC_CONCAT
6153 of two parts. */ 6566 of two parts. */
6154 if (GET_CODE (op) == CONCAT 6567 if (GET_CODE (op) == CONCAT
6155 || GET_CODE (op) == VEC_CONCAT) 6568 || GET_CODE (op) == VEC_CONCAT)
6156 { 6569 {
6157 unsigned int part_size, final_offset; 6570 poly_uint64 final_offset;
6158 rtx part, res; 6571 rtx part, res;
6159 6572
6160 machine_mode part_mode = GET_MODE (XEXP (op, 0)); 6573 machine_mode part_mode = GET_MODE (XEXP (op, 0));
6161 if (part_mode == VOIDmode) 6574 if (part_mode == VOIDmode)
6162 part_mode = GET_MODE_INNER (GET_MODE (op)); 6575 part_mode = GET_MODE_INNER (GET_MODE (op));
6163 part_size = GET_MODE_SIZE (part_mode); 6576 poly_uint64 part_size = GET_MODE_SIZE (part_mode);
6164 if (byte < part_size) 6577 if (known_lt (byte, part_size))
6165 { 6578 {
6166 part = XEXP (op, 0); 6579 part = XEXP (op, 0);
6167 final_offset = byte; 6580 final_offset = byte;
6168 } 6581 }
6169 else 6582 else if (known_ge (byte, part_size))
6170 { 6583 {
6171 part = XEXP (op, 1); 6584 part = XEXP (op, 1);
6172 final_offset = byte - part_size; 6585 final_offset = byte - part_size;
6173 } 6586 }
6174 6587 else
6175 if (final_offset + GET_MODE_SIZE (outermode) > part_size) 6588 return NULL_RTX;
6589
6590 if (maybe_gt (final_offset + outersize, part_size))
6176 return NULL_RTX; 6591 return NULL_RTX;
6177 6592
6178 part_mode = GET_MODE (part); 6593 part_mode = GET_MODE (part);
6179 if (part_mode == VOIDmode) 6594 if (part_mode == VOIDmode)
6180 part_mode = GET_MODE_INNER (GET_MODE (op)); 6595 part_mode = GET_MODE_INNER (GET_MODE (op));
6184 if (validate_subreg (outermode, part_mode, part, final_offset)) 6599 if (validate_subreg (outermode, part_mode, part, final_offset))
6185 return gen_rtx_SUBREG (outermode, part, final_offset); 6600 return gen_rtx_SUBREG (outermode, part, final_offset);
6186 return NULL_RTX; 6601 return NULL_RTX;
6187 } 6602 }
6188 6603
6604 /* Simplify
6605 (subreg (vec_merge (X)
6606 (vector)
6607 (const_int ((1 << N) | M)))
6608 (N * sizeof (outermode)))
6609 to
6610 (subreg (X) (N * sizeof (outermode)))
6611 */
6612 unsigned int idx;
6613 if (constant_multiple_p (byte, GET_MODE_SIZE (outermode), &idx)
6614 && idx < HOST_BITS_PER_WIDE_INT
6615 && GET_CODE (op) == VEC_MERGE
6616 && GET_MODE_INNER (innermode) == outermode
6617 && CONST_INT_P (XEXP (op, 2))
6618 && (UINTVAL (XEXP (op, 2)) & (HOST_WIDE_INT_1U << idx)) != 0)
6619 return simplify_gen_subreg (outermode, XEXP (op, 0), innermode, byte);
6620
6189 /* A SUBREG resulting from a zero extension may fold to zero if 6621 /* A SUBREG resulting from a zero extension may fold to zero if
6190 it extracts higher bits that the ZERO_EXTEND's source bits. */ 6622 it extracts higher bits that the ZERO_EXTEND's source bits. */
6191 if (GET_CODE (op) == ZERO_EXTEND && SCALAR_INT_MODE_P (innermode)) 6623 if (GET_CODE (op) == ZERO_EXTEND && SCALAR_INT_MODE_P (innermode))
6192 { 6624 {
6193 unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte); 6625 poly_uint64 bitpos = subreg_lsb_1 (outermode, innermode, byte);
6194 if (bitpos >= GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))) 6626 if (known_ge (bitpos, GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))))
6195 return CONST0_RTX (outermode); 6627 return CONST0_RTX (outermode);
6196 } 6628 }
6197 6629
6198 scalar_int_mode int_outermode, int_innermode; 6630 scalar_int_mode int_outermode, int_innermode;
6199 if (is_a <scalar_int_mode> (outermode, &int_outermode) 6631 if (is_a <scalar_int_mode> (outermode, &int_outermode)
6200 && is_a <scalar_int_mode> (innermode, &int_innermode) 6632 && is_a <scalar_int_mode> (innermode, &int_innermode)
6201 && (GET_MODE_PRECISION (int_outermode) 6633 && known_eq (byte, subreg_lowpart_offset (int_outermode, int_innermode)))
6634 {
6635 /* Handle polynomial integers. The upper bits of a paradoxical
6636 subreg are undefined, so this is safe regardless of whether
6637 we're truncating or extending. */
6638 if (CONST_POLY_INT_P (op))
6639 {
6640 poly_wide_int val
6641 = poly_wide_int::from (const_poly_int_value (op),
6642 GET_MODE_PRECISION (int_outermode),
6643 SIGNED);
6644 return immed_wide_int_const (val, int_outermode);
6645 }
6646
6647 if (GET_MODE_PRECISION (int_outermode)
6202 < GET_MODE_PRECISION (int_innermode)) 6648 < GET_MODE_PRECISION (int_innermode))
6203 && byte == subreg_lowpart_offset (int_outermode, int_innermode)) 6649 {
6204 { 6650 rtx tem = simplify_truncation (int_outermode, op, int_innermode);
6205 rtx tem = simplify_truncation (int_outermode, op, int_innermode); 6651 if (tem)
6206 if (tem) 6652 return tem;
6207 return tem; 6653 }
6208 } 6654 }
6209 6655
6210 return NULL_RTX; 6656 return NULL_RTX;
6211 } 6657 }
6212 6658
6213 /* Make a SUBREG operation or equivalent if it folds. */ 6659 /* Make a SUBREG operation or equivalent if it folds. */
6214 6660
6215 rtx 6661 rtx
6216 simplify_gen_subreg (machine_mode outermode, rtx op, 6662 simplify_gen_subreg (machine_mode outermode, rtx op,
6217 machine_mode innermode, unsigned int byte) 6663 machine_mode innermode, poly_uint64 byte)
6218 { 6664 {
6219 rtx newx; 6665 rtx newx;
6220 6666
6221 newx = simplify_subreg (outermode, op, innermode, byte); 6667 newx = simplify_subreg (outermode, op, innermode, byte);
6222 if (newx) 6668 if (newx)
6340 default: 6786 default:
6341 break; 6787 break;
6342 } 6788 }
6343 return NULL; 6789 return NULL;
6344 } 6790 }
6791
6792 #if CHECKING_P
6793
6794 namespace selftest {
6795
6796 /* Make a unique pseudo REG of mode MODE for use by selftests. */
6797
6798 static rtx
6799 make_test_reg (machine_mode mode)
6800 {
6801 static int test_reg_num = LAST_VIRTUAL_REGISTER + 1;
6802
6803 return gen_rtx_REG (mode, test_reg_num++);
6804 }
6805
6806 /* Test vector simplifications involving VEC_DUPLICATE in which the
6807 operands and result have vector mode MODE. SCALAR_REG is a pseudo
6808 register that holds one element of MODE. */
6809
6810 static void
6811 test_vector_ops_duplicate (machine_mode mode, rtx scalar_reg)
6812 {
6813 scalar_mode inner_mode = GET_MODE_INNER (mode);
6814 rtx duplicate = gen_rtx_VEC_DUPLICATE (mode, scalar_reg);
6815 poly_uint64 nunits = GET_MODE_NUNITS (mode);
6816 if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
6817 {
6818 /* Test some simple unary cases with VEC_DUPLICATE arguments. */
6819 rtx not_scalar_reg = gen_rtx_NOT (inner_mode, scalar_reg);
6820 rtx duplicate_not = gen_rtx_VEC_DUPLICATE (mode, not_scalar_reg);
6821 ASSERT_RTX_EQ (duplicate,
6822 simplify_unary_operation (NOT, mode,
6823 duplicate_not, mode));
6824
6825 rtx neg_scalar_reg = gen_rtx_NEG (inner_mode, scalar_reg);
6826 rtx duplicate_neg = gen_rtx_VEC_DUPLICATE (mode, neg_scalar_reg);
6827 ASSERT_RTX_EQ (duplicate,
6828 simplify_unary_operation (NEG, mode,
6829 duplicate_neg, mode));
6830
6831 /* Test some simple binary cases with VEC_DUPLICATE arguments. */
6832 ASSERT_RTX_EQ (duplicate,
6833 simplify_binary_operation (PLUS, mode, duplicate,
6834 CONST0_RTX (mode)));
6835
6836 ASSERT_RTX_EQ (duplicate,
6837 simplify_binary_operation (MINUS, mode, duplicate,
6838 CONST0_RTX (mode)));
6839
6840 ASSERT_RTX_PTR_EQ (CONST0_RTX (mode),
6841 simplify_binary_operation (MINUS, mode, duplicate,
6842 duplicate));
6843 }
6844
6845 /* Test a scalar VEC_SELECT of a VEC_DUPLICATE. */
6846 rtx zero_par = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const0_rtx));
6847 ASSERT_RTX_PTR_EQ (scalar_reg,
6848 simplify_binary_operation (VEC_SELECT, inner_mode,
6849 duplicate, zero_par));
6850
6851 unsigned HOST_WIDE_INT const_nunits;
6852 if (nunits.is_constant (&const_nunits))
6853 {
6854 /* And again with the final element. */
6855 rtx last_index = gen_int_mode (const_nunits - 1, word_mode);
6856 rtx last_par = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, last_index));
6857 ASSERT_RTX_PTR_EQ (scalar_reg,
6858 simplify_binary_operation (VEC_SELECT, inner_mode,
6859 duplicate, last_par));
6860
6861 /* Test a scalar subreg of a VEC_MERGE of a VEC_DUPLICATE. */
6862 rtx vector_reg = make_test_reg (mode);
6863 for (unsigned HOST_WIDE_INT i = 0; i < const_nunits; i++)
6864 {
6865 if (i >= HOST_BITS_PER_WIDE_INT)
6866 break;
6867 rtx mask = GEN_INT ((HOST_WIDE_INT_1U << i) | (i + 1));
6868 rtx vm = gen_rtx_VEC_MERGE (mode, duplicate, vector_reg, mask);
6869 poly_uint64 offset = i * GET_MODE_SIZE (inner_mode);
6870 ASSERT_RTX_EQ (scalar_reg,
6871 simplify_gen_subreg (inner_mode, vm,
6872 mode, offset));
6873 }
6874 }
6875
6876 /* Test a scalar subreg of a VEC_DUPLICATE. */
6877 poly_uint64 offset = subreg_lowpart_offset (inner_mode, mode);
6878 ASSERT_RTX_EQ (scalar_reg,
6879 simplify_gen_subreg (inner_mode, duplicate,
6880 mode, offset));
6881
6882 machine_mode narrower_mode;
6883 if (maybe_ne (nunits, 2U)
6884 && multiple_p (nunits, 2)
6885 && mode_for_vector (inner_mode, 2).exists (&narrower_mode)
6886 && VECTOR_MODE_P (narrower_mode))
6887 {
6888 /* Test VEC_SELECT of a vector. */
6889 rtx vec_par
6890 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, const1_rtx, const0_rtx));
6891 rtx narrower_duplicate
6892 = gen_rtx_VEC_DUPLICATE (narrower_mode, scalar_reg);
6893 ASSERT_RTX_EQ (narrower_duplicate,
6894 simplify_binary_operation (VEC_SELECT, narrower_mode,
6895 duplicate, vec_par));
6896
6897 /* Test a vector subreg of a VEC_DUPLICATE. */
6898 poly_uint64 offset = subreg_lowpart_offset (narrower_mode, mode);
6899 ASSERT_RTX_EQ (narrower_duplicate,
6900 simplify_gen_subreg (narrower_mode, duplicate,
6901 mode, offset));
6902 }
6903 }
6904
6905 /* Test vector simplifications involving VEC_SERIES in which the
6906 operands and result have vector mode MODE. SCALAR_REG is a pseudo
6907 register that holds one element of MODE. */
6908
6909 static void
6910 test_vector_ops_series (machine_mode mode, rtx scalar_reg)
6911 {
6912 /* Test unary cases with VEC_SERIES arguments. */
6913 scalar_mode inner_mode = GET_MODE_INNER (mode);
6914 rtx duplicate = gen_rtx_VEC_DUPLICATE (mode, scalar_reg);
6915 rtx neg_scalar_reg = gen_rtx_NEG (inner_mode, scalar_reg);
6916 rtx series_0_r = gen_rtx_VEC_SERIES (mode, const0_rtx, scalar_reg);
6917 rtx series_0_nr = gen_rtx_VEC_SERIES (mode, const0_rtx, neg_scalar_reg);
6918 rtx series_nr_1 = gen_rtx_VEC_SERIES (mode, neg_scalar_reg, const1_rtx);
6919 rtx series_r_m1 = gen_rtx_VEC_SERIES (mode, scalar_reg, constm1_rtx);
6920 rtx series_r_r = gen_rtx_VEC_SERIES (mode, scalar_reg, scalar_reg);
6921 rtx series_nr_nr = gen_rtx_VEC_SERIES (mode, neg_scalar_reg,
6922 neg_scalar_reg);
6923 ASSERT_RTX_EQ (series_0_r,
6924 simplify_unary_operation (NEG, mode, series_0_nr, mode));
6925 ASSERT_RTX_EQ (series_r_m1,
6926 simplify_unary_operation (NEG, mode, series_nr_1, mode));
6927 ASSERT_RTX_EQ (series_r_r,
6928 simplify_unary_operation (NEG, mode, series_nr_nr, mode));
6929
6930 /* Test that a VEC_SERIES with a zero step is simplified away. */
6931 ASSERT_RTX_EQ (duplicate,
6932 simplify_binary_operation (VEC_SERIES, mode,
6933 scalar_reg, const0_rtx));
6934
6935 /* Test PLUS and MINUS with VEC_SERIES. */
6936 rtx series_0_1 = gen_const_vec_series (mode, const0_rtx, const1_rtx);
6937 rtx series_0_m1 = gen_const_vec_series (mode, const0_rtx, constm1_rtx);
6938 rtx series_r_1 = gen_rtx_VEC_SERIES (mode, scalar_reg, const1_rtx);
6939 ASSERT_RTX_EQ (series_r_r,
6940 simplify_binary_operation (PLUS, mode, series_0_r,
6941 duplicate));
6942 ASSERT_RTX_EQ (series_r_1,
6943 simplify_binary_operation (PLUS, mode, duplicate,
6944 series_0_1));
6945 ASSERT_RTX_EQ (series_r_m1,
6946 simplify_binary_operation (PLUS, mode, duplicate,
6947 series_0_m1));
6948 ASSERT_RTX_EQ (series_0_r,
6949 simplify_binary_operation (MINUS, mode, series_r_r,
6950 duplicate));
6951 ASSERT_RTX_EQ (series_r_m1,
6952 simplify_binary_operation (MINUS, mode, duplicate,
6953 series_0_1));
6954 ASSERT_RTX_EQ (series_r_1,
6955 simplify_binary_operation (MINUS, mode, duplicate,
6956 series_0_m1));
6957 ASSERT_RTX_EQ (series_0_m1,
6958 simplify_binary_operation (VEC_SERIES, mode, const0_rtx,
6959 constm1_rtx));
6960 }
6961
6962 /* Verify simplify_merge_mask works correctly. */
6963
6964 static void
6965 test_vec_merge (machine_mode mode)
6966 {
6967 rtx op0 = make_test_reg (mode);
6968 rtx op1 = make_test_reg (mode);
6969 rtx op2 = make_test_reg (mode);
6970 rtx op3 = make_test_reg (mode);
6971 rtx op4 = make_test_reg (mode);
6972 rtx op5 = make_test_reg (mode);
6973 rtx mask1 = make_test_reg (SImode);
6974 rtx mask2 = make_test_reg (SImode);
6975 rtx vm1 = gen_rtx_VEC_MERGE (mode, op0, op1, mask1);
6976 rtx vm2 = gen_rtx_VEC_MERGE (mode, op2, op3, mask1);
6977 rtx vm3 = gen_rtx_VEC_MERGE (mode, op4, op5, mask1);
6978
6979 /* Simple vec_merge. */
6980 ASSERT_EQ (op0, simplify_merge_mask (vm1, mask1, 0));
6981 ASSERT_EQ (op1, simplify_merge_mask (vm1, mask1, 1));
6982 ASSERT_EQ (NULL_RTX, simplify_merge_mask (vm1, mask2, 0));
6983 ASSERT_EQ (NULL_RTX, simplify_merge_mask (vm1, mask2, 1));
6984
6985 /* Nested vec_merge.
6986 It's tempting to make this simplify right down to opN, but we don't
6987 because all the simplify_* functions assume that the operands have
6988 already been simplified. */
6989 rtx nvm = gen_rtx_VEC_MERGE (mode, vm1, vm2, mask1);
6990 ASSERT_EQ (vm1, simplify_merge_mask (nvm, mask1, 0));
6991 ASSERT_EQ (vm2, simplify_merge_mask (nvm, mask1, 1));
6992
6993 /* Intermediate unary op. */
6994 rtx unop = gen_rtx_NOT (mode, vm1);
6995 ASSERT_RTX_EQ (gen_rtx_NOT (mode, op0),
6996 simplify_merge_mask (unop, mask1, 0));
6997 ASSERT_RTX_EQ (gen_rtx_NOT (mode, op1),
6998 simplify_merge_mask (unop, mask1, 1));
6999
7000 /* Intermediate binary op. */
7001 rtx binop = gen_rtx_PLUS (mode, vm1, vm2);
7002 ASSERT_RTX_EQ (gen_rtx_PLUS (mode, op0, op2),
7003 simplify_merge_mask (binop, mask1, 0));
7004 ASSERT_RTX_EQ (gen_rtx_PLUS (mode, op1, op3),
7005 simplify_merge_mask (binop, mask1, 1));
7006
7007 /* Intermediate ternary op. */
7008 rtx tenop = gen_rtx_FMA (mode, vm1, vm2, vm3);
7009 ASSERT_RTX_EQ (gen_rtx_FMA (mode, op0, op2, op4),
7010 simplify_merge_mask (tenop, mask1, 0));
7011 ASSERT_RTX_EQ (gen_rtx_FMA (mode, op1, op3, op5),
7012 simplify_merge_mask (tenop, mask1, 1));
7013
7014 /* Side effects. */
7015 rtx badop0 = gen_rtx_PRE_INC (mode, op0);
7016 rtx badvm = gen_rtx_VEC_MERGE (mode, badop0, op1, mask1);
7017 ASSERT_EQ (badop0, simplify_merge_mask (badvm, mask1, 0));
7018 ASSERT_EQ (NULL_RTX, simplify_merge_mask (badvm, mask1, 1));
7019
7020 /* Called indirectly. */
7021 ASSERT_RTX_EQ (gen_rtx_VEC_MERGE (mode, op0, op3, mask1),
7022 simplify_rtx (nvm));
7023 }
7024
7025 /* Verify some simplifications involving vectors. */
7026
7027 static void
7028 test_vector_ops ()
7029 {
7030 for (unsigned int i = 0; i < NUM_MACHINE_MODES; ++i)
7031 {
7032 machine_mode mode = (machine_mode) i;
7033 if (VECTOR_MODE_P (mode))
7034 {
7035 rtx scalar_reg = make_test_reg (GET_MODE_INNER (mode));
7036 test_vector_ops_duplicate (mode, scalar_reg);
7037 if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
7038 && maybe_gt (GET_MODE_NUNITS (mode), 2))
7039 test_vector_ops_series (mode, scalar_reg);
7040 test_vec_merge (mode);
7041 }
7042 }
7043 }
7044
7045 template<unsigned int N>
7046 struct simplify_const_poly_int_tests
7047 {
7048 static void run ();
7049 };
7050
7051 template<>
7052 struct simplify_const_poly_int_tests<1>
7053 {
7054 static void run () {}
7055 };
7056
7057 /* Test various CONST_POLY_INT properties. */
7058
7059 template<unsigned int N>
7060 void
7061 simplify_const_poly_int_tests<N>::run ()
7062 {
7063 rtx x1 = gen_int_mode (poly_int64 (1, 1), QImode);
7064 rtx x2 = gen_int_mode (poly_int64 (-80, 127), QImode);
7065 rtx x3 = gen_int_mode (poly_int64 (-79, -128), QImode);
7066 rtx x4 = gen_int_mode (poly_int64 (5, 4), QImode);
7067 rtx x5 = gen_int_mode (poly_int64 (30, 24), QImode);
7068 rtx x6 = gen_int_mode (poly_int64 (20, 16), QImode);
7069 rtx x7 = gen_int_mode (poly_int64 (7, 4), QImode);
7070 rtx x8 = gen_int_mode (poly_int64 (30, 24), HImode);
7071 rtx x9 = gen_int_mode (poly_int64 (-30, -24), HImode);
7072 rtx x10 = gen_int_mode (poly_int64 (-31, -24), HImode);
7073 rtx two = GEN_INT (2);
7074 rtx six = GEN_INT (6);
7075 poly_uint64 offset = subreg_lowpart_offset (QImode, HImode);
7076
7077 /* These tests only try limited operation combinations. Fuller arithmetic
7078 testing is done directly on poly_ints. */
7079 ASSERT_EQ (simplify_unary_operation (NEG, HImode, x8, HImode), x9);
7080 ASSERT_EQ (simplify_unary_operation (NOT, HImode, x8, HImode), x10);
7081 ASSERT_EQ (simplify_unary_operation (TRUNCATE, QImode, x8, HImode), x5);
7082 ASSERT_EQ (simplify_binary_operation (PLUS, QImode, x1, x2), x3);
7083 ASSERT_EQ (simplify_binary_operation (MINUS, QImode, x3, x1), x2);
7084 ASSERT_EQ (simplify_binary_operation (MULT, QImode, x4, six), x5);
7085 ASSERT_EQ (simplify_binary_operation (MULT, QImode, six, x4), x5);
7086 ASSERT_EQ (simplify_binary_operation (ASHIFT, QImode, x4, two), x6);
7087 ASSERT_EQ (simplify_binary_operation (IOR, QImode, x4, two), x7);
7088 ASSERT_EQ (simplify_subreg (HImode, x5, QImode, 0), x8);
7089 ASSERT_EQ (simplify_subreg (QImode, x8, HImode, offset), x5);
7090 }
7091
7092 /* Run all of the selftests within this file. */
7093
7094 void
7095 simplify_rtx_c_tests ()
7096 {
7097 test_vector_ops ();
7098 simplify_const_poly_int_tests<NUM_POLY_INT_COEFFS>::run ();
7099 }
7100
7101 } // namespace selftest
7102
7103 #endif /* CHECKING_P */