This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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





> 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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]