aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorCarl Love <cel@us.ibm.com>2021-04-21 18:07:39 -0400
committerCarl Love <cel@us.ibm.com>2021-06-09 11:20:07 -0500
commit9090f4807161876033f6bf0e1133364b38d91865 (patch)
tree5360f8bb969758257a28e52ef2839137fd8934bf /gcc
parentf170186446d03638cd82e37aa2a1bcf4dc1adba2 (diff)
downloadgcc-9090f4807161876033f6bf0e1133364b38d91865.zip
gcc-9090f4807161876033f6bf0e1133364b38d91865.tar.gz
gcc-9090f4807161876033f6bf0e1133364b38d91865.tar.bz2
Conversions between 128-bit integer and floating point values.
The files fixkfti-sw.c and fixunskfti-sw.c are renamed versions of fixkfti.c and fixunskfti.c respectively to do the conversions in software. The function names in the files were updated with the rename as well as some white spaces fixes. The file float128-p10.c contains the functions for using the ISA 3.1 hardware instructions to perform the conversions. 2021-06-08 Carl Love <cel@us.ibm.com> gcc/ChangeLog * config/rs6000/rs6000.c (__fixkfti, __fixunskfti, __floattikf, __floatuntikf): Names changed to __fixkfti_sw, __fixunskfti_sw, __floattikf_sw, __floatuntikf_sw respectively. * config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2, fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add define_insn for mode IEEE 128. gcc/testsuite/ChangeLog * gcc.target/powerpc/fp128_conversions.c: New file. * gcc.target/powerpc/int_128bit-runnable.c(vextsd2q, vcmpuq, vcmpsq, vcmpequq, vcmpequq., vcmpgtsq, vcmpgtsq. vcmpgtuq, vcmpgtuq.): Update scan-assembler-times. (ppc_native_128bit): Remove dg-require-effective-target. libgcc/ChangeLog * config.host: Add if test and set for libgcc_cv_powerpc_3_1_float128_hw. * config/rs6000/fixkfti.c: Renamed to fixkfti-sw.c. Change calls of __fixkfti to __fixkfti_sw. * config/rs6000/fixunskfti.c: Renamed to fixunskfti-sw.c. Change calls of __fixunskfti to __fixunskfti_sw. * config/rs6000/float128-p10.c (__floattikf_hw, __floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw): New file. * config/rs6000/float128-ifunc.c (SW_OR_HW_ISA3_1): New macro. (__floattikf_resolve, __floatuntikf_resolve, __fixkfti_resolve, __fixunskfti_resolve): Add resolve functions. (__floattikf, __floatuntikf, __fixkfti, __fixunskfti): New functions. * config/rs6000/float128-sed (floattitf, __floatuntitf, __fixtfti, __fixunstfti): Add editor commands to change names. * config/rs6000/float128-sed-hw (__floattitf, __floatuntitf, __fixtfti, __fixunstfti): Add editor commands to change names. * config/rs6000/floattikf.c: Renamed to floattikf-sw.c. * config/rs6000/floatuntikf.c: Renamed to floatuntikf-sw.c. * config/rs6000/quad-float128.h (__floattikf_sw, __floatuntikf_sw, __fixkfti_sw, __fixunskfti_sw, __floattikf_hw, __floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw, __floattikf, __floatuntikf, __fixkfti, __fixunskfti): New extern declarations. * config/rs6000/t-float128 (floattikf, floatuntikf, fixkfti, fixunskfti): Remove file names from fp128_ppc_funcs. (floattikf-sw, floatuntikf-sw, fixkfti-sw, fixunskfti-sw): Add file names to fp128_ppc_funcs. * config/rs6000/t-float128-hw(fp128_3_1_hw_funcs, fp128_3_1_hw_src, fp128_3_1_hw_static_obj, fp128_3_1_hw_shared_obj, fp128_3_1_hw_obj): Add variables for ISA 3.1 support. * config/rs6000/t-float128-p10-hw: New file. * configure: Update script for isa 3.1 128-bit float support. * configure.ac: Add check for 128-bit float hardware support.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.c8
-rw-r--r--gcc/config/rs6000/rs6000.md36
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fp128_conversions.c294
-rw-r--r--gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c13
4 files changed, 338 insertions, 13 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 328dc10..75c2cc4 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -11014,10 +11014,10 @@ init_float128_ieee (machine_mode mode)
if (TARGET_POWERPC64)
{
- set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti");
- set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti");
- set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf");
- set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf");
+ set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti_sw");
+ set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti_sw");
+ set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf_sw");
+ set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf_sw");
}
}
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 3f59b54..89c70f4 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -6441,6 +6441,42 @@
xscvsxddp %x0,%x1"
[(set_attr "type" "fp")])
+(define_insn "floatti<mode>2"
+ [(set (match_operand:IEEE128 0 "vsx_register_operand" "=v")
+ (float:IEEE128 (match_operand:TI 1 "vsx_register_operand" "v")))]
+ "TARGET_POWER10"
+{
+ return "xscvsqqp %0,%1";
+}
+ [(set_attr "type" "fp")])
+
+(define_insn "floatunsti<mode>2"
+ [(set (match_operand:IEEE128 0 "vsx_register_operand" "=v")
+ (unsigned_float:IEEE128 (match_operand:TI 1 "vsx_register_operand" "v")))]
+ "TARGET_POWER10"
+{
+ return "xscvuqqp %0,%1";
+}
+ [(set_attr "type" "fp")])
+
+(define_insn "fix_trunc<mode>ti2"
+ [(set (match_operand:TI 0 "vsx_register_operand" "=v")
+ (fix:TI (match_operand:IEEE128 1 "vsx_register_operand" "v")))]
+ "TARGET_POWER10"
+{
+ return "xscvqpsqz %0,%1";
+}
+ [(set_attr "type" "fp")])
+
+(define_insn "fixuns_trunc<mode>ti2"
+ [(set (match_operand:TI 0 "vsx_register_operand" "=v")
+ (unsigned_fix:TI (match_operand:IEEE128 1 "vsx_register_operand" "v")))]
+ "TARGET_POWER10"
+{
+ return "xscvqpuqz %0,%1";
+}
+ [(set_attr "type" "fp")])
+
; Allow the combiner to merge source memory operands to the conversion so that
; the optimizer/register allocator doesn't try to load the value too early in a
; GPR and then use store/load to move it to a FPR and suffer from a store-load
diff --git a/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
new file mode 100644
index 0000000..c20282f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
@@ -0,0 +1,294 @@
+/* { dg-do run } */
+/* { dg-require-effective-target power10_hw } */
+/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
+
+/* Check that the expected 128-bit instructions are generated if the processor
+ supports the 128-bit integer instructions. */
+/* { dg-final { scan-assembler-times {\mxscvsqqp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 } } */
+
+#include <stdio.h>
+#include <math.h>
+#include <fenv.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#define DEBUG 0
+
+void
+abort (void);
+
+float
+conv_i_2_fp( long long int a)
+{
+ return (float) a;
+}
+
+double
+conv_i_2_fpd( long long int a)
+{
+ return (double) a;
+}
+
+double
+conv_ui_2_fpd( unsigned long long int a)
+{
+ return (double) a;
+}
+
+__float128
+conv_i128_2_fp128 (__int128_t a)
+{
+ // default, gen inst KF mode
+ // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+ // -mabi=ieeelongdouble gen inst floattiieee TF mode
+ return (__float128) a;
+}
+
+__float128
+conv_ui128_2_fp128 (__uint128_t a)
+{
+ // default, gen inst KF mode
+ // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+ // -mabi=ieeelongdouble gen inst floattiieee TF mode
+ return (__float128) a;
+}
+
+__int128_t
+conv_fp128_2_i128 (__float128 a)
+{
+ // default, gen inst KF mode
+ // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+ // -mabi=ieeelongdouble gen inst floattiieee TF mode
+ return (__int128_t) a;
+}
+
+__uint128_t
+conv_fp128_2_ui128 (__float128 a)
+{
+ // default, gen inst KF mode
+ // -mabi=ibmlongdouble, gen inst floattiieee KF mode
+ // -mabi=ieeelongdouble gen inst floattiieee TF mode
+ return (__uint128_t) a;
+}
+
+long double
+conv_i128_2_ld (__int128_t a)
+{
+ // default, gen call __floattitf
+ // -mabi=ibmlongdouble, gen call __floattitf
+ // -mabi=ieeelongdouble gen inst floattiieee TF mode
+ return (long double) a;
+}
+
+__ibm128
+conv_i128_2_ibm128 (__int128_t a)
+{
+ // default, gen call __floattitf
+ // -mabi=ibmlongdouble, gen call __floattitf
+ // -mabi=ieeelongdouble, message uses IBM long double, no binary output
+ return (__ibm128) a;
+}
+
+int
+main()
+{
+ float a, expected_result_float;
+ double b, expected_result_double;
+ long long int c, expected_result_llint;
+ unsigned long long int u;
+ __int128_t d;
+ __uint128_t u128;
+ unsigned long long expected_result_uint128[2] ;
+ __float128 e;
+ long double ld; // another 128-bit float version
+
+ union conv_t {
+ float a;
+ double b;
+ long long int c;
+ long long int128[2] ;
+ unsigned long long uint128[2] ;
+ unsigned long long int u;
+ __int128_t d;
+ __uint128_t u128;
+ __float128 e;
+ long double ld; // another 128-bit float version
+ } conv, conv_result;
+
+ c = 20;
+ expected_result_llint = 20.00000;
+ a = conv_i_2_fp (c);
+
+ if (a != expected_result_llint) {
+#if DEBUG
+ printf("ERROR: conv_i_2_fp(%lld) = %10.5f\n", c, a);
+ printf("\n does not match expected_result = %10.5f\n\n",
+ expected_result_llint);
+#else
+ abort();
+#endif
+ }
+
+ c = 20;
+ expected_result_double = 20.00000;
+ b = conv_i_2_fpd (c);
+
+ if (b != expected_result_double) {
+#if DEBUG
+ printf("ERROR: conv_i_2_fpd(%lld) = %10.5f\n", d, b);
+ printf("\n does not match expected_result = %10.5f\n\n",
+ expected_result_double);
+ #else
+ abort();
+#endif
+ }
+
+ u = 20;
+ expected_result_double = 20.00000;
+ b = conv_ui_2_fpd (u);
+
+ if (b != expected_result_double) {
+#if DEBUG
+ printf("ERROR: conv_ui_2_fpd(%llu) = %10.5f\n", u, b);
+ printf("\n does not match expected_result = %10.5f\n\n",
+ expected_result_double);
+ #else
+ abort();
+#endif
+ }
+
+ d = -3210;
+ d = (d * 10000000000) + 9876543210;
+ conv_result.e = conv_i128_2_fp128 (d);
+ expected_result_uint128[1] = 0xc02bd2f9068d1160;
+ expected_result_uint128[0] = 0x0;
+
+ if ((conv_result.uint128[1] != expected_result_uint128[1])
+ && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+ printf("ERROR: conv_i128_2_fp128(-32109876543210) = (result in hex) 0x%llx %llx\n",
+ conv.uint128[1], conv.uint128[0]);
+ printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+ expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+ abort();
+#endif
+ }
+
+ d = 123;
+ d = (d * 10000000000) + 1234567890;
+ conv_result.ld = conv_i128_2_fp128 (d);
+ expected_result_uint128[1] = 0x0;
+ expected_result_uint128[0] = 0x4271eab4c8ed2000;
+
+ if ((conv_result.uint128[1] != expected_result_uint128[1])
+ && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+ printf("ERROR: conv_i128_2_fp128(1231234567890) = (result in hex) 0x%llx %llx\n",
+ conv.uint128[1], conv.uint128[0]);
+ printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+ expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+ abort();
+#endif
+ }
+
+ u128 = 8760;
+ u128 = (u128 * 10000000000) + 1234567890;
+ conv_result.e = conv_ui128_2_fp128 (u128);
+ expected_result_uint128[1] = 0x402d3eb101df8b48;
+ expected_result_uint128[0] = 0x0;
+
+ if ((conv_result.uint128[1] != expected_result_uint128[1])
+ && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+ printf("ERROR: conv_ui128_2_fp128(87601234567890) = (result in hex) 0x%llx %llx\n",
+ conv.uint128[1], conv.uint128[0]);
+ printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+ expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+ abort();
+#endif
+ }
+
+ u128 = 3210;
+ u128 = (u128 * 10000000000) + 9876543210;
+ expected_result_uint128[1] = 0x402bd3429c8feea0;
+ expected_result_uint128[0] = 0x0;
+ conv_result.e = conv_ui128_2_fp128 (u128);
+
+ if ((conv_result.uint128[1] != expected_result_uint128[1])
+ && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+ printf("ERROR: conv_ui128_2_fp128(32109876543210) = (result in hex) 0x%llx %llx\n",
+ conv.uint128[1], conv.uint128[0]);
+ printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+ expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+ abort();
+#endif
+ }
+
+ conv.e = 12345.6789;
+ expected_result_uint128[1] = 0x1407374883526960;
+ expected_result_uint128[0] = 0x3039;
+
+ conv_result.d = conv_fp128_2_i128 (conv.e);
+
+ if ((conv_result.uint128[1] != expected_result_uint128[1])
+ && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+ printf("ERROR: conv_fp128_2_i128(0x%llx %llx) = ",
+ conv.uint128[1], conv.uint128[0]);
+ printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+
+ printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+ expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+ abort();
+#endif
+ }
+
+ conv.e = -6789.12345;
+ expected_result_uint128[1] = 0x0;
+ expected_result_uint128[0] = 0xffffffffffffe57b;
+ conv_result.d = conv_fp128_2_i128 (conv.e);
+
+ if ((conv_result.uint128[1] != expected_result_uint128[1])
+ && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+ printf("ERROR: conv_fp128_2_i128(0x%llx %llx) = ",
+ conv.uint128[1], conv.uint128[0]);
+ printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+
+ printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+ expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+ abort();
+#endif
+ }
+
+ conv.e = 6789.12345;
+ expected_result_uint128[1] = 0x0;
+ expected_result_uint128[0] = 0x1a85;
+ conv_result.d = conv_fp128_2_ui128 (conv.e);
+
+ if ((conv_result.uint128[1] != expected_result_uint128[1])
+ && (conv_result.uint128[0] != expected_result_uint128[0])) {
+#if DEBUG
+ printf("ERROR: conv_fp128_2_ui128(0x%llx %llx) = ",
+ conv.uint128[1], conv.uint128[0]);
+ printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
+
+ printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
+ expected_result_uint128[1], expected_result_uint128[0]);
+ #else
+ abort();
+#endif
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
index 9f7dbc6..94dbd2b 100644
--- a/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
+++ b/gcc/testsuite/gcc.target/powerpc/int_128bit-runnable.c
@@ -4,21 +4,16 @@
/* Check that the expected 128-bit instructions are generated if the processor
supports the 128-bit integer instructions. */
+/* { dg-final { scan-assembler-times {\mvextsd2q\M} 4 } } */
/* { dg-final { scan-assembler-times {\mvslq\M} 2 } } */
/* { dg-final { scan-assembler-times {\mvsrq\M} 2 } } */
/* { dg-final { scan-assembler-times {\mvsraq\M} 2 } } */
/* { dg-final { scan-assembler-times {\mvrlq\M} 2 } } */
/* { dg-final { scan-assembler-times {\mvrlqnm\M} 2 } } */
/* { dg-final { scan-assembler-times {\mvrlqmi\M} 2 } } */
-/* { dg-final { scan-assembler-times {\mvcmpuq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpsq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpequq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpequq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtsq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 0 } } */
-/* { dg-final { scan-assembler-times {\mvcmpgtuq.\M} 16 } } */
-/* { dg-final { scan-assembler-times {\mvmuleud\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvcmpequq\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 16 } } */
/* { dg-final { scan-assembler-times {\mvmuloud\M} 1 } } */
/* { dg-final { scan-assembler-times {\mvmulesd\M} 1 } } */
/* { dg-final { scan-assembler-times {\mvmulosd\M} 1 } } */