/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
* This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
*/
/**
* @file
* @brief boolean condition/control flow optimizations
* @author Matthias Braun, Christoph Mallon, Michael Beck
- * @version $Id: cfopt.c 22579 2008-10-07 14:54:04Z beck $
*/
#include "config.h"
int changed; /**< Set if the graph was changed. */
} bool_opt_env_t;
-DEBUG_ONLY(static firm_dbg_module_t *dbg);
+DEBUG_ONLY(static firm_dbg_module_t *dbg;)
/**
* Check if tho given nodes, l and r, represent two compares with
*/
static bool find_cond_pair(ir_node *const l, ir_node *const r, cond_pair *const res)
{
- if (!is_Cmp(l) || !is_Cmp(r))
- return false;
-
- ir_node *const lol = get_Cmp_left(l);
- ir_node *const lor = get_Cmp_right(l);
- ir_node *const rol = get_Cmp_left(r);
- ir_node *const ror = get_Cmp_right(r);
- ir_relation const pnc_l = get_Cmp_relation(l);
- ir_relation const pnc_r = get_Cmp_relation(r);
-
- if (is_Const(lor) && is_Const_null(lor) &&
- is_Const(ror) && is_Const_null(ror) &&
- pnc_l == pnc_r &&
- (pnc_l == ir_relation_less_greater || pnc_l == ir_relation_equal)) {
- /* l == (lol !=|== NULL) && r == (rol !=|== NULL) */
- res->cmp_lo = l;
- res->cmp_hi = r;
- res->rel_lo = pnc_l;
- res->rel_hi = pnc_l;
- res->tv_lo = get_Const_tarval(lor);
- res->tv_hi = get_Const_tarval(ror);
- res->lo_mode = get_irn_mode(lor);
-
- return true;
- }
-
- if (lol == rol && lor != ror && is_Const(lor) && is_Const(ror)) {
- /* l == (x CMP c_l), r == (x cmp c_r) */
- ir_tarval *const tv_l = get_Const_tarval(lor);
- ir_tarval *const tv_r = get_Const_tarval(ror);
- ir_relation const rel = tarval_cmp(tv_l, tv_r);
-
- res->lo_mode = get_irn_mode(lol);
-
- if (rel == ir_relation_less) {
- /* c_l < c_r */
+ if (is_Cmp(l) && is_Cmp(r)) {
+ ir_node *const lol = get_Cmp_left(l);
+ ir_node *const lor = get_Cmp_right(l);
+ ir_node *const rol = get_Cmp_left(r);
+ ir_node *const ror = get_Cmp_right(r);
+ ir_relation const pnc_l = get_Cmp_relation(l);
+ ir_relation const pnc_r = get_Cmp_relation(r);
+
+ if (is_Const(lor) && is_Const_null(lor) &&
+ is_Const(ror) && is_Const_null(ror) &&
+ pnc_l == pnc_r &&
+ (pnc_l == ir_relation_less_greater || pnc_l == ir_relation_equal)) {
+ /* l == (lol !=|== NULL) && r == (rol !=|== NULL) */
res->cmp_lo = l;
res->cmp_hi = r;
res->rel_lo = pnc_l;
- res->rel_hi = pnc_r;
- res->tv_lo = tv_l;
- res->tv_hi = tv_r;
- } else if (rel == ir_relation_greater) {
- /* c_l > c_r */
- res->cmp_lo = r;
- res->cmp_hi = l;
- res->rel_lo = pnc_r;
res->rel_hi = pnc_l;
- res->tv_lo = tv_r;
- res->tv_hi = tv_l;
- } else {
- /* The constants shall be unequal but comparable.
- * Local optimizations handle the equal case. */
- return false;
+ res->tv_lo = get_Const_tarval(lor);
+ res->tv_hi = get_Const_tarval(ror);
+ res->lo_mode = get_irn_mode(lor);
+
+ return true;
+ }
+
+ if (lol == rol && lor != ror && is_Const(lor) && is_Const(ror)) {
+ /* l == (x CMP c_l), r == (x cmp c_r) */
+ ir_tarval *const tv_l = get_Const_tarval(lor);
+ ir_tarval *const tv_r = get_Const_tarval(ror);
+ ir_relation const rel = tarval_cmp(tv_l, tv_r);
+
+ res->lo_mode = get_irn_mode(lol);
+
+ if (rel == ir_relation_less) {
+ /* c_l < c_r */
+ res->cmp_lo = l;
+ res->cmp_hi = r;
+ res->rel_lo = pnc_l;
+ res->rel_hi = pnc_r;
+ res->tv_lo = tv_l;
+ res->tv_hi = tv_r;
+ } else if (rel == ir_relation_greater) {
+ /* c_l > c_r */
+ res->cmp_lo = r;
+ res->cmp_hi = l;
+ res->rel_lo = pnc_r;
+ res->rel_hi = pnc_l;
+ res->tv_lo = tv_r;
+ res->tv_hi = tv_l;
+ } else {
+ /* The constants shall be unequal but comparable.
+ * Local optimizations handle the equal case. */
+ return false;
+ }
+ return true;
}
- return true;
}
return false;
}
ir_node *lower_block;
ir_node *lower_cf;
ir_node *cond;
- ir_node *cond_selector;
- ir_node *lower_pred;
lower_cf = get_Block_cfgpred(block, low_idx);
lower_cf = skip_empty_blocks(lower_cf);
if (get_Block_mark(lower_block))
continue;
- cond_selector = get_Cond_selector(cond);
- if (get_irn_mode(cond_selector) != mode_b)
- continue;
-
- lower_pred = get_Block_cfgpred_block(lower_block, 0);
-
+ ir_node *const cond_selector = get_Cond_selector(cond);
+ ir_node *const lower_pred = get_Block_cfgpred_block(lower_block, 0);
for (up_idx = 0; up_idx < n_cfgpreds; ++up_idx) {
ir_node *upper_block;
ir_node *upper_cf;
- ir_node *upper_cond;
- ir_node *upper_cond_selector;
ir_node *replacement;
cond_pair cpair;
if (!block_dominates(upper_block, block))
continue;
- assert(is_Proj(upper_cf));
- upper_cond = get_Proj_pred(upper_cf);
- assert(is_Cond(upper_cond));
- upper_cond_selector = get_Cond_selector(upper_cond);
- if (get_irn_mode(upper_cond_selector) != mode_b)
- continue;
-
/* we have found the structure */
/* check Phis: There must be NO Phi in block that
depends on the existence of low block */
continue;
/* all fine, try it */
+ ir_node *const upper_cond = get_Proj_pred(upper_cf);
+ ir_node *const upper_cond_selector = get_Cond_selector(upper_cond);
if (!find_cond_pair(cond_selector, upper_cond_selector, &cpair))
continue;
/* normalize pncs: we need the true case to jump into the
- * common block (ie. conjunctive normal form) */
+ * common block (i.e. conjunctive normal form) */
if (get_Proj_proj(lower_cf) == pn_Cond_false) {
if (cpair.cmp_lo == cond_selector) {
ir_node *cmp = cpair.cmp_lo;
/* register a debug mask */
FIRM_DBG_REGISTER(dbg, "firm.opt.bool");
- /* works better with one return block only */
- normalize_one_return(irg);
-
env.changed = 0;
/* optimize simple Andb and Orb cases */
irg_walk_graph(irg, NULL, bool_walk, &env);
- ir_reserve_resources(irg, IR_RESOURCE_BLOCK_MARK | IR_RESOURCE_PHI_LIST);
-
/* now more complicated cases: find control flow And/Or and optimize. */
+ ir_reserve_resources(irg, IR_RESOURCE_BLOCK_MARK | IR_RESOURCE_PHI_LIST);
irg_walk_graph(irg, clear_block_infos, collect_phis, NULL);
irg_block_walk_graph(irg, NULL, find_cf_and_or_walker, &env);
-
- if (env.changed) {
- set_irg_outs_inconsistent(irg);
- set_irg_doms_inconsistent(irg);
- set_irg_extblk_inconsistent(irg);
- set_irg_loopinfo_inconsistent(irg);
- }
-
ir_free_resources(irg, IR_RESOURCE_BLOCK_MARK | IR_RESOURCE_PHI_LIST);
+
+ confirm_irg_properties(irg,
+ env.changed ? IR_GRAPH_PROPERTIES_NONE : IR_GRAPH_PROPERTIES_ALL);
}
/* Creates an ir_graph pass for opt_bool. */