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