This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Backport PowerPC complex __float128 compiler support to GCC 6.x
- From: Richard Biener <rguenther at suse dot de>
- To: Michael Meissner <meissner at linux dot vnet dot ibm dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Segher Boessenkool <segher at kernel dot crashing dot org>, Bill Schmidt <wschmidt at linux dot vnet dot ibm dot com>, David Edelsohn <dje dot gcc at gmail dot com>, Richard Henderson <rth at redhat dot com>, Jakub Jelinek <jakub at redhat dot com>, Jeff Law <law at redhat dot com>, Jason Merrill <jason at redhat dot com>, Joseph Myers <joseph at codesourcery dot com>, Bernd Schmidt <bschmidt at redhat dot com>, Ian Lance Taylor <ian at airs dot com>, Jim Wilson <wilson at tuliptree dot org>
- Date: Fri, 10 Jun 2016 09:06:10 +0200 (CEST)
- Subject: Re: [PATCH] Backport PowerPC complex __float128 compiler support to GCC 6.x
- Authentication-results: sourceware.org; auth=none
- References: <20160603133335 dot GA28522 at ibm-tiger dot the-meissners dot org> <20160609200653 dot GA3361 at ibm-tiger dot the-meissners dot org>
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)