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