From patchwork Wed Jun 22 18:17:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 639336 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rZXsD0nGZz9snk for ; Thu, 23 Jun 2016 04:18:23 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=xcTtjd3y; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:references:mime-version:content-type :in-reply-to:message-id; q=dns; s=default; b=HPIKsnqw7wkZsrwtOlF af38knPCRi/Oh1XBwFbN+r9DQsLg3Q4Anysge1yjmak/LRWGEFkoL1uOifWeI8Wm qnLtvG11eXk3UAMu2bs5Ea7EHZXjcPS06mWT3/aKmgfjUKfl857gk1QzXpkSD6Mw pt5s/a5YBijm9ukvIxSH8k84= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:references:mime-version:content-type :in-reply-to:message-id; s=default; bh=yiPv86HwvlEYgpIxwzy/blPeJ 5w=; b=xcTtjd3yTODztr0ogPPB+dlquHZ4pAqHqHymmiMM49pcPQAH7lQ/KDqQR nSsnevpMFMLRjSMQU+ufIf/JtGOem8f8a4sSDEwvm++GGsjepBFFCbC2uddvQNmp eqATTmuphvkstBEfZLWi6fbZmCsoyJ6G6O7PdyhV3KGUAglDxI= Received: (qmail 32152 invoked by alias); 22 Jun 2016 18:18:15 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 32137 invoked by uid 89); 22 Jun 2016 18:18:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.2 required=5.0 tests=AWL, BAYES_20, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, KAM_MANYTO, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=SET_TYPE_MODE, set_type_mode, Types, _decimal128 X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Wed, 22 Jun 2016 18:18:03 +0000 Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u5MICwqe085558 for ; Wed, 22 Jun 2016 14:18:01 -0400 Received: from e36.co.us.ibm.com (e36.co.us.ibm.com [32.97.110.154]) by mx0b-001b2d01.pphosted.com with ESMTP id 23qd1hcpy1-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 22 Jun 2016 14:18:01 -0400 Received: from localhost by e36.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 22 Jun 2016 12:18:00 -0600 Received: from d03dlp02.boulder.ibm.com (9.17.202.178) by e36.co.us.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 22 Jun 2016 12:17:56 -0600 X-IBM-Helo: d03dlp02.boulder.ibm.com X-IBM-MailFrom: meissner@ibm-tiger.the-meissners.org Received: from b03cxnp08026.gho.boulder.ibm.com (b03cxnp08026.gho.boulder.ibm.com [9.17.130.18]) by d03dlp02.boulder.ibm.com (Postfix) with ESMTP id E27203E40048; Wed, 22 Jun 2016 12:17:55 -0600 (MDT) Received: from b03ledav001.gho.boulder.ibm.com (b03ledav001.gho.boulder.ibm.com [9.17.130.232]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u5MIHt8h45285614; Wed, 22 Jun 2016 11:17:55 -0700 Received: from b03ledav001.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BF3296E010; Wed, 22 Jun 2016 12:17:55 -0600 (MDT) Received: from ibm-tiger.the-meissners.org (unknown [9.32.77.111]) by b03ledav001.gho.boulder.ibm.com (Postfix) with ESMTP id 81CCE6E03D; Wed, 22 Jun 2016 12:17:55 -0600 (MDT) Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id BEAD3443B7; Wed, 22 Jun 2016 14:17:54 -0400 (EDT) Date: Wed, 22 Jun 2016 14:17:54 -0400 From: Michael Meissner To: Richard Biener , Bill Schmidt , Michael Meissner , GCC Patches , Segher Boessenkool , David Edelsohn , Richard Henderson , Jakub Jelinek , Jeff Law Cc: Jason Merrill , Joseph Myers , Bernd Schmidt , Ian Lance Taylor , Jim Wilson Subject: Re: [PATCH] Backport PowerPC complex __float128 compiler support to GCC 6.x Mail-Followup-To: Michael Meissner , Richard Biener , Bill Schmidt , GCC Patches , Segher Boessenkool , David Edelsohn , Richard Henderson , Jakub Jelinek , Jeff Law , Jason Merrill , Joseph Myers , Bernd Schmidt , Ian Lance Taylor , Jim Wilson References: <20160603133335.GA28522@ibm-tiger.the-meissners.org> <20160609200653.GA3361@ibm-tiger.the-meissners.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-12-10) X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16062218-0020-0000-0000-000009293197 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16062218-0021-0000-0000-0000530DAB20 Message-Id: <20160622181754.GA24386@ibm-tiger.the-meissners.org> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-06-22_11:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1606220186 X-IsSubscribed: yes On Wed, Jun 15, 2016 at 11:01:05AM +0200, Richard Biener wrote: > And I don't understand the layout_type change either - it looks to me > it could just have used > > SET_TYPE_MODE (type, GET_MODE_COMPLEX_MODE (TYPE_MODE > (TREE_TYPE (type)))); > > and be done with it. To me that looks a lot safer. I made this change in the trunk, and now I would like approval for applying this code which includes the above change in the GCC 6.2 branch. Here is the change for the trunk: https://gcc.gnu.org/ml/gcc-patches/2016-06/msg01489.html I tested it on both a big endian power7 and a little endian power8 systems with no regressions. Is it ok to apply to the GCC 6.2 branch? [gcc] 2016-06-22 Michael Meissner Back port from trunk 2016-06-21 Michael Meissner * stor-layout.c (layout_type): Move setting complex MODE to layout_type, instead of setting it ahead of time by the caller. 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/testsuite] 2016-06-22 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. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 237619) +++ 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)) @@ -10447,6 +10459,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 @@ -10531,6 +10572,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)) @@ -10910,11 +10952,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. */ @@ -11571,11 +11609,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. */ @@ -12496,19 +12530,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 @@ -12528,7 +12558,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 { @@ -12549,7 +12579,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)); @@ -12576,7 +12606,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); @@ -18645,25 +18675,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; } @@ -19324,6 +19362,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); } @@ -19734,6 +19775,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. */ @@ -19784,6 +19835,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; @@ -34728,8 +34798,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 237619) +++ 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 237619) +++ 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/genmodes.c =================================================================== --- gcc/genmodes.c (revision 237619) +++ 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/machmode.h =================================================================== --- gcc/machmode.h (revision 237619) +++ 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 237619) +++ gcc/stor-layout.c (working copy) @@ -2147,10 +2147,8 @@ 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)); + GET_MODE_COMPLEX_MODE (TYPE_MODE (TREE_TYPE (type)))); + 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/testsuite/gcc.target/powerpc/float128-complex-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-complex-1.c (.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-complex-1.c (.../gcc/testsuite/gcc.target/powerpc) (revision 235777) @@ -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 (.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-complex-2.c (.../gcc/testsuite/gcc.target/powerpc) (revision 235777) @@ -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" } } */