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:
Jim Wilson 2018-06-04 23:44:43 +00:00 committed by Jim Wilson
parent 7f5a398246
commit fd1e52dc25
4 changed files with 74 additions and 17 deletions

View File

@ -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

View File

@ -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);

View File

@ -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));
}

View File

@ -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;")
;;
;; ....................
;;