From a09f784a60ab1685b8711ae6820c77403fe6a299 Mon Sep 17 00:00:00 2001
From: Jeff Law <law@redhat.com>
Date: Mon, 28 Aug 2017 23:03:22 -0600
Subject: [PATCH] tree-ssa-dom.c (class edge_info): Changed from a struct to a
 class.

	* tree-ssa-dom.c (class edge_info): Changed from a struct
	to a class.  Add ctor/dtor, methods and data members.
	(edge_info::edge_info): Renamed from allocate_edge_info.
	Initialize additional members.
	(edge_info::~edge_info): New.
	(free_dom_edge_info): Delete the edge info.
	(record_edge_info): Use new class & associated member functions.
	Tighten forms for testing for edge equivalences.
	(record_temporary_equivalences): Iterate over the simple
	equivalences rather than assuming there's only one per edge.
	(cprop_into_successor_phis): Iterate over the simple
	equivalences rather than assuming there's only one per edge.
	(optimize_stmt): Use operand_equal_p rather than pointer
	equality for mini-DSE code.

From-SVN: r251396
---
 gcc/ChangeLog      |  17 +++
 gcc/tree-ssa-dom.c | 272 ++++++++++++++++++++++++---------------------
 2 files changed, 163 insertions(+), 126 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index abe7d855260f..258d4242f301 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2017-08-28  Jeff Law  <law@redhat.com>
+
+	* tree-ssa-dom.c (class edge_info): Changed from a struct
+	to a class.  Add ctor/dtor, methods and data members.
+	(edge_info::edge_info): Renamed from allocate_edge_info.
+	Initialize additional members.
+	(edge_info::~edge_info): New.
+	(free_dom_edge_info): Delete the edge info.
+	(record_edge_info): Use new class & associated member functions.
+	Tighten forms for testing for edge equivalences.
+	(record_temporary_equivalences): Iterate over the simple
+	equivalences rather than assuming there's only one per edge.
+	(cprop_into_successor_phis): Iterate over the simple
+	equivalences rather than assuming there's only one per edge.
+	(optimize_stmt): Use operand_equal_p rather than pointer
+	equality for mini-DSE code.
+
 2017-08-28  Nathan Sidwell  <nathan@acm.org>
 
 	* gcc.c (execute): Fold SIGPIPE handling into switch
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 407a4ef97d25..403485b3c553 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -58,17 +58,28 @@ along with GCC; see the file COPYING3.  If not see
    These structures live for a single iteration of the dominator
    optimizer in the edge's AUX field.  At the end of an iteration we
    free each of these structures.  */
-
-struct edge_info
+class edge_info
 {
-  /* If this edge creates a simple equivalence, the LHS and RHS of
-     the equivalence will be stored here.  */
-  tree lhs;
-  tree rhs;
+ public:
+  typedef std::pair <tree, tree> equiv_pair;
+  edge_info (edge);
+  ~edge_info ();
+
+  /* Record a simple LHS = RHS equivalence.  This may trigger
+     calls to derive_equivalences.  */
+  void record_simple_equiv (tree, tree);
+
+  /* If traversing this edge creates simple equivalences, we store
+     them as LHS/RHS pairs within this vector.  */
+  vec<equiv_pair> simple_equivalences;
 
   /* Traversing an edge may also indicate one or more particular conditions
      are true or false.  */
   vec<cond_equivalence> cond_equivalences;
+
+ private:
+  /* Derive equivalences by walking the use-def chains.  */
+  void derive_equivalences (tree, tree, int);
 };
 
 /* Track whether or not we have changed the control flow graph.  */
@@ -109,36 +120,46 @@ static edge single_incoming_edge_ignoring_loop_edges (basic_block);
 static void dump_dominator_optimization_stats (FILE *file,
 					       hash_table<expr_elt_hasher> *);
 
+/* Constructor for EDGE_INFO.  An EDGE_INFO instance is always
+   associated with an edge E.  */
 
-/* Free the edge_info data attached to E, if it exists.  */
-
-void
-free_dom_edge_info (edge e)
+edge_info::edge_info (edge e)
 {
-  struct edge_info *edge_info = (struct edge_info *)e->aux;
+  /* Free the old one associated with E, if it exists and
+     associate our new object with E.  */
+  free_dom_edge_info (e);
+  e->aux = this;
 
-  if (edge_info)
-    {
-      edge_info->cond_equivalences.release ();
-      free (edge_info);
-    }
+  /* And initialize the embedded vectors.  */
+  simple_equivalences = vNULL;
+  cond_equivalences = vNULL;
 }
 
-/* Allocate an EDGE_INFO for edge E and attach it to E.
-   Return the new EDGE_INFO structure.  */
+/* Destructor just needs to release the vectors.  */
+edge_info::~edge_info (void)
+{
+  this->cond_equivalences.release ();
+  this->simple_equivalences.release ();
+}
+
+/* Record that LHS is known to be equal to RHS at runtime when the
+   edge associated with THIS is traversed.  */
 
-static struct edge_info *
-allocate_edge_info (edge e)
+void
+edge_info::record_simple_equiv (tree lhs, tree rhs)
 {
-  struct edge_info *edge_info;
+  simple_equivalences.safe_push (equiv_pair (lhs, rhs));
+}
 
-  /* Free the old one, if it exists.  */
-  free_dom_edge_info (e);
+/* Free the edge_info data attached to E, if it exists.  */
 
-  edge_info = XCNEW (struct edge_info);
+void
+free_dom_edge_info (edge e)
+{
+  class edge_info *edge_info = (struct edge_info *)e->aux;
 
-  e->aux = edge_info;
-  return edge_info;
+  if (edge_info)
+    delete edge_info;
 }
 
 /* Free all EDGE_INFO structures associated with edges in the CFG.
@@ -171,7 +192,7 @@ static void
 record_edge_info (basic_block bb)
 {
   gimple_stmt_iterator gsi = gsi_last_bb (bb);
-  struct edge_info *edge_info;
+  class edge_info *edge_info;
 
   if (! gsi_end_p (gsi))
     {
@@ -212,9 +233,8 @@ record_edge_info (basic_block bb)
 		    {
 		      tree x = fold_convert_loc (loc, TREE_TYPE (index),
 						 CASE_LOW (label));
-		      edge_info = allocate_edge_info (e);
-		      edge_info->lhs = index;
-		      edge_info->rhs = x;
+		      edge_info = new class edge_info (e);
+		      edge_info->record_simple_equiv (index, x);
 		    }
 		}
 	      free (info);
@@ -251,28 +271,32 @@ record_edge_info (basic_block bb)
 
               if (code == EQ_EXPR)
                 {
-                  edge_info = allocate_edge_info (true_edge);
-                  edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1) ? false_val : true_val);
-
-                  edge_info = allocate_edge_info (false_edge);
-                  edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1) ? true_val : false_val);
+		  edge_info = new class edge_info (true_edge);
+		  edge_info->record_simple_equiv (op0,
+						  (integer_zerop (op1)
+						   ? false_val : true_val));
+		  edge_info = new class edge_info (false_edge);
+		  edge_info->record_simple_equiv (op0,
+						  (integer_zerop (op1)
+						   ? true_val : false_val));
                 }
               else
                 {
-                  edge_info = allocate_edge_info (true_edge);
-                  edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1) ? true_val : false_val);
-
-                  edge_info = allocate_edge_info (false_edge);
-                  edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1) ? false_val : true_val);
+		  edge_info = new class edge_info (true_edge);
+		  edge_info->record_simple_equiv (op0,
+						  (integer_zerop (op1)
+						   ? true_val : false_val));
+		  edge_info = new class edge_info (false_edge);
+		  edge_info->record_simple_equiv (op0,
+						  (integer_zerop (op1)
+						   ? false_val : true_val));
                 }
             }
+	  /* This can show up in the IL as a result of copy propagation
+	     it will eventually be canonicalized, but we have to cope
+	     with this case within the pass.  */
           else if (is_gimple_min_invariant (op0)
-                   && (TREE_CODE (op1) == SSA_NAME
-                       || is_gimple_min_invariant (op1)))
+                   && TREE_CODE (op1) == SSA_NAME)
             {
               tree cond = build2 (code, boolean_type_node, op0, op1);
               tree inverted = invert_truthvalue_loc (loc, cond);
@@ -281,23 +305,17 @@ record_edge_info (basic_block bb)
                     && real_zerop (op0));
               struct edge_info *edge_info;
 
-              edge_info = allocate_edge_info (true_edge);
+	      edge_info = new class edge_info (true_edge);
               record_conditions (&edge_info->cond_equivalences, cond, inverted);
 
               if (can_infer_simple_equiv && code == EQ_EXPR)
-                {
-                  edge_info->lhs = op1;
-                  edge_info->rhs = op0;
-                }
+		edge_info->record_simple_equiv (op1, op0);
 
-              edge_info = allocate_edge_info (false_edge);
+	      edge_info = new class edge_info (false_edge);
               record_conditions (&edge_info->cond_equivalences, inverted, cond);
 
               if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
-                {
-                  edge_info->lhs = op1;
-                  edge_info->rhs = op0;
-                }
+		edge_info->record_simple_equiv (op1, op0);
             }
 
           else if (TREE_CODE (op0) == SSA_NAME
@@ -311,27 +329,19 @@ record_edge_info (basic_block bb)
                     && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1)));
               struct edge_info *edge_info;
 
-              edge_info = allocate_edge_info (true_edge);
+	      edge_info = new class edge_info (true_edge);
               record_conditions (&edge_info->cond_equivalences, cond, inverted);
 
               if (can_infer_simple_equiv && code == EQ_EXPR)
-                {
-                  edge_info->lhs = op0;
-                  edge_info->rhs = op1;
-                }
+		edge_info->record_simple_equiv (op0, op1);
 
-              edge_info = allocate_edge_info (false_edge);
+	      edge_info = new class edge_info (false_edge);
               record_conditions (&edge_info->cond_equivalences, inverted, cond);
 
               if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
-                {
-                  edge_info->lhs = op0;
-                  edge_info->rhs = op1;
-                }
+		edge_info->record_simple_equiv (op0, op1);
             }
         }
-
-      /* ??? TRUTH_NOT_EXPR can create an equivalence too.  */
     }
 }
 
@@ -738,7 +748,7 @@ record_temporary_equivalences (edge e,
 			       class avail_exprs_stack *avail_exprs_stack)
 {
   int i;
-  struct edge_info *edge_info = (struct edge_info *) e->aux;
+  class edge_info *edge_info = (class edge_info *) e->aux;
 
   /* If we have info associated with this edge, record it into
      our equivalence tables.  */
@@ -771,68 +781,73 @@ record_temporary_equivalences (edge e,
 	    }
 	}
 
-      tree lhs = edge_info->lhs;
-      if (!lhs || TREE_CODE (lhs) != SSA_NAME)
-	return;
+      edge_info::equiv_pair *seq;
+      for (i = 0; edge_info->simple_equivalences.iterate (i, &seq); ++i)
+	{
+	  tree lhs = seq->first;
+	  if (!lhs || TREE_CODE (lhs) != SSA_NAME)
+	    continue;
 
-      /* Record the simple NAME = VALUE equivalence.  */
-      tree rhs = edge_info->rhs;
+	  /* Record the simple NAME = VALUE equivalence.  */
+	  tree rhs = seq->second;
 
-      /* If this is a SSA_NAME = SSA_NAME equivalence and one operand is
-	 cheaper to compute than the other, then set up the equivalence
-	 such that we replace the expensive one with the cheap one.
+	  /* If this is a SSA_NAME = SSA_NAME equivalence and one operand is
+	     cheaper to compute than the other, then set up the equivalence
+	     such that we replace the expensive one with the cheap one.
 
-	 If they are the same cost to compute, then do not record anything.  */
-      if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME)
-	{
-	  gimple *rhs_def = SSA_NAME_DEF_STMT (rhs);
-	  int rhs_cost = estimate_num_insns (rhs_def, &eni_size_weights);
+	     If they are the same cost to compute, then do not record
+	     anything.  */
+	  if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME)
+	    {
+	      gimple *rhs_def = SSA_NAME_DEF_STMT (rhs);
+	      int rhs_cost = estimate_num_insns (rhs_def, &eni_size_weights);
 
-	  gimple *lhs_def = SSA_NAME_DEF_STMT (lhs);
-	  int lhs_cost = estimate_num_insns (lhs_def, &eni_size_weights);
+	      gimple *lhs_def = SSA_NAME_DEF_STMT (lhs);
+	      int lhs_cost = estimate_num_insns (lhs_def, &eni_size_weights);
 
-	  if (rhs_cost > lhs_cost)
-	    record_equality (rhs, lhs, const_and_copies);
-	  else if (rhs_cost < lhs_cost)
+	      if (rhs_cost > lhs_cost)
+		record_equality (rhs, lhs, const_and_copies);
+	      else if (rhs_cost < lhs_cost)
+		record_equality (lhs, rhs, const_and_copies);
+	    }
+	  else
 	    record_equality (lhs, rhs, const_and_copies);
-	}
-      else
-	record_equality (lhs, rhs, const_and_copies);
 
-      /* If LHS is an SSA_NAME and RHS is a constant integer and LHS was
-	 set via a widening type conversion, then we may be able to record
-	 additional equivalences.  */
-      if (TREE_CODE (rhs) == INTEGER_CST)
-	{
-	  gimple *defstmt = SSA_NAME_DEF_STMT (lhs);
-
-	  if (defstmt
-	      && is_gimple_assign (defstmt)
-	      && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (defstmt)))
+	  /* If LHS is an SSA_NAME and RHS is a constant integer and LHS was
+	     set via a widening type conversion, then we may be able to record
+	     additional equivalences.  */
+	  if (TREE_CODE (rhs) == INTEGER_CST)
 	    {
-	      tree old_rhs = gimple_assign_rhs1 (defstmt);
-
-	      /* If the conversion widens the original value and
-		 the constant is in the range of the type of OLD_RHS,
-		 then convert the constant and record the equivalence.
-
-		 Note that int_fits_type_p does not check the precision
-		 if the upper and lower bounds are OK.  */
-	      if (INTEGRAL_TYPE_P (TREE_TYPE (old_rhs))
-		  && (TYPE_PRECISION (TREE_TYPE (lhs))
-		      > TYPE_PRECISION (TREE_TYPE (old_rhs)))
-		  && int_fits_type_p (rhs, TREE_TYPE (old_rhs)))
+	      gimple *defstmt = SSA_NAME_DEF_STMT (lhs);
+
+	      if (defstmt
+		  && is_gimple_assign (defstmt)
+		  && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (defstmt)))
 		{
-		  tree newval = fold_convert (TREE_TYPE (old_rhs), rhs);
-		  record_equality (old_rhs, newval, const_and_copies);
+		  tree old_rhs = gimple_assign_rhs1 (defstmt);
+
+		  /* If the conversion widens the original value and
+		     the constant is in the range of the type of OLD_RHS,
+		     then convert the constant and record the equivalence.
+
+		     Note that int_fits_type_p does not check the precision
+		     if the upper and lower bounds are OK.  */
+		  if (INTEGRAL_TYPE_P (TREE_TYPE (old_rhs))
+		      && (TYPE_PRECISION (TREE_TYPE (lhs))
+			  > TYPE_PRECISION (TREE_TYPE (old_rhs)))
+		      && int_fits_type_p (rhs, TREE_TYPE (old_rhs)))
+		    {
+		      tree newval = fold_convert (TREE_TYPE (old_rhs), rhs);
+		      record_equality (old_rhs, newval, const_and_copies);
+		    }
 		}
 	    }
-	}
 
-      /* Any equivalence found for LHS may result in additional
-	 equivalences for other uses of LHS that we have already
-	 processed.  */
-      back_propagate_equivalences (lhs, e, const_and_copies);
+	  /* Any equivalence found for LHS may result in additional
+	     equivalences for other uses of LHS that we have already
+	     processed.  */
+	  back_propagate_equivalences (lhs, e, const_and_copies);
+	}
     }
 }
 
@@ -1124,14 +1139,20 @@ cprop_into_successor_phis (basic_block bb,
 
 	 Don't bother with [01] = COND equivalences, they're not useful
 	 here.  */
-      struct edge_info *edge_info = (struct edge_info *) e->aux;
+      class edge_info *edge_info = (class edge_info *) e->aux;
+
       if (edge_info)
 	{
-	  tree lhs = edge_info->lhs;
-	  tree rhs = edge_info->rhs;
+	  edge_info::equiv_pair *seq;
+	  for (int i = 0; edge_info->simple_equivalences.iterate (i, &seq); ++i)
+	    {
+	      tree lhs = seq->first;
+	      tree rhs = seq->second;
+
+	      if (lhs && TREE_CODE (lhs) == SSA_NAME)
+		const_and_copies->record_const_or_copy (lhs, rhs);
+	    }
 
-	  if (lhs && TREE_CODE (lhs) == SSA_NAME)
-	    const_and_copies->record_const_or_copy (lhs, rhs);
 	}
 
       indx = e->dest_idx;
@@ -1701,8 +1722,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 	  gimple_set_vuse (new_stmt, gimple_vuse (stmt));
 	  cached_lhs = avail_exprs_stack->lookup_avail_expr (new_stmt, false,
 							     false);
-	  if (cached_lhs
-	      && rhs == cached_lhs)
+	  if (cached_lhs && operand_equal_p (rhs, cached_lhs, 0))
 	    {
 	      basic_block bb = gimple_bb (stmt);
 	      unlink_stmt_vdef (stmt);
-- 
GitLab