Hazard barrier return support
authorJunxian Zhu <zhujunxian@oss.cipunited.com>
Fri, 17 Feb 2023 08:24:55 +0000 (16:24 +0800)
committerYunQiang Su <yunqiang.su@cipunited.com>
Fri, 24 Feb 2023 03:19:55 +0000 (11:19 +0800)
This patch allows a function to request clearing of all instruction and execution
hazards upon normal return via __attribute__ ((use_hazard_barrier_return)).

2017-04-25  Prachi Godbole  <prachi.godbole@imgtec.com>

gcc/ChangeLog:

* config/mips/mips.h (machine_function): New variable
use_hazard_barrier_return_p.
* config/mips/mips.md (UNSPEC_JRHB): New unspec.
(mips_hb_return_internal): New insn pattern.
* config/mips/mips.cc (mips_attribute_table): Add attribute
use_hazard_barrier_return.
(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.
* doc/extend.texi: Document use_hazard_barrier_return.

gcc/testsuite/ChangeLog:

* gcc.target/mips/hazard-barrier-return-attribute.c: New test.

Signed-off-by: Junxian Zhu <zhujunxian@oss.cipunited.com>
gcc/config/mips/mips.cc
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/doc/extend.texi
gcc/testsuite/gcc.target/mips/hazard-barrier-return-attribute.c [new file with mode: 0644]

index 0b25db4..b066a2c 100644 (file)
@@ -630,6 +630,7 @@ static const struct attribute_spec mips_attribute_table[] = {
     mips_handle_use_shadow_register_set_attr, NULL },
   { "keep_interrupts_masked",  0, 0, false, true,  true, false, NULL, NULL },
   { "use_debug_exception_return", 0, 0, false, true, true, false, NULL, NULL },
+  { "use_hazard_barrier_return", 0, 0, true, false, false, false, NULL, NULL },
   { NULL,         0, 0, false, false, false, false, NULL, NULL }
 };
 \f
index fbb4372..f664d30 100644 (file)
@@ -3386,6 +3386,9 @@ struct GTY(())  machine_function {
 
   /* True if GCC stored callee saved registers in the frame header.  */
   bool use_frame_header_for_callee_saved_regs;
+
+  /* True if the function should generate hazard barrier return.  */
+  bool use_hazard_barrier_return_p;
 };
 #endif
 
index e3bf32a..f881a8b 100644 (file)
 
   ;; The `.insn' pseudo-op.
   UNSPEC_INSN_PSEUDO
+  UNSPEC_JRHB
 ])
 
 (define_constants
   [(set_attr "type"    "jump")
    (set_attr "mode"    "none")])
 
+;; Insn to clear execution and instruction hazards while returning.
+;; However, it doesn't clear hazards created by the insn in its delay slot.
+;; Thus, explicitly place a nop in its delay slot.
+
+(define_insn "mips_hb_return_internal"
+  [(return)
+   (unspec_volatile [(match_operand 0 "pmode_register_operand" "")]
+                   UNSPEC_JRHB)]
+  ""
+  {
+    return "%(jr.hb\t$31%/%)";
+  }
+  [(set_attr "insn_count" "2")])
+
 ;; Normal return.
 
 (define_insn "<optab>_internal"
index 0e11e43..c112291 100644 (file)
@@ -5653,6 +5653,12 @@ On MIPS targets, you can use the @code{nocompression} function attribute
 to locally turn off MIPS16 and microMIPS code generation.  This attribute
 overrides the @option{-mips16} and @option{-mmicromips} options on the
 command line (@pxref{MIPS Options}).
+
+@item use_hazard_barrier_return
+@cindex @code{use_hazard_barrier_return} function attribute, MIPS
+This function attribute instructs the compiler to generate a hazard barrier
+return that clears all execution and instruction hazards while returning,
+instead of generating a normal return instruction.
 @end table
 
 @node MSP430 Function Attributes
diff --git a/gcc/testsuite/gcc.target/mips/hazard-barrier-return-attribute.c b/gcc/testsuite/gcc.target/mips/hazard-barrier-return-attribute.c
new file mode 100644 (file)
index 0000000..3575af4
--- /dev/null
@@ -0,0 +1,20 @@
+/* Test attribute for clearing hazards while returning.  */
+/* { dg-do compile } */
+/* { dg-options "isa_rev>=2 -mno-mips16" } */
+
+extern int bar ();
+
+static int __attribute__ ((use_hazard_barrier_return))
+foo0 ()
+{
+  return bar ();
+}
+
+int
+foo1 ()
+{
+  return foo0 ();
+}
+
+/* { dg-final { scan-assembler "foo0:" } } */
+/* { dg-final { scan-assembler-times "\tjr.hb\t\\\$31\n\tnop\\n" 1 } } */