[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