xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-ssa-dom.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* SSA Dominator optimizations for trees
2*e4b17023SJohn Marino    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Diego Novillo <dnovillo@redhat.com>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11*e4b17023SJohn Marino any later version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*e4b17023SJohn Marino GNU General Public License for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "tree.h"
27*e4b17023SJohn Marino #include "flags.h"
28*e4b17023SJohn Marino #include "tm_p.h"
29*e4b17023SJohn Marino #include "basic-block.h"
30*e4b17023SJohn Marino #include "cfgloop.h"
31*e4b17023SJohn Marino #include "output.h"
32*e4b17023SJohn Marino #include "function.h"
33*e4b17023SJohn Marino #include "tree-pretty-print.h"
34*e4b17023SJohn Marino #include "gimple-pretty-print.h"
35*e4b17023SJohn Marino #include "timevar.h"
36*e4b17023SJohn Marino #include "tree-dump.h"
37*e4b17023SJohn Marino #include "tree-flow.h"
38*e4b17023SJohn Marino #include "domwalk.h"
39*e4b17023SJohn Marino #include "tree-pass.h"
40*e4b17023SJohn Marino #include "tree-ssa-propagate.h"
41*e4b17023SJohn Marino #include "langhooks.h"
42*e4b17023SJohn Marino #include "params.h"
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino /* This file implements optimizations on the dominator tree.  */
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* Representation of a "naked" right-hand-side expression, to be used
47*e4b17023SJohn Marino    in recording available expressions in the expression hash table.  */
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino enum expr_kind
50*e4b17023SJohn Marino {
51*e4b17023SJohn Marino   EXPR_SINGLE,
52*e4b17023SJohn Marino   EXPR_UNARY,
53*e4b17023SJohn Marino   EXPR_BINARY,
54*e4b17023SJohn Marino   EXPR_TERNARY,
55*e4b17023SJohn Marino   EXPR_CALL,
56*e4b17023SJohn Marino   EXPR_PHI
57*e4b17023SJohn Marino };
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino struct hashable_expr
60*e4b17023SJohn Marino {
61*e4b17023SJohn Marino   tree type;
62*e4b17023SJohn Marino   enum expr_kind kind;
63*e4b17023SJohn Marino   union {
64*e4b17023SJohn Marino     struct { tree rhs; } single;
65*e4b17023SJohn Marino     struct { enum tree_code op;  tree opnd; } unary;
66*e4b17023SJohn Marino     struct { enum tree_code op;  tree opnd0, opnd1; } binary;
67*e4b17023SJohn Marino     struct { enum tree_code op;  tree opnd0, opnd1, opnd2; } ternary;
68*e4b17023SJohn Marino     struct { gimple fn_from; bool pure; size_t nargs; tree *args; } call;
69*e4b17023SJohn Marino     struct { size_t nargs; tree *args; } phi;
70*e4b17023SJohn Marino   } ops;
71*e4b17023SJohn Marino };
72*e4b17023SJohn Marino 
73*e4b17023SJohn Marino /* Structure for recording known values of a conditional expression
74*e4b17023SJohn Marino    at the exits from its block.  */
75*e4b17023SJohn Marino 
76*e4b17023SJohn Marino typedef struct cond_equivalence_s
77*e4b17023SJohn Marino {
78*e4b17023SJohn Marino   struct hashable_expr cond;
79*e4b17023SJohn Marino   tree value;
80*e4b17023SJohn Marino } cond_equivalence;
81*e4b17023SJohn Marino 
82*e4b17023SJohn Marino DEF_VEC_O(cond_equivalence);
83*e4b17023SJohn Marino DEF_VEC_ALLOC_O(cond_equivalence,heap);
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino /* Structure for recording edge equivalences as well as any pending
86*e4b17023SJohn Marino    edge redirections during the dominator optimizer.
87*e4b17023SJohn Marino 
88*e4b17023SJohn Marino    Computing and storing the edge equivalences instead of creating
89*e4b17023SJohn Marino    them on-demand can save significant amounts of time, particularly
90*e4b17023SJohn Marino    for pathological cases involving switch statements.
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino    These structures live for a single iteration of the dominator
93*e4b17023SJohn Marino    optimizer in the edge's AUX field.  At the end of an iteration we
94*e4b17023SJohn Marino    free each of these structures and update the AUX field to point
95*e4b17023SJohn Marino    to any requested redirection target (the code for updating the
96*e4b17023SJohn Marino    CFG and SSA graph for edge redirection expects redirection edge
97*e4b17023SJohn Marino    targets to be in the AUX field for each edge.  */
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino struct edge_info
100*e4b17023SJohn Marino {
101*e4b17023SJohn Marino   /* If this edge creates a simple equivalence, the LHS and RHS of
102*e4b17023SJohn Marino      the equivalence will be stored here.  */
103*e4b17023SJohn Marino   tree lhs;
104*e4b17023SJohn Marino   tree rhs;
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino   /* Traversing an edge may also indicate one or more particular conditions
107*e4b17023SJohn Marino      are true or false.  */
108*e4b17023SJohn Marino   VEC(cond_equivalence, heap) *cond_equivalences;
109*e4b17023SJohn Marino };
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino /* Hash table with expressions made available during the renaming process.
112*e4b17023SJohn Marino    When an assignment of the form X_i = EXPR is found, the statement is
113*e4b17023SJohn Marino    stored in this table.  If the same expression EXPR is later found on the
114*e4b17023SJohn Marino    RHS of another statement, it is replaced with X_i (thus performing
115*e4b17023SJohn Marino    global redundancy elimination).  Similarly as we pass through conditionals
116*e4b17023SJohn Marino    we record the conditional itself as having either a true or false value
117*e4b17023SJohn Marino    in this table.  */
118*e4b17023SJohn Marino static htab_t avail_exprs;
119*e4b17023SJohn Marino 
120*e4b17023SJohn Marino /* Stack of available expressions in AVAIL_EXPRs.  Each block pushes any
121*e4b17023SJohn Marino    expressions it enters into the hash table along with a marker entry
122*e4b17023SJohn Marino    (null).  When we finish processing the block, we pop off entries and
123*e4b17023SJohn Marino    remove the expressions from the global hash table until we hit the
124*e4b17023SJohn Marino    marker.  */
125*e4b17023SJohn Marino typedef struct expr_hash_elt * expr_hash_elt_t;
126*e4b17023SJohn Marino DEF_VEC_P(expr_hash_elt_t);
127*e4b17023SJohn Marino DEF_VEC_ALLOC_P(expr_hash_elt_t,heap);
128*e4b17023SJohn Marino 
VEC(expr_hash_elt_t,heap)129*e4b17023SJohn Marino static VEC(expr_hash_elt_t,heap) *avail_exprs_stack;
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino /* Structure for entries in the expression hash table.  */
132*e4b17023SJohn Marino 
133*e4b17023SJohn Marino struct expr_hash_elt
134*e4b17023SJohn Marino {
135*e4b17023SJohn Marino   /* The value (lhs) of this expression.  */
136*e4b17023SJohn Marino   tree lhs;
137*e4b17023SJohn Marino 
138*e4b17023SJohn Marino   /* The expression (rhs) we want to record.  */
139*e4b17023SJohn Marino   struct hashable_expr expr;
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino   /* The stmt pointer if this element corresponds to a statement.  */
142*e4b17023SJohn Marino   gimple stmt;
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino   /* The hash value for RHS.  */
145*e4b17023SJohn Marino   hashval_t hash;
146*e4b17023SJohn Marino 
147*e4b17023SJohn Marino   /* A unique stamp, typically the address of the hash
148*e4b17023SJohn Marino      element itself, used in removing entries from the table.  */
149*e4b17023SJohn Marino   struct expr_hash_elt *stamp;
150*e4b17023SJohn Marino };
151*e4b17023SJohn Marino 
152*e4b17023SJohn Marino /* Stack of dest,src pairs that need to be restored during finalization.
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino    A NULL entry is used to mark the end of pairs which need to be
155*e4b17023SJohn Marino    restored during finalization of this block.  */
156*e4b17023SJohn Marino static VEC(tree,heap) *const_and_copies_stack;
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino /* Track whether or not we have changed the control flow graph.  */
159*e4b17023SJohn Marino static bool cfg_altered;
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino /* Bitmap of blocks that have had EH statements cleaned.  We should
162*e4b17023SJohn Marino    remove their dead edges eventually.  */
163*e4b17023SJohn Marino static bitmap need_eh_cleanup;
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino /* Statistics for dominator optimizations.  */
166*e4b17023SJohn Marino struct opt_stats_d
167*e4b17023SJohn Marino {
168*e4b17023SJohn Marino   long num_stmts;
169*e4b17023SJohn Marino   long num_exprs_considered;
170*e4b17023SJohn Marino   long num_re;
171*e4b17023SJohn Marino   long num_const_prop;
172*e4b17023SJohn Marino   long num_copy_prop;
173*e4b17023SJohn Marino };
174*e4b17023SJohn Marino 
175*e4b17023SJohn Marino static struct opt_stats_d opt_stats;
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino /* Local functions.  */
178*e4b17023SJohn Marino static void optimize_stmt (basic_block, gimple_stmt_iterator);
179*e4b17023SJohn Marino static tree lookup_avail_expr (gimple, bool);
180*e4b17023SJohn Marino static hashval_t avail_expr_hash (const void *);
181*e4b17023SJohn Marino static hashval_t real_avail_expr_hash (const void *);
182*e4b17023SJohn Marino static int avail_expr_eq (const void *, const void *);
183*e4b17023SJohn Marino static void htab_statistics (FILE *, htab_t);
184*e4b17023SJohn Marino static void record_cond (cond_equivalence *);
185*e4b17023SJohn Marino static void record_const_or_copy (tree, tree);
186*e4b17023SJohn Marino static void record_equality (tree, tree);
187*e4b17023SJohn Marino static void record_equivalences_from_phis (basic_block);
188*e4b17023SJohn Marino static void record_equivalences_from_incoming_edge (basic_block);
189*e4b17023SJohn Marino static void eliminate_redundant_computations (gimple_stmt_iterator *);
190*e4b17023SJohn Marino static void record_equivalences_from_stmt (gimple, int);
191*e4b17023SJohn Marino static void dom_thread_across_edge (struct dom_walk_data *, edge);
192*e4b17023SJohn Marino static void dom_opt_leave_block (struct dom_walk_data *, basic_block);
193*e4b17023SJohn Marino static void dom_opt_enter_block (struct dom_walk_data *, basic_block);
194*e4b17023SJohn Marino static void remove_local_expressions_from_table (void);
195*e4b17023SJohn Marino static void restore_vars_to_original_value (void);
196*e4b17023SJohn Marino static edge single_incoming_edge_ignoring_loop_edges (basic_block);
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino /* Given a statement STMT, initialize the hash table element pointed to
200*e4b17023SJohn Marino    by ELEMENT.  */
201*e4b17023SJohn Marino 
202*e4b17023SJohn Marino static void
initialize_hash_element(gimple stmt,tree lhs,struct expr_hash_elt * element)203*e4b17023SJohn Marino initialize_hash_element (gimple stmt, tree lhs,
204*e4b17023SJohn Marino                          struct expr_hash_elt *element)
205*e4b17023SJohn Marino {
206*e4b17023SJohn Marino   enum gimple_code code = gimple_code (stmt);
207*e4b17023SJohn Marino   struct hashable_expr *expr = &element->expr;
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino   if (code == GIMPLE_ASSIGN)
210*e4b17023SJohn Marino     {
211*e4b17023SJohn Marino       enum tree_code subcode = gimple_assign_rhs_code (stmt);
212*e4b17023SJohn Marino 
213*e4b17023SJohn Marino       switch (get_gimple_rhs_class (subcode))
214*e4b17023SJohn Marino         {
215*e4b17023SJohn Marino         case GIMPLE_SINGLE_RHS:
216*e4b17023SJohn Marino 	  expr->kind = EXPR_SINGLE;
217*e4b17023SJohn Marino 	  expr->type = TREE_TYPE (gimple_assign_rhs1 (stmt));
218*e4b17023SJohn Marino 	  expr->ops.single.rhs = gimple_assign_rhs1 (stmt);
219*e4b17023SJohn Marino 	  break;
220*e4b17023SJohn Marino         case GIMPLE_UNARY_RHS:
221*e4b17023SJohn Marino 	  expr->kind = EXPR_UNARY;
222*e4b17023SJohn Marino 	  expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
223*e4b17023SJohn Marino 	  expr->ops.unary.op = subcode;
224*e4b17023SJohn Marino 	  expr->ops.unary.opnd = gimple_assign_rhs1 (stmt);
225*e4b17023SJohn Marino 	  break;
226*e4b17023SJohn Marino         case GIMPLE_BINARY_RHS:
227*e4b17023SJohn Marino 	  expr->kind = EXPR_BINARY;
228*e4b17023SJohn Marino 	  expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
229*e4b17023SJohn Marino 	  expr->ops.binary.op = subcode;
230*e4b17023SJohn Marino 	  expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt);
231*e4b17023SJohn Marino 	  expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt);
232*e4b17023SJohn Marino 	  break;
233*e4b17023SJohn Marino         case GIMPLE_TERNARY_RHS:
234*e4b17023SJohn Marino 	  expr->kind = EXPR_TERNARY;
235*e4b17023SJohn Marino 	  expr->type = TREE_TYPE (gimple_assign_lhs (stmt));
236*e4b17023SJohn Marino 	  expr->ops.ternary.op = subcode;
237*e4b17023SJohn Marino 	  expr->ops.ternary.opnd0 = gimple_assign_rhs1 (stmt);
238*e4b17023SJohn Marino 	  expr->ops.ternary.opnd1 = gimple_assign_rhs2 (stmt);
239*e4b17023SJohn Marino 	  expr->ops.ternary.opnd2 = gimple_assign_rhs3 (stmt);
240*e4b17023SJohn Marino 	  break;
241*e4b17023SJohn Marino         default:
242*e4b17023SJohn Marino           gcc_unreachable ();
243*e4b17023SJohn Marino         }
244*e4b17023SJohn Marino     }
245*e4b17023SJohn Marino   else if (code == GIMPLE_COND)
246*e4b17023SJohn Marino     {
247*e4b17023SJohn Marino       expr->type = boolean_type_node;
248*e4b17023SJohn Marino       expr->kind = EXPR_BINARY;
249*e4b17023SJohn Marino       expr->ops.binary.op = gimple_cond_code (stmt);
250*e4b17023SJohn Marino       expr->ops.binary.opnd0 = gimple_cond_lhs (stmt);
251*e4b17023SJohn Marino       expr->ops.binary.opnd1 = gimple_cond_rhs (stmt);
252*e4b17023SJohn Marino     }
253*e4b17023SJohn Marino   else if (code == GIMPLE_CALL)
254*e4b17023SJohn Marino     {
255*e4b17023SJohn Marino       size_t nargs = gimple_call_num_args (stmt);
256*e4b17023SJohn Marino       size_t i;
257*e4b17023SJohn Marino 
258*e4b17023SJohn Marino       gcc_assert (gimple_call_lhs (stmt));
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino       expr->type = TREE_TYPE (gimple_call_lhs (stmt));
261*e4b17023SJohn Marino       expr->kind = EXPR_CALL;
262*e4b17023SJohn Marino       expr->ops.call.fn_from = stmt;
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino       if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
265*e4b17023SJohn Marino         expr->ops.call.pure = true;
266*e4b17023SJohn Marino       else
267*e4b17023SJohn Marino         expr->ops.call.pure = false;
268*e4b17023SJohn Marino 
269*e4b17023SJohn Marino       expr->ops.call.nargs = nargs;
270*e4b17023SJohn Marino       expr->ops.call.args = XCNEWVEC (tree, nargs);
271*e4b17023SJohn Marino       for (i = 0; i < nargs; i++)
272*e4b17023SJohn Marino         expr->ops.call.args[i] = gimple_call_arg (stmt, i);
273*e4b17023SJohn Marino     }
274*e4b17023SJohn Marino   else if (code == GIMPLE_SWITCH)
275*e4b17023SJohn Marino     {
276*e4b17023SJohn Marino       expr->type = TREE_TYPE (gimple_switch_index (stmt));
277*e4b17023SJohn Marino       expr->kind = EXPR_SINGLE;
278*e4b17023SJohn Marino       expr->ops.single.rhs = gimple_switch_index (stmt);
279*e4b17023SJohn Marino     }
280*e4b17023SJohn Marino   else if (code == GIMPLE_GOTO)
281*e4b17023SJohn Marino     {
282*e4b17023SJohn Marino       expr->type = TREE_TYPE (gimple_goto_dest (stmt));
283*e4b17023SJohn Marino       expr->kind = EXPR_SINGLE;
284*e4b17023SJohn Marino       expr->ops.single.rhs = gimple_goto_dest (stmt);
285*e4b17023SJohn Marino     }
286*e4b17023SJohn Marino   else if (code == GIMPLE_PHI)
287*e4b17023SJohn Marino     {
288*e4b17023SJohn Marino       size_t nargs = gimple_phi_num_args (stmt);
289*e4b17023SJohn Marino       size_t i;
290*e4b17023SJohn Marino 
291*e4b17023SJohn Marino       expr->type = TREE_TYPE (gimple_phi_result (stmt));
292*e4b17023SJohn Marino       expr->kind = EXPR_PHI;
293*e4b17023SJohn Marino       expr->ops.phi.nargs = nargs;
294*e4b17023SJohn Marino       expr->ops.phi.args = XCNEWVEC (tree, nargs);
295*e4b17023SJohn Marino 
296*e4b17023SJohn Marino       for (i = 0; i < nargs; i++)
297*e4b17023SJohn Marino         expr->ops.phi.args[i] = gimple_phi_arg_def (stmt, i);
298*e4b17023SJohn Marino     }
299*e4b17023SJohn Marino   else
300*e4b17023SJohn Marino     gcc_unreachable ();
301*e4b17023SJohn Marino 
302*e4b17023SJohn Marino   element->lhs = lhs;
303*e4b17023SJohn Marino   element->stmt = stmt;
304*e4b17023SJohn Marino   element->hash = avail_expr_hash (element);
305*e4b17023SJohn Marino   element->stamp = element;
306*e4b17023SJohn Marino }
307*e4b17023SJohn Marino 
308*e4b17023SJohn Marino /* Given a conditional expression COND as a tree, initialize
309*e4b17023SJohn Marino    a hashable_expr expression EXPR.  The conditional must be a
310*e4b17023SJohn Marino    comparison or logical negation.  A constant or a variable is
311*e4b17023SJohn Marino    not permitted.  */
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino static void
initialize_expr_from_cond(tree cond,struct hashable_expr * expr)314*e4b17023SJohn Marino initialize_expr_from_cond (tree cond, struct hashable_expr *expr)
315*e4b17023SJohn Marino {
316*e4b17023SJohn Marino   expr->type = boolean_type_node;
317*e4b17023SJohn Marino 
318*e4b17023SJohn Marino   if (COMPARISON_CLASS_P (cond))
319*e4b17023SJohn Marino     {
320*e4b17023SJohn Marino       expr->kind = EXPR_BINARY;
321*e4b17023SJohn Marino       expr->ops.binary.op = TREE_CODE (cond);
322*e4b17023SJohn Marino       expr->ops.binary.opnd0 = TREE_OPERAND (cond, 0);
323*e4b17023SJohn Marino       expr->ops.binary.opnd1 = TREE_OPERAND (cond, 1);
324*e4b17023SJohn Marino     }
325*e4b17023SJohn Marino   else if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
326*e4b17023SJohn Marino     {
327*e4b17023SJohn Marino       expr->kind = EXPR_UNARY;
328*e4b17023SJohn Marino       expr->ops.unary.op = TRUTH_NOT_EXPR;
329*e4b17023SJohn Marino       expr->ops.unary.opnd = TREE_OPERAND (cond, 0);
330*e4b17023SJohn Marino     }
331*e4b17023SJohn Marino   else
332*e4b17023SJohn Marino     gcc_unreachable ();
333*e4b17023SJohn Marino }
334*e4b17023SJohn Marino 
335*e4b17023SJohn Marino /* Given a hashable_expr expression EXPR and an LHS,
336*e4b17023SJohn Marino    initialize the hash table element pointed to by ELEMENT.  */
337*e4b17023SJohn Marino 
338*e4b17023SJohn Marino static void
initialize_hash_element_from_expr(struct hashable_expr * expr,tree lhs,struct expr_hash_elt * element)339*e4b17023SJohn Marino initialize_hash_element_from_expr (struct hashable_expr *expr,
340*e4b17023SJohn Marino                                    tree lhs,
341*e4b17023SJohn Marino                                    struct expr_hash_elt *element)
342*e4b17023SJohn Marino {
343*e4b17023SJohn Marino   element->expr = *expr;
344*e4b17023SJohn Marino   element->lhs = lhs;
345*e4b17023SJohn Marino   element->stmt = NULL;
346*e4b17023SJohn Marino   element->hash = avail_expr_hash (element);
347*e4b17023SJohn Marino   element->stamp = element;
348*e4b17023SJohn Marino }
349*e4b17023SJohn Marino 
350*e4b17023SJohn Marino /* Compare two hashable_expr structures for equivalence.
351*e4b17023SJohn Marino    They are considered equivalent when the the expressions
352*e4b17023SJohn Marino    they denote must necessarily be equal.  The logic is intended
353*e4b17023SJohn Marino    to follow that of operand_equal_p in fold-const.c  */
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino static bool
hashable_expr_equal_p(const struct hashable_expr * expr0,const struct hashable_expr * expr1)356*e4b17023SJohn Marino hashable_expr_equal_p (const struct hashable_expr *expr0,
357*e4b17023SJohn Marino                         const struct hashable_expr *expr1)
358*e4b17023SJohn Marino {
359*e4b17023SJohn Marino   tree type0 = expr0->type;
360*e4b17023SJohn Marino   tree type1 = expr1->type;
361*e4b17023SJohn Marino 
362*e4b17023SJohn Marino   /* If either type is NULL, there is nothing to check.  */
363*e4b17023SJohn Marino   if ((type0 == NULL_TREE) ^ (type1 == NULL_TREE))
364*e4b17023SJohn Marino     return false;
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino   /* If both types don't have the same signedness, precision, and mode,
367*e4b17023SJohn Marino      then we can't consider  them equal.  */
368*e4b17023SJohn Marino   if (type0 != type1
369*e4b17023SJohn Marino       && (TREE_CODE (type0) == ERROR_MARK
370*e4b17023SJohn Marino 	  || TREE_CODE (type1) == ERROR_MARK
371*e4b17023SJohn Marino 	  || TYPE_UNSIGNED (type0) != TYPE_UNSIGNED (type1)
372*e4b17023SJohn Marino 	  || TYPE_PRECISION (type0) != TYPE_PRECISION (type1)
373*e4b17023SJohn Marino 	  || TYPE_MODE (type0) != TYPE_MODE (type1)))
374*e4b17023SJohn Marino     return false;
375*e4b17023SJohn Marino 
376*e4b17023SJohn Marino   if (expr0->kind != expr1->kind)
377*e4b17023SJohn Marino     return false;
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino   switch (expr0->kind)
380*e4b17023SJohn Marino     {
381*e4b17023SJohn Marino     case EXPR_SINGLE:
382*e4b17023SJohn Marino       return operand_equal_p (expr0->ops.single.rhs,
383*e4b17023SJohn Marino                               expr1->ops.single.rhs, 0);
384*e4b17023SJohn Marino 
385*e4b17023SJohn Marino     case EXPR_UNARY:
386*e4b17023SJohn Marino       if (expr0->ops.unary.op != expr1->ops.unary.op)
387*e4b17023SJohn Marino         return false;
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino       if ((CONVERT_EXPR_CODE_P (expr0->ops.unary.op)
390*e4b17023SJohn Marino            || expr0->ops.unary.op == NON_LVALUE_EXPR)
391*e4b17023SJohn Marino           && TYPE_UNSIGNED (expr0->type) != TYPE_UNSIGNED (expr1->type))
392*e4b17023SJohn Marino         return false;
393*e4b17023SJohn Marino 
394*e4b17023SJohn Marino       return operand_equal_p (expr0->ops.unary.opnd,
395*e4b17023SJohn Marino                               expr1->ops.unary.opnd, 0);
396*e4b17023SJohn Marino 
397*e4b17023SJohn Marino     case EXPR_BINARY:
398*e4b17023SJohn Marino       if (expr0->ops.binary.op != expr1->ops.binary.op)
399*e4b17023SJohn Marino 	return false;
400*e4b17023SJohn Marino 
401*e4b17023SJohn Marino       if (operand_equal_p (expr0->ops.binary.opnd0,
402*e4b17023SJohn Marino 			   expr1->ops.binary.opnd0, 0)
403*e4b17023SJohn Marino 	  && operand_equal_p (expr0->ops.binary.opnd1,
404*e4b17023SJohn Marino 			      expr1->ops.binary.opnd1, 0))
405*e4b17023SJohn Marino 	return true;
406*e4b17023SJohn Marino 
407*e4b17023SJohn Marino       /* For commutative ops, allow the other order.  */
408*e4b17023SJohn Marino       return (commutative_tree_code (expr0->ops.binary.op)
409*e4b17023SJohn Marino 	      && operand_equal_p (expr0->ops.binary.opnd0,
410*e4b17023SJohn Marino 				  expr1->ops.binary.opnd1, 0)
411*e4b17023SJohn Marino 	      && operand_equal_p (expr0->ops.binary.opnd1,
412*e4b17023SJohn Marino 				  expr1->ops.binary.opnd0, 0));
413*e4b17023SJohn Marino 
414*e4b17023SJohn Marino     case EXPR_TERNARY:
415*e4b17023SJohn Marino       if (expr0->ops.ternary.op != expr1->ops.ternary.op
416*e4b17023SJohn Marino 	  || !operand_equal_p (expr0->ops.ternary.opnd2,
417*e4b17023SJohn Marino 			       expr1->ops.ternary.opnd2, 0))
418*e4b17023SJohn Marino 	return false;
419*e4b17023SJohn Marino 
420*e4b17023SJohn Marino       if (operand_equal_p (expr0->ops.ternary.opnd0,
421*e4b17023SJohn Marino 			   expr1->ops.ternary.opnd0, 0)
422*e4b17023SJohn Marino 	  && operand_equal_p (expr0->ops.ternary.opnd1,
423*e4b17023SJohn Marino 			      expr1->ops.ternary.opnd1, 0))
424*e4b17023SJohn Marino 	return true;
425*e4b17023SJohn Marino 
426*e4b17023SJohn Marino       /* For commutative ops, allow the other order.  */
427*e4b17023SJohn Marino       return (commutative_ternary_tree_code (expr0->ops.ternary.op)
428*e4b17023SJohn Marino 	      && operand_equal_p (expr0->ops.ternary.opnd0,
429*e4b17023SJohn Marino 				  expr1->ops.ternary.opnd1, 0)
430*e4b17023SJohn Marino 	      && operand_equal_p (expr0->ops.ternary.opnd1,
431*e4b17023SJohn Marino 				  expr1->ops.ternary.opnd0, 0));
432*e4b17023SJohn Marino 
433*e4b17023SJohn Marino     case EXPR_CALL:
434*e4b17023SJohn Marino       {
435*e4b17023SJohn Marino         size_t i;
436*e4b17023SJohn Marino 
437*e4b17023SJohn Marino         /* If the calls are to different functions, then they
438*e4b17023SJohn Marino            clearly cannot be equal.  */
439*e4b17023SJohn Marino         if (!gimple_call_same_target_p (expr0->ops.call.fn_from,
440*e4b17023SJohn Marino                                         expr1->ops.call.fn_from))
441*e4b17023SJohn Marino           return false;
442*e4b17023SJohn Marino 
443*e4b17023SJohn Marino         if (! expr0->ops.call.pure)
444*e4b17023SJohn Marino           return false;
445*e4b17023SJohn Marino 
446*e4b17023SJohn Marino         if (expr0->ops.call.nargs !=  expr1->ops.call.nargs)
447*e4b17023SJohn Marino           return false;
448*e4b17023SJohn Marino 
449*e4b17023SJohn Marino         for (i = 0; i < expr0->ops.call.nargs; i++)
450*e4b17023SJohn Marino           if (! operand_equal_p (expr0->ops.call.args[i],
451*e4b17023SJohn Marino                                  expr1->ops.call.args[i], 0))
452*e4b17023SJohn Marino             return false;
453*e4b17023SJohn Marino 
454*e4b17023SJohn Marino         return true;
455*e4b17023SJohn Marino       }
456*e4b17023SJohn Marino 
457*e4b17023SJohn Marino     case EXPR_PHI:
458*e4b17023SJohn Marino       {
459*e4b17023SJohn Marino         size_t i;
460*e4b17023SJohn Marino 
461*e4b17023SJohn Marino         if (expr0->ops.phi.nargs !=  expr1->ops.phi.nargs)
462*e4b17023SJohn Marino           return false;
463*e4b17023SJohn Marino 
464*e4b17023SJohn Marino         for (i = 0; i < expr0->ops.phi.nargs; i++)
465*e4b17023SJohn Marino           if (! operand_equal_p (expr0->ops.phi.args[i],
466*e4b17023SJohn Marino                                  expr1->ops.phi.args[i], 0))
467*e4b17023SJohn Marino             return false;
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino         return true;
470*e4b17023SJohn Marino       }
471*e4b17023SJohn Marino 
472*e4b17023SJohn Marino     default:
473*e4b17023SJohn Marino       gcc_unreachable ();
474*e4b17023SJohn Marino     }
475*e4b17023SJohn Marino }
476*e4b17023SJohn Marino 
477*e4b17023SJohn Marino /* Compute a hash value for a hashable_expr value EXPR and a
478*e4b17023SJohn Marino    previously accumulated hash value VAL.  If two hashable_expr
479*e4b17023SJohn Marino    values compare equal with hashable_expr_equal_p, they must
480*e4b17023SJohn Marino    hash to the same value, given an identical value of VAL.
481*e4b17023SJohn Marino    The logic is intended to follow iterative_hash_expr in tree.c.  */
482*e4b17023SJohn Marino 
483*e4b17023SJohn Marino static hashval_t
iterative_hash_hashable_expr(const struct hashable_expr * expr,hashval_t val)484*e4b17023SJohn Marino iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val)
485*e4b17023SJohn Marino {
486*e4b17023SJohn Marino   switch (expr->kind)
487*e4b17023SJohn Marino     {
488*e4b17023SJohn Marino     case EXPR_SINGLE:
489*e4b17023SJohn Marino       val = iterative_hash_expr (expr->ops.single.rhs, val);
490*e4b17023SJohn Marino       break;
491*e4b17023SJohn Marino 
492*e4b17023SJohn Marino     case EXPR_UNARY:
493*e4b17023SJohn Marino       val = iterative_hash_object (expr->ops.unary.op, val);
494*e4b17023SJohn Marino 
495*e4b17023SJohn Marino       /* Make sure to include signedness in the hash computation.
496*e4b17023SJohn Marino          Don't hash the type, that can lead to having nodes which
497*e4b17023SJohn Marino          compare equal according to operand_equal_p, but which
498*e4b17023SJohn Marino          have different hash codes.  */
499*e4b17023SJohn Marino       if (CONVERT_EXPR_CODE_P (expr->ops.unary.op)
500*e4b17023SJohn Marino           || expr->ops.unary.op == NON_LVALUE_EXPR)
501*e4b17023SJohn Marino         val += TYPE_UNSIGNED (expr->type);
502*e4b17023SJohn Marino 
503*e4b17023SJohn Marino       val = iterative_hash_expr (expr->ops.unary.opnd, val);
504*e4b17023SJohn Marino       break;
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino     case EXPR_BINARY:
507*e4b17023SJohn Marino       val = iterative_hash_object (expr->ops.binary.op, val);
508*e4b17023SJohn Marino       if (commutative_tree_code (expr->ops.binary.op))
509*e4b17023SJohn Marino 	val = iterative_hash_exprs_commutative (expr->ops.binary.opnd0,
510*e4b17023SJohn Marino 						expr->ops.binary.opnd1, val);
511*e4b17023SJohn Marino       else
512*e4b17023SJohn Marino         {
513*e4b17023SJohn Marino           val = iterative_hash_expr (expr->ops.binary.opnd0, val);
514*e4b17023SJohn Marino           val = iterative_hash_expr (expr->ops.binary.opnd1, val);
515*e4b17023SJohn Marino         }
516*e4b17023SJohn Marino       break;
517*e4b17023SJohn Marino 
518*e4b17023SJohn Marino     case EXPR_TERNARY:
519*e4b17023SJohn Marino       val = iterative_hash_object (expr->ops.ternary.op, val);
520*e4b17023SJohn Marino       if (commutative_ternary_tree_code (expr->ops.ternary.op))
521*e4b17023SJohn Marino 	val = iterative_hash_exprs_commutative (expr->ops.ternary.opnd0,
522*e4b17023SJohn Marino 						expr->ops.ternary.opnd1, val);
523*e4b17023SJohn Marino       else
524*e4b17023SJohn Marino         {
525*e4b17023SJohn Marino           val = iterative_hash_expr (expr->ops.ternary.opnd0, val);
526*e4b17023SJohn Marino           val = iterative_hash_expr (expr->ops.ternary.opnd1, val);
527*e4b17023SJohn Marino         }
528*e4b17023SJohn Marino       val = iterative_hash_expr (expr->ops.ternary.opnd2, val);
529*e4b17023SJohn Marino       break;
530*e4b17023SJohn Marino 
531*e4b17023SJohn Marino     case EXPR_CALL:
532*e4b17023SJohn Marino       {
533*e4b17023SJohn Marino         size_t i;
534*e4b17023SJohn Marino         enum tree_code code = CALL_EXPR;
535*e4b17023SJohn Marino         gimple fn_from;
536*e4b17023SJohn Marino 
537*e4b17023SJohn Marino         val = iterative_hash_object (code, val);
538*e4b17023SJohn Marino         fn_from = expr->ops.call.fn_from;
539*e4b17023SJohn Marino         if (gimple_call_internal_p (fn_from))
540*e4b17023SJohn Marino           val = iterative_hash_hashval_t
541*e4b17023SJohn Marino             ((hashval_t) gimple_call_internal_fn (fn_from), val);
542*e4b17023SJohn Marino         else
543*e4b17023SJohn Marino           val = iterative_hash_expr (gimple_call_fn (fn_from), val);
544*e4b17023SJohn Marino         for (i = 0; i < expr->ops.call.nargs; i++)
545*e4b17023SJohn Marino           val = iterative_hash_expr (expr->ops.call.args[i], val);
546*e4b17023SJohn Marino       }
547*e4b17023SJohn Marino       break;
548*e4b17023SJohn Marino 
549*e4b17023SJohn Marino     case EXPR_PHI:
550*e4b17023SJohn Marino       {
551*e4b17023SJohn Marino         size_t i;
552*e4b17023SJohn Marino 
553*e4b17023SJohn Marino         for (i = 0; i < expr->ops.phi.nargs; i++)
554*e4b17023SJohn Marino           val = iterative_hash_expr (expr->ops.phi.args[i], val);
555*e4b17023SJohn Marino       }
556*e4b17023SJohn Marino       break;
557*e4b17023SJohn Marino 
558*e4b17023SJohn Marino     default:
559*e4b17023SJohn Marino       gcc_unreachable ();
560*e4b17023SJohn Marino     }
561*e4b17023SJohn Marino 
562*e4b17023SJohn Marino   return val;
563*e4b17023SJohn Marino }
564*e4b17023SJohn Marino 
565*e4b17023SJohn Marino /* Print a diagnostic dump of an expression hash table entry.  */
566*e4b17023SJohn Marino 
567*e4b17023SJohn Marino static void
print_expr_hash_elt(FILE * stream,const struct expr_hash_elt * element)568*e4b17023SJohn Marino print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
569*e4b17023SJohn Marino {
570*e4b17023SJohn Marino   if (element->stmt)
571*e4b17023SJohn Marino     fprintf (stream, "STMT ");
572*e4b17023SJohn Marino   else
573*e4b17023SJohn Marino     fprintf (stream, "COND ");
574*e4b17023SJohn Marino 
575*e4b17023SJohn Marino   if (element->lhs)
576*e4b17023SJohn Marino     {
577*e4b17023SJohn Marino       print_generic_expr (stream, element->lhs, 0);
578*e4b17023SJohn Marino       fprintf (stream, " = ");
579*e4b17023SJohn Marino     }
580*e4b17023SJohn Marino 
581*e4b17023SJohn Marino   switch (element->expr.kind)
582*e4b17023SJohn Marino     {
583*e4b17023SJohn Marino       case EXPR_SINGLE:
584*e4b17023SJohn Marino         print_generic_expr (stream, element->expr.ops.single.rhs, 0);
585*e4b17023SJohn Marino         break;
586*e4b17023SJohn Marino 
587*e4b17023SJohn Marino       case EXPR_UNARY:
588*e4b17023SJohn Marino         fprintf (stream, "%s ", tree_code_name[element->expr.ops.unary.op]);
589*e4b17023SJohn Marino         print_generic_expr (stream, element->expr.ops.unary.opnd, 0);
590*e4b17023SJohn Marino         break;
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino       case EXPR_BINARY:
593*e4b17023SJohn Marino         print_generic_expr (stream, element->expr.ops.binary.opnd0, 0);
594*e4b17023SJohn Marino         fprintf (stream, " %s ", tree_code_name[element->expr.ops.binary.op]);
595*e4b17023SJohn Marino         print_generic_expr (stream, element->expr.ops.binary.opnd1, 0);
596*e4b17023SJohn Marino         break;
597*e4b17023SJohn Marino 
598*e4b17023SJohn Marino       case EXPR_TERNARY:
599*e4b17023SJohn Marino         fprintf (stream, " %s <", tree_code_name[element->expr.ops.ternary.op]);
600*e4b17023SJohn Marino         print_generic_expr (stream, element->expr.ops.ternary.opnd0, 0);
601*e4b17023SJohn Marino 	fputs (", ", stream);
602*e4b17023SJohn Marino         print_generic_expr (stream, element->expr.ops.ternary.opnd1, 0);
603*e4b17023SJohn Marino 	fputs (", ", stream);
604*e4b17023SJohn Marino         print_generic_expr (stream, element->expr.ops.ternary.opnd2, 0);
605*e4b17023SJohn Marino 	fputs (">", stream);
606*e4b17023SJohn Marino         break;
607*e4b17023SJohn Marino 
608*e4b17023SJohn Marino       case EXPR_CALL:
609*e4b17023SJohn Marino         {
610*e4b17023SJohn Marino           size_t i;
611*e4b17023SJohn Marino           size_t nargs = element->expr.ops.call.nargs;
612*e4b17023SJohn Marino           gimple fn_from;
613*e4b17023SJohn Marino 
614*e4b17023SJohn Marino           fn_from = element->expr.ops.call.fn_from;
615*e4b17023SJohn Marino           if (gimple_call_internal_p (fn_from))
616*e4b17023SJohn Marino             fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
617*e4b17023SJohn Marino                    stream);
618*e4b17023SJohn Marino           else
619*e4b17023SJohn Marino             print_generic_expr (stream, gimple_call_fn (fn_from), 0);
620*e4b17023SJohn Marino           fprintf (stream, " (");
621*e4b17023SJohn Marino           for (i = 0; i < nargs; i++)
622*e4b17023SJohn Marino             {
623*e4b17023SJohn Marino               print_generic_expr (stream, element->expr.ops.call.args[i], 0);
624*e4b17023SJohn Marino               if (i + 1 < nargs)
625*e4b17023SJohn Marino                 fprintf (stream, ", ");
626*e4b17023SJohn Marino             }
627*e4b17023SJohn Marino           fprintf (stream, ")");
628*e4b17023SJohn Marino         }
629*e4b17023SJohn Marino         break;
630*e4b17023SJohn Marino 
631*e4b17023SJohn Marino       case EXPR_PHI:
632*e4b17023SJohn Marino         {
633*e4b17023SJohn Marino           size_t i;
634*e4b17023SJohn Marino           size_t nargs = element->expr.ops.phi.nargs;
635*e4b17023SJohn Marino 
636*e4b17023SJohn Marino           fprintf (stream, "PHI <");
637*e4b17023SJohn Marino           for (i = 0; i < nargs; i++)
638*e4b17023SJohn Marino             {
639*e4b17023SJohn Marino               print_generic_expr (stream, element->expr.ops.phi.args[i], 0);
640*e4b17023SJohn Marino               if (i + 1 < nargs)
641*e4b17023SJohn Marino                 fprintf (stream, ", ");
642*e4b17023SJohn Marino             }
643*e4b17023SJohn Marino           fprintf (stream, ">");
644*e4b17023SJohn Marino         }
645*e4b17023SJohn Marino         break;
646*e4b17023SJohn Marino     }
647*e4b17023SJohn Marino   fprintf (stream, "\n");
648*e4b17023SJohn Marino 
649*e4b17023SJohn Marino   if (element->stmt)
650*e4b17023SJohn Marino     {
651*e4b17023SJohn Marino       fprintf (stream, "          ");
652*e4b17023SJohn Marino       print_gimple_stmt (stream, element->stmt, 0, 0);
653*e4b17023SJohn Marino     }
654*e4b17023SJohn Marino }
655*e4b17023SJohn Marino 
656*e4b17023SJohn Marino /* Delete an expr_hash_elt and reclaim its storage.  */
657*e4b17023SJohn Marino 
658*e4b17023SJohn Marino static void
free_expr_hash_elt(void * elt)659*e4b17023SJohn Marino free_expr_hash_elt (void *elt)
660*e4b17023SJohn Marino {
661*e4b17023SJohn Marino   struct expr_hash_elt *element = ((struct expr_hash_elt *)elt);
662*e4b17023SJohn Marino 
663*e4b17023SJohn Marino   if (element->expr.kind == EXPR_CALL)
664*e4b17023SJohn Marino     free (element->expr.ops.call.args);
665*e4b17023SJohn Marino 
666*e4b17023SJohn Marino   if (element->expr.kind == EXPR_PHI)
667*e4b17023SJohn Marino     free (element->expr.ops.phi.args);
668*e4b17023SJohn Marino 
669*e4b17023SJohn Marino   free (element);
670*e4b17023SJohn Marino }
671*e4b17023SJohn Marino 
672*e4b17023SJohn Marino /* Allocate an EDGE_INFO for edge E and attach it to E.
673*e4b17023SJohn Marino    Return the new EDGE_INFO structure.  */
674*e4b17023SJohn Marino 
675*e4b17023SJohn Marino static struct edge_info *
allocate_edge_info(edge e)676*e4b17023SJohn Marino allocate_edge_info (edge e)
677*e4b17023SJohn Marino {
678*e4b17023SJohn Marino   struct edge_info *edge_info;
679*e4b17023SJohn Marino 
680*e4b17023SJohn Marino   edge_info = XCNEW (struct edge_info);
681*e4b17023SJohn Marino 
682*e4b17023SJohn Marino   e->aux = edge_info;
683*e4b17023SJohn Marino   return edge_info;
684*e4b17023SJohn Marino }
685*e4b17023SJohn Marino 
686*e4b17023SJohn Marino /* Free all EDGE_INFO structures associated with edges in the CFG.
687*e4b17023SJohn Marino    If a particular edge can be threaded, copy the redirection
688*e4b17023SJohn Marino    target from the EDGE_INFO structure into the edge's AUX field
689*e4b17023SJohn Marino    as required by code to update the CFG and SSA graph for
690*e4b17023SJohn Marino    jump threading.  */
691*e4b17023SJohn Marino 
692*e4b17023SJohn Marino static void
free_all_edge_infos(void)693*e4b17023SJohn Marino free_all_edge_infos (void)
694*e4b17023SJohn Marino {
695*e4b17023SJohn Marino   basic_block bb;
696*e4b17023SJohn Marino   edge_iterator ei;
697*e4b17023SJohn Marino   edge e;
698*e4b17023SJohn Marino 
699*e4b17023SJohn Marino   FOR_EACH_BB (bb)
700*e4b17023SJohn Marino     {
701*e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->preds)
702*e4b17023SJohn Marino         {
703*e4b17023SJohn Marino 	 struct edge_info *edge_info = (struct edge_info *) e->aux;
704*e4b17023SJohn Marino 
705*e4b17023SJohn Marino 	  if (edge_info)
706*e4b17023SJohn Marino 	    {
707*e4b17023SJohn Marino 	      if (edge_info->cond_equivalences)
708*e4b17023SJohn Marino 		VEC_free (cond_equivalence, heap, edge_info->cond_equivalences);
709*e4b17023SJohn Marino 	      free (edge_info);
710*e4b17023SJohn Marino 	      e->aux = NULL;
711*e4b17023SJohn Marino 	    }
712*e4b17023SJohn Marino 	}
713*e4b17023SJohn Marino     }
714*e4b17023SJohn Marino }
715*e4b17023SJohn Marino 
716*e4b17023SJohn Marino /* Jump threading, redundancy elimination and const/copy propagation.
717*e4b17023SJohn Marino 
718*e4b17023SJohn Marino    This pass may expose new symbols that need to be renamed into SSA.  For
719*e4b17023SJohn Marino    every new symbol exposed, its corresponding bit will be set in
720*e4b17023SJohn Marino    VARS_TO_RENAME.  */
721*e4b17023SJohn Marino 
722*e4b17023SJohn Marino static unsigned int
tree_ssa_dominator_optimize(void)723*e4b17023SJohn Marino tree_ssa_dominator_optimize (void)
724*e4b17023SJohn Marino {
725*e4b17023SJohn Marino   struct dom_walk_data walk_data;
726*e4b17023SJohn Marino 
727*e4b17023SJohn Marino   memset (&opt_stats, 0, sizeof (opt_stats));
728*e4b17023SJohn Marino 
729*e4b17023SJohn Marino   /* Create our hash tables.  */
730*e4b17023SJohn Marino   avail_exprs = htab_create (1024, real_avail_expr_hash, avail_expr_eq, free_expr_hash_elt);
731*e4b17023SJohn Marino   avail_exprs_stack = VEC_alloc (expr_hash_elt_t, heap, 20);
732*e4b17023SJohn Marino   const_and_copies_stack = VEC_alloc (tree, heap, 20);
733*e4b17023SJohn Marino   need_eh_cleanup = BITMAP_ALLOC (NULL);
734*e4b17023SJohn Marino 
735*e4b17023SJohn Marino   /* Setup callbacks for the generic dominator tree walker.  */
736*e4b17023SJohn Marino   walk_data.dom_direction = CDI_DOMINATORS;
737*e4b17023SJohn Marino   walk_data.initialize_block_local_data = NULL;
738*e4b17023SJohn Marino   walk_data.before_dom_children = dom_opt_enter_block;
739*e4b17023SJohn Marino   walk_data.after_dom_children = dom_opt_leave_block;
740*e4b17023SJohn Marino   /* Right now we only attach a dummy COND_EXPR to the global data pointer.
741*e4b17023SJohn Marino      When we attach more stuff we'll need to fill this out with a real
742*e4b17023SJohn Marino      structure.  */
743*e4b17023SJohn Marino   walk_data.global_data = NULL;
744*e4b17023SJohn Marino   walk_data.block_local_data_size = 0;
745*e4b17023SJohn Marino 
746*e4b17023SJohn Marino   /* Now initialize the dominator walker.  */
747*e4b17023SJohn Marino   init_walk_dominator_tree (&walk_data);
748*e4b17023SJohn Marino 
749*e4b17023SJohn Marino   calculate_dominance_info (CDI_DOMINATORS);
750*e4b17023SJohn Marino   cfg_altered = false;
751*e4b17023SJohn Marino 
752*e4b17023SJohn Marino   /* We need to know loop structures in order to avoid destroying them
753*e4b17023SJohn Marino      in jump threading.  Note that we still can e.g. thread through loop
754*e4b17023SJohn Marino      headers to an exit edge, or through loop header to the loop body, assuming
755*e4b17023SJohn Marino      that we update the loop info.  */
756*e4b17023SJohn Marino   loop_optimizer_init (LOOPS_HAVE_SIMPLE_LATCHES);
757*e4b17023SJohn Marino 
758*e4b17023SJohn Marino   /* Initialize the value-handle array.  */
759*e4b17023SJohn Marino   threadedge_initialize_values ();
760*e4b17023SJohn Marino 
761*e4b17023SJohn Marino   /* We need accurate information regarding back edges in the CFG
762*e4b17023SJohn Marino      for jump threading; this may include back edges that are not part of
763*e4b17023SJohn Marino      a single loop.  */
764*e4b17023SJohn Marino   mark_dfs_back_edges ();
765*e4b17023SJohn Marino 
766*e4b17023SJohn Marino   /* Recursively walk the dominator tree optimizing statements.  */
767*e4b17023SJohn Marino   walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
768*e4b17023SJohn Marino 
769*e4b17023SJohn Marino   {
770*e4b17023SJohn Marino     gimple_stmt_iterator gsi;
771*e4b17023SJohn Marino     basic_block bb;
772*e4b17023SJohn Marino     FOR_EACH_BB (bb)
773*e4b17023SJohn Marino       {
774*e4b17023SJohn Marino 	for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
775*e4b17023SJohn Marino 	  update_stmt_if_modified (gsi_stmt (gsi));
776*e4b17023SJohn Marino       }
777*e4b17023SJohn Marino   }
778*e4b17023SJohn Marino 
779*e4b17023SJohn Marino   /* If we exposed any new variables, go ahead and put them into
780*e4b17023SJohn Marino      SSA form now, before we handle jump threading.  This simplifies
781*e4b17023SJohn Marino      interactions between rewriting of _DECL nodes into SSA form
782*e4b17023SJohn Marino      and rewriting SSA_NAME nodes into SSA form after block
783*e4b17023SJohn Marino      duplication and CFG manipulation.  */
784*e4b17023SJohn Marino   update_ssa (TODO_update_ssa);
785*e4b17023SJohn Marino 
786*e4b17023SJohn Marino   free_all_edge_infos ();
787*e4b17023SJohn Marino 
788*e4b17023SJohn Marino   /* Thread jumps, creating duplicate blocks as needed.  */
789*e4b17023SJohn Marino   cfg_altered |= thread_through_all_blocks (first_pass_instance);
790*e4b17023SJohn Marino 
791*e4b17023SJohn Marino   if (cfg_altered)
792*e4b17023SJohn Marino     free_dominance_info (CDI_DOMINATORS);
793*e4b17023SJohn Marino 
794*e4b17023SJohn Marino   /* Removal of statements may make some EH edges dead.  Purge
795*e4b17023SJohn Marino      such edges from the CFG as needed.  */
796*e4b17023SJohn Marino   if (!bitmap_empty_p (need_eh_cleanup))
797*e4b17023SJohn Marino     {
798*e4b17023SJohn Marino       unsigned i;
799*e4b17023SJohn Marino       bitmap_iterator bi;
800*e4b17023SJohn Marino 
801*e4b17023SJohn Marino       /* Jump threading may have created forwarder blocks from blocks
802*e4b17023SJohn Marino 	 needing EH cleanup; the new successor of these blocks, which
803*e4b17023SJohn Marino 	 has inherited from the original block, needs the cleanup.  */
804*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (need_eh_cleanup, 0, i, bi)
805*e4b17023SJohn Marino 	{
806*e4b17023SJohn Marino 	  basic_block bb = BASIC_BLOCK (i);
807*e4b17023SJohn Marino 	  if (bb
808*e4b17023SJohn Marino 	      && single_succ_p (bb)
809*e4b17023SJohn Marino 	      && (single_succ_edge (bb)->flags & EDGE_EH) == 0)
810*e4b17023SJohn Marino 	    {
811*e4b17023SJohn Marino 	      bitmap_clear_bit (need_eh_cleanup, i);
812*e4b17023SJohn Marino 	      bitmap_set_bit (need_eh_cleanup, single_succ (bb)->index);
813*e4b17023SJohn Marino 	    }
814*e4b17023SJohn Marino 	}
815*e4b17023SJohn Marino 
816*e4b17023SJohn Marino       gimple_purge_all_dead_eh_edges (need_eh_cleanup);
817*e4b17023SJohn Marino       bitmap_zero (need_eh_cleanup);
818*e4b17023SJohn Marino     }
819*e4b17023SJohn Marino 
820*e4b17023SJohn Marino   statistics_counter_event (cfun, "Redundant expressions eliminated",
821*e4b17023SJohn Marino 			    opt_stats.num_re);
822*e4b17023SJohn Marino   statistics_counter_event (cfun, "Constants propagated",
823*e4b17023SJohn Marino 			    opt_stats.num_const_prop);
824*e4b17023SJohn Marino   statistics_counter_event (cfun, "Copies propagated",
825*e4b17023SJohn Marino 			    opt_stats.num_copy_prop);
826*e4b17023SJohn Marino 
827*e4b17023SJohn Marino   /* Debugging dumps.  */
828*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_STATS))
829*e4b17023SJohn Marino     dump_dominator_optimization_stats (dump_file);
830*e4b17023SJohn Marino 
831*e4b17023SJohn Marino   loop_optimizer_finalize ();
832*e4b17023SJohn Marino 
833*e4b17023SJohn Marino   /* Delete our main hashtable.  */
834*e4b17023SJohn Marino   htab_delete (avail_exprs);
835*e4b17023SJohn Marino 
836*e4b17023SJohn Marino   /* And finalize the dominator walker.  */
837*e4b17023SJohn Marino   fini_walk_dominator_tree (&walk_data);
838*e4b17023SJohn Marino 
839*e4b17023SJohn Marino   /* Free asserted bitmaps and stacks.  */
840*e4b17023SJohn Marino   BITMAP_FREE (need_eh_cleanup);
841*e4b17023SJohn Marino 
842*e4b17023SJohn Marino   VEC_free (expr_hash_elt_t, heap, avail_exprs_stack);
843*e4b17023SJohn Marino   VEC_free (tree, heap, const_and_copies_stack);
844*e4b17023SJohn Marino 
845*e4b17023SJohn Marino   /* Free the value-handle array.  */
846*e4b17023SJohn Marino   threadedge_finalize_values ();
847*e4b17023SJohn Marino   ssa_name_values = NULL;
848*e4b17023SJohn Marino 
849*e4b17023SJohn Marino   return 0;
850*e4b17023SJohn Marino }
851*e4b17023SJohn Marino 
852*e4b17023SJohn Marino static bool
gate_dominator(void)853*e4b17023SJohn Marino gate_dominator (void)
854*e4b17023SJohn Marino {
855*e4b17023SJohn Marino   return flag_tree_dom != 0;
856*e4b17023SJohn Marino }
857*e4b17023SJohn Marino 
858*e4b17023SJohn Marino struct gimple_opt_pass pass_dominator =
859*e4b17023SJohn Marino {
860*e4b17023SJohn Marino  {
861*e4b17023SJohn Marino   GIMPLE_PASS,
862*e4b17023SJohn Marino   "dom",				/* name */
863*e4b17023SJohn Marino   gate_dominator,			/* gate */
864*e4b17023SJohn Marino   tree_ssa_dominator_optimize,		/* execute */
865*e4b17023SJohn Marino   NULL,					/* sub */
866*e4b17023SJohn Marino   NULL,					/* next */
867*e4b17023SJohn Marino   0,					/* static_pass_number */
868*e4b17023SJohn Marino   TV_TREE_SSA_DOMINATOR_OPTS,		/* tv_id */
869*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
870*e4b17023SJohn Marino   0,					/* properties_provided */
871*e4b17023SJohn Marino   0,					/* properties_destroyed */
872*e4b17023SJohn Marino   0,					/* todo_flags_start */
873*e4b17023SJohn Marino   TODO_cleanup_cfg
874*e4b17023SJohn Marino     | TODO_update_ssa
875*e4b17023SJohn Marino     | TODO_verify_ssa
876*e4b17023SJohn Marino     | TODO_verify_flow			/* todo_flags_finish */
877*e4b17023SJohn Marino  }
878*e4b17023SJohn Marino };
879*e4b17023SJohn Marino 
880*e4b17023SJohn Marino 
881*e4b17023SJohn Marino /* Given a conditional statement CONDSTMT, convert the
882*e4b17023SJohn Marino    condition to a canonical form.  */
883*e4b17023SJohn Marino 
884*e4b17023SJohn Marino static void
canonicalize_comparison(gimple condstmt)885*e4b17023SJohn Marino canonicalize_comparison (gimple condstmt)
886*e4b17023SJohn Marino {
887*e4b17023SJohn Marino   tree op0;
888*e4b17023SJohn Marino   tree op1;
889*e4b17023SJohn Marino   enum tree_code code;
890*e4b17023SJohn Marino 
891*e4b17023SJohn Marino   gcc_assert (gimple_code (condstmt) == GIMPLE_COND);
892*e4b17023SJohn Marino 
893*e4b17023SJohn Marino   op0 = gimple_cond_lhs (condstmt);
894*e4b17023SJohn Marino   op1 = gimple_cond_rhs (condstmt);
895*e4b17023SJohn Marino 
896*e4b17023SJohn Marino   code = gimple_cond_code (condstmt);
897*e4b17023SJohn Marino 
898*e4b17023SJohn Marino   /* If it would be profitable to swap the operands, then do so to
899*e4b17023SJohn Marino      canonicalize the statement, enabling better optimization.
900*e4b17023SJohn Marino 
901*e4b17023SJohn Marino      By placing canonicalization of such expressions here we
902*e4b17023SJohn Marino      transparently keep statements in canonical form, even
903*e4b17023SJohn Marino      when the statement is modified.  */
904*e4b17023SJohn Marino   if (tree_swap_operands_p (op0, op1, false))
905*e4b17023SJohn Marino     {
906*e4b17023SJohn Marino       /* For relationals we need to swap the operands
907*e4b17023SJohn Marino 	 and change the code.  */
908*e4b17023SJohn Marino       if (code == LT_EXPR
909*e4b17023SJohn Marino 	  || code == GT_EXPR
910*e4b17023SJohn Marino 	  || code == LE_EXPR
911*e4b17023SJohn Marino 	  || code == GE_EXPR)
912*e4b17023SJohn Marino 	{
913*e4b17023SJohn Marino           code = swap_tree_comparison (code);
914*e4b17023SJohn Marino 
915*e4b17023SJohn Marino           gimple_cond_set_code (condstmt, code);
916*e4b17023SJohn Marino           gimple_cond_set_lhs (condstmt, op1);
917*e4b17023SJohn Marino           gimple_cond_set_rhs (condstmt, op0);
918*e4b17023SJohn Marino 
919*e4b17023SJohn Marino           update_stmt (condstmt);
920*e4b17023SJohn Marino 	}
921*e4b17023SJohn Marino     }
922*e4b17023SJohn Marino }
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino /* Initialize local stacks for this optimizer and record equivalences
925*e4b17023SJohn Marino    upon entry to BB.  Equivalences can come from the edge traversed to
926*e4b17023SJohn Marino    reach BB or they may come from PHI nodes at the start of BB.  */
927*e4b17023SJohn Marino 
928*e4b17023SJohn Marino /* Remove all the expressions in LOCALS from TABLE, stopping when there are
929*e4b17023SJohn Marino    LIMIT entries left in LOCALs.  */
930*e4b17023SJohn Marino 
931*e4b17023SJohn Marino static void
remove_local_expressions_from_table(void)932*e4b17023SJohn Marino remove_local_expressions_from_table (void)
933*e4b17023SJohn Marino {
934*e4b17023SJohn Marino   /* Remove all the expressions made available in this block.  */
935*e4b17023SJohn Marino   while (VEC_length (expr_hash_elt_t, avail_exprs_stack) > 0)
936*e4b17023SJohn Marino     {
937*e4b17023SJohn Marino       expr_hash_elt_t victim = VEC_pop (expr_hash_elt_t, avail_exprs_stack);
938*e4b17023SJohn Marino       void **slot;
939*e4b17023SJohn Marino 
940*e4b17023SJohn Marino       if (victim == NULL)
941*e4b17023SJohn Marino 	break;
942*e4b17023SJohn Marino 
943*e4b17023SJohn Marino       /* This must precede the actual removal from the hash table,
944*e4b17023SJohn Marino          as ELEMENT and the table entry may share a call argument
945*e4b17023SJohn Marino          vector which will be freed during removal.  */
946*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
947*e4b17023SJohn Marino         {
948*e4b17023SJohn Marino           fprintf (dump_file, "<<<< ");
949*e4b17023SJohn Marino           print_expr_hash_elt (dump_file, victim);
950*e4b17023SJohn Marino         }
951*e4b17023SJohn Marino 
952*e4b17023SJohn Marino       slot = htab_find_slot_with_hash (avail_exprs,
953*e4b17023SJohn Marino 				       victim, victim->hash, NO_INSERT);
954*e4b17023SJohn Marino       gcc_assert (slot && *slot == (void *) victim);
955*e4b17023SJohn Marino       htab_clear_slot (avail_exprs, slot);
956*e4b17023SJohn Marino     }
957*e4b17023SJohn Marino }
958*e4b17023SJohn Marino 
959*e4b17023SJohn Marino /* Use the source/dest pairs in CONST_AND_COPIES_STACK to restore
960*e4b17023SJohn Marino    CONST_AND_COPIES to its original state, stopping when we hit a
961*e4b17023SJohn Marino    NULL marker.  */
962*e4b17023SJohn Marino 
963*e4b17023SJohn Marino static void
restore_vars_to_original_value(void)964*e4b17023SJohn Marino restore_vars_to_original_value (void)
965*e4b17023SJohn Marino {
966*e4b17023SJohn Marino   while (VEC_length (tree, const_and_copies_stack) > 0)
967*e4b17023SJohn Marino     {
968*e4b17023SJohn Marino       tree prev_value, dest;
969*e4b17023SJohn Marino 
970*e4b17023SJohn Marino       dest = VEC_pop (tree, const_and_copies_stack);
971*e4b17023SJohn Marino 
972*e4b17023SJohn Marino       if (dest == NULL)
973*e4b17023SJohn Marino 	break;
974*e4b17023SJohn Marino 
975*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
976*e4b17023SJohn Marino 	{
977*e4b17023SJohn Marino 	  fprintf (dump_file, "<<<< COPY ");
978*e4b17023SJohn Marino 	  print_generic_expr (dump_file, dest, 0);
979*e4b17023SJohn Marino 	  fprintf (dump_file, " = ");
980*e4b17023SJohn Marino 	  print_generic_expr (dump_file, SSA_NAME_VALUE (dest), 0);
981*e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
982*e4b17023SJohn Marino 	}
983*e4b17023SJohn Marino 
984*e4b17023SJohn Marino       prev_value = VEC_pop (tree, const_and_copies_stack);
985*e4b17023SJohn Marino       set_ssa_name_value (dest, prev_value);
986*e4b17023SJohn Marino     }
987*e4b17023SJohn Marino }
988*e4b17023SJohn Marino 
989*e4b17023SJohn Marino /* A trivial wrapper so that we can present the generic jump
990*e4b17023SJohn Marino    threading code with a simple API for simplifying statements.  */
991*e4b17023SJohn Marino static tree
simplify_stmt_for_jump_threading(gimple stmt,gimple within_stmt ATTRIBUTE_UNUSED)992*e4b17023SJohn Marino simplify_stmt_for_jump_threading (gimple stmt,
993*e4b17023SJohn Marino 				  gimple within_stmt ATTRIBUTE_UNUSED)
994*e4b17023SJohn Marino {
995*e4b17023SJohn Marino   return lookup_avail_expr (stmt, false);
996*e4b17023SJohn Marino }
997*e4b17023SJohn Marino 
998*e4b17023SJohn Marino /* Wrapper for common code to attempt to thread an edge.  For example,
999*e4b17023SJohn Marino    it handles lazily building the dummy condition and the bookkeeping
1000*e4b17023SJohn Marino    when jump threading is successful.  */
1001*e4b17023SJohn Marino 
1002*e4b17023SJohn Marino static void
dom_thread_across_edge(struct dom_walk_data * walk_data,edge e)1003*e4b17023SJohn Marino dom_thread_across_edge (struct dom_walk_data *walk_data, edge e)
1004*e4b17023SJohn Marino {
1005*e4b17023SJohn Marino   if (! walk_data->global_data)
1006*e4b17023SJohn Marino   {
1007*e4b17023SJohn Marino     gimple dummy_cond =
1008*e4b17023SJohn Marino         gimple_build_cond (NE_EXPR,
1009*e4b17023SJohn Marino                            integer_zero_node, integer_zero_node,
1010*e4b17023SJohn Marino                            NULL, NULL);
1011*e4b17023SJohn Marino     walk_data->global_data = dummy_cond;
1012*e4b17023SJohn Marino   }
1013*e4b17023SJohn Marino 
1014*e4b17023SJohn Marino   thread_across_edge ((gimple) walk_data->global_data, e, false,
1015*e4b17023SJohn Marino 		      &const_and_copies_stack,
1016*e4b17023SJohn Marino 		      simplify_stmt_for_jump_threading);
1017*e4b17023SJohn Marino }
1018*e4b17023SJohn Marino 
1019*e4b17023SJohn Marino /* PHI nodes can create equivalences too.
1020*e4b17023SJohn Marino 
1021*e4b17023SJohn Marino    Ignoring any alternatives which are the same as the result, if
1022*e4b17023SJohn Marino    all the alternatives are equal, then the PHI node creates an
1023*e4b17023SJohn Marino    equivalence.  */
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino static void
record_equivalences_from_phis(basic_block bb)1026*e4b17023SJohn Marino record_equivalences_from_phis (basic_block bb)
1027*e4b17023SJohn Marino {
1028*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
1029*e4b17023SJohn Marino 
1030*e4b17023SJohn Marino   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1031*e4b17023SJohn Marino     {
1032*e4b17023SJohn Marino       gimple phi = gsi_stmt (gsi);
1033*e4b17023SJohn Marino 
1034*e4b17023SJohn Marino       tree lhs = gimple_phi_result (phi);
1035*e4b17023SJohn Marino       tree rhs = NULL;
1036*e4b17023SJohn Marino       size_t i;
1037*e4b17023SJohn Marino 
1038*e4b17023SJohn Marino       for (i = 0; i < gimple_phi_num_args (phi); i++)
1039*e4b17023SJohn Marino 	{
1040*e4b17023SJohn Marino 	  tree t = gimple_phi_arg_def (phi, i);
1041*e4b17023SJohn Marino 
1042*e4b17023SJohn Marino 	  /* Ignore alternatives which are the same as our LHS.  Since
1043*e4b17023SJohn Marino 	     LHS is a PHI_RESULT, it is known to be a SSA_NAME, so we
1044*e4b17023SJohn Marino 	     can simply compare pointers.  */
1045*e4b17023SJohn Marino 	  if (lhs == t)
1046*e4b17023SJohn Marino 	    continue;
1047*e4b17023SJohn Marino 
1048*e4b17023SJohn Marino 	  /* If we have not processed an alternative yet, then set
1049*e4b17023SJohn Marino 	     RHS to this alternative.  */
1050*e4b17023SJohn Marino 	  if (rhs == NULL)
1051*e4b17023SJohn Marino 	    rhs = t;
1052*e4b17023SJohn Marino 	  /* If we have processed an alternative (stored in RHS), then
1053*e4b17023SJohn Marino 	     see if it is equal to this one.  If it isn't, then stop
1054*e4b17023SJohn Marino 	     the search.  */
1055*e4b17023SJohn Marino 	  else if (! operand_equal_for_phi_arg_p (rhs, t))
1056*e4b17023SJohn Marino 	    break;
1057*e4b17023SJohn Marino 	}
1058*e4b17023SJohn Marino 
1059*e4b17023SJohn Marino       /* If we had no interesting alternatives, then all the RHS alternatives
1060*e4b17023SJohn Marino 	 must have been the same as LHS.  */
1061*e4b17023SJohn Marino       if (!rhs)
1062*e4b17023SJohn Marino 	rhs = lhs;
1063*e4b17023SJohn Marino 
1064*e4b17023SJohn Marino       /* If we managed to iterate through each PHI alternative without
1065*e4b17023SJohn Marino 	 breaking out of the loop, then we have a PHI which may create
1066*e4b17023SJohn Marino 	 a useful equivalence.  We do not need to record unwind data for
1067*e4b17023SJohn Marino 	 this, since this is a true assignment and not an equivalence
1068*e4b17023SJohn Marino 	 inferred from a comparison.  All uses of this ssa name are dominated
1069*e4b17023SJohn Marino 	 by this assignment, so unwinding just costs time and space.  */
1070*e4b17023SJohn Marino       if (i == gimple_phi_num_args (phi) && may_propagate_copy (lhs, rhs))
1071*e4b17023SJohn Marino 	set_ssa_name_value (lhs, rhs);
1072*e4b17023SJohn Marino     }
1073*e4b17023SJohn Marino }
1074*e4b17023SJohn Marino 
1075*e4b17023SJohn Marino /* Ignoring loop backedges, if BB has precisely one incoming edge then
1076*e4b17023SJohn Marino    return that edge.  Otherwise return NULL.  */
1077*e4b17023SJohn Marino static edge
single_incoming_edge_ignoring_loop_edges(basic_block bb)1078*e4b17023SJohn Marino single_incoming_edge_ignoring_loop_edges (basic_block bb)
1079*e4b17023SJohn Marino {
1080*e4b17023SJohn Marino   edge retval = NULL;
1081*e4b17023SJohn Marino   edge e;
1082*e4b17023SJohn Marino   edge_iterator ei;
1083*e4b17023SJohn Marino 
1084*e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->preds)
1085*e4b17023SJohn Marino     {
1086*e4b17023SJohn Marino       /* A loop back edge can be identified by the destination of
1087*e4b17023SJohn Marino 	 the edge dominating the source of the edge.  */
1088*e4b17023SJohn Marino       if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
1089*e4b17023SJohn Marino 	continue;
1090*e4b17023SJohn Marino 
1091*e4b17023SJohn Marino       /* If we have already seen a non-loop edge, then we must have
1092*e4b17023SJohn Marino 	 multiple incoming non-loop edges and thus we return NULL.  */
1093*e4b17023SJohn Marino       if (retval)
1094*e4b17023SJohn Marino 	return NULL;
1095*e4b17023SJohn Marino 
1096*e4b17023SJohn Marino       /* This is the first non-loop incoming edge we have found.  Record
1097*e4b17023SJohn Marino 	 it.  */
1098*e4b17023SJohn Marino       retval = e;
1099*e4b17023SJohn Marino     }
1100*e4b17023SJohn Marino 
1101*e4b17023SJohn Marino   return retval;
1102*e4b17023SJohn Marino }
1103*e4b17023SJohn Marino 
1104*e4b17023SJohn Marino /* Record any equivalences created by the incoming edge to BB.  If BB
1105*e4b17023SJohn Marino    has more than one incoming edge, then no equivalence is created.  */
1106*e4b17023SJohn Marino 
1107*e4b17023SJohn Marino static void
record_equivalences_from_incoming_edge(basic_block bb)1108*e4b17023SJohn Marino record_equivalences_from_incoming_edge (basic_block bb)
1109*e4b17023SJohn Marino {
1110*e4b17023SJohn Marino   edge e;
1111*e4b17023SJohn Marino   basic_block parent;
1112*e4b17023SJohn Marino   struct edge_info *edge_info;
1113*e4b17023SJohn Marino 
1114*e4b17023SJohn Marino   /* If our parent block ended with a control statement, then we may be
1115*e4b17023SJohn Marino      able to record some equivalences based on which outgoing edge from
1116*e4b17023SJohn Marino      the parent was followed.  */
1117*e4b17023SJohn Marino   parent = get_immediate_dominator (CDI_DOMINATORS, bb);
1118*e4b17023SJohn Marino 
1119*e4b17023SJohn Marino   e = single_incoming_edge_ignoring_loop_edges (bb);
1120*e4b17023SJohn Marino 
1121*e4b17023SJohn Marino   /* If we had a single incoming edge from our parent block, then enter
1122*e4b17023SJohn Marino      any data associated with the edge into our tables.  */
1123*e4b17023SJohn Marino   if (e && e->src == parent)
1124*e4b17023SJohn Marino     {
1125*e4b17023SJohn Marino       unsigned int i;
1126*e4b17023SJohn Marino 
1127*e4b17023SJohn Marino       edge_info = (struct edge_info *) e->aux;
1128*e4b17023SJohn Marino 
1129*e4b17023SJohn Marino       if (edge_info)
1130*e4b17023SJohn Marino 	{
1131*e4b17023SJohn Marino 	  tree lhs = edge_info->lhs;
1132*e4b17023SJohn Marino 	  tree rhs = edge_info->rhs;
1133*e4b17023SJohn Marino 	  cond_equivalence *eq;
1134*e4b17023SJohn Marino 
1135*e4b17023SJohn Marino 	  if (lhs)
1136*e4b17023SJohn Marino 	    record_equality (lhs, rhs);
1137*e4b17023SJohn Marino 
1138*e4b17023SJohn Marino 	  for (i = 0; VEC_iterate (cond_equivalence,
1139*e4b17023SJohn Marino 				   edge_info->cond_equivalences, i, eq); ++i)
1140*e4b17023SJohn Marino 	    record_cond (eq);
1141*e4b17023SJohn Marino 	}
1142*e4b17023SJohn Marino     }
1143*e4b17023SJohn Marino }
1144*e4b17023SJohn Marino 
1145*e4b17023SJohn Marino /* Dump SSA statistics on FILE.  */
1146*e4b17023SJohn Marino 
1147*e4b17023SJohn Marino void
dump_dominator_optimization_stats(FILE * file)1148*e4b17023SJohn Marino dump_dominator_optimization_stats (FILE *file)
1149*e4b17023SJohn Marino {
1150*e4b17023SJohn Marino   fprintf (file, "Total number of statements:                   %6ld\n\n",
1151*e4b17023SJohn Marino 	   opt_stats.num_stmts);
1152*e4b17023SJohn Marino   fprintf (file, "Exprs considered for dominator optimizations: %6ld\n",
1153*e4b17023SJohn Marino            opt_stats.num_exprs_considered);
1154*e4b17023SJohn Marino 
1155*e4b17023SJohn Marino   fprintf (file, "\nHash table statistics:\n");
1156*e4b17023SJohn Marino 
1157*e4b17023SJohn Marino   fprintf (file, "    avail_exprs: ");
1158*e4b17023SJohn Marino   htab_statistics (file, avail_exprs);
1159*e4b17023SJohn Marino }
1160*e4b17023SJohn Marino 
1161*e4b17023SJohn Marino 
1162*e4b17023SJohn Marino /* Dump SSA statistics on stderr.  */
1163*e4b17023SJohn Marino 
1164*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_dominator_optimization_stats(void)1165*e4b17023SJohn Marino debug_dominator_optimization_stats (void)
1166*e4b17023SJohn Marino {
1167*e4b17023SJohn Marino   dump_dominator_optimization_stats (stderr);
1168*e4b17023SJohn Marino }
1169*e4b17023SJohn Marino 
1170*e4b17023SJohn Marino 
1171*e4b17023SJohn Marino /* Dump statistics for the hash table HTAB.  */
1172*e4b17023SJohn Marino 
1173*e4b17023SJohn Marino static void
htab_statistics(FILE * file,htab_t htab)1174*e4b17023SJohn Marino htab_statistics (FILE *file, htab_t htab)
1175*e4b17023SJohn Marino {
1176*e4b17023SJohn Marino   fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n",
1177*e4b17023SJohn Marino 	   (long) htab_size (htab),
1178*e4b17023SJohn Marino 	   (long) htab_elements (htab),
1179*e4b17023SJohn Marino 	   htab_collisions (htab));
1180*e4b17023SJohn Marino }
1181*e4b17023SJohn Marino 
1182*e4b17023SJohn Marino 
1183*e4b17023SJohn Marino /* Enter condition equivalence into the expression hash table.
1184*e4b17023SJohn Marino    This indicates that a conditional expression has a known
1185*e4b17023SJohn Marino    boolean value.  */
1186*e4b17023SJohn Marino 
1187*e4b17023SJohn Marino static void
record_cond(cond_equivalence * p)1188*e4b17023SJohn Marino record_cond (cond_equivalence *p)
1189*e4b17023SJohn Marino {
1190*e4b17023SJohn Marino   struct expr_hash_elt *element = XCNEW (struct expr_hash_elt);
1191*e4b17023SJohn Marino   void **slot;
1192*e4b17023SJohn Marino 
1193*e4b17023SJohn Marino   initialize_hash_element_from_expr (&p->cond, p->value, element);
1194*e4b17023SJohn Marino 
1195*e4b17023SJohn Marino   slot = htab_find_slot_with_hash (avail_exprs, (void *)element,
1196*e4b17023SJohn Marino 				   element->hash, INSERT);
1197*e4b17023SJohn Marino   if (*slot == NULL)
1198*e4b17023SJohn Marino     {
1199*e4b17023SJohn Marino       *slot = (void *) element;
1200*e4b17023SJohn Marino 
1201*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1202*e4b17023SJohn Marino         {
1203*e4b17023SJohn Marino           fprintf (dump_file, "1>>> ");
1204*e4b17023SJohn Marino           print_expr_hash_elt (dump_file, element);
1205*e4b17023SJohn Marino         }
1206*e4b17023SJohn Marino 
1207*e4b17023SJohn Marino       VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, element);
1208*e4b17023SJohn Marino     }
1209*e4b17023SJohn Marino   else
1210*e4b17023SJohn Marino     free (element);
1211*e4b17023SJohn Marino }
1212*e4b17023SJohn Marino 
1213*e4b17023SJohn Marino /* Build a cond_equivalence record indicating that the comparison
1214*e4b17023SJohn Marino    CODE holds between operands OP0 and OP1 and push it to **P.  */
1215*e4b17023SJohn Marino 
1216*e4b17023SJohn Marino static void
build_and_record_new_cond(enum tree_code code,tree op0,tree op1,VEC (cond_equivalence,heap)** p)1217*e4b17023SJohn Marino build_and_record_new_cond (enum tree_code code,
1218*e4b17023SJohn Marino                            tree op0, tree op1,
1219*e4b17023SJohn Marino                            VEC(cond_equivalence, heap) **p)
1220*e4b17023SJohn Marino {
1221*e4b17023SJohn Marino   cond_equivalence c;
1222*e4b17023SJohn Marino   struct hashable_expr *cond = &c.cond;
1223*e4b17023SJohn Marino 
1224*e4b17023SJohn Marino   gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison);
1225*e4b17023SJohn Marino 
1226*e4b17023SJohn Marino   cond->type = boolean_type_node;
1227*e4b17023SJohn Marino   cond->kind = EXPR_BINARY;
1228*e4b17023SJohn Marino   cond->ops.binary.op = code;
1229*e4b17023SJohn Marino   cond->ops.binary.opnd0 = op0;
1230*e4b17023SJohn Marino   cond->ops.binary.opnd1 = op1;
1231*e4b17023SJohn Marino 
1232*e4b17023SJohn Marino   c.value = boolean_true_node;
1233*e4b17023SJohn Marino   VEC_safe_push (cond_equivalence, heap, *p, &c);
1234*e4b17023SJohn Marino }
1235*e4b17023SJohn Marino 
1236*e4b17023SJohn Marino /* Record that COND is true and INVERTED is false into the edge information
1237*e4b17023SJohn Marino    structure.  Also record that any conditions dominated by COND are true
1238*e4b17023SJohn Marino    as well.
1239*e4b17023SJohn Marino 
1240*e4b17023SJohn Marino    For example, if a < b is true, then a <= b must also be true.  */
1241*e4b17023SJohn Marino 
1242*e4b17023SJohn Marino static void
record_conditions(struct edge_info * edge_info,tree cond,tree inverted)1243*e4b17023SJohn Marino record_conditions (struct edge_info *edge_info, tree cond, tree inverted)
1244*e4b17023SJohn Marino {
1245*e4b17023SJohn Marino   tree op0, op1;
1246*e4b17023SJohn Marino   cond_equivalence c;
1247*e4b17023SJohn Marino 
1248*e4b17023SJohn Marino   if (!COMPARISON_CLASS_P (cond))
1249*e4b17023SJohn Marino     return;
1250*e4b17023SJohn Marino 
1251*e4b17023SJohn Marino   op0 = TREE_OPERAND (cond, 0);
1252*e4b17023SJohn Marino   op1 = TREE_OPERAND (cond, 1);
1253*e4b17023SJohn Marino 
1254*e4b17023SJohn Marino   switch (TREE_CODE (cond))
1255*e4b17023SJohn Marino     {
1256*e4b17023SJohn Marino     case LT_EXPR:
1257*e4b17023SJohn Marino     case GT_EXPR:
1258*e4b17023SJohn Marino       if (FLOAT_TYPE_P (TREE_TYPE (op0)))
1259*e4b17023SJohn Marino 	{
1260*e4b17023SJohn Marino 	  build_and_record_new_cond (ORDERED_EXPR, op0, op1,
1261*e4b17023SJohn Marino 				     &edge_info->cond_equivalences);
1262*e4b17023SJohn Marino 	  build_and_record_new_cond (LTGT_EXPR, op0, op1,
1263*e4b17023SJohn Marino 				     &edge_info->cond_equivalences);
1264*e4b17023SJohn Marino 	}
1265*e4b17023SJohn Marino 
1266*e4b17023SJohn Marino       build_and_record_new_cond ((TREE_CODE (cond) == LT_EXPR
1267*e4b17023SJohn Marino 				  ? LE_EXPR : GE_EXPR),
1268*e4b17023SJohn Marino 				 op0, op1, &edge_info->cond_equivalences);
1269*e4b17023SJohn Marino       build_and_record_new_cond (NE_EXPR, op0, op1,
1270*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1271*e4b17023SJohn Marino       break;
1272*e4b17023SJohn Marino 
1273*e4b17023SJohn Marino     case GE_EXPR:
1274*e4b17023SJohn Marino     case LE_EXPR:
1275*e4b17023SJohn Marino       if (FLOAT_TYPE_P (TREE_TYPE (op0)))
1276*e4b17023SJohn Marino 	{
1277*e4b17023SJohn Marino 	  build_and_record_new_cond (ORDERED_EXPR, op0, op1,
1278*e4b17023SJohn Marino 				     &edge_info->cond_equivalences);
1279*e4b17023SJohn Marino 	}
1280*e4b17023SJohn Marino       break;
1281*e4b17023SJohn Marino 
1282*e4b17023SJohn Marino     case EQ_EXPR:
1283*e4b17023SJohn Marino       if (FLOAT_TYPE_P (TREE_TYPE (op0)))
1284*e4b17023SJohn Marino 	{
1285*e4b17023SJohn Marino 	  build_and_record_new_cond (ORDERED_EXPR, op0, op1,
1286*e4b17023SJohn Marino 				     &edge_info->cond_equivalences);
1287*e4b17023SJohn Marino 	}
1288*e4b17023SJohn Marino       build_and_record_new_cond (LE_EXPR, op0, op1,
1289*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1290*e4b17023SJohn Marino       build_and_record_new_cond (GE_EXPR, op0, op1,
1291*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1292*e4b17023SJohn Marino       break;
1293*e4b17023SJohn Marino 
1294*e4b17023SJohn Marino     case UNORDERED_EXPR:
1295*e4b17023SJohn Marino       build_and_record_new_cond (NE_EXPR, op0, op1,
1296*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1297*e4b17023SJohn Marino       build_and_record_new_cond (UNLE_EXPR, op0, op1,
1298*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1299*e4b17023SJohn Marino       build_and_record_new_cond (UNGE_EXPR, op0, op1,
1300*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1301*e4b17023SJohn Marino       build_and_record_new_cond (UNEQ_EXPR, op0, op1,
1302*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1303*e4b17023SJohn Marino       build_and_record_new_cond (UNLT_EXPR, op0, op1,
1304*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1305*e4b17023SJohn Marino       build_and_record_new_cond (UNGT_EXPR, op0, op1,
1306*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1307*e4b17023SJohn Marino       break;
1308*e4b17023SJohn Marino 
1309*e4b17023SJohn Marino     case UNLT_EXPR:
1310*e4b17023SJohn Marino     case UNGT_EXPR:
1311*e4b17023SJohn Marino       build_and_record_new_cond ((TREE_CODE (cond) == UNLT_EXPR
1312*e4b17023SJohn Marino 				  ? UNLE_EXPR : UNGE_EXPR),
1313*e4b17023SJohn Marino 				 op0, op1, &edge_info->cond_equivalences);
1314*e4b17023SJohn Marino       build_and_record_new_cond (NE_EXPR, op0, op1,
1315*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1316*e4b17023SJohn Marino       break;
1317*e4b17023SJohn Marino 
1318*e4b17023SJohn Marino     case UNEQ_EXPR:
1319*e4b17023SJohn Marino       build_and_record_new_cond (UNLE_EXPR, op0, op1,
1320*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1321*e4b17023SJohn Marino       build_and_record_new_cond (UNGE_EXPR, op0, op1,
1322*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1323*e4b17023SJohn Marino       break;
1324*e4b17023SJohn Marino 
1325*e4b17023SJohn Marino     case LTGT_EXPR:
1326*e4b17023SJohn Marino       build_and_record_new_cond (NE_EXPR, op0, op1,
1327*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1328*e4b17023SJohn Marino       build_and_record_new_cond (ORDERED_EXPR, op0, op1,
1329*e4b17023SJohn Marino 				 &edge_info->cond_equivalences);
1330*e4b17023SJohn Marino       break;
1331*e4b17023SJohn Marino 
1332*e4b17023SJohn Marino     default:
1333*e4b17023SJohn Marino       break;
1334*e4b17023SJohn Marino     }
1335*e4b17023SJohn Marino 
1336*e4b17023SJohn Marino   /* Now store the original true and false conditions into the first
1337*e4b17023SJohn Marino      two slots.  */
1338*e4b17023SJohn Marino   initialize_expr_from_cond (cond, &c.cond);
1339*e4b17023SJohn Marino   c.value = boolean_true_node;
1340*e4b17023SJohn Marino   VEC_safe_push (cond_equivalence, heap, edge_info->cond_equivalences, &c);
1341*e4b17023SJohn Marino 
1342*e4b17023SJohn Marino   /* It is possible for INVERTED to be the negation of a comparison,
1343*e4b17023SJohn Marino      and not a valid RHS or GIMPLE_COND condition.  This happens because
1344*e4b17023SJohn Marino      invert_truthvalue may return such an expression when asked to invert
1345*e4b17023SJohn Marino      a floating-point comparison.  These comparisons are not assumed to
1346*e4b17023SJohn Marino      obey the trichotomy law.  */
1347*e4b17023SJohn Marino   initialize_expr_from_cond (inverted, &c.cond);
1348*e4b17023SJohn Marino   c.value = boolean_false_node;
1349*e4b17023SJohn Marino   VEC_safe_push (cond_equivalence, heap, edge_info->cond_equivalences, &c);
1350*e4b17023SJohn Marino }
1351*e4b17023SJohn Marino 
1352*e4b17023SJohn Marino /* A helper function for record_const_or_copy and record_equality.
1353*e4b17023SJohn Marino    Do the work of recording the value and undo info.  */
1354*e4b17023SJohn Marino 
1355*e4b17023SJohn Marino static void
record_const_or_copy_1(tree x,tree y,tree prev_x)1356*e4b17023SJohn Marino record_const_or_copy_1 (tree x, tree y, tree prev_x)
1357*e4b17023SJohn Marino {
1358*e4b17023SJohn Marino   set_ssa_name_value (x, y);
1359*e4b17023SJohn Marino 
1360*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1361*e4b17023SJohn Marino     {
1362*e4b17023SJohn Marino       fprintf (dump_file, "0>>> COPY ");
1363*e4b17023SJohn Marino       print_generic_expr (dump_file, x, 0);
1364*e4b17023SJohn Marino       fprintf (dump_file, " = ");
1365*e4b17023SJohn Marino       print_generic_expr (dump_file, y, 0);
1366*e4b17023SJohn Marino       fprintf (dump_file, "\n");
1367*e4b17023SJohn Marino     }
1368*e4b17023SJohn Marino 
1369*e4b17023SJohn Marino   VEC_reserve (tree, heap, const_and_copies_stack, 2);
1370*e4b17023SJohn Marino   VEC_quick_push (tree, const_and_copies_stack, prev_x);
1371*e4b17023SJohn Marino   VEC_quick_push (tree, const_and_copies_stack, x);
1372*e4b17023SJohn Marino }
1373*e4b17023SJohn Marino 
1374*e4b17023SJohn Marino /* Return the loop depth of the basic block of the defining statement of X.
1375*e4b17023SJohn Marino    This number should not be treated as absolutely correct because the loop
1376*e4b17023SJohn Marino    information may not be completely up-to-date when dom runs.  However, it
1377*e4b17023SJohn Marino    will be relatively correct, and as more passes are taught to keep loop info
1378*e4b17023SJohn Marino    up to date, the result will become more and more accurate.  */
1379*e4b17023SJohn Marino 
1380*e4b17023SJohn Marino int
loop_depth_of_name(tree x)1381*e4b17023SJohn Marino loop_depth_of_name (tree x)
1382*e4b17023SJohn Marino {
1383*e4b17023SJohn Marino   gimple defstmt;
1384*e4b17023SJohn Marino   basic_block defbb;
1385*e4b17023SJohn Marino 
1386*e4b17023SJohn Marino   /* If it's not an SSA_NAME, we have no clue where the definition is.  */
1387*e4b17023SJohn Marino   if (TREE_CODE (x) != SSA_NAME)
1388*e4b17023SJohn Marino     return 0;
1389*e4b17023SJohn Marino 
1390*e4b17023SJohn Marino   /* Otherwise return the loop depth of the defining statement's bb.
1391*e4b17023SJohn Marino      Note that there may not actually be a bb for this statement, if the
1392*e4b17023SJohn Marino      ssa_name is live on entry.  */
1393*e4b17023SJohn Marino   defstmt = SSA_NAME_DEF_STMT (x);
1394*e4b17023SJohn Marino   defbb = gimple_bb (defstmt);
1395*e4b17023SJohn Marino   if (!defbb)
1396*e4b17023SJohn Marino     return 0;
1397*e4b17023SJohn Marino 
1398*e4b17023SJohn Marino   return defbb->loop_depth;
1399*e4b17023SJohn Marino }
1400*e4b17023SJohn Marino 
1401*e4b17023SJohn Marino /* Record that X is equal to Y in const_and_copies.  Record undo
1402*e4b17023SJohn Marino    information in the block-local vector.  */
1403*e4b17023SJohn Marino 
1404*e4b17023SJohn Marino static void
record_const_or_copy(tree x,tree y)1405*e4b17023SJohn Marino record_const_or_copy (tree x, tree y)
1406*e4b17023SJohn Marino {
1407*e4b17023SJohn Marino   tree prev_x = SSA_NAME_VALUE (x);
1408*e4b17023SJohn Marino 
1409*e4b17023SJohn Marino   gcc_assert (TREE_CODE (x) == SSA_NAME);
1410*e4b17023SJohn Marino 
1411*e4b17023SJohn Marino   if (TREE_CODE (y) == SSA_NAME)
1412*e4b17023SJohn Marino     {
1413*e4b17023SJohn Marino       tree tmp = SSA_NAME_VALUE (y);
1414*e4b17023SJohn Marino       if (tmp)
1415*e4b17023SJohn Marino 	y = tmp;
1416*e4b17023SJohn Marino     }
1417*e4b17023SJohn Marino 
1418*e4b17023SJohn Marino   record_const_or_copy_1 (x, y, prev_x);
1419*e4b17023SJohn Marino }
1420*e4b17023SJohn Marino 
1421*e4b17023SJohn Marino /* Similarly, but assume that X and Y are the two operands of an EQ_EXPR.
1422*e4b17023SJohn Marino    This constrains the cases in which we may treat this as assignment.  */
1423*e4b17023SJohn Marino 
1424*e4b17023SJohn Marino static void
record_equality(tree x,tree y)1425*e4b17023SJohn Marino record_equality (tree x, tree y)
1426*e4b17023SJohn Marino {
1427*e4b17023SJohn Marino   tree prev_x = NULL, prev_y = NULL;
1428*e4b17023SJohn Marino 
1429*e4b17023SJohn Marino   if (TREE_CODE (x) == SSA_NAME)
1430*e4b17023SJohn Marino     prev_x = SSA_NAME_VALUE (x);
1431*e4b17023SJohn Marino   if (TREE_CODE (y) == SSA_NAME)
1432*e4b17023SJohn Marino     prev_y = SSA_NAME_VALUE (y);
1433*e4b17023SJohn Marino 
1434*e4b17023SJohn Marino   /* If one of the previous values is invariant, or invariant in more loops
1435*e4b17023SJohn Marino      (by depth), then use that.
1436*e4b17023SJohn Marino      Otherwise it doesn't matter which value we choose, just so
1437*e4b17023SJohn Marino      long as we canonicalize on one value.  */
1438*e4b17023SJohn Marino   if (is_gimple_min_invariant (y))
1439*e4b17023SJohn Marino     ;
1440*e4b17023SJohn Marino   else if (is_gimple_min_invariant (x)
1441*e4b17023SJohn Marino 	   || (loop_depth_of_name (x) <= loop_depth_of_name (y)))
1442*e4b17023SJohn Marino     prev_x = x, x = y, y = prev_x, prev_x = prev_y;
1443*e4b17023SJohn Marino   else if (prev_x && is_gimple_min_invariant (prev_x))
1444*e4b17023SJohn Marino     x = y, y = prev_x, prev_x = prev_y;
1445*e4b17023SJohn Marino   else if (prev_y)
1446*e4b17023SJohn Marino     y = prev_y;
1447*e4b17023SJohn Marino 
1448*e4b17023SJohn Marino   /* After the swapping, we must have one SSA_NAME.  */
1449*e4b17023SJohn Marino   if (TREE_CODE (x) != SSA_NAME)
1450*e4b17023SJohn Marino     return;
1451*e4b17023SJohn Marino 
1452*e4b17023SJohn Marino   /* For IEEE, -0.0 == 0.0, so we don't necessarily know the sign of a
1453*e4b17023SJohn Marino      variable compared against zero.  If we're honoring signed zeros,
1454*e4b17023SJohn Marino      then we cannot record this value unless we know that the value is
1455*e4b17023SJohn Marino      nonzero.  */
1456*e4b17023SJohn Marino   if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (x)))
1457*e4b17023SJohn Marino       && (TREE_CODE (y) != REAL_CST
1458*e4b17023SJohn Marino 	  || REAL_VALUES_EQUAL (dconst0, TREE_REAL_CST (y))))
1459*e4b17023SJohn Marino     return;
1460*e4b17023SJohn Marino 
1461*e4b17023SJohn Marino   record_const_or_copy_1 (x, y, prev_x);
1462*e4b17023SJohn Marino }
1463*e4b17023SJohn Marino 
1464*e4b17023SJohn Marino /* Returns true when STMT is a simple iv increment.  It detects the
1465*e4b17023SJohn Marino    following situation:
1466*e4b17023SJohn Marino 
1467*e4b17023SJohn Marino    i_1 = phi (..., i_2)
1468*e4b17023SJohn Marino    i_2 = i_1 +/- ...  */
1469*e4b17023SJohn Marino 
1470*e4b17023SJohn Marino bool
simple_iv_increment_p(gimple stmt)1471*e4b17023SJohn Marino simple_iv_increment_p (gimple stmt)
1472*e4b17023SJohn Marino {
1473*e4b17023SJohn Marino   enum tree_code code;
1474*e4b17023SJohn Marino   tree lhs, preinc;
1475*e4b17023SJohn Marino   gimple phi;
1476*e4b17023SJohn Marino   size_t i;
1477*e4b17023SJohn Marino 
1478*e4b17023SJohn Marino   if (gimple_code (stmt) != GIMPLE_ASSIGN)
1479*e4b17023SJohn Marino     return false;
1480*e4b17023SJohn Marino 
1481*e4b17023SJohn Marino   lhs = gimple_assign_lhs (stmt);
1482*e4b17023SJohn Marino   if (TREE_CODE (lhs) != SSA_NAME)
1483*e4b17023SJohn Marino     return false;
1484*e4b17023SJohn Marino 
1485*e4b17023SJohn Marino   code = gimple_assign_rhs_code (stmt);
1486*e4b17023SJohn Marino   if (code != PLUS_EXPR
1487*e4b17023SJohn Marino       && code != MINUS_EXPR
1488*e4b17023SJohn Marino       && code != POINTER_PLUS_EXPR)
1489*e4b17023SJohn Marino     return false;
1490*e4b17023SJohn Marino 
1491*e4b17023SJohn Marino   preinc = gimple_assign_rhs1 (stmt);
1492*e4b17023SJohn Marino   if (TREE_CODE (preinc) != SSA_NAME)
1493*e4b17023SJohn Marino     return false;
1494*e4b17023SJohn Marino 
1495*e4b17023SJohn Marino   phi = SSA_NAME_DEF_STMT (preinc);
1496*e4b17023SJohn Marino   if (gimple_code (phi) != GIMPLE_PHI)
1497*e4b17023SJohn Marino     return false;
1498*e4b17023SJohn Marino 
1499*e4b17023SJohn Marino   for (i = 0; i < gimple_phi_num_args (phi); i++)
1500*e4b17023SJohn Marino     if (gimple_phi_arg_def (phi, i) == lhs)
1501*e4b17023SJohn Marino       return true;
1502*e4b17023SJohn Marino 
1503*e4b17023SJohn Marino   return false;
1504*e4b17023SJohn Marino }
1505*e4b17023SJohn Marino 
1506*e4b17023SJohn Marino /* CONST_AND_COPIES is a table which maps an SSA_NAME to the current
1507*e4b17023SJohn Marino    known value for that SSA_NAME (or NULL if no value is known).
1508*e4b17023SJohn Marino 
1509*e4b17023SJohn Marino    Propagate values from CONST_AND_COPIES into the PHI nodes of the
1510*e4b17023SJohn Marino    successors of BB.  */
1511*e4b17023SJohn Marino 
1512*e4b17023SJohn Marino static void
cprop_into_successor_phis(basic_block bb)1513*e4b17023SJohn Marino cprop_into_successor_phis (basic_block bb)
1514*e4b17023SJohn Marino {
1515*e4b17023SJohn Marino   edge e;
1516*e4b17023SJohn Marino   edge_iterator ei;
1517*e4b17023SJohn Marino 
1518*e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->succs)
1519*e4b17023SJohn Marino     {
1520*e4b17023SJohn Marino       int indx;
1521*e4b17023SJohn Marino       gimple_stmt_iterator gsi;
1522*e4b17023SJohn Marino 
1523*e4b17023SJohn Marino       /* If this is an abnormal edge, then we do not want to copy propagate
1524*e4b17023SJohn Marino 	 into the PHI alternative associated with this edge.  */
1525*e4b17023SJohn Marino       if (e->flags & EDGE_ABNORMAL)
1526*e4b17023SJohn Marino 	continue;
1527*e4b17023SJohn Marino 
1528*e4b17023SJohn Marino       gsi = gsi_start_phis (e->dest);
1529*e4b17023SJohn Marino       if (gsi_end_p (gsi))
1530*e4b17023SJohn Marino 	continue;
1531*e4b17023SJohn Marino 
1532*e4b17023SJohn Marino       indx = e->dest_idx;
1533*e4b17023SJohn Marino       for ( ; !gsi_end_p (gsi); gsi_next (&gsi))
1534*e4b17023SJohn Marino 	{
1535*e4b17023SJohn Marino 	  tree new_val;
1536*e4b17023SJohn Marino 	  use_operand_p orig_p;
1537*e4b17023SJohn Marino 	  tree orig_val;
1538*e4b17023SJohn Marino           gimple phi = gsi_stmt (gsi);
1539*e4b17023SJohn Marino 
1540*e4b17023SJohn Marino 	  /* The alternative may be associated with a constant, so verify
1541*e4b17023SJohn Marino 	     it is an SSA_NAME before doing anything with it.  */
1542*e4b17023SJohn Marino 	  orig_p = gimple_phi_arg_imm_use_ptr (phi, indx);
1543*e4b17023SJohn Marino 	  orig_val = get_use_from_ptr (orig_p);
1544*e4b17023SJohn Marino 	  if (TREE_CODE (orig_val) != SSA_NAME)
1545*e4b17023SJohn Marino 	    continue;
1546*e4b17023SJohn Marino 
1547*e4b17023SJohn Marino 	  /* If we have *ORIG_P in our constant/copy table, then replace
1548*e4b17023SJohn Marino 	     ORIG_P with its value in our constant/copy table.  */
1549*e4b17023SJohn Marino 	  new_val = SSA_NAME_VALUE (orig_val);
1550*e4b17023SJohn Marino 	  if (new_val
1551*e4b17023SJohn Marino 	      && new_val != orig_val
1552*e4b17023SJohn Marino 	      && (TREE_CODE (new_val) == SSA_NAME
1553*e4b17023SJohn Marino 		  || is_gimple_min_invariant (new_val))
1554*e4b17023SJohn Marino 	      && may_propagate_copy (orig_val, new_val))
1555*e4b17023SJohn Marino 	    propagate_value (orig_p, new_val);
1556*e4b17023SJohn Marino 	}
1557*e4b17023SJohn Marino     }
1558*e4b17023SJohn Marino }
1559*e4b17023SJohn Marino 
1560*e4b17023SJohn Marino /* We have finished optimizing BB, record any information implied by
1561*e4b17023SJohn Marino    taking a specific outgoing edge from BB.  */
1562*e4b17023SJohn Marino 
1563*e4b17023SJohn Marino static void
record_edge_info(basic_block bb)1564*e4b17023SJohn Marino record_edge_info (basic_block bb)
1565*e4b17023SJohn Marino {
1566*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_last_bb (bb);
1567*e4b17023SJohn Marino   struct edge_info *edge_info;
1568*e4b17023SJohn Marino 
1569*e4b17023SJohn Marino   if (! gsi_end_p (gsi))
1570*e4b17023SJohn Marino     {
1571*e4b17023SJohn Marino       gimple stmt = gsi_stmt (gsi);
1572*e4b17023SJohn Marino       location_t loc = gimple_location (stmt);
1573*e4b17023SJohn Marino 
1574*e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_SWITCH)
1575*e4b17023SJohn Marino 	{
1576*e4b17023SJohn Marino 	  tree index = gimple_switch_index (stmt);
1577*e4b17023SJohn Marino 
1578*e4b17023SJohn Marino 	  if (TREE_CODE (index) == SSA_NAME)
1579*e4b17023SJohn Marino 	    {
1580*e4b17023SJohn Marino 	      int i;
1581*e4b17023SJohn Marino               int n_labels = gimple_switch_num_labels (stmt);
1582*e4b17023SJohn Marino 	      tree *info = XCNEWVEC (tree, last_basic_block);
1583*e4b17023SJohn Marino 	      edge e;
1584*e4b17023SJohn Marino 	      edge_iterator ei;
1585*e4b17023SJohn Marino 
1586*e4b17023SJohn Marino 	      for (i = 0; i < n_labels; i++)
1587*e4b17023SJohn Marino 		{
1588*e4b17023SJohn Marino 		  tree label = gimple_switch_label (stmt, i);
1589*e4b17023SJohn Marino 		  basic_block target_bb = label_to_block (CASE_LABEL (label));
1590*e4b17023SJohn Marino 		  if (CASE_HIGH (label)
1591*e4b17023SJohn Marino 		      || !CASE_LOW (label)
1592*e4b17023SJohn Marino 		      || info[target_bb->index])
1593*e4b17023SJohn Marino 		    info[target_bb->index] = error_mark_node;
1594*e4b17023SJohn Marino 		  else
1595*e4b17023SJohn Marino 		    info[target_bb->index] = label;
1596*e4b17023SJohn Marino 		}
1597*e4b17023SJohn Marino 
1598*e4b17023SJohn Marino 	      FOR_EACH_EDGE (e, ei, bb->succs)
1599*e4b17023SJohn Marino 		{
1600*e4b17023SJohn Marino 		  basic_block target_bb = e->dest;
1601*e4b17023SJohn Marino 		  tree label = info[target_bb->index];
1602*e4b17023SJohn Marino 
1603*e4b17023SJohn Marino 		  if (label != NULL && label != error_mark_node)
1604*e4b17023SJohn Marino 		    {
1605*e4b17023SJohn Marino 		      tree x = fold_convert_loc (loc, TREE_TYPE (index),
1606*e4b17023SJohn Marino 						 CASE_LOW (label));
1607*e4b17023SJohn Marino 		      edge_info = allocate_edge_info (e);
1608*e4b17023SJohn Marino 		      edge_info->lhs = index;
1609*e4b17023SJohn Marino 		      edge_info->rhs = x;
1610*e4b17023SJohn Marino 		    }
1611*e4b17023SJohn Marino 		}
1612*e4b17023SJohn Marino 	      free (info);
1613*e4b17023SJohn Marino 	    }
1614*e4b17023SJohn Marino 	}
1615*e4b17023SJohn Marino 
1616*e4b17023SJohn Marino       /* A COND_EXPR may create equivalences too.  */
1617*e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_COND)
1618*e4b17023SJohn Marino 	{
1619*e4b17023SJohn Marino 	  edge true_edge;
1620*e4b17023SJohn Marino 	  edge false_edge;
1621*e4b17023SJohn Marino 
1622*e4b17023SJohn Marino           tree op0 = gimple_cond_lhs (stmt);
1623*e4b17023SJohn Marino           tree op1 = gimple_cond_rhs (stmt);
1624*e4b17023SJohn Marino           enum tree_code code = gimple_cond_code (stmt);
1625*e4b17023SJohn Marino 
1626*e4b17023SJohn Marino 	  extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
1627*e4b17023SJohn Marino 
1628*e4b17023SJohn Marino           /* Special case comparing booleans against a constant as we
1629*e4b17023SJohn Marino              know the value of OP0 on both arms of the branch.  i.e., we
1630*e4b17023SJohn Marino              can record an equivalence for OP0 rather than COND.  */
1631*e4b17023SJohn Marino           if ((code == EQ_EXPR || code == NE_EXPR)
1632*e4b17023SJohn Marino               && TREE_CODE (op0) == SSA_NAME
1633*e4b17023SJohn Marino               && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
1634*e4b17023SJohn Marino               && is_gimple_min_invariant (op1))
1635*e4b17023SJohn Marino             {
1636*e4b17023SJohn Marino               if (code == EQ_EXPR)
1637*e4b17023SJohn Marino                 {
1638*e4b17023SJohn Marino                   edge_info = allocate_edge_info (true_edge);
1639*e4b17023SJohn Marino                   edge_info->lhs = op0;
1640*e4b17023SJohn Marino                   edge_info->rhs = (integer_zerop (op1)
1641*e4b17023SJohn Marino                                     ? boolean_false_node
1642*e4b17023SJohn Marino                                     : boolean_true_node);
1643*e4b17023SJohn Marino 
1644*e4b17023SJohn Marino                   edge_info = allocate_edge_info (false_edge);
1645*e4b17023SJohn Marino                   edge_info->lhs = op0;
1646*e4b17023SJohn Marino                   edge_info->rhs = (integer_zerop (op1)
1647*e4b17023SJohn Marino                                     ? boolean_true_node
1648*e4b17023SJohn Marino                                     : boolean_false_node);
1649*e4b17023SJohn Marino                 }
1650*e4b17023SJohn Marino               else
1651*e4b17023SJohn Marino                 {
1652*e4b17023SJohn Marino                   edge_info = allocate_edge_info (true_edge);
1653*e4b17023SJohn Marino                   edge_info->lhs = op0;
1654*e4b17023SJohn Marino                   edge_info->rhs = (integer_zerop (op1)
1655*e4b17023SJohn Marino                                     ? boolean_true_node
1656*e4b17023SJohn Marino                                     : boolean_false_node);
1657*e4b17023SJohn Marino 
1658*e4b17023SJohn Marino                   edge_info = allocate_edge_info (false_edge);
1659*e4b17023SJohn Marino                   edge_info->lhs = op0;
1660*e4b17023SJohn Marino                   edge_info->rhs = (integer_zerop (op1)
1661*e4b17023SJohn Marino                                     ? boolean_false_node
1662*e4b17023SJohn Marino                                     : boolean_true_node);
1663*e4b17023SJohn Marino                 }
1664*e4b17023SJohn Marino             }
1665*e4b17023SJohn Marino           else if (is_gimple_min_invariant (op0)
1666*e4b17023SJohn Marino                    && (TREE_CODE (op1) == SSA_NAME
1667*e4b17023SJohn Marino                        || is_gimple_min_invariant (op1)))
1668*e4b17023SJohn Marino             {
1669*e4b17023SJohn Marino               tree cond = build2 (code, boolean_type_node, op0, op1);
1670*e4b17023SJohn Marino               tree inverted = invert_truthvalue_loc (loc, cond);
1671*e4b17023SJohn Marino               bool can_infer_simple_equiv
1672*e4b17023SJohn Marino                 = !(HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0)))
1673*e4b17023SJohn Marino                     && real_zerop (op0));
1674*e4b17023SJohn Marino               struct edge_info *edge_info;
1675*e4b17023SJohn Marino 
1676*e4b17023SJohn Marino               edge_info = allocate_edge_info (true_edge);
1677*e4b17023SJohn Marino               record_conditions (edge_info, cond, inverted);
1678*e4b17023SJohn Marino 
1679*e4b17023SJohn Marino               if (can_infer_simple_equiv && code == EQ_EXPR)
1680*e4b17023SJohn Marino                 {
1681*e4b17023SJohn Marino                   edge_info->lhs = op1;
1682*e4b17023SJohn Marino                   edge_info->rhs = op0;
1683*e4b17023SJohn Marino                 }
1684*e4b17023SJohn Marino 
1685*e4b17023SJohn Marino               edge_info = allocate_edge_info (false_edge);
1686*e4b17023SJohn Marino               record_conditions (edge_info, inverted, cond);
1687*e4b17023SJohn Marino 
1688*e4b17023SJohn Marino               if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
1689*e4b17023SJohn Marino                 {
1690*e4b17023SJohn Marino                   edge_info->lhs = op1;
1691*e4b17023SJohn Marino                   edge_info->rhs = op0;
1692*e4b17023SJohn Marino                 }
1693*e4b17023SJohn Marino             }
1694*e4b17023SJohn Marino 
1695*e4b17023SJohn Marino           else if (TREE_CODE (op0) == SSA_NAME
1696*e4b17023SJohn Marino                    && (TREE_CODE (op1) == SSA_NAME
1697*e4b17023SJohn Marino                        || is_gimple_min_invariant (op1)))
1698*e4b17023SJohn Marino             {
1699*e4b17023SJohn Marino               tree cond = build2 (code, boolean_type_node, op0, op1);
1700*e4b17023SJohn Marino               tree inverted = invert_truthvalue_loc (loc, cond);
1701*e4b17023SJohn Marino               bool can_infer_simple_equiv
1702*e4b17023SJohn Marino                 = !(HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op1)))
1703*e4b17023SJohn Marino                     && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1)));
1704*e4b17023SJohn Marino               struct edge_info *edge_info;
1705*e4b17023SJohn Marino 
1706*e4b17023SJohn Marino               edge_info = allocate_edge_info (true_edge);
1707*e4b17023SJohn Marino               record_conditions (edge_info, cond, inverted);
1708*e4b17023SJohn Marino 
1709*e4b17023SJohn Marino               if (can_infer_simple_equiv && code == EQ_EXPR)
1710*e4b17023SJohn Marino                 {
1711*e4b17023SJohn Marino                   edge_info->lhs = op0;
1712*e4b17023SJohn Marino                   edge_info->rhs = op1;
1713*e4b17023SJohn Marino                 }
1714*e4b17023SJohn Marino 
1715*e4b17023SJohn Marino               edge_info = allocate_edge_info (false_edge);
1716*e4b17023SJohn Marino               record_conditions (edge_info, inverted, cond);
1717*e4b17023SJohn Marino 
1718*e4b17023SJohn Marino               if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
1719*e4b17023SJohn Marino                 {
1720*e4b17023SJohn Marino                   edge_info->lhs = op0;
1721*e4b17023SJohn Marino                   edge_info->rhs = op1;
1722*e4b17023SJohn Marino                 }
1723*e4b17023SJohn Marino             }
1724*e4b17023SJohn Marino         }
1725*e4b17023SJohn Marino 
1726*e4b17023SJohn Marino       /* ??? TRUTH_NOT_EXPR can create an equivalence too.  */
1727*e4b17023SJohn Marino     }
1728*e4b17023SJohn Marino }
1729*e4b17023SJohn Marino 
1730*e4b17023SJohn Marino static void
dom_opt_enter_block(struct dom_walk_data * walk_data ATTRIBUTE_UNUSED,basic_block bb)1731*e4b17023SJohn Marino dom_opt_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
1732*e4b17023SJohn Marino 		     basic_block bb)
1733*e4b17023SJohn Marino {
1734*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
1735*e4b17023SJohn Marino 
1736*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1737*e4b17023SJohn Marino     fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index);
1738*e4b17023SJohn Marino 
1739*e4b17023SJohn Marino   /* Push a marker on the stacks of local information so that we know how
1740*e4b17023SJohn Marino      far to unwind when we finalize this block.  */
1741*e4b17023SJohn Marino   VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL);
1742*e4b17023SJohn Marino   VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE);
1743*e4b17023SJohn Marino 
1744*e4b17023SJohn Marino   record_equivalences_from_incoming_edge (bb);
1745*e4b17023SJohn Marino 
1746*e4b17023SJohn Marino   /* PHI nodes can create equivalences too.  */
1747*e4b17023SJohn Marino   record_equivalences_from_phis (bb);
1748*e4b17023SJohn Marino 
1749*e4b17023SJohn Marino   /* Create equivalences from redundant PHIs.  PHIs are only truly
1750*e4b17023SJohn Marino      redundant when they exist in the same block, so push another
1751*e4b17023SJohn Marino      marker and unwind right afterwards.  */
1752*e4b17023SJohn Marino   VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL);
1753*e4b17023SJohn Marino   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1754*e4b17023SJohn Marino     eliminate_redundant_computations (&gsi);
1755*e4b17023SJohn Marino   remove_local_expressions_from_table ();
1756*e4b17023SJohn Marino 
1757*e4b17023SJohn Marino   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1758*e4b17023SJohn Marino     optimize_stmt (bb, gsi);
1759*e4b17023SJohn Marino 
1760*e4b17023SJohn Marino   /* Now prepare to process dominated blocks.  */
1761*e4b17023SJohn Marino   record_edge_info (bb);
1762*e4b17023SJohn Marino   cprop_into_successor_phis (bb);
1763*e4b17023SJohn Marino }
1764*e4b17023SJohn Marino 
1765*e4b17023SJohn Marino /* We have finished processing the dominator children of BB, perform
1766*e4b17023SJohn Marino    any finalization actions in preparation for leaving this node in
1767*e4b17023SJohn Marino    the dominator tree.  */
1768*e4b17023SJohn Marino 
1769*e4b17023SJohn Marino static void
dom_opt_leave_block(struct dom_walk_data * walk_data,basic_block bb)1770*e4b17023SJohn Marino dom_opt_leave_block (struct dom_walk_data *walk_data, basic_block bb)
1771*e4b17023SJohn Marino {
1772*e4b17023SJohn Marino   gimple last;
1773*e4b17023SJohn Marino 
1774*e4b17023SJohn Marino   /* If we have an outgoing edge to a block with multiple incoming and
1775*e4b17023SJohn Marino      outgoing edges, then we may be able to thread the edge, i.e., we
1776*e4b17023SJohn Marino      may be able to statically determine which of the outgoing edges
1777*e4b17023SJohn Marino      will be traversed when the incoming edge from BB is traversed.  */
1778*e4b17023SJohn Marino   if (single_succ_p (bb)
1779*e4b17023SJohn Marino       && (single_succ_edge (bb)->flags & EDGE_ABNORMAL) == 0
1780*e4b17023SJohn Marino       && potentially_threadable_block (single_succ (bb)))
1781*e4b17023SJohn Marino     {
1782*e4b17023SJohn Marino       /* Push a marker on the stack, which thread_across_edge expects
1783*e4b17023SJohn Marino 	 and will remove.  */
1784*e4b17023SJohn Marino       VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE);
1785*e4b17023SJohn Marino       dom_thread_across_edge (walk_data, single_succ_edge (bb));
1786*e4b17023SJohn Marino     }
1787*e4b17023SJohn Marino   else if ((last = last_stmt (bb))
1788*e4b17023SJohn Marino 	   && gimple_code (last) == GIMPLE_COND
1789*e4b17023SJohn Marino 	   && EDGE_COUNT (bb->succs) == 2
1790*e4b17023SJohn Marino 	   && (EDGE_SUCC (bb, 0)->flags & EDGE_ABNORMAL) == 0
1791*e4b17023SJohn Marino 	   && (EDGE_SUCC (bb, 1)->flags & EDGE_ABNORMAL) == 0)
1792*e4b17023SJohn Marino     {
1793*e4b17023SJohn Marino       edge true_edge, false_edge;
1794*e4b17023SJohn Marino 
1795*e4b17023SJohn Marino       extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
1796*e4b17023SJohn Marino 
1797*e4b17023SJohn Marino       /* Only try to thread the edge if it reaches a target block with
1798*e4b17023SJohn Marino 	 more than one predecessor and more than one successor.  */
1799*e4b17023SJohn Marino       if (potentially_threadable_block (true_edge->dest))
1800*e4b17023SJohn Marino 	{
1801*e4b17023SJohn Marino 	  struct edge_info *edge_info;
1802*e4b17023SJohn Marino 	  unsigned int i;
1803*e4b17023SJohn Marino 
1804*e4b17023SJohn Marino 	  /* Push a marker onto the available expression stack so that we
1805*e4b17023SJohn Marino 	     unwind any expressions related to the TRUE arm before processing
1806*e4b17023SJohn Marino 	     the false arm below.  */
1807*e4b17023SJohn Marino           VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL);
1808*e4b17023SJohn Marino 	  VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE);
1809*e4b17023SJohn Marino 
1810*e4b17023SJohn Marino 	  edge_info = (struct edge_info *) true_edge->aux;
1811*e4b17023SJohn Marino 
1812*e4b17023SJohn Marino 	  /* If we have info associated with this edge, record it into
1813*e4b17023SJohn Marino 	     our equivalence tables.  */
1814*e4b17023SJohn Marino 	  if (edge_info)
1815*e4b17023SJohn Marino 	    {
1816*e4b17023SJohn Marino 	      cond_equivalence *eq;
1817*e4b17023SJohn Marino 	      tree lhs = edge_info->lhs;
1818*e4b17023SJohn Marino 	      tree rhs = edge_info->rhs;
1819*e4b17023SJohn Marino 
1820*e4b17023SJohn Marino 	      /* If we have a simple NAME = VALUE equivalence, record it.  */
1821*e4b17023SJohn Marino 	      if (lhs && TREE_CODE (lhs) == SSA_NAME)
1822*e4b17023SJohn Marino 		record_const_or_copy (lhs, rhs);
1823*e4b17023SJohn Marino 
1824*e4b17023SJohn Marino 	      /* If we have 0 = COND or 1 = COND equivalences, record them
1825*e4b17023SJohn Marino 		 into our expression hash tables.  */
1826*e4b17023SJohn Marino 	      for (i = 0; VEC_iterate (cond_equivalence,
1827*e4b17023SJohn Marino 				       edge_info->cond_equivalences, i, eq); ++i)
1828*e4b17023SJohn Marino 		record_cond (eq);
1829*e4b17023SJohn Marino 	    }
1830*e4b17023SJohn Marino 
1831*e4b17023SJohn Marino 	  dom_thread_across_edge (walk_data, true_edge);
1832*e4b17023SJohn Marino 
1833*e4b17023SJohn Marino 	  /* And restore the various tables to their state before
1834*e4b17023SJohn Marino 	     we threaded this edge.  */
1835*e4b17023SJohn Marino 	  remove_local_expressions_from_table ();
1836*e4b17023SJohn Marino 	}
1837*e4b17023SJohn Marino 
1838*e4b17023SJohn Marino       /* Similarly for the ELSE arm.  */
1839*e4b17023SJohn Marino       if (potentially_threadable_block (false_edge->dest))
1840*e4b17023SJohn Marino 	{
1841*e4b17023SJohn Marino 	  struct edge_info *edge_info;
1842*e4b17023SJohn Marino 	  unsigned int i;
1843*e4b17023SJohn Marino 
1844*e4b17023SJohn Marino 	  VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE);
1845*e4b17023SJohn Marino 	  edge_info = (struct edge_info *) false_edge->aux;
1846*e4b17023SJohn Marino 
1847*e4b17023SJohn Marino 	  /* If we have info associated with this edge, record it into
1848*e4b17023SJohn Marino 	     our equivalence tables.  */
1849*e4b17023SJohn Marino 	  if (edge_info)
1850*e4b17023SJohn Marino 	    {
1851*e4b17023SJohn Marino 	      cond_equivalence *eq;
1852*e4b17023SJohn Marino 	      tree lhs = edge_info->lhs;
1853*e4b17023SJohn Marino 	      tree rhs = edge_info->rhs;
1854*e4b17023SJohn Marino 
1855*e4b17023SJohn Marino 	      /* If we have a simple NAME = VALUE equivalence, record it.  */
1856*e4b17023SJohn Marino 	      if (lhs && TREE_CODE (lhs) == SSA_NAME)
1857*e4b17023SJohn Marino 		record_const_or_copy (lhs, rhs);
1858*e4b17023SJohn Marino 
1859*e4b17023SJohn Marino 	      /* If we have 0 = COND or 1 = COND equivalences, record them
1860*e4b17023SJohn Marino 		 into our expression hash tables.  */
1861*e4b17023SJohn Marino 	      for (i = 0; VEC_iterate (cond_equivalence,
1862*e4b17023SJohn Marino 				       edge_info->cond_equivalences, i, eq); ++i)
1863*e4b17023SJohn Marino 		record_cond (eq);
1864*e4b17023SJohn Marino 	    }
1865*e4b17023SJohn Marino 
1866*e4b17023SJohn Marino 	  /* Now thread the edge.  */
1867*e4b17023SJohn Marino 	  dom_thread_across_edge (walk_data, false_edge);
1868*e4b17023SJohn Marino 
1869*e4b17023SJohn Marino 	  /* No need to remove local expressions from our tables
1870*e4b17023SJohn Marino 	     or restore vars to their original value as that will
1871*e4b17023SJohn Marino 	     be done immediately below.  */
1872*e4b17023SJohn Marino 	}
1873*e4b17023SJohn Marino     }
1874*e4b17023SJohn Marino 
1875*e4b17023SJohn Marino   remove_local_expressions_from_table ();
1876*e4b17023SJohn Marino   restore_vars_to_original_value ();
1877*e4b17023SJohn Marino }
1878*e4b17023SJohn Marino 
1879*e4b17023SJohn Marino /* Search for redundant computations in STMT.  If any are found, then
1880*e4b17023SJohn Marino    replace them with the variable holding the result of the computation.
1881*e4b17023SJohn Marino 
1882*e4b17023SJohn Marino    If safe, record this expression into the available expression hash
1883*e4b17023SJohn Marino    table.  */
1884*e4b17023SJohn Marino 
1885*e4b17023SJohn Marino static void
eliminate_redundant_computations(gimple_stmt_iterator * gsi)1886*e4b17023SJohn Marino eliminate_redundant_computations (gimple_stmt_iterator* gsi)
1887*e4b17023SJohn Marino {
1888*e4b17023SJohn Marino   tree expr_type;
1889*e4b17023SJohn Marino   tree cached_lhs;
1890*e4b17023SJohn Marino   tree def;
1891*e4b17023SJohn Marino   bool insert = true;
1892*e4b17023SJohn Marino   bool assigns_var_p = false;
1893*e4b17023SJohn Marino 
1894*e4b17023SJohn Marino   gimple stmt = gsi_stmt (*gsi);
1895*e4b17023SJohn Marino 
1896*e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_PHI)
1897*e4b17023SJohn Marino     def = gimple_phi_result (stmt);
1898*e4b17023SJohn Marino   else
1899*e4b17023SJohn Marino     def = gimple_get_lhs (stmt);
1900*e4b17023SJohn Marino 
1901*e4b17023SJohn Marino   /* Certain expressions on the RHS can be optimized away, but can not
1902*e4b17023SJohn Marino      themselves be entered into the hash tables.  */
1903*e4b17023SJohn Marino   if (! def
1904*e4b17023SJohn Marino       || TREE_CODE (def) != SSA_NAME
1905*e4b17023SJohn Marino       || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)
1906*e4b17023SJohn Marino       || gimple_vdef (stmt)
1907*e4b17023SJohn Marino       /* Do not record equivalences for increments of ivs.  This would create
1908*e4b17023SJohn Marino 	 overlapping live ranges for a very questionable gain.  */
1909*e4b17023SJohn Marino       || simple_iv_increment_p (stmt))
1910*e4b17023SJohn Marino     insert = false;
1911*e4b17023SJohn Marino 
1912*e4b17023SJohn Marino   /* Check if the expression has been computed before.  */
1913*e4b17023SJohn Marino   cached_lhs = lookup_avail_expr (stmt, insert);
1914*e4b17023SJohn Marino 
1915*e4b17023SJohn Marino   opt_stats.num_exprs_considered++;
1916*e4b17023SJohn Marino 
1917*e4b17023SJohn Marino   /* Get the type of the expression we are trying to optimize.  */
1918*e4b17023SJohn Marino   if (is_gimple_assign (stmt))
1919*e4b17023SJohn Marino     {
1920*e4b17023SJohn Marino       expr_type = TREE_TYPE (gimple_assign_lhs (stmt));
1921*e4b17023SJohn Marino       assigns_var_p = true;
1922*e4b17023SJohn Marino     }
1923*e4b17023SJohn Marino   else if (gimple_code (stmt) == GIMPLE_COND)
1924*e4b17023SJohn Marino     expr_type = boolean_type_node;
1925*e4b17023SJohn Marino   else if (is_gimple_call (stmt))
1926*e4b17023SJohn Marino     {
1927*e4b17023SJohn Marino       gcc_assert (gimple_call_lhs (stmt));
1928*e4b17023SJohn Marino       expr_type = TREE_TYPE (gimple_call_lhs (stmt));
1929*e4b17023SJohn Marino       assigns_var_p = true;
1930*e4b17023SJohn Marino     }
1931*e4b17023SJohn Marino   else if (gimple_code (stmt) == GIMPLE_SWITCH)
1932*e4b17023SJohn Marino     expr_type = TREE_TYPE (gimple_switch_index (stmt));
1933*e4b17023SJohn Marino   else if (gimple_code (stmt) == GIMPLE_PHI)
1934*e4b17023SJohn Marino     /* We can't propagate into a phi, so the logic below doesn't apply.
1935*e4b17023SJohn Marino        Instead record an equivalence between the cached LHS and the
1936*e4b17023SJohn Marino        PHI result of this statement, provided they are in the same block.
1937*e4b17023SJohn Marino        This should be sufficient to kill the redundant phi.  */
1938*e4b17023SJohn Marino     {
1939*e4b17023SJohn Marino       if (def && cached_lhs)
1940*e4b17023SJohn Marino 	record_const_or_copy (def, cached_lhs);
1941*e4b17023SJohn Marino       return;
1942*e4b17023SJohn Marino     }
1943*e4b17023SJohn Marino   else
1944*e4b17023SJohn Marino     gcc_unreachable ();
1945*e4b17023SJohn Marino 
1946*e4b17023SJohn Marino   if (!cached_lhs)
1947*e4b17023SJohn Marino     return;
1948*e4b17023SJohn Marino 
1949*e4b17023SJohn Marino   /* It is safe to ignore types here since we have already done
1950*e4b17023SJohn Marino      type checking in the hashing and equality routines.  In fact
1951*e4b17023SJohn Marino      type checking here merely gets in the way of constant
1952*e4b17023SJohn Marino      propagation.  Also, make sure that it is safe to propagate
1953*e4b17023SJohn Marino      CACHED_LHS into the expression in STMT.  */
1954*e4b17023SJohn Marino   if ((TREE_CODE (cached_lhs) != SSA_NAME
1955*e4b17023SJohn Marino        && (assigns_var_p
1956*e4b17023SJohn Marino            || useless_type_conversion_p (expr_type, TREE_TYPE (cached_lhs))))
1957*e4b17023SJohn Marino       || may_propagate_copy_into_stmt (stmt, cached_lhs))
1958*e4b17023SJohn Marino   {
1959*e4b17023SJohn Marino       gcc_checking_assert (TREE_CODE (cached_lhs) == SSA_NAME
1960*e4b17023SJohn Marino 			   || is_gimple_min_invariant (cached_lhs));
1961*e4b17023SJohn Marino 
1962*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1963*e4b17023SJohn Marino 	{
1964*e4b17023SJohn Marino 	  fprintf (dump_file, "  Replaced redundant expr '");
1965*e4b17023SJohn Marino 	  print_gimple_expr (dump_file, stmt, 0, dump_flags);
1966*e4b17023SJohn Marino 	  fprintf (dump_file, "' with '");
1967*e4b17023SJohn Marino 	  print_generic_expr (dump_file, cached_lhs, dump_flags);
1968*e4b17023SJohn Marino           fprintf (dump_file, "'\n");
1969*e4b17023SJohn Marino 	}
1970*e4b17023SJohn Marino 
1971*e4b17023SJohn Marino       opt_stats.num_re++;
1972*e4b17023SJohn Marino 
1973*e4b17023SJohn Marino       if (assigns_var_p
1974*e4b17023SJohn Marino 	  && !useless_type_conversion_p (expr_type, TREE_TYPE (cached_lhs)))
1975*e4b17023SJohn Marino 	cached_lhs = fold_convert (expr_type, cached_lhs);
1976*e4b17023SJohn Marino 
1977*e4b17023SJohn Marino       propagate_tree_value_into_stmt (gsi, cached_lhs);
1978*e4b17023SJohn Marino 
1979*e4b17023SJohn Marino       /* Since it is always necessary to mark the result as modified,
1980*e4b17023SJohn Marino          perhaps we should move this into propagate_tree_value_into_stmt
1981*e4b17023SJohn Marino          itself.  */
1982*e4b17023SJohn Marino       gimple_set_modified (gsi_stmt (*gsi), true);
1983*e4b17023SJohn Marino   }
1984*e4b17023SJohn Marino }
1985*e4b17023SJohn Marino 
1986*e4b17023SJohn Marino /* STMT, a GIMPLE_ASSIGN, may create certain equivalences, in either
1987*e4b17023SJohn Marino    the available expressions table or the const_and_copies table.
1988*e4b17023SJohn Marino    Detect and record those equivalences.  */
1989*e4b17023SJohn Marino /* We handle only very simple copy equivalences here.  The heavy
1990*e4b17023SJohn Marino    lifing is done by eliminate_redundant_computations.  */
1991*e4b17023SJohn Marino 
1992*e4b17023SJohn Marino static void
record_equivalences_from_stmt(gimple stmt,int may_optimize_p)1993*e4b17023SJohn Marino record_equivalences_from_stmt (gimple stmt, int may_optimize_p)
1994*e4b17023SJohn Marino {
1995*e4b17023SJohn Marino   tree lhs;
1996*e4b17023SJohn Marino   enum tree_code lhs_code;
1997*e4b17023SJohn Marino 
1998*e4b17023SJohn Marino   gcc_assert (is_gimple_assign (stmt));
1999*e4b17023SJohn Marino 
2000*e4b17023SJohn Marino   lhs = gimple_assign_lhs (stmt);
2001*e4b17023SJohn Marino   lhs_code = TREE_CODE (lhs);
2002*e4b17023SJohn Marino 
2003*e4b17023SJohn Marino   if (lhs_code == SSA_NAME
2004*e4b17023SJohn Marino       && gimple_assign_single_p (stmt))
2005*e4b17023SJohn Marino     {
2006*e4b17023SJohn Marino       tree rhs = gimple_assign_rhs1 (stmt);
2007*e4b17023SJohn Marino 
2008*e4b17023SJohn Marino       /* If the RHS of the assignment is a constant or another variable that
2009*e4b17023SJohn Marino 	 may be propagated, register it in the CONST_AND_COPIES table.  We
2010*e4b17023SJohn Marino 	 do not need to record unwind data for this, since this is a true
2011*e4b17023SJohn Marino 	 assignment and not an equivalence inferred from a comparison.  All
2012*e4b17023SJohn Marino 	 uses of this ssa name are dominated by this assignment, so unwinding
2013*e4b17023SJohn Marino 	 just costs time and space.  */
2014*e4b17023SJohn Marino       if (may_optimize_p
2015*e4b17023SJohn Marino 	  && (TREE_CODE (rhs) == SSA_NAME
2016*e4b17023SJohn Marino 	      || is_gimple_min_invariant (rhs)))
2017*e4b17023SJohn Marino       {
2018*e4b17023SJohn Marino 	if (dump_file && (dump_flags & TDF_DETAILS))
2019*e4b17023SJohn Marino 	  {
2020*e4b17023SJohn Marino 	    fprintf (dump_file, "==== ASGN ");
2021*e4b17023SJohn Marino 	    print_generic_expr (dump_file, lhs, 0);
2022*e4b17023SJohn Marino 	    fprintf (dump_file, " = ");
2023*e4b17023SJohn Marino 	    print_generic_expr (dump_file, rhs, 0);
2024*e4b17023SJohn Marino 	    fprintf (dump_file, "\n");
2025*e4b17023SJohn Marino 	  }
2026*e4b17023SJohn Marino 
2027*e4b17023SJohn Marino 	set_ssa_name_value (lhs, rhs);
2028*e4b17023SJohn Marino       }
2029*e4b17023SJohn Marino     }
2030*e4b17023SJohn Marino 
2031*e4b17023SJohn Marino   /* A memory store, even an aliased store, creates a useful
2032*e4b17023SJohn Marino      equivalence.  By exchanging the LHS and RHS, creating suitable
2033*e4b17023SJohn Marino      vops and recording the result in the available expression table,
2034*e4b17023SJohn Marino      we may be able to expose more redundant loads.  */
2035*e4b17023SJohn Marino   if (!gimple_has_volatile_ops (stmt)
2036*e4b17023SJohn Marino       && gimple_references_memory_p (stmt)
2037*e4b17023SJohn Marino       && gimple_assign_single_p (stmt)
2038*e4b17023SJohn Marino       && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
2039*e4b17023SJohn Marino 	  || is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
2040*e4b17023SJohn Marino       && !is_gimple_reg (lhs))
2041*e4b17023SJohn Marino     {
2042*e4b17023SJohn Marino       tree rhs = gimple_assign_rhs1 (stmt);
2043*e4b17023SJohn Marino       gimple new_stmt;
2044*e4b17023SJohn Marino 
2045*e4b17023SJohn Marino       /* Build a new statement with the RHS and LHS exchanged.  */
2046*e4b17023SJohn Marino       if (TREE_CODE (rhs) == SSA_NAME)
2047*e4b17023SJohn Marino         {
2048*e4b17023SJohn Marino           /* NOTE tuples.  The call to gimple_build_assign below replaced
2049*e4b17023SJohn Marino              a call to build_gimple_modify_stmt, which did not set the
2050*e4b17023SJohn Marino              SSA_NAME_DEF_STMT on the LHS of the assignment.  Doing so
2051*e4b17023SJohn Marino              may cause an SSA validation failure, as the LHS may be a
2052*e4b17023SJohn Marino              default-initialized name and should have no definition.  I'm
2053*e4b17023SJohn Marino              a bit dubious of this, as the artificial statement that we
2054*e4b17023SJohn Marino              generate here may in fact be ill-formed, but it is simply
2055*e4b17023SJohn Marino              used as an internal device in this pass, and never becomes
2056*e4b17023SJohn Marino              part of the CFG.  */
2057*e4b17023SJohn Marino           gimple defstmt = SSA_NAME_DEF_STMT (rhs);
2058*e4b17023SJohn Marino           new_stmt = gimple_build_assign (rhs, lhs);
2059*e4b17023SJohn Marino           SSA_NAME_DEF_STMT (rhs) = defstmt;
2060*e4b17023SJohn Marino         }
2061*e4b17023SJohn Marino       else
2062*e4b17023SJohn Marino         new_stmt = gimple_build_assign (rhs, lhs);
2063*e4b17023SJohn Marino 
2064*e4b17023SJohn Marino       gimple_set_vuse (new_stmt, gimple_vdef (stmt));
2065*e4b17023SJohn Marino 
2066*e4b17023SJohn Marino       /* Finally enter the statement into the available expression
2067*e4b17023SJohn Marino 	 table.  */
2068*e4b17023SJohn Marino       lookup_avail_expr (new_stmt, true);
2069*e4b17023SJohn Marino     }
2070*e4b17023SJohn Marino }
2071*e4b17023SJohn Marino 
2072*e4b17023SJohn Marino /* Replace *OP_P in STMT with any known equivalent value for *OP_P from
2073*e4b17023SJohn Marino    CONST_AND_COPIES.  */
2074*e4b17023SJohn Marino 
2075*e4b17023SJohn Marino static void
cprop_operand(gimple stmt,use_operand_p op_p)2076*e4b17023SJohn Marino cprop_operand (gimple stmt, use_operand_p op_p)
2077*e4b17023SJohn Marino {
2078*e4b17023SJohn Marino   tree val;
2079*e4b17023SJohn Marino   tree op = USE_FROM_PTR (op_p);
2080*e4b17023SJohn Marino 
2081*e4b17023SJohn Marino   /* If the operand has a known constant value or it is known to be a
2082*e4b17023SJohn Marino      copy of some other variable, use the value or copy stored in
2083*e4b17023SJohn Marino      CONST_AND_COPIES.  */
2084*e4b17023SJohn Marino   val = SSA_NAME_VALUE (op);
2085*e4b17023SJohn Marino   if (val && val != op)
2086*e4b17023SJohn Marino     {
2087*e4b17023SJohn Marino       /* Do not replace hard register operands in asm statements.  */
2088*e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_ASM
2089*e4b17023SJohn Marino 	  && !may_propagate_copy_into_asm (op))
2090*e4b17023SJohn Marino 	return;
2091*e4b17023SJohn Marino 
2092*e4b17023SJohn Marino       /* Certain operands are not allowed to be copy propagated due
2093*e4b17023SJohn Marino 	 to their interaction with exception handling and some GCC
2094*e4b17023SJohn Marino 	 extensions.  */
2095*e4b17023SJohn Marino       if (!may_propagate_copy (op, val))
2096*e4b17023SJohn Marino 	return;
2097*e4b17023SJohn Marino 
2098*e4b17023SJohn Marino       /* Do not propagate addresses that point to volatiles into memory
2099*e4b17023SJohn Marino 	 stmts without volatile operands.  */
2100*e4b17023SJohn Marino       if (POINTER_TYPE_P (TREE_TYPE (val))
2101*e4b17023SJohn Marino 	  && TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (val)))
2102*e4b17023SJohn Marino 	  && gimple_has_mem_ops (stmt)
2103*e4b17023SJohn Marino 	  && !gimple_has_volatile_ops (stmt))
2104*e4b17023SJohn Marino 	return;
2105*e4b17023SJohn Marino 
2106*e4b17023SJohn Marino       /* Do not propagate copies if the propagated value is at a deeper loop
2107*e4b17023SJohn Marino 	 depth than the propagatee.  Otherwise, this may move loop variant
2108*e4b17023SJohn Marino 	 variables outside of their loops and prevent coalescing
2109*e4b17023SJohn Marino 	 opportunities.  If the value was loop invariant, it will be hoisted
2110*e4b17023SJohn Marino 	 by LICM and exposed for copy propagation.  */
2111*e4b17023SJohn Marino       if (loop_depth_of_name (val) > loop_depth_of_name (op))
2112*e4b17023SJohn Marino 	return;
2113*e4b17023SJohn Marino 
2114*e4b17023SJohn Marino       /* Do not propagate copies into simple IV increment statements.
2115*e4b17023SJohn Marino          See PR23821 for how this can disturb IV analysis.  */
2116*e4b17023SJohn Marino       if (TREE_CODE (val) != INTEGER_CST
2117*e4b17023SJohn Marino 	  && simple_iv_increment_p (stmt))
2118*e4b17023SJohn Marino 	return;
2119*e4b17023SJohn Marino 
2120*e4b17023SJohn Marino       /* Dump details.  */
2121*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2122*e4b17023SJohn Marino 	{
2123*e4b17023SJohn Marino 	  fprintf (dump_file, "  Replaced '");
2124*e4b17023SJohn Marino 	  print_generic_expr (dump_file, op, dump_flags);
2125*e4b17023SJohn Marino 	  fprintf (dump_file, "' with %s '",
2126*e4b17023SJohn Marino 		   (TREE_CODE (val) != SSA_NAME ? "constant" : "variable"));
2127*e4b17023SJohn Marino 	  print_generic_expr (dump_file, val, dump_flags);
2128*e4b17023SJohn Marino 	  fprintf (dump_file, "'\n");
2129*e4b17023SJohn Marino 	}
2130*e4b17023SJohn Marino 
2131*e4b17023SJohn Marino       if (TREE_CODE (val) != SSA_NAME)
2132*e4b17023SJohn Marino 	opt_stats.num_const_prop++;
2133*e4b17023SJohn Marino       else
2134*e4b17023SJohn Marino 	opt_stats.num_copy_prop++;
2135*e4b17023SJohn Marino 
2136*e4b17023SJohn Marino       propagate_value (op_p, val);
2137*e4b17023SJohn Marino 
2138*e4b17023SJohn Marino       /* And note that we modified this statement.  This is now
2139*e4b17023SJohn Marino 	 safe, even if we changed virtual operands since we will
2140*e4b17023SJohn Marino 	 rescan the statement and rewrite its operands again.  */
2141*e4b17023SJohn Marino       gimple_set_modified (stmt, true);
2142*e4b17023SJohn Marino     }
2143*e4b17023SJohn Marino }
2144*e4b17023SJohn Marino 
2145*e4b17023SJohn Marino /* CONST_AND_COPIES is a table which maps an SSA_NAME to the current
2146*e4b17023SJohn Marino    known value for that SSA_NAME (or NULL if no value is known).
2147*e4b17023SJohn Marino 
2148*e4b17023SJohn Marino    Propagate values from CONST_AND_COPIES into the uses, vuses and
2149*e4b17023SJohn Marino    vdef_ops of STMT.  */
2150*e4b17023SJohn Marino 
2151*e4b17023SJohn Marino static void
cprop_into_stmt(gimple stmt)2152*e4b17023SJohn Marino cprop_into_stmt (gimple stmt)
2153*e4b17023SJohn Marino {
2154*e4b17023SJohn Marino   use_operand_p op_p;
2155*e4b17023SJohn Marino   ssa_op_iter iter;
2156*e4b17023SJohn Marino 
2157*e4b17023SJohn Marino   FOR_EACH_SSA_USE_OPERAND (op_p, stmt, iter, SSA_OP_USE)
2158*e4b17023SJohn Marino     cprop_operand (stmt, op_p);
2159*e4b17023SJohn Marino }
2160*e4b17023SJohn Marino 
2161*e4b17023SJohn Marino /* Optimize the statement pointed to by iterator SI.
2162*e4b17023SJohn Marino 
2163*e4b17023SJohn Marino    We try to perform some simplistic global redundancy elimination and
2164*e4b17023SJohn Marino    constant propagation:
2165*e4b17023SJohn Marino 
2166*e4b17023SJohn Marino    1- To detect global redundancy, we keep track of expressions that have
2167*e4b17023SJohn Marino       been computed in this block and its dominators.  If we find that the
2168*e4b17023SJohn Marino       same expression is computed more than once, we eliminate repeated
2169*e4b17023SJohn Marino       computations by using the target of the first one.
2170*e4b17023SJohn Marino 
2171*e4b17023SJohn Marino    2- Constant values and copy assignments.  This is used to do very
2172*e4b17023SJohn Marino       simplistic constant and copy propagation.  When a constant or copy
2173*e4b17023SJohn Marino       assignment is found, we map the value on the RHS of the assignment to
2174*e4b17023SJohn Marino       the variable in the LHS in the CONST_AND_COPIES table.  */
2175*e4b17023SJohn Marino 
2176*e4b17023SJohn Marino static void
optimize_stmt(basic_block bb,gimple_stmt_iterator si)2177*e4b17023SJohn Marino optimize_stmt (basic_block bb, gimple_stmt_iterator si)
2178*e4b17023SJohn Marino {
2179*e4b17023SJohn Marino   gimple stmt, old_stmt;
2180*e4b17023SJohn Marino   bool may_optimize_p;
2181*e4b17023SJohn Marino   bool modified_p = false;
2182*e4b17023SJohn Marino 
2183*e4b17023SJohn Marino   old_stmt = stmt = gsi_stmt (si);
2184*e4b17023SJohn Marino 
2185*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2186*e4b17023SJohn Marino     {
2187*e4b17023SJohn Marino       fprintf (dump_file, "Optimizing statement ");
2188*e4b17023SJohn Marino       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2189*e4b17023SJohn Marino     }
2190*e4b17023SJohn Marino 
2191*e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_COND)
2192*e4b17023SJohn Marino     canonicalize_comparison (stmt);
2193*e4b17023SJohn Marino 
2194*e4b17023SJohn Marino   update_stmt_if_modified (stmt);
2195*e4b17023SJohn Marino   opt_stats.num_stmts++;
2196*e4b17023SJohn Marino 
2197*e4b17023SJohn Marino   /* Const/copy propagate into USES, VUSES and the RHS of VDEFs.  */
2198*e4b17023SJohn Marino   cprop_into_stmt (stmt);
2199*e4b17023SJohn Marino 
2200*e4b17023SJohn Marino   /* If the statement has been modified with constant replacements,
2201*e4b17023SJohn Marino      fold its RHS before checking for redundant computations.  */
2202*e4b17023SJohn Marino   if (gimple_modified_p (stmt))
2203*e4b17023SJohn Marino     {
2204*e4b17023SJohn Marino       tree rhs = NULL;
2205*e4b17023SJohn Marino 
2206*e4b17023SJohn Marino       /* Try to fold the statement making sure that STMT is kept
2207*e4b17023SJohn Marino 	 up to date.  */
2208*e4b17023SJohn Marino       if (fold_stmt (&si))
2209*e4b17023SJohn Marino 	{
2210*e4b17023SJohn Marino 	  stmt = gsi_stmt (si);
2211*e4b17023SJohn Marino 	  gimple_set_modified (stmt, true);
2212*e4b17023SJohn Marino 
2213*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2214*e4b17023SJohn Marino 	    {
2215*e4b17023SJohn Marino 	      fprintf (dump_file, "  Folded to: ");
2216*e4b17023SJohn Marino 	      print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
2217*e4b17023SJohn Marino 	    }
2218*e4b17023SJohn Marino 	}
2219*e4b17023SJohn Marino 
2220*e4b17023SJohn Marino       /* We only need to consider cases that can yield a gimple operand.  */
2221*e4b17023SJohn Marino       if (gimple_assign_single_p (stmt))
2222*e4b17023SJohn Marino         rhs = gimple_assign_rhs1 (stmt);
2223*e4b17023SJohn Marino       else if (gimple_code (stmt) == GIMPLE_GOTO)
2224*e4b17023SJohn Marino         rhs = gimple_goto_dest (stmt);
2225*e4b17023SJohn Marino       else if (gimple_code (stmt) == GIMPLE_SWITCH)
2226*e4b17023SJohn Marino         /* This should never be an ADDR_EXPR.  */
2227*e4b17023SJohn Marino         rhs = gimple_switch_index (stmt);
2228*e4b17023SJohn Marino 
2229*e4b17023SJohn Marino       if (rhs && TREE_CODE (rhs) == ADDR_EXPR)
2230*e4b17023SJohn Marino         recompute_tree_invariant_for_addr_expr (rhs);
2231*e4b17023SJohn Marino 
2232*e4b17023SJohn Marino       /* Indicate that maybe_clean_or_replace_eh_stmt needs to be called,
2233*e4b17023SJohn Marino 	 even if fold_stmt updated the stmt already and thus cleared
2234*e4b17023SJohn Marino 	 gimple_modified_p flag on it.  */
2235*e4b17023SJohn Marino       modified_p = true;
2236*e4b17023SJohn Marino     }
2237*e4b17023SJohn Marino 
2238*e4b17023SJohn Marino   /* Check for redundant computations.  Do this optimization only
2239*e4b17023SJohn Marino      for assignments that have no volatile ops and conditionals.  */
2240*e4b17023SJohn Marino   may_optimize_p = (!gimple_has_side_effects (stmt)
2241*e4b17023SJohn Marino                     && (is_gimple_assign (stmt)
2242*e4b17023SJohn Marino                         || (is_gimple_call (stmt)
2243*e4b17023SJohn Marino                             && gimple_call_lhs (stmt) != NULL_TREE)
2244*e4b17023SJohn Marino                         || gimple_code (stmt) == GIMPLE_COND
2245*e4b17023SJohn Marino                         || gimple_code (stmt) == GIMPLE_SWITCH));
2246*e4b17023SJohn Marino 
2247*e4b17023SJohn Marino   if (may_optimize_p)
2248*e4b17023SJohn Marino     {
2249*e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_CALL)
2250*e4b17023SJohn Marino 	{
2251*e4b17023SJohn Marino 	  /* Resolve __builtin_constant_p.  If it hasn't been
2252*e4b17023SJohn Marino 	     folded to integer_one_node by now, it's fairly
2253*e4b17023SJohn Marino 	     certain that the value simply isn't constant.  */
2254*e4b17023SJohn Marino 	  tree callee = gimple_call_fndecl (stmt);
2255*e4b17023SJohn Marino 	  if (callee
2256*e4b17023SJohn Marino 	      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
2257*e4b17023SJohn Marino 	      && DECL_FUNCTION_CODE (callee) == BUILT_IN_CONSTANT_P)
2258*e4b17023SJohn Marino 	    {
2259*e4b17023SJohn Marino 	      propagate_tree_value_into_stmt (&si, integer_zero_node);
2260*e4b17023SJohn Marino 	      stmt = gsi_stmt (si);
2261*e4b17023SJohn Marino 	    }
2262*e4b17023SJohn Marino 	}
2263*e4b17023SJohn Marino 
2264*e4b17023SJohn Marino       update_stmt_if_modified (stmt);
2265*e4b17023SJohn Marino       eliminate_redundant_computations (&si);
2266*e4b17023SJohn Marino       stmt = gsi_stmt (si);
2267*e4b17023SJohn Marino 
2268*e4b17023SJohn Marino       /* Perform simple redundant store elimination.  */
2269*e4b17023SJohn Marino       if (gimple_assign_single_p (stmt)
2270*e4b17023SJohn Marino 	  && TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
2271*e4b17023SJohn Marino 	{
2272*e4b17023SJohn Marino 	  tree lhs = gimple_assign_lhs (stmt);
2273*e4b17023SJohn Marino 	  tree rhs = gimple_assign_rhs1 (stmt);
2274*e4b17023SJohn Marino 	  tree cached_lhs;
2275*e4b17023SJohn Marino 	  gimple new_stmt;
2276*e4b17023SJohn Marino 	  if (TREE_CODE (rhs) == SSA_NAME)
2277*e4b17023SJohn Marino 	    {
2278*e4b17023SJohn Marino 	      tree tem = SSA_NAME_VALUE (rhs);
2279*e4b17023SJohn Marino 	      if (tem)
2280*e4b17023SJohn Marino 		rhs = tem;
2281*e4b17023SJohn Marino 	    }
2282*e4b17023SJohn Marino 	  /* Build a new statement with the RHS and LHS exchanged.  */
2283*e4b17023SJohn Marino 	  if (TREE_CODE (rhs) == SSA_NAME)
2284*e4b17023SJohn Marino 	    {
2285*e4b17023SJohn Marino 	      gimple defstmt = SSA_NAME_DEF_STMT (rhs);
2286*e4b17023SJohn Marino 	      new_stmt = gimple_build_assign (rhs, lhs);
2287*e4b17023SJohn Marino 	      SSA_NAME_DEF_STMT (rhs) = defstmt;
2288*e4b17023SJohn Marino 	    }
2289*e4b17023SJohn Marino 	  else
2290*e4b17023SJohn Marino 	    new_stmt = gimple_build_assign (rhs, lhs);
2291*e4b17023SJohn Marino 	  gimple_set_vuse (new_stmt, gimple_vuse (stmt));
2292*e4b17023SJohn Marino 	  cached_lhs = lookup_avail_expr (new_stmt, false);
2293*e4b17023SJohn Marino 	  if (cached_lhs
2294*e4b17023SJohn Marino 	      && rhs == cached_lhs)
2295*e4b17023SJohn Marino 	    {
2296*e4b17023SJohn Marino 	      basic_block bb = gimple_bb (stmt);
2297*e4b17023SJohn Marino 	      int lp_nr = lookup_stmt_eh_lp (stmt);
2298*e4b17023SJohn Marino 	      unlink_stmt_vdef (stmt);
2299*e4b17023SJohn Marino 	      gsi_remove (&si, true);
2300*e4b17023SJohn Marino 	      if (lp_nr != 0)
2301*e4b17023SJohn Marino 		{
2302*e4b17023SJohn Marino 		  bitmap_set_bit (need_eh_cleanup, bb->index);
2303*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
2304*e4b17023SJohn Marino 		    fprintf (dump_file, "  Flagged to clear EH edges.\n");
2305*e4b17023SJohn Marino 		}
2306*e4b17023SJohn Marino 	      return;
2307*e4b17023SJohn Marino 	    }
2308*e4b17023SJohn Marino 	}
2309*e4b17023SJohn Marino     }
2310*e4b17023SJohn Marino 
2311*e4b17023SJohn Marino   /* Record any additional equivalences created by this statement.  */
2312*e4b17023SJohn Marino   if (is_gimple_assign (stmt))
2313*e4b17023SJohn Marino     record_equivalences_from_stmt (stmt, may_optimize_p);
2314*e4b17023SJohn Marino 
2315*e4b17023SJohn Marino   /* If STMT is a COND_EXPR and it was modified, then we may know
2316*e4b17023SJohn Marino      where it goes.  If that is the case, then mark the CFG as altered.
2317*e4b17023SJohn Marino 
2318*e4b17023SJohn Marino      This will cause us to later call remove_unreachable_blocks and
2319*e4b17023SJohn Marino      cleanup_tree_cfg when it is safe to do so.  It is not safe to
2320*e4b17023SJohn Marino      clean things up here since removal of edges and such can trigger
2321*e4b17023SJohn Marino      the removal of PHI nodes, which in turn can release SSA_NAMEs to
2322*e4b17023SJohn Marino      the manager.
2323*e4b17023SJohn Marino 
2324*e4b17023SJohn Marino      That's all fine and good, except that once SSA_NAMEs are released
2325*e4b17023SJohn Marino      to the manager, we must not call create_ssa_name until all references
2326*e4b17023SJohn Marino      to released SSA_NAMEs have been eliminated.
2327*e4b17023SJohn Marino 
2328*e4b17023SJohn Marino      All references to the deleted SSA_NAMEs can not be eliminated until
2329*e4b17023SJohn Marino      we remove unreachable blocks.
2330*e4b17023SJohn Marino 
2331*e4b17023SJohn Marino      We can not remove unreachable blocks until after we have completed
2332*e4b17023SJohn Marino      any queued jump threading.
2333*e4b17023SJohn Marino 
2334*e4b17023SJohn Marino      We can not complete any queued jump threads until we have taken
2335*e4b17023SJohn Marino      appropriate variables out of SSA form.  Taking variables out of
2336*e4b17023SJohn Marino      SSA form can call create_ssa_name and thus we lose.
2337*e4b17023SJohn Marino 
2338*e4b17023SJohn Marino      Ultimately I suspect we're going to need to change the interface
2339*e4b17023SJohn Marino      into the SSA_NAME manager.  */
2340*e4b17023SJohn Marino   if (gimple_modified_p (stmt) || modified_p)
2341*e4b17023SJohn Marino     {
2342*e4b17023SJohn Marino       tree val = NULL;
2343*e4b17023SJohn Marino 
2344*e4b17023SJohn Marino       update_stmt_if_modified (stmt);
2345*e4b17023SJohn Marino 
2346*e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_COND)
2347*e4b17023SJohn Marino         val = fold_binary_loc (gimple_location (stmt),
2348*e4b17023SJohn Marino 			   gimple_cond_code (stmt), boolean_type_node,
2349*e4b17023SJohn Marino                            gimple_cond_lhs (stmt),  gimple_cond_rhs (stmt));
2350*e4b17023SJohn Marino       else if (gimple_code (stmt) == GIMPLE_SWITCH)
2351*e4b17023SJohn Marino 	val = gimple_switch_index (stmt);
2352*e4b17023SJohn Marino 
2353*e4b17023SJohn Marino       if (val && TREE_CODE (val) == INTEGER_CST && find_taken_edge (bb, val))
2354*e4b17023SJohn Marino 	cfg_altered = true;
2355*e4b17023SJohn Marino 
2356*e4b17023SJohn Marino       /* If we simplified a statement in such a way as to be shown that it
2357*e4b17023SJohn Marino 	 cannot trap, update the eh information and the cfg to match.  */
2358*e4b17023SJohn Marino       if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
2359*e4b17023SJohn Marino 	{
2360*e4b17023SJohn Marino 	  bitmap_set_bit (need_eh_cleanup, bb->index);
2361*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2362*e4b17023SJohn Marino 	    fprintf (dump_file, "  Flagged to clear EH edges.\n");
2363*e4b17023SJohn Marino 	}
2364*e4b17023SJohn Marino     }
2365*e4b17023SJohn Marino }
2366*e4b17023SJohn Marino 
2367*e4b17023SJohn Marino /* Search for an existing instance of STMT in the AVAIL_EXPRS table.
2368*e4b17023SJohn Marino    If found, return its LHS. Otherwise insert STMT in the table and
2369*e4b17023SJohn Marino    return NULL_TREE.
2370*e4b17023SJohn Marino 
2371*e4b17023SJohn Marino    Also, when an expression is first inserted in the  table, it is also
2372*e4b17023SJohn Marino    is also added to AVAIL_EXPRS_STACK, so that it can be removed when
2373*e4b17023SJohn Marino    we finish processing this block and its children.  */
2374*e4b17023SJohn Marino 
2375*e4b17023SJohn Marino static tree
lookup_avail_expr(gimple stmt,bool insert)2376*e4b17023SJohn Marino lookup_avail_expr (gimple stmt, bool insert)
2377*e4b17023SJohn Marino {
2378*e4b17023SJohn Marino   void **slot;
2379*e4b17023SJohn Marino   tree lhs;
2380*e4b17023SJohn Marino   tree temp;
2381*e4b17023SJohn Marino   struct expr_hash_elt element;
2382*e4b17023SJohn Marino 
2383*e4b17023SJohn Marino   /* Get LHS of phi, assignment, or call; else NULL_TREE.  */
2384*e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_PHI)
2385*e4b17023SJohn Marino     lhs = gimple_phi_result (stmt);
2386*e4b17023SJohn Marino   else
2387*e4b17023SJohn Marino     lhs = gimple_get_lhs (stmt);
2388*e4b17023SJohn Marino 
2389*e4b17023SJohn Marino   initialize_hash_element (stmt, lhs, &element);
2390*e4b17023SJohn Marino 
2391*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2392*e4b17023SJohn Marino     {
2393*e4b17023SJohn Marino       fprintf (dump_file, "LKUP ");
2394*e4b17023SJohn Marino       print_expr_hash_elt (dump_file, &element);
2395*e4b17023SJohn Marino     }
2396*e4b17023SJohn Marino 
2397*e4b17023SJohn Marino   /* Don't bother remembering constant assignments and copy operations.
2398*e4b17023SJohn Marino      Constants and copy operations are handled by the constant/copy propagator
2399*e4b17023SJohn Marino      in optimize_stmt.  */
2400*e4b17023SJohn Marino   if (element.expr.kind == EXPR_SINGLE
2401*e4b17023SJohn Marino       && (TREE_CODE (element.expr.ops.single.rhs) == SSA_NAME
2402*e4b17023SJohn Marino           || is_gimple_min_invariant (element.expr.ops.single.rhs)))
2403*e4b17023SJohn Marino     return NULL_TREE;
2404*e4b17023SJohn Marino 
2405*e4b17023SJohn Marino   /* Finally try to find the expression in the main expression hash table.  */
2406*e4b17023SJohn Marino   slot = htab_find_slot_with_hash (avail_exprs, &element, element.hash,
2407*e4b17023SJohn Marino 				   (insert ? INSERT : NO_INSERT));
2408*e4b17023SJohn Marino   if (slot == NULL)
2409*e4b17023SJohn Marino     return NULL_TREE;
2410*e4b17023SJohn Marino 
2411*e4b17023SJohn Marino   if (*slot == NULL)
2412*e4b17023SJohn Marino     {
2413*e4b17023SJohn Marino       struct expr_hash_elt *element2 = XNEW (struct expr_hash_elt);
2414*e4b17023SJohn Marino       *element2 = element;
2415*e4b17023SJohn Marino       element2->stamp = element2;
2416*e4b17023SJohn Marino       *slot = (void *) element2;
2417*e4b17023SJohn Marino 
2418*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2419*e4b17023SJohn Marino         {
2420*e4b17023SJohn Marino           fprintf (dump_file, "2>>> ");
2421*e4b17023SJohn Marino           print_expr_hash_elt (dump_file, element2);
2422*e4b17023SJohn Marino         }
2423*e4b17023SJohn Marino 
2424*e4b17023SJohn Marino       VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, element2);
2425*e4b17023SJohn Marino       return NULL_TREE;
2426*e4b17023SJohn Marino     }
2427*e4b17023SJohn Marino 
2428*e4b17023SJohn Marino   /* Extract the LHS of the assignment so that it can be used as the current
2429*e4b17023SJohn Marino      definition of another variable.  */
2430*e4b17023SJohn Marino   lhs = ((struct expr_hash_elt *)*slot)->lhs;
2431*e4b17023SJohn Marino 
2432*e4b17023SJohn Marino   /* See if the LHS appears in the CONST_AND_COPIES table.  If it does, then
2433*e4b17023SJohn Marino      use the value from the const_and_copies table.  */
2434*e4b17023SJohn Marino   if (TREE_CODE (lhs) == SSA_NAME)
2435*e4b17023SJohn Marino     {
2436*e4b17023SJohn Marino       temp = SSA_NAME_VALUE (lhs);
2437*e4b17023SJohn Marino       if (temp)
2438*e4b17023SJohn Marino 	lhs = temp;
2439*e4b17023SJohn Marino     }
2440*e4b17023SJohn Marino 
2441*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2442*e4b17023SJohn Marino     {
2443*e4b17023SJohn Marino       fprintf (dump_file, "FIND: ");
2444*e4b17023SJohn Marino       print_generic_expr (dump_file, lhs, 0);
2445*e4b17023SJohn Marino       fprintf (dump_file, "\n");
2446*e4b17023SJohn Marino     }
2447*e4b17023SJohn Marino 
2448*e4b17023SJohn Marino   return lhs;
2449*e4b17023SJohn Marino }
2450*e4b17023SJohn Marino 
2451*e4b17023SJohn Marino /* Hashing and equality functions for AVAIL_EXPRS.  We compute a value number
2452*e4b17023SJohn Marino    for expressions using the code of the expression and the SSA numbers of
2453*e4b17023SJohn Marino    its operands.  */
2454*e4b17023SJohn Marino 
2455*e4b17023SJohn Marino static hashval_t
avail_expr_hash(const void * p)2456*e4b17023SJohn Marino avail_expr_hash (const void *p)
2457*e4b17023SJohn Marino {
2458*e4b17023SJohn Marino   gimple stmt = ((const struct expr_hash_elt *)p)->stmt;
2459*e4b17023SJohn Marino   const struct hashable_expr *expr = &((const struct expr_hash_elt *)p)->expr;
2460*e4b17023SJohn Marino   tree vuse;
2461*e4b17023SJohn Marino   hashval_t val = 0;
2462*e4b17023SJohn Marino 
2463*e4b17023SJohn Marino   val = iterative_hash_hashable_expr (expr, val);
2464*e4b17023SJohn Marino 
2465*e4b17023SJohn Marino   /* If the hash table entry is not associated with a statement, then we
2466*e4b17023SJohn Marino      can just hash the expression and not worry about virtual operands
2467*e4b17023SJohn Marino      and such.  */
2468*e4b17023SJohn Marino   if (!stmt)
2469*e4b17023SJohn Marino     return val;
2470*e4b17023SJohn Marino 
2471*e4b17023SJohn Marino   /* Add the SSA version numbers of the vuse operand.  This is important
2472*e4b17023SJohn Marino      because compound variables like arrays are not renamed in the
2473*e4b17023SJohn Marino      operands.  Rather, the rename is done on the virtual variable
2474*e4b17023SJohn Marino      representing all the elements of the array.  */
2475*e4b17023SJohn Marino   if ((vuse = gimple_vuse (stmt)))
2476*e4b17023SJohn Marino     val = iterative_hash_expr (vuse, val);
2477*e4b17023SJohn Marino 
2478*e4b17023SJohn Marino   return val;
2479*e4b17023SJohn Marino }
2480*e4b17023SJohn Marino 
2481*e4b17023SJohn Marino static hashval_t
real_avail_expr_hash(const void * p)2482*e4b17023SJohn Marino real_avail_expr_hash (const void *p)
2483*e4b17023SJohn Marino {
2484*e4b17023SJohn Marino   return ((const struct expr_hash_elt *)p)->hash;
2485*e4b17023SJohn Marino }
2486*e4b17023SJohn Marino 
2487*e4b17023SJohn Marino static int
avail_expr_eq(const void * p1,const void * p2)2488*e4b17023SJohn Marino avail_expr_eq (const void *p1, const void *p2)
2489*e4b17023SJohn Marino {
2490*e4b17023SJohn Marino   gimple stmt1 = ((const struct expr_hash_elt *)p1)->stmt;
2491*e4b17023SJohn Marino   const struct hashable_expr *expr1 = &((const struct expr_hash_elt *)p1)->expr;
2492*e4b17023SJohn Marino   const struct expr_hash_elt *stamp1 = ((const struct expr_hash_elt *)p1)->stamp;
2493*e4b17023SJohn Marino   gimple stmt2 = ((const struct expr_hash_elt *)p2)->stmt;
2494*e4b17023SJohn Marino   const struct hashable_expr *expr2 = &((const struct expr_hash_elt *)p2)->expr;
2495*e4b17023SJohn Marino   const struct expr_hash_elt *stamp2 = ((const struct expr_hash_elt *)p2)->stamp;
2496*e4b17023SJohn Marino 
2497*e4b17023SJohn Marino   /* This case should apply only when removing entries from the table.  */
2498*e4b17023SJohn Marino   if (stamp1 == stamp2)
2499*e4b17023SJohn Marino     return true;
2500*e4b17023SJohn Marino 
2501*e4b17023SJohn Marino   /* FIXME tuples:
2502*e4b17023SJohn Marino      We add stmts to a hash table and them modify them. To detect the case
2503*e4b17023SJohn Marino      that we modify a stmt and then search for it, we assume that the hash
2504*e4b17023SJohn Marino      is always modified by that change.
2505*e4b17023SJohn Marino      We have to fully check why this doesn't happen on trunk or rewrite
2506*e4b17023SJohn Marino      this in a more  reliable (and easier to understand) way. */
2507*e4b17023SJohn Marino   if (((const struct expr_hash_elt *)p1)->hash
2508*e4b17023SJohn Marino       != ((const struct expr_hash_elt *)p2)->hash)
2509*e4b17023SJohn Marino     return false;
2510*e4b17023SJohn Marino 
2511*e4b17023SJohn Marino   /* In case of a collision, both RHS have to be identical and have the
2512*e4b17023SJohn Marino      same VUSE operands.  */
2513*e4b17023SJohn Marino   if (hashable_expr_equal_p (expr1, expr2)
2514*e4b17023SJohn Marino       && types_compatible_p (expr1->type, expr2->type))
2515*e4b17023SJohn Marino     {
2516*e4b17023SJohn Marino       /* Note that STMT1 and/or STMT2 may be NULL.  */
2517*e4b17023SJohn Marino       return ((stmt1 ? gimple_vuse (stmt1) : NULL_TREE)
2518*e4b17023SJohn Marino 	      == (stmt2 ? gimple_vuse (stmt2) : NULL_TREE));
2519*e4b17023SJohn Marino     }
2520*e4b17023SJohn Marino 
2521*e4b17023SJohn Marino   return false;
2522*e4b17023SJohn Marino }
2523*e4b17023SJohn Marino 
2524*e4b17023SJohn Marino /* PHI-ONLY copy and constant propagation.  This pass is meant to clean
2525*e4b17023SJohn Marino    up degenerate PHIs created by or exposed by jump threading.  */
2526*e4b17023SJohn Marino 
2527*e4b17023SJohn Marino /* Given PHI, return its RHS if the PHI is a degenerate, otherwise return
2528*e4b17023SJohn Marino    NULL.  */
2529*e4b17023SJohn Marino 
2530*e4b17023SJohn Marino tree
degenerate_phi_result(gimple phi)2531*e4b17023SJohn Marino degenerate_phi_result (gimple phi)
2532*e4b17023SJohn Marino {
2533*e4b17023SJohn Marino   tree lhs = gimple_phi_result (phi);
2534*e4b17023SJohn Marino   tree val = NULL;
2535*e4b17023SJohn Marino   size_t i;
2536*e4b17023SJohn Marino 
2537*e4b17023SJohn Marino   /* Ignoring arguments which are the same as LHS, if all the remaining
2538*e4b17023SJohn Marino      arguments are the same, then the PHI is a degenerate and has the
2539*e4b17023SJohn Marino      value of that common argument.  */
2540*e4b17023SJohn Marino   for (i = 0; i < gimple_phi_num_args (phi); i++)
2541*e4b17023SJohn Marino     {
2542*e4b17023SJohn Marino       tree arg = gimple_phi_arg_def (phi, i);
2543*e4b17023SJohn Marino 
2544*e4b17023SJohn Marino       if (arg == lhs)
2545*e4b17023SJohn Marino 	continue;
2546*e4b17023SJohn Marino       else if (!arg)
2547*e4b17023SJohn Marino 	break;
2548*e4b17023SJohn Marino       else if (!val)
2549*e4b17023SJohn Marino 	val = arg;
2550*e4b17023SJohn Marino       else if (arg == val)
2551*e4b17023SJohn Marino 	continue;
2552*e4b17023SJohn Marino       /* We bring in some of operand_equal_p not only to speed things
2553*e4b17023SJohn Marino 	 up, but also to avoid crashing when dereferencing the type of
2554*e4b17023SJohn Marino 	 a released SSA name.  */
2555*e4b17023SJohn Marino       else if (TREE_CODE (val) != TREE_CODE (arg)
2556*e4b17023SJohn Marino 	       || TREE_CODE (val) == SSA_NAME
2557*e4b17023SJohn Marino 	       || !operand_equal_p (arg, val, 0))
2558*e4b17023SJohn Marino 	break;
2559*e4b17023SJohn Marino     }
2560*e4b17023SJohn Marino   return (i == gimple_phi_num_args (phi) ? val : NULL);
2561*e4b17023SJohn Marino }
2562*e4b17023SJohn Marino 
2563*e4b17023SJohn Marino /* Given a statement STMT, which is either a PHI node or an assignment,
2564*e4b17023SJohn Marino    remove it from the IL.  */
2565*e4b17023SJohn Marino 
2566*e4b17023SJohn Marino static void
remove_stmt_or_phi(gimple stmt)2567*e4b17023SJohn Marino remove_stmt_or_phi (gimple stmt)
2568*e4b17023SJohn Marino {
2569*e4b17023SJohn Marino   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
2570*e4b17023SJohn Marino 
2571*e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_PHI)
2572*e4b17023SJohn Marino     remove_phi_node (&gsi, true);
2573*e4b17023SJohn Marino   else
2574*e4b17023SJohn Marino     {
2575*e4b17023SJohn Marino       gsi_remove (&gsi, true);
2576*e4b17023SJohn Marino       release_defs (stmt);
2577*e4b17023SJohn Marino     }
2578*e4b17023SJohn Marino }
2579*e4b17023SJohn Marino 
2580*e4b17023SJohn Marino /* Given a statement STMT, which is either a PHI node or an assignment,
2581*e4b17023SJohn Marino    return the "rhs" of the node, in the case of a non-degenerate
2582*e4b17023SJohn Marino    phi, NULL is returned.  */
2583*e4b17023SJohn Marino 
2584*e4b17023SJohn Marino static tree
get_rhs_or_phi_arg(gimple stmt)2585*e4b17023SJohn Marino get_rhs_or_phi_arg (gimple stmt)
2586*e4b17023SJohn Marino {
2587*e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_PHI)
2588*e4b17023SJohn Marino     return degenerate_phi_result (stmt);
2589*e4b17023SJohn Marino   else if (gimple_assign_single_p (stmt))
2590*e4b17023SJohn Marino     return gimple_assign_rhs1 (stmt);
2591*e4b17023SJohn Marino   else
2592*e4b17023SJohn Marino     gcc_unreachable ();
2593*e4b17023SJohn Marino }
2594*e4b17023SJohn Marino 
2595*e4b17023SJohn Marino 
2596*e4b17023SJohn Marino /* Given a statement STMT, which is either a PHI node or an assignment,
2597*e4b17023SJohn Marino    return the "lhs" of the node.  */
2598*e4b17023SJohn Marino 
2599*e4b17023SJohn Marino static tree
get_lhs_or_phi_result(gimple stmt)2600*e4b17023SJohn Marino get_lhs_or_phi_result (gimple stmt)
2601*e4b17023SJohn Marino {
2602*e4b17023SJohn Marino   if (gimple_code (stmt) == GIMPLE_PHI)
2603*e4b17023SJohn Marino     return gimple_phi_result (stmt);
2604*e4b17023SJohn Marino   else if (is_gimple_assign (stmt))
2605*e4b17023SJohn Marino     return gimple_assign_lhs (stmt);
2606*e4b17023SJohn Marino   else
2607*e4b17023SJohn Marino     gcc_unreachable ();
2608*e4b17023SJohn Marino }
2609*e4b17023SJohn Marino 
2610*e4b17023SJohn Marino /* Propagate RHS into all uses of LHS (when possible).
2611*e4b17023SJohn Marino 
2612*e4b17023SJohn Marino    RHS and LHS are derived from STMT, which is passed in solely so
2613*e4b17023SJohn Marino    that we can remove it if propagation is successful.
2614*e4b17023SJohn Marino 
2615*e4b17023SJohn Marino    When propagating into a PHI node or into a statement which turns
2616*e4b17023SJohn Marino    into a trivial copy or constant initialization, set the
2617*e4b17023SJohn Marino    appropriate bit in INTERESTING_NAMEs so that we will visit those
2618*e4b17023SJohn Marino    nodes as well in an effort to pick up secondary optimization
2619*e4b17023SJohn Marino    opportunities.  */
2620*e4b17023SJohn Marino 
2621*e4b17023SJohn Marino static void
propagate_rhs_into_lhs(gimple stmt,tree lhs,tree rhs,bitmap interesting_names)2622*e4b17023SJohn Marino propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_names)
2623*e4b17023SJohn Marino {
2624*e4b17023SJohn Marino   /* First verify that propagation is valid and isn't going to move a
2625*e4b17023SJohn Marino      loop variant variable outside its loop.  */
2626*e4b17023SJohn Marino   if (! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)
2627*e4b17023SJohn Marino       && (TREE_CODE (rhs) != SSA_NAME
2628*e4b17023SJohn Marino 	  || ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs))
2629*e4b17023SJohn Marino       && may_propagate_copy (lhs, rhs)
2630*e4b17023SJohn Marino       && loop_depth_of_name (lhs) >= loop_depth_of_name (rhs))
2631*e4b17023SJohn Marino     {
2632*e4b17023SJohn Marino       use_operand_p use_p;
2633*e4b17023SJohn Marino       imm_use_iterator iter;
2634*e4b17023SJohn Marino       gimple use_stmt;
2635*e4b17023SJohn Marino       bool all = true;
2636*e4b17023SJohn Marino 
2637*e4b17023SJohn Marino       /* Dump details.  */
2638*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2639*e4b17023SJohn Marino 	{
2640*e4b17023SJohn Marino 	  fprintf (dump_file, "  Replacing '");
2641*e4b17023SJohn Marino 	  print_generic_expr (dump_file, lhs, dump_flags);
2642*e4b17023SJohn Marino 	  fprintf (dump_file, "' with %s '",
2643*e4b17023SJohn Marino 	           (TREE_CODE (rhs) != SSA_NAME ? "constant" : "variable"));
2644*e4b17023SJohn Marino 		   print_generic_expr (dump_file, rhs, dump_flags);
2645*e4b17023SJohn Marino 	  fprintf (dump_file, "'\n");
2646*e4b17023SJohn Marino 	}
2647*e4b17023SJohn Marino 
2648*e4b17023SJohn Marino       /* Walk over every use of LHS and try to replace the use with RHS.
2649*e4b17023SJohn Marino 	 At this point the only reason why such a propagation would not
2650*e4b17023SJohn Marino 	 be successful would be if the use occurs in an ASM_EXPR.  */
2651*e4b17023SJohn Marino       FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
2652*e4b17023SJohn Marino 	{
2653*e4b17023SJohn Marino 	  /* Leave debug stmts alone.  If we succeed in propagating
2654*e4b17023SJohn Marino 	     all non-debug uses, we'll drop the DEF, and propagation
2655*e4b17023SJohn Marino 	     into debug stmts will occur then.  */
2656*e4b17023SJohn Marino 	  if (gimple_debug_bind_p (use_stmt))
2657*e4b17023SJohn Marino 	    continue;
2658*e4b17023SJohn Marino 
2659*e4b17023SJohn Marino 	  /* It's not always safe to propagate into an ASM_EXPR.  */
2660*e4b17023SJohn Marino 	  if (gimple_code (use_stmt) == GIMPLE_ASM
2661*e4b17023SJohn Marino               && ! may_propagate_copy_into_asm (lhs))
2662*e4b17023SJohn Marino 	    {
2663*e4b17023SJohn Marino 	      all = false;
2664*e4b17023SJohn Marino 	      continue;
2665*e4b17023SJohn Marino 	    }
2666*e4b17023SJohn Marino 
2667*e4b17023SJohn Marino 	  /* It's not ok to propagate into the definition stmt of RHS.
2668*e4b17023SJohn Marino 		<bb 9>:
2669*e4b17023SJohn Marino 		  # prephitmp.12_36 = PHI <g_67.1_6(9)>
2670*e4b17023SJohn Marino 		  g_67.1_6 = prephitmp.12_36;
2671*e4b17023SJohn Marino 		  goto <bb 9>;
2672*e4b17023SJohn Marino 	     While this is strictly all dead code we do not want to
2673*e4b17023SJohn Marino 	     deal with this here.  */
2674*e4b17023SJohn Marino 	  if (TREE_CODE (rhs) == SSA_NAME
2675*e4b17023SJohn Marino 	      && SSA_NAME_DEF_STMT (rhs) == use_stmt)
2676*e4b17023SJohn Marino 	    {
2677*e4b17023SJohn Marino 	      all = false;
2678*e4b17023SJohn Marino 	      continue;
2679*e4b17023SJohn Marino 	    }
2680*e4b17023SJohn Marino 
2681*e4b17023SJohn Marino 	  /* Dump details.  */
2682*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2683*e4b17023SJohn Marino 	    {
2684*e4b17023SJohn Marino 	      fprintf (dump_file, "    Original statement:");
2685*e4b17023SJohn Marino 	      print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
2686*e4b17023SJohn Marino 	    }
2687*e4b17023SJohn Marino 
2688*e4b17023SJohn Marino 	  /* Propagate the RHS into this use of the LHS.  */
2689*e4b17023SJohn Marino 	  FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
2690*e4b17023SJohn Marino 	    propagate_value (use_p, rhs);
2691*e4b17023SJohn Marino 
2692*e4b17023SJohn Marino 	  /* Special cases to avoid useless calls into the folding
2693*e4b17023SJohn Marino 	     routines, operand scanning, etc.
2694*e4b17023SJohn Marino 
2695*e4b17023SJohn Marino 	     First, propagation into a PHI may cause the PHI to become
2696*e4b17023SJohn Marino 	     a degenerate, so mark the PHI as interesting.  No other
2697*e4b17023SJohn Marino 	     actions are necessary.
2698*e4b17023SJohn Marino 
2699*e4b17023SJohn Marino 	     Second, if we're propagating a virtual operand and the
2700*e4b17023SJohn Marino 	     propagation does not change the underlying _DECL node for
2701*e4b17023SJohn Marino 	     the virtual operand, then no further actions are necessary.  */
2702*e4b17023SJohn Marino 	  if (gimple_code (use_stmt) == GIMPLE_PHI
2703*e4b17023SJohn Marino 	      || (! is_gimple_reg (lhs)
2704*e4b17023SJohn Marino 		  && TREE_CODE (rhs) == SSA_NAME
2705*e4b17023SJohn Marino 		  && SSA_NAME_VAR (lhs) == SSA_NAME_VAR (rhs)))
2706*e4b17023SJohn Marino 	    {
2707*e4b17023SJohn Marino 	      /* Dump details.  */
2708*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
2709*e4b17023SJohn Marino 		{
2710*e4b17023SJohn Marino 		  fprintf (dump_file, "    Updated statement:");
2711*e4b17023SJohn Marino 		  print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
2712*e4b17023SJohn Marino 		}
2713*e4b17023SJohn Marino 
2714*e4b17023SJohn Marino 	      /* Propagation into a PHI may expose new degenerate PHIs,
2715*e4b17023SJohn Marino 		 so mark the result of the PHI as interesting.  */
2716*e4b17023SJohn Marino 	      if (gimple_code (use_stmt) == GIMPLE_PHI)
2717*e4b17023SJohn Marino 		{
2718*e4b17023SJohn Marino 		  tree result = get_lhs_or_phi_result (use_stmt);
2719*e4b17023SJohn Marino 		  bitmap_set_bit (interesting_names, SSA_NAME_VERSION (result));
2720*e4b17023SJohn Marino 		}
2721*e4b17023SJohn Marino 
2722*e4b17023SJohn Marino 	      continue;
2723*e4b17023SJohn Marino 	    }
2724*e4b17023SJohn Marino 
2725*e4b17023SJohn Marino 	  /* From this point onward we are propagating into a
2726*e4b17023SJohn Marino 	     real statement.  Folding may (or may not) be possible,
2727*e4b17023SJohn Marino 	     we may expose new operands, expose dead EH edges,
2728*e4b17023SJohn Marino 	     etc.  */
2729*e4b17023SJohn Marino           /* NOTE tuples. In the tuples world, fold_stmt_inplace
2730*e4b17023SJohn Marino              cannot fold a call that simplifies to a constant,
2731*e4b17023SJohn Marino              because the GIMPLE_CALL must be replaced by a
2732*e4b17023SJohn Marino              GIMPLE_ASSIGN, and there is no way to effect such a
2733*e4b17023SJohn Marino              transformation in-place.  We might want to consider
2734*e4b17023SJohn Marino              using the more general fold_stmt here.  */
2735*e4b17023SJohn Marino 	    {
2736*e4b17023SJohn Marino 	      gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
2737*e4b17023SJohn Marino 	      fold_stmt_inplace (&gsi);
2738*e4b17023SJohn Marino 	    }
2739*e4b17023SJohn Marino 
2740*e4b17023SJohn Marino 	  /* Sometimes propagation can expose new operands to the
2741*e4b17023SJohn Marino 	     renamer.  */
2742*e4b17023SJohn Marino 	  update_stmt (use_stmt);
2743*e4b17023SJohn Marino 
2744*e4b17023SJohn Marino 	  /* Dump details.  */
2745*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2746*e4b17023SJohn Marino 	    {
2747*e4b17023SJohn Marino 	      fprintf (dump_file, "    Updated statement:");
2748*e4b17023SJohn Marino 	      print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
2749*e4b17023SJohn Marino 	    }
2750*e4b17023SJohn Marino 
2751*e4b17023SJohn Marino 	  /* If we replaced a variable index with a constant, then
2752*e4b17023SJohn Marino 	     we would need to update the invariant flag for ADDR_EXPRs.  */
2753*e4b17023SJohn Marino           if (gimple_assign_single_p (use_stmt)
2754*e4b17023SJohn Marino               && TREE_CODE (gimple_assign_rhs1 (use_stmt)) == ADDR_EXPR)
2755*e4b17023SJohn Marino 	    recompute_tree_invariant_for_addr_expr
2756*e4b17023SJohn Marino                 (gimple_assign_rhs1 (use_stmt));
2757*e4b17023SJohn Marino 
2758*e4b17023SJohn Marino 	  /* If we cleaned up EH information from the statement,
2759*e4b17023SJohn Marino 	     mark its containing block as needing EH cleanups.  */
2760*e4b17023SJohn Marino 	  if (maybe_clean_or_replace_eh_stmt (use_stmt, use_stmt))
2761*e4b17023SJohn Marino 	    {
2762*e4b17023SJohn Marino 	      bitmap_set_bit (need_eh_cleanup, gimple_bb (use_stmt)->index);
2763*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
2764*e4b17023SJohn Marino 		fprintf (dump_file, "  Flagged to clear EH edges.\n");
2765*e4b17023SJohn Marino 	    }
2766*e4b17023SJohn Marino 
2767*e4b17023SJohn Marino 	  /* Propagation may expose new trivial copy/constant propagation
2768*e4b17023SJohn Marino 	     opportunities.  */
2769*e4b17023SJohn Marino           if (gimple_assign_single_p (use_stmt)
2770*e4b17023SJohn Marino               && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
2771*e4b17023SJohn Marino               && (TREE_CODE (gimple_assign_rhs1 (use_stmt)) == SSA_NAME
2772*e4b17023SJohn Marino                   || is_gimple_min_invariant (gimple_assign_rhs1 (use_stmt))))
2773*e4b17023SJohn Marino             {
2774*e4b17023SJohn Marino 	      tree result = get_lhs_or_phi_result (use_stmt);
2775*e4b17023SJohn Marino 	      bitmap_set_bit (interesting_names, SSA_NAME_VERSION (result));
2776*e4b17023SJohn Marino 	    }
2777*e4b17023SJohn Marino 
2778*e4b17023SJohn Marino 	  /* Propagation into these nodes may make certain edges in
2779*e4b17023SJohn Marino 	     the CFG unexecutable.  We want to identify them as PHI nodes
2780*e4b17023SJohn Marino 	     at the destination of those unexecutable edges may become
2781*e4b17023SJohn Marino 	     degenerates.  */
2782*e4b17023SJohn Marino 	  else if (gimple_code (use_stmt) == GIMPLE_COND
2783*e4b17023SJohn Marino 		   || gimple_code (use_stmt) == GIMPLE_SWITCH
2784*e4b17023SJohn Marino 		   || gimple_code (use_stmt) == GIMPLE_GOTO)
2785*e4b17023SJohn Marino             {
2786*e4b17023SJohn Marino 	      tree val;
2787*e4b17023SJohn Marino 
2788*e4b17023SJohn Marino 	      if (gimple_code (use_stmt) == GIMPLE_COND)
2789*e4b17023SJohn Marino                 val = fold_binary_loc (gimple_location (use_stmt),
2790*e4b17023SJohn Marino 				   gimple_cond_code (use_stmt),
2791*e4b17023SJohn Marino                                    boolean_type_node,
2792*e4b17023SJohn Marino                                    gimple_cond_lhs (use_stmt),
2793*e4b17023SJohn Marino                                    gimple_cond_rhs (use_stmt));
2794*e4b17023SJohn Marino               else if (gimple_code (use_stmt) == GIMPLE_SWITCH)
2795*e4b17023SJohn Marino 		val = gimple_switch_index (use_stmt);
2796*e4b17023SJohn Marino 	      else
2797*e4b17023SJohn Marino 		val = gimple_goto_dest  (use_stmt);
2798*e4b17023SJohn Marino 
2799*e4b17023SJohn Marino 	      if (val && is_gimple_min_invariant (val))
2800*e4b17023SJohn Marino 		{
2801*e4b17023SJohn Marino 		  basic_block bb = gimple_bb (use_stmt);
2802*e4b17023SJohn Marino 		  edge te = find_taken_edge (bb, val);
2803*e4b17023SJohn Marino 		  edge_iterator ei;
2804*e4b17023SJohn Marino 		  edge e;
2805*e4b17023SJohn Marino 		  gimple_stmt_iterator gsi, psi;
2806*e4b17023SJohn Marino 
2807*e4b17023SJohn Marino 		  /* Remove all outgoing edges except TE.  */
2808*e4b17023SJohn Marino 		  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei));)
2809*e4b17023SJohn Marino 		    {
2810*e4b17023SJohn Marino 		      if (e != te)
2811*e4b17023SJohn Marino 			{
2812*e4b17023SJohn Marino 			  /* Mark all the PHI nodes at the destination of
2813*e4b17023SJohn Marino 			     the unexecutable edge as interesting.  */
2814*e4b17023SJohn Marino                           for (psi = gsi_start_phis (e->dest);
2815*e4b17023SJohn Marino                                !gsi_end_p (psi);
2816*e4b17023SJohn Marino                                gsi_next (&psi))
2817*e4b17023SJohn Marino                             {
2818*e4b17023SJohn Marino                               gimple phi = gsi_stmt (psi);
2819*e4b17023SJohn Marino 
2820*e4b17023SJohn Marino 			      tree result = gimple_phi_result (phi);
2821*e4b17023SJohn Marino 			      int version = SSA_NAME_VERSION (result);
2822*e4b17023SJohn Marino 
2823*e4b17023SJohn Marino 			      bitmap_set_bit (interesting_names, version);
2824*e4b17023SJohn Marino 			    }
2825*e4b17023SJohn Marino 
2826*e4b17023SJohn Marino 			  te->probability += e->probability;
2827*e4b17023SJohn Marino 
2828*e4b17023SJohn Marino 			  te->count += e->count;
2829*e4b17023SJohn Marino 			  remove_edge (e);
2830*e4b17023SJohn Marino 			  cfg_altered = true;
2831*e4b17023SJohn Marino 			}
2832*e4b17023SJohn Marino 		      else
2833*e4b17023SJohn Marino 			ei_next (&ei);
2834*e4b17023SJohn Marino 		    }
2835*e4b17023SJohn Marino 
2836*e4b17023SJohn Marino 		  gsi = gsi_last_bb (gimple_bb (use_stmt));
2837*e4b17023SJohn Marino 		  gsi_remove (&gsi, true);
2838*e4b17023SJohn Marino 
2839*e4b17023SJohn Marino 		  /* And fixup the flags on the single remaining edge.  */
2840*e4b17023SJohn Marino 		  te->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
2841*e4b17023SJohn Marino 		  te->flags &= ~EDGE_ABNORMAL;
2842*e4b17023SJohn Marino 		  te->flags |= EDGE_FALLTHRU;
2843*e4b17023SJohn Marino 		  if (te->probability > REG_BR_PROB_BASE)
2844*e4b17023SJohn Marino 		    te->probability = REG_BR_PROB_BASE;
2845*e4b17023SJohn Marino 	        }
2846*e4b17023SJohn Marino 	    }
2847*e4b17023SJohn Marino 	}
2848*e4b17023SJohn Marino 
2849*e4b17023SJohn Marino       /* Ensure there is nothing else to do. */
2850*e4b17023SJohn Marino       gcc_assert (!all || has_zero_uses (lhs));
2851*e4b17023SJohn Marino 
2852*e4b17023SJohn Marino       /* If we were able to propagate away all uses of LHS, then
2853*e4b17023SJohn Marino 	 we can remove STMT.  */
2854*e4b17023SJohn Marino       if (all)
2855*e4b17023SJohn Marino 	remove_stmt_or_phi (stmt);
2856*e4b17023SJohn Marino     }
2857*e4b17023SJohn Marino }
2858*e4b17023SJohn Marino 
2859*e4b17023SJohn Marino /* STMT is either a PHI node (potentially a degenerate PHI node) or
2860*e4b17023SJohn Marino    a statement that is a trivial copy or constant initialization.
2861*e4b17023SJohn Marino 
2862*e4b17023SJohn Marino    Attempt to eliminate T by propagating its RHS into all uses of
2863*e4b17023SJohn Marino    its LHS.  This may in turn set new bits in INTERESTING_NAMES
2864*e4b17023SJohn Marino    for nodes we want to revisit later.
2865*e4b17023SJohn Marino 
2866*e4b17023SJohn Marino    All exit paths should clear INTERESTING_NAMES for the result
2867*e4b17023SJohn Marino    of STMT.  */
2868*e4b17023SJohn Marino 
2869*e4b17023SJohn Marino static void
eliminate_const_or_copy(gimple stmt,bitmap interesting_names)2870*e4b17023SJohn Marino eliminate_const_or_copy (gimple stmt, bitmap interesting_names)
2871*e4b17023SJohn Marino {
2872*e4b17023SJohn Marino   tree lhs = get_lhs_or_phi_result (stmt);
2873*e4b17023SJohn Marino   tree rhs;
2874*e4b17023SJohn Marino   int version = SSA_NAME_VERSION (lhs);
2875*e4b17023SJohn Marino 
2876*e4b17023SJohn Marino   /* If the LHS of this statement or PHI has no uses, then we can
2877*e4b17023SJohn Marino      just eliminate it.  This can occur if, for example, the PHI
2878*e4b17023SJohn Marino      was created by block duplication due to threading and its only
2879*e4b17023SJohn Marino      use was in the conditional at the end of the block which was
2880*e4b17023SJohn Marino      deleted.  */
2881*e4b17023SJohn Marino   if (has_zero_uses (lhs))
2882*e4b17023SJohn Marino     {
2883*e4b17023SJohn Marino       bitmap_clear_bit (interesting_names, version);
2884*e4b17023SJohn Marino       remove_stmt_or_phi (stmt);
2885*e4b17023SJohn Marino       return;
2886*e4b17023SJohn Marino     }
2887*e4b17023SJohn Marino 
2888*e4b17023SJohn Marino   /* Get the RHS of the assignment or PHI node if the PHI is a
2889*e4b17023SJohn Marino      degenerate.  */
2890*e4b17023SJohn Marino   rhs = get_rhs_or_phi_arg (stmt);
2891*e4b17023SJohn Marino   if (!rhs)
2892*e4b17023SJohn Marino     {
2893*e4b17023SJohn Marino       bitmap_clear_bit (interesting_names, version);
2894*e4b17023SJohn Marino       return;
2895*e4b17023SJohn Marino     }
2896*e4b17023SJohn Marino 
2897*e4b17023SJohn Marino   propagate_rhs_into_lhs (stmt, lhs, rhs, interesting_names);
2898*e4b17023SJohn Marino 
2899*e4b17023SJohn Marino   /* Note that STMT may well have been deleted by now, so do
2900*e4b17023SJohn Marino      not access it, instead use the saved version # to clear
2901*e4b17023SJohn Marino      T's entry in the worklist.  */
2902*e4b17023SJohn Marino   bitmap_clear_bit (interesting_names, version);
2903*e4b17023SJohn Marino }
2904*e4b17023SJohn Marino 
2905*e4b17023SJohn Marino /* The first phase in degenerate PHI elimination.
2906*e4b17023SJohn Marino 
2907*e4b17023SJohn Marino    Eliminate the degenerate PHIs in BB, then recurse on the
2908*e4b17023SJohn Marino    dominator children of BB.  */
2909*e4b17023SJohn Marino 
2910*e4b17023SJohn Marino static void
eliminate_degenerate_phis_1(basic_block bb,bitmap interesting_names)2911*e4b17023SJohn Marino eliminate_degenerate_phis_1 (basic_block bb, bitmap interesting_names)
2912*e4b17023SJohn Marino {
2913*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
2914*e4b17023SJohn Marino   basic_block son;
2915*e4b17023SJohn Marino 
2916*e4b17023SJohn Marino   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2917*e4b17023SJohn Marino     {
2918*e4b17023SJohn Marino       gimple phi = gsi_stmt (gsi);
2919*e4b17023SJohn Marino 
2920*e4b17023SJohn Marino       eliminate_const_or_copy (phi, interesting_names);
2921*e4b17023SJohn Marino     }
2922*e4b17023SJohn Marino 
2923*e4b17023SJohn Marino   /* Recurse into the dominator children of BB.  */
2924*e4b17023SJohn Marino   for (son = first_dom_son (CDI_DOMINATORS, bb);
2925*e4b17023SJohn Marino        son;
2926*e4b17023SJohn Marino        son = next_dom_son (CDI_DOMINATORS, son))
2927*e4b17023SJohn Marino     eliminate_degenerate_phis_1 (son, interesting_names);
2928*e4b17023SJohn Marino }
2929*e4b17023SJohn Marino 
2930*e4b17023SJohn Marino 
2931*e4b17023SJohn Marino /* A very simple pass to eliminate degenerate PHI nodes from the
2932*e4b17023SJohn Marino    IL.  This is meant to be fast enough to be able to be run several
2933*e4b17023SJohn Marino    times in the optimization pipeline.
2934*e4b17023SJohn Marino 
2935*e4b17023SJohn Marino    Certain optimizations, particularly those which duplicate blocks
2936*e4b17023SJohn Marino    or remove edges from the CFG can create or expose PHIs which are
2937*e4b17023SJohn Marino    trivial copies or constant initializations.
2938*e4b17023SJohn Marino 
2939*e4b17023SJohn Marino    While we could pick up these optimizations in DOM or with the
2940*e4b17023SJohn Marino    combination of copy-prop and CCP, those solutions are far too
2941*e4b17023SJohn Marino    heavy-weight for our needs.
2942*e4b17023SJohn Marino 
2943*e4b17023SJohn Marino    This implementation has two phases so that we can efficiently
2944*e4b17023SJohn Marino    eliminate the first order degenerate PHIs and second order
2945*e4b17023SJohn Marino    degenerate PHIs.
2946*e4b17023SJohn Marino 
2947*e4b17023SJohn Marino    The first phase performs a dominator walk to identify and eliminate
2948*e4b17023SJohn Marino    the vast majority of the degenerate PHIs.  When a degenerate PHI
2949*e4b17023SJohn Marino    is identified and eliminated any affected statements or PHIs
2950*e4b17023SJohn Marino    are put on a worklist.
2951*e4b17023SJohn Marino 
2952*e4b17023SJohn Marino    The second phase eliminates degenerate PHIs and trivial copies
2953*e4b17023SJohn Marino    or constant initializations using the worklist.  This is how we
2954*e4b17023SJohn Marino    pick up the secondary optimization opportunities with minimal
2955*e4b17023SJohn Marino    cost.  */
2956*e4b17023SJohn Marino 
2957*e4b17023SJohn Marino static unsigned int
eliminate_degenerate_phis(void)2958*e4b17023SJohn Marino eliminate_degenerate_phis (void)
2959*e4b17023SJohn Marino {
2960*e4b17023SJohn Marino   bitmap interesting_names;
2961*e4b17023SJohn Marino   bitmap interesting_names1;
2962*e4b17023SJohn Marino 
2963*e4b17023SJohn Marino   /* Bitmap of blocks which need EH information updated.  We can not
2964*e4b17023SJohn Marino      update it on-the-fly as doing so invalidates the dominator tree.  */
2965*e4b17023SJohn Marino   need_eh_cleanup = BITMAP_ALLOC (NULL);
2966*e4b17023SJohn Marino 
2967*e4b17023SJohn Marino   /* INTERESTING_NAMES is effectively our worklist, indexed by
2968*e4b17023SJohn Marino      SSA_NAME_VERSION.
2969*e4b17023SJohn Marino 
2970*e4b17023SJohn Marino      A set bit indicates that the statement or PHI node which
2971*e4b17023SJohn Marino      defines the SSA_NAME should be (re)examined to determine if
2972*e4b17023SJohn Marino      it has become a degenerate PHI or trivial const/copy propagation
2973*e4b17023SJohn Marino      opportunity.
2974*e4b17023SJohn Marino 
2975*e4b17023SJohn Marino      Experiments have show we generally get better compilation
2976*e4b17023SJohn Marino      time behavior with bitmaps rather than sbitmaps.  */
2977*e4b17023SJohn Marino   interesting_names = BITMAP_ALLOC (NULL);
2978*e4b17023SJohn Marino   interesting_names1 = BITMAP_ALLOC (NULL);
2979*e4b17023SJohn Marino 
2980*e4b17023SJohn Marino   calculate_dominance_info (CDI_DOMINATORS);
2981*e4b17023SJohn Marino   cfg_altered = false;
2982*e4b17023SJohn Marino 
2983*e4b17023SJohn Marino   /* First phase.  Eliminate degenerate PHIs via a dominator
2984*e4b17023SJohn Marino      walk of the CFG.
2985*e4b17023SJohn Marino 
2986*e4b17023SJohn Marino      Experiments have indicated that we generally get better
2987*e4b17023SJohn Marino      compile-time behavior by visiting blocks in the first
2988*e4b17023SJohn Marino      phase in dominator order.  Presumably this is because walking
2989*e4b17023SJohn Marino      in dominator order leaves fewer PHIs for later examination
2990*e4b17023SJohn Marino      by the worklist phase.  */
2991*e4b17023SJohn Marino   eliminate_degenerate_phis_1 (ENTRY_BLOCK_PTR, interesting_names);
2992*e4b17023SJohn Marino 
2993*e4b17023SJohn Marino   /* Second phase.  Eliminate second order degenerate PHIs as well
2994*e4b17023SJohn Marino      as trivial copies or constant initializations identified by
2995*e4b17023SJohn Marino      the first phase or this phase.  Basically we keep iterating
2996*e4b17023SJohn Marino      until our set of INTERESTING_NAMEs is empty.   */
2997*e4b17023SJohn Marino   while (!bitmap_empty_p (interesting_names))
2998*e4b17023SJohn Marino     {
2999*e4b17023SJohn Marino       unsigned int i;
3000*e4b17023SJohn Marino       bitmap_iterator bi;
3001*e4b17023SJohn Marino 
3002*e4b17023SJohn Marino       /* EXECUTE_IF_SET_IN_BITMAP does not like its bitmap
3003*e4b17023SJohn Marino 	 changed during the loop.  Copy it to another bitmap and
3004*e4b17023SJohn Marino 	 use that.  */
3005*e4b17023SJohn Marino       bitmap_copy (interesting_names1, interesting_names);
3006*e4b17023SJohn Marino 
3007*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (interesting_names1, 0, i, bi)
3008*e4b17023SJohn Marino 	{
3009*e4b17023SJohn Marino 	  tree name = ssa_name (i);
3010*e4b17023SJohn Marino 
3011*e4b17023SJohn Marino 	  /* Ignore SSA_NAMEs that have been released because
3012*e4b17023SJohn Marino 	     their defining statement was deleted (unreachable).  */
3013*e4b17023SJohn Marino 	  if (name)
3014*e4b17023SJohn Marino 	    eliminate_const_or_copy (SSA_NAME_DEF_STMT (ssa_name (i)),
3015*e4b17023SJohn Marino 				     interesting_names);
3016*e4b17023SJohn Marino 	}
3017*e4b17023SJohn Marino     }
3018*e4b17023SJohn Marino 
3019*e4b17023SJohn Marino   if (cfg_altered)
3020*e4b17023SJohn Marino     free_dominance_info (CDI_DOMINATORS);
3021*e4b17023SJohn Marino 
3022*e4b17023SJohn Marino   /* Propagation of const and copies may make some EH edges dead.  Purge
3023*e4b17023SJohn Marino      such edges from the CFG as needed.  */
3024*e4b17023SJohn Marino   if (!bitmap_empty_p (need_eh_cleanup))
3025*e4b17023SJohn Marino     {
3026*e4b17023SJohn Marino       gimple_purge_all_dead_eh_edges (need_eh_cleanup);
3027*e4b17023SJohn Marino       BITMAP_FREE (need_eh_cleanup);
3028*e4b17023SJohn Marino     }
3029*e4b17023SJohn Marino 
3030*e4b17023SJohn Marino   BITMAP_FREE (interesting_names);
3031*e4b17023SJohn Marino   BITMAP_FREE (interesting_names1);
3032*e4b17023SJohn Marino   return 0;
3033*e4b17023SJohn Marino }
3034*e4b17023SJohn Marino 
3035*e4b17023SJohn Marino struct gimple_opt_pass pass_phi_only_cprop =
3036*e4b17023SJohn Marino {
3037*e4b17023SJohn Marino  {
3038*e4b17023SJohn Marino   GIMPLE_PASS,
3039*e4b17023SJohn Marino   "phicprop",                           /* name */
3040*e4b17023SJohn Marino   gate_dominator,                       /* gate */
3041*e4b17023SJohn Marino   eliminate_degenerate_phis,            /* execute */
3042*e4b17023SJohn Marino   NULL,                                 /* sub */
3043*e4b17023SJohn Marino   NULL,                                 /* next */
3044*e4b17023SJohn Marino   0,                                    /* static_pass_number */
3045*e4b17023SJohn Marino   TV_TREE_PHI_CPROP,                    /* tv_id */
3046*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
3047*e4b17023SJohn Marino   0,                                    /* properties_provided */
3048*e4b17023SJohn Marino   0,		                        /* properties_destroyed */
3049*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
3050*e4b17023SJohn Marino   TODO_cleanup_cfg
3051*e4b17023SJohn Marino     | TODO_ggc_collect
3052*e4b17023SJohn Marino     | TODO_verify_ssa
3053*e4b17023SJohn Marino     | TODO_verify_stmts
3054*e4b17023SJohn Marino     | TODO_update_ssa			/* todo_flags_finish */
3055*e4b17023SJohn Marino  }
3056*e4b17023SJohn Marino };
3057