diff mbox

[11/n] Merge from match-and-simplify, bit patterns from forwprop

Message ID alpine.LSU.2.11.1411060952430.27850@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Nov. 6, 2014, 8:55 a.m. UTC
This merges patterns implementing the bitwise patterns from 
tree-ssa-forwprop.c.  I've removed duplicate functionality from
fold-const.c as I found them, some may be still lurking in the
depths.

This also fixes a bug in genmatch which made user-defined predicates
matching anything, thus

(match foo
 @0
 (if ...

not work (that is: ignored).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

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.

Comments

Andrew Pinski Nov. 6, 2014, 9:10 a.m. UTC | #1
> On Nov 6, 2014, at 12:55 AM, Richard Biener <rguenther@suse.de> wrote:
> 
> 
> This merges patterns implementing the bitwise patterns from 
> tree-ssa-forwprop.c.  I've removed duplicate functionality from
> fold-const.c as I found them, some may be still lurking in the
> depths.
> 
> This also fixes a bug in genmatch which made user-defined predicates
> matching anything, thus
> 
> (match foo
> @0
> (if ...
> 
> not work (that is: ignored).
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Only one small comment. 

> 
> Richard.
> 
> 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.
> 
> Index: trunk/gcc/fold-const.c
> ===================================================================
> --- trunk.orig/gcc/fold-const.c    2014-11-05 13:31:01.131942296 +0100
> +++ trunk/gcc/fold-const.c    2014-11-05 13:35:29.362930558 +0100
> @@ -8008,8 +8008,6 @@ fold_unary_loc (location_t loc, enum tre
>     case BIT_NOT_EXPR:
>       if (TREE_CODE (arg0) == INTEGER_CST)
>         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.  */
>       else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
>    return fold_build2_loc (loc, MINUS_EXPR, type,
> @@ -11152,26 +11150,6 @@ fold_binary_loc (location_t loc,
>                    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 */
>       if (TREE_CODE (arg0) == BIT_AND_EXPR
>      && TREE_CODE (arg1) == BIT_AND_EXPR)
> @@ -11391,42 +11369,6 @@ fold_binary_loc (location_t loc,
>      && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
>    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.  */
>       if (TREE_CODE (arg0) == BIT_XOR_EXPR
>      && INTEGRAL_TYPE_P (type)
> Index: trunk/gcc/match.pd
> ===================================================================
> --- trunk.orig/gcc/match.pd    2014-11-05 13:31:01.131942296 +0100
> +++ trunk/gcc/match.pd    2014-11-05 13:37:57.099924093 +0100
> @@ -113,6 +113,134 @@ along with GCC; see the file COPYING3.
>  @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.  */

This above comment is no longer true as far as I can tell. 

> +(simplify
> + (negate (negate @0))
> + @0)

Thanks,
Andrew


> +
> +
> /* Simplifications of conversions.  */
> 
> /* Basic strip-useless-type-conversions / strip_nops.  */
> Index: trunk/gcc/tree-ssa-forwprop.c
> ===================================================================
> --- trunk.orig/gcc/tree-ssa-forwprop.c    2014-11-05 13:31:01.131942296 +0100
> +++ trunk/gcc/tree-ssa-forwprop.c    2014-11-05 13:35:29.365930558 +0100
> @@ -1253,49 +1253,6 @@ simplify_conversion_from_bitmask (gimple
> }
> 
> 
> -/* If we have lhs = ~x (STMT), look and see if earlier we had x = ~y.
> -   If so, we can change STMT into lhs = y which can later be copy
> -   propagated.  Similarly for negation.
> -
> -   This could trivially be formulated as a forward propagation
> -   to immediate uses.  However, we already had an implementation
> -   from DOM which used backward propagation via the use-def links.
> -
> -   It turns out that backward propagation is actually faster as
> -   there's less work to do for each NOT/NEG expression we find.
> -   Backwards propagation needs to look at the statement in a single
> -   backlink.  Forward propagation needs to look at potentially more
> -   than one forward link.
> -
> -   Returns true when the statement was changed.  */
> -
> -static bool 
> -simplify_not_neg_expr (gimple_stmt_iterator *gsi_p)
> -{
> -  gimple stmt = gsi_stmt (*gsi_p);
> -  tree rhs = gimple_assign_rhs1 (stmt);
> -  gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
> -
> -  /* See if the RHS_DEF_STMT has the same form as our statement.  */
> -  if (is_gimple_assign (rhs_def_stmt)
> -      && gimple_assign_rhs_code (rhs_def_stmt) == gimple_assign_rhs_code (stmt))
> -    {
> -      tree rhs_def_operand = gimple_assign_rhs1 (rhs_def_stmt);
> -
> -      /* Verify that RHS_DEF_OPERAND is a suitable SSA_NAME.  */
> -      if (TREE_CODE (rhs_def_operand) == SSA_NAME
> -      && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs_def_operand))
> -    {
> -      gimple_assign_set_rhs_from_tree (gsi_p, rhs_def_operand);
> -      stmt = gsi_stmt (*gsi_p);
> -      update_stmt (stmt);
> -      return true;
> -    }
> -    }
> -
> -  return false;
> -}
> -
> /* Helper function for simplify_gimple_switch.  Remove case labels that
>    have values outside the range of the new type.  */
> 
> @@ -1714,126 +1671,6 @@ simplify_builtin_call (gimple_stmt_itera
>   return false;
> }
> 
> -/* Checks if expression has type of one-bit precision, or is a known
> -   truth-valued expression.  */
> -static bool
> -truth_valued_ssa_name (tree name)
> -{
> -  gimple def;
> -  tree type = TREE_TYPE (name);
> -
> -  if (!INTEGRAL_TYPE_P (type))
> -    return false;
> -  /* Don't check here for BOOLEAN_TYPE as the precision isn't
> -     necessarily one and so ~X is not equal to !X.  */
> -  if (TYPE_PRECISION (type) == 1)
> -    return true;
> -  def = SSA_NAME_DEF_STMT (name);
> -  if (is_gimple_assign (def))
> -    return truth_value_p (gimple_assign_rhs_code (def));
> -  return false;
> -}
> -
> -/* Helper routine for simplify_bitwise_binary_1 function.
> -   Return for the SSA name NAME the expression X if it mets condition
> -   NAME = !X. Otherwise return NULL_TREE.
> -   Detected patterns for NAME = !X are:
> -     !X and X == 0 for X with integral type.
> -     X ^ 1, X != 1,or ~X for X with integral type with precision of one.  */
> -static tree
> -lookup_logical_inverted_value (tree name)
> -{
> -  tree op1, op2;
> -  enum tree_code code;
> -  gimple def;
> -
> -  /* If name has none-intergal type, or isn't a SSA_NAME, then
> -     return.  */
> -  if (TREE_CODE (name) != SSA_NAME
> -      || !INTEGRAL_TYPE_P (TREE_TYPE (name)))
> -    return NULL_TREE;
> -  def = SSA_NAME_DEF_STMT (name);
> -  if (!is_gimple_assign (def))
> -    return NULL_TREE;
> -
> -  code = gimple_assign_rhs_code (def);
> -  op1 = gimple_assign_rhs1 (def);
> -  op2 = NULL_TREE;
> -
> -  /* Get for EQ_EXPR or BIT_XOR_EXPR operation the second operand.
> -     If CODE isn't an EQ_EXPR, BIT_XOR_EXPR, or BIT_NOT_EXPR, then return.  */
> -  if (code == EQ_EXPR || code == NE_EXPR
> -      || code == BIT_XOR_EXPR)
> -    op2 = gimple_assign_rhs2 (def);
> -
> -  switch (code)
> -    {
> -    case BIT_NOT_EXPR:
> -      if (truth_valued_ssa_name (name))
> -    return op1;
> -      break;
> -    case EQ_EXPR:
> -      /* Check if we have X == 0 and X has an integral type.  */
> -      if (!INTEGRAL_TYPE_P (TREE_TYPE (op1)))
> -    break;
> -      if (integer_zerop (op2))
> -    return op1;
> -      break;
> -    case NE_EXPR:
> -      /* Check if we have X != 1 and X is a truth-valued.  */
> -      if (!INTEGRAL_TYPE_P (TREE_TYPE (op1)))
> -    break;
> -      if (integer_onep (op2) && truth_valued_ssa_name (op1))
> -    return op1;
> -      break;
> -    case BIT_XOR_EXPR:
> -      /* Check if we have X ^ 1 and X is truth valued.  */
> -      if (integer_onep (op2) && truth_valued_ssa_name (op1))
> -    return op1;
> -      break;
> -    default:
> -      break;
> -    }
> -
> -  return NULL_TREE;
> -}
> -
> -/* Optimize ARG1 CODE ARG2 to a constant for bitwise binary
> -   operations CODE, if one operand has the logically inverted
> -   value of the other.  */
> -static tree
> -simplify_bitwise_binary_1 (enum tree_code code, tree type,
> -               tree arg1, tree arg2)
> -{
> -  tree anot;
> -
> -  /* If CODE isn't a bitwise binary operation, return NULL_TREE.  */
> -  if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR
> -      && code != BIT_XOR_EXPR)
> -    return NULL_TREE;
> -
> -  /* First check if operands ARG1 and ARG2 are equal.  If so
> -     return NULL_TREE as this optimization is handled fold_stmt.  */
> -  if (arg1 == arg2)
> -    return NULL_TREE;
> -  /* See if we have in arguments logical-not patterns.  */
> -  if (((anot = lookup_logical_inverted_value (arg1)) == NULL_TREE
> -       || anot != arg2)
> -      && ((anot = lookup_logical_inverted_value (arg2)) == NULL_TREE
> -      || anot != arg1))
> -    return NULL_TREE;
> -
> -  /* X & !X -> 0.  */
> -  if (code == BIT_AND_EXPR)
> -    return fold_convert (type, integer_zero_node);
> -  /* X | !X -> 1 and X ^ !X -> 1, if X is truth-valued.  */
> -  if (truth_valued_ssa_name (anot))
> -    return fold_convert (type, integer_one_node);
> -
> -  /* ??? Otherwise result is (X != 0 ? X : 1).  not handled.  */
> -  return NULL_TREE;
> -}
> -
> /* Given a ssa_name in NAME see if it was defined by an assignment and
>    set CODE to be the code and ARG1 to the first operand on the rhs and ARG2
>    to the second operand on the rhs. */
> @@ -1879,353 +1716,6 @@ defcodefor_name (tree name, enum tree_co
>   /* Ignore arg3 currently. */
> }
> 
> -/* Return true if a conversion of an operand from type FROM to type TO
> -   should be applied after performing the operation instead.  */
> -
> -static bool
> -hoist_conversion_for_bitop_p (tree to, tree from)
> -{
> -  /* That's a good idea if the conversion widens the operand, thus
> -     after hoisting the conversion the operation will be narrower.  */
> -  if (TYPE_PRECISION (from) < TYPE_PRECISION (to))
> -    return true;
> -
> -  /* It's also a good idea if the conversion is to a non-integer mode.  */
> -  if (GET_MODE_CLASS (TYPE_MODE (to)) != MODE_INT)
> -    return true;
> -
> -  /* Or if the precision of TO is not the same as the precision
> -     of its mode.  */
> -  if (TYPE_PRECISION (to) != GET_MODE_PRECISION (TYPE_MODE (to)))
> -    return true;
> -
> -  return false;
> -}
> -
> -/* GSI points to a statement of the form
> -
> -   result = OP0 CODE OP1
> -
> -   Where OP0 and OP1 are single bit SSA_NAMEs and CODE is either
> -   BIT_AND_EXPR or BIT_IOR_EXPR.
> -
> -   If OP0 is fed by a bitwise negation of another single bit SSA_NAME,
> -   then we can simplify the two statements into a single LT_EXPR or LE_EXPR
> -   when code is BIT_AND_EXPR and BIT_IOR_EXPR respectively.
> -
> -   If a simplification is made, return TRUE, else return FALSE.  */
> -static bool
> -simplify_bitwise_binary_boolean (gimple_stmt_iterator *gsi,
> -                 enum tree_code code,
> -                 tree op0, tree op1)
> -{
> -  gimple op0_def_stmt = SSA_NAME_DEF_STMT (op0);
> -
> -  if (!is_gimple_assign (op0_def_stmt)
> -      || (gimple_assign_rhs_code (op0_def_stmt) != BIT_NOT_EXPR))
> -    return false;
> -
> -  tree x = gimple_assign_rhs1 (op0_def_stmt);
> -  if (TREE_CODE (x) == SSA_NAME
> -      && INTEGRAL_TYPE_P (TREE_TYPE (x))
> -      && TYPE_PRECISION (TREE_TYPE (x)) == 1
> -      && TYPE_UNSIGNED (TREE_TYPE (x)) == TYPE_UNSIGNED (TREE_TYPE (op1)))
> -    {
> -      enum tree_code newcode;
> -
> -      gimple stmt = gsi_stmt (*gsi);
> -      gimple_assign_set_rhs1 (stmt, x);
> -      gimple_assign_set_rhs2 (stmt, op1);
> -      if (code == BIT_AND_EXPR)
> -    newcode = TYPE_UNSIGNED (TREE_TYPE (x)) ? LT_EXPR : GT_EXPR;
> -      else
> -    newcode = TYPE_UNSIGNED (TREE_TYPE (x)) ? LE_EXPR : GE_EXPR;
> -      gimple_assign_set_rhs_code (stmt, newcode); 
> -      update_stmt (stmt);
> -      return true;
> -    }
> -  return false;
> -
> -}
> -
> -/* Simplify bitwise binary operations.
> -   Return true if a transformation applied, otherwise return false.  */
> -
> -static bool
> -simplify_bitwise_binary (gimple_stmt_iterator *gsi)
> -{
> -  gimple stmt = gsi_stmt (*gsi);
> -  tree arg1 = gimple_assign_rhs1 (stmt);
> -  tree arg2 = gimple_assign_rhs2 (stmt);
> -  enum tree_code code = gimple_assign_rhs_code (stmt);
> -  tree res;
> -  tree def1_arg1, def1_arg2, def2_arg1, def2_arg2;
> -  enum tree_code def1_code, def2_code;
> -
> -  defcodefor_name (arg1, &def1_code, &def1_arg1, &def1_arg2);
> -  defcodefor_name (arg2, &def2_code, &def2_arg1, &def2_arg2);
> -
> -  /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
> -     when profitable.  */
> -  if (TREE_CODE (arg2) == INTEGER_CST
> -      && CONVERT_EXPR_CODE_P (def1_code)
> -      && hoist_conversion_for_bitop_p (TREE_TYPE (arg1), TREE_TYPE (def1_arg1))
> -      && INTEGRAL_TYPE_P (TREE_TYPE (def1_arg1))
> -      && int_fits_type_p (arg2, TREE_TYPE (def1_arg1)))
> -    {
> -      gimple newop;
> -      tree tem = make_ssa_name (TREE_TYPE (def1_arg1), NULL);
> -      newop =
> -        gimple_build_assign_with_ops (code, tem, def1_arg1,
> -                      fold_convert_loc (gimple_location (stmt),
> -                            TREE_TYPE (def1_arg1),
> -                            arg2));
> -      gimple_set_location (newop, gimple_location (stmt));
> -      gsi_insert_before (gsi, newop, GSI_SAME_STMT);
> -      gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR,
> -                    tem, NULL_TREE, NULL_TREE);
> -      update_stmt (gsi_stmt (*gsi));
> -      return true;
> -    }
> -
> -  /* 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.  */
> -  if (CONVERT_EXPR_CODE_P (def1_code)
> -      && CONVERT_EXPR_CODE_P (def2_code)
> -      && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1))
> -      && hoist_conversion_for_bitop_p (TREE_TYPE (arg1), TREE_TYPE (def1_arg1)))
> -    {
> -      gimple newop;
> -      tree tem = make_ssa_name (TREE_TYPE (def1_arg1), NULL);
> -      newop = gimple_build_assign_with_ops (code, tem, def1_arg1, def2_arg1);
> -      gimple_set_location (newop, gimple_location (stmt));
> -      gsi_insert_before (gsi, newop, GSI_SAME_STMT);
> -      gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR,
> -                    tem, NULL_TREE, NULL_TREE);
> -      update_stmt (gsi_stmt (*gsi));
> -      return true;
> -    }
> -
> -
> -   /* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
> -   if (def1_code == def2_code
> -       && def1_code == BIT_AND_EXPR
> -       && operand_equal_for_phi_arg_p (def1_arg2,
> -                       def2_arg2))
> -    {
> -      tree b = def1_arg2;
> -      tree a = def1_arg1;
> -      tree c = def2_arg1;
> -      tree inner = fold_build2 (code, TREE_TYPE (arg2), a, c);
> -      /* If A OP0 C (this usually means C is the same as A) is 0
> -     then fold it down correctly. */
> -      if (integer_zerop (inner))
> -    {
> -      gimple_assign_set_rhs_from_tree (gsi, inner);
> -      update_stmt (stmt);
> -      return true;
> -    }
> -      /* If A OP0 C (this usually means C is the same as A) is a ssa_name
> -     then fold it down correctly. */
> -      else if (TREE_CODE (inner) == SSA_NAME)
> -    {
> -            tree outer = fold_build2 (def1_code, TREE_TYPE (inner),
> -                    inner, b);
> -      gimple_assign_set_rhs_from_tree (gsi, outer);
> -      update_stmt (stmt);
> -      return true;
> -    }
> -      else
> -    {
> -      gimple newop;
> -      tree tem;
> -      tem = make_ssa_name (TREE_TYPE (arg2), NULL);
> -      newop = gimple_build_assign_with_ops (code, tem, a, c);
> -      gimple_set_location (newop, gimple_location (stmt));
> -      /* Make sure to re-process the new stmt as it's walking upwards.  */
> -      gsi_insert_before (gsi, newop, GSI_NEW_STMT);
> -      gimple_assign_set_rhs1 (stmt, tem);
> -      gimple_assign_set_rhs2 (stmt, b);
> -      gimple_assign_set_rhs_code (stmt, def1_code);
> -      update_stmt (stmt);
> -      return true;
> -    }
> -    }
> -
> -  /* (a | CST1) & CST2  ->  (a & CST2) | (CST1 & CST2).  */
> -  if (code == BIT_AND_EXPR
> -      && def1_code == BIT_IOR_EXPR
> -      && CONSTANT_CLASS_P (arg2)
> -      && CONSTANT_CLASS_P (def1_arg2))
> -    {
> -      tree cst = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg2),
> -                  arg2, def1_arg2);
> -      tree tem;
> -      gimple newop;
> -      if (integer_zerop (cst))
> -    {
> -      gimple_assign_set_rhs1 (stmt, def1_arg1);
> -      update_stmt (stmt);
> -      return true;
> -    }
> -      tem = make_ssa_name (TREE_TYPE (arg2), NULL);
> -      newop = gimple_build_assign_with_ops (BIT_AND_EXPR,
> -                        tem, def1_arg1, arg2);
> -      gimple_set_location (newop, gimple_location (stmt));
> -      /* Make sure to re-process the new stmt as it's walking upwards.  */
> -      gsi_insert_before (gsi, newop, GSI_NEW_STMT);
> -      gimple_assign_set_rhs1 (stmt, tem);
> -      gimple_assign_set_rhs2 (stmt, cst);
> -      gimple_assign_set_rhs_code (stmt, BIT_IOR_EXPR);
> -      update_stmt (stmt);
> -      return true;
> -    }
> -
> -  /* Combine successive equal operations with constants.  */
> -  if ((code == BIT_AND_EXPR
> -       || code == BIT_IOR_EXPR
> -       || code == BIT_XOR_EXPR)
> -      && def1_code == code 
> -      && CONSTANT_CLASS_P (arg2)
> -      && CONSTANT_CLASS_P (def1_arg2))
> -    {
> -      tree cst = fold_build2 (code, TREE_TYPE (arg2),
> -                  arg2, def1_arg2);
> -      gimple_assign_set_rhs1 (stmt, def1_arg1);
> -      gimple_assign_set_rhs2 (stmt, cst);
> -      update_stmt (stmt);
> -      return true;
> -    }
> -
> -  /* Try simple folding for X op !X, and X op X.  */
> -  res = simplify_bitwise_binary_1 (code, TREE_TYPE (arg1), arg1, arg2);
> -  if (res != NULL_TREE)
> -    {
> -      gimple_assign_set_rhs_from_tree (gsi, res);
> -      update_stmt (gsi_stmt (*gsi));
> -      return true;
> -    }
> -
> -  if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
> -    {
> -      enum tree_code ocode = code == BIT_AND_EXPR ? BIT_IOR_EXPR : BIT_AND_EXPR;
> -      if (def1_code == ocode)
> -    {
> -      tree x = arg2;
> -      enum tree_code coden;
> -      tree a1, a2;
> -      /* ( X | Y) & X -> X */
> -      /* ( X & Y) | X -> X */
> -      if (x == def1_arg1
> -          || x == def1_arg2)
> -        {
> -          gimple_assign_set_rhs_from_tree (gsi, x);
> -          update_stmt (gsi_stmt (*gsi));
> -          return true;
> -        }
> -
> -      defcodefor_name (def1_arg1, &coden, &a1, &a2);
> -      /* (~X | Y) & X -> X & Y */
> -      /* (~X & Y) | X -> X | Y */
> -      if (coden == BIT_NOT_EXPR && a1 == x)
> -        {
> -          gimple_assign_set_rhs_with_ops (gsi, code,
> -                          x, def1_arg2);
> -          gcc_assert (gsi_stmt (*gsi) == stmt);
> -          update_stmt (stmt);
> -          return true;
> -        }
> -      defcodefor_name (def1_arg2, &coden, &a1, &a2);
> -      /* (Y | ~X) & X -> X & Y */
> -      /* (Y & ~X) | X -> X | Y */
> -      if (coden == BIT_NOT_EXPR && a1 == x)
> -        {
> -          gimple_assign_set_rhs_with_ops (gsi, code,
> -                          x, def1_arg1);
> -          gcc_assert (gsi_stmt (*gsi) == stmt);
> -          update_stmt (stmt);
> -          return true;
> -        }
> -    }
> -      if (def2_code == ocode)
> -    {
> -      enum tree_code coden;
> -      tree a1;
> -      tree x = arg1;
> -      /* X & ( X | Y) -> X */
> -      /* X | ( X & Y) -> X */
> -      if (x == def2_arg1
> -          || x == def2_arg2)
> -        {
> -          gimple_assign_set_rhs_from_tree (gsi, x);
> -          update_stmt (gsi_stmt (*gsi));
> -          return true;
> -        }
> -      defcodefor_name (def2_arg1, &coden, &a1, NULL);
> -      /* (~X | Y) & X -> X & Y */
> -      /* (~X & Y) | X -> X | Y */
> -      if (coden == BIT_NOT_EXPR && a1 == x)
> -        {
> -          gimple_assign_set_rhs_with_ops (gsi, code,
> -                          x, def2_arg2);
> -          gcc_assert (gsi_stmt (*gsi) == stmt);
> -          update_stmt (stmt);
> -          return true;
> -        }
> -      defcodefor_name (def2_arg2, &coden, &a1, NULL);
> -      /* (Y | ~X) & X -> X & Y */
> -      /* (Y & ~X) | X -> X | Y */
> -      if (coden == BIT_NOT_EXPR && a1 == x)
> -        {
> -          gimple_assign_set_rhs_with_ops (gsi, code,
> -                          x, def2_arg1);
> -          gcc_assert (gsi_stmt (*gsi) == stmt);
> -          update_stmt (stmt);
> -          return true;
> -        }
> -    }
> -
> -      /* 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.  */
> -      if (TREE_CODE (arg1) == SSA_NAME
> -      && TREE_CODE (arg2) == SSA_NAME
> -      && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
> -      && TYPE_PRECISION (TREE_TYPE (arg1)) == 1
> -      && TYPE_PRECISION (TREE_TYPE (arg2)) == 1
> -      && (TYPE_UNSIGNED (TREE_TYPE (arg1))
> -          == TYPE_UNSIGNED (TREE_TYPE (arg2))))
> -    {
> -      use_operand_p use_p;
> -          gimple use_stmt;
> -
> -      if (single_imm_use (gimple_assign_lhs (stmt), &use_p, &use_stmt))
> -        {
> -          if (gimple_code (use_stmt) == GIMPLE_COND
> -          && gimple_cond_lhs (use_stmt) == gimple_assign_lhs (stmt)
> -          && integer_zerop (gimple_cond_rhs (use_stmt))
> -          && gimple_cond_code (use_stmt) == NE_EXPR)
> -        {
> -              if (simplify_bitwise_binary_boolean (gsi, code, arg1, arg2))
> -            return true;
> -              if (simplify_bitwise_binary_boolean (gsi, code, arg2, arg1))
> -            return true;
> -        }
> -        }
> -    }
> -    }
> -  return false;
> -}
> -
> 
> /* Recognize rotation patterns.  Return true if a transformation
>    applied, otherwise return false.
> @@ -3760,12 +3250,8 @@ pass_forwprop::execute (function *fun)
>        tree rhs1 = gimple_assign_rhs1 (stmt);
>        enum tree_code code = gimple_assign_rhs_code (stmt);
> 
> -        if ((code == BIT_NOT_EXPR
> -             || code == NEGATE_EXPR)
> -            && TREE_CODE (rhs1) == SSA_NAME)
> -          changed = simplify_not_neg_expr (&gsi);
> -        else if (code == COND_EXPR
> -             || code == VEC_COND_EXPR)
> +        if (code == COND_EXPR
> +            || code == VEC_COND_EXPR)
>          {
>            /* In this case the entire COND_EXPR is in rhs1. */
>            if (forward_propagate_into_cond (&gsi)
> @@ -3788,10 +3274,6 @@ pass_forwprop::execute (function *fun)
>              || code == BIT_XOR_EXPR)
>             && simplify_rotate (&gsi))
>          changed = true;
> -        else if (code == BIT_AND_EXPR
> -             || code == BIT_IOR_EXPR
> -             || code == BIT_XOR_EXPR)
> -          changed = simplify_bitwise_binary (&gsi);
>        else if (code == MULT_EXPR)
>          {
>            changed = simplify_mult (&gsi);
> Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c
> ===================================================================
> --- trunk.orig/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c    2014-11-05 13:30:43.209943080 +0100
> +++ trunk/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c    2014-11-05 13:35:29.365930558 +0100
> @@ -1,7 +1,7 @@
> /* Setting LOGICAL_OP_NON_SHORT_CIRCUIT to 0 leads to two conditional jumps
>    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-options "-O2 -fdump-tree-forwprop1" } */
> +/* { dg-options "-O2 -fdump-tree-forwprop1-details" } */
> 
> extern char *frob (void);
> extern _Bool testit (void);
> @@ -79,6 +79,6 @@ test_8 (int code)
>     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" } } */
> 
> Index: trunk/gcc/genmatch.c
> ===================================================================
> --- trunk.orig/gcc/genmatch.c    2014-11-05 13:38:00.799923931 +0100
> +++ trunk/gcc/genmatch.c    2014-11-05 13:38:48.927921825 +0100
> @@ -1126,7 +1126,7 @@ dt_node::append_op (operand *op, dt_node
> dt_node *
> 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);
>   return append_node (n);
> }
> @@ -1232,9 +1232,6 @@ at_assert_elm:
> void
> 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_node *p = decision_tree::insert_operand (root, s->match, indexes);
>   p->append_simplify (s, pattern_no, indexes);
Marc Glisse Nov. 6, 2014, 12:17 p.m. UTC | #2
On Thu, 6 Nov 2014, Richard Biener wrote:

> +/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */

> +/* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */

As soon as there are 2+ operations in the result, this comment in 
fwprop_ssa_val becomes outdated, no?

   /* We continue matching along SSA use-def edges for SSA names
      that are not single-use.  Currently there are no patterns
      that would cause any issues with that.  */

(I am not opposing the patch, just trying to understand how things work 
for when I'll propose new patterns)
Marc Glisse Nov. 6, 2014, 12:31 p.m. UTC | #3
On Thu, 6 Nov 2014, Richard Biener wrote:

> +/* 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); }))

Shouldn't that be build_true_cst (type) so it is -1 for vectors? It
seems that it could match:
vec a, b;
vec c=a<b;
vec d=~c;
vec e=c|d;
Richard Biener Nov. 6, 2014, 1:43 p.m. UTC | #4
On Thu, 6 Nov 2014, Marc Glisse wrote:

> On Thu, 6 Nov 2014, Richard Biener wrote:
> 
> > +/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
> 
> > +/* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
> 
> As soon as there are 2+ operations in the result, this comment in
> fwprop_ssa_val becomes outdated, no?

Yes, but in the above case the 2nd operand of the outer | folds
to a constant, thus the whole expression only uses a single SSA
name.  Btw, I was careful to only convert patterns from 
tree-ssa-forwprop.c that do not care about the number of uses
(if you look there are not many that do - mainly all the
comparison simplification)

>   /* We continue matching along SSA use-def edges for SSA names
>      that are not single-use.  Currently there are no patterns
>      that would cause any issues with that.  */
> 
> (I am not opposing the patch, just trying to understand how things work for
> when I'll propose new patterns)

If it's entirely new patterns and the pattern is a simplification
I wouldn't care about single-uses.  CSE is supposed to fix things up
for us.  Exceptions may apply if for example the operation we transform
to is more expensive than the two we combine it from.

But well - apply common sense.

I am currently trying to make us not regress ;)  (I don't expect
to get to replace the comparison simplification tree-ssa-forwprop.c
does with patterns as fold_comparison and friends has so many
transforms with "interesting" implementations - not during this
stage1 at least)

Richard.
Richard Biener Nov. 6, 2014, 1:45 p.m. UTC | #5
On Thu, 6 Nov 2014, Marc Glisse wrote:

> On Thu, 6 Nov 2014, Richard Biener wrote:
> 
> > +/* 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); }))
> 
> Shouldn't that be build_true_cst (type) so it is -1 for vectors? It
> seems that it could match:
> vec a, b;
> vec c=a<b;
> vec d=~c;
> vec e=c|d;

Probably.  Note that I copied this from tree-ssa-forwprop.c.

Generally I try to avoid fixing bugs or improving things at this point
to make the transition more obvious.

Richard.
Marc Glisse Nov. 6, 2014, 2:06 p.m. UTC | #6
On Thu, 6 Nov 2014, Richard Biener wrote:

> On Thu, 6 Nov 2014, Marc Glisse wrote:
>
>> On Thu, 6 Nov 2014, Richard Biener wrote:
>>
>>> +/* 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); }))
>>
>> Shouldn't that be build_true_cst (type) so it is -1 for vectors? It
>> seems that it could match:
>> vec a, b;
>> vec c=a<b;
>> vec d=~c;
>> vec e=c|d;
>
> Probably.  Note that I copied this from tree-ssa-forwprop.c.
>
> Generally I try to avoid fixing bugs or improving things at this point
> to make the transition more obvious.

But truth_valued_ssa_name starts with:

   if (!INTEGRAL_TYPE_P (type))
     return false;

so it does not match vectors. lookup_logical_inverted_value has a similar 
test.
Richard Biener Nov. 6, 2014, 2:30 p.m. UTC | #7
On Thu, 6 Nov 2014, Marc Glisse wrote:

> On Thu, 6 Nov 2014, Richard Biener wrote:
> 
> > On Thu, 6 Nov 2014, Marc Glisse wrote:
> > 
> > > On Thu, 6 Nov 2014, Richard Biener wrote:
> > > 
> > > > +/* 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); }))
> > > 
> > > Shouldn't that be build_true_cst (type) so it is -1 for vectors? It
> > > seems that it could match:
> > > vec a, b;
> > > vec c=a<b;
> > > vec d=~c;
> > > vec e=c|d;
> > 
> > Probably.  Note that I copied this from tree-ssa-forwprop.c.
> > 
> > Generally I try to avoid fixing bugs or improving things at this point
> > to make the transition more obvious.
> 
> But truth_valued_ssa_name starts with:
> 
>   if (!INTEGRAL_TYPE_P (type))
>     return false;
> 
> so it does not match vectors. lookup_logical_inverted_value has a similar
> test.

But truth_valued_p doesn't catch vector types, no?  That said,
the

> > > > +(match (logical_inverted_value @0)
> > > > + (bit_xor truth_valued_p@0 integer_onep))

would have a similar issue for vectors?

I'll happily approve a patch that makes it work correctly for vectors
(with a testcase)!

A bug with a testcase that is miscompiled is also ok, I'll fix that
then.

Thanks,
Richard.
Marc Glisse Nov. 6, 2014, 2:48 p.m. UTC | #8
On Thu, 6 Nov 2014, Richard Biener wrote:

> On Thu, 6 Nov 2014, Marc Glisse wrote:
>
>> On Thu, 6 Nov 2014, Richard Biener wrote:
>>
>>> On Thu, 6 Nov 2014, Marc Glisse wrote:
>>>
>>>> On Thu, 6 Nov 2014, Richard Biener wrote:
>>>>
>>>>> +/* 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); }))
>>>>
>>>> Shouldn't that be build_true_cst (type) so it is -1 for vectors? It
>>>> seems that it could match:
>>>> vec a, b;
>>>> vec c=a<b;
>>>> vec d=~c;
>>>> vec e=c|d;
>>>
>>> Probably.  Note that I copied this from tree-ssa-forwprop.c.
>>>
>>> Generally I try to avoid fixing bugs or improving things at this point
>>> to make the transition more obvious.
>>
>> But truth_valued_ssa_name starts with:
>>
>>   if (!INTEGRAL_TYPE_P (type))
>>     return false;
>>
>> so it does not match vectors. lookup_logical_inverted_value has a similar
>> test.
>
> But truth_valued_p doesn't catch vector types, no?

IIUC it catches a<b, whether this is a vector or not.

> That said, the
>
>>>>> +(match (logical_inverted_value @0)
>>>>> + (bit_xor truth_valued_p@0 integer_onep))
>
> would have a similar issue for vectors?

Probably, yes. integer_truep maybe, to match a new build_true_cst...

> I'll happily approve a patch that makes it work correctly for vectors
> (with a testcase)!

I'd like to wait until you are mostly done merging, so I can make just one 
pass on the .pd file.
H.J. Lu Nov. 9, 2014, 2:31 a.m. UTC | #9
On Thu, Nov 6, 2014 at 12:55 AM, Richard Biener <rguenther@suse.de> wrote:
>
> This merges patterns implementing the bitwise patterns from
> tree-ssa-forwprop.c.  I've removed duplicate functionality from
> fold-const.c as I found them, some may be still lurking in the
> depths.
>
> This also fixes a bug in genmatch which made user-defined predicates
> matching anything, thus
>
> (match foo
>  @0
>  (if ...
>
> not work (that is: ignored).
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
>
> Richard.
>
> 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.
>

This caused:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63787


H.J.
diff mbox

Patch

Index: trunk/gcc/fold-const.c
===================================================================
--- trunk.orig/gcc/fold-const.c	2014-11-05 13:31:01.131942296 +0100
+++ trunk/gcc/fold-const.c	2014-11-05 13:35:29.362930558 +0100
@@ -8008,8 +8008,6 @@  fold_unary_loc (location_t loc, enum tre
     case BIT_NOT_EXPR:
       if (TREE_CODE (arg0) == INTEGER_CST)
         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.  */
       else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
 	return fold_build2_loc (loc, MINUS_EXPR, type,
@@ -11152,26 +11150,6 @@  fold_binary_loc (location_t loc,
 				    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 */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
 	  && TREE_CODE (arg1) == BIT_AND_EXPR)
@@ -11391,42 +11369,6 @@  fold_binary_loc (location_t loc,
 	  && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
 	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.  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
 	  && INTEGRAL_TYPE_P (type)
Index: trunk/gcc/match.pd
===================================================================
--- trunk.orig/gcc/match.pd	2014-11-05 13:31:01.131942296 +0100
+++ trunk/gcc/match.pd	2014-11-05 13:37:57.099924093 +0100
@@ -113,6 +113,134 @@  along with GCC; see the file COPYING3.
  @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.  */
 
 /* Basic strip-useless-type-conversions / strip_nops.  */
Index: trunk/gcc/tree-ssa-forwprop.c
===================================================================
--- trunk.orig/gcc/tree-ssa-forwprop.c	2014-11-05 13:31:01.131942296 +0100
+++ trunk/gcc/tree-ssa-forwprop.c	2014-11-05 13:35:29.365930558 +0100
@@ -1253,49 +1253,6 @@  simplify_conversion_from_bitmask (gimple
 }
 
 
-/* If we have lhs = ~x (STMT), look and see if earlier we had x = ~y.
-   If so, we can change STMT into lhs = y which can later be copy
-   propagated.  Similarly for negation.
-
-   This could trivially be formulated as a forward propagation
-   to immediate uses.  However, we already had an implementation
-   from DOM which used backward propagation via the use-def links.
-
-   It turns out that backward propagation is actually faster as
-   there's less work to do for each NOT/NEG expression we find.
-   Backwards propagation needs to look at the statement in a single
-   backlink.  Forward propagation needs to look at potentially more
-   than one forward link.
-
-   Returns true when the statement was changed.  */
-
-static bool 
-simplify_not_neg_expr (gimple_stmt_iterator *gsi_p)
-{
-  gimple stmt = gsi_stmt (*gsi_p);
-  tree rhs = gimple_assign_rhs1 (stmt);
-  gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
-
-  /* See if the RHS_DEF_STMT has the same form as our statement.  */
-  if (is_gimple_assign (rhs_def_stmt)
-      && gimple_assign_rhs_code (rhs_def_stmt) == gimple_assign_rhs_code (stmt))
-    {
-      tree rhs_def_operand = gimple_assign_rhs1 (rhs_def_stmt);
-
-      /* Verify that RHS_DEF_OPERAND is a suitable SSA_NAME.  */
-      if (TREE_CODE (rhs_def_operand) == SSA_NAME
-	  && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs_def_operand))
-	{
-	  gimple_assign_set_rhs_from_tree (gsi_p, rhs_def_operand);
-	  stmt = gsi_stmt (*gsi_p);
-	  update_stmt (stmt);
-	  return true;
-	}
-    }
-
-  return false;
-}
-
 /* Helper function for simplify_gimple_switch.  Remove case labels that
    have values outside the range of the new type.  */
 
@@ -1714,126 +1671,6 @@  simplify_builtin_call (gimple_stmt_itera
   return false;
 }
 
-/* Checks if expression has type of one-bit precision, or is a known
-   truth-valued expression.  */
-static bool
-truth_valued_ssa_name (tree name)
-{
-  gimple def;
-  tree type = TREE_TYPE (name);
-
-  if (!INTEGRAL_TYPE_P (type))
-    return false;
-  /* Don't check here for BOOLEAN_TYPE as the precision isn't
-     necessarily one and so ~X is not equal to !X.  */
-  if (TYPE_PRECISION (type) == 1)
-    return true;
-  def = SSA_NAME_DEF_STMT (name);
-  if (is_gimple_assign (def))
-    return truth_value_p (gimple_assign_rhs_code (def));
-  return false;
-}
-
-/* Helper routine for simplify_bitwise_binary_1 function.
-   Return for the SSA name NAME the expression X if it mets condition
-   NAME = !X. Otherwise return NULL_TREE.
-   Detected patterns for NAME = !X are:
-     !X and X == 0 for X with integral type.
-     X ^ 1, X != 1,or ~X for X with integral type with precision of one.  */
-static tree
-lookup_logical_inverted_value (tree name)
-{
-  tree op1, op2;
-  enum tree_code code;
-  gimple def;
-
-  /* If name has none-intergal type, or isn't a SSA_NAME, then
-     return.  */
-  if (TREE_CODE (name) != SSA_NAME
-      || !INTEGRAL_TYPE_P (TREE_TYPE (name)))
-    return NULL_TREE;
-  def = SSA_NAME_DEF_STMT (name);
-  if (!is_gimple_assign (def))
-    return NULL_TREE;
-
-  code = gimple_assign_rhs_code (def);
-  op1 = gimple_assign_rhs1 (def);
-  op2 = NULL_TREE;
-
-  /* Get for EQ_EXPR or BIT_XOR_EXPR operation the second operand.
-     If CODE isn't an EQ_EXPR, BIT_XOR_EXPR, or BIT_NOT_EXPR, then return.  */
-  if (code == EQ_EXPR || code == NE_EXPR
-      || code == BIT_XOR_EXPR)
-    op2 = gimple_assign_rhs2 (def);
-
-  switch (code)
-    {
-    case BIT_NOT_EXPR:
-      if (truth_valued_ssa_name (name))
-	return op1;
-      break;
-    case EQ_EXPR:
-      /* Check if we have X == 0 and X has an integral type.  */
-      if (!INTEGRAL_TYPE_P (TREE_TYPE (op1)))
-	break;
-      if (integer_zerop (op2))
-	return op1;
-      break;
-    case NE_EXPR:
-      /* Check if we have X != 1 and X is a truth-valued.  */
-      if (!INTEGRAL_TYPE_P (TREE_TYPE (op1)))
-	break;
-      if (integer_onep (op2) && truth_valued_ssa_name (op1))
-	return op1;
-      break;
-    case BIT_XOR_EXPR:
-      /* Check if we have X ^ 1 and X is truth valued.  */
-      if (integer_onep (op2) && truth_valued_ssa_name (op1))
-	return op1;
-      break;
-    default:
-      break;
-    }
-
-  return NULL_TREE;
-}
-
-/* Optimize ARG1 CODE ARG2 to a constant for bitwise binary
-   operations CODE, if one operand has the logically inverted
-   value of the other.  */
-static tree
-simplify_bitwise_binary_1 (enum tree_code code, tree type,
-			   tree arg1, tree arg2)
-{
-  tree anot;
-
-  /* If CODE isn't a bitwise binary operation, return NULL_TREE.  */
-  if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR
-      && code != BIT_XOR_EXPR)
-    return NULL_TREE;
-
-  /* First check if operands ARG1 and ARG2 are equal.  If so
-     return NULL_TREE as this optimization is handled fold_stmt.  */
-  if (arg1 == arg2)
-    return NULL_TREE;
-  /* See if we have in arguments logical-not patterns.  */
-  if (((anot = lookup_logical_inverted_value (arg1)) == NULL_TREE
-       || anot != arg2)
-      && ((anot = lookup_logical_inverted_value (arg2)) == NULL_TREE
-	  || anot != arg1))
-    return NULL_TREE;
-
-  /* X & !X -> 0.  */
-  if (code == BIT_AND_EXPR)
-    return fold_convert (type, integer_zero_node);
-  /* X | !X -> 1 and X ^ !X -> 1, if X is truth-valued.  */
-  if (truth_valued_ssa_name (anot))
-    return fold_convert (type, integer_one_node);
-
-  /* ??? Otherwise result is (X != 0 ? X : 1).  not handled.  */
-  return NULL_TREE;
-}
-
 /* Given a ssa_name in NAME see if it was defined by an assignment and
    set CODE to be the code and ARG1 to the first operand on the rhs and ARG2
    to the second operand on the rhs. */
@@ -1879,353 +1716,6 @@  defcodefor_name (tree name, enum tree_co
   /* Ignore arg3 currently. */
 }
 
-/* Return true if a conversion of an operand from type FROM to type TO
-   should be applied after performing the operation instead.  */
-
-static bool
-hoist_conversion_for_bitop_p (tree to, tree from)
-{
-  /* That's a good idea if the conversion widens the operand, thus
-     after hoisting the conversion the operation will be narrower.  */
-  if (TYPE_PRECISION (from) < TYPE_PRECISION (to))
-    return true;
-
-  /* It's also a good idea if the conversion is to a non-integer mode.  */
-  if (GET_MODE_CLASS (TYPE_MODE (to)) != MODE_INT)
-    return true;
-
-  /* Or if the precision of TO is not the same as the precision
-     of its mode.  */
-  if (TYPE_PRECISION (to) != GET_MODE_PRECISION (TYPE_MODE (to)))
-    return true;
-
-  return false;
-}
-
-/* GSI points to a statement of the form
-
-   result = OP0 CODE OP1
-
-   Where OP0 and OP1 are single bit SSA_NAMEs and CODE is either
-   BIT_AND_EXPR or BIT_IOR_EXPR.
-
-   If OP0 is fed by a bitwise negation of another single bit SSA_NAME,
-   then we can simplify the two statements into a single LT_EXPR or LE_EXPR
-   when code is BIT_AND_EXPR and BIT_IOR_EXPR respectively.
-
-   If a simplification is made, return TRUE, else return FALSE.  */
-static bool
-simplify_bitwise_binary_boolean (gimple_stmt_iterator *gsi,
-				 enum tree_code code,
-				 tree op0, tree op1)
-{
-  gimple op0_def_stmt = SSA_NAME_DEF_STMT (op0);
-
-  if (!is_gimple_assign (op0_def_stmt)
-      || (gimple_assign_rhs_code (op0_def_stmt) != BIT_NOT_EXPR))
-    return false;
-
-  tree x = gimple_assign_rhs1 (op0_def_stmt);
-  if (TREE_CODE (x) == SSA_NAME
-      && INTEGRAL_TYPE_P (TREE_TYPE (x))
-      && TYPE_PRECISION (TREE_TYPE (x)) == 1
-      && TYPE_UNSIGNED (TREE_TYPE (x)) == TYPE_UNSIGNED (TREE_TYPE (op1)))
-    {
-      enum tree_code newcode;
-
-      gimple stmt = gsi_stmt (*gsi);
-      gimple_assign_set_rhs1 (stmt, x);
-      gimple_assign_set_rhs2 (stmt, op1);
-      if (code == BIT_AND_EXPR)
-	newcode = TYPE_UNSIGNED (TREE_TYPE (x)) ? LT_EXPR : GT_EXPR;
-      else
-	newcode = TYPE_UNSIGNED (TREE_TYPE (x)) ? LE_EXPR : GE_EXPR;
-      gimple_assign_set_rhs_code (stmt, newcode); 
-      update_stmt (stmt);
-      return true;
-    }
-  return false;
-
-}
-
-/* Simplify bitwise binary operations.
-   Return true if a transformation applied, otherwise return false.  */
-
-static bool
-simplify_bitwise_binary (gimple_stmt_iterator *gsi)
-{
-  gimple stmt = gsi_stmt (*gsi);
-  tree arg1 = gimple_assign_rhs1 (stmt);
-  tree arg2 = gimple_assign_rhs2 (stmt);
-  enum tree_code code = gimple_assign_rhs_code (stmt);
-  tree res;
-  tree def1_arg1, def1_arg2, def2_arg1, def2_arg2;
-  enum tree_code def1_code, def2_code;
-
-  defcodefor_name (arg1, &def1_code, &def1_arg1, &def1_arg2);
-  defcodefor_name (arg2, &def2_code, &def2_arg1, &def2_arg2);
-
-  /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
-     when profitable.  */
-  if (TREE_CODE (arg2) == INTEGER_CST
-      && CONVERT_EXPR_CODE_P (def1_code)
-      && hoist_conversion_for_bitop_p (TREE_TYPE (arg1), TREE_TYPE (def1_arg1))
-      && INTEGRAL_TYPE_P (TREE_TYPE (def1_arg1))
-      && int_fits_type_p (arg2, TREE_TYPE (def1_arg1)))
-    {
-      gimple newop;
-      tree tem = make_ssa_name (TREE_TYPE (def1_arg1), NULL);
-      newop =
-        gimple_build_assign_with_ops (code, tem, def1_arg1,
-				      fold_convert_loc (gimple_location (stmt),
-							TREE_TYPE (def1_arg1),
-							arg2));
-      gimple_set_location (newop, gimple_location (stmt));
-      gsi_insert_before (gsi, newop, GSI_SAME_STMT);
-      gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR,
-					tem, NULL_TREE, NULL_TREE);
-      update_stmt (gsi_stmt (*gsi));
-      return true;
-    }
-
-  /* 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.  */
-  if (CONVERT_EXPR_CODE_P (def1_code)
-      && CONVERT_EXPR_CODE_P (def2_code)
-      && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1))
-      && hoist_conversion_for_bitop_p (TREE_TYPE (arg1), TREE_TYPE (def1_arg1)))
-    {
-      gimple newop;
-      tree tem = make_ssa_name (TREE_TYPE (def1_arg1), NULL);
-      newop = gimple_build_assign_with_ops (code, tem, def1_arg1, def2_arg1);
-      gimple_set_location (newop, gimple_location (stmt));
-      gsi_insert_before (gsi, newop, GSI_SAME_STMT);
-      gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR,
-					tem, NULL_TREE, NULL_TREE);
-      update_stmt (gsi_stmt (*gsi));
-      return true;
-    }
-
-
-   /* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
-   if (def1_code == def2_code
-       && def1_code == BIT_AND_EXPR
-       && operand_equal_for_phi_arg_p (def1_arg2,
-				       def2_arg2))
-    {
-      tree b = def1_arg2;
-      tree a = def1_arg1;
-      tree c = def2_arg1;
-      tree inner = fold_build2 (code, TREE_TYPE (arg2), a, c);
-      /* If A OP0 C (this usually means C is the same as A) is 0
-	 then fold it down correctly. */
-      if (integer_zerop (inner))
-	{
-	  gimple_assign_set_rhs_from_tree (gsi, inner);
-	  update_stmt (stmt);
-	  return true;
-	}
-      /* If A OP0 C (this usually means C is the same as A) is a ssa_name
-	 then fold it down correctly. */
-      else if (TREE_CODE (inner) == SSA_NAME)
-	{
-      	  tree outer = fold_build2 (def1_code, TREE_TYPE (inner),
-				    inner, b);
-	  gimple_assign_set_rhs_from_tree (gsi, outer);
-	  update_stmt (stmt);
-	  return true;
-	}
-      else
-	{
-	  gimple newop;
-	  tree tem;
-	  tem = make_ssa_name (TREE_TYPE (arg2), NULL);
-	  newop = gimple_build_assign_with_ops (code, tem, a, c);
-	  gimple_set_location (newop, gimple_location (stmt));
-	  /* Make sure to re-process the new stmt as it's walking upwards.  */
-	  gsi_insert_before (gsi, newop, GSI_NEW_STMT);
-	  gimple_assign_set_rhs1 (stmt, tem);
-	  gimple_assign_set_rhs2 (stmt, b);
-	  gimple_assign_set_rhs_code (stmt, def1_code);
-	  update_stmt (stmt);
-	  return true;
-	}
-    }
-
-  /* (a | CST1) & CST2  ->  (a & CST2) | (CST1 & CST2).  */
-  if (code == BIT_AND_EXPR
-      && def1_code == BIT_IOR_EXPR
-      && CONSTANT_CLASS_P (arg2)
-      && CONSTANT_CLASS_P (def1_arg2))
-    {
-      tree cst = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg2),
-			      arg2, def1_arg2);
-      tree tem;
-      gimple newop;
-      if (integer_zerop (cst))
-	{
-	  gimple_assign_set_rhs1 (stmt, def1_arg1);
-	  update_stmt (stmt);
-	  return true;
-	}
-      tem = make_ssa_name (TREE_TYPE (arg2), NULL);
-      newop = gimple_build_assign_with_ops (BIT_AND_EXPR,
-					    tem, def1_arg1, arg2);
-      gimple_set_location (newop, gimple_location (stmt));
-      /* Make sure to re-process the new stmt as it's walking upwards.  */
-      gsi_insert_before (gsi, newop, GSI_NEW_STMT);
-      gimple_assign_set_rhs1 (stmt, tem);
-      gimple_assign_set_rhs2 (stmt, cst);
-      gimple_assign_set_rhs_code (stmt, BIT_IOR_EXPR);
-      update_stmt (stmt);
-      return true;
-    }
-
-  /* Combine successive equal operations with constants.  */
-  if ((code == BIT_AND_EXPR
-       || code == BIT_IOR_EXPR
-       || code == BIT_XOR_EXPR)
-      && def1_code == code 
-      && CONSTANT_CLASS_P (arg2)
-      && CONSTANT_CLASS_P (def1_arg2))
-    {
-      tree cst = fold_build2 (code, TREE_TYPE (arg2),
-			      arg2, def1_arg2);
-      gimple_assign_set_rhs1 (stmt, def1_arg1);
-      gimple_assign_set_rhs2 (stmt, cst);
-      update_stmt (stmt);
-      return true;
-    }
-
-  /* Try simple folding for X op !X, and X op X.  */
-  res = simplify_bitwise_binary_1 (code, TREE_TYPE (arg1), arg1, arg2);
-  if (res != NULL_TREE)
-    {
-      gimple_assign_set_rhs_from_tree (gsi, res);
-      update_stmt (gsi_stmt (*gsi));
-      return true;
-    }
-
-  if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
-    {
-      enum tree_code ocode = code == BIT_AND_EXPR ? BIT_IOR_EXPR : BIT_AND_EXPR;
-      if (def1_code == ocode)
-	{
-	  tree x = arg2;
-	  enum tree_code coden;
-	  tree a1, a2;
-	  /* ( X | Y) & X -> X */
-	  /* ( X & Y) | X -> X */
-	  if (x == def1_arg1
-	      || x == def1_arg2)
-	    {
-	      gimple_assign_set_rhs_from_tree (gsi, x);
-	      update_stmt (gsi_stmt (*gsi));
-	      return true;
-	    }
-
-	  defcodefor_name (def1_arg1, &coden, &a1, &a2);
-	  /* (~X | Y) & X -> X & Y */
-	  /* (~X & Y) | X -> X | Y */
-	  if (coden == BIT_NOT_EXPR && a1 == x)
-	    {
-	      gimple_assign_set_rhs_with_ops (gsi, code,
-					      x, def1_arg2);
-	      gcc_assert (gsi_stmt (*gsi) == stmt);
-	      update_stmt (stmt);
-	      return true;
-	    }
-	  defcodefor_name (def1_arg2, &coden, &a1, &a2);
-	  /* (Y | ~X) & X -> X & Y */
-	  /* (Y & ~X) | X -> X | Y */
-	  if (coden == BIT_NOT_EXPR && a1 == x)
-	    {
-	      gimple_assign_set_rhs_with_ops (gsi, code,
-					      x, def1_arg1);
-	      gcc_assert (gsi_stmt (*gsi) == stmt);
-	      update_stmt (stmt);
-	      return true;
-	    }
-	}
-      if (def2_code == ocode)
-	{
-	  enum tree_code coden;
-	  tree a1;
-	  tree x = arg1;
-	  /* X & ( X | Y) -> X */
-	  /* X | ( X & Y) -> X */
-	  if (x == def2_arg1
-	      || x == def2_arg2)
-	    {
-	      gimple_assign_set_rhs_from_tree (gsi, x);
-	      update_stmt (gsi_stmt (*gsi));
-	      return true;
-	    }
-	  defcodefor_name (def2_arg1, &coden, &a1, NULL);
-	  /* (~X | Y) & X -> X & Y */
-	  /* (~X & Y) | X -> X | Y */
-	  if (coden == BIT_NOT_EXPR && a1 == x)
-	    {
-	      gimple_assign_set_rhs_with_ops (gsi, code,
-					      x, def2_arg2);
-	      gcc_assert (gsi_stmt (*gsi) == stmt);
-	      update_stmt (stmt);
-	      return true;
-	    }
-	  defcodefor_name (def2_arg2, &coden, &a1, NULL);
-	  /* (Y | ~X) & X -> X & Y */
-	  /* (Y & ~X) | X -> X | Y */
-	  if (coden == BIT_NOT_EXPR && a1 == x)
-	    {
-	      gimple_assign_set_rhs_with_ops (gsi, code,
-					      x, def2_arg1);
-	      gcc_assert (gsi_stmt (*gsi) == stmt);
-	      update_stmt (stmt);
-	      return true;
-	    }
-	}
-
-      /* 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.  */
-      if (TREE_CODE (arg1) == SSA_NAME
-	  && TREE_CODE (arg2) == SSA_NAME
-	  && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-	  && TYPE_PRECISION (TREE_TYPE (arg1)) == 1
-	  && TYPE_PRECISION (TREE_TYPE (arg2)) == 1
-	  && (TYPE_UNSIGNED (TREE_TYPE (arg1))
-	      == TYPE_UNSIGNED (TREE_TYPE (arg2))))
-	{
-	  use_operand_p use_p;
-          gimple use_stmt;
-
-	  if (single_imm_use (gimple_assign_lhs (stmt), &use_p, &use_stmt))
-	    {
-	      if (gimple_code (use_stmt) == GIMPLE_COND
-		  && gimple_cond_lhs (use_stmt) == gimple_assign_lhs (stmt)
-		  && integer_zerop (gimple_cond_rhs (use_stmt))
-		  && gimple_cond_code (use_stmt) == NE_EXPR)
-		{
-	          if (simplify_bitwise_binary_boolean (gsi, code, arg1, arg2))
-		    return true;
-	          if (simplify_bitwise_binary_boolean (gsi, code, arg2, arg1))
-		    return true;
-		}
-	    }
-	}
-    }
-  return false;
-}
-
 
 /* Recognize rotation patterns.  Return true if a transformation
    applied, otherwise return false.
@@ -3760,12 +3250,8 @@  pass_forwprop::execute (function *fun)
 		tree rhs1 = gimple_assign_rhs1 (stmt);
 		enum tree_code code = gimple_assign_rhs_code (stmt);
 
-		if ((code == BIT_NOT_EXPR
-		     || code == NEGATE_EXPR)
-		    && TREE_CODE (rhs1) == SSA_NAME)
-		  changed = simplify_not_neg_expr (&gsi);
-		else if (code == COND_EXPR
-			 || code == VEC_COND_EXPR)
+		if (code == COND_EXPR
+		    || code == VEC_COND_EXPR)
 		  {
 		    /* In this case the entire COND_EXPR is in rhs1. */
 		    if (forward_propagate_into_cond (&gsi)
@@ -3788,10 +3274,6 @@  pass_forwprop::execute (function *fun)
 			  || code == BIT_XOR_EXPR)
 			 && simplify_rotate (&gsi))
 		  changed = true;
-		else if (code == BIT_AND_EXPR
-			 || code == BIT_IOR_EXPR
-			 || code == BIT_XOR_EXPR)
-		  changed = simplify_bitwise_binary (&gsi);
 		else if (code == MULT_EXPR)
 		  {
 		    changed = simplify_mult (&gsi);
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c
===================================================================
--- trunk.orig/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c	2014-11-05 13:30:43.209943080 +0100
+++ trunk/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c	2014-11-05 13:35:29.365930558 +0100
@@ -1,7 +1,7 @@ 
 /* Setting LOGICAL_OP_NON_SHORT_CIRCUIT to 0 leads to two conditional jumps
    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-options "-O2 -fdump-tree-forwprop1" } */
+/* { dg-options "-O2 -fdump-tree-forwprop1-details" } */
 
 extern char *frob (void);
 extern _Bool testit (void);
@@ -79,6 +79,6 @@  test_8 (int code)
     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" } } */
 
Index: trunk/gcc/genmatch.c
===================================================================
--- trunk.orig/gcc/genmatch.c	2014-11-05 13:38:00.799923931 +0100
+++ trunk/gcc/genmatch.c	2014-11-05 13:38:48.927921825 +0100
@@ -1126,7 +1126,7 @@  dt_node::append_op (operand *op, dt_node
 dt_node *
 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);
   return append_node (n);
 }
@@ -1232,9 +1232,6 @@  at_assert_elm:
 void
 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_node *p = decision_tree::insert_operand (root, s->match, indexes);
   p->append_simplify (s, pattern_no, indexes);