nvptx: Use fatal_error when -march= is missing not an assert [PR111093]

Message ID 928b02fd-2662-4a4d-9c55-ab538464b7fb@codesourcery.com
State Accepted
Headers
Series nvptx: Use fatal_error when -march= is missing not an assert [PR111093] |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Tobias Burnus Oct. 16, 2023, 9:18 a.m. UTC
  While mkoffload ensures that there is always a -march=, nvptx's
cc1 can also be run directly.

In my case, I wanted to know which target-specific #define are
available; hence, I did run:
   accel/nvptx-none/cc1 -E -dM < /dev/null
which gave an ICE. After some debugging, the reasons was
clear (missing -march=) but somehow a (fatal) error would have been
nicer than an ICE + debugging.

OK for mainline?

Tobias
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
  

Comments

Thomas Schwinge Oct. 18, 2023, 10:16 a.m. UTC | #1
Hi Tobias!

On 2023-10-16T11:18:45+0200, Tobias Burnus <tobias@codesourcery.com> wrote:
> While mkoffload ensures that there is always a -march=, nvptx's
> cc1 can also be run directly.
>
> In my case, I wanted to know which target-specific #define are
> available; hence, I did run:
>    accel/nvptx-none/cc1 -E -dM < /dev/null
> which gave an ICE. After some debugging, the reasons was
> clear (missing -march=) but somehow a (fatal) error would have been
> nicer than an ICE + debugging.
>
> OK for mainline?

Yes, thanks.  I think I prefer this over hard-coding some default
'ptx_isa_option' -- but may be convinced otherwise (incremental change),
if that's maybe more convenient for others?  (Roger?)


Grüße
 Thomas


> nvptx: Use fatal_error when -march= is missing not an assert [PR111093]
>
> gcc/ChangeLog:
>
>       PR target/111093
>       * config/nvptx/nvptx.cc (nvptx_option_override): Issue fatal error
>       instead of an assert ICE when no -march= has been specified.
>
> diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
> index edef39fb5e1..634c31673be 100644
> --- a/gcc/config/nvptx/nvptx.cc
> +++ b/gcc/config/nvptx/nvptx.cc
> @@ -335,8 +335,9 @@ nvptx_option_override (void)
>    init_machine_status = nvptx_init_machine_status;
>
>    /* Via nvptx 'OPTION_DEFAULT_SPECS', '-misa' always appears on the command
> -     line.  */
> -  gcc_checking_assert (OPTION_SET_P (ptx_isa_option));
> +     line; but handle the case that the compiler is not run via the driver.  */
> +  if (!OPTION_SET_P (ptx_isa_option))
> +    fatal_error (UNKNOWN_LOCATION, "%<-march=%> must be specified");
>
>    handle_ptx_version_option ();
>
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
  
Roger Sayle Oct. 18, 2023, 4:01 p.m. UTC | #2
Hi Tomas, Tobias and Tom,
Thanks for asking.  Interestingly, I've a patch (attached) from last year that
tackled some of the issues here.  The surface problem is that nvptx's march
and misa are related in complicated ways.  Specifying an arch defines the
range of valid isa's, and specifying an isa restricts the set of valid arches.

The current approach, which I agree is problematic, is to force these to
be specified (compatibly) on the cc1 command line.  Certainly, an error
is better than an abort.  My proposed solution was to allow either to 
imply a default for the other, and only issue an error if they are explicitly
specified incompatibly.

One reason for supporting this approach was to ultimately support an
-march=native in the driver (calling libcuda.so to determine the hardware
available on the current machine).

The other use case is bumping the "default" nvptx architecture to something
more recent, say sm_53, by providing/honoring a default arch at configure
time.

Alas, it turns out that specifying a recent arch during GCC bootstrap, allows
the build to notice that the backend (now) supports 16-bit floats, which then
prompts libgcc to contain the floathf and fixhf support that would be required.
Then this in turn shows up as a limitation in the middle-end's handling of 
libcalls, which I submitted as a patch to back in July 2022:
https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598848.html

That patch hasn't yet been approved, so the whole nvptx -march= patch
series became backlogged/forgotten.

Hopefully, the attached "proof-of-concept" patch looks interesting (food
for thought).  If this approach seems reasonable, I'm happy to brush the
dust off, and resubmit it (or a series of pieces) for review.

Best regards,
Roger
--

> -----Original Message-----
> From: Thomas Schwinge <thomas@codesourcery.com>
> Sent: 18 October 2023 11:16
> To: Tobias Burnus <tobias@codesourcery.com>
> Cc: gcc-patches@gcc.gnu.org; Tom de Vries <tdevries@suse.de>; Roger Sayle
> <roger@nextmovesoftware.com>
> Subject: Re: [Patch] nvptx: Use fatal_error when -march= is missing not an assert
> [PR111093]
> 
> Hi Tobias!
> 
> On 2023-10-16T11:18:45+0200, Tobias Burnus <tobias@codesourcery.com>
> wrote:
> > While mkoffload ensures that there is always a -march=, nvptx's
> > cc1 can also be run directly.
> >
> > In my case, I wanted to know which target-specific #define are
> > available; hence, I did run:
> >    accel/nvptx-none/cc1 -E -dM < /dev/null which gave an ICE. After
> > some debugging, the reasons was clear (missing -march=) but somehow a
> > (fatal) error would have been nicer than an ICE + debugging.
> >
> > OK for mainline?
> 
> Yes, thanks.  I think I prefer this over hard-coding some default 'ptx_isa_option' --
> but may be convinced otherwise (incremental change), if that's maybe more
> convenient for others?  (Roger?)
> 
> 
> Grüße
>  Thomas
> 
> 
> > nvptx: Use fatal_error when -march= is missing not an assert
> > [PR111093]
> >
> > gcc/ChangeLog:
> >
> >       PR target/111093
> >       * config/nvptx/nvptx.cc (nvptx_option_override): Issue fatal error
> >       instead of an assert ICE when no -march= has been specified.
> >
> > diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
> > index edef39fb5e1..634c31673be 100644
> > --- a/gcc/config/nvptx/nvptx.cc
> > +++ b/gcc/config/nvptx/nvptx.cc
> > @@ -335,8 +335,9 @@ nvptx_option_override (void)
> >    init_machine_status = nvptx_init_machine_status;
> >
> >    /* Via nvptx 'OPTION_DEFAULT_SPECS', '-misa' always appears on the
> command
> > -     line.  */
> > -  gcc_checking_assert (OPTION_SET_P (ptx_isa_option));
> > +     line; but handle the case that the compiler is not run via the
> > + driver.  */  if (!OPTION_SET_P (ptx_isa_option))
> > +    fatal_error (UNKNOWN_LOCATION, "%<-march=%> must be specified");
> >
> >    handle_ptx_version_option ();
> >
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634
> München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas
> Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht
> München, HRB 106955
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 "floatuns<mode>hf2"
+  [(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 "float<mode>hf2"
+  [(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_trunchf<mode>2"
+  [(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_trunchf<mode>2"
+  [(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<mode>_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 <scalar_float_mode> (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
+<http://www.gnu.org/licenses/>.  */
+
+#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
+# <http://www.gnu.org/licenses/>.
+
+softfp_wrap_start := '\#if __PTX_SM__ >= 530'
+softfp_wrap_end := '\#endif'
+
+softfp_extras := fixhfti fixunshfti floattihf floatuntihf
+
  

Patch

nvptx: Use fatal_error when -march= is missing not an assert [PR111093]

gcc/ChangeLog:

	PR target/111093
	* config/nvptx/nvptx.cc (nvptx_option_override): Issue fatal error
	instead of an assert ICE when no -march= has been specified.

diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
index edef39fb5e1..634c31673be 100644
--- a/gcc/config/nvptx/nvptx.cc
+++ b/gcc/config/nvptx/nvptx.cc
@@ -335,8 +335,9 @@  nvptx_option_override (void)
   init_machine_status = nvptx_init_machine_status;
 
   /* Via nvptx 'OPTION_DEFAULT_SPECS', '-misa' always appears on the command
-     line.  */
-  gcc_checking_assert (OPTION_SET_P (ptx_isa_option));
+     line; but handle the case that the compiler is not run via the driver.  */
+  if (!OPTION_SET_P (ptx_isa_option))
+    fatal_error (UNKNOWN_LOCATION, "%<-march=%> must be specified");
 
   handle_ptx_version_option ();