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)); +}