diff options
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index b1ff8e6..d913759 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -5687,6 +5687,71 @@ tree_execute_on_shrinking_pred (edge e) remove_phi_args (e); } +/*--------------------------------------------------------------------------- + Helper functions for Loop versioning + ---------------------------------------------------------------------------*/ + +/* Adjust phi nodes for 'first' basic block. 'second' basic block is a copy + of 'first'. Both of them are dominated by 'new_head' basic block. When + 'new_head' was created by 'second's incoming edge it received phi arguments + on the edge by split_edge(). Later, additional edge 'e' was created to + connect 'new_head' and 'first'. Now this routine adds phi args on this + additional edge 'e' that new_head to second edge received as part of edge + splitting. +*/ + +static void +tree_lv_adjust_loop_header_phi (basic_block first, basic_block second, + basic_block new_head, edge e) +{ + tree phi1, phi2; + + /* Browse all 'second' basic block phi nodes and add phi args to + edge 'e' for 'first' head. PHI args are always in correct order. */ + + for (phi2 = phi_nodes (second), phi1 = phi_nodes (first); + phi2 && phi1; + phi2 = PHI_CHAIN (phi2), phi1 = PHI_CHAIN (phi1)) + { + edge e2 = find_edge (new_head, second); + + if (e2) + { + tree def = PHI_ARG_DEF (phi2, e2->dest_idx); + add_phi_arg (phi1, def, e); + } + } +} + +/* Adds a if else statement to COND_BB with condition COND_EXPR. + SECOND_HEAD is the destination of the THEN and FIRST_HEAD is + the destination of the ELSE part. */ +static void +tree_lv_add_condition_to_bb (basic_block first_head, basic_block second_head, + basic_block cond_bb, void *cond_e) +{ + block_stmt_iterator bsi; + tree goto1 = NULL_TREE; + tree goto2 = NULL_TREE; + tree new_cond_expr = NULL_TREE; + tree cond_expr = (tree) cond_e; + edge e0; + + /* Build new conditional expr */ + goto1 = build1 (GOTO_EXPR, void_type_node, tree_block_label (first_head)); + goto2 = build1 (GOTO_EXPR, void_type_node, tree_block_label (second_head)); + new_cond_expr = build3 (COND_EXPR, void_type_node, cond_expr, goto1, goto2); + + /* Add new cond in cond_bb. */ + bsi = bsi_start (cond_bb); + bsi_insert_after (&bsi, new_cond_expr, BSI_NEW_STMT); + /* Adjust edges appropriately to connect new head with first head + as well as second head. */ + e0 = single_succ_edge (cond_bb); + e0->flags &= ~EDGE_FALLTHRU; + e0->flags |= EDGE_FALSE_VALUE; +} + struct cfg_hooks tree_cfg_hooks = { "tree", tree_verify_flow_info, @@ -5711,6 +5776,11 @@ struct cfg_hooks tree_cfg_hooks = { tree_flow_call_edges_add, /* flow_call_edges_add */ tree_execute_on_growing_pred, /* execute_on_growing_pred */ tree_execute_on_shrinking_pred, /* execute_on_shrinking_pred */ + tree_duplicate_loop_to_header_edge, /* duplicate loop for trees */ + tree_lv_add_condition_to_bb, /* lv_add_condition_to_bb */ + tree_lv_adjust_loop_header_phi, /* lv_adjust_loop_header_phi*/ + extract_true_false_edges_from_block, /* extract_cond_bb_edges */ + flush_pending_stmts /* flush_pending_stmts */ }; |