Hello!
The testcase in PR58792 [1], where a function returns its result in
multiple registers, triggered a very picky assert in mode-switching
code. The problem was, that x86_64 didn't mark correctly all of its
possible return registers, so code assumed that something went wrong
here.
The mode-switching code already handles __builtin_apply builtin, which
also generates multiple return registers. When a sequence of USEs is
detected, maybe_builtin_apply flag is raised to bypass the assert.
However, functions that pass their result in multiple registers also
generate multiple USEs, so the patch clarifies that __builtin_apply
situation actually applies to all multiple return register exits. The
patch clarifies this situation.
No functional changes (modulo converting a couple of variables to boolean type).
2013-10-19 Uros Bizjak <[email protected]>
* mode-switching.c (create_pre_exit): Rename maybe_builtin_apply
to multi_reg_return. Clarify that we are skipping USEs of multiple
return registers. Use bool type where appropriate.
Tested on x86_64-pc-linux-gnu and committed to mainline SVN.
[1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58792
Uros.
Index: mode-switching.c
===================================================================
--- mode-switching.c (revision 203845)
+++ mode-switching.c (working copy)
@@ -229,9 +229,9 @@ create_pre_exit (int n_entities, int *entity_map,
int ret_start = REGNO (ret_reg);
int nregs = hard_regno_nregs[ret_start][GET_MODE (ret_reg)];
int ret_end = ret_start + nregs;
- int short_block = 0;
- int maybe_builtin_apply = 0;
- int forced_late_switch = 0;
+ bool short_block = false;
+ bool multi_reg_return = false;
+ bool forced_late_switch = false;
rtx before_return_copy;
do
@@ -251,19 +251,20 @@ create_pre_exit (int n_entities, int *entity_map,
copy yet, the copy must have been deleted. */
if (CALL_P (return_copy))
{
- short_block = 1;
+ short_block = true;
break;
}
return_copy_pat = PATTERN (return_copy);
switch (GET_CODE (return_copy_pat))
{
case USE:
- /* Skip __builtin_apply pattern. */
+ /* Skip return values in multiple registers.
+ __builtin_apply pattern is also handled here. */
if (GET_CODE (XEXP (return_copy_pat, 0)) == REG
&& (targetm.calls.function_value_regno_p
(REGNO (XEXP (return_copy_pat, 0)))))
{
- maybe_builtin_apply = 1;
+ multi_reg_return = true;
last_insn = return_copy;
continue;
}
@@ -326,7 +327,7 @@ create_pre_exit (int n_entities, int *entity_map,
there are no return copy insns at all. This
avoids an ice on that invalid function. */
if (ret_start + nregs == ret_end)
- short_block = 1;
+ short_block = true;
break;
}
if (!targetm.calls.function_value_regno_p (copy_start))
@@ -354,10 +355,10 @@ create_pre_exit (int n_entities, int *entity_map,
another mode than MODE_EXIT, even if it is
unrelated to the return value, so we want to put
the final mode switch after it. */
- if (maybe_builtin_apply
+ if (multi_reg_return
&& targetm.calls.function_value_regno_p
(copy_start))
- forced_late_switch = 1;
+ forced_late_switch = true;
/* For the SH4, floating point loads depend on fpscr,
thus we might need to put the final mode switch
@@ -367,7 +368,7 @@ create_pre_exit (int n_entities, int *entity_map,
if (copy_start >= ret_start
&& copy_start + copy_num <= ret_end
&& OBJECT_P (SET_SRC (return_copy_pat)))
- forced_late_switch = 1;
+ forced_late_switch = true;
break;
}
if (copy_num == 0)
@@ -379,7 +380,7 @@ create_pre_exit (int n_entities, int *entity_map,
if (copy_start >= ret_start
&& copy_start + copy_num <= ret_end)
nregs -= copy_num;
- else if (!maybe_builtin_apply
+ else if (!multi_reg_return
|| !targetm.calls.function_value_regno_p
(copy_start))
break;
@@ -393,7 +394,7 @@ create_pre_exit (int n_entities, int *entity_map,
isolated use. */
if (return_copy == BB_HEAD (src_bb))
{
- short_block = 1;
+ short_block = true;
break;
}
last_insn = return_copy;