[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