/** * lower 64bit minus operation */ static void ia32_lower_minus64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *op = get_Minus_op(node); ir_node *op_low = get_lowered_low(op); ir_node *op_high = get_lowered_high(op); ir_node *minus = new_bd_ia32_l_Minus64(dbg, block, op_low, op_high); ir_node *l_res = new_r_Proj(minus, ia32_mode_gp, pn_ia32_Minus64_res_low); ir_node *h_res = new_r_Proj(minus, mode, pn_ia32_Minus64_res_high); ir_set_dw_lowered(node, l_res, h_res); }
static void lower64_minus(ir_node *node, ir_mode *mode) { dbg_info *dbgi = get_irn_dbg_info(node); ir_graph *irg = get_irn_irg(node); ir_node *block = get_nodes_block(node); ir_node *op = get_Minus_op(node); ir_node *right_low = get_lowered_low(op); ir_node *right_high = get_lowered_high(op); ir_mode *low_unsigned = get_irn_mode(right_low); ir_node *left_low = new_r_Const_null(irg, low_unsigned); ir_node *left_high = new_r_Const_null(irg, mode); ir_node *subs = new_bd_arm_SubS_t(dbgi, block, left_low, right_low); ir_node *res_low = new_r_Proj(subs, low_unsigned, pn_arm_SubS_t_res); ir_node *res_flags = new_r_Proj(subs, mode_ANY, pn_arm_SubS_t_flags); ir_node *sbc = new_bd_arm_SbC_t(dbgi, block, left_high, right_high, res_flags, mode); ir_set_dw_lowered(node, res_low, sbc); }
/* * Check, if the value of a node is != 0. * * This is a often needed case, so we handle here Confirm * nodes too. */ int value_not_zero(const ir_node *n, const ir_node **confirm) { #define RET_ON(x) if (x) { *confirm = n; return 1; } break ir_tarval *tv; ir_mode *mode = get_irn_mode(n); ir_relation relation; *confirm = NULL; /* there might be several Confirms one after other that form an interval */ for (;;) { if (is_Minus(n)) { /* we can safely skip Minus when checking for != 0 */ n = get_Minus_op(n); continue; } if (! is_Confirm(n)) break; /* * Note: A Confirm is never after a Const. So, * we simply can check the bound for being a Const * without the fear that is might be hidden by a further Confirm. */ tv = value_of(get_Confirm_bound(n)); if (tv == tarval_bad) { n = get_Confirm_value(n); continue; } relation = tarval_cmp(tv, get_mode_null(mode)); /* * Beware: C might by a NaN. It is not clear, what we should do * than. Of course a NaN is != 0, but we might use this function * to remove up Exceptions, and NaN's might generate Exception. * So, we do NOT handle NaNs here for safety. * * Note that only the C != 0 case need additional checking. */ switch (get_Confirm_relation(n)) { case ir_relation_equal: /* n == C /\ C != 0 ==> n != 0 */ RET_ON(relation != ir_relation_equal && relation != ir_relation_unordered); case ir_relation_less_greater: /* n != C /\ C == 0 ==> n != 0 */ RET_ON(relation == ir_relation_equal); case ir_relation_less: /* n < C /\ C <= 0 ==> n != 0 */ RET_ON(relation == ir_relation_less || relation == ir_relation_equal); case ir_relation_less_equal: /* n <= C /\ C < 0 ==> n != 0 */ RET_ON(relation == ir_relation_less); case ir_relation_greater_equal: /* n >= C /\ C > 0 ==> n != 0 */ RET_ON(relation == ir_relation_greater); case ir_relation_greater: /* n > C /\ C >= 0 ==> n != 0 */ RET_ON(relation == ir_relation_greater || relation == ir_relation_equal); default: break; } n = get_Confirm_value(n); } /* global entities are never NULL */ if (is_SymConst_addr_ent(n)) return true; tv = value_of(n); if (tv == tarval_bad) return false; relation = tarval_cmp(tv, get_mode_null(mode)); /* again, need check for NaN */ return (relation != ir_relation_equal) && (relation != ir_relation_unordered); #undef RET_ON }
/* * Check, if the value of a node can be confirmed >= 0 or <= 0, * If the mode of the value did not honor signed zeros, else * check for >= 0 or < 0. */ ir_value_classify_sign classify_value_sign(ir_node *n) { ir_tarval *tv, *c; ir_mode *mode; ir_relation cmp, ncmp; int negate = 1; for (;;) { unsigned code = get_irn_opcode(n); switch (code) { case iro_Minus: negate *= -1; n = get_Minus_op(n); continue; case iro_Confirm: break; default: return value_classified_unknown; } break; } if (!is_Confirm(n)) return value_classified_unknown; tv = value_of(get_Confirm_bound(n)); if (tv == tarval_bad) return value_classified_unknown; mode = get_irn_mode(n); /* * We can handle only >=, >, <, <= cases. * We could handle == too, but this will be optimized into * a constant either. * * Note that for integer modes we have a slightly better * optimization possibilities, so we handle this * different. */ cmp = get_Confirm_relation(n); switch (cmp) { case ir_relation_less: /* * must be x < c <= 1 to be useful if integer mode and -0 = 0 * x < c <= 0 to be useful else */ case ir_relation_less_equal: /* * must be x <= c < 1 to be useful if integer mode and -0 = 0 * x <= c < 0 to be useful else */ c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ? get_mode_one(mode) : get_mode_null(mode); ncmp = tarval_cmp(tv, c); if (ncmp == ir_relation_equal) ncmp = ir_relation_less_equal; if (cmp != (ncmp ^ ir_relation_equal)) return value_classified_unknown; /* yep, negative */ return value_classified_negative * negate; case ir_relation_greater_equal: /* * must be x >= c > -1 to be useful if integer mode * x >= c >= 0 to be useful else */ case ir_relation_greater: /* * must be x > c >= -1 to be useful if integer mode * x > c >= 0 to be useful else */ if (mode_is_int(mode)) { c = get_mode_minus_one(mode); ncmp = tarval_cmp(tv, c); if (ncmp == ir_relation_equal) ncmp = ir_relation_greater_equal; if (cmp != (ncmp ^ ir_relation_equal)) return value_classified_unknown; } else { c = get_mode_minus_one(mode); ncmp = tarval_cmp(tv, c); if (ncmp != ir_relation_equal && ncmp != ir_relation_greater) return value_classified_unknown; } /* yep, positive */ return value_classified_positive * negate; default: return value_classified_unknown; } }
ir_node *copy_const_value(dbg_info *dbg, ir_node *n, ir_node *block) { ir_graph *irg = get_irn_irg(block); /* @@@ GL I think we should implement this using the routines from irgopt * for dead node elimination/inlineing. */ ir_mode *m = get_irn_mode(n); ir_node *nn; switch (get_irn_opcode(n)) { case iro_Const: nn = new_rd_Const(dbg, irg, get_Const_tarval(n)); break; case iro_SymConst: nn = new_rd_SymConst(dbg, irg, get_irn_mode(n), get_SymConst_symbol(n), get_SymConst_kind(n)); break; case iro_Add: nn = new_rd_Add(dbg, block, copy_const_value(dbg, get_Add_left(n), block), copy_const_value(dbg, get_Add_right(n), block), m); break; case iro_Sub: nn = new_rd_Sub(dbg, block, copy_const_value(dbg, get_Sub_left(n), block), copy_const_value(dbg, get_Sub_right(n), block), m); break; case iro_Mul: nn = new_rd_Mul(dbg, block, copy_const_value(dbg, get_Mul_left(n), block), copy_const_value(dbg, get_Mul_right(n), block), m); break; case iro_And: nn = new_rd_And(dbg, block, copy_const_value(dbg, get_And_left(n), block), copy_const_value(dbg, get_And_right(n), block), m); break; case iro_Or: nn = new_rd_Or(dbg, block, copy_const_value(dbg, get_Or_left(n), block), copy_const_value(dbg, get_Or_right(n), block), m); break; case iro_Eor: nn = new_rd_Eor(dbg, block, copy_const_value(dbg, get_Eor_left(n), block), copy_const_value(dbg, get_Eor_right(n), block), m); break; case iro_Conv: nn = new_rd_Conv(dbg, block, copy_const_value(dbg, get_Conv_op(n), block), m); break; case iro_Minus: nn = new_rd_Minus(dbg, block, copy_const_value(dbg, get_Minus_op(n), block), m); break; case iro_Not: nn = new_rd_Not(dbg, block, copy_const_value(dbg, get_Not_op(n), block), m); break; case iro_Unknown: nn = new_r_Unknown(irg, m); break; default: panic("opcode invalid or not implemented %+F", n); } return nn; }