[PATCH] Fix PR46399 - missing mode promotion for libcall args - updated

Andreas Krebbel krebbel@linux.vnet.ibm.com
Thu Mar 3 16:32:00 GMT 2011


Hi,

I've refreshed the patch:

[PATCH] Fix PR46399 - missing mode promotion for libcall args
http://gcc.gnu.org/ml/gcc-patches/2011-02/msg01595.html

after removing the FUNCTION_VALUE target macro with:

[Committed] S/390: Remove deprecated target macro FUNCTION_VALUE
http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00127.html

And I've moved the documentation of the new target hook to target.def
as requested by Nathan.

Bootstrapped on x86_64, s390 and s390x. No regressions.

Two testcases fixed on s390x:

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

Ok for mainline?

Bye,

-Andreas-


2011-03-04  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	PR middle-end/46399
	* calls.c (emit_library_call_value_1): Promote libcall arguments
	using promote_libcall_mode.
	* explow.c (promote_libcall_mode): New function.
	* expr.h (promote_libcall_mode): New prototype.
	* target.def (promote_libcall_mode): New target hook.
	* targhooks.c (default_promote_libcall_mode): New function.
	* targhooks.h (default_promote_libcall_mode): New prototype.
	* config/s390/s390.c (s390_promote_libcall_mode): New function.

	* doc/tm.texi: Regenerate.


Index: gcc/calls.c
===================================================================
*** gcc/calls.c.orig
--- gcc/calls.c
*************** emit_library_call_value_1 (int retval, r
*** 3481,3486 ****
--- 3481,3487 ----
      {
        rtx val = va_arg (p, rtx);
        enum machine_mode mode = (enum machine_mode) va_arg (p, int);
+       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,3536 ****
  	  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);
  
--- 3529,3537 ----
  	  val = force_operand (XEXP (slot, 0), NULL_RTX);
  	}
  
!       mode = promote_libcall_mode (mode, &unsigned_p, fntype, 1);
        argvec[count].mode = mode;
!       argvec[count].value = convert_modes (mode, GET_MODE (val), val, unsigned_p);
        argvec[count].reg = targetm.calls.function_arg (&args_so_far, mode,
  						      NULL_TREE, true);
  
Index: gcc/explow.c
===================================================================
*** gcc/explow.c.orig
--- gcc/explow.c
*************** promote_function_mode (const_tree type, 
*** 783,788 ****
--- 783,807 ----
        return mode;
      }
  }
+ 
+ /* Return the mode to use to pass or return a scalar of MODE for a libcall.
+    PUNSIGNEDP points to the signedness of the type and may be adjusted
+    to show what signedness to use on extension operations.
+ 
+    FOR_RETURN is nonzero if the caller is promoting the return value
+    of FNDECL, else it is for promoting args.  */
+ 
+ enum machine_mode
+ promote_libcall_mode (enum machine_mode mode, int *punsignedp,
+ 		      const_tree funtype, int for_return)
+ {
+   if (INTEGRAL_MODE_P (mode))
+       return targetm.calls.promote_libcall_mode (mode, punsignedp, funtype,
+ 						 for_return);
+   else
+     return mode;
+ }
+ 
  /* Return the mode to use to store a scalar of TYPE and MODE.
     PUNSIGNEDP points to the signedness of the type and may be adjusted
     to show what signedness to use on extension operations.  */
Index: gcc/expr.h
===================================================================
*** gcc/expr.h.orig
--- gcc/expr.h
*************** extern rtx force_not_mem (rtx);
*** 613,618 ****
--- 613,623 ----
  extern enum machine_mode promote_function_mode (const_tree, enum machine_mode, int *,
  					        const_tree, int);
  
+ /* Return mode and signedness to use when an libcall argument or
+    result in the given mode is promoted.  */
+ extern enum machine_mode promote_libcall_mode (enum machine_mode, int *,
+ 					       const_tree, int);
+ 
  /* Return mode and signedness to use when an object in the given mode
     is promoted.  */
  extern enum machine_mode promote_mode (const_tree, enum machine_mode, int *);
Index: gcc/target.def
===================================================================
*** gcc/target.def.orig
--- gcc/target.def
*************** DEFHOOK
*** 1918,1923 ****
--- 1918,1935 ----
   default_promote_function_mode)
  
  DEFHOOK
+ (promote_libcall_mode,
+  "Like @code{TARGET_PROMOTE_FUNCTION_MODE}, but it is applied to libcall\
+  arguments only.  Define this if your target requires function\
+  arguments to be promoted to a larger mode and uses C compiled libcall\
+  routines (e.g. libdecnumber).\
+ \
+  The default is not promote arguments and return values.",
+  enum machine_mode, (enum machine_mode mode, int *punsignedp,
+ 		     const_tree funtype, int for_return),
+  default_promote_libcall_mode)
+ 
+ DEFHOOK
  (promote_prototypes,
   "",
   bool, (const_tree fntype),
Index: gcc/targhooks.c
===================================================================
*** gcc/targhooks.c.orig
--- gcc/targhooks.c
*************** default_promote_function_mode_always_pro
*** 139,144 ****
--- 139,153 ----
    return promote_mode (type, mode, punsignedp);
  }
  
+ enum machine_mode
+ default_promote_libcall_mode (enum machine_mode mode,
+ 			      int *punsignedp ATTRIBUTE_UNUSED,
+ 			      const_tree funtype ATTRIBUTE_UNUSED,
+ 			      int for_return ATTRIBUTE_UNUSED)
+ {
+   return mode;
+ }
+ 
  
  enum machine_mode
  default_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
Index: gcc/targhooks.h
===================================================================
*** gcc/targhooks.h.orig
--- gcc/targhooks.h
*************** extern enum machine_mode default_promote
*** 28,33 ****
--- 28,35 ----
  							int *, const_tree, int);
  extern enum machine_mode default_promote_function_mode_always_promote
  			(const_tree, enum machine_mode, int *, const_tree, int);
+ extern enum machine_mode default_promote_libcall_mode (enum machine_mode,
+ 						       int *, const_tree, int);
  
  extern enum machine_mode default_cc_modes_compatible (enum machine_mode,
  						      enum machine_mode);
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig
--- gcc/config/s390/s390.c
*************** s390_promote_function_mode (const_tree t
*** 8687,8692 ****
--- 8687,8706 ----
    return mode;
  }
  
+ /* Libcall arguments and return values are promoted to word size.  */
+ 
+ static enum machine_mode
+ s390_promote_libcall_mode (enum machine_mode mode,
+ 			   int *punsignedp ATTRIBUTE_UNUSED,
+ 			   const_tree fntype ATTRIBUTE_UNUSED,
+ 			   int for_return ATTRIBUTE_UNUSED)
+ {
+   if (GET_MODE_SIZE (mode) < UNITS_PER_LONG)
+    return Pmode;
+ 
+   return mode;
+ }
+ 
  /* Define where to return a (scalar) value of type RET_TYPE.
     If RET_TYPE is null, define where to return a (scalar)
     value of mode MODE from a libcall.  */
*************** s390_function_and_libcall_value (enum ma
*** 8698,8710 ****
  				 bool outgoing ATTRIBUTE_UNUSED)
  {
    /* For normal functions perform the promotion as
!      promote_function_mode would do.  */
    if (ret_type)
      {
        int unsignedp = TYPE_UNSIGNED (ret_type);
        mode = promote_function_mode (ret_type, mode, &unsignedp,
  				    fntype_or_decl, 1);
      }
  
    gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || SCALAR_FLOAT_MODE_P (mode));
    gcc_assert (GET_MODE_SIZE (mode) <= 8);
--- 8712,8732 ----
  				 bool outgoing ATTRIBUTE_UNUSED)
  {
    /* For normal functions perform the promotion as
!      promote_function_mode would do and for libcalls use
!      promote_libcall_mode instead.  */
    if (ret_type)
      {
        int unsignedp = TYPE_UNSIGNED (ret_type);
        mode = promote_function_mode (ret_type, mode, &unsignedp,
  				    fntype_or_decl, 1);
      }
+   else
+     {
+       int unsignedp = 0;
+       mode = promote_libcall_mode (mode, &unsignedp,
+ 				   fntype_or_decl, 1);
+     }
+ 
  
    gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || SCALAR_FLOAT_MODE_P (mode));
    gcc_assert (GET_MODE_SIZE (mode) <= 8);
*************** s390_loop_unroll_adjust (unsigned nunrol
*** 10715,10720 ****
--- 10737,10745 ----
  
  #undef TARGET_PROMOTE_FUNCTION_MODE
  #define TARGET_PROMOTE_FUNCTION_MODE s390_promote_function_mode
+ #undef TARGET_PROMOTE_LIBCALL_MODE
+ #define TARGET_PROMOTE_LIBCALL_MODE s390_promote_libcall_mode
+ 
  #undef TARGET_PASS_BY_REFERENCE
  #define TARGET_PASS_BY_REFERENCE s390_pass_by_reference
  
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi.orig
--- gcc/doc/tm.texi
*************** Do not define this macro if it would nev
*** 959,964 ****
--- 959,968 ----
  @end defmac
  
  @deftypefn {Target Hook} {enum machine_mode} TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, enum machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
+ 
+ @deftypefn {Target Hook} {enum machine_mode} TARGET_PROMOTE_LIBCALL_MODE (enum machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
+ Like @code{TARGET_PROMOTE_FUNCTION_MODE}, but it is applied to libcall arguments only.  Define this if your target requires function arguments to be promoted to a larger mode and uses C compiled libcall routines (e.g. libdecnumber). The default is not promote arguments and return values.
+ @end deftypefn
  Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
  function return values.  The target hook should return the new mode
  and possibly change @code{*@var{punsignedp}} if the promotion should



More information about the Gcc-patches mailing list