1e4b17023SJohn Marino /* If-conversion for vectorizer.
2e4b17023SJohn Marino Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3e4b17023SJohn Marino Free Software Foundation, Inc.
4e4b17023SJohn Marino Contributed by Devang Patel <dpatel@apple.com>
5e4b17023SJohn Marino
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11e4b17023SJohn Marino version.
12e4b17023SJohn Marino
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16e4b17023SJohn Marino for more details.
17e4b17023SJohn Marino
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21e4b17023SJohn Marino
22e4b17023SJohn Marino /* This pass implements a tree level if-conversion of loops. Its
23e4b17023SJohn Marino initial goal is to help the vectorizer to vectorize loops with
24e4b17023SJohn Marino conditions.
25e4b17023SJohn Marino
26e4b17023SJohn Marino A short description of if-conversion:
27e4b17023SJohn Marino
28e4b17023SJohn Marino o Decide if a loop is if-convertible or not.
29e4b17023SJohn Marino o Walk all loop basic blocks in breadth first order (BFS order).
30e4b17023SJohn Marino o Remove conditional statements (at the end of basic block)
31e4b17023SJohn Marino and propagate condition into destination basic blocks'
32e4b17023SJohn Marino predicate list.
33e4b17023SJohn Marino o Replace modify expression with conditional modify expression
34e4b17023SJohn Marino using current basic block's condition.
35e4b17023SJohn Marino o Merge all basic blocks
36e4b17023SJohn Marino o Replace phi nodes with conditional modify expr
37e4b17023SJohn Marino o Merge all basic blocks into header
38e4b17023SJohn Marino
39e4b17023SJohn Marino Sample transformation:
40e4b17023SJohn Marino
41e4b17023SJohn Marino INPUT
42e4b17023SJohn Marino -----
43e4b17023SJohn Marino
44e4b17023SJohn Marino # i_23 = PHI <0(0), i_18(10)>;
45e4b17023SJohn Marino <L0>:;
46e4b17023SJohn Marino j_15 = A[i_23];
47e4b17023SJohn Marino if (j_15 > 41) goto <L1>; else goto <L17>;
48e4b17023SJohn Marino
49e4b17023SJohn Marino <L17>:;
50e4b17023SJohn Marino goto <bb 3> (<L3>);
51e4b17023SJohn Marino
52e4b17023SJohn Marino <L1>:;
53e4b17023SJohn Marino
54e4b17023SJohn Marino # iftmp.2_4 = PHI <0(8), 42(2)>;
55e4b17023SJohn Marino <L3>:;
56e4b17023SJohn Marino A[i_23] = iftmp.2_4;
57e4b17023SJohn Marino i_18 = i_23 + 1;
58e4b17023SJohn Marino if (i_18 <= 15) goto <L19>; else goto <L18>;
59e4b17023SJohn Marino
60e4b17023SJohn Marino <L19>:;
61e4b17023SJohn Marino goto <bb 1> (<L0>);
62e4b17023SJohn Marino
63e4b17023SJohn Marino <L18>:;
64e4b17023SJohn Marino
65e4b17023SJohn Marino OUTPUT
66e4b17023SJohn Marino ------
67e4b17023SJohn Marino
68e4b17023SJohn Marino # i_23 = PHI <0(0), i_18(10)>;
69e4b17023SJohn Marino <L0>:;
70e4b17023SJohn Marino j_15 = A[i_23];
71e4b17023SJohn Marino
72e4b17023SJohn Marino <L3>:;
73e4b17023SJohn Marino iftmp.2_4 = j_15 > 41 ? 42 : 0;
74e4b17023SJohn Marino A[i_23] = iftmp.2_4;
75e4b17023SJohn Marino i_18 = i_23 + 1;
76e4b17023SJohn Marino if (i_18 <= 15) goto <L19>; else goto <L18>;
77e4b17023SJohn Marino
78e4b17023SJohn Marino <L19>:;
79e4b17023SJohn Marino goto <bb 1> (<L0>);
80e4b17023SJohn Marino
81e4b17023SJohn Marino <L18>:;
82e4b17023SJohn Marino */
83e4b17023SJohn Marino
84e4b17023SJohn Marino #include "config.h"
85e4b17023SJohn Marino #include "system.h"
86e4b17023SJohn Marino #include "coretypes.h"
87e4b17023SJohn Marino #include "tm.h"
88e4b17023SJohn Marino #include "tree.h"
89e4b17023SJohn Marino #include "flags.h"
90e4b17023SJohn Marino #include "timevar.h"
91e4b17023SJohn Marino #include "basic-block.h"
92e4b17023SJohn Marino #include "tree-pretty-print.h"
93e4b17023SJohn Marino #include "gimple-pretty-print.h"
94e4b17023SJohn Marino #include "tree-flow.h"
95e4b17023SJohn Marino #include "tree-dump.h"
96e4b17023SJohn Marino #include "cfgloop.h"
97e4b17023SJohn Marino #include "tree-chrec.h"
98e4b17023SJohn Marino #include "tree-data-ref.h"
99e4b17023SJohn Marino #include "tree-scalar-evolution.h"
100e4b17023SJohn Marino #include "tree-pass.h"
101e4b17023SJohn Marino #include "dbgcnt.h"
102e4b17023SJohn Marino
103e4b17023SJohn Marino /* List of basic blocks in if-conversion-suitable order. */
104e4b17023SJohn Marino static basic_block *ifc_bbs;
105e4b17023SJohn Marino
106e4b17023SJohn Marino /* Structure used to predicate basic blocks. This is attached to the
107e4b17023SJohn Marino ->aux field of the BBs in the loop to be if-converted. */
108e4b17023SJohn Marino typedef struct bb_predicate_s {
109e4b17023SJohn Marino
110e4b17023SJohn Marino /* The condition under which this basic block is executed. */
111e4b17023SJohn Marino tree predicate;
112e4b17023SJohn Marino
113e4b17023SJohn Marino /* PREDICATE is gimplified, and the sequence of statements is
114e4b17023SJohn Marino recorded here, in order to avoid the duplication of computations
115e4b17023SJohn Marino that occur in previous conditions. See PR44483. */
116e4b17023SJohn Marino gimple_seq predicate_gimplified_stmts;
117e4b17023SJohn Marino } *bb_predicate_p;
118e4b17023SJohn Marino
119e4b17023SJohn Marino /* Returns true when the basic block BB has a predicate. */
120e4b17023SJohn Marino
121e4b17023SJohn Marino static inline bool
bb_has_predicate(basic_block bb)122e4b17023SJohn Marino bb_has_predicate (basic_block bb)
123e4b17023SJohn Marino {
124e4b17023SJohn Marino return bb->aux != NULL;
125e4b17023SJohn Marino }
126e4b17023SJohn Marino
127e4b17023SJohn Marino /* Returns the gimplified predicate for basic block BB. */
128e4b17023SJohn Marino
129e4b17023SJohn Marino static inline tree
bb_predicate(basic_block bb)130e4b17023SJohn Marino bb_predicate (basic_block bb)
131e4b17023SJohn Marino {
132e4b17023SJohn Marino return ((bb_predicate_p) bb->aux)->predicate;
133e4b17023SJohn Marino }
134e4b17023SJohn Marino
135e4b17023SJohn Marino /* Sets the gimplified predicate COND for basic block BB. */
136e4b17023SJohn Marino
137e4b17023SJohn Marino static inline void
set_bb_predicate(basic_block bb,tree cond)138e4b17023SJohn Marino set_bb_predicate (basic_block bb, tree cond)
139e4b17023SJohn Marino {
140e4b17023SJohn Marino gcc_assert ((TREE_CODE (cond) == TRUTH_NOT_EXPR
141e4b17023SJohn Marino && is_gimple_condexpr (TREE_OPERAND (cond, 0)))
142e4b17023SJohn Marino || is_gimple_condexpr (cond));
143e4b17023SJohn Marino ((bb_predicate_p) bb->aux)->predicate = cond;
144e4b17023SJohn Marino }
145e4b17023SJohn Marino
146e4b17023SJohn Marino /* Returns the sequence of statements of the gimplification of the
147e4b17023SJohn Marino predicate for basic block BB. */
148e4b17023SJohn Marino
149e4b17023SJohn Marino static inline gimple_seq
bb_predicate_gimplified_stmts(basic_block bb)150e4b17023SJohn Marino bb_predicate_gimplified_stmts (basic_block bb)
151e4b17023SJohn Marino {
152e4b17023SJohn Marino return ((bb_predicate_p) bb->aux)->predicate_gimplified_stmts;
153e4b17023SJohn Marino }
154e4b17023SJohn Marino
155e4b17023SJohn Marino /* Sets the sequence of statements STMTS of the gimplification of the
156e4b17023SJohn Marino predicate for basic block BB. */
157e4b17023SJohn Marino
158e4b17023SJohn Marino static inline void
set_bb_predicate_gimplified_stmts(basic_block bb,gimple_seq stmts)159e4b17023SJohn Marino set_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts)
160e4b17023SJohn Marino {
161e4b17023SJohn Marino ((bb_predicate_p) bb->aux)->predicate_gimplified_stmts = stmts;
162e4b17023SJohn Marino }
163e4b17023SJohn Marino
164e4b17023SJohn Marino /* Adds the sequence of statements STMTS to the sequence of statements
165e4b17023SJohn Marino of the predicate for basic block BB. */
166e4b17023SJohn Marino
167e4b17023SJohn Marino static inline void
add_bb_predicate_gimplified_stmts(basic_block bb,gimple_seq stmts)168e4b17023SJohn Marino add_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts)
169e4b17023SJohn Marino {
170e4b17023SJohn Marino gimple_seq_add_seq
171e4b17023SJohn Marino (&(((bb_predicate_p) bb->aux)->predicate_gimplified_stmts), stmts);
172e4b17023SJohn Marino }
173e4b17023SJohn Marino
174e4b17023SJohn Marino /* Initializes to TRUE the predicate of basic block BB. */
175e4b17023SJohn Marino
176e4b17023SJohn Marino static inline void
init_bb_predicate(basic_block bb)177e4b17023SJohn Marino init_bb_predicate (basic_block bb)
178e4b17023SJohn Marino {
179e4b17023SJohn Marino bb->aux = XNEW (struct bb_predicate_s);
180e4b17023SJohn Marino set_bb_predicate_gimplified_stmts (bb, NULL);
181e4b17023SJohn Marino set_bb_predicate (bb, boolean_true_node);
182e4b17023SJohn Marino }
183e4b17023SJohn Marino
184e4b17023SJohn Marino /* Free the predicate of basic block BB. */
185e4b17023SJohn Marino
186e4b17023SJohn Marino static inline void
free_bb_predicate(basic_block bb)187e4b17023SJohn Marino free_bb_predicate (basic_block bb)
188e4b17023SJohn Marino {
189e4b17023SJohn Marino gimple_seq stmts;
190e4b17023SJohn Marino
191e4b17023SJohn Marino if (!bb_has_predicate (bb))
192e4b17023SJohn Marino return;
193e4b17023SJohn Marino
194e4b17023SJohn Marino /* Release the SSA_NAMEs created for the gimplification of the
195e4b17023SJohn Marino predicate. */
196e4b17023SJohn Marino stmts = bb_predicate_gimplified_stmts (bb);
197e4b17023SJohn Marino if (stmts)
198e4b17023SJohn Marino {
199e4b17023SJohn Marino gimple_stmt_iterator i;
200e4b17023SJohn Marino
201e4b17023SJohn Marino for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
202e4b17023SJohn Marino free_stmt_operands (gsi_stmt (i));
203e4b17023SJohn Marino }
204e4b17023SJohn Marino
205e4b17023SJohn Marino free (bb->aux);
206e4b17023SJohn Marino bb->aux = NULL;
207e4b17023SJohn Marino }
208e4b17023SJohn Marino
209e4b17023SJohn Marino /* Free the predicate of BB and reinitialize it with the true
210e4b17023SJohn Marino predicate. */
211e4b17023SJohn Marino
212e4b17023SJohn Marino static inline void
reset_bb_predicate(basic_block bb)213e4b17023SJohn Marino reset_bb_predicate (basic_block bb)
214e4b17023SJohn Marino {
215e4b17023SJohn Marino free_bb_predicate (bb);
216e4b17023SJohn Marino init_bb_predicate (bb);
217e4b17023SJohn Marino }
218e4b17023SJohn Marino
219e4b17023SJohn Marino /* Returns a new SSA_NAME of type TYPE that is assigned the value of
220e4b17023SJohn Marino the expression EXPR. Inserts the statement created for this
221e4b17023SJohn Marino computation before GSI and leaves the iterator GSI at the same
222e4b17023SJohn Marino statement. */
223e4b17023SJohn Marino
224e4b17023SJohn Marino static tree
ifc_temp_var(tree type,tree expr,gimple_stmt_iterator * gsi)225e4b17023SJohn Marino ifc_temp_var (tree type, tree expr, gimple_stmt_iterator *gsi)
226e4b17023SJohn Marino {
227e4b17023SJohn Marino const char *name = "_ifc_";
228e4b17023SJohn Marino tree var, new_name;
229e4b17023SJohn Marino gimple stmt;
230e4b17023SJohn Marino
231e4b17023SJohn Marino /* Create new temporary variable. */
232e4b17023SJohn Marino var = create_tmp_var (type, name);
233e4b17023SJohn Marino add_referenced_var (var);
234e4b17023SJohn Marino
235e4b17023SJohn Marino /* Build new statement to assign EXPR to new variable. */
236e4b17023SJohn Marino stmt = gimple_build_assign (var, expr);
237e4b17023SJohn Marino
238e4b17023SJohn Marino /* Get SSA name for the new variable and set make new statement
239e4b17023SJohn Marino its definition statement. */
240e4b17023SJohn Marino new_name = make_ssa_name (var, stmt);
241e4b17023SJohn Marino gimple_assign_set_lhs (stmt, new_name);
242e4b17023SJohn Marino SSA_NAME_DEF_STMT (new_name) = stmt;
243e4b17023SJohn Marino update_stmt (stmt);
244e4b17023SJohn Marino
245e4b17023SJohn Marino gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
246e4b17023SJohn Marino return gimple_assign_lhs (stmt);
247e4b17023SJohn Marino }
248e4b17023SJohn Marino
249e4b17023SJohn Marino /* Return true when COND is a true predicate. */
250e4b17023SJohn Marino
251e4b17023SJohn Marino static inline bool
is_true_predicate(tree cond)252e4b17023SJohn Marino is_true_predicate (tree cond)
253e4b17023SJohn Marino {
254e4b17023SJohn Marino return (cond == NULL_TREE
255e4b17023SJohn Marino || cond == boolean_true_node
256e4b17023SJohn Marino || integer_onep (cond));
257e4b17023SJohn Marino }
258e4b17023SJohn Marino
259e4b17023SJohn Marino /* Returns true when BB has a predicate that is not trivial: true or
260e4b17023SJohn Marino NULL_TREE. */
261e4b17023SJohn Marino
262e4b17023SJohn Marino static inline bool
is_predicated(basic_block bb)263e4b17023SJohn Marino is_predicated (basic_block bb)
264e4b17023SJohn Marino {
265e4b17023SJohn Marino return !is_true_predicate (bb_predicate (bb));
266e4b17023SJohn Marino }
267e4b17023SJohn Marino
268e4b17023SJohn Marino /* Parses the predicate COND and returns its comparison code and
269e4b17023SJohn Marino operands OP0 and OP1. */
270e4b17023SJohn Marino
271e4b17023SJohn Marino static enum tree_code
parse_predicate(tree cond,tree * op0,tree * op1)272e4b17023SJohn Marino parse_predicate (tree cond, tree *op0, tree *op1)
273e4b17023SJohn Marino {
274e4b17023SJohn Marino gimple s;
275e4b17023SJohn Marino
276e4b17023SJohn Marino if (TREE_CODE (cond) == SSA_NAME
277e4b17023SJohn Marino && is_gimple_assign (s = SSA_NAME_DEF_STMT (cond)))
278e4b17023SJohn Marino {
279e4b17023SJohn Marino if (TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison)
280e4b17023SJohn Marino {
281e4b17023SJohn Marino *op0 = gimple_assign_rhs1 (s);
282e4b17023SJohn Marino *op1 = gimple_assign_rhs2 (s);
283e4b17023SJohn Marino return gimple_assign_rhs_code (s);
284e4b17023SJohn Marino }
285e4b17023SJohn Marino
286e4b17023SJohn Marino else if (gimple_assign_rhs_code (s) == TRUTH_NOT_EXPR)
287e4b17023SJohn Marino {
288e4b17023SJohn Marino tree op = gimple_assign_rhs1 (s);
289e4b17023SJohn Marino tree type = TREE_TYPE (op);
290e4b17023SJohn Marino enum tree_code code = parse_predicate (op, op0, op1);
291e4b17023SJohn Marino
292e4b17023SJohn Marino return code == ERROR_MARK ? ERROR_MARK
293e4b17023SJohn Marino : invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
294e4b17023SJohn Marino }
295e4b17023SJohn Marino
296e4b17023SJohn Marino return ERROR_MARK;
297e4b17023SJohn Marino }
298e4b17023SJohn Marino
299e4b17023SJohn Marino if (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison)
300e4b17023SJohn Marino {
301e4b17023SJohn Marino *op0 = TREE_OPERAND (cond, 0);
302e4b17023SJohn Marino *op1 = TREE_OPERAND (cond, 1);
303e4b17023SJohn Marino return TREE_CODE (cond);
304e4b17023SJohn Marino }
305e4b17023SJohn Marino
306e4b17023SJohn Marino return ERROR_MARK;
307e4b17023SJohn Marino }
308e4b17023SJohn Marino
309e4b17023SJohn Marino /* Returns the fold of predicate C1 OR C2 at location LOC. */
310e4b17023SJohn Marino
311e4b17023SJohn Marino static tree
fold_or_predicates(location_t loc,tree c1,tree c2)312e4b17023SJohn Marino fold_or_predicates (location_t loc, tree c1, tree c2)
313e4b17023SJohn Marino {
314e4b17023SJohn Marino tree op1a, op1b, op2a, op2b;
315e4b17023SJohn Marino enum tree_code code1 = parse_predicate (c1, &op1a, &op1b);
316e4b17023SJohn Marino enum tree_code code2 = parse_predicate (c2, &op2a, &op2b);
317e4b17023SJohn Marino
318e4b17023SJohn Marino if (code1 != ERROR_MARK && code2 != ERROR_MARK)
319e4b17023SJohn Marino {
320e4b17023SJohn Marino tree t = maybe_fold_or_comparisons (code1, op1a, op1b,
321e4b17023SJohn Marino code2, op2a, op2b);
322e4b17023SJohn Marino if (t)
323e4b17023SJohn Marino return t;
324e4b17023SJohn Marino }
325e4b17023SJohn Marino
326e4b17023SJohn Marino return fold_build2_loc (loc, TRUTH_OR_EXPR, boolean_type_node, c1, c2);
327e4b17023SJohn Marino }
328e4b17023SJohn Marino
329e4b17023SJohn Marino /* Add condition NC to the predicate list of basic block BB. */
330e4b17023SJohn Marino
331e4b17023SJohn Marino static inline void
add_to_predicate_list(basic_block bb,tree nc)332e4b17023SJohn Marino add_to_predicate_list (basic_block bb, tree nc)
333e4b17023SJohn Marino {
334e4b17023SJohn Marino tree bc, *tp;
335e4b17023SJohn Marino
336e4b17023SJohn Marino if (is_true_predicate (nc))
337e4b17023SJohn Marino return;
338e4b17023SJohn Marino
339e4b17023SJohn Marino if (!is_predicated (bb))
340e4b17023SJohn Marino bc = nc;
341e4b17023SJohn Marino else
342e4b17023SJohn Marino {
343e4b17023SJohn Marino bc = bb_predicate (bb);
344e4b17023SJohn Marino bc = fold_or_predicates (EXPR_LOCATION (bc), nc, bc);
345e4b17023SJohn Marino if (is_true_predicate (bc))
346e4b17023SJohn Marino {
347e4b17023SJohn Marino reset_bb_predicate (bb);
348e4b17023SJohn Marino return;
349e4b17023SJohn Marino }
350e4b17023SJohn Marino }
351e4b17023SJohn Marino
352e4b17023SJohn Marino /* Allow a TRUTH_NOT_EXPR around the main predicate. */
353e4b17023SJohn Marino if (TREE_CODE (bc) == TRUTH_NOT_EXPR)
354e4b17023SJohn Marino tp = &TREE_OPERAND (bc, 0);
355e4b17023SJohn Marino else
356e4b17023SJohn Marino tp = &bc;
357e4b17023SJohn Marino if (!is_gimple_condexpr (*tp))
358e4b17023SJohn Marino {
359e4b17023SJohn Marino gimple_seq stmts;
360e4b17023SJohn Marino *tp = force_gimple_operand_1 (*tp, &stmts, is_gimple_condexpr, NULL_TREE);
361e4b17023SJohn Marino add_bb_predicate_gimplified_stmts (bb, stmts);
362e4b17023SJohn Marino }
363e4b17023SJohn Marino set_bb_predicate (bb, bc);
364e4b17023SJohn Marino }
365e4b17023SJohn Marino
366e4b17023SJohn Marino /* Add the condition COND to the previous condition PREV_COND, and add
367e4b17023SJohn Marino this to the predicate list of the destination of edge E. LOOP is
368e4b17023SJohn Marino the loop to be if-converted. */
369e4b17023SJohn Marino
370e4b17023SJohn Marino static void
add_to_dst_predicate_list(struct loop * loop,edge e,tree prev_cond,tree cond)371e4b17023SJohn Marino add_to_dst_predicate_list (struct loop *loop, edge e,
372e4b17023SJohn Marino tree prev_cond, tree cond)
373e4b17023SJohn Marino {
374e4b17023SJohn Marino if (!flow_bb_inside_loop_p (loop, e->dest))
375e4b17023SJohn Marino return;
376e4b17023SJohn Marino
377e4b17023SJohn Marino if (!is_true_predicate (prev_cond))
378e4b17023SJohn Marino cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
379e4b17023SJohn Marino prev_cond, cond);
380e4b17023SJohn Marino
381e4b17023SJohn Marino add_to_predicate_list (e->dest, cond);
382e4b17023SJohn Marino }
383e4b17023SJohn Marino
384e4b17023SJohn Marino /* Return true if one of the successor edges of BB exits LOOP. */
385e4b17023SJohn Marino
386e4b17023SJohn Marino static bool
bb_with_exit_edge_p(struct loop * loop,basic_block bb)387e4b17023SJohn Marino bb_with_exit_edge_p (struct loop *loop, basic_block bb)
388e4b17023SJohn Marino {
389e4b17023SJohn Marino edge e;
390e4b17023SJohn Marino edge_iterator ei;
391e4b17023SJohn Marino
392e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
393e4b17023SJohn Marino if (loop_exit_edge_p (loop, e))
394e4b17023SJohn Marino return true;
395e4b17023SJohn Marino
396e4b17023SJohn Marino return false;
397e4b17023SJohn Marino }
398e4b17023SJohn Marino
399e4b17023SJohn Marino /* Return true when PHI is if-convertible. PHI is part of loop LOOP
400e4b17023SJohn Marino and it belongs to basic block BB.
401e4b17023SJohn Marino
402e4b17023SJohn Marino PHI is not if-convertible if:
403e4b17023SJohn Marino - it has more than 2 arguments.
404e4b17023SJohn Marino
405e4b17023SJohn Marino When the flag_tree_loop_if_convert_stores is not set, PHI is not
406e4b17023SJohn Marino if-convertible if:
407e4b17023SJohn Marino - a virtual PHI is immediately used in another PHI node,
408e4b17023SJohn Marino - there is a virtual PHI in a BB other than the loop->header. */
409e4b17023SJohn Marino
410e4b17023SJohn Marino static bool
if_convertible_phi_p(struct loop * loop,basic_block bb,gimple phi)411e4b17023SJohn Marino if_convertible_phi_p (struct loop *loop, basic_block bb, gimple phi)
412e4b17023SJohn Marino {
413e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
414e4b17023SJohn Marino {
415e4b17023SJohn Marino fprintf (dump_file, "-------------------------\n");
416e4b17023SJohn Marino print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
417e4b17023SJohn Marino }
418e4b17023SJohn Marino
419e4b17023SJohn Marino if (bb != loop->header && gimple_phi_num_args (phi) != 2)
420e4b17023SJohn Marino {
421e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
422e4b17023SJohn Marino fprintf (dump_file, "More than two phi node args.\n");
423e4b17023SJohn Marino return false;
424e4b17023SJohn Marino }
425e4b17023SJohn Marino
426e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores)
427e4b17023SJohn Marino return true;
428e4b17023SJohn Marino
429e4b17023SJohn Marino /* When the flag_tree_loop_if_convert_stores is not set, check
430e4b17023SJohn Marino that there are no memory writes in the branches of the loop to be
431e4b17023SJohn Marino if-converted. */
432e4b17023SJohn Marino if (!is_gimple_reg (SSA_NAME_VAR (gimple_phi_result (phi))))
433e4b17023SJohn Marino {
434e4b17023SJohn Marino imm_use_iterator imm_iter;
435e4b17023SJohn Marino use_operand_p use_p;
436e4b17023SJohn Marino
437e4b17023SJohn Marino if (bb != loop->header)
438e4b17023SJohn Marino {
439e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
440e4b17023SJohn Marino fprintf (dump_file, "Virtual phi not on loop->header.\n");
441e4b17023SJohn Marino return false;
442e4b17023SJohn Marino }
443e4b17023SJohn Marino
444e4b17023SJohn Marino FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_phi_result (phi))
445e4b17023SJohn Marino {
446e4b17023SJohn Marino if (gimple_code (USE_STMT (use_p)) == GIMPLE_PHI)
447e4b17023SJohn Marino {
448e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
449e4b17023SJohn Marino fprintf (dump_file, "Difficult to handle this virtual phi.\n");
450e4b17023SJohn Marino return false;
451e4b17023SJohn Marino }
452e4b17023SJohn Marino }
453e4b17023SJohn Marino }
454e4b17023SJohn Marino
455e4b17023SJohn Marino return true;
456e4b17023SJohn Marino }
457e4b17023SJohn Marino
458e4b17023SJohn Marino /* Records the status of a data reference. This struct is attached to
459e4b17023SJohn Marino each DR->aux field. */
460e4b17023SJohn Marino
461e4b17023SJohn Marino struct ifc_dr {
462e4b17023SJohn Marino /* -1 when not initialized, 0 when false, 1 when true. */
463e4b17023SJohn Marino int written_at_least_once;
464e4b17023SJohn Marino
465e4b17023SJohn Marino /* -1 when not initialized, 0 when false, 1 when true. */
466e4b17023SJohn Marino int rw_unconditionally;
467e4b17023SJohn Marino };
468e4b17023SJohn Marino
469e4b17023SJohn Marino #define IFC_DR(DR) ((struct ifc_dr *) (DR)->aux)
470e4b17023SJohn Marino #define DR_WRITTEN_AT_LEAST_ONCE(DR) (IFC_DR (DR)->written_at_least_once)
471e4b17023SJohn Marino #define DR_RW_UNCONDITIONALLY(DR) (IFC_DR (DR)->rw_unconditionally)
472e4b17023SJohn Marino
473e4b17023SJohn Marino /* Returns true when the memory references of STMT are read or written
474e4b17023SJohn Marino unconditionally. In other words, this function returns true when
475e4b17023SJohn Marino for every data reference A in STMT there exist other accesses to
476e4b17023SJohn Marino a data reference with the same base with predicates that add up (OR-up) to
477e4b17023SJohn Marino the true predicate: this ensures that the data reference A is touched
478e4b17023SJohn Marino (read or written) on every iteration of the if-converted loop. */
479e4b17023SJohn Marino
480e4b17023SJohn Marino static bool
memrefs_read_or_written_unconditionally(gimple stmt,VEC (data_reference_p,heap)* drs)481e4b17023SJohn Marino memrefs_read_or_written_unconditionally (gimple stmt,
482e4b17023SJohn Marino VEC (data_reference_p, heap) *drs)
483e4b17023SJohn Marino {
484e4b17023SJohn Marino int i, j;
485e4b17023SJohn Marino data_reference_p a, b;
486e4b17023SJohn Marino tree ca = bb_predicate (gimple_bb (stmt));
487e4b17023SJohn Marino
488e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, drs, i, a); i++)
489e4b17023SJohn Marino if (DR_STMT (a) == stmt)
490e4b17023SJohn Marino {
491e4b17023SJohn Marino bool found = false;
492e4b17023SJohn Marino int x = DR_RW_UNCONDITIONALLY (a);
493e4b17023SJohn Marino
494e4b17023SJohn Marino if (x == 0)
495e4b17023SJohn Marino return false;
496e4b17023SJohn Marino
497e4b17023SJohn Marino if (x == 1)
498e4b17023SJohn Marino continue;
499e4b17023SJohn Marino
500e4b17023SJohn Marino for (j = 0; VEC_iterate (data_reference_p, drs, j, b); j++)
501e4b17023SJohn Marino {
502e4b17023SJohn Marino tree ref_base_a = DR_REF (a);
503e4b17023SJohn Marino tree ref_base_b = DR_REF (b);
504e4b17023SJohn Marino
505e4b17023SJohn Marino if (DR_STMT (b) == stmt)
506e4b17023SJohn Marino continue;
507e4b17023SJohn Marino
508e4b17023SJohn Marino while (TREE_CODE (ref_base_a) == COMPONENT_REF
509e4b17023SJohn Marino || TREE_CODE (ref_base_a) == IMAGPART_EXPR
510e4b17023SJohn Marino || TREE_CODE (ref_base_a) == REALPART_EXPR)
511e4b17023SJohn Marino ref_base_a = TREE_OPERAND (ref_base_a, 0);
512e4b17023SJohn Marino
513e4b17023SJohn Marino while (TREE_CODE (ref_base_b) == COMPONENT_REF
514e4b17023SJohn Marino || TREE_CODE (ref_base_b) == IMAGPART_EXPR
515e4b17023SJohn Marino || TREE_CODE (ref_base_b) == REALPART_EXPR)
516e4b17023SJohn Marino ref_base_b = TREE_OPERAND (ref_base_b, 0);
517e4b17023SJohn Marino
518e4b17023SJohn Marino if (!operand_equal_p (ref_base_a, ref_base_b, 0))
519e4b17023SJohn Marino {
520e4b17023SJohn Marino tree cb = bb_predicate (gimple_bb (DR_STMT (b)));
521e4b17023SJohn Marino
522e4b17023SJohn Marino if (DR_RW_UNCONDITIONALLY (b) == 1
523e4b17023SJohn Marino || is_true_predicate (cb)
524e4b17023SJohn Marino || is_true_predicate (ca
525e4b17023SJohn Marino = fold_or_predicates (EXPR_LOCATION (cb), ca, cb)))
526e4b17023SJohn Marino {
527e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (a) = 1;
528e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (b) = 1;
529e4b17023SJohn Marino found = true;
530e4b17023SJohn Marino break;
531e4b17023SJohn Marino }
532e4b17023SJohn Marino }
533e4b17023SJohn Marino }
534e4b17023SJohn Marino
535e4b17023SJohn Marino if (!found)
536e4b17023SJohn Marino {
537e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (a) = 0;
538e4b17023SJohn Marino return false;
539e4b17023SJohn Marino }
540e4b17023SJohn Marino }
541e4b17023SJohn Marino
542e4b17023SJohn Marino return true;
543e4b17023SJohn Marino }
544e4b17023SJohn Marino
545e4b17023SJohn Marino /* Returns true when the memory references of STMT are unconditionally
546e4b17023SJohn Marino written. In other words, this function returns true when for every
547e4b17023SJohn Marino data reference A written in STMT, there exist other writes to the
548e4b17023SJohn Marino same data reference with predicates that add up (OR-up) to the true
549e4b17023SJohn Marino predicate: this ensures that the data reference A is written on
550e4b17023SJohn Marino every iteration of the if-converted loop. */
551e4b17023SJohn Marino
552e4b17023SJohn Marino static bool
write_memrefs_written_at_least_once(gimple stmt,VEC (data_reference_p,heap)* drs)553e4b17023SJohn Marino write_memrefs_written_at_least_once (gimple stmt,
554e4b17023SJohn Marino VEC (data_reference_p, heap) *drs)
555e4b17023SJohn Marino {
556e4b17023SJohn Marino int i, j;
557e4b17023SJohn Marino data_reference_p a, b;
558e4b17023SJohn Marino tree ca = bb_predicate (gimple_bb (stmt));
559e4b17023SJohn Marino
560e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, drs, i, a); i++)
561e4b17023SJohn Marino if (DR_STMT (a) == stmt
562e4b17023SJohn Marino && DR_IS_WRITE (a))
563e4b17023SJohn Marino {
564e4b17023SJohn Marino bool found = false;
565e4b17023SJohn Marino int x = DR_WRITTEN_AT_LEAST_ONCE (a);
566e4b17023SJohn Marino
567e4b17023SJohn Marino if (x == 0)
568e4b17023SJohn Marino return false;
569e4b17023SJohn Marino
570e4b17023SJohn Marino if (x == 1)
571e4b17023SJohn Marino continue;
572e4b17023SJohn Marino
573e4b17023SJohn Marino for (j = 0; VEC_iterate (data_reference_p, drs, j, b); j++)
574e4b17023SJohn Marino if (DR_STMT (b) != stmt
575e4b17023SJohn Marino && DR_IS_WRITE (b)
576e4b17023SJohn Marino && same_data_refs_base_objects (a, b))
577e4b17023SJohn Marino {
578e4b17023SJohn Marino tree cb = bb_predicate (gimple_bb (DR_STMT (b)));
579e4b17023SJohn Marino
580e4b17023SJohn Marino if (DR_WRITTEN_AT_LEAST_ONCE (b) == 1
581e4b17023SJohn Marino || is_true_predicate (cb)
582e4b17023SJohn Marino || is_true_predicate (ca = fold_or_predicates (EXPR_LOCATION (cb),
583e4b17023SJohn Marino ca, cb)))
584e4b17023SJohn Marino {
585e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (a) = 1;
586e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (b) = 1;
587e4b17023SJohn Marino found = true;
588e4b17023SJohn Marino break;
589e4b17023SJohn Marino }
590e4b17023SJohn Marino }
591e4b17023SJohn Marino
592e4b17023SJohn Marino if (!found)
593e4b17023SJohn Marino {
594e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (a) = 0;
595e4b17023SJohn Marino return false;
596e4b17023SJohn Marino }
597e4b17023SJohn Marino }
598e4b17023SJohn Marino
599e4b17023SJohn Marino return true;
600e4b17023SJohn Marino }
601e4b17023SJohn Marino
602e4b17023SJohn Marino /* Return true when the memory references of STMT won't trap in the
603e4b17023SJohn Marino if-converted code. There are two things that we have to check for:
604e4b17023SJohn Marino
605e4b17023SJohn Marino - writes to memory occur to writable memory: if-conversion of
606e4b17023SJohn Marino memory writes transforms the conditional memory writes into
607e4b17023SJohn Marino unconditional writes, i.e. "if (cond) A[i] = foo" is transformed
608e4b17023SJohn Marino into "A[i] = cond ? foo : A[i]", and as the write to memory may not
609e4b17023SJohn Marino be executed at all in the original code, it may be a readonly
610e4b17023SJohn Marino memory. To check that A is not const-qualified, we check that
611e4b17023SJohn Marino there exists at least an unconditional write to A in the current
612e4b17023SJohn Marino function.
613e4b17023SJohn Marino
614e4b17023SJohn Marino - reads or writes to memory are valid memory accesses for every
615e4b17023SJohn Marino iteration. To check that the memory accesses are correctly formed
616e4b17023SJohn Marino and that we are allowed to read and write in these locations, we
617e4b17023SJohn Marino check that the memory accesses to be if-converted occur at every
618e4b17023SJohn Marino iteration unconditionally. */
619e4b17023SJohn Marino
620e4b17023SJohn Marino static bool
ifcvt_memrefs_wont_trap(gimple stmt,VEC (data_reference_p,heap)* refs)621e4b17023SJohn Marino ifcvt_memrefs_wont_trap (gimple stmt, VEC (data_reference_p, heap) *refs)
622e4b17023SJohn Marino {
623e4b17023SJohn Marino return write_memrefs_written_at_least_once (stmt, refs)
624e4b17023SJohn Marino && memrefs_read_or_written_unconditionally (stmt, refs);
625e4b17023SJohn Marino }
626e4b17023SJohn Marino
627e4b17023SJohn Marino /* Wrapper around gimple_could_trap_p refined for the needs of the
628e4b17023SJohn Marino if-conversion. Try to prove that the memory accesses of STMT could
629e4b17023SJohn Marino not trap in the innermost loop containing STMT. */
630e4b17023SJohn Marino
631e4b17023SJohn Marino static bool
ifcvt_could_trap_p(gimple stmt,VEC (data_reference_p,heap)* refs)632e4b17023SJohn Marino ifcvt_could_trap_p (gimple stmt, VEC (data_reference_p, heap) *refs)
633e4b17023SJohn Marino {
634e4b17023SJohn Marino if (gimple_vuse (stmt)
635e4b17023SJohn Marino && !gimple_could_trap_p_1 (stmt, false, false)
636e4b17023SJohn Marino && ifcvt_memrefs_wont_trap (stmt, refs))
637e4b17023SJohn Marino return false;
638e4b17023SJohn Marino
639e4b17023SJohn Marino return gimple_could_trap_p (stmt);
640e4b17023SJohn Marino }
641e4b17023SJohn Marino
642e4b17023SJohn Marino /* Return true when STMT is if-convertible.
643e4b17023SJohn Marino
644e4b17023SJohn Marino GIMPLE_ASSIGN statement is not if-convertible if,
645e4b17023SJohn Marino - it is not movable,
646e4b17023SJohn Marino - it could trap,
647e4b17023SJohn Marino - LHS is not var decl. */
648e4b17023SJohn Marino
649e4b17023SJohn Marino static bool
if_convertible_gimple_assign_stmt_p(gimple stmt,VEC (data_reference_p,heap)* refs)650e4b17023SJohn Marino if_convertible_gimple_assign_stmt_p (gimple stmt,
651e4b17023SJohn Marino VEC (data_reference_p, heap) *refs)
652e4b17023SJohn Marino {
653e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt);
654e4b17023SJohn Marino basic_block bb;
655e4b17023SJohn Marino
656e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
657e4b17023SJohn Marino {
658e4b17023SJohn Marino fprintf (dump_file, "-------------------------\n");
659e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
660e4b17023SJohn Marino }
661e4b17023SJohn Marino
662e4b17023SJohn Marino if (!is_gimple_reg_type (TREE_TYPE (lhs)))
663e4b17023SJohn Marino return false;
664e4b17023SJohn Marino
665e4b17023SJohn Marino /* Some of these constrains might be too conservative. */
666e4b17023SJohn Marino if (stmt_ends_bb_p (stmt)
667e4b17023SJohn Marino || gimple_has_volatile_ops (stmt)
668e4b17023SJohn Marino || (TREE_CODE (lhs) == SSA_NAME
669e4b17023SJohn Marino && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
670e4b17023SJohn Marino || gimple_has_side_effects (stmt))
671e4b17023SJohn Marino {
672e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
673e4b17023SJohn Marino fprintf (dump_file, "stmt not suitable for ifcvt\n");
674e4b17023SJohn Marino return false;
675e4b17023SJohn Marino }
676e4b17023SJohn Marino
677e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores)
678e4b17023SJohn Marino {
679e4b17023SJohn Marino if (ifcvt_could_trap_p (stmt, refs))
680e4b17023SJohn Marino {
681e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
682e4b17023SJohn Marino fprintf (dump_file, "tree could trap...\n");
683e4b17023SJohn Marino return false;
684e4b17023SJohn Marino }
685e4b17023SJohn Marino return true;
686e4b17023SJohn Marino }
687e4b17023SJohn Marino
688e4b17023SJohn Marino if (gimple_assign_rhs_could_trap_p (stmt))
689e4b17023SJohn Marino {
690e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
691e4b17023SJohn Marino fprintf (dump_file, "tree could trap...\n");
692e4b17023SJohn Marino return false;
693e4b17023SJohn Marino }
694e4b17023SJohn Marino
695e4b17023SJohn Marino bb = gimple_bb (stmt);
696e4b17023SJohn Marino
697e4b17023SJohn Marino if (TREE_CODE (lhs) != SSA_NAME
698e4b17023SJohn Marino && bb != bb->loop_father->header
699e4b17023SJohn Marino && !bb_with_exit_edge_p (bb->loop_father, bb))
700e4b17023SJohn Marino {
701e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
702e4b17023SJohn Marino {
703e4b17023SJohn Marino fprintf (dump_file, "LHS is not var\n");
704e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
705e4b17023SJohn Marino }
706e4b17023SJohn Marino return false;
707e4b17023SJohn Marino }
708e4b17023SJohn Marino
709e4b17023SJohn Marino return true;
710e4b17023SJohn Marino }
711e4b17023SJohn Marino
712e4b17023SJohn Marino /* Return true when STMT is if-convertible.
713e4b17023SJohn Marino
714e4b17023SJohn Marino A statement is if-convertible if:
715e4b17023SJohn Marino - it is an if-convertible GIMPLE_ASSGIN,
716e4b17023SJohn Marino - it is a GIMPLE_LABEL or a GIMPLE_COND. */
717e4b17023SJohn Marino
718e4b17023SJohn Marino static bool
if_convertible_stmt_p(gimple stmt,VEC (data_reference_p,heap)* refs)719e4b17023SJohn Marino if_convertible_stmt_p (gimple stmt, VEC (data_reference_p, heap) *refs)
720e4b17023SJohn Marino {
721e4b17023SJohn Marino switch (gimple_code (stmt))
722e4b17023SJohn Marino {
723e4b17023SJohn Marino case GIMPLE_LABEL:
724e4b17023SJohn Marino case GIMPLE_DEBUG:
725e4b17023SJohn Marino case GIMPLE_COND:
726e4b17023SJohn Marino return true;
727e4b17023SJohn Marino
728e4b17023SJohn Marino case GIMPLE_ASSIGN:
729e4b17023SJohn Marino return if_convertible_gimple_assign_stmt_p (stmt, refs);
730e4b17023SJohn Marino
731e4b17023SJohn Marino case GIMPLE_CALL:
732e4b17023SJohn Marino {
733e4b17023SJohn Marino tree fndecl = gimple_call_fndecl (stmt);
734e4b17023SJohn Marino if (fndecl)
735e4b17023SJohn Marino {
736e4b17023SJohn Marino int flags = gimple_call_flags (stmt);
737e4b17023SJohn Marino if ((flags & ECF_CONST)
738e4b17023SJohn Marino && !(flags & ECF_LOOPING_CONST_OR_PURE)
739e4b17023SJohn Marino /* We can only vectorize some builtins at the moment,
740e4b17023SJohn Marino so restrict if-conversion to those. */
741e4b17023SJohn Marino && DECL_BUILT_IN (fndecl))
742e4b17023SJohn Marino return true;
743e4b17023SJohn Marino }
744e4b17023SJohn Marino return false;
745e4b17023SJohn Marino }
746e4b17023SJohn Marino
747e4b17023SJohn Marino default:
748e4b17023SJohn Marino /* Don't know what to do with 'em so don't do anything. */
749e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
750e4b17023SJohn Marino {
751e4b17023SJohn Marino fprintf (dump_file, "don't know what to do\n");
752e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
753e4b17023SJohn Marino }
754e4b17023SJohn Marino return false;
755e4b17023SJohn Marino break;
756e4b17023SJohn Marino }
757e4b17023SJohn Marino
758e4b17023SJohn Marino return true;
759e4b17023SJohn Marino }
760e4b17023SJohn Marino
761e4b17023SJohn Marino /* Return true when BB is if-convertible. This routine does not check
762e4b17023SJohn Marino basic block's statements and phis.
763e4b17023SJohn Marino
764e4b17023SJohn Marino A basic block is not if-convertible if:
765e4b17023SJohn Marino - it is non-empty and it is after the exit block (in BFS order),
766e4b17023SJohn Marino - it is after the exit block but before the latch,
767e4b17023SJohn Marino - its edges are not normal.
768e4b17023SJohn Marino
769e4b17023SJohn Marino EXIT_BB is the basic block containing the exit of the LOOP. BB is
770e4b17023SJohn Marino inside LOOP. */
771e4b17023SJohn Marino
772e4b17023SJohn Marino static bool
if_convertible_bb_p(struct loop * loop,basic_block bb,basic_block exit_bb)773e4b17023SJohn Marino if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
774e4b17023SJohn Marino {
775e4b17023SJohn Marino edge e;
776e4b17023SJohn Marino edge_iterator ei;
777e4b17023SJohn Marino
778e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
779e4b17023SJohn Marino fprintf (dump_file, "----------[%d]-------------\n", bb->index);
780e4b17023SJohn Marino
781e4b17023SJohn Marino if (EDGE_COUNT (bb->preds) > 2
782e4b17023SJohn Marino || EDGE_COUNT (bb->succs) > 2)
783e4b17023SJohn Marino return false;
784e4b17023SJohn Marino
785e4b17023SJohn Marino if (exit_bb)
786e4b17023SJohn Marino {
787e4b17023SJohn Marino if (bb != loop->latch)
788e4b17023SJohn Marino {
789e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
790e4b17023SJohn Marino fprintf (dump_file, "basic block after exit bb but before latch\n");
791e4b17023SJohn Marino return false;
792e4b17023SJohn Marino }
793e4b17023SJohn Marino else if (!empty_block_p (bb))
794e4b17023SJohn Marino {
795e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
796e4b17023SJohn Marino fprintf (dump_file, "non empty basic block after exit bb\n");
797e4b17023SJohn Marino return false;
798e4b17023SJohn Marino }
799e4b17023SJohn Marino else if (bb == loop->latch
800e4b17023SJohn Marino && bb != exit_bb
801e4b17023SJohn Marino && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb))
802e4b17023SJohn Marino {
803e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
804e4b17023SJohn Marino fprintf (dump_file, "latch is not dominated by exit_block\n");
805e4b17023SJohn Marino return false;
806e4b17023SJohn Marino }
807e4b17023SJohn Marino }
808e4b17023SJohn Marino
809e4b17023SJohn Marino /* Be less adventurous and handle only normal edges. */
810e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
811e4b17023SJohn Marino if (e->flags &
812e4b17023SJohn Marino (EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP))
813e4b17023SJohn Marino {
814e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
815e4b17023SJohn Marino fprintf (dump_file, "Difficult to handle edges\n");
816e4b17023SJohn Marino return false;
817e4b17023SJohn Marino }
818e4b17023SJohn Marino
819*95d28233SJohn Marino /* At least one incoming edge has to be non-critical as otherwise edge
820*95d28233SJohn Marino predicates are not equal to basic-block predicates of the edge
821*95d28233SJohn Marino source. */
822*95d28233SJohn Marino if (EDGE_COUNT (bb->preds) > 1
823*95d28233SJohn Marino && bb != loop->header)
824*95d28233SJohn Marino {
825*95d28233SJohn Marino bool found = false;
826*95d28233SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds)
827*95d28233SJohn Marino if (EDGE_COUNT (e->src->succs) == 1)
828*95d28233SJohn Marino found = true;
829*95d28233SJohn Marino if (!found)
830*95d28233SJohn Marino {
831*95d28233SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
832*95d28233SJohn Marino fprintf (dump_file, "only critical predecessors\n");
833e4b17023SJohn Marino return false;
834*95d28233SJohn Marino }
835*95d28233SJohn Marino }
836e4b17023SJohn Marino
837e4b17023SJohn Marino return true;
838e4b17023SJohn Marino }
839e4b17023SJohn Marino
840e4b17023SJohn Marino /* Return true when all predecessor blocks of BB are visited. The
841e4b17023SJohn Marino VISITED bitmap keeps track of the visited blocks. */
842e4b17023SJohn Marino
843e4b17023SJohn Marino static bool
pred_blocks_visited_p(basic_block bb,bitmap * visited)844e4b17023SJohn Marino pred_blocks_visited_p (basic_block bb, bitmap *visited)
845e4b17023SJohn Marino {
846e4b17023SJohn Marino edge e;
847e4b17023SJohn Marino edge_iterator ei;
848e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds)
849e4b17023SJohn Marino if (!bitmap_bit_p (*visited, e->src->index))
850e4b17023SJohn Marino return false;
851e4b17023SJohn Marino
852e4b17023SJohn Marino return true;
853e4b17023SJohn Marino }
854e4b17023SJohn Marino
855e4b17023SJohn Marino /* Get body of a LOOP in suitable order for if-conversion. It is
856e4b17023SJohn Marino caller's responsibility to deallocate basic block list.
857e4b17023SJohn Marino If-conversion suitable order is, breadth first sort (BFS) order
858e4b17023SJohn Marino with an additional constraint: select a block only if all its
859e4b17023SJohn Marino predecessors are already selected. */
860e4b17023SJohn Marino
861e4b17023SJohn Marino static basic_block *
get_loop_body_in_if_conv_order(const struct loop * loop)862e4b17023SJohn Marino get_loop_body_in_if_conv_order (const struct loop *loop)
863e4b17023SJohn Marino {
864e4b17023SJohn Marino basic_block *blocks, *blocks_in_bfs_order;
865e4b17023SJohn Marino basic_block bb;
866e4b17023SJohn Marino bitmap visited;
867e4b17023SJohn Marino unsigned int index = 0;
868e4b17023SJohn Marino unsigned int visited_count = 0;
869e4b17023SJohn Marino
870e4b17023SJohn Marino gcc_assert (loop->num_nodes);
871e4b17023SJohn Marino gcc_assert (loop->latch != EXIT_BLOCK_PTR);
872e4b17023SJohn Marino
873e4b17023SJohn Marino blocks = XCNEWVEC (basic_block, loop->num_nodes);
874e4b17023SJohn Marino visited = BITMAP_ALLOC (NULL);
875e4b17023SJohn Marino
876e4b17023SJohn Marino blocks_in_bfs_order = get_loop_body_in_bfs_order (loop);
877e4b17023SJohn Marino
878e4b17023SJohn Marino index = 0;
879e4b17023SJohn Marino while (index < loop->num_nodes)
880e4b17023SJohn Marino {
881e4b17023SJohn Marino bb = blocks_in_bfs_order [index];
882e4b17023SJohn Marino
883e4b17023SJohn Marino if (bb->flags & BB_IRREDUCIBLE_LOOP)
884e4b17023SJohn Marino {
885e4b17023SJohn Marino free (blocks_in_bfs_order);
886e4b17023SJohn Marino BITMAP_FREE (visited);
887e4b17023SJohn Marino free (blocks);
888e4b17023SJohn Marino return NULL;
889e4b17023SJohn Marino }
890e4b17023SJohn Marino
891e4b17023SJohn Marino if (!bitmap_bit_p (visited, bb->index))
892e4b17023SJohn Marino {
893e4b17023SJohn Marino if (pred_blocks_visited_p (bb, &visited)
894e4b17023SJohn Marino || bb == loop->header)
895e4b17023SJohn Marino {
896e4b17023SJohn Marino /* This block is now visited. */
897e4b17023SJohn Marino bitmap_set_bit (visited, bb->index);
898e4b17023SJohn Marino blocks[visited_count++] = bb;
899e4b17023SJohn Marino }
900e4b17023SJohn Marino }
901e4b17023SJohn Marino
902e4b17023SJohn Marino index++;
903e4b17023SJohn Marino
904e4b17023SJohn Marino if (index == loop->num_nodes
905e4b17023SJohn Marino && visited_count != loop->num_nodes)
906e4b17023SJohn Marino /* Not done yet. */
907e4b17023SJohn Marino index = 0;
908e4b17023SJohn Marino }
909e4b17023SJohn Marino free (blocks_in_bfs_order);
910e4b17023SJohn Marino BITMAP_FREE (visited);
911e4b17023SJohn Marino return blocks;
912e4b17023SJohn Marino }
913e4b17023SJohn Marino
914e4b17023SJohn Marino /* Returns true when the analysis of the predicates for all the basic
915e4b17023SJohn Marino blocks in LOOP succeeded.
916e4b17023SJohn Marino
917e4b17023SJohn Marino predicate_bbs first allocates the predicates of the basic blocks.
918e4b17023SJohn Marino These fields are then initialized with the tree expressions
919e4b17023SJohn Marino representing the predicates under which a basic block is executed
920e4b17023SJohn Marino in the LOOP. As the loop->header is executed at each iteration, it
921e4b17023SJohn Marino has the "true" predicate. Other statements executed under a
922e4b17023SJohn Marino condition are predicated with that condition, for example
923e4b17023SJohn Marino
924e4b17023SJohn Marino | if (x)
925e4b17023SJohn Marino | S1;
926e4b17023SJohn Marino | else
927e4b17023SJohn Marino | S2;
928e4b17023SJohn Marino
929e4b17023SJohn Marino S1 will be predicated with "x", and
930e4b17023SJohn Marino S2 will be predicated with "!x". */
931e4b17023SJohn Marino
932e4b17023SJohn Marino static bool
predicate_bbs(loop_p loop)933e4b17023SJohn Marino predicate_bbs (loop_p loop)
934e4b17023SJohn Marino {
935e4b17023SJohn Marino unsigned int i;
936e4b17023SJohn Marino
937e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
938e4b17023SJohn Marino init_bb_predicate (ifc_bbs[i]);
939e4b17023SJohn Marino
940e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
941e4b17023SJohn Marino {
942e4b17023SJohn Marino basic_block bb = ifc_bbs[i];
943e4b17023SJohn Marino tree cond;
944e4b17023SJohn Marino gimple_stmt_iterator itr;
945e4b17023SJohn Marino
946e4b17023SJohn Marino /* The loop latch is always executed and has no extra conditions
947e4b17023SJohn Marino to be processed: skip it. */
948e4b17023SJohn Marino if (bb == loop->latch)
949e4b17023SJohn Marino {
950e4b17023SJohn Marino reset_bb_predicate (loop->latch);
951e4b17023SJohn Marino continue;
952e4b17023SJohn Marino }
953e4b17023SJohn Marino
954e4b17023SJohn Marino cond = bb_predicate (bb);
955e4b17023SJohn Marino
956e4b17023SJohn Marino for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr))
957e4b17023SJohn Marino {
958e4b17023SJohn Marino gimple stmt = gsi_stmt (itr);
959e4b17023SJohn Marino
960e4b17023SJohn Marino switch (gimple_code (stmt))
961e4b17023SJohn Marino {
962e4b17023SJohn Marino case GIMPLE_LABEL:
963e4b17023SJohn Marino case GIMPLE_ASSIGN:
964e4b17023SJohn Marino case GIMPLE_CALL:
965e4b17023SJohn Marino case GIMPLE_DEBUG:
966e4b17023SJohn Marino break;
967e4b17023SJohn Marino
968e4b17023SJohn Marino case GIMPLE_COND:
969e4b17023SJohn Marino {
970e4b17023SJohn Marino tree c2, tem;
971e4b17023SJohn Marino edge true_edge, false_edge;
972e4b17023SJohn Marino location_t loc = gimple_location (stmt);
973e4b17023SJohn Marino tree c = fold_build2_loc (loc, gimple_cond_code (stmt),
974e4b17023SJohn Marino boolean_type_node,
975e4b17023SJohn Marino gimple_cond_lhs (stmt),
976e4b17023SJohn Marino gimple_cond_rhs (stmt));
977e4b17023SJohn Marino
978e4b17023SJohn Marino /* Add new condition into destination's predicate list. */
979e4b17023SJohn Marino extract_true_false_edges_from_block (gimple_bb (stmt),
980e4b17023SJohn Marino &true_edge, &false_edge);
981e4b17023SJohn Marino
982e4b17023SJohn Marino /* If C is true, then TRUE_EDGE is taken. */
983e4b17023SJohn Marino add_to_dst_predicate_list (loop, true_edge,
984e4b17023SJohn Marino unshare_expr (cond),
985e4b17023SJohn Marino unshare_expr (c));
986e4b17023SJohn Marino
987e4b17023SJohn Marino /* If C is false, then FALSE_EDGE is taken. */
988e4b17023SJohn Marino c2 = invert_truthvalue_loc (loc, unshare_expr (c));
989e4b17023SJohn Marino tem = canonicalize_cond_expr_cond (c2);
990e4b17023SJohn Marino if (tem)
991e4b17023SJohn Marino c2 = tem;
992e4b17023SJohn Marino add_to_dst_predicate_list (loop, false_edge,
993e4b17023SJohn Marino unshare_expr (cond), c2);
994e4b17023SJohn Marino
995e4b17023SJohn Marino cond = NULL_TREE;
996e4b17023SJohn Marino break;
997e4b17023SJohn Marino }
998e4b17023SJohn Marino
999e4b17023SJohn Marino default:
1000e4b17023SJohn Marino /* Not handled yet in if-conversion. */
1001e4b17023SJohn Marino return false;
1002e4b17023SJohn Marino }
1003e4b17023SJohn Marino }
1004e4b17023SJohn Marino
1005e4b17023SJohn Marino /* If current bb has only one successor, then consider it as an
1006e4b17023SJohn Marino unconditional goto. */
1007e4b17023SJohn Marino if (single_succ_p (bb))
1008e4b17023SJohn Marino {
1009e4b17023SJohn Marino basic_block bb_n = single_succ (bb);
1010e4b17023SJohn Marino
1011e4b17023SJohn Marino /* The successor bb inherits the predicate of its
1012e4b17023SJohn Marino predecessor. If there is no predicate in the predecessor
1013e4b17023SJohn Marino bb, then consider the successor bb as always executed. */
1014e4b17023SJohn Marino if (cond == NULL_TREE)
1015e4b17023SJohn Marino cond = boolean_true_node;
1016e4b17023SJohn Marino
1017e4b17023SJohn Marino add_to_predicate_list (bb_n, cond);
1018e4b17023SJohn Marino }
1019e4b17023SJohn Marino }
1020e4b17023SJohn Marino
1021e4b17023SJohn Marino /* The loop header is always executed. */
1022e4b17023SJohn Marino reset_bb_predicate (loop->header);
1023e4b17023SJohn Marino gcc_assert (bb_predicate_gimplified_stmts (loop->header) == NULL
1024e4b17023SJohn Marino && bb_predicate_gimplified_stmts (loop->latch) == NULL);
1025e4b17023SJohn Marino
1026e4b17023SJohn Marino return true;
1027e4b17023SJohn Marino }
1028e4b17023SJohn Marino
1029e4b17023SJohn Marino /* Return true when LOOP is if-convertible. This is a helper function
1030e4b17023SJohn Marino for if_convertible_loop_p. REFS and DDRS are initialized and freed
1031e4b17023SJohn Marino in if_convertible_loop_p. */
1032e4b17023SJohn Marino
1033e4b17023SJohn Marino static bool
if_convertible_loop_p_1(struct loop * loop,VEC (loop_p,heap)** loop_nest,VEC (data_reference_p,heap)** refs,VEC (ddr_p,heap)** ddrs)1034e4b17023SJohn Marino if_convertible_loop_p_1 (struct loop *loop,
1035e4b17023SJohn Marino VEC (loop_p, heap) **loop_nest,
1036e4b17023SJohn Marino VEC (data_reference_p, heap) **refs,
1037e4b17023SJohn Marino VEC (ddr_p, heap) **ddrs)
1038e4b17023SJohn Marino {
1039e4b17023SJohn Marino bool res;
1040e4b17023SJohn Marino unsigned int i;
1041e4b17023SJohn Marino basic_block exit_bb = NULL;
1042e4b17023SJohn Marino
1043e4b17023SJohn Marino /* Don't if-convert the loop when the data dependences cannot be
1044e4b17023SJohn Marino computed: the loop won't be vectorized in that case. */
1045e4b17023SJohn Marino res = compute_data_dependences_for_loop (loop, true, loop_nest, refs, ddrs);
1046e4b17023SJohn Marino if (!res)
1047e4b17023SJohn Marino return false;
1048e4b17023SJohn Marino
1049e4b17023SJohn Marino calculate_dominance_info (CDI_DOMINATORS);
1050e4b17023SJohn Marino
1051e4b17023SJohn Marino /* Allow statements that can be handled during if-conversion. */
1052e4b17023SJohn Marino ifc_bbs = get_loop_body_in_if_conv_order (loop);
1053e4b17023SJohn Marino if (!ifc_bbs)
1054e4b17023SJohn Marino {
1055e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1056e4b17023SJohn Marino fprintf (dump_file, "Irreducible loop\n");
1057e4b17023SJohn Marino return false;
1058e4b17023SJohn Marino }
1059e4b17023SJohn Marino
1060e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
1061e4b17023SJohn Marino {
1062e4b17023SJohn Marino basic_block bb = ifc_bbs[i];
1063e4b17023SJohn Marino
1064e4b17023SJohn Marino if (!if_convertible_bb_p (loop, bb, exit_bb))
1065e4b17023SJohn Marino return false;
1066e4b17023SJohn Marino
1067e4b17023SJohn Marino if (bb_with_exit_edge_p (loop, bb))
1068e4b17023SJohn Marino exit_bb = bb;
1069e4b17023SJohn Marino }
1070e4b17023SJohn Marino
1071e4b17023SJohn Marino res = predicate_bbs (loop);
1072e4b17023SJohn Marino if (!res)
1073e4b17023SJohn Marino return false;
1074e4b17023SJohn Marino
1075e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores)
1076e4b17023SJohn Marino {
1077e4b17023SJohn Marino data_reference_p dr;
1078e4b17023SJohn Marino
1079e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, *refs, i, dr); i++)
1080e4b17023SJohn Marino {
1081e4b17023SJohn Marino dr->aux = XNEW (struct ifc_dr);
1082e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (dr) = -1;
1083e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (dr) = -1;
1084e4b17023SJohn Marino }
1085e4b17023SJohn Marino }
1086e4b17023SJohn Marino
1087e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
1088e4b17023SJohn Marino {
1089e4b17023SJohn Marino basic_block bb = ifc_bbs[i];
1090e4b17023SJohn Marino gimple_stmt_iterator itr;
1091e4b17023SJohn Marino
1092e4b17023SJohn Marino for (itr = gsi_start_phis (bb); !gsi_end_p (itr); gsi_next (&itr))
1093e4b17023SJohn Marino if (!if_convertible_phi_p (loop, bb, gsi_stmt (itr)))
1094e4b17023SJohn Marino return false;
1095e4b17023SJohn Marino
1096e4b17023SJohn Marino /* Check the if-convertibility of statements in predicated BBs. */
1097e4b17023SJohn Marino if (is_predicated (bb))
1098e4b17023SJohn Marino for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr))
1099e4b17023SJohn Marino if (!if_convertible_stmt_p (gsi_stmt (itr), *refs))
1100e4b17023SJohn Marino return false;
1101e4b17023SJohn Marino }
1102e4b17023SJohn Marino
1103e4b17023SJohn Marino if (dump_file)
1104e4b17023SJohn Marino fprintf (dump_file, "Applying if-conversion\n");
1105e4b17023SJohn Marino
1106e4b17023SJohn Marino return true;
1107e4b17023SJohn Marino }
1108e4b17023SJohn Marino
1109e4b17023SJohn Marino /* Return true when LOOP is if-convertible.
1110e4b17023SJohn Marino LOOP is if-convertible if:
1111e4b17023SJohn Marino - it is innermost,
1112e4b17023SJohn Marino - it has two or more basic blocks,
1113e4b17023SJohn Marino - it has only one exit,
1114e4b17023SJohn Marino - loop header is not the exit edge,
1115e4b17023SJohn Marino - if its basic blocks and phi nodes are if convertible. */
1116e4b17023SJohn Marino
1117e4b17023SJohn Marino static bool
if_convertible_loop_p(struct loop * loop)1118e4b17023SJohn Marino if_convertible_loop_p (struct loop *loop)
1119e4b17023SJohn Marino {
1120e4b17023SJohn Marino edge e;
1121e4b17023SJohn Marino edge_iterator ei;
1122e4b17023SJohn Marino bool res = false;
1123e4b17023SJohn Marino VEC (data_reference_p, heap) *refs;
1124e4b17023SJohn Marino VEC (ddr_p, heap) *ddrs;
1125e4b17023SJohn Marino VEC (loop_p, heap) *loop_nest;
1126e4b17023SJohn Marino
1127e4b17023SJohn Marino /* Handle only innermost loop. */
1128e4b17023SJohn Marino if (!loop || loop->inner)
1129e4b17023SJohn Marino {
1130e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1131e4b17023SJohn Marino fprintf (dump_file, "not innermost loop\n");
1132e4b17023SJohn Marino return false;
1133e4b17023SJohn Marino }
1134e4b17023SJohn Marino
1135e4b17023SJohn Marino /* If only one block, no need for if-conversion. */
1136e4b17023SJohn Marino if (loop->num_nodes <= 2)
1137e4b17023SJohn Marino {
1138e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1139e4b17023SJohn Marino fprintf (dump_file, "less than 2 basic blocks\n");
1140e4b17023SJohn Marino return false;
1141e4b17023SJohn Marino }
1142e4b17023SJohn Marino
1143e4b17023SJohn Marino /* More than one loop exit is too much to handle. */
1144e4b17023SJohn Marino if (!single_exit (loop))
1145e4b17023SJohn Marino {
1146e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1147e4b17023SJohn Marino fprintf (dump_file, "multiple exits\n");
1148e4b17023SJohn Marino return false;
1149e4b17023SJohn Marino }
1150e4b17023SJohn Marino
1151e4b17023SJohn Marino /* If one of the loop header's edge is an exit edge then do not
1152e4b17023SJohn Marino apply if-conversion. */
1153e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, loop->header->succs)
1154e4b17023SJohn Marino if (loop_exit_edge_p (loop, e))
1155e4b17023SJohn Marino return false;
1156e4b17023SJohn Marino
1157e4b17023SJohn Marino refs = VEC_alloc (data_reference_p, heap, 5);
1158e4b17023SJohn Marino ddrs = VEC_alloc (ddr_p, heap, 25);
1159e4b17023SJohn Marino loop_nest = VEC_alloc (loop_p, heap, 3);
1160e4b17023SJohn Marino res = if_convertible_loop_p_1 (loop, &loop_nest, &refs, &ddrs);
1161e4b17023SJohn Marino
1162e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores)
1163e4b17023SJohn Marino {
1164e4b17023SJohn Marino data_reference_p dr;
1165e4b17023SJohn Marino unsigned int i;
1166e4b17023SJohn Marino
1167e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, refs, i, dr); i++)
1168e4b17023SJohn Marino free (dr->aux);
1169e4b17023SJohn Marino }
1170e4b17023SJohn Marino
1171e4b17023SJohn Marino VEC_free (loop_p, heap, loop_nest);
1172e4b17023SJohn Marino free_data_refs (refs);
1173e4b17023SJohn Marino free_dependence_relations (ddrs);
1174e4b17023SJohn Marino return res;
1175e4b17023SJohn Marino }
1176e4b17023SJohn Marino
1177e4b17023SJohn Marino /* Basic block BB has two predecessors. Using predecessor's bb
1178e4b17023SJohn Marino predicate, set an appropriate condition COND for the PHI node
1179e4b17023SJohn Marino replacement. Return the true block whose phi arguments are
1180e4b17023SJohn Marino selected when cond is true. LOOP is the loop containing the
1181e4b17023SJohn Marino if-converted region, GSI is the place to insert the code for the
1182e4b17023SJohn Marino if-conversion. */
1183e4b17023SJohn Marino
1184e4b17023SJohn Marino static basic_block
find_phi_replacement_condition(basic_block bb,tree * cond,gimple_stmt_iterator * gsi)1185*95d28233SJohn Marino find_phi_replacement_condition (basic_block bb, tree *cond,
1186e4b17023SJohn Marino gimple_stmt_iterator *gsi)
1187e4b17023SJohn Marino {
1188e4b17023SJohn Marino edge first_edge, second_edge;
1189e4b17023SJohn Marino tree tmp_cond;
1190e4b17023SJohn Marino
1191e4b17023SJohn Marino gcc_assert (EDGE_COUNT (bb->preds) == 2);
1192e4b17023SJohn Marino first_edge = EDGE_PRED (bb, 0);
1193e4b17023SJohn Marino second_edge = EDGE_PRED (bb, 1);
1194e4b17023SJohn Marino
1195*95d28233SJohn Marino /* Prefer an edge with a not negated predicate.
1196*95d28233SJohn Marino ??? That's a very weak cost model. */
1197e4b17023SJohn Marino tmp_cond = bb_predicate (first_edge->src);
1198e4b17023SJohn Marino gcc_assert (tmp_cond);
1199e4b17023SJohn Marino if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
1200e4b17023SJohn Marino {
1201e4b17023SJohn Marino edge tmp_edge;
1202e4b17023SJohn Marino
1203e4b17023SJohn Marino tmp_edge = first_edge;
1204e4b17023SJohn Marino first_edge = second_edge;
1205e4b17023SJohn Marino second_edge = tmp_edge;
1206e4b17023SJohn Marino }
1207e4b17023SJohn Marino
1208*95d28233SJohn Marino /* Check if the edge we take the condition from is not critical.
1209*95d28233SJohn Marino We know that at least one non-critical edge exists. */
1210*95d28233SJohn Marino if (EDGE_COUNT (first_edge->src->succs) > 1)
1211e4b17023SJohn Marino {
1212e4b17023SJohn Marino *cond = bb_predicate (second_edge->src);
1213e4b17023SJohn Marino
1214e4b17023SJohn Marino if (TREE_CODE (*cond) == TRUTH_NOT_EXPR)
1215e4b17023SJohn Marino *cond = TREE_OPERAND (*cond, 0);
1216e4b17023SJohn Marino else
1217e4b17023SJohn Marino /* Select non loop header bb. */
1218e4b17023SJohn Marino first_edge = second_edge;
1219e4b17023SJohn Marino }
1220e4b17023SJohn Marino else
1221e4b17023SJohn Marino *cond = bb_predicate (first_edge->src);
1222e4b17023SJohn Marino
1223e4b17023SJohn Marino /* Gimplify the condition to a valid cond-expr conditonal operand. */
1224e4b17023SJohn Marino *cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (*cond),
1225e4b17023SJohn Marino is_gimple_condexpr, NULL_TREE,
1226e4b17023SJohn Marino true, GSI_SAME_STMT);
1227e4b17023SJohn Marino
1228e4b17023SJohn Marino return first_edge->src;
1229e4b17023SJohn Marino }
1230e4b17023SJohn Marino
1231e4b17023SJohn Marino /* Replace a scalar PHI node with a COND_EXPR using COND as condition.
1232e4b17023SJohn Marino This routine does not handle PHI nodes with more than two
1233e4b17023SJohn Marino arguments.
1234e4b17023SJohn Marino
1235e4b17023SJohn Marino For example,
1236e4b17023SJohn Marino S1: A = PHI <x1(1), x2(5)>
1237e4b17023SJohn Marino is converted into,
1238e4b17023SJohn Marino S2: A = cond ? x1 : x2;
1239e4b17023SJohn Marino
1240e4b17023SJohn Marino The generated code is inserted at GSI that points to the top of
1241e4b17023SJohn Marino basic block's statement list. When COND is true, phi arg from
1242e4b17023SJohn Marino TRUE_BB is selected. */
1243e4b17023SJohn Marino
1244e4b17023SJohn Marino static void
predicate_scalar_phi(gimple phi,tree cond,basic_block true_bb,gimple_stmt_iterator * gsi)1245e4b17023SJohn Marino predicate_scalar_phi (gimple phi, tree cond,
1246e4b17023SJohn Marino basic_block true_bb,
1247e4b17023SJohn Marino gimple_stmt_iterator *gsi)
1248e4b17023SJohn Marino {
1249e4b17023SJohn Marino gimple new_stmt;
1250e4b17023SJohn Marino basic_block bb;
1251e4b17023SJohn Marino tree rhs, res, arg, scev;
1252e4b17023SJohn Marino
1253e4b17023SJohn Marino gcc_assert (gimple_code (phi) == GIMPLE_PHI
1254e4b17023SJohn Marino && gimple_phi_num_args (phi) == 2);
1255e4b17023SJohn Marino
1256e4b17023SJohn Marino res = gimple_phi_result (phi);
1257e4b17023SJohn Marino /* Do not handle virtual phi nodes. */
1258e4b17023SJohn Marino if (!is_gimple_reg (SSA_NAME_VAR (res)))
1259e4b17023SJohn Marino return;
1260e4b17023SJohn Marino
1261e4b17023SJohn Marino bb = gimple_bb (phi);
1262e4b17023SJohn Marino
1263e4b17023SJohn Marino if ((arg = degenerate_phi_result (phi))
1264e4b17023SJohn Marino || ((scev = analyze_scalar_evolution (gimple_bb (phi)->loop_father,
1265e4b17023SJohn Marino res))
1266e4b17023SJohn Marino && !chrec_contains_undetermined (scev)
1267e4b17023SJohn Marino && scev != res
1268e4b17023SJohn Marino && (arg = gimple_phi_arg_def (phi, 0))))
1269e4b17023SJohn Marino rhs = arg;
1270e4b17023SJohn Marino else
1271e4b17023SJohn Marino {
1272e4b17023SJohn Marino tree arg_0, arg_1;
1273e4b17023SJohn Marino /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */
1274e4b17023SJohn Marino if (EDGE_PRED (bb, 1)->src == true_bb)
1275e4b17023SJohn Marino {
1276e4b17023SJohn Marino arg_0 = gimple_phi_arg_def (phi, 1);
1277e4b17023SJohn Marino arg_1 = gimple_phi_arg_def (phi, 0);
1278e4b17023SJohn Marino }
1279e4b17023SJohn Marino else
1280e4b17023SJohn Marino {
1281e4b17023SJohn Marino arg_0 = gimple_phi_arg_def (phi, 0);
1282e4b17023SJohn Marino arg_1 = gimple_phi_arg_def (phi, 1);
1283e4b17023SJohn Marino }
1284e4b17023SJohn Marino
1285e4b17023SJohn Marino /* Build new RHS using selected condition and arguments. */
1286e4b17023SJohn Marino rhs = build3 (COND_EXPR, TREE_TYPE (res),
1287e4b17023SJohn Marino unshare_expr (cond), arg_0, arg_1);
1288e4b17023SJohn Marino }
1289e4b17023SJohn Marino
1290e4b17023SJohn Marino new_stmt = gimple_build_assign (res, rhs);
1291e4b17023SJohn Marino SSA_NAME_DEF_STMT (gimple_phi_result (phi)) = new_stmt;
1292e4b17023SJohn Marino gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
1293e4b17023SJohn Marino update_stmt (new_stmt);
1294e4b17023SJohn Marino
1295e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1296e4b17023SJohn Marino {
1297e4b17023SJohn Marino fprintf (dump_file, "new phi replacement stmt\n");
1298e4b17023SJohn Marino print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
1299e4b17023SJohn Marino }
1300e4b17023SJohn Marino }
1301e4b17023SJohn Marino
1302e4b17023SJohn Marino /* Replaces in LOOP all the scalar phi nodes other than those in the
1303e4b17023SJohn Marino LOOP->header block with conditional modify expressions. */
1304e4b17023SJohn Marino
1305e4b17023SJohn Marino static void
predicate_all_scalar_phis(struct loop * loop)1306e4b17023SJohn Marino predicate_all_scalar_phis (struct loop *loop)
1307e4b17023SJohn Marino {
1308e4b17023SJohn Marino basic_block bb;
1309e4b17023SJohn Marino unsigned int orig_loop_num_nodes = loop->num_nodes;
1310e4b17023SJohn Marino unsigned int i;
1311e4b17023SJohn Marino
1312e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++)
1313e4b17023SJohn Marino {
1314e4b17023SJohn Marino gimple phi;
1315e4b17023SJohn Marino tree cond = NULL_TREE;
1316e4b17023SJohn Marino gimple_stmt_iterator gsi, phi_gsi;
1317e4b17023SJohn Marino basic_block true_bb = NULL;
1318e4b17023SJohn Marino bb = ifc_bbs[i];
1319e4b17023SJohn Marino
1320e4b17023SJohn Marino if (bb == loop->header)
1321e4b17023SJohn Marino continue;
1322e4b17023SJohn Marino
1323e4b17023SJohn Marino phi_gsi = gsi_start_phis (bb);
1324e4b17023SJohn Marino if (gsi_end_p (phi_gsi))
1325e4b17023SJohn Marino continue;
1326e4b17023SJohn Marino
1327e4b17023SJohn Marino /* BB has two predecessors. Using predecessor's aux field, set
1328e4b17023SJohn Marino appropriate condition for the PHI node replacement. */
1329e4b17023SJohn Marino gsi = gsi_after_labels (bb);
1330*95d28233SJohn Marino true_bb = find_phi_replacement_condition (bb, &cond, &gsi);
1331e4b17023SJohn Marino
1332e4b17023SJohn Marino while (!gsi_end_p (phi_gsi))
1333e4b17023SJohn Marino {
1334e4b17023SJohn Marino phi = gsi_stmt (phi_gsi);
1335e4b17023SJohn Marino predicate_scalar_phi (phi, cond, true_bb, &gsi);
1336e4b17023SJohn Marino release_phi_node (phi);
1337e4b17023SJohn Marino gsi_next (&phi_gsi);
1338e4b17023SJohn Marino }
1339e4b17023SJohn Marino
1340e4b17023SJohn Marino set_phi_nodes (bb, NULL);
1341e4b17023SJohn Marino }
1342e4b17023SJohn Marino }
1343e4b17023SJohn Marino
1344e4b17023SJohn Marino /* Insert in each basic block of LOOP the statements produced by the
1345e4b17023SJohn Marino gimplification of the predicates. */
1346e4b17023SJohn Marino
1347e4b17023SJohn Marino static void
insert_gimplified_predicates(loop_p loop)1348e4b17023SJohn Marino insert_gimplified_predicates (loop_p loop)
1349e4b17023SJohn Marino {
1350e4b17023SJohn Marino unsigned int i;
1351e4b17023SJohn Marino
1352e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
1353e4b17023SJohn Marino {
1354e4b17023SJohn Marino basic_block bb = ifc_bbs[i];
1355e4b17023SJohn Marino gimple_seq stmts;
1356e4b17023SJohn Marino
1357e4b17023SJohn Marino if (!is_predicated (bb))
1358e4b17023SJohn Marino {
1359e4b17023SJohn Marino /* Do not insert statements for a basic block that is not
1360e4b17023SJohn Marino predicated. Also make sure that the predicate of the
1361e4b17023SJohn Marino basic block is set to true. */
1362e4b17023SJohn Marino reset_bb_predicate (bb);
1363e4b17023SJohn Marino continue;
1364e4b17023SJohn Marino }
1365e4b17023SJohn Marino
1366e4b17023SJohn Marino stmts = bb_predicate_gimplified_stmts (bb);
1367e4b17023SJohn Marino if (stmts)
1368e4b17023SJohn Marino {
1369e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores)
1370e4b17023SJohn Marino {
1371e4b17023SJohn Marino /* Insert the predicate of the BB just after the label,
1372e4b17023SJohn Marino as the if-conversion of memory writes will use this
1373e4b17023SJohn Marino predicate. */
1374e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_after_labels (bb);
1375e4b17023SJohn Marino gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
1376e4b17023SJohn Marino }
1377e4b17023SJohn Marino else
1378e4b17023SJohn Marino {
1379e4b17023SJohn Marino /* Insert the predicate of the BB at the end of the BB
1380e4b17023SJohn Marino as this would reduce the register pressure: the only
1381e4b17023SJohn Marino use of this predicate will be in successor BBs. */
1382e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last_bb (bb);
1383e4b17023SJohn Marino
1384e4b17023SJohn Marino if (gsi_end_p (gsi)
1385e4b17023SJohn Marino || stmt_ends_bb_p (gsi_stmt (gsi)))
1386e4b17023SJohn Marino gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
1387e4b17023SJohn Marino else
1388e4b17023SJohn Marino gsi_insert_seq_after (&gsi, stmts, GSI_SAME_STMT);
1389e4b17023SJohn Marino }
1390e4b17023SJohn Marino
1391e4b17023SJohn Marino /* Once the sequence is code generated, set it to NULL. */
1392e4b17023SJohn Marino set_bb_predicate_gimplified_stmts (bb, NULL);
1393e4b17023SJohn Marino }
1394e4b17023SJohn Marino }
1395e4b17023SJohn Marino }
1396e4b17023SJohn Marino
1397e4b17023SJohn Marino /* Predicate each write to memory in LOOP.
1398e4b17023SJohn Marino
1399e4b17023SJohn Marino This function transforms control flow constructs containing memory
1400e4b17023SJohn Marino writes of the form:
1401e4b17023SJohn Marino
1402e4b17023SJohn Marino | for (i = 0; i < N; i++)
1403e4b17023SJohn Marino | if (cond)
1404e4b17023SJohn Marino | A[i] = expr;
1405e4b17023SJohn Marino
1406e4b17023SJohn Marino into the following form that does not contain control flow:
1407e4b17023SJohn Marino
1408e4b17023SJohn Marino | for (i = 0; i < N; i++)
1409e4b17023SJohn Marino | A[i] = cond ? expr : A[i];
1410e4b17023SJohn Marino
1411e4b17023SJohn Marino The original CFG looks like this:
1412e4b17023SJohn Marino
1413e4b17023SJohn Marino | bb_0
1414e4b17023SJohn Marino | i = 0
1415e4b17023SJohn Marino | end_bb_0
1416e4b17023SJohn Marino |
1417e4b17023SJohn Marino | bb_1
1418e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_2
1419e4b17023SJohn Marino | end_bb_1
1420e4b17023SJohn Marino |
1421e4b17023SJohn Marino | bb_2
1422e4b17023SJohn Marino | cond = some_computation;
1423e4b17023SJohn Marino | if (cond) goto bb_3 else goto bb_4
1424e4b17023SJohn Marino | end_bb_2
1425e4b17023SJohn Marino |
1426e4b17023SJohn Marino | bb_3
1427e4b17023SJohn Marino | A[i] = expr;
1428e4b17023SJohn Marino | goto bb_4
1429e4b17023SJohn Marino | end_bb_3
1430e4b17023SJohn Marino |
1431e4b17023SJohn Marino | bb_4
1432e4b17023SJohn Marino | goto bb_1
1433e4b17023SJohn Marino | end_bb_4
1434e4b17023SJohn Marino
1435e4b17023SJohn Marino insert_gimplified_predicates inserts the computation of the COND
1436e4b17023SJohn Marino expression at the beginning of the destination basic block:
1437e4b17023SJohn Marino
1438e4b17023SJohn Marino | bb_0
1439e4b17023SJohn Marino | i = 0
1440e4b17023SJohn Marino | end_bb_0
1441e4b17023SJohn Marino |
1442e4b17023SJohn Marino | bb_1
1443e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_2
1444e4b17023SJohn Marino | end_bb_1
1445e4b17023SJohn Marino |
1446e4b17023SJohn Marino | bb_2
1447e4b17023SJohn Marino | cond = some_computation;
1448e4b17023SJohn Marino | if (cond) goto bb_3 else goto bb_4
1449e4b17023SJohn Marino | end_bb_2
1450e4b17023SJohn Marino |
1451e4b17023SJohn Marino | bb_3
1452e4b17023SJohn Marino | cond = some_computation;
1453e4b17023SJohn Marino | A[i] = expr;
1454e4b17023SJohn Marino | goto bb_4
1455e4b17023SJohn Marino | end_bb_3
1456e4b17023SJohn Marino |
1457e4b17023SJohn Marino | bb_4
1458e4b17023SJohn Marino | goto bb_1
1459e4b17023SJohn Marino | end_bb_4
1460e4b17023SJohn Marino
1461e4b17023SJohn Marino predicate_mem_writes is then predicating the memory write as follows:
1462e4b17023SJohn Marino
1463e4b17023SJohn Marino | bb_0
1464e4b17023SJohn Marino | i = 0
1465e4b17023SJohn Marino | end_bb_0
1466e4b17023SJohn Marino |
1467e4b17023SJohn Marino | bb_1
1468e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_2
1469e4b17023SJohn Marino | end_bb_1
1470e4b17023SJohn Marino |
1471e4b17023SJohn Marino | bb_2
1472e4b17023SJohn Marino | if (cond) goto bb_3 else goto bb_4
1473e4b17023SJohn Marino | end_bb_2
1474e4b17023SJohn Marino |
1475e4b17023SJohn Marino | bb_3
1476e4b17023SJohn Marino | cond = some_computation;
1477e4b17023SJohn Marino | A[i] = cond ? expr : A[i];
1478e4b17023SJohn Marino | goto bb_4
1479e4b17023SJohn Marino | end_bb_3
1480e4b17023SJohn Marino |
1481e4b17023SJohn Marino | bb_4
1482e4b17023SJohn Marino | goto bb_1
1483e4b17023SJohn Marino | end_bb_4
1484e4b17023SJohn Marino
1485e4b17023SJohn Marino and finally combine_blocks removes the basic block boundaries making
1486e4b17023SJohn Marino the loop vectorizable:
1487e4b17023SJohn Marino
1488e4b17023SJohn Marino | bb_0
1489e4b17023SJohn Marino | i = 0
1490e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_1
1491e4b17023SJohn Marino | end_bb_0
1492e4b17023SJohn Marino |
1493e4b17023SJohn Marino | bb_1
1494e4b17023SJohn Marino | cond = some_computation;
1495e4b17023SJohn Marino | A[i] = cond ? expr : A[i];
1496e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_4
1497e4b17023SJohn Marino | end_bb_1
1498e4b17023SJohn Marino |
1499e4b17023SJohn Marino | bb_4
1500e4b17023SJohn Marino | goto bb_1
1501e4b17023SJohn Marino | end_bb_4
1502e4b17023SJohn Marino */
1503e4b17023SJohn Marino
1504e4b17023SJohn Marino static void
predicate_mem_writes(loop_p loop)1505e4b17023SJohn Marino predicate_mem_writes (loop_p loop)
1506e4b17023SJohn Marino {
1507e4b17023SJohn Marino unsigned int i, orig_loop_num_nodes = loop->num_nodes;
1508e4b17023SJohn Marino
1509e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++)
1510e4b17023SJohn Marino {
1511e4b17023SJohn Marino gimple_stmt_iterator gsi;
1512e4b17023SJohn Marino basic_block bb = ifc_bbs[i];
1513e4b17023SJohn Marino tree cond = bb_predicate (bb);
1514e4b17023SJohn Marino bool swap;
1515e4b17023SJohn Marino gimple stmt;
1516e4b17023SJohn Marino
1517e4b17023SJohn Marino if (is_true_predicate (cond))
1518e4b17023SJohn Marino continue;
1519e4b17023SJohn Marino
1520e4b17023SJohn Marino swap = false;
1521e4b17023SJohn Marino if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
1522e4b17023SJohn Marino {
1523e4b17023SJohn Marino swap = true;
1524e4b17023SJohn Marino cond = TREE_OPERAND (cond, 0);
1525e4b17023SJohn Marino }
1526e4b17023SJohn Marino
1527e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1528e4b17023SJohn Marino if ((stmt = gsi_stmt (gsi))
1529e4b17023SJohn Marino && gimple_assign_single_p (stmt)
1530e4b17023SJohn Marino && gimple_vdef (stmt))
1531e4b17023SJohn Marino {
1532e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt);
1533e4b17023SJohn Marino tree rhs = gimple_assign_rhs1 (stmt);
1534e4b17023SJohn Marino tree type = TREE_TYPE (lhs);
1535e4b17023SJohn Marino
1536e4b17023SJohn Marino lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi);
1537e4b17023SJohn Marino rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi);
1538e4b17023SJohn Marino if (swap)
1539e4b17023SJohn Marino {
1540e4b17023SJohn Marino tree tem = lhs;
1541e4b17023SJohn Marino lhs = rhs;
1542e4b17023SJohn Marino rhs = tem;
1543e4b17023SJohn Marino }
1544e4b17023SJohn Marino cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond),
1545e4b17023SJohn Marino is_gimple_condexpr, NULL_TREE,
1546e4b17023SJohn Marino true, GSI_SAME_STMT);
1547e4b17023SJohn Marino rhs = build3 (COND_EXPR, type, unshare_expr (cond), rhs, lhs);
1548e4b17023SJohn Marino gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi));
1549e4b17023SJohn Marino update_stmt (stmt);
1550e4b17023SJohn Marino }
1551e4b17023SJohn Marino }
1552e4b17023SJohn Marino }
1553e4b17023SJohn Marino
1554e4b17023SJohn Marino /* Remove all GIMPLE_CONDs and GIMPLE_LABELs of all the basic blocks
1555e4b17023SJohn Marino other than the exit and latch of the LOOP. Also resets the
1556e4b17023SJohn Marino GIMPLE_DEBUG information. */
1557e4b17023SJohn Marino
1558e4b17023SJohn Marino static void
remove_conditions_and_labels(loop_p loop)1559e4b17023SJohn Marino remove_conditions_and_labels (loop_p loop)
1560e4b17023SJohn Marino {
1561e4b17023SJohn Marino gimple_stmt_iterator gsi;
1562e4b17023SJohn Marino unsigned int i;
1563e4b17023SJohn Marino
1564e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
1565e4b17023SJohn Marino {
1566e4b17023SJohn Marino basic_block bb = ifc_bbs[i];
1567e4b17023SJohn Marino
1568e4b17023SJohn Marino if (bb_with_exit_edge_p (loop, bb)
1569e4b17023SJohn Marino || bb == loop->latch)
1570e4b17023SJohn Marino continue;
1571e4b17023SJohn Marino
1572e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
1573e4b17023SJohn Marino switch (gimple_code (gsi_stmt (gsi)))
1574e4b17023SJohn Marino {
1575e4b17023SJohn Marino case GIMPLE_COND:
1576e4b17023SJohn Marino case GIMPLE_LABEL:
1577e4b17023SJohn Marino gsi_remove (&gsi, true);
1578e4b17023SJohn Marino break;
1579e4b17023SJohn Marino
1580e4b17023SJohn Marino case GIMPLE_DEBUG:
1581e4b17023SJohn Marino /* ??? Should there be conditional GIMPLE_DEBUG_BINDs? */
1582e4b17023SJohn Marino if (gimple_debug_bind_p (gsi_stmt (gsi)))
1583e4b17023SJohn Marino {
1584e4b17023SJohn Marino gimple_debug_bind_reset_value (gsi_stmt (gsi));
1585e4b17023SJohn Marino update_stmt (gsi_stmt (gsi));
1586e4b17023SJohn Marino }
1587e4b17023SJohn Marino gsi_next (&gsi);
1588e4b17023SJohn Marino break;
1589e4b17023SJohn Marino
1590e4b17023SJohn Marino default:
1591e4b17023SJohn Marino gsi_next (&gsi);
1592e4b17023SJohn Marino }
1593e4b17023SJohn Marino }
1594e4b17023SJohn Marino }
1595e4b17023SJohn Marino
1596e4b17023SJohn Marino /* Combine all the basic blocks from LOOP into one or two super basic
1597e4b17023SJohn Marino blocks. Replace PHI nodes with conditional modify expressions. */
1598e4b17023SJohn Marino
1599e4b17023SJohn Marino static void
combine_blocks(struct loop * loop)1600e4b17023SJohn Marino combine_blocks (struct loop *loop)
1601e4b17023SJohn Marino {
1602e4b17023SJohn Marino basic_block bb, exit_bb, merge_target_bb;
1603e4b17023SJohn Marino unsigned int orig_loop_num_nodes = loop->num_nodes;
1604e4b17023SJohn Marino unsigned int i;
1605e4b17023SJohn Marino edge e;
1606e4b17023SJohn Marino edge_iterator ei;
1607e4b17023SJohn Marino
1608e4b17023SJohn Marino remove_conditions_and_labels (loop);
1609e4b17023SJohn Marino insert_gimplified_predicates (loop);
1610e4b17023SJohn Marino predicate_all_scalar_phis (loop);
1611e4b17023SJohn Marino
1612e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores)
1613e4b17023SJohn Marino predicate_mem_writes (loop);
1614e4b17023SJohn Marino
1615e4b17023SJohn Marino /* Merge basic blocks: first remove all the edges in the loop,
1616e4b17023SJohn Marino except for those from the exit block. */
1617e4b17023SJohn Marino exit_bb = NULL;
1618e4b17023SJohn Marino for (i = 0; i < orig_loop_num_nodes; i++)
1619e4b17023SJohn Marino {
1620e4b17023SJohn Marino bb = ifc_bbs[i];
1621e4b17023SJohn Marino free_bb_predicate (bb);
1622e4b17023SJohn Marino if (bb_with_exit_edge_p (loop, bb))
1623e4b17023SJohn Marino {
1624e4b17023SJohn Marino exit_bb = bb;
1625e4b17023SJohn Marino break;
1626e4b17023SJohn Marino }
1627e4b17023SJohn Marino }
1628e4b17023SJohn Marino gcc_assert (exit_bb != loop->latch);
1629e4b17023SJohn Marino
1630e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++)
1631e4b17023SJohn Marino {
1632e4b17023SJohn Marino bb = ifc_bbs[i];
1633e4b17023SJohn Marino
1634e4b17023SJohn Marino for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
1635e4b17023SJohn Marino {
1636e4b17023SJohn Marino if (e->src == exit_bb)
1637e4b17023SJohn Marino ei_next (&ei);
1638e4b17023SJohn Marino else
1639e4b17023SJohn Marino remove_edge (e);
1640e4b17023SJohn Marino }
1641e4b17023SJohn Marino }
1642e4b17023SJohn Marino
1643e4b17023SJohn Marino if (exit_bb != NULL)
1644e4b17023SJohn Marino {
1645e4b17023SJohn Marino if (exit_bb != loop->header)
1646e4b17023SJohn Marino {
1647e4b17023SJohn Marino /* Connect this node to loop header. */
1648e4b17023SJohn Marino make_edge (loop->header, exit_bb, EDGE_FALLTHRU);
1649e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
1650e4b17023SJohn Marino }
1651e4b17023SJohn Marino
1652e4b17023SJohn Marino /* Redirect non-exit edges to loop->latch. */
1653e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, exit_bb->succs)
1654e4b17023SJohn Marino {
1655e4b17023SJohn Marino if (!loop_exit_edge_p (loop, e))
1656e4b17023SJohn Marino redirect_edge_and_branch (e, loop->latch);
1657e4b17023SJohn Marino }
1658e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb);
1659e4b17023SJohn Marino }
1660e4b17023SJohn Marino else
1661e4b17023SJohn Marino {
1662e4b17023SJohn Marino /* If the loop does not have an exit, reconnect header and latch. */
1663e4b17023SJohn Marino make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
1664e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
1665e4b17023SJohn Marino }
1666e4b17023SJohn Marino
1667e4b17023SJohn Marino merge_target_bb = loop->header;
1668e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++)
1669e4b17023SJohn Marino {
1670e4b17023SJohn Marino gimple_stmt_iterator gsi;
1671e4b17023SJohn Marino gimple_stmt_iterator last;
1672e4b17023SJohn Marino
1673e4b17023SJohn Marino bb = ifc_bbs[i];
1674e4b17023SJohn Marino
1675e4b17023SJohn Marino if (bb == exit_bb || bb == loop->latch)
1676e4b17023SJohn Marino continue;
1677e4b17023SJohn Marino
1678e4b17023SJohn Marino /* Make stmts member of loop->header. */
1679e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1680e4b17023SJohn Marino gimple_set_bb (gsi_stmt (gsi), merge_target_bb);
1681e4b17023SJohn Marino
1682e4b17023SJohn Marino /* Update stmt list. */
1683e4b17023SJohn Marino last = gsi_last_bb (merge_target_bb);
1684e4b17023SJohn Marino gsi_insert_seq_after (&last, bb_seq (bb), GSI_NEW_STMT);
1685e4b17023SJohn Marino set_bb_seq (bb, NULL);
1686e4b17023SJohn Marino
1687e4b17023SJohn Marino delete_basic_block (bb);
1688e4b17023SJohn Marino }
1689e4b17023SJohn Marino
1690e4b17023SJohn Marino /* If possible, merge loop header to the block with the exit edge.
1691e4b17023SJohn Marino This reduces the number of basic blocks to two, to please the
1692e4b17023SJohn Marino vectorizer that handles only loops with two nodes. */
1693e4b17023SJohn Marino if (exit_bb
1694e4b17023SJohn Marino && exit_bb != loop->header
1695e4b17023SJohn Marino && can_merge_blocks_p (loop->header, exit_bb))
1696e4b17023SJohn Marino merge_blocks (loop->header, exit_bb);
1697e4b17023SJohn Marino
1698e4b17023SJohn Marino free (ifc_bbs);
1699e4b17023SJohn Marino ifc_bbs = NULL;
1700e4b17023SJohn Marino }
1701e4b17023SJohn Marino
1702e4b17023SJohn Marino /* If-convert LOOP when it is legal. For the moment this pass has no
1703e4b17023SJohn Marino profitability analysis. Returns true when something changed. */
1704e4b17023SJohn Marino
1705e4b17023SJohn Marino static bool
tree_if_conversion(struct loop * loop)1706e4b17023SJohn Marino tree_if_conversion (struct loop *loop)
1707e4b17023SJohn Marino {
1708e4b17023SJohn Marino bool changed = false;
1709e4b17023SJohn Marino ifc_bbs = NULL;
1710e4b17023SJohn Marino
1711e4b17023SJohn Marino if (!if_convertible_loop_p (loop)
1712e4b17023SJohn Marino || !dbg_cnt (if_conversion_tree))
1713e4b17023SJohn Marino goto cleanup;
1714e4b17023SJohn Marino
1715e4b17023SJohn Marino /* Now all statements are if-convertible. Combine all the basic
1716e4b17023SJohn Marino blocks into one huge basic block doing the if-conversion
1717e4b17023SJohn Marino on-the-fly. */
1718e4b17023SJohn Marino combine_blocks (loop);
1719e4b17023SJohn Marino
1720e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores)
1721e4b17023SJohn Marino mark_sym_for_renaming (gimple_vop (cfun));
1722e4b17023SJohn Marino
1723e4b17023SJohn Marino changed = true;
1724e4b17023SJohn Marino
1725e4b17023SJohn Marino cleanup:
1726e4b17023SJohn Marino if (ifc_bbs)
1727e4b17023SJohn Marino {
1728e4b17023SJohn Marino unsigned int i;
1729e4b17023SJohn Marino
1730e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++)
1731e4b17023SJohn Marino free_bb_predicate (ifc_bbs[i]);
1732e4b17023SJohn Marino
1733e4b17023SJohn Marino free (ifc_bbs);
1734e4b17023SJohn Marino ifc_bbs = NULL;
1735e4b17023SJohn Marino }
1736e4b17023SJohn Marino
1737e4b17023SJohn Marino return changed;
1738e4b17023SJohn Marino }
1739e4b17023SJohn Marino
1740e4b17023SJohn Marino /* Tree if-conversion pass management. */
1741e4b17023SJohn Marino
1742e4b17023SJohn Marino static unsigned int
main_tree_if_conversion(void)1743e4b17023SJohn Marino main_tree_if_conversion (void)
1744e4b17023SJohn Marino {
1745e4b17023SJohn Marino loop_iterator li;
1746e4b17023SJohn Marino struct loop *loop;
1747e4b17023SJohn Marino bool changed = false;
1748e4b17023SJohn Marino unsigned todo = 0;
1749e4b17023SJohn Marino
1750e4b17023SJohn Marino if (number_of_loops () <= 1)
1751e4b17023SJohn Marino return 0;
1752e4b17023SJohn Marino
1753e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, 0)
1754e4b17023SJohn Marino changed |= tree_if_conversion (loop);
1755e4b17023SJohn Marino
1756e4b17023SJohn Marino if (changed)
1757e4b17023SJohn Marino todo |= TODO_cleanup_cfg;
1758e4b17023SJohn Marino
1759e4b17023SJohn Marino if (changed && flag_tree_loop_if_convert_stores)
1760e4b17023SJohn Marino todo |= TODO_update_ssa_only_virtuals;
1761e4b17023SJohn Marino
1762e4b17023SJohn Marino return todo;
1763e4b17023SJohn Marino }
1764e4b17023SJohn Marino
1765e4b17023SJohn Marino /* Returns true when the if-conversion pass is enabled. */
1766e4b17023SJohn Marino
1767e4b17023SJohn Marino static bool
gate_tree_if_conversion(void)1768e4b17023SJohn Marino gate_tree_if_conversion (void)
1769e4b17023SJohn Marino {
1770e4b17023SJohn Marino return ((flag_tree_vectorize && flag_tree_loop_if_convert != 0)
1771e4b17023SJohn Marino || flag_tree_loop_if_convert == 1
1772e4b17023SJohn Marino || flag_tree_loop_if_convert_stores == 1);
1773e4b17023SJohn Marino }
1774e4b17023SJohn Marino
1775e4b17023SJohn Marino struct gimple_opt_pass pass_if_conversion =
1776e4b17023SJohn Marino {
1777e4b17023SJohn Marino {
1778e4b17023SJohn Marino GIMPLE_PASS,
1779e4b17023SJohn Marino "ifcvt", /* name */
1780e4b17023SJohn Marino gate_tree_if_conversion, /* gate */
1781e4b17023SJohn Marino main_tree_if_conversion, /* execute */
1782e4b17023SJohn Marino NULL, /* sub */
1783e4b17023SJohn Marino NULL, /* next */
1784e4b17023SJohn Marino 0, /* static_pass_number */
1785e4b17023SJohn Marino TV_NONE, /* tv_id */
1786e4b17023SJohn Marino PROP_cfg | PROP_ssa, /* properties_required */
1787e4b17023SJohn Marino 0, /* properties_provided */
1788e4b17023SJohn Marino 0, /* properties_destroyed */
1789e4b17023SJohn Marino 0, /* todo_flags_start */
1790e4b17023SJohn Marino TODO_verify_stmts | TODO_verify_flow
1791e4b17023SJohn Marino /* todo_flags_finish */
1792e4b17023SJohn Marino }
1793e4b17023SJohn Marino };
1794