From: Chao-ying Fu <[email protected]>

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 <[email protected]>
Signed-off-by: Matthew Fortune <[email protected]>
Signed-off-by: Faraz Shahbazker <[email protected]>
Signed-off-by: Chao-ying Fu <[email protected]>
Signed-off-by: Aleksandar Rakic <[email protected]>
Signed-off-by: Eldar Osmanovic <[email protected]>
---
 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 80828ed20af..6799057646c 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -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
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.43.0

Reply via email to