mirror of git://gcc.gnu.org/git/gcc.git
RISC-V: Don't clobber retval when __builtin_eh_return called.
gcc/ * config/riscv/riscv-protos.h (riscv_expand_epilogue): Change bool arg to int. * config/riscv/riscv.c (riscv_for_each_saved_reg): New args epilogue and maybe_eh_return. Change regno to unsigned int. Use new args to handle EH_RETURN_DATA_REGNO registers properly. (riscv_expand_prologue): Pass new args to riscv_for_each_saved_reg. (riscv_expand_epilogue): Update comment. Change argument name and type. Update code to use new name and type. Pass new args to riscv_for_each_saved_reg. Only use EH_RETURN_STACKADJ_RTX when EXCEPTION_RETURN. * config/riscv/riscv.md (NORMAL_RETURN): New. (SIBCALL_RETURN, EXCEPTION_RETURN): New. (epilogue, sibcall_epilogue): Update riscv_expand_epilogue arg. (eh_return): Call gen_eh_return_internal and emit barrier. (eh_return_internal): Call riscv_expand_epilogue. From-SVN: r261176
This commit is contained in:
parent
7f5a398246
commit
fd1e52dc25
|
|
@ -1,3 +1,21 @@
|
|||
2018-06-04 Jim Wilson <jimw@sifive.com>
|
||||
|
||||
* config/riscv/riscv-protos.h (riscv_expand_epilogue): Change bool arg
|
||||
to int.
|
||||
* config/riscv/riscv.c (riscv_for_each_saved_reg): New args epilogue
|
||||
and maybe_eh_return. Change regno to unsigned int. Use new args to
|
||||
handle EH_RETURN_DATA_REGNO registers properly.
|
||||
(riscv_expand_prologue): Pass new args to riscv_for_each_saved_reg.
|
||||
(riscv_expand_epilogue): Update comment. Change argument name and
|
||||
type. Update code to use new name and type. Pass new args to
|
||||
riscv_for_each_saved_reg. Only use EH_RETURN_STACKADJ_RTX when
|
||||
EXCEPTION_RETURN.
|
||||
* config/riscv/riscv.md (NORMAL_RETURN): New.
|
||||
(SIBCALL_RETURN, EXCEPTION_RETURN): New.
|
||||
(epilogue, sibcall_epilogue): Update riscv_expand_epilogue arg.
|
||||
(eh_return): Call gen_eh_return_internal and emit barrier.
|
||||
(eh_return_internal): Call riscv_expand_epilogue.
|
||||
|
||||
2018-06-04 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gimple-ssa-store-merging.c (struct merged_store_group): Move up
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ extern bool riscv_expand_block_move (rtx, rtx, rtx);
|
|||
extern rtx riscv_return_addr (int, rtx);
|
||||
extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int);
|
||||
extern void riscv_expand_prologue (void);
|
||||
extern void riscv_expand_epilogue (bool);
|
||||
extern void riscv_expand_epilogue (int);
|
||||
extern bool riscv_epilogue_uses (unsigned int);
|
||||
extern bool riscv_can_use_return_insn (void);
|
||||
extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode);
|
||||
|
|
|
|||
|
|
@ -3502,23 +3502,45 @@ riscv_save_restore_reg (machine_mode mode, int regno,
|
|||
of the frame. */
|
||||
|
||||
static void
|
||||
riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn)
|
||||
riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn,
|
||||
bool epilogue, bool maybe_eh_return)
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
|
||||
/* Save the link register and s-registers. */
|
||||
offset = cfun->machine->frame.gp_sp_offset - sp_offset;
|
||||
for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
|
||||
for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
|
||||
if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
|
||||
{
|
||||
riscv_save_restore_reg (word_mode, regno, offset, fn);
|
||||
bool handle_reg = TRUE;
|
||||
|
||||
/* If this is a normal return in a function that calls the eh_return
|
||||
builtin, then do not restore the eh return data registers as that
|
||||
would clobber the return value. But we do still need to save them
|
||||
in the prologue, and restore them for an exception return, so we
|
||||
need special handling here. */
|
||||
if (epilogue && !maybe_eh_return && crtl->calls_eh_return)
|
||||
{
|
||||
unsigned int i, regnum;
|
||||
|
||||
for (i = 0; (regnum = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM;
|
||||
i++)
|
||||
if (regno == regnum)
|
||||
{
|
||||
handle_reg = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle_reg)
|
||||
riscv_save_restore_reg (word_mode, regno, offset, fn);
|
||||
offset -= UNITS_PER_WORD;
|
||||
}
|
||||
|
||||
/* This loop must iterate over the same space as its companion in
|
||||
riscv_compute_frame_info. */
|
||||
offset = cfun->machine->frame.fp_sp_offset - sp_offset;
|
||||
for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
|
||||
for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
|
||||
if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
|
||||
{
|
||||
machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
|
||||
|
|
@ -3694,7 +3716,7 @@ riscv_expand_prologue (void)
|
|||
GEN_INT (-step1));
|
||||
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
|
||||
size -= step1;
|
||||
riscv_for_each_saved_reg (size, riscv_save_reg);
|
||||
riscv_for_each_saved_reg (size, riscv_save_reg, false, false);
|
||||
}
|
||||
|
||||
frame->mask = mask; /* Undo the above fib. */
|
||||
|
|
@ -3756,11 +3778,11 @@ riscv_adjust_libcall_cfi_epilogue ()
|
|||
return dwarf;
|
||||
}
|
||||
|
||||
/* Expand an "epilogue" or "sibcall_epilogue" pattern; SIBCALL_P
|
||||
says which. */
|
||||
/* Expand an "epilogue", "sibcall_epilogue", or "eh_return_internal" pattern;
|
||||
style says which. */
|
||||
|
||||
void
|
||||
riscv_expand_epilogue (bool sibcall_p)
|
||||
riscv_expand_epilogue (int style)
|
||||
{
|
||||
/* Split the frame into two. STEP1 is the amount of stack we should
|
||||
deallocate before restoring the registers. STEP2 is the amount we
|
||||
|
|
@ -3771,7 +3793,8 @@ riscv_expand_epilogue (bool sibcall_p)
|
|||
unsigned mask = frame->mask;
|
||||
HOST_WIDE_INT step1 = frame->total_size;
|
||||
HOST_WIDE_INT step2 = 0;
|
||||
bool use_restore_libcall = !sibcall_p && riscv_use_save_libcall (frame);
|
||||
bool use_restore_libcall = ((style == NORMAL_RETURN)
|
||||
&& riscv_use_save_libcall (frame));
|
||||
rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
|
||||
rtx insn;
|
||||
|
||||
|
|
@ -3781,14 +3804,14 @@ riscv_expand_epilogue (bool sibcall_p)
|
|||
|
||||
if (cfun->machine->naked_p)
|
||||
{
|
||||
gcc_assert (!sibcall_p);
|
||||
gcc_assert (style == NORMAL_RETURN);
|
||||
|
||||
emit_jump_insn (gen_return ());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sibcall_p && riscv_can_use_return_insn ())
|
||||
if ((style == NORMAL_RETURN) && riscv_can_use_return_insn ())
|
||||
{
|
||||
emit_jump_insn (gen_return ());
|
||||
return;
|
||||
|
|
@ -3863,7 +3886,8 @@ riscv_expand_epilogue (bool sibcall_p)
|
|||
frame->mask = 0; /* Temporarily fib that we need not save GPRs. */
|
||||
|
||||
/* Restore the registers. */
|
||||
riscv_for_each_saved_reg (frame->total_size - step2, riscv_restore_reg);
|
||||
riscv_for_each_saved_reg (frame->total_size - step2, riscv_restore_reg,
|
||||
true, style == EXCEPTION_RETURN);
|
||||
|
||||
if (use_restore_libcall)
|
||||
{
|
||||
|
|
@ -3902,14 +3926,14 @@ riscv_expand_epilogue (bool sibcall_p)
|
|||
}
|
||||
|
||||
/* Add in the __builtin_eh_return stack adjustment. */
|
||||
if (crtl->calls_eh_return)
|
||||
if ((style == EXCEPTION_RETURN) && crtl->calls_eh_return)
|
||||
emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
|
||||
EH_RETURN_STACKADJ_RTX));
|
||||
|
||||
/* Return from interrupt. */
|
||||
if (cfun->machine->interrupt_handler_p)
|
||||
emit_insn (gen_riscv_mret ());
|
||||
else if (!sibcall_p)
|
||||
else if (style != SIBCALL_RETURN)
|
||||
emit_jump_insn (gen_simple_return_internal (ra));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@
|
|||
(S0_REGNUM 8)
|
||||
(S1_REGNUM 9)
|
||||
(S2_REGNUM 18)
|
||||
|
||||
(NORMAL_RETURN 0)
|
||||
(SIBCALL_RETURN 1)
|
||||
(EXCEPTION_RETURN 2)
|
||||
])
|
||||
|
||||
(include "predicates.md")
|
||||
|
|
@ -2036,7 +2040,7 @@
|
|||
[(const_int 2)]
|
||||
""
|
||||
{
|
||||
riscv_expand_epilogue (false);
|
||||
riscv_expand_epilogue (NORMAL_RETURN);
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
|
@ -2044,7 +2048,7 @@
|
|||
[(const_int 2)]
|
||||
""
|
||||
{
|
||||
riscv_expand_epilogue (true);
|
||||
riscv_expand_epilogue (SIBCALL_RETURN);
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
|
@ -2086,6 +2090,9 @@
|
|||
emit_insn (gen_eh_set_lr_di (operands[0]));
|
||||
else
|
||||
emit_insn (gen_eh_set_lr_si (operands[0]));
|
||||
|
||||
emit_jump_insn (gen_eh_return_internal ());
|
||||
emit_barrier ();
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
|
@ -2114,6 +2121,14 @@
|
|||
DONE;
|
||||
})
|
||||
|
||||
(define_insn_and_split "eh_return_internal"
|
||||
[(eh_return)]
|
||||
""
|
||||
"#"
|
||||
"epilogue_completed"
|
||||
[(const_int 0)]
|
||||
"riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
|
||||
|
||||
;;
|
||||
;; ....................
|
||||
;;
|
||||
|
|
|
|||
Loading…
Reference in New Issue