2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
7 * @brief Remove all Bad nodes from ir graph
8 * @author Andreas Zwinkau
23 * Return the number of non-Bad predecessors of the given node.
25 static int count_non_bads(ir_node *node)
27 int arity = get_Block_n_cfgpreds(node);
30 for (i = 0; i < arity; ++i) {
31 if (!is_Bad(get_irn_n(node, i)))
38 * Block-walker, remove Bad block predecessors and shorten Phis.
39 * Phi links must be uptodate.
41 static void block_remove_bads(ir_node *block)
43 ir_graph *irg = get_irn_irg(block);
44 const int max = get_Block_n_cfgpreds(block);
45 const int new_max = count_non_bads(block);
46 ir_node **new_in = ALLOCAN(ir_node*, new_max);
52 ir_entity *block_entity;
53 assert(max >= new_max);
55 /* 1. Create a new block without Bad inputs */
56 for (i = j = 0; i < max; ++i) {
57 ir_node *const block_pred = get_Block_cfgpred(block, i);
58 if (!is_Bad(block_pred)) {
59 new_in[j++] = block_pred;
64 /* If the end block is unreachable, it might have zero predecessors. */
66 ir_node *end_block = get_irg_end_block(irg);
67 if (block == end_block) {
68 set_irn_in(block, new_max, new_in);
73 new_block = new_r_Block(irg, new_max, new_in);
74 block_entity = get_Block_entity(block);
76 set_Block_entity(new_block, block_entity);
78 /* 2. Remove inputs on Phis, where the block input is Bad. */
79 for (phi = get_Block_phis(block); phi != NULL; phi = next) {
82 next = get_Phi_next(phi);
83 assert(get_irn_arity(phi) == max);
85 for (i = j = 0; i < max; ++i) {
86 ir_node *const block_pred = get_Block_cfgpred(block, i);
87 if (!is_Bad(block_pred)) {
88 ir_node *pred = get_irn_n(phi, i);
94 new_phi = new_r_Phi(new_block, new_max, new_in, get_irn_mode(phi));
95 exchange(phi, new_phi);
98 exchange(block, new_block);
101 static void collect(ir_node *node, void *env)
103 firm_collect_block_phis(node, NULL);
104 if (is_Block(node)) {
105 ir_node ***blocks_to_process = (ir_node***)env;
106 int arity = get_Block_n_cfgpreds(node);
107 int non_bads = count_non_bads(node);
108 if (arity != non_bads)
109 ARR_APP1(ir_node*, *blocks_to_process, node);
113 void remove_bads(ir_graph *irg)
117 ir_node **blocks_to_process = NEW_ARR_F(ir_node*, 0);
119 /* build phi list per block */
120 irg_walk_graph(irg, firm_clear_block_phis, collect, &blocks_to_process);
122 n_to_process = ARR_LEN(blocks_to_process);
123 for (i = 0; i < n_to_process; ++i) {
124 ir_node *block = blocks_to_process[i];
125 block_remove_bads(block);
127 DEL_ARR_F(blocks_to_process);
129 if (n_to_process > 0) {
130 edges_deactivate(irg);
131 clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
132 clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
134 add_irg_properties(irg, IR_GRAPH_PROPERTY_NO_BADS);