From: Marc Glisse Date: Mon, 31 Aug 2015 14:02:00 +0000 (+0200) Subject: Move some comparison simplifications to match.pd X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b0eb889bf88eff3316690c6397a7f3dc75fbeda7;p=gcc.git Move some comparison simplifications to match.pd 2015-08-31 Marc Glisse gcc/ * tree.h (zerop): New function. * tree.c (zerop): Likewise. (element_precision): Handle expressions. * match.pd (define_predicates): Add zerop. (x <= +Inf): Fix comment. (abs (x) == 0, A & C == C, A & C != 0): Converted from ... * fold-const.c (fold_binary_loc): ... here. Remove. gcc/testsuite/ * gcc.dg/tree-ssa/cmp-1.c: New file. From-SVN: r227346 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index adc85fe964a..fdc02094e27 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-08-31 Marc Glisse + + * tree.h (zerop): New function. + * tree.c (zerop): Likewise. + (element_precision): Handle expressions. + * match.pd (define_predicates): Add zerop. + (x <= +Inf): Fix comment. + (abs (x) == 0, A & C == C, A & C != 0): Converted from ... + * fold-const.c (fold_binary_loc): ... here. Remove. + 2015-08-31 Richard Biener PR middle-end/67381 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a5d58a86692..d478c4dc1c2 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10678,11 +10678,6 @@ fold_binary_loc (location_t loc, TREE_OPERAND (arg0, 1), arg1); } - /* Convert ABS_EXPR == 0 or ABS_EXPR != 0 to x == 0 or x != 0. */ - if (TREE_CODE (arg0) == ABS_EXPR - && (integer_zerop (arg1) || real_zerop (arg1))) - return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), arg1); - /* If this is an EQ or NE comparison with zero and ARG0 is (1 << foo) & bar, convert it to (bar >> foo) & 1. Both require two operations, but the latter can be done in one less insn @@ -10785,21 +10780,6 @@ fold_binary_loc (location_t loc, } } - /* If we have (A & C) == C where C is a power of 2, convert this into - (A & C) != 0. Similarly for NE_EXPR. */ - if (TREE_CODE (arg0) == BIT_AND_EXPR - && integer_pow2p (TREE_OPERAND (arg0, 1)) - && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)) - return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type, - arg0, fold_convert_loc (loc, TREE_TYPE (arg0), - integer_zero_node)); - - /* If we have (A & C) != 0 or (A & C) == 0 and C is the sign - bit, then fold the expression into A < 0 or A >= 0. */ - tem = fold_single_bit_test_into_sign_test (loc, code, arg0, arg1, type); - if (tem) - return tem; - /* If we have (A & C) == D where D & ~C != 0, convert this into 0. Similarly for NE_EXPR. */ if (TREE_CODE (arg0) == BIT_AND_EXPR diff --git a/gcc/match.pd b/gcc/match.pd index 50de7bbf8a6..fb4b342d31d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see integer_onep integer_zerop integer_all_onesp integer_minus_onep integer_each_onep integer_truep integer_nonzerop real_zerop real_onep real_minus_onep + zerop CONSTANT_CLASS_P tree_expr_nonnegative_p integer_pow2p @@ -1608,7 +1609,7 @@ along with GCC; see the file COPYING3. If not see /* x <= +Inf is always true, if we don't case about NaNs. */ (if (! HONOR_NANS (@0)) { constant_boolean_node (true, type); } - /* x <= +Inf is the same as x == x, i.e. isfinite(x). */ + /* x <= +Inf is the same as x == x, i.e. !isnan(x). */ (eq @0 @0))) /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */ (if (code == EQ_EXPR || code == GE_EXPR) @@ -1765,6 +1766,12 @@ along with GCC; see the file COPYING3. If not see (if (tem && !TREE_OVERFLOW (tem)) (scmp @0 { tem; })))))) +/* Convert ABS_EXPR == 0 or ABS_EXPR != 0 to x == 0 or x != 0. */ +(for op (eq ne) + (simplify + (op (abs @0) zerop@1) + (op @0 @1))) + /* From fold_sign_changed_comparison and fold_widened_comparison. */ (for cmp (simple_comparison) (simplify @@ -1871,6 +1878,28 @@ along with GCC; see the file COPYING3. If not see (if (tree_single_nonzero_warnv_p (@0, NULL)) { constant_boolean_node (cmp == NE_EXPR, type); }))) +/* If we have (A & C) == C where C is a power of 2, convert this into + (A & C) != 0. Similarly for NE_EXPR. */ +(for cmp (eq ne) + icmp (ne eq) + (simplify + (cmp (bit_and@2 @0 integer_pow2p@1) @1) + (icmp @2 { build_zero_cst (TREE_TYPE (@0)); }))) + +/* If we have (A & C) != 0 where C is the sign bit of A, convert + this into A < 0. Similarly for (A & C) == 0 into A >= 0. */ +(for cmp (eq ne) + ncmp (ge lt) + (simplify + (cmp (bit_and (convert?@2 @0) integer_pow2p@1) integer_zerop) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && (TYPE_PRECISION (TREE_TYPE (@0)) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@0)))) + && element_precision (@2) >= element_precision (@0) + && wi::only_sign_bit_p (@1, element_precision (@0))) + (with { tree stype = signed_type_for (TREE_TYPE (@0)); } + (ncmp (convert:stype @0) { build_zero_cst (stype); }))))) + /* When the addresses are not directly of decls compare base and offset. This implements some remaining parts of fold_comparison address comparisons but still no complete part of it. Still it is good diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 24f93142db6..15dc00dd211 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-08-31 Marc Glisse + + * gcc.dg/tree-ssa/cmp-1.c: New file. + 2015-08-31 Marc Glisse * gcc.dg/tree-ssa/complex-7.c: New file. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c new file mode 100644 index 00000000000..6faa70c8df3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-gimple -fdump-tree-optimized" } */ + +int f(int a){ + int b = -__INT_MAX__-1; + a &= b; + return a == b; +} +int g(int x){ + x = x < 0 ? -x : x; + return x == 0; +} + +/* This should work even if int is not 32 bits, it is just not meaningful in + that case. */ +/* { dg-final { scan-tree-dump-not "-2147483648" "optimized"} } */ +/* { dg-final { scan-tree-dump " < 0" "optimized"} } */ +/* { dg-final { scan-tree-dump "ABS_EXPR" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized"} } */ diff --git a/gcc/tree.c b/gcc/tree.c index af3a6a340e4..ed64fe7d273 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -2215,6 +2215,17 @@ grow_tree_vec_stat (tree v, int len MEM_STAT_DECL) return v; } +/* Return 1 if EXPR is the constant zero, whether it is integral, float or + fixed, and scalar, complex or vector. */ + +int +zerop (const_tree expr) +{ + return (integer_zerop (expr) + || real_zerop (expr) + || fixed_zerop (expr)); +} + /* Return 1 if EXPR is the integer constant zero or a complex constant of zero. */ @@ -7512,6 +7523,8 @@ valid_constant_size_p (const_tree size) unsigned int element_precision (const_tree type) { + if (!TYPE_P (type)) + type = TREE_TYPE (type); enum tree_code code = TREE_CODE (type); if (code == COMPLEX_TYPE || code == VECTOR_TYPE) type = TREE_TYPE (type); diff --git a/gcc/tree.h b/gcc/tree.h index 2cd6ec475a8..e5001510bdc 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4109,6 +4109,10 @@ extern tree uniform_vector_p (const_tree); extern vec *ctor_to_vec (tree); +/* zerop (tree x) is nonzero if X is a constant of value 0. */ + +extern int zerop (const_tree); + /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0. */ extern int integer_zerop (const_tree);