diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bf05ff94461..98468169d1c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2005-12-17 Jon Grimm + Janis Johnson + Ben Elliston + + * optabs.c (init_floating_libfuncs): Handle decimal float modes. + (init_optabs): Handle libfuncs for decimal float. + * genopinit.c (gen_insn): Handle MODE_DECIMAL_FLOAT. + * stor-layout.c (int_mode_for_mode): Likewise. + * simplify-rtx.c (simplify_immed_subreg): Likewise. + (simplify_unary_operation_1): Skip optimisations for decimal float + modes. + * varasm.c (output_constant_pool_2): Handle MODE_DECIMAL_FLOAT. + * emit-rtl.c (gen_const_vector): Add assertion check. + (init_emit_once): Populate const_tiny_rtx with constants in each + decimal float mode. + * expmed.c (extract_high_half, expand_mult_highpart_optab, + expand_mult_highpart): Assert that mode is not a scalar float + mode. + * expr.c (convert_move): Handle conversion between decimal and + binary floats of the same size. + * convert.c (convert_to_real): Consider decimal float types when + folding. + * dwarf2out.c (base_type_die): Use DW_ATE_decimal_float to + describe decimal floating point types. + 2005-12-18 Ulrich Weigand PR rtl-optimization/21041 diff --git a/gcc/convert.c b/gcc/convert.c index 49d4a3ac5d6..e8030bf9f01 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -263,6 +263,28 @@ convert_to_real (tree type, tree expr) && FLOAT_TYPE_P (TREE_TYPE (arg1))) { tree newtype = type; + + if (TYPE_MODE (TREE_TYPE (arg0)) == SDmode + || TYPE_MODE (TREE_TYPE (arg1)) == SDmode) + newtype = dfloat32_type_node; + if (TYPE_MODE (TREE_TYPE (arg0)) == DDmode + || TYPE_MODE (TREE_TYPE (arg1)) == DDmode) + newtype = dfloat64_type_node; + if (TYPE_MODE (TREE_TYPE (arg0)) == TDmode + || TYPE_MODE (TREE_TYPE (arg1)) == TDmode) + newtype = dfloat128_type_node; + if (newtype == dfloat32_type_node + || newtype == dfloat64_type_node + || newtype == dfloat128_type_node) + { + expr = build2 (TREE_CODE (expr), newtype, + fold (convert_to_real (newtype, arg0)), + fold (convert_to_real (newtype, arg1))); + if (newtype == type) + return expr; + break; + } + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (newtype)) newtype = TREE_TYPE (arg0); if (TYPE_PRECISION (TREE_TYPE (arg1)) > TYPE_PRECISION (newtype)) diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f5860f213ec..96c655637bd 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -8124,7 +8124,10 @@ base_type_die (tree type) break; case REAL_TYPE: - encoding = DW_ATE_float; + if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))) + encoding = DW_ATE_decimal_float; + else + encoding = DW_ATE_float; break; /* Dwarf2 doesn't know anything about complex ints, so use diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index d17258795fb..828651041a0 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -5151,6 +5151,8 @@ gen_const_vector (enum machine_mode mode, int constant) units = GET_MODE_NUNITS (mode); inner = GET_MODE_INNER (mode); + gcc_assert (!DECIMAL_FLOAT_MODE_P (inner)); + v = rtvec_alloc (units); /* We need to call this function after we set the scalar const_tiny_rtx @@ -5227,7 +5229,8 @@ init_emit_once (int line_numbers) word_mode = VOIDmode; double_mode = VOIDmode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) { if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT @@ -5239,7 +5242,8 @@ init_emit_once (int line_numbers) word_mode = mode; } - for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) { if (GET_MODE_BITSIZE (mode) == DOUBLE_TYPE_SIZE @@ -5324,14 +5328,22 @@ init_emit_once (int line_numbers) REAL_VALUE_TYPE *r = (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2); - for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + const_tiny_rtx[i][(int) mode] = + CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_DECIMAL_FLOAT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) const_tiny_rtx[i][(int) mode] = CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i); - for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) const_tiny_rtx[i][(int) mode] = GEN_INT (i); diff --git a/gcc/expmed.c b/gcc/expmed.c index 28f876ba22b..23909404005 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -3383,6 +3383,8 @@ extract_high_half (enum machine_mode mode, rtx op) if (mode == word_mode) return gen_highpart (mode, op); + gcc_assert (!SCALAR_FLOAT_MODE_P (mode)); + wider_mode = GET_MODE_WIDER_MODE (mode); op = expand_shift (RSHIFT_EXPR, wider_mode, op, build_int_cst (NULL_TREE, GET_MODE_BITSIZE (mode)), 0, 1); @@ -3402,6 +3404,8 @@ expand_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1, rtx tem; int size; + gcc_assert (!SCALAR_FLOAT_MODE_P (mode)); + wider_mode = GET_MODE_WIDER_MODE (mode); size = GET_MODE_BITSIZE (mode); @@ -3512,6 +3516,7 @@ expand_mult_highpart (enum machine_mode mode, rtx op0, rtx op1, struct algorithm alg; rtx tem; + gcc_assert (!SCALAR_FLOAT_MODE_P (mode)); /* We can't support modes wider than HOST_BITS_PER_INT. */ gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT); diff --git a/gcc/expr.c b/gcc/expr.c index df86a57ee18..322db4ff273 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -410,10 +410,15 @@ convert_move (rtx to, rtx from, int unsignedp) rtx value, insns; convert_optab tab; - gcc_assert (GET_MODE_PRECISION (from_mode) - != GET_MODE_PRECISION (to_mode)); + gcc_assert ((GET_MODE_PRECISION (from_mode) + != GET_MODE_PRECISION (to_mode)) + || (DECIMAL_FLOAT_MODE_P (from_mode) + != DECIMAL_FLOAT_MODE_P (to_mode))); - if (GET_MODE_PRECISION (from_mode) < GET_MODE_PRECISION (to_mode)) + if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode)) + /* Conversion between decimal float and binary float, same size. */ + tab = DECIMAL_FLOAT_MODE_P (from_mode) ? trunc_optab : sext_optab; + else if (GET_MODE_PRECISION (from_mode) < GET_MODE_PRECISION (to_mode)) tab = sext_optab; else tab = trunc_optab; diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 0c4a397667e..ec8076b8206 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -304,7 +304,9 @@ gen_insn (rtx insn) || mode_class[i] == MODE_INT || mode_class[i] == MODE_PARTIAL_INT || mode_class[i] == MODE_VECTOR_INT) - && (! force_float || mode_class[i] == MODE_FLOAT + && (! force_float + || mode_class[i] == MODE_FLOAT + || mode_class[i] == MODE_DECIMAL_FLOAT || mode_class[i] == MODE_COMPLEX_FLOAT || mode_class[i] == MODE_VECTOR_FLOAT)) break; diff --git a/gcc/optabs.c b/gcc/optabs.c index 45bfbbde482..d79cf668c60 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4375,9 +4375,10 @@ expand_float (rtx to, rtx from, int unsignedp) } } - /* Unsigned integer, and no way to convert directly. - Convert as signed, then conditionally adjust the result. */ - if (unsignedp && can_do_signed) + /* Unsigned integer, and no way to convert directly. For binary + floating point modes, convert as signed, then conditionally adjust + the result. */ + if (unsignedp && can_do_signed && !DECIMAL_FLOAT_MODE_P (GET_MODE (to))) { rtx label = gen_label_rtx (); rtx temp; @@ -4837,6 +4838,8 @@ static void init_floating_libfuncs (optab optable, const char *opname, int suffix) { init_libfuncs (optable, MIN_MODE_FLOAT, MAX_MODE_FLOAT, opname, suffix); + init_libfuncs (optable, MIN_MODE_DECIMAL_FLOAT, MAX_MODE_DECIMAL_FLOAT, + opname, suffix); } /* Initialize the libfunc fields of an entire group of entries of an @@ -5254,16 +5257,32 @@ init_optabs (void) /* Conversions. */ init_interclass_conv_libfuncs (sfloat_optab, "float", MODE_INT, MODE_FLOAT); + init_interclass_conv_libfuncs (sfloat_optab, "float", + MODE_INT, MODE_DECIMAL_FLOAT); init_interclass_conv_libfuncs (ufloat_optab, "floatun", MODE_INT, MODE_FLOAT); + init_interclass_conv_libfuncs (ufloat_optab, "floatun", + MODE_INT, MODE_DECIMAL_FLOAT); init_interclass_conv_libfuncs (sfix_optab, "fix", MODE_FLOAT, MODE_INT); + init_interclass_conv_libfuncs (sfix_optab, "fix", + MODE_DECIMAL_FLOAT, MODE_INT); init_interclass_conv_libfuncs (ufix_optab, "fixuns", MODE_FLOAT, MODE_INT); + init_interclass_conv_libfuncs (ufix_optab, "fixuns", + MODE_DECIMAL_FLOAT, MODE_INT); + init_interclass_conv_libfuncs (ufloat_optab, "floatuns", + MODE_INT, MODE_DECIMAL_FLOAT); /* sext_optab is also used for FLOAT_EXTEND. */ init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true); + init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_DECIMAL_FLOAT, true); + init_interclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, MODE_DECIMAL_FLOAT); + init_interclass_conv_libfuncs (sext_optab, "extend", MODE_DECIMAL_FLOAT, MODE_FLOAT); init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false); + init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_DECIMAL_FLOAT, false); + init_interclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, MODE_DECIMAL_FLOAT); + init_interclass_conv_libfuncs (trunc_optab, "trunc", MODE_DECIMAL_FLOAT, MODE_FLOAT); /* Use cabs for double complex abs, since systems generally have cabs. Don't define any libcall for float complex, so that cabs will be used. */ diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 3c5da5e9aeb..c773900c405 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -640,6 +640,9 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) break; case FLOAT_TRUNCATE: + if (DECIMAL_FLOAT_MODE_P (mode)) + break; + /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF. */ if (GET_CODE (op) == FLOAT_EXTEND && GET_MODE (XEXP (op, 0)) == mode) @@ -693,6 +696,9 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) break; case FLOAT_EXTEND: + if (DECIMAL_FLOAT_MODE_P (mode)) + break; + /* (float_extend (float_extend x)) is (float_extend x) (float_extend (float x)) is (float x) assuming that double @@ -4284,6 +4290,7 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op, break; case MODE_FLOAT: + case MODE_DECIMAL_FLOAT: { REAL_VALUE_TYPE r; long tmp[max_bitsize / 32]; diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index b4e9ad1072f..7db35673d57 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -232,6 +232,7 @@ int_mode_for_mode (enum machine_mode mode) case MODE_COMPLEX_INT: case MODE_COMPLEX_FLOAT: case MODE_FLOAT: + case MODE_DECIMAL_FLOAT: case MODE_VECTOR_INT: case MODE_VECTOR_FLOAT: mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0); diff --git a/gcc/varasm.c b/gcc/varasm.c index 82c2df32c14..3a2fe22b116 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -3077,6 +3077,7 @@ output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align) switch (GET_MODE_CLASS (mode)) { case MODE_FLOAT: + case MODE_DECIMAL_FLOAT: { REAL_VALUE_TYPE r;