On Tue, 10 May 2011, Richard Guenther wrote:

> And I now get
> 
> FAIL: gcc.target/i386/pr45903.c scan-assembler-not shr[qdl]
> 
> because the optimization Jakub put in place relies on operations
> carried out in smaller modes.
> 
> That's of course a conflict of interest.  I'm going to sit on this
> patch for a little longer.

The following seems to work for all cases I am interested in.  It
avoids undoing narrowing optimizations if they were not to bitfield
types.

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

Richard.

2011-05-11  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/18041
        * tree-ssa-forwprop.c (simplify_bitwise_and): Rename to ...
        (simplify_bitwise_binary): ... this.  Handle operand conversions
        by applying them to the result instead.
        (tree_ssa_forward_propagate_single_use_vars): Adjust.  CSE tree code.

        * gcc.dg/tree-ssa/forwprop-13.c: New testcase.

Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c.orig        2011-05-10 16:18:16.000000000 +0200
--- gcc/tree-ssa-forwprop.c     2011-05-10 17:50:43.000000000 +0200
*************** simplify_builtin_call (gimple_stmt_itera
*** 1612,1655 ****
    return false;
  }
  
! /* Run bitwise and assignments throug the folder.  If the first argument is an
!    ssa name that is itself a result of a typecast of an ADDR_EXPR to an
!    integer, feed the ADDR_EXPR to the folder rather than the ssa name.
! */
  
! static void
! simplify_bitwise_and (gimple_stmt_iterator *gsi, gimple stmt)
  {
!   tree res;
    tree arg1 = gimple_assign_rhs1 (stmt);
    tree arg2 = gimple_assign_rhs2 (stmt);
  
!   if (TREE_CODE (arg2) != INTEGER_CST)
!     return;
! 
!   if (TREE_CODE (arg1) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (arg1))
      {
        gimple def = SSA_NAME_DEF_STMT (arg1);
  
!       if (gimple_assign_cast_p (def)
!         && INTEGRAL_TYPE_P (gimple_expr_type (def)))
!       {
!         tree op = gimple_assign_rhs1 (def);
  
!         if (TREE_CODE (op) == ADDR_EXPR)
!           arg1 = op;
        }
      }
  
!   res = fold_binary_loc (gimple_location (stmt),
!                    BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)),
!                    arg1, arg2);
!   if (res && is_gimple_min_invariant (res))
      {
!       gimple_assign_set_rhs_from_tree (gsi, res);
!       update_stmt (stmt);
      }
!   return;
  }
  
  
--- 1612,1701 ----
    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;
  
!   /* If the first argument is an SSA name that is itself a result of a
!      typecast of an ADDR_EXPR to an integer, feed the ADDR_EXPR to the
!      folder rather than the ssa name.  */
!   if (code == BIT_AND_EXPR
!       && TREE_CODE (arg2) == INTEGER_CST
!       && TREE_CODE (arg1) == SSA_NAME)
      {
        gimple def = SSA_NAME_DEF_STMT (arg1);
+       tree op = arg1;
  
!       /* ???  This looks bogus - the conversion could be truncating.  */
!       if (is_gimple_assign (def)
!         && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))
!         && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
!       {
!         tree opp = gimple_assign_rhs1 (def);
!         if (TREE_CODE (opp) == ADDR_EXPR)
!           op = opp;
!       }
  
!       res = fold_binary_loc (gimple_location (stmt),
!                            BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)),
!                            op, arg2);
!       if (res && is_gimple_min_invariant (res))
!       {
!         gimple_assign_set_rhs_from_tree (gsi, res);
!         update_stmt (stmt);
!         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 (TREE_CODE (arg1) == SSA_NAME
!       && TREE_CODE (arg2) == SSA_NAME)
      {
!       gimple def_stmt1 = SSA_NAME_DEF_STMT (arg1);
!       gimple def_stmt2 = SSA_NAME_DEF_STMT (arg2);
!       if (is_gimple_assign (def_stmt1)
!         && is_gimple_assign (def_stmt2)
!         && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt1))
!         && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2)))
!       {
!         tree darg1 = gimple_assign_rhs1 (def_stmt1);
!         tree darg2 = gimple_assign_rhs1 (def_stmt2);
!         /* Make sure that the conversion widens the operands or that it
!            changes the operation to a bitfield precision.  */
!         if (types_compatible_p (TREE_TYPE (darg1), TREE_TYPE (darg2))
!             && ((TYPE_PRECISION (TREE_TYPE (darg1))
!                  < TYPE_PRECISION (TREE_TYPE (arg1)))
!                 || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1)))
!                     != MODE_INT)
!                 || (TYPE_PRECISION (TREE_TYPE (arg1))
!                     != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg1))))))
!           {
!             gimple newop;
!             tree tem = create_tmp_reg (TREE_TYPE (darg1),
!                                        NULL);
!             newop = gimple_build_assign_with_ops (code, tem, darg1, darg2);
!             tem = make_ssa_name (tem, newop);
!             gimple_assign_set_lhs (newop, tem);
!             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;
!           }
!       }
      }
! 
!   return false;
  }
  
  
*************** tree_ssa_forward_propagate_single_use_va
*** 2123,2128 ****
--- 2169,2175 ----
            {
              tree lhs = gimple_assign_lhs (stmt);
              tree rhs = gimple_assign_rhs1 (stmt);
+             enum tree_code code = gimple_assign_rhs_code (stmt);
  
              if (TREE_CODE (lhs) != SSA_NAME)
                {
*************** tree_ssa_forward_propagate_single_use_va
*** 2130,2139 ****
                  continue;
                }
  
!             if (gimple_assign_rhs_code (stmt) == ADDR_EXPR
                  /* Handle pointer conversions on invariant addresses
                     as well, as this is valid gimple.  */
!                 || (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
                      && TREE_CODE (rhs) == ADDR_EXPR
                      && POINTER_TYPE_P (TREE_TYPE (lhs))))
                {
--- 2177,2186 ----
                  continue;
                }
  
!             if (code == ADDR_EXPR
                  /* Handle pointer conversions on invariant addresses
                     as well, as this is valid gimple.  */
!                 || (CONVERT_EXPR_CODE_P (code)
                      && TREE_CODE (rhs) == ADDR_EXPR
                      && POINTER_TYPE_P (TREE_TYPE (lhs))))
                {
*************** tree_ssa_forward_propagate_single_use_va
*** 2151,2157 ****
                  else
                    gsi_next (&gsi);
                }
!             else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
                       && can_propagate_from (stmt))
                {
                  if (TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST
--- 2198,2204 ----
                  else
                    gsi_next (&gsi);
                }
!             else if (code == POINTER_PLUS_EXPR
                       && can_propagate_from (stmt))
                {
                  if (TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST
*************** tree_ssa_forward_propagate_single_use_va
*** 2183,2196 ****
                  else
                    gsi_next (&gsi);
                }
!             else if ((gimple_assign_rhs_code (stmt) == BIT_NOT_EXPR
!                       || gimple_assign_rhs_code (stmt) == NEGATE_EXPR)
                       && TREE_CODE (rhs) == SSA_NAME)
                {
                  simplify_not_neg_expr (&gsi);
                  gsi_next (&gsi);
                }
!             else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
                  {
                    /* In this case the entire COND_EXPR is in rhs1. */
                  int did_something;
--- 2230,2243 ----
                  else
                    gsi_next (&gsi);
                }
!             else if ((code == BIT_NOT_EXPR
!                       || code == NEGATE_EXPR)
                       && TREE_CODE (rhs) == SSA_NAME)
                {
                  simplify_not_neg_expr (&gsi);
                  gsi_next (&gsi);
                }
!             else if (code == COND_EXPR)
                  {
                    /* In this case the entire COND_EXPR is in rhs1. */
                  int did_something;
*************** tree_ssa_forward_propagate_single_use_va
*** 2203,2229 ****
                    && did_something, stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
                  gsi_next (&gsi);
                  }
!             else if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
!                                       == tcc_comparison)
                {
                  if (forward_propagate_comparison (stmt))
                    cfg_changed = true;
                  gsi_next (&gsi);
                }
!             else if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR)
                {
!                 simplify_bitwise_and (&gsi, stmt);
!                 gsi_next (&gsi);
                }
!             else if (gimple_assign_rhs_code (stmt) == PLUS_EXPR
!                      || gimple_assign_rhs_code (stmt) == MINUS_EXPR)
                {
                  cfg_changed |= associate_plusminus (stmt);
                  gsi_next (&gsi);
                }
!             else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
!                      || gimple_assign_rhs_code (stmt) == FLOAT_EXPR
!                      || gimple_assign_rhs_code (stmt) == FIX_TRUNC_EXPR)
                {
                  if (!combine_conversions (&gsi))
                    gsi_next (&gsi);
--- 2250,2277 ----
                    && did_something, stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
                  gsi_next (&gsi);
                  }
!             else if (TREE_CODE_CLASS (code) == tcc_comparison)
                {
                  if (forward_propagate_comparison (stmt))
                    cfg_changed = true;
                  gsi_next (&gsi);
                }
!             else if (code == BIT_AND_EXPR
!                      || code == BIT_IOR_EXPR
!                      || code == BIT_XOR_EXPR)
                {
!                 if (!simplify_bitwise_binary (&gsi))
!                   gsi_next (&gsi);
                }
!             else if (code == PLUS_EXPR
!                      || code == MINUS_EXPR)
                {
                  cfg_changed |= associate_plusminus (stmt);
                  gsi_next (&gsi);
                }
!             else if (CONVERT_EXPR_CODE_P (code)
!                      || code == FLOAT_EXPR
!                      || code == FIX_TRUNC_EXPR)
                {
                  if (!combine_conversions (&gsi))
                    gsi_next (&gsi);
Index: gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c
===================================================================
*** /dev/null   1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c 2011-05-10 17:42:33.000000000 
+0200
***************
*** 0 ****
--- 1,16 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-optimized" } */
+ 
+ struct B {
+     unsigned bit0 : 1;
+     unsigned bit1 : 1;
+ };
+ 
+ void
+ foo (struct B *b)
+ {
+   b->bit0 = b->bit0 | b->bit1;
+ }
+ 
+ /* { dg-final { scan-tree-dump-not "\\\(unsigned" "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */

Reply via email to