aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2019-01-07 12:16:30 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-01-07 12:16:30 +0000
commit46c66a46aa33077bda821e0428cc7859945c04c8 (patch)
tree4c12a6c6d89c857b70db55d83846f5b0a0828cf6 /gcc/tree.c
parent3340164d5db7a65cd98138f1eead1f2d66dd221c (diff)
downloadgcc-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.c63
1 files changed, 56 insertions, 7 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 2c0a09d..533694c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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)