This patch adds support for the compare bytes instruction, which has
been available in the rs6000 architecture since Power6.

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/ChangeLog:

2017-04-28  Kelvin Nilsen  <kel...@gcc.gnu.org>

        * config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add
        support for TARGET_CMPB.
        * config/rs6000/rs6000.h: Add support for RS6000_BTM_CMPB.
        * config/rs6000/rs6000-builtin.def (BU_P6_CMPB_2): New macro.
        (BU_P6_64BIT_CMPB_2): New macro.
        (CMPB_32): Add compare-bytes support for 32-bit only targets.
        (CMPB): Add compare-bytes support for 32-bit and 64-bit targets.
        * doc/extend.texi (PowerPC AltiVec Built-in Functions): Add
        documentation of __builtin_cmpb and __builtin_cmpb_32 built-in
        functions.

gcc/testsuite/ChangeLog:

2017-04-28  Kelvin Nilsen  <kel...@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.


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,26 @@
                     | RS6000_BTC_SPECIAL),                             \
                    CODE_FOR_nothing)                   /* ICODE */
 
+/* ISA 2.05 (power6) convenience macros. */
+/* For functions that depend on the CMPB instruction */
+#define BU_P6_CMPB_2(ENUM, NAME, ATTR, ICODE)                          \
+  RS6000_BUILTIN_2 (P6_BUILTIN_ ## ENUM,               /* ENUM */      \
+                   "__builtin_" 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_CMPB_2(ENUM, NAME, ATTR, ICODE)                    \
+  RS6000_BUILTIN_2 (P6_BUILTIN_ ## ENUM,               /* ENUM */      \
+                   "__builtin_" NAME,                  /* NAME */      \
+                   RS6000_BTM_CMPB                                     \
+                     | RS6000_BTM_64BIT,               /* MASK */      \
+                   (RS6000_BTC_ ## ATTR                /* ATTR */      \
+                    | RS6000_BTC_BINARY),                              \
+                   CODE_FOR_ ## ICODE)                 /* 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 +1798,10 @@ BU_VSX_OVERLOAD_X (ST,        "st")
 BU_VSX_OVERLOAD_X (XL,      "xl")
 BU_VSX_OVERLOAD_X (XST,             "xst")
 
+/* 2 argument CMPB instructions added in ISA 2.05. */
+BU_P6_CMPB_2 (CMPB_32,        "cmpb_32",       CONST,  cmpbsi3)
+BU_P6_64BIT_CMPB_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)
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: cmopare 
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/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi (revision 247069)
+++ gcc/doc/extend.texi (working copy)
@@ -15107,6 +15107,22 @@ 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
+long long __builtin_cmpb (long long, long long);
+int __builtin_cmpb_32 (int, int);
+@end smallexample
+
+The @code{__builtin_cmpb} and @code{__builtin_cmpb_32} functions
+perform a byte-wise compare on the contents of their 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 input bytes are equal, and 0 if the input bytes
+are not equal.  The @code{__builtin_cmpb} function requires a
+64-bit environment.
+
+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 247279)
@@ -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 ();
+
+long long int
+do_compare (long long int a, long long int b)
+{
+  return __builtin_cmpb (a, b);
+}
+
+void
+expect (long long int pattern, long long int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff00000000000000,
+         do_compare (0x0123456789abcdef, 0x0100000000000000));
+  expect (0x00ffffffffffffff,
+         do_compare (0x0123456789abcdef, 0x0023456789abcdef));
+  expect (0x00000000000000ff,
+         do_compare (0x00000000000000ef, 0x0123456789abcdef));
+}
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 247393)
@@ -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 ();
+
+long long int
+do_compare (long long int a, long long int b)
+{
+  return __builtin_cmpb (a, b);        /* { dg-warning "implicit declaration 
of function '__builtin_cmpb'" } */
+}
+
+void
+expect (long long int pattern, long long int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff00000000000000,
+         do_compare (0x0123456789abcdef, 0x0100000000000000));
+  expect (0x00ffffffffffffff,
+         do_compare (0x0123456789abcdef, 0x0023456789abcdef));
+  expect (0x00000000000000ff,
+         do_compare (0x00000000000000ef, 0x0123456789abcdef));
+}
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 247393)
@@ -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-warning "implicit declaration 
of function '__builtin_cmpb'" } */
+}
+
+void expect (long long int pattern, long long int value)
+{
+  if (pattern != value)
+    abort ();
+}
+
+int
+main (int argc, char *argv[])
+{
+  expect (0xff00000000000000,
+         do_compare (0x0123456789abcdef, 0x0100000000000000));
+  expect (0x00ffffffffffffff,
+         do_compare (0x0123456789abcdef, 0x0023456789abcdef));
+  expect (0x00000000000000ff,
+         do_compare (0x00000000000000ef, 0x0123456789abcdef));
+}
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 247279)
@@ -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 ();
+
+int
+do_compare (int a, int b)
+{
+  return __builtin_cmpb_32 (a, b);
+}
+
+void
+expect (int pattern, 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 247393)
@@ -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 ();
+
+int
+do_compare (int a, int b)
+{
+  return __builtin_cmpb_32 (a, b);  /* { dg-warning "implicit declaration of 
function '__builtin_cmpb_32'" } */
+}
+
+void
+expect (int pattern, 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));
+}

Reply via email to