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][25/25] Remove GENERIC stmt combining from SCCVN


On Wed, 30 Sep 2015, Richard Biener wrote:

> 
> This is the last patch in the series and it finally ditches the
> stmt combining code from SCCVN which uses GENERIC.  I've been sitting
> on this for a while because of the "bad" interface that new mprts_hook
> is but I couldn't think of a better way than completely refactoring
> stmt folding into more C++ (and I'm not even sure how that end result
> would look like).  So rather than pondering on this forever the following
> patch goes forward.
> 
> Net result is that there will be hopefully no regressions (I know
> about a few corner cases I found with plastering the code with asserts
> but I do not consider them important) but progression both with regarding
> to compile-time / memory-use and optimization (because the new code
> is strictly more powerful, not relying on the has_constants heuristic).
> 
> This is also the last major piece that was sitting on the
> match-and-simplify branch.
> 
> Bootstrapped on x86_64-unknown-linux-gnu, re-testing in progress.

This is the variant I committed.

Richard.

2015-10-01  Richard Biener  <rguenther@suse.de>

	* gimple-match.h (mprts_hook): Declare.
	* gimple-match.head.c (mprts_hook): Define.
	(maybe_push_res_to_seq): Use new hook.
	* gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise.
	* tree-ssa-sccvn.h (vn_ssa_aux::expr): Change to a gimple_seq.
	(vn_ssa_aux::has_constants): Remove.
	* tree-ssa-sccvn.c: Include gimple-match.h.
	(VN_INFO_GET): Assert we don't re-use SSA names.
	(vn_get_expr_for): Remove.
	(expr_has_constants): Likewise.
	(stmt_has_constants): Likewise.
	(simplify_binary_expression): Likewise.
	(simplify_unary_expression): Likewise.
	(vn_lookup_simplify_result): New hook.
	(visit_copy): Adjust.
	(visit_reference_op_call): Likewise.
	(visit_phi): Likewise.
	(visit_use): Likewise.
	(process_scc): Likewise.
	(init_scc_vn): Likewise.
	(visit_reference_op_load): Likewise.  Use match-and-simplify and
	a gimple seq for inserted expressions.
	(try_to_simplify): Remove GENERIC stmt combining code.
	(sccvn_dom_walker::before_dom_children): Use match-and-simplify.
	* tree-ssa-pre.c (eliminate_insert): Adjust.
	(eliminate_dom_walker::before_dom_children): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-7.c: Adjust.
	* gcc.dg/tree-ssa/ssa-fre-8.c: Likewise.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2015-09-30 15:00:30.636706575 +0200
--- gcc/tree-ssa-sccvn.c	2015-09-30 15:32:03.543978540 +0200
*************** along with GCC; see the file COPYING3.
*** 58,63 ****
--- 58,64 ----
  #include "domwalk.h"
  #include "cgraph.h"
  #include "gimple-iterator.h"
+ #include "gimple-match.h"
  
  /* This algorithm is based on the SCC algorithm presented by Keith
     Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
*************** VN_INFO_GET (tree name)
*** 401,406 ****
--- 402,409 ----
  {
    vn_ssa_aux_t newinfo;
  
+   gcc_assert (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ()
+ 	      || vn_ssa_aux_table[SSA_NAME_VERSION (name)] == NULL);
    newinfo = XOBNEW (&vn_ssa_aux_obstack, struct vn_ssa_aux);
    memset (newinfo, 0, sizeof (struct vn_ssa_aux));
    if (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ())
*************** VN_INFO_GET (tree name)
*** 410,501 ****
  }
  
  
- /* Get the representative expression for the SSA_NAME NAME.  Returns
-    the representative SSA_NAME if there is no expression associated with it.  */
- 
- tree
- vn_get_expr_for (tree name)
- {
-   vn_ssa_aux_t vn = VN_INFO (name);
-   gimple *def_stmt;
-   tree expr = NULL_TREE;
-   enum tree_code code;
- 
-   if (vn->valnum == VN_TOP)
-     return name;
- 
-   /* If the value-number is a constant it is the representative
-      expression.  */
-   if (TREE_CODE (vn->valnum) != SSA_NAME)
-     return vn->valnum;
- 
-   /* Get to the information of the value of this SSA_NAME.  */
-   vn = VN_INFO (vn->valnum);
- 
-   /* If the value-number is a constant it is the representative
-      expression.  */
-   if (TREE_CODE (vn->valnum) != SSA_NAME)
-     return vn->valnum;
- 
-   /* Else if we have an expression, return it.  */
-   if (vn->expr != NULL_TREE)
-     return vn->expr;
- 
-   /* Otherwise use the defining statement to build the expression.  */
-   def_stmt = SSA_NAME_DEF_STMT (vn->valnum);
- 
-   /* If the value number is not an assignment use it directly.  */
-   if (!is_gimple_assign (def_stmt))
-     return vn->valnum;
- 
-   /* Note that we can valueize here because we clear the cached
-      simplified expressions after each optimistic iteration.  */
-   code = gimple_assign_rhs_code (def_stmt);
-   switch (TREE_CODE_CLASS (code))
-     {
-     case tcc_reference:
-       if ((code == REALPART_EXPR
- 	   || code == IMAGPART_EXPR
- 	   || code == VIEW_CONVERT_EXPR)
- 	  && TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (def_stmt),
- 				      0)) == SSA_NAME)
- 	expr = fold_build1 (code,
- 			    gimple_expr_type (def_stmt),
- 			    vn_valueize (TREE_OPERAND
- 					   (gimple_assign_rhs1 (def_stmt), 0)));
-       break;
- 
-     case tcc_unary:
-       expr = fold_build1 (code,
- 			  gimple_expr_type (def_stmt),
- 			  vn_valueize (gimple_assign_rhs1 (def_stmt)));
-       break;
- 
-     case tcc_binary:
-       expr = fold_build2 (code,
- 			  gimple_expr_type (def_stmt),
- 			  vn_valueize (gimple_assign_rhs1 (def_stmt)),
- 			  vn_valueize (gimple_assign_rhs2 (def_stmt)));
-       break;
- 
-     case tcc_exceptional:
-       if (code == CONSTRUCTOR
- 	  && TREE_CODE
- 	       (TREE_TYPE (gimple_assign_rhs1 (def_stmt))) == VECTOR_TYPE)
- 	expr = gimple_assign_rhs1 (def_stmt);
-       break;
- 
-     default:;
-     }
-   if (expr == NULL_TREE)
-     return vn->valnum;
- 
-   /* Cache the expression.  */
-   vn->expr = expr;
- 
-   return expr;
- }
- 
  /* Return the vn_kind the expression computed by the stmt should be
     associated with.  */
  
--- 413,418 ----
*************** vn_nary_op_lookup_stmt (gimple *stmt, vn
*** 2685,2690 ****
--- 2602,2619 ----
    return vn_nary_op_lookup_1 (vno1, vnresult);
  }
  
+ /* Hook for maybe_push_res_to_seq, lookup the expression in the VN tables.  */
+ 
+ static tree
+ vn_lookup_simplify_result (code_helper rcode, tree type, tree *ops)
+ {
+   if (!rcode.is_tree_code ())
+     return NULL_TREE;
+   vn_nary_op_t vnresult = NULL;
+   return vn_nary_op_lookup_pieces (TREE_CODE_LENGTH ((tree_code) rcode),
+ 				   (tree_code) rcode, type, ops, &vnresult);
+ }
+ 
  /* Allocate a vn_nary_op_t with LENGTH operands on STACK.  */
  
  static vn_nary_op_t
*************** defs_to_varying (gimple *stmt)
*** 3047,3066 ****
    return changed;
  }
  
- static bool expr_has_constants (tree expr);
- 
  /* Visit a copy between LHS and RHS, return true if the value number
     changed.  */
  
  static bool
  visit_copy (tree lhs, tree rhs)
  {
!   /* The copy may have a more interesting constant filled expression
!      (we don't, since we know our RHS is just an SSA name).  */
!   VN_INFO (lhs)->has_constants = VN_INFO (rhs)->has_constants;
!   VN_INFO (lhs)->expr = VN_INFO (rhs)->expr;
! 
!   /* And finally valueize.  */
    rhs = SSA_VAL (rhs);
  
    return set_ssa_val_to (lhs, rhs);
--- 2976,2988 ----
    return changed;
  }
  
  /* Visit a copy between LHS and RHS, return true if the value number
     changed.  */
  
  static bool
  visit_copy (tree lhs, tree rhs)
  {
!   /* Valueize.  */
    rhs = SSA_VAL (rhs);
  
    return set_ssa_val_to (lhs, rhs);
*************** visit_reference_op_call (tree lhs, gcall
*** 3111,3122 ****
  	vnresult->result = lhs;
  
        if (vnresult->result && lhs)
! 	{
! 	  changed |= set_ssa_val_to (lhs, vnresult->result);
! 
! 	  if (VN_INFO (vnresult->result)->has_constants)
! 	    VN_INFO (lhs)->has_constants = true;
! 	}
      }
    else
      {
--- 3033,3039 ----
  	vnresult->result = lhs;
  
        if (vnresult->result && lhs)
! 	changed |= set_ssa_val_to (lhs, vnresult->result);
      }
    else
      {
*************** visit_reference_op_load (tree lhs, tree
*** 3172,3204 ****
  	 of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
  	 So first simplify and lookup this expression to see if it
  	 is already available.  */
!       tree val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
!       if ((CONVERT_EXPR_P (val)
! 	   || TREE_CODE (val) == VIEW_CONVERT_EXPR)
! 	  && TREE_CODE (TREE_OPERAND (val, 0)) == SSA_NAME)
!         {
! 	  tree tem = vn_get_expr_for (TREE_OPERAND (val, 0));
! 	  if ((CONVERT_EXPR_P (tem)
! 	       || TREE_CODE (tem) == VIEW_CONVERT_EXPR)
! 	      && (tem = fold_unary_ignore_overflow (TREE_CODE (val),
! 						    TREE_TYPE (val), tem)))
! 	    val = tem;
! 	}
!       result = val;
!       if (!is_gimple_min_invariant (val)
! 	  && TREE_CODE (val) != SSA_NAME)
! 	result = vn_nary_op_lookup (val, NULL);
!       /* If the expression is not yet available, value-number lhs to
! 	 a new SSA_NAME we create.  */
!       if (!result)
!         {
! 	  result = make_temp_ssa_name (TREE_TYPE (lhs), gimple_build_nop (),
! 				       "vntemp");
  	  /* Initialize value-number information properly.  */
  	  VN_INFO_GET (result)->valnum = result;
  	  VN_INFO (result)->value_id = get_next_value_id ();
! 	  VN_INFO (result)->expr = val;
! 	  VN_INFO (result)->has_constants = expr_has_constants (val);
  	  VN_INFO (result)->needs_insertion = true;
  	  /* As all "inserted" statements are singleton SCCs, insert
  	     to the valid table.  This is strictly needed to
--- 3089,3126 ----
  	 of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
  	 So first simplify and lookup this expression to see if it
  	 is already available.  */
!       gimple_seq stmts = NULL;
!       mprts_hook = vn_lookup_simplify_result;
!       tree val = gimple_simplify (VIEW_CONVERT_EXPR, TREE_TYPE (op),
! 				  result, &stmts, vn_valueize);
!       mprts_hook = NULL;
!       if (!val)
! 	{
! 	  val = vn_nary_op_lookup_pieces (1, VIEW_CONVERT_EXPR,
! 					  TREE_TYPE (op), &result, NULL);
! 	  if (!val)
! 	    {
! 	      val = make_ssa_name (TREE_TYPE (op));
! 	      gimple *new_stmt = gimple_build_assign (val, VIEW_CONVERT_EXPR,
! 						      build1 (VIEW_CONVERT_EXPR,
! 							      TREE_TYPE (op),
! 							      result));
! 	      gimple_seq_add_stmt_without_update (&stmts, new_stmt);
! 	    }
! 	}
!       if (gimple_seq_empty_p (stmts))
! 	/* The expression is already available.  */
! 	result = val;
!       else
! 	{
! 	  gcc_assert (gimple_seq_singleton_p (stmts));
! 	  /* The expression is not yet available, value-number lhs to
! 	     the new SSA_NAME we created.  */
! 	  result = val;
  	  /* Initialize value-number information properly.  */
  	  VN_INFO_GET (result)->valnum = result;
  	  VN_INFO (result)->value_id = get_next_value_id ();
! 	  VN_INFO (result)->expr = stmts;
  	  VN_INFO (result)->needs_insertion = true;
  	  /* As all "inserted" statements are singleton SCCs, insert
  	     to the valid table.  This is strictly needed to
*************** visit_reference_op_load (tree lhs, tree
*** 3210,3241 ****
  	  if (current_info == optimistic_info)
  	    {
  	      current_info = valid_info;
! 	      vn_nary_op_insert (val, result);
  	      current_info = optimistic_info;
  	    }
  	  else
! 	    vn_nary_op_insert (val, result);
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
  	      fprintf (dump_file, "Inserting name ");
  	      print_generic_expr (dump_file, result, 0);
  	      fprintf (dump_file, " for expression ");
! 	      print_generic_expr (dump_file, val, 0);
  	      fprintf (dump_file, "\n");
  	    }
  	}
      }
  
    if (result)
!     {
!       changed = set_ssa_val_to (lhs, result);
!       if (TREE_CODE (result) == SSA_NAME
! 	  && VN_INFO (result)->has_constants)
! 	{
! 	  VN_INFO (lhs)->expr = VN_INFO (result)->expr;
! 	  VN_INFO (lhs)->has_constants = true;
! 	}
!     }
    else
      {
        changed = set_ssa_val_to (lhs, lhs);
--- 3132,3156 ----
  	  if (current_info == optimistic_info)
  	    {
  	      current_info = valid_info;
! 	      vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result);
  	      current_info = optimistic_info;
  	    }
  	  else
! 	    vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result);
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
  	      fprintf (dump_file, "Inserting name ");
  	      print_generic_expr (dump_file, result, 0);
  	      fprintf (dump_file, " for expression ");
! 	      print_gimple_expr (dump_file, gimple_seq_first_stmt (stmts),
! 				 0, TDF_SLIM);
  	      fprintf (dump_file, "\n");
  	    }
  	}
      }
  
    if (result)
!     changed = set_ssa_val_to (lhs, result);
    else
      {
        changed = set_ssa_val_to (lhs, lhs);
*************** visit_phi (gimple *phi)
*** 3401,3608 ****
    else
      {
        vn_phi_insert (phi, PHI_RESULT (phi));
-       VN_INFO (PHI_RESULT (phi))->has_constants = false;
-       VN_INFO (PHI_RESULT (phi))->expr = PHI_RESULT (phi);
        changed = set_ssa_val_to (PHI_RESULT (phi), PHI_RESULT (phi));
      }
  
    return changed;
  }
  
- /* Return true if EXPR contains constants.  */
- 
- static bool
- expr_has_constants (tree expr)
- {
-   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
-     {
-     case tcc_unary:
-       return is_gimple_min_invariant (TREE_OPERAND (expr, 0));
- 
-     case tcc_binary:
-       return is_gimple_min_invariant (TREE_OPERAND (expr, 0))
- 	|| is_gimple_min_invariant (TREE_OPERAND (expr, 1));
-       /* Constants inside reference ops are rarely interesting, but
- 	 it can take a lot of looking to find them.  */
-     case tcc_reference:
-     case tcc_declaration:
-       return false;
-     default:
-       return is_gimple_min_invariant (expr);
-     }
-   return false;
- }
- 
- /* Return true if STMT contains constants.  */
- 
- static bool
- stmt_has_constants (gimple *stmt)
- {
-   tree tem;
- 
-   if (gimple_code (stmt) != GIMPLE_ASSIGN)
-     return false;
- 
-   switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
-     {
-     case GIMPLE_TERNARY_RHS:
-       tem = gimple_assign_rhs3 (stmt);
-       if (TREE_CODE (tem) == SSA_NAME)
- 	tem = SSA_VAL (tem);
-       if (is_gimple_min_invariant (tem))
- 	return true;
-       /* Fallthru.  */
- 
-     case GIMPLE_BINARY_RHS:
-       tem = gimple_assign_rhs2 (stmt);
-       if (TREE_CODE (tem) == SSA_NAME)
- 	tem = SSA_VAL (tem);
-       if (is_gimple_min_invariant (tem))
- 	return true;
-       /* Fallthru.  */
- 
-     case GIMPLE_SINGLE_RHS:
-       /* Constants inside reference ops are rarely interesting, but
- 	 it can take a lot of looking to find them.  */
-     case GIMPLE_UNARY_RHS:
-       tem = gimple_assign_rhs1 (stmt);
-       if (TREE_CODE (tem) == SSA_NAME)
- 	tem = SSA_VAL (tem);
-       return is_gimple_min_invariant (tem);
- 
-     default:
-       gcc_unreachable ();
-     }
-   return false;
- }
- 
- /* Simplify the binary expression RHS, and return the result if
-    simplified. */
- 
- static tree
- simplify_binary_expression (gimple *stmt)
- {
-   tree result = NULL_TREE;
-   tree op0 = gimple_assign_rhs1 (stmt);
-   tree op1 = gimple_assign_rhs2 (stmt);
-   enum tree_code code = gimple_assign_rhs_code (stmt);
- 
-   /* This will not catch every single case we could combine, but will
-      catch those with constants.  The goal here is to simultaneously
-      combine constants between expressions, but avoid infinite
-      expansion of expressions during simplification.  */
-   op0 = vn_valueize (op0);
-   if (TREE_CODE (op0) == SSA_NAME
-       && (VN_INFO (op0)->has_constants
- 	  || TREE_CODE_CLASS (code) == tcc_comparison
- 	  || code == COMPLEX_EXPR))
-     op0 = vn_get_expr_for (op0);
- 
-   op1 = vn_valueize (op1);
-   if (TREE_CODE (op1) == SSA_NAME
-       && (VN_INFO (op1)->has_constants
- 	  || code == COMPLEX_EXPR))
-     op1 = vn_get_expr_for (op1);
- 
-   /* Pointer plus constant can be represented as invariant address.
-      Do so to allow further propatation, see also tree forwprop.  */
-   if (code == POINTER_PLUS_EXPR
-       && tree_fits_uhwi_p (op1)
-       && TREE_CODE (op0) == ADDR_EXPR
-       && is_gimple_min_invariant (op0))
-     return build_invariant_address (TREE_TYPE (op0),
- 				    TREE_OPERAND (op0, 0),
- 				    tree_to_uhwi (op1));
- 
-   /* Avoid folding if nothing changed.  */
-   if (op0 == gimple_assign_rhs1 (stmt)
-       && op1 == gimple_assign_rhs2 (stmt))
-     return NULL_TREE;
- 
-   fold_defer_overflow_warnings ();
- 
-   result = fold_binary (code, gimple_expr_type (stmt), op0, op1);
-   if (result)
-     STRIP_USELESS_TYPE_CONVERSION (result);
- 
-   fold_undefer_overflow_warnings (result && valid_gimple_rhs_p (result),
- 				  stmt, 0);
- 
-   /* Make sure result is not a complex expression consisting
-      of operators of operators (IE (a + b) + (a + c))
-      Otherwise, we will end up with unbounded expressions if
-      fold does anything at all.  */
-   if (result && valid_gimple_rhs_p (result))
-     return result;
- 
-   return NULL_TREE;
- }
- 
- /* Simplify the unary expression RHS, and return the result if
-    simplified. */
- 
- static tree
- simplify_unary_expression (gassign *stmt)
- {
-   tree result = NULL_TREE;
-   tree orig_op0, op0 = gimple_assign_rhs1 (stmt);
-   enum tree_code code = gimple_assign_rhs_code (stmt);
- 
-   /* We handle some tcc_reference codes here that are all
-      GIMPLE_ASSIGN_SINGLE codes.  */
-   if (code == REALPART_EXPR
-       || code == IMAGPART_EXPR
-       || code == VIEW_CONVERT_EXPR
-       || code == BIT_FIELD_REF)
-     op0 = TREE_OPERAND (op0, 0);
- 
-   orig_op0 = op0;
-   op0 = vn_valueize (op0);
-   if (TREE_CODE (op0) == SSA_NAME)
-     {
-       if (VN_INFO (op0)->has_constants)
- 	op0 = vn_get_expr_for (op0);
-       else if (CONVERT_EXPR_CODE_P (code)
- 	       || code == REALPART_EXPR
- 	       || code == IMAGPART_EXPR
- 	       || code == VIEW_CONVERT_EXPR
- 	       || code == BIT_FIELD_REF)
- 	{
- 	  /* We want to do tree-combining on conversion-like expressions.
- 	     Make sure we feed only SSA_NAMEs or constants to fold though.  */
- 	  tree tem = vn_get_expr_for (op0);
- 	  if (UNARY_CLASS_P (tem)
- 	      || BINARY_CLASS_P (tem)
- 	      || TREE_CODE (tem) == VIEW_CONVERT_EXPR
- 	      || TREE_CODE (tem) == SSA_NAME
- 	      || TREE_CODE (tem) == CONSTRUCTOR
- 	      || is_gimple_min_invariant (tem))
- 	    op0 = tem;
- 	}
-     }
- 
-   /* Avoid folding if nothing changed, but remember the expression.  */
-   if (op0 == orig_op0)
-     return NULL_TREE;
- 
-   if (code == BIT_FIELD_REF)
-     {
-       tree rhs = gimple_assign_rhs1 (stmt);
-       result = fold_ternary (BIT_FIELD_REF, TREE_TYPE (rhs),
- 			     op0, TREE_OPERAND (rhs, 1), TREE_OPERAND (rhs, 2));
-     }
-   else
-     result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0);
-   if (result)
-     {
-       STRIP_USELESS_TYPE_CONVERSION (result);
-       if (valid_gimple_rhs_p (result))
-         return result;
-     }
- 
-   return NULL_TREE;
- }
- 
  /* Try to simplify RHS using equivalences and constant folding.  */
  
  static tree
--- 3316,3327 ----
*************** try_to_simplify (gassign *stmt)
*** 3617,3651 ****
      return NULL_TREE;
  
    /* First try constant folding based on our current lattice.  */
    tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize, vn_valueize);
    if (tem
        && (TREE_CODE (tem) == SSA_NAME
  	  || is_gimple_min_invariant (tem)))
      return tem;
  
-   /* If that didn't work try combining multiple statements.  */
-   switch (TREE_CODE_CLASS (code))
-     {
-     case tcc_reference:
-       /* Fallthrough for some unary codes that can operate on registers.  */
-       if (!(code == REALPART_EXPR
- 	    || code == IMAGPART_EXPR
- 	    || code == VIEW_CONVERT_EXPR
- 	    || code == BIT_FIELD_REF))
- 	break;
-       /* We could do a little more with unary ops, if they expand
- 	 into binary ops, but it's debatable whether it is worth it. */
-     case tcc_unary:
-       return simplify_unary_expression (stmt);
- 
-     case tcc_comparison:
-     case tcc_binary:
-       return simplify_binary_expression (stmt);
- 
-     default:
-       break;
-     }
- 
    return NULL_TREE;
  }
  
--- 3336,3349 ----
      return NULL_TREE;
  
    /* First try constant folding based on our current lattice.  */
+   mprts_hook = vn_lookup_simplify_result;
    tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize, vn_valueize);
+   mprts_hook = NULL;
    if (tem
        && (TREE_CODE (tem) == SSA_NAME
  	  || is_gimple_min_invariant (tem)))
      return tem;
  
    return NULL_TREE;
  }
  
*************** visit_use (tree use)
*** 3703,3713 ****
  		  print_gimple_expr (dump_file, stmt, 0, 0);
  		  fprintf (dump_file, " simplified to ");
  		  print_generic_expr (dump_file, simplified, 0);
! 		  if (TREE_CODE (lhs) == SSA_NAME)
! 		    fprintf (dump_file, " has constants %d\n",
! 			     expr_has_constants (simplified));
! 		  else
! 		    fprintf (dump_file, "\n");
  		}
  	    }
  	  /* Setting value numbers to constants will occasionally
--- 3401,3407 ----
  		  print_gimple_expr (dump_file, stmt, 0, 0);
  		  fprintf (dump_file, " simplified to ");
  		  print_generic_expr (dump_file, simplified, 0);
! 		  fprintf (dump_file, "\n");
  		}
  	    }
  	  /* Setting value numbers to constants will occasionally
*************** visit_use (tree use)
*** 3718,3725 ****
  	      && is_gimple_min_invariant (simplified)
  	      && TREE_CODE (lhs) == SSA_NAME)
  	    {
- 	      VN_INFO (lhs)->expr = simplified;
- 	      VN_INFO (lhs)->has_constants = true;
  	      changed = set_ssa_val_to (lhs, simplified);
  	      goto done;
  	    }
--- 3412,3417 ----
*************** visit_use (tree use)
*** 3730,3758 ****
  	      changed = visit_copy (lhs, simplified);
  	      goto done;
  	    }
- 	  else if (simplified)
- 	    {
- 	      if (TREE_CODE (lhs) == SSA_NAME)
- 		{
- 		  VN_INFO (lhs)->has_constants = expr_has_constants (simplified);
- 		  /* We have to unshare the expression or else
- 		     valuizing may change the IL stream.  */
- 		  VN_INFO (lhs)->expr = unshare_expr (simplified);
- 		}
- 	    }
- 	  else if (stmt_has_constants (stmt)
- 		   && TREE_CODE (lhs) == SSA_NAME)
- 	    VN_INFO (lhs)->has_constants = true;
- 	  else if (TREE_CODE (lhs) == SSA_NAME)
- 	    {
- 	      /* We reset expr and constantness here because we may
- 		 have been value numbering optimistically, and
- 		 iterating. They may become non-constant in this case,
- 		 even if they were optimistically constant. */
- 
- 	      VN_INFO (lhs)->has_constants = false;
- 	      VN_INFO (lhs)->expr = NULL_TREE;
- 	    }
  
  	  if ((TREE_CODE (lhs) == SSA_NAME
  	       /* We can substitute SSA_NAMEs that are live over
--- 3422,3427 ----
*************** visit_use (tree use)
*** 3777,3783 ****
  		  || (simplified
  		      && is_gimple_min_invariant (simplified)))
  		{
- 		  VN_INFO (lhs)->has_constants = true;
  		  if (simplified)
  		    changed = set_ssa_val_to (lhs, simplified);
  		  else
--- 3446,3451 ----
*************** visit_use (tree use)
*** 3840,3850 ****
  		      print_gimple_expr (dump_file, stmt, 0, 0);
  		      fprintf (dump_file, " simplified to ");
  		      print_generic_expr (dump_file, simplified, 0);
! 		      if (TREE_CODE (lhs) == SSA_NAME)
! 			fprintf (dump_file, " has constants %d\n",
! 				 expr_has_constants (simplified));
! 		      else
! 			fprintf (dump_file, "\n");
  		    }
  		}
  	      /* Setting value numbers to constants will occasionally
--- 3508,3514 ----
  		      print_gimple_expr (dump_file, stmt, 0, 0);
  		      fprintf (dump_file, " simplified to ");
  		      print_generic_expr (dump_file, simplified, 0);
! 		      fprintf (dump_file, "\n");
  		    }
  		}
  	      /* Setting value numbers to constants will occasionally
*************** visit_use (tree use)
*** 3854,3861 ****
  	      if (simplified
  		  && is_gimple_min_invariant (simplified))
  		{
- 		  VN_INFO (lhs)->expr = simplified;
- 		  VN_INFO (lhs)->has_constants = true;
  		  changed = set_ssa_val_to (lhs, simplified);
  		  if (gimple_vdef (stmt))
  		    changed |= set_ssa_val_to (gimple_vdef (stmt),
--- 3518,3523 ----
*************** visit_use (tree use)
*** 3873,3890 ****
  		}
  	      else
  		{
- 		  if (stmt_has_constants (stmt))
- 		    VN_INFO (lhs)->has_constants = true;
- 		  else
- 		    {
- 		      /* We reset expr and constantness here because we may
- 			 have been value numbering optimistically, and
- 			 iterating.  They may become non-constant in this case,
- 			 even if they were optimistically constant.  */
- 		      VN_INFO (lhs)->has_constants = false;
- 		      VN_INFO (lhs)->expr = NULL_TREE;
- 		    }
- 
  		  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
  		    {
  		      changed = defs_to_varying (stmt);
--- 3535,3540 ----
*************** process_scc (vec<tree> scc)
*** 4083,4089 ****
        optimistic_info->phis_pool->release ();
        optimistic_info->references_pool->release ();
        FOR_EACH_VEC_ELT (scc, i, var)
! 	VN_INFO (var)->expr = NULL_TREE;
        FOR_EACH_VEC_ELT (scc, i, var)
  	changed |= visit_use (var);
      }
--- 3733,3740 ----
        optimistic_info->phis_pool->release ();
        optimistic_info->references_pool->release ();
        FOR_EACH_VEC_ELT (scc, i, var)
! 	gcc_assert (!VN_INFO (var)->needs_insertion
! 		    && VN_INFO (var)->expr == NULL);
        FOR_EACH_VEC_ELT (scc, i, var)
  	changed |= visit_use (var);
      }
*************** init_scc_vn (void)
*** 4338,4344 ****
  	continue;
  
        VN_INFO_GET (name)->valnum = VN_TOP;
!       VN_INFO (name)->expr = NULL_TREE;
        VN_INFO (name)->value_id = 0;
  
        if (!SSA_NAME_IS_DEFAULT_DEF (name))
--- 3989,3996 ----
  	continue;
  
        VN_INFO_GET (name)->valnum = VN_TOP;
!       VN_INFO (name)->needs_insertion = false;
!       VN_INFO (name)->expr = NULL;
        VN_INFO (name)->value_id = 0;
  
        if (!SSA_NAME_IS_DEFAULT_DEF (name))
*************** sccvn_dom_walker::before_dom_children (b
*** 4692,4714 ****
      {
      case GIMPLE_COND:
        {
! 	tree lhs = gimple_cond_lhs (stmt);
! 	tree rhs = gimple_cond_rhs (stmt);
! 	/* Work hard in computing the condition and take into account
! 	   the valueization of the defining stmt.  */
! 	if (TREE_CODE (lhs) == SSA_NAME)
! 	  lhs = vn_get_expr_for (lhs);
! 	if (TREE_CODE (rhs) == SSA_NAME)
! 	  rhs = vn_get_expr_for (rhs);
! 	val = fold_binary (gimple_cond_code (stmt),
! 			   boolean_type_node, lhs, rhs);
  	/* If that didn't simplify to a constant see if we have recorded
  	   temporary expressions from taken edges.  */
  	if (!val || TREE_CODE (val) != INTEGER_CST)
  	  {
  	    tree ops[2];
! 	    ops[0] = gimple_cond_lhs (stmt);
! 	    ops[1] = gimple_cond_rhs (stmt);
  	    val = vn_nary_op_lookup_pieces (2, gimple_cond_code (stmt),
  					    boolean_type_node, ops, NULL);
  	  }
--- 4344,4361 ----
      {
      case GIMPLE_COND:
        {
! 	tree lhs = vn_valueize (gimple_cond_lhs (stmt));
! 	tree rhs = vn_valueize (gimple_cond_rhs (stmt));
! 	val = gimple_simplify (gimple_cond_code (stmt),
! 			       boolean_type_node, lhs, rhs,
! 			       NULL, vn_valueize);
  	/* If that didn't simplify to a constant see if we have recorded
  	   temporary expressions from taken edges.  */
  	if (!val || TREE_CODE (val) != INTEGER_CST)
  	  {
  	    tree ops[2];
! 	    ops[0] = lhs;
! 	    ops[1] = rhs;
  	    val = vn_nary_op_lookup_pieces (2, gimple_cond_code (stmt),
  					    boolean_type_node, ops, NULL);
  	  }
Index: gcc/gimple-match-head.c
===================================================================
*** gcc/gimple-match-head.c.orig	2015-09-30 15:00:30.636706575 +0200
--- gcc/gimple-match-head.c	2015-09-30 15:22:48.939766818 +0200
*************** maybe_build_generic_op (enum tree_code c
*** 293,298 ****
--- 293,300 ----
      }
  }
  
+ tree (*mprts_hook) (code_helper, tree, tree *);
+ 
  /* Push the exploded expression described by RCODE, TYPE and OPS
     as a statement to SEQ if necessary and return a gimple value
     denoting the value of the expression.  If RES is not NULL
*************** maybe_push_res_to_seq (code_helper rcode
*** 310,315 ****
--- 312,323 ----
  	      || ((tree_code) rcode) == ADDR_EXPR)
  	  && is_gimple_val (ops[0]))
  	return ops[0];
+       if (mprts_hook)
+ 	{
+ 	  tree tem = mprts_hook (rcode, type, ops);
+ 	  if (tem)
+ 	    return tem;
+ 	}
        if (!seq)
  	return NULL_TREE;
        /* Play safe and do not allow abnormals to be mentioned in
Index: gcc/gimple-match.h
===================================================================
*** gcc/gimple-match.h.orig	2015-09-30 15:00:30.636706575 +0200
--- gcc/gimple-match.h	2015-09-30 15:22:48.939766818 +0200
*************** private:
*** 40,45 ****
--- 40,47 ----
    int rep;
  };
  
+ extern tree (*mprts_hook) (code_helper, tree, tree *);
+ 
  bool gimple_simplify (gimple *, code_helper *, tree *, gimple_seq *,
  		      tree (*)(tree), tree (*)(tree));
  tree maybe_push_res_to_seq (code_helper, tree, tree *,
Index: gcc/tree-ssa-sccvn.h
===================================================================
*** gcc/tree-ssa-sccvn.h.orig	2015-09-30 15:00:30.636706575 +0200
--- gcc/tree-ssa-sccvn.h	2015-09-30 15:22:48.940766830 +0200
*************** typedef struct vn_ssa_aux
*** 165,172 ****
  {
    /* Value number. This may be an SSA name or a constant.  */
    tree valnum;
!   /* Representative expression, if not a direct constant. */
!   tree expr;
  
    /* Unique identifier that all expressions with the same value have. */
    unsigned int value_id;
--- 165,172 ----
  {
    /* Value number. This may be an SSA name or a constant.  */
    tree valnum;
!   /* Statements to insert if needs_insertion is true.  */
!   gimple_seq expr;
  
    /* Unique identifier that all expressions with the same value have. */
    unsigned int value_id;
*************** typedef struct vn_ssa_aux
*** 177,184 ****
    unsigned visited : 1;
    unsigned on_sccstack : 1;
  
-   /* Whether the representative expression contains constants.  */
-   unsigned has_constants : 1;
    /* Whether the SSA_NAME has been value numbered already.  This is
       only saying whether visit_use has been called on it at least
       once.  It cannot be used to avoid visitation for SSA_NAME's
--- 177,182 ----
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c.orig	2015-09-30 15:00:30.636706575 +0200
--- gcc/tree-ssa-pre.c	2015-09-30 15:22:48.941766841 +0200
*************** eliminate_push_avail (tree op)
*** 3953,3973 ****
  static tree
  eliminate_insert (gimple_stmt_iterator *gsi, tree val)
  {
!   tree expr = vn_get_expr_for (val);
!   if (!CONVERT_EXPR_P (expr)
!       && TREE_CODE (expr) != VIEW_CONVERT_EXPR)
      return NULL_TREE;
  
!   tree op = TREE_OPERAND (expr, 0);
    tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (op) : op;
    if (!leader)
      return NULL_TREE;
  
!   tree res = make_temp_ssa_name (TREE_TYPE (val), NULL, "pretmp");
!   gassign *tem = gimple_build_assign (res,
! 				      fold_build1 (TREE_CODE (expr),
! 						   TREE_TYPE (expr), leader));
!   gsi_insert_before (gsi, tem, GSI_SAME_STMT);
    VN_INFO_GET (res)->valnum = val;
  
    if (TREE_CODE (leader) == SSA_NAME)
--- 3953,3975 ----
  static tree
  eliminate_insert (gimple_stmt_iterator *gsi, tree val)
  {
!   gimple *stmt = gimple_seq_first_stmt (VN_INFO (val)->expr);
!   if (!is_gimple_assign (stmt)
!       || (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
! 	  && gimple_assign_rhs_code (stmt) != VIEW_CONVERT_EXPR))
      return NULL_TREE;
  
!   tree op = gimple_assign_rhs1 (stmt);
!   if (gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR)
!     op = TREE_OPERAND (op, 0);
    tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (op) : op;
    if (!leader)
      return NULL_TREE;
  
!   gimple_seq stmts = NULL;
!   tree res = gimple_build (&stmts, gimple_assign_rhs_code (stmt),
! 			   TREE_TYPE (val), leader);
!   gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
    VN_INFO_GET (res)->valnum = val;
  
    if (TREE_CODE (leader) == SSA_NAME)
*************** eliminate_insert (gimple_stmt_iterator *
*** 3977,3983 ****
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
        fprintf (dump_file, "Inserted ");
!       print_gimple_stmt (dump_file, tem, 0, 0);
      }
  
    return res;
--- 3979,3985 ----
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
        fprintf (dump_file, "Inserted ");
!       print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (res), 0, 0);
      }
  
    return res;
*************** eliminate_dom_walker::before_dom_childre
*** 4101,4107 ****
  	      if (val != VN_TOP
  		  && TREE_CODE (val) == SSA_NAME
  		  && VN_INFO (val)->needs_insertion
! 		  && VN_INFO (val)->expr != NULL_TREE
  		  && (sprime = eliminate_insert (&gsi, val)) != NULL_TREE)
  		eliminate_push_avail (sprime);
  	    }
--- 4103,4109 ----
  	      if (val != VN_TOP
  		  && TREE_CODE (val) == SSA_NAME
  		  && VN_INFO (val)->needs_insertion
! 		  && VN_INFO (val)->expr != NULL
  		  && (sprime = eliminate_insert (&gsi, val)) != NULL_TREE)
  		eliminate_push_avail (sprime);
  	    }
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c.orig	2015-09-30 15:00:30.636706575 +0200
--- gcc/gimple-fold.c	2015-09-30 15:22:48.942766852 +0200
*************** gimple_fold_stmt_to_constant_1 (gimple *
*** 4883,4904 ****
       edges if there are intermediate VARYING defs.  For this reason
       do not follow SSA edges here even though SCCVN can technically
       just deal fine with that.  */
!   if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize)
!       && rcode.is_tree_code ()
!       && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
! 	  || ((tree_code) rcode) == ADDR_EXPR)
!       && is_gimple_val (ops[0]))
      {
!       tree res = ops[0];
!       if (dump_file && dump_flags & TDF_DETAILS)
  	{
! 	  fprintf (dump_file, "Match-and-simplified ");
! 	  print_gimple_expr (dump_file, stmt, 0, TDF_SLIM);
! 	  fprintf (dump_file, " to ");
! 	  print_generic_expr (dump_file, res, 0);
! 	  fprintf (dump_file, "\n");
  	}
-       return res;
      }
  
    location_t loc = gimple_location (stmt);
--- 4883,4910 ----
       edges if there are intermediate VARYING defs.  For this reason
       do not follow SSA edges here even though SCCVN can technically
       just deal fine with that.  */
!   if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize))
      {
!       tree res = NULL_TREE;
!       if (rcode.is_tree_code ()
! 	  && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
! 	      || ((tree_code) rcode) == ADDR_EXPR)
! 	  && is_gimple_val (ops[0]))
! 	res = ops[0];
!       else if (mprts_hook)
! 	res = mprts_hook (rcode, gimple_expr_type (stmt), ops);
!       if (res)
  	{
! 	  if (dump_file && dump_flags & TDF_DETAILS)
! 	    {
! 	      fprintf (dump_file, "Match-and-simplified ");
! 	      print_gimple_expr (dump_file, stmt, 0, TDF_SLIM);
! 	      fprintf (dump_file, " to ");
! 	      print_generic_expr (dump_file, res, 0);
! 	      fprintf (dump_file, "\n");
! 	    }
! 	  return res;
  	}
      }
  
    location_t loc = gimple_location (stmt);
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c.orig	2015-09-30 15:35:37.715366242 +0200
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c	2015-09-30 15:35:48.739489118 +0200
*************** intflt foo(intflt j)
*** 29,36 ****
    return a.u.k;
  }
  
! /* { dg-final { scan-tree-dump-times "Inserted pretmp" 1 "fre1" } } */
! /* { dg-final { scan-tree-dump-times "Replaced a.u.f with pretmp" 3 "fre1" } } */
  /* { dg-final { scan-tree-dump-times "Replaced a.u.k with j" 1 "fre1" } } */
  /* { dg-final { scan-tree-dump "= VIEW_CONVERT_EXPR<float>\\\(j_" "fre1" } } */
  /* { dg-final { scan-tree-dump "return j" "optimized" } } */
--- 29,36 ----
    return a.u.k;
  }
  
! /* { dg-final { scan-tree-dump-times "Inserted" 1 "fre1" } } */
! /* { dg-final { scan-tree-dump-times "Replaced a.u.f with" 3 "fre1" } } */
  /* { dg-final { scan-tree-dump-times "Replaced a.u.k with j" 1 "fre1" } } */
  /* { dg-final { scan-tree-dump "= VIEW_CONVERT_EXPR<float>\\\(j_" "fre1" } } */
  /* { dg-final { scan-tree-dump "return j" "optimized" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c.orig	2015-09-30 15:35:37.724366342 +0200
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c	2015-09-30 15:35:48.740489129 +0200
*************** intflt foo(int i, int b)
*** 28,32 ****
      }
  }
  
! /* { dg-final { scan-tree-dump-times "Replaced u.f with pretmp" 2 "fre1" } } */
! /* { dg-final { scan-tree-dump-times "Inserted pretmp" 2 "fre1" } } */
--- 28,32 ----
      }
  }
  
! /* { dg-final { scan-tree-dump-times "Replaced u.f with" 2 "fre1" } } */
! /* { dg-final { scan-tree-dump-times "Inserted" 2 "fre1" } } */


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