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] Return true when gimple_simplify valueizes


The stmt interface for gimple_simplify currently does not return
"changed" when valueization would change it (it does if canonicalization
does).  This causes "missed" optimizations compared to the fold based
code in fold_stmt.

Fixed as follows which runs into the issue that for variadic builtins
type_num_arguments doesn't yield the number of arguments.  So take
that from the ops array state instead.  Also special-case valueization
when replacing a call with its valueized variant so it works in-place.

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

Richard.

2015-07-24  Richard Biener  <rguenther@suse.de>

	* gimple-fold.c (replace_stmt_with_simplification): Special-case
	valueizing call operands.
	* gimple-match-head.c (maybe_push_res_to_seq): Take
	number of call arguments from ops array.
	(do_valueize): New function.
	(gimple_simplify): Return true if valueization changed
	any operand even if the result didn't simplify further.

Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c	(revision 226086)
--- gcc/gimple-fold.c	(working copy)
*************** replace_stmt_with_simplification (gimple
*** 3398,3403 ****
--- 3398,3416 ----
  	  return true;
  	}
      }
+   else if (rcode.is_fn_code ()
+ 	   && gimple_call_builtin_p (stmt, rcode))
+     {
+       unsigned i;
+       for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ 	{
+ 	  gcc_assert (ops[i] != NULL_TREE);
+ 	  gimple_call_set_arg (stmt, i, ops[i]);
+ 	}
+       if (i < 3)
+ 	gcc_assert (ops[i] == NULL_TREE);
+       return true;
+     }
    else if (!inplace)
      {
        if (gimple_has_lhs (stmt))
Index: gcc/gimple-match-head.c
===================================================================
*** gcc/gimple-match-head.c	(revision 226086)
--- gcc/gimple-match-head.c	(working copy)
*************** maybe_push_res_to_seq (code_helper rcode
*** 337,355 ****
        tree decl = builtin_decl_implicit (rcode);
        if (!decl)
  	return NULL_TREE;
-       unsigned nargs = type_num_arguments (TREE_TYPE (decl));
-       gcc_assert (nargs <= 3);
        /* Play safe and do not allow abnormals to be mentioned in
           newly created statements.  */
!       if ((TREE_CODE (ops[0]) == SSA_NAME
! 	   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0]))
! 	  || (nargs >= 2
! 	      && TREE_CODE (ops[1]) == SSA_NAME
! 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1]))
! 	  || (nargs == 3
! 	      && TREE_CODE (ops[2]) == SSA_NAME
! 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2])))
! 	return NULL_TREE;
        if (!res)
  	res = make_ssa_name (type);
        gimple new_stmt = gimple_build_call (decl, nargs, ops[0], ops[1], ops[2]);
--- 337,354 ----
        tree decl = builtin_decl_implicit (rcode);
        if (!decl)
  	return NULL_TREE;
        /* Play safe and do not allow abnormals to be mentioned in
           newly created statements.  */
!       unsigned nargs;
!       for (nargs = 0; nargs < 3; ++nargs)
! 	{
! 	  if (!ops[nargs])
! 	    break;
! 	  if (TREE_CODE (ops[nargs]) == SSA_NAME
! 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[nargs]))
! 	    return NULL_TREE;
! 	}
!       gcc_assert (nargs != 0);
        if (!res)
  	res = make_ssa_name (type);
        gimple new_stmt = gimple_build_call (decl, nargs, ops[0], ops[1], ops[2]);
*************** gimple_simplify (enum built_in_function
*** 562,567 ****
--- 561,583 ----
    return maybe_push_res_to_seq (rcode, type, ops, seq);
  }
  
+ /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
+    VALUEIZED to true if valueization changed OP.  */
+ 
+ static inline tree
+ do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
+ {
+   if (valueize && TREE_CODE (op) == SSA_NAME)
+     {
+       tree tem = valueize (op);
+       if (tem && tem != op)
+ 	{
+ 	  op = tem;
+ 	  valueized = true;
+ 	}
+     }
+   return op;
+ }
  
  /* The main STMT based simplification entry.  It is used by the fold_stmt
     and the fold_stmt_to_constant APIs.  */
*************** gimple_simplify (gimple stmt,
*** 586,616 ****
  		|| code == VIEW_CONVERT_EXPR)
  	      {
  		tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
! 		if (top_valueize && TREE_CODE (op0) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (op0);
! 		    if (tem)
! 		      op0 = tem;
! 		  }
  		*rcode = code;
  		ops[0] = op0;
! 		return gimple_resimplify1 (seq, rcode, type, ops, valueize);
  	      }
  	    else if (code == BIT_FIELD_REF)
  	      {
  		tree rhs1 = gimple_assign_rhs1 (stmt);
  		tree op0 = TREE_OPERAND (rhs1, 0);
! 		if (top_valueize && TREE_CODE (op0) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (op0);
! 		    if (tem)
! 		      op0 = tem;
! 		  }
  		*rcode = code;
  		ops[0] = op0;
  		ops[1] = TREE_OPERAND (rhs1, 1);
  		ops[2] = TREE_OPERAND (rhs1, 2);
! 		return gimple_resimplify3 (seq, rcode, type, ops, valueize);
  	      }
  	    else if (code == SSA_NAME
  		     && top_valueize)
--- 602,626 ----
  		|| code == VIEW_CONVERT_EXPR)
  	      {
  		tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
! 		bool valueized = false;
! 		op0 = do_valueize (op0, top_valueize, valueized);
  		*rcode = code;
  		ops[0] = op0;
! 		return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
! 			|| valueized);
  	      }
  	    else if (code == BIT_FIELD_REF)
  	      {
  		tree rhs1 = gimple_assign_rhs1 (stmt);
  		tree op0 = TREE_OPERAND (rhs1, 0);
! 		bool valueized = false;
! 		op0 = do_valueize (op0, top_valueize, valueized);
  		*rcode = code;
  		ops[0] = op0;
  		ops[1] = TREE_OPERAND (rhs1, 1);
  		ops[2] = TREE_OPERAND (rhs1, 2);
! 		return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
! 			|| valueized);
  	      }
  	    else if (code == SSA_NAME
  		     && top_valueize)
*************** gimple_simplify (gimple stmt,
*** 627,691 ****
  	  case GIMPLE_UNARY_RHS:
  	    {
  	      tree rhs1 = gimple_assign_rhs1 (stmt);
! 	      if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
! 		{
! 		  tree tem = top_valueize (rhs1);
! 		  if (tem)
! 		    rhs1 = tem;
! 		}
  	      *rcode = code;
  	      ops[0] = rhs1;
! 	      return gimple_resimplify1 (seq, rcode, type, ops, valueize);
  	    }
  	  case GIMPLE_BINARY_RHS:
  	    {
  	      tree rhs1 = gimple_assign_rhs1 (stmt);
- 	      if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
- 		{
- 		  tree tem = top_valueize (rhs1);
- 		  if (tem)
- 		    rhs1 = tem;
- 		}
  	      tree rhs2 = gimple_assign_rhs2 (stmt);
! 	      if (top_valueize && TREE_CODE (rhs2) == SSA_NAME)
! 		{
! 		  tree tem = top_valueize (rhs2);
! 		  if (tem)
! 		    rhs2 = tem;
! 		}
  	      *rcode = code;
  	      ops[0] = rhs1;
  	      ops[1] = rhs2;
! 	      return gimple_resimplify2 (seq, rcode, type, ops, valueize);
  	    }
  	  case GIMPLE_TERNARY_RHS:
  	    {
  	      tree rhs1 = gimple_assign_rhs1 (stmt);
- 	      if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
- 		{
- 		  tree tem = top_valueize (rhs1);
- 		  if (tem)
- 		    rhs1 = tem;
- 		}
  	      tree rhs2 = gimple_assign_rhs2 (stmt);
- 	      if (top_valueize && TREE_CODE (rhs2) == SSA_NAME)
- 		{
- 		  tree tem = top_valueize (rhs2);
- 		  if (tem)
- 		    rhs2 = tem;
- 		}
  	      tree rhs3 = gimple_assign_rhs3 (stmt);
! 	      if (top_valueize && TREE_CODE (rhs3) == SSA_NAME)
! 		{
! 		  tree tem = top_valueize (rhs3);
! 		  if (tem)
! 		    rhs3 = tem;
! 		}
  	      *rcode = code;
  	      ops[0] = rhs1;
  	      ops[1] = rhs2;
  	      ops[2] = rhs3;
! 	      return gimple_resimplify3 (seq, rcode, type, ops, valueize);
  	    }
  	  default:
  	    gcc_unreachable ();
--- 637,677 ----
  	  case GIMPLE_UNARY_RHS:
  	    {
  	      tree rhs1 = gimple_assign_rhs1 (stmt);
! 	      bool valueized = false;
! 	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
  	      *rcode = code;
  	      ops[0] = rhs1;
! 	      return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
! 		      || valueized);
  	    }
  	  case GIMPLE_BINARY_RHS:
  	    {
  	      tree rhs1 = gimple_assign_rhs1 (stmt);
  	      tree rhs2 = gimple_assign_rhs2 (stmt);
! 	      bool valueized = false;
! 	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
! 	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
  	      *rcode = code;
  	      ops[0] = rhs1;
  	      ops[1] = rhs2;
! 	      return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
! 		      || valueized);
  	    }
  	  case GIMPLE_TERNARY_RHS:
  	    {
  	      tree rhs1 = gimple_assign_rhs1 (stmt);
  	      tree rhs2 = gimple_assign_rhs2 (stmt);
  	      tree rhs3 = gimple_assign_rhs3 (stmt);
! 	      bool valueized = false;
! 	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
! 	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
! 	      rhs3 = do_valueize (rhs3, top_valueize, valueized);
  	      *rcode = code;
  	      ops[0] = rhs1;
  	      ops[1] = rhs2;
  	      ops[2] = rhs3;
! 	      return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
! 		      || valueized);
  	    }
  	  default:
  	    gcc_unreachable ();
*************** gimple_simplify (gimple stmt,
*** 695,790 ****
  
      case GIMPLE_CALL:
        /* ???  This way we can't simplify calls with side-effects.  */
!       if (gimple_call_lhs (stmt) != NULL_TREE)
  	{
  	  tree fn = gimple_call_fn (stmt);
  	  /* ???  Internal function support missing.  */
  	  if (!fn)
  	    return false;
! 	  if (top_valueize && TREE_CODE (fn) == SSA_NAME)
! 	    {
! 	      tree tem = top_valueize (fn);
! 	      if (tem)
! 		fn = tem;
! 	    }
! 	  if (!fn
! 	      || TREE_CODE (fn) != ADDR_EXPR
! 	      || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL
! 	      || DECL_BUILT_IN_CLASS (TREE_OPERAND (fn, 0)) != BUILT_IN_NORMAL
! 	      || !builtin_decl_implicit (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)))
! 	      || !gimple_builtin_call_types_compatible_p (stmt,
! 							  TREE_OPERAND (fn, 0)))
  	    return false;
  
  	  tree decl = TREE_OPERAND (fn, 0);
  	  tree type = TREE_TYPE (gimple_call_lhs (stmt));
  	  switch (gimple_call_num_args (stmt))
  	    {
  	    case 1:
! 	      {
! 		tree arg1 = gimple_call_arg (stmt, 0);
! 		if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (arg1);
! 		    if (tem)
! 		      arg1 = tem;
! 		  }
! 		*rcode = DECL_FUNCTION_CODE (decl);
! 		ops[0] = arg1;
! 		return gimple_resimplify1 (seq, rcode, type, ops, valueize);
! 	      }
  	    case 2:
! 	      {
! 		tree arg1 = gimple_call_arg (stmt, 0);
! 		if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (arg1);
! 		    if (tem)
! 		      arg1 = tem;
! 		  }
! 		tree arg2 = gimple_call_arg (stmt, 1);
! 		if (top_valueize && TREE_CODE (arg2) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (arg2);
! 		    if (tem)
! 		      arg2 = tem;
! 		  }
! 		*rcode = DECL_FUNCTION_CODE (decl);
! 		ops[0] = arg1;
! 		ops[1] = arg2;
! 		return gimple_resimplify2 (seq, rcode, type, ops, valueize);
! 	      }
  	    case 3:
! 	      {
! 		tree arg1 = gimple_call_arg (stmt, 0);
! 		if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (arg1);
! 		    if (tem)
! 		      arg1 = tem;
! 		  }
! 		tree arg2 = gimple_call_arg (stmt, 1);
! 		if (top_valueize && TREE_CODE (arg2) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (arg2);
! 		    if (tem)
! 		      arg2 = tem;
! 		  }
! 		tree arg3 = gimple_call_arg (stmt, 2);
! 		if (top_valueize && TREE_CODE (arg3) == SSA_NAME)
! 		  {
! 		    tree tem = top_valueize (arg3);
! 		    if (tem)
! 		      arg3 = tem;
! 		  }
! 		*rcode = DECL_FUNCTION_CODE (decl);
! 		ops[0] = arg1;
! 		ops[1] = arg2;
! 		ops[2] = arg3;
! 		return gimple_resimplify3 (seq, rcode, type, ops, valueize);
! 	      }
  	    default:
! 	      return false;
  	    }
  	}
        break;
--- 681,726 ----
  
      case GIMPLE_CALL:
        /* ???  This way we can't simplify calls with side-effects.  */
!       if (gimple_call_lhs (stmt) != NULL_TREE
! 	  && gimple_call_num_args (stmt) >= 1
! 	  && gimple_call_num_args (stmt) <= 3)
  	{
  	  tree fn = gimple_call_fn (stmt);
  	  /* ???  Internal function support missing.  */
  	  if (!fn)
  	    return false;
! 	  bool valueized = false;
! 	  fn = do_valueize (fn, top_valueize, valueized);
! 	  if (TREE_CODE (fn) != ADDR_EXPR
! 	      || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
  	    return false;
  
  	  tree decl = TREE_OPERAND (fn, 0);
+ 	  if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
+ 	      || !builtin_decl_implicit (DECL_FUNCTION_CODE (decl))
+ 	      || !gimple_builtin_call_types_compatible_p (stmt, decl))
+ 	    return false;
+ 
  	  tree type = TREE_TYPE (gimple_call_lhs (stmt));
+ 	  *rcode = DECL_FUNCTION_CODE (decl);
+ 	  for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
+ 	    {
+ 	      tree arg = gimple_call_arg (stmt, i);
+ 	      ops[i] = do_valueize (arg, top_valueize, valueized);
+ 	    }
  	  switch (gimple_call_num_args (stmt))
  	    {
  	    case 1:
! 	      return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
! 		      || valueized);
  	    case 2:
! 	      return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
! 		      || valueized);
  	    case 3:
! 	      return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
! 		      || valueized);
  	    default:
! 	     gcc_unreachable ();
  	    }
  	}
        break;
*************** gimple_simplify (gimple stmt,
*** 792,814 ****
      case GIMPLE_COND:
        {
  	tree lhs = gimple_cond_lhs (stmt);
- 	if (top_valueize && TREE_CODE (lhs) == SSA_NAME)
- 	  {
- 	    tree tem = top_valueize (lhs);
- 	    if (tem)
- 	      lhs = tem;
- 	  }
  	tree rhs = gimple_cond_rhs (stmt);
! 	if (top_valueize && TREE_CODE (rhs) == SSA_NAME)
! 	  {
! 	    tree tem = top_valueize (rhs);
! 	    if (tem)
! 	      rhs = tem;
! 	  }
  	*rcode = gimple_cond_code (stmt);
  	ops[0] = lhs;
  	ops[1] = rhs;
!         return gimple_resimplify2 (seq, rcode, boolean_type_node, ops, valueize);
        }
  
      default:
--- 728,743 ----
      case GIMPLE_COND:
        {
  	tree lhs = gimple_cond_lhs (stmt);
  	tree rhs = gimple_cond_rhs (stmt);
! 	bool valueized = false;
! 	lhs = do_valueize (lhs, top_valueize, valueized);
! 	rhs = do_valueize (rhs, top_valueize, valueized);
  	*rcode = gimple_cond_code (stmt);
  	ops[0] = lhs;
  	ops[1] = rhs;
!         return (gimple_resimplify2 (seq, rcode,
! 				    boolean_type_node, ops, valueize)
! 		|| valueized);
        }
  
      default:


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