[PATCH] PR46399: Promote modes of libcall arguments

Andreas Krebbel krebbel@linux.vnet.ibm.com
Thu Jan 13 13:40:00 GMT 2011


Hi,

I've noticed that we do not promote the modes of function args when
emitting a libcall.  Usually the reason for these kind of things is
that "libcalls are special". But since we do emit calls to normal C
functions with the libcall mechanism I think it is necessary to adhere
to the relevant ABI which includes promoting certain values - at least
on s390.

In the testcase in BZ 46399 the library function __dpd_floatunssisd is
invoked without promoting a 32 bit integer argument to 64 bit register
size as it is expected on s390x.  The callee relies on the fact the
value is zero extended and produces wrong results if the upper 32 bits
contain anything else than zeros.

emit_library_call_value_1 already does mode promotion for the return
value.  The attached patch does the same for its arguments.

This fixes two testsuite failures on s390x:

< FAIL: gcc.dg/dfp/pr41049.c execution test
< FAIL: decimal/comparison.cc execution test

Bootstrapped on s390x and x86_64.

Ok for mainline?

Bye,

-Andreas-


2011-01-13  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	PR middle-end/46399
	* calls.c (emit_library_call_value_1): Promote function args using
	the back end hook.


Index: gcc/calls.c
===================================================================
*** gcc/calls.c.orig
--- gcc/calls.c
*************** emit_library_call_value_1 (int retval, r
*** 3481,3486 ****
--- 3481,3488 ----
      {
        rtx val = va_arg (p, rtx);
        enum machine_mode mode = (enum machine_mode) va_arg (p, int);
+       tree type = lang_hooks.types.type_for_mode (mode, 0);
+       int unsigned_p = 0;
  
        /* We cannot convert the arg value to the mode the library wants here;
  	 must do it earlier where we know the signedness of the arg.  */
*************** emit_library_call_value_1 (int retval, r
*** 3528,3538 ****
  	  val = force_operand (XEXP (slot, 0), NULL_RTX);
  	}
  
!       argvec[count].value = val;
        argvec[count].mode = mode;
  
        argvec[count].reg = targetm.calls.function_arg (&args_so_far, mode,
  						      NULL_TREE, true);
  
        argvec[count].partial
  	= targetm.calls.arg_partial_bytes (&args_so_far, mode, NULL_TREE, 1);
--- 3530,3542 ----
  	  val = force_operand (XEXP (slot, 0), NULL_RTX);
  	}
  
!       mode = promote_function_mode (type, mode, &unsigned_p, NULL_TREE, 0);
! 
        argvec[count].mode = mode;
  
        argvec[count].reg = targetm.calls.function_arg (&args_so_far, mode,
  						      NULL_TREE, true);
+       argvec[count].value = convert_modes (mode, GET_MODE (val), val, 0);
  
        argvec[count].partial
  	= targetm.calls.arg_partial_bytes (&args_so_far, mode, NULL_TREE, 1);



More information about the Gcc-patches mailing list