This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, rs6000] Fix PR target/80246, DFP builtins using the wrong types


PR80246 shows a problem with the dxex, dxexq, diex and diexq insn patterns,
that shows up when calling their associated builtins.  The dxex and dxexq
instructions are defined to return 64-bit signed integers (in a FP register),
but the output mode of their patterns is _Decimal64/_Decimal128.
This leads to corrupting of the returned value if we assign the return
value to a integer type variable (ie, we do a cast).  A similar problem
exists with the diex and diexq patterns on their input operand that
is supposed to hold a 64-bit signed integer.

This patch fixes the patterns to use DImode (ie, a 64-bit integer).
Google shows no use of the builtins anywhere except in the GCC source,
so it should be safe to change these.  If there were users, they would
have noticed how broken the builtins were.

This passed bootstrap and regtesting on powerpc64le-linux and
powerpc64-linux (testsuite in both 32-bit and 64-bit).  Ok for mainline?
Ok for the open release branches too?

Peter

gcc/
	PR target/80246
	* config/rs6000/dfp.md (dfp_dxex_<mode>): Update mode of operand 0.
	(dfp_diex_<mode>): Update mode of operand 1.
	* doc/extend.texi (dxex, dxexq): Document change to return type.
	(diex, diexq): Document change to argument type.

gcc/testsuite/
	PR target/80246
	* gcc.target/powerpc/dfp-builtin-1.c (dxex, dxexq): Update return types.
	(diex, diexq): Update argment types.
	* gcc.target/powerpc/pr80246.c: New test.


Index: gcc/config/rs6000/dfp.md
===================================================================
--- gcc/config/rs6000/dfp.md	(revision 246539)
+++ gcc/config/rs6000/dfp.md	(working copy)
@@ -348,9 +348,9 @@
   [(set_attr "type" "dfp")])
 
 (define_insn "dfp_dxex_<mode>"
-  [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
-	(unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
-			 UNSPEC_DXEX))]
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=d")
+	(unspec:DI [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
+		   UNSPEC_DXEX))]
   "TARGET_DFP"
   "dxex<dfp_suffix> %0,%1"
   [(set_attr "type" "dfp")])
@@ -357,7 +357,7 @@
 
 (define_insn "dfp_diex_<mode>"
   [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
-	(unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
+	(unspec:D64_D128 [(match_operand:DI 1 "gpc_reg_operand" "d")
 			  (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
 			 UNSPEC_DXEX))]
   "TARGET_DFP"
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 246539)
+++ gcc/doc/extend.texi	(working copy)
@@ -15427,14 +15427,14 @@
 of processors when hardware decimal floating point
 (@option{-mhard-dfp}) is available:
 @smallexample
-_Decimal64 __builtin_dxex (_Decimal64);
-_Decimal128 __builtin_dxexq (_Decimal128);
+long long __builtin_dxex (_Decimal64);
+long long __builtin_dxexq (_Decimal128);
 _Decimal64 __builtin_ddedpd (int, _Decimal64);
 _Decimal128 __builtin_ddedpdq (int, _Decimal128);
 _Decimal64 __builtin_denbcd (int, _Decimal64);
 _Decimal128 __builtin_denbcdq (int, _Decimal128);
-_Decimal64 __builtin_diex (_Decimal64, _Decimal64);
-_Decimal128 _builtin_diexq (_Decimal128, _Decimal128);
+_Decimal64 __builtin_diex (long long, _Decimal64);
+_Decimal128 _builtin_diexq (long long, _Decimal128);
 _Decimal64 __builtin_dscli (_Decimal64, int);
 _Decimal128 __builtin_dscliq (_Decimal128, int);
 _Decimal64 __builtin_dscri (_Decimal64, int);
Index: gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c	(revision 246539)
+++ gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c	(working copy)
@@ -52,7 +52,7 @@
   return __builtin_denbcd (1, a);
 }
 
-_Decimal64
+long long
 do_xex (_Decimal64 a)
 {
   return __builtin_dxex (a);
@@ -59,7 +59,7 @@
 }
 
 _Decimal64
-do_iex (_Decimal64 a, _Decimal64 b)
+do_iex (long long a, _Decimal64 b)
 {
   return __builtin_diex (a, b);
 }
Index: gcc/testsuite/gcc.target/powerpc/pr80246.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr80246.c	(nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr80246.c	(working copy)
@@ -0,0 +1,40 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target dfp } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "dxex "  1 } } */
+/* { dg-final { scan-assembler-times "dxexq " 1 } } */
+/* { dg-final { scan-assembler-times "diex "  1 } } */
+/* { dg-final { scan-assembler-times "diexq " 1 } } */
+/* { dg-final { scan-assembler-not "bl __builtin" } } */
+/* { dg-final { scan-assembler-not "drintn\\." } } */
+/* { dg-final { scan-assembler-not "drintnq\\." } } */
+/* { dg-final { scan-assembler-not "dctfix" } } */
+/* { dg-final { scan-assembler-not "dctfixq" } } */
+/* { dg-final { scan-assembler-not "dcffix" } } */
+/* { dg-final { scan-assembler-not "dcffixq" } } */
+
+long long
+do_xex (_Decimal64 arg)
+{
+  return __builtin_dxex (arg);
+}
+
+long long
+do_xexq (_Decimal128 arg)
+{
+  return __builtin_dxexq (arg);
+}
+
+_Decimal64
+do_iex (long long exp, _Decimal64 arg)
+{
+  return __builtin_diex (exp, arg);
+}
+
+_Decimal128
+do_iexq (long long exp, _Decimal128 arg)
+{
+  return __builtin_diexq (exp, arg);
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]