Mercurial > hg > CbC > CbC_gcc
comparison gcc/simplify-rtx.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* RTL simplification functions for GNU compiler. | 1 /* RTL simplification functions for GNU compiler. |
2 Copyright (C) 1987-2018 Free Software Foundation, Inc. | 2 Copyright (C) 1987-2020 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 |
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" | 36 #include "selftest.h" |
37 #include "selftest-rtl.h" | 37 #include "selftest-rtl.h" |
38 #include "rtx-vector-builder.h" | |
38 | 39 |
39 /* Simplification and canonicalization of RTL. */ | 40 /* Simplification and canonicalization of RTL. */ |
40 | 41 |
41 /* Much code operates on (low, high) pairs; the low value is an | 42 /* Much code operates on (low, high) pairs; the low value is an |
42 unsigned wide int, the high value a signed wide int. We | 43 unsigned wide int, the high value a signed wide int. We |
43 occasionally need to sign extend from low to high as if low were a | 44 occasionally need to sign extend from low to high as if low were a |
44 signed wide int. */ | 45 signed wide int. */ |
45 #define HWI_SIGN_EXTEND(low) \ | 46 #define HWI_SIGN_EXTEND(low) \ |
46 ((((HOST_WIDE_INT) low) < 0) ? HOST_WIDE_INT_M1 : HOST_WIDE_INT_0) | 47 ((((HOST_WIDE_INT) low) < 0) ? HOST_WIDE_INT_M1 : HOST_WIDE_INT_0) |
47 | 48 |
48 static rtx neg_const_int (machine_mode, const_rtx); | |
49 static bool plus_minus_operand_p (const_rtx); | 49 static bool plus_minus_operand_p (const_rtx); |
50 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); |
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); |
56 static rtx simplify_binary_operation_1 (enum rtx_code, machine_mode, | 56 static rtx simplify_binary_operation_1 (enum rtx_code, machine_mode, |
57 rtx, rtx, rtx, rtx); | 57 rtx, rtx, rtx, rtx); |
58 | 58 |
59 /* Negate a CONST_INT rtx. */ | 59 /* Negate I, which satisfies poly_int_rtx_p. MODE is the mode of I. */ |
60 | |
60 static rtx | 61 static rtx |
61 neg_const_int (machine_mode mode, const_rtx i) | 62 neg_poly_int_rtx (machine_mode mode, const_rtx i) |
62 { | 63 { |
63 unsigned HOST_WIDE_INT val = -UINTVAL (i); | 64 return immed_wide_int_const (-wi::to_poly_wide (i, mode), mode); |
64 | |
65 if (!HWI_COMPUTABLE_MODE_P (mode) | |
66 && val == UINTVAL (i)) | |
67 return simplify_const_unary_operation (NEG, mode, CONST_CAST_RTX (i), | |
68 mode); | |
69 return gen_int_mode (val, mode); | |
70 } | 65 } |
71 | 66 |
72 /* Test whether expression, X, is an immediate constant that represents | 67 /* Test whether expression, X, is an immediate constant that represents |
73 the most significant bit of machine mode MODE. */ | 68 the most significant bit of machine mode MODE. */ |
74 | 69 |
1502 && GET_CODE (XEXP (op, 0)) == ASHIFT | 1497 && GET_CODE (XEXP (op, 0)) == ASHIFT |
1503 && is_a <scalar_int_mode> (mode, &int_mode) | 1498 && is_a <scalar_int_mode> (mode, &int_mode) |
1504 && CONST_INT_P (XEXP (op, 1)) | 1499 && CONST_INT_P (XEXP (op, 1)) |
1505 && XEXP (XEXP (op, 0), 1) == XEXP (op, 1) | 1500 && XEXP (XEXP (op, 0), 1) == XEXP (op, 1) |
1506 && (op_mode = as_a <scalar_int_mode> (GET_MODE (op)), | 1501 && (op_mode = as_a <scalar_int_mode> (GET_MODE (op)), |
1507 GET_MODE_BITSIZE (op_mode) > INTVAL (XEXP (op, 1)))) | 1502 GET_MODE_PRECISION (op_mode) > INTVAL (XEXP (op, 1)))) |
1508 { | 1503 { |
1509 scalar_int_mode tmode; | 1504 scalar_int_mode tmode; |
1510 gcc_assert (GET_MODE_BITSIZE (int_mode) | 1505 gcc_assert (GET_MODE_PRECISION (int_mode) |
1511 > GET_MODE_BITSIZE (op_mode)); | 1506 > GET_MODE_PRECISION (op_mode)); |
1512 if (int_mode_for_size (GET_MODE_BITSIZE (op_mode) | 1507 if (int_mode_for_size (GET_MODE_PRECISION (op_mode) |
1513 - INTVAL (XEXP (op, 1)), 1).exists (&tmode)) | 1508 - INTVAL (XEXP (op, 1)), 1).exists (&tmode)) |
1514 { | 1509 { |
1515 rtx inner = | 1510 rtx inner = |
1516 rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); | 1511 rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); |
1517 if (inner) | 1512 if (inner) |
1733 gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER | 1728 gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER |
1734 (GET_MODE (op))); | 1729 (GET_MODE (op))); |
1735 } | 1730 } |
1736 if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op)) | 1731 if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op)) |
1737 return gen_const_vec_duplicate (mode, op); | 1732 return gen_const_vec_duplicate (mode, op); |
1738 unsigned int n_elts; | |
1739 if (GET_CODE (op) == CONST_VECTOR | 1733 if (GET_CODE (op) == CONST_VECTOR |
1740 && GET_MODE_NUNITS (mode).is_constant (&n_elts)) | 1734 && (CONST_VECTOR_DUPLICATE_P (op) |
1741 { | 1735 || CONST_VECTOR_NUNITS (op).is_constant ())) |
1742 /* This must be constant if we're duplicating it to a constant | 1736 { |
1743 number of elements. */ | 1737 unsigned int npatterns = (CONST_VECTOR_DUPLICATE_P (op) |
1744 unsigned int in_n_elts = CONST_VECTOR_NUNITS (op).to_constant (); | 1738 ? CONST_VECTOR_NPATTERNS (op) |
1745 gcc_assert (in_n_elts < n_elts); | 1739 : CONST_VECTOR_NUNITS (op).to_constant ()); |
1746 gcc_assert ((n_elts % in_n_elts) == 0); | 1740 gcc_assert (multiple_p (GET_MODE_NUNITS (mode), npatterns)); |
1747 rtvec v = rtvec_alloc (n_elts); | 1741 rtx_vector_builder builder (mode, npatterns, 1); |
1748 for (unsigned i = 0; i < n_elts; i++) | 1742 for (unsigned i = 0; i < npatterns; i++) |
1749 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts); | 1743 builder.quick_push (CONST_VECTOR_ELT (op, i)); |
1750 return gen_rtx_CONST_VECTOR (mode, v); | 1744 return builder.build (); |
1751 } | 1745 } |
1752 } | 1746 } |
1753 | 1747 |
1754 if (VECTOR_MODE_P (mode) && GET_CODE (op) == CONST_VECTOR) | 1748 if (VECTOR_MODE_P (mode) |
1755 { | 1749 && GET_CODE (op) == CONST_VECTOR |
1756 unsigned int n_elts; | 1750 && known_eq (GET_MODE_NUNITS (mode), CONST_VECTOR_NUNITS (op))) |
1757 if (!CONST_VECTOR_NUNITS (op).is_constant (&n_elts)) | 1751 { |
1758 return NULL_RTX; | 1752 gcc_assert (GET_MODE (op) == op_mode); |
1759 | 1753 |
1760 machine_mode opmode = GET_MODE (op); | 1754 rtx_vector_builder builder; |
1761 gcc_assert (known_eq (GET_MODE_NUNITS (mode), n_elts)); | 1755 if (!builder.new_unary_operation (mode, op, false)) |
1762 gcc_assert (known_eq (GET_MODE_NUNITS (opmode), n_elts)); | 1756 return 0; |
1763 | 1757 |
1764 rtvec v = rtvec_alloc (n_elts); | 1758 unsigned int count = builder.encoded_nelts (); |
1765 unsigned int i; | 1759 for (unsigned int i = 0; i < count; i++) |
1766 | |
1767 for (i = 0; i < n_elts; i++) | |
1768 { | 1760 { |
1769 rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode), | 1761 rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode), |
1770 CONST_VECTOR_ELT (op, i), | 1762 CONST_VECTOR_ELT (op, i), |
1771 GET_MODE_INNER (opmode)); | 1763 GET_MODE_INNER (op_mode)); |
1772 if (!x || !valid_for_const_vector_p (mode, x)) | 1764 if (!x || !valid_for_const_vector_p (mode, x)) |
1773 return 0; | 1765 return 0; |
1774 RTVEC_ELT (v, i) = x; | 1766 builder.quick_push (x); |
1775 } | 1767 } |
1776 return gen_rtx_CONST_VECTOR (mode, v); | 1768 return builder.build (); |
1777 } | 1769 } |
1778 | 1770 |
1779 /* The order of these tests is critical so that, for example, we don't | 1771 /* The order of these tests is critical so that, for example, we don't |
1780 check the wrong mode (input vs. output) for a conversion operation, | 1772 check the wrong mode (input vs. output) for a conversion operation, |
1781 such as FIX. At some point, this should be simplified. */ | 1773 such as FIX. At some point, this should be simplified. */ |
1830 } | 1822 } |
1831 | 1823 |
1832 if (CONST_SCALAR_INT_P (op) && is_a <scalar_int_mode> (mode, &result_mode)) | 1824 if (CONST_SCALAR_INT_P (op) && is_a <scalar_int_mode> (mode, &result_mode)) |
1833 { | 1825 { |
1834 unsigned int width = GET_MODE_PRECISION (result_mode); | 1826 unsigned int width = GET_MODE_PRECISION (result_mode); |
1827 if (width > MAX_BITSIZE_MODE_ANY_INT) | |
1828 return 0; | |
1829 | |
1835 wide_int result; | 1830 wide_int result; |
1836 scalar_int_mode imode = (op_mode == VOIDmode | 1831 scalar_int_mode imode = (op_mode == VOIDmode |
1837 ? result_mode | 1832 ? result_mode |
1838 : as_a <scalar_int_mode> (op_mode)); | 1833 : as_a <scalar_int_mode> (op_mode)); |
1839 rtx_mode_t op0 = rtx_mode_t (op, imode); | 1834 rtx_mode_t op0 = rtx_mode_t (op, imode); |
1974 else if (CONST_DOUBLE_AS_FLOAT_P (op) | 1969 else if (CONST_DOUBLE_AS_FLOAT_P (op) |
1975 && SCALAR_FLOAT_MODE_P (GET_MODE (op)) | 1970 && SCALAR_FLOAT_MODE_P (GET_MODE (op)) |
1976 && is_int_mode (mode, &result_mode)) | 1971 && is_int_mode (mode, &result_mode)) |
1977 { | 1972 { |
1978 unsigned int width = GET_MODE_PRECISION (result_mode); | 1973 unsigned int width = GET_MODE_PRECISION (result_mode); |
1974 if (width > MAX_BITSIZE_MODE_ANY_INT) | |
1975 return 0; | |
1976 | |
1979 /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX | 1977 /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX |
1980 operators are intentionally left unspecified (to ease implementation | 1978 operators are intentionally left unspecified (to ease implementation |
1981 by target backends), for consistency, this routine implements the | 1979 by target backends), for consistency, this routine implements the |
1982 same semantics for constant folding as used by the middle-end. */ | 1980 same semantics for constant folding as used by the middle-end. */ |
1983 | 1981 |
2131 } | 2129 } |
2132 | 2130 |
2133 return 0; | 2131 return 0; |
2134 } | 2132 } |
2135 | 2133 |
2134 /* Return a mask describing the COMPARISON. */ | |
2135 static int | |
2136 comparison_to_mask (enum rtx_code comparison) | |
2137 { | |
2138 switch (comparison) | |
2139 { | |
2140 case LT: | |
2141 return 8; | |
2142 case GT: | |
2143 return 4; | |
2144 case EQ: | |
2145 return 2; | |
2146 case UNORDERED: | |
2147 return 1; | |
2148 | |
2149 case LTGT: | |
2150 return 12; | |
2151 case LE: | |
2152 return 10; | |
2153 case GE: | |
2154 return 6; | |
2155 case UNLT: | |
2156 return 9; | |
2157 case UNGT: | |
2158 return 5; | |
2159 case UNEQ: | |
2160 return 3; | |
2161 | |
2162 case ORDERED: | |
2163 return 14; | |
2164 case NE: | |
2165 return 13; | |
2166 case UNLE: | |
2167 return 11; | |
2168 case UNGE: | |
2169 return 7; | |
2170 | |
2171 default: | |
2172 gcc_unreachable (); | |
2173 } | |
2174 } | |
2175 | |
2176 /* Return a comparison corresponding to the MASK. */ | |
2177 static enum rtx_code | |
2178 mask_to_comparison (int mask) | |
2179 { | |
2180 switch (mask) | |
2181 { | |
2182 case 8: | |
2183 return LT; | |
2184 case 4: | |
2185 return GT; | |
2186 case 2: | |
2187 return EQ; | |
2188 case 1: | |
2189 return UNORDERED; | |
2190 | |
2191 case 12: | |
2192 return LTGT; | |
2193 case 10: | |
2194 return LE; | |
2195 case 6: | |
2196 return GE; | |
2197 case 9: | |
2198 return UNLT; | |
2199 case 5: | |
2200 return UNGT; | |
2201 case 3: | |
2202 return UNEQ; | |
2203 | |
2204 case 14: | |
2205 return ORDERED; | |
2206 case 13: | |
2207 return NE; | |
2208 case 11: | |
2209 return UNLE; | |
2210 case 7: | |
2211 return UNGE; | |
2212 | |
2213 default: | |
2214 gcc_unreachable (); | |
2215 } | |
2216 } | |
2217 | |
2218 /* Simplify a logical operation CODE with result mode MODE, operating on OP0 | |
2219 and OP1, which should be both relational operations. Return 0 if no such | |
2220 simplification is possible. */ | |
2221 rtx | |
2222 simplify_logical_relational_operation (enum rtx_code code, machine_mode mode, | |
2223 rtx op0, rtx op1) | |
2224 { | |
2225 /* We only handle IOR of two relational operations. */ | |
2226 if (code != IOR) | |
2227 return 0; | |
2228 | |
2229 if (!(COMPARISON_P (op0) && COMPARISON_P (op1))) | |
2230 return 0; | |
2231 | |
2232 if (!(rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) | |
2233 && rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1)))) | |
2234 return 0; | |
2235 | |
2236 enum rtx_code code0 = GET_CODE (op0); | |
2237 enum rtx_code code1 = GET_CODE (op1); | |
2238 | |
2239 /* We don't handle unsigned comparisons currently. */ | |
2240 if (code0 == LTU || code0 == GTU || code0 == LEU || code0 == GEU) | |
2241 return 0; | |
2242 if (code1 == LTU || code1 == GTU || code1 == LEU || code1 == GEU) | |
2243 return 0; | |
2244 | |
2245 int mask0 = comparison_to_mask (code0); | |
2246 int mask1 = comparison_to_mask (code1); | |
2247 | |
2248 int mask = mask0 | mask1; | |
2249 | |
2250 if (mask == 15) | |
2251 return const_true_rtx; | |
2252 | |
2253 code = mask_to_comparison (mask); | |
2254 | |
2255 op0 = XEXP (op1, 0); | |
2256 op1 = XEXP (op1, 1); | |
2257 | |
2258 return simplify_gen_relational (code, mode, VOIDmode, op0, op1); | |
2259 } | |
2136 | 2260 |
2137 /* Simplify a binary operation CODE with result mode MODE, operating on OP0 | 2261 /* Simplify a binary operation CODE with result mode MODE, operating on OP0 |
2138 and OP1. Return 0 if no simplification is possible. | 2262 and OP1. Return 0 if no simplification is possible. |
2139 | 2263 |
2140 Don't use this for relational operations such as EQ or LT. | 2264 Don't use this for relational operations such as EQ or LT. |
2547 || GET_CODE (op0) == LABEL_REF) | 2671 || GET_CODE (op0) == LABEL_REF) |
2548 && poly_int_rtx_p (op1, &offset)) | 2672 && poly_int_rtx_p (op1, &offset)) |
2549 return plus_constant (mode, op0, trunc_int_for_mode (-offset, mode)); | 2673 return plus_constant (mode, op0, trunc_int_for_mode (-offset, mode)); |
2550 | 2674 |
2551 /* Don't let a relocatable value get a negative coeff. */ | 2675 /* Don't let a relocatable value get a negative coeff. */ |
2552 if (CONST_INT_P (op1) && GET_MODE (op0) != VOIDmode) | 2676 if (poly_int_rtx_p (op1) && GET_MODE (op0) != VOIDmode) |
2553 return simplify_gen_binary (PLUS, mode, | 2677 return simplify_gen_binary (PLUS, mode, |
2554 op0, | 2678 op0, |
2555 neg_const_int (mode, op1)); | 2679 neg_poly_int_rtx (mode, op1)); |
2556 | 2680 |
2557 /* (x - (x & y)) -> (x & ~y) */ | 2681 /* (x - (x & y)) -> (x & ~y) */ |
2558 if (INTEGRAL_MODE_P (mode) && GET_CODE (op1) == AND) | 2682 if (INTEGRAL_MODE_P (mode) && GET_CODE (op1) == AND) |
2559 { | 2683 { |
2560 if (rtx_equal_p (op0, XEXP (op1, 0))) | 2684 if (rtx_equal_p (op0, XEXP (op1, 0))) |
2855 plus_constant (mode, XEXP (op0, 0), | 2979 plus_constant (mode, XEXP (op0, 0), |
2856 mask), | 2980 mask), |
2857 XEXP (op0, 1)); | 2981 XEXP (op0, 1)); |
2858 } | 2982 } |
2859 | 2983 |
2984 /* The following happens with bitfield merging. | |
2985 (X & C) | ((X | Y) & ~C) -> X | (Y & ~C) */ | |
2986 if (GET_CODE (op0) == AND | |
2987 && GET_CODE (op1) == AND | |
2988 && CONST_INT_P (XEXP (op0, 1)) | |
2989 && CONST_INT_P (XEXP (op1, 1)) | |
2990 && (INTVAL (XEXP (op0, 1)) | |
2991 == ~INTVAL (XEXP (op1, 1)))) | |
2992 { | |
2993 /* The IOR may be on both sides. */ | |
2994 rtx top0 = NULL_RTX, top1 = NULL_RTX; | |
2995 if (GET_CODE (XEXP (op1, 0)) == IOR) | |
2996 top0 = op0, top1 = op1; | |
2997 else if (GET_CODE (XEXP (op0, 0)) == IOR) | |
2998 top0 = op1, top1 = op0; | |
2999 if (top0 && top1) | |
3000 { | |
3001 /* X may be on either side of the inner IOR. */ | |
3002 rtx tem = NULL_RTX; | |
3003 if (rtx_equal_p (XEXP (top0, 0), | |
3004 XEXP (XEXP (top1, 0), 0))) | |
3005 tem = XEXP (XEXP (top1, 0), 1); | |
3006 else if (rtx_equal_p (XEXP (top0, 0), | |
3007 XEXP (XEXP (top1, 0), 1))) | |
3008 tem = XEXP (XEXP (top1, 0), 0); | |
3009 if (tem) | |
3010 return simplify_gen_binary (IOR, mode, XEXP (top0, 0), | |
3011 simplify_gen_binary | |
3012 (AND, mode, tem, XEXP (top1, 1))); | |
3013 } | |
3014 } | |
3015 | |
2860 tem = simplify_byte_swapping_operation (code, mode, op0, op1); | 3016 tem = simplify_byte_swapping_operation (code, mode, op0, op1); |
2861 if (tem) | 3017 if (tem) |
2862 return tem; | 3018 return tem; |
2863 | 3019 |
2864 tem = simplify_associative_operation (code, mode, op0, op1); | 3020 tem = simplify_associative_operation (code, mode, op0, op1); |
3021 if (tem) | |
3022 return tem; | |
3023 | |
3024 tem = simplify_logical_relational_operation (code, mode, op0, op1); | |
2865 if (tem) | 3025 if (tem) |
2866 return tem; | 3026 return tem; |
2867 break; | 3027 break; |
2868 | 3028 |
2869 case XOR: | 3029 case XOR: |
3485 == GET_MODE_BITSIZE (inner_mode) - GET_MODE_BITSIZE (int_mode)) | 3645 == GET_MODE_BITSIZE (inner_mode) - GET_MODE_BITSIZE (int_mode)) |
3486 && subreg_lowpart_p (op0)) | 3646 && subreg_lowpart_p (op0)) |
3487 { | 3647 { |
3488 rtx tmp = gen_int_shift_amount | 3648 rtx tmp = gen_int_shift_amount |
3489 (inner_mode, INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (op1)); | 3649 (inner_mode, INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (op1)); |
3490 tmp = simplify_gen_binary (code, inner_mode, | 3650 |
3491 XEXP (SUBREG_REG (op0), 0), | 3651 /* Combine would usually zero out the value when combining two |
3492 tmp); | 3652 local shifts and the range becomes larger or equal to the mode. |
3653 However since we fold away one of the shifts here combine won't | |
3654 see it so we should immediately zero the result if it's out of | |
3655 range. */ | |
3656 if (code == LSHIFTRT | |
3657 && INTVAL (tmp) >= GET_MODE_BITSIZE (inner_mode)) | |
3658 tmp = const0_rtx; | |
3659 else | |
3660 tmp = simplify_gen_binary (code, | |
3661 inner_mode, | |
3662 XEXP (SUBREG_REG (op0), 0), | |
3663 tmp); | |
3664 | |
3493 return lowpart_subreg (int_mode, tmp, inner_mode); | 3665 return lowpart_subreg (int_mode, tmp, inner_mode); |
3494 } | 3666 } |
3495 | 3667 |
3496 if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1)) | 3668 if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1)) |
3497 { | 3669 { |
4025 } | 4197 } |
4026 | 4198 |
4027 return 0; | 4199 return 0; |
4028 } | 4200 } |
4029 | 4201 |
4202 /* Return true if binary operation OP distributes over addition in operand | |
4203 OPNO, with the other operand being held constant. OPNO counts from 1. */ | |
4204 | |
4205 static bool | |
4206 distributes_over_addition_p (rtx_code op, int opno) | |
4207 { | |
4208 switch (op) | |
4209 { | |
4210 case PLUS: | |
4211 case MINUS: | |
4212 case MULT: | |
4213 return true; | |
4214 | |
4215 case ASHIFT: | |
4216 return opno == 1; | |
4217 | |
4218 default: | |
4219 return false; | |
4220 } | |
4221 } | |
4222 | |
4030 rtx | 4223 rtx |
4031 simplify_const_binary_operation (enum rtx_code code, machine_mode mode, | 4224 simplify_const_binary_operation (enum rtx_code code, machine_mode mode, |
4032 rtx op0, rtx op1) | 4225 rtx op0, rtx op1) |
4033 { | 4226 { |
4034 if (VECTOR_MODE_P (mode) | 4227 if (VECTOR_MODE_P (mode) |
4035 && code != VEC_CONCAT | 4228 && code != VEC_CONCAT |
4036 && GET_CODE (op0) == CONST_VECTOR | 4229 && GET_CODE (op0) == CONST_VECTOR |
4037 && GET_CODE (op1) == CONST_VECTOR) | 4230 && GET_CODE (op1) == CONST_VECTOR) |
4038 { | 4231 { |
4039 unsigned int n_elts; | 4232 bool step_ok_p; |
4040 if (!CONST_VECTOR_NUNITS (op0).is_constant (&n_elts)) | 4233 if (CONST_VECTOR_STEPPED_P (op0) |
4041 return NULL_RTX; | 4234 && CONST_VECTOR_STEPPED_P (op1)) |
4042 | 4235 /* We can operate directly on the encoding if: |
4043 gcc_assert (known_eq (n_elts, CONST_VECTOR_NUNITS (op1))); | 4236 |
4044 gcc_assert (known_eq (n_elts, GET_MODE_NUNITS (mode))); | 4237 a3 - a2 == a2 - a1 && b3 - b2 == b2 - b1 |
4045 rtvec v = rtvec_alloc (n_elts); | 4238 implies |
4046 unsigned int i; | 4239 (a3 op b3) - (a2 op b2) == (a2 op b2) - (a1 op b1) |
4047 | 4240 |
4048 for (i = 0; i < n_elts; i++) | 4241 Addition and subtraction are the supported operators |
4242 for which this is true. */ | |
4243 step_ok_p = (code == PLUS || code == MINUS); | |
4244 else if (CONST_VECTOR_STEPPED_P (op0)) | |
4245 /* We can operate directly on stepped encodings if: | |
4246 | |
4247 a3 - a2 == a2 - a1 | |
4248 implies: | |
4249 (a3 op c) - (a2 op c) == (a2 op c) - (a1 op c) | |
4250 | |
4251 which is true if (x -> x op c) distributes over addition. */ | |
4252 step_ok_p = distributes_over_addition_p (code, 1); | |
4253 else | |
4254 /* Similarly in reverse. */ | |
4255 step_ok_p = distributes_over_addition_p (code, 2); | |
4256 rtx_vector_builder builder; | |
4257 if (!builder.new_binary_operation (mode, op0, op1, step_ok_p)) | |
4258 return 0; | |
4259 | |
4260 unsigned int count = builder.encoded_nelts (); | |
4261 for (unsigned int i = 0; i < count; i++) | |
4049 { | 4262 { |
4050 rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), | 4263 rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), |
4051 CONST_VECTOR_ELT (op0, i), | 4264 CONST_VECTOR_ELT (op0, i), |
4052 CONST_VECTOR_ELT (op1, i)); | 4265 CONST_VECTOR_ELT (op1, i)); |
4053 if (!x || !valid_for_const_vector_p (mode, x)) | 4266 if (!x || !valid_for_const_vector_p (mode, x)) |
4054 return 0; | 4267 return 0; |
4055 RTVEC_ELT (v, i) = x; | 4268 builder.quick_push (x); |
4056 } | 4269 } |
4057 | 4270 return builder.build (); |
4058 return gen_rtx_CONST_VECTOR (mode, v); | |
4059 } | 4271 } |
4060 | 4272 |
4061 if (VECTOR_MODE_P (mode) | 4273 if (VECTOR_MODE_P (mode) |
4062 && code == VEC_CONCAT | 4274 && code == VEC_CONCAT |
4063 && (CONST_SCALAR_INT_P (op0) | 4275 && (CONST_SCALAR_INT_P (op0) |
4226 | 4438 |
4227 /* We can fold some multi-word operations. */ | 4439 /* We can fold some multi-word operations. */ |
4228 scalar_int_mode int_mode; | 4440 scalar_int_mode int_mode; |
4229 if (is_a <scalar_int_mode> (mode, &int_mode) | 4441 if (is_a <scalar_int_mode> (mode, &int_mode) |
4230 && CONST_SCALAR_INT_P (op0) | 4442 && CONST_SCALAR_INT_P (op0) |
4231 && CONST_SCALAR_INT_P (op1)) | 4443 && CONST_SCALAR_INT_P (op1) |
4444 && GET_MODE_PRECISION (int_mode) <= MAX_BITSIZE_MODE_ANY_INT) | |
4232 { | 4445 { |
4233 wide_int result; | 4446 wide_int result; |
4234 wi::overflow_type overflow; | 4447 wi::overflow_type overflow; |
4235 rtx_mode_t pop0 = rtx_mode_t (op0, int_mode); | 4448 rtx_mode_t pop0 = rtx_mode_t (op0, int_mode); |
4236 rtx_mode_t pop1 = rtx_mode_t (op1, int_mode); | 4449 rtx_mode_t pop1 = rtx_mode_t (op1, int_mode); |
4547 changed = 1; | 4760 changed = 1; |
4548 canonicalized = 1; | 4761 canonicalized = 1; |
4549 } | 4762 } |
4550 break; | 4763 break; |
4551 | 4764 |
4552 case CONST_INT: | 4765 CASE_CONST_SCALAR_INT: |
4766 case CONST_POLY_INT: | |
4553 n_constants++; | 4767 n_constants++; |
4554 if (this_neg) | 4768 if (this_neg) |
4555 { | 4769 { |
4556 ops[i].op = neg_const_int (mode, this_op); | 4770 ops[i].op = neg_poly_int_rtx (mode, this_op); |
4557 ops[i].neg = 0; | 4771 ops[i].neg = 0; |
4558 changed = 1; | 4772 changed = 1; |
4559 canonicalized = 1; | 4773 canonicalized = 1; |
4560 } | 4774 } |
4561 break; | 4775 break; |
4676 && XEXP (XEXP (tem, 0), 1) == rhs) | 4890 && XEXP (XEXP (tem, 0), 1) == rhs) |
4677 break; | 4891 break; |
4678 lneg &= rneg; | 4892 lneg &= rneg; |
4679 if (GET_CODE (tem) == NEG) | 4893 if (GET_CODE (tem) == NEG) |
4680 tem = XEXP (tem, 0), lneg = !lneg; | 4894 tem = XEXP (tem, 0), lneg = !lneg; |
4681 if (CONST_INT_P (tem) && lneg) | 4895 if (poly_int_rtx_p (tem) && lneg) |
4682 tem = neg_const_int (mode, tem), lneg = 0; | 4896 tem = neg_poly_int_rtx (mode, tem), lneg = 0; |
4683 | 4897 |
4684 ops[i].op = tem; | 4898 ops[i].op = tem; |
4685 ops[i].neg = lneg; | 4899 ops[i].neg = lneg; |
4686 ops[j].op = NULL_RTX; | 4900 ops[j].op = NULL_RTX; |
4687 changed = 1; | 4901 changed = 1; |
4736 The combination loop should have ensured that there is exactly | 4950 The combination loop should have ensured that there is exactly |
4737 one CONST_INT, and the sort will have ensured that it is last | 4951 one CONST_INT, and the sort will have ensured that it is last |
4738 in the array and that any other constant will be next-to-last. */ | 4952 in the array and that any other constant will be next-to-last. */ |
4739 | 4953 |
4740 if (n_ops > 1 | 4954 if (n_ops > 1 |
4741 && CONST_INT_P (ops[n_ops - 1].op) | 4955 && poly_int_rtx_p (ops[n_ops - 1].op) |
4742 && CONSTANT_P (ops[n_ops - 2].op)) | 4956 && CONSTANT_P (ops[n_ops - 2].op)) |
4743 { | 4957 { |
4744 rtx value = ops[n_ops - 1].op; | 4958 rtx value = ops[n_ops - 1].op; |
4745 if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg) | 4959 if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg) |
4746 value = neg_const_int (mode, value); | 4960 value = neg_poly_int_rtx (mode, value); |
4747 if (CONST_INT_P (value)) | 4961 if (CONST_INT_P (value)) |
4748 { | 4962 { |
4749 ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op, | 4963 ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op, |
4750 INTVAL (value)); | 4964 INTVAL (value)); |
4751 n_ops--; | 4965 n_ops--; |
4840 } | 5054 } |
4841 #else | 5055 #else |
4842 return NULL_RTX; | 5056 return NULL_RTX; |
4843 #endif | 5057 #endif |
4844 } | 5058 } |
5059 /* For vector comparison with scalar int result, it is unknown | |
5060 if the target means here a comparison into an integral bitmask, | |
5061 or comparison where all comparisons true mean const_true_rtx | |
5062 whole result, or where any comparisons true mean const_true_rtx | |
5063 whole result. For const0_rtx all the cases are the same. */ | |
5064 if (VECTOR_MODE_P (cmp_mode) | |
5065 && SCALAR_INT_MODE_P (mode) | |
5066 && tem == const_true_rtx) | |
5067 return NULL_RTX; | |
4845 | 5068 |
4846 return tem; | 5069 return tem; |
4847 } | 5070 } |
4848 | 5071 |
4849 /* For the following tests, ensure const0_rtx is op1. */ | 5072 /* For the following tests, ensure const0_rtx is op1. */ |
5186 gcc_unreachable (); | 5409 gcc_unreachable (); |
5187 } | 5410 } |
5188 } | 5411 } |
5189 | 5412 |
5190 /* Check if the given comparison (done in the given MODE) is actually | 5413 /* Check if the given comparison (done in the given MODE) is actually |
5191 a tautology or a contradiction. If the mode is VOID_mode, the | 5414 a tautology or a contradiction. If the mode is VOIDmode, the |
5192 comparison is done in "infinite precision". If no simplification | 5415 comparison is done in "infinite precision". If no simplification |
5193 is possible, this function returns zero. Otherwise, it returns | 5416 is possible, this function returns zero. Otherwise, it returns |
5194 either const_true_rtx or const0_rtx. */ | 5417 either const_true_rtx or const0_rtx. */ |
5195 | 5418 |
5196 rtx | 5419 rtx |
5613 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 1))), nunits)) | 5836 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 1))), nunits)) |
5614 { | 5837 { |
5615 rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op); | 5838 rtx top0 = simplify_merge_mask (XEXP (x, 0), mask, op); |
5616 rtx top1 = simplify_merge_mask (XEXP (x, 1), mask, op); | 5839 rtx top1 = simplify_merge_mask (XEXP (x, 1), mask, op); |
5617 if (top0 || top1) | 5840 if (top0 || top1) |
5618 return simplify_gen_binary (GET_CODE (x), GET_MODE (x), | 5841 { |
5619 top0 ? top0 : XEXP (x, 0), | 5842 if (COMPARISON_P (x)) |
5620 top1 ? top1 : XEXP (x, 1)); | 5843 return simplify_gen_relational (GET_CODE (x), GET_MODE (x), |
5844 GET_MODE (XEXP (x, 0)) != VOIDmode | |
5845 ? GET_MODE (XEXP (x, 0)) | |
5846 : GET_MODE (XEXP (x, 1)), | |
5847 top0 ? top0 : XEXP (x, 0), | |
5848 top1 ? top1 : XEXP (x, 1)); | |
5849 else | |
5850 return simplify_gen_binary (GET_CODE (x), GET_MODE (x), | |
5851 top0 ? top0 : XEXP (x, 0), | |
5852 top1 ? top1 : XEXP (x, 1)); | |
5853 } | |
5621 } | 5854 } |
5622 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY | 5855 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY |
5623 && VECTOR_MODE_P (GET_MODE (XEXP (x, 0))) | 5856 && VECTOR_MODE_P (GET_MODE (XEXP (x, 0))) |
5624 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits) | 5857 && known_eq (GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))), nunits) |
5625 && VECTOR_MODE_P (GET_MODE (XEXP (x, 1))) | 5858 && VECTOR_MODE_P (GET_MODE (XEXP (x, 1))) |
6029 && !side_effects_p (op2) && !side_effects_p (op1)) | 6262 && !side_effects_p (op2) && !side_effects_p (op1)) |
6030 return op0; | 6263 return op0; |
6031 | 6264 |
6032 if (!side_effects_p (op2)) | 6265 if (!side_effects_p (op2)) |
6033 { | 6266 { |
6034 rtx top0 = simplify_merge_mask (op0, op2, 0); | 6267 rtx top0 |
6035 rtx top1 = simplify_merge_mask (op1, op2, 1); | 6268 = may_trap_p (op0) ? NULL_RTX : simplify_merge_mask (op0, op2, 0); |
6269 rtx top1 | |
6270 = may_trap_p (op1) ? NULL_RTX : simplify_merge_mask (op1, op2, 1); | |
6036 if (top0 || top1) | 6271 if (top0 || top1) |
6037 return simplify_gen_ternary (code, mode, mode, | 6272 return simplify_gen_ternary (code, mode, mode, |
6038 top0 ? top0 : op0, | 6273 top0 ? top0 : op0, |
6039 top1 ? top1 : op1, op2); | 6274 top1 ? top1 : op1, op2); |
6040 } | 6275 } |
6046 } | 6281 } |
6047 | 6282 |
6048 return 0; | 6283 return 0; |
6049 } | 6284 } |
6050 | 6285 |
6051 /* Evaluate a SUBREG of a CONST_INT or CONST_WIDE_INT or CONST_DOUBLE | 6286 /* Try to calculate NUM_BYTES bytes of the target memory image of X, |
6052 or CONST_FIXED or CONST_VECTOR, returning another CONST_INT or | 6287 starting at byte FIRST_BYTE. Return true on success and add the |
6053 CONST_WIDE_INT or CONST_DOUBLE or CONST_FIXED or CONST_VECTOR. | 6288 bytes to BYTES, such that each byte has BITS_PER_UNIT bits and such |
6054 | 6289 that the bytes follow target memory order. Leave BYTES unmodified |
6055 Works by unpacking INNER_BYTES bytes of OP into a collection of 8-bit values | 6290 on failure. |
6056 represented as a little-endian array of 'unsigned char', selecting by BYTE, | 6291 |
6057 and then repacking them again for OUTERMODE. If OP is a CONST_VECTOR, | 6292 MODE is the mode of X. The caller must reserve NUM_BYTES bytes in |
6058 FIRST_ELEM is the number of the first element to extract, otherwise | 6293 BYTES before calling this function. */ |
6059 FIRST_ELEM is ignored. */ | 6294 |
6295 bool | |
6296 native_encode_rtx (machine_mode mode, rtx x, vec<target_unit> &bytes, | |
6297 unsigned int first_byte, unsigned int num_bytes) | |
6298 { | |
6299 /* Check the mode is sensible. */ | |
6300 gcc_assert (GET_MODE (x) == VOIDmode | |
6301 ? is_a <scalar_int_mode> (mode) | |
6302 : mode == GET_MODE (x)); | |
6303 | |
6304 if (GET_CODE (x) == CONST_VECTOR) | |
6305 { | |
6306 /* CONST_VECTOR_ELT follows target memory order, so no shuffling | |
6307 is necessary. The only complication is that MODE_VECTOR_BOOL | |
6308 vectors can have several elements per byte. */ | |
6309 unsigned int elt_bits = vector_element_size (GET_MODE_BITSIZE (mode), | |
6310 GET_MODE_NUNITS (mode)); | |
6311 unsigned int elt = first_byte * BITS_PER_UNIT / elt_bits; | |
6312 if (elt_bits < BITS_PER_UNIT) | |
6313 { | |
6314 /* This is the only case in which elements can be smaller than | |
6315 a byte. */ | |
6316 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL); | |
6317 for (unsigned int i = 0; i < num_bytes; ++i) | |
6318 { | |
6319 target_unit value = 0; | |
6320 for (unsigned int j = 0; j < BITS_PER_UNIT; j += elt_bits) | |
6321 { | |
6322 value |= (INTVAL (CONST_VECTOR_ELT (x, elt)) & 1) << j; | |
6323 elt += 1; | |
6324 } | |
6325 bytes.quick_push (value); | |
6326 } | |
6327 return true; | |
6328 } | |
6329 | |
6330 unsigned int start = bytes.length (); | |
6331 unsigned int elt_bytes = GET_MODE_UNIT_SIZE (mode); | |
6332 /* Make FIRST_BYTE relative to ELT. */ | |
6333 first_byte %= elt_bytes; | |
6334 while (num_bytes > 0) | |
6335 { | |
6336 /* Work out how many bytes we want from element ELT. */ | |
6337 unsigned int chunk_bytes = MIN (num_bytes, elt_bytes - first_byte); | |
6338 if (!native_encode_rtx (GET_MODE_INNER (mode), | |
6339 CONST_VECTOR_ELT (x, elt), bytes, | |
6340 first_byte, chunk_bytes)) | |
6341 { | |
6342 bytes.truncate (start); | |
6343 return false; | |
6344 } | |
6345 elt += 1; | |
6346 first_byte = 0; | |
6347 num_bytes -= chunk_bytes; | |
6348 } | |
6349 return true; | |
6350 } | |
6351 | |
6352 /* All subsequent cases are limited to scalars. */ | |
6353 scalar_mode smode; | |
6354 if (!is_a <scalar_mode> (mode, &smode)) | |
6355 return false; | |
6356 | |
6357 /* Make sure that the region is in range. */ | |
6358 unsigned int end_byte = first_byte + num_bytes; | |
6359 unsigned int mode_bytes = GET_MODE_SIZE (smode); | |
6360 gcc_assert (end_byte <= mode_bytes); | |
6361 | |
6362 if (CONST_SCALAR_INT_P (x)) | |
6363 { | |
6364 /* The target memory layout is affected by both BYTES_BIG_ENDIAN | |
6365 and WORDS_BIG_ENDIAN. Use the subreg machinery to get the lsb | |
6366 position of each byte. */ | |
6367 rtx_mode_t value (x, smode); | |
6368 wide_int_ref value_wi (value); | |
6369 for (unsigned int byte = first_byte; byte < end_byte; ++byte) | |
6370 { | |
6371 /* Always constant because the inputs are. */ | |
6372 unsigned int lsb | |
6373 = subreg_size_lsb (1, mode_bytes, byte).to_constant (); | |
6374 /* Operate directly on the encoding rather than using | |
6375 wi::extract_uhwi, so that we preserve the sign or zero | |
6376 extension for modes that are not a whole number of bits in | |
6377 size. (Zero extension is only used for the combination of | |
6378 innermode == BImode && STORE_FLAG_VALUE == 1). */ | |
6379 unsigned int elt = lsb / HOST_BITS_PER_WIDE_INT; | |
6380 unsigned int shift = lsb % HOST_BITS_PER_WIDE_INT; | |
6381 unsigned HOST_WIDE_INT uhwi = value_wi.elt (elt); | |
6382 bytes.quick_push (uhwi >> shift); | |
6383 } | |
6384 return true; | |
6385 } | |
6386 | |
6387 if (CONST_DOUBLE_P (x)) | |
6388 { | |
6389 /* real_to_target produces an array of integers in target memory order. | |
6390 All integers before the last one have 32 bits; the last one may | |
6391 have 32 bits or fewer, depending on whether the mode bitsize | |
6392 is divisible by 32. Each of these integers is then laid out | |
6393 in target memory as any other integer would be. */ | |
6394 long el32[MAX_BITSIZE_MODE_ANY_MODE / 32]; | |
6395 real_to_target (el32, CONST_DOUBLE_REAL_VALUE (x), smode); | |
6396 | |
6397 /* The (maximum) number of target bytes per element of el32. */ | |
6398 unsigned int bytes_per_el32 = 32 / BITS_PER_UNIT; | |
6399 gcc_assert (bytes_per_el32 != 0); | |
6400 | |
6401 /* Build up the integers in a similar way to the CONST_SCALAR_INT_P | |
6402 handling above. */ | |
6403 for (unsigned int byte = first_byte; byte < end_byte; ++byte) | |
6404 { | |
6405 unsigned int index = byte / bytes_per_el32; | |
6406 unsigned int subbyte = byte % bytes_per_el32; | |
6407 unsigned int int_bytes = MIN (bytes_per_el32, | |
6408 mode_bytes - index * bytes_per_el32); | |
6409 /* Always constant because the inputs are. */ | |
6410 unsigned int lsb | |
6411 = subreg_size_lsb (1, int_bytes, subbyte).to_constant (); | |
6412 bytes.quick_push ((unsigned long) el32[index] >> lsb); | |
6413 } | |
6414 return true; | |
6415 } | |
6416 | |
6417 if (GET_CODE (x) == CONST_FIXED) | |
6418 { | |
6419 for (unsigned int byte = first_byte; byte < end_byte; ++byte) | |
6420 { | |
6421 /* Always constant because the inputs are. */ | |
6422 unsigned int lsb | |
6423 = subreg_size_lsb (1, mode_bytes, byte).to_constant (); | |
6424 unsigned HOST_WIDE_INT piece = CONST_FIXED_VALUE_LOW (x); | |
6425 if (lsb >= HOST_BITS_PER_WIDE_INT) | |
6426 { | |
6427 lsb -= HOST_BITS_PER_WIDE_INT; | |
6428 piece = CONST_FIXED_VALUE_HIGH (x); | |
6429 } | |
6430 bytes.quick_push (piece >> lsb); | |
6431 } | |
6432 return true; | |
6433 } | |
6434 | |
6435 return false; | |
6436 } | |
6437 | |
6438 /* Read a vector of mode MODE from the target memory image given by BYTES, | |
6439 starting at byte FIRST_BYTE. The vector is known to be encodable using | |
6440 NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements each, | |
6441 and BYTES is known to have enough bytes to supply NPATTERNS * | |
6442 NELTS_PER_PATTERN vector elements. Each element of BYTES contains | |
6443 BITS_PER_UNIT bits and the bytes are in target memory order. | |
6444 | |
6445 Return the vector on success, otherwise return NULL_RTX. */ | |
6446 | |
6447 rtx | |
6448 native_decode_vector_rtx (machine_mode mode, vec<target_unit> bytes, | |
6449 unsigned int first_byte, unsigned int npatterns, | |
6450 unsigned int nelts_per_pattern) | |
6451 { | |
6452 rtx_vector_builder builder (mode, npatterns, nelts_per_pattern); | |
6453 | |
6454 unsigned int elt_bits = vector_element_size (GET_MODE_BITSIZE (mode), | |
6455 GET_MODE_NUNITS (mode)); | |
6456 if (elt_bits < BITS_PER_UNIT) | |
6457 { | |
6458 /* This is the only case in which elements can be smaller than a byte. | |
6459 Element 0 is always in the lsb of the containing byte. */ | |
6460 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL); | |
6461 for (unsigned int i = 0; i < builder.encoded_nelts (); ++i) | |
6462 { | |
6463 unsigned int bit_index = first_byte * BITS_PER_UNIT + i * elt_bits; | |
6464 unsigned int byte_index = bit_index / BITS_PER_UNIT; | |
6465 unsigned int lsb = bit_index % BITS_PER_UNIT; | |
6466 builder.quick_push (bytes[byte_index] & (1 << lsb) | |
6467 ? CONST1_RTX (BImode) | |
6468 : CONST0_RTX (BImode)); | |
6469 } | |
6470 } | |
6471 else | |
6472 { | |
6473 for (unsigned int i = 0; i < builder.encoded_nelts (); ++i) | |
6474 { | |
6475 rtx x = native_decode_rtx (GET_MODE_INNER (mode), bytes, first_byte); | |
6476 if (!x) | |
6477 return NULL_RTX; | |
6478 builder.quick_push (x); | |
6479 first_byte += elt_bits / BITS_PER_UNIT; | |
6480 } | |
6481 } | |
6482 return builder.build (); | |
6483 } | |
6484 | |
6485 /* Read an rtx of mode MODE from the target memory image given by BYTES, | |
6486 starting at byte FIRST_BYTE. Each element of BYTES contains BITS_PER_UNIT | |
6487 bits and the bytes are in target memory order. The image has enough | |
6488 values to specify all bytes of MODE. | |
6489 | |
6490 Return the rtx on success, otherwise return NULL_RTX. */ | |
6491 | |
6492 rtx | |
6493 native_decode_rtx (machine_mode mode, vec<target_unit> bytes, | |
6494 unsigned int first_byte) | |
6495 { | |
6496 if (VECTOR_MODE_P (mode)) | |
6497 { | |
6498 /* If we know at compile time how many elements there are, | |
6499 pull each element directly from BYTES. */ | |
6500 unsigned int nelts; | |
6501 if (GET_MODE_NUNITS (mode).is_constant (&nelts)) | |
6502 return native_decode_vector_rtx (mode, bytes, first_byte, nelts, 1); | |
6503 return NULL_RTX; | |
6504 } | |
6505 | |
6506 scalar_int_mode imode; | |
6507 if (is_a <scalar_int_mode> (mode, &imode) | |
6508 && GET_MODE_PRECISION (imode) <= MAX_BITSIZE_MODE_ANY_INT) | |
6509 { | |
6510 /* Pull the bytes msb first, so that we can use simple | |
6511 shift-and-insert wide_int operations. */ | |
6512 unsigned int size = GET_MODE_SIZE (imode); | |
6513 wide_int result (wi::zero (GET_MODE_PRECISION (imode))); | |
6514 for (unsigned int i = 0; i < size; ++i) | |
6515 { | |
6516 unsigned int lsb = (size - i - 1) * BITS_PER_UNIT; | |
6517 /* Always constant because the inputs are. */ | |
6518 unsigned int subbyte | |
6519 = subreg_size_offset_from_lsb (1, size, lsb).to_constant (); | |
6520 result <<= BITS_PER_UNIT; | |
6521 result |= bytes[first_byte + subbyte]; | |
6522 } | |
6523 return immed_wide_int_const (result, imode); | |
6524 } | |
6525 | |
6526 scalar_float_mode fmode; | |
6527 if (is_a <scalar_float_mode> (mode, &fmode)) | |
6528 { | |
6529 /* We need to build an array of integers in target memory order. | |
6530 All integers before the last one have 32 bits; the last one may | |
6531 have 32 bits or fewer, depending on whether the mode bitsize | |
6532 is divisible by 32. */ | |
6533 long el32[MAX_BITSIZE_MODE_ANY_MODE / 32]; | |
6534 unsigned int num_el32 = CEIL (GET_MODE_BITSIZE (fmode), 32); | |
6535 memset (el32, 0, num_el32 * sizeof (long)); | |
6536 | |
6537 /* The (maximum) number of target bytes per element of el32. */ | |
6538 unsigned int bytes_per_el32 = 32 / BITS_PER_UNIT; | |
6539 gcc_assert (bytes_per_el32 != 0); | |
6540 | |
6541 unsigned int mode_bytes = GET_MODE_SIZE (fmode); | |
6542 for (unsigned int byte = 0; byte < mode_bytes; ++byte) | |
6543 { | |
6544 unsigned int index = byte / bytes_per_el32; | |
6545 unsigned int subbyte = byte % bytes_per_el32; | |
6546 unsigned int int_bytes = MIN (bytes_per_el32, | |
6547 mode_bytes - index * bytes_per_el32); | |
6548 /* Always constant because the inputs are. */ | |
6549 unsigned int lsb | |
6550 = subreg_size_lsb (1, int_bytes, subbyte).to_constant (); | |
6551 el32[index] |= (unsigned long) bytes[first_byte + byte] << lsb; | |
6552 } | |
6553 REAL_VALUE_TYPE r; | |
6554 real_from_target (&r, el32, fmode); | |
6555 return const_double_from_real_value (r, fmode); | |
6556 } | |
6557 | |
6558 if (ALL_SCALAR_FIXED_POINT_MODE_P (mode)) | |
6559 { | |
6560 scalar_mode smode = as_a <scalar_mode> (mode); | |
6561 FIXED_VALUE_TYPE f; | |
6562 f.data.low = 0; | |
6563 f.data.high = 0; | |
6564 f.mode = smode; | |
6565 | |
6566 unsigned int mode_bytes = GET_MODE_SIZE (smode); | |
6567 for (unsigned int byte = 0; byte < mode_bytes; ++byte) | |
6568 { | |
6569 /* Always constant because the inputs are. */ | |
6570 unsigned int lsb | |
6571 = subreg_size_lsb (1, mode_bytes, byte).to_constant (); | |
6572 unsigned HOST_WIDE_INT unit = bytes[first_byte + byte]; | |
6573 if (lsb >= HOST_BITS_PER_WIDE_INT) | |
6574 f.data.high |= unit << (lsb - HOST_BITS_PER_WIDE_INT); | |
6575 else | |
6576 f.data.low |= unit << lsb; | |
6577 } | |
6578 return CONST_FIXED_FROM_FIXED_VALUE (f, mode); | |
6579 } | |
6580 | |
6581 return NULL_RTX; | |
6582 } | |
6583 | |
6584 /* Simplify a byte offset BYTE into CONST_VECTOR X. The main purpose | |
6585 is to convert a runtime BYTE value into a constant one. */ | |
6586 | |
6587 static poly_uint64 | |
6588 simplify_const_vector_byte_offset (rtx x, poly_uint64 byte) | |
6589 { | |
6590 /* Cope with MODE_VECTOR_BOOL by operating on bits rather than bytes. */ | |
6591 machine_mode mode = GET_MODE (x); | |
6592 unsigned int elt_bits = vector_element_size (GET_MODE_BITSIZE (mode), | |
6593 GET_MODE_NUNITS (mode)); | |
6594 /* The number of bits needed to encode one element from each pattern. */ | |
6595 unsigned int sequence_bits = CONST_VECTOR_NPATTERNS (x) * elt_bits; | |
6596 | |
6597 /* Identify the start point in terms of a sequence number and a byte offset | |
6598 within that sequence. */ | |
6599 poly_uint64 first_sequence; | |
6600 unsigned HOST_WIDE_INT subbit; | |
6601 if (can_div_trunc_p (byte * BITS_PER_UNIT, sequence_bits, | |
6602 &first_sequence, &subbit)) | |
6603 { | |
6604 unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (x); | |
6605 if (nelts_per_pattern == 1) | |
6606 /* This is a duplicated vector, so the value of FIRST_SEQUENCE | |
6607 doesn't matter. */ | |
6608 byte = subbit / BITS_PER_UNIT; | |
6609 else if (nelts_per_pattern == 2 && known_gt (first_sequence, 0U)) | |
6610 { | |
6611 /* The subreg drops the first element from each pattern and | |
6612 only uses the second element. Find the first sequence | |
6613 that starts on a byte boundary. */ | |
6614 subbit += least_common_multiple (sequence_bits, BITS_PER_UNIT); | |
6615 byte = subbit / BITS_PER_UNIT; | |
6616 } | |
6617 } | |
6618 return byte; | |
6619 } | |
6620 | |
6621 /* Subroutine of simplify_subreg in which: | |
6622 | |
6623 - X is known to be a CONST_VECTOR | |
6624 - OUTERMODE is known to be a vector mode | |
6625 | |
6626 Try to handle the subreg by operating on the CONST_VECTOR encoding | |
6627 rather than on each individual element of the CONST_VECTOR. | |
6628 | |
6629 Return the simplified subreg on success, otherwise return NULL_RTX. */ | |
6060 | 6630 |
6061 static rtx | 6631 static rtx |
6062 simplify_immed_subreg (fixed_size_mode outermode, rtx op, | 6632 simplify_const_vector_subreg (machine_mode outermode, rtx x, |
6063 machine_mode innermode, unsigned int byte, | 6633 machine_mode innermode, unsigned int first_byte) |
6064 unsigned int first_elem, unsigned int inner_bytes) | |
6065 { | 6634 { |
6066 enum { | 6635 /* Paradoxical subregs of vectors have dubious semantics. */ |
6067 value_bit = 8, | 6636 if (paradoxical_subreg_p (outermode, innermode)) |
6068 value_mask = (1 << value_bit) - 1 | 6637 return NULL_RTX; |
6069 }; | 6638 |
6070 unsigned char value[MAX_BITSIZE_MODE_ANY_MODE / value_bit]; | 6639 /* We can only preserve the semantics of a stepped pattern if the new |
6071 int value_start; | 6640 vector element is the same as the original one. */ |
6072 int i; | 6641 if (CONST_VECTOR_STEPPED_P (x) |
6073 int elem; | 6642 && GET_MODE_INNER (outermode) != GET_MODE_INNER (innermode)) |
6074 | 6643 return NULL_RTX; |
6075 int num_elem; | 6644 |
6076 rtx * elems; | 6645 /* Cope with MODE_VECTOR_BOOL by operating on bits rather than bytes. */ |
6077 int elem_bitsize; | 6646 unsigned int x_elt_bits |
6078 rtx result_s = NULL; | 6647 = vector_element_size (GET_MODE_BITSIZE (innermode), |
6079 rtvec result_v = NULL; | 6648 GET_MODE_NUNITS (innermode)); |
6080 enum mode_class outer_class; | 6649 unsigned int out_elt_bits |
6081 scalar_mode outer_submode; | 6650 = vector_element_size (GET_MODE_BITSIZE (outermode), |
6082 int max_bitsize; | 6651 GET_MODE_NUNITS (outermode)); |
6652 | |
6653 /* The number of bits needed to encode one element from every pattern | |
6654 of the original vector. */ | |
6655 unsigned int x_sequence_bits = CONST_VECTOR_NPATTERNS (x) * x_elt_bits; | |
6656 | |
6657 /* The number of bits needed to encode one element from every pattern | |
6658 of the result. */ | |
6659 unsigned int out_sequence_bits | |
6660 = least_common_multiple (x_sequence_bits, out_elt_bits); | |
6661 | |
6662 /* Work out the number of interleaved patterns in the output vector | |
6663 and the number of encoded elements per pattern. */ | |
6664 unsigned int out_npatterns = out_sequence_bits / out_elt_bits; | |
6665 unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (x); | |
6666 | |
6667 /* The encoding scheme requires the number of elements to be a multiple | |
6668 of the number of patterns, so that each pattern appears at least once | |
6669 and so that the same number of elements appear from each pattern. */ | |
6670 bool ok_p = multiple_p (GET_MODE_NUNITS (outermode), out_npatterns); | |
6671 unsigned int const_nunits; | |
6672 if (GET_MODE_NUNITS (outermode).is_constant (&const_nunits) | |
6673 && (!ok_p || out_npatterns * nelts_per_pattern > const_nunits)) | |
6674 { | |
6675 /* Either the encoding is invalid, or applying it would give us | |
6676 more elements than we need. Just encode each element directly. */ | |
6677 out_npatterns = const_nunits; | |
6678 nelts_per_pattern = 1; | |
6679 } | |
6680 else if (!ok_p) | |
6681 return NULL_RTX; | |
6682 | |
6683 /* Get enough bytes of X to form the new encoding. */ | |
6684 unsigned int buffer_bits = out_npatterns * nelts_per_pattern * out_elt_bits; | |
6685 unsigned int buffer_bytes = CEIL (buffer_bits, BITS_PER_UNIT); | |
6686 auto_vec<target_unit, 128> buffer (buffer_bytes); | |
6687 if (!native_encode_rtx (innermode, x, buffer, first_byte, buffer_bytes)) | |
6688 return NULL_RTX; | |
6689 | |
6690 /* Reencode the bytes as OUTERMODE. */ | |
6691 return native_decode_vector_rtx (outermode, buffer, 0, out_npatterns, | |
6692 nelts_per_pattern); | |
6693 } | |
6694 | |
6695 /* Try to simplify a subreg of a constant by encoding the subreg region | |
6696 as a sequence of target bytes and reading them back in the new mode. | |
6697 Return the new value on success, otherwise return null. | |
6698 | |
6699 The subreg has outer mode OUTERMODE, inner mode INNERMODE, inner value X | |
6700 and byte offset FIRST_BYTE. */ | |
6701 | |
6702 static rtx | |
6703 simplify_immed_subreg (fixed_size_mode outermode, rtx x, | |
6704 machine_mode innermode, unsigned int first_byte) | |
6705 { | |
6706 unsigned int buffer_bytes = GET_MODE_SIZE (outermode); | |
6707 auto_vec<target_unit, 128> buffer (buffer_bytes); | |
6083 | 6708 |
6084 /* Some ports misuse CCmode. */ | 6709 /* Some ports misuse CCmode. */ |
6085 if (GET_MODE_CLASS (outermode) == MODE_CC && CONST_INT_P (op)) | 6710 if (GET_MODE_CLASS (outermode) == MODE_CC && CONST_INT_P (x)) |
6086 return op; | 6711 return x; |
6087 | 6712 |
6088 /* We have no way to represent a complex constant at the rtl level. */ | 6713 /* Paradoxical subregs read undefined values for bytes outside of the |
6089 if (COMPLEX_MODE_P (outermode)) | 6714 inner value. However, we have traditionally always sign-extended |
6090 return NULL_RTX; | 6715 integer constants and zero-extended others. */ |
6091 | 6716 unsigned int inner_bytes = buffer_bytes; |
6092 /* We support any size mode. */ | 6717 if (paradoxical_subreg_p (outermode, innermode)) |
6093 max_bitsize = MAX (GET_MODE_BITSIZE (outermode), | 6718 { |
6094 inner_bytes * BITS_PER_UNIT); | 6719 if (!GET_MODE_SIZE (innermode).is_constant (&inner_bytes)) |
6095 | 6720 return NULL_RTX; |
6096 /* Unpack the value. */ | 6721 |
6097 | 6722 target_unit filler = 0; |
6098 if (GET_CODE (op) == CONST_VECTOR) | 6723 if (CONST_SCALAR_INT_P (x) && wi::neg_p (rtx_mode_t (x, innermode))) |
6099 { | 6724 filler = -1; |
6100 num_elem = CEIL (inner_bytes, GET_MODE_UNIT_SIZE (innermode)); | 6725 |
6101 elem_bitsize = GET_MODE_UNIT_BITSIZE (innermode); | 6726 /* Add any leading bytes due to big-endian layout. The number of |
6727 bytes must be constant because both modes have constant size. */ | |
6728 unsigned int leading_bytes | |
6729 = -byte_lowpart_offset (outermode, innermode).to_constant (); | |
6730 for (unsigned int i = 0; i < leading_bytes; ++i) | |
6731 buffer.quick_push (filler); | |
6732 | |
6733 if (!native_encode_rtx (innermode, x, buffer, first_byte, inner_bytes)) | |
6734 return NULL_RTX; | |
6735 | |
6736 /* Add any trailing bytes due to little-endian layout. */ | |
6737 while (buffer.length () < buffer_bytes) | |
6738 buffer.quick_push (filler); | |
6102 } | 6739 } |
6103 else | 6740 else |
6104 { | 6741 { |
6105 num_elem = 1; | 6742 if (!native_encode_rtx (innermode, x, buffer, first_byte, inner_bytes)) |
6106 elem_bitsize = max_bitsize; | 6743 return NULL_RTX; |
6107 } | |
6108 /* If this asserts, it is too complicated; reducing value_bit may help. */ | |
6109 gcc_assert (BITS_PER_UNIT % value_bit == 0); | |
6110 /* I don't know how to handle endianness of sub-units. */ | |
6111 gcc_assert (elem_bitsize % BITS_PER_UNIT == 0); | |
6112 | |
6113 for (elem = 0; elem < num_elem; elem++) | |
6114 { | |
6115 unsigned char * vp; | |
6116 rtx el = (GET_CODE (op) == CONST_VECTOR | |
6117 ? CONST_VECTOR_ELT (op, first_elem + elem) | |
6118 : op); | |
6119 | |
6120 /* Vectors are kept in target memory order. (This is probably | |
6121 a mistake.) */ | |
6122 { | |
6123 unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; | |
6124 unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) | |
6125 / BITS_PER_UNIT); | |
6126 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; | |
6127 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; | |
6128 unsigned bytele = (subword_byte % UNITS_PER_WORD | |
6129 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); | |
6130 vp = value + (bytele * BITS_PER_UNIT) / value_bit; | |
6131 } | 6744 } |
6132 | 6745 return native_decode_rtx (outermode, buffer, 0); |
6133 switch (GET_CODE (el)) | |
6134 { | |
6135 case CONST_INT: | |
6136 for (i = 0; | |
6137 i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; | |
6138 i += value_bit) | |
6139 *vp++ = INTVAL (el) >> i; | |
6140 /* CONST_INTs are always logically sign-extended. */ | |
6141 for (; i < elem_bitsize; i += value_bit) | |
6142 *vp++ = INTVAL (el) < 0 ? -1 : 0; | |
6143 break; | |
6144 | |
6145 case CONST_WIDE_INT: | |
6146 { | |
6147 rtx_mode_t val = rtx_mode_t (el, GET_MODE_INNER (innermode)); | |
6148 unsigned char extend = wi::sign_mask (val); | |
6149 int prec = wi::get_precision (val); | |
6150 | |
6151 for (i = 0; i < prec && i < elem_bitsize; i += value_bit) | |
6152 *vp++ = wi::extract_uhwi (val, i, value_bit); | |
6153 for (; i < elem_bitsize; i += value_bit) | |
6154 *vp++ = extend; | |
6155 } | |
6156 break; | |
6157 | |
6158 case CONST_DOUBLE: | |
6159 if (TARGET_SUPPORTS_WIDE_INT == 0 && GET_MODE (el) == VOIDmode) | |
6160 { | |
6161 unsigned char extend = 0; | |
6162 /* If this triggers, someone should have generated a | |
6163 CONST_INT instead. */ | |
6164 gcc_assert (elem_bitsize > HOST_BITS_PER_WIDE_INT); | |
6165 | |
6166 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit) | |
6167 *vp++ = CONST_DOUBLE_LOW (el) >> i; | |
6168 while (i < HOST_BITS_PER_DOUBLE_INT && i < elem_bitsize) | |
6169 { | |
6170 *vp++ | |
6171 = CONST_DOUBLE_HIGH (el) >> (i - HOST_BITS_PER_WIDE_INT); | |
6172 i += value_bit; | |
6173 } | |
6174 | |
6175 if (CONST_DOUBLE_HIGH (el) >> (HOST_BITS_PER_WIDE_INT - 1)) | |
6176 extend = -1; | |
6177 for (; i < elem_bitsize; i += value_bit) | |
6178 *vp++ = extend; | |
6179 } | |
6180 else | |
6181 { | |
6182 /* This is big enough for anything on the platform. */ | |
6183 long tmp[MAX_BITSIZE_MODE_ANY_MODE / 32]; | |
6184 scalar_float_mode el_mode; | |
6185 | |
6186 el_mode = as_a <scalar_float_mode> (GET_MODE (el)); | |
6187 int bitsize = GET_MODE_BITSIZE (el_mode); | |
6188 | |
6189 gcc_assert (bitsize <= elem_bitsize); | |
6190 gcc_assert (bitsize % value_bit == 0); | |
6191 | |
6192 real_to_target (tmp, CONST_DOUBLE_REAL_VALUE (el), | |
6193 GET_MODE (el)); | |
6194 | |
6195 /* real_to_target produces its result in words affected by | |
6196 FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, | |
6197 and use WORDS_BIG_ENDIAN instead; see the documentation | |
6198 of SUBREG in rtl.texi. */ | |
6199 for (i = 0; i < bitsize; i += value_bit) | |
6200 { | |
6201 int ibase; | |
6202 if (WORDS_BIG_ENDIAN) | |
6203 ibase = bitsize - 1 - i; | |
6204 else | |
6205 ibase = i; | |
6206 *vp++ = tmp[ibase / 32] >> i % 32; | |
6207 } | |
6208 | |
6209 /* It shouldn't matter what's done here, so fill it with | |
6210 zero. */ | |
6211 for (; i < elem_bitsize; i += value_bit) | |
6212 *vp++ = 0; | |
6213 } | |
6214 break; | |
6215 | |
6216 case CONST_FIXED: | |
6217 if (elem_bitsize <= HOST_BITS_PER_WIDE_INT) | |
6218 { | |
6219 for (i = 0; i < elem_bitsize; i += value_bit) | |
6220 *vp++ = CONST_FIXED_VALUE_LOW (el) >> i; | |
6221 } | |
6222 else | |
6223 { | |
6224 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit) | |
6225 *vp++ = CONST_FIXED_VALUE_LOW (el) >> i; | |
6226 for (; i < HOST_BITS_PER_DOUBLE_INT && i < elem_bitsize; | |
6227 i += value_bit) | |
6228 *vp++ = CONST_FIXED_VALUE_HIGH (el) | |
6229 >> (i - HOST_BITS_PER_WIDE_INT); | |
6230 for (; i < elem_bitsize; i += value_bit) | |
6231 *vp++ = 0; | |
6232 } | |
6233 break; | |
6234 | |
6235 default: | |
6236 gcc_unreachable (); | |
6237 } | |
6238 } | |
6239 | |
6240 /* Now, pick the right byte to start with. */ | |
6241 /* Renumber BYTE so that the least-significant byte is byte 0. A special | |
6242 case is paradoxical SUBREGs, which shouldn't be adjusted since they | |
6243 will already have offset 0. */ | |
6244 if (inner_bytes >= GET_MODE_SIZE (outermode)) | |
6245 { | |
6246 unsigned ibyte = inner_bytes - GET_MODE_SIZE (outermode) - byte; | |
6247 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; | |
6248 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; | |
6249 byte = (subword_byte % UNITS_PER_WORD | |
6250 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); | |
6251 } | |
6252 | |
6253 /* BYTE should still be inside OP. (Note that BYTE is unsigned, | |
6254 so if it's become negative it will instead be very large.) */ | |
6255 gcc_assert (byte < inner_bytes); | |
6256 | |
6257 /* Convert from bytes to chunks of size value_bit. */ | |
6258 value_start = byte * (BITS_PER_UNIT / value_bit); | |
6259 | |
6260 /* Re-pack the value. */ | |
6261 num_elem = GET_MODE_NUNITS (outermode); | |
6262 | |
6263 if (VECTOR_MODE_P (outermode)) | |
6264 { | |
6265 result_v = rtvec_alloc (num_elem); | |
6266 elems = &RTVEC_ELT (result_v, 0); | |
6267 } | |
6268 else | |
6269 elems = &result_s; | |
6270 | |
6271 outer_submode = GET_MODE_INNER (outermode); | |
6272 outer_class = GET_MODE_CLASS (outer_submode); | |
6273 elem_bitsize = GET_MODE_BITSIZE (outer_submode); | |
6274 | |
6275 gcc_assert (elem_bitsize % value_bit == 0); | |
6276 gcc_assert (elem_bitsize + value_start * value_bit <= max_bitsize); | |
6277 | |
6278 for (elem = 0; elem < num_elem; elem++) | |
6279 { | |
6280 unsigned char *vp; | |
6281 | |
6282 /* Vectors are stored in target memory order. (This is probably | |
6283 a mistake.) */ | |
6284 { | |
6285 unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; | |
6286 unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) | |
6287 / BITS_PER_UNIT); | |
6288 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; | |
6289 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; | |
6290 unsigned bytele = (subword_byte % UNITS_PER_WORD | |
6291 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); | |
6292 vp = value + value_start + (bytele * BITS_PER_UNIT) / value_bit; | |
6293 } | |
6294 | |
6295 switch (outer_class) | |
6296 { | |
6297 case MODE_INT: | |
6298 case MODE_PARTIAL_INT: | |
6299 { | |
6300 int u; | |
6301 int base = 0; | |
6302 int units | |
6303 = (GET_MODE_BITSIZE (outer_submode) + HOST_BITS_PER_WIDE_INT - 1) | |
6304 / HOST_BITS_PER_WIDE_INT; | |
6305 HOST_WIDE_INT tmp[MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT]; | |
6306 wide_int r; | |
6307 | |
6308 if (GET_MODE_PRECISION (outer_submode) > MAX_BITSIZE_MODE_ANY_INT) | |
6309 return NULL_RTX; | |
6310 for (u = 0; u < units; u++) | |
6311 { | |
6312 unsigned HOST_WIDE_INT buf = 0; | |
6313 for (i = 0; | |
6314 i < HOST_BITS_PER_WIDE_INT && base + i < elem_bitsize; | |
6315 i += value_bit) | |
6316 buf |= (unsigned HOST_WIDE_INT)(*vp++ & value_mask) << i; | |
6317 | |
6318 tmp[u] = buf; | |
6319 base += HOST_BITS_PER_WIDE_INT; | |
6320 } | |
6321 r = wide_int::from_array (tmp, units, | |
6322 GET_MODE_PRECISION (outer_submode)); | |
6323 #if TARGET_SUPPORTS_WIDE_INT == 0 | |
6324 /* Make sure r will fit into CONST_INT or CONST_DOUBLE. */ | |
6325 if (wi::min_precision (r, SIGNED) > HOST_BITS_PER_DOUBLE_INT) | |
6326 return NULL_RTX; | |
6327 #endif | |
6328 elems[elem] = immed_wide_int_const (r, outer_submode); | |
6329 } | |
6330 break; | |
6331 | |
6332 case MODE_FLOAT: | |
6333 case MODE_DECIMAL_FLOAT: | |
6334 { | |
6335 REAL_VALUE_TYPE r; | |
6336 long tmp[MAX_BITSIZE_MODE_ANY_MODE / 32] = { 0 }; | |
6337 | |
6338 /* real_from_target wants its input in words affected by | |
6339 FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, | |
6340 and use WORDS_BIG_ENDIAN instead; see the documentation | |
6341 of SUBREG in rtl.texi. */ | |
6342 for (i = 0; i < elem_bitsize; i += value_bit) | |
6343 { | |
6344 int ibase; | |
6345 if (WORDS_BIG_ENDIAN) | |
6346 ibase = elem_bitsize - 1 - i; | |
6347 else | |
6348 ibase = i; | |
6349 tmp[ibase / 32] |= (*vp++ & value_mask) << i % 32; | |
6350 } | |
6351 | |
6352 real_from_target (&r, tmp, outer_submode); | |
6353 elems[elem] = const_double_from_real_value (r, outer_submode); | |
6354 } | |
6355 break; | |
6356 | |
6357 case MODE_FRACT: | |
6358 case MODE_UFRACT: | |
6359 case MODE_ACCUM: | |
6360 case MODE_UACCUM: | |
6361 { | |
6362 FIXED_VALUE_TYPE f; | |
6363 f.data.low = 0; | |
6364 f.data.high = 0; | |
6365 f.mode = outer_submode; | |
6366 | |
6367 for (i = 0; | |
6368 i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; | |
6369 i += value_bit) | |
6370 f.data.low |= (unsigned HOST_WIDE_INT)(*vp++ & value_mask) << i; | |
6371 for (; i < elem_bitsize; i += value_bit) | |
6372 f.data.high |= ((unsigned HOST_WIDE_INT)(*vp++ & value_mask) | |
6373 << (i - HOST_BITS_PER_WIDE_INT)); | |
6374 | |
6375 elems[elem] = CONST_FIXED_FROM_FIXED_VALUE (f, outer_submode); | |
6376 } | |
6377 break; | |
6378 | |
6379 default: | |
6380 gcc_unreachable (); | |
6381 } | |
6382 } | |
6383 if (VECTOR_MODE_P (outermode)) | |
6384 return gen_rtx_CONST_VECTOR (outermode, result_v); | |
6385 else | |
6386 return result_s; | |
6387 } | 6746 } |
6388 | 6747 |
6389 /* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE) | 6748 /* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE) |
6390 Return 0 if no simplifications are possible. */ | 6749 Return 0 if no simplifications are possible. */ |
6391 rtx | 6750 rtx |
6410 return NULL_RTX; | 6769 return NULL_RTX; |
6411 | 6770 |
6412 if (outermode == innermode && known_eq (byte, 0U)) | 6771 if (outermode == innermode && known_eq (byte, 0U)) |
6413 return op; | 6772 return op; |
6414 | 6773 |
6774 if (GET_CODE (op) == CONST_VECTOR) | |
6775 byte = simplify_const_vector_byte_offset (op, byte); | |
6776 | |
6415 if (multiple_p (byte, GET_MODE_UNIT_SIZE (innermode))) | 6777 if (multiple_p (byte, GET_MODE_UNIT_SIZE (innermode))) |
6416 { | 6778 { |
6417 rtx elt; | 6779 rtx elt; |
6418 | 6780 |
6419 if (VECTOR_MODE_P (outermode) | 6781 if (VECTOR_MODE_P (outermode) |
6429 if (CONST_SCALAR_INT_P (op) | 6791 if (CONST_SCALAR_INT_P (op) |
6430 || CONST_DOUBLE_AS_FLOAT_P (op) | 6792 || CONST_DOUBLE_AS_FLOAT_P (op) |
6431 || CONST_FIXED_P (op) | 6793 || CONST_FIXED_P (op) |
6432 || GET_CODE (op) == CONST_VECTOR) | 6794 || GET_CODE (op) == CONST_VECTOR) |
6433 { | 6795 { |
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; | 6796 unsigned HOST_WIDE_INT cbyte; |
6441 if (is_a <fixed_size_mode> (outermode, &fs_outermode) | 6797 if (byte.is_constant (&cbyte)) |
6442 && is_a <fixed_size_mode> (innermode, &fs_innermode) | 6798 { |
6443 && byte.is_constant (&cbyte)) | 6799 if (GET_CODE (op) == CONST_VECTOR && VECTOR_MODE_P (outermode)) |
6444 return simplify_immed_subreg (fs_outermode, op, fs_innermode, cbyte, | 6800 { |
6445 0, GET_MODE_SIZE (fs_innermode)); | 6801 rtx tmp = simplify_const_vector_subreg (outermode, op, |
6446 | 6802 innermode, cbyte); |
6447 /* Handle constant-sized outer modes and variable-sized inner modes. */ | 6803 if (tmp) |
6448 unsigned HOST_WIDE_INT first_elem; | 6804 return tmp; |
6449 if (GET_CODE (op) == CONST_VECTOR | 6805 } |
6450 && is_a <fixed_size_mode> (outermode, &fs_outermode) | 6806 |
6451 && constant_multiple_p (byte, GET_MODE_UNIT_SIZE (innermode), | 6807 fixed_size_mode fs_outermode; |
6452 &first_elem)) | 6808 if (is_a <fixed_size_mode> (outermode, &fs_outermode)) |
6453 return simplify_immed_subreg (fs_outermode, op, innermode, 0, | 6809 return simplify_immed_subreg (fs_outermode, op, innermode, cbyte); |
6454 first_elem, | 6810 } |
6455 GET_MODE_SIZE (fs_outermode)); | |
6456 | |
6457 return NULL_RTX; | |
6458 } | 6811 } |
6459 | 6812 |
6460 /* Changing mode twice with SUBREG => just change it once, | 6813 /* Changing mode twice with SUBREG => just change it once, |
6461 or not at all if changing back op starting mode. */ | 6814 or not at all if changing back op starting mode. */ |
6462 if (GET_CODE (op) == SUBREG) | 6815 if (GET_CODE (op) == SUBREG) |
6537 subreg_memory_offset (outermode, | 6890 subreg_memory_offset (outermode, |
6538 innermode, byte)); | 6891 innermode, byte)); |
6539 | 6892 |
6540 /* Propagate original regno. We don't have any way to specify | 6893 /* Propagate original regno. We don't have any way to specify |
6541 the offset inside original regno, so do so only for lowpart. | 6894 the offset inside original regno, so do so only for lowpart. |
6542 The information is used only by alias analysis that can not | 6895 The information is used only by alias analysis that cannot |
6543 grog partial register anyway. */ | 6896 grog partial register anyway. */ |
6544 | 6897 |
6545 if (known_eq (subreg_lowpart_offset (outermode, innermode), byte)) | 6898 if (known_eq (subreg_lowpart_offset (outermode, innermode), byte)) |
6546 ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op); | 6899 ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op); |
6547 return x; | 6900 return x; |
6651 if (tem) | 7004 if (tem) |
6652 return tem; | 7005 return tem; |
6653 } | 7006 } |
6654 } | 7007 } |
6655 | 7008 |
7009 /* If OP is a vector comparison and the subreg is not changing the | |
7010 number of elements or the size of the elements, change the result | |
7011 of the comparison to the new mode. */ | |
7012 if (COMPARISON_P (op) | |
7013 && VECTOR_MODE_P (outermode) | |
7014 && VECTOR_MODE_P (innermode) | |
7015 && known_eq (GET_MODE_NUNITS (outermode), GET_MODE_NUNITS (innermode)) | |
7016 && known_eq (GET_MODE_UNIT_SIZE (outermode), | |
7017 GET_MODE_UNIT_SIZE (innermode))) | |
7018 return simplify_gen_relational (GET_CODE (op), outermode, innermode, | |
7019 XEXP (op, 0), XEXP (op, 1)); | |
6656 return NULL_RTX; | 7020 return NULL_RTX; |
6657 } | 7021 } |
6658 | 7022 |
6659 /* Make a SUBREG operation or equivalent if it folds. */ | 7023 /* Make a SUBREG operation or equivalent if it folds. */ |
6660 | 7024 |
6883 if (maybe_ne (nunits, 2U) | 7247 if (maybe_ne (nunits, 2U) |
6884 && multiple_p (nunits, 2) | 7248 && multiple_p (nunits, 2) |
6885 && mode_for_vector (inner_mode, 2).exists (&narrower_mode) | 7249 && mode_for_vector (inner_mode, 2).exists (&narrower_mode) |
6886 && VECTOR_MODE_P (narrower_mode)) | 7250 && VECTOR_MODE_P (narrower_mode)) |
6887 { | 7251 { |
7252 /* Test VEC_DUPLICATE of a vector. */ | |
7253 rtx_vector_builder nbuilder (narrower_mode, 2, 1); | |
7254 nbuilder.quick_push (const0_rtx); | |
7255 nbuilder.quick_push (const1_rtx); | |
7256 rtx_vector_builder builder (mode, 2, 1); | |
7257 builder.quick_push (const0_rtx); | |
7258 builder.quick_push (const1_rtx); | |
7259 ASSERT_RTX_EQ (builder.build (), | |
7260 simplify_unary_operation (VEC_DUPLICATE, mode, | |
7261 nbuilder.build (), | |
7262 narrower_mode)); | |
7263 | |
6888 /* Test VEC_SELECT of a vector. */ | 7264 /* Test VEC_SELECT of a vector. */ |
6889 rtx vec_par | 7265 rtx vec_par |
6890 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, const1_rtx, const0_rtx)); | 7266 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, const1_rtx, const0_rtx)); |
6891 rtx narrower_duplicate | 7267 rtx narrower_duplicate |
6892 = gen_rtx_VEC_DUPLICATE (narrower_mode, scalar_reg); | 7268 = gen_rtx_VEC_DUPLICATE (narrower_mode, scalar_reg); |
6955 simplify_binary_operation (MINUS, mode, duplicate, | 7331 simplify_binary_operation (MINUS, mode, duplicate, |
6956 series_0_m1)); | 7332 series_0_m1)); |
6957 ASSERT_RTX_EQ (series_0_m1, | 7333 ASSERT_RTX_EQ (series_0_m1, |
6958 simplify_binary_operation (VEC_SERIES, mode, const0_rtx, | 7334 simplify_binary_operation (VEC_SERIES, mode, const0_rtx, |
6959 constm1_rtx)); | 7335 constm1_rtx)); |
7336 | |
7337 /* Test NEG on constant vector series. */ | |
7338 ASSERT_RTX_EQ (series_0_m1, | |
7339 simplify_unary_operation (NEG, mode, series_0_1, mode)); | |
7340 ASSERT_RTX_EQ (series_0_1, | |
7341 simplify_unary_operation (NEG, mode, series_0_m1, mode)); | |
7342 | |
7343 /* Test PLUS and MINUS on constant vector series. */ | |
7344 rtx scalar2 = gen_int_mode (2, inner_mode); | |
7345 rtx scalar3 = gen_int_mode (3, inner_mode); | |
7346 rtx series_1_1 = gen_const_vec_series (mode, const1_rtx, const1_rtx); | |
7347 rtx series_0_2 = gen_const_vec_series (mode, const0_rtx, scalar2); | |
7348 rtx series_1_3 = gen_const_vec_series (mode, const1_rtx, scalar3); | |
7349 ASSERT_RTX_EQ (series_1_1, | |
7350 simplify_binary_operation (PLUS, mode, series_0_1, | |
7351 CONST1_RTX (mode))); | |
7352 ASSERT_RTX_EQ (series_0_m1, | |
7353 simplify_binary_operation (PLUS, mode, CONST0_RTX (mode), | |
7354 series_0_m1)); | |
7355 ASSERT_RTX_EQ (series_1_3, | |
7356 simplify_binary_operation (PLUS, mode, series_1_1, | |
7357 series_0_2)); | |
7358 ASSERT_RTX_EQ (series_0_1, | |
7359 simplify_binary_operation (MINUS, mode, series_1_1, | |
7360 CONST1_RTX (mode))); | |
7361 ASSERT_RTX_EQ (series_1_1, | |
7362 simplify_binary_operation (MINUS, mode, CONST1_RTX (mode), | |
7363 series_0_m1)); | |
7364 ASSERT_RTX_EQ (series_1_1, | |
7365 simplify_binary_operation (MINUS, mode, series_1_3, | |
7366 series_0_2)); | |
7367 | |
7368 /* Test MULT between constant vectors. */ | |
7369 rtx vec2 = gen_const_vec_duplicate (mode, scalar2); | |
7370 rtx vec3 = gen_const_vec_duplicate (mode, scalar3); | |
7371 rtx scalar9 = gen_int_mode (9, inner_mode); | |
7372 rtx series_3_9 = gen_const_vec_series (mode, scalar3, scalar9); | |
7373 ASSERT_RTX_EQ (series_0_2, | |
7374 simplify_binary_operation (MULT, mode, series_0_1, vec2)); | |
7375 ASSERT_RTX_EQ (series_3_9, | |
7376 simplify_binary_operation (MULT, mode, vec3, series_1_3)); | |
7377 if (!GET_MODE_NUNITS (mode).is_constant ()) | |
7378 ASSERT_FALSE (simplify_binary_operation (MULT, mode, series_0_1, | |
7379 series_0_1)); | |
7380 | |
7381 /* Test ASHIFT between constant vectors. */ | |
7382 ASSERT_RTX_EQ (series_0_2, | |
7383 simplify_binary_operation (ASHIFT, mode, series_0_1, | |
7384 CONST1_RTX (mode))); | |
7385 if (!GET_MODE_NUNITS (mode).is_constant ()) | |
7386 ASSERT_FALSE (simplify_binary_operation (ASHIFT, mode, CONST1_RTX (mode), | |
7387 series_0_1)); | |
6960 } | 7388 } |
6961 | 7389 |
6962 /* Verify simplify_merge_mask works correctly. */ | 7390 /* Verify simplify_merge_mask works correctly. */ |
6963 | 7391 |
6964 static void | 7392 static void |
7020 /* Called indirectly. */ | 7448 /* Called indirectly. */ |
7021 ASSERT_RTX_EQ (gen_rtx_VEC_MERGE (mode, op0, op3, mask1), | 7449 ASSERT_RTX_EQ (gen_rtx_VEC_MERGE (mode, op0, op3, mask1), |
7022 simplify_rtx (nvm)); | 7450 simplify_rtx (nvm)); |
7023 } | 7451 } |
7024 | 7452 |
7453 /* Test subregs of integer vector constant X, trying elements in | |
7454 the range [ELT_BIAS, ELT_BIAS + constant_lower_bound (NELTS)), | |
7455 where NELTS is the number of elements in X. Subregs involving | |
7456 elements [ELT_BIAS, ELT_BIAS + FIRST_VALID) are expected to fail. */ | |
7457 | |
7458 static void | |
7459 test_vector_subregs_modes (rtx x, poly_uint64 elt_bias = 0, | |
7460 unsigned int first_valid = 0) | |
7461 { | |
7462 machine_mode inner_mode = GET_MODE (x); | |
7463 scalar_mode int_mode = GET_MODE_INNER (inner_mode); | |
7464 | |
7465 for (unsigned int modei = 0; modei < NUM_MACHINE_MODES; ++modei) | |
7466 { | |
7467 machine_mode outer_mode = (machine_mode) modei; | |
7468 if (!VECTOR_MODE_P (outer_mode)) | |
7469 continue; | |
7470 | |
7471 unsigned int outer_nunits; | |
7472 if (GET_MODE_INNER (outer_mode) == int_mode | |
7473 && GET_MODE_NUNITS (outer_mode).is_constant (&outer_nunits) | |
7474 && multiple_p (GET_MODE_NUNITS (inner_mode), outer_nunits)) | |
7475 { | |
7476 /* Test subregs in which the outer mode is a smaller, | |
7477 constant-sized vector of the same element type. */ | |
7478 unsigned int limit | |
7479 = constant_lower_bound (GET_MODE_NUNITS (inner_mode)); | |
7480 for (unsigned int elt = 0; elt < limit; elt += outer_nunits) | |
7481 { | |
7482 rtx expected = NULL_RTX; | |
7483 if (elt >= first_valid) | |
7484 { | |
7485 rtx_vector_builder builder (outer_mode, outer_nunits, 1); | |
7486 for (unsigned int i = 0; i < outer_nunits; ++i) | |
7487 builder.quick_push (CONST_VECTOR_ELT (x, elt + i)); | |
7488 expected = builder.build (); | |
7489 } | |
7490 poly_uint64 byte = (elt_bias + elt) * GET_MODE_SIZE (int_mode); | |
7491 ASSERT_RTX_EQ (expected, | |
7492 simplify_subreg (outer_mode, x, | |
7493 inner_mode, byte)); | |
7494 } | |
7495 } | |
7496 else if (known_eq (GET_MODE_SIZE (outer_mode), | |
7497 GET_MODE_SIZE (inner_mode)) | |
7498 && known_eq (elt_bias, 0U) | |
7499 && (GET_MODE_CLASS (outer_mode) != MODE_VECTOR_BOOL | |
7500 || known_eq (GET_MODE_BITSIZE (outer_mode), | |
7501 GET_MODE_NUNITS (outer_mode))) | |
7502 && (!FLOAT_MODE_P (outer_mode) | |
7503 || (FLOAT_MODE_FORMAT (outer_mode)->ieee_bits | |
7504 == GET_MODE_UNIT_PRECISION (outer_mode))) | |
7505 && (GET_MODE_SIZE (inner_mode).is_constant () | |
7506 || !CONST_VECTOR_STEPPED_P (x))) | |
7507 { | |
7508 /* Try converting to OUTER_MODE and back. */ | |
7509 rtx outer_x = simplify_subreg (outer_mode, x, inner_mode, 0); | |
7510 ASSERT_TRUE (outer_x != NULL_RTX); | |
7511 ASSERT_RTX_EQ (x, simplify_subreg (inner_mode, outer_x, | |
7512 outer_mode, 0)); | |
7513 } | |
7514 } | |
7515 | |
7516 if (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN) | |
7517 { | |
7518 /* Test each byte in the element range. */ | |
7519 unsigned int limit | |
7520 = constant_lower_bound (GET_MODE_SIZE (inner_mode)); | |
7521 for (unsigned int i = 0; i < limit; ++i) | |
7522 { | |
7523 unsigned int elt = i / GET_MODE_SIZE (int_mode); | |
7524 rtx expected = NULL_RTX; | |
7525 if (elt >= first_valid) | |
7526 { | |
7527 unsigned int byte_shift = i % GET_MODE_SIZE (int_mode); | |
7528 if (BYTES_BIG_ENDIAN) | |
7529 byte_shift = GET_MODE_SIZE (int_mode) - byte_shift - 1; | |
7530 rtx_mode_t vec_elt (CONST_VECTOR_ELT (x, elt), int_mode); | |
7531 wide_int shifted_elt | |
7532 = wi::lrshift (vec_elt, byte_shift * BITS_PER_UNIT); | |
7533 expected = immed_wide_int_const (shifted_elt, QImode); | |
7534 } | |
7535 poly_uint64 byte = elt_bias * GET_MODE_SIZE (int_mode) + i; | |
7536 ASSERT_RTX_EQ (expected, | |
7537 simplify_subreg (QImode, x, inner_mode, byte)); | |
7538 } | |
7539 } | |
7540 } | |
7541 | |
7542 /* Test constant subregs of integer vector mode INNER_MODE, using 1 | |
7543 element per pattern. */ | |
7544 | |
7545 static void | |
7546 test_vector_subregs_repeating (machine_mode inner_mode) | |
7547 { | |
7548 poly_uint64 nunits = GET_MODE_NUNITS (inner_mode); | |
7549 unsigned int min_nunits = constant_lower_bound (nunits); | |
7550 scalar_mode int_mode = GET_MODE_INNER (inner_mode); | |
7551 unsigned int count = gcd (min_nunits, 8); | |
7552 | |
7553 rtx_vector_builder builder (inner_mode, count, 1); | |
7554 for (unsigned int i = 0; i < count; ++i) | |
7555 builder.quick_push (gen_int_mode (8 - i, int_mode)); | |
7556 rtx x = builder.build (); | |
7557 | |
7558 test_vector_subregs_modes (x); | |
7559 if (!nunits.is_constant ()) | |
7560 test_vector_subregs_modes (x, nunits - min_nunits); | |
7561 } | |
7562 | |
7563 /* Test constant subregs of integer vector mode INNER_MODE, using 2 | |
7564 elements per pattern. */ | |
7565 | |
7566 static void | |
7567 test_vector_subregs_fore_back (machine_mode inner_mode) | |
7568 { | |
7569 poly_uint64 nunits = GET_MODE_NUNITS (inner_mode); | |
7570 unsigned int min_nunits = constant_lower_bound (nunits); | |
7571 scalar_mode int_mode = GET_MODE_INNER (inner_mode); | |
7572 unsigned int count = gcd (min_nunits, 4); | |
7573 | |
7574 rtx_vector_builder builder (inner_mode, count, 2); | |
7575 for (unsigned int i = 0; i < count; ++i) | |
7576 builder.quick_push (gen_int_mode (i, int_mode)); | |
7577 for (unsigned int i = 0; i < count; ++i) | |
7578 builder.quick_push (gen_int_mode (-(int) i, int_mode)); | |
7579 rtx x = builder.build (); | |
7580 | |
7581 test_vector_subregs_modes (x); | |
7582 if (!nunits.is_constant ()) | |
7583 test_vector_subregs_modes (x, nunits - min_nunits, count); | |
7584 } | |
7585 | |
7586 /* Test constant subregs of integer vector mode INNER_MODE, using 3 | |
7587 elements per pattern. */ | |
7588 | |
7589 static void | |
7590 test_vector_subregs_stepped (machine_mode inner_mode) | |
7591 { | |
7592 /* Build { 0, 1, 2, 3, ... }. */ | |
7593 scalar_mode int_mode = GET_MODE_INNER (inner_mode); | |
7594 rtx_vector_builder builder (inner_mode, 1, 3); | |
7595 for (unsigned int i = 0; i < 3; ++i) | |
7596 builder.quick_push (gen_int_mode (i, int_mode)); | |
7597 rtx x = builder.build (); | |
7598 | |
7599 test_vector_subregs_modes (x); | |
7600 } | |
7601 | |
7602 /* Test constant subregs of integer vector mode INNER_MODE. */ | |
7603 | |
7604 static void | |
7605 test_vector_subregs (machine_mode inner_mode) | |
7606 { | |
7607 test_vector_subregs_repeating (inner_mode); | |
7608 test_vector_subregs_fore_back (inner_mode); | |
7609 test_vector_subregs_stepped (inner_mode); | |
7610 } | |
7611 | |
7025 /* Verify some simplifications involving vectors. */ | 7612 /* Verify some simplifications involving vectors. */ |
7026 | 7613 |
7027 static void | 7614 static void |
7028 test_vector_ops () | 7615 test_vector_ops () |
7029 { | 7616 { |
7034 { | 7621 { |
7035 rtx scalar_reg = make_test_reg (GET_MODE_INNER (mode)); | 7622 rtx scalar_reg = make_test_reg (GET_MODE_INNER (mode)); |
7036 test_vector_ops_duplicate (mode, scalar_reg); | 7623 test_vector_ops_duplicate (mode, scalar_reg); |
7037 if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT | 7624 if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT |
7038 && maybe_gt (GET_MODE_NUNITS (mode), 2)) | 7625 && maybe_gt (GET_MODE_NUNITS (mode), 2)) |
7039 test_vector_ops_series (mode, scalar_reg); | 7626 { |
7627 test_vector_ops_series (mode, scalar_reg); | |
7628 test_vector_subregs (mode); | |
7629 } | |
7040 test_vec_merge (mode); | 7630 test_vec_merge (mode); |
7041 } | 7631 } |
7042 } | 7632 } |
7043 } | 7633 } |
7044 | 7634 |