summaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index fb24cc48a4a..f596c75fe27 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -99,6 +99,7 @@ static void make_edges (void);
static void make_cond_expr_edges (basic_block);
static void make_gimple_switch_edges (basic_block);
static void make_goto_expr_edges (basic_block);
+static void make_gimple_asm_edges (basic_block);
static unsigned int locus_map_hash (const void *);
static int locus_map_eq (const void *, const void *);
static void assign_discriminator (location_t, basic_block);
@@ -572,6 +573,11 @@ make_edges (void)
fallthru = true;
break;
+ case GIMPLE_ASM:
+ make_gimple_asm_edges (bb);
+ fallthru = true;
+ break;
+
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_FOR:
@@ -593,13 +599,11 @@ make_edges (void)
fallthru = false;
break;
-
case GIMPLE_OMP_ATOMIC_LOAD:
case GIMPLE_OMP_ATOMIC_STORE:
fallthru = true;
break;
-
case GIMPLE_OMP_RETURN:
/* In the case of a GIMPLE_OMP_SECTION, the edge will go
somewhere other than the next block. This will be
@@ -1011,6 +1015,23 @@ make_goto_expr_edges (basic_block bb)
make_abnormal_goto_edges (bb, false);
}
+/* Create edges for an asm statement with labels at block BB. */
+
+static void
+make_gimple_asm_edges (basic_block bb)
+{
+ gimple stmt = last_stmt (bb);
+ location_t stmt_loc = gimple_location (stmt);
+ int i, n = gimple_asm_nlabels (stmt);
+
+ for (i = 0; i < n; ++i)
+ {
+ tree label = TREE_VALUE (gimple_asm_label_op (stmt, i));
+ basic_block label_bb = label_to_block (label);
+ make_edge (bb, label_bb, 0);
+ assign_discriminator (stmt_loc, label_bb);
+ }
+}
/*---------------------------------------------------------------------------
Flowgraph analysis
@@ -1188,6 +1209,19 @@ cleanup_dead_labels (void)
break;
}
+ case GIMPLE_ASM:
+ {
+ int i, n = gimple_asm_nlabels (stmt);
+
+ for (i = 0; i < n; ++i)
+ {
+ tree cons = gimple_asm_label_op (stmt, i);
+ tree label = main_block_label (TREE_VALUE (cons));
+ TREE_VALUE (cons) = label;
+ }
+ break;
+ }
+
/* We have to handle gotos until they're removed, and we don't
remove them until after we've created the CFG edges. */
case GIMPLE_GOTO:
@@ -1195,8 +1229,8 @@ cleanup_dead_labels (void)
{
tree new_dest = main_block_label (gimple_goto_dest (stmt));
gimple_goto_set_dest (stmt, new_dest);
- break;
}
+ break;
default:
break;
@@ -2821,6 +2855,11 @@ is_ctrl_altering_stmt (gimple t)
fallthru to the next statement as well. */
return true;
+ case GIMPLE_ASM:
+ if (gimple_asm_nlabels (t) > 0)
+ return true;
+ break;
+
CASE_GIMPLE_OMP:
/* OpenMP directives alter control flow. */
return true;
@@ -5184,9 +5223,22 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
CASE_LABEL (elt) = label;
}
}
+ }
+ break;
- break;
+ case GIMPLE_ASM:
+ {
+ int i, n = gimple_asm_nlabels (stmt);
+ tree label = gimple_block_label (dest);
+
+ for (i = 0; i < n; ++i)
+ {
+ tree cons = gimple_asm_label_op (stmt, i);
+ if (label_to_block (TREE_VALUE (cons)) == e->dest)
+ TREE_VALUE (cons) = label;
+ }
}
+ break;
case GIMPLE_RETURN:
gsi_remove (&gsi, true);