/** * lower 64bit Mul operation. */ static void ia32_lower_mul64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left = get_Mul_left(node); ir_node *right = get_Mul_right(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); /* EDX:EAX = left_low * right_low l_res = EAX t1 = right_low * left_high t2 = t1 + EDX t3 = left_low * right_high h_res = t2 + t3 */ /* handle the often used case of 32x32=64 mul */ ir_node *h_res; ir_node *l_res; if (is_sign_extend(left_low, left_high) && is_sign_extend(right_low, right_high)) { ir_node *mul = new_bd_ia32_l_IMul(dbg, block, left_low, right_low); h_res = new_rd_Proj(dbg, mul, mode, pn_ia32_l_IMul_res_high); l_res = new_rd_Proj(dbg, mul, ia32_mode_gp, pn_ia32_l_IMul_res_low); } else { /* note that zero extension is handled hare efficiently */ ir_node *mul = new_bd_ia32_l_Mul(dbg, block, left_low, right_low); ir_node *pEDX = new_rd_Proj(dbg, mul, mode, pn_ia32_l_Mul_res_high); l_res = new_rd_Proj(dbg, mul, ia32_mode_gp, pn_ia32_l_Mul_res_low); ir_node *right_lowc = new_rd_Conv(dbg, block, right_low, mode); ir_node *mul1 = new_rd_Mul(dbg, block, left_high, right_lowc, mode); ir_node *add = new_rd_Add(dbg, block, mul1, pEDX, mode); ir_node *left_lowc = new_rd_Conv(dbg, block, left_low, mode); ir_node *mul2 = new_rd_Mul(dbg, block, left_lowc, right_high, mode); h_res = new_rd_Add(dbg, block, add, mul2, mode); } ir_set_dw_lowered(node, l_res, h_res); }
static void lower64_mul(ir_node *node, ir_mode *mode) { dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left = get_Mul_left(node); ir_node *right = get_Mul_right(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); ir_node *conv_l_low = new_rd_Conv(dbgi, block, left_low, mode); ir_node *mul1 = new_rd_Mul(dbgi, block, conv_l_low, right_high, mode); ir_node *umull = new_bd_arm_UMulL_t(dbgi, block, left_low, right_low); ir_mode *umode = get_irn_mode(right_low); ir_node *umull_low = new_r_Proj(umull, umode, pn_arm_UMulL_t_low); ir_node *umull_high = new_r_Proj(umull, mode, pn_arm_UMulL_t_high); ir_node *conv_r_low = new_rd_Conv(dbgi, block, right_low, mode); ir_node *mul2 = new_rd_Mul(dbgi, block, conv_r_low, left_high, mode); ir_node *add1 = new_rd_Add(dbgi, block, mul2, mul1, mode); ir_node *add2 = new_rd_Add(dbgi, block, add1, umull_high, mode); ir_set_dw_lowered(node, umull_low, add2); }
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; }