From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 98460 invoked by alias); 10 Jun 2016 07:06:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 98439 invoked by uid 89); 10 Jun 2016 07:06:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.2 required=5.0 tests=BAYES_50,KAM_ASCII_DIVIDERS,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=sk:altivec, AltiVec, unshare_expr, TYPE_UNSIGNED X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Fri, 10 Jun 2016 07:06:15 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 38C08AAAD; Fri, 10 Jun 2016 07:06:11 +0000 (UTC) Date: Fri, 10 Jun 2016 07:06:00 -0000 From: Richard Biener To: Michael Meissner cc: gcc-patches@gcc.gnu.org, Segher Boessenkool , Bill Schmidt , David Edelsohn , Richard Henderson , Jakub Jelinek , Jeff Law , Jason Merrill , Joseph Myers , Bernd Schmidt , Ian Lance Taylor , Jim Wilson Subject: Re: [PATCH] Backport PowerPC complex __float128 compiler support to GCC 6.x In-Reply-To: <20160609200653.GA3361@ibm-tiger.the-meissners.org> Message-ID: References: <20160603133335.GA28522@ibm-tiger.the-meissners.org> <20160609200653.GA3361@ibm-tiger.the-meissners.org> User-Agent: Alpine 2.11 (LSU 23 2013-08-11) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2016-06/txt/msg00770.txt.bz2 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 > > > > Back port from trunk > > 2016-05-11 Alan Modra > > > > * 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 > > > > * 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 > > > > Back port from trunk > > 2016-05-02 Michael Meissner > > > > * trans-types.c (gfc_build_complex_type): > > > > [gcc/testsuite] > > 2016-06-02 Michael Meissner > > > > Back port from trunk > > 2016-05-02 Michael Meissner > > > > * 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, "", MAX_MODE_CLASS, > > -1U, -1U, -1U, -1U, > > - 0, 0, 0, 0, 0, > > + 0, 0, 0, 0, 0, 0, > > "", 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 SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)