From: Chao-ying Fu <cfu@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.godbole@imgtec.com>
Signed-off-by: Matthew Fortune <matthew.fortune@imgtec.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Chao-ying Fu <cfu@mips.com>
Signed-off-by: Aleksandar Rakic <aleksandar.rakic@htecgroup.com>
---
gcc/config/mips/mips.cc | 60 +++++++++++++++++--
.../mips/hazard-barrier-return-attribute.c | 2 +-
2 files changed, 57 insertions(+), 5 deletions(-)
@@ -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
@@ -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)" } } */