diff options
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index 949a92e..4ad3e34 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -194,10 +194,19 @@ prepare_call_address (tree fndecl_or_type, rtx funexp, rtx static_chain_value, && targetm.small_register_classes_for_mode_p (FUNCTION_MODE)) ? force_not_mem (memory_address (FUNCTION_MODE, funexp)) : memory_address (FUNCTION_MODE, funexp)); - else if (! sibcallp) + else { - if (!NO_FUNCTION_CSE && optimize && ! flag_no_function_cse) - funexp = force_reg (Pmode, funexp); + /* funexp could be a SYMBOL_REF represents a function pointer which is + of ptr_mode. In this case, it should be converted into address mode + to be a valid address for memory rtx pattern. See PR 64971. */ + if (GET_MODE (funexp) != Pmode) + funexp = convert_memory_address (Pmode, funexp); + + if (! sibcallp) + { + if (!NO_FUNCTION_CSE && optimize && ! flag_no_function_cse) + funexp = force_reg (Pmode, funexp); + } } if (static_chain_value != 0 |