diff mbox

[1/2] Support fnspecs for internal functions

Message ID 53E46A0D.6020602@samsung.com
State New
Headers show

Commit Message

Yury Gribov Aug. 8, 2014, 6:11 a.m. UTC
Hi all,

Following discussion in 
https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00016.html this patch adds 
support for fnspecs to internal function machinery which should 
(hopefully) allow compiler to perform better analysis and optimization 
of this construct.

For now the only internal functions using this machinery would be 
UBSAN_NULL and ASAN_CHECK (both would take EAF_DIRECT and EAF_NOESCAPE 
for their pointer argument).

The patch was bootstrapped and regtested on x64.

Ok for trunk?

-Y

Comments

Jakub Jelinek Aug. 8, 2014, 8:07 a.m. UTC | #1
On Fri, Aug 08, 2014 at 10:11:25AM +0400, Yury Gribov wrote:
> commit b90c4abf0b804c60b548f94fe59118d029363140
> Author: Yury Gribov <y.gribov@samsung.com>
> Date:   Wed Aug 6 11:05:39 2014 +0400
> 
>     Added fnspec to internal functions.
>     
>     2014-08-08  Yury Gribov  <y.gribov@samsung.com>
>     
>     	* gimple.c (gimple_call_fnspec): Support internal functions.
>     	(gimple_call_return_flags): Use const.
>     	* Makefile.in: Add internal-fn.h to list of GC files.
>     	* internal-fn.def: Add fnspec information.
>     	* internal-fn.h (internal_fn_fnspec): New function.
>     	(init_internal_fns): Declare new function.
>     	* internal-fn.c (internal_fn_fnspec_array): New global variable.
>     	(init_internal_fns): New function.
>     	* tree-core.h: Update macro call.
>     	* tree.c (build_common_builtin_nodes): Initialize internal fns.

Ok, thanks, with a minor nit:

> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -9870,8 +9870,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code,
>  }
>  
>  /* Call this function after instantiating all builtins that the language
> -   front end cares about.  This will build the rest of the builtins that
> -   are relied upon by the tree optimizers and the middle-end.  */
> +   front end cares about.  This will build the rest of the builtins
> +   and internal function that are relied upon by the tree optimizers and

s/function/functions/

	Jakub
Yury Gribov Aug. 11, 2014, 6:13 a.m. UTC | #2
> On 08/08/2014 12:07 PM, Jakub Jelinek wrote:
 > Ok, thanks, with a minor nit:

Done in r213806 (the nit fixed in patch 2/2).

-Y
diff mbox

Patch

commit b90c4abf0b804c60b548f94fe59118d029363140
Author: Yury Gribov <y.gribov@samsung.com>
Date:   Wed Aug 6 11:05:39 2014 +0400

    Added fnspec to internal functions.
    
    2014-08-08  Yury Gribov  <y.gribov@samsung.com>
    
    	* gimple.c (gimple_call_fnspec): Support internal functions.
    	(gimple_call_return_flags): Use const.
    	* Makefile.in: Add internal-fn.h to list of GC files.
    	* internal-fn.def: Add fnspec information.
    	* internal-fn.h (internal_fn_fnspec): New function.
    	(init_internal_fns): Declare new function.
    	* internal-fn.c (internal_fn_fnspec_array): New global variable.
    	(init_internal_fns): New function.
    	* tree-core.h: Update macro call.
    	* tree.c (build_common_builtin_nodes): Initialize internal fns.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a2fb5f5..67b497f 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2297,7 +2297,9 @@  GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/vtable-verify.c \
   $(srcdir)/asan.c \
   $(srcdir)/ubsan.c \
-  $(srcdir)/tsan.c $(srcdir)/ipa-devirt.c \
+  $(srcdir)/tsan.c \
+  $(srcdir)/ipa-devirt.c \
+  $(srcdir)/internal-fn.h \
   @all_gtfiles@
 
 # Compute the list of GT header files from the corresponding C sources,
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 4a9d379..4763a59 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1327,11 +1327,14 @@  gimple_call_flags (const_gimple stmt)
 
 /* Return the "fn spec" string for call STMT.  */
 
-static tree
+static const_tree
 gimple_call_fnspec (const_gimple stmt)
 {
   tree type, attr;
 
+  if (gimple_call_internal_p (stmt))
+    return internal_fn_fnspec (gimple_call_internal_fn (stmt));
+
   type = gimple_call_fntype (stmt);
   if (!type)
     return NULL_TREE;
@@ -1348,7 +1351,7 @@  gimple_call_fnspec (const_gimple stmt)
 int
 gimple_call_arg_flags (const_gimple stmt, unsigned arg)
 {
-  tree attr = gimple_call_fnspec (stmt);
+  const_tree attr = gimple_call_fnspec (stmt);
 
   if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
     return 0;
@@ -1382,7 +1385,7 @@  gimple_call_arg_flags (const_gimple stmt, unsigned arg)
 int
 gimple_call_return_flags (const_gimple stmt)
 {
-  tree attr;
+  const_tree attr;
 
   if (gimple_call_flags (stmt) & ECF_MALLOC)
     return ERF_NOALIAS;
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 78f59d6..b58b868 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -40,7 +40,7 @@  along with GCC; see the file COPYING3.  If not see
 
 /* The names of each internal function, indexed by function number.  */
 const char *const internal_fn_name_array[] = {
-#define DEF_INTERNAL_FN(CODE, FLAGS) #CODE,
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
 #include "internal-fn.def"
 #undef DEF_INTERNAL_FN
   "<invalid-fn>"
@@ -48,12 +48,26 @@  const char *const internal_fn_name_array[] = {
 
 /* The ECF_* flags of each internal function, indexed by function number.  */
 const int internal_fn_flags_array[] = {
-#define DEF_INTERNAL_FN(CODE, FLAGS) FLAGS,
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
 #include "internal-fn.def"
 #undef DEF_INTERNAL_FN
   0
 };
 
+/* Fnspec of each internal function, indexed by function number.  */
+const_tree internal_fn_fnspec_array[IFN_LAST + 1];
+
+void
+init_internal_fns ()
+{
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
+  if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
+    build_string ((int) sizeof (FNSPEC) + 1, FNSPEC ? FNSPEC : "");
+#include "internal-fn.def"
+#undef DEF_INTERNAL_FN
+  internal_fn_fnspec_array[IFN_LAST] = 0;
+}
+
 /* ARRAY_TYPE is an array of vector modes.  Return the associated insn
    for load-lanes-style optab OPTAB.  The insn must exist.  */
 
@@ -897,7 +911,7 @@  expand_BUILTIN_EXPECT (gimple stmt)
 
    where STMT is the statement that performs the call. */
 static void (*const internal_fn_expanders[]) (gimple) = {
-#define DEF_INTERNAL_FN(CODE, FLAGS) expand_##CODE,
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
 #include "internal-fn.def"
 #undef DEF_INTERNAL_FN
   0
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index f0766bc..9857542 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -28,29 +28,30 @@  along with GCC; see the file COPYING3.  If not see
 
    Each entry in this file has the form:
 
-     DEF_INTERNAL_FN (NAME, FLAGS)
+     DEF_INTERNAL_FN (NAME, FLAGS, FNSPEC)
 
-   where NAME is the name of the function and FLAGS is a set of
-   ECF_* flags.  Each entry must have a corresponding expander
-   of the form:
+   where NAME is the name of the function, FLAGS is a set of
+   ECF_* flags and FNSPEC is a string describing functions fnspec.
+   
+   Each entry must have a corresponding expander of the form:
 
      void expand_NAME (gimple stmt)
 
    where STMT is the statement that performs the call.  */
 
-DEF_INTERNAL_FN (LOAD_LANES, ECF_CONST | ECF_LEAF)
-DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF)
-DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (MASK_LOAD, ECF_PURE | ECF_LEAF)
-DEF_INTERNAL_FN (MASK_STORE, ECF_LEAF)
-DEF_INTERNAL_FN (ANNOTATE,  ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN)
-DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (LOAD_LANES, ECF_CONST | ECF_LEAF, NULL)
+DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (MASK_LOAD, ECF_PURE | ECF_LEAF, NULL)
+DEF_INTERNAL_FN (MASK_STORE, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ANNOTATE,  ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW, ".W.")
+DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL)
+DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index 2dcf44e..14573aa 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -20,6 +20,12 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_INTERNAL_FN_H
 #define GCC_INTERNAL_FN_H
 
+#include "coretypes.h"
+
+/* Initialize internal function tables.  */
+
+extern void init_internal_fns ();
+
 /* Return the name of internal function FN.  The name is only meaningful
    for dumps; it has no linkage.  */
 
@@ -41,6 +47,16 @@  internal_fn_flags (enum internal_fn fn)
   return internal_fn_flags_array[(int) fn];
 }
 
+/* Return fnspec for function FN.  */
+
+extern GTY(()) const_tree internal_fn_fnspec_array[IFN_LAST + 1];
+
+static inline const_tree
+internal_fn_fnspec (enum internal_fn fn)
+{
+  return internal_fn_fnspec_array[(int) fn];
+}
+
 extern void expand_internal_call (gimple);
 
 #endif
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 9d462d1..9e9ca8c 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -667,7 +667,7 @@  enum annot_expr_kind {
 
 /* Internal functions.  */
 enum internal_fn {
-#define DEF_INTERNAL_FN(CODE, FLAGS) IFN_##CODE,
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) IFN_##CODE,
 #include "internal-fn.def"
 #undef DEF_INTERNAL_FN
   IFN_LAST
diff --git a/gcc/tree.c b/gcc/tree.c
index d95cf78..1545a86 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9870,8 +9870,9 @@  local_define_builtin (const char *name, tree type, enum built_in_function code,
 }
 
 /* Call this function after instantiating all builtins that the language
-   front end cares about.  This will build the rest of the builtins that
-   are relied upon by the tree optimizers and the middle-end.  */
+   front end cares about.  This will build the rest of the builtins
+   and internal function that are relied upon by the tree optimizers and
+   the middle-end.  */
 
 void
 build_common_builtin_nodes (void)
@@ -10104,6 +10105,8 @@  build_common_builtin_nodes (void)
 			      ECF_CONST | ECF_NOTHROW | ECF_LEAF);
       }
   }
+
+  init_internal_fns ();
 }
 
 /* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a