becopyilp: Inline struct size_red_t into struct ilp_env_t.
[libfirm] / ir / opt / critical_edges.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief    Remove critical edges.
9  * @author   Christian Schaefer, Goetz Lindenmaier, Sebastian Felis,
10  *           Michael Beck
11  */
12 #include "config.h"
13
14 #include "irop_t.h"
15 #include "irnode_t.h"
16 #include "ircons.h"
17 #include "irgwalk.h"
18 #include "irgopt.h"
19
20 typedef struct cf_env {
21         char ignore_exc_edges; /**< set if exception edges should be ignored. */
22         char changed;          /**< flag indicates that the cf graphs has changed. */
23 } cf_env;
24
25 /**
26  * Called by walker of remove_critical_cf_edges().
27  *
28  * Place an empty block to an edge between a blocks of multiple
29  * predecessors and a block of multiple successors.
30  *
31  * @param n   IR node
32  * @param env Environment of walker.
33  */
34 static void walk_critical_cf_edges(ir_node *n, void *env)
35 {
36         int arity, i;
37         ir_node *pre, *block, *jmp;
38         cf_env *cenv = (cf_env*)env;
39         ir_graph *irg = get_irn_irg(n);
40
41         /* Block has multiple predecessors */
42         arity = get_irn_arity(n);
43         if (arity > 1) {
44                 if (n == get_irg_end_block(irg))
45                         return;  /*  No use to add a block here.      */
46
47                 for (i = 0; i < arity; ++i) {
48                         const ir_op *cfop;
49
50                         pre = get_irn_n(n, i);
51                         /* don't count Bad's */
52                         if (is_Bad(pre))
53                                 continue;
54
55                         cfop = get_irn_op(skip_Proj(pre));
56                         if (is_op_fragile(cfop)) {
57                                 if (cenv->ignore_exc_edges && is_x_except_Proj(pre))
58                                         continue;
59                                 goto insert;
60                         }
61                         if (is_unknown_jump(pre)) {
62                                 /* we can't add blocks in between ijmp and its destinations
63                                  * TODO: What now, we can't split all critical edges because of this... */
64                                 fprintf(stderr, "libfirm warning: Couldn't split all critical edges (compiler will probably fail now)\n");
65                                 continue;
66                         }
67                         /* we don't want place nodes in the start block, so handle it like forking */
68                         if (is_op_forking(cfop) || cfop == op_Start) {
69                                 /* Predecessor has multiple successors. Insert new control flow edge edges. */
70 insert:
71                                 /* set predecessor of new block */
72                                 block = new_r_Block(irg, 1, &pre);
73                                 /* insert new jmp node to new block */
74                                 jmp = new_r_Jmp(block);
75                                 /* set successor of new block */
76                                 set_irn_n(n, i, jmp);
77                                 cenv->changed = 1;
78                         }
79                 }
80         }
81 }
82
83 void remove_critical_cf_edges_ex(ir_graph *irg, int ignore_exception_edges)
84 {
85         cf_env env;
86
87         env.ignore_exc_edges = (char)ignore_exception_edges;
88         env.changed          = 0;
89
90         irg_block_walk_graph(irg, NULL, walk_critical_cf_edges, &env);
91         if (env.changed) {
92                 /* control flow changed */
93                 clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
94         }
95         add_irg_properties(irg, IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES);
96 }
97
98 void remove_critical_cf_edges(ir_graph *irg)
99 {
100         remove_critical_cf_edges_ex(irg, 1);
101 }