From patchwork Tue Jun 16 22:15:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 485214 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 A721E1401F6 for ; Wed, 17 Jun 2015 08:16:11 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=YPfxTY22; 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:subject:message-id:references:mime-version:content-type :in-reply-to; q=dns; s=default; b=CoV1hU0GHAItD/lVTKVWJdRe5fIKvA 01ddCHrdFxaU2G0AxHzOMr0RqS7M3BnFE4GZB+dShHedMWwUD0xjfuqCsLcDjJgF wgugvr5FMqVRRREPQ6MM1BS9UNMfAoZH8/RGLzrt3rfG7BW1B6EVdIil4A/WB3Vy aF/nyt24LvlCE= 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:subject:message-id:references:mime-version:content-type :in-reply-to; s=default; bh=6tjmI4HwzZY5km3cw7KzZ/sMBS4=; b=YPfx TY221pxKgf9SfNM/zZ/wYPSJ7vVNPq1I1zmHmOWzf76exGtv7ys+dh/SdSv7EoWx MXLa2T/i6CqCIM8HfcKvCACLTAAYL/P34s1qMrKiAt49hs2l6C52U7jWq6YaBK4g PFbwoGLIiUYJhux3ogVnxBvepZCjm2Xz6q64ADU= Received: (qmail 76873 invoked by alias); 16 Jun 2015 22:16:03 -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 76860 invoked by uid 89); 16 Jun 2015 22:16:02 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.7 required=5.0 tests=AWL, BAYES_50, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 X-HELO: e39.co.us.ibm.com Received: from e39.co.us.ibm.com (HELO e39.co.us.ibm.com) (32.97.110.160) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Tue, 16 Jun 2015 22:16:00 +0000 Received: from /spool/local by e39.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 16 Jun 2015 16:15:58 -0600 Received: from d01dlp02.pok.ibm.com (9.56.250.167) by e39.co.us.ibm.com (192.168.1.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 16 Jun 2015 16:15:56 -0600 X-MailFrom: meissner@ibm-tiger.the-meissners.org X-RcptTo: gcc-patches@gcc.gnu.org Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 2B3196E8047 for ; Tue, 16 Jun 2015 18:07:42 -0400 (EDT) Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t5GMFtp761734934 for ; Tue, 16 Jun 2015 22:15:55 GMT Received: from d01av04.pok.ibm.com (localhost [127.0.0.1]) by d01av04.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t5GMFssq010366 for ; Tue, 16 Jun 2015 18:15:54 -0400 Received: from ibm-tiger.the-meissners.org (dhcp-9-32-77-111.usma.ibm.com [9.32.77.111]) by d01av04.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t5GMFs4E010333; Tue, 16 Jun 2015 18:15:54 -0400 Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id 7051A45EBF; Tue, 16 Jun 2015 18:15:53 -0400 (EDT) Date: Tue, 16 Jun 2015 18:15:53 -0400 From: Michael Meissner To: David Edelsohn , GCC Patches Subject: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Message-ID: <20150616221553.GA14264@ibm-tiger.the-meissners.org> Mail-Followup-To: Michael Meissner , David Edelsohn , GCC Patches References: <20150522212414.GA25650@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-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15061622-0033-0000-0000-000004E162C8 X-IsSubscribed: yes This is the second of my IEEE 128-bit floating point support. This patch adds new helper macros to the infrastructure, and changes the code in rs6000.c where we are supporting floating point to deal with IEEE 128-bit floating point when the rest of the patches are installed. I have tested these patches on a big endian power7 and a little endian power8 with no regressions. Are these patches ok to install in the trunk? 2015-06-16 Michael Meissner * config/rs6000/rs6000-protos.h (rs6000_secondary_reload_memory): Use machine mode, not enum machine_mode in the prototype. * config/rs6000/rs6000.h (FLOAT128_IEEE_P): New helper macros to classify 128-bit floating point support. (FLOAT128_IBM_P): Likewise. (FLOAT128_VECTOR_P): Likewise. (FLOAT128_2REG_P): Likewise. (SCALAR_FLOAT_MODE_NOT_VECTOR_P): Likewise. (SLOW_UNALIGNED_ACCESS): Add IEEE 128-bit floating point support. (HARD_REGNO_CALLER_SAVE_MODE): Likewise. (HARD_REGNO_CALL_PART_CLOBBERED): Likewise. * config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Drop tests against TFmode/TDmode, since those modes do not use VSX addresses. (rs6000_hard_regno_mode_ok): Add IEEE 128-bit floating point support. (rs6000_init_hard_regno_mode_ok): Use new helper macros instead of tests against TFmode, etc. (invalid_e500_subreg): Add tests against IFmode/KFmode. (reg_offset_addressing_ok_p): Likewise. (rs6000_legitimate_offset_address_p): Likewise. (rs6000_legitimize_address): Likewise. (rs6000_legitimize_reload_address): Likewise. (rs6000_legitimate_address_p): Clean up tests against TFmode and TDmode to use the new helper macros, which will include IFmode and KFmode. (rs6000_emit_move): Likewise. (rs6000_darwin64_record_arg_recurse): Likewise. (print_operand): Likewise. (rs6000_member_type_forces_blk): Treat IEEE 128-bit floating point that uses a single vector register as a vector and not as a floating point register in terms of the calling sequence. (rs6000_discover_homogeneous_aggregate): Likewise. (rs6000_return_in_memory): Likewise. (init_cumulative_args): Likewise. (rs6000_function_arg_boundary): Likewise. (rs6000_function_arg_advance_1): Likewise. (rs6000_function_arg): Likewise. (rs6000_pass_by_reference): Likewise. (rs6000_gimplify_va_arg): Likewise. (rs6000_secondary_reload_memory): Use machine_mode not enum machine mode. (rs6000_split_multireg_move): Use new helper macros. (spe_func_has_64bit_regs_p): Likewise. (rs6000_output_function_epilogue): Add IFmode/KFmode support. (output_toc): Use new helper macros. (rs6000_register_move_cost): Likewise. (rs6000_function_value): Add IEEE 128-bit floating point calling sequence support. (rs6000_libcall_value): Likewise. (rs6000_scalar_mode_supported_p): Add support for IEEE 128-bit floating point support. (rs6000_vector_mode_supported_p): Likewise. Note, I will be on vacation starting on Friday evening, and I will return on July 1st. If the patch approval comes after Thursday, I will hold these patches until I return and retest them. Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 224486) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -133,8 +133,7 @@ extern void rs6000_split_multireg_move ( extern void rs6000_emit_le_vsx_move (rtx, rtx, machine_mode); extern void rs6000_emit_move (rtx, rtx, machine_mode); extern rtx rs6000_secondary_memory_needed_rtx (machine_mode); -extern machine_mode rs6000_secondary_memory_needed_mode (enum - machine_mode); +extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode); extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode, int, int, int, int *); extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx, Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 224486) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -402,6 +402,33 @@ extern const char *host_detect_local_cpu #define TARGET_DEBUG_TARGET (rs6000_debug & MASK_DEBUG_TARGET) #define TARGET_DEBUG_BUILTIN (rs6000_debug & MASK_DEBUG_BUILTIN) +/* Helper macros for TFmode. Quad floating point (TFmode) can be either IBM + long double format that uses a pair of doubles, or IEEE 128-bit floating + point. KFmode was added as a way to represent IEEE 128-bit floating point, + even if the default for long double is the IBM long double format. + Similarly IFmode is the IBM long double format even if the default is IEEE + 128-bit. */ +#define FLOAT128_IEEE_P(MODE) \ + (((MODE) == KFmode) \ + || (((MODE) == TFmode) && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)) + +#define FLOAT128_IBM_P(MODE) \ + ((((MODE) == TFmode) && !TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128) \ + || ((MODE) == IFmode)) + +/* 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. */ +#define FLOAT128_VECTOR_P(MODE) (TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE)) + +#define FLOAT128_2REG_P(MODE) \ + (FLOAT128_IBM_P (MODE) \ + || ((MODE) == TDmode) \ + || (!TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE))) + +/* Return true for floating point that does not use a vector register. */ +#define SCALAR_FLOAT_MODE_NOT_VECTOR_P(MODE) \ + (SCALAR_FLOAT_MODE_P (MODE) && !FLOAT128_VECTOR_P (MODE)) + /* Describe the vector unit used for arithmetic operations. */ extern enum rs6000_vector rs6000_vector_unit[]; @@ -888,11 +915,10 @@ enum data_align { align_abi, align_opt, aligned to 4 or 8 bytes. */ #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \ (STRICT_ALIGNMENT \ - || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \ - || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode) \ - && (ALIGN) < 32) \ + || (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE) && (ALIGN) < 32) \ || (!TARGET_EFFICIENT_UNALIGNED_VSX \ - && (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE))))) + && ((VECTOR_MODE_P (MODE) || FLOAT128_VECTOR_P (MODE)) \ + && (((int)(ALIGN)) < VECTOR_ALIGN (MODE))))) /* Standard register usage. */ @@ -1174,7 +1200,7 @@ enum data_align { align_abi, align_opt, ? V2DFmode \ : TARGET_E500_DOUBLE && ((MODE) == VOIDmode || (MODE) == DFmode) \ ? DFmode \ - : !TARGET_E500_DOUBLE && (MODE) == TFmode && FP_REGNO_P (REGNO) \ + : !TARGET_E500_DOUBLE && FLOAT128_IBM_P (MODE) && FP_REGNO_P (REGNO) \ ? DFmode \ : !TARGET_E500_DOUBLE && (MODE) == TDmode && FP_REGNO_P (REGNO) \ ? DImode \ @@ -1185,8 +1211,7 @@ enum data_align { align_abi, align_opt, && (GET_MODE_SIZE (MODE) > 4) \ && INT_REGNO_P (REGNO)) ? 1 : 0) \ || (TARGET_VSX && FP_REGNO_P (REGNO) \ - && GET_MODE_SIZE (MODE) > 8 && ((MODE) != TDmode) \ - && ((MODE) != TFmode))) + && GET_MODE_SIZE (MODE) > 8 && !FLOAT128_2REG_P (MODE))) #define VSX_VECTOR_MODE(MODE) \ ((MODE) == V4SFmode \ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 224486) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1750,9 +1750,11 @@ rs6000_hard_regno_nregs_internal (int re { unsigned HOST_WIDE_INT reg_size; - /* TF/TD modes are special in that they always take 2 registers. */ + /* 128-bit floating point usually takes 2 registers, unless it is IEEE + 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) && mode != TDmode && mode != TFmode) + reg_size = (VECTOR_MEM_VSX_P (mode) ? UNITS_PER_VSX_WORD : UNITS_PER_FP_WORD); @@ -1809,6 +1811,7 @@ rs6000_hard_regno_mode_ok (int regno, ma asked for it. */ if (TARGET_VSX && VSX_REGNO_P (regno) && (VECTOR_MEM_VSX_P (mode) + || FLOAT128_VECTOR_P (mode) || reg_addr[mode].scalar_in_vmx_p || (TARGET_VSX_TIMODE && mode == TImode) || (TARGET_VADDUQM && mode == V1TImode))) @@ -1834,6 +1837,9 @@ rs6000_hard_regno_mode_ok (int regno, ma modes and DImode. */ if (FP_REGNO_P (regno)) { + if (FLOAT128_VECTOR_P (mode)) + return false; + if (SCALAR_FLOAT_MODE_P (mode) && (mode != TDmode || (regno % 2) == 0) && FP_REGNO_P (last_regno)) @@ -3009,9 +3015,9 @@ rs6000_init_hard_regno_mode_ok (bool glo machine_mode m2 = (machine_mode)m; int reg_size2 = reg_size; - /* TFmode/TDmode always takes 2 registers, even in VSX. */ - if (TARGET_VSX && VSX_REG_CLASS_P (c) - && (m == TDmode || m == TFmode)) + /* TDmode & IBM 128-bit floating point always takes 2 registers, even + in VSX. */ + if (TARGET_VSX && VSX_REG_CLASS_P (c) && FLOAT128_2REG_P (m)) reg_size2 = UNITS_PER_FP_WORD; rs6000_class_max_nregs[m][c] @@ -6116,13 +6122,16 @@ invalid_e500_subreg (rtx op, machine_mod || mode == DDmode || mode == TDmode || mode == PTImode) && REG_P (SUBREG_REG (op)) && (GET_MODE (SUBREG_REG (op)) == DFmode - || GET_MODE (SUBREG_REG (op)) == TFmode)) + || GET_MODE (SUBREG_REG (op)) == TFmode + || GET_MODE (SUBREG_REG (op)) == IFmode + || GET_MODE (SUBREG_REG (op)) == KFmode)) return true; /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and reg:TI. */ if (GET_CODE (op) == SUBREG - && (mode == DFmode || mode == TFmode) + && (mode == DFmode || mode == TFmode || mode == IFmode + || mode == KFmode) && REG_P (SUBREG_REG (op)) && (GET_MODE (SUBREG_REG (op)) == DImode || GET_MODE (SUBREG_REG (op)) == TImode @@ -6484,10 +6493,13 @@ reg_offset_addressing_ok_p (machine_mode case V2DImode: case V1TImode: case TImode: + case TFmode: + case KFmode: /* AltiVec/VSX vector modes. Only reg+reg addressing is valid. While TImode is not a vector mode, if we want to use the VSX registers to - move it around, we need to restrict ourselves to reg+reg - addressing. */ + move it around, we need to restrict ourselves to reg+reg addressing. + Similarly for IEEE 128-bit floating point that is passed in a single + vector register. */ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)) return false; break; @@ -6753,6 +6765,8 @@ rs6000_legitimate_offset_address_p (mach break; case TFmode: + case IFmode: + case KFmode: if (TARGET_E500_DOUBLE) return (SPE_CONST_OFFSET_OK (offset) && SPE_CONST_OFFSET_OK (offset + 8)); @@ -6946,6 +6960,8 @@ rs6000_legitimize_address (rtx x, rtx ol case TDmode: case TImode: case PTImode: + case IFmode: + case KFmode: /* As in legitimate_offset_address_p we do not assume worst-case. The mode here is just a hint as to the registers used. A TImode is usually in gprs, but may actually be in @@ -7718,6 +7734,8 @@ rs6000_legitimize_reload_address (rtx x, && !reg_addr[mode].scalar_in_vmx_p && mode != TFmode && mode != TDmode + && mode != IFmode + && mode != KFmode && (mode != TImode || !TARGET_VSX_TIMODE) && mode != PTImode && (mode != DImode || TARGET_POWERPC64) @@ -7871,8 +7889,7 @@ rs6000_legitimate_address_p (machine_mod return 1; if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict, false)) return 1; - if (mode != TFmode - && mode != TDmode + if (!FLOAT128_2REG_P (mode) && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_POWERPC64 || (mode != DFmode && mode != DDmode) @@ -8540,9 +8557,8 @@ rs6000_emit_move (rtx dest, rtx source, /* 128-bit constant floating-point values on Darwin should really be loaded as two parts. However, this premature splitting is a problem when DFmode values can go into Altivec registers. */ - if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 - && !reg_addr[DFmode].scalar_in_vmx_p - && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE) + if (FLOAT128_IBM_P (mode) && !reg_addr[DFmode].scalar_in_vmx_p + && GET_CODE (operands[1]) == CONST_DOUBLE) { rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode, 0), simplify_gen_subreg (DFmode, operands[1], mode, 0), @@ -8734,7 +8750,10 @@ rs6000_emit_move (rtx dest, rtx source, case TFmode: case TDmode: - rs6000_eliminate_indexed_memrefs (operands); + case IFmode: + case KFmode: + if (FLOAT128_2REG_P (mode)) + rs6000_eliminate_indexed_memrefs (operands); /* fall through */ case DFmode: @@ -8958,7 +8977,7 @@ rs6000_member_type_forces_blk (const_tre /* Nonzero if we can use a floating-point register to pass this arg. */ #define USE_FP_FOR_ARG_P(CUM,MODE) \ - (SCALAR_FLOAT_MODE_P (MODE) \ + (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE) \ && (CUM)->fregno <= FP_ARG_MAX_REG \ && TARGET_HARD_FLOAT && TARGET_FPRS) @@ -9159,7 +9178,7 @@ rs6000_discover_homogeneous_aggregate (m if (field_count > 0) { - int n_regs = (SCALAR_FLOAT_MODE_P (field_mode)? + int n_regs = (SCALAR_FLOAT_MODE_P (field_mode) ? (GET_MODE_SIZE (field_mode) + 7) >> 3 : 1); /* The ELFv2 ABI allows homogeneous aggregates to occupy @@ -9269,7 +9288,8 @@ rs6000_return_in_memory (const_tree type return true; } - if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && TYPE_MODE (type) == TFmode) + if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD + && FLOAT128_IEEE_P (TYPE_MODE (type))) return true; return false; @@ -9399,7 +9419,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c <= 8)) rs6000_returns_struct = true; } - if (SCALAR_FLOAT_MODE_P (return_mode)) + if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (return_mode)) rs6000_passes_float = true; else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode) || SPE_VECTOR_MODE (return_mode)) @@ -9537,8 +9557,10 @@ rs6000_function_arg_boundary (machine_mo && (GET_MODE_SIZE (mode) == 8 || (TARGET_HARD_FLOAT && TARGET_FPRS - && (mode == TFmode || mode == TDmode)))) + && FLOAT128_2REG_P (mode)))) return 64; + else if (FLOAT128_VECTOR_P (mode)) + return 128; else if (SPE_VECTOR_MODE (mode) || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) >= 8 @@ -9810,7 +9832,7 @@ rs6000_function_arg_advance_1 (CUMULATIV if (DEFAULT_ABI == ABI_V4 && cum->escapes) { - if (SCALAR_FLOAT_MODE_P (mode)) + if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode)) rs6000_passes_float = true; else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) rs6000_passes_vector = true; @@ -9917,21 +9939,21 @@ rs6000_function_arg_advance_1 (CUMULATIV if (TARGET_HARD_FLOAT && TARGET_FPRS && ((TARGET_SINGLE_FLOAT && mode == SFmode) || (TARGET_DOUBLE_FLOAT && mode == DFmode) - || (mode == TFmode && !TARGET_IEEEQUAD) - || mode == SDmode || mode == DDmode || mode == TDmode)) + || FLOAT128_2REG_P (mode) + || DECIMAL_FLOAT_MODE_P (mode))) { /* _Decimal128 must use an even/odd register pair. This assumes that the register number is odd when fregno is odd. */ if (mode == TDmode && (cum->fregno % 2) == 1) cum->fregno++; - if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0) + if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0) <= FP_ARG_V4_MAX_REG) cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3; else { cum->fregno = FP_ARG_V4_MAX_REG + 1; - if (mode == DFmode || mode == TFmode + if (mode == DFmode || FLOAT128_IBM_P (mode) || mode == DDmode || mode == TDmode) cum->words += cum->words & 1; cum->words += rs6000_arg_size (mode, type); @@ -9983,8 +10005,7 @@ rs6000_function_arg_advance_1 (CUMULATIV cum->words = align_words + n_words; - if (SCALAR_FLOAT_MODE_P (elt_mode) - && TARGET_HARD_FLOAT && TARGET_FPRS) + if (SCALAR_FLOAT_MODE_P (elt_mode) && TARGET_HARD_FLOAT && TARGET_FPRS) { /* _Decimal128 must be passed in an even/odd float register pair. This assumes that the register number is odd when fregno is @@ -10226,7 +10247,7 @@ rs6000_darwin64_record_arg_recurse (CUMU = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode, cum->fregno++), GEN_INT (bitpos / BITS_PER_UNIT)); - if (mode == TFmode || mode == TDmode) + if (FLOAT128_2REG_P (mode)) cum->fregno++; } else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, 1)) @@ -10577,15 +10598,15 @@ rs6000_function_arg (cumulative_args_t c if (TARGET_HARD_FLOAT && TARGET_FPRS && ((TARGET_SINGLE_FLOAT && mode == SFmode) || (TARGET_DOUBLE_FLOAT && mode == DFmode) - || (mode == TFmode && !TARGET_IEEEQUAD) - || mode == SDmode || mode == DDmode || mode == TDmode)) + || FLOAT128_2REG_P (mode) + || DECIMAL_FLOAT_MODE_P (mode))) { /* _Decimal128 must use an even/odd register pair. This assumes that the register number is odd when fregno is odd. */ if (mode == TDmode && (cum->fregno % 2) == 1) cum->fregno++; - if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0) + if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0) <= FP_ARG_V4_MAX_REG) return gen_rtx_REG (mode, cum->fregno); else @@ -10647,7 +10668,7 @@ rs6000_function_arg (cumulative_args_t c machine_mode fmode = elt_mode; if (cum->fregno + (i + 1) * n_fpreg > FP_ARG_MAX_REG + 1) { - gcc_assert (fmode == TFmode || fmode == TDmode); + gcc_assert (FLOAT128_2REG_P (fmode)); fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode; } @@ -10821,10 +10842,11 @@ rs6000_pass_by_reference (cumulative_arg machine_mode mode, const_tree type, bool named ATTRIBUTE_UNUSED) { - if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && mode == TFmode) + if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD + && FLOAT128_IEEE_P (TYPE_MODE (type))) { if (TARGET_DEBUG_ARG) - fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n"); + fprintf (stderr, "function_arg_pass_by_reference: V4 IEEE 128-bit\n"); return 1; } @@ -11499,10 +11521,8 @@ rs6000_gimplify_va_arg (tree valist, tre && ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode) || (TARGET_DOUBLE_FLOAT && (TYPE_MODE (type) == DFmode - || TYPE_MODE (type) == TFmode - || TYPE_MODE (type) == SDmode - || TYPE_MODE (type) == DDmode - || TYPE_MODE (type) == TDmode)))) + || FLOAT128_2REG_P (TYPE_MODE (type)) + || DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)))))) { /* FP args go in FP registers, if present. */ reg = fpr; @@ -16765,7 +16785,7 @@ rs6000_secondary_reload_toc_costs (addr_ static int rs6000_secondary_reload_memory (rtx addr, enum reg_class rclass, - enum machine_mode mode) + machine_mode mode) { int extra_cost = 0; rtx reg, and_arg, plus_arg0, plus_arg1; @@ -19063,7 +19083,7 @@ print_operand (FILE *file, rtx x, int co /* Ugly hack because %y is overloaded. */ if ((TARGET_SPE || TARGET_E500_DOUBLE) && (GET_MODE_SIZE (GET_MODE (x)) == 8 - || GET_MODE (x) == TFmode + || FLOAT128_2REG_P (GET_MODE (x)) || GET_MODE (x) == TImode || GET_MODE (x) == PTImode)) { @@ -21013,7 +21033,7 @@ rs6000_split_multireg_move (rtx dst, rtx ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? DFmode : SFmode); else if (ALTIVEC_REGNO_P (reg)) reg_mode = V16QImode; - else if (TARGET_E500_DOUBLE && mode == TFmode) + else if (TARGET_E500_DOUBLE && FLOAT128_2REG_P (mode)) reg_mode = DFmode; else reg_mode = word_mode; @@ -22090,7 +22110,8 @@ spe_func_has_64bit_regs_p (void) if (SPE_VECTOR_MODE (mode)) return true; - if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode)) + if (TARGET_E500_DOUBLE + && (mode == DFmode || FLOAT128_2REG_P (mode))) return true; } } @@ -25853,6 +25874,8 @@ rs6000_output_function_epilogue (FILE *f case DDmode: case TFmode: case TDmode: + case IFmode: + case KFmode: bits = 0x3; break; @@ -26526,7 +26549,8 @@ output_toc (FILE *file, rtx x, int label TOC, things we put here aren't actually in the TOC, so we can allow FP constants. */ if (GET_CODE (x) == CONST_DOUBLE && - (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode)) + (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode + || GET_MODE (x) == IFmode || GET_MODE (x) == KFmode)) { REAL_VALUE_TYPE rv; long k[4]; @@ -31050,7 +31074,7 @@ rs6000_register_move_cost (machine_mode /* Moving between two similar registers is just one instruction. */ else if (reg_classes_intersect_p (to, from)) - ret = (mode == TFmode || mode == TDmode) ? 4 : 2; + ret = (FLOAT128_2REG_P (mode)) ? 4 : 2; /* Everything else has to go through GENERAL_REGS. */ else @@ -32117,7 +32141,7 @@ rs6000_function_value (const_tree valtyp { int first_reg, n_regs; - if (SCALAR_FLOAT_MODE_P (elt_mode)) + if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (elt_mode)) { /* _Decimal128 must use even/odd register pairs. */ first_reg = (elt_mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN; @@ -32154,7 +32178,7 @@ rs6000_function_value (const_tree valtyp if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS) /* _Decimal128 must use an even/odd register pair. */ regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN; - else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS + else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS && ((TARGET_SINGLE_FLOAT && (mode == SFmode)) || TARGET_DOUBLE_FLOAT)) regno = FP_ARG_RETURN; else if (TREE_CODE (valtype) == COMPLEX_TYPE @@ -32163,13 +32187,13 @@ rs6000_function_value (const_tree valtyp /* VSX is a superset of Altivec and adds V2DImode/V2DFmode. Since the same return register is used in both cases, and we won't see V2DImode/V2DFmode for pure altivec, combine the two cases. */ - else if (TREE_CODE (valtype) == VECTOR_TYPE + else if ((TREE_CODE (valtype) == VECTOR_TYPE || FLOAT128_VECTOR_P (mode)) && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) regno = ALTIVEC_ARG_RETURN; else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT && (mode == DFmode || mode == DCmode - || mode == TFmode || mode == TCmode)) + || FLOAT128_IBM_P (mode) || mode == TCmode)) return spe_build_register_parallel (mode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; @@ -32191,7 +32215,7 @@ rs6000_libcall_value (machine_mode mode) if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS) /* _Decimal128 must use an even/odd register pair. */ regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN; - else if (SCALAR_FLOAT_MODE_P (mode) + else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS && ((TARGET_SINGLE_FLOAT && mode == SFmode) || TARGET_DOUBLE_FLOAT)) regno = FP_ARG_RETURN; @@ -32205,7 +32229,7 @@ rs6000_libcall_value (machine_mode mode) return rs6000_complex_function_value (mode); else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT && (mode == DFmode || mode == DCmode - || mode == TFmode || mode == TCmode)) + || FLOAT128_IBM_P (mode) || mode == TCmode)) return spe_build_register_parallel (mode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; @@ -32431,6 +32455,8 @@ rs6000_scalar_mode_supported_p (machine_ if (DECIMAL_FLOAT_MODE_P (mode)) return default_decimal_float_supported_p (); + else if (mode == KFmode) + return TARGET_FLOAT128; else return default_scalar_mode_supported_p (mode); } @@ -32446,7 +32472,10 @@ rs6000_vector_mode_supported_p (machine_ if (TARGET_SPE && SPE_VECTOR_MODE (mode)) return true; - else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)) + /* There is no vector form for IEEE 128-bit. If we return true for IEEE + 128-bit, the compiler might try to widen IEEE 128-bit to IBM + double-double. */ + else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) && !FLOAT128_IEEE_P (mode)) return true; else