]>
Commit | Line | Data |
---|---|---|
40923b20 DP |
1 | /* If-conversion for vectorizer. |
2 | Copyright (C) 2004 Free Software Foundation, Inc. | |
3 | Contributed by Devang Patel <dpatel@apple.com> | |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 2, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING. If not, write to the Free | |
19 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
20 | 02111-1307, USA. */ | |
21 | ||
61b5f210 | 22 | /* This pass implements tree level if-conversion transformation of loops. |
40923b20 DP |
23 | Initial goal is to help vectorizer vectorize loops with conditions. |
24 | ||
25 | A short description of if-conversion: | |
26 | ||
27 | o Decide if a loop is if-convertable or not. | |
28 | o Walk all loop basic blocks in breadth first order (BFS order). | |
29 | o Remove conditional statements (at the end of basic block) | |
61b5f210 | 30 | and propagate condition into destination basic blocks' |
40923b20 DP |
31 | predicate list. |
32 | o Replace modify expression with conditional modify expression | |
33 | using current basic block's condition. | |
34 | o Merge all basic blocks | |
35 | o Replace phi nodes with conditional modify expr | |
36 | o Merge all basic blocks into header | |
37 | ||
38 | Sample transformation: | |
39 | ||
40 | INPUT | |
41 | ----- | |
42 | ||
43 | # i_23 = PHI <0(0), i_18(10)>; | |
44 | <L0>:; | |
45 | j_15 = A[i_23]; | |
46 | if (j_15 > 41) goto <L1>; else goto <L17>; | |
47 | ||
48 | <L17>:; | |
49 | goto <bb 3> (<L3>); | |
50 | ||
51 | <L1>:; | |
52 | ||
53 | # iftmp.2_4 = PHI <0(8), 42(2)>; | |
54 | <L3>:; | |
55 | A[i_23] = iftmp.2_4; | |
56 | i_18 = i_23 + 1; | |
57 | if (i_18 <= 15) goto <L19>; else goto <L18>; | |
58 | ||
59 | <L19>:; | |
60 | goto <bb 1> (<L0>); | |
61 | ||
62 | <L18>:; | |
63 | ||
64 | OUTPUT | |
65 | ------ | |
66 | ||
67 | # i_23 = PHI <0(0), i_18(10)>; | |
68 | <L0>:; | |
69 | j_15 = A[i_23]; | |
61b5f210 | 70 | |
40923b20 DP |
71 | <L3>:; |
72 | iftmp.2_4 = j_15 > 41 ? 42 : 0; | |
73 | A[i_23] = iftmp.2_4; | |
74 | i_18 = i_23 + 1; | |
75 | if (i_18 <= 15) goto <L19>; else goto <L18>; | |
61b5f210 | 76 | |
40923b20 DP |
77 | <L19>:; |
78 | goto <bb 1> (<L0>); | |
79 | ||
80 | <L18>:; | |
81 | */ | |
82 | ||
83 | #include "config.h" | |
84 | #include "system.h" | |
85 | #include "coretypes.h" | |
86 | #include "tm.h" | |
87 | #include "errors.h" | |
88 | #include "tree.h" | |
89 | #include "c-common.h" | |
90 | #include "flags.h" | |
91 | #include "timevar.h" | |
92 | #include "varray.h" | |
93 | #include "rtl.h" | |
94 | #include "basic-block.h" | |
95 | #include "diagnostic.h" | |
96 | #include "tree-flow.h" | |
97 | #include "tree-dump.h" | |
98 | #include "cfgloop.h" | |
99 | #include "tree-chrec.h" | |
100 | #include "tree-data-ref.h" | |
101 | #include "tree-scalar-evolution.h" | |
102 | #include "tree-pass.h" | |
103 | #include "target.h" | |
104 | ||
105 | /* local function prototypes */ | |
106 | static void main_tree_if_conversion (void); | |
61b5f210 | 107 | static tree tree_if_convert_stmt (struct loop *loop, tree, tree, |
40923b20 | 108 | block_stmt_iterator *); |
61b5f210 | 109 | static void tree_if_convert_cond_expr (struct loop *, tree, tree, |
40923b20 DP |
110 | block_stmt_iterator *); |
111 | static bool if_convertable_phi_p (struct loop *, basic_block, tree); | |
112 | static bool if_convertable_modify_expr_p (struct loop *, basic_block, tree); | |
113 | static bool if_convertable_stmt_p (struct loop *, basic_block, tree); | |
114 | static bool if_convertable_bb_p (struct loop *, basic_block, bool); | |
115 | static bool if_convertable_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, tree, tree, tree, | |
118 | block_stmt_iterator *); | |
119 | static void clean_predicate_lists (struct loop *loop); | |
7f7e0703 DP |
120 | static basic_block find_phi_replacement_condition (basic_block, tree *, |
121 | block_stmt_iterator *); | |
122 | static void replace_phi_with_cond_modify_expr (tree, tree, basic_block, | |
40923b20 DP |
123 | block_stmt_iterator *); |
124 | static void process_phi_nodes (struct loop *); | |
125 | static void combine_blocks (struct loop *); | |
126 | static tree ifc_temp_var (tree, tree); | |
127 | static bool pred_blocks_visited_p (basic_block, bitmap *); | |
128 | static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop); | |
129 | static bool bb_with_exit_edge_p (basic_block); | |
130 | ||
131 | /* List of basic blocks in if-conversion-suitable order. */ | |
132 | static basic_block *ifc_bbs; | |
133 | ||
134 | /* Main entry point. | |
135 | Apply if-conversion to the LOOP. Return true if successful otherwise return | |
61b5f210 | 136 | false. If false is returned then loop remains unchanged. |
40923b20 DP |
137 | FOR_VECTORIZER is a boolean flag. It indicates whether if-conversion is used |
138 | for vectorizer or not. If it is used for vectorizer, additional checks are | |
61b5f210 | 139 | used. (Vectorization checks are not yet implemented). */ |
40923b20 DP |
140 | |
141 | bool | |
142 | tree_if_conversion (struct loop *loop, bool for_vectorizer) | |
143 | { | |
144 | basic_block bb; | |
145 | block_stmt_iterator itr; | |
146 | tree cond; | |
147 | unsigned int i; | |
148 | ||
149 | ifc_bbs = NULL; | |
150 | ||
151 | /* if-conversion is not appropriate for all loops. First, check if loop is | |
152 | if-convertable or not. */ | |
153 | if (!if_convertable_loop_p (loop, for_vectorizer)) | |
154 | { | |
155 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
156 | fprintf (dump_file,"-------------------------\n"); | |
157 | if (ifc_bbs) | |
158 | { | |
159 | free (ifc_bbs); | |
160 | ifc_bbs = NULL; | |
161 | } | |
162 | free_dominance_info (CDI_POST_DOMINATORS); | |
163 | free_df (); | |
164 | return false; | |
165 | } | |
166 | ||
167 | cond = NULL_TREE; | |
61b5f210 | 168 | |
40923b20 | 169 | /* Do actual work now. */ |
61b5f210 | 170 | for (i = 0; i < loop->num_nodes; i++) |
40923b20 DP |
171 | { |
172 | bb = ifc_bbs [i]; | |
173 | ||
174 | /* Update condition using predicate list. */ | |
175 | cond = bb->aux; | |
176 | ||
177 | /* Process all statements in this basic block. | |
61b5f210 | 178 | Remove conditional expression, if any, and annotate |
40923b20 DP |
179 | destination basic block(s) appropriately. */ |
180 | for (itr = bsi_start (bb); !bsi_end_p (itr); /* empty */) | |
181 | { | |
182 | tree t = bsi_stmt (itr); | |
183 | cond = tree_if_convert_stmt (loop, t, cond, &itr); | |
184 | if (!bsi_end_p (itr)) | |
185 | bsi_next (&itr); | |
186 | } | |
187 | ||
61b5f210 | 188 | /* If current bb has only one successor, then consider it as an |
40923b20 | 189 | unconditional goto. */ |
628f6a4e | 190 | if (EDGE_COUNT (bb->succs) == 1) |
40923b20 | 191 | { |
628f6a4e | 192 | basic_block bb_n = EDGE_SUCC (bb, 0)->dest; |
40923b20 DP |
193 | if (cond != NULL_TREE) |
194 | add_to_predicate_list (bb_n, cond); | |
195 | cond = NULL_TREE; | |
196 | } | |
197 | } | |
198 | ||
199 | /* Now, all statements are if-converted and basic blocks are | |
200 | annotated appropriately. Combine all basic block into one huge | |
201 | basic block. */ | |
202 | combine_blocks (loop); | |
203 | ||
204 | /* clean up */ | |
205 | clean_predicate_lists (loop); | |
206 | free (ifc_bbs); | |
207 | ifc_bbs = NULL; | |
208 | free_df (); | |
209 | ||
210 | return true; | |
211 | } | |
212 | ||
61b5f210 AJ |
213 | /* if-convert stmt T which is part of LOOP. |
214 | If T is a MODIFY_EXPR than it is converted into conditional modify | |
215 | expression using COND. For conditional expressions, add condition in the | |
216 | destination basic block's predicate list and remove conditional | |
217 | expression itself. BSI is the iterator used to traverse statements of | |
40923b20 DP |
218 | loop. It is used here when it is required to delete current statement. */ |
219 | ||
220 | static tree | |
61b5f210 | 221 | tree_if_convert_stmt (struct loop * loop, tree t, tree cond, |
40923b20 DP |
222 | block_stmt_iterator *bsi) |
223 | { | |
224 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
225 | { | |
226 | fprintf (dump_file, "------if-convert stmt\n"); | |
227 | print_generic_stmt (dump_file, t, TDF_SLIM); | |
228 | print_generic_stmt (dump_file, cond, TDF_SLIM); | |
229 | } | |
230 | ||
231 | switch (TREE_CODE (t)) | |
232 | { | |
233 | /* Labels are harmless here. */ | |
234 | case LABEL_EXPR: | |
235 | break; | |
236 | ||
237 | case MODIFY_EXPR: | |
238 | /* This modify_expr is killing previous value of LHS. Appropriate value will | |
239 | be selected by PHI node based on condition. It is possible that before | |
240 | this transformation, PHI nodes was selecting default value and now it will | |
61b5f210 | 241 | use this new value. This is OK because it does not change validity the |
40923b20 DP |
242 | program. */ |
243 | break; | |
244 | ||
245 | case GOTO_EXPR: | |
246 | /* Unconditional goto */ | |
247 | add_to_predicate_list (bb_for_stmt (TREE_OPERAND (t, 1)), cond); | |
248 | bsi_remove (bsi); | |
249 | cond = NULL_TREE; | |
250 | break; | |
251 | ||
252 | case COND_EXPR: | |
253 | /* Update destination blocks' predicate list and remove this | |
254 | condition expression. */ | |
255 | tree_if_convert_cond_expr (loop, t, cond, bsi); | |
61b5f210 | 256 | cond = NULL_TREE; |
40923b20 | 257 | break; |
61b5f210 AJ |
258 | |
259 | default: | |
1e128c5f | 260 | gcc_unreachable (); |
40923b20 DP |
261 | } |
262 | return cond; | |
263 | } | |
264 | ||
265 | /* STMT is COND_EXPR. Update two destination's predicate list. | |
266 | Remove COND_EXPR, if it is not the loop exit condition. Otherwise | |
61b5f210 | 267 | update loop exit condition appropriately. BSI is the iterator |
40923b20 DP |
268 | used to traverse statement list. STMT is part of loop LOOP. */ |
269 | ||
270 | static void | |
61b5f210 | 271 | tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond, |
40923b20 DP |
272 | block_stmt_iterator *bsi) |
273 | { | |
274 | tree then_clause, else_clause, c, new_cond; | |
275 | new_cond = NULL_TREE; | |
276 | ||
1e128c5f | 277 | gcc_assert (TREE_CODE (stmt) == COND_EXPR); |
40923b20 DP |
278 | |
279 | c = TREE_OPERAND (stmt, 0); | |
280 | then_clause = TREE_OPERAND (stmt, 1); | |
281 | else_clause = TREE_OPERAND (stmt, 2); | |
61b5f210 | 282 | |
40923b20 | 283 | /* Create temp. for condition. */ |
a2159c4c | 284 | if (!is_gimple_condexpr (c)) |
40923b20 DP |
285 | { |
286 | tree new_stmt; | |
287 | new_stmt = ifc_temp_var (TREE_TYPE (c), unshare_expr (c)); | |
288 | bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT); | |
289 | c = TREE_OPERAND (new_stmt, 0); | |
290 | } | |
61b5f210 | 291 | |
40923b20 DP |
292 | /* Add new condition into destination's predicate list. */ |
293 | if (then_clause) | |
294 | /* if 'c' is true then then_clause is reached. */ | |
a2159c4c DP |
295 | new_cond = add_to_dst_predicate_list (loop, then_clause, cond, |
296 | unshare_expr (c), bsi); | |
61b5f210 | 297 | |
40923b20 DP |
298 | if (else_clause) |
299 | { | |
a2159c4c DP |
300 | tree c2; |
301 | if (!is_gimple_reg(c) && is_gimple_condexpr (c)) | |
302 | { | |
303 | tree new_stmt; | |
304 | new_stmt = ifc_temp_var (TREE_TYPE (c), unshare_expr (c)); | |
305 | bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT); | |
306 | c = TREE_OPERAND (new_stmt, 0); | |
307 | } | |
308 | ||
40923b20 | 309 | /* if 'c' is false then else_clause is reached. */ |
a2159c4c | 310 | c2 = invert_truthvalue (unshare_expr (c)); |
40923b20 DP |
311 | add_to_dst_predicate_list (loop, else_clause, cond, c2, bsi); |
312 | } | |
313 | ||
61b5f210 | 314 | /* Now this conditional statement is redundant. Remove it. |
40923b20 DP |
315 | But, do not remove exit condition! Update exit condition |
316 | using new condition. */ | |
317 | if (!bb_with_exit_edge_p (bb_for_stmt (stmt))) | |
318 | { | |
319 | bsi_remove (bsi); | |
320 | cond = NULL_TREE; | |
321 | } | |
40923b20 DP |
322 | return; |
323 | } | |
324 | ||
325 | /* Return true, iff PHI is if-convertable. PHI is part of loop LOOP | |
326 | and it belongs to basic block BB. | |
61b5f210 | 327 | PHI is not if-convertable |
40923b20 DP |
328 | - if it has more than 2 arguments. |
329 | - Virtual PHI is immediately used in another PHI node. */ | |
330 | ||
331 | static bool | |
332 | if_convertable_phi_p (struct loop *loop, basic_block bb, tree phi) | |
333 | { | |
334 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
335 | { | |
336 | fprintf (dump_file, "-------------------------\n"); | |
337 | print_generic_stmt (dump_file, phi, TDF_SLIM); | |
338 | } | |
61b5f210 | 339 | |
40923b20 DP |
340 | if (bb != loop->header && PHI_NUM_ARGS (phi) != 2) |
341 | { | |
342 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
343 | fprintf (dump_file, "More than two phi node args.\n"); | |
344 | return false; | |
345 | } | |
61b5f210 | 346 | |
40923b20 DP |
347 | if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi)))) |
348 | { | |
349 | int j; | |
350 | dataflow_t df = get_immediate_uses (phi); | |
351 | int num_uses = num_immediate_uses (df); | |
352 | for (j = 0; j < num_uses; j++) | |
353 | { | |
354 | tree use = immediate_use (df, j); | |
355 | if (TREE_CODE (use) == PHI_NODE) | |
356 | { | |
357 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
358 | fprintf (dump_file, "Difficult to handle this virtual phi.\n"); | |
359 | return false; | |
360 | } | |
361 | } | |
362 | } | |
363 | ||
364 | return true; | |
365 | } | |
366 | ||
61b5f210 | 367 | /* Return true, if M_EXPR is if-convertable. |
40923b20 DP |
368 | MODIFY_EXPR is not if-convertable if, |
369 | - It is not movable. | |
370 | - It could trap. | |
371 | - LHS is not var decl. | |
372 | MODIFY_EXPR is part of block BB, which is inside loop LOOP. | |
373 | */ | |
374 | ||
375 | static bool | |
376 | if_convertable_modify_expr_p (struct loop *loop, basic_block bb, tree m_expr) | |
377 | { | |
378 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
379 | { | |
380 | fprintf (dump_file, "-------------------------\n"); | |
381 | print_generic_stmt (dump_file, m_expr, TDF_SLIM); | |
382 | } | |
61b5f210 | 383 | |
40923b20 DP |
384 | /* Be conservative and do not handle immovable expressions. */ |
385 | if (movement_possibility (m_expr) == MOVE_IMPOSSIBLE) | |
386 | { | |
387 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
388 | fprintf (dump_file, "stmt is movable. Don't take risk\n"); | |
389 | return false; | |
390 | } | |
391 | ||
392 | /* See if it needs speculative loading or not. */ | |
61b5f210 | 393 | if (bb != loop->header |
40923b20 DP |
394 | && tree_could_trap_p (TREE_OPERAND (m_expr, 1))) |
395 | { | |
396 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
397 | fprintf (dump_file, "tree could trap...\n"); | |
398 | return false; | |
399 | } | |
400 | ||
401 | if (TREE_CODE (TREE_OPERAND (m_expr, 1)) == CALL_EXPR) | |
402 | { | |
403 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
404 | fprintf (dump_file, "CALL_EXPR \n"); | |
405 | return false; | |
406 | } | |
407 | ||
408 | if (TREE_CODE (TREE_OPERAND (m_expr, 0)) != SSA_NAME | |
409 | && bb != loop->header | |
410 | && !bb_with_exit_edge_p (bb)) | |
411 | { | |
412 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
413 | { | |
414 | fprintf (dump_file, "LHS is not var\n"); | |
415 | print_generic_stmt (dump_file, m_expr, TDF_SLIM); | |
416 | } | |
417 | return false; | |
418 | } | |
419 | ||
420 | ||
421 | return true; | |
422 | } | |
423 | ||
61b5f210 | 424 | /* Return true, iff STMT is if-convertable. |
40923b20 | 425 | Statement is if-convertable if, |
61b5f210 AJ |
426 | - It is if-convertable MODIFY_EXPR |
427 | - IT is LABEL_EXPR, GOTO_EXPR or COND_EXPR. | |
40923b20 DP |
428 | STMT is inside block BB, which is inside loop LOOP. */ |
429 | ||
430 | static bool | |
431 | if_convertable_stmt_p (struct loop *loop, basic_block bb, tree stmt) | |
432 | { | |
433 | switch (TREE_CODE (stmt)) | |
434 | { | |
435 | case LABEL_EXPR: | |
436 | break; | |
61b5f210 | 437 | |
40923b20 | 438 | case MODIFY_EXPR: |
61b5f210 | 439 | |
40923b20 DP |
440 | if (!if_convertable_modify_expr_p (loop, bb, stmt)) |
441 | return false; | |
442 | break; | |
61b5f210 | 443 | |
40923b20 DP |
444 | case GOTO_EXPR: |
445 | case COND_EXPR: | |
446 | break; | |
61b5f210 | 447 | |
40923b20 DP |
448 | default: |
449 | /* Don't know what to do with 'em so don't do anything. */ | |
450 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
451 | { | |
452 | fprintf (dump_file, "don't know what to do\n"); | |
453 | print_generic_stmt (dump_file, stmt, TDF_SLIM); | |
454 | } | |
455 | return false; | |
456 | break; | |
457 | } | |
458 | ||
459 | return true; | |
460 | } | |
461 | ||
61b5f210 | 462 | /* Return true, iff BB is if-convertable. |
40923b20 | 463 | Note: This routine does _not_ check basic block statements and phis. |
61b5f210 AJ |
464 | Basic block is not if-convertable if, |
465 | - Basic block is non-empty and it is after exit block (in BFS order). | |
40923b20 | 466 | - Basic block is after exit block but before latch. |
61b5f210 | 467 | - Basic block edge(s) is not normal. |
40923b20 | 468 | EXIT_BB_SEEN is true if basic block with exit edge is already seen. |
8c27b7d4 | 469 | BB is inside loop LOOP. */ |
40923b20 | 470 | |
61b5f210 | 471 | static bool |
40923b20 DP |
472 | if_convertable_bb_p (struct loop *loop, basic_block bb, bool exit_bb_seen) |
473 | { | |
474 | edge e; | |
628f6a4e | 475 | edge_iterator ei; |
40923b20 DP |
476 | |
477 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
478 | fprintf (dump_file, "----------[%d]-------------\n", bb->index); | |
61b5f210 | 479 | |
40923b20 DP |
480 | if (exit_bb_seen) |
481 | { | |
482 | if (bb != loop->latch) | |
483 | { | |
484 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
485 | fprintf (dump_file, "basic block after exit bb but before latch\n"); | |
486 | return false; | |
487 | } | |
488 | else if (!empty_block_p (bb)) | |
489 | { | |
490 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
491 | fprintf (dump_file, "non empty basic block after exit bb\n"); | |
492 | return false; | |
493 | } | |
494 | } | |
61b5f210 AJ |
495 | |
496 | /* Be less adventurous and handle only normal edges. */ | |
628f6a4e | 497 | FOR_EACH_EDGE (e, ei, bb->succs) |
61b5f210 | 498 | if (e->flags & |
40923b20 DP |
499 | (EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP)) |
500 | { | |
501 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
502 | fprintf (dump_file,"Difficult to handle edges\n"); | |
503 | return false; | |
504 | } | |
505 | ||
506 | return true; | |
507 | } | |
508 | ||
61b5f210 | 509 | /* Return true, iff LOOP is if-convertable. |
40923b20 DP |
510 | LOOP is if-convertable if, |
511 | - It is innermost. | |
512 | - It has two or more basic blocks. | |
513 | - It has only one exit. | |
61b5f210 AJ |
514 | - Loop header is not the exit edge. |
515 | - If its basic blocks and phi nodes are if convertable. See above for | |
516 | more info. | |
40923b20 DP |
517 | FOR_VECTORIZER enables vectorizer specific checks. For example, support |
518 | for vector conditions, data dependency checks etc.. (Not implemented yet). */ | |
519 | ||
520 | static bool | |
521 | if_convertable_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) | |
522 | { | |
523 | tree phi; | |
524 | basic_block bb; | |
525 | block_stmt_iterator itr; | |
526 | unsigned int i; | |
527 | edge e; | |
628f6a4e | 528 | edge_iterator ei; |
40923b20 DP |
529 | bool exit_bb_seen = false; |
530 | ||
531 | /* Handle only inner most loop. */ | |
532 | if (!loop || loop->inner) | |
533 | { | |
534 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
535 | fprintf (dump_file, "not inner most loop\n"); | |
536 | return false; | |
537 | } | |
61b5f210 | 538 | |
40923b20 DP |
539 | flow_loop_scan (loop, LOOP_ALL); |
540 | ||
541 | /* If only one block, no need for if-conversion. */ | |
542 | if (loop->num_nodes <= 2) | |
543 | { | |
544 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
61b5f210 | 545 | fprintf (dump_file, "less than 2 basic blocks\n"); |
40923b20 DP |
546 | return false; |
547 | } | |
61b5f210 | 548 | |
40923b20 DP |
549 | /* More than one loop exit is too much to handle. */ |
550 | if (loop->num_exits > 1) | |
551 | { | |
552 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
553 | fprintf (dump_file, "multiple exits\n"); | |
554 | return false; | |
555 | } | |
556 | ||
557 | /* ??? Check target's vector conditional operation support for vectorizer. */ | |
558 | ||
559 | /* If one of the loop header's edge is exit edge then do not apply | |
560 | if-conversion. */ | |
628f6a4e | 561 | FOR_EACH_EDGE (e, ei, loop->header->succs) |
40923b20 DP |
562 | if ( e->flags & EDGE_LOOP_EXIT) |
563 | return false; | |
564 | ||
565 | compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL); | |
566 | ||
567 | calculate_dominance_info (CDI_DOMINATORS); | |
568 | calculate_dominance_info (CDI_POST_DOMINATORS); | |
569 | ||
570 | /* Allow statements that can be handled during if-conversion. */ | |
571 | ifc_bbs = get_loop_body_in_if_conv_order (loop); | |
572 | if (!ifc_bbs) | |
573 | { | |
574 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
575 | fprintf (dump_file,"Irreducible loop\n"); | |
576 | free_dominance_info (CDI_POST_DOMINATORS); | |
577 | return false; | |
578 | } | |
61b5f210 | 579 | |
40923b20 DP |
580 | for (i = 0; i < loop->num_nodes; i++) |
581 | { | |
582 | bb = ifc_bbs[i]; | |
583 | ||
584 | if (!if_convertable_bb_p (loop, bb, exit_bb_seen)) | |
585 | return false; | |
586 | ||
587 | /* Check statements. */ | |
588 | for (itr = bsi_start (bb); !bsi_end_p (itr); bsi_next (&itr)) | |
589 | if (!if_convertable_stmt_p (loop, bb, bsi_stmt (itr))) | |
590 | return false; | |
591 | /* ??? Check data dependency for vectorizer. */ | |
592 | ||
593 | /* What about phi nodes ? */ | |
594 | for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi)) | |
595 | if (!if_convertable_phi_p (loop, bb, phi)) | |
596 | return false; | |
597 | ||
598 | if (bb_with_exit_edge_p (bb)) | |
599 | exit_bb_seen = true; | |
600 | } | |
601 | ||
602 | /* OK. Did not find any potential issues so go ahead in if-convert | |
603 | this loop. Now there is no looking back. */ | |
604 | if (dump_file) | |
605 | fprintf (dump_file,"Applying if-conversion\n"); | |
606 | ||
607 | free_dominance_info (CDI_POST_DOMINATORS); | |
608 | return true; | |
609 | } | |
610 | ||
611 | /* Add condition COND into predicate list of basic block BB. */ | |
612 | ||
613 | static void | |
614 | add_to_predicate_list (basic_block bb, tree new_cond) | |
615 | { | |
616 | tree cond = bb->aux; | |
61b5f210 | 617 | |
40923b20 DP |
618 | if (cond) |
619 | cond = fold (build (TRUTH_OR_EXPR, boolean_type_node, | |
620 | unshare_expr (cond), new_cond)); | |
621 | else | |
622 | cond = new_cond; | |
623 | ||
624 | bb->aux = cond; | |
625 | } | |
626 | ||
627 | /* Add condition COND into DST's predicate list. PREV_COND is | |
628 | existing condition. */ | |
629 | ||
630 | static tree | |
61b5f210 | 631 | add_to_dst_predicate_list (struct loop * loop, tree dst, |
40923b20 DP |
632 | tree prev_cond, tree cond, |
633 | block_stmt_iterator *bsi) | |
634 | { | |
635 | basic_block bb; | |
636 | tree new_cond = NULL_TREE; | |
637 | ||
1e128c5f | 638 | gcc_assert (TREE_CODE (dst) == GOTO_EXPR); |
40923b20 DP |
639 | bb = label_to_block (TREE_OPERAND (dst, 0)); |
640 | if (!flow_bb_inside_loop_p (loop, bb)) | |
641 | return NULL_TREE; | |
642 | ||
643 | if (prev_cond == boolean_true_node || !prev_cond) | |
644 | new_cond = unshare_expr (cond); | |
645 | else | |
646 | { | |
647 | tree tmp_stmt; | |
648 | /* new_cond == prev_cond AND cond */ | |
649 | tree tmp = build (TRUTH_AND_EXPR, boolean_type_node, | |
650 | unshare_expr (prev_cond), cond); | |
651 | tmp_stmt = ifc_temp_var (boolean_type_node, tmp); | |
652 | bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT); | |
653 | new_cond = TREE_OPERAND (tmp_stmt, 0); | |
654 | } | |
655 | add_to_predicate_list (bb, new_cond); | |
656 | return new_cond; | |
657 | } | |
658 | ||
659 | /* During if-conversion aux field from basic block is used to hold predicate | |
660 | list. Clean each basic block's predicate list for the given LOOP. */ | |
661 | ||
662 | static void | |
663 | clean_predicate_lists (struct loop *loop) | |
664 | { | |
665 | unsigned int i; | |
666 | ||
667 | for (i = 0; i < loop->num_nodes; i++) | |
668 | ifc_bbs[i]->aux = NULL; | |
669 | } | |
670 | ||
671 | /* Basic block BB has two predecessors. Using predecessor's aux field, set | |
7f7e0703 DP |
672 | appropriate condition COND for the PHI node replacement. Return true block |
673 | whose phi arguments are selected when cond is true. */ | |
40923b20 | 674 | |
7f7e0703 | 675 | static basic_block |
40923b20 DP |
676 | find_phi_replacement_condition (basic_block bb, tree *cond, |
677 | block_stmt_iterator *bsi) | |
678 | { | |
679 | edge e; | |
680 | basic_block p1 = NULL; | |
681 | basic_block p2 = NULL; | |
7f7e0703 | 682 | basic_block true_bb = NULL; |
40923b20 | 683 | tree tmp_cond; |
628f6a4e | 684 | edge_iterator ei; |
40923b20 | 685 | |
628f6a4e | 686 | FOR_EACH_EDGE (e, ei, bb->preds) |
40923b20 DP |
687 | { |
688 | if (p1 == NULL) | |
628f6a4e | 689 | p1 = e->src; |
1e128c5f GB |
690 | else |
691 | { | |
692 | gcc_assert (!p2); | |
693 | p2 = e->src; | |
694 | } | |
40923b20 DP |
695 | } |
696 | ||
697 | /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */ | |
698 | tmp_cond = p1->aux; | |
699 | if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR) | |
700 | { | |
701 | *cond = p2->aux; | |
7f7e0703 | 702 | true_bb = p2; |
40923b20 DP |
703 | } |
704 | else | |
705 | { | |
706 | *cond = p1->aux; | |
7f7e0703 | 707 | true_bb = p1; |
40923b20 | 708 | } |
61b5f210 AJ |
709 | |
710 | /* Create temp. for the condition. Vectorizer prefers to have gimple | |
711 | value as condition. Various targets use different means to communicate | |
712 | condition in vector compare operation. Using gimple value allows compiler | |
40923b20 DP |
713 | to emit vector compare and select RTL without exposing compare's result. */ |
714 | if (!is_gimple_reg (*cond) && !is_gimple_condexpr (*cond)) | |
715 | { | |
716 | tree new_stmt; | |
717 | ||
718 | new_stmt = ifc_temp_var (TREE_TYPE (*cond), unshare_expr (*cond)); | |
719 | bsi_insert_after (bsi, new_stmt, BSI_SAME_STMT); | |
720 | bsi_next (bsi); | |
721 | *cond = TREE_OPERAND (new_stmt, 0); | |
722 | } | |
723 | ||
1e128c5f | 724 | gcc_assert (*cond); |
40923b20 | 725 | |
7f7e0703 | 726 | return true_bb; |
40923b20 DP |
727 | } |
728 | ||
729 | ||
61b5f210 AJ |
730 | /* Replace PHI node with conditional modify expr using COND. |
731 | This routine does not handle PHI nodes with more than two arguments. | |
40923b20 DP |
732 | For example, |
733 | S1: A = PHI <x1(1), x2(5) | |
734 | is converted into, | |
735 | S2: A = cond ? x1 : x2; | |
736 | S2 is inserted at the top of basic block's statement list. | |
7f7e0703 | 737 | When COND is true, phi arg from TRUE_BB is selected. |
40923b20 DP |
738 | */ |
739 | ||
740 | static void | |
7f7e0703 | 741 | replace_phi_with_cond_modify_expr (tree phi, tree cond, basic_block true_bb, |
40923b20 DP |
742 | block_stmt_iterator *bsi) |
743 | { | |
744 | tree new_stmt; | |
745 | basic_block bb; | |
746 | tree rhs; | |
747 | tree arg_0, arg_1; | |
40923b20 | 748 | |
1e128c5f GB |
749 | gcc_assert (TREE_CODE (phi) == PHI_NODE); |
750 | ||
40923b20 | 751 | /* If this is not filtered earlier, then now it is too late. */ |
1e128c5f | 752 | gcc_assert (PHI_NUM_ARGS (phi) == 2); |
40923b20 DP |
753 | |
754 | /* Find basic block and initialize iterator. */ | |
755 | bb = bb_for_stmt (phi); | |
756 | ||
757 | new_stmt = NULL_TREE; | |
758 | arg_0 = NULL_TREE; | |
759 | arg_1 = NULL_TREE; | |
61b5f210 | 760 | |
40923b20 | 761 | /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */ |
7f7e0703 | 762 | if (PHI_ARG_EDGE(phi, 1)->src == true_bb) |
40923b20 DP |
763 | { |
764 | arg_0 = PHI_ARG_DEF (phi, 1); | |
765 | arg_1 = PHI_ARG_DEF (phi, 0); | |
766 | } | |
767 | else | |
768 | { | |
769 | arg_0 = PHI_ARG_DEF (phi, 0); | |
770 | arg_1 = PHI_ARG_DEF (phi, 1); | |
771 | } | |
772 | ||
61b5f210 | 773 | /* Build new RHS using selected condition and arguments. */ |
40923b20 DP |
774 | rhs = build (COND_EXPR, TREE_TYPE (PHI_RESULT (phi)), |
775 | unshare_expr (cond), unshare_expr (arg_0), | |
776 | unshare_expr (arg_1)); | |
777 | ||
61b5f210 | 778 | /* Create new MODIFY expression using RHS. */ |
40923b20 DP |
779 | new_stmt = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)), |
780 | unshare_expr (PHI_RESULT (phi)), rhs); | |
781 | ||
782 | /* Make new statement definition of the original phi result. */ | |
783 | SSA_NAME_DEF_STMT (PHI_RESULT (phi)) = new_stmt; | |
784 | ||
785 | /* Set basic block and insert using iterator. */ | |
786 | set_bb_for_stmt (new_stmt, bb); | |
787 | ||
788 | bsi_insert_after (bsi, new_stmt, BSI_SAME_STMT); | |
789 | bsi_next (bsi); | |
790 | ||
791 | modify_stmt (new_stmt); | |
792 | ||
793 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
794 | { | |
795 | fprintf (dump_file, "new phi replacement stmt\n"); | |
796 | print_generic_stmt (dump_file, new_stmt, TDF_SLIM); | |
797 | } | |
798 | } | |
799 | ||
61b5f210 | 800 | /* Process phi nodes for the given LOOP. Replace phi nodes with cond |
40923b20 DP |
801 | modify expr. */ |
802 | ||
803 | static void | |
804 | process_phi_nodes (struct loop *loop) | |
805 | { | |
806 | basic_block bb; | |
807 | unsigned int orig_loop_num_nodes = loop->num_nodes; | |
808 | unsigned int i; | |
809 | ||
810 | /* Replace phi nodes with cond. modify expr. */ | |
811 | for (i = 1; i < orig_loop_num_nodes; i++) | |
812 | { | |
813 | tree phi, cond; | |
814 | block_stmt_iterator bsi; | |
7f7e0703 | 815 | basic_block true_bb = NULL; |
40923b20 | 816 | bb = ifc_bbs[i]; |
61b5f210 | 817 | |
40923b20 DP |
818 | if (bb == loop->header || bb == loop->latch) |
819 | continue; | |
820 | ||
821 | phi = phi_nodes (bb); | |
822 | bsi = bsi_start (bb); | |
823 | ||
824 | /* BB has two predecessors. Using predecessor's aux field, set | |
825 | appropriate condition for the PHI node replacement. */ | |
826 | if (phi) | |
7f7e0703 | 827 | true_bb = find_phi_replacement_condition (bb, &cond, &bsi); |
40923b20 DP |
828 | |
829 | while (phi) | |
830 | { | |
831 | tree next = TREE_CHAIN (phi); | |
7f7e0703 | 832 | replace_phi_with_cond_modify_expr (phi, cond, true_bb, &bsi); |
40923b20 DP |
833 | release_phi_node (phi); |
834 | phi = next; | |
835 | } | |
836 | bb_ann (bb)->phi_nodes = NULL; | |
837 | } | |
838 | return; | |
839 | } | |
840 | ||
61b5f210 | 841 | /* Combine all basic block from the given LOOP into one or two super |
8c27b7d4 | 842 | basic block. Replace PHI nodes with conditional modify expression. */ |
40923b20 DP |
843 | |
844 | static void | |
845 | combine_blocks (struct loop *loop) | |
846 | { | |
847 | basic_block bb, exit_bb, merge_target_bb; | |
848 | unsigned int orig_loop_num_nodes = loop->num_nodes; | |
849 | unsigned int i; | |
850 | ||
851 | /* Process phi nodes to prepare blocks for merge. */ | |
852 | process_phi_nodes (loop); | |
853 | ||
854 | exit_bb = NULL; | |
855 | ||
856 | /* Merge basic blocks */ | |
857 | merge_target_bb = loop->header; | |
858 | for (i = 1; i < orig_loop_num_nodes; i++) | |
859 | { | |
860 | edge e; | |
861 | block_stmt_iterator bsi; | |
862 | tree_stmt_iterator last; | |
863 | ||
864 | bb = ifc_bbs[i]; | |
865 | ||
866 | if (bb == loop->latch) | |
867 | continue; | |
868 | ||
869 | if (!exit_bb && bb_with_exit_edge_p (bb)) | |
870 | exit_bb = bb; | |
871 | ||
872 | if (bb == exit_bb) | |
873 | { | |
874 | edge new_e; | |
628f6a4e | 875 | edge_iterator ei; |
40923b20 DP |
876 | |
877 | /* Connect this node with loop header. */ | |
878 | new_e = make_edge (ifc_bbs[0], bb, EDGE_FALLTHRU); | |
879 | set_immediate_dominator (CDI_DOMINATORS, bb, ifc_bbs[0]); | |
880 | ||
881 | if (exit_bb != loop->latch) | |
882 | { | |
883 | /* Redirect non-exit edge to loop->latch. */ | |
628f6a4e | 884 | FOR_EACH_EDGE (e, ei, bb->succs) |
40923b20 DP |
885 | if (!(e->flags & EDGE_LOOP_EXIT)) |
886 | { | |
887 | redirect_edge_and_branch (e, loop->latch); | |
888 | set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb); | |
889 | } | |
890 | } | |
891 | continue; | |
892 | } | |
893 | ||
894 | /* It is time to remove this basic block. First remove edges. */ | |
628f6a4e BE |
895 | while (EDGE_COUNT (bb->succs) > 0) |
896 | ssa_remove_edge (EDGE_SUCC (bb, 0)); | |
897 | while (EDGE_COUNT (bb->preds) > 0) | |
898 | ssa_remove_edge (EDGE_PRED (bb, 0)); | |
40923b20 DP |
899 | |
900 | /* Remove labels and make stmts member of loop->header. */ | |
901 | for (bsi = bsi_start (bb); !bsi_end_p (bsi); ) | |
902 | { | |
903 | if (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR) | |
904 | bsi_remove (&bsi); | |
905 | else | |
906 | { | |
907 | set_bb_for_stmt (bsi_stmt (bsi), merge_target_bb); | |
908 | bsi_next (&bsi); | |
909 | } | |
910 | } | |
911 | ||
912 | /* Update stmt list. */ | |
913 | last = tsi_last (merge_target_bb->stmt_list); | |
914 | tsi_link_after (&last, bb->stmt_list, TSI_NEW_STMT); | |
915 | bb->stmt_list = NULL; | |
916 | ||
917 | /* Update dominator info. */ | |
918 | if (dom_computed[CDI_DOMINATORS]) | |
919 | delete_from_dominance_info (CDI_DOMINATORS, bb); | |
920 | if (dom_computed[CDI_POST_DOMINATORS]) | |
921 | delete_from_dominance_info (CDI_POST_DOMINATORS, bb); | |
61b5f210 | 922 | |
40923b20 DP |
923 | /* Remove basic block. */ |
924 | remove_bb_from_loops (bb); | |
925 | expunge_block (bb); | |
926 | } | |
a2159c4c DP |
927 | |
928 | /* Now if possible, merge loop header and block with exit edge. | |
929 | This reduces number of basic blocks to 2. Auto vectorizer addresses | |
930 | loops with two nodes only. FIXME: Use cleanup_tree_cfg(). */ | |
931 | if (exit_bb != loop->latch && empty_block_p (loop->latch)) | |
932 | { | |
933 | if (can_merge_blocks_p (loop->header, exit_bb)) | |
934 | { | |
935 | remove_bb_from_loops (exit_bb); | |
936 | merge_blocks (loop->header, exit_bb); | |
937 | } | |
938 | } | |
40923b20 DP |
939 | } |
940 | ||
61b5f210 | 941 | /* Make new temp variable of type TYPE. Add MODIFY_EXPR to assign EXP |
40923b20 DP |
942 | to the new variable. */ |
943 | ||
944 | static tree | |
945 | ifc_temp_var (tree type, tree exp) | |
946 | { | |
947 | const char *name = "_ifc_"; | |
948 | tree var, stmt, new_name; | |
949 | ||
950 | if (is_gimple_reg (exp)) | |
951 | return exp; | |
952 | ||
953 | /* Create new temporary variable. */ | |
954 | var = create_tmp_var (type, name); | |
955 | add_referenced_tmp_var (var); | |
956 | ||
2a7e31df | 957 | /* Build new statement to assign EXP to new variable. */ |
40923b20 | 958 | stmt = build (MODIFY_EXPR, type, var, exp); |
61b5f210 | 959 | |
40923b20 DP |
960 | /* Get SSA name for the new variable and set make new statement |
961 | its definition statment. */ | |
962 | new_name = make_ssa_name (var, stmt); | |
963 | TREE_OPERAND (stmt, 0) = new_name; | |
964 | SSA_NAME_DEF_STMT (new_name) = stmt; | |
965 | ||
966 | return stmt; | |
967 | } | |
968 | ||
969 | ||
970 | /* Return TRUE iff, all pred blocks of BB are visited. | |
971 | Bitmap VISITED keeps history of visited blocks. */ | |
972 | ||
973 | static bool | |
974 | pred_blocks_visited_p (basic_block bb, bitmap *visited) | |
975 | { | |
976 | edge e; | |
628f6a4e BE |
977 | edge_iterator ei; |
978 | FOR_EACH_EDGE (e, ei, bb->preds) | |
40923b20 DP |
979 | if (!bitmap_bit_p (*visited, e->src->index)) |
980 | return false; | |
61b5f210 | 981 | |
40923b20 DP |
982 | return true; |
983 | } | |
984 | ||
985 | /* Get body of a LOOP in suitable order for if-conversion. | |
986 | It is caller's responsibility to deallocate basic block | |
987 | list. If-conversion suitable order is, BFS order with one | |
988 | additional constraint. Select block in BFS block, if all | |
989 | pred are already selected. */ | |
990 | ||
61b5f210 | 991 | static basic_block * |
40923b20 DP |
992 | get_loop_body_in_if_conv_order (const struct loop *loop) |
993 | { | |
994 | basic_block *blocks, *blocks_in_bfs_order; | |
995 | basic_block bb; | |
996 | bitmap visited; | |
997 | unsigned int index = 0; | |
998 | unsigned int visited_count = 0; | |
999 | ||
1e128c5f GB |
1000 | gcc_assert (loop->num_nodes); |
1001 | gcc_assert (loop->latch != EXIT_BLOCK_PTR); | |
40923b20 DP |
1002 | |
1003 | blocks = xcalloc (loop->num_nodes, sizeof (basic_block)); | |
1004 | visited = BITMAP_XMALLOC (); | |
1005 | ||
1006 | blocks_in_bfs_order = get_loop_body_in_bfs_order (loop); | |
1007 | ||
1008 | index = 0; | |
1009 | while (index < loop->num_nodes) | |
1010 | { | |
1011 | bb = blocks_in_bfs_order [index]; | |
61b5f210 | 1012 | |
40923b20 DP |
1013 | if (bb->flags & BB_IRREDUCIBLE_LOOP) |
1014 | { | |
1015 | free (blocks_in_bfs_order); | |
1016 | BITMAP_FREE (visited); | |
1017 | free (blocks); | |
1018 | return NULL; | |
1019 | } | |
1020 | if (!bitmap_bit_p (visited, bb->index)) | |
1021 | { | |
1022 | if (pred_blocks_visited_p (bb, &visited) | |
1023 | || bb == loop->header) | |
1024 | { | |
1025 | /* This block is now visited. */ | |
1026 | bitmap_set_bit (visited, bb->index); | |
1027 | blocks[visited_count++] = bb; | |
1028 | } | |
1029 | } | |
1030 | index++; | |
1031 | if (index == loop->num_nodes | |
1032 | && visited_count != loop->num_nodes) | |
1033 | { | |
1034 | /* Not done yet. */ | |
1035 | index = 0; | |
1036 | } | |
1037 | } | |
1038 | free (blocks_in_bfs_order); | |
1039 | BITMAP_XFREE (visited); | |
1040 | return blocks; | |
1041 | } | |
1042 | ||
1043 | /* Return true if one of the basic block BB edge is loop exit. */ | |
1044 | ||
1045 | static bool | |
1046 | bb_with_exit_edge_p (basic_block bb) | |
1047 | { | |
1048 | edge e; | |
628f6a4e | 1049 | edge_iterator ei; |
40923b20 DP |
1050 | bool exit_edge_found = false; |
1051 | ||
628f6a4e | 1052 | FOR_EACH_EDGE (e, ei, bb->succs) |
40923b20 | 1053 | if (e->flags & EDGE_LOOP_EXIT) |
628f6a4e BE |
1054 | { |
1055 | exit_edge_found = true; | |
1056 | break; | |
1057 | } | |
40923b20 DP |
1058 | |
1059 | return exit_edge_found; | |
1060 | } | |
1061 | ||
1062 | /* Tree if-conversion pass management. */ | |
1063 | ||
1064 | static void | |
1065 | main_tree_if_conversion (void) | |
1066 | { | |
1067 | unsigned i, loop_num; | |
1068 | struct loop *loop; | |
1069 | ||
1070 | if (!current_loops) | |
1071 | return; | |
1072 | ||
1073 | loop_num = current_loops->num; | |
1074 | for (i = 0; i < loop_num; i++) | |
1075 | { | |
1076 | loop = current_loops->parray[i]; | |
1077 | if (!loop) | |
1078 | continue; | |
1079 | ||
1080 | tree_if_conversion (loop, true); | |
1081 | } | |
1082 | ||
1083 | } | |
1084 | ||
1085 | static bool | |
1086 | gate_tree_if_conversion (void) | |
1087 | { | |
2addf926 | 1088 | return flag_tree_vectorize != 0; |
40923b20 DP |
1089 | } |
1090 | ||
1091 | struct tree_opt_pass pass_if_conversion = | |
1092 | { | |
1093 | "ifcvt", /* name */ | |
1094 | gate_tree_if_conversion, /* gate */ | |
1095 | main_tree_if_conversion, /* execute */ | |
1096 | NULL, /* sub */ | |
1097 | NULL, /* next */ | |
1098 | 0, /* static_pass_number */ | |
1099 | 0, /* tv_id */ | |
1100 | PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */ | |
1101 | 0, /* properties_provided */ | |
1102 | 0, /* properties_destroyed */ | |
1103 | TODO_dump_func, /* todo_flags_start */ | |
61b5f210 | 1104 | TODO_dump_func |
40923b20 | 1105 | | TODO_verify_ssa |
61b5f210 | 1106 | | TODO_verify_stmts |
9f8628ba PB |
1107 | | TODO_verify_flow, /* todo_flags_finish */ |
1108 | 0 /* letter */ | |
40923b20 | 1109 | }; |