static ir_tarval *fold_binary_sub(binary_expression_t const *const binexpr) { ir_tarval *const l = fold_expression(binexpr->left); ir_tarval *const r = fold_expression(binexpr->right); type_t *const type = skip_typeref(binexpr->base.type); ir_mode *const res_mode = get_ir_mode_arithmetic(type); type_t *const typel = skip_typeref(binexpr->left->base.type); if (is_type_pointer(typel)) { type_t *const elem = skip_typeref(typel->pointer.points_to); type_t *const typer = skip_typeref(binexpr->right->base.type); if (is_type_pointer(typer)) { ir_tarval *const size = get_type_size_tarval(elem, res_mode); ir_tarval *const diff = tarval_sub(l, r); return tarval_div(diff, size); } else { ir_mode *const mode = get_tarval_mode(r); ir_tarval *const size = get_type_size_tarval(elem, mode); ir_tarval *const rr = tarval_mul(r, size); return tarval_sub(l, rr); } } else { ir_tarval *const conv_l = tarval_convert_to(l, res_mode); ir_tarval *const conv_r = tarval_convert_to(r, res_mode); return tarval_sub(conv_l, conv_r); } }
static carry_result lower_sub_borrow(ir_node *left, ir_node *right, ir_mode *mode) { assert(!mode_is_signed(mode)); bitinfo *bi_left = get_bitinfo(left); if (!bi_left) { return can_carry; } bitinfo *bi_right = get_bitinfo(right); // If we have bitinfo for one node, we should also have it for // the other assert(bi_right); ir_tarval *lmin = tarval_convert_to(bitinfo_min(bi_left), mode); ir_tarval *rmin = tarval_convert_to(bitinfo_min(bi_right), mode); ir_tarval *lmax = tarval_convert_to(bitinfo_max(bi_left), mode); ir_tarval *rmax = tarval_convert_to(bitinfo_max(bi_right), mode); carry_result result = no_carry; int old_wrap_on_overflow = tarval_get_wrap_on_overflow(); tarval_set_wrap_on_overflow(false); if (tarval_sub(lmin, rmax) == tarval_bad) { result = can_carry; if (tarval_sub(lmax, rmin) == tarval_bad) { result = must_carry; } } tarval_set_wrap_on_overflow(old_wrap_on_overflow); return result; }
static complex_constant fold_complex_sub(complex_constant const left, complex_constant const right) { return (complex_constant) { tarval_sub(left.real, right.real), tarval_sub(left.imag, right.imag) }; }
static complex_constant fold_complex_mul(complex_constant const left, complex_constant const right) { ir_tarval *const op1 = tarval_mul(left.real, right.real); ir_tarval *const op2 = tarval_mul(left.imag, right.imag); ir_tarval *const op3 = tarval_mul(left.real, right.imag); ir_tarval *const op4 = tarval_mul(left.imag, right.real); return (complex_constant) { tarval_sub(op1, op2), tarval_add(op3, op4) }; }
static complex_constant fold_complex_div(complex_constant const left, complex_constant const right) { ir_tarval *const op1 = tarval_mul(left.real, right.real); ir_tarval *const op2 = tarval_mul(left.imag, right.imag); ir_tarval *const op3 = tarval_mul(left.imag, right.real); ir_tarval *const op4 = tarval_mul(left.real, right.imag); ir_tarval *const op5 = tarval_mul(right.real, right.real); ir_tarval *const op6 = tarval_mul(right.imag, right.imag); ir_tarval *const real_dividend = tarval_add(op1, op2); ir_tarval *const real_divisor = tarval_add(op5, op6); ir_tarval *const imag_dividend = tarval_sub(op3, op4); ir_tarval *const imag_divisor = tarval_add(op5, op6); return (complex_constant) { tarval_div(real_dividend, real_divisor), tarval_div(imag_dividend, imag_divisor) }; }