Commit fd1e52dc by Jim Wilson Committed by Jim Wilson

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
parent 7f5a3982
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> 2018-06-04 Eric Botcazou <ebotcazou@adacore.com>
* gimple-ssa-store-merging.c (struct merged_store_group): Move up * gimple-ssa-store-merging.c (struct merged_store_group): Move up
......
...@@ -66,7 +66,7 @@ extern bool riscv_expand_block_move (rtx, rtx, rtx); ...@@ -66,7 +66,7 @@ extern bool riscv_expand_block_move (rtx, rtx, rtx);
extern rtx riscv_return_addr (int, rtx); extern rtx riscv_return_addr (int, rtx);
extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int); extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int);
extern void riscv_expand_prologue (void); 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_epilogue_uses (unsigned int);
extern bool riscv_can_use_return_insn (void); extern bool riscv_can_use_return_insn (void);
extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode); 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, ...@@ -3502,23 +3502,45 @@ riscv_save_restore_reg (machine_mode mode, int regno,
of the frame. */ of the frame. */
static void 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; HOST_WIDE_INT offset;
/* Save the link register and s-registers. */ /* Save the link register and s-registers. */
offset = cfun->machine->frame.gp_sp_offset - sp_offset; 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)) 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; offset -= UNITS_PER_WORD;
} }
/* This loop must iterate over the same space as its companion in /* This loop must iterate over the same space as its companion in
riscv_compute_frame_info. */ riscv_compute_frame_info. */
offset = cfun->machine->frame.fp_sp_offset - sp_offset; 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)) if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
{ {
machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
...@@ -3694,7 +3716,7 @@ riscv_expand_prologue (void) ...@@ -3694,7 +3716,7 @@ riscv_expand_prologue (void)
GEN_INT (-step1)); GEN_INT (-step1));
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
size -= step1; 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. */ frame->mask = mask; /* Undo the above fib. */
...@@ -3756,11 +3778,11 @@ riscv_adjust_libcall_cfi_epilogue () ...@@ -3756,11 +3778,11 @@ riscv_adjust_libcall_cfi_epilogue ()
return dwarf; return dwarf;
} }
/* Expand an "epilogue" or "sibcall_epilogue" pattern; SIBCALL_P /* Expand an "epilogue", "sibcall_epilogue", or "eh_return_internal" pattern;
says which. */ style says which. */
void 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 /* Split the frame into two. STEP1 is the amount of stack we should
deallocate before restoring the registers. STEP2 is the amount we deallocate before restoring the registers. STEP2 is the amount we
...@@ -3771,7 +3793,8 @@ riscv_expand_epilogue (bool sibcall_p) ...@@ -3771,7 +3793,8 @@ riscv_expand_epilogue (bool sibcall_p)
unsigned mask = frame->mask; unsigned mask = frame->mask;
HOST_WIDE_INT step1 = frame->total_size; HOST_WIDE_INT step1 = frame->total_size;
HOST_WIDE_INT step2 = 0; 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 ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
rtx insn; rtx insn;
...@@ -3781,14 +3804,14 @@ riscv_expand_epilogue (bool sibcall_p) ...@@ -3781,14 +3804,14 @@ riscv_expand_epilogue (bool sibcall_p)
if (cfun->machine->naked_p) if (cfun->machine->naked_p)
{ {
gcc_assert (!sibcall_p); gcc_assert (style == NORMAL_RETURN);
emit_jump_insn (gen_return ()); emit_jump_insn (gen_return ());
return; return;
} }
if (!sibcall_p && riscv_can_use_return_insn ()) if ((style == NORMAL_RETURN) && riscv_can_use_return_insn ())
{ {
emit_jump_insn (gen_return ()); emit_jump_insn (gen_return ());
return; return;
...@@ -3863,7 +3886,8 @@ riscv_expand_epilogue (bool sibcall_p) ...@@ -3863,7 +3886,8 @@ riscv_expand_epilogue (bool sibcall_p)
frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ frame->mask = 0; /* Temporarily fib that we need not save GPRs. */
/* Restore the registers. */ /* 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) if (use_restore_libcall)
{ {
...@@ -3902,14 +3926,14 @@ riscv_expand_epilogue (bool sibcall_p) ...@@ -3902,14 +3926,14 @@ riscv_expand_epilogue (bool sibcall_p)
} }
/* Add in the __builtin_eh_return stack adjustment. */ /* 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, emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
EH_RETURN_STACKADJ_RTX)); EH_RETURN_STACKADJ_RTX));
/* Return from interrupt. */ /* Return from interrupt. */
if (cfun->machine->interrupt_handler_p) if (cfun->machine->interrupt_handler_p)
emit_insn (gen_riscv_mret ()); emit_insn (gen_riscv_mret ());
else if (!sibcall_p) else if (style != SIBCALL_RETURN)
emit_jump_insn (gen_simple_return_internal (ra)); emit_jump_insn (gen_simple_return_internal (ra));
} }
......
...@@ -73,6 +73,10 @@ ...@@ -73,6 +73,10 @@
(S0_REGNUM 8) (S0_REGNUM 8)
(S1_REGNUM 9) (S1_REGNUM 9)
(S2_REGNUM 18) (S2_REGNUM 18)
(NORMAL_RETURN 0)
(SIBCALL_RETURN 1)
(EXCEPTION_RETURN 2)
]) ])
(include "predicates.md") (include "predicates.md")
...@@ -2036,7 +2040,7 @@ ...@@ -2036,7 +2040,7 @@
[(const_int 2)] [(const_int 2)]
"" ""
{ {
riscv_expand_epilogue (false); riscv_expand_epilogue (NORMAL_RETURN);
DONE; DONE;
}) })
...@@ -2044,7 +2048,7 @@ ...@@ -2044,7 +2048,7 @@
[(const_int 2)] [(const_int 2)]
"" ""
{ {
riscv_expand_epilogue (true); riscv_expand_epilogue (SIBCALL_RETURN);
DONE; DONE;
}) })
...@@ -2086,6 +2090,9 @@ ...@@ -2086,6 +2090,9 @@
emit_insn (gen_eh_set_lr_di (operands[0])); emit_insn (gen_eh_set_lr_di (operands[0]));
else else
emit_insn (gen_eh_set_lr_si (operands[0])); emit_insn (gen_eh_set_lr_si (operands[0]));
emit_jump_insn (gen_eh_return_internal ());
emit_barrier ();
DONE; DONE;
}) })
...@@ -2114,6 +2121,14 @@ ...@@ -2114,6 +2121,14 @@
DONE; DONE;
}) })
(define_insn_and_split "eh_return_internal"
[(eh_return)]
""
"#"
"epilogue_completed"
[(const_int 0)]
"riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
;; ;;
;; .................... ;; ....................
;; ;;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment