File riscv-builtin-eh-return.patch of Package gcc8.8625
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.
Index: gcc-8.0.1+r259636/gcc/config/riscv/riscv-protos.h
===================================================================
--- gcc-8.0.1+r259636.orig/gcc/config/riscv/riscv-protos.h
+++ gcc-8.0.1+r259636/gcc/config/riscv/riscv-protos.h
@@ -66,7 +66,7 @@ extern bool riscv_expand_block_move (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_can_use_return_insn (void);
extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode);
extern bool riscv_expand_block_move (rtx, rtx, rtx);
Index: gcc-8.0.1+r259636/gcc/config/riscv/riscv.c
===================================================================
--- gcc-8.0.1+r259636.orig/gcc/config/riscv/riscv.c
+++ gcc-8.0.1+r259636/gcc/config/riscv/riscv.c
@@ -3433,23 +3433,45 @@ riscv_save_restore_reg (machine_mode mod
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;
@@ -3630,7 +3652,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. */
@@ -3692,11 +3714,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
@@ -3707,7 +3729,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;
@@ -3717,14 +3740,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;
@@ -3799,7 +3822,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)
{
@@ -3838,11 +3862,11 @@ 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));
- if (!sibcall_p)
+ if (style != SIBCALL_RETURN)
emit_jump_insn (gen_simple_return_internal (ra));
}
Index: gcc-8.0.1+r259636/gcc/config/riscv/riscv.md
===================================================================
--- gcc-8.0.1+r259636.orig/gcc/config/riscv/riscv.md
+++ gcc-8.0.1+r259636/gcc/config/riscv/riscv.md
@@ -69,6 +69,10 @@
(S0_REGNUM 8)
(S1_REGNUM 9)
(S2_REGNUM 18)
+
+ (NORMAL_RETURN 0)
+ (SIBCALL_RETURN 1)
+ (EXCEPTION_RETURN 2)
])
(include "predicates.md")
@@ -2032,7 +2036,7 @@
[(const_int 2)]
""
{
- riscv_expand_epilogue (false);
+ riscv_expand_epilogue (NORMAL_RETURN);
DONE;
})
@@ -2040,7 +2044,7 @@
[(const_int 2)]
""
{
- riscv_expand_epilogue (true);
+ riscv_expand_epilogue (SIBCALL_RETURN);
DONE;
})
@@ -2082,6 +2086,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;
})
@@ -2110,6 +2117,14 @@
DONE;
})
+(define_insn_and_split "eh_return_internal"
+ [(eh_return)]
+ ""
+ "#"
+ "epilogue_completed"
+ [(const_int 0)]
+ "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
+
;;
;; ....................
;;