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]

Re: [Patch] 1/3 Add new builtin __builtin_flush_icache().


Mark Mitchell wrote:
David Daney wrote:

If it is deemed to be useless, I will remove
__builtin_clear_cache_inline_p() from the patch as it is unneeded for my
current target of interest (MIPS).

Since you don't need it yet, I would suggest leaving it out for now. The ARM and 68K ports are using OS syscalls to clear the cache, which is ISA-independent, so they don't need the inline_p test either.

I understand what you were trying to accomplish, and we may well end up
needing it, but let's not do it until we do. If we do need it, we may
want it as a predefined macro, not as a builtin, so that it can be used
in preprocessor tests. (I believe we've done that with other builtins.)
Here is a new version of the patch. Taking Mark's suggestion to remove __builtin_clear_cache_inline_p() simplifies things somewhat.

My new implementation has three cases for __builtin___clear_cache():

1) No "clear_cache" insn is supplied but the target does supply a definition for CLEAR_INSN_CACHE. In this case (arm, m68k IIRC) the new builtin will expand to a call to the existing __clear_cache in libgcc.

2) A "clear_cache" insn is supplied. For this case, the builtin expands to said insn. The mips portion of the patch currently has the only implemtation of "clear_cache".

3) Neither "clear_cache" or CLEAR_INSN_CACHE is defined. This case covers most GCC targets including but not limited to i386 and x86_64. In this case the builtin expands to nothing, so it is a nop.

As additional targets add support for __builtin___clear_cache(), there are several options:

* Do everything in libgcc via a definition of CLEAR_INSN_CACHE. If this is done, backwards compatibility will have to be maintained in all future versions of libgcc.

* Do everything in a clear_cache insn. In this case there are no backwards compatibility issues in libgcc. This is what we chose to do in the MIPS portion of the patch.

* Some sort of hybrid of the other two options. Care should be taken to avoid situations where calls to either the builtin or the library function would recursively call each other.

Bootstrapped and regression tested on: x86_64-unknown-linux-gnu all default languages.
i686-unknown-linux-gnu to mipsel-linux (--with-arch=mips32 and --with-arch-mips32r2) cross tested with no regressions.


OK to commit?

:ADDPATCH middle-end:

2007-07-08 David Daney <ddaney@avtrex.com>

   * builtins.def (BUILT_IN_CLEAR_CACHE): New builtin.
   * builtins.c (expand_builtin___clear_cache): New function.
   (expand_builtin): Call expand_builtin___clear_cache for
   BUILT_IN_CLEAR_CACHE case.
   * doc/extend.texi (__builtin___clear_cache): Document new builtin.
   * testsuite/gcc.dg/builtins-64.c: New test.

Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def	(revision 125997)
+++ gcc/builtins.def	(working copy)
@@ -1,6 +1,6 @@
 /* This file contains the definitions and documentation for the
    builtins used in the GNU compiler.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -609,6 +609,7 @@ DEF_GCC_BUILTIN        (BUILT_IN_APPLY_A
 DEF_GCC_BUILTIN        (BUILT_IN_ARGS_INFO, "args_info", BT_FN_INT_INT, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LIST)
 DEF_LIB_BUILTIN        (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 125997)
+++ gcc/builtins.c	(working copy)
@@ -5513,6 +5513,58 @@ expand_builtin_profile_func (bool exitp)
   return const0_rtx;
 }
 
+/* Expand a call to __builtin___clear_cache.  */
+
+static rtx
+expand_builtin___clear_cache (tree exp ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_clear_cache
+#ifdef CLEAR_INSN_CACHE
+  /* There is no "clear_cache" insn, and __clear_cache() in libgcc
+     does something.  Just do the default expansion to a call to __clear_cache().  */
+  return NULL_RTX;
+#else
+  /* There is no "clear_cache" insn, and __clear_cache() in libgcc
+     does nothing.  There is no need to call it.  Do nothing.  */
+  return const0_rtx;
+#endif /* CLEAR_INSN_CACHE */
+#else
+  /*  We have a "clear_cache" insn, and it will handle everything.  */
+  tree begin, end;
+  rtx begin_rtx, end_rtx;
+  enum insn_code icode;
+
+  /* We must not expand to a library call.  If we did, any
+     fallback library function in libgcc that might contain a call to
+     __builtin___clear_cache() would recurse infinitely.  */
+  if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+    {
+      error ("both arguments to %<__builtin___clear_cache%> must be pointers");
+      return const0_rtx;
+    }
+
+  if (HAVE_clear_cache)
+    {
+      icode = CODE_FOR_clear_cache;
+
+      begin = CALL_EXPR_ARG (exp, 0);
+      begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL);
+      begin_rtx = convert_memory_address (Pmode, begin_rtx);
+      if (!insn_data[icode].operand[0].predicate (begin_rtx, Pmode))
+	begin_rtx = copy_to_mode_reg (Pmode, begin_rtx);
+
+      end = CALL_EXPR_ARG (exp, 1);
+      end_rtx = expand_expr (end, NULL_RTX, Pmode, EXPAND_NORMAL);
+      end_rtx = convert_memory_address (Pmode, end_rtx);
+      if (!insn_data[icode].operand[1].predicate (end_rtx, Pmode))
+	end_rtx = copy_to_mode_reg (Pmode, end_rtx);
+
+      emit_insn (gen_clear_cache (begin_rtx, end_rtx));
+    }
+  return const0_rtx;
+#endif /* HAVE_clear_cache */
+}
+
 /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
 
 static rtx
@@ -6181,6 +6233,12 @@ expand_builtin (tree exp, rtx target, rt
 	return const0_rtx;
       return expand_builtin_next_arg ();
 
+    case BUILT_IN_CLEAR_CACHE:
+      target = expand_builtin___clear_cache (exp);
+      if (target)
+        return target;
+      break;
+
     case BUILT_IN_CLASSIFY_TYPE:
       return expand_builtin_classify_type (exp);
 
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 125997)
+++ gcc/doc/extend.texi	(working copy)
@@ -6086,6 +6086,18 @@ if (__builtin_expect (ptr != NULL, 1))
 when testing pointer or floating-point values.
 @end deftypefn
 
+@deftypefn {Built-in Function} void __builtin___clear_cache (char *@var{begin}, char *@var{end})
+This functions is used to flush the processor's instruction cache for
+the region of memory between @var{begin} and @var{end}.  Some
+targets require that the instruction cache be flushed, after modifying
+memory containing code, in order to obtain deterministic behavior.
+
+If the target does not require instruction cache flushes,
+@code{__builtin___clear_cache} has no effect.  Otherwise either
+instructions are emitted in-line to clear the instruction cache or a
+call to the @code{__clear_cache} function in libgcc is made.
+@end deftypefn
+
 @deftypefn {Built-in Function} void __builtin_prefetch (const void *@var{addr}, ...)
 This function is used to minimize cache-miss latency by moving data into
 a cache before it is accessed.
Index: gcc/testsuite/gcc.dg/builtins-64.c
===================================================================
--- gcc/testsuite/gcc.dg/builtins-64.c	(revision 0)
+++ gcc/testsuite/gcc.dg/builtins-64.c	(revision 0)
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+int main ()
+{
+  char *mem = __builtin_alloca (40);
+  __builtin___clear_cache (mem, mem + 40);
+  return 0;
+}

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