Commit cc7b5acf by Richard Biener Committed by Richard Biener

match.pd: Implement patterns from associate_plusminus and factor in differences from the...

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

	* match.pd: Implement patterns from associate_plusminus
	and factor in differences from the fold-const.c implementation.
	* fold-const.c (fold_binary_loc): Remove patterns here.
	* tree-ssa-forwprop.c (associate_plusminus): Remove.
	(pass_forwprop::execute): Don't call it.
	* tree.c (tree_nop_conversion_p): New function, factored
	from tree_nop_conversion.
	* tree.h (tree_nop_conversion_p): Declare.

From-SVN: r217349
parent 9310366b
2014-11-11 Richard Biener <rguenther@suse.de>
* match.pd: Implement patterns from associate_plusminus
and factor in differences from the fold-const.c implementation.
* fold-const.c (fold_binary_loc): Remove patterns here.
* tree-ssa-forwprop.c (associate_plusminus): Remove.
(pass_forwprop::execute): Don't call it.
* tree.c (tree_nop_conversion_p): New function, factored
from tree_nop_conversion.
* tree.h (tree_nop_conversion_p): Declare.
2014-11-11 Uros Bizjak <ubizjak@gmail.com> 2014-11-11 Uros Bizjak <ubizjak@gmail.com>
* system.h: Include algorithm and utility. * system.h: Include algorithm and utility.
...@@ -9939,59 +9939,8 @@ fold_binary_loc (location_t loc, ...@@ -9939,59 +9939,8 @@ fold_binary_loc (location_t loc,
return NULL_TREE; return NULL_TREE;
case PLUS_EXPR: case PLUS_EXPR:
/* A + (-B) -> A - B */
if (TREE_CODE (arg1) == NEGATE_EXPR
&& (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type, arg0),
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
/* (-A) + B -> B - A */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& reorder_operands_p (TREE_OPERAND (arg0, 0), arg1)
&& (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type, arg1),
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
{ {
/* Convert ~A + 1 to -A. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& integer_each_onep (arg1))
return fold_build1_loc (loc, NEGATE_EXPR, type,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
/* ~X + X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& !TYPE_OVERFLOW_TRAPS (type))
{
tree tem = TREE_OPERAND (arg0, 0);
STRIP_NOPS (tem);
if (operand_equal_p (tem, arg1, 0))
{
t1 = build_all_ones_cst (type);
return omit_one_operand_loc (loc, type, t1, arg1);
}
}
/* X + ~X is -1. */
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& !TYPE_OVERFLOW_TRAPS (type))
{
tree tem = TREE_OPERAND (arg1, 0);
STRIP_NOPS (tem);
if (operand_equal_p (arg0, tem, 0))
{
t1 = build_all_ones_cst (type);
return omit_one_operand_loc (loc, type, t1, arg0);
}
}
/* X + (X / CST) * -CST is X % CST. */ /* X + (X / CST) * -CST is X % CST. */
if (TREE_CODE (arg1) == MULT_EXPR if (TREE_CODE (arg1) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
...@@ -10469,11 +10418,6 @@ fold_binary_loc (location_t loc, ...@@ -10469,11 +10418,6 @@ fold_binary_loc (location_t loc,
return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11); return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11);
} }
} }
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
return fold_build2_loc (loc, PLUS_EXPR, type, op0,
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */ /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR if (TREE_CODE (arg0) == NEGATE_EXPR
&& negate_expr_p (arg1) && negate_expr_p (arg1)
......
...@@ -25,8 +25,9 @@ along with GCC; see the file COPYING3. If not see ...@@ -25,8 +25,9 @@ along with GCC; see the file COPYING3. If not see
/* Generic tree predicates we inherit. */ /* Generic tree predicates we inherit. */
(define_predicates (define_predicates
integer_onep integer_zerop integer_all_onesp integer_onep integer_zerop integer_all_onesp integer_minus_onep
real_zerop real_onep integer_each_onep
real_zerop real_onep real_minus_onep
CONSTANT_CLASS_P CONSTANT_CLASS_P
tree_expr_nonnegative_p) tree_expr_nonnegative_p)
...@@ -239,10 +240,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -239,10 +240,6 @@ along with GCC; see the file COPYING3. If not see
(bit_not (bit_not @0)) (bit_not (bit_not @0))
@0) @0)
(simplify
(negate (negate @0))
@0)
/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */
(simplify (simplify
...@@ -278,6 +275,116 @@ along with GCC; see the file COPYING3. If not see ...@@ -278,6 +275,116 @@ along with GCC; see the file COPYING3. If not see
(bit_and @0 { algn; }))) (bit_and @0 { algn; })))
/* We can't reassociate at all for saturating types. */
(if (!TYPE_SATURATING (type))
/* Contract negates. */
/* A + (-B) -> A - B */
(simplify
(plus:c (convert1? @0) (convert2? (negate @1)))
/* Apply STRIP_NOPS on @0 and the negate. */
(if (tree_nop_conversion_p (type, TREE_TYPE (@0))
&& tree_nop_conversion_p (type, TREE_TYPE (@1))
&& (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
(minus (convert @0) (convert @1))))
/* A - (-B) -> A + B */
(simplify
(minus (convert1? @0) (convert2? (negate @1)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@0))
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(plus (convert @0) (convert @1))))
/* -(-A) -> A */
(simplify
(negate (convert? (negate @1)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@1))
&& (TYPE_OVERFLOW_WRAPS (type)
|| (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0))
@1))
/* We can't reassociate floating-point or fixed-point plus or minus
because of saturation to +-Inf. */
(if (!FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
/* Match patterns that allow contracting a plus-minus pair
irrespective of overflow issues. */
/* (A +- B) - A -> +- B */
/* (A +- B) -+ B -> A */
/* A - (A +- B) -> -+ B */
/* A +- (B -+ A) -> +- B */
(simplify
(minus (plus:c @0 @1) @0)
@1)
(simplify
(minus (minus @0 @1) @0)
(negate @1))
(simplify
(plus:c (minus @0 @1) @1)
@0)
(simplify
(minus @0 (plus:c @0 @1))
(negate @1))
(simplify
(minus @0 (minus @0 @1))
@1)
/* (A +- CST) +- CST -> A + CST */
(for outer_op (plus minus)
(for inner_op (plus minus)
(simplify
(outer_op (inner_op @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
/* If the constant operation overflows we cannot do the transform
as we would introduce undefined overflow, for example
with (a - 1) + INT_MIN. */
(with { tree cst = fold_binary (outer_op == inner_op
? PLUS_EXPR : MINUS_EXPR, type, @1, @2); }
(if (cst && !TREE_OVERFLOW (cst))
(inner_op @0 { cst; } ))))))
/* (CST - A) +- CST -> CST - A */
(for outer_op (plus minus)
(simplify
(outer_op (minus CONSTANT_CLASS_P@1 @0) CONSTANT_CLASS_P@2)
(with { tree cst = fold_binary (outer_op, type, @1, @2); }
(if (cst && !TREE_OVERFLOW (cst))
(minus { cst; } @0)))))
/* ~A + A -> -1 */
(simplify
(plus:c (bit_not @0) @0)
(if (!TYPE_OVERFLOW_TRAPS (type))
{ build_all_ones_cst (type); }))
/* ~A + 1 -> -A */
(simplify
(plus (bit_not @0) integer_each_onep)
(negate @0))
/* (T)(P + A) - (T)P -> (T) A */
(for add (plus pointer_plus)
(simplify
(minus (convert (add @0 @1))
(convert @0))
(if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
/* For integer types, if A has a smaller type
than T the result depends on the possible
overflow in P + A.
E.g. T=size_t, A=(unsigned)429497295, P>0.
However, if an overflow in P + A would cause
undefined behavior, we can assume that there
is no overflow. */
|| (INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
/* For pointer types, if the conversion of A to the
final type requires a sign- or zero-extension,
then we have to punt - it is not defined which
one is correct. */
|| (POINTER_TYPE_P (TREE_TYPE (@0))
&& TREE_CODE (@1) == INTEGER_CST
&& tree_int_cst_sign_bit (@1) == 0))
(convert @1))))))
/* Simplifications of conversions. */ /* Simplifications of conversions. */
/* Basic strip-useless-type-conversions / strip_nops. */ /* Basic strip-useless-type-conversions / strip_nops. */
......
...@@ -11659,6 +11659,27 @@ block_ultimate_origin (const_tree block) ...@@ -11659,6 +11659,27 @@ block_ultimate_origin (const_tree block)
} }
} }
/* Return true iff conversion from INNER_TYPE to OUTER_TYPE generates
no instruction. */
bool
tree_nop_conversion_p (const_tree outer_type, const_tree inner_type)
{
/* Use precision rather then machine mode when we can, which gives
the correct answer even for submode (bit-field) types. */
if ((INTEGRAL_TYPE_P (outer_type)
|| POINTER_TYPE_P (outer_type)
|| TREE_CODE (outer_type) == OFFSET_TYPE)
&& (INTEGRAL_TYPE_P (inner_type)
|| POINTER_TYPE_P (inner_type)
|| TREE_CODE (inner_type) == OFFSET_TYPE))
return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
/* Otherwise fall back on comparing machine modes (e.g. for
aggregate types, floats). */
return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
}
/* Return true iff conversion in EXP generates no instruction. Mark /* Return true iff conversion in EXP generates no instruction. Mark
it inline so that we fully inline into the stripping functions even it inline so that we fully inline into the stripping functions even
though we have two uses of this function. */ though we have two uses of this function. */
...@@ -11680,19 +11701,7 @@ tree_nop_conversion (const_tree exp) ...@@ -11680,19 +11701,7 @@ tree_nop_conversion (const_tree exp)
if (!inner_type) if (!inner_type)
return false; return false;
/* Use precision rather then machine mode when we can, which gives return tree_nop_conversion_p (outer_type, inner_type);
the correct answer even for submode (bit-field) types. */
if ((INTEGRAL_TYPE_P (outer_type)
|| POINTER_TYPE_P (outer_type)
|| TREE_CODE (outer_type) == OFFSET_TYPE)
&& (INTEGRAL_TYPE_P (inner_type)
|| POINTER_TYPE_P (inner_type)
|| TREE_CODE (inner_type) == OFFSET_TYPE))
return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
/* Otherwise fall back on comparing machine modes (e.g. for
aggregate types, floats). */
return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
} }
/* Return true iff conversion in EXP generates no instruction. Don't /* Return true iff conversion in EXP generates no instruction. Don't
......
...@@ -4226,6 +4226,7 @@ extern bool is_typedef_decl (tree x); ...@@ -4226,6 +4226,7 @@ extern bool is_typedef_decl (tree x);
extern bool typedef_variant_p (tree); extern bool typedef_variant_p (tree);
extern bool auto_var_in_fn_p (const_tree, const_tree); extern bool auto_var_in_fn_p (const_tree, const_tree);
extern tree build_low_bits_mask (tree, unsigned); extern tree build_low_bits_mask (tree, unsigned);
extern bool tree_nop_conversion_p (const_tree, const_tree);
extern tree tree_strip_nop_conversions (tree); extern tree tree_strip_nop_conversions (tree);
extern tree tree_strip_sign_nop_conversions (tree); extern tree tree_strip_sign_nop_conversions (tree);
extern const_tree strip_invariant_refs (const_tree); extern const_tree strip_invariant_refs (const_tree);
......
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