diff options
author | Lawrence Crowl <crowl@google.com> | 2012-09-24 18:22:31 +0000 |
---|---|---|
committer | Lawrence Crowl <crowl@gcc.gnu.org> | 2012-09-24 18:22:31 +0000 |
commit | 9be0ac8c9e638bc1b52b83d34a98e8176af645e1 (patch) | |
tree | 023b0bf502c0f425e346dd501e463d522b3de28e /gcc/simplify-rtx.c | |
parent | ee38ecd4066dc3af0b893f2f4cda42d7938fa951 (diff) | |
download | gcc-9be0ac8c9e638bc1b52b83d34a98e8176af645e1.zip gcc-9be0ac8c9e638bc1b52b83d34a98e8176af645e1.tar.gz gcc-9be0ac8c9e638bc1b52b83d34a98e8176af645e1.tar.bz2 |
Finish conversion of uses of double_int to the new API.
Some old functionality required new interfaces, and these have been added to
double-int.[hc]:
double_int::from_pair - static constructor function
wide_mul_with_sign - double-wide multiply instruction
sub_with_overflow - subtraction with overlow testing
neg_with_overflow - negation with overlow testing
divmod_with_overflow - div and mod with overlow testing
This patch corrects the bootstrap problem on HPPA, via the addition of
sub_with_overflow. (The overflow properties of negation and addition are
different from subtraction.)
The prior two generations of the interface have been removed.
Some of these old interfaces are still used as static implementation in
double-int.c.
The changed compiler appears 0.321% faster with 80% confidence of being faster.
Tested on x86_64, HPPA, and SPARC. However, there are changes to the avr
config files, and I have not tested those.
Index: gcc/java/ChangeLog
2012-09-24 Lawrence Crowl <crowl@google.com>
* decl.c (java_init_decl_processing): Change to new double_int API.
* jcf-parse.c (get_constant): Likewise.
* boehm.c (mark_reference_fields): Likewise.
(get_boehm_type_descriptor): Likewise.
Index: gcc/ChangeLog
2012-09-24 Lawrence Crowl <crowl@google.com>
* double-int.h (double_int::from_pair): New.
(double_int::wide_mul_with_sign): New.
(double_int::sub_with_overflow): New.
(double_int::neg_with_overflow): New.
(double_int::divmod_with_overflow): New.
(shwi_to_double_int): Remove.
(uhwi_to_double_int): Remove.
(double_int_to_shwi): Remove.
(double_int_to_uhwi): Remove.
(double_int_fits_in_uhwi_p): Remove.
(double_int_fits_in_shwi_p): Remove.
(double_int_fits_in_hwi_p): Remove.
(double_int_mul): Remove.
(double_int_mul_with_sign): Remove.
(double_int_add): Remove.
(double_int_sub): Remove.
(double_int_neg): Remove.
(double_int_div): Remove.
(double_int_sdiv): Remove.
(double_int_udiv): Remove.
(double_int_mod): Remove.
(double_int_smod): Remove.
(double_int_umod): Remove.
(double_int_divmod): Remove.
(double_int_sdivmod): Remove.
(double_int_udivmod): Remove.
(double_int_multiple_of): Remove.
(double_int_setbit): Remove.
(double_int_ctz): Remove.
(double_int_not): Remove.
(double_int_ior): Remove.
(double_int_and): Remove.
(double_int_and_not): Remove.
(double_int_xor): Remove.
(double_int_lshift): Remove.
(double_int_rshift): Remove.
(double_int_lrotate): Remove.
(double_int_rrotate): Remove.
(double_int_negative_p): Remove.
(double_int_cmp): Remove.
(double_int_scmp): Remove.
(double_int_ucmp): Remove.
(double_int_max): Remove.
(double_int_smax): Remove.
(double_int_umax): Remove.
(double_int_min): Remove.
(double_int_smin): Remove.
(double_int_umin): Remove.
(double_int_ext): Remove.
(double_int_sext): Remove.
(double_int_zext): Remove.
(double_int_mask): Remove.
(double_int_max_value): Remove.
(double_int_min_value): Remove.
(double_int_zero_p): Remove.
(double_int_one_p): Remove.
(double_int_minus_one_p): Remove.
(double_int_equal_p): Remove.
(double_int_popcount): Remove.
(extern add_double_with_sign): Remove.
(#define add_double): Remove.
(extern neg_double): Remove.
(extern mul_double_with_sign): Remove.
(extern mul_double_wide_with_sign): Remove.
(#define mul_double): Remove.
(extern lshift_double): Remove.
(extern div_and_round_double): Remove.
* double-int.c (add_double_with_sign): Make static.
(#defined add_double): Localized from header.
(neg_double): Make static.
(mul_double_with_sign): Make static.
(mul_double_wide_with_sign): Make static.
(#defined mul_double): Localized from header.
(lshift_double): Make static.
(div_and_round_double): Make static.
(double_int::wide_mul_with_sign): New.
(double_int::sub_with_overflow): New.
(double_int::neg_with_overflow): New.
(double_int::divmod_with_overflow): New.
* emit-rtl.c (init_emit_once): Change to new double_int API.
* explow.c (plus_constant): Likewise.
* expmed.c (choose_multiplier): Likewise.
* fold-const.c (#define OVERFLOW_SUM_SIGN): Remove.
(int_const_binop_1): Change to new double_int API.
(fold_div_compare): Likewise.
(maybe_canonicalize_comparison): Likewise.
(pointer_may_wrap_p): Likewise.
(fold_negate_const): Likewise.
(fold_abs_const): Likewise.
* simplify-rtx.c (simplify_const_unary_operation): Likewise.
(simplify_const_binary_operation): Likewise.
* tree-chrec.c (tree_fold_binomial): Likewise.
* tree-vrp.c (extract_range_from_binary_expr_1): Likewise.
* config/sparc/sparc.c (sparc_fold_builtin): Likewise.
* config/avr/avr.c (avr_double_int_push_digit): Likewise.
(avr_map): Likewise.
(avr_map_decompose): Likewise.
(avr_out_insert_bits): Likewise.
Index: gcc/cp/ChangeLog
2012-09-24 Lawrence Crowl <crowl@google.com>
* init.c (build_new_1): Change to new double_int API.
* decl.c (build_enumerator): Likewise.
* typeck2.c (process_init_constructor_array): Likewise.
* mangle.c (write_array_type): Likewise.
Index: gcc/fortran/ChangeLog
2012-09-24 Lawrence Crowl <crowl@google.com>
* trans-expr.c (gfc_conv_cst_int_power): Change to new double_int API.
* target-memory.c (gfc_interpret_logical): Likewise.
From-SVN: r191675
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 152 |
1 files changed, 78 insertions, 74 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 9ed98e6..97a9330 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1525,109 +1525,117 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, else if (width <= HOST_BITS_PER_DOUBLE_INT && (CONST_DOUBLE_AS_INT_P (op) || CONST_INT_P (op))) { - unsigned HOST_WIDE_INT l1, lv; - HOST_WIDE_INT h1, hv; + double_int first, value; if (CONST_DOUBLE_AS_INT_P (op)) - l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op); + first = double_int::from_pair (CONST_DOUBLE_HIGH (op), + CONST_DOUBLE_LOW (op)); else - l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1); + first = double_int::from_shwi (INTVAL (op)); switch (code) { case NOT: - lv = ~ l1; - hv = ~ h1; + value = ~first; break; case NEG: - neg_double (l1, h1, &lv, &hv); + value = -first; break; case ABS: - if (h1 < 0) - neg_double (l1, h1, &lv, &hv); + if (first.is_negative ()) + value = -first; else - lv = l1, hv = h1; + value = first; break; case FFS: - hv = 0; - if (l1 != 0) - lv = ffs_hwi (l1); - else if (h1 != 0) - lv = HOST_BITS_PER_WIDE_INT + ffs_hwi (h1); + value.high = 0; + if (first.low != 0) + value.low = ffs_hwi (first.low); + else if (first.high != 0) + value.low = HOST_BITS_PER_WIDE_INT + ffs_hwi (first.high); else - lv = 0; + value.low = 0; break; case CLZ: - hv = 0; - if (h1 != 0) - lv = GET_MODE_PRECISION (mode) - floor_log2 (h1) - 1 - - HOST_BITS_PER_WIDE_INT; - else if (l1 != 0) - lv = GET_MODE_PRECISION (mode) - floor_log2 (l1) - 1; - else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv)) - lv = GET_MODE_PRECISION (mode); + value.high = 0; + if (first.high != 0) + value.low = GET_MODE_PRECISION (mode) - floor_log2 (first.high) - 1 + - HOST_BITS_PER_WIDE_INT; + else if (first.low != 0) + value.low = GET_MODE_PRECISION (mode) - floor_log2 (first.low) - 1; + else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, value.low)) + value.low = GET_MODE_PRECISION (mode); break; case CTZ: - hv = 0; - if (l1 != 0) - lv = ctz_hwi (l1); - else if (h1 != 0) - lv = HOST_BITS_PER_WIDE_INT + ctz_hwi (h1); - else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv)) - lv = GET_MODE_PRECISION (mode); + value.high = 0; + if (first.low != 0) + value.low = ctz_hwi (first.low); + else if (first.high != 0) + value.low = HOST_BITS_PER_WIDE_INT + ctz_hwi (first.high); + else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, value.low)) + value.low = GET_MODE_PRECISION (mode); break; case POPCOUNT: - hv = 0; - lv = 0; - while (l1) - lv++, l1 &= l1 - 1; - while (h1) - lv++, h1 &= h1 - 1; + value = double_int_zero; + while (first.low) + { + value.low++; + first.low &= first.low - 1; + } + while (first.high) + { + value.low++; + first.high &= first.high - 1; + } break; case PARITY: - hv = 0; - lv = 0; - while (l1) - lv++, l1 &= l1 - 1; - while (h1) - lv++, h1 &= h1 - 1; - lv &= 1; + value = double_int_zero; + while (first.low) + { + value.low++; + first.low &= first.low - 1; + } + while (first.high) + { + value.low++; + first.high &= first.high - 1; + } + value.low &= 1; break; case BSWAP: { unsigned int s; - hv = 0; - lv = 0; + value = double_int_zero; for (s = 0; s < width; s += 8) { unsigned int d = width - s - 8; unsigned HOST_WIDE_INT byte; if (s < HOST_BITS_PER_WIDE_INT) - byte = (l1 >> s) & 0xff; + byte = (first.low >> s) & 0xff; else - byte = (h1 >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff; + byte = (first.high >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff; if (d < HOST_BITS_PER_WIDE_INT) - lv |= byte << d; + value.low |= byte << d; else - hv |= byte << (d - HOST_BITS_PER_WIDE_INT); + value.high |= byte << (d - HOST_BITS_PER_WIDE_INT); } } break; case TRUNCATE: /* This is just a change-of-mode, so do nothing. */ - lv = l1, hv = h1; + value = first; break; case ZERO_EXTEND: @@ -1636,8 +1644,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, if (op_width > HOST_BITS_PER_WIDE_INT) return 0; - hv = 0; - lv = l1 & GET_MODE_MASK (op_mode); + value = double_int::from_uhwi (first.low & GET_MODE_MASK (op_mode)); break; case SIGN_EXTEND: @@ -1646,11 +1653,11 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, return 0; else { - lv = l1 & GET_MODE_MASK (op_mode); - if (val_signbit_known_set_p (op_mode, lv)) - lv |= ~GET_MODE_MASK (op_mode); + value.low = first.low & GET_MODE_MASK (op_mode); + if (val_signbit_known_set_p (op_mode, value.low)) + value.low |= ~GET_MODE_MASK (op_mode); - hv = HWI_SIGN_EXTEND (lv); + value.high = HWI_SIGN_EXTEND (value.low); } break; @@ -1661,7 +1668,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, return 0; } - return immed_double_const (lv, hv, mode); + return immed_double_int_const (value, mode); } else if (CONST_DOUBLE_AS_FLOAT_P (op) @@ -3578,6 +3585,7 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode, && (CONST_DOUBLE_AS_INT_P (op1) || CONST_INT_P (op1))) { double_int o0, o1, res, tmp; + bool overflow; o0 = rtx_to_double_int (op0); o1 = rtx_to_double_int (op1); @@ -3599,34 +3607,30 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode, break; case DIV: - if (div_and_round_double (TRUNC_DIV_EXPR, 0, - o0.low, o0.high, o1.low, o1.high, - &res.low, &res.high, - &tmp.low, &tmp.high)) + res = o0.divmod_with_overflow (o1, false, TRUNC_DIV_EXPR, + &tmp, &overflow); + if (overflow) return 0; break; case MOD: - if (div_and_round_double (TRUNC_DIV_EXPR, 0, - o0.low, o0.high, o1.low, o1.high, - &tmp.low, &tmp.high, - &res.low, &res.high)) + tmp = o0.divmod_with_overflow (o1, false, TRUNC_DIV_EXPR, + &res, &overflow); + if (overflow) return 0; break; case UDIV: - if (div_and_round_double (TRUNC_DIV_EXPR, 1, - o0.low, o0.high, o1.low, o1.high, - &res.low, &res.high, - &tmp.low, &tmp.high)) + res = o0.divmod_with_overflow (o1, true, TRUNC_DIV_EXPR, + &tmp, &overflow); + if (overflow) return 0; break; case UMOD: - if (div_and_round_double (TRUNC_DIV_EXPR, 1, - o0.low, o0.high, o1.low, o1.high, - &tmp.low, &tmp.high, - &res.low, &res.high)) + tmp = o0.divmod_with_overflow (o1, true, TRUNC_DIV_EXPR, + &res, &overflow); + if (overflow) return 0; break; |