diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4f11df7c9d3..e9ee311c356 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2007-07-10 David Daney + + * 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. + * doc/md.texi (clear_cache): Document new instruction pattern. + * testsuite/gcc.dg/builtins-64.c: New test. + 2007-07-11 Hans-Peter Nilsson * config/cris/cris.md ("movsi"): Fix typo in last change. diff --git a/gcc/builtins.c b/gcc/builtins.c index c01d4d0642e..da76f61db32 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5512,6 +5512,59 @@ 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 @@ -6198,6 +6251,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, 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); diff --git a/gcc/builtins.def b/gcc/builtins.def index 7289fa6f9a8..dd06d4b38f6 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -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_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_N 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) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index f6fbbfaebf2..9fa09f4c460 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -6143,6 +6143,19 @@ 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 function is used to flush the processor's instruction cache for +the region of memory between @var{begin} inclusive and @var{end} +exclusive. 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. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index d8f1abb7717..dc45ed8acd1 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -5036,6 +5036,16 @@ weren't equal. If this pattern is not defined, then a plain compare pattern and conditional branch pattern is used. +@cindex @code{clear_cache} instruction pattern +@item @samp{clear_cache} + +This pattern, if defined, flushes the instruction cache for a region of +memory. The region is bounded to by the Pmode pointers in operand 0 +inclusive and operand 1 exclusive. + +If this pattern is not defined, a call to the library function +@code{__clear_cache} is used. + @end table @end ifset diff --git a/gcc/testsuite/gcc.dg/builtins-64.c b/gcc/testsuite/gcc.dg/builtins-64.c new file mode 100644 index 00000000000..6e84633d591 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-64.c @@ -0,0 +1,8 @@ +/* { dg-do run } */ + +int main () +{ + char *mem = __builtin_alloca (40); + __builtin___clear_cache (mem, mem + 40); + return 0; +}