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
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).