fold-const.c (fold_widened_comparison): Remove.
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. * gcc.dg/tree-ssa/pr21031.c: Adjust. From-SVN: r225861
This commit is contained in:
parent
612b9d1364
commit
79d4f7c66e
@ -1,3 +1,13 @@
|
||||
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.
|
||||
|
158
gcc/fold-const.c
158
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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
56
gcc/match.pd
56
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)
|
||||
|
@ -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
|
||||
|
@ -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" } } */
|
||||
|
Loading…
Reference in New Issue
Block a user