Improve DOM's ability to derive equivalences when traversing edges

Jeff Law law@redhat.com
Tue Aug 29 08:36:00 GMT 2017


This is a two part patchkit to improve DOM's ability to derive constant
equivalences that arise as a result of traversing a particular edge in
the CFG.

Until now we only allowed a single NAME = NAME|CONST equivalence to be
associated with an edge in the CFG.  Patch #1 generalizes that code so
that we can record multiple simple equivalences on an edge.  Much like
expression equivalences, we just shove them into a vec and iterate on
the vec in the appropriate places.

Patch #2 has the interesting bits.

Back in the gcc-7 effort I added the ability to look at the operands of
a BIT_IOR_EXPR that had a zero result.  In that case each operand of the
BIT_IOR must have a zero value.  This was to address a missed
optimization regression bug during stage4.

The plan was always to add analogous BIT_AND support, but I didn't feel
like handling BIT_AND was appropriate at the time (no bz entry and no
regressions related to that capability).

I'd also had the sense that further improvements could be made here. For
example, it is common for the BIT_IOR or BIT_AND to be fed by a
comparison and we ought to be able to record the result of the
comparison.  If the comparison happened to be an equality test, then we
may ultimately derive a constant for on operand of the equality test as
well.

It also seemed like the NOP/CONVERT_EXPR handling could be incorporated
into such a change.

So I pulled together some instrumentation.  Lots of things generate
equivalences -- but a much smaller subset of those equivalences are
ultimately useful.

Probably the most surprising was BIT_XOR, which allows us to generate
all kinds of equivalences, but none that were useful for ultimate
simplification in any of the tests I looked at.


The most subtle was COND_EXPRs.  We might have something like

res = (a != 5) ? x : 1;


We can't actually derive anything useful for "a" here, even if we know
the result is one.  That's because "x" could have the value 1.  So you
end up only being able to derive equivalences for COND_EXPRs when both
arms have a constant value.  That restriction dramatically reduces the
utility of handling COND_EXPR -- to the point where I'm not including it.

So what we end up with is BIT_AND/BIT_IOR, conversions, plus/minus,
comparisons and neg/not.

So when we determine that a particular SSA_NAME has a constant value, we
look at the defining statement and essentially try to derive a value for
the input operand(s) based on knowing the result value.  If we can
derive a constant value for an input operand, we record that value and
recurse.

In cases where we walk backwards to a condition.  We will record the
condition into the available expression table.


The code is written such that if we find cases where the equivalences
for other nodes are useful, they're easy to add.


These equivalences are most useful to the threader, but I've seen them
help in other cases as well.  There's a half-dozen or so new tests
reduced from GCC itself.

Bootstrapped and regression tested on x86_64, lightly tested on ppc64le
via bootstrapping and running the new tests to verify they do the right
thing on a !logical_op_short_circuit target.

Installing on the trunk.

Jeff

-------------- next part --------------
commit 506ac60cacbc4c4e5e166513ea83c1d2e14eaf3b
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Aug 29 05:03:22 2017 +0000

            * 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.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@251396 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index abe7d855260..258d4242f30 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 407a4ef97d2..403485b3c55 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);
-------------- next part --------------
commit a370df2c52074abbb044d1921a0c7df235758050
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Aug 29 05:03:36 2017 +0000

            * tree-ssa-dom.c (edge_info::record_simple_equiv): Call
            derive_equivalences.
            (derive_equivalences_from_bit_ior, record_temporary_equivalences):
            Code moved into....
            (edge_info::derive_equivalences): New private member function
    
            * gcc.dg/torture/pr57214.c: Fix type of loop counter.
            * gcc.dg/tree-ssa/ssa-sink-16.c: Disable DOM.
            * gcc.dg/tree-ssa/ssa-dom-thread-11.c: New test.
            * gcc.dg/tree-ssa/ssa-dom-thread-12.c: New test.
            * gcc.dg/tree-ssa/ssa-dom-thread-13.c: New test.
            * gcc.dg/tree-ssa/ssa-dom-thread-14.c: New test.
            * gcc.dg/tree-ssa/ssa-dom-thread-15.c: New test.
            * gcc.dg/tree-ssa/ssa-dom-thread-16.c: New test.
            * gcc.dg/tree-ssa/ssa-dom-thread-17.c: New test.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@251397 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 258d4242f30..9a60a80b746 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
 2017-08-28  Jeff Law  <law@redhat.com>
 
+	* tree-ssa-dom.c (edge_info::record_simple_equiv): Call
+	derive_equivalences.
+	(derive_equivalences_from_bit_ior, record_temporary_equivalences):
+	Code moved into....
+	(edge_info::derive_equivalences): New private member function
+
 	* 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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cfe90904f6d..0ffc4f9a70f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2017-08-28  Jeff Law  <law@redhat.com>
+
+	* gcc.dg/torture/pr57214.c: Fix type of loop counter.
+	* gcc.dg/tree-ssa/ssa-sink-16.c: Disable DOM.
+	* gcc.dg/tree-ssa/ssa-dom-thread-11.c: New test.
+	* gcc.dg/tree-ssa/ssa-dom-thread-12.c: New test.
+	* gcc.dg/tree-ssa/ssa-dom-thread-13.c: New test.
+	* gcc.dg/tree-ssa/ssa-dom-thread-14.c: New test.
+	* gcc.dg/tree-ssa/ssa-dom-thread-15.c: New test.
+	* gcc.dg/tree-ssa/ssa-dom-thread-16.c: New test.
+	* gcc.dg/tree-ssa/ssa-dom-thread-17.c: New test.
+
 2017-08-28  Janus Weil  <janus@gcc.gnu.org>
 
 	PR fortran/81770
diff --git a/gcc/testsuite/gcc.dg/torture/pr57214.c b/gcc/testsuite/gcc.dg/torture/pr57214.c
index d51067d95d8..c697f84514e 100644
--- a/gcc/testsuite/gcc.dg/torture/pr57214.c
+++ b/gcc/testsuite/gcc.dg/torture/pr57214.c
@@ -15,7 +15,7 @@ bar (_Bool b)
       b = 1;
       baz ();
       x = 0;
-      int i;
+      unsigned int i;
       while (buf[i] && i)
 	i++;
       foo ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
new file mode 100644
index 00000000000..f42d64bed71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { ! logical_op_short_circuit  } } } */
+/* { dg-options "-O2 -fdump-tree-dom2-details" } */
+
+static int *bb_ticks;
+extern void frob (void);
+void
+mark_target_live_regs (int b, int block, int bb_tick)
+{
+  if (b == block && b != -1 && bb_tick == bb_ticks[b])
+      return;
+  if (b != -1)
+    frob ();
+}
+
+/* When the first two conditionals in the first IF are true, but
+   the third conditional is false, then there's a jump threading
+   opportunity to bypass the second IF statement.  */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-12.c
new file mode 100644
index 00000000000..63bd12a06a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-12.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
+typedef long unsigned int size_t;
+union tree_node;
+typedef union tree_node *tree;
+typedef union gimple_statement_d *gimple;
+typedef const union gimple_statement_d *const_gimple;
+union gimple_statement_d
+{
+  unsigned num_ops;
+  tree exp;
+};
+
+unsigned int x;
+static inline tree
+gimple_op (const_gimple gs, unsigned i)
+{
+  if (!(i < gs->num_ops))
+    abort ();
+  return gs->exp;
+}
+
+unsigned char
+scan_function (gimple stmt)
+{
+  unsigned i;
+  for (i = 0; i < stmt->num_ops - 3 ; i++)
+    gimple_call_arg (stmt, i);
+  gimple_op (stmt, 1);
+}
+
+/* The test which bypasses the loop is simplified prior to DOM to check
+   that stmt->num_ops - 3 != 0.  When that test is false, we can derive
+   a value for stmt->num_ops.  That in turn allows us to thread the jump
+   for the conditional at the start of the call to gimple_op.  */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-13.c
new file mode 100644
index 00000000000..209c40d4c95
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-13.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
+
+union tree_node;
+typedef union tree_node *tree;
+extern unsigned char tree_contains_struct[0xdead][64];
+struct tree_base
+{
+  int code:16;
+};
+struct tree_typed
+{
+  tree type;
+};
+struct tree_type_common
+{
+  tree main_variant;
+};
+extern tree build_target_option_node (void);
+union tree_node
+{
+  struct tree_base base;
+  struct tree_typed typed;
+  struct tree_type_common type_common;
+};
+tree
+convert (tree type, tree expr)
+{
+  tree e = expr;
+  int code = (type)->base.code;
+  const char *invalid_conv_diag;
+  tree ret;
+  if (tree_contains_struct[expr->base.code][(42)] != 1)
+    abort ();
+  if (type->type_common.main_variant == expr->typed.type->type_common.main_variant
+      && (expr->typed.type->base.code != 123
+	  || e->base.code == 456))
+    return arf ();
+  if (expr->typed.type->base.code == 42)
+    error ("void value not ignored as it ought to be");
+}
+
+/* When the *->base.code tests in the second IF statement are false, we
+   know that expr->typed.base->base.code has the value 123.  That allows
+   us to thread the test for the final IF statement on that path.  */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
new file mode 100644
index 00000000000..2d97f86fa28
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-14.c
@@ -0,0 +1,40 @@
+/* { dg-do compile { target { ! logical_op_short_circuit  } } } */
+/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
+
+enum optab_methods
+{
+  OPTAB_DIRECT,
+  OPTAB_LIB,
+  OPTAB_WIDEN,
+  OPTAB_LIB_WIDEN,
+  OPTAB_MUST_WIDEN
+};
+struct optab_d { };
+typedef struct optab_d *optab;
+void
+expand_shift_1 (int code, int unsignedp, int rotate,
+		optab lshift_optab, optab rshift_arith_optab)
+{
+  int left = (code == 42 || code == 0xde);
+  int attempt;
+  enum optab_methods methods;
+  if (attempt == 0)
+    methods = OPTAB_DIRECT;
+  else if (attempt == 1)
+    methods = OPTAB_WIDEN;
+  if ((!unsignedp || (!left && methods == OPTAB_WIDEN)))
+    {
+      enum optab_methods methods1 = methods;
+      if (unsignedp)
+	methods1 = OPTAB_MUST_WIDEN;
+      expand_binop (left ? lshift_optab : rshift_arith_optab,
+			   unsignedp, methods1);
+    }
+}
+
+/* When UNSIGNEDP is true, LEFT is false and METHOD == OPTAB_WIDEN
+   we will enter the TRUE arm of the conditional and we can thread
+   the test to compute the first first argument of the expand_binop
+   call if we look backwards through the boolean logicals.  */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-15.c
new file mode 100644
index 00000000000..df6a9b32eb1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-15.c
@@ -0,0 +1,67 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
+struct rtx_def;
+typedef struct rtx_def *rtx;
+struct machine_frame_state
+{
+  rtx cfa_reg;
+  long sp_offset;
+};
+struct machine_function {
+  struct machine_frame_state fs;
+};
+enum global_rtl_index
+{
+  GR_PC,
+  GR_CC0,
+  GR_RETURN,
+  GR_SIMPLE_RETURN,
+  GR_STACK_POINTER,
+  GR_FRAME_POINTER,
+  GR_HARD_FRAME_POINTER,
+  GR_ARG_POINTER,
+  GR_VIRTUAL_INCOMING_ARGS,
+  GR_VIRTUAL_STACK_ARGS,
+  GR_VIRTUAL_STACK_DYNAMIC,
+  GR_VIRTUAL_OUTGOING_ARGS,
+  GR_VIRTUAL_CFA,
+  GR_VIRTUAL_PREFERRED_STACK_BOUNDARY,
+  GR_MAX
+};
+struct target_rtl {
+  rtx x_global_rtl[GR_MAX];
+};
+extern struct target_rtl default_target_rtl;
+struct function {
+  struct machine_function * machine;
+};
+extern struct function *cfun;
+struct ix86_frame
+{
+  long stack_pointer_offset;
+};
+void
+ix86_expand_prologue (void)
+{
+  struct machine_function *m = (cfun + 0)->machine;
+  struct ix86_frame frame;
+  long allocate;
+  allocate = frame.stack_pointer_offset - m->fs.sp_offset;
+  if (allocate == 0)
+    ;
+  else if (!ix86_target_stack_probe ()) 
+    {
+      pro_epilogue_adjust_stack ((((&default_target_rtl)->x_global_rtl)[GR_STACK_POINTER]), (((&default_target_rtl)->x_global_rtl)[GR_STACK_POINTER]),
+            gen_rtx_CONST_INT ((-allocate)), -1,
+            m->fs.cfa_reg == (((&default_target_rtl)->x_global_rtl)[GR_STACK_POINTER]));
+    }
+  ((void)(!(m->fs.sp_offset == frame.stack_pointer_offset) ? fancy_abort ("../../gcc-4.7.3/gcc/config/i386/i386.c", 10435, __FUNCTION__), 0 : 0));
+}
+
+/* In the case where ALLOCATE is zero, we know that sp_offset and
+   stack_poitner_offset within their respective structures are the
+   same.  That allows us to thread the jump from the true arm of the
+   first IF conditional around the test controlling the call to
+   fancy_abort.  */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
new file mode 100644
index 00000000000..e2e0d20fb9f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { ! logical_op_short_circuit  } } } */
+/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
+unsigned char
+validate_subreg (unsigned int offset, unsigned int isize, unsigned int osize, int zz, int qq)
+{
+if (osize >= (((zz & (1L << 2)) != 0) ? 8 : 4) && isize >= osize)
+    ;
+  else if (qq == 99)
+ return 0;
+  if (osize > isize)
+    return offset == 0;
+  return 1;
+}
+/* When we test isize >= osize in the first IF conditional and it is
+   false and qq != 99, then we can thread the osize > isize test of
+   the second conditional.  */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-17.c
new file mode 100644
index 00000000000..2c5c5a6cf94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-17.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dom2 -w" } */
+
+struct rtx_def;
+typedef struct rtx_def *rtx;
+struct reload
+{
+  rtx in;
+  rtx reg_rtx;
+};
+extern struct reload rld[(2 * 30 * (2 + 1))];
+static rtx find_dummy_reload (rtx);
+extern int frob ();
+extern int arf ();
+int
+push_reload (rtx in, rtx out
+)
+{
+  int i;
+  if (out != 0 && in != out)
+    {
+      rld[i].reg_rtx = find_dummy_reload (out);
+      if (rld[i].reg_rtx == out)
+	 rld[i].in = out;
+    }
+}
+rtx
+find_dummy_reload (rtx real_out)
+{
+   unsigned int nwords = frob ();
+   unsigned int regno = frob ();
+   unsigned int i;
+   for (i = 0; i < nwords; i++)
+     if (arf ())
+       break;
+   if (i == nwords)
+     return real_out;
+  return 0;
+}
+
+/* In the case where the call to find_dummy_reload returns 0,
+   the final test in push_reload will never be true and it will
+   be eliminated.  */
+/* { dg-final { scan-tree-dump-not "out_\[^\n\r]+ == 0" "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c
index 1b94c336806..610c8d60ebe 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-16.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* Note PRE rotates the loop and blocks the sinking opportunity.  */
-/* { dg-options "-O2 -fno-tree-pre -fdump-tree-sink -fdump-tree-optimized" } */
+/* Note PRE and DOM jump threading rotate the loop and blocks the sinking opportunity.  */
+/* { dg-options "-O2 -fno-tree-pre -fno-tree-dominator-opts -fdump-tree-sink -fdump-tree-optimized" } */
 
 int f(int n)
 {
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 403485b3c55..d91766e902e 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -136,19 +136,240 @@ edge_info::edge_info (edge e)
 }
 
 /* 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.  */
+/* NAME is known to have the value VALUE, which must be a constant.
+
+   Walk through its use-def chain to see if there are other equivalences
+   we might be able to derive.
+
+   RECURSION_LIMIT controls how far back we recurse through the use-def
+   chains.  */
+
+void
+edge_info::derive_equivalences (tree name, tree value, int recursion_limit)
+{
+  if (TREE_CODE (name) != SSA_NAME || TREE_CODE (value) != INTEGER_CST)
+    return;
+
+  /* This records the equivalence for the toplevel object.  Do
+     this before checking the recursion limit.  */
+  simple_equivalences.safe_push (equiv_pair (name, value));
+
+  /* Limit how far up the use-def chains we are willing to walk.  */
+  if (recursion_limit == 0)
+    return;
+
+  /* We can walk up the use-def chains to potentially find more
+     equivalences.  */
+  gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+  if (is_gimple_assign (def_stmt))
+    {
+      /* We know the result of DEF_STMT was zero.  See if that allows
+	 us to deduce anything about the SSA_NAMEs used on the RHS.  */
+      enum tree_code code = gimple_assign_rhs_code (def_stmt);
+      switch (code)
+	{
+	case BIT_IOR_EXPR:
+	  if (integer_zerop (value))
+	    {
+	      tree rhs1 = gimple_assign_rhs1 (def_stmt);
+	      tree rhs2 = gimple_assign_rhs2 (def_stmt);
+
+	      value = build_zero_cst (TREE_TYPE (rhs1));
+	      derive_equivalences (rhs1, value, recursion_limit - 1);
+	      value = build_zero_cst (TREE_TYPE (rhs2));
+	      derive_equivalences (rhs2, value, recursion_limit - 1);
+	    }
+	  break;
+
+      /* We know the result of DEF_STMT was one.  See if that allows
+	 us to deduce anything about the SSA_NAMEs used on the RHS.  */
+	case BIT_AND_EXPR:
+	  if (!integer_zerop (value))
+	    {
+	      tree rhs1 = gimple_assign_rhs1 (def_stmt);
+	      tree rhs2 = gimple_assign_rhs2 (def_stmt);
+
+	      /* If either operand has a boolean range, then we
+		 know its value must be one, otherwise we just know it
+		 is nonzero.  The former is clearly useful, I haven't
+		 seen cases where the latter is helpful yet.  */
+	      if (TREE_CODE (rhs1) == SSA_NAME)
+		{
+		  if (ssa_name_has_boolean_range (rhs1))
+		    {
+		      value = build_one_cst (TREE_TYPE (rhs1));
+		      derive_equivalences (rhs1, value, recursion_limit - 1);
+		    }
+		}
+	      if (TREE_CODE (rhs2) == SSA_NAME)
+		{
+		  if (ssa_name_has_boolean_range (rhs2))
+		    {
+		      value = build_one_cst (TREE_TYPE (rhs2));
+		      derive_equivalences (rhs2, value, recursion_limit - 1);
+		    }
+		}
+	    }
+	  break;
+
+	/* 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.  */
+	case NOP_EXPR:
+	case CONVERT_EXPR:
+	  {
+	    tree rhs = gimple_assign_rhs1 (def_stmt);
+	    tree rhs_type = TREE_TYPE (rhs);
+	    if (INTEGRAL_TYPE_P (rhs_type)
+		&& (TYPE_PRECISION (TREE_TYPE (name))
+		    >= TYPE_PRECISION (rhs_type))
+		&& int_fits_type_p (value, rhs_type))
+	      derive_equivalences (rhs,
+				   fold_convert (rhs_type, value),
+				   recursion_limit - 1);
+	    break;
+	  }
+
+	/* We can invert the operation of these codes trivially if
+	   one of the RHS operands is a constant to produce a known
+	   value for the other RHS operand.  */
+	case POINTER_PLUS_EXPR:
+	case PLUS_EXPR:
+	  {
+	    tree rhs1 = gimple_assign_rhs1 (def_stmt);
+	    tree rhs2 = gimple_assign_rhs2 (def_stmt);
+
+	    /* If either argument is a constant, then we can compute
+	       a constant value for the nonconstant argument.  */
+	    if (TREE_CODE (rhs1) == INTEGER_CST
+		&& TREE_CODE (rhs2) == SSA_NAME)
+	      derive_equivalences (rhs2,
+				   fold_binary (MINUS_EXPR, TREE_TYPE (rhs1),
+						value, rhs1),
+				   recursion_limit - 1);
+	    else if (TREE_CODE (rhs2) == INTEGER_CST
+		     && TREE_CODE (rhs1) == SSA_NAME)
+	      derive_equivalences (rhs1,
+				   fold_binary (MINUS_EXPR, TREE_TYPE (rhs1),
+						value, rhs2),
+				   recursion_limit - 1);
+	    break;
+	  }
+
+	/* If one of the operands is a constant, then we can compute
+	   the value of the other operand.  If both operands are
+	   SSA_NAMEs, then they must be equal if the result is zero.  */
+	case MINUS_EXPR:
+	  {
+	    tree rhs1 = gimple_assign_rhs1 (def_stmt);
+	    tree rhs2 = gimple_assign_rhs2 (def_stmt);
+
+	    /* If either argument is a constant, then we can compute
+	       a constant value for the nonconstant argument.  */
+	    if (TREE_CODE (rhs1) == INTEGER_CST
+		&& TREE_CODE (rhs2) == SSA_NAME)
+	      derive_equivalences (rhs2,
+				   fold_binary (MINUS_EXPR, TREE_TYPE (rhs1),
+						rhs1, value),
+				   recursion_limit - 1);
+	    else if (TREE_CODE (rhs2) == INTEGER_CST
+		     && TREE_CODE (rhs1) == SSA_NAME)
+	      derive_equivalences (rhs1,
+				   fold_binary (PLUS_EXPR, TREE_TYPE (rhs1),
+						value, rhs2),
+				   recursion_limit - 1);
+	    else if (integer_zerop (value))
+	      {
+		tree cond = build2 (EQ_EXPR, boolean_type_node,
+				    gimple_assign_rhs1 (def_stmt),
+				    gimple_assign_rhs2 (def_stmt));
+		tree inverted = invert_truthvalue (cond);
+		record_conditions (&this->cond_equivalences, cond, inverted);
+	      }
+	    break;
+	  }
+
+
+	case EQ_EXPR:
+	case NE_EXPR:
+	  {
+	    if ((code == EQ_EXPR && integer_onep (value))
+		|| (code == NE_EXPR && integer_zerop (value)))
+	      {
+		tree rhs1 = gimple_assign_rhs1 (def_stmt);
+		tree rhs2 = gimple_assign_rhs2 (def_stmt);
+
+		/* If either argument is a constant, then record the
+		   other argument as being the same as that constant.
+
+		   If neither operand is a constant, then we have a
+		   conditional name == name equivalence.  */
+		if (TREE_CODE (rhs1) == INTEGER_CST)
+		  derive_equivalences (rhs2, rhs1, recursion_limit - 1);
+		else if (TREE_CODE (rhs2) == INTEGER_CST)
+		  derive_equivalences (rhs1, rhs2, recursion_limit - 1);
+	      }
+	    else
+	      {
+		tree cond = build2 (code, boolean_type_node,
+				    gimple_assign_rhs1 (def_stmt),
+				    gimple_assign_rhs2 (def_stmt));
+		tree inverted = invert_truthvalue (cond);
+		if (integer_zerop (value))
+		  std::swap (cond, inverted);
+		record_conditions (&this->cond_equivalences, cond, inverted);
+	      }
+	    break;
+	  }
+
+	/* For BIT_NOT and NEGATE, we can just apply the operation to the
+	   VALUE to get the new equivalence.  It will always be a constant
+	   so we can recurse.  */
+	case BIT_NOT_EXPR:
+	case NEGATE_EXPR:
+	  {
+	    tree rhs = gimple_assign_rhs1 (def_stmt);
+	    tree res = fold_build1 (code, TREE_TYPE (rhs), value);
+	    derive_equivalences (rhs, res, recursion_limit - 1);
+	    break;
+	  }
+
+	default:
+	  {
+	    if (TREE_CODE_CLASS (code) == tcc_comparison)
+	      {
+		tree cond = build2 (code, boolean_type_node,
+				    gimple_assign_rhs1 (def_stmt),
+				    gimple_assign_rhs2 (def_stmt));
+		tree inverted = invert_truthvalue (cond);
+		if (integer_zerop (value))
+		  std::swap (cond, inverted);
+		record_conditions (&this->cond_equivalences, cond, inverted);
+		break;
+	      }
+	    break;
+	  }
+	}
+    }
+}
 
 void
 edge_info::record_simple_equiv (tree lhs, tree rhs)
 {
-  simple_equivalences.safe_push (equiv_pair (lhs, rhs));
+  /* If the RHS is a constant, then we may be able to derive
+     further equivalences.  Else just record the name = name
+     equivalence.  */
+  if (TREE_CODE (rhs) == INTEGER_CST)
+    derive_equivalences (lhs, rhs, 4);
+  else
+    simple_equivalences.safe_push (equiv_pair (lhs, rhs));
 }
 
 /* Free the edge_info data attached to E, if it exists.  */
@@ -702,42 +923,6 @@ back_propagate_equivalences (tree lhs, edge e,
     BITMAP_FREE (domby);
 }
 
-/* Record NAME has the value zero and if NAME was set from a BIT_IOR_EXPR
-   recurse into both operands recording their values as zero too. 
-   RECURSION_DEPTH controls how far back we recurse through the operands
-   of the BIT_IOR_EXPR.  */
-
-static void
-derive_equivalences_from_bit_ior (tree name,
-				  const_and_copies *const_and_copies,
-				  int recursion_limit)
-{
-  if (recursion_limit == 0)
-    return;
-
-  if (TREE_CODE (name) == SSA_NAME)
-    {
-      tree value = build_zero_cst (TREE_TYPE (name));
-
-      /* This records the equivalence for the toplevel object.  */
-      record_equality (name, value, const_and_copies);
-
-      /* And we can recurse into each operand to potentially find more
-	 equivalences.  */
-      gimple *def_stmt = SSA_NAME_DEF_STMT (name);
-      if (is_gimple_assign (def_stmt)
-	  && gimple_assign_rhs_code (def_stmt) == BIT_IOR_EXPR)
-	{
-	  derive_equivalences_from_bit_ior (gimple_assign_rhs1 (def_stmt),
-					    const_and_copies,
-					    recursion_limit - 1);
-	  derive_equivalences_from_bit_ior (gimple_assign_rhs2 (def_stmt),
-					    const_and_copies,
-					    recursion_limit - 1);
-	}
-    }
-}
-
 /* Record into CONST_AND_COPIES and AVAIL_EXPRS_STACK any equivalences implied
    by traversing edge E (which are cached in E->aux).
 
@@ -758,28 +943,7 @@ record_temporary_equivalences (edge e,
       /* If we have 0 = COND or 1 = COND equivalences, record them
 	 into our expression hash tables.  */
       for (i = 0; edge_info->cond_equivalences.iterate (i, &eq); ++i)
-	{
-	  avail_exprs_stack->record_cond (eq);
-
-	  /* If the condition is testing that X == 0 is true or X != 0 is false
-	     and X is set from a BIT_IOR_EXPR, then we can record equivalences
-	     for the operands of the BIT_IOR_EXPR (and recurse on those).  */
-	  tree op0 = eq->cond.ops.binary.opnd0;
-	  tree op1 = eq->cond.ops.binary.opnd1;
-	  if (TREE_CODE (op0) == SSA_NAME && integer_zerop (op1))
-	    {
-	      enum tree_code code = eq->cond.ops.binary.op;
-	      if ((code == EQ_EXPR && eq->value == boolean_true_node)
-		  || (code == NE_EXPR && eq->value == boolean_false_node))
-		derive_equivalences_from_bit_ior (op0, const_and_copies, 4);
-
-	      /* TODO: We could handle BIT_AND_EXPR in a similar fashion
-		 recording that the operands have a nonzero value.  */
-
-	      /* TODO: We can handle more cases here, particularly when OP0 is
-		 known to have a boolean range.  */
-	    }
-	}
+	avail_exprs_stack->record_cond (eq);
 
       edge_info::equiv_pair *seq;
       for (i = 0; edge_info->simple_equivalences.iterate (i, &seq); ++i)
@@ -806,42 +970,13 @@ record_temporary_equivalences (edge e,
 	      int lhs_cost = estimate_num_insns (lhs_def, &eni_size_weights);
 
 	      if (rhs_cost > lhs_cost)
-		record_equality (rhs, lhs, const_and_copies);
+	        record_equality (rhs, lhs, const_and_copies);
 	      else if (rhs_cost < lhs_cost)
-		record_equality (lhs, rhs, const_and_copies);
+	        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)))
-		{
-		  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


More information about the Gcc-patches mailing list