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]

[PATCH] Fix tree parts of PR18041


This patch makes us apply operand conversions of bitwise binary
operations to the operation result instead, which in turn allows
us to combine those conversions which helps bitfield related
operations.  For

struct B {
  unsigned bit0 : 1;
  unsigned bit1 : 1;
};

void
foo (struct B *b)
{
  b->bit0 = b->bit0 | b->bit1;
}

we with this patch generate

  D.2686_2 = b_1(D)->bit0;
  D.2688_4 = b_1(D)->bit1;
  D.2693_10 = D.2688_4 ^ D.2686_2;
  b_1(D)->bit0 = D.2693_10;

instead of

  D.2686_2 = b_1(D)->bit0;
  D.2687_3 = (unsigned char) D.2686_2;
  D.2688_4 = b_1(D)->bit1;
  D.2689_5 = (unsigned char) D.2688_4;
  D.2690_6 = D.2687_3 | D.2689_5;
  D.2691_7 = (<unnamed-unsigned:1>) D.2690_6;
  b_1(D)->bit0 = D.2691_7;

which is shorter and easier to analyze.  The generated code is
the same though, and still contains too many masking operations.

Bitfield lowering will expose more conversion combining
opportunities similar to the above.

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

Richard.

2011-05-10  Richard Guenther  <rguenther@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	(revision 173612)
--- gcc/tree-ssa-forwprop.c	(working copy)
*************** 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,1691 ----
    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))
! 	  && types_compatible_p (TREE_TYPE (gimple_assign_rhs1 (def_stmt1)),
! 				 TREE_TYPE (gimple_assign_rhs1 (def_stmt2))))
! 	{
! 	  gimple newop;
! 	  tree tem = create_tmp_reg (TREE_TYPE (gimple_assign_rhs1 (def_stmt1)),
! 				     NULL);
! 	  newop = gimple_build_assign_with_ops (code, tem,
! 						gimple_assign_rhs1 (def_stmt1),
! 						gimple_assign_rhs1 (def_stmt2));
! 	  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 ****
--- 2159,2165 ----
  	    {
  	      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))))
  		{
--- 2167,2176 ----
  		  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
--- 2188,2194 ----
  		  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;
--- 2220,2233 ----
  		  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);
--- 2240,2267 ----
  		    && 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
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c	(revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c	(revision 0)
***************
*** 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 char\\\)" "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */


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