aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c70
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 */
};