I’m woking on TARGET_PROMOTE_FUNCTION_MODE for csky, and now there’s some
confusion.
For csky, the “POMOTE_MODE” is:
qi/hi -> si
the code is
#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
if (GET_MODE_CLASS (MODE) == MODE_INT \
&& GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
(MODE) = SImode;
And the TARGET_PROMOTE_FUNCTION_MODE is
default_promote_function_mode_always_promote.
I expected it can work as “POMOTE_MODE” just as the description at “gcc
internal”. But it calls promote_mode() and treat “libcalls” specially.:
machine_mode
promote_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode,
int *punsignedp ATTRIBUTE_UNUSED)
{
#ifdef PROMOTE_MODE
enum tree_code code;
int unsignedp;
scalar_mode smode;
#endif
/* For libcalls this is invoked without TYPE from the backends
TARGET_PROMOTE_FUNCTION_MODE hooks. Don't do anything in that
case. */
if (type == NULL_TREE)
return mode;
……
Why don’t promote the mode here? And when I compile runtime library, the
“char” and “short” args are promoted WITHOUT special treatment!
So, I modified the code to make sure the TARGET_PROMOTE_FUNCTION_MODE work
as POMOTE_MODE:
#undef TARGET_PROMOTE_FUNCTION_MODE
#define TARGET_PROMOTE_FUNCTION_MODE \
csky_promote_function_mode
……
static machine_mode
csky_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
machine_mode mode,
int *punsignedp ATTRIBUTE_UNUSED,
const_tree fntype ATTRIBUTE_UNUSED,
int for_return ATTRIBUTE_UNUSED)
{
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
return SImode;
return mode;
}
But this code could lead to another mistake when I use some builtin
functions.
The __sync_val_compare_and_swap_1() coded at
“libgcc/config/csky/linux-atomic.c” use type “unsigned char” as its
argrument.
And this is consistent with the definition at gcc/builtins.def.
But when the code run at emit_library_call_value_1, all of the args are
treated as “signed”.
Part of source code of emit_library_call_value_1 ↓. The “unsigned_p” was
inited to 0, and was used at prmote_funciton_mode without reassignment.
for (unsigned int i = 0; count < nargs; i++, count++)
{
rtx val = args[i].first;
function_arg_info arg (args[i].second, /*named=*/true);
int unsigned_p = 0;
……
arg.mode = promote_function_mode (NULL_TREE, arg.mode, &unsigned_p,
NULL_TREE, 0);
argvec[count].mode = arg.mode;
argvec[count].value = convert_modes (arg.mode, GET_MODE (val), val,
unsigned_p);
argvec[count].reg = targetm.calls.function_arg (args_so_far, arg);
……
What’s reason for this act?