X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fboolopt.c;h=6ff2a34c71f01177feb570688ed3518d37480f1c;hb=9e11e8bbbe517056f03a823a564f91793920a078;hp=680a11ec75a651bd4f4a24426f70e9c469541f1f;hpb=907510bd4b55ef7ffe46361f0c8d5c66f772ce66;p=libfirm diff --git a/ir/opt/boolopt.c b/ir/opt/boolopt.c index 680a11ec7..6ff2a34c7 100644 --- a/ir/opt/boolopt.c +++ b/ir/opt/boolopt.c @@ -6,7 +6,7 @@ #include "irgmod.h" #include "irgwalk.h" #include "irprintf.h" -#include "irnode.h" +#include "irnode_t.h" #include "tv.h" typedef struct cond_pair { @@ -86,20 +86,21 @@ static ir_node *bool_and(cond_pair* const cpair) tarval *const tv_lo = cpair->tv_lo; tarval *const tv_hi = cpair->tv_hi; + /* Beware of NaN's, we can only check for (ordered) != here (which is Lg, not Ne) */ if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le || pnc_lo == pn_Cmp_Eq) && (pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) { /* x <|<=|== lo | x ==|>=|> hi -> false */ ir_node *const t = new_Const(mode_b, tarval_b_false); return t; } else if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le || pnc_lo == pn_Cmp_Eq) && - (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Ne)) { + (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Lg)) { /* x <|<=|== lo && x <|<=|!= hi -> x <|<=|== lo */ return proj_lo; - } else if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Ne) && + } else if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Lg) && (pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) { /* x >=|>|!= lo || x ==|>=|> hi -> x ==|>=|> hi */ return proj_hi; - } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo))) { /* lo + 1 == hi */ + } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo, NULL))) { /* lo + 1 == hi */ if (pnc_lo == pn_Cmp_Ge && pnc_hi == pn_Cmp_Lt) { /* x >= c || x < c + 1 -> x == c */ ir_graph *const irg = current_ir_graph; @@ -107,7 +108,7 @@ static ir_node *bool_and(cond_pair* const cpair) ir_node *const p = new_r_Proj(irg, block, cmp_lo, mode_b, pn_Cmp_Eq); return p; } else if (pnc_lo == pn_Cmp_Gt) { - if (pnc_hi == pn_Cmp_Ne) { + if (pnc_hi == pn_Cmp_Lg) { /* x > c || x != c + 1 -> x > c + 1 */ ir_graph *const irg = current_ir_graph; ir_node *const block = get_nodes_block(cmp_hi); @@ -124,7 +125,7 @@ static ir_node *bool_and(cond_pair* const cpair) ir_node *const p = new_r_Proj(irg, block, cmp_hi, mode_b, pn_Cmp_Eq); return p; } - } else if (pnc_lo == pn_Cmp_Ne && pnc_hi == pn_Cmp_Lt) { + } else if (pnc_lo == pn_Cmp_Lg && pnc_hi == pn_Cmp_Lt) { /* x != c || c < c + 1 -> x < c */ ir_graph *const irg = current_ir_graph; ir_node *const block = get_nodes_block(cmp_lo); @@ -146,25 +147,26 @@ static ir_node *bool_or(cond_pair *const cpair) tarval *const tv_lo = cpair->tv_lo; tarval *const tv_hi = cpair->tv_hi; - if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Ne) && - (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Ne)) { + /* Beware of NaN's, we can only check for (ordered) != here (which is Lg, not Ne) */ + if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Lg) && + (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Lg)) { /* x >=|>|!= lo | x <|<=|!= hi -> true */ ir_node *const t = new_Const(mode_b, tarval_b_true); return t; } else if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le || pnc_lo == pn_Cmp_Eq) && - (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Ne)) { + (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Lg)) { /* x <|<=|== lo || x <|<=|!= hi -> x <|<=|!= hi */ return proj_hi; - } else if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Ne) && + } else if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Lg) && (pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) { /* x >=|>|!= lo || x ==|>=|> hi -> x >=|>|!= lo */ return proj_lo; - } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo))) { /* lo + 1 == hi */ + } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo, NULL))) { /* lo + 1 == hi */ if (pnc_lo == pn_Cmp_Lt && pnc_hi == pn_Cmp_Ge) { /* x < c || x >= c + 1 -> x != c */ ir_graph *const irg = current_ir_graph; ir_node *const block = get_nodes_block(cmp_lo); - ir_node *const p = new_r_Proj(irg, block, cmp_lo, mode_b, pn_Cmp_Ne); + ir_node *const p = new_r_Proj(irg, block, cmp_lo, mode_b, pn_Cmp_Lg); return p; } else if (pnc_lo == pn_Cmp_Le) { if (pnc_hi == pn_Cmp_Eq) { @@ -181,7 +183,7 @@ static ir_node *bool_or(cond_pair *const cpair) /* x <= c || x > c + 1 -> x != c + 1 */ ir_graph *const irg = current_ir_graph; ir_node *const block = get_nodes_block(cmp_hi); - ir_node *const p = new_r_Proj(irg, block, cmp_hi, mode_b, pn_Cmp_Ne); + ir_node *const p = new_r_Proj(irg, block, cmp_hi, mode_b, pn_Cmp_Lg); return p; } } else if (pnc_lo == pn_Cmp_Eq && pnc_hi == pn_Cmp_Ge) { @@ -225,60 +227,51 @@ static void bool_walk(ir_node *n, void *env) } } -static struct obstack obst; - -typedef struct block_info_t { - ir_node *phi; /**< head of the Phi list */ - int has_pinned; /**< set if the block contains instructions that cannot be - moved */ -} block_info_t; - -static block_info_t* get_block_blockinfo(ir_node* block) -{ - return get_irn_link(block); -} - -static void create_blockinfos(ir_node *node, void *env) +/** + * Walker, clear Block mark and Phi list + */ +static void clear_block_infos(ir_node *node, void *env) { - block_info_t *block_info; (void) env; /* we visit blocks before any other nodes (from the block) */ if (!is_Block(node)) return; - block_info = obstack_alloc(&obst, sizeof(block_info[0])); - memset(block_info, 0, sizeof(block_info[0])); - set_irn_link(node, block_info); + /* clear the PHI list */ + set_Block_phis(node, NULL); + set_Block_mark(node, 0); } +/** + * Walker: collect Phi nodes and update the + */ static void collect_phis(ir_node *node, void *env) { (void) env; if (is_Phi(node)) { - ir_node *block = get_nodes_block(node); - block_info_t *bi = get_block_blockinfo(block); - - set_irn_link(node, bi->phi); - bi->phi = node; + ir_node *block = get_nodes_block(node); + add_Block_phi(block, node); return; } /* Ignore control flow nodes, these will be removed. */ if (get_irn_pinned(node) == op_pin_state_pinned && !is_Block(node) && !is_cfop(node)) { - ir_node *block = get_nodes_block(node); - block_info_t *bi = get_block_blockinfo(block); - - bi->has_pinned = 1; + ir_node *block = get_nodes_block(node); + set_Block_mark(block, 1); } } -ir_node *skip_empty_block(ir_node *node) +/** + * If node is a Jmp in a block containing no pinned instruction + * and having only one predecessor, skip the block and return its + * cf predecessor, else the node itself. + */ +static ir_node *skip_empty_block(ir_node *node) { ir_node *block; - block_info_t *block_info; if(!is_Jmp(node)) return node; @@ -287,8 +280,7 @@ ir_node *skip_empty_block(ir_node *node) if(get_Block_n_cfgpreds(block) != 1) return node; - block_info = get_block_blockinfo(block); - if(block_info->has_pinned) + if(get_Block_mark(block)) return node; return get_Block_cfgpred(block, 0); @@ -320,7 +312,6 @@ restart: ir_node *lower_cf; ir_node *cond; ir_node *cond_selector; - block_info_t *block_info; ir_node *lower_pred; lower_cf = get_Block_cfgpred(block, i); @@ -328,21 +319,20 @@ restart: if(!is_Proj(lower_cf)) continue; - lower_block = get_nodes_block(lower_cf); - if(get_Block_n_cfgpreds(lower_block) != 1) - continue; - cond = get_Proj_pred(lower_cf); if(!is_Cond(cond)) continue; - cond_selector = get_Cond_selector(cond); - if(get_irn_mode(cond_selector) != mode_b) + lower_block = get_nodes_block(cond); + if(get_Block_n_cfgpreds(lower_block) != 1) continue; /* the block must not produce any side-effects */ - block_info = get_block_blockinfo(lower_block); - if(block_info->has_pinned) + 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); @@ -377,7 +367,7 @@ restart: continue; /* normalize pncs: we need the true case to jump into the - * common block */ + * common block (ie. conjunctive normal form) */ irg = current_ir_graph; if(get_Proj_proj(lower_cf) == pn_Cond_false) { if(cpair.proj_lo == cond_selector) { @@ -436,20 +426,16 @@ void opt_bool(ir_graph *const irg) { irg_walk_graph(irg, NULL, bool_walk, NULL); - set_using_irn_link(irg); + set_using_block_mark(irg); - obstack_init(&obst); - - irg_walk_graph(irg, create_blockinfos, collect_phis, NULL); + irg_walk_graph(irg, clear_block_infos, collect_phis, NULL); irg_block_walk_graph(irg, NULL, find_cf_and_or_walker, NULL); - obstack_free(&obst, NULL); - set_irg_outs_inconsistent(irg); set_irg_doms_inconsistent(irg); set_irg_extblk_inconsistent(irg); set_irg_loopinfo_inconsistent(irg); - clear_using_irn_link(irg); + clear_using_block_mark(irg); }