* PURPOSE.
*/
-/*
- * Project: libFIRM
- * File name: ir/opt/cfopt.c
- * Purpose: Partial condition evaluation
- * Author: Christoph Mallon, Matthias Braun
- * Created: 10. Sep. 2006
- * CVS-ID: $Id$
- * Copyright: (c) 1998-2006 Universität Karlsruhe
+/**
+ * @file
+ * @brief Partial condition evaluation
+ * @date 10. Sep. 2006
+ * @author Christoph Mallon, Matthias Braun
+ * @version $Id$
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include "iroptimize.h"
+
#include <assert.h>
#include "array.h"
-#include "condeval.h"
#include "debug.h"
#include "ircons.h"
#include "irgmod.h"
set_irn_in(node, n + 1, ins);
}
-/**
- * Remove predecessor j from node, which is either a Block or a Phi
- * returns true if only one predecessor is left
- */
-static int remove_pred(ir_node* node, int j)
-{
- int n;
-
- assert(is_Block(node) || is_Phi(node));
-
- n = get_irn_arity(node);
- if (n == 2) {
- ir_node* pred = get_irn_n(node, 1 - j);
-
- if (is_Block(node)) {
- pred = get_nodes_block(pred);
- edges_reroute(node, pred, current_ir_graph);
- } else {
- exchange(node, pred);
- }
- return 1;
- } else {
- ir_node** ins;
- int i;
-
- NEW_ARR_A(ir_node*, ins, n - 1);
- for (i = 0; i < j; i++)
- ins[i] = get_irn_n(node, i);
- for (i++; i < n; i++)
- ins[i - 1] = get_irn_n(node, i);
-
- set_irn_in(node, n - 1, ins);
- return 0;
- }
-}
-
static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode)
{
int i;
ir_mode *mode = get_irn_mode(node);
/* ignore control flow */
- if (mode == mode_X)
+ if (mode == mode_X || is_Cond(node))
continue;
/* we may not copy mode_b nodes, because this could produce phi with mode_bs which can't
be handled in all backends. Instead we duplicate the node and move it to it's users */
ir_node *node = get_edge_src_irn(edge);
ir_mode *mode = get_irn_mode(node);
- if (mode == mode_X)
+ if (mode == mode_X || is_Cond(node))
continue;
if (mode == mode_b)
continue;
/**
- * Block-walker: searchs for the following construct
+ * Block-walker: searches for the following construct
*
* Const or Phi with constants
* |
* jumps into the true_block. We also have to shorten phis
* in our block because of this */
const ir_edge_t *edge, *next;
+ ir_node* bad = new_Bad();
+ size_t cnst_pos = env.cnst_pos;
/* shorten phis */
foreach_out_edge_safe(env.cnst_pred, edge, next) {
ir_node *node = get_edge_src_irn(edge);
if(is_Phi(node))
- remove_pred(node, env.cnst_pos);
+ set_Phi_pred(node, cnst_pos, bad);
}
- remove_pred(env.cnst_pred, env.cnst_pos);
+ set_Block_cfgpred(env.cnst_pred, cnst_pos, bad);
- // the graph is changed now
+ /* the graph is changed now */
*changed = 1;
- set_irg_doms_inconsistent(irg);
- set_irg_extblk_inconsistent(irg);
- set_irg_loopinfo_inconsistent(irg);
}
}
}
void opt_cond_eval(ir_graph* irg)
{
- int changed;
+ int changed, rerun;
FIRM_DBG_REGISTER(dbg, "firm.opt.condeval");
DB((dbg, LEVEL_1, "===> Performing condition evaluation on %+F\n", irg));
- edges_assure(irg);
remove_critical_cf_edges(irg);
-
normalize_proj_nodes(irg);
+ edges_assure(irg);
set_using_irn_link(irg);
set_using_visited(irg);
+ changed = 0;
do {
- changed = 0;
- irg_block_walk_graph(irg, cond_eval, NULL, &changed);
- } while(changed);
+ rerun = 0;
+ irg_block_walk_graph(irg, cond_eval, NULL, &rerun);
+ changed |= rerun;
+ } while (rerun);
+
+ if (changed) {
+ /* control flow changed, some blocks may become dead */
+ set_irg_outs_inconsistent(irg);
+ set_irg_doms_inconsistent(irg);
+ set_irg_extblk_inconsistent(irg);
+ set_irg_loopinfo_inconsistent(irg);
+ }
clear_using_visited(irg);
clear_using_irn_link(irg);