aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/fold-const.c158
-rw-r--r--gcc/generic-match-head.c1
-rw-r--r--gcc/gimple-match-head.c1
-rw-r--r--gcc/match.pd56
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21031.c4
7 files changed, 74 insertions, 160 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 47c7c16..0287697 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2015-07-16 Richard Biener <rguenther@suse.de>
+ * fold-const.c (fold_widened_comparison): Remove.
+ (fold_sign_changed_comparison): Likewise.
+ (fold_comparison): Move widened and sign-changed comparison
+ simplification ...
+ * match.pd: ... to patterns here.
+ * generic-match-head.c: Include target.h.
+ * gimple-match-head.c: Likewise.
+
+2015-07-16 Richard Biener <rguenther@suse.de>
+
* tree-ssa-dom.c (dom_valueize): New function.
(record_temporary_equivalences): Also record equivalences
for dominating stmts that have uses of equivalences we are
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index acccb3c..93dd29d 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6685,148 +6685,6 @@ tree_swap_operands_p (const_tree arg0, const_tree arg1, bool reorder)
return 0;
}
-/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where
- ARG0 is extended to a wider type. */
-
-static tree
-fold_widened_comparison (location_t loc, enum tree_code code,
- tree type, tree arg0, tree arg1)
-{
- tree arg0_unw = get_unwidened (arg0, NULL_TREE);
- tree arg1_unw;
- tree shorter_type, outer_type;
- tree min, max;
- bool above, below;
-
- if (arg0_unw == arg0)
- return NULL_TREE;
- shorter_type = TREE_TYPE (arg0_unw);
-
- /* Disable this optimization if we're casting a function pointer
- type on targets that require function pointer canonicalization. */
- if (targetm.have_canonicalize_funcptr_for_compare ()
- && TREE_CODE (shorter_type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (shorter_type)) == FUNCTION_TYPE)
- return NULL_TREE;
-
- if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
- return NULL_TREE;
-
- arg1_unw = get_unwidened (arg1, NULL_TREE);
-
- /* If possible, express the comparison in the shorter mode. */
- if ((code == EQ_EXPR || code == NE_EXPR
- || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
- && (TREE_TYPE (arg1_unw) == shorter_type
- || ((TYPE_PRECISION (shorter_type)
- >= TYPE_PRECISION (TREE_TYPE (arg1_unw)))
- && (TYPE_UNSIGNED (shorter_type)
- == TYPE_UNSIGNED (TREE_TYPE (arg1_unw))))
- || (TREE_CODE (arg1_unw) == INTEGER_CST
- && (TREE_CODE (shorter_type) == INTEGER_TYPE
- || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
- && int_fits_type_p (arg1_unw, shorter_type))))
- return fold_build2_loc (loc, code, type, arg0_unw,
- fold_convert_loc (loc, shorter_type, arg1_unw));
-
- if (TREE_CODE (arg1_unw) != INTEGER_CST
- || TREE_CODE (shorter_type) != INTEGER_TYPE
- || int_fits_type_p (arg1_unw, shorter_type))
- return NULL_TREE;
-
- /* If we are comparing with the integer that does not fit into the range
- of the shorter type, the result is known. */
- outer_type = TREE_TYPE (arg1_unw);
- min = lower_bound_in_type (outer_type, shorter_type);
- max = upper_bound_in_type (outer_type, shorter_type);
-
- above = integer_nonzerop (fold_relational_const (LT_EXPR, type,
- max, arg1_unw));
- below = integer_nonzerop (fold_relational_const (LT_EXPR, type,
- arg1_unw, min));
-
- switch (code)
- {
- case EQ_EXPR:
- if (above || below)
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
- break;
-
- case NE_EXPR:
- if (above || below)
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
- break;
-
- case LT_EXPR:
- case LE_EXPR:
- if (above)
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
- else if (below)
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
-
- case GT_EXPR:
- case GE_EXPR:
- if (above)
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
- else if (below)
- return omit_one_operand_loc (loc, type, integer_one_node, arg0);
-
- default:
- break;
- }
-
- return NULL_TREE;
-}
-
-/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where for
- ARG0 just the signedness is changed. */
-
-static tree
-fold_sign_changed_comparison (location_t loc, enum tree_code code, tree type,
- tree arg0, tree arg1)
-{
- tree arg0_inner;
- tree inner_type, outer_type;
-
- if (!CONVERT_EXPR_P (arg0))
- return NULL_TREE;
-
- outer_type = TREE_TYPE (arg0);
- arg0_inner = TREE_OPERAND (arg0, 0);
- inner_type = TREE_TYPE (arg0_inner);
-
- /* Disable this optimization if we're casting a function pointer
- type on targets that require function pointer canonicalization. */
- if (targetm.have_canonicalize_funcptr_for_compare ()
- && TREE_CODE (inner_type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE)
- return NULL_TREE;
-
- if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
- return NULL_TREE;
-
- if (TREE_CODE (arg1) != INTEGER_CST
- && !(CONVERT_EXPR_P (arg1)
- && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
- return NULL_TREE;
-
- if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
- && code != NE_EXPR
- && code != EQ_EXPR)
- return NULL_TREE;
-
- if (POINTER_TYPE_P (inner_type) != POINTER_TYPE_P (outer_type))
- return NULL_TREE;
-
- if (TREE_CODE (arg1) == INTEGER_CST)
- arg1 = force_fit_type (inner_type, wi::to_widest (arg1), 0,
- TREE_OVERFLOW (arg1));
- else
- arg1 = fold_convert_loc (loc, inner_type, arg1);
-
- return fold_build2_loc (loc, code, type, arg0_inner, arg1);
-}
-
/* Fold A < X && A + 1 > Y to A < X && A >= Y. Normally A + 1 > Y
means A >= Y && A != MAX, but in this case we know that
@@ -8813,22 +8671,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
if (tem)
return tem;
- if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
- && CONVERT_EXPR_P (arg0))
- {
- /* If we are widening one operand of an integer comparison,
- see if the other operand is similarly being widened. Perhaps we
- can do the comparison in the narrower type. */
- tem = fold_widened_comparison (loc, code, type, arg0, arg1);
- if (tem)
- return tem;
-
- /* Or if we are changing signedness. */
- tem = fold_sign_changed_comparison (loc, code, type, arg0, arg1);
- if (tem)
- return tem;
- }
-
/* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
constant, we can simplify it. */
if (TREE_CODE (arg1) == INTEGER_CST
diff --git a/gcc/generic-match-head.c b/gcc/generic-match-head.c
index 66615a4..da7abc6 100644
--- a/gcc/generic-match-head.c
+++ b/gcc/generic-match-head.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-dfa.h"
#include "builtins.h"
#include "dumpfile.h"
+#include "target.h"
#include "generic-match.h"
/* Routine to determine if the types T1 and T2 are effectively
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index 875b724..2b14238 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-dfa.h"
#include "builtins.h"
#include "dumpfile.h"
+#include "target.h"
#include "gimple-match.h"
diff --git a/gcc/match.pd b/gcc/match.pd
index a3fba51..c335ada 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1664,6 +1664,62 @@ along with GCC; see the file COPYING3. If not see
(if (tem && !TREE_OVERFLOW (tem))
(scmp @0 { tem; }))))))
+/* From fold_sign_changed_comparison and fold_widened_comparison. */
+(for cmp (simple_comparison)
+ (simplify
+ (cmp (convert@0 @00) (convert?@1 @10))
+ (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+ /* Disable this optimization if we're casting a function pointer
+ type on targets that require function pointer canonicalization. */
+ && !(targetm.have_canonicalize_funcptr_for_compare ()
+ && TREE_CODE (TREE_TYPE (@00)) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (@00))) == FUNCTION_TYPE))
+ (if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0))
+ && (TREE_CODE (@10) == INTEGER_CST
+ || (@1 != @10 && types_match (TREE_TYPE (@10), TREE_TYPE (@00))))
+ && (TYPE_UNSIGNED (TREE_TYPE (@00)) == TYPE_UNSIGNED (TREE_TYPE (@0))
+ || cmp == NE_EXPR
+ || cmp == EQ_EXPR)
+ && (POINTER_TYPE_P (TREE_TYPE (@00)) == POINTER_TYPE_P (TREE_TYPE (@0))))
+ /* ??? The special-casing of INTEGER_CST conversion was in the original
+ code and here to avoid a spurious overflow flag on the resulting
+ constant which fold_convert produces. */
+ (if (TREE_CODE (@1) == INTEGER_CST)
+ (cmp @00 { force_fit_type (TREE_TYPE (@00), wi::to_widest (@1), 0,
+ TREE_OVERFLOW (@1)); })
+ (cmp @00 (convert @1)))
+
+ (if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@00)))
+ /* If possible, express the comparison in the shorter mode. */
+ (if ((cmp == EQ_EXPR || cmp == NE_EXPR
+ || TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (TREE_TYPE (@00)))
+ && (types_match (TREE_TYPE (@10), TREE_TYPE (@00))
+ || ((TYPE_PRECISION (TREE_TYPE (@00))
+ >= TYPE_PRECISION (TREE_TYPE (@10)))
+ && (TYPE_UNSIGNED (TREE_TYPE (@00))
+ == TYPE_UNSIGNED (TREE_TYPE (@10))))
+ || (TREE_CODE (@10) == INTEGER_CST
+ && (TREE_CODE (TREE_TYPE (@00)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (@00)) == BOOLEAN_TYPE)
+ && int_fits_type_p (@10, TREE_TYPE (@00)))))
+ (cmp @00 (convert @10))
+ (if (TREE_CODE (@10) == INTEGER_CST
+ && TREE_CODE (TREE_TYPE (@00)) == INTEGER_TYPE
+ && !int_fits_type_p (@10, TREE_TYPE (@00)))
+ (with
+ {
+ tree min = lower_bound_in_type (TREE_TYPE (@10), TREE_TYPE (@00));
+ tree max = upper_bound_in_type (TREE_TYPE (@10), TREE_TYPE (@00));
+ bool above = integer_nonzerop (const_binop (LT_EXPR, type, max, @10));
+ bool below = integer_nonzerop (const_binop (LT_EXPR, type, @10, min));
+ }
+ (if (above || below)
+ (if (cmp == EQ_EXPR || cmp == NE_EXPR)
+ { constant_boolean_node (cmp == EQ_EXPR ? false : true, type); }
+ (if (cmp == LT_EXPR || cmp == LE_EXPR)
+ { constant_boolean_node (above ? true : false, type); }
+ (if (cmp == GT_EXPR || cmp == GE_EXPR)
+ { constant_boolean_node (above ? false : true, type); }))))))))))))
/* Equality compare simplifications from fold_binary */
(for cmp (eq ne)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a3ae9d5..8bc9341 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2015-07-16 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/pr21031.c: Adjust.
+
2015-07-16 Uros Bizjak <ubizjak@gmail.com>
PR target/66866
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c
index f39c127..a6f5b6e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c
@@ -3,7 +3,7 @@
Make sure that a != 0 is propagated into the "if" statement. */
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-forwprop1-details" } */
+/* { dg-options "-O1 -fdump-tree-forwprop1" } */
int
foo (int a)
@@ -16,4 +16,4 @@ foo (int a)
return 0;
}
-/* { dg-final { scan-tree-dump-times "Replaced" 2 "forwprop1" } } */
+/* { dg-final { scan-tree-dump "if \\(a_\[0-9\]+\\(D\\) != 0\\)" "forwprop1" } } */