[05/61] Hazard barrier return support

Message ID 20250131171232.1018281-7-aleksandar.rakic@htecgroup.com
State New
Headers
Series Improve Mips target |

Commit Message

Aleksandar Rakic Jan. 31, 2025, 5:13 p.m. UTC
  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(-)
  

Patch

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)" } } */