Commit 09240451 by Marc Glisse Committed by Marc Glisse

tree.c (element_mode, [...]): New functions.

2014-11-18  Marc Glisse  <marc.glisse@inria.fr>

	* tree.c (element_mode, integer_truep): New functions.
	* tree.h (element_mode, integer_truep): Declare them.
	* fold-const.c (negate_expr_p, fold_negate_expr, combine_comparisons,
	fold_cond_expr_with_comparison, fold_real_zero_addition_p,
	fold_comparison, fold_ternary_loc, tree_call_nonnegative_warnv_p,
	fold_strip_sign_ops): Use element_mode.
	(fold_binary_loc): Use element_mode and element_precision.
	* match.pd: Use integer_truep, element_mode, element_precision,
	VECTOR_TYPE_P and build_one_cst. Extend some transformations to
	vectors. Simplify A/-A.

From-SVN: r217702
parent 9f37760a
2014-11-18 Marc Glisse <marc.glisse@inria.fr>
* tree.c (element_mode, integer_truep): New functions.
* tree.h (element_mode, integer_truep): Declare them.
* fold-const.c (negate_expr_p, fold_negate_expr, combine_comparisons,
fold_cond_expr_with_comparison, fold_real_zero_addition_p,
fold_comparison, fold_ternary_loc, tree_call_nonnegative_warnv_p,
fold_strip_sign_ops): Use element_mode.
(fold_binary_loc): Use element_mode and element_precision.
* match.pd: Use integer_truep, element_mode, element_precision,
VECTOR_TYPE_P and build_one_cst. Extend some transformations to
vectors. Simplify A/-A.
2014-11-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com> 2014-11-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/arm/arm.md (unaligned_loaddi): Use std::swap instead of * config/arm/arm.md (unaligned_loaddi): Use std::swap instead of
...@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3. If not see
/* Generic tree predicates we inherit. */ /* Generic tree predicates we inherit. */
(define_predicates (define_predicates
integer_onep integer_zerop integer_all_onesp integer_minus_onep integer_onep integer_zerop integer_all_onesp integer_minus_onep
integer_each_onep integer_each_onep integer_truep
real_zerop real_onep real_minus_onep real_zerop real_onep real_minus_onep
CONSTANT_CLASS_P CONSTANT_CLASS_P
tree_expr_nonnegative_p) tree_expr_nonnegative_p)
...@@ -73,7 +73,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -73,7 +73,7 @@ along with GCC; see the file COPYING3. If not see
is volatile. */ is volatile. */
(simplify (simplify
(minus @0 @0) (minus @0 @0)
(if (!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type))) (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (element_mode (type)))
{ build_zero_cst (type); })) { build_zero_cst (type); }))
(simplify (simplify
...@@ -86,24 +86,24 @@ along with GCC; see the file COPYING3. If not see ...@@ -86,24 +86,24 @@ along with GCC; see the file COPYING3. If not see
negative value by 0 gives -0, not +0. */ negative value by 0 gives -0, not +0. */
(simplify (simplify
(mult @0 real_zerop@1) (mult @0 real_zerop@1)
(if (!HONOR_NANS (TYPE_MODE (type)) (if (!HONOR_NANS (element_mode (type))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (type))) && !HONOR_SIGNED_ZEROS (element_mode (type)))
@1)) @1))
/* In IEEE floating point, x*1 is not equivalent to x for snans. /* In IEEE floating point, x*1 is not equivalent to x for snans.
Likewise for complex arithmetic with signed zeros. */ Likewise for complex arithmetic with signed zeros. */
(simplify (simplify
(mult @0 real_onep) (mult @0 real_onep)
(if (!HONOR_SNANS (TYPE_MODE (type)) (if (!HONOR_SNANS (element_mode (type))
&& (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)) && (!HONOR_SIGNED_ZEROS (element_mode (type))
|| !COMPLEX_FLOAT_TYPE_P (type))) || !COMPLEX_FLOAT_TYPE_P (type)))
(non_lvalue @0))) (non_lvalue @0)))
/* Transform x * -1.0 into -x. */ /* Transform x * -1.0 into -x. */
(simplify (simplify
(mult @0 real_minus_onep) (mult @0 real_minus_onep)
(if (!HONOR_SNANS (TYPE_MODE (type)) (if (!HONOR_SNANS (element_mode (type))
&& (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)) && (!HONOR_SIGNED_ZEROS (element_mode (type))
|| !COMPLEX_FLOAT_TYPE_P (type))) || !COMPLEX_FLOAT_TYPE_P (type)))
(negate @0))) (negate @0)))
...@@ -117,44 +117,46 @@ along with GCC; see the file COPYING3. If not see ...@@ -117,44 +117,46 @@ along with GCC; see the file COPYING3. If not see
/* X / -1 is -X. */ /* X / -1 is -X. */
(for div (trunc_div ceil_div floor_div round_div exact_div) (for div (trunc_div ceil_div floor_div round_div exact_div)
(simplify (simplify
(div @0 INTEGER_CST@1) (div @0 integer_minus_onep@1)
(if (!TYPE_UNSIGNED (type) (if (!TYPE_UNSIGNED (type))
&& wi::eq_p (@1, -1))
(negate @0)))) (negate @0))))
/* For unsigned integral types, FLOOR_DIV_EXPR is the same as /* For unsigned integral types, FLOOR_DIV_EXPR is the same as
TRUNC_DIV_EXPR. Rewrite into the latter in this case. */ TRUNC_DIV_EXPR. Rewrite into the latter in this case. */
(simplify (simplify
(floor_div @0 @1) (floor_div @0 @1)
(if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)) (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
&& TYPE_UNSIGNED (type))
(trunc_div @0 @1))) (trunc_div @0 @1)))
/* Optimize A / A to 1.0 if we don't care about /* Optimize A / A to 1.0 if we don't care about
NaNs or Infinities. Skip the transformation NaNs or Infinities. */
for non-real operands. */
(simplify (simplify
(rdiv @0 @0) (rdiv @0 @0)
(if (SCALAR_FLOAT_TYPE_P (type) (if (FLOAT_TYPE_P (type)
&& ! HONOR_NANS (TYPE_MODE (type)) && ! HONOR_NANS (element_mode (type))
&& ! HONOR_INFINITIES (TYPE_MODE (type))) && ! HONOR_INFINITIES (element_mode (type)))
{ build_real (type, dconst1); }) { build_one_cst (type); }))
/* The complex version of the above A / A optimization. */
(if (COMPLEX_FLOAT_TYPE_P (type) /* Optimize -A / A to -1.0 if we don't care about
&& ! HONOR_NANS (TYPE_MODE (TREE_TYPE (type))) NaNs or Infinities. */
&& ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type)))) (simplify
{ build_complex (type, build_real (TREE_TYPE (type), dconst1), (rdiv:c @0 (negate @0))
build_real (TREE_TYPE (type), dconst0)); })) (if (FLOAT_TYPE_P (type)
&& ! HONOR_NANS (element_mode (type))
&& ! HONOR_INFINITIES (element_mode (type)))
{ build_minus_one_cst (type); }))
/* In IEEE floating point, x/1 is not equivalent to x for snans. */ /* In IEEE floating point, x/1 is not equivalent to x for snans. */
(simplify (simplify
(rdiv @0 real_onep) (rdiv @0 real_onep)
(if (!HONOR_SNANS (TYPE_MODE (type))) (if (!HONOR_SNANS (element_mode (type)))
(non_lvalue @0))) (non_lvalue @0)))
/* In IEEE floating point, x/-1 is not equivalent to -x for snans. */ /* In IEEE floating point, x/-1 is not equivalent to -x for snans. */
(simplify (simplify
(rdiv @0 real_minus_onep) (rdiv @0 real_minus_onep)
(if (!HONOR_SNANS (TYPE_MODE (type))) (if (!HONOR_SNANS (element_mode (type)))
(negate @0))) (negate @0)))
/* If ARG1 is a constant, we can convert this to a multiply by the /* If ARG1 is a constant, we can convert this to a multiply by the
...@@ -192,9 +194,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -192,9 +194,8 @@ along with GCC; see the file COPYING3. If not see
{ build_zero_cst (type); }) { build_zero_cst (type); })
/* X % -1 is zero. */ /* X % -1 is zero. */
(simplify (simplify
(mod @0 INTEGER_CST@1) (mod @0 integer_minus_onep@1)
(if (!TYPE_UNSIGNED (type) (if (!TYPE_UNSIGNED (type))
&& wi::eq_p (@1, -1))
{ build_zero_cst (type); }))) { build_zero_cst (type); })))
/* X % -C is the same as X % C. */ /* X % -C is the same as X % C. */
...@@ -309,14 +310,11 @@ along with GCC; see the file COPYING3. If not see ...@@ -309,14 +310,11 @@ along with GCC; see the file COPYING3. If not see
(match (logical_inverted_value @0) (match (logical_inverted_value @0)
(bit_not truth_valued_p@0)) (bit_not truth_valued_p@0))
(match (logical_inverted_value @0) (match (logical_inverted_value @0)
(eq @0 integer_zerop) (eq @0 integer_zerop))
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
(match (logical_inverted_value @0) (match (logical_inverted_value @0)
(ne truth_valued_p@0 integer_onep) (ne truth_valued_p@0 integer_truep))
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
(match (logical_inverted_value @0) (match (logical_inverted_value @0)
(bit_xor truth_valued_p@0 integer_onep) (bit_xor truth_valued_p@0 integer_truep))
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
/* X & !X -> 0. */ /* X & !X -> 0. */
(simplify (simplify
...@@ -493,7 +491,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -493,7 +491,7 @@ along with GCC; see the file COPYING3. If not see
(simplify (simplify
(minus (convert (add @0 @1)) (minus (convert (add @0 @1))
(convert @0)) (convert @0))
(if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1)) (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
/* For integer types, if A has a smaller type /* For integer types, if A has a smaller type
than T the result depends on the possible than T the result depends on the possible
overflow in P + A. overflow in P + A.
...@@ -626,19 +624,19 @@ along with GCC; see the file COPYING3. If not see ...@@ -626,19 +624,19 @@ along with GCC; see the file COPYING3. If not see
int inside_int = INTEGRAL_TYPE_P (inside_type); int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type); int inside_ptr = POINTER_TYPE_P (inside_type);
int inside_float = FLOAT_TYPE_P (inside_type); int inside_float = FLOAT_TYPE_P (inside_type);
int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE; int inside_vec = VECTOR_TYPE_P (inside_type);
unsigned int inside_prec = TYPE_PRECISION (inside_type); unsigned int inside_prec = TYPE_PRECISION (inside_type);
int inside_unsignedp = TYPE_UNSIGNED (inside_type); int inside_unsignedp = TYPE_UNSIGNED (inside_type);
int inter_int = INTEGRAL_TYPE_P (inter_type); int inter_int = INTEGRAL_TYPE_P (inter_type);
int inter_ptr = POINTER_TYPE_P (inter_type); int inter_ptr = POINTER_TYPE_P (inter_type);
int inter_float = FLOAT_TYPE_P (inter_type); int inter_float = FLOAT_TYPE_P (inter_type);
int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE; int inter_vec = VECTOR_TYPE_P (inter_type);
unsigned int inter_prec = TYPE_PRECISION (inter_type); unsigned int inter_prec = TYPE_PRECISION (inter_type);
int inter_unsignedp = TYPE_UNSIGNED (inter_type); int inter_unsignedp = TYPE_UNSIGNED (inter_type);
int final_int = INTEGRAL_TYPE_P (type); int final_int = INTEGRAL_TYPE_P (type);
int final_ptr = POINTER_TYPE_P (type); int final_ptr = POINTER_TYPE_P (type);
int final_float = FLOAT_TYPE_P (type); int final_float = FLOAT_TYPE_P (type);
int final_vec = TREE_CODE (type) == VECTOR_TYPE; int final_vec = VECTOR_TYPE_P (type);
unsigned int final_prec = TYPE_PRECISION (type); unsigned int final_prec = TYPE_PRECISION (type);
int final_unsignedp = TYPE_UNSIGNED (type); int final_unsignedp = TYPE_UNSIGNED (type);
} }
...@@ -666,8 +664,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -666,8 +664,8 @@ along with GCC; see the file COPYING3. If not see
&& inter_prec >= inside_prec && inter_prec >= inside_prec
&& (inter_float || inter_vec && (inter_float || inter_vec
|| inter_unsignedp == inside_unsignedp) || inter_unsignedp == inside_unsignedp)
&& ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type)) && ! (final_prec != GET_MODE_PRECISION (element_mode (type))
&& TYPE_MODE (type) == TYPE_MODE (inter_type)) && element_mode (type) == element_mode (inter_type))
&& ! final_ptr && ! final_ptr
&& (! final_vec || inter_prec == inside_prec)) && (! final_vec || inter_prec == inside_prec))
(ocvt @0)) (ocvt @0))
...@@ -845,12 +843,12 @@ along with GCC; see the file COPYING3. If not see ...@@ -845,12 +843,12 @@ along with GCC; see the file COPYING3. If not see
/* A ? B : B -> B. */ /* A ? B : B -> B. */
(simplify (simplify
(cnd @0 @1 @1) (cnd @0 @1 @1)
@1)) @1)
/* !A ? B : C -> A ? C : B. */ /* !A ? B : C -> A ? C : B. */
(simplify (simplify
(cond (logical_inverted_value truth_valued_p@0) @1 @2) (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
(cond @0 @2 @1)) (cnd @0 @2 @1)))
/* Simplifications of comparisons. */ /* Simplifications of comparisons. */
...@@ -876,17 +874,16 @@ along with GCC; see the file COPYING3. If not see ...@@ -876,17 +874,16 @@ along with GCC; see the file COPYING3. If not see
a computed operator in the replacement tree thus we have a computed operator in the replacement tree thus we have
to play the trick below. */ to play the trick below. */
(with { enum tree_code ic = invert_tree_comparison (with { enum tree_code ic = invert_tree_comparison
(cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); } (cmp, HONOR_NANS (element_mode (@0))); }
(if (ic == icmp) (if (ic == icmp)
(icmp @0 @1)) (icmp @0 @1))
(if (ic == ncmp) (if (ic == ncmp)
(ncmp @0 @1))))) (ncmp @0 @1)))))
(simplify (simplify
(bit_xor (cmp @0 @1) integer_onep) (bit_xor (cmp @0 @1) integer_truep)
(if (INTEGRAL_TYPE_P (type)) (with { enum tree_code ic = invert_tree_comparison
(with { enum tree_code ic = invert_tree_comparison (cmp, HONOR_NANS (element_mode (@0))); }
(cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); } (if (ic == icmp)
(if (ic == icmp) (icmp @0 @1))
(icmp @0 @1)) (if (ic == ncmp)
(if (ic == ncmp) (ncmp @0 @1)))))
(ncmp @0 @1))))))
...@@ -2275,6 +2275,20 @@ integer_nonzerop (const_tree expr) ...@@ -2275,6 +2275,20 @@ integer_nonzerop (const_tree expr)
|| integer_nonzerop (TREE_IMAGPART (expr))))); || integer_nonzerop (TREE_IMAGPART (expr)))));
} }
/* Return 1 if EXPR is the integer constant one. For vector,
return 1 if every piece is the integer constant minus one
(representing the value TRUE). */
int
integer_truep (const_tree expr)
{
STRIP_NOPS (expr);
if (TREE_CODE (expr) == VECTOR_CST)
return integer_all_onesp (expr);
return integer_onep (expr);
}
/* Return 1 if EXPR is the fixed-point constant zero. */ /* Return 1 if EXPR is the fixed-point constant zero. */
int int
...@@ -12310,4 +12324,18 @@ get_base_address (tree t) ...@@ -12310,4 +12324,18 @@ get_base_address (tree t)
return t; return t;
} }
/* Return the machine mode of T. For vectors, returns the mode of the
inner type. The main use case is to feed the result to HONOR_NANS,
avoiding the BLKmode that a direct TYPE_MODE (T) might return. */
machine_mode
element_mode (const_tree t)
{
if (!TYPE_P (t))
t = TREE_TYPE (t);
if (VECTOR_TYPE_P (t) || TREE_CODE (t) == COMPLEX_TYPE)
t = TREE_TYPE (t);
return TYPE_MODE (t);
}
#include "gt-tree.h" #include "gt-tree.h"
...@@ -1564,6 +1564,8 @@ extern void protected_set_expr_location (tree, location_t); ...@@ -1564,6 +1564,8 @@ extern void protected_set_expr_location (tree, location_t);
#define SET_TYPE_MODE(NODE, MODE) \ #define SET_TYPE_MODE(NODE, MODE) \
(TYPE_CHECK (NODE)->type_common.mode = (MODE)) (TYPE_CHECK (NODE)->type_common.mode = (MODE))
extern machine_mode element_mode (const_tree t);
/* The "canonical" type for this type node, which is used by frontends to /* The "canonical" type for this type node, which is used by frontends to
compare the type for equality with another type. If two types are compare the type for equality with another type. If two types are
equal (based on the semantics of the language), then they will have equal (based on the semantics of the language), then they will have
...@@ -3999,6 +4001,11 @@ extern int integer_pow2p (const_tree); ...@@ -3999,6 +4001,11 @@ extern int integer_pow2p (const_tree);
extern int integer_nonzerop (const_tree); extern int integer_nonzerop (const_tree);
/* integer_truep (tree x) is nonzero if X is an integer constant of value 1 or
a vector where each element is an integer constant of value -1. */
extern int integer_truep (const_tree);
extern bool cst_and_fits_in_hwi (const_tree); extern bool cst_and_fits_in_hwi (const_tree);
extern tree num_ending_zeros (const_tree); extern tree num_ending_zeros (const_tree);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment