+2017-05-11 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.
+
2017-05-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/80705
| 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. */
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)
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")
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,
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);
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);
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)
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. */
@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}):
+2017-05-11 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.
+
2017-05-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/80705
--- /dev/null
+/* { 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));
+}
--- /dev/null
+/* { 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));
+}
--- /dev/null
+/* { 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));
+}
--- /dev/null
+/* { 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));
+}
--- /dev/null
+/* { 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));
+}