Move some comparison simplifications to match.pd
2015-08-31 Marc Glisse <marc.glisse@inria.fr> 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
This commit is contained in:
parent
f196d06291
commit
b0eb889bf8
7 changed files with 80 additions and 21 deletions
|
@ -1,3 +1,13 @@
|
|||
2015-08-31 Marc Glisse <marc.glisse@inria.fr>
|
||||
|
||||
* 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 <rguenther@suse.de>
|
||||
|
||||
PR middle-end/67381
|
||||
|
|
|
@ -10678,11 +10678,6 @@ fold_binary_loc (location_t loc,
|
|||
TREE_OPERAND (arg0, 1), arg1);
|
||||
}
|
||||
|
||||
/* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 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
|
||||
|
|
31
gcc/match.pd
31
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<x> == 0 or ABS_EXPR<x> != 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
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2015-08-31 Marc Glisse <marc.glisse@inria.fr>
|
||||
|
||||
* gcc.dg/tree-ssa/cmp-1.c: New file.
|
||||
|
||||
2015-08-31 Marc Glisse <marc.glisse@inria.fr>
|
||||
|
||||
* gcc.dg/tree-ssa/complex-7.c: New file.
|
||||
|
|
19
gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c
Normal file
19
gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c
Normal file
|
@ -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"} } */
|
13
gcc/tree.c
13
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);
|
||||
|
|
|
@ -4109,6 +4109,10 @@ extern tree uniform_vector_p (const_tree);
|
|||
|
||||
extern vec<tree, va_gc> *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);
|
||||
|
|
Loading…
Add table
Reference in a new issue