diff mbox

Change to argument promotion in fixed conversion library calls

Message ID 1447088342.3867.27.camel@ubuntu-sellcey
State New
Headers show

Commit Message

Steve Ellcey Nov. 9, 2015, 4:59 p.m. UTC
On Fri, 2015-11-06 at 20:29 +0100, Bernd Schmidt wrote:
> On 11/06/2015 08:27 PM, Steve Ellcey wrote:
> >
> > Are you thinking of a simple function that is called on all targets or a
> > target specific function?  Maybe a target specific function would be
> > safer.
> 
> No, I think just what you have there is probably sufficient.
> 
> 
> Bernd

Bernd,

Here is a version with the code moved into a new function.  How does
this look?

2015-11-09  Steve Ellcey  <sellcey@imgtec.com>

	* optabs.c (prepare_libcall_arg): New function.
	(expand_fixed_convert): Add call to prepare_libcall_arg.

Comments

Bernd Schmidt Nov. 9, 2015, 8:47 p.m. UTC | #1
On 11/09/2015 05:59 PM, Steve Ellcey wrote:
> Here is a version with the code moved into a new function.  How does
> this look?
>
> 2015-11-09  Steve Ellcey  <sellcey@imgtec.com>
>
> 	* optabs.c (prepare_libcall_arg): New function.
> 	(expand_fixed_convert): Add call to prepare_libcall_arg.

Hold on a moment - I see that emit_library_call_value_1 calls 
promote_function_mode for arguments. Can you investigate why that 
doesn't do what you need?


Bernd
Steve Ellcey Nov. 9, 2015, 9:10 p.m. UTC | #2
On Mon, 2015-11-09 at 21:47 +0100, Bernd Schmidt wrote:
> On 11/09/2015 05:59 PM, Steve Ellcey wrote:
> > Here is a version with the code moved into a new function.  How does
> > this look?
> >
> > 2015-11-09  Steve Ellcey  <sellcey@imgtec.com>
> >
> > 	* optabs.c (prepare_libcall_arg): New function.
> > 	(expand_fixed_convert): Add call to prepare_libcall_arg.
> 
> Hold on a moment - I see that emit_library_call_value_1 calls 
> promote_function_mode for arguments. Can you investigate why that 
> doesn't do what you need?
> 
> 
> Bernd


emit_library_call_value_1 has no way of knowing if the promotion should
be signed or unsigned because it has a mode (probably QImode or HImode)
that it knows may need to be promoted to SImode but it has no way to
know if that should be a signed or unsigned promotion because it has no
tree type information about the library call argument types.

Right now it guesses based on the return type but it may guess wrong
when converting an unsigned int to a signed fixed type or visa versa.

By doing the promotion in expand_fixed_convert GCC can use the uintp
argument to ensure that the signedness of the promotion is done
correctly.  We could pass that argument into emit_library_call_value_1
so it can do the correct promotion but that would require changing the
argument list for emit_library_call and emit_library_call_value_1 and
changing all the other call locations for those functions and that
seemed like overkill.

Steve Ellcey
Bernd Schmidt Nov. 9, 2015, 11:33 p.m. UTC | #3
On 11/09/2015 10:10 PM, Steve Ellcey wrote:
> emit_library_call_value_1 has no way of knowing if the promotion should
> be signed or unsigned because it has a mode (probably QImode or HImode)
> that it knows may need to be promoted to SImode but it has no way to
> know if that should be a signed or unsigned promotion because it has no
> tree type information about the library call argument types.
>
> Right now it guesses based on the return type but it may guess wrong
> when converting an unsigned int to a signed fixed type or visa versa.

That's not quite how I read the code, but it doesn't matter - the lack 
of a type seems to be a real issue. Since I don't see anything better, 
please install your patch.


Bernd
diff mbox

Patch

diff --git a/gcc/optabs.c b/gcc/optabs.c
index fdcdc6a..fb25f90 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -4838,6 +4838,33 @@  expand_fix (rtx to, rtx from, int unsignedp)
     }
 }
 
+
+/* Promote integer arguments for a libcall if necessary.
+   emit_library_call_value cannot do the promotion because it does not
+   know if it should do a signed or unsigned promotion.  This is because
+   there are no tree types defined for libcalls.  */
+
+static rtx
+prepare_libcall_arg (rtx arg, int uintp)
+{
+  machine_mode mode = GET_MODE (arg);
+  machine_mode arg_mode;
+  if (SCALAR_INT_MODE_P (mode))
+    {
+      /*  If we need to promote the integer function argument we need to do
+	  it here instead of inside emit_library_call_value because in
+	  emit_library_call_value we don't know if we should do a signed or
+	  unsigned promotion.  */
+
+      int unsigned_p = 0;
+      arg_mode = promote_function_mode (NULL_TREE, mode,
+					&unsigned_p, NULL_TREE, 0);
+      if (arg_mode != mode)
+	return convert_to_mode (arg_mode, arg, uintp);
+    }
+    return arg;
+}
+
 /* Generate code to convert FROM or TO a fixed-point.
    If UINTP is true, either TO or FROM is an unsigned integer.
    If SATP is true, we need to saturate the result.  */
@@ -4880,6 +4907,9 @@  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_mode = GET_MODE (from);
+
   start_sequence ();
   value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
 				   1, from, from_mode);