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  <meiss...@linux.vnet.ibm.com>
> > 
> >     Back port from trunk
> >     2016-05-11  Alan Modra  <amo...@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  <meiss...@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  <meiss...@linux.vnet.ibm.com>
> > 
> >     Back port from trunk
> >     2016-05-02  Michael Meissner  <meiss...@linux.vnet.ibm.com>
> > 
> >     * trans-types.c (gfc_build_complex_type):
> > 
> > [gcc/testsuite]
> > 2016-06-02  Michael Meissner  <meiss...@linux.vnet.ibm.com>
> > 
> >     Back port from trunk
> >     2016-05-02  Michael Meissner  <meiss...@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: meiss...@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 <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to