diff mbox

[v3,rs6000] Add built-in function support for Power9 byte instructions

Message ID 89d65b8f-3e15-5c08-2554-16341b7de999@linux.vnet.ibm.com
State New
Headers show

Commit Message

Kelvin Nilsen Dec. 13, 2016, 12:40 a.m. UTC
This patch adds built-in function support for the new setb, cmprb, and
cmpeqb Power9 instructions.  This third version of the patch differs
from the second in the following ways:

1. Changed the name of the *cmprb, *setb, *cmprb2, and *cmpeqb new
instructions to *cmprb_internal, *setb_internal, and *cmprb2_internal
respectively.

2. Added comments to the cmprb, setb, and cmprb2 instructions to
acknowledge that, as implemented, we do not currently support the use
of double-integer operands though support for this might be added in
the future.

3. Changed the names of the new non-overloaded builtin functions to 
be of the form __builtin_scalar_<xxx> instead of
__builtin_altivec_<xxx>.  Changed the names of the new overloaded
functions to be of the form __builtin_<xxx> instead of
__builtin_scalar_<xxx>.

4. Corrected the comments describing range encodings and simplified the
descriptions by speaking of individual bytes instead of bit numbers
(cmprb, cmprb2, cmpeqb define_expand patterns and *cmprb_internal,
*cmprb2_internal, *cmpeqb_internal define_insn patterns).

5. Updated documentation to use the new function names and to speak of
range encodings in terms of individual bytes instead of bit numbers.

6. Changed the test cases to use the new function names.

7. Corrected bit shifting of arguments in the byte-in-range-0.c and
byte-in-range-1.c test cases.


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:

2016-12-12  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	* gcc.target/powerpc/byte-in-either-range-0.c: New test.
	* gcc.target/powerpc/byte-in-either-range-1.c: New test.
	* gcc.target/powerpc/byte-in-range-0.c: New test.
	* gcc.target/powerpc/byte-in-range-1.c: New test.
	* gcc.target/powerpc/byte-in-set-0.c: New test.
	* gcc.target/powerpc/byte-in-set-1.c: New test.
	* gcc.target/powerpc/byte-in-set-2.c: New test.


gcc/ChangeLog:

2016-12-12  Kelvin Nilsen  <kelvin@gcc.gnu.org>

	* config/rs6000/altivec.md (UNSPEC_CMPRB): New unspec value.
	(UNSPEC_CMPRB2): New unspec value.
	(UNSPEC_CMPEQB): New unspec value.
	(cmprb): New expansion.
	(*cmprb_internal): New insn.
	(*setb_internal): New insn.
	(cmprb2): New expansion.
	(*cmprb2_internal): New insn.
	(cmpeqb): New expansion.
	(*cmpeqb_internal): New insn.
	* config/rs6000/rs6000-builtin.def (BU_P9_2): New macro.
	(BU_P9_64BIT_2): Likewise.
	(BU_P9_OVERLOAD_2): Likewise.
	(CMPRB): Add byte-in-range built-in function.
	(CMBRB2): Add byte-in-either-range built-in function.
	(CMPEQB): Add byte-in-set built-in function.
	(CMPRB): Add overload support for byte-in-range function.
	(CMPRB2): Add overload support for byte-in-either-range function.
	(CMPEQB): Add overload support for byte-in-set built-in function.
	* config/rs6000/rs6000-c.c (P9_BUILTIN_CMPRB): Macro expansion to
	define argument types for new builtin. 
	(P9_BUILTIN_CMPRB2): Likewise.
	(P9_BUILTIN_CMPEQB): Likewise.
	* doc/extend.texi (PowerPC AltiVec Built-in Functions): Rearrange
	the order of presentation for certain built-in functions
	(scalar_extract_exp, scalar_extract_sig, scalar_insert_exp)
	(scalar_cmp_exp_gt, scalar_cmp_exp_lt, scalar_cmp_exp_eq)
	(scalar_cmp_exp_unordered, scalar_test_data_class)
	(scalar_test_neg) to improve locality and flow.  Document
	the new __builtin_scalar_byte_in_set,
	__builtin_scalar_byte_in_range, and
	__builtin_scalar_byte_in_either_range functions.

Comments

Segher Boessenkool Dec. 13, 2016, 10:14 p.m. UTC | #1
Hi Kelvin,

On Mon, Dec 12, 2016 at 05:40:05PM -0700, Kelvin Nilsen wrote:
> 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?

Yes it is, much better, thanks!  Two comments below, please fix the testcase
one before commit if it is indeed a problem:

> +;; Though the instructions to which this expansion maps operate on
> +;; 64-bit registers, the current implementation only operates on
> +;; SI-mode operands as the high-order bits provide no information
> +;; that is not already available in the low-order bits.  To avoid the
> +;; costs of data widening operations, a future enhancement might add
> +;; support for DI-mode operands.

And operands[1] could be QImode.

> +(define_expand "cmprb"
> +  [(set (match_dup 3)
> +	(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
> +		    (match_operand:SI 2 "gpc_reg_operand" "r")]
> +	 UNSPEC_CMPRB))


> --- gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c	(revision 0)
> +++ gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c	(working copy)

Did you forget the scan-assembler here and in the next one, or do you only
want to test it does indeed compile?


Segher
Kelvin Nilsen Dec. 14, 2016, 12:25 a.m. UTC | #2
Thanks for your quick feedback.

I'll update the comments regarding possible future enhancement to
support QImode for operands[1] as well.

Regarding the two test cases that are missing the scan-assembler
directive (byte-in-set-1.c and byte-in-set-2.c), those tests are both
expected to fail.  They are checking that the compiler rejects those
programs with appropriate error messages.

On 12/13/2016 03:14 PM, Segher Boessenkool wrote:
> Hi Kelvin,
> 
> On Mon, Dec 12, 2016 at 05:40:05PM -0700, Kelvin Nilsen wrote:
>> 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?
> 
> Yes it is, much better, thanks!  Two comments below, please fix the testcase
> one before commit if it is indeed a problem:
> 
>> +;; Though the instructions to which this expansion maps operate on
>> +;; 64-bit registers, the current implementation only operates on
>> +;; SI-mode operands as the high-order bits provide no information
>> +;; that is not already available in the low-order bits.  To avoid the
>> +;; costs of data widening operations, a future enhancement might add
>> +;; support for DI-mode operands.
> 
> And operands[1] could be QImode.
> 
>> +(define_expand "cmprb"
>> +  [(set (match_dup 3)
>> +	(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
>> +		    (match_operand:SI 2 "gpc_reg_operand" "r")]
>> +	 UNSPEC_CMPRB))
> 
> 
>> --- gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c	(revision 0)
>> +++ gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c	(working copy)
> 
> Did you forget the scan-assembler here and in the next one, or do you only
> want to test it does indeed compile?
> 
> 
> Segher
> 
>
Segher Boessenkool Dec. 14, 2016, 1:06 a.m. UTC | #3
On Tue, Dec 13, 2016 at 05:25:52PM -0700, Kelvin Nilsen wrote:
> Regarding the two test cases that are missing the scan-assembler
> directive (byte-in-set-1.c and byte-in-set-2.c), those tests are both
> expected to fail.  They are checking that the compiler rejects those
> programs with appropriate error messages.

Oh, apparently I cannot read.  Sorry about that.


Segher
Sandra Loosemore Dec. 14, 2016, 4:11 a.m. UTC | #4
On 12/12/2016 05:40 PM, Kelvin Nilsen wrote:

> @@ -15105,6 +15109,24 @@ If all of the enabled test conditions are false, t
>   The @code{scalar_test_neg} built-in functions return a non-zero value
>   if their @code{source} argument holds a negative value.
>
> +The @code{__builtin_byte_in_set} function requires a
> +64-bit environment supporting ISA 3.0 or later.  This function returns
> +a non-zero value if and only if its @code{u} argument exactly equals one of
> +the eight bytes contained within its 64-bit @code{set} argument.
> +
> +The @code{__builtin_byte_in_range} and
> +@code{__builtin_byte_in_either_range} require an environment
> +supporting ISA 3.0 or later.  For these two functions, the
> +@code{range} argument is encoded as 4 bytes, organized as
> +@code{hi_1:lo_1:hi_2:lo_2}.
> +The first of these functions returns a
> +non-zero value if and only if its @code{u} argument is within the
> +range bounded between @code{lo_2} and @code{hi_2} inclusive.
> +The second of these functions returns non-zero if and only
> +if its @code{u} argument is either within the range bounded between
> +@code{lo_1} and @code{hi_1} inclusive or is within the range bounded between
> +@code{lo_2} and @code{hi_2} inclusive.

I would prefer that you refer to the functions by name instead of "the 
first/second of these functions".

Also, you have a parallel construction problem in the second sentence: 
"is either within... or is within...".  I suggest rephrasing as "is 
within either...  or...".

-Sandra the nit-picky
diff mbox

Patch

Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 241245)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -153,6 +153,9 @@ 
    UNSPEC_BCDADD
    UNSPEC_BCDSUB
    UNSPEC_BCD_OVERFLOW
+   UNSPEC_CMPRB
+   UNSPEC_CMPRB2
+   UNSPEC_CMPEQB
 ])
 
 (define_c_enum "unspecv"
@@ -3709,6 +3712,189 @@ 
   "darn %0,1"
   [(set_attr "type" "integer")])
 
+;; Test byte within range.
+;;
+;; The bytes of operand 1 are organized as xx:xx:xx:vv, where xx
+;; represents a byte whose value is ignored in this context and
+;; vv, the least significant byte, holds the byte value that is to
+;; be tested for membership within the range specified by operand 2.
+;; The bytes of operand 2 are organized as xx:xx:hi:lo.
+;;
+;; Return in target register operand 0 a value of 1 if lo <= vv and
+;; vv <= hi.  Otherwise, set register operand 0 to 0.
+;;
+;; Though the instructions to which this expansion maps operate on
+;; 64-bit registers, the current implementation only operates on
+;; SI-mode operands as the high-order bits provide no information
+;; that is not already available in the low-order bits.  To avoid the
+;; costs of data widening operations, a future enhancement might add
+;; support for DI-mode operands.
+(define_expand "cmprb"
+  [(set (match_dup 3)
+	(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+		    (match_operand:SI 2 "gpc_reg_operand" "r")]
+	 UNSPEC_CMPRB))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(if_then_else:SI (lt (match_dup 3)
+			     (const_int 0))
+			 (const_int -1)
+			 (if_then_else (gt (match_dup 3)
+					   (const_int 0))
+				       (const_int 1)
+				       (const_int 0))))]
+  "TARGET_P9_MISC"
+{
+  operands[3] = gen_reg_rtx (CCmode);
+})
+
+;; The bytes of operand 1 are organized as xx:xx:xx:vv, where xx
+;; represents a byte whose value is ignored in this context and
+;; vv, the least significant byte, holds the byte value that is to
+;; be tested for membership within the range specified by operand 2.
+;; The bytes of operand 2 are organized as xx:xx:hi:lo.
+;;
+;; Set bit 1 (the GT bit, 0x4) of CR register operand 0 to 1 if
+;; lo <= vv and vv <= hi.  Otherwise, set the GT bit to 0.  The other
+;; 3 bits of the target CR register are all set to 0.
+(define_insn "*cmprb_internal"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+	(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+		    (match_operand:SI 2 "gpc_reg_operand" "r")]
+	 UNSPEC_CMPRB))]
+  "TARGET_P9_MISC"
+  "cmprb %0,0,%1,%2"
+  [(set_attr "type" "logical")])
+
+;; Set operand 0 register to -1 if the LT bit (0x8) of condition
+;; register operand 1 is on.  Otherwise, set operand 0 register to 1
+;; if the GT bit (0x4) of condition register operand 1 is on.
+;; Otherwise, set operand 0 to 0.  Note that the result stored into
+;; register operand 0 is non-zero iff either the LT or GT bits are on
+;; within condition register operand 1.
+(define_insn "*setb_internal"
+   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	 (if_then_else:SI (lt (match_operand:CC 1 "cc_reg_operand" "y")
+			      (const_int 0))
+			  (const_int -1)
+			  (if_then_else (gt (match_dup 1)
+					    (const_int 0))
+					(const_int 1)
+					(const_int 0))))]
+  "TARGET_P9_MISC"
+  "setb %0,%1"
+  [(set_attr "type" "logical")])
+
+;; Test byte within two ranges.
+;;
+;; The bytes of operand 1 are organized as xx:xx:xx:vv, where xx
+;; represents a byte whose value is ignored in this context and
+;; vv, the least significant byte, holds the byte value that is to
+;; be tested for membership within the range specified by operand 2.
+;; The bytes of operand 2 are organized as hi_1:lo_1:hi_2:lo_2.
+;;
+;; Return in target register operand 0 a value of 1 if (lo_1 <= vv and
+;; vv <= hi_1) or if (lo_2 <= vv and vv <= hi_2).  Otherwise, set register
+;; operand 0 to 0.
+;;
+;; Though the instructions to which this expansion maps operate on
+;; 64-bit registers, the current implementation only operates on
+;; SI-mode operands as the high-order bits provide no information
+;; that is not already available in the low-order bits.  To avoid the
+;; costs of data widening operations, a future enhancement might add
+;; support for DI-mode operands.
+(define_expand "cmprb2"
+  [(set (match_dup 3)
+	(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+		    (match_operand:SI 2 "gpc_reg_operand" "r")]
+	 UNSPEC_CMPRB2))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(if_then_else:SI (lt (match_dup 3)
+			     (const_int 0))
+			 (const_int -1)
+			 (if_then_else (gt (match_dup 3)
+					   (const_int 0))
+				       (const_int 1)
+				       (const_int 0))))]
+  "TARGET_P9_MISC"
+{
+  operands[3] = gen_reg_rtx (CCmode);
+})
+
+;; The bytes of operand 1 are organized as xx:xx:xx:vv, where xx
+;; represents a byte whose value is ignored in this context and
+;; vv, the least significant byte, holds the byte value that is to
+;; be tested for membership within the ranges specified by operand 2.
+;; The bytes of operand 2 are organized as hi_1:lo_1:hi_2:lo_2.
+;;
+;; Set bit 1 (the GT bit, 0x4) of CR register operand 0 to 1 if
+;; (lo_1 <= vv and vv <= hi_1) or if (lo_2 <= vv and vv <= hi_2).
+;; Otherwise, set the GT bit to 0.  The other 3 bits of the target
+;; CR register are all set to 0.
+(define_insn "*cmprb2_internal"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+	(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+		    (match_operand:SI 2 "gpc_reg_operand" "r")]
+	 UNSPEC_CMPRB2))]
+  "TARGET_P9_MISC"
+  "cmprb %0,1,%1,%2"
+  [(set_attr "type" "logical")])
+
+;; Test byte membership within set of 8 bytes.
+;;
+;; The bytes of operand 1 are organized as xx:xx:xx:vv, where xx
+;; represents a byte whose value is ignored in this context and
+;; vv, the least significant byte, holds the byte value that is to
+;; be tested for membership within the set specified by operand 2.
+;; The bytes of operand 2 are organized as e0:e1:e2:e3:e4:e5:e6:e7.
+;;
+;; Return in target register operand 0 a value of 1 if vv equals one
+;; of the values e0, e1, e2, e3, e4, e5, e6, or e7.  Otherwise, set
+;; register operand 0 to 0.  Note that the 8 byte values held within
+;; operand 2 need not be unique.
+;;
+;; Though the instructions to which this expansion maps operate on
+;; 64-bit registers, the current implementation requires that operands
+;; 0 and 1 have mode SI as the high-order bits provide no information
+;; that is not already available in the low-order bits.  To avoid the
+;; costs of data widening operations, a future enhancement might add
+;; support for DI-mode operands.
+(define_expand "cmpeqb"
+  [(set (match_dup 3)
+	(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+		    (match_operand:DI 2 "gpc_reg_operand" "r")]
+	 UNSPEC_CMPEQB))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(if_then_else:SI (lt (match_dup 3)
+			     (const_int 0))
+			 (const_int -1)
+			 (if_then_else (gt (match_dup 3)
+					   (const_int 0))
+				       (const_int 1)
+				       (const_int 0))))]
+  "TARGET_P9_MISC && TARGET_64BIT"
+{
+  operands[3] = gen_reg_rtx (CCmode);
+})
+
+;; The bytes of operand 1 are organized as xx:xx:xx:vv, where xx
+;; represents a byte whose value is ignored in this context and
+;; vv, the least significant byte, holds the byte value that is to
+;; be tested for membership within the set specified by operand 2.
+;; The bytes of operand 2 are organized as e0:e1:e2:e3:e4:e5:e6:e7.
+;;
+;; Set bit 1 (the GT bit, 0x4) of CR register operand 0 to 1 if vv
+;; equals one of the values e0, e1, e2, e3, e4, e5, e6, or e7.  Otherwise,
+;; set the GT bit to zero.  The other 3 bits of the target CR register
+;; are all set to 0.
+(define_insn "*cmpeqb_internal"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+	 (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+		     (match_operand:DI 2 "gpc_reg_operand" "r")]
+	  UNSPEC_CMPEQB))]
+  "TARGET_P9_MISC && TARGET_64BIT"
+  "cmpeqb %0,%1,%2"
+  [(set_attr "type" "logical")])
+
 (define_expand "bcd<bcd_add_sub>_<code>"
   [(parallel [(set (reg:CCFP CR6_REGNO)
 		   (compare:CCFP
Index: gcc/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(revision 241245)
+++ gcc/config/rs6000/rs6000-builtin.def	(working copy)
@@ -825,6 +825,23 @@ 
 		     | RS6000_BTC_BINARY),				\
 		    CODE_FOR_ ## ICODE)			/* ICODE */
 
+#define BU_P9_2(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_2 (P9_BUILTIN_SCALAR_ ## ENUM,		/* ENUM */	\
+		    "__builtin_scalar_" NAME,		/* NAME */	\
+		    RS6000_BTM_P9_VECTOR,		/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+#define BU_P9_64BIT_2(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_2 (P9_BUILTIN_SCALAR_ ## ENUM,		/* ENUM */	\
+		    "__builtin_scalar_" NAME,		/* NAME */	\
+		    RS6000_BTM_P9_VECTOR				\
+		    | RS6000_BTM_64BIT,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
 #define BU_P9V_OVERLOAD_1(ENUM, NAME)					\
   RS6000_BUILTIN_1 (P9V_BUILTIN_VEC_ ## ENUM,		/* ENUM */	\
 		    "__builtin_vec_" NAME,		/* NAME */	\
@@ -848,6 +865,15 @@ 
 		    (RS6000_BTC_OVERLOADED		/* ATTR */	\
 		     | RS6000_BTC_TERNARY),				\
 		    CODE_FOR_nothing)			/* ICODE */
+
+#define BU_P9_OVERLOAD_2(ENUM, NAME)					\
+  RS6000_BUILTIN_2 (P9_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_P9_VECTOR,		/* MASK */	\
+		    (RS6000_BTC_OVERLOADED		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_nothing)			/* ICODE */
+
 #endif
 
 
@@ -2004,6 +2030,16 @@  BU_P9V_OVERLOAD_1 (VPRTYBD,	"vprtybd")
 BU_P9V_OVERLOAD_1 (VPRTYBQ,	"vprtybq")
 BU_P9V_OVERLOAD_1 (VPRTYBW,	"vprtybw")
 
+/* 2 argument functions added in ISA 3.0 (power9).  */
+BU_P9_2 (CMPRB,	"byte_in_range",	CONST,	cmprb)
+BU_P9_2 (CMPRB2,	"byte_in_either_range",	CONST,	cmprb2)
+BU_P9_64BIT_2 (CMPEQB,	"byte_in_set",	CONST,	cmpeqb)
+
+/* 2 argument overloaded functions added in ISA 3.0 (power9).  */
+BU_P9_OVERLOAD_2 (CMPRB,	"byte_in_range")
+BU_P9_OVERLOAD_2 (CMPRB2,	"byte_in_either_range")
+BU_P9_OVERLOAD_2 (CMPEQB,	"byte_in_set")
+
 /* 1 argument IEEE 128-bit floating-point functions.  */
 BU_FLOAT128_1 (FABSQ,		"fabsq",       CONST, abskf2)
 
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 241245)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -4556,6 +4556,13 @@  const struct altivec_builtin_types altivec_overloa
   { P9V_BUILTIN_VEC_VPRTYBQ, P9V_BUILTIN_VPRTYBQ,
     RS6000_BTI_UINTTI, RS6000_BTI_UINTTI, 0, 0 },
 
+  { P9_BUILTIN_CMPRB, P9_BUILTIN_SCALAR_CMPRB,
+    RS6000_BTI_INTSI, RS6000_BTI_UINTQI, RS6000_BTI_UINTSI, 0 },
+  { P9_BUILTIN_CMPRB2, P9_BUILTIN_SCALAR_CMPRB2,
+    RS6000_BTI_INTSI, RS6000_BTI_UINTQI, RS6000_BTI_UINTSI, 0 },
+  { P9_BUILTIN_CMPEQB, P9_BUILTIN_SCALAR_CMPEQB,
+    RS6000_BTI_INTSI, RS6000_BTI_UINTQI, RS6000_BTI_UINTDI, 0 },
+
   { P8V_BUILTIN_VEC_VPKUDUM, P8V_BUILTIN_VPKUDUM,
     RS6000_BTI_V4SI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 },
   { P8V_BUILTIN_VEC_VPKUDUM, P8V_BUILTIN_VPKUDUM,
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 241245)
+++ gcc/doc/extend.texi	(working copy)
@@ -15015,6 +15015,27 @@  long long __builtin_darn (void);
 long long __builtin_darn_raw (void);
 int __builtin_darn_32 (void);
 
+unsigned int scalar_extract_exp (double source);
+unsigned long long int scalar_extract_sig (double source);
+
+double
+scalar_insert_exp (unsigned long long int significand, unsigned long long int exponent);
+
+int scalar_cmp_exp_gt (double arg1, double arg2);
+int scalar_cmp_exp_lt (double arg1, double arg2);
+int scalar_cmp_exp_eq (double arg1, double arg2);
+int scalar_cmp_exp_unordered (double arg1, double arg2);
+
+int scalar_test_data_class (float source, unsigned int condition);
+int scalar_test_data_class (double source, unsigned int condition);
+
+int scalar_test_neg (float source);
+int scalar_test_neg (double source);
+
+int __builtin_byte_in_set (unsigned char u, unsigned long long set);
+int __builtin_byte_in_range (unsigned char u, unsigned int range);
+int __builtin_byte_in_either_range (unsigned char u, unsigned int ranges);
+
 int __builtin_dfp_dtstsfi_lt (unsigned int comparison, _Decimal64 value);
 int __builtin_dfp_dtstsfi_lt (unsigned int comparison, _Decimal128 value);
 int __builtin_dfp_dtstsfi_lt_dd (unsigned int comparison, _Decimal64 value);
@@ -15034,23 +15055,6 @@  int __builtin_dfp_dtstsfi_ov (unsigned int compari
 int __builtin_dfp_dtstsfi_ov (unsigned int comparison, _Decimal128 value);
 int __builtin_dfp_dtstsfi_ov_dd (unsigned int comparison, _Decimal64 value);
 int __builtin_dfp_dtstsfi_ov_td (unsigned int comparison, _Decimal128 value);
-
-unsigned int scalar_extract_exp (double source);
-unsigned long long int scalar_extract_sig (double source);
-
-double
-scalar_insert_exp (unsigned long long int significand, unsigned long long int exponent);
-
-int scalar_cmp_exp_gt (double arg1, double arg2);
-int scalar_cmp_exp_lt (double arg1, double arg2);
-int scalar_cmp_exp_eq (double arg1, double arg2);
-int scalar_cmp_exp_unordered (double arg1, double arg2);
-
-int scalar_test_data_class (float source, unsigned int condition);
-int scalar_test_data_class (double source, unsigned int condition);
-
-int scalar_test_neg (float source);
-int scalar_test_neg (double source);
 @end smallexample
 
 The @code{__builtin_darn} and @code{__builtin_darn_raw}
@@ -15105,6 +15109,24 @@  If all of the enabled test conditions are false, t
 The @code{scalar_test_neg} built-in functions return a non-zero value
 if their @code{source} argument holds a negative value.
 
+The @code{__builtin_byte_in_set} function requires a
+64-bit environment supporting ISA 3.0 or later.  This function returns
+a non-zero value if and only if its @code{u} argument exactly equals one of
+the eight bytes contained within its 64-bit @code{set} argument.
+
+The @code{__builtin_byte_in_range} and
+@code{__builtin_byte_in_either_range} require an environment
+supporting ISA 3.0 or later.  For these two functions, the
+@code{range} argument is encoded as 4 bytes, organized as
+@code{hi_1:lo_1:hi_2:lo_2}.
+The first of these functions returns a
+non-zero value if and only if its @code{u} argument is within the
+range bounded between @code{lo_2} and @code{hi_2} inclusive.
+The second of these functions returns non-zero if and only
+if its @code{u} argument is either within the range bounded between
+@code{lo_1} and @code{hi_1} inclusive or is within the range bounded between
+@code{lo_2} and @code{hi_2} inclusive.
+
 The @code{__builtin_dfp_dtstsfi_lt} function returns a non-zero value
 if and only if the number of signficant digits of its @code{value} argument
 is less than its @code{comparison} argument.  The
Index: gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/byte-in-either-range-0.c	(working copy)
@@ -0,0 +1,25 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on both 32- and 64-bit configurations.  */
+#include <altivec.h>
+
+int
+test_byte_in_either_range (unsigned char b,
+			   unsigned char first_lo_bound,
+			   unsigned char first_hi_bound,
+			   unsigned char second_lo_bound,
+			   unsigned char second_hi_bound)
+{
+  unsigned int range_encoding;
+  range_encoding = ((first_hi_bound << 24) | (first_lo_bound << 16)
+		    | (second_hi_bound << 8) | second_lo_bound);
+
+  return __builtin_byte_in_either_range (b, range_encoding);
+}
+
+/* { dg-final { scan-assembler "cmprb" } } */
+/* { dg-final { scan-assembler "setb" } } */
Index: gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c	(working copy)
@@ -0,0 +1,22 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-options "-mcpu=power8" } */
+
+/* This test should succeed on both 32- and 64-bit configurations.  */
+#include <altivec.h>
+
+int
+test_byte_in_either_range (unsigned char b,
+			   unsigned char first_lo_bound,
+			   unsigned char first_hi_bound,
+			   unsigned char second_lo_bound,
+			   unsigned char second_hi_bound)
+{
+  unsigned int range_encoding;
+  range_encoding = ((first_hi_bound << 24) | (first_lo_bound << 16)
+		    | (second_hi_bound << 8) | second_lo_bound);
+
+  return __builtin_byte_in_either_range (b, range_encoding); /* { dg-error "Builtin function __builtin_scalar_byte_in_either_range requires" } */
+}
Index: gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/byte-in-range-0.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on both 32- and 64-bit configurations.  */
+#include <altivec.h>
+
+int
+test_byte_in_range (unsigned char b,
+		    unsigned char low_range, unsigned char high_range)
+{
+  unsigned int range_encoding = (high_range << 8) | low_range;
+  return __builtin_byte_in_range (b, range_encoding);
+}
+
+/* { dg-final { scan-assembler "cmprb" } } */
+/* { dg-final { scan-assembler "setb" } } */
Index: gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c	(working copy)
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-options "-mcpu=power8" } */
+
+#include <altivec.h>
+
+int
+test_byte_in_range (unsigned char b,
+		    unsigned char low_range, unsigned char high_range)
+{
+  unsigned int range_encoding = (high_range << 8) | low_range;
+  return __builtin_byte_in_range (b, range_encoding); /* { dg-error "Builtin function __builtin_scalar_byte_in_range requires" } */
+}
+
Index: gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/byte-in-set-0.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed only on 64-bit configurations.  */
+#include <altivec.h>
+
+int
+test_byte_in_set (unsigned char b, unsigned long long set_members)
+{
+  return __builtin_byte_in_set (b, set_members);
+}
+
+/* { dg-final { scan-assembler "cmpeqb" } } */
+/* { dg-final { scan-assembler "setb" } } */
Index: gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c	(working copy)
@@ -0,0 +1,14 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-options "-mcpu=power8" } */
+
+#include <altivec.h>
+
+int
+test_byte_in_set (unsigned char b, unsigned long long set_members)
+{
+  return __builtin_byte_in_set (b, set_members); /* { dg-error "Builtin function __builtin_scalar_byte_in_set requires" } */
+}
Index: gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c	(working copy)
@@ -0,0 +1,16 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "" { powerpc*-*-aix* } } */
+/* { dg-options "-mcpu=power9" } */
+
+#include <altivec.h>
+
+/* This test should succeed only on 32-bit configurations.  */
+
+int
+test_byte_in_set (unsigned char b, unsigned long long set_members)
+{
+  return __builtin_byte_in_set (b, set_members); /* { dg-error "Builtin function __builtin_byte_in_set not supported in this compiler configuration" } */
+}