From: Chao-ying Fu <c...@wavecomp.com> gcc/ * config/mips/mips.cc (mips_use_hazard_barrier_return_p): New static function. (mips_function_attr_inlinable_p): Likewise. (mips_compute_frame_info): Set use_hazard_barrier_return_p. Emit error for unsupported architecture choice. (mips_function_ok_for_sibcall, mips_can_use_return_insn): Return false for use_hazard_barrier_return. (mips_expand_epilogue): Emit hazard barrier return.
gcc/testsuite/ * gcc.target/mips/hazard-barrier-return-attribute.c: Modified test. Cherry-picked 42eb0571165dbb5ae518808ba7123b0b9db09a11 from https://github.com/MIPS/gcc Signed-off-by: Prachi Godbole <prachi.godb...@imgtec.com> Signed-off-by: Matthew Fortune <matthew.fort...@imgtec.com> Signed-off-by: Faraz Shahbazker <fshahbaz...@wavecomp.com> Signed-off-by: Chao-ying Fu <c...@mips.com> Signed-off-by: Aleksandar Rakic <aleksandar.ra...@htecgroup.com> --- gcc/config/mips/mips.cc | 60 +++++++++++++++++-- .../mips/hazard-barrier-return-attribute.c | 2 +- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 392755316eb..9db2a2a9396 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -1391,6 +1391,16 @@ mips_get_code_readable_attr (tree decl) } +/* Check if the attribute to use hazard barrier return is set for + the function declaration DECL. */ + +static bool +mips_use_hazard_barrier_return_p (const_tree decl) +{ + return lookup_attribute ("use_hazard_barrier_return", + DECL_ATTRIBUTES (decl)) != NULL; +} + /* Return the set of compression modes that are explicitly required by the attributes in ATTRIBUTES. */ @@ -1576,6 +1586,21 @@ mips_can_inline_p (tree caller, tree callee) return default_target_can_inline_p (caller, callee); } +/* Implement TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P. + + A function reqeuesting clearing of all instruction and execution hazards + before returning cannot be inlined - thereby not clearing any hazards. + All our other function attributes are related to how out-of-line copies + should be compiled or called. They don't in themselves prevent inlining. */ + +static bool +mips_function_attr_inlinable_p (const_tree decl) +{ + if (mips_use_hazard_barrier_return_p (decl)) + return false; + return hook_bool_const_tree_true (decl); +} + /* Handle an "interrupt" attribute with an optional argument. */ static tree @@ -8350,6 +8375,11 @@ mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) && !targetm.binds_local_p (decl)) return false; + /* Can't generate sibling calls if returning from current function using + hazard barrier return. */ + if (mips_use_hazard_barrier_return_p (current_function_decl)) + return false; + /* Otherwise OK. */ return true; } @@ -11450,6 +11480,18 @@ mips_compute_frame_info (void) } } + /* Determine whether to use hazard barrier return or not. */ + if (mips_use_hazard_barrier_return_p (current_function_decl)) + { + if (mips_isa_rev < 2) + error ("hazard barrier returns require a MIPS32r2 processor or" + " greater"); + else if (TARGET_MIPS16) + error ("hazard barrier returns are not supported for MIPS16 functions"); + else + cfun->machine->use_hazard_barrier_return_p = true; + } + frame = &cfun->machine->frame; memset (frame, 0, sizeof (*frame)); size = get_frame_size (); @@ -13139,7 +13181,8 @@ mips_expand_epilogue (bool sibcall_p) && !crtl->calls_eh_return && !sibcall_p && step2 > 0 - && mips_unsigned_immediate_p (step2, 5, 2)) + && mips_unsigned_immediate_p (step2, 5, 2) + && !cfun->machine->use_hazard_barrier_return_p) use_jraddiusp_p = true; else /* Deallocate the final bit of the frame. */ @@ -13180,6 +13223,11 @@ mips_expand_epilogue (bool sibcall_p) else emit_jump_insn (gen_mips_eret ()); } + else if (cfun->machine->use_hazard_barrier_return_p) + { + rtx reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); + emit_jump_insn (gen_mips_hb_return_internal (reg)); + } else { rtx pat; @@ -13238,6 +13286,11 @@ mips_can_use_return_insn (void) if (cfun->machine->interrupt_handler_p) return false; + /* Even if the function has a null epilogue, generating hazard barrier return + in epilogue handler is a lot cleaner and more manageable. */ + if (cfun->machine->use_hazard_barrier_return_p) + return false; + if (!reload_completed) return false; @@ -23506,10 +23559,9 @@ mips_bit_clear_p (enum machine_mode mode, unsigned HOST_WIDE_INT m) #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE mips_attribute_table -/* All our function attributes are related to how out-of-line copies should - be compiled or called. They don't in themselves prevent inlining. */ + #undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P -#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_const_tree_true +#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P mips_function_attr_inlinable_p #undef TARGET_EXTRA_LIVE_ON_ENTRY #define TARGET_EXTRA_LIVE_ON_ENTRY mips_extra_live_on_entry diff --git a/gcc/testsuite/gcc.target/mips/hazard-barrier-return-attribute.c b/gcc/testsuite/gcc.target/mips/hazard-barrier-return-attribute.c index 3575af44dcd..c5b1973af36 100644 --- a/gcc/testsuite/gcc.target/mips/hazard-barrier-return-attribute.c +++ b/gcc/testsuite/gcc.target/mips/hazard-barrier-return-attribute.c @@ -17,4 +17,4 @@ foo1 () } /* { dg-final { scan-assembler "foo0:" } } */ -/* { dg-final { scan-assembler-times "\tjr.hb\t\\\$31\n\tnop\\n" 1 } } */ +/* { dg-final { scan-assembler "(\tjr.hb\t\\\$31\n\tnop\\n|\tjrc.hb\t)" } } */ -- 2.34.1