diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2019-01-07 12:16:30 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2019-01-07 12:16:30 +0000 |
commit | 46c66a46aa33077bda821e0428cc7859945c04c8 (patch) | |
tree | 4c12a6c6d89c857b70db55d83846f5b0a0828cf6 /gcc/tree.c | |
parent | 3340164d5db7a65cd98138f1eead1f2d66dd221c (diff) | |
download | gcc-46c66a46aa33077bda821e0428cc7859945c04c8.zip gcc-46c66a46aa33077bda821e0428cc7859945c04c8.tar.gz gcc-46c66a46aa33077bda821e0428cc7859945c04c8.tar.bz2 |
[1/2] PR88598: Optimise x * { 0 or 1, 0 or 1, ... }
The PR has:
vect__6.24_42 = vect__5.23_41 * { 0.0, 1.0e+0, 0.0, 0.0 };
which for -fno-signed-zeros -fno-signaling-nans can be simplified to:
vect__6.24_42 = vect__5.23_41 & { 0, -1, 0, 0 };
I deliberately didn't handle COMPLEX_CST or CONSTRUCTOR in
initializer_each_zero_or_onep since there are no current use cases.
The patch also makes (un)signed_type_for handle floating-point types.
I tried to audit all callers and the few that handle null returns would
be unaffected.
2019-01-07 Richard Sandiford <richard.sandiford@arm.com>
gcc/
PR tree-optimization/88598
* tree.h (initializer_each_zero_or_onep): Declare.
* tree.c (initializer_each_zero_or_onep): New function.
(signed_or_unsigned_type_for): Handle float types too.
(unsigned_type_for, signed_type_for): Update comments accordingly.
* match.pd: Fold x * { 0 or 1, 0 or 1, ...} to
x & { 0 or -1, 0 or -1, ... }.
gcc/testsuite/
PR tree-optimization/88598
* gcc.dg/pr88598-1.c: New test.
* gcc.dg/pr88598-2.c: Likewise.
* gcc.dg/pr88598-3.c: Likewise.
* gcc.dg/pr88598-4.c: Likewise.
* gcc.dg/pr88598-5.c: Likewise.
From-SVN: r267645
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 63 |
1 files changed, 56 insertions, 7 deletions
@@ -11229,6 +11229,45 @@ initializer_zerop (const_tree init, bool *nonzero /* = NULL */) } } +/* Return true if EXPR is an initializer expression in which every element + is a constant that is numerically equal to 0 or 1. The elements do not + need to be equal to each other. */ + +bool +initializer_each_zero_or_onep (const_tree expr) +{ + STRIP_ANY_LOCATION_WRAPPER (expr); + + switch (TREE_CODE (expr)) + { + case INTEGER_CST: + return integer_zerop (expr) || integer_onep (expr); + + case REAL_CST: + return real_zerop (expr) || real_onep (expr); + + case VECTOR_CST: + { + unsigned HOST_WIDE_INT nelts = vector_cst_encoded_nelts (expr); + if (VECTOR_CST_STEPPED_P (expr) + && !TYPE_VECTOR_SUBPARTS (TREE_TYPE (expr)).is_constant (&nelts)) + return false; + + for (unsigned int i = 0; i < nelts; ++i) + { + tree elt = VECTOR_CST_ENCODED_ELT (expr, i); + if (!initializer_each_zero_or_onep (elt)) + return false; + } + + return true; + } + + default: + return false; + } +} + /* Check if vector VEC consists of all the equal elements and that the number of elements corresponds to the type of VEC. The function returns first element of the vector @@ -11672,7 +11711,10 @@ int_cst_value (const_tree x) /* If TYPE is an integral or pointer type, return an integer type with the same precision which is unsigned iff UNSIGNEDP is true, or itself - if TYPE is already an integer type of signedness UNSIGNEDP. */ + if TYPE is already an integer type of signedness UNSIGNEDP. + If TYPE is a floating-point type, return an integer type with the same + bitsize and with the signedness given by UNSIGNEDP; this is useful + when doing bit-level operations on a floating-point value. */ tree signed_or_unsigned_type_for (int unsignedp, tree type) @@ -11702,17 +11744,23 @@ signed_or_unsigned_type_for (int unsignedp, tree type) return build_complex_type (inner2); } - if (!INTEGRAL_TYPE_P (type) - && !POINTER_TYPE_P (type) - && TREE_CODE (type) != OFFSET_TYPE) + unsigned int bits; + if (INTEGRAL_TYPE_P (type) + || POINTER_TYPE_P (type) + || TREE_CODE (type) == OFFSET_TYPE) + bits = TYPE_PRECISION (type); + else if (TREE_CODE (type) == REAL_TYPE) + bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (type)); + else return NULL_TREE; - return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp); + return build_nonstandard_integer_type (bits, unsignedp); } /* If TYPE is an integral or pointer type, return an integer type with the same precision which is unsigned, or itself if TYPE is already an - unsigned integer type. */ + unsigned integer type. If TYPE is a floating-point type, return an + unsigned integer type with the same bitsize as TYPE. */ tree unsigned_type_for (tree type) @@ -11722,7 +11770,8 @@ unsigned_type_for (tree type) /* If TYPE is an integral or pointer type, return an integer type with the same precision which is signed, or itself if TYPE is already a - signed integer type. */ + signed integer type. If TYPE is a floating-point type, return a + signed integer type with the same bitsize as TYPE. */ tree signed_type_for (tree type) |