[PATCH][25/25] Remove GENERIC stmt combining from SCCVN

Richard Biener rguenther@suse.de
Wed Sep 30 13:37:00 GMT 2015


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.

Richard.

2015-09-30  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.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2015-09-30 14:49:24.613211956 +0200
--- gcc/tree-ssa-sccvn.c	2015-09-30 14:58:48.018555783 +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,4707 ****
      {
      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)
--- 4344,4353 ----
      {
      case GIMPLE_COND:
        {
! 	val = gimple_simplify (gimple_cond_code (stmt),
! 			       boolean_type_node,
! 			       gimple_cond_lhs (stmt), gimple_cond_rhs (stmt),
! 			       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)
Index: gcc/gimple-match-head.c
===================================================================
*** gcc/gimple-match-head.c.orig	2015-09-30 14:49:24.613211956 +0200
--- gcc/gimple-match-head.c	2015-09-30 14:58:48.002555604 +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 14:49:24.613211956 +0200
--- gcc/gimple-match.h	2015-09-30 14:58:48.002555604 +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 14:49:24.613211956 +0200
--- gcc/tree-ssa-sccvn.h	2015-09-30 14:58:48.018555783 +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 14:49:23.864203487 +0200
--- gcc/tree-ssa-pre.c	2015-09-30 14:58:48.017555772 +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 14:49:23.864203487 +0200
--- gcc/gimple-fold.c	2015-09-30 14:58:48.031555929 +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);



More information about the Gcc-patches mailing list