Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-if-conv.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* If-conversion for vectorizer. | 1 /* If-conversion for vectorizer. |
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 | 2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 Contributed by Devang Patel <dpatel@apple.com> | 4 Contributed by Devang Patel <dpatel@apple.com> |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
17 | 17 |
18 You should have received a copy of the GNU General Public License | 18 You should have received a copy of the GNU General Public License |
19 along with GCC; see the file COPYING3. If not see | 19 along with GCC; see the file COPYING3. If not see |
20 <http://www.gnu.org/licenses/>. */ | 20 <http://www.gnu.org/licenses/>. */ |
21 | 21 |
22 /* This pass implements tree level if-conversion transformation of loops. | 22 /* This pass implements a tree level if-conversion of loops. Its |
23 Initial goal is to help vectorizer vectorize loops with conditions. | 23 initial goal is to help the vectorizer to vectorize loops with |
24 conditions. | |
24 | 25 |
25 A short description of if-conversion: | 26 A short description of if-conversion: |
26 | 27 |
27 o Decide if a loop is if-convertible or not. | 28 o Decide if a loop is if-convertible or not. |
28 o Walk all loop basic blocks in breadth first order (BFS order). | 29 o Walk all loop basic blocks in breadth first order (BFS order). |
85 #include "coretypes.h" | 86 #include "coretypes.h" |
86 #include "tm.h" | 87 #include "tm.h" |
87 #include "tree.h" | 88 #include "tree.h" |
88 #include "flags.h" | 89 #include "flags.h" |
89 #include "timevar.h" | 90 #include "timevar.h" |
90 #include "varray.h" | |
91 #include "rtl.h" | |
92 #include "basic-block.h" | 91 #include "basic-block.h" |
93 #include "diagnostic.h" | 92 #include "diagnostic.h" |
93 #include "tree-pretty-print.h" | |
94 #include "gimple-pretty-print.h" | |
94 #include "tree-flow.h" | 95 #include "tree-flow.h" |
95 #include "tree-dump.h" | 96 #include "tree-dump.h" |
96 #include "cfgloop.h" | 97 #include "cfgloop.h" |
97 #include "tree-chrec.h" | 98 #include "tree-chrec.h" |
98 #include "tree-data-ref.h" | 99 #include "tree-data-ref.h" |
99 #include "tree-scalar-evolution.h" | 100 #include "tree-scalar-evolution.h" |
100 #include "tree-pass.h" | 101 #include "tree-pass.h" |
101 #include "target.h" | |
102 | |
103 | |
104 /* local function prototypes */ | |
105 static unsigned int main_tree_if_conversion (void); | |
106 static tree tree_if_convert_stmt (struct loop *loop, gimple, tree, | |
107 gimple_stmt_iterator *); | |
108 static void tree_if_convert_cond_stmt (struct loop *, gimple, tree, | |
109 gimple_stmt_iterator *); | |
110 static bool if_convertible_phi_p (struct loop *, basic_block, gimple); | |
111 static bool if_convertible_gimple_assign_stmt_p (struct loop *, basic_block, | |
112 gimple); | |
113 static bool if_convertible_stmt_p (struct loop *, basic_block, gimple); | |
114 static bool if_convertible_bb_p (struct loop *, basic_block, basic_block); | |
115 static bool if_convertible_loop_p (struct loop *, bool); | |
116 static void add_to_predicate_list (basic_block, tree); | |
117 static tree add_to_dst_predicate_list (struct loop * loop, edge, | |
118 tree, tree, | |
119 gimple_stmt_iterator *); | |
120 static void clean_predicate_lists (struct loop *loop); | |
121 static basic_block find_phi_replacement_condition (struct loop *loop, | |
122 basic_block, tree *, | |
123 gimple_stmt_iterator *); | |
124 static void replace_phi_with_cond_gimple_assign_stmt (gimple, tree, | |
125 basic_block, | |
126 gimple_stmt_iterator *); | |
127 static void process_phi_nodes (struct loop *); | |
128 static void combine_blocks (struct loop *); | |
129 static gimple ifc_temp_var (tree, tree); | |
130 static bool pred_blocks_visited_p (basic_block, bitmap *); | |
131 static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop); | |
132 static bool bb_with_exit_edge_p (struct loop *, basic_block); | |
133 | 102 |
134 /* List of basic blocks in if-conversion-suitable order. */ | 103 /* List of basic blocks in if-conversion-suitable order. */ |
135 static basic_block *ifc_bbs; | 104 static basic_block *ifc_bbs; |
136 | 105 |
137 /* Main entry point. | 106 /* Create a new temp variable of type TYPE. Add GIMPLE_ASSIGN to assign EXP |
138 Apply if-conversion to the LOOP. Return true if successful otherwise return | 107 to the new variable. */ |
139 false. If false is returned then loop remains unchanged. | 108 |
140 FOR_VECTORIZER is a boolean flag. It indicates whether if-conversion is used | 109 static gimple |
141 for vectorizer or not. If it is used for vectorizer, additional checks are | 110 ifc_temp_var (tree type, tree exp) |
142 used. (Vectorization checks are not yet implemented). */ | 111 { |
112 const char *name = "_ifc_"; | |
113 tree var, new_name; | |
114 gimple stmt; | |
115 | |
116 /* Create new temporary variable. */ | |
117 var = create_tmp_var (type, name); | |
118 add_referenced_var (var); | |
119 | |
120 /* Build new statement to assign EXP to new variable. */ | |
121 stmt = gimple_build_assign (var, exp); | |
122 | |
123 /* Get SSA name for the new variable and set make new statement | |
124 its definition statement. */ | |
125 new_name = make_ssa_name (var, stmt); | |
126 gimple_assign_set_lhs (stmt, new_name); | |
127 SSA_NAME_DEF_STMT (new_name) = stmt; | |
128 update_stmt (stmt); | |
129 | |
130 return stmt; | |
131 } | |
132 | |
133 /* Add condition NEW_COND to the predicate list of basic block BB. */ | |
134 | |
135 static void | |
136 add_to_predicate_list (basic_block bb, tree new_cond) | |
137 { | |
138 tree cond = (tree) bb->aux; | |
139 | |
140 if (cond) | |
141 cond = fold_build2_loc (EXPR_LOCATION (cond), | |
142 TRUTH_OR_EXPR, boolean_type_node, | |
143 unshare_expr (cond), new_cond); | |
144 else | |
145 cond = new_cond; | |
146 | |
147 bb->aux = cond; | |
148 } | |
149 | |
150 /* Add the condition COND to the previous condition PREV_COND, and add this | |
151 to the predicate list of the destination of edge E. GSI is the | |
152 place where the gimplification of the resulting condition should | |
153 output code. LOOP is the loop to be if-converted. */ | |
154 | |
155 static tree | |
156 add_to_dst_predicate_list (struct loop *loop, edge e, | |
157 tree prev_cond, tree cond, | |
158 gimple_stmt_iterator *gsi) | |
159 { | |
160 tree new_cond = NULL_TREE; | |
161 | |
162 if (!flow_bb_inside_loop_p (loop, e->dest)) | |
163 return NULL_TREE; | |
164 | |
165 if (prev_cond == boolean_true_node || !prev_cond) | |
166 new_cond = unshare_expr (cond); | |
167 else | |
168 { | |
169 tree tmp; | |
170 gimple tmp_stmt = NULL; | |
171 | |
172 prev_cond = force_gimple_operand_gsi (gsi, unshare_expr (prev_cond), | |
173 true, NULL, true, GSI_SAME_STMT); | |
174 | |
175 cond = force_gimple_operand_gsi (gsi, unshare_expr (cond), | |
176 true, NULL, true, GSI_SAME_STMT); | |
177 | |
178 /* Add the condition COND to the e->aux field. In case the edge | |
179 destination is a PHI node, this condition will be added to | |
180 the block predicate to construct a complete condition. */ | |
181 e->aux = cond; | |
182 | |
183 tmp = build2 (TRUTH_AND_EXPR, boolean_type_node, | |
184 unshare_expr (prev_cond), cond); | |
185 tmp_stmt = ifc_temp_var (boolean_type_node, tmp); | |
186 gsi_insert_before (gsi, tmp_stmt, GSI_SAME_STMT); | |
187 new_cond = gimple_assign_lhs (tmp_stmt); | |
188 } | |
189 | |
190 add_to_predicate_list (e->dest, new_cond); | |
191 return new_cond; | |
192 } | |
193 | |
194 /* Return true if one of the successor edges of BB exits LOOP. */ | |
143 | 195 |
144 static bool | 196 static bool |
145 tree_if_conversion (struct loop *loop, bool for_vectorizer) | 197 bb_with_exit_edge_p (struct loop *loop, basic_block bb) |
146 { | 198 { |
147 basic_block bb; | 199 edge e; |
148 gimple_stmt_iterator itr; | 200 edge_iterator ei; |
149 unsigned int i; | 201 |
150 | 202 FOR_EACH_EDGE (e, ei, bb->succs) |
151 ifc_bbs = NULL; | 203 if (loop_exit_edge_p (loop, e)) |
152 | 204 return true; |
153 /* if-conversion is not appropriate for all loops. First, check if loop is | 205 |
154 if-convertible or not. */ | 206 return false; |
155 if (!if_convertible_loop_p (loop, for_vectorizer)) | 207 } |
156 { | 208 |
157 if (dump_file && (dump_flags & TDF_DETAILS)) | 209 /* STMT is a GIMPLE_COND. Update two destination's predicate list. |
158 fprintf (dump_file,"-------------------------\n"); | 210 Remove COND_EXPR, if it is not the exit condition of LOOP. |
159 if (ifc_bbs) | 211 Otherwise update the exit condition of LOOP appropriately. GSI |
160 { | 212 points to the statement STMT. */ |
161 free (ifc_bbs); | 213 |
162 ifc_bbs = NULL; | 214 static void |
163 } | 215 tree_if_convert_cond_stmt (struct loop *loop, gimple stmt, tree cond, |
164 free_dominance_info (CDI_POST_DOMINATORS); | 216 gimple_stmt_iterator *gsi) |
165 return false; | 217 { |
166 } | 218 tree c2; |
167 | 219 edge true_edge, false_edge; |
168 /* Do actual work now. */ | 220 location_t loc = gimple_location (stmt); |
169 for (i = 0; i < loop->num_nodes; i++) | 221 tree c = fold_build2_loc (loc, gimple_cond_code (stmt), boolean_type_node, |
170 { | 222 gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); |
171 tree cond; | 223 |
172 | 224 extract_true_false_edges_from_block (gimple_bb (stmt), |
173 bb = ifc_bbs [i]; | 225 &true_edge, &false_edge); |
174 | 226 |
175 /* Update condition using predicate list. */ | 227 /* Add new condition into destination's predicate list. */ |
176 cond = (tree) bb->aux; | 228 |
177 | 229 /* If C is true, then TRUE_EDGE is taken. */ |
178 /* Process all statements in this basic block. | 230 add_to_dst_predicate_list (loop, true_edge, cond, c, gsi); |
179 Remove conditional expression, if any, and annotate | 231 |
180 destination basic block(s) appropriately. */ | 232 /* If C is false, then FALSE_EDGE is taken. */ |
181 for (itr = gsi_start_bb (bb); !gsi_end_p (itr); /* empty */) | 233 c2 = invert_truthvalue_loc (loc, unshare_expr (c)); |
182 { | 234 add_to_dst_predicate_list (loop, false_edge, cond, c2, gsi); |
183 gimple t = gsi_stmt (itr); | 235 |
184 cond = tree_if_convert_stmt (loop, t, cond, &itr); | 236 /* Now this conditional statement is redundant. Remove it. But, do |
185 if (!gsi_end_p (itr)) | 237 not remove the exit condition! Update the exit condition using |
186 gsi_next (&itr); | 238 the new condition. */ |
187 } | 239 if (!bb_with_exit_edge_p (loop, gimple_bb (stmt))) |
188 | 240 { |
189 /* If current bb has only one successor, then consider it as an | 241 gsi_remove (gsi, true); |
190 unconditional goto. */ | 242 cond = NULL_TREE; |
191 if (single_succ_p (bb)) | 243 } |
192 { | 244 } |
193 basic_block bb_n = single_succ (bb); | 245 |
194 | 246 /* If-convert stmt T which is part of LOOP. |
195 /* Successor bb inherits predicate of its predecessor. If there | 247 |
196 is no predicate in predecessor bb, then consider successor bb | 248 If T is a GIMPLE_ASSIGN then it is converted into a conditional |
197 as always executed. */ | 249 modify expression using COND. For conditional expressions, add |
198 if (cond == NULL_TREE) | 250 a condition in the destination basic block's predicate list and |
199 cond = boolean_true_node; | 251 remove the conditional expression itself. GSI points to the |
200 | 252 statement T. */ |
201 add_to_predicate_list (bb_n, cond); | |
202 } | |
203 } | |
204 | |
205 /* Now, all statements are if-converted and basic blocks are | |
206 annotated appropriately. Combine all basic block into one huge | |
207 basic block. */ | |
208 combine_blocks (loop); | |
209 | |
210 /* clean up */ | |
211 clean_predicate_lists (loop); | |
212 free (ifc_bbs); | |
213 ifc_bbs = NULL; | |
214 | |
215 return true; | |
216 } | |
217 | |
218 /* if-convert stmt T which is part of LOOP. | |
219 If T is a GIMPLE_ASSIGN then it is converted into conditional modify | |
220 expression using COND. For conditional expressions, add condition in the | |
221 destination basic block's predicate list and remove conditional | |
222 expression itself. BSI is the iterator used to traverse statements of | |
223 loop. It is used here when it is required to delete current statement. */ | |
224 | 253 |
225 static tree | 254 static tree |
226 tree_if_convert_stmt (struct loop * loop, gimple t, tree cond, | 255 tree_if_convert_stmt (struct loop *loop, gimple t, tree cond, |
227 gimple_stmt_iterator *gsi) | 256 gimple_stmt_iterator *gsi) |
228 { | 257 { |
229 if (dump_file && (dump_flags & TDF_DETAILS)) | 258 if (dump_file && (dump_flags & TDF_DETAILS)) |
230 { | 259 { |
231 fprintf (dump_file, "------if-convert stmt\n"); | 260 fprintf (dump_file, "------if-convert stmt\n"); |
247 update_stmt (gsi_stmt (*gsi)); | 276 update_stmt (gsi_stmt (*gsi)); |
248 } | 277 } |
249 break; | 278 break; |
250 | 279 |
251 case GIMPLE_ASSIGN: | 280 case GIMPLE_ASSIGN: |
252 /* This GIMPLE_ASSIGN is killing previous value of LHS. Appropriate | 281 /* This GIMPLE_ASSIGN is killing previous value of LHS. Appropriate |
253 value will be selected by PHI node based on condition. It is possible | 282 value will be selected by PHI node based on condition. It is possible |
254 that before this transformation, PHI nodes was selecting default | 283 that before this transformation, PHI nodes was selecting default |
255 value and now it will use this new value. This is OK because it does | 284 value and now it will use this new value. This is OK because it does |
256 not change validity the program. */ | 285 not change the validity of the program. */ |
257 break; | 286 break; |
258 | 287 |
259 case GIMPLE_COND: | 288 case GIMPLE_COND: |
260 /* Update destination blocks' predicate list and remove this | 289 /* Update destination blocks' predicate list and remove this |
261 condition expression. */ | 290 condition expression. */ |
264 break; | 293 break; |
265 | 294 |
266 default: | 295 default: |
267 gcc_unreachable (); | 296 gcc_unreachable (); |
268 } | 297 } |
298 | |
269 return cond; | 299 return cond; |
270 } | 300 } |
271 | 301 |
272 /* STMT is a GIMPLE_COND. Update two destination's predicate list. | 302 /* Return true when PHI is if-convertible. PHI is part of loop LOOP |
273 Remove COND_EXPR, if it is not the loop exit condition. Otherwise | |
274 update loop exit condition appropriately. GSI is the iterator | |
275 used to traverse statement list. STMT is part of loop LOOP. */ | |
276 | |
277 static void | |
278 tree_if_convert_cond_stmt (struct loop *loop, gimple stmt, tree cond, | |
279 gimple_stmt_iterator *gsi) | |
280 { | |
281 tree c, c2; | |
282 edge true_edge, false_edge; | |
283 location_t loc = gimple_location (stmt); | |
284 | |
285 gcc_assert (gimple_code (stmt) == GIMPLE_COND); | |
286 | |
287 c = fold_build2_loc (loc, gimple_cond_code (stmt), boolean_type_node, | |
288 gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); | |
289 | |
290 extract_true_false_edges_from_block (gimple_bb (stmt), | |
291 &true_edge, &false_edge); | |
292 | |
293 /* Add new condition into destination's predicate list. */ | |
294 | |
295 /* If C is true then TRUE_EDGE is taken. */ | |
296 add_to_dst_predicate_list (loop, true_edge, cond, c, gsi); | |
297 | |
298 /* If 'c' is false then FALSE_EDGE is taken. */ | |
299 c2 = invert_truthvalue_loc (loc, unshare_expr (c)); | |
300 add_to_dst_predicate_list (loop, false_edge, cond, c2, gsi); | |
301 | |
302 /* Now this conditional statement is redundant. Remove it. | |
303 But, do not remove exit condition! Update exit condition | |
304 using new condition. */ | |
305 if (!bb_with_exit_edge_p (loop, gimple_bb (stmt))) | |
306 { | |
307 gsi_remove (gsi, true); | |
308 cond = NULL_TREE; | |
309 } | |
310 return; | |
311 } | |
312 | |
313 /* Return true, iff PHI is if-convertible. PHI is part of loop LOOP | |
314 and it belongs to basic block BB. | 303 and it belongs to basic block BB. |
315 PHI is not if-convertible | 304 |
316 - if it has more than 2 arguments. | 305 PHI is not if-convertible if: |
317 - Virtual PHI is immediately used in another PHI node. | 306 - it has more than 2 arguments, |
318 - Virtual PHI on BB other than header. */ | 307 - virtual PHI is immediately used in another PHI node, |
308 - virtual PHI on BB other than header. */ | |
319 | 309 |
320 static bool | 310 static bool |
321 if_convertible_phi_p (struct loop *loop, basic_block bb, gimple phi) | 311 if_convertible_phi_p (struct loop *loop, basic_block bb, gimple phi) |
322 { | 312 { |
323 if (dump_file && (dump_flags & TDF_DETAILS)) | 313 if (dump_file && (dump_flags & TDF_DETAILS)) |
356 } | 346 } |
357 | 347 |
358 return true; | 348 return true; |
359 } | 349 } |
360 | 350 |
361 /* Return true, if STMT is if-convertible. | 351 /* Return true when STMT is if-convertible. |
352 | |
362 GIMPLE_ASSIGN statement is not if-convertible if, | 353 GIMPLE_ASSIGN statement is not if-convertible if, |
363 - It is not movable. | 354 - it is not movable, |
364 - It could trap. | 355 - it could trap, |
365 - LHS is not var decl. | 356 - LHS is not var decl. |
366 GIMPLE_ASSIGN is part of block BB, which is inside loop LOOP. */ | 357 |
358 GIMPLE_ASSIGN is part of block BB, which is inside loop LOOP. */ | |
367 | 359 |
368 static bool | 360 static bool |
369 if_convertible_gimple_assign_stmt_p (struct loop *loop, basic_block bb, | 361 if_convertible_gimple_assign_stmt_p (struct loop *loop, basic_block bb, |
370 gimple stmt) | 362 gimple stmt) |
371 { | 363 { |
372 tree lhs; | 364 tree lhs = gimple_assign_lhs (stmt); |
373 | |
374 if (!is_gimple_assign (stmt)) | |
375 return false; | |
376 | 365 |
377 if (dump_file && (dump_flags & TDF_DETAILS)) | 366 if (dump_file && (dump_flags & TDF_DETAILS)) |
378 { | 367 { |
379 fprintf (dump_file, "-------------------------\n"); | 368 fprintf (dump_file, "-------------------------\n"); |
380 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); | 369 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); |
381 } | 370 } |
382 | |
383 lhs = gimple_assign_lhs (stmt); | |
384 | 371 |
385 /* Some of these constrains might be too conservative. */ | 372 /* Some of these constrains might be too conservative. */ |
386 if (stmt_ends_bb_p (stmt) | 373 if (stmt_ends_bb_p (stmt) |
387 || gimple_has_volatile_ops (stmt) | 374 || gimple_has_volatile_ops (stmt) |
388 || (TREE_CODE (lhs) == SSA_NAME | 375 || (TREE_CODE (lhs) == SSA_NAME |
416 } | 403 } |
417 | 404 |
418 return true; | 405 return true; |
419 } | 406 } |
420 | 407 |
421 /* Return true, iff STMT is if-convertible. | 408 /* Return true when STMT is if-convertible. |
422 Statement is if-convertible if, | 409 |
423 - It is if-convertible GIMPLE_ASSGIN | 410 A statement is if-convertible if: |
424 - It is GIMPLE_LABEL or GIMPLE_COND. | 411 - it is an if-convertible GIMPLE_ASSGIN, |
425 STMT is inside block BB, which is inside loop LOOP. */ | 412 - it is a GIMPLE_LABEL or a GIMPLE_COND. |
413 | |
414 STMT is inside BB, which is inside loop LOOP. */ | |
426 | 415 |
427 static bool | 416 static bool |
428 if_convertible_stmt_p (struct loop *loop, basic_block bb, gimple stmt) | 417 if_convertible_stmt_p (struct loop *loop, basic_block bb, gimple stmt) |
429 { | 418 { |
430 switch (gimple_code (stmt)) | 419 switch (gimple_code (stmt)) |
431 { | 420 { |
432 case GIMPLE_LABEL: | 421 case GIMPLE_LABEL: |
433 break; | |
434 | |
435 case GIMPLE_DEBUG: | 422 case GIMPLE_DEBUG: |
436 break; | 423 case GIMPLE_COND: |
424 return true; | |
437 | 425 |
438 case GIMPLE_ASSIGN: | 426 case GIMPLE_ASSIGN: |
439 if (!if_convertible_gimple_assign_stmt_p (loop, bb, stmt)) | 427 return if_convertible_gimple_assign_stmt_p (loop, bb, stmt); |
440 return false; | |
441 break; | |
442 | |
443 case GIMPLE_COND: | |
444 break; | |
445 | 428 |
446 default: | 429 default: |
447 /* Don't know what to do with 'em so don't do anything. */ | 430 /* Don't know what to do with 'em so don't do anything. */ |
448 if (dump_file && (dump_flags & TDF_DETAILS)) | 431 if (dump_file && (dump_flags & TDF_DETAILS)) |
449 { | 432 { |
455 } | 438 } |
456 | 439 |
457 return true; | 440 return true; |
458 } | 441 } |
459 | 442 |
460 /* Return true, iff BB is if-convertible. | 443 /* Return true when BB is if-convertible. This routine does not check |
461 Note: This routine does _not_ check basic block statements and phis. | 444 basic block's statements and phis. |
462 Basic block is not if-convertible if, | 445 |
463 - Basic block is non-empty and it is after exit block (in BFS order). | 446 A basic block is not if-convertible if: |
464 - Basic block is after exit block but before latch. | 447 - it is non-empty and it is after the exit block (in BFS order), |
465 - Basic block edge(s) is not normal. | 448 - it is after the exit block but before the latch, |
466 EXIT_BB_SEEN is true if basic block with exit edge is already seen. | 449 - its edges are not normal. |
467 BB is inside loop LOOP. */ | 450 |
451 EXIT_BB is the basic block containing the exit of the LOOP. BB is | |
452 inside LOOP. */ | |
468 | 453 |
469 static bool | 454 static bool |
470 if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb) | 455 if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb) |
471 { | 456 { |
472 edge e; | 457 edge e; |
503 FOR_EACH_EDGE (e, ei, bb->succs) | 488 FOR_EACH_EDGE (e, ei, bb->succs) |
504 if (e->flags & | 489 if (e->flags & |
505 (EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP)) | 490 (EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP)) |
506 { | 491 { |
507 if (dump_file && (dump_flags & TDF_DETAILS)) | 492 if (dump_file && (dump_flags & TDF_DETAILS)) |
508 fprintf (dump_file,"Difficult to handle edges\n"); | 493 fprintf (dump_file, "Difficult to handle edges\n"); |
509 return false; | 494 return false; |
510 } | 495 } |
511 | 496 |
512 return true; | 497 return true; |
513 } | 498 } |
514 | 499 |
515 /* Return true, iff LOOP is if-convertible. | 500 /* Return true when all predecessor blocks of BB are visited. The |
516 LOOP is if-convertible if, | 501 VISITED bitmap keeps track of the visited blocks. */ |
517 - It is innermost. | |
518 - It has two or more basic blocks. | |
519 - It has only one exit. | |
520 - Loop header is not the exit edge. | |
521 - If its basic blocks and phi nodes are if convertible. See above for | |
522 more info. | |
523 FOR_VECTORIZER enables vectorizer specific checks. For example, support | |
524 for vector conditions, data dependency checks etc.. (Not implemented yet). */ | |
525 | 502 |
526 static bool | 503 static bool |
527 if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) | 504 pred_blocks_visited_p (basic_block bb, bitmap *visited) |
505 { | |
506 edge e; | |
507 edge_iterator ei; | |
508 FOR_EACH_EDGE (e, ei, bb->preds) | |
509 if (!bitmap_bit_p (*visited, e->src->index)) | |
510 return false; | |
511 | |
512 return true; | |
513 } | |
514 | |
515 /* Get body of a LOOP in suitable order for if-conversion. It is | |
516 caller's responsibility to deallocate basic block list. | |
517 If-conversion suitable order is, breadth first sort (BFS) order | |
518 with an additional constraint: select a block only if all its | |
519 predecessors are already selected. */ | |
520 | |
521 static basic_block * | |
522 get_loop_body_in_if_conv_order (const struct loop *loop) | |
523 { | |
524 basic_block *blocks, *blocks_in_bfs_order; | |
525 basic_block bb; | |
526 bitmap visited; | |
527 unsigned int index = 0; | |
528 unsigned int visited_count = 0; | |
529 | |
530 gcc_assert (loop->num_nodes); | |
531 gcc_assert (loop->latch != EXIT_BLOCK_PTR); | |
532 | |
533 blocks = XCNEWVEC (basic_block, loop->num_nodes); | |
534 visited = BITMAP_ALLOC (NULL); | |
535 | |
536 blocks_in_bfs_order = get_loop_body_in_bfs_order (loop); | |
537 | |
538 index = 0; | |
539 while (index < loop->num_nodes) | |
540 { | |
541 bb = blocks_in_bfs_order [index]; | |
542 | |
543 if (bb->flags & BB_IRREDUCIBLE_LOOP) | |
544 { | |
545 free (blocks_in_bfs_order); | |
546 BITMAP_FREE (visited); | |
547 free (blocks); | |
548 return NULL; | |
549 } | |
550 | |
551 if (!bitmap_bit_p (visited, bb->index)) | |
552 { | |
553 if (pred_blocks_visited_p (bb, &visited) | |
554 || bb == loop->header) | |
555 { | |
556 /* This block is now visited. */ | |
557 bitmap_set_bit (visited, bb->index); | |
558 blocks[visited_count++] = bb; | |
559 } | |
560 } | |
561 | |
562 index++; | |
563 | |
564 if (index == loop->num_nodes | |
565 && visited_count != loop->num_nodes) | |
566 /* Not done yet. */ | |
567 index = 0; | |
568 } | |
569 free (blocks_in_bfs_order); | |
570 BITMAP_FREE (visited); | |
571 return blocks; | |
572 } | |
573 | |
574 /* Return true when LOOP is if-convertible. | |
575 LOOP is if-convertible if: | |
576 - it is innermost, | |
577 - it has two or more basic blocks, | |
578 - it has only one exit, | |
579 - loop header is not the exit edge, | |
580 - if its basic blocks and phi nodes are if convertible. */ | |
581 | |
582 static bool | |
583 if_convertible_loop_p (struct loop *loop) | |
528 { | 584 { |
529 basic_block bb; | 585 basic_block bb; |
530 gimple_stmt_iterator itr; | 586 gimple_stmt_iterator itr; |
531 unsigned int i; | 587 unsigned int i; |
532 edge e; | 588 edge e; |
585 bb = ifc_bbs[i]; | 641 bb = ifc_bbs[i]; |
586 | 642 |
587 if (!if_convertible_bb_p (loop, bb, exit_bb)) | 643 if (!if_convertible_bb_p (loop, bb, exit_bb)) |
588 return false; | 644 return false; |
589 | 645 |
590 /* Check statements. */ | |
591 for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr)) | 646 for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr)) |
592 if (!if_convertible_stmt_p (loop, bb, gsi_stmt (itr))) | 647 if (!if_convertible_stmt_p (loop, bb, gsi_stmt (itr))) |
593 return false; | 648 return false; |
594 /* ??? Check data dependency for vectorizer. */ | 649 |
595 | |
596 /* What about phi nodes ? */ | |
597 itr = gsi_start_phis (bb); | 650 itr = gsi_start_phis (bb); |
598 | 651 |
599 /* Clear aux field of incoming edges to a bb with a phi node. */ | |
600 if (!gsi_end_p (itr)) | 652 if (!gsi_end_p (itr)) |
601 FOR_EACH_EDGE (e, ei, bb->preds) | 653 FOR_EACH_EDGE (e, ei, bb->preds) |
602 e->aux = NULL; | 654 e->aux = NULL; |
603 | 655 |
604 /* Check statements. */ | |
605 for (; !gsi_end_p (itr); gsi_next (&itr)) | 656 for (; !gsi_end_p (itr); gsi_next (&itr)) |
606 if (!if_convertible_phi_p (loop, bb, gsi_stmt (itr))) | 657 if (!if_convertible_phi_p (loop, bb, gsi_stmt (itr))) |
607 return false; | 658 return false; |
608 | 659 |
609 if (bb_with_exit_edge_p (loop, bb)) | 660 if (bb_with_exit_edge_p (loop, bb)) |
610 exit_bb = bb; | 661 exit_bb = bb; |
611 } | 662 } |
612 | 663 |
613 /* OK. Did not find any potential issues so go ahead in if-convert | |
614 this loop. Now there is no looking back. */ | |
615 if (dump_file) | 664 if (dump_file) |
616 fprintf (dump_file,"Applying if-conversion\n"); | 665 fprintf (dump_file,"Applying if-conversion\n"); |
617 | 666 |
618 free_dominance_info (CDI_POST_DOMINATORS); | 667 free_dominance_info (CDI_POST_DOMINATORS); |
619 return true; | 668 return true; |
620 } | 669 } |
621 | 670 |
622 /* Add condition COND into predicate list of basic block BB. */ | 671 /* During if-conversion, the bb->aux field is used to hold a predicate |
623 | 672 list. This function cleans for all the basic blocks in the given |
624 static void | 673 LOOP their predicate list. It also cleans up the e->aux field of |
625 add_to_predicate_list (basic_block bb, tree new_cond) | 674 all the successor edges: e->aux is used to hold the true and false |
626 { | 675 conditions for conditional expressions. */ |
627 tree cond = (tree) bb->aux; | |
628 | |
629 if (cond) | |
630 cond = fold_build2_loc (EXPR_LOCATION (cond), | |
631 TRUTH_OR_EXPR, boolean_type_node, | |
632 unshare_expr (cond), new_cond); | |
633 else | |
634 cond = new_cond; | |
635 | |
636 bb->aux = cond; | |
637 } | |
638 | |
639 /* Add condition COND into BB's predicate list. PREV_COND is | |
640 existing condition. */ | |
641 | |
642 static tree | |
643 add_to_dst_predicate_list (struct loop * loop, edge e, | |
644 tree prev_cond, tree cond, | |
645 gimple_stmt_iterator *gsi) | |
646 { | |
647 tree new_cond = NULL_TREE; | |
648 | |
649 if (!flow_bb_inside_loop_p (loop, e->dest)) | |
650 return NULL_TREE; | |
651 | |
652 if (prev_cond == boolean_true_node || !prev_cond) | |
653 new_cond = unshare_expr (cond); | |
654 else | |
655 { | |
656 tree tmp; | |
657 gimple tmp_stmt = NULL; | |
658 | |
659 prev_cond = force_gimple_operand_gsi (gsi, unshare_expr (prev_cond), | |
660 true, NULL, true, GSI_SAME_STMT); | |
661 | |
662 cond = force_gimple_operand_gsi (gsi, unshare_expr (cond), | |
663 true, NULL, true, GSI_SAME_STMT); | |
664 | |
665 /* Add the condition to aux field of the edge. In case edge | |
666 destination is a PHI node, this condition will be ANDed with | |
667 block predicate to construct complete condition. */ | |
668 e->aux = cond; | |
669 | |
670 /* new_cond == prev_cond AND cond */ | |
671 tmp = build2 (TRUTH_AND_EXPR, boolean_type_node, | |
672 unshare_expr (prev_cond), cond); | |
673 tmp_stmt = ifc_temp_var (boolean_type_node, tmp); | |
674 gsi_insert_before (gsi, tmp_stmt, GSI_SAME_STMT); | |
675 new_cond = gimple_assign_lhs (tmp_stmt); | |
676 } | |
677 add_to_predicate_list (e->dest, new_cond); | |
678 return new_cond; | |
679 } | |
680 | |
681 /* During if-conversion aux field from basic block structure is used to hold | |
682 predicate list. Clean each basic block's predicate list for the given LOOP. | |
683 Also clean aux field of successor edges, used to hold true and false | |
684 condition from conditional expression. */ | |
685 | 676 |
686 static void | 677 static void |
687 clean_predicate_lists (struct loop *loop) | 678 clean_predicate_lists (struct loop *loop) |
688 { | 679 { |
689 basic_block *bb; | 680 basic_block *bb; |
699 e->aux = NULL; | 690 e->aux = NULL; |
700 } | 691 } |
701 free (bb); | 692 free (bb); |
702 } | 693 } |
703 | 694 |
704 /* Basic block BB has two predecessors. Using predecessor's aux field, set | 695 /* Basic block BB has two predecessors. Using predecessor's bb->aux |
705 appropriate condition COND for the PHI node replacement. Return true block | 696 field, set appropriate condition COND for the PHI node replacement. |
706 whose phi arguments are selected when cond is true. */ | 697 Return true block whose phi arguments are selected when cond is |
698 true. LOOP is the loop containing the if-converted region, GSI is | |
699 the place to insert the code for the if-conversion. */ | |
707 | 700 |
708 static basic_block | 701 static basic_block |
709 find_phi_replacement_condition (struct loop *loop, | 702 find_phi_replacement_condition (struct loop *loop, |
710 basic_block bb, tree *cond, | 703 basic_block bb, tree *cond, |
711 gimple_stmt_iterator *gsi) | 704 gimple_stmt_iterator *gsi) |
760 || dominated_by_p (CDI_DOMINATORS, | 753 || dominated_by_p (CDI_DOMINATORS, |
761 second_edge->src, first_edge->src)) | 754 second_edge->src, first_edge->src)) |
762 { | 755 { |
763 *cond = (tree) (second_edge->src)->aux; | 756 *cond = (tree) (second_edge->src)->aux; |
764 | 757 |
765 /* If there is a condition on an incoming edge, | 758 /* If there is a condition on an incoming edge, add it to the |
766 AND it with the incoming bb predicate. */ | 759 incoming bb predicate. */ |
767 if (second_edge->aux) | 760 if (second_edge->aux) |
768 *cond = build2 (TRUTH_AND_EXPR, boolean_type_node, | 761 *cond = build2 (TRUTH_AND_EXPR, boolean_type_node, |
769 *cond, (tree) second_edge->aux); | 762 *cond, (tree) second_edge->aux); |
770 | 763 |
771 if (TREE_CODE (*cond) == TRUTH_NOT_EXPR) | 764 if (TREE_CODE (*cond) == TRUTH_NOT_EXPR) |
772 /* We can be smart here and choose inverted | |
773 condition without switching bbs. */ | |
774 *cond = invert_truthvalue (*cond); | 765 *cond = invert_truthvalue (*cond); |
775 else | 766 else |
776 /* Select non loop header bb. */ | 767 /* Select non loop header bb. */ |
777 first_edge = second_edge; | 768 first_edge = second_edge; |
778 } | 769 } |
779 else | 770 else |
780 { | 771 { |
781 /* FIRST_BB is not loop header */ | |
782 *cond = (tree) (first_edge->src)->aux; | 772 *cond = (tree) (first_edge->src)->aux; |
783 | 773 |
784 /* If there is a condition on an incoming edge, | 774 /* If there is a condition on an incoming edge, add it to the |
785 AND it with the incoming bb predicate. */ | 775 incoming bb predicate. */ |
786 if (first_edge->aux) | 776 if (first_edge->aux) |
787 *cond = build2 (TRUTH_AND_EXPR, boolean_type_node, | 777 *cond = build2 (TRUTH_AND_EXPR, boolean_type_node, |
788 *cond, (tree) first_edge->aux); | 778 *cond, (tree) first_edge->aux); |
789 } | 779 } |
790 | 780 |
791 /* Create temp. for the condition. Vectorizer prefers to have gimple | 781 /* Gimplify the condition: the vectorizer prefers to have gimple |
792 value as condition. Various targets use different means to communicate | 782 values as conditions. Various targets use different means to |
793 condition in vector compare operation. Using gimple value allows | 783 communicate conditions in vector compare operations. Using a |
794 compiler to emit vector compare and select RTL without exposing | 784 gimple value allows the compiler to emit vector compare and |
795 compare's result. */ | 785 select RTL without exposing compare's result. */ |
796 *cond = force_gimple_operand_gsi (gsi, unshare_expr (*cond), | 786 *cond = force_gimple_operand_gsi (gsi, unshare_expr (*cond), |
797 false, NULL_TREE, | 787 false, NULL_TREE, |
798 true, GSI_SAME_STMT); | 788 true, GSI_SAME_STMT); |
799 if (!is_gimple_reg (*cond) && !is_gimple_condexpr (*cond)) | 789 if (!is_gimple_reg (*cond) && !is_gimple_condexpr (*cond)) |
800 { | 790 { |
808 gcc_assert (*cond); | 798 gcc_assert (*cond); |
809 | 799 |
810 return first_edge->src; | 800 return first_edge->src; |
811 } | 801 } |
812 | 802 |
813 | 803 /* Replace PHI node with conditional modify expr using COND. This |
814 /* Replace PHI node with conditional modify expr using COND. | 804 routine does not handle PHI nodes with more than two arguments. |
815 This routine does not handle PHI nodes with more than two arguments. | 805 |
816 For example, | 806 For example, |
817 S1: A = PHI <x1(1), x2(5) | 807 S1: A = PHI <x1(1), x2(5) |
818 is converted into, | 808 is converted into, |
819 S2: A = cond ? x1 : x2; | 809 S2: A = cond ? x1 : x2; |
820 S2 is inserted at the top of basic block's statement list. | 810 |
821 When COND is true, phi arg from TRUE_BB is selected. | 811 The generated code is inserted at GSI that points to the top of |
822 */ | 812 basic block's statement list. When COND is true, phi arg from |
813 TRUE_BB is selected. */ | |
823 | 814 |
824 static void | 815 static void |
825 replace_phi_with_cond_gimple_assign_stmt (gimple phi, tree cond, | 816 replace_phi_with_cond_gimple_assign_stmt (gimple phi, tree cond, |
826 basic_block true_bb, | 817 basic_block true_bb, |
827 gimple_stmt_iterator *gsi) | 818 gimple_stmt_iterator *gsi) |
829 gimple new_stmt; | 820 gimple new_stmt; |
830 basic_block bb; | 821 basic_block bb; |
831 tree rhs; | 822 tree rhs; |
832 tree arg_0, arg_1; | 823 tree arg_0, arg_1; |
833 | 824 |
834 gcc_assert (gimple_code (phi) == GIMPLE_PHI); | 825 gcc_assert (gimple_code (phi) == GIMPLE_PHI |
835 | 826 && gimple_phi_num_args (phi) == 2); |
836 /* If this is not filtered earlier, then now it is too late. */ | 827 |
837 gcc_assert (gimple_phi_num_args (phi) == 2); | |
838 | |
839 /* Find basic block and initialize iterator. */ | |
840 bb = gimple_bb (phi); | 828 bb = gimple_bb (phi); |
841 | 829 |
842 /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */ | 830 /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */ |
843 if (EDGE_PRED (bb, 1)->src == true_bb) | 831 if (EDGE_PRED (bb, 1)->src == true_bb) |
844 { | 832 { |
854 /* Build new RHS using selected condition and arguments. */ | 842 /* Build new RHS using selected condition and arguments. */ |
855 rhs = build3 (COND_EXPR, TREE_TYPE (PHI_RESULT (phi)), | 843 rhs = build3 (COND_EXPR, TREE_TYPE (PHI_RESULT (phi)), |
856 unshare_expr (cond), unshare_expr (arg_0), | 844 unshare_expr (cond), unshare_expr (arg_0), |
857 unshare_expr (arg_1)); | 845 unshare_expr (arg_1)); |
858 | 846 |
859 /* Create new GIMPLE_ASSIGN statement using RHS. */ | |
860 new_stmt = gimple_build_assign (unshare_expr (PHI_RESULT (phi)), rhs); | 847 new_stmt = gimple_build_assign (unshare_expr (PHI_RESULT (phi)), rhs); |
861 | |
862 /* Make new statement definition of the original phi result. */ | |
863 SSA_NAME_DEF_STMT (gimple_phi_result (phi)) = new_stmt; | 848 SSA_NAME_DEF_STMT (gimple_phi_result (phi)) = new_stmt; |
864 | |
865 /* Insert using iterator. */ | |
866 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); | 849 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); |
867 update_stmt (new_stmt); | 850 update_stmt (new_stmt); |
868 | 851 |
869 if (dump_file && (dump_flags & TDF_DETAILS)) | 852 if (dump_file && (dump_flags & TDF_DETAILS)) |
870 { | 853 { |
871 fprintf (dump_file, "new phi replacement stmt\n"); | 854 fprintf (dump_file, "new phi replacement stmt\n"); |
872 print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM); | 855 print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM); |
873 } | 856 } |
874 } | 857 } |
875 | 858 |
876 /* Process phi nodes for the given LOOP. Replace phi nodes with cond | 859 /* Process phi nodes for the given LOOP. Replace phi nodes with |
877 modify expr. */ | 860 conditional modify expressions. */ |
878 | 861 |
879 static void | 862 static void |
880 process_phi_nodes (struct loop *loop) | 863 process_phi_nodes (struct loop *loop) |
881 { | 864 { |
882 basic_block bb; | 865 basic_block bb; |
883 unsigned int orig_loop_num_nodes = loop->num_nodes; | 866 unsigned int orig_loop_num_nodes = loop->num_nodes; |
884 unsigned int i; | 867 unsigned int i; |
885 | 868 |
886 /* Replace phi nodes with cond. modify expr. */ | |
887 for (i = 1; i < orig_loop_num_nodes; i++) | 869 for (i = 1; i < orig_loop_num_nodes; i++) |
888 { | 870 { |
889 gimple phi; | 871 gimple phi; |
890 tree cond = NULL_TREE; | 872 tree cond = NULL_TREE; |
891 gimple_stmt_iterator gsi, phi_gsi; | 873 gimple_stmt_iterator gsi, phi_gsi; |
896 continue; | 878 continue; |
897 | 879 |
898 phi_gsi = gsi_start_phis (bb); | 880 phi_gsi = gsi_start_phis (bb); |
899 gsi = gsi_after_labels (bb); | 881 gsi = gsi_after_labels (bb); |
900 | 882 |
901 /* BB has two predecessors. Using predecessor's aux field, set | 883 /* BB has two predecessors. Using predecessor's aux field, set |
902 appropriate condition for the PHI node replacement. */ | 884 appropriate condition for the PHI node replacement. */ |
903 if (!gsi_end_p (phi_gsi)) | 885 if (!gsi_end_p (phi_gsi)) |
904 true_bb = find_phi_replacement_condition (loop, bb, &cond, &gsi); | 886 true_bb = find_phi_replacement_condition (loop, bb, &cond, &gsi); |
905 | 887 |
906 while (!gsi_end_p (phi_gsi)) | 888 while (!gsi_end_p (phi_gsi)) |
910 release_phi_node (phi); | 892 release_phi_node (phi); |
911 gsi_next (&phi_gsi); | 893 gsi_next (&phi_gsi); |
912 } | 894 } |
913 set_phi_nodes (bb, NULL); | 895 set_phi_nodes (bb, NULL); |
914 } | 896 } |
915 return; | 897 } |
916 } | 898 |
917 | 899 /* Combine all the basic blocks from LOOP into one or two super basic |
918 /* Combine all basic block from the given LOOP into one or two super | 900 blocks. Replace PHI nodes with conditional modify expressions. */ |
919 basic block. Replace PHI nodes with conditional modify expression. */ | |
920 | 901 |
921 static void | 902 static void |
922 combine_blocks (struct loop *loop) | 903 combine_blocks (struct loop *loop) |
923 { | 904 { |
924 basic_block bb, exit_bb, merge_target_bb; | 905 basic_block bb, exit_bb, merge_target_bb; |
928 edge_iterator ei; | 909 edge_iterator ei; |
929 | 910 |
930 /* Process phi nodes to prepare blocks for merge. */ | 911 /* Process phi nodes to prepare blocks for merge. */ |
931 process_phi_nodes (loop); | 912 process_phi_nodes (loop); |
932 | 913 |
933 /* Merge basic blocks. First remove all the edges in the loop, except | 914 /* Merge basic blocks: first remove all the edges in the loop, |
934 for those from the exit block. */ | 915 except for those from the exit block. */ |
935 exit_bb = NULL; | 916 exit_bb = NULL; |
936 for (i = 0; i < orig_loop_num_nodes; i++) | 917 for (i = 0; i < orig_loop_num_nodes; i++) |
937 { | 918 { |
938 bb = ifc_bbs[i]; | 919 bb = ifc_bbs[i]; |
939 if (bb_with_exit_edge_p (loop, bb)) | 920 if (bb_with_exit_edge_p (loop, bb)) |
959 | 940 |
960 if (exit_bb != NULL) | 941 if (exit_bb != NULL) |
961 { | 942 { |
962 if (exit_bb != loop->header) | 943 if (exit_bb != loop->header) |
963 { | 944 { |
964 /* Connect this node with loop header. */ | 945 /* Connect this node to loop header. */ |
965 make_edge (loop->header, exit_bb, EDGE_FALLTHRU); | 946 make_edge (loop->header, exit_bb, EDGE_FALLTHRU); |
966 set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header); | 947 set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header); |
967 } | 948 } |
968 | 949 |
969 /* Redirect non-exit edges to loop->latch. */ | 950 /* Redirect non-exit edges to loop->latch. */ |
974 } | 955 } |
975 set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb); | 956 set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb); |
976 } | 957 } |
977 else | 958 else |
978 { | 959 { |
979 /* If the loop does not have exit then reconnect header and latch. */ | 960 /* If the loop does not have an exit, reconnect header and latch. */ |
980 make_edge (loop->header, loop->latch, EDGE_FALLTHRU); | 961 make_edge (loop->header, loop->latch, EDGE_FALLTHRU); |
981 set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header); | 962 set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header); |
982 } | 963 } |
983 | 964 |
984 merge_target_bb = loop->header; | 965 merge_target_bb = loop->header; |
1010 set_bb_seq (bb, NULL); | 991 set_bb_seq (bb, NULL); |
1011 | 992 |
1012 delete_basic_block (bb); | 993 delete_basic_block (bb); |
1013 } | 994 } |
1014 | 995 |
1015 /* Now if possible, merge loop header and block with exit edge. | 996 /* If possible, merge loop header to the block with the exit edge. |
1016 This reduces number of basic blocks to 2. Auto vectorizer addresses | 997 This reduces the number of basic blocks to two, to please the |
1017 loops with two nodes only. FIXME: Use cleanup_tree_cfg(). */ | 998 vectorizer that handles only loops with two nodes. |
999 | |
1000 FIXME: Call cleanup_tree_cfg. */ | |
1018 if (exit_bb | 1001 if (exit_bb |
1019 && exit_bb != loop->header | 1002 && exit_bb != loop->header |
1020 && can_merge_blocks_p (loop->header, exit_bb)) | 1003 && can_merge_blocks_p (loop->header, exit_bb)) |
1021 merge_blocks (loop->header, exit_bb); | 1004 merge_blocks (loop->header, exit_bb); |
1022 } | 1005 } |
1023 | 1006 |
1024 /* Make a new temp variable of type TYPE. Add GIMPLE_ASSIGN to assign EXP | 1007 /* Main entry point: return true when LOOP is if-converted, otherwise |
1025 to the new variable. */ | 1008 the loop remains unchanged. */ |
1026 | |
1027 static gimple | |
1028 ifc_temp_var (tree type, tree exp) | |
1029 { | |
1030 const char *name = "_ifc_"; | |
1031 tree var, new_name; | |
1032 gimple stmt; | |
1033 | |
1034 /* Create new temporary variable. */ | |
1035 var = create_tmp_var (type, name); | |
1036 add_referenced_var (var); | |
1037 | |
1038 /* Build new statement to assign EXP to new variable. */ | |
1039 stmt = gimple_build_assign (var, exp); | |
1040 | |
1041 /* Get SSA name for the new variable and set make new statement | |
1042 its definition statement. */ | |
1043 new_name = make_ssa_name (var, stmt); | |
1044 gimple_assign_set_lhs (stmt, new_name); | |
1045 SSA_NAME_DEF_STMT (new_name) = stmt; | |
1046 update_stmt (stmt); | |
1047 | |
1048 return stmt; | |
1049 } | |
1050 | |
1051 | |
1052 /* Return TRUE iff, all pred blocks of BB are visited. | |
1053 Bitmap VISITED keeps history of visited blocks. */ | |
1054 | 1009 |
1055 static bool | 1010 static bool |
1056 pred_blocks_visited_p (basic_block bb, bitmap *visited) | 1011 tree_if_conversion (struct loop *loop) |
1057 { | 1012 { |
1058 edge e; | 1013 gimple_stmt_iterator itr; |
1059 edge_iterator ei; | 1014 unsigned int i; |
1060 FOR_EACH_EDGE (e, ei, bb->preds) | 1015 |
1061 if (!bitmap_bit_p (*visited, e->src->index)) | 1016 ifc_bbs = NULL; |
1017 | |
1018 /* If-conversion is not appropriate for all loops. First, check if | |
1019 the loop is if-convertible. */ | |
1020 if (!if_convertible_loop_p (loop)) | |
1021 { | |
1022 if (dump_file && (dump_flags & TDF_DETAILS)) | |
1023 fprintf (dump_file,"-------------------------\n"); | |
1024 if (ifc_bbs) | |
1025 { | |
1026 free (ifc_bbs); | |
1027 ifc_bbs = NULL; | |
1028 } | |
1029 free_dominance_info (CDI_POST_DOMINATORS); | |
1062 return false; | 1030 return false; |
1031 } | |
1032 | |
1033 for (i = 0; i < loop->num_nodes; i++) | |
1034 { | |
1035 basic_block bb = ifc_bbs [i]; | |
1036 tree cond = (tree) bb->aux; | |
1037 | |
1038 /* Process all the statements in this basic block. | |
1039 Remove conditional expression, if any, and annotate | |
1040 destination basic block(s) appropriately. */ | |
1041 for (itr = gsi_start_bb (bb); !gsi_end_p (itr); /* empty */) | |
1042 { | |
1043 gimple t = gsi_stmt (itr); | |
1044 cond = tree_if_convert_stmt (loop, t, cond, &itr); | |
1045 if (!gsi_end_p (itr)) | |
1046 gsi_next (&itr); | |
1047 } | |
1048 | |
1049 /* If current bb has only one successor, then consider it as an | |
1050 unconditional goto. */ | |
1051 if (single_succ_p (bb)) | |
1052 { | |
1053 basic_block bb_n = single_succ (bb); | |
1054 | |
1055 /* The successor bb inherits the predicate of its | |
1056 predecessor. If there is no predicate in the predecessor | |
1057 bb, then consider the successor bb as always executed. */ | |
1058 if (cond == NULL_TREE) | |
1059 cond = boolean_true_node; | |
1060 | |
1061 add_to_predicate_list (bb_n, cond); | |
1062 } | |
1063 } | |
1064 | |
1065 /* Now, all statements are if-converted and basic blocks are | |
1066 annotated appropriately. Combine all the basic blocks into one | |
1067 huge basic block. */ | |
1068 combine_blocks (loop); | |
1069 | |
1070 /* clean up */ | |
1071 clean_predicate_lists (loop); | |
1072 free (ifc_bbs); | |
1073 ifc_bbs = NULL; | |
1063 | 1074 |
1064 return true; | 1075 return true; |
1065 } | |
1066 | |
1067 /* Get body of a LOOP in suitable order for if-conversion. | |
1068 It is caller's responsibility to deallocate basic block | |
1069 list. If-conversion suitable order is, BFS order with one | |
1070 additional constraint. Select block in BFS block, if all | |
1071 pred are already selected. */ | |
1072 | |
1073 static basic_block * | |
1074 get_loop_body_in_if_conv_order (const struct loop *loop) | |
1075 { | |
1076 basic_block *blocks, *blocks_in_bfs_order; | |
1077 basic_block bb; | |
1078 bitmap visited; | |
1079 unsigned int index = 0; | |
1080 unsigned int visited_count = 0; | |
1081 | |
1082 gcc_assert (loop->num_nodes); | |
1083 gcc_assert (loop->latch != EXIT_BLOCK_PTR); | |
1084 | |
1085 blocks = XCNEWVEC (basic_block, loop->num_nodes); | |
1086 visited = BITMAP_ALLOC (NULL); | |
1087 | |
1088 blocks_in_bfs_order = get_loop_body_in_bfs_order (loop); | |
1089 | |
1090 index = 0; | |
1091 while (index < loop->num_nodes) | |
1092 { | |
1093 bb = blocks_in_bfs_order [index]; | |
1094 | |
1095 if (bb->flags & BB_IRREDUCIBLE_LOOP) | |
1096 { | |
1097 free (blocks_in_bfs_order); | |
1098 BITMAP_FREE (visited); | |
1099 free (blocks); | |
1100 return NULL; | |
1101 } | |
1102 if (!bitmap_bit_p (visited, bb->index)) | |
1103 { | |
1104 if (pred_blocks_visited_p (bb, &visited) | |
1105 || bb == loop->header) | |
1106 { | |
1107 /* This block is now visited. */ | |
1108 bitmap_set_bit (visited, bb->index); | |
1109 blocks[visited_count++] = bb; | |
1110 } | |
1111 } | |
1112 index++; | |
1113 if (index == loop->num_nodes | |
1114 && visited_count != loop->num_nodes) | |
1115 { | |
1116 /* Not done yet. */ | |
1117 index = 0; | |
1118 } | |
1119 } | |
1120 free (blocks_in_bfs_order); | |
1121 BITMAP_FREE (visited); | |
1122 return blocks; | |
1123 } | |
1124 | |
1125 /* Return true if one of the basic block BB edge is exit of LOOP. */ | |
1126 | |
1127 static bool | |
1128 bb_with_exit_edge_p (struct loop *loop, basic_block bb) | |
1129 { | |
1130 edge e; | |
1131 edge_iterator ei; | |
1132 bool exit_edge_found = false; | |
1133 | |
1134 FOR_EACH_EDGE (e, ei, bb->succs) | |
1135 if (loop_exit_edge_p (loop, e)) | |
1136 { | |
1137 exit_edge_found = true; | |
1138 break; | |
1139 } | |
1140 | |
1141 return exit_edge_found; | |
1142 } | 1076 } |
1143 | 1077 |
1144 /* Tree if-conversion pass management. */ | 1078 /* Tree if-conversion pass management. */ |
1145 | 1079 |
1146 static unsigned int | 1080 static unsigned int |
1151 | 1085 |
1152 if (number_of_loops () <= 1) | 1086 if (number_of_loops () <= 1) |
1153 return 0; | 1087 return 0; |
1154 | 1088 |
1155 FOR_EACH_LOOP (li, loop, 0) | 1089 FOR_EACH_LOOP (li, loop, 0) |
1156 { | 1090 tree_if_conversion (loop); |
1157 tree_if_conversion (loop, true); | 1091 |
1158 } | |
1159 return 0; | 1092 return 0; |
1160 } | 1093 } |
1161 | 1094 |
1162 static bool | 1095 static bool |
1163 gate_tree_if_conversion (void) | 1096 gate_tree_if_conversion (void) |
1178 TV_NONE, /* tv_id */ | 1111 TV_NONE, /* tv_id */ |
1179 PROP_cfg | PROP_ssa, /* properties_required */ | 1112 PROP_cfg | PROP_ssa, /* properties_required */ |
1180 0, /* properties_provided */ | 1113 0, /* properties_provided */ |
1181 0, /* properties_destroyed */ | 1114 0, /* properties_destroyed */ |
1182 0, /* todo_flags_start */ | 1115 0, /* todo_flags_start */ |
1183 TODO_dump_func | TODO_verify_loops | TODO_verify_stmts | TODO_verify_flow | 1116 TODO_dump_func | TODO_verify_stmts | TODO_verify_flow |
1184 /* todo_flags_finish */ | 1117 /* todo_flags_finish */ |
1185 } | 1118 } |
1186 }; | 1119 }; |