This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] 2/3 MIPS support for builtin __builtin_flush_icache().


This is the second part of the __builtin_flush_icache patch.  It adds
support for MIPS.

flush_icache is expanded to either a library call or an in-line cache
flushing sequence if the ISA supports it.

It it is expanded in-line it is done by two insns (synci_loop and
clear_hazard).  A possible follow on optimization would be to fold the
clear_hazard into the next jump instruction that follows the synci_loop.

I also changed INITIALIZE_TRAMPOLINE to emit flush_icache instead of
the library call it used previously.

Bootstrapped and tested on x86_64-unknown-linux-gnu all default
languages with no regressions.

Also tested on:
x86_64 cross to mipsel-linux --with-arch=mips32
i686   cross to mipsel-linux --with-arch=mips32r2

with no regressions.

OK to commit?

2007-06-30 David Daney <ddaney@avtrex.com>

   * config/mips/mips.h (ISA_HAS_SYNCI): New target capability
   predicate.
   (INITIALIZE_TRAMPOLINE): Emit flush_icache instead library call.
   * config/mips/mips.md (UNSPEC_SYNCI_LOOP): New constant
   (UNSPEC_CLEAR_HAZARD): New constant.
   (flush_icache): New expand.
   (synci_loop): New insn.
   (clear_hazard): New insn.
   * testsuite/gcc.target/mips/flush-icache-2.c: New test.
   * testsuite/gcc.target/mips/flush-icache-1.c: New test.
   * testsuite/gcc.target/mips/flush-icache-3.c: New test.

Index: config/mips/mips.h
===================================================================
--- config/mips/mips.h	(revision 125997)
+++ config/mips/mips.h	(working copy)
@@ -770,6 +770,10 @@ extern const struct mips_rtx_cost_data *
 				 || ISA_MIPS32R2			\
 				 || ISA_MIPS64				\
 				 || TARGET_MIPS5500)
+
+/* ISA includes synci, jr.hb and jalr.hb */
+#define ISA_HAS_SYNCI ISA_MIPS32R2
+
 
 /* Add -G xx support.  */
 
@@ -2122,15 +2126,7 @@ typedef struct mips_args {
   chain_addr = plus_constant (func_addr, GET_MODE_SIZE (ptr_mode));	    \
   emit_move_insn (gen_rtx_MEM (ptr_mode, func_addr), FUNC);		    \
   emit_move_insn (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN);		    \
-									    \
-  /* Flush both caches.  We need to flush the data cache in case	    \
-     the system has a write-back cache.  */				    \
-  /* ??? Should check the return value for errors.  */			    \
-  if (mips_cache_flush_func && mips_cache_flush_func[0])		    \
-    emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func),   \
-		       0, VOIDmode, 3, ADDR, Pmode,			    \
-		       GEN_INT (TRAMPOLINE_SIZE), TYPE_MODE (integer_type_node),\
-		       GEN_INT (3), TYPE_MODE (integer_type_node));	    \
+  emit_insn (gen_flush_icache (copy_rtx (ADDR), GEN_INT (TRAMPOLINE_SIZE))); \
 }
 
 /* Addressing modes, and classification of registers for them.  */
Index: config/mips/mips.md
===================================================================
--- config/mips/mips.md	(revision 125997)
+++ config/mips/mips.md	(working copy)
@@ -50,6 +50,8 @@ (define_constants
    (UNSPEC_TLS_GET_TP		28)
    (UNSPEC_MFHC1		31)
    (UNSPEC_MTHC1		32)
+   (UNSPEC_SYNCI_LOOP		33)
+   (UNSPEC_CLEAR_HAZARD		34)
 
    (UNSPEC_ADDRESS_FIRST	100)
 
@@ -4171,6 +4173,72 @@ (define_insn "cprestore"
 }
   [(set_attr "type" "store")
    (set_attr "length" "4,12")])
+
+(define_expand "flush_icache"
+  [(match_operand:SI 0 "general_operand" "r")
+   (match_operand:SI 1 "general_operand" "r")]
+  ""
+  "
+{
+  if (ISA_HAS_SYNCI)
+    {
+      emit_insn (gen_synci_loop (copy_rtx (operands[0]),
+                                           copy_rtx (operands[1])));
+      emit_insn (gen_clear_hazard ());
+    }
+  else
+    /* Flush both caches.  We need to flush the data cache in case
+       the system has a write-back cache.  */
+    /* ??? Should check the return value for errors.  */
+    if (mips_cache_flush_func && mips_cache_flush_func[0])
+      emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func),
+                         0, VOIDmode, 3, copy_rtx (operands[0]), Pmode,
+                         copy_rtx (operands[1]), TYPE_MODE (integer_type_node),
+                         GEN_INT (3), TYPE_MODE (integer_type_node));
+  DONE;
+}")
+
+(define_insn "synci_loop"
+  [(unspec_volatile[(match_operand:SI 0 "general_operand" "r")
+                    (match_operand:SI 1 "general_operand" "r")
+                    (clobber (match_scratch:SI 2 "=0"))
+                    (clobber (match_scratch:SI 3 "=1"))
+                    (clobber (match_scratch:SI 4 "=r"))
+		    (clobber (match_scratch:SI 5 "=r"))]
+                    UNSPEC_SYNCI_LOOP)]
+  "ISA_HAS_SYNCI"
+{
+  return ".set\tpush\n"
+         "\t.set\tnoreorder\n"
+         "\t.set\tnomacro\n"
+         "\taddu\t%3,%0,%1\n"
+         "\trdhwr\t%4,$1\n"
+         "1:\tsynci\t0(%2)\n"
+         "\tsltu\t%5,%2,%3\n"
+         "\tbne\t%5,$0,1b\n"
+         "\taddu\t%2,%2,%4\n"
+         "\tsync\n"
+         "\t.set\tpop";
+ }
+  [(set_attr "length" "28")])
+
+(define_insn "clear_hazard"
+  [(unspec_volatile [(clobber (match_scratch:SI 0 "=r"))] UNSPEC_CLEAR_HAZARD)
+   (clobber (reg:SI 31))]
+  "ISA_HAS_SYNCI"
+{
+  return ".set\tpush\n"
+         "\t.set\tnoreorder\n"
+         "\t.set\tnomacro\n"
+         "\tbal\t1f\n"
+         "\tnop\n"
+         "1:\taddiu\t%0,$31,12\n"
+         "\tjr.hb\t%0\n"
+         "\tnop\n"
+         "\t.set\tpop";
+}
+  [(set_attr "length" "20")])
+
 
 ;; Block moves, see mips.c for more details.
 ;; Argument 0 is the destination
Index: testsuite/gcc.target/mips/flush-icache-2.c
===================================================================
--- testsuite/gcc.target/mips/flush-icache-2.c	(revision 0)
+++ testsuite/gcc.target/mips/flush-icache-2.c	(revision 0)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32" } */
+/* { dg-final { scan-assembler-not "synci" } } */
+/* { dg-final { scan-assembler-not "jr.hb" } } */
+/* { dg-final { scan-assembler "_flush_cache" } } */
+
+void f()
+{
+  int size = 40;
+  char *memory = __builtin_alloca(size);
+  __builtin_flush_icache(memory, size);
+}
+
Index: testsuite/gcc.target/mips/flush-icache-1.c
===================================================================
--- testsuite/gcc.target/mips/flush-icache-1.c	(revision 0)
+++ testsuite/gcc.target/mips/flush-icache-1.c	(revision 0)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32r2" } */
+/* { dg-final { scan-assembler "synci" } } */
+/* { dg-final { scan-assembler "jr.hb" } } */
+/* { dg-final { scan-assembler-not "_flush_cache" } } */
+
+void f()
+{
+  int size = 40;
+  char *memory = __builtin_alloca(size);
+  __builtin_flush_icache(memory, size);
+}
+
Index: testsuite/gcc.target/mips/flush-icache-3.c
===================================================================
--- testsuite/gcc.target/mips/flush-icache-3.c	(revision 0)
+++ testsuite/gcc.target/mips/flush-icache-3.c	(revision 0)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32r2" } */
+/* { dg-final { scan-assembler-not "synci" } } */
+/* { dg-final { scan-assembler-not "jr.hb" } } */
+/* { dg-final { scan-assembler-not "_flush_cache" } } */
+
+void f()
+{
+  char *memory = __builtin_alloca(40);
+  __builtin_flush_icache(memory, 0);
+}
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]