From 4fd18c782de4833736d9b3604a3b031f74429f5c Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Thu, 11 May 2017 14:13:31 +0000 Subject: [PATCH] cmpb-1.c: New test. gcc/testsuite/ChangeLog: 2017-05-11 Kelvin Nilsen * 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-11 Kelvin Nilsen * 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. From-SVN: r247907 --- gcc/ChangeLog | 22 ++++++ gcc/config/rs6000/rs6000-builtin.def | 35 +++++++++ gcc/config/rs6000/rs6000-c.c | 78 ++++++++++++++++++--- gcc/config/rs6000/rs6000.c | 1 + gcc/config/rs6000/rs6000.h | 1 + gcc/doc/extend.texi | 18 +++++ gcc/testsuite/ChangeLog | 8 +++ gcc/testsuite/gcc.target/powerpc/cmpb-1.c | 31 ++++++++ gcc/testsuite/gcc.target/powerpc/cmpb-2.c | 31 ++++++++ gcc/testsuite/gcc.target/powerpc/cmpb-3.c | 30 ++++++++ gcc/testsuite/gcc.target/powerpc/cmpb32-1.c | 27 +++++++ gcc/testsuite/gcc.target/powerpc/cmpb32-2.c | 27 +++++++ 12 files changed, 298 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/cmpb-1.c create mode 100644 gcc/testsuite/gcc.target/powerpc/cmpb-2.c create mode 100644 gcc/testsuite/gcc.target/powerpc/cmpb-3.c create mode 100644 gcc/testsuite/gcc.target/powerpc/cmpb32-1.c create mode 100644 gcc/testsuite/gcc.target/powerpc/cmpb32-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a317c211ebe..447f72f95ec 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2017-05-11 Kelvin Nilsen + + * 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. + 2017-05-11 Richard Biener PR tree-optimization/80705 diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 50b1588e0c2..e5ab9d3255c 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -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. */ @@ -1787,6 +1815,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_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) @@ -1873,6 +1905,9 @@ BU_P8V_AV_P (VCMPEQUD_P, "vcmpequd_p", CONST, vector_eq_v2di_p) 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") diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 3309f8de2d9..ccf9cac1db8 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -5362,6 +5362,11 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { 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, @@ -6424,17 +6429,48 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, 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) + { + 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 ((GET_MODE_PRECISION (arg1_mode) > 32) + || (GET_MODE_PRECISION (arg2_mode) > 32)) + { + /* 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); @@ -6442,7 +6478,27 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, 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); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index e77026a931c..d55e552f492 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -3873,6 +3873,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) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 3780a49d902..c4e98dd2f13 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -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. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index f2b304211eb..a16396155ef 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -15106,6 +15106,24 @@ Similar to @code{__builtin_nans}, except the return type is @code{__float128}. @findex __builtin_nansq @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}): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1af2958dfee..411996f2794 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-05-11 Kelvin Nilsen + + * 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. + 2017-05-11 Richard Biener PR tree-optimization/80705 diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb-1.c b/gcc/testsuite/gcc.target/powerpc/cmpb-1.c new file mode 100644 index 00000000000..1f04a76e7e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/cmpb-1.c @@ -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)); +} diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb-2.c b/gcc/testsuite/gcc.target/powerpc/cmpb-2.c new file mode 100644 index 00000000000..4dde1742cab --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/cmpb-2.c @@ -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)); +} diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb-3.c b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c new file mode 100644 index 00000000000..edb62f19b83 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c @@ -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)); +} diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb32-1.c b/gcc/testsuite/gcc.target/powerpc/cmpb32-1.c new file mode 100644 index 00000000000..6338ccf0cb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/cmpb32-1.c @@ -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)); +} diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb32-2.c b/gcc/testsuite/gcc.target/powerpc/cmpb32-2.c new file mode 100644 index 00000000000..30403a1482f --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/cmpb32-2.c @@ -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)); +} -- 2.30.2