rs6000: Don't emit a use of LR in returns and sibcalls
The exit block (to which every return artificially jumps) already has a use of LR. The LR use in all returns and sibcalls is an anachronism, probably made unnecessary by the dataflow merge. The simple_returns that shrink-wrapping generates also do not have such a use. Newer backends do not do this either it seems. With this use removed, a normal return is no longer a parallel but just a return insn, and cfgcleanup then can transform conditional jumps to those into conditional returns. This splits the return emission code with restoring_FPRs_inline from that without it; this is simpler code, fewer lines, and less indentation. The return_internal_<mode> pattern can now be deleted since nothing uses it anymore. * config/rs6000/rs6000.c (rs6000_emit_epilogue): Do not emit USEs of LR_REGNO in returns and sibcalls. (rs6000_output_mi_thunk): Similar. (rs6000_sibcall_aix): Similar. * config/rs6000/rs6000.md (sibcall, sibcall_value, sibcall_local32, sibcall_local64, sibcall_value_local32, sibcall_value_local64, sibcall_nonlocal_sysv<mode>, sibcall_value_nonlocal_sysv<mode>): Remove the USE of LR_REGNO from the patterns as well. Delete an obsolete comment. (return_internal_<mode>): Delete. From-SVN: r239866
This commit is contained in:
parent
ac45b2ba8c
commit
dd9fe1b95b
3 changed files with 64 additions and 90 deletions
|
@ -1,3 +1,16 @@
|
|||
2016-08-30 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_emit_epilogue): Do not emit
|
||||
USEs of LR_REGNO in returns and sibcalls.
|
||||
(rs6000_output_mi_thunk): Similar.
|
||||
(rs6000_sibcall_aix): Similar.
|
||||
* config/rs6000/rs6000.md (sibcall, sibcall_value, sibcall_local32,
|
||||
sibcall_local64, sibcall_value_local32, sibcall_value_local64,
|
||||
sibcall_nonlocal_sysv<mode>, sibcall_value_nonlocal_sysv<mode>):
|
||||
Remove the USE of LR_REGNO from the patterns as well. Delete an
|
||||
obsolete comment.
|
||||
(return_internal_<mode>): Delete.
|
||||
|
||||
2016-08-30 Tamar Christina <tamar.christina@arm.com>
|
||||
|
||||
* gcc/config/aarch64/aarch64-simd.md
|
||||
|
|
|
@ -28277,7 +28277,6 @@ rs6000_emit_epilogue (int sibcall)
|
|||
longer necessary. */
|
||||
|
||||
p = rtvec_alloc (9
|
||||
+ 1
|
||||
+ 32 - info->first_gp_reg_save
|
||||
+ LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
|
||||
+ 63 + 1 - info->first_fp_reg_save);
|
||||
|
@ -28288,9 +28287,6 @@ rs6000_emit_epilogue (int sibcall)
|
|||
|
||||
j = 0;
|
||||
RTVEC_ELT (p, j++) = ret_rtx;
|
||||
RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
|
||||
gen_rtx_REG (Pmode,
|
||||
LR_REGNO));
|
||||
RTVEC_ELT (p, j++)
|
||||
= gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname));
|
||||
/* The instruction pattern requires a clobber here;
|
||||
|
@ -29013,73 +29009,63 @@ rs6000_emit_epilogue (int sibcall)
|
|||
emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
|
||||
}
|
||||
|
||||
if (!sibcall)
|
||||
if (!sibcall && restoring_FPRs_inline)
|
||||
{
|
||||
if (cfa_restores)
|
||||
{
|
||||
/* We can't hang the cfa_restores off a simple return,
|
||||
since the shrink-wrap code sometimes uses an existing
|
||||
return. This means there might be a path from
|
||||
pre-prologue code to this return, and dwarf2cfi code
|
||||
wants the eh_frame unwinder state to be the same on
|
||||
all paths to any point. So we need to emit the
|
||||
cfa_restores before the return. For -m64 we really
|
||||
don't need epilogue cfa_restores at all, except for
|
||||
this irritating dwarf2cfi with shrink-wrap
|
||||
requirement; The stack red-zone means eh_frame info
|
||||
from the prologue telling the unwinder to restore
|
||||
from the stack is perfectly good right to the end of
|
||||
the function. */
|
||||
emit_insn (gen_blockage ());
|
||||
emit_cfa_restores (cfa_restores);
|
||||
cfa_restores = NULL_RTX;
|
||||
}
|
||||
|
||||
emit_jump_insn (targetm.gen_simple_return ());
|
||||
}
|
||||
|
||||
if (!sibcall && !restoring_FPRs_inline)
|
||||
{
|
||||
rtvec p;
|
||||
bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
|
||||
if (! restoring_FPRs_inline)
|
||||
{
|
||||
p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
|
||||
RTVEC_ELT (p, 0) = ret_rtx;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cfa_restores)
|
||||
{
|
||||
/* We can't hang the cfa_restores off a simple return,
|
||||
since the shrink-wrap code sometimes uses an existing
|
||||
return. This means there might be a path from
|
||||
pre-prologue code to this return, and dwarf2cfi code
|
||||
wants the eh_frame unwinder state to be the same on
|
||||
all paths to any point. So we need to emit the
|
||||
cfa_restores before the return. For -m64 we really
|
||||
don't need epilogue cfa_restores at all, except for
|
||||
this irritating dwarf2cfi with shrink-wrap
|
||||
requirement; The stack red-zone means eh_frame info
|
||||
from the prologue telling the unwinder to restore
|
||||
from the stack is perfectly good right to the end of
|
||||
the function. */
|
||||
emit_insn (gen_blockage ());
|
||||
emit_cfa_restores (cfa_restores);
|
||||
cfa_restores = NULL_RTX;
|
||||
}
|
||||
p = rtvec_alloc (2);
|
||||
RTVEC_ELT (p, 0) = simple_return_rtx;
|
||||
}
|
||||
rtvec p = rtvec_alloc (3 + !!lr + 64 - info->first_fp_reg_save);
|
||||
int elt = 0;
|
||||
RTVEC_ELT (p, elt++) = ret_rtx;
|
||||
if (lr)
|
||||
RTVEC_ELT (p, elt++)
|
||||
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
|
||||
|
||||
RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
|
||||
? gen_rtx_USE (VOIDmode,
|
||||
gen_rtx_REG (Pmode, LR_REGNO))
|
||||
: gen_rtx_CLOBBER (VOIDmode,
|
||||
gen_rtx_REG (Pmode, LR_REGNO)));
|
||||
|
||||
/* If we have to restore more than two FP registers, branch to the
|
||||
/* We have to restore more than two FP registers, so branch to the
|
||||
restore function. It will return to our caller. */
|
||||
if (! restoring_FPRs_inline)
|
||||
int i;
|
||||
int reg;
|
||||
rtx sym;
|
||||
|
||||
if (flag_shrink_wrap)
|
||||
cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
|
||||
|
||||
sym = rs6000_savres_routine_sym (info, SAVRES_FPR | (lr ? SAVRES_LR : 0));
|
||||
RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, sym);
|
||||
reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
|
||||
RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
|
||||
|
||||
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
|
||||
{
|
||||
int i;
|
||||
int reg;
|
||||
rtx sym;
|
||||
rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
|
||||
|
||||
RTVEC_ELT (p, elt++)
|
||||
= gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
|
||||
if (flag_shrink_wrap)
|
||||
cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
|
||||
|
||||
sym = rs6000_savres_routine_sym (info,
|
||||
SAVRES_FPR | (lr ? SAVRES_LR : 0));
|
||||
RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
|
||||
reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
|
||||
RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
|
||||
|
||||
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
|
||||
{
|
||||
rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
|
||||
|
||||
RTVEC_ELT (p, i + 4)
|
||||
= gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
|
||||
if (flag_shrink_wrap)
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
|
||||
cfa_restores);
|
||||
}
|
||||
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
|
||||
}
|
||||
|
||||
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
|
@ -29667,13 +29653,10 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
|
|||
generate sibcall RTL explicitly. */
|
||||
insn = emit_call_insn (
|
||||
gen_rtx_PARALLEL (VOIDmode,
|
||||
gen_rtvec (4,
|
||||
gen_rtvec (3,
|
||||
gen_rtx_CALL (VOIDmode,
|
||||
funexp, const0_rtx),
|
||||
gen_rtx_USE (VOIDmode, const0_rtx),
|
||||
gen_rtx_USE (VOIDmode,
|
||||
gen_rtx_REG (SImode,
|
||||
LR_REGNO)),
|
||||
simple_return_rtx)));
|
||||
SIBLING_CALL_P (insn) = 1;
|
||||
emit_barrier ();
|
||||
|
@ -37578,9 +37561,6 @@ rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
|
|||
|
||||
/* Note use of the TOC register. */
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
|
||||
/* We need to also mark a use of the link register since the function we
|
||||
sibling-call to will use it to return to our caller. */
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, LR_REGNO));
|
||||
}
|
||||
|
||||
/* Return whether we need to always update the saved TOC pointer when we update
|
||||
|
|
|
@ -10523,7 +10523,6 @@
|
|||
[(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
|
||||
(match_operand 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)])]
|
||||
""
|
||||
"
|
||||
|
@ -10550,7 +10549,6 @@
|
|||
(call (mem:SI (match_operand 1 "address_operand" ""))
|
||||
(match_operand 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)])]
|
||||
""
|
||||
"
|
||||
|
@ -10572,15 +10570,10 @@
|
|||
}
|
||||
}")
|
||||
|
||||
;; this and similar patterns must be marked as using LR, otherwise
|
||||
;; dataflow will try to delete the store into it. This is true
|
||||
;; even when the actual reg to jump to is in CTR, when LR was
|
||||
;; saved and restored around the PIC-setting BCL.
|
||||
(define_insn "*sibcall_local32"
|
||||
[(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"(INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"*
|
||||
|
@ -10600,7 +10593,6 @@
|
|||
[(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"*
|
||||
|
@ -10621,7 +10613,6 @@
|
|||
(call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"(INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"*
|
||||
|
@ -10642,7 +10633,6 @@
|
|||
(call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"*
|
||||
|
@ -10662,7 +10652,6 @@
|
|||
[(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c"))
|
||||
(match_operand 1 "" ""))
|
||||
(use (match_operand 2 "immediate_operand" "O,n,O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"(DEFAULT_ABI == ABI_DARWIN
|
||||
|| DEFAULT_ABI == ABI_V4)
|
||||
|
@ -10693,7 +10682,6 @@
|
|||
(call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c"))
|
||||
(match_operand 2 "" "")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"(DEFAULT_ABI == ABI_DARWIN
|
||||
|| DEFAULT_ABI == ABI_V4)
|
||||
|
@ -12612,13 +12600,6 @@
|
|||
(set_attr "indexed" "yes")
|
||||
(set_attr "cell_micro" "always")])
|
||||
|
||||
(define_insn "*return_internal_<mode>"
|
||||
[(simple_return)
|
||||
(use (match_operand:P 0 "register_operand" "lc"))]
|
||||
""
|
||||
"b%T0"
|
||||
[(set_attr "type" "jmpreg")])
|
||||
|
||||
; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
|
||||
; stuff was in GCC. Oh, and "any_parallel_operand" is a bit flexible...
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue