From fd1e52dc252b33f918891458774f784e96fdf47e Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Mon, 4 Jun 2018 23:44:43 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 18 ++++++++++++ gcc/config/riscv/riscv-protos.h | 2 +- gcc/config/riscv/riscv.c | 52 ++++++++++++++++++++++++--------- gcc/config/riscv/riscv.md | 19 ++++++++++-- 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 074e1492afc..ebf9dc43ee6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2018-06-04 Jim Wilson + + * 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 * gimple-ssa-store-merging.c (struct merged_store_group): Move up diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index a194b192a2b..f158ed007dd 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -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); diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index 6e389fa0102..c418dc1ec2e 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -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)); } diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index fa681971c4c..b9faf00d076 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -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;") + ;; ;; .................... ;; -- 2.30.2