From: Michael Beck Date: Mon, 2 Jun 2008 13:08:04 +0000 (+0000) Subject: - better handling for strictConv's, optimized conv_orgie.c now X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=bfaef15ed7171535e63d147881ef9b8298527564;p=libfirm - better handling for strictConv's, optimized conv_orgie.c now [r19927] --- diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 5d040f2fb..c991c206d 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -1223,19 +1223,22 @@ static ir_node *equivalent_node_Conv(ir_node *n) { ir_mode *n_mode = get_irn_mode(n); ir_mode *a_mode = get_irn_mode(a); +restart: if (n_mode == a_mode) { /* No Conv necessary */ if (get_Conv_strict(n)) { /* special case: the predecessor might be a also a Conv */ if (is_Conv(a)) { if (! get_Conv_strict(a)) { /* first one is not strict, kick it */ - set_Conv_op(n, get_Conv_op(a)); - return n; + a = get_Conv_op(a); + a_mode = get_irn_mode(a); + set_Conv_op(n, a); + goto restart; } /* else both are strict conv, second is superfluous */ - } else if(is_Proj(a)) { + } else if (is_Proj(a)) { ir_node *pred = get_Proj_pred(a); - if(is_Load(pred)) { + if (is_Load(pred)) { /* loads always return with the exact precision of n_mode */ assert(get_Load_mode(pred) == n_mode); return a; @@ -1251,16 +1254,33 @@ static ir_node *equivalent_node_Conv(ir_node *n) { ir_node *b = get_Conv_op(a); ir_mode *b_mode = get_irn_mode(b); + if (get_Conv_strict(n) && get_Conv_strict(a)) { + /* both are strict conv */ + if (smaller_mode(a_mode, n_mode)) { + /* both are strict, but the first is smaller, so + the second cannot remove more precision, remove the + strict bit */ + set_Conv_strict(n, 0); + } + } if (n_mode == b_mode) { - if (n_mode == mode_b) { - n = b; /* Convb(Conv*(xxxb(...))) == xxxb(...) */ - DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV); - } else if (mode_is_int(n_mode)) { - if (get_mode_size_bits(b_mode) <= get_mode_size_bits(a_mode)) { - n = b; /* ConvS(ConvL(xxxS(...))) == xxxS(...) */ + if (! get_Conv_strict(n) && ! get_Conv_strict(a)) { + if (n_mode == mode_b) { + n = b; /* Convb(Conv*(xxxb(...))) == xxxb(...) */ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV); + } else if (get_mode_arithmetic(n_mode) == get_mode_arithmetic(a_mode)) { + if (smaller_mode(b_mode, a_mode)) { + n = b; /* ConvS(ConvL(xxxS(...))) == xxxS(...) */ + DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV); + } } } + if (is_Conv(b)) { + if (get_Conv_strict(n)) + set_Conv_strict(b, 1); + n = b; /* ConvA(ConvB(ConvA(...))) == ConvA(...) */ + DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV); + } } } return n;