On Thu, Dec 21, 2017 at 01:03:26PM -0600, Segher Boessenkool wrote: > On Thu, Dec 21, 2017 at 06:16:16PM +0000, Joseph Myers wrote: > > On Fri, 17 Nov 2017, Michael Meissner wrote: > > The architecture-independent changes are OK. However, I have a comment on > > the target parts: > > > > > +(define_insn "round<mode>2" > > > + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") > > > + (unspec:IEEE128 > > > + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] > > > + UNSPEC_FRIN))] > > > + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" > > > + "xsrqpi 0,%0,%1,3" > > > + [(set_attr "type" "vecfloat") > > > + (set_attr "size" "128")]) > > > > My reading of Power ISA 3.0B documentation is that 0,%0,%1,3 means round > > in the mode specified by FPSCR and you need 0,%0,%1,0 for > > round-to-nearest-away semantics which are what the round<mode>2 > > instruction has (i.e., what you've written here is actually correct for > > nearbyint<mode>2, and would be rint<mode>2 if xsrqpix were used instead). > > Ah yes, the roundM2 insn is round-away-from-zero, so you are right. > Tricky, from the name I assumed it would be "current rounding mode" :-/ > Not that "frin" would make sense if that were true. > > Thanks! And thanks for all the reviews in general.
Here is the corrected rs6000 part of the patch. I added more round tests and I checked it on a power9 prototype machine. Roundf128 now produces the correct answer. Can I check this into the trunk? [gcc] 2017-12-29 Michael Meissner <meiss...@linux.vnet.ibm.com> * config/rs6000/rs6000.md (floor<mode>2): Add support for IEEE 128-bit round to integer instructions. (ceil<mode>2): Likewise. (btrunc<mode>2): Likewise. (round<mode>2): Likewise. [gcc/testsuite] 2017-12-29 Michael Meissner <meiss...@linux.vnet.ibm.com> * gcc.target/powerpc/float128-hw2.c: Add tests for ceilf128, floorf128, truncf128, and roundf128. * gcc.target/powerpc/float128-hw5.c: New tests for _Float128 optimizations added in match.pd. * gcc.target/powerpc/float128-hw6.c: Likewise. * gcc.target/powerpc/float128-hw7.c: Likewise. * gcc.target/powerpc/float128-hw8.c: Likewise. * gcc.target/powerpc/float128-hw9.c: Likewise. * gcc.target/powerpc/float128-hw10.c: Likewise. * gcc.target/powerpc/float128-hw11.c: Likewise. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 256026) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -14777,6 +14777,47 @@ (define_insn_and_split "floatuns<QHI:mod (set_attr "type" "vecfloat") (set_attr "size" "128")]) +;; IEEE 128-bit round to integer built-in functions +(define_insn "floor<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIM))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 1,%0,%1,3" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + +(define_insn "ceil<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIP))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 1,%0,%1,2" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + +(define_insn "btrunc<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIZ))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 1,%0,%1,1" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + +(define_insn "round<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIN))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 0,%0,%1,0" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + ;; IEEE 128-bit instructions with round to odd semantics (define_insn "add<mode>3_odd" [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") Index: gcc/testsuite/gcc.target/powerpc/float128-hw2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw2.c (revision 256026) +++ gcc/testsuite/gcc.target/powerpc/float128-hw2.c (working copy) @@ -14,6 +14,10 @@ extern _Float128 copysignf128 (_Float128, _Float128); extern _Float128 sqrtf128 (_Float128); extern _Float128 fmaf128 (_Float128, _Float128, _Float128); +extern _Float128 ceilf128 (_Float128); +extern _Float128 floorf128 (_Float128); +extern _Float128 truncf128 (_Float128); +extern _Float128 roundf128 (_Float128); _Float128 do_copysign (_Float128 a, _Float128 b) @@ -51,10 +55,35 @@ do_nfms (_Float128 a, _Float128 b, _Floa return -fmaf128 (a, b, -c); } +_Float128 +do_ceil (_Float128 a) +{ + return ceilf128 (a); +} + +_Float128 +do_floor (_Float128 a) +{ + return floorf128 (a); +} + +_Float128 +do_trunc (_Float128 a) +{ + return truncf128 (a); +} + +_Float128 +do_round (_Float128 a) +{ + return roundf128 (a); +} + /* { dg-final { scan-assembler {\mxscpsgnqp\M} } } */ /* { dg-final { scan-assembler {\mxssqrtqp\M} } } */ /* { dg-final { scan-assembler {\mxsmaddqp\M} } } */ /* { dg-final { scan-assembler {\mxsmsubqp\M} } } */ /* { dg-final { scan-assembler {\mxsnmaddqp\M} } } */ /* { dg-final { scan-assembler {\mxsnmsubqp\M} } } */ +/* { dg-final { scan-assembler {\mxsrqpi\M} } } */ /* { dg-final { scan-assembler-not {\mbl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/float128-hw5.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw5.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/float128-hw5.c (working copy) @@ -0,0 +1,33 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-vector -O2 -ffast-math" } */ + +extern _Float128 copysignf128 (_Float128, _Float128); + +/* Check copysign optimizations that are done for double are also done for + _Float128. */ + +_Float128 +x_times_cs_one_negx (_Float128 x) +{ + return x * copysignf128 (1.0Q, -x); /* XSNABSQP */ +} + +_Float128 +x_times_cs_one_x (_Float128 x) +{ + return x * copysignf128 (1.0Q, x); /* XSABSQP */ +} + +_Float128 +cs_x_x (_Float128 x) +{ + return copysignf128 (x, x); /* no operation. */ +} + +/* { dg-final { scan-assembler-times {\mxsabsqp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxsnabsqp\M} 1 } } */ +/* { dg-final { scan-assembler-not {\mxscpsgnqp\M} } } */ +/* { dg-final { scan-assembler-not {\mlxvx\M} } } */ +/* { dg-final { scan-assembler-not {\mlxv\M} } } */ +/* { dg-final { scan-assembler-not {\mbl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/float128-hw6.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw6.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/float128-hw6.c (working copy) @@ -0,0 +1,26 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-vector -O2" } */ + +extern _Float128 fabsf128 (_Float128); +extern _Float128 copysignf128 (_Float128, _Float128); + +/* Check copysign optimizations that are done for double are also done for + _Float128. */ + +_Float128 +cs_negx_y (_Float128 x, _Float128 y) +{ + return copysignf128 (-x, y); /* eliminate negation. */ +} + +_Float128 +cs_absx_y (_Float128 x, _Float128 y) +{ + return copysignf128 (fabsf128 (x), y); /* eliminate fabsf128. */ +} + +/* { dg-final { scan-assembler-times {\mxscpsgnqp\M} 2 } } */ +/* { dg-final { scan-assembler-not {\mxsnegqp\M} } } */ +/* { dg-final { scan-assembler-not {\mxsabsqp\M} } } */ +/* { dg-final { scan-assembler-not {\mbl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/float128-hw7.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw7.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/float128-hw7.c (working copy) @@ -0,0 +1,27 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-vector -O2" } */ + +extern _Float128 fabsf128 (_Float128); +extern _Float128 copysignf128 (_Float128, _Float128); + +/* Check copysign optimizations that are done for double are also done for + _Float128. */ + +_Float128 +cs_x_pos1 (_Float128 x) +{ + return copysignf128 (x, 1.0Q); /* XSABSQP. */ +} + +_Float128 cs_x_neg2 (_Float128 x) +{ + return copysignf128 (x, -2.0Q); /* XSNABSQP. */ +} + +/* { dg-final { scan-assembler-times {\mxsabsqp\M} 1 } } */ +/* { dg-final { scan-assembler-not {\mxsnabsqp\M} 1 } } */ +/* { dg-final { scan-assembler-not {\mxscpsgnqp\M} } } */ +/* { dg-final { scan-assembler-not {\mlxvx\M} } } */ +/* { dg-final { scan-assembler-not {\mlxv\M} } } */ +/* { dg-final { scan-assembler-not {\mbl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/float128-hw8.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw8.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/float128-hw8.c (working copy) @@ -0,0 +1,24 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-vector -O2" } */ + +extern _Float128 fminf128 (_Float128, _Float128); +extern _Float128 fmaxf128 (_Float128, _Float128); + +/* Check min/max optimizations that are done for double are also done for + _Float128. */ + +_Float128 +min_x_x (_Float128 x) +{ + return fminf128 (x, x); +} + +_Float128 +max_x_x (_Float128 x) +{ + return fmaxf128 (x, x); +} + +/* { dg-final { scan-assembler-not {\mxscmpuqp\M} } } */ +/* { dg-final { scan-assembler-not {\mbl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/float128-hw9.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw9.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/float128-hw9.c (working copy) @@ -0,0 +1,17 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-vector -O2 -ffast-math" } */ + +extern _Float128 sqrtf128 (_Float128); + +/* Check sqrt optimizations that are done for double are also done for + _Float128. */ + +_Float128 +sqrt_x_times_sqrt_x (_Float128 x) +{ + return sqrtf128 (x) * sqrtf128 (x); +} + +/* { dg-final { scan-assembler-not {\mxssqrtqp\M} } } */ +/* { dg-final { scan-assembler-not {\mbl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/float128-hw10.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw10.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/float128-hw10.c (working copy) @@ -0,0 +1,38 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-options "-mpower9-vector -O2" } */ + +extern _Float128 floorf128 (_Float128); +extern _Float128 ceilf128 (_Float128); +extern _Float128 roundf128 (_Float128); +extern _Float128 truncf128 (_Float128); + +/* Check rounding optimizations that are done for double are also done for + _Float128. */ + +_Float128 +floor_floor_x (_Float128 x) +{ + return floorf128 (floorf128 (x)); +} + +_Float128 +ceil_ceil_x (_Float128 x) +{ + return ceilf128 (ceilf128 (x)); +} + +_Float128 +trunc_trunc_x (_Float128 x) +{ + return truncf128 (truncf128 (x)); +} + +_Float128 +round_round_x (_Float128 x) +{ + return roundf128 (roundf128 (x)); +} + +/* { dg-final { scan-assembler-times {\mxsrqpi\M} 4 } } */ +/* { dg-final { scan-assembler-not {\mbl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/float128-hw11.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-hw11.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/float128-hw11.c (working copy) @@ -0,0 +1,85 @@ +/* { dg-do run { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target p9vector_hw } */ +/* { dg-options "-mpower9-vector -O2" } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 +#define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 + +#include <math.h> +#include <stdlib.h> +#include <stddef.h> + +#ifdef DEBUG +#include <stdio.h> +#define FAIL(T,G,E) printf ("%s: %g %g\n", (T), (G), (E)) +#else +#define FAIL(T,G,E) abort () +#endif + +extern _Float128 roundf128 (_Float128); +extern _Float128 floorf128 (_Float128); +extern _Float128 ceilf128 (_Float128); +extern _Float128 truncf128 (_Float128); + +static const _Float128 values[] = { + -3.7f128, + -3.5f128, + -3.3f128, + -3.0f128, + -2.7f128, + -2.5f128, + -2.3f128, + -2.0f128, + -1.7f128, + -1.5f128, + -1.3f128, + -0.7f128, + -0.5f128, + -0.3f128, + +0.0f128, + +0.3f128, + +0.5f128, + +0.7f128, + +1.0f128, + +1.3f128, + +1.5f128, + +1.7f128, + +2.0f128, + +2.3f128, + +2.5f128, + +2.7f128, + +3.0f128, + +3.3f128, + +3.5f128, + +3.7f128, +}; + +__attribute__((__noinline__)) +void +do_test (const char *test, _Float128 got, double expected) +{ + double got2 = (double) got; + if (got2 != expected) + FAIL (test, got2, expected); +} + +int +main (void) +{ + size_t i; + _Float128 v; + double v2; + + for (i = 0; i < sizeof (values) / sizeof (values[0]); i++) + { + v = values[i]; + v2 = (double) v; + + do_test ("roundf128", roundf128 (v), round (v2)); + do_test ("floorf128", floorf128 (v), floor (v2)); + do_test ("ceilf128", ceilf128 (v), ceil (v2)); + do_test ("truncf128", truncf128 (v), trunc (v2)); + } + + return 0; +}