On Thu, Jul 13, 2017 at 5:12 PM, Andrew Pinski <apin...@cavium.com> wrote: > Hi, > This patch adds Decimal floating point support to aarch64. It is > the base support in that since there is no hardware support for DFP, > it just defines the ABI. The ABI I chose is that _Decimal32 is > treated like float, _Decimal64 is treated like double and _Decimal128 > is treated like long double. In that they are passed via the floating > registers (sN, dN, qN). > Is this ok an ABI? > > Is the patch ok? Bootstrapped and tested on aarch64-linux-gnu with > --enable-decimal-float with no regressions and all of the dfp > testcases pass.
I just noticed I messed up by attaching the wrong patch. Here is the correct one. Thanks, Andrew > > Thanks, > Andrew Pinski > > gcc/ChangeLog: > * config/aarch64/aarch64.c (aarch64_split_128bit_move): Handle TDmode. > (aarch64_classify_address): Likewise. > (aarch64_legitimize_address_displacement): Likewise. > (aarch64_legitimize_address): Likewise. > (aarch64_constant_pool_reload_icode): Handle SD, DD, and TD modes. > (aarch64_secondary_reload): Handle TDmode. > (aarch64_valid_floating_const): For decimal floating point return false. > (aarch64_gimplify_va_arg_expr): Handle SD, DD, and TD modes. > (aapcs_vfp_sub_candidate): Likewise. > (aarch64_vfp_is_call_or_return_candidate): Handle MODE_DECIMAL_FLOAT. > (aarch64_scalar_mode_supported_p): For DECIMAL_FLOAT_MODE_P, return > default_decimal_float_supported_p. > * config/aarch64/iterators.md (GPF_TF_F16): Add SD, DD, and TD modes. > (SFD): New iterator. > (DFD): New iterator. > (TFD): New iterator. > (GPF_TF): Add SD, DD, and TD modes. > (TX): Add TD mode. > * config/aarch64/aarch64.md (*movsf_aarch64): Use SFD iterator. > (*movdf_aarch64): Use DFD iterator. > (*movtf_aarch64): Use TFD iterator. > (define_split for TF): Use TFD iterator. > > > gcc/testsuite/ChangeLog: > * c-c++-common/dfp/pr39986.c: Allow for word instead of just long. > > libgcc/ChangeLog: > * config.host (aarch64*-*-elf): Add t-dfprules to tmake_file. > (aarch64*-*-freebsd*): Likewise. > (aarch64*-*-linux*): Likewise.
Index: gcc/config/aarch64/aarch64.c =================================================================== --- gcc/config/aarch64/aarch64.c (revision 250186) +++ gcc/config/aarch64/aarch64.c (working copy) @@ -1653,7 +1653,7 @@ aarch64_split_128bit_move (rtx dst, rtx machine_mode mode = GET_MODE (dst); - gcc_assert (mode == TImode || mode == TFmode); + gcc_assert (mode == TImode || mode == TFmode || mode == TDmode); gcc_assert (!(side_effects_p (src) || side_effects_p (dst))); gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode); @@ -1673,11 +1673,16 @@ aarch64_split_128bit_move (rtx dst, rtx emit_insn (gen_aarch64_movtilow_di (dst, src_lo)); emit_insn (gen_aarch64_movtihigh_di (dst, src_hi)); } - else + else if (mode == TFmode) { emit_insn (gen_aarch64_movtflow_di (dst, src_lo)); emit_insn (gen_aarch64_movtfhigh_di (dst, src_hi)); } + else + { + emit_insn (gen_aarch64_movtdlow_di (dst, src_lo)); + emit_insn (gen_aarch64_movtdhigh_di (dst, src_hi)); + } return; } else if (GP_REGNUM_P (dst_regno) && FP_REGNUM_P (src_regno)) @@ -1690,11 +1695,16 @@ aarch64_split_128bit_move (rtx dst, rtx emit_insn (gen_aarch64_movdi_tilow (dst_lo, src)); emit_insn (gen_aarch64_movdi_tihigh (dst_hi, src)); } - else + else if (mode == TFmode) { emit_insn (gen_aarch64_movdi_tflow (dst_lo, src)); emit_insn (gen_aarch64_movdi_tfhigh (dst_hi, src)); } + else if (mode == TDmode) + { + emit_insn (gen_aarch64_movdi_tdlow (dst_lo, src)); + emit_insn (gen_aarch64_movdi_tdhigh (dst_hi, src)); + } return; } } @@ -4420,10 +4430,11 @@ aarch64_classify_address (struct aarch64 rtx op0, op1; /* On BE, we use load/store pair for all large int mode load/stores. - TI/TFmode may also use a load/store pair. */ + TI/TF/TDmode may also use a load/store pair. */ bool load_store_pair_p = (outer_code == PARALLEL || mode == TImode || mode == TFmode + || mode == TDmode || (BYTES_BIG_ENDIAN && aarch64_vect_struct_mode_p (mode))); @@ -4473,7 +4484,7 @@ aarch64_classify_address (struct aarch64 info->base = op0; info->offset = op1; - /* TImode and TFmode values are allowed in both pairs of X + /* TImode and TFmode and TDmode values are allowed in both pairs of X registers and individual Q registers. The available address modes are: X,X: 7-bit signed scaled offset @@ -4482,7 +4493,7 @@ aarch64_classify_address (struct aarch64 When performing the check for pairs of X registers i.e. LDP/STP pass down DImode since that is the natural size of the LDP/STP instruction memory accesses. */ - if (mode == TImode || mode == TFmode) + if (mode == TImode || mode == TFmode || mode == TDmode) return (aarch64_offset_7bit_signed_scaled_p (DImode, offset) && (offset_9bit_signed_unscaled_p (mode, offset) || offset_12bit_unsigned_scaled_p (mode, offset))); @@ -4558,14 +4569,14 @@ aarch64_classify_address (struct aarch64 info->offset = XEXP (XEXP (x, 1), 1); offset = INTVAL (info->offset); - /* TImode and TFmode values are allowed in both pairs of X + /* TImode and TFmode and TDmode values are allowed in both pairs of X registers and individual Q registers. The available address modes are: X,X: 7-bit signed scaled offset Q: 9-bit signed offset We conservatively require an offset representable in either mode. */ - if (mode == TImode || mode == TFmode) + if (mode == TImode || mode == TFmode || mode == TDmode) return (aarch64_offset_7bit_signed_scaled_p (mode, offset) && offset_9bit_signed_unscaled_p (mode, offset)); @@ -4714,7 +4725,7 @@ aarch64_legitimize_address_displacement HOST_WIDE_INT offset = INTVAL (*disp); HOST_WIDE_INT base = offset & ~(GET_MODE_SIZE (mode) < 4 ? 0xfff : 0x3ffc); - if (mode == TImode || mode == TFmode + if (mode == TImode || mode == TFmode || mode == TDmode || (offset & (GET_MODE_SIZE (mode) - 1)) != 0) base = (offset + 0x100) & ~0x1ff; @@ -5649,7 +5660,7 @@ aarch64_legitimize_address (rtx x, rtx / /* Small negative offsets are supported. */ else if (IN_RANGE (offset, -256, 0)) base_offset = 0; - else if (mode == TImode || mode == TFmode) + else if (mode == TImode || mode == TFmode || mode == TDmode) base_offset = (offset + 0x100) & ~0x1ff; /* Use 12-bit offset by access size. */ else @@ -5681,6 +5692,15 @@ aarch64_constant_pool_reload_icode (mach case TFmode: return CODE_FOR_aarch64_reload_movcptfdi; + case SDmode: + return CODE_FOR_aarch64_reload_movcpsddi; + + case DDmode: + return CODE_FOR_aarch64_reload_movcpdddi; + + case TDmode: + return CODE_FOR_aarch64_reload_movcptddi; + case V8QImode: return CODE_FOR_aarch64_reload_movcpv8qidi; @@ -5731,25 +5751,27 @@ aarch64_secondary_reload (bool in_p ATTR /* Without the TARGET_SIMD instructions we cannot move a Q register to a Q register directly. We need a scratch. */ - if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x) + if (REG_P (x) && (mode == TFmode || mode == TDmode || mode == TImode) && mode == GET_MODE (x) && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD && reg_class_subset_p (rclass, FP_REGS)) { if (mode == TFmode) sri->icode = CODE_FOR_aarch64_reload_movtf; + else if (mode == TDmode) + sri->icode = CODE_FOR_aarch64_reload_movtd; else if (mode == TImode) sri->icode = CODE_FOR_aarch64_reload_movti; return NO_REGS; } - /* A TFmode or TImode memory access should be handled via an FP_REGS + /* A TFmode or TImode or TDmode memory access should be handled via an FP_REGS because AArch64 has richer addressing modes for LDR/STR instructions than LDP/STP instructions. */ if (TARGET_FLOAT && rclass == GENERAL_REGS && GET_MODE_SIZE (mode) == 16 && MEM_P (x)) return FP_REGS; - if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x)) + if (rclass == FP_REGS && (mode == TImode || mode == TFmode || mode == TDmode) && CONSTANT_P(x)) return GENERAL_REGS; return NO_REGS; @@ -10215,6 +10237,10 @@ aarch64_legitimate_pic_operand_p (rtx x) static bool aarch64_valid_floating_const (machine_mode mode, rtx x) { + /* FIXME: Handle decimal floating point constants. */ + if (GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT) + return false; + if (!CONST_DOUBLE_P (x)) return false; @@ -10636,6 +10662,18 @@ aarch64_gimplify_va_arg_expr (tree valis field_t = long_double_type_node; field_ptr_t = long_double_ptr_type_node; break; + case SDmode: + field_t = dfloat32_type_node; + field_ptr_t = dfloat32_ptr_type_node; + break; + case DDmode: + field_t = dfloat64_type_node; + field_ptr_t = dfloat64_ptr_type_node; + break; + case TDmode: + field_t = dfloat128_type_node; + field_ptr_t = dfloat128_ptr_type_node; + break; case HFmode: field_t = aarch64_fp16_type_node; field_ptr_t = aarch64_fp16_ptr_type_node; @@ -10802,7 +10840,9 @@ aapcs_vfp_sub_candidate (const_tree type case REAL_TYPE: mode = TYPE_MODE (type); if (mode != DFmode && mode != SFmode - && mode != TFmode && mode != HFmode) + && mode != TFmode && mode != HFmode + && mode != DDmode && mode != SDmode + && mode != TDmode) return -1; if (*modep == VOIDmode) @@ -11030,7 +11070,9 @@ aarch64_vfp_is_call_or_return_candidate if (is_ha != NULL) *is_ha = false; - if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT) + if ((!composite_p + && (GET_MODE_CLASS (mode) == MODE_FLOAT + || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)) || aarch64_short_vector_p (type, mode)) { *count = 1; @@ -15028,6 +15070,9 @@ aarch64_libgcc_floating_mode_supported_p static bool aarch64_scalar_mode_supported_p (machine_mode mode) { + if (DECIMAL_FLOAT_MODE_P (mode)) + return default_decimal_float_supported_p (); + return (mode == HFmode ? true : default_scalar_mode_supported_p (mode)); Index: gcc/config/aarch64/aarch64.md =================================================================== --- gcc/config/aarch64/aarch64.md (revision 250186) +++ gcc/config/aarch64/aarch64.md (working copy) @@ -1081,11 +1081,11 @@ (define_insn "*movhf_aarch64" (set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")] ) -(define_insn "*movsf_aarch64" - [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r") - (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))] - "TARGET_FLOAT && (register_operand (operands[0], SFmode) - || aarch64_reg_or_fp_zero (operands[1], SFmode))" +(define_insn "*mov<mode>_aarch64" + [(set (match_operand:SFD 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r") + (match_operand:SFD 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))] + "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode) + || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))" "@ movi\\t%0.2s, #0 fmov\\t%s0, %w1 @@ -1102,11 +1102,11 @@ (define_insn "*movsf_aarch64" (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")] ) -(define_insn "*movdf_aarch64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r") - (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))] - "TARGET_FLOAT && (register_operand (operands[0], DFmode) - || aarch64_reg_or_fp_zero (operands[1], DFmode))" +(define_insn "*mov<mode>_aarch64" + [(set (match_operand:DFD 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r") + (match_operand:DFD 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))] + "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode) + || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))" "@ movi\\t%d0, #0 fmov\\t%d0, %x1 @@ -1123,13 +1123,13 @@ (define_insn "*movdf_aarch64" (set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")] ) -(define_insn "*movtf_aarch64" - [(set (match_operand:TF 0 +(define_insn "*mov<mode>_aarch64" + [(set (match_operand:TFD 0 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m") - (match_operand:TF 1 + (match_operand:TFD 1 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))] - "TARGET_FLOAT && (register_operand (operands[0], TFmode) - || aarch64_reg_or_fp_zero (operands[1], TFmode))" + "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode) + || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))" "@ mov\\t%0.16b, %1.16b # @@ -1149,8 +1149,8 @@ (define_insn "*movtf_aarch64" ) (define_split - [(set (match_operand:TF 0 "register_operand" "") - (match_operand:TF 1 "aarch64_reg_or_imm" ""))] + [(set (match_operand:TFD 0 "register_operand" "") + (match_operand:TFD 1 "aarch64_reg_or_imm" ""))] "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])" [(const_int 0)] { Index: gcc/config/aarch64/iterators.md =================================================================== --- gcc/config/aarch64/iterators.md (revision 250186) +++ gcc/config/aarch64/iterators.md (working copy) @@ -44,14 +44,23 @@ (define_mode_iterator GPF [SF DF]) ;; Iterator for all scalar floating point modes (HF, SF, DF) (define_mode_iterator GPF_F16 [(HF "AARCH64_ISA_F16") SF DF]) -;; Iterator for all scalar floating point modes (HF, SF, DF and TF) -(define_mode_iterator GPF_TF_F16 [HF SF DF TF]) +;; Iterator for all scalar floating point modes (HF, SF, DF and TF [SD, DD, and TD]) +(define_mode_iterator GPF_TF_F16 [HF SF DF TF SD DD TD]) + +;; Iterator for scalar 32bit fp modes (SF, SD) +(define_mode_iterator SFD [SD SF]) + +;; Iterator for scalar 64bit fp modes (DF, DD) +(define_mode_iterator DFD [DD DF]) + +;; Iterator for scalar 128bit fp modes (TF, TD) +(define_mode_iterator TFD [TD TF]) ;; Double vector modes. (define_mode_iterator VDF [V2SF V4HF]) -;; Iterator for all scalar floating point modes (SF, DF and TF) -(define_mode_iterator GPF_TF [SF DF TF]) +;; Iterator for all scalar floating point modes (SF, DF and TF [SD, DD, and TD]) +(define_mode_iterator GPF_TF [SF DF TF SD DD TD]) ;; Integer vector modes. (define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI]) @@ -224,7 +233,7 @@ (define_mode_iterator VB [V8QI V16QI]) ;; 2 and 4 lane SI modes. (define_mode_iterator VS [V2SI V4SI]) -(define_mode_iterator TX [TI TF]) +(define_mode_iterator TX [TI TF TD]) ;; Opaque structure modes. (define_mode_iterator VSTRUCT [OI CI XI]) Index: gcc/testsuite/c-c++-common/dfp/pr39986.c =================================================================== --- gcc/testsuite/c-c++-common/dfp/pr39986.c (revision 250186) +++ gcc/testsuite/c-c++-common/dfp/pr39986.c (working copy) @@ -14,19 +14,19 @@ _Decimal128 f = -678901.234e-6dl; /* The first value is DPD, the second is BID. The order differs depending on whether the target is big-endian or little-endian. */ -/* { dg-final { scan-assembler ".long\t(572653859|822183807)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(572653859|822183807)\n" } } */ -/* { dg-final { scan-assembler ".long\t(-1572863965|-1308622825)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(-1572863965|-1308622825)\n" } } */ -/* { dg-final { scan-assembler ".long\t(52|34)\n" } } */ -/* { dg-final { scan-assembler ".long\t(572784640|824180736)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(52|34)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(572784640|824180736)\n" } } */ -/* { dg-final { scan-assembler ".long\t(4736|4500)\n" } } */ -/* { dg-final { scan-assembler ".long\t(-1574174720|-1319108608)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(4736|4500)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(-1574174720|-1319108608)\n" } } */ -/* { dg-final { scan-assembler ".long\t(-1975952433|957645077)\n" } } */ -/* { dg-final { scan-assembler ".long\t(190215|132222)\n" } } */ -/* { dg-final { scan-assembler ".long\t(574193664|835452928)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(-1975952433|957645077)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(190215|132222)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(574193664|835452928)\n" } } */ -/* { dg-final { scan-assembler ".long\t(931280180|678901234)\n" } } */ -/* { dg-final { scan-assembler ".long\t(-1576681472|-1339162624)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(931280180|678901234)\n" } } */ +/* { dg-final { scan-assembler ".(word|long)\t(-1576681472|-1339162624)\n" } } */ Index: libgcc/config.host =================================================================== --- libgcc/config.host (revision 250186) +++ libgcc/config.host (working copy) @@ -334,13 +334,13 @@ aarch64*-*-elf | aarch64*-*-rtems*) extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o" extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} ${cpu_type}/t-aarch64" - tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" + tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm t-dfprules" md_unwind_header=aarch64/aarch64-unwind.h ;; aarch64*-*-freebsd*) extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} ${cpu_type}/t-aarch64" - tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" + tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm t-dfprules" md_unwind_header=aarch64/freebsd-unwind.h ;; aarch64*-*-fuchsia*) @@ -351,7 +351,7 @@ aarch64*-*-linux*) extra_parts="$extra_parts crtfastmath.o" md_unwind_header=aarch64/linux-unwind.h tmake_file="${tmake_file} ${cpu_type}/t-aarch64" - tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" + tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm t-dfprules" ;; alpha*-*-linux*) tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm alpha/t-linux"