diff --git a/gcc/calls.cc b/gcc/calls.cc index 6dd6f73..8a18eae 100644 --- a/gcc/calls.cc +++ b/gcc/calls.cc @@ -4795,14 +4795,20 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, else { /* Convert to the proper mode if a promotion has been active. */ - if (GET_MODE (valreg) != outmode) + enum machine_mode valmode = GET_MODE (valreg); + if (valmode != outmode) { int unsignedp = TYPE_UNSIGNED (tfom); gcc_assert (promote_function_mode (tfom, outmode, &unsignedp, fndecl ? TREE_TYPE (fndecl) : fntype, 1) - == GET_MODE (valreg)); - valreg = convert_modes (outmode, GET_MODE (valreg), valreg, 0); + == valmode); + if (SCALAR_INT_MODE_P (valmode) + && SCALAR_FLOAT_MODE_P (outmode) + && known_gt (GET_MODE_SIZE (valmode), GET_MODE_SIZE (outmode))) + valreg = convert_wider_int_to_float (outmode, valmode, valreg); + else + valreg = convert_modes (outmode, valmode, valreg, 0); } if (value != 0) @@ -5007,8 +5013,20 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, /* If we are promoting object (or for any other reason) the mode doesn't agree, convert the mode. */ - if (arg->mode != TYPE_MODE (TREE_TYPE (pval))) - arg->value = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)), + machine_mode old_mode = TYPE_MODE (TREE_TYPE (pval)); + + /* Some ABIs require scalar floating point modes to be passed + in a wider scalar integer mode. We need to explicitly + reinterpret to an integer mode of the correct precision + before extending to the desired result. */ + if (SCALAR_INT_MODE_P (arg->mode) + && SCALAR_FLOAT_MODE_P (old_mode) + && known_gt (GET_MODE_SIZE (arg->mode), + GET_MODE_SIZE (old_mode))) + arg->value = convert_float_to_wider_int (arg->mode, old_mode, + arg->value); + else if (arg->mode != old_mode) + arg->value = convert_modes (arg->mode, old_mode, arg->value, arg->unsignedp); if (arg->pass_on_stack) diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc index 06a9585..537c892 100644 --- a/gcc/config/nvptx/nvptx.cc +++ b/gcc/config/nvptx/nvptx.cc @@ -228,6 +228,31 @@ first_ptx_version_supporting_sm (enum ptx_isa sm) } } +/* Used when the specified -mptx version is incompatible with + the default ptx ISA to lower the default ISA. */ + +static enum ptx_isa +last_sm_supporting_ptx_version (enum ptx_version v) +{ + switch (v) + { + case PTX_VERSION_3_0: + return PTX_ISA_SM30; + case PTX_VERSION_3_1: + return PTX_ISA_SM35; + case PTX_VERSION_4_2: + return PTX_ISA_SM53; + case PTX_VERSION_6_0: + return PTX_ISA_SM70; + case PTX_VERSION_6_3: + return PTX_ISA_SM75; + case PTX_VERSION_7_0: + return PTX_ISA_SM80; + default: + gcc_unreachable (); + } +} + static enum ptx_version default_ptx_version_option (void) { @@ -322,9 +347,16 @@ handle_ptx_version_option (void) = first_ptx_version_supporting_sm ((enum ptx_isa) ptx_isa_option); if (ptx_version_option < first) - error ("PTX version (%<-mptx%>) needs to be at least %s to support selected" - " %<-misa%> (sm_%s)", ptx_version_to_string (first), - sm_version_to_string ((enum ptx_isa)ptx_isa_option)); + { + if (!OPTION_SET_P (ptx_isa_option)) + ptx_isa_option + = last_sm_supporting_ptx_version ((enum ptx_version) + ptx_version_option); + else + error ("PTX version (%<-mptx%>) needs to be at least %s to support" + " selected %<-misa%> (sm_%s)", ptx_version_to_string (first), + sm_version_to_string ((enum ptx_isa)ptx_isa_option)); + } } /* Implement TARGET_OPTION_OVERRIDE. */ @@ -751,6 +783,9 @@ nvptx_strict_argument_naming (cumulative_args_t cum_v) static rtx nvptx_libcall_value (machine_mode mode, const_rtx) { + if (mode == HFmode) + mode = SImode; + if (!cfun || !cfun->machine->doing_call) /* Pretend to return in a hard reg for early uses before pseudos can be generated. */ @@ -2693,9 +2728,12 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee) fprintf (asm_out_file, "\t{\n"); if (result != NULL) - fprintf (asm_out_file, "\t\t.param%s %s_in;\n", - nvptx_ptx_type_from_mode (GET_MODE (result), false), - reg_names[NVPTX_RETURN_REGNUM]); + { + machine_mode mode = GET_MODE (result); + const char *ptx_type = nvptx_ptx_type_from_mode (mode, false); + fprintf (asm_out_file, "\t\t.param%s %s_in;\n", ptx_type, + reg_names[NVPTX_RETURN_REGNUM]); + } /* Ensure we have a ptx declaration in the output if necessary. */ if (GET_CODE (callee) == SYMBOL_REF) @@ -2724,6 +2762,10 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee) machine_mode mode = GET_MODE (t); const char *ptx_type = nvptx_ptx_type_from_mode (mode, false); + /* Use st.param.b16 for HFmode. */ + if (mode == HFmode) + ptx_type = ".b16"; + /* Mode splitting has already been done. */ fprintf (asm_out_file, "\t\t.param%s %%out_arg%d;\n" "\t\tst.param%s [%%out_arg%d], ", @@ -2797,6 +2839,7 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee) /* We must escape the '%' that starts RETURN_REGNUM. */ sprintf (rval, "\tld.param%%t0\t%%0, [%%%s_in];\n\t}", reg_names[NVPTX_RETURN_REGNUM]); + return rval; } @@ -3141,6 +3184,8 @@ nvptx_print_operand (FILE *file, rtx x, int code) vals[1] &= 0xffffffff; if (mode == SFmode) fprintf (file, "0f%08lx", vals[0]); + else if (mode == HFmode) + fprintf (file, "0x%04lx", vals[0] & 0xffff); else fprintf (file, "0d%08lx%08lx", vals[1], vals[0]); break; @@ -7286,7 +7331,7 @@ nvptx_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, static bool nvptx_scalar_mode_supported_p (scalar_mode mode) { - if (nvptx_experimental && mode == HFmode && TARGET_SM53) + if (mode == HFmode && TARGET_SM53) return true; return default_scalar_mode_supported_p (mode); @@ -7295,7 +7340,7 @@ nvptx_scalar_mode_supported_p (scalar_mode mode) static bool nvptx_libgcc_floating_mode_supported_p (scalar_float_mode mode) { - if (nvptx_experimental && mode == HFmode && TARGET_SM53) + if (mode == HFmode && TARGET_SM53) return true; return default_libgcc_floating_mode_supported_p (mode); diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 740c4de..58bc492 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -298,7 +298,7 @@ (define_insn "*movhf_insn" [(set (match_operand:HF 0 "nonimmediate_operand" "=R,R,m") - (match_operand:HF 1 "nonimmediate_operand" "R,m,R"))] + (match_operand:HF 1 "general_operand" "RF,m,R"))] "!MEM_P (operands[0]) || REG_P (operands[1])" "@ %.\\tmov.b16\\t%0, %1; @@ -308,28 +308,9 @@ (define_expand "movhf" [(set (match_operand:HF 0 "nonimmediate_operand" "") - (match_operand:HF 1 "nonimmediate_operand" ""))] + (match_operand:HF 1 "general_operand" ""))] "" { - /* Load HFmode constants as SFmode with an explicit FLOAT_TRUNCATE. */ - if (CONST_DOUBLE_P (operands[1])) - { - rtx tmp1 = gen_reg_rtx (SFmode); - REAL_VALUE_TYPE d = *CONST_DOUBLE_REAL_VALUE (operands[1]); - real_convert (&d, SFmode, &d); - emit_move_insn (tmp1, const_double_from_real_value (d, SFmode)); - - if (!REG_P (operands[0])) - { - rtx tmp2 = gen_reg_rtx (HFmode); - emit_insn (gen_truncsfhf2 (tmp2, tmp1)); - emit_move_insn (operands[0], tmp2); - } - else - emit_insn (gen_truncsfhf2 (operands[0], tmp1)); - DONE; - } - if (MEM_P (operands[0]) && !REG_P (operands[1])) { rtx tmp = gen_reg_rtx (HFmode); @@ -896,7 +877,7 @@ [(set (match_operand:BI 0 "nvptx_register_operand" "=R") (match_operator:BI 1 "nvptx_float_comparison_operator" [(match_operand:HF 2 "nvptx_register_operand" "R") - (match_operand:HF 3 "nvptx_nonmemory_operand" "RF")]))] + (match_operand:HF 3 "nvptx_register_operand" "R")]))] "TARGET_SM53" "%.\\tsetp%c1\\t%0, %2, %3;") @@ -1151,7 +1132,7 @@ [(set (match_operand:SI 0 "nvptx_register_operand") (match_operator:SI 1 "nvptx_float_comparison_operator" [(match_operand:HF 2 "nvptx_register_operand") - (match_operand:HF 3 "nvptx_nonmemory_operand")]))] + (match_operand:HF 3 "nvptx_register_operand")]))] "TARGET_SM53" { rtx reg = gen_reg_rtx (BImode); @@ -1371,8 +1352,8 @@ (define_insn "fmahf4" [(set (match_operand:HF 0 "nvptx_register_operand" "=R") (fma:HF (match_operand:HF 1 "nvptx_register_operand" "R") - (match_operand:HF 2 "nvptx_nonmemory_operand" "RF") - (match_operand:HF 3 "nvptx_nonmemory_operand" "RF")))] + (match_operand:HF 2 "nvptx_register_operand" "R") + (match_operand:HF 3 "nvptx_register_operand" "R")))] "TARGET_SM53" "%.\\tfma%#.f16\\t%0, %1, %2, %3;") @@ -1523,6 +1504,30 @@ "TARGET_SM53" "%.\\tcvt%#%t0%t1\\t%0, %1;") +(define_insn "floatunshf2" + [(set (match_operand:HF 0 "nvptx_register_operand" "=R") + (unsigned_float:HF (match_operand:SDIM 1 "nvptx_register_operand" "R")))] + "TARGET_SM53" + "%.\\tcvt%#%t0.u%T1\\t%0, %1;") + +(define_insn "floathf2" + [(set (match_operand:HF 0 "nvptx_register_operand" "=R") + (float:HF (match_operand:SDIM 1 "nvptx_register_operand" "R")))] + "TARGET_SM53" + "%.\\tcvt%#%t0.s%T1\\t%0, %1;") + +(define_insn "fixuns_trunchf2" + [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") + (unsigned_fix:SDIM (match_operand:HF 1 "nvptx_register_operand" "R")))] + "TARGET_SM53" + "%.\\tcvt.rzi.u%T0%t1\\t%0, %1;") + +(define_insn "fix_trunchf2" + [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") + (fix:SDIM (match_operand:HF 1 "nvptx_register_operand" "R")))] + "TARGET_SM53" + "%.\\tcvt.rzi.s%T0%t1\\t%0, %1;") + ;; Vector operations (define_insn "*vec_set_0" diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt index 71d3b68..17557f3 100644 --- a/gcc/config/nvptx/nvptx.opt +++ b/gcc/config/nvptx/nvptx.opt @@ -53,7 +53,7 @@ Target Mask(GOMP) Generate code for OpenMP offloading: enables -msoft-stack and -muniform-simt. misa= -Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) +Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) Init(PTX_ISA_SM53) Specify the PTX ISA target architecture to use. march= @@ -144,5 +144,3 @@ Target Var(nvptx_comment) Init(1) Undocumented malias Target Var(nvptx_alias) Init(0) Undocumented -mexperimental -Target Var(nvptx_experimental) Init(0) Undocumented diff --git a/gcc/function.cc b/gcc/function.cc index dc333c2..90ca779 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -3587,7 +3587,16 @@ assign_parms_unsplit_complex (struct assign_parm_data_all *all, real = DECL_RTL (fnargs[i]); imag = DECL_RTL (fnargs[i + 1]); - if (inner != GET_MODE (real)) + machine_mode orig_mode = GET_MODE (real); + if (SCALAR_FLOAT_MODE_P (inner) + && SCALAR_INT_MODE_P (orig_mode) + && known_lt (GET_MODE_SIZE (inner), + GET_MODE_SIZE (orig_mode))) + { + real = convert_wider_int_to_float (inner, orig_mode, real); + imag = convert_wider_int_to_float (inner, orig_mode, imag); + } + else if (inner != orig_mode) { real = gen_lowpart_SUBREG (inner, real); imag = gen_lowpart_SUBREG (inner, imag); @@ -3621,7 +3630,23 @@ assign_parms_unsplit_complex (struct assign_parm_data_all *all, real = DECL_INCOMING_RTL (fnargs[i]); imag = DECL_INCOMING_RTL (fnargs[i + 1]); - if (inner != GET_MODE (real)) + orig_mode = GET_MODE (real); + if (SCALAR_FLOAT_MODE_P (inner) + && SCALAR_INT_MODE_P (orig_mode) + && known_lt (GET_MODE_SIZE (inner), + GET_MODE_SIZE (orig_mode))) + { + push_to_sequence2 (all->first_conversion_insn, + all->last_conversion_insn); + real = force_reg (orig_mode, real); + imag = force_reg (orig_mode, imag); + real = convert_wider_int_to_float (inner, orig_mode, real); + imag = convert_wider_int_to_float (inner, orig_mode, imag); + all->first_conversion_insn = get_insns (); + all->last_conversion_insn = get_last_insn (); + end_sequence (); + } + else if (inner != orig_mode) { real = gen_lowpart_SUBREG (inner, real); imag = gen_lowpart_SUBREG (inner, imag); diff --git a/gcc/optabs.cc b/gcc/optabs.cc index 2ffd455..92c1745 100644 --- a/gcc/optabs.cc +++ b/gcc/optabs.cc @@ -5643,6 +5643,37 @@ expand_float (rtx to, rtx from, int unsignedp) } } +/* Promote floating point arguments for a libcall if necessary. + There are no tree types defined for libcalls. */ + +static rtx +prepare_libcall_fp_arg (rtx arg) +{ + scalar_float_mode mode; + machine_mode arg_mode; + if (is_a (GET_MODE (arg), &mode)) + { + /* If we need to promote the floating point function argument, do + it here instead of inside emit_library_call_value matching the + use of prepare_libcall_int_arg. */ + + int unsigned_p = 0; + arg_mode = targetm.calls.promote_function_mode (NULL_TREE, mode, + &unsigned_p, + NULL_TREE, 0); + /* Some ABIs require scalar floating point modes to be passed + in a wider scalar integer mode. We need to explicitly + reinterpret to an integer mode of the correct precision + before extending to the desired result. */ + if (SCALAR_INT_MODE_P (arg_mode) + && known_gt (GET_MODE_SIZE (arg_mode), GET_MODE_SIZE (mode))) + return convert_float_to_wider_int (arg_mode, mode, arg); + if (arg_mode != mode) + return convert_to_mode (arg_mode, arg, unsigned_p); + } + return arg; +} + /* Generate code to convert FROM to fixed point and store in TO. FROM must be floating point. */ @@ -5805,15 +5836,19 @@ expand_fix (rtx to, rtx from, int unsignedp) rtx_insn *insns; rtx value; rtx libfunc; + rtx promoted_from; convert_optab tab = unsignedp ? ufix_optab : sfix_optab; libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from)); gcc_assert (libfunc); + promoted_from = prepare_libcall_fp_arg (from); + start_sequence (); value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, - GET_MODE (to), from, GET_MODE (from)); + GET_MODE (to), promoted_from, + GET_MODE (promoted_from)); insns = get_insns (); end_sequence (); @@ -5838,7 +5873,7 @@ expand_fix (rtx to, rtx from, int unsignedp) there are no tree types defined for libcalls. */ static rtx -prepare_libcall_arg (rtx arg, int uintp) +prepare_libcall_int_arg (rtx arg, int uintp) { scalar_int_mode mode; machine_mode arg_mode; @@ -5900,7 +5935,7 @@ expand_fixed_convert (rtx to, rtx from, int uintp, int satp) libfunc = convert_optab_libfunc (tab, to_mode, from_mode); gcc_assert (libfunc); - from = prepare_libcall_arg (from, uintp); + from = prepare_libcall_int_arg (from, uintp); from_mode = GET_MODE (from); start_sequence (); diff --git a/gcc/testsuite/gcc.target/nvptx/float16-1.c b/gcc/testsuite/gcc.target/nvptx/float16-1.c index 017774c..873a054 100644 --- a/gcc/testsuite/gcc.target/nvptx/float16-1.c +++ b/gcc/testsuite/gcc.target/nvptx/float16-1.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -ffast-math -misa=sm_53 -mptx=_" } */ -/* { dg-additional-options "-mexperimental" } */ _Float16 var; diff --git a/gcc/testsuite/gcc.target/nvptx/float16-2.c b/gcc/testsuite/gcc.target/nvptx/float16-2.c index e15b685..30a3092 100644 --- a/gcc/testsuite/gcc.target/nvptx/float16-2.c +++ b/gcc/testsuite/gcc.target/nvptx/float16-2.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -ffast-math -misa=sm_80 -mptx=_" } */ -/* { dg-additional-options "-mexperimental" } */ _Float16 x; _Float16 y; diff --git a/gcc/testsuite/gcc.target/nvptx/float16-3.c b/gcc/testsuite/gcc.target/nvptx/float16-3.c index 1c64690..edd6514 100644 --- a/gcc/testsuite/gcc.target/nvptx/float16-3.c +++ b/gcc/testsuite/gcc.target/nvptx/float16-3.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -misa=sm_53 -mptx=_" } */ -/* { dg-additional-options "-mexperimental" } */ _Float16 var; diff --git a/gcc/testsuite/gcc.target/nvptx/float16-4.c b/gcc/testsuite/gcc.target/nvptx/float16-4.c index 1c24ec8..0a82397 100644 --- a/gcc/testsuite/gcc.target/nvptx/float16-4.c +++ b/gcc/testsuite/gcc.target/nvptx/float16-4.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -ffast-math -misa=sm_53 -mptx=_" } */ -/* { dg-additional-options "-mexperimental" } */ _Float16 var; diff --git a/gcc/testsuite/gcc.target/nvptx/float16-5.c b/gcc/testsuite/gcc.target/nvptx/float16-5.c index 9ae3365..2261f42 100644 --- a/gcc/testsuite/gcc.target/nvptx/float16-5.c +++ b/gcc/testsuite/gcc.target/nvptx/float16-5.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -ffast-math -misa=sm_53 -mptx=_" } */ -/* { dg-additional-options "-mexperimental" } */ _Float16 a; _Float16 b; diff --git a/gcc/testsuite/gcc.target/nvptx/float16-6.c b/gcc/testsuite/gcc.target/nvptx/float16-6.c index 37c5804..9ca714c 100644 --- a/gcc/testsuite/gcc.target/nvptx/float16-6.c +++ b/gcc/testsuite/gcc.target/nvptx/float16-6.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -misa=sm_53 -mptx=_" } */ -/* { dg-additional-options "-mexperimental" } */ _Float16 x; _Float16 y; diff --git a/libgcc/config.host b/libgcc/config.host index d208765..9b315c0 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1498,7 +1498,7 @@ m32c-*-elf*) tmake_file="$tmake_file m32c/t-m32c" ;; nvptx-*) - tmake_file="$tmake_file nvptx/t-nvptx" + tmake_file="$tmake_file nvptx/t-nvptx nvptx/t-softfp t-softfp" extra_parts="crt0.o" ;; *) diff --git a/libgcc/config/nvptx/sfp-machine.h b/libgcc/config/nvptx/sfp-machine.h new file mode 100644 index 0000000..a4c9fc3 --- /dev/null +++ b/libgcc/config/nvptx/sfp-machine.h @@ -0,0 +1,46 @@ +/* Machine description for NVPTX architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE unsigned long long +#define _FP_WS_TYPE signed long long +#define _FP_I_TYPE long long + +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype)) + +#define _FP_TININESS_AFTER_ROUNDING 1 + +#define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 + +#define _FP_NANSIGN_H 1 +#define _FP_NANFRAC_H _FP_QNANBIT_H + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#define __BYTE_ORDER __LITTLE_ENDIAN + diff --git a/libgcc/config/nvptx/t-softfp b/libgcc/config/nvptx/t-softfp new file mode 100644 index 0000000..b63151c --- /dev/null +++ b/libgcc/config/nvptx/t-softfp @@ -0,0 +1,24 @@ +# Soft float configuration for NVPTX +# Copyright (C) 2006-2022 Free Software Foundation, Inc. + +# This file is part of GCC. + +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. + +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +softfp_wrap_start := '\#if __PTX_SM__ >= 530' +softfp_wrap_end := '\#endif' + +softfp_extras := fixhfti fixunshfti floattihf floatuntihf +