diff mbox

, PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #07

Message ID 20151023174355.GH18348@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Oct. 23, 2015, 5:43 p.m. UTC
This patch updates to use the unordered comparison function for IEEE 128-bit
floating point to mimic the behaviour of SFmode/DFmode using the fcmpu
instruction.

It also restructures the code to allow a future change to drop in easier.

I have built the compiler with this patch and the previous subpatches (1-6).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (rs6000_generate_compare): For IEEE
	128-bit floating point comparisons, call the unordered comparison
	function instead of the ordered comparison function.
	(rs6000_expand_float128_convert): Deal with operands that are
	memory operands. Restructure the code to use a switch statement on
	the mode. Add support for TFmode defaulting to either IBM extended
	double or IEEE 128-bit floating point. If the underlying types are
	the same, use a move instead of a conversion function.

Comments

David Edelsohn Oct. 29, 2015, 2:35 p.m. UTC | #1
On Fri, Oct 23, 2015 at 1:43 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch updates to use the unordered comparison function for IEEE 128-bit
> floating point to mimic the behaviour of SFmode/DFmode using the fcmpu
> instruction.
>
> It also restructures the code to allow a future change to drop in easier.
>
> I have built the compiler with this patch and the previous subpatches (1-6).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (rs6000_generate_compare): For IEEE
>         128-bit floating point comparisons, call the unordered comparison
>         function instead of the ordered comparison function.
>         (rs6000_expand_float128_convert): Deal with operands that are
>         memory operands. Restructure the code to use a switch statement on
>         the mode. Add support for TFmode defaulting to either IBM extended
>         double or IEEE 128-bit floating point. If the underlying types are
>         the same, use a move instead of a conversion function.

Okay.

Thanks, David
diff mbox

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229191)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -20098,17 +20098,18 @@  rs6000_generate_compare (rtx cmp, machin
       emit_insn (cmp);
     }
 
-  /* IEEE 128-bit support in VSX registers.  The comparison function (__cmpkf2)
-     returns 0..15 that is laid out the same way as the PowerPC CR register
-     would for a normal floating point comparison.  */
+  /* IEEE 128-bit support in VSX registers.  The comparison functions
+     (__cmpokf2 and __cmpukf2) returns 0..15 that is laid out the same way as
+     the PowerPC CR register would for a normal floating point comparison from
+     the fcmpo and fcmpu instructions.  */
   else if (FLOAT128_IEEE_P (mode))
     {
       rtx and_reg = gen_reg_rtx (SImode);
       rtx dest = gen_reg_rtx (SImode);
-      rtx libfunc = optab_libfunc (cmp_optab, mode);
+      rtx libfunc = optab_libfunc (ucmp_optab, mode);
       HOST_WIDE_INT mask_value = 0;
 
-      /* Values that __cmpkf2 returns.  */
+      /* Values that __cmpokf2/__cmpukf2 returns.  */
 #define PPC_CMP_UNORDERED	0x1		/* isnan (a) || isnan (b).  */
 #define PPC_CMP_EQUAL		0x2		/* a == b.  */
 #define PPC_CMP_GREATER_THEN	0x4		/* a > b.  */
@@ -20280,6 +20281,7 @@  rs6000_generate_compare (rtx cmp, machin
 }
 
 
+
 /* Expand floating point conversion to/from __float128 and __ibm128.  */
 
 void
@@ -20288,60 +20290,121 @@  rs6000_expand_float128_convert (rtx dest
   machine_mode dest_mode = GET_MODE (dest);
   machine_mode src_mode = GET_MODE (src);
   convert_optab cvt = unknown_optab;
+  bool do_move = false;
   rtx libfunc = NULL_RTX;
   rtx dest2;
 
   if (dest_mode == src_mode)
     gcc_unreachable ();
 
+  /* Eliminate memory operations.  */
+  if (MEM_P (src))
+    src = force_reg (src_mode, src);
+
+  if (MEM_P (dest))
+    {
+      rtx tmp = gen_reg_rtx (dest_mode);
+      rs6000_expand_float128_convert (tmp, src, unsigned_p);
+      rs6000_emit_move (dest, tmp, dest_mode);
+      return;
+    }
+
+  /* Convert to IEEE 128-bit floating point.  */
   if (FLOAT128_IEEE_P (dest_mode))
     {
-      if (src_mode == SFmode
-	  || src_mode == DFmode
-	  || FLOAT128_IBM_P (src_mode))
-	cvt = sext_optab;
+      switch (src_mode)
+	{
+	case DFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (src_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	case SFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (FLOAT128_IEEE_P (src_mode))
-	emit_move_insn (dest, gen_lowpart (dest_mode, src));
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (src_mode))
+	    cvt = sext_optab;
+	  else
+	    do_move = true;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
+  /* Convert from IEEE 128-bit floating point.  */
   else if (FLOAT128_IEEE_P (src_mode))
     {
-      if (dest_mode == SFmode
-	  || dest_mode == DFmode
-	  || FLOAT128_IBM_P (dest_mode))
-	cvt = trunc_optab;
+      switch (dest_mode)
+	{
+	case DFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (dest_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	case SFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (dest_mode))
+	    cvt = trunc_optab;
+	  else
+	    do_move = true;
+	  break;
+
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
+  /* Both IBM format.  */
+  else if (FLOAT128_IBM_P (dest_mode) && FLOAT128_IBM_P (src_mode))
+    do_move = true;
+
   else
     gcc_unreachable ();
 
-  gcc_assert (cvt != unknown_optab);
-  libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
-  gcc_assert (libfunc != NULL_RTX);
-
-  dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
-				   src_mode);
-
-  gcc_assert (dest != NULL_RTX);
-  if (!rtx_equal_p (dest, dest2))
-    emit_move_insn (dest, dest2);
+  /* Handle conversion between TFmode/KFmode.  */
+  if (do_move)
+    emit_move_insn (dest, gen_lowpart (dest_mode, src));
+
+  /* Call an external function to do the conversion.  */
+  else if (cvt != unknown_optab)
+    {
+      libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
+      gcc_assert (libfunc != NULL_RTX);
+
+      dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
+				       src_mode);
+
+      gcc_assert (dest2 != NULL_RTX);
+      if (!rtx_equal_p (dest, dest2))
+	emit_move_insn (dest, dest2);
+    }
+
+  else
+    gcc_unreachable ();
 
   return;
 }
 
+
 /* Emit the RTL for an sISEL pattern.  */
 
 void