xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-if-conv.c (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
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