Commit 5609420f by Richard Biener Committed by Richard Biener

match.pd: Implement bitwise binary and unary simplifications from tree-ssa-forwprop.c.

2014-11-06  Richard Biener  <rguenther@suse.de>

	* match.pd: Implement bitwise binary and unary simplifications
	from tree-ssa-forwprop.c.
	* fold-const.c (fold_unary_loc): Remove them here.
	(fold_binary_loc): Likewise.
	* tree-ssa-forwprop.c (simplify_not_neg_expr): Remove.
	(truth_valued_ssa_name): Likewise.
	(lookup_logical_inverted_value): Likewise.
	(simplify_bitwise_binary_1): Likewise.
	(hoist_conversion_for_bitop_p): Likewise.
	(simplify_bitwise_binary_boolean): Likewise.
	(simplify_bitwise_binary): Likewise.
	(pass_forwprop::execute): Remove calls to simplify_not_neg_expr
	and simplify_bitwise_binary.
	* genmatch.c (dt_node::append_true_op): Use safe_as_a for parent.
	(decision_tree::insert): Also insert non-expressions.

	* gcc.dg/tree-ssa/forwprop-28.c: Adjust scanning for the
	desired transform.

From-SVN: r217178
parent 45ea41fe
2014-11-06 Richard Biener <rguenther@suse.de>
* match.pd: Implement bitwise binary and unary simplifications
from tree-ssa-forwprop.c.
* fold-const.c (fold_unary_loc): Remove them here.
(fold_binary_loc): Likewise.
* tree-ssa-forwprop.c (simplify_not_neg_expr): Remove.
(truth_valued_ssa_name): Likewise.
(lookup_logical_inverted_value): Likewise.
(simplify_bitwise_binary_1): Likewise.
(hoist_conversion_for_bitop_p): Likewise.
(simplify_bitwise_binary_boolean): Likewise.
(simplify_bitwise_binary): Likewise.
(pass_forwprop::execute): Remove calls to simplify_not_neg_expr
and simplify_bitwise_binary.
* genmatch.c (dt_node::append_true_op): Use safe_as_a for parent.
(decision_tree::insert): Also insert non-expressions.
2014-11-06 Hale Wang <Hale.Wang@arm.com> 2014-11-06 Hale Wang <Hale.Wang@arm.com>
* config/arm/arm-cores.def: Add support for * config/arm/arm-cores.def: Add support for
...@@ -8008,8 +8008,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -8008,8 +8008,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
if (TREE_CODE (arg0) == INTEGER_CST) if (TREE_CODE (arg0) == INTEGER_CST)
return fold_not_const (arg0, type); return fold_not_const (arg0, type);
else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
/* Convert ~ (-A) to A - 1. */ /* Convert ~ (-A) to A - 1. */
else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR) else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
return fold_build2_loc (loc, MINUS_EXPR, type, return fold_build2_loc (loc, MINUS_EXPR, type,
...@@ -11152,26 +11150,6 @@ fold_binary_loc (location_t loc, ...@@ -11152,26 +11150,6 @@ fold_binary_loc (location_t loc,
arg1); arg1);
} }
/* (X & Y) | Y is (X, Y). */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 0));
/* (X & Y) | X is (Y, X). */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 1));
/* X | (X & Y) is (Y, X). */
if (TREE_CODE (arg1) == BIT_AND_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 1));
/* X | (Y & X) is (Y, X). */
if (TREE_CODE (arg1) == BIT_AND_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
/* (X & ~Y) | (~X & Y) is X ^ Y */ /* (X & ~Y) | (~X & Y) is X ^ Y */
if (TREE_CODE (arg0) == BIT_AND_EXPR if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == BIT_AND_EXPR) && TREE_CODE (arg1) == BIT_AND_EXPR)
...@@ -11391,42 +11369,6 @@ fold_binary_loc (location_t loc, ...@@ -11391,42 +11369,6 @@ fold_binary_loc (location_t loc,
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)) && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return omit_one_operand_loc (loc, type, integer_zero_node, arg0); return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
/* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2). */
if (TREE_CODE (arg0) == BIT_IOR_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
tree tmp1 = fold_convert_loc (loc, type, arg1);
tree tmp2 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
tree tmp3 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
tmp2 = fold_build2_loc (loc, BIT_AND_EXPR, type, tmp2, tmp1);
tmp3 = fold_build2_loc (loc, BIT_AND_EXPR, type, tmp3, tmp1);
return
fold_convert_loc (loc, type,
fold_build2_loc (loc, BIT_IOR_EXPR,
type, tmp2, tmp3));
}
/* (X | Y) & Y is (X, Y). */
if (TREE_CODE (arg0) == BIT_IOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 0));
/* (X | Y) & X is (Y, X). */
if (TREE_CODE (arg0) == BIT_IOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
return omit_one_operand_loc (loc, type, arg1, TREE_OPERAND (arg0, 1));
/* X & (X | Y) is (Y, X). */
if (TREE_CODE (arg1) == BIT_IOR_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 1));
/* X & (Y | X) is (Y, X). */
if (TREE_CODE (arg1) == BIT_IOR_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
/* Fold (X ^ 1) & 1 as (X & 1) == 0. */ /* Fold (X ^ 1) & 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (type)
......
...@@ -1126,7 +1126,7 @@ dt_node::append_op (operand *op, dt_node *parent, unsigned pos) ...@@ -1126,7 +1126,7 @@ dt_node::append_op (operand *op, dt_node *parent, unsigned pos)
dt_node * dt_node *
dt_node::append_true_op (dt_node *parent, unsigned pos) dt_node::append_true_op (dt_node *parent, unsigned pos)
{ {
dt_operand *parent_ = as_a<dt_operand *> (parent); dt_operand *parent_ = safe_as_a<dt_operand *> (parent);
dt_operand *n = new dt_operand (DT_TRUE, 0, 0, parent_, pos); dt_operand *n = new dt_operand (DT_TRUE, 0, 0, parent_, pos);
return append_node (n); return append_node (n);
} }
...@@ -1232,9 +1232,6 @@ at_assert_elm: ...@@ -1232,9 +1232,6 @@ at_assert_elm:
void void
decision_tree::insert (struct simplify *s, unsigned pattern_no) decision_tree::insert (struct simplify *s, unsigned pattern_no)
{ {
if (s->match->type != operand::OP_EXPR)
return;
dt_operand **indexes = XCNEWVEC (dt_operand *, s->capture_max + 1); dt_operand **indexes = XCNEWVEC (dt_operand *, s->capture_max + 1);
dt_node *p = decision_tree::insert_operand (root, s->match, indexes); dt_node *p = decision_tree::insert_operand (root, s->match, indexes);
p->append_simplify (s, pattern_no, indexes); p->append_simplify (s, pattern_no, indexes);
......
...@@ -113,6 +113,134 @@ along with GCC; see the file COPYING3. If not see ...@@ -113,6 +113,134 @@ along with GCC; see the file COPYING3. If not see
@0) @0)
/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
when profitable.
For bitwise binary operations apply operand conversions to the
binary operation result instead of to the operands. This allows
to combine successive conversions and bitwise binary operations.
We combine the above two cases by using a conditional convert. */
(for bitop (bit_and bit_ior bit_xor)
(simplify
(bitop (convert @0) (convert? @1))
(if (((TREE_CODE (@1) == INTEGER_CST
&& INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& int_fits_type_p (@1, TREE_TYPE (@0))
/* ??? This transform conflicts with fold-const.c doing
Convert (T)(x & c) into (T)x & (T)c, if c is an integer
constants (if x has signed type, the sign bit cannot be set
in c). This folds extension into the BIT_AND_EXPR.
Restrict it to GIMPLE to avoid endless recursions. */
&& (bitop != BIT_AND_EXPR || GIMPLE))
|| types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1)))
&& (/* That's a good idea if the conversion widens the operand, thus
after hoisting the conversion the operation will be narrower. */
TYPE_PRECISION (TREE_TYPE (@0)) < TYPE_PRECISION (type)
/* It's also a good idea if the conversion is to a non-integer
mode. */
|| GET_MODE_CLASS (TYPE_MODE (type)) != MODE_INT
/* Or if the precision of TO is not the same as the precision
of its mode. */
|| TYPE_PRECISION (type) != GET_MODE_PRECISION (TYPE_MODE (type))))
(convert (bitop @0 (convert @1))))))
/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
(for bitop (bit_and bit_ior bit_xor)
(simplify
(bitop (bit_and:c @0 @1) (bit_and @2 @1))
(bit_and (bitop @0 @2) @1)))
/* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
(simplify
(bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
(bit_ior (bit_and @0 @2) (bit_and @1 @2)))
/* Combine successive equal operations with constants. */
(for bitop (bit_and bit_ior bit_xor)
(simplify
(bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
(bitop @0 (bitop @1 @2))))
/* Try simple folding for X op !X, and X op X with the help
of the truth_valued_p and logical_inverted_value predicates. */
(match truth_valued_p
@0
(if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
(for op (lt le eq ne ge gt truth_and truth_andif truth_or truth_orif truth_xor)
(match truth_valued_p
(op @0 @1)))
(match truth_valued_p
(truth_not @0))
(match (logical_inverted_value @0)
(bit_not truth_valued_p@0))
(match (logical_inverted_value @0)
(eq @0 integer_zerop)
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
(match (logical_inverted_value @0)
(ne truth_valued_p@0 integer_onep)
(if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
(match (logical_inverted_value @0)
(bit_xor truth_valued_p@0 integer_onep))
/* X & !X -> 0. */
(simplify
(bit_and:c @0 (logical_inverted_value @0))
{ build_zero_cst (type); })
/* X | !X and X ^ !X -> 1, , if X is truth-valued. */
(for op (bit_ior bit_xor)
(simplify
(op:c truth_valued_p@0 (logical_inverted_value @0))
{ build_one_cst (type); }))
(for bitop (bit_and bit_ior)
rbitop (bit_ior bit_and)
/* (x | y) & x -> x */
/* (x & y) | x -> x */
(simplify
(bitop:c (rbitop:c @0 @1) @0)
@0)
/* (~x | y) & x -> x & y */
/* (~x & y) | x -> x | y */
(simplify
(bitop:c (rbitop:c (bit_not @0) @1) @0)
(bitop @0 @1)))
/* If arg1 and arg2 are booleans (or any single bit type)
then try to simplify:
(~X & Y) -> X < Y
(X & ~Y) -> Y < X
(~X | Y) -> X <= Y
(X | ~Y) -> Y <= X
But only do this if our result feeds into a comparison as
this transformation is not always a win, particularly on
targets with and-not instructions.
-> simplify_bitwise_binary_boolean */
(simplify
(ne (bit_and:c (bit_not @0) @1) integer_zerop)
(if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
&& TYPE_PRECISION (TREE_TYPE (@1)) == 1)
(lt @0 @1)))
(simplify
(ne (bit_ior:c (bit_not @0) @1) integer_zerop)
(if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
&& TYPE_PRECISION (TREE_TYPE (@1)) == 1)
(le @0 @1)))
/* From tree-ssa-forwprop.c:simplify_not_neg_expr. */
/* ~~x -> x */
(simplify
(bit_not (bit_not @0))
@0)
/* The corresponding (negate (negate @0)) -> @0 is in match-plusminus.pd. */
(simplify
(negate (negate @0))
@0)
/* Simplifications of conversions. */ /* Simplifications of conversions. */
/* Basic strip-useless-type-conversions / strip_nops. */ /* Basic strip-useless-type-conversions / strip_nops. */
......
2014-11-06 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/forwprop-28.c: Adjust scanning for the
desired transform.
2014-11-05 Matthew Fortune <matthew.fortune@imgtec.com> 2014-11-05 Matthew Fortune <matthew.fortune@imgtec.com>
* gcc.target/mips/asm-1.c (bar): Add prototype. * gcc.target/mips/asm-1.c (bar): Add prototype.
......
/* Setting LOGICAL_OP_NON_SHORT_CIRCUIT to 0 leads to two conditional jumps /* Setting LOGICAL_OP_NON_SHORT_CIRCUIT to 0 leads to two conditional jumps
when evaluating an && condition. VRP is not able to optimize this. */ when evaluating an && condition. VRP is not able to optimize this. */
/* { dg-do compile { target { ! { logical_op_short_circuit || { m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* } } } } } */ /* { dg-do compile { target { ! { logical_op_short_circuit || { m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* } } } } } */
/* { dg-options "-O2 -fdump-tree-forwprop1" } */ /* { dg-options "-O2 -fdump-tree-forwprop1-details" } */
extern char *frob (void); extern char *frob (void);
extern _Bool testit (void); extern _Bool testit (void);
...@@ -79,6 +79,6 @@ test_8 (int code) ...@@ -79,6 +79,6 @@ test_8 (int code)
oof (); oof ();
} }
/* { dg-final { scan-tree-dump-times "Replaced" 8 "forwprop1"} } */ /* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* <" 8 "forwprop1"} } */
/* { dg-final { cleanup-tree-dump "forwprop1" } } */ /* { dg-final { cleanup-tree-dump "forwprop1" } } */
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