diff mbox

[rs6000] Add built-in support for new Power9 darn (deliver a random number) instruction

Message ID 572B7419.7030205@linux.vnet.ibm.com
State New
Headers show

Commit Message

Kelvin Nilsen May 5, 2016, 4:26 p.m. UTC
This patch adds built-in function support for the Power9 darn 
instruction.

I have bootstrapped and tested on both powerpc64le-unknown-linux-gnu and
powerpc64-unknown-linux-gnu with no regressions.  Is this ok for trunk
and for backpatching to ???.

Thanks,
Kelvin


gcc/testsuite/ChangeLog:

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

	* gcc.target/powerpc/darn-0.c: New test.
	* gcc.target/powerpc/darn-1.c: New test.
	* gcc.target/powerpc/darn-2.c: New test.


gcc/ChangeLog:

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

	* config/rs6000/altivec.h: Add macro definitions for darn,
	darn_32, and darn_raw.
	* config/rs6000/altivec.md (UNSPEC_DARN): New unspec constant.
	(UNSPEC_DARN_32): New usnpec constant.
	(UNSPEC_DARN_RAW): New unspec constant.
	("darn_32"): New instruction.
	("darn_raw"): New instruction.
	("darn"): New instruction.
	* config/rs6000/rs6000-builtin.def (RS6000_BUILTIN_0): Add
	support and documentation for this macro.
	(BU_P9_MISC_1): New macro definition.
	(BU_P9_64BIT_MISC_0): New macro definition.
	(BU_P9_MISC_0): New macro definition.
	("darn_32"): New builtin definition.
	("darn_raw"): New builtin definition.
	("darn"): New builtin definition.
	* config/rs6000/rs6000.c: Add #define RS6000_BUILTIN_0 and #undef
	RS6000_BUILTIN_0 directives to surround each occurrence of
	#include "rs6000-builtin.def".
	(rs6000_builtin_mask_calculate): Add in the RS6000_BTM_MODULO and
	RS6000_BTM_64BIT flags to the returned mask, depending on
	configuration. 
	(def_builtin): Correct an error in the assignments made to the
	debugging variable attr_string.
	(rs6000_expand_builtin): Add support for no-operand built-in
	functions. 
	(builtin_function_type): Remove fatal_error assertion that is no
	longer valid.
	(rs6000_common_init_builtins): Add support for no-operand built-in
	functions. 
	* config/rs6000/rs6000.h (RS6000_BTM_MODULO): New macro
	definition. 
	(RS6000_BTM_PURE): Enhance comment to clarify intent of this flag
	definition. 
	(RS6000_BTM_64BIT): New macro definition.
	* doc/extend.texi: Document __builtin_darn (void),
	__builtin_darn_raw (void), and __builtin_darn_32 (void) built-in
	functions.

Comments

Bernhard Reutner-Fischer May 5, 2016, 9:25 p.m. UTC | #1
On May 5, 2016 6:26:01 PM GMT+02:00, Kelvin Nilsen <kdnilsen@linux.vnet.ibm.com> wrote:

>+  /* Handle simple no-argument operations. */
>+  d = bdesc_0arg;
>+  for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++)
>+    if (d->code == fcode)
>+      return rs6000_expand_zeroop_builtin (d->icode, target);
>+
>+  gcc_assert (false);
>   gcc_unreachable ();
> }

Surplus assert.

>+	  if (TARGET_DEBUG_BUILTIN)
>+	    fprintf (stderr, "rs6000_builtin, skip no-argumen %s\n",
>d->name);

s/argumen %s/argument %s/

thanks,
Segher Boessenkool May 9, 2016, 1:58 p.m. UTC | #2
Hi Kelvin,

On Thu, May 05, 2016 at 10:26:01AM -0600, Kelvin Nilsen wrote:
> 	(UNSPEC_DARN_32): New usnpec constant.

Typo.

> 	("darn_32"): New instruction.

We don't normally use quotes for insn names.

> 	(rs6000_builtin_mask_calculate): Add in the RS6000_BTM_MODULO and
> 	RS6000_BTM_64BIT flags to the returned mask, depending on
> 	configuration. 

Trailing space (many, in this changelog).

> --- gcc/config/rs6000/altivec.h	(revision 235884)
> +++ gcc/config/rs6000/altivec.h	(working copy)
> @@ -382,6 +382,11 @@
>  #define vec_vsubuqm __builtin_vec_vsubuqm
>  #define vec_vupkhsw __builtin_vec_vupkhsw
>  #define vec_vupklsw __builtin_vec_vupklsw
> +
> +/* Non-Vector additions added in ISA 3.0. */
> +#define darn __builtin_darn
> +#define darn_32 __builtin_darn_32
> +#define darn_raw __builtin_darn_raw
>  #endif

Do we really want to #define short words like "darn"?  If this is already
set in stone, so be it.

> +(define_insn "darn_32"
> +  [(set (match_operand:SI 0 "register_operand" "")

The constraint should be "r" I suppose?

> +        (unspec:SI [(const_int 0)] UNSPEC_DARN_32))]
> +  "TARGET_MODULO"
> +  {
> +     return "darn %0,0";
> +  }
> +  [(set_attr "type" "add")  

Trailing spaces.  "add" isn't the correct type; use "integer" if there
is no better type.

> +   (set_attr "length" "4")])

That is the default, no need to mention it.  Most insns are implicitly
length 4.

> +/* Miscellaneous builtins for instructions added in ISA 3.0.  These
> +   instructions don't require either the DFP or VSX options, just the basic 

Trailing space.

> @@ -3634,6 +3639,8 @@ rs6000_builtin_mask_calculate (void)
>  	  | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL      : 0)
>  	  | ((TARGET_P8_VECTOR)		    ? RS6000_BTM_P8_VECTOR : 0)
>  	  | ((TARGET_P9_VECTOR)		    ? RS6000_BTM_P9_VECTOR : 0)
> +	  | ((TARGET_MODULO)		    ? RS6000_BTM_MODULO    : 0)
> +	  | ((TARGET_64BIT)		    ? RS6000_BTM_64BIT    : 0)

Missing space?

> +  /* RS6000_BTC_SPECIAL represents no-operand operators.  */
>    gcc_assert (attr == RS6000_BTC_UNARY
>  	      || attr == RS6000_BTC_BINARY
> -	      || attr == RS6000_BTC_TERNARY);
> -
> +	      || attr == RS6000_BTC_TERNARY
> +	      || attr == RS6000_BTC_SPECIAL);
> +  

Why SPECIAL and not NULLARY or such?

> +      if (rs6000_overloaded_builtin_p (d->code))
> +	{
> +	  if (! (type = opaque_ftype_opaque))
> +	    type = opaque_ftype_opaque
> +	      = build_function_type_list (opaque_V4SI_type_node,
> +					  NULL_TREE);
> +	}

Eww.

  if (!opaque_ftype_opaque)
    opaque_ftype_opaque = build_function_type_list (...);
  type = opaque_ftype_opaque;

> +	  enum insn_code icode = d->icode;
> +	  if (d->name == 0)
> +	    {
> +	      if (TARGET_DEBUG_BUILTIN)
> +		fprintf (stderr, "rs6000_builtin, bdesc_0arg[%ld] no name\n",
> +			 (long unsigned)i);

unsigned is %u, not %d.  Space after cast.

Cheers,


Segher
Bill Schmidt May 9, 2016, 5:35 p.m. UTC | #3
On Mon, 2016-05-09 at 08:58 -0500, Segher Boessenkool wrote:
> Hi Kelvin,
> 
> On Thu, May 05, 2016 at 10:26:01AM -0600, Kelvin Nilsen wrote:
> > 	(UNSPEC_DARN_32): New usnpec constant.
> 
> Typo.
> 
> > 	("darn_32"): New instruction.
> 
> We don't normally use quotes for insn names.
> 
> > 	(rs6000_builtin_mask_calculate): Add in the RS6000_BTM_MODULO and
> > 	RS6000_BTM_64BIT flags to the returned mask, depending on
> > 	configuration. 
> 
> Trailing space (many, in this changelog).
> 
> > --- gcc/config/rs6000/altivec.h	(revision 235884)
> > +++ gcc/config/rs6000/altivec.h	(working copy)
> > @@ -382,6 +382,11 @@
> >  #define vec_vsubuqm __builtin_vec_vsubuqm
> >  #define vec_vupkhsw __builtin_vec_vupkhsw
> >  #define vec_vupklsw __builtin_vec_vupklsw
> > +
> > +/* Non-Vector additions added in ISA 3.0. */
> > +#define darn __builtin_darn
> > +#define darn_32 __builtin_darn_32
> > +#define darn_raw __builtin_darn_raw
> >  #endif
> 
> Do we really want to #define short words like "darn"?  If this is already
> set in stone, so be it.

I don't think we do, and in any case altivec.h would not be the place to
do it.  darn is not a vector instruction.

For these, just having __builtin_darn* be the available interfaces will
be fine.

My two cents,
Bill

> 
> > +(define_insn "darn_32"
> > +  [(set (match_operand:SI 0 "register_operand" "")
> 
> The constraint should be "r" I suppose?
> 
> > +        (unspec:SI [(const_int 0)] UNSPEC_DARN_32))]
> > +  "TARGET_MODULO"
> > +  {
> > +     return "darn %0,0";
> > +  }
> > +  [(set_attr "type" "add")  
> 
> Trailing spaces.  "add" isn't the correct type; use "integer" if there
> is no better type.
> 
> > +   (set_attr "length" "4")])
> 
> That is the default, no need to mention it.  Most insns are implicitly
> length 4.
> 
> > +/* Miscellaneous builtins for instructions added in ISA 3.0.  These
> > +   instructions don't require either the DFP or VSX options, just the basic 
> 
> Trailing space.
> 
> > @@ -3634,6 +3639,8 @@ rs6000_builtin_mask_calculate (void)
> >  	  | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL      : 0)
> >  	  | ((TARGET_P8_VECTOR)		    ? RS6000_BTM_P8_VECTOR : 0)
> >  	  | ((TARGET_P9_VECTOR)		    ? RS6000_BTM_P9_VECTOR : 0)
> > +	  | ((TARGET_MODULO)		    ? RS6000_BTM_MODULO    : 0)
> > +	  | ((TARGET_64BIT)		    ? RS6000_BTM_64BIT    : 0)
> 
> Missing space?
> 
> > +  /* RS6000_BTC_SPECIAL represents no-operand operators.  */
> >    gcc_assert (attr == RS6000_BTC_UNARY
> >  	      || attr == RS6000_BTC_BINARY
> > -	      || attr == RS6000_BTC_TERNARY);
> > -
> > +	      || attr == RS6000_BTC_TERNARY
> > +	      || attr == RS6000_BTC_SPECIAL);
> > +  
> 
> Why SPECIAL and not NULLARY or such?
> 
> > +      if (rs6000_overloaded_builtin_p (d->code))
> > +	{
> > +	  if (! (type = opaque_ftype_opaque))
> > +	    type = opaque_ftype_opaque
> > +	      = build_function_type_list (opaque_V4SI_type_node,
> > +					  NULL_TREE);
> > +	}
> 
> Eww.
> 
>   if (!opaque_ftype_opaque)
>     opaque_ftype_opaque = build_function_type_list (...);
>   type = opaque_ftype_opaque;
> 
> > +	  enum insn_code icode = d->icode;
> > +	  if (d->name == 0)
> > +	    {
> > +	      if (TARGET_DEBUG_BUILTIN)
> > +		fprintf (stderr, "rs6000_builtin, bdesc_0arg[%ld] no name\n",
> > +			 (long unsigned)i);
> 
> unsigned is %u, not %d.  Space after cast.
> 
> Cheers,
> 
> 
> Segher
>
Peter Bergner May 9, 2016, 6:51 p.m. UTC | #4
On Mon, 2016-05-09 at 12:35 -0500, Bill Schmidt wrote:
> On Mon, 2016-05-09 at 08:58 -0500, Segher Boessenkool wrote:
> > On Thu, May 05, 2016 at 10:26:01AM -0600, Kelvin Nilsen wrote:


> > Do we really want to #define short words like "darn"?  If this is already
> > set in stone, so be it.
> 
> I don't think we do, and in any case altivec.h would not be the place to
> do it.  darn is not a vector instruction.
> 
> For these, just having __builtin_darn* be the available interfaces will
> be fine.
> 

Agreed, I don't think we need a fancy short names for this builtin
which will be infrequently used.  The __builtin_darn name is enough.


Peter
diff mbox

Patch

Index: gcc/config/rs6000/altivec.h
===================================================================
--- gcc/config/rs6000/altivec.h	(revision 235884)
+++ gcc/config/rs6000/altivec.h	(working copy)
@@ -382,6 +382,11 @@ 
 #define vec_vsubuqm __builtin_vec_vsubuqm
 #define vec_vupkhsw __builtin_vec_vupkhsw
 #define vec_vupklsw __builtin_vec_vupklsw
+
+/* Non-Vector additions added in ISA 3.0. */
+#define darn __builtin_darn
+#define darn_32 __builtin_darn_32
+#define darn_raw __builtin_darn_raw
 #endif
 
 /* Predicates.
Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 235884)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -73,6 +73,9 @@ 
    UNSPEC_VUNPACK_LO_SIGN_DIRECT
    UNSPEC_VUPKHPX
    UNSPEC_VUPKLPX
+   UNSPEC_DARN
+   UNSPEC_DARN_32
+   UNSPEC_DARN_RAW
    UNSPEC_DST
    UNSPEC_DSTT
    UNSPEC_DSTST
@@ -3590,6 +3593,37 @@ 
   [(set_attr "length" "4")
    (set_attr "type" "vecsimple")])
 
+(define_insn "darn_32"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (unspec:SI [(const_int 0)] UNSPEC_DARN_32))]
+  "TARGET_MODULO"
+  {
+     return "darn %0,0";
+  }
+  [(set_attr "type" "add")  
+   (set_attr "length" "4")])
+
+(define_insn "darn_raw"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (unspec:DI [(const_int 0)] UNSPEC_DARN_RAW))]
+  "TARGET_MODULO && TARGET_64BIT"
+  {
+     return "darn %0,2";
+  }
+  [(set_attr "type" "add")  
+   (set_attr "length" "4")])
+
+(define_insn "darn"
+  [(set (match_operand:DI 0 "register_operand" "")
+        (unspec:DI [(const_int 0)] UNSPEC_DARN))]
+  "TARGET_MODULO && TARGET_64BIT"
+  {
+     return "darn %0,1";
+  }
+  [(set_attr "type" "add")  
+   (set_attr "length" "4")])
+
+
 (define_expand "bcd<bcd_add_sub>_<code>"
   [(parallel [(set (reg:CCFP 74)
 		   (compare:CCFP
Index: gcc/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(revision 235884)
+++ gcc/config/rs6000/rs6000-builtin.def	(working copy)
@@ -24,6 +24,7 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 /* Before including this file, some macros must be defined:
+   RS6000_BUILTIN_0 -- 0 arg builtins
    RS6000_BUILTIN_1 -- 1 arg builtins
    RS6000_BUILTIN_2 -- 2 arg builtins
    RS6000_BUILTIN_3 -- 3 arg builtins
@@ -43,6 +44,10 @@ 
 	ATTR	builtin attribute information.
 	ICODE	Insn code of the function that implents the builtin.  */
 
+#ifndef RS6000_BUILTIN_0
+  #error "RS6000_BUILTIN_0 is not defined."
+#endif
+
 #ifndef RS6000_BUILTIN_1
   #error "RS6000_BUILTIN_1 is not defined."
 #endif
@@ -637,6 +642,41 @@ 
 		     | RS6000_BTC_TERNARY),				\
 		    CODE_FOR_ ## ICODE)			/* ICODE */
 
+/* Miscellaneous builtins for instructions added in ISA 3.0.  These
+   instructions don't require either the DFP or VSX options, just the basic 
+   ISA 3.0 enablement since they operate on general purpose registers.  */
+#define BU_P9_MISC_1(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_MODULO,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_UNARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+/* Miscellaneous builtins for instructions added in ISA 3.0.  These
+   instructions don't require either the DFP or VSX options, just the basic 
+   ISA 3.0 enablement since they operate on general purpose registers,
+   and they require 64-bit addressing.  */
+#define BU_P9_64BIT_MISC_0(ENUM, NAME, ATTR, ICODE)			\
+  RS6000_BUILTIN_0 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_MODULO                                   \
+                     | RS6000_BTM_64BIT,		/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_SPECIAL),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+/* Miscellaneous builtins for instructions added in ISA 3.0.  These
+   instructions don't require either the DFP or VSX options, just the basic 
+   ISA 3.0 enablement since they operate on general purpose registers.  */
+#define BU_P9_MISC_0(ENUM, NAME, ATTR, ICODE)                      \
+  RS6000_BUILTIN_0 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_MODULO,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_SPECIAL),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
 /* 128-bit long double floating point builtins.  */
 #define BU_LDBL128_2(ENUM, NAME, ATTR, ICODE)				\
   RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
@@ -1653,6 +1693,11 @@  BU_P8V_MISC_3 (BCDSUB_OV,	"bcdsub_ov",	CONST,	bcds
 BU_DFP_MISC_2 (PACK_TD,		"pack_dec128",		CONST,	packtd)
 BU_DFP_MISC_2 (UNPACK_TD,	"unpack_dec128",	CONST,	unpacktd)
 
+/* 0 argument general-purpose register functions added in ISA 3.0 (power9).  */
+BU_P9_MISC_0 (DARN_32,		"darn_32", 		MISC, darn_32)
+BU_P9_64BIT_MISC_0 (DARN_RAW,	"darn_raw", 		MISC, darn_raw)
+BU_P9_64BIT_MISC_0 (DARN,	"darn",			MISC, darn)
+
 BU_LDBL128_2 (PACK_TF,		"pack_longdouble",	CONST,	packtf)
 BU_LDBL128_2 (UNPACK_TF,	"unpack_longdouble",	CONST,	unpacktf)
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 235884)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1128,6 +1128,7 @@  struct processor_costs ppca2_cost = {
 
 
 /* Table that classifies rs6000 builtin functions (pure, const, etc.).  */
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -1140,6 +1141,9 @@  struct processor_costs ppca2_cost = {
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) \
+  { NAME, ICODE, MASK, ATTR },
+
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \
   { NAME, ICODE, MASK, ATTR },
 
@@ -1185,6 +1189,7 @@  static const struct rs6000_builtin_info_type rs600
 #include "rs6000-builtin.def"
 };
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -3634,6 +3639,8 @@  rs6000_builtin_mask_calculate (void)
 	  | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL      : 0)
 	  | ((TARGET_P8_VECTOR)		    ? RS6000_BTM_P8_VECTOR : 0)
 	  | ((TARGET_P9_VECTOR)		    ? RS6000_BTM_P9_VECTOR : 0)
+	  | ((TARGET_MODULO)		    ? RS6000_BTM_MODULO    : 0)
+	  | ((TARGET_64BIT)		    ? RS6000_BTM_64BIT    : 0)
 	  | ((TARGET_CRYPTO)		    ? RS6000_BTM_CRYPTO	   : 0)
 	  | ((TARGET_HTM)		    ? RS6000_BTM_HTM	   : 0)
 	  | ((TARGET_DFP)		    ? RS6000_BTM_DFP	   : 0)
@@ -12268,7 +12275,7 @@  def_builtin (const char *name, tree type, enum rs6
       /* const function, function only depends on the inputs.  */
       TREE_READONLY (t) = 1;
       TREE_NOTHROW (t) = 1;
-      attr_string = ", pure";
+      attr_string = ", const";
     }
   else if ((classify & RS6000_BTC_PURE) != 0)
     {
@@ -12276,7 +12283,7 @@  def_builtin (const char *name, tree type, enum rs6
 	 external state.  */
       DECL_PURE_P (t) = 1;
       TREE_NOTHROW (t) = 1;
-      attr_string = ", const";
+      attr_string = ", pure";
     }
   else if ((classify & RS6000_BTC_FP) != 0)
     {
@@ -12308,6 +12315,7 @@  def_builtin (const char *name, tree type, enum rs6
 
 /* Simple ternary operations: VECd = foo (VECa, VECb, VECc).  */
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12320,6 +12328,7 @@  def_builtin (const char *name, tree type, enum rs6
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \
@@ -12341,6 +12350,7 @@  static const struct builtin_description bdesc_3arg
 
 /* DST operations: void foo (void *, const int, const char).  */
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12353,6 +12363,7 @@  static const struct builtin_description bdesc_3arg
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
@@ -12374,6 +12385,7 @@  static const struct builtin_description bdesc_dst[
 
 /* Simple binary operations: VECc = foo (VECa, VECb).  */
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12386,6 +12398,7 @@  static const struct builtin_description bdesc_dst[
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) \
   { MASK, ICODE, NAME, ENUM },
@@ -12405,6 +12418,7 @@  static const struct builtin_description bdesc_2arg
 #include "rs6000-builtin.def"
 };
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12417,6 +12431,7 @@  static const struct builtin_description bdesc_2arg
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
@@ -12439,6 +12454,7 @@  static const struct builtin_description bdesc_alti
 };
 
 /* SPE predicates.  */
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12451,6 +12467,7 @@  static const struct builtin_description bdesc_alti
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
@@ -12471,6 +12488,7 @@  static const struct builtin_description bdesc_spe_
 };
 
 /* SPE evsel predicates.  */
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12483,6 +12501,7 @@  static const struct builtin_description bdesc_spe_
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
@@ -12503,6 +12522,7 @@  static const struct builtin_description bdesc_spe_
 };
 
 /* PAIRED predicates.  */
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12515,6 +12535,7 @@  static const struct builtin_description bdesc_spe_
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
@@ -12536,6 +12557,7 @@  static const struct builtin_description bdesc_pair
 
 /* ABS* operations.  */
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12548,6 +12570,7 @@  static const struct builtin_description bdesc_pair
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
@@ -12570,6 +12593,7 @@  static const struct builtin_description bdesc_abs[
 /* Simple unary operations: VECb = foo (unsigned literal) or VECb =
    foo (VECa).  */
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12582,6 +12606,7 @@  static const struct builtin_description bdesc_abs[
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \
   { MASK, ICODE, NAME, ENUM },
 
@@ -12601,7 +12626,43 @@  static const struct builtin_description bdesc_1arg
 #include "rs6000-builtin.def"
 };
 
+/* Simple no-argument operations: result = __builtin_darn_32 () */
+
+#undef RS6000_BUILTIN_0
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+#undef RS6000_BUILTIN_X
+
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) \
+  { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_0arg[] =
+{
+#include "rs6000-builtin.def"
+};
+
 /* HTM builtins.  */
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12614,6 +12675,7 @@  static const struct builtin_description bdesc_1arg
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
@@ -12633,6 +12695,7 @@  static const struct builtin_description bdesc_htm[
 #include "rs6000-builtin.def"
 };
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -12717,7 +12780,6 @@  rs6000_expand_mtfsf_builtin (enum insn_code icode,
   return NULL_RTX;
 }
 
-
 static rtx
 rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target)
 {
@@ -15157,10 +15219,12 @@  rs6000_expand_builtin (tree exp, rtx target, rtx s
     }  
 
   unsigned attr = rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK;
+  /* RS6000_BTC_SPECIAL represents no-operand operators.  */
   gcc_assert (attr == RS6000_BTC_UNARY
 	      || attr == RS6000_BTC_BINARY
-	      || attr == RS6000_BTC_TERNARY);
-
+	      || attr == RS6000_BTC_TERNARY
+	      || attr == RS6000_BTC_SPECIAL);
+  
   /* Handle simple unary operations.  */
   d = bdesc_1arg;
   for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
@@ -15179,6 +15243,13 @@  rs6000_expand_builtin (tree exp, rtx target, rtx s
     if (d->code == fcode)
       return rs6000_expand_ternop_builtin (d->icode, exp, target);
 
+  /* Handle simple no-argument operations. */
+  d = bdesc_0arg;
+  for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++)
+    if (d->code == fcode)
+      return rs6000_expand_zeroop_builtin (d->icode, target);
+
+  gcc_assert (false);
   gcc_unreachable ();
 }
 
@@ -16559,10 +16630,6 @@  builtin_function_type (machine_mode mode_ret, mach
   while (num_args > 0 && h.mode[num_args] == VOIDmode)
     num_args--;
 
-  if (num_args == 0)
-    fatal_error (input_location,
-		 "internal error: builtin function %s had no type", name);
-
   ret_type = builtin_mode_to_type[h.mode[0]][h.uns_p[0]];
   if (!ret_type && h.uns_p[0])
     ret_type = builtin_mode_to_type[h.mode[0]][0];
@@ -16614,6 +16681,7 @@  rs6000_common_init_builtins (void)
   tree opaque_ftype_opaque = NULL_TREE;
   tree opaque_ftype_opaque_opaque = NULL_TREE;
   tree opaque_ftype_opaque_opaque_opaque = NULL_TREE;
+  tree v2si_ftype = NULL_TREE;
   tree v2si_ftype_qi = NULL_TREE;
   tree v2si_ftype_v2si_qi = NULL_TREE;
   tree v2si_ftype_int_qi = NULL_TREE;
@@ -16830,6 +16898,69 @@  rs6000_common_init_builtins (void)
 
       def_builtin (d->name, type, d->code);
     }
+
+  /* Add the simple no-argument operators.  */
+  d = bdesc_0arg;
+  for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++)
+    {
+      machine_mode mode0;
+      tree type;
+      HOST_WIDE_INT mask = d->mask;
+
+      if ((mask & builtin_mask) != mask)
+	{
+	  if (TARGET_DEBUG_BUILTIN)
+	    fprintf (stderr, "rs6000_builtin, skip no-argumen %s\n", d->name);
+	  continue;
+	}
+
+      if (rs6000_overloaded_builtin_p (d->code))
+	{
+	  if (! (type = opaque_ftype_opaque))
+	    type = opaque_ftype_opaque
+	      = build_function_type_list (opaque_V4SI_type_node,
+					  NULL_TREE);
+	}
+      else
+        {
+	  enum insn_code icode = d->icode;
+	  if (d->name == 0)
+	    {
+	      if (TARGET_DEBUG_BUILTIN)
+		fprintf (stderr, "rs6000_builtin, bdesc_0arg[%ld] no name\n",
+			 (long unsigned)i);
+
+	      continue;
+	    }
+
+          if (icode == CODE_FOR_nothing)
+	    {
+	      if (TARGET_DEBUG_BUILTIN)
+		fprintf (stderr, 
+			 "rs6000_builtin, skip no-argument %s (no code)\n",
+			 d->name);
+
+	      continue;
+	    }
+
+          mode0 = insn_data[icode].operand[0].mode;
+
+	  if (mode0 == V2SImode)
+	    {
+	      /* code for SPE */
+	      if (! (type = v2si_ftype))
+		type = v2si_ftype
+		  = build_function_type_list (opaque_V2SI_type_node,
+					      NULL_TREE);
+	    }
+
+	  else
+	    type = builtin_function_type (mode0, VOIDmode, VOIDmode, VOIDmode,
+					  d->code, d->name);
+	}
+
+      def_builtin (d->name, type, d->code);
+    }
 }
 
 /* Set up AIX/Darwin/64-bit Linux quad floating point routines.  */
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 235884)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -656,6 +656,11 @@  extern int rs6000_vector_align[];
 #define MASK_PROTOTYPE			OPTION_MASK_PROTOTYPE
 #endif
 
+#ifdef TARGET_MODULO
+#define RS6000_BTM_MODULO		OPTION_MASK_MODULO
+#endif
+
+
 /* For power systems, we want to enable Altivec and VSX builtins even if the
    user did not use -maltivec or -mvsx to allow the builtins to be used inside
    of #pragma GCC target or the target attribute to change the code level for a
@@ -2644,7 +2649,9 @@  extern int frame_pointer_needed;
 
 #define RS6000_BTC_MISC		0x00000000	/* No special attributes.  */
 #define RS6000_BTC_CONST	0x00000100	/* uses no global state.  */
-#define RS6000_BTC_PURE		0x00000200	/* reads global state/mem.  */
+#define RS6000_BTC_PURE		0x00000200	/* reads global
+						   state/mem and does
+						   not modify global state.  */
 #define RS6000_BTC_FP		0x00000400	/* depends on rounding mode.  */
 #define RS6000_BTC_ATTR_MASK	0x00000700	/* Mask of the attributes.  */
 
@@ -2680,6 +2687,7 @@  extern int frame_pointer_needed;
 #define RS6000_BTM_DFP		MASK_DFP	/* Decimal floating point.  */
 #define RS6000_BTM_HARD_FLOAT	MASK_SOFT_FLOAT	/* Hardware floating point.  */
 #define RS6000_BTM_LDBL128	MASK_MULTIPLE	/* 128-bit long double.  */
+#define RS6000_BTM_64BIT	MASK_64BIT	/* 64-bit addressing.  */
 
 #define RS6000_BTM_COMMON	(RS6000_BTM_ALTIVEC			\
 				 | RS6000_BTM_VSX			\
@@ -2699,6 +2707,7 @@  extern int frame_pointer_needed;
 
 /* Define builtin enum index.  */
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
@@ -2711,6 +2720,7 @@  extern int frame_pointer_needed;
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
@@ -2730,6 +2740,7 @@  enum rs6000_builtins
   RS6000_BUILTIN_COUNT
 };
 
+#undef RS6000_BUILTIN_0
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 235884)
+++ gcc/doc/extend.texi	(working copy)
@@ -13897,6 +13897,23 @@  The @code{__builtin_divde}, @code{__builtin_divdeo
 64-bit environment support ISA 2.06 or later.
 
 The following built-in functions are available for the PowerPC family
+of processors, starting with ISA 3.0 or later (@option{-mcpu=power9}
+or @option{-mmodulo}):
+@smallexample
+long long __builtin_darn (void);
+long long __builtin_darn_raw (void);
+int __builtin_darn_32 (void);
+@end smallexample
+
+The @code{__builtin_darn} and @code{__builtin_darn_raw}
+functions require a
+64-bit environment supporting ISA 3.0 or later.
+The @code{__builtin_darn} function provides a 64-bit conditioned
+random number.  The @code{__builtin_darn_raw} function provides a
+64-bit raw random number.  The @code{__builtin_darn_32} function
+provides a 32-bit random number.
+
+The following built-in functions are available for the PowerPC family
 of processors when hardware decimal floating point
 (@option{-mhard-dfp}) is available:
 @smallexample
Index: gcc/testsuite/gcc.target/powerpc/darn-0.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/darn-0.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/darn-0.c	(working copy)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-mcpu=power9" } */
+
+/* This test should succeed on both 32- and 64-bit configurations.  */
+#include <altivec.h>
+
+int get_random() 
+{
+  return __builtin_darn_32 ();
+}
+
+/* { dg-final { scan-assembler	   "darn" } } */
Index: gcc/testsuite/gcc.target/powerpc/darn-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/darn-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/darn-1.c	(working copy)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-mcpu=power9" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <altivec.h>
+
+long long get_conditioned_random() 
+{
+  return __builtin_darn ();
+}
+
+/* { dg-final { scan-assembler	   "darn" } } */
Index: gcc/testsuite/gcc.target/powerpc/darn-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/darn-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/darn-2.c	(working copy)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-mcpu=power9" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <altivec.h>
+
+long long get_raw_random() 
+{
+  return __builtin_darn_raw ();
+}
+
+/* { dg-final { scan-assembler	   "darn" } } */