public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v2,rs6000] Add built-in function support for compare bytes instruction
@ 2017-05-08 17:15 Kelvin Nilsen
  2017-05-09 20:58 ` Segher Boessenkool
  0 siblings, 1 reply; 2+ messages in thread
From: Kelvin Nilsen @ 2017-05-08 17:15 UTC (permalink / raw)
  To: gcc-patches; +Cc: Segher Boessenkool


This patch adds support for the compare bytes instruction, which has
been available in the rs6000 architecture since Power6.  Thank you to
Segher Boessenkool for feedback on the original submission of this
patch.  The following refinements have been incorporated:

1. Changed the implementation and documentation to present a single
overloaded function that handles either 32-bit or 64-bit arguments.

2. Corrected the spelling of compare in the comment describing the
RS6000_BTM_CMPB macro.  In response to reviewer question of whether
this line is too long: it is not.  It only appears that way due to
alignment of tabs in the diff output.

The patch has been bootstrapped and tested on powerpc64le-unknown-linux
and powerpc-unknown-linux (big-endian, with both -m32 and -m64 target
options) with no regressions.

Is this ok for the trunk?

gcc/testsuite/ChangeLog:

2017-05-08  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	* gcc.target/powerpc/cmpb-1.c: New test.
	* gcc.target/powerpc/cmpb-2.c: New test.
	* gcc.target/powerpc/cmpb-3.c: New test.
	* gcc.target/powerpc/cmpb32-1.c: New test.
	* gcc.target/powerpc/cmpb32-2.c: New test.

gcc/ChangeLog:

2017-05-08  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	* config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add
	array entries to represent two legal parameterizations of the
	overloaded __builtin_cmpb function, as represented by the
	P6_OV_BUILTIN_CMPB constant.
	(altivec_resolve_overloaded_builtin): Add special case handling
	for the __builtin_cmpb function, as represented by the
	P6_OV_BUILTIN_CMPB constant.
	* config/rs6000/rs6000-builtin.def (BU_P6_2): New macro.
	(BU_P6_64BIT_2): New macro.
	(BU_P6_OVERLOAD_2): New macro
	(CMPB_32): Add 32-bit compare-bytes support for 32-bit only targets.
	(CMPB): Add 64-bit compare-bytes support for 32-bit and 64-bit targets.
	(CMPB): Add overload support to represent both 32-bit and 64-bit
	compare-bytes function.
	* config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add
	support for TARGET_CMPB.
	* config/rs6000/rs6000.h: Add support for RS6000_BTM_CMPB.
	* doc/extend.texi (PowerPC AltiVec Built-in Functions): Add
	documentation of the __builtin_cmpb overloaded built-in function.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 247069)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -3788,6 +3788,7 @@ HOST_WIDE_INT
 rs6000_builtin_mask_calculate (void)
 {
   return (((TARGET_ALTIVEC)		    ? RS6000_BTM_ALTIVEC   : 0)
+	  | ((TARGET_CMPB)		    ? RS6000_BTM_CMPB	   : 0)
 	  | ((TARGET_VSX)		    ? RS6000_BTM_VSX	   : 0)
 	  | ((TARGET_SPE)		    ? RS6000_BTM_SPE	   : 0)
 	  | ((TARGET_PAIRED_FLOAT)	    ? RS6000_BTM_PAIRED	   : 0)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 247069)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -2717,6 +2717,7 @@ extern int frame_pointer_needed;
    aren't in target_flags.  */
 #define RS6000_BTM_ALWAYS	0		/* Always enabled.  */
 #define RS6000_BTM_ALTIVEC	MASK_ALTIVEC	/* VMX/altivec vectors.  */
+#define RS6000_BTM_CMPB		MASK_CMPB	/* ISA 2.05: compare bytes.  */
 #define RS6000_BTM_VSX		MASK_VSX	/* VSX (vector/scalar).  */
 #define RS6000_BTM_P8_VECTOR	MASK_P8_VECTOR	/* ISA 2.07 vector.  */
 #define RS6000_BTM_P9_VECTOR	MASK_P9_VECTOR	/* ISA 3.0 vector.  */
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 247069)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -5348,6 +5348,11 @@ const struct altivec_builtin_types altivec_overloa
     RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI,
     RS6000_BTI_unsigned_V1TI, 0 },
 
+  { P6_OV_BUILTIN_CMPB, P6_BUILTIN_CMPB_32,
+    RS6000_BTI_UINTSI, RS6000_BTI_UINTSI, RS6000_BTI_UINTSI, 0 },
+  { P6_OV_BUILTIN_CMPB, P6_BUILTIN_CMPB,
+    RS6000_BTI_UINTDI, RS6000_BTI_UINTDI, RS6000_BTI_UINTDI, 0 },
+
   { P8V_BUILTIN_VEC_VUPKHSW, P8V_BUILTIN_VUPKHSW,
     RS6000_BTI_V2DI, RS6000_BTI_V4SI, 0, 0 },
   { P8V_BUILTIN_VEC_VUPKHSW, P8V_BUILTIN_VUPKHSW,
@@ -6409,25 +6414,76 @@ altivec_resolve_overloaded_builtin (location_t loc
     for (desc = altivec_overloaded_builtins;
 	 desc->code && desc->code != fcode; desc++)
       continue;
-    
-    /* For arguments after the last, we have RS6000_BTI_NOT_OPAQUE in
-       the opX fields.  */
-    for (; desc->code == fcode; desc++)
+
+    /* Need to special case __builtin_cmp because the overloaded forms
+       of this function take (unsigned int, unsigned int) or (unsigned
+       long long int, unsigned long long int).  Since C conventions
+       allow the respective argument types to be implicitly coerced into
+       each other, the default handling does not provide adequate
+       discrimination between the desired forms of the function.  */
+    if (fcode == P6_OV_BUILTIN_CMPB)
       {
-	if ((desc->op1 == RS6000_BTI_NOT_OPAQUE
-	     || rs6000_builtin_type_compatible (types[0], desc->op1))
-	    && (desc->op2 == RS6000_BTI_NOT_OPAQUE
-		|| rs6000_builtin_type_compatible (types[1], desc->op2))
-	    && (desc->op3 == RS6000_BTI_NOT_OPAQUE
-		|| rs6000_builtin_type_compatible (types[2], desc->op3)))
+	int overloaded_code;
+	int arg1_mode = TYPE_MODE (types[0]);
+	int arg2_mode = TYPE_MODE (types[1]);
+
+	if (nargs != 2)
 	  {
-	    if (rs6000_builtin_decls[desc->overloaded_code] != NULL_TREE)
-	      return altivec_build_resolved_builtin (args, n, desc);
-	    else
-	      unsupported_builtin = true;
+	    error ("__builtin_cmpb only accepts 2 arguments");
+	    return error_mark_node;
 	  }
+
+      /* If any supplied arguments are wider than 32 bits, resolve to
+	 64-bit variant of built-in function.  */
+      if ((arg1_mode == TImode) || (arg1_mode == DImode) ||
+	  (arg2_mode == TImode) || (arg2_mode == DImode))
+	{
+	  /* Assure all argument and result types are compatible with
+	     the built-in function represented by P6_BUILTIN_CMPB.  */
+	  overloaded_code = P6_BUILTIN_CMPB;
+	}
+      else
+	{
+	  /* Assure all argument and result types are compatible with
+	     the built-in function represented by P6_BUILTIN_CMPB_32.  */
+	  overloaded_code = P6_BUILTIN_CMPB_32;
+	}
+
+      while (desc->code && desc->code == fcode &&
+	     desc->overloaded_code != overloaded_code)
+	desc++;
+
+      if (desc->code && (desc->code == fcode)
+	  && rs6000_builtin_type_compatible (types[0], desc->op1)
+	  && rs6000_builtin_type_compatible (types[1], desc->op2))
+	{
+	  if (rs6000_builtin_decls[desc->overloaded_code] != NULL_TREE)
+	    return altivec_build_resolved_builtin (args, n, desc);
+	  else
+	    unsupported_builtin = true;
+	}
       }
-    
+    else
+      {
+	/* For arguments after the last, we have RS6000_BTI_NOT_OPAQUE in
+	   the opX fields.  */
+	for (; desc->code == fcode; desc++)
+	  {
+	    if ((desc->op1 == RS6000_BTI_NOT_OPAQUE
+		 || rs6000_builtin_type_compatible (types[0], desc->op1))
+		&& (desc->op2 == RS6000_BTI_NOT_OPAQUE
+		    || rs6000_builtin_type_compatible (types[1], desc->op2))
+		&& (desc->op3 == RS6000_BTI_NOT_OPAQUE
+		    || rs6000_builtin_type_compatible (types[2], desc->op3)))
+	      {
+		if (rs6000_builtin_decls[desc->overloaded_code] != NULL_TREE)
+		  return altivec_build_resolved_builtin (args, n, desc);
+		else
+		  unsupported_builtin = true;
+	      }
+	  }
+      }
+
     if (unsupported_builtin)
       {
 	const char *name = rs6000_overloaded_builtin_name (fcode);
Index: gcc/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(revision 247069)
+++ gcc/config/rs6000/rs6000-builtin.def	(working copy)
@@ -339,6 +339,34 @@
 		     | RS6000_BTC_SPECIAL),				\
 		    CODE_FOR_nothing)			/* ICODE */
 
+/* ISA 2.05 (power6) convenience macros. */
+/* For functions that depend on the CMPB instruction */
+#define BU_P6_2(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_2 (P6_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_p6_" NAME,		/* NAME */	\
+		    RS6000_BTM_CMPB,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+/* For functions that depend on 64-BIT support and on the CMPB instruction */
+#define BU_P6_64BIT_2(ENUM, NAME, ATTR, ICODE)			\
+  RS6000_BUILTIN_2 (P6_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_p6_" NAME,		/* NAME */	\
+		    RS6000_BTM_CMPB			   		\
+		      | RS6000_BTM_64BIT,		/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+#define BU_P6_OVERLOAD_2(ENUM, NAME)					\
+  RS6000_BUILTIN_2 (P6_OV_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_CMPB,			/* MASK */	\
+		    (RS6000_BTC_OVERLOADED		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_nothing)			/* ICODE */
+
 /* ISA 2.07 (power8) vector convenience macros.  */
 /* For the instructions that are encoded as altivec instructions use
    __builtin_altivec_ as the builtin name.  */
@@ -1778,6 +1806,10 @@ BU_VSX_OVERLOAD_X (ST,	     "st")
 BU_VSX_OVERLOAD_X (XL,	     "xl")
 BU_VSX_OVERLOAD_X (XST,	     "xst")
 \f
+/* 2 argument CMPB instructions added in ISA 2.05. */
+BU_P6_2 (CMPB_32,        "cmpb_32",	CONST,	cmpbsi3)
+BU_P6_64BIT_2 (CMPB,     "cmpb",	CONST,	cmpbdi3)
+
 /* 1 argument VSX instructions added in ISA 2.07.  */
 BU_P8V_VSX_1 (XSCVSPDPN,      "xscvspdpn",	CONST,	vsx_xscvspdpn)
 BU_P8V_VSX_1 (XSCVDPSPN,      "xscvdpspn",	CONST,	vsx_xscvdpspn)
@@ -1864,6 +1896,9 @@ BU_P8V_AV_P (VCMPEQUD_P,	"vcmpequd_p",	CONST,	vect
 BU_P8V_AV_P (VCMPGTSD_P,	"vcmpgtsd_p",	CONST,	vector_gt_v2di_p)
 BU_P8V_AV_P (VCMPGTUD_P,	"vcmpgtud_p",	CONST,	vector_gtu_v2di_p)
 
+/* ISA 2.05 overloaded 2 argument functions.  */
+BU_P6_OVERLOAD_2 (CMPB, "cmpb")
+
 /* ISA 2.07 vector overloaded 1 argument functions.  */
 BU_P8V_OVERLOAD_1 (VUPKHSW,	"vupkhsw")
 BU_P8V_OVERLOAD_1 (VUPKLSW,	"vupklsw")
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 247069)
+++ gcc/doc/extend.texi	(working copy)
@@ -15107,6 +15107,24 @@ Similar to @code{__builtin_nans}, except the retur
 @end table
 
 The following built-in functions are available for the PowerPC family
+of processors, starting with ISA 2.05 or later (@option{-mcpu=power6}
+or @option{-mcmpb}):
+@smallexample
+unsigned long long __builtin_cmpb (unsigned long long int, unsigned long long int);
+unsigned int __builtin_cmpb (unsigned int, unsigned int);
+@end smallexample
+
+The @code{__builtin_cmpb} function
+performs a byte-wise compare on the contents of its two arguments,
+returning the result of the byte-wise comparison as the returned
+value.  For each byte comparison, the corresponding byte of the return
+value holds 0xff if the input bytes are equal and 0 if the input bytes
+are not equal.  If either of the arguments to this built-in function
+is wider than 32 bits, the function call expands into the form that
+expects @code{unsigned long long int} arguments
+which is only available on 64-bit targets.
+
+The following built-in functions are available for the PowerPC family
 of processors, starting with ISA 2.06 or later (@option{-mcpu=power7}
 or @option{-mpopcntd}):
 @smallexample
Index: gcc/testsuite/gcc.target/powerpc/cmpb-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/cmpb-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/cmpb-1.c	(revision 247560)
@@ -0,0 +1,31 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power6" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-options "-mcpu=power6" } */
+
+void abort ();
+
+unsigned long long int
+do_compare (unsigned long long int a, unsigned long long int b)
+{
+  return __builtin_cmpb (a, b);
+}
+
+void
+expect (unsigned long long int pattern, unsigned long long int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff00000000000000LL,
+	  do_compare (0x0123456789abcdefLL, 0x0100000000000000LL));
+  expect (0x00ffffffffffffff,
+	  do_compare (0x0123456789abcdefLL, 0x0023456789abcdefLL));
+  expect (0x00000000000000ff,
+	  do_compare (0x00000000000000efLL, 0x0123456789abcdefLL));
+}
Index: gcc/testsuite/gcc.target/powerpc/cmpb-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/cmpb-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/cmpb-2.c	(revision 247560)
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power5" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_popcntb_ok } */
+/* { dg-options "-mcpu=power5" } */
+
+void abort ();
+
+unsigned long long int
+do_compare (unsigned long long int a, unsigned long long int b)
+{
+  return __builtin_cmpb (a, b);	/* { dg-warning "implicit declaration of function '__builtin_cmpb'" } */
+}
+
+void
+expect (unsigned long long int pattern, unsigned long long int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff00000000000000LL,
+	  do_compare (0x0123456789abcdefLL, 0x0100000000000000LL));
+  expect (0x00ffffffffffffff,
+	  do_compare (0x0123456789abcdefLL, 0x0023456789abcdefLL));
+  expect (0x00000000000000ff,
+	  do_compare (0x00000000000000efLL, 0x0123456789abcdefLL));
+}
Index: gcc/testsuite/gcc.target/powerpc/cmpb-3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/cmpb-3.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/cmpb-3.c	(revision 247649)
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power6" } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_popcntb_ok } */
+/* { dg-options "-mcpu=power6" } */
+
+void abort ();
+
+long long int
+do_compare (long long int a, long long int b)
+{
+  return __builtin_cmpb (a, b);	/* { dg-error "Builtin function __builtin_cmpb not supported in this compiler configuration" } */
+}
+
+void expect (long long int pattern, long long int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff00000000000000LL,
+	  do_compare (0x0123456789abcdefLL, 0x0100000000000000LL));
+  expect (0x00ffffffffffffff,
+	  do_compare (0x0123456789abcdefLL, 0x0023456789abcdefLL));
+  expect (0x00000000000000ff,
+	  do_compare (0x00000000000000efLL, 0x0123456789abcdefLL));
+}
Index: gcc/testsuite/gcc.target/powerpc/cmpb32-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/cmpb32-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/cmpb32-1.c	(revision 247560)
@@ -0,0 +1,27 @@
+/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power6" } } */
+/* { dg-require-effective-target dfp_hw } */
+/* { dg-options "-mcpu=power6" } */
+
+void abort ();
+
+unsigned int
+do_compare (unsigned int a, unsigned int b)
+{
+  return __builtin_cmpb (a, b);
+}
+
+void
+expect (unsigned int pattern, unsigned int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff000000, do_compare (0x12345678, 0x12000000));
+  expect (0x00ffffff, do_compare (0x12345678, 0x00345678));
+  expect (0x000000ff, do_compare (0x00000078, 0x12345678));
+}
Index: gcc/testsuite/gcc.target/powerpc/cmpb32-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/cmpb32-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/cmpb32-2.c	(revision 247560)
@@ -0,0 +1,27 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power5" } } */
+/* { dg-require-effective-target powerpc_popcntb_ok } */
+/* { dg-options "-mcpu=power5" } */
+
+void abort ();
+
+unsigned int
+do_compare (unsigned int a, unsigned int b)
+{
+  return __builtin_cmpb (a, b);  /* { dg-warning "implicit declaration of function '__builtin_cmpb'" } */
+}
+
+void
+expect (unsigned int pattern, unsigned int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff000000, do_compare (0x12345678, 0x12000000));
+  expect (0x00ffffff, do_compare (0x12345678, 0x00345678));
+  expect (0x000000ff, do_compare (0x00000078, 0x12345678));
+}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2,rs6000] Add built-in function support for compare bytes instruction
  2017-05-08 17:15 [PATCH v2,rs6000] Add built-in function support for compare bytes instruction Kelvin Nilsen
@ 2017-05-09 20:58 ` Segher Boessenkool
  0 siblings, 0 replies; 2+ messages in thread
From: Segher Boessenkool @ 2017-05-09 20:58 UTC (permalink / raw)
  To: Kelvin Nilsen; +Cc: gcc-patches

Hi Kelvin,

On Mon, May 08, 2017 at 11:04:59AM -0600, Kelvin Nilsen wrote:
> +      /* If any supplied arguments are wider than 32 bits, resolve to
> +	 64-bit variant of built-in function.  */
> +      if ((arg1_mode == TImode) || (arg1_mode == DImode) ||
> +	  (arg2_mode == TImode) || (arg2_mode == DImode))

Use GET_MODE_PRECISION instead?  Or GET_MODE_BITSIZE, not sure which
is better here.

The rest of the patch looks fine to me.


Segher

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-05-09 20:55 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-08 17:15 [PATCH v2,rs6000] Add built-in function support for compare bytes instruction Kelvin Nilsen
2017-05-09 20:58 ` Segher Boessenkool

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).