diff options
author | janis <janis@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-09-07 16:42:48 +0000 |
---|---|---|
committer | janis <janis@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-09-07 16:42:48 +0000 |
commit | 4e6322c5d9bd7cfc57385d871d958414cf4f042b (patch) | |
tree | e011b37bc7813088d4d4ff9521e41fe27d9e73ac /gcc | |
parent | 47aaf6e6cb103ab06e8fd6bb7d326d41d16eefa1 (diff) | |
download | gcc-4e6322c5d9bd7cfc57385d871d958414cf4f042b.tar.gz |
gcc/ada/
Reapply reverted change:
2007-09-06 Eric Botcazou <ebotcazou@adacore.com>
* trans.c (convert_with_check): Update call to real_2expN.
gcc/
config/m68k/m68k.c (floating_exact_log2): Update call to real_2expN.
config/s390/s390.md (fixuns_trunc<BFP:mode><GPR:mode>2): Ditto.
Reapply reverted changes:
2007-09-06 Jan Hubicka <jh@suse.cz>
* config/i386.c (ix86_expand_lround, ix86_expand_round): Update call of
real_2expN.
2007-09-06 Richard Sandiford <richard@codesourcery.com>
* config/mips/mips.md (fixuns_truncdfsi2, fixuns_truncdfdi2)
(fixuns_truncsfsi2, fixuns_truncsfdi2): Update calls to real_2expN.
2007-09-05 Janis Johnson <janis187@us.ibm.com>
* optabs.c (expand_float): Convert unsigned integer as signed only
if it provides sufficient accuracy; add mode argument to real_2expN.
(expand_fix): Fix comment typos; extend binary float into mode
wider than destination for converion to unsigned integer; add mode
argument to real_2expN.
* real.c (real_2expN): Add mode argument to special-case decimal
float values.
* real.h (real_2expN): Ditto.
* fixed-value.c (check_real_for_fixed_mode): Add mode argument to
real_2expN.
(fixed_from_string): Ditto.
(fixed_to_decimal): Ditto.
(fixed_convert_from_real): Ditto.
(real_convert_from_fixed): Ditto.
* config/rs6000/rs6000.md (FP): Include DD and TD modes.
* config/rs6000/dfp.md (extendddtd2, adddd3, addtd3, subdd3, subtd3,
muldd3, multd3, divdd3, divtd3, cmpdd_internal1, cmptd_internal1,
floatditd2, ftruncdd2, fixdddi2, ftrunctd2, fixddi2): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128247 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 38 | ||||
-rw-r--r-- | gcc/ada/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/ada/trans.c | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 4 | ||||
-rw-r--r-- | gcc/config/m68k/m68k.c | 2 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/dfp.md | 148 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 4 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 4 | ||||
-rw-r--r-- | gcc/fixed-value.c | 12 | ||||
-rw-r--r-- | gcc/optabs.c | 24 | ||||
-rw-r--r-- | gcc/real.c | 4 | ||||
-rw-r--r-- | gcc/real.h | 2 |
13 files changed, 231 insertions, 29 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a76df2a2665..04922ebca13 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2007-09-07 Janis Johnson <janis187@us.ibm.com> + + config/m68k/m68k.c (floating_exact_log2): Update call to real_2expN. + config/s390/s390.md (fixuns_trunc<BFP:mode><GPR:mode>2): Ditto. + + Reapply reverted changes: + + 2007-09-06 Jan Hubicka <jh@suse.cz> + + * config/i386.c (ix86_expand_lround, ix86_expand_round): Update call of + real_2expN. + + 2007-09-06 Richard Sandiford <richard@codesourcery.com> + + * config/mips/mips.md (fixuns_truncdfsi2, fixuns_truncdfdi2) + (fixuns_truncsfsi2, fixuns_truncsfdi2): Update calls to real_2expN. + + 2007-09-05 Janis Johnson <janis187@us.ibm.com> + + * optabs.c (expand_float): Convert unsigned integer as signed only + if it provides sufficient accuracy; add mode argument to real_2expN. + (expand_fix): Fix comment typos; extend binary float into mode + wider than destination for converion to unsigned integer; add mode + argument to real_2expN. + * real.c (real_2expN): Add mode argument to special-case decimal + float values. + * real.h (real_2expN): Ditto. + * fixed-value.c (check_real_for_fixed_mode): Add mode argument to + real_2expN. + (fixed_from_string): Ditto. + (fixed_to_decimal): Ditto. + (fixed_convert_from_real): Ditto. + (real_convert_from_fixed): Ditto. + * config/rs6000/rs6000.md (FP): Include DD and TD modes. + * config/rs6000/dfp.md (extendddtd2, adddd3, addtd3, subdd3, subtd3, + muldd3, multd3, divdd3, divtd3, cmpdd_internal1, cmptd_internal1, + floatditd2, ftruncdd2, fixdddi2, ftrunctd2, fixddi2): New. + 2007-09-07 Diego Novillo <dnovillo@google.com> * tree-flow.h (const_block_stmt_iterator): Remove. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7ec2c1d2cdd..8de9c577d15 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2007-09-07 Janis Johnson <janis187@us.ibm.com> + + Reapply reverted change: + + 2007-09-06 Eric Botcazou <ebotcazou@adacore.com> + + * trans.c (convert_with_check): Update call to real_2expN. + 2007-09-06 Janis Johnson <janis187@us.ibm.com> Revert: diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index 4d79cb3f9b6..24797753fd8 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -5893,7 +5893,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, /* Compute the exact value calc_type'Pred (0.5) at compile time. */ fmt = REAL_MODE_FORMAT (TYPE_MODE (calc_type)); - real_2expN (&half_minus_pred_half, -(fmt->p) - 1); + real_2expN (&half_minus_pred_half, -(fmt->p) - 1, TYPE_MODE (calc_type)); REAL_ARITHMETIC (pred_half, MINUS_EXPR, dconsthalf, half_minus_pred_half); gnu_pred_half = build_real (calc_type, pred_half); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index dba72dfa737..f6f80a05969 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -23144,7 +23144,7 @@ ix86_expand_lround (rtx op0, rtx op1) /* load nextafter (0.5, 0.0) */ fmt = REAL_MODE_FORMAT (mode); - real_2expN (&half_minus_pred_half, -(fmt->p) - 1); + real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode); REAL_ARITHMETIC (pred_half, MINUS_EXPR, dconsthalf, half_minus_pred_half); /* adj = copysign (0.5, op1) */ @@ -23555,7 +23555,7 @@ ix86_expand_round (rtx operand0, rtx operand1) /* load nextafter (0.5, 0.0) */ fmt = REAL_MODE_FORMAT (mode); - real_2expN (&half_minus_pred_half, -(fmt->p) - 1); + real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode); REAL_ARITHMETIC (pred_half, MINUS_EXPR, dconsthalf, half_minus_pred_half); /* xa = xa + 0.5 */ diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 76d765e7252..cd7f493815c 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -3571,7 +3571,7 @@ floating_exact_log2 (rtx x) return 0; exp = real_exponent (&r); - real_2expN (&r1, exp); + real_2expN (&r1, exp, DFmode); if (REAL_VALUES_EQUAL (r1, r)) return exp; diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 2006f920600..76dde25fc9c 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -2805,7 +2805,7 @@ rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset; - real_2expN (&offset, 31); + real_2expN (&offset, 31, DFmode); if (reg1) /* Turn off complaints about unreached code. */ { @@ -2850,7 +2850,7 @@ rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset; - real_2expN (&offset, 63); + real_2expN (&offset, 63, DFmode); mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); @@ -2892,7 +2892,7 @@ rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset; - real_2expN (&offset, 31); + real_2expN (&offset, 31, SFmode); mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); @@ -2934,7 +2934,7 @@ rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset; - real_2expN (&offset, 63); + real_2expN (&offset, 63, SFmode); mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md index 0bc405a3f54..fa20f7d0652 100644 --- a/gcc/config/rs6000/dfp.md +++ b/gcc/config/rs6000/dfp.md @@ -405,3 +405,151 @@ { rs6000_split_multireg_move (operands[0], operands[1]); DONE; } [(set_attr "length" "8,8,8,20,20,16")]) +;; Hardware support for decimal floating point operations. + +(define_insn "extendddtd2" + [(set (match_operand:TD 0 "gpc_reg_operand" "=f") + (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dctqpq %0,%1" + [(set_attr "type" "fp")]) + +;; The result of drdpq is an even/odd register pair with the converted +;; value in the even register and zero in the odd register. +;; FIXME: Avoid the register move by using a reload constraint to ensure +;; that the result is the first of the pair receiving the result of drdpq. + +(define_insn "trunctddd2" + [(set (match_operand:DD 0 "gpc_reg_operand" "=f") + (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "f"))) + (clobber (match_scratch:TD 2 "=f"))] + "TARGET_DFP" + "drdpq %2,%1\;fmr %0,%2" + [(set_attr "type" "fp")]) + +(define_insn "adddd3" + [(set (match_operand:DD 0 "gpc_reg_operand" "=f") + (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%f") + (match_operand:DD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dadd %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "addtd3" + [(set (match_operand:TD 0 "gpc_reg_operand" "=f") + (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%f") + (match_operand:TD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "daddq %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "subdd3" + [(set (match_operand:DD 0 "gpc_reg_operand" "=f") + (minus:DD (match_operand:DD 1 "gpc_reg_operand" "f") + (match_operand:DD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dsub %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "subtd3" + [(set (match_operand:TD 0 "gpc_reg_operand" "=f") + (minus:TD (match_operand:TD 1 "gpc_reg_operand" "f") + (match_operand:TD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dsubq %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "muldd3" + [(set (match_operand:DD 0 "gpc_reg_operand" "=f") + (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%f") + (match_operand:DD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dmul %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "multd3" + [(set (match_operand:TD 0 "gpc_reg_operand" "=f") + (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%f") + (match_operand:TD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dmulq %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "divdd3" + [(set (match_operand:DD 0 "gpc_reg_operand" "=f") + (div:DD (match_operand:DD 1 "gpc_reg_operand" "f") + (match_operand:DD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "ddiv %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "divtd3" + [(set (match_operand:TD 0 "gpc_reg_operand" "=f") + (div:TD (match_operand:TD 1 "gpc_reg_operand" "f") + (match_operand:TD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "ddivq %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "*cmpdd_internal1" + [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") + (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "f") + (match_operand:DD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dcmpu %0,%1,%2" + [(set_attr "type" "fpcompare")]) + +(define_insn "*cmptd_internal1" + [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") + (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "f") + (match_operand:TD 2 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dcmpuq %0,%1,%2" + [(set_attr "type" "fpcompare")]) + +(define_insn "floatditd2" + [(set (match_operand:TD 0 "gpc_reg_operand" "=f") + (float:TD (match_operand:DI 1 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dcffixq %0,%1" + [(set_attr "type" "fp")]) + +;; Convert a decimal64 to a decimal64 whose value is an integer. +;; This is the first stage of converting it to an integer type. + +(define_insn "ftruncdd2" + [(set (match_operand:DD 0 "gpc_reg_operand" "=f") + (fix:DD (match_operand:DD 1 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "drintn. 0,%0,%1,1" + [(set_attr "type" "fp")]) + +;; Convert a decimal64 whose value is an integer to an actual integer. +;; This is the second stage of converting decimal float to integer type. + +(define_insn "fixdddi2" + [(set (match_operand:DI 0 "gpc_reg_operand" "=f") + (fix:DI (match_operand:DD 1 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dctfix %0,%1" + [(set_attr "type" "fp")]) + +;; Convert a decimal128 to a decimal128 whose value is an integer. +;; This is the first stage of converting it to an integer type. + +(define_insn "ftrunctd2" + [(set (match_operand:TD 0 "gpc_reg_operand" "=f") + (fix:TD (match_operand:TD 1 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "drintnq. 0,%0,%1,1" + [(set_attr "type" "fp")]) + +;; Convert a decimal128 whose value is an integer to an actual integer. +;; This is the second stage of converting decimal float to integer type. + +(define_insn "fixtddi2" + [(set (match_operand:DI 0 "gpc_reg_operand" "=f") + (fix:DI (match_operand:TD 1 "gpc_reg_operand" "f")))] + "TARGET_DFP" + "dctfixq %0,%1" + [(set_attr "type" "fp")]) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index e3505d1e5ae..debacdc74b4 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -204,7 +204,9 @@ (TF "!TARGET_IEEEQUAD && TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) - && TARGET_LONG_DOUBLE_128")]) + && TARGET_LONG_DOUBLE_128") + (DD "TARGET_DFP") + (TD "TARGET_DFP")]) ; Various instructions that come in SI and DI forms. ; A generic w/d attribute, for things like cmpw/cmpd. diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 66cf5612da6..b1350336e18 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3295,8 +3295,8 @@ REAL_VALUE_TYPE cmp, sub; operands[1] = force_reg (<BFP:MODE>mode, operands[1]); - real_2expN (&cmp, GET_MODE_BITSIZE(<GPR:MODE>mode) - 1); - real_2expN (&sub, GET_MODE_BITSIZE(<GPR:MODE>mode)); + real_2expN (&cmp, GET_MODE_BITSIZE(<GPR:MODE>mode) - 1, <BFP:mode>mode); + real_2expN (&sub, GET_MODE_BITSIZE(<GPR:MODE>mode), <BFP:mode>mode); emit_insn (gen_cmp<BFP:mode> (operands[1], CONST_DOUBLE_FROM_REAL_VALUE (cmp, <BFP:MODE>mode))); diff --git a/gcc/fixed-value.c b/gcc/fixed-value.c index aca386a6d9c..8c8d3719044 100644 --- a/gcc/fixed-value.c +++ b/gcc/fixed-value.c @@ -64,8 +64,8 @@ check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, enum machine_mode mode) { REAL_VALUE_TYPE max_value, min_value, epsilon_value; - real_2expN (&max_value, GET_MODE_IBIT (mode)); - real_2expN (&epsilon_value, -GET_MODE_FBIT (mode)); + real_2expN (&max_value, GET_MODE_IBIT (mode), mode); + real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), mode); if (SIGNED_FIXED_POINT_MODE_P (mode)) min_value = REAL_VALUE_NEGATE (max_value); @@ -102,7 +102,7 @@ fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode) || (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode))) warning (OPT_Woverflow, "large fixed-point constant implicitly truncated to fixed-point type"); - real_2expN (&base_value, fbit); + real_2expN (&base_value, fbit, mode); real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value); real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, &fixed_value); @@ -132,7 +132,7 @@ fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig, { REAL_VALUE_TYPE real_value, base_value, fixed_value; - real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode)); + real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode); real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high, UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode)); real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value); @@ -1067,7 +1067,7 @@ fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode, real_value = *a; f->mode = mode; - real_2expN (&base_value, fbit); + real_2expN (&base_value, fbit, mode); real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value); real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, &fixed_value); temp = check_real_for_fixed_mode (&real_value, mode); @@ -1116,7 +1116,7 @@ real_convert_from_fixed (REAL_VALUE_TYPE *r, enum machine_mode mode, { REAL_VALUE_TYPE base_value, fixed_value, real_value; - real_2expN (&base_value, GET_MODE_FBIT (f->mode)); + real_2expN (&base_value, GET_MODE_FBIT (f->mode), f->mode); real_from_integer (&fixed_value, VOIDmode, f->data.low, f->data.high, UNSIGNED_FIXED_POINT_MODE_P (f->mode)); real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value); diff --git a/gcc/optabs.c b/gcc/optabs.c index b1b32efb441..32b195c2a5c 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5135,10 +5135,11 @@ expand_float (rtx to, rtx from, int unsignedp) } } - /* 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))) + /* Unsigned integer, and no way to convert directly. Convert as signed, + then unconditionally adjust the result. For decimal float values we + do this only if we have already determined that a signed conversion + provides sufficient accuracy. */ + if (unsignedp && (can_do_signed || !DECIMAL_FLOAT_MODE_P (GET_MODE (to)))) { rtx label = gen_label_rtx (); rtx temp; @@ -5229,7 +5230,7 @@ expand_float (rtx to, rtx from, int unsignedp) 0, label); - real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from))); + real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)), fmode); temp = expand_binop (fmode, add_optab, target, CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode), target, 0, OPTAB_LIB_WIDEN); @@ -5340,14 +5341,16 @@ expand_fix (rtx to, rtx from, int unsignedp) anything with a wider integer mode. This code used to extend FP value into mode wider than the destination. - This is not needed. Consider, for instance conversion from SFmode + This is needed for decimal float modes which cannot accurately + represent one plus the highest signed number of the same size, but + not for binary modes. Consider, for instance conversion from SFmode into DImode. The hot path through the code is dealing with inputs smaller than 2^63 and doing just the conversion, so there is no bits to lose. In the other path we know the value is positive in the range 2^63..2^64-1 - inclusive. (as for other imput overflow happens and result is undefined) + inclusive. (as for other input overflow happens and result is undefined) So we know that the most important bit set in mantissa corresponds to 2^63. The subtraction of 2^63 should not generate any rounding as it simply clears out that bit. The rest is trivial. */ @@ -5355,15 +5358,16 @@ expand_fix (rtx to, rtx from, int unsignedp) if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT) for (fmode = GET_MODE (from); fmode != VOIDmode; fmode = GET_MODE_WIDER_MODE (fmode)) - if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, - &must_trunc)) + if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc) + && (!DECIMAL_FLOAT_MODE_P (fmode) + || GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to)))) { int bitsize; REAL_VALUE_TYPE offset; rtx limit, lab1, lab2, insn; bitsize = GET_MODE_BITSIZE (GET_MODE (to)); - real_2expN (&offset, bitsize - 1); + real_2expN (&offset, bitsize - 1, fmode); limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode); lab1 = gen_label_rtx (); lab2 = gen_label_rtx (); diff --git a/gcc/real.c b/gcc/real.c index 9686309cf3d..ec7d56b7b10 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -2304,7 +2304,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) /* Fills R with 2**N. */ void -real_2expN (REAL_VALUE_TYPE *r, int n) +real_2expN (REAL_VALUE_TYPE *r, int n, enum machine_mode fmode) { memset (r, 0, sizeof (*r)); @@ -2319,6 +2319,8 @@ real_2expN (REAL_VALUE_TYPE *r, int n) SET_REAL_EXP (r, n); r->sig[SIGSZ-1] = SIG_MSB; } + if (DECIMAL_FLOAT_MODE_P (fmode)) + decimal_real_convert (r, fmode, r); } diff --git a/gcc/real.h b/gcc/real.h index e24a0df8a64..1eaabed28c0 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -248,7 +248,7 @@ extern bool real_nan (REAL_VALUE_TYPE *, const char *, int, enum machine_mode); extern void real_maxval (REAL_VALUE_TYPE *, int, enum machine_mode); -extern void real_2expN (REAL_VALUE_TYPE *, int); +extern void real_2expN (REAL_VALUE_TYPE *, int, enum machine_mode); extern unsigned int real_hash (const REAL_VALUE_TYPE *); |