[PATCH] SPU float format: Extended exponent range

Richard Guenther richard.guenther@gmail.com
Mon Aug 4 19:41:00 GMT 2008


On Mon, Aug 4, 2008 at 9:27 PM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> Hello,
>
> a while back, Trevor started a discussion on making GCC compile-time
> arithmetic respect the not-quite-IEEE single-precision floating-point
> format on the SPU.  Unfortunately, this didn't in the end result in
> anything being committed to mainline.  Here's a link to the last patch:
> http://gcc.gnu.org/ml/gcc-patches/2007-09/msg00540.html
>
> I'd like to take this up again.  Instead of one big patch, I hope to
> make mainline inclusion more straightforward by proposing a series
> of smaller patches, each addressing a particular feature.
>
> This first patch introduces a new real_format structure to describe
> the SPU single-precision format.  It handles the extended exponent
> range (biased exponent of 255 denotes regular numbers, not Inf or Nan
> values).
>
> One interesting feature of SPU floating point is that the single->
> double and double->single conversion instructions simply ignore the
> fact that the single-precision format is not IEEE.  This means that
> after introducing the new format, common code no longer correctly
> models those instructions.  At some later time, we might want to
> add back specical knowledge of those conversions; for now this patch
> simply switches the back-end to use UNSPECs for those instructions.
>
> The common code changes are straightforward, but they exposed a bug
> in spu_split_immediate where bit-wise operation on parts of floating-
> point constants was peformed in SFmode.  This breaks when the pieces
> by themselves are not valid in the given floating-point format.  In
> another case of the switch this was already addressed by doing the
> bit-wise operation in an integral mode instead.  This patch extends
> that to the second case of that switch ...
>
> In addition, the change exposed another testcase that used
> _builtin_inff -- this doesn't work on SPU because the format does
> not support infinity.  The patch disables that testcase (just like
> similar testcases were disabled).
>
> Tested on spu-elf on mainline and 4.3 branch.  OK to commit?

The middle-end parts are ok for the mainline.

Thanks,
Richard.

> Bye,
> Ulrich
>
>
> ChangeLog:
>
>        * real.c (spu_single_format): New variable.
>        * real.h (spu_single_format): Declare.
>
>        * config/spu/spu.c (spu_override_options): Install SFmode format.
>        (spu_split_immediate): Use integer mode to operate on pieces of
>        floating-point values in all cases.
>
>        * config/spu/spu.md (UNSPEC_FLOAT_EXTEND, UNSPEC_FLOAT_TRUNCATE): New.
>        ("extendsfdf2"): Use UNSPEC_FLOAT_EXTEND instead of FLOAT_EXTEND.
>        ("truncdfsf2"): Use UNSPEC_FLOAT_TRUNCATE instead of FLOAT_TRUNCATE.
>
> testsuite/ChangeLog:
>
>        * gcc.c-torture/execute/ieee/inf-2.c (testf): Skip on the SPU.
>
>
> diff -x .svn -urNp gcc-head-orig/gcc/config/spu/spu.c gcc-head/gcc/config/spu/spu.c
> --- gcc-head-orig/gcc/config/spu/spu.c  2008-08-03 20:12:58.000000000 +0200
> +++ gcc-head/gcc/config/spu/spu.c       2008-08-02 14:02:51.000000000 +0200
> @@ -352,6 +352,8 @@ spu_override_options (void)
>       else
>         error ("Unknown architecture '%s'", &spu_tune_string[0]);
>     }
> +
> +  REAL_MODE_FORMAT (SFmode) = &spu_single_format;
>  }
>
>  /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
> @@ -1519,10 +1521,18 @@ spu_split_immediate (rtx * ops)
>       {
>        unsigned char arrhi[16];
>        unsigned char arrlo[16];
> -       rtx to, hi, lo;
> +       rtx to, temp, hi, lo;
>        int i;
> +       enum machine_mode imode = mode;
> +       /* We need to do reals as ints because the constant used in the
> +          IOR might not be a legitimate real constant. */
> +       imode = int_mode_for_mode (mode);
>        constant_to_array (mode, ops[1], arrhi);
> -       to = !can_create_pseudo_p () ? ops[0] : gen_reg_rtx (mode);
> +       if (imode != mode)
> +         to = simplify_gen_subreg (imode, ops[0], mode, 0);
> +       else
> +         to = ops[0];
> +       temp = !can_create_pseudo_p () ? to : gen_reg_rtx (imode);
>        for (i = 0; i < 16; i += 4)
>          {
>            arrlo[i + 2] = arrhi[i + 2];
> @@ -1530,11 +1540,11 @@ spu_split_immediate (rtx * ops)
>            arrlo[i + 0] = arrlo[i + 1] = 0;
>            arrhi[i + 2] = arrhi[i + 3] = 0;
>          }
> -       hi = array_to_constant (mode, arrhi);
> -       lo = array_to_constant (mode, arrlo);
> -       emit_move_insn (to, hi);
> +       hi = array_to_constant (imode, arrhi);
> +       lo = array_to_constant (imode, arrlo);
> +       emit_move_insn (temp, hi);
>        emit_insn (gen_rtx_SET
> -                  (VOIDmode, ops[0], gen_rtx_IOR (mode, to, lo)));
> +                  (VOIDmode, to, gen_rtx_IOR (imode, temp, lo)));
>        return 1;
>       }
>     case IC_FSMBI2:
> diff -x .svn -urNp gcc-head-orig/gcc/config/spu/spu.md gcc-head/gcc/config/spu/spu.md
> --- gcc-head-orig/gcc/config/spu/spu.md 2008-07-20 23:08:42.000000000 +0200
> +++ gcc-head/gcc/config/spu/spu.md      2008-08-03 20:10:48.000000000 +0200
> @@ -153,6 +153,8 @@
>  (UNSPEC_SPU_REALIGN_LOAD 49)
>  (UNSPEC_SPU_MASK_FOR_LOAD 50)
>  (UNSPEC_DFTSV          51)
> + (UNSPEC_FLOAT_EXTEND   52)
> + (UNSPEC_FLOAT_TRUNCATE         53)
>  ])
>
>  (include "predicates.md")
> @@ -648,14 +650,16 @@
>
>  (define_insn "extendsfdf2"
>   [(set (match_operand:DF 0 "spu_reg_operand" "=r")
> -       (float_extend:DF (match_operand:SF 1 "spu_reg_operand" "r")))]
> +       (unspec:DF [(match_operand:SF 1 "spu_reg_operand" "r")]
> +                   UNSPEC_FLOAT_EXTEND))]
>   ""
>   "fesd\t%0,%1"
>   [(set_attr "type" "fpd")])
>
>  (define_insn "truncdfsf2"
>   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
> -       (float_truncate:SF (match_operand:DF 1 "spu_reg_operand" "r")))]
> +       (unspec:SF [(match_operand:DF 1 "spu_reg_operand" "r")]
> +                   UNSPEC_FLOAT_TRUNCATE))]
>   ""
>   "frds\t%0,%1"
>   [(set_attr "type" "fpd")])
> diff -x .svn -urNp gcc-head-orig/gcc/real.c gcc-head/gcc/real.c
> --- gcc-head-orig/gcc/real.c    2008-08-03 20:12:58.000000000 +0200
> +++ gcc-head/gcc/real.c 2008-08-03 20:10:48.000000000 +0200
> @@ -2862,6 +2862,36 @@ const struct real_format motorola_single
>     true,
>     true
>   };
> +
> +/*  SPU Single Precision (Extended-Range Mode) format is the same as IEEE
> +    single precision with the following differences:
> +      - Infinities are not supported.  Instead MAX_FLOAT or MIN_FLOAT
> +       are generated.
> +      - NaNs are not supported.
> +      - The range of non-zero numbers in binary is
> +       (001)[1.]000...000 to (255)[1.]111...111.
> +      - Denormals can be represented, but are treated as +0.0 when
> +       used as an operand and are never generated as a result.
> +      - -0.0 can be represented, but a zero result is always +0.0.
> +      - the only supported rounding mode is trunction (towards zero).  */
> +const struct real_format spu_single_format =
> +  {
> +    encode_ieee_single,
> +    decode_ieee_single,
> +    2,
> +    24,
> +    24,
> +    -125,
> +    129,
> +    31,
> +    31,
> +    false,
> +    false,
> +    true,
> +    true,
> +    false,
> +    false
> +  };
>
>  /* IEEE double-precision format.  */
>
> diff -x .svn -urNp gcc-head-orig/gcc/real.h gcc-head/gcc/real.h
> --- gcc-head-orig/gcc/real.h    2008-08-03 20:12:58.000000000 +0200
> +++ gcc-head/gcc/real.h 2008-08-03 20:10:48.000000000 +0200
> @@ -259,6 +259,7 @@ extern unsigned int real_hash (const REA
>  extern const struct real_format ieee_single_format;
>  extern const struct real_format mips_single_format;
>  extern const struct real_format motorola_single_format;
> +extern const struct real_format spu_single_format;
>  extern const struct real_format ieee_double_format;
>  extern const struct real_format mips_double_format;
>  extern const struct real_format motorola_double_format;
> diff -x .svn -urNp gcc-head-orig/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c gcc-head/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c
> --- gcc-head-orig/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c      2008-08-03 20:12:58.000000000 +0200
> +++ gcc-head/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c   2008-08-02 14:02:51.000000000 +0200
> @@ -25,6 +25,9 @@ void test(double f, double i)
>
>  void testf(float f, float i)
>  {
> +#ifndef __SPU__
> +  /* The SPU single-precision floating point format does not support Inf.  */
> +
>   if (f == __builtin_inff())
>     abort ();
>   if (f == -__builtin_inff())
> @@ -44,6 +47,7 @@ void testf(float f, float i)
>     abort ();
>   if (f < -__builtin_inff())
>     abort ();
> +#endif
>  }
>
>  void testl(long double f, long double i)
>
> --
>  Dr. Ulrich Weigand
>  GNU Toolchain for Linux on System z and Cell BE
>  Ulrich.Weigand@de.ibm.com
>



More information about the Gcc-patches mailing list