* [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 @ 2015-05-22 21:47 Michael Meissner 2015-06-02 17:51 ` David Edelsohn 2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers 0 siblings, 2 replies; 13+ messages in thread From: Michael Meissner @ 2015-05-22 21:47 UTC (permalink / raw) To: gcc-patches, dje.gcc [-- Attachment #1: Type: text/plain, Size: 2794 bytes --] This patch is the first in a series of patches that will eventually add support for IEEE 128-bit floating point support to the PowerPC GCC compiler. At the current time, we do not plan to change the default for long double. I added a new type keyword (__float128) to get access to IEEE 128-bit floating point, and another (__ibm128) to get access to IBM extended double type. Until all of the GCC and LIBGCC patches have been committed, you will not be able to use IEEE 128-bit floating point, and -mfloat128-software will not be turned on by default. This patch adds the new modes (KFmode and IFmode) and the switches (-mfloat128-{none,software}). Due to the fact that TFmode in the PowerPC compiler either represents IEEE 128-bit floating point or the IBM extended double (double-double) format. For most PowerPC users, the default is to use IBM extended double for long double. Because TFmode can be either floating point format, I added new new modes: KFmode -- IEEE 128-bit floating point IFmode -- IBM extended double floating point If the default for TFmode is ibm extended double, the port will eventually use KFmode for IEEE 128-bit floating point. Likewise if the default for TFmode is IEEE 128-bit floating point, the port will use TFmode for IEEE 128-bit floating point, and IFmode for IBM extended double. I have bootstraped these patches on a power7 and compared them to the unpatched compiler. There were no changes when running make check. Are these patches ok to install in the trunk? 2015-05-22 Michael Meissner <meissner@linux.vnet.ibm.com> * config/rs6000/rs6000-modes.def (IFmode): Define IFmode to provide access to the IBM extended double floating point mode if long double is IEEE 128-bit floating point. (KFmode): Define KFmode to provide access to IEEE 128-bit floating point if long double is the IBM extended double type. * config/rs6000/rs6000.opt (-mfloat128-none): New switches to enable adding IEEE 128-bit floating point support. (-mfloat128-software): Likewise. (-mfloat128-sw): Likewise. * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Do not allow 128-bit floating point types to occupy any register if -mlong-double-64. Do not allow use of IFmode/KFmode unless -mfloat128-software is enabled. (rs6000_debug_reg_global): Add IEEE 128-bit floating point debug support. (rs6000_option_override_internal): Add -mfloat128-* support. (rs6000_init_builtins): Setup __ibm128 and __float128 type modes. * config/rs6000/rs6000.h (rs6000_builtin_type_index): Add ibm128 and float128 type nodes. (ieee128_float_type_node): Likewise. (ibm128_float_type_node): 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 [-- Attachment #2: ieee128-patch01b --] [-- Type: text/plain, Size: 7913 bytes --] Index: gcc/config/rs6000/rs6000-modes.def =================================================================== --- gcc/config/rs6000/rs6000-modes.def (revision 223458) +++ gcc/config/rs6000/rs6000-modes.def (working copy) @@ -18,6 +18,13 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* IBM 128-bit floating point. IFmode and KFmode use the fractional float + support in order to declare 3 128-bit floating point types. */ +FRACTIONAL_FLOAT_MODE (IF, 106, 16, ibm_extended_format); + +/* Explicit IEEE 128-bit floating point. */ +FRACTIONAL_FLOAT_MODE (KF, 113, 16, ieee_quad_format); + /* 128-bit floating point. ABI_V4 uses IEEE quad, AIX/Darwin adjust this in rs6000_option_override_internal. */ FLOAT_MODE (TF, 16, ieee_quad_format); Index: gcc/config/rs6000/rs6000.opt =================================================================== --- gcc/config/rs6000/rs6000.opt (revision 223458) +++ gcc/config/rs6000/rs6000.opt (working copy) @@ -600,3 +600,19 @@ Allow float/double variables in upper re moptimize-swaps Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save Analyze and remove doubleword swaps from VSX computations. + +mfloat128- +Target RejectNegative Joined Enum(float128_type_t) Var(TARGET_FLOAT128) Init(FLOAT128_UNSET) Save +-mfloat128-{software,none} - Specify how IEEE 128-bit floating point is used. + +Enum +Name(float128_type_t) Type(enum float128_type_t) + +EnumValue +Enum(float128_type_t) String(none) Value(FLOAT128_NONE) + +EnumValue +Enum(float128_type_t) String(software) Value(FLOAT128_SW) + +EnumValue +Enum(float128_type_t) String(sw) Value(FLOAT128_SW) Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 223458) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1817,6 +1817,16 @@ rs6000_hard_regno_mode_ok (int regno, ma && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO) && ((regno & 1) == 0)); + /* If we don't allow 128-bit binary floating point, disallow the 128-bit + types from going in any registers. Similarly if __float128 is not + supported, don't allow __float128/__ibm128 types. */ + if (!TARGET_LONG_DOUBLE_128 + && (mode == TFmode || mode == KFmode || mode == IFmode)) + return false; + + if (!TARGET_FLOAT128 && (mode == KFmode || mode == IFmode)) + return false; + /* VSX registers that overlap the FPR registers are larger than for non-VSX implementations. Don't allow an item to be split between a FP register and an Altivec register. Allow TImode in all VSX registers if the user @@ -2086,6 +2096,7 @@ rs6000_debug_reg_global (void) const char *trace_str; const char *abi_str; const char *cmodel_str; + const char *float128_str; struct cl_target_option cl_opts; /* Modes we want tieable information on. */ @@ -2099,6 +2110,8 @@ rs6000_debug_reg_global (void) SFmode, DFmode, TFmode, + IFmode, + KFmode, SDmode, DDmode, TDmode, @@ -2445,6 +2458,15 @@ rs6000_debug_reg_global (void) fprintf (stderr, DEBUG_FMT_S, "e500_double", (TARGET_E500_DOUBLE ? "true" : "false")); + switch (TARGET_FLOAT128) + { + case FLOAT128_NONE: float128_str = "none"; break; + case FLOAT128_SW: float128_str = "software"; break; + default: float128_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "float128", float128_str); + if (TARGET_LINK_STACK) fprintf (stderr, DEBUG_FMT_S, "link_stack", "true"); @@ -3703,6 +3725,13 @@ rs6000_option_override_internal (bool gl && optimize >= 3) rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN; + /* Set the appropriate IEEE 128-bit floating option. Do not enable float128 + support by default until the libgcc support is added. */ + if (TARGET_FLOAT128 == FLOAT128_UNSET) + TARGET_FLOAT128 = FLOAT128_NONE; + else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX) + error ("-mfloat128-software requires VSX support"); + if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags); @@ -14320,6 +14349,8 @@ rs6000_init_builtins (void) tree tdecl; tree ftype; machine_mode mode; + machine_mode ieee128_mode; + machine_mode ibm128_mode; if (TARGET_DEBUG_BUILTIN) fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n", @@ -14387,6 +14418,32 @@ rs6000_init_builtins (void) dfloat128_type_internal_node = dfloat128_type_node; void_type_internal_node = void_type_node; + /* 128-bit floating point support. KFmode is IEEE 128-bit floating point. + IFmode is the IBM extended 128-bit format that is a pair of doubles. + TFmode will be either IEEE 128-bit floating point or the IBM double-double + format that uses a pair of doubles, depending on the switches and + defaults. */ + if (TARGET_IEEEQUAD) + { + ieee128_mode = TFmode; + ibm128_mode = IFmode; + } + else + { + ieee128_mode = KFmode; + ibm128_mode = TFmode; + } + + ieee128_float_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (ieee128_float_type_node) = 128; + layout_type (ieee128_float_type_node); + SET_TYPE_MODE (ieee128_float_type_node, ieee128_mode); + + ibm128_float_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (ibm128_float_type_node) = 128; + layout_type (ibm128_float_type_node); + SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode); + /* Initialize the modes for builtin_function_type, mapping a machine mode to tree type node. */ builtin_mode_to_type[QImode][0] = integer_type_node; @@ -14399,6 +14456,8 @@ rs6000_init_builtins (void) builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node; builtin_mode_to_type[SFmode][0] = float_type_node; builtin_mode_to_type[DFmode][0] = double_type_node; + builtin_mode_to_type[IFmode][0] = ibm128_float_type_node; + builtin_mode_to_type[KFmode][0] = ieee128_float_type_node; builtin_mode_to_type[TFmode][0] = long_double_type_node; builtin_mode_to_type[DDmode][0] = dfloat64_type_node; builtin_mode_to_type[TDmode][0] = dfloat128_type_node; Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 223458) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -2715,6 +2715,8 @@ enum rs6000_builtin_type_index RS6000_BTI_dfloat64, /* dfloat64_type_node */ RS6000_BTI_dfloat128, /* dfloat128_type_node */ RS6000_BTI_void, /* void_type_node */ + RS6000_BTI_ieee128_float, /* ieee 128-bit floating point */ + RS6000_BTI_ibm128_float, /* IBM 128-bit floating point */ RS6000_BTI_MAX }; @@ -2769,6 +2771,8 @@ enum rs6000_builtin_type_index #define dfloat64_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat64]) #define dfloat128_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat128]) #define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void]) +#define ieee128_float_type_node (rs6000_builtin_types[RS6000_BTI_ieee128_float]) +#define ibm128_float_type_node (rs6000_builtin_types[RS6000_BTI_ibm128_float]) extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX]; extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT]; Index: gcc/config/rs6000/rs6000-opts.h =================================================================== --- gcc/config/rs6000/rs6000-opts.h (revision 223458) +++ gcc/config/rs6000/rs6000-opts.h (working copy) @@ -79,6 +79,15 @@ enum fpu_type_t FPU_DF_FULL /* Full Double Single Precision FPU */ }; + +/* Float128 support. */ +enum float128_type_t +{ + FLOAT128_UNSET = -1, /* Initial value. */ + FLOAT128_NONE, /* No __float128 support. */ + FLOAT128_SW /* software __float128 support. */ +}; + /* Types of costly dependences. */ enum rs6000_dependence_cost { ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-05-22 21:47 [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Michael Meissner @ 2015-06-02 17:51 ` David Edelsohn 2015-06-02 18:33 ` Michael Meissner 2015-06-16 22:33 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner 2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers 1 sibling, 2 replies; 13+ messages in thread From: David Edelsohn @ 2015-06-02 17:51 UTC (permalink / raw) To: Michael Meissner, GCC Patches On Fri, May 22, 2015 at 5:24 PM, Michael Meissner <meissner@linux.vnet.ibm.com> wrote: > This patch is the first in a series of patches that will eventually add support > for IEEE 128-bit floating point support to the PowerPC GCC compiler. At the > current time, we do not plan to change the default for long double. I added a > new type keyword (__float128) to get access to IEEE 128-bit floating point, and > another (__ibm128) to get access to IBM extended double type. > > Until all of the GCC and LIBGCC patches have been committed, you will not be > able to use IEEE 128-bit floating point, and -mfloat128-software will not be > turned on by default. > > This patch adds the new modes (KFmode and IFmode) and the switches > (-mfloat128-{none,software}). > > Due to the fact that TFmode in the PowerPC compiler either represents IEEE > 128-bit floating point or the IBM extended double (double-double) format. For > most PowerPC users, the default is to use IBM extended double for long double. > Because TFmode can be either floating point format, I added new new modes: > > KFmode -- IEEE 128-bit floating point > IFmode -- IBM extended double floating point > > If the default for TFmode is ibm extended double, the port will eventually use > KFmode for IEEE 128-bit floating point. Likewise if the default for TFmode is > IEEE 128-bit floating point, the port will use TFmode for IEEE 128-bit floating > point, and IFmode for IBM extended double. > > I have bootstraped these patches on a power7 and compared them to the unpatched > compiler. There were no changes when running make check. Are these patches ok > to install in the trunk? Mike, What is the purpose of the TARGET_LONG_DOUBLE_128 change in rs6000_hard_regno_mode_ok()? + /* If we don't allow 128-bit binary floating point, disallow the 128-bit + types from going in any registers. Similarly if __float128 is not + supported, don't allow __float128/__ibm128 types. */ + if (!TARGET_LONG_DOUBLE_128 + && (mode == TFmode || mode == KFmode || mode == IFmode)) + return false; Why is this necessary now? Thanks, David ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-06-02 17:51 ` David Edelsohn @ 2015-06-02 18:33 ` Michael Meissner 2015-06-02 19:32 ` David Edelsohn 2015-06-16 22:33 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner 1 sibling, 1 reply; 13+ messages in thread From: Michael Meissner @ 2015-06-02 18:33 UTC (permalink / raw) To: David Edelsohn; +Cc: Michael Meissner, GCC Patches On Tue, Jun 02, 2015 at 01:43:08PM -0400, David Edelsohn wrote: > Mike, > > What is the purpose of the TARGET_LONG_DOUBLE_128 change in > rs6000_hard_regno_mode_ok()? > > + /* If we don't allow 128-bit binary floating point, disallow the 128-bit > + types from going in any registers. Similarly if __float128 is not > + supported, don't allow __float128/__ibm128 types. */ > + if (!TARGET_LONG_DOUBLE_128 > + && (mode == TFmode || mode == KFmode || mode == IFmode)) > + return false; > > Why is this necessary now? I was trying to avoid problems if there was no move/convert patterns for KFmode/IFmode. I made it when I transitioned from SPECIAL_FLOAT_MODE to FRACTIONAL_FLOAT_MODE. Given there are 2 fractional float modes now, if the compiler was automatically trying to find a larger type than DFmode, it would first try IFmode, then KFmode, and finally TFmode (under the old SPECIAL_FLOAT_MODE, it wouldn't look at those types in the normal course of things). With the current set of patches, there is no move or convert options for IFmode/KFmode, but also the emulator functions are not properly defined. I can remove the lines and do the build again, if you would prefer. I don't think it is strictly necessary. -- 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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-06-02 18:33 ` Michael Meissner @ 2015-06-02 19:32 ` David Edelsohn 0 siblings, 0 replies; 13+ messages in thread From: David Edelsohn @ 2015-06-02 19:32 UTC (permalink / raw) To: Michael Meissner, GCC Patches On Tue, Jun 2, 2015 at 2:27 PM, Michael Meissner <meissner@linux.vnet.ibm.com> wrote: > On Tue, Jun 02, 2015 at 01:43:08PM -0400, David Edelsohn wrote: >> Mike, >> >> What is the purpose of the TARGET_LONG_DOUBLE_128 change in >> rs6000_hard_regno_mode_ok()? >> >> + /* If we don't allow 128-bit binary floating point, disallow the 128-bit >> + types from going in any registers. Similarly if __float128 is not >> + supported, don't allow __float128/__ibm128 types. */ >> + if (!TARGET_LONG_DOUBLE_128 >> + && (mode == TFmode || mode == KFmode || mode == IFmode)) >> + return false; >> >> Why is this necessary now? > > I was trying to avoid problems if there was no move/convert patterns for > KFmode/IFmode. I made it when I transitioned from SPECIAL_FLOAT_MODE to > FRACTIONAL_FLOAT_MODE. Given there are 2 fractional float modes now, if the > compiler was automatically trying to find a larger type than DFmode, it would > first try IFmode, then KFmode, and finally TFmode (under the old > SPECIAL_FLOAT_MODE, it wouldn't look at those types in the normal course of > things). > > With the current set of patches, there is no move or convert options for > IFmode/KFmode, but also the emulator functions are not properly defined. The first patch is okay. This clearly is going to require a lot of interations with libgcc and GLIBC. Thanks, David ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 2015-06-02 17:51 ` David Edelsohn 2015-06-02 18:33 ` Michael Meissner @ 2015-06-16 22:33 ` Michael Meissner 2015-07-09 0:02 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b Michael Meissner 1 sibling, 1 reply; 13+ messages in thread From: Michael Meissner @ 2015-06-16 22:33 UTC (permalink / raw) To: David Edelsohn, GCC Patches [-- Attachment #1: Type: text/plain, Size: 3224 bytes --] 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 <meissner@linux.vnet.ibm.com> * 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. -- 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 [-- Attachment #2: ieee128-patch02b --] [-- Type: text/plain, Size: 21492 bytes --] 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))))) \f /* 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 \f /* 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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b 2015-06-16 22:33 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner @ 2015-07-09 0:02 ` Michael Meissner 2015-07-09 0:21 ` David Edelsohn 0 siblings, 1 reply; 13+ messages in thread From: Michael Meissner @ 2015-07-09 0:02 UTC (permalink / raw) To: David Edelsohn, GCC Patches [-- Attachment #1: Type: text/plain, Size: 3196 bytes --] David asked me to change the definition of FLOAT128_IBM_P and FLOAT128_IEEE_P so that they were more consistant. In doing so, I realized that I didn't need to test TARGET_LONG_DOUBLE_128 in those macros, since the mode would never be TFmode, IFmode, or KFmode unless TARGET_LONG_DOUBLE_128 was true. He also asked for better verification that the existing calling sequence with long double (which needs the subsequent patches to test), and I will write such tests and test them, putting them in the final patches. It bootstraps fine with no regressions. Is this patch ok to install? 2015-07-08 Michael Meissner <meissner@linux.vnet.ibm.com> * 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. -- 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 [-- Attachment #2: ieee128-patch02b --] [-- Type: text/plain, Size: 21435 bytes --] Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 225574) +++ 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.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 225574) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1740,9 +1740,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); @@ -1799,6 +1801,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))) @@ -1824,6 +1827,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)) @@ -2999,9 +3005,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] @@ -6106,13 +6112,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 @@ -6474,10 +6483,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; @@ -6743,6 +6755,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)); @@ -6936,6 +6950,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 @@ -7708,6 +7724,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) @@ -7861,8 +7879,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) @@ -8530,9 +8547,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), @@ -8724,7 +8740,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: @@ -8948,7 +8967,7 @@ rs6000_member_type_forces_blk (const_tre \f /* 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) @@ -9149,7 +9168,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 @@ -9259,7 +9278,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; @@ -9389,7 +9409,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)) @@ -9527,8 +9547,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 @@ -9800,7 +9822,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; @@ -9907,21 +9929,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); @@ -9973,8 +9995,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 @@ -10216,7 +10237,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)) @@ -10567,15 +10588,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 @@ -10637,7 +10658,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; } @@ -10811,10 +10832,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; } @@ -11489,10 +11511,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; @@ -16755,7 +16775,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; @@ -19053,7 +19073,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)) { @@ -21003,7 +21023,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; @@ -22080,7 +22100,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; } } @@ -25843,6 +25864,8 @@ rs6000_output_function_epilogue (FILE *f case DDmode: case TFmode: case TDmode: + case IFmode: + case KFmode: bits = 0x3; break; @@ -26516,7 +26539,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]; @@ -31040,7 +31064,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 @@ -32107,7 +32131,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; @@ -32144,7 +32168,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 @@ -32153,13 +32177,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; @@ -32181,7 +32205,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; @@ -32195,7 +32219,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; @@ -32421,6 +32445,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); } @@ -32436,7 +32462,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 Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 225574) +++ 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) == TFmode && TARGET_IEEEQUAD) \ + || ((MODE) == KFmode)) + +#define FLOAT128_IBM_P(MODE) \ + (((MODE) == TFmode && !TARGET_IEEEQUAD) \ + || ((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))))) \f /* 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 \ ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b 2015-07-09 0:02 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b Michael Meissner @ 2015-07-09 0:21 ` David Edelsohn 0 siblings, 0 replies; 13+ messages in thread From: David Edelsohn @ 2015-07-09 0:21 UTC (permalink / raw) To: Michael Meissner, GCC Patches On Wed, Jul 8, 2015 at 8:01 PM, Michael Meissner <meissner@linux.vnet.ibm.com> wrote: > David asked me to change the definition of FLOAT128_IBM_P and FLOAT128_IEEE_P > so that they were more consistant. In doing so, I realized that I didn't need > to test TARGET_LONG_DOUBLE_128 in those macros, since the mode would never be > TFmode, IFmode, or KFmode unless TARGET_LONG_DOUBLE_128 was true. > > He also asked for better verification that the existing calling sequence with > long double (which needs the subsequent patches to test), and I will write such > tests and test them, putting them in the final patches. > > It bootstraps fine with no regressions. Is this patch ok to install? > > 2015-07-08 Michael Meissner <meissner@linux.vnet.ibm.com> > > * 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. Okay. Thanks, David ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-05-22 21:47 [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Michael Meissner 2015-06-02 17:51 ` David Edelsohn @ 2015-06-02 17:57 ` Joseph Myers 2015-06-02 18:40 ` Michael Meissner 1 sibling, 1 reply; 13+ messages in thread From: Joseph Myers @ 2015-06-02 17:57 UTC (permalink / raw) To: Michael Meissner; +Cc: gcc-patches, dje.gcc Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over floating-point modes including these modes when they shouldn't, as discussed previously? If so, how do you deal (in subsequent patches?) with iterations that *should* include these modes? In particular, where libgcc uses __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an interation in c-cppbuiltin.c, how do you handle getting the relevant information in libgcc to build applicable libgcc functions for these modes? (I'm presuming that you do want complex arithmetic to work for both 128-bit types, for example, although you won't want them to be used for intermediate conversions in libgcc operations on other types.) -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers @ 2015-06-02 18:40 ` Michael Meissner 2015-06-02 20:25 ` Joseph Myers 0 siblings, 1 reply; 13+ messages in thread From: Michael Meissner @ 2015-06-02 18:40 UTC (permalink / raw) To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over > floating-point modes including these modes when they shouldn't, as > discussed previously? > > If so, how do you deal (in subsequent patches?) with iterations that > *should* include these modes? In particular, where libgcc uses > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an > interation in c-cppbuiltin.c, how do you handle getting the relevant > information in libgcc to build applicable libgcc functions for these > modes? (I'm presuming that you do want complex arithmetic to work for > both 128-bit types, for example, although you won't want them to be used > for intermediate conversions in libgcc operations on other types.) I have a catch-22 situation. We can't really do the glibc stuff until we have the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies the various TF files and modifies it for KF files. After we get the basic support in, we can then start tackling glibc. It may be when we get to doing the work in glibc itself, we will need to make further modifications. However, in order for the glibc people to start, I need the basic support in the compiler in the tree. -- 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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-06-02 18:40 ` Michael Meissner @ 2015-06-02 20:25 ` Joseph Myers 2015-06-02 20:50 ` David Edelsohn 2015-06-02 20:56 ` Michael Meissner 0 siblings, 2 replies; 13+ messages in thread From: Joseph Myers @ 2015-06-02 20:25 UTC (permalink / raw) To: Michael Meissner; +Cc: gcc-patches, dje.gcc On Tue, 2 Jun 2015, Michael Meissner wrote: > On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: > > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over > > floating-point modes including these modes when they shouldn't, as > > discussed previously? > > > > If so, how do you deal (in subsequent patches?) with iterations that > > *should* include these modes? In particular, where libgcc uses > > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an > > interation in c-cppbuiltin.c, how do you handle getting the relevant > > information in libgcc to build applicable libgcc functions for these > > modes? (I'm presuming that you do want complex arithmetic to work for > > both 128-bit types, for example, although you won't want them to be used > > for intermediate conversions in libgcc operations on other types.) > > I have a catch-22 situation. We can't really do the glibc stuff until we have > the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies > the various TF files and modifies it for KF files. The functions I'm mainly thinking of are the libgcc2.c ones rather than the soft-fp ones (powi?f2 mul?c3 div?c3). > After we get the basic support in, we can then start tackling glibc. It may be > when we get to doing the work in glibc itself, we will need to make further > modifications. However, in order for the glibc people to start, I need the > basic support in the compiler in the tree. It's not obvious what glibc support should look like in the absence of a change to the default for long double; that would require discussion on libc-alpha at an early stage to establish a consensus on the design. libquadmath support should be easy (given working compiler / libgcc support). But if you want more than libquadmath support, there are several possible forms for support in glibc proper depending on e.g. whether you want to support a -m option to change long double, or using the functions via the __float128 type name and separate names for the functions, or both. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-06-02 20:25 ` Joseph Myers @ 2015-06-02 20:50 ` David Edelsohn 2015-06-02 20:56 ` Michael Meissner 1 sibling, 0 replies; 13+ messages in thread From: David Edelsohn @ 2015-06-02 20:50 UTC (permalink / raw) To: Joseph Myers, munroesj; +Cc: Michael Meissner, GCC Patches On Tue, Jun 2, 2015 at 4:14 PM, Joseph Myers <joseph@codesourcery.com> wrote: > On Tue, 2 Jun 2015, Michael Meissner wrote: > >> On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: >> > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over >> > floating-point modes including these modes when they shouldn't, as >> > discussed previously? >> > >> > If so, how do you deal (in subsequent patches?) with iterations that >> > *should* include these modes? In particular, where libgcc uses >> > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an >> > interation in c-cppbuiltin.c, how do you handle getting the relevant >> > information in libgcc to build applicable libgcc functions for these >> > modes? (I'm presuming that you do want complex arithmetic to work for >> > both 128-bit types, for example, although you won't want them to be used >> > for intermediate conversions in libgcc operations on other types.) >> >> I have a catch-22 situation. We can't really do the glibc stuff until we have >> the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies >> the various TF files and modifies it for KF files. > > The functions I'm mainly thinking of are the libgcc2.c ones rather than > the soft-fp ones (powi?f2 mul?c3 div?c3). > >> After we get the basic support in, we can then start tackling glibc. It may be >> when we get to doing the work in glibc itself, we will need to make further >> modifications. However, in order for the glibc people to start, I need the >> basic support in the compiler in the tree. > > It's not obvious what glibc support should look like in the absence of a > change to the default for long double; that would require discussion on > libc-alpha at an early stage to establish a consensus on the design. > > libquadmath support should be easy (given working compiler / libgcc > support). But if you want more than libquadmath support, there are > several possible forms for support in glibc proper depending on e.g. > whether you want to support a -m option to change long double, or using > the functions via the __float128 type name and separate names for the > functions, or both. Sounds like a fun night at a Czech pub during GNU Cauldron. - David ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-06-02 20:25 ` Joseph Myers 2015-06-02 20:50 ` David Edelsohn @ 2015-06-02 20:56 ` Michael Meissner 2015-06-02 21:18 ` Joseph Myers 1 sibling, 1 reply; 13+ messages in thread From: Michael Meissner @ 2015-06-02 20:56 UTC (permalink / raw) To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc On Tue, Jun 02, 2015 at 08:14:12PM +0000, Joseph Myers wrote: > On Tue, 2 Jun 2015, Michael Meissner wrote: > > > On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: > > > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over > > > floating-point modes including these modes when they shouldn't, as > > > discussed previously? > > > > > > If so, how do you deal (in subsequent patches?) with iterations that > > > *should* include these modes? In particular, where libgcc uses > > > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an > > > interation in c-cppbuiltin.c, how do you handle getting the relevant > > > information in libgcc to build applicable libgcc functions for these > > > modes? (I'm presuming that you do want complex arithmetic to work for > > > both 128-bit types, for example, although you won't want them to be used > > > for intermediate conversions in libgcc operations on other types.) > > > > I have a catch-22 situation. We can't really do the glibc stuff until we have > > the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies > > the various TF files and modifies it for KF files. > > The functions I'm mainly thinking of are the libgcc2.c ones rather than > the soft-fp ones (powi?f2 mul?c3 div?c3). Ok, I will look into those. > > After we get the basic support in, we can then start tackling glibc. It may be > > when we get to doing the work in glibc itself, we will need to make further > > modifications. However, in order for the glibc people to start, I need the > > basic support in the compiler in the tree. > > It's not obvious what glibc support should look like in the absence of a > change to the default for long double; that would require discussion on > libc-alpha at an early stage to establish a consensus on the design. > > libquadmath support should be easy (given working compiler / libgcc > support). But if you want more than libquadmath support, there are > several possible forms for support in glibc proper depending on e.g. > whether you want to support a -m option to change long double, or using > the functions via the __float128 type name and separate names for the > functions, or both. There already is an option to change long double, but it currently does not work (and in fact is disabled in 64-bit environments). I see there are many roadblocks to changing the type of long double (i.e. making sure printf %Lg works correctly, etc.). None of the distros want another multilib (where long double is IEEE 128-bit). For the scope of GCC 6.0, my assumption is long double will remain IBM extended double. My assumption of the steps are: 1) Get the basic compiler support in. 2) Add the basic soft-float, either with my current hack or preferrably doing it right in glibc (I suspect we may want to temporarily do it via the hack, and when the glibc support is in, remove the hack). 3) Deal with all of the complexities of libgcc2 and glibc for the additional type. 4) Add float128 versions of the basic math libraries. For this it will probably be simpler if we can force long double to be IEEE 128-bit so you don't have to change as much code, but you want to suppress whatever check there will be to prevent user code from linking against the wrong library. 5) Add support in other libraries as needed (IBM's MASS library, the new vector library, libquadmath, etc.). Note, by the time of GCC 7.0, the C17/C++-17 standards may be final, and there they have new names for IEEE 128-bit, etc. -- 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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 2015-06-02 20:56 ` Michael Meissner @ 2015-06-02 21:18 ` Joseph Myers 0 siblings, 0 replies; 13+ messages in thread From: Joseph Myers @ 2015-06-02 21:18 UTC (permalink / raw) To: Michael Meissner; +Cc: gcc-patches, dje.gcc On Tue, 2 Jun 2015, Michael Meissner wrote: > 4) Add float128 versions of the basic math libraries. For this it will > probably be simpler if we can force long double to be IEEE 128-bit so you > don't have to change as much code, but you want to suppress whatever check > there will be to prevent user code from linking against the wrong library. I'd say it's simpler if you don't force long double to be IEEE 128-bit (because then one answer is simply libquadmath, which already exists, to provide versions of libm functions for __float128, while making long double IEEE 128-bit affects a huge number of printf variant functions; libquadmath is a few years out of date with respect to glibc, but updating it shouldn't be hard). Building libm twice with different options seems much nastier. > Note, by the time of GCC 7.0, the C17/C++-17 standards may be final, and there > they have new names for IEEE 128-bit, etc. Since there is no project for a new major revision of the C standard (no work ongoing, no NWIP, etc.) I'm skeptical of any reference to "C17". And the last suggestion I saw referring to integration of the IEEE 754-2008 bindings into the C standard only suggested putting parts 1 and 2 in there (and even that involved some misconception about the extent to which those have been implemented). The relevant part for this is part 3, defining the _Float128 type name, functions such as sinf128, etc. Now, I think it would make sense eventually to support TS 18661 (any or all parts) in glibc, including providing the *f128 functions and so superseding libquadmath. That is, I think it would be appropriate to revisit the rejection of such support in <https://sourceware.org/ml/libc-alpha/2004-03/msg00326.html> and <https://sourceware.org/ml/libc-alpha/2004-05/msg00055.html> now appropriate standard bindings exist (but this is only my view, not a community consensus). But making the functions support building both for long double and for _Float128 would certainly be a large project. Support in accordance with TS 18661-3 would *not* involve any printf changes, since the TS 18661 approach is to use the strfrom* functions (new in part 1) for that purpose rather than e.g. adding new printf formats. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-07-09 0:21 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-05-22 21:47 [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Michael Meissner 2015-06-02 17:51 ` David Edelsohn 2015-06-02 18:33 ` Michael Meissner 2015-06-02 19:32 ` David Edelsohn 2015-06-16 22:33 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner 2015-07-09 0:02 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b Michael Meissner 2015-07-09 0:21 ` David Edelsohn 2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers 2015-06-02 18:40 ` Michael Meissner 2015-06-02 20:25 ` Joseph Myers 2015-06-02 20:50 ` David Edelsohn 2015-06-02 20:56 ` Michael Meissner 2015-06-02 21:18 ` Joseph Myers
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).