[v3,01/14] MIPS: Hazard barrier return support
Commit Message
From: Chao-ying Fu <cfu@wavecomp.com>
Add support for generating hazard barrier returns in function
epilogues. Disable inlining and sibling calls for affected functions,
and report an error when the selected architecture does not support
them.
gcc/ChangeLog:
* 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/ChangeLog:
* gcc.target/mips/hazard-barrier-return-attribute.c:
Modified test.
* gcc.target/mips/clear-cache-1.c: Accept jrc for clear cache
intrinsic.
Cherry-picked 42eb0571165dbb5ae518808ba7123b0b9db09a11,
and e8186b2f4b5e843a83775a10f923916c4c9253a5
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>
Signed-off-by: Eldar Osmanovic <eldar.osmanovic@htecgroup.com>
---
gcc/config/mips/mips.cc | 60 +++++++++++++++++--
.../mips/hazard-barrier-return-attribute.c | 2 +-
2 files changed, 57 insertions(+), 5 deletions(-)
@@ -1404,6 +1404,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. */
@@ -1589,6 +1599,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
@@ -8375,6 +8400,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;
}
@@ -11475,6 +11505,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 ();
@@ -13164,7 +13206,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. */
@@ -13205,6 +13248,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;
@@ -13263,6 +13311,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;
@@ -23565,10 +23618,9 @@ mips_print_patchable_function_entry (FILE *file ATTRIBUTE_UNUSED,
#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)" } } */