Mercurial > hg > CbC > CbC_gcc
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 */ |