Hi Jeff,
On 29 August 2017 at 07:07, Jeff Law <l...@redhat.com> wrote: > 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 > > > 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 <l...@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 <nat...@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); > > 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 > 3 of the new tests fail on arm-none-linux-gnueabihf --with-cpu=cortex-a15 --with-fpu=vfpv3-d16-fp16 FAIL: gcc.dg/tree-ssa/ssa-dom-thread-11.c scan-tree-dump-times dom2 "Threaded" 1 FAIL: gcc.dg/tree-ssa/ssa-dom-thread-14.c scan-tree-dump-times dom2 "Threaded" 1 FAIL: gcc.dg/tree-ssa/ssa-dom-thread-16.c scan-tree-dump-times dom2 "Threaded" 1 they do pass when configuring for cpu cortex-a9/a15 and fpu neon-fp16/neon-vfpv4 I do not have the dumps since it's automated testing; let me know if you need me to reproduce it manually and extract the dumps. Thanks, Christophe > 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 <l...@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 <l...@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 <ja...@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 >