This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Backport PowerPC complex __float128 compiler support to GCC 6.x


On Thu, 9 Jun 2016, Michael Meissner wrote:

> I'm including the global reviewers on the list.  I just want to be sure that
> there is no problem installing these patches on the GCC 6.2 branch.  While it
> is technically an enchancement, it is needed to be able to install the glibc
> support that is needed to complete the work to add IEEE 128-bit floating point.
> 
> The issue being fixed is that when we are creating the complex type, we used to
> do a lookup for the size, and that fails on the PowerPC which has 2 128-bit
> floating point types (__ibm128 and __float128, with long double currently
> defaulting to __ibm128).

As this enhancement includes middle-end changes I am hesitant to approve
it for the branch.  Why is it desirable to backport this change?

Thanks,
Richard.

> On Fri, Jun 03, 2016 at 09:33:35AM -0400, Michael Meissner wrote:
> > These patches were installed on the trunk on May 2nd, with a fix from Alan
> > Modra on May 11th.  Unless I here objections in the next few days, I will
> > commit these changes to the GCC 6.x branch.  These changes will allow people to
> > use complex __float128 types (via an attribute) on the PowerPC.
> > 
> > Note, we will need patches to libgcc to fully enable complex __float128 support
> > on the PowerPC.  These patches enable the compiler support, so that the libgcc
> > changes can be coded.
> > 
> > In addition to bootstrapping and regtesting on the PowerPC (little endian
> > power8), I also bootstrapped and regested the changes on x86_64 running RHEL
> > 6.2.  There were no regressions in either case.
> > 
> > [gcc]
> > 2016-06-02  Michael Meissner  <meissner@linux.vnet.ibm.com>
> > 
> > 	Back port from trunk
> > 	2016-05-11  Alan Modra  <amodra@gmail.com>
> > 
> > 	* config/rs6000/rs6000.c (is_complex_IBM_long_double,
> > 	abi_v4_pass_in_fpr): New functions.
> > 	(rs6000_function_arg_boundary): Exclude complex IBM long double
> > 	from 64-bit alignment when ABI_V4.
> > 	(rs6000_function_arg, rs6000_function_arg_advance_1,
> > 	rs6000_gimplify_va_arg): Use abi_v4_pass_in_fpr.
> > 
> > 	Back port from trunk
> > 	2016-05-02  Michael Meissner  <meissner@linux.vnet.ibm.com>
> > 
> > 	* machmode.h (mode_complex): Add support to give the complex mode
> > 	for a given mode.
> > 	(GET_MODE_COMPLEX_MODE): Likewise.
> > 	* stor-layout.c (layout_type): For COMPLEX_TYPE, use the mode
> > 	stored by build_complex_type and gfc_build_complex_type instead of
> > 	trying to figure out the appropriate mode based on the size. Raise
> > 	an assertion error, if the type was not set.
> > 	* genmodes.c (struct mode_data): Add field for the complex type of
> > 	the given type.
> > 	(blank_mode): Likewise.
> > 	(make_complex_modes): Remember the complex mode created in the
> > 	base type.
> > 	(emit_mode_complex): Write out the mode_complex array to map a
> > 	type mode to the complex version.
> > 	(emit_insn_modes_c): Likewise.
> > 	* tree.c (build_complex_type): Set the complex type to use before
> > 	calling layout_type.
> > 	* config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Add
> > 	support for __float128 complex datatypes.
> > 	(rs6000_hard_regno_mode_ok): Likewise.
> > 	(rs6000_setup_reg_addr_masks): Likewise.
> > 	(rs6000_complex_function_value): Likewise.
> > 	* config/rs6000/rs6000.h (FLOAT128_IEEE_P): Likewise.
> > 	__float128 and __ibm128 complex.
> > 	(FLOAT128_IBM_P): Likewise.
> > 	(ALTIVEC_ARG_MAX_RETURN): Likewise.
> > 	* doc/extend.texi (Additional Floating Types): Document that
> > 	-mfloat128 must be used to enable __float128.  Document complex
> > 	__float128 and __ibm128 support.
> > 
> > [gcc/fortran]
> > 2016-06-02  Michael Meissner  <meissner@linux.vnet.ibm.com>
> > 
> > 	Back port from trunk
> > 	2016-05-02  Michael Meissner  <meissner@linux.vnet.ibm.com>
> > 
> > 	* trans-types.c (gfc_build_complex_type):
> > 
> > [gcc/testsuite]
> > 2016-06-02  Michael Meissner  <meissner@linux.vnet.ibm.com>
> > 
> > 	Back port from trunk
> > 	2016-05-02  Michael Meissner  <meissner@linux.vnet.ibm.com>
> > 
> > 	* gcc.target/powerpc/float128-complex-1.c: New tests for complex
> > 	__float128.
> > 	* gcc.target/powerpc/float128-complex-2.c: Likewise.
> > 
> > -- 
> > Michael Meissner, IBM
> > IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
> > email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797
> 
> > Index: gcc/machmode.h
> > ===================================================================
> > --- gcc/machmode.h	(revision 237045)
> > +++ gcc/machmode.h	(working copy)
> > @@ -269,6 +269,10 @@ extern const unsigned char mode_wider[NU
> >  extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
> >  #define GET_MODE_2XWIDER_MODE(MODE) ((machine_mode) mode_2xwider[MODE])
> > 
> > +/* Get the complex mode from the component mode.  */
> > +extern const unsigned char mode_complex[NUM_MACHINE_MODES];
> > +#define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
> > +
> >  /* Return the mode for data of a given size SIZE and mode class CLASS.
> >     If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
> >     The value is BLKmode if no other mode is found.  */
> > Index: gcc/stor-layout.c
> > ===================================================================
> > --- gcc/stor-layout.c	(revision 237045)
> > +++ gcc/stor-layout.c	(working copy)
> > @@ -2146,11 +2146,13 @@ layout_type (tree type)
> > 
> >      case COMPLEX_TYPE:
> >        TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
> > -      SET_TYPE_MODE (type,
> > -		     mode_for_size (2 * TYPE_PRECISION (TREE_TYPE (type)),
> > -				    (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE
> > -				     ? MODE_COMPLEX_FLOAT : MODE_COMPLEX_INT),
> > -				     0));
> > +
> > +      /* build_complex_type and fortran's gfc_build_complex_type have set the
> > +	 expected mode to allow having multiple complex types for multiple
> > +	 floating point types that have the same size such as the PowerPC with
> > +	 __ibm128 and __float128.  */
> > +      gcc_assert (TYPE_MODE (type) != VOIDmode);
> > +
> >        TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
> >        TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
> >        break;
> > Index: gcc/genmodes.c
> > ===================================================================
> > --- gcc/genmodes.c	(revision 237045)
> > +++ gcc/genmodes.c	(working copy)
> > @@ -66,6 +66,7 @@ struct mode_data
> >  				   this mode as a component.  */
> >    struct mode_data *next_cont;  /* Next mode in that list.  */
> > 
> > +  struct mode_data *complex;	/* complex type with mode as component.  */
> >    const char *file;		/* file and line of definition, */
> >    unsigned int line;		/* for error reporting */
> >    unsigned int counter;		/* Rank ordering of modes */
> > @@ -83,7 +84,7 @@ static struct mode_data *void_mode;
> >  static const struct mode_data blank_mode = {
> >    0, "<unknown>", MAX_MODE_CLASS,
> >    -1U, -1U, -1U, -1U,
> > -  0, 0, 0, 0, 0,
> > +  0, 0, 0, 0, 0, 0,
> >    "<unknown>", 0, 0, 0, 0, false, 0
> >  };
> > 
> > @@ -472,6 +473,7 @@ make_complex_modes (enum mode_class cl,
> > 
> >        c = new_mode (cclass, buf, file, line);
> >        c->component = m;
> > +      m->complex = c;
> >      }
> >  }
> > 
> > @@ -1381,6 +1383,22 @@ emit_mode_wider (void)
> >  }
> > 
> >  static void
> > +emit_mode_complex (void)
> > +{
> > +  int c;
> > +  struct mode_data *m;
> > +
> > +  print_decl ("unsigned char", "mode_complex", "NUM_MACHINE_MODES");
> > +
> > +  for_all_modes (c, m)
> > +    tagged_printf ("%smode",
> > +		   m->complex ? m->complex->name : void_mode->name,
> > +		   m->name);
> > +
> > +  print_closer ();
> > +}
> > +
> > +static void
> >  emit_mode_mask (void)
> >  {
> >    int c;
> > @@ -1745,6 +1763,7 @@ emit_insn_modes_c (void)
> >    emit_mode_size ();
> >    emit_mode_nunits ();
> >    emit_mode_wider ();
> > +  emit_mode_complex ();
> >    emit_mode_mask ();
> >    emit_mode_inner ();
> >    emit_mode_unit_size ();
> > Index: gcc/tree.c
> > ===================================================================
> > --- gcc/tree.c	(revision 237045)
> > +++ gcc/tree.c	(working copy)
> > @@ -8675,6 +8675,7 @@ build_complex_type (tree component_type)
> >    t = make_node (COMPLEX_TYPE);
> > 
> >    TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type);
> > +  SET_TYPE_MODE (t, GET_MODE_COMPLEX_MODE (TYPE_MODE (component_type)));
> > 
> >    /* If we already have such a type, use the old one.  */
> >    hstate.add_object (TYPE_HASH (component_type));
> > Index: gcc/config/rs6000/rs6000.c
> > ===================================================================
> > --- gcc/config/rs6000/rs6000.c	(revision 237045)
> > +++ gcc/config/rs6000/rs6000.c	(working copy)
> > @@ -1882,7 +1882,7 @@ rs6000_hard_regno_nregs_internal (int re
> >       128-bit floating point that can go in vector registers, which has VSX
> >       memory addressing.  */
> >    if (FP_REGNO_P (regno))
> > -    reg_size = (VECTOR_MEM_VSX_P (mode)
> > +    reg_size = (VECTOR_MEM_VSX_P (mode) || FLOAT128_VECTOR_P (mode)
> >  		? UNITS_PER_VSX_WORD
> >  		: UNITS_PER_FP_WORD);
> > 
> > @@ -1914,6 +1914,9 @@ rs6000_hard_regno_mode_ok (int regno, ma
> >  {
> >    int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1;
> > 
> > +  if (COMPLEX_MODE_P (mode))
> > +    mode = GET_MODE_INNER (mode);
> > +
> >    /* PTImode can only go in GPRs.  Quad word memory operations require even/odd
> >       register combinations, and use PTImode where we need to deal with quad
> >       word memory operations.  Don't allow quad words in the argument or frame
> > @@ -2716,8 +2719,17 @@ rs6000_setup_reg_addr_masks (void)
> > 
> >    for (m = 0; m < NUM_MACHINE_MODES; ++m)
> >      {
> > -      machine_mode m2 = (machine_mode)m;
> > -      unsigned short msize = GET_MODE_SIZE (m2);
> > +      machine_mode m2 = (machine_mode) m;
> > +      bool complex_p = false;
> > +      size_t msize;
> > +
> > +      if (COMPLEX_MODE_P (m2))
> > +	{
> > +	  complex_p = true;
> > +	  m2 = GET_MODE_INNER (m2);
> > +	}
> > +
> > +      msize = GET_MODE_SIZE (m2);
> > 
> >        /* SDmode is special in that we want to access it only via REG+REG
> >  	 addressing on power7 and above, since we want to use the LFIWZX and
> > @@ -2739,7 +2751,7 @@ rs6000_setup_reg_addr_masks (void)
> >  	      /* Indicate if the mode takes more than 1 physical register.  If
> >  		 it takes a single register, indicate it can do REG+REG
> >  		 addressing.  */
> > -	      if (nregs > 1 || m == BLKmode)
> > +	      if (nregs > 1 || m == BLKmode || complex_p)
> >  		addr_mask |= RELOAD_REG_MULTIPLE;
> >  	      else
> >  		addr_mask |= RELOAD_REG_INDEXED;
> > @@ -2755,7 +2767,7 @@ rs6000_setup_reg_addr_masks (void)
> >  		  && msize <= 8
> >  		  && !VECTOR_MODE_P (m2)
> >  		  && !FLOAT128_VECTOR_P (m2)
> > -		  && !COMPLEX_MODE_P (m2)
> > +		  && !complex_p
> >  		  && (m2 != DFmode || !TARGET_UPPER_REGS_DF)
> >  		  && (m2 != SFmode || !TARGET_UPPER_REGS_SF)
> >  		  && !(TARGET_E500_DOUBLE && msize == 8))
> > @@ -10266,6 +10278,35 @@ rs6000_must_pass_in_stack (machine_mode 
> >      return must_pass_in_stack_var_size_or_pad (mode, type);
> >  }
> > 
> > +static inline bool
> > +is_complex_IBM_long_double (machine_mode mode)
> > +{
> > +  return mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode);
> > +}
> > +
> > +/* Whether ABI_V4 passes MODE args to a function in floating point
> > +   registers.  */
> > +
> > +static bool
> > +abi_v4_pass_in_fpr (machine_mode mode)
> > +{
> > +  if (!TARGET_FPRS || !TARGET_HARD_FLOAT)
> > +    return false;
> > +  if (TARGET_SINGLE_FLOAT && mode == SFmode)
> > +    return true;
> > +  if (TARGET_DOUBLE_FLOAT && mode == DFmode)
> > +    return true;
> > +  /* ABI_V4 passes complex IBM long double in 8 gprs.
> > +     Stupid, but we can't change the ABI now.  */
> > +  if (is_complex_IBM_long_double (mode))
> > +    return false;
> > +  if (FLOAT128_2REG_P (mode))
> > +    return true;
> > +  if (DECIMAL_FLOAT_MODE_P (mode))
> > +    return true;
> > +  return false;
> > +}
> > +
> >  /* If defined, a C expression which determines whether, and in which
> >     direction, to pad out an argument with extra space.  The value
> >     should be of type `enum direction': either `upward' to pad above
> > @@ -10350,6 +10391,7 @@ rs6000_function_arg_boundary (machine_mo
> >        && (GET_MODE_SIZE (mode) == 8
> >  	  || (TARGET_HARD_FLOAT
> >  	      && TARGET_FPRS
> > +	      && !is_complex_IBM_long_double (mode)
> >  	      && FLOAT128_2REG_P (mode))))
> >      return 64;
> >    else if (FLOAT128_VECTOR_P (mode))
> > @@ -10729,11 +10771,7 @@ rs6000_function_arg_advance_1 (CUMULATIV
> >      }
> >    else if (DEFAULT_ABI == ABI_V4)
> >      {
> > -      if (TARGET_HARD_FLOAT && TARGET_FPRS
> > -	  && ((TARGET_SINGLE_FLOAT && mode == SFmode)
> > -	      || (TARGET_DOUBLE_FLOAT && mode == DFmode)
> > -	      || FLOAT128_2REG_P (mode)
> > -	      || DECIMAL_FLOAT_MODE_P (mode)))
> > +      if (abi_v4_pass_in_fpr (mode))
> >  	{
> >  	  /* _Decimal128 must use an even/odd register pair.  This assumes
> >  	     that the register number is odd when fregno is odd.  */
> > @@ -11390,11 +11428,7 @@ rs6000_function_arg (cumulative_args_t c
> > 
> >    else if (abi == ABI_V4)
> >      {
> > -      if (TARGET_HARD_FLOAT && TARGET_FPRS
> > -	  && ((TARGET_SINGLE_FLOAT && mode == SFmode)
> > -	      || (TARGET_DOUBLE_FLOAT && mode == DFmode)
> > -	      || FLOAT128_2REG_P (mode)
> > -	      || DECIMAL_FLOAT_MODE_P (mode)))
> > +      if (abi_v4_pass_in_fpr (mode))
> >  	{
> >  	  /* _Decimal128 must use an even/odd register pair.  This assumes
> >  	     that the register number is odd when fregno is odd.  */
> > @@ -12315,19 +12349,15 @@ rs6000_gimplify_va_arg (tree valist, tre
> >    rsize = (size + 3) / 4;
> >    align = 1;
> > 
> > -  if (TARGET_HARD_FLOAT && TARGET_FPRS
> > -      && ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode)
> > -          || (TARGET_DOUBLE_FLOAT 
> > -              && (TYPE_MODE (type) == DFmode 
> > -		  || FLOAT128_2REG_P (TYPE_MODE (type))
> > -		  || DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))))))
> > +  machine_mode mode = TYPE_MODE (type);
> > +  if (abi_v4_pass_in_fpr (mode))
> >      {
> >        /* FP args go in FP registers, if present.  */
> >        reg = fpr;
> >        n_reg = (size + 7) / 8;
> >        sav_ofs = ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? 8 : 4) * 4;
> >        sav_scale = ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? 8 : 4);
> > -      if (TYPE_MODE (type) != SFmode && TYPE_MODE (type) != SDmode)
> > +      if (mode != SFmode && mode != SDmode)
> >  	align = 8;
> >      }
> >    else
> > @@ -12347,7 +12377,7 @@ rs6000_gimplify_va_arg (tree valist, tre
> >    addr = create_tmp_var (ptr_type_node, "addr");
> > 
> >    /*  AltiVec vectors never go in registers when -mabi=altivec.  */
> > -  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
> > +  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
> >      align = 16;
> >    else
> >      {
> > @@ -12368,7 +12398,7 @@ rs6000_gimplify_va_arg (tree valist, tre
> >  	}
> >        /* _Decimal128 is passed in even/odd fpr pairs; the stored
> >  	 reg number is 0 for f1, so we want to make it odd.  */
> > -      else if (reg == fpr && TYPE_MODE (type) == TDmode)
> > +      else if (reg == fpr && mode == TDmode)
> >  	{
> >  	  t = build2 (BIT_IOR_EXPR, TREE_TYPE (reg), unshare_expr (reg),
> >  		      build_int_cst (TREE_TYPE (reg), 1));
> > @@ -12395,7 +12425,7 @@ rs6000_gimplify_va_arg (tree valist, tre
> >  	 FP register for 32-bit binaries.  */
> >        if (TARGET_32BIT
> >  	  && TARGET_HARD_FLOAT && TARGET_FPRS
> > -	  && TYPE_MODE (type) == SDmode)
> > +	  && mode == SDmode)
> >  	t = fold_build_pointer_plus_hwi (t, size);
> > 
> >        gimplify_assign (addr, t, pre_p);
> > @@ -18464,25 +18494,33 @@ rs6000_secondary_reload_memory (rtx addr
> >      addr_mask = (reg_addr[mode].addr_mask[RELOAD_REG_VMX]
> >  		 & ~RELOAD_REG_AND_M16);
> > 
> > -  else
> > +  /* If the register allocator hasn't made up its mind yet on the register
> > +     class to use, settle on defaults to use.  */
> > +  else if (rclass == NO_REGS)
> >      {
> > -      if (TARGET_DEBUG_ADDR)
> > -	fprintf (stderr,
> > -		 "rs6000_secondary_reload_memory: mode = %s, class = %s, "
> > -		 "class is not GPR, FPR, VMX\n",
> > -		 GET_MODE_NAME (mode), reg_class_names[rclass]);
> > +      addr_mask = (reg_addr[mode].addr_mask[RELOAD_REG_ANY]
> > +		   & ~RELOAD_REG_AND_M16);
> > 
> > -      return -1;
> > +      if ((addr_mask & RELOAD_REG_MULTIPLE) != 0)
> > +	addr_mask &= ~(RELOAD_REG_INDEXED
> > +		       | RELOAD_REG_PRE_INCDEC
> > +		       | RELOAD_REG_PRE_MODIFY);
> >      }
> > 
> > +  else
> > +    addr_mask = 0;
> > +
> >    /* If the register isn't valid in this register class, just return now.  */
> >    if ((addr_mask & RELOAD_REG_VALID) == 0)
> >      {
> >        if (TARGET_DEBUG_ADDR)
> > -	fprintf (stderr,
> > -		 "rs6000_secondary_reload_memory: mode = %s, class = %s, "
> > -		 "not valid in class\n",
> > -		 GET_MODE_NAME (mode), reg_class_names[rclass]);
> > +	{
> > +	  fprintf (stderr,
> > +		   "rs6000_secondary_reload_memory: mode = %s, class = %s, "
> > +		   "not valid in class\n",
> > +		   GET_MODE_NAME (mode), reg_class_names[rclass]);
> > +	  debug_rtx (addr);
> > +	}
> > 
> >        return -1;
> >      }
> > @@ -19143,6 +19181,9 @@ rs6000_secondary_reload (bool in_p,
> >  	fprintf (stderr, ", reload func = %s, extra cost = %d",
> >  		 insn_data[sri->icode].name, sri->extra_cost);
> > 
> > +      else if (sri->extra_cost > 0)
> > +	fprintf (stderr, ", extra cost = %d", sri->extra_cost);
> > +
> >        fputs ("\n", stderr);
> >        debug_rtx (x);
> >      }
> > @@ -19553,6 +19594,16 @@ rs6000_preferred_reload_class (rtx x, en
> >    machine_mode mode = GET_MODE (x);
> >    bool is_constant = CONSTANT_P (x);
> > 
> > +  /* If a mode can't go in FPR/ALTIVEC/VSX registers, don't return a preferred
> > +     reload class for it.  */
> > +  if ((rclass == ALTIVEC_REGS || rclass == VSX_REGS)
> > +      && (reg_addr[mode].addr_mask[RELOAD_REG_VMX] & RELOAD_REG_VALID) == 0)
> > +    return NO_REGS;
> > +
> > +  if ((rclass == FLOAT_REGS || rclass == VSX_REGS)
> > +      && (reg_addr[mode].addr_mask[RELOAD_REG_FPR] & RELOAD_REG_VALID) == 0)
> > +    return NO_REGS;
> > +
> >    /* For VSX, see if we should prefer FLOAT_REGS or ALTIVEC_REGS.  Do not allow
> >       the reloading of address expressions using PLUS into floating point
> >       registers.  */
> > @@ -19603,6 +19654,25 @@ rs6000_preferred_reload_class (rtx x, en
> >        return NO_REGS;
> >      }
> > 
> > +  /* If we haven't picked a register class, and the type is a vector or
> > +     floating point type, prefer to use the VSX, FPR, or Altivec register
> > +     classes.  */
> > +  if (rclass == NO_REGS)
> > +    {
> > +      if (TARGET_VSX && VECTOR_MEM_VSX_OR_P8_VECTOR_P (mode))
> > +	return VSX_REGS;
> > +
> > +      if (TARGET_ALTIVEC && VECTOR_MEM_ALTIVEC_P (mode))
> > +	return ALTIVEC_REGS;
> > +
> > +      if (DECIMAL_FLOAT_MODE_P (mode))
> > +	return TARGET_DFP ? FLOAT_REGS : NO_REGS;
> > +
> > +      if (TARGET_FPRS && TARGET_HARD_FLOAT && FLOAT_MODE_P (mode)
> > +	  && (reg_addr[mode].addr_mask[RELOAD_REG_FPR] & RELOAD_REG_VALID) == 0)
> > +	return FLOAT_REGS;
> > +    }
> > +
> >    if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
> >      return GENERAL_REGS;
> > 
> > @@ -34549,8 +34619,14 @@ rs6000_complex_function_value (machine_m
> >    machine_mode inner = GET_MODE_INNER (mode);
> >    unsigned int inner_bytes = GET_MODE_UNIT_SIZE (mode);
> > 
> > -  if (FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
> > +  if (TARGET_FLOAT128
> > +      && (mode == KCmode
> > +	  || (mode == TCmode && TARGET_IEEEQUAD)))
> > +    regno = ALTIVEC_ARG_RETURN;
> > +
> > +  else if (FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
> >      regno = FP_ARG_RETURN;
> > +
> >    else
> >      {
> >        regno = GP_ARG_RETURN;
> > Index: gcc/config/rs6000/rs6000.h
> > ===================================================================
> > --- gcc/config/rs6000/rs6000.h	(revision 237045)
> > +++ gcc/config/rs6000/rs6000.h	(working copy)
> > @@ -418,12 +418,12 @@ extern const char *host_detect_local_cpu
> >     Similarly IFmode is the IBM long double format even if the default is IEEE
> >     128-bit.  */
> >  #define FLOAT128_IEEE_P(MODE)						\
> > -  (((MODE) == TFmode && TARGET_IEEEQUAD)				\
> > -   || ((MODE) == KFmode))
> > +  ((TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode))		\
> > +   || ((MODE) == KFmode) || ((MODE) == KCmode))
> > 
> >  #define FLOAT128_IBM_P(MODE)						\
> > -  (((MODE) == TFmode && !TARGET_IEEEQUAD)				\
> > -   || ((MODE) == IFmode))
> > +  ((!TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode))		\
> > +   || ((MODE) == IFmode) || ((MODE) == ICmode))
> > 
> >  /* Helper macros to say whether a 128-bit floating point type can go in a
> >     single vector register, or whether it needs paired scalar values.  */
> > @@ -1789,7 +1789,9 @@ extern enum reg_class rs6000_constraints
> >  #define ALTIVEC_ARG_RETURN (FIRST_ALTIVEC_REGNO + 2)
> >  #define FP_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2 ? FP_ARG_RETURN	\
> >  			   : (FP_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
> > -#define ALTIVEC_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2 ? ALTIVEC_ARG_RETURN \
> > +#define ALTIVEC_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2		\
> > +				? (ALTIVEC_ARG_RETURN			\
> > +				   + (TARGET_FLOAT128 ? 1 : 0))		\
> >  			        : (ALTIVEC_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
> > 
> >  /* Flags for the call/call_value rtl operations set up by function_arg */
> > Index: gcc/doc/extend.texi
> > ===================================================================
> > --- gcc/doc/extend.texi	(revision 237045)
> > +++ gcc/doc/extend.texi	(working copy)
> > @@ -962,8 +962,13 @@ complex @code{__float128} type.  When th
> >  would use the following syntax to declare @code{_Complex128} to be a
> >  complex @code{__float128} type:
> > 
> > +On the PowerPC Linux VSX targets, you can declare complex types using
> > +the corresponding internal complex type, @code{KCmode} for
> > +@code{__float128} type and @code{ICmode} for @code{__ibm128} type:
> > +
> >  @smallexample
> > -typedef _Complex float __attribute__((mode(KC))) _Complex128;
> > +typedef _Complex float __attribute__((mode(KC))) _Complex_float128;
> > +typedef _Complex float __attribute__((mode(IC))) _Complex_ibm128;
> >  @end smallexample
> > 
> >  Not all targets support additional floating-point types.
> > Index: gcc/fortran/trans-types.c
> > ===================================================================
> > --- gcc/fortran/trans-types.c	(revision 237045)
> > +++ gcc/fortran/trans-types.c	(working copy)
> > @@ -828,6 +828,7 @@ gfc_build_complex_type (tree scalar_type
> > 
> >    new_type = make_node (COMPLEX_TYPE);
> >    TREE_TYPE (new_type) = scalar_type;
> > +  SET_TYPE_MODE (new_type, GET_MODE_COMPLEX_MODE (TYPE_MODE (scalar_type)));
> >    layout_type (new_type);
> >    return new_type;
> >  }
> > Index: gcc/testsuite/gcc.target/powerpc/float128-complex-1.c
> > ===================================================================
> > --- gcc/testsuite/gcc.target/powerpc/float128-complex-1.c	(revision 0)
> > +++ gcc/testsuite/gcc.target/powerpc/float128-complex-1.c	(revision 0)
> > @@ -0,0 +1,157 @@
> > +/* { dg-do compile { target { powerpc*-*-linux* } } } */
> > +/* { dg-require-effective-target powerpc_float128_sw_ok } */
> > +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
> > +/* { dg-options "-O2 -mcpu=power7 -mfloat128" } */
> > +
> > +#ifndef NO_FLOAT
> > +typedef _Complex float	float_complex;
> > +extern float_complex cfloat1 (void);
> > +extern float_complex cfloat2 (void);
> > +
> > +#define FLOAT_ARG(NAME, OP)	ARG_OP(float, float_complex, NAME, OP)
> > +#define FLOAT_PTR(NAME, OP)	PTR_OP(float, float_complex, NAME, OP)
> > +#define FLOAT_CALL()		CALL_OP(float, float_complex, cfloat1, cfloat2)
> > +
> > +#else
> > +#define FLOAT_ARG(NAME, OP)
> > +#define FLOAT_PTR(NAME, OP)
> > +#define FLOAT_CALL()
> > +#endif
> > +
> > +#ifndef NO_DOUBLE
> > +typedef _Complex double	double_complex;
> > +extern double_complex cdouble1 (void);
> > +extern double_complex cdouble2 (void);
> > +
> > +#define DOUBLE_ARG(NAME, OP)	ARG_OP(double, double_complex, NAME, OP)
> > +#define DOUBLE_PTR(NAME, OP)	PTR_OP(double, double_complex, NAME, OP)
> > +#define DOUBLE_CALL()		CALL_OP(double, double_complex, cdouble1, cdouble2)
> > +
> > +#else
> > +#define DOUBLE_ARG(NAME, OP)
> > +#define DOUBLE_PTR(NAME, OP)
> > +#define DOUBLE_CALL()
> > +#endif
> > +
> > +#ifndef NO_FLOAT128
> > +#ifdef __VSX__
> > +typedef _Complex float __attribute__((mode(KC)))	float128_complex;
> > +#else
> > +typedef _Complex float __attribute__((mode(TC)))	float128_complex;
> > +#endif
> > +
> > +extern float128_complex cfloat128_1 (void);
> > +extern float128_complex cfloat128_2 (void);
> > +
> > +#define FLOAT128_ARG(NAME, OP)	ARG_OP(float128, float128_complex, NAME, OP)
> > +#define FLOAT128_PTR(NAME, OP)	PTR_OP(float128, float128_complex, NAME, OP)
> > +#define FLOAT128_CALL()		CALL_OP(float128, float128_complex, cfloat128_1, cfloat128_2)
> > +
> > +#else
> > +#define FLOAT128_ARG(NAME, OP)
> > +#define FLOAT128_PTR(NAME, OP)
> > +#define FLOAT128_CALL()
> > +#endif
> > +
> > +#ifndef NO_LDOUBLE
> > +typedef _Complex long double ldouble_complex;
> > +extern ldouble_complex cldouble1 (void);
> > +extern ldouble_complex cldouble2 (void);
> > +
> > +#define LDOUBLE_ARG(NAME, OP)	ARG_OP(ldouble, ldouble_complex, NAME, OP)
> > +#define LDOUBLE_PTR(NAME, OP)	PTR_OP(ldouble, ldouble_complex, NAME, OP)
> > +#define LDOUBLE_CALL()		CALL_OP(ldouble, ldouble_complex, cldouble1, cldouble2)
> > +
> > +#else
> > +#define LDOUBLE_ARG(NAME, OP)
> > +#define LDOUBLE_PTR(NAME, OP)
> > +#define LDOUBLE_CALL()
> > +#endif
> > +
> > +
> > +#define ARG_OP(SUFFIX, TYPE, NAME, OP)					\
> > +TYPE arg_ ## NAME ## _ ## SUFFIX (TYPE a, TYPE b)			\
> > +{									\
> > +  return a OP b;							\
> > +}
> > +
> > +#define PTR_OP(SUFFIX, TYPE, NAME, OP)					\
> > +void ptr_ ## NAME ## _ ## SUFFIX (TYPE *p, TYPE *a, TYPE *b)		\
> > +{									\
> > +  *p = *a OP *b;							\
> > +}
> > +
> > +#define CALL_OP(SUFFIX, TYPE, FUNC1, FUNC2)				\
> > +TYPE call_ ## SUFFIX (void)						\
> > +{									\
> > +  TYPE value1 = FUNC1 ();						\
> > +  TYPE value2 = FUNC2 ();						\
> > +  return value1 + value2;						\
> > +}
> > +
> > +#ifndef NO_ARG
> > +#ifndef NO_ADD
> > +FLOAT_ARG    (add, +)
> > +DOUBLE_ARG   (add, +)
> > +FLOAT128_ARG (add, +)
> > +LDOUBLE_ARG  (add, +)
> > +#endif
> > +
> > +#ifndef NO_SUB
> > +FLOAT_ARG    (sub, -)
> > +DOUBLE_ARG   (sub, -)
> > +FLOAT128_ARG (sub, -)
> > +LDOUBLE_ARG  (sub, -)
> > +#endif
> > +
> > +#ifndef NO_MUL
> > +FLOAT_ARG    (mul, *)
> > +DOUBLE_ARG   (mul, *)
> > +FLOAT128_ARG (mul, *)
> > +LDOUBLE_ARG  (mul, *)
> > +#endif
> > +
> > +#ifndef NO_DIV
> > +FLOAT_ARG    (div, /)
> > +DOUBLE_ARG   (div, /)
> > +FLOAT128_ARG (div, /)
> > +LDOUBLE_ARG  (div, /)
> > +#endif
> > +#endif
> > +
> > +#ifndef NO_PTR
> > +#ifndef NO_ADD
> > +FLOAT_PTR    (add, +)
> > +DOUBLE_PTR   (add, +)
> > +FLOAT128_PTR (add, +)
> > +LDOUBLE_PTR  (add, +)
> > +#endif
> > +
> > +#ifndef NO_SUB
> > +FLOAT_PTR    (sub, -)
> > +DOUBLE_PTR   (sub, -)
> > +FLOAT128_PTR (sub, -)
> > +LDOUBLE_PTR  (sub, -)
> > +#endif
> > +
> > +#ifndef NO_MUL
> > +FLOAT_PTR    (mul, *)
> > +DOUBLE_PTR   (mul, *)
> > +FLOAT128_PTR (mul, *)
> > +LDOUBLE_PTR  (mul, *)
> > +#endif
> > +
> > +#ifndef NO_DIV
> > +FLOAT_PTR    (div, /)
> > +DOUBLE_PTR   (div, /)
> > +FLOAT128_PTR (div, /)
> > +LDOUBLE_PTR  (div, /)
> > +#endif
> > +#endif
> > +
> > +#ifndef NO_CALL
> > +FLOAT_CALL    ()
> > +DOUBLE_CALL   ()
> > +FLOAT128_CALL ()
> > +LDOUBLE_CALL  ()
> > +#endif
> > Index: gcc/testsuite/gcc.target/powerpc/float128-complex-2.c
> > ===================================================================
> > --- gcc/testsuite/gcc.target/powerpc/float128-complex-2.c	(revision 0)
> > +++ gcc/testsuite/gcc.target/powerpc/float128-complex-2.c	(revision 0)
> > @@ -0,0 +1,160 @@
> > +/* { dg-do compile { target { powerpc*-*-linux* } } } */
> > +/* { dg-require-effective-target powerpc_float128_hw_ok } */
> > +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
> > +/* { dg-options "-O2 -mcpu=power9 -mfloat128 -mfloat128-hardware" } */
> > +
> > +#ifndef NO_FLOAT
> > +typedef _Complex float	float_complex;
> > +extern float_complex cfloat1 (void);
> > +extern float_complex cfloat2 (void);
> > +
> > +#define FLOAT_ARG(NAME, OP)	ARG_OP(float, float_complex, NAME, OP)
> > +#define FLOAT_PTR(NAME, OP)	PTR_OP(float, float_complex, NAME, OP)
> > +#define FLOAT_CALL()		CALL_OP(float, float_complex, cfloat1, cfloat2)
> > +
> > +#else
> > +#define FLOAT_ARG(NAME, OP)
> > +#define FLOAT_PTR(NAME, OP)
> > +#define FLOAT_CALL()
> > +#endif
> > +
> > +#ifndef NO_DOUBLE
> > +typedef _Complex double	double_complex;
> > +extern double_complex cdouble1 (void);
> > +extern double_complex cdouble2 (void);
> > +
> > +#define DOUBLE_ARG(NAME, OP)	ARG_OP(double, double_complex, NAME, OP)
> > +#define DOUBLE_PTR(NAME, OP)	PTR_OP(double, double_complex, NAME, OP)
> > +#define DOUBLE_CALL()		CALL_OP(double, double_complex, cdouble1, cdouble2)
> > +
> > +#else
> > +#define DOUBLE_ARG(NAME, OP)
> > +#define DOUBLE_PTR(NAME, OP)
> > +#define DOUBLE_CALL()
> > +#endif
> > +
> > +#ifndef NO_FLOAT128
> > +#ifdef __VSX__
> > +typedef _Complex float __attribute__((mode(KC)))	float128_complex;
> > +#else
> > +typedef _Complex float __attribute__((mode(TC)))	float128_complex;
> > +#endif
> > +
> > +extern float128_complex cfloat128_1 (void);
> > +extern float128_complex cfloat128_2 (void);
> > +
> > +#define FLOAT128_ARG(NAME, OP)	ARG_OP(float128, float128_complex, NAME, OP)
> > +#define FLOAT128_PTR(NAME, OP)	PTR_OP(float128, float128_complex, NAME, OP)
> > +#define FLOAT128_CALL()		CALL_OP(float128, float128_complex, cfloat128_1, cfloat128_2)
> > +
> > +#else
> > +#define FLOAT128_ARG(NAME, OP)
> > +#define FLOAT128_PTR(NAME, OP)
> > +#define FLOAT128_CALL()
> > +#endif
> > +
> > +#ifndef NO_LDOUBLE
> > +typedef _Complex long double ldouble_complex;
> > +extern ldouble_complex cldouble1 (void);
> > +extern ldouble_complex cldouble2 (void);
> > +
> > +#define LDOUBLE_ARG(NAME, OP)	ARG_OP(ldouble, ldouble_complex, NAME, OP)
> > +#define LDOUBLE_PTR(NAME, OP)	PTR_OP(ldouble, ldouble_complex, NAME, OP)
> > +#define LDOUBLE_CALL()		CALL_OP(ldouble, ldouble_complex, cldouble1, cldouble2)
> > +
> > +#else
> > +#define LDOUBLE_ARG(NAME, OP)
> > +#define LDOUBLE_PTR(NAME, OP)
> > +#define LDOUBLE_CALL()
> > +#endif
> > +
> > +
> > +#define ARG_OP(SUFFIX, TYPE, NAME, OP)					\
> > +TYPE arg_ ## NAME ## _ ## SUFFIX (TYPE a, TYPE b)			\
> > +{									\
> > +  return a OP b;							\
> > +}
> > +
> > +#define PTR_OP(SUFFIX, TYPE, NAME, OP)					\
> > +void ptr_ ## NAME ## _ ## SUFFIX (TYPE *p, TYPE *a, TYPE *b)		\
> > +{									\
> > +  *p = *a OP *b;							\
> > +}
> > +
> > +#define CALL_OP(SUFFIX, TYPE, FUNC1, FUNC2)				\
> > +TYPE call_ ## SUFFIX (void)						\
> > +{									\
> > +  TYPE value1 = FUNC1 ();						\
> > +  TYPE value2 = FUNC2 ();						\
> > +  return value1 + value2;						\
> > +}
> > +
> > +#ifndef NO_ARG
> > +#ifndef NO_ADD
> > +FLOAT_ARG    (add, +)
> > +DOUBLE_ARG   (add, +)
> > +FLOAT128_ARG (add, +)
> > +LDOUBLE_ARG  (add, +)
> > +#endif
> > +
> > +#ifndef NO_SUB
> > +FLOAT_ARG    (sub, -)
> > +DOUBLE_ARG   (sub, -)
> > +FLOAT128_ARG (sub, -)
> > +LDOUBLE_ARG  (sub, -)
> > +#endif
> > +
> > +#ifndef NO_MUL
> > +FLOAT_ARG    (mul, *)
> > +DOUBLE_ARG   (mul, *)
> > +FLOAT128_ARG (mul, *)
> > +LDOUBLE_ARG  (mul, *)
> > +#endif
> > +
> > +#ifndef NO_DIV
> > +FLOAT_ARG    (div, /)
> > +DOUBLE_ARG   (div, /)
> > +FLOAT128_ARG (div, /)
> > +LDOUBLE_ARG  (div, /)
> > +#endif
> > +#endif
> > +
> > +#ifndef NO_PTR
> > +#ifndef NO_ADD
> > +FLOAT_PTR    (add, +)
> > +DOUBLE_PTR   (add, +)
> > +FLOAT128_PTR (add, +)
> > +LDOUBLE_PTR  (add, +)
> > +#endif
> > +
> > +#ifndef NO_SUB
> > +FLOAT_PTR    (sub, -)
> > +DOUBLE_PTR   (sub, -)
> > +FLOAT128_PTR (sub, -)
> > +LDOUBLE_PTR  (sub, -)
> > +#endif
> > +
> > +#ifndef NO_MUL
> > +FLOAT_PTR    (mul, *)
> > +DOUBLE_PTR   (mul, *)
> > +FLOAT128_PTR (mul, *)
> > +LDOUBLE_PTR  (mul, *)
> > +#endif
> > +
> > +#ifndef NO_DIV
> > +FLOAT_PTR    (div, /)
> > +DOUBLE_PTR   (div, /)
> > +FLOAT128_PTR (div, /)
> > +LDOUBLE_PTR  (div, /)
> > +#endif
> > +#endif
> > +
> > +#ifndef NO_CALL
> > +FLOAT_CALL    ()
> > +DOUBLE_CALL   ()
> > +FLOAT128_CALL ()
> > +LDOUBLE_CALL  ()
> > +#endif
> > +
> > +/* { dg-final { scan-assembler "xsaddqp"  } } */
> > +/* { dg-final { scan-assembler "xssubqp"  } } */
> 
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]