aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/convert.c22
-rw-r--r--gcc/dwarf2out.c5
-rw-r--r--gcc/emit-rtl.c20
-rw-r--r--gcc/expmed.c5
-rw-r--r--gcc/expr.c11
-rw-r--r--gcc/genopinit.c4
-rw-r--r--gcc/optabs.c25
-rw-r--r--gcc/simplify-rtx.c7
-rw-r--r--gcc/stor-layout.c1
-rw-r--r--gcc/varasm.c1
11 files changed, 114 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bf05ff9..9846816 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+2005-12-17 Jon Grimm <jgrimm2@us.ibm.com>
+ Janis Johnson <janis187@us.ibm.com>
+ Ben Elliston <bje@au.ibm.com>
+
+ * 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 <uweigand@de.ibm.com>
PR rtl-optimization/21041
diff --git a/gcc/convert.c b/gcc/convert.c
index 49d4a3a..e8030bf 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 f5860f2..96c6556 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 d172587..8286510 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 28f876b..2390940 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 df86a57..322db4f 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 0c4a397..ec8076b 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 45bfbbd..d79cf66 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 3c5da5e..c773900 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 b4e9ad1..7db3567 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 82c2df3..3a2fe22 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;