Patchwork [go] bulitins housekeeping; add __bultin_unreachable

login
register
mail settings
Submitter Jan Hubicka
Date Oct. 16, 2012, 3:14 p.m.
Message ID <20121016151400.GB4090@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/191814/
State New
Headers show

Comments

Jan Hubicka - Oct. 16, 2012, 3:14 p.m.
Hi,
this patch udpates go-frontend to deifine unreachable bultin I need for loop
and LTO optimizations.  I also noticed that GO ignores existence of all flags
except for CONST and thus I synchronized the flags with C FE variants.

(I plan to use set_call_expr_flags in other FEs too)

Regtested x86_64-linux, OK?

Honza

	* gofrontend/gogo-tree.cc (define_bultin): Accept ECF flags and
	use set_call_expr_flags.
	(define_builtin_function_trees): Update; add BULIT_IN_UNREACHALE.

	* calls.c (set_call_expr_flags): New.
	* tree.h (set_call_expr_flags): Declare.
Ian Taylor - Oct. 16, 2012, 4:36 p.m.
On Tue, Oct 16, 2012 at 8:14 AM, Jan Hubicka <hubicka@ucw.cz> wrote:

> this patch udpates go-frontend to deifine unreachable bultin I need for loop
> and LTO optimizations.  I also noticed that GO ignores existence of all flags
> except for CONST and thus I synchronized the flags with C FE variants.

I can't see how it makes sense to have to change the frontends in
order to be able to generate calls to a builtin function in the
middle-end.  Builtin functions used by the middle-end should be
defined by the middle-end, without any effort required on the part of
the frontend.  The frontend should only need to define functions that
might appear in the language that the frontend is compiling.

In other words, why not just have the middle-end call
add_builtin_function as required?  I see that some builtin functions
are already added by the middle-end in build_common_builtin_nodes.

Ian
Jan Hubicka - Oct. 16, 2012, 4:44 p.m.
> On Tue, Oct 16, 2012 at 8:14 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> 
> > this patch udpates go-frontend to deifine unreachable bultin I need for loop
> > and LTO optimizations.  I also noticed that GO ignores existence of all flags
> > except for CONST and thus I synchronized the flags with C FE variants.
> 
> I can't see how it makes sense to have to change the frontends in
> order to be able to generate calls to a builtin function in the
> middle-end.  Builtin functions used by the middle-end should be
> defined by the middle-end, without any effort required on the part of
> the frontend.  The frontend should only need to define functions that
> might appear in the language that the frontend is compiling.
> 
> In other words, why not just have the middle-end call
> add_builtin_function as required?  I see that some builtin functions
> are already added by the middle-end in build_common_builtin_nodes.

Hmm, I was not aware of these bits (and yes, I agree it is non-sence this being
duplicated everywhere).  I will add UNREACHABLE there.  What about rest of the
change (i.e. adding the proper bits)?

honza
> 
> Ian
Ian Taylor - Oct. 16, 2012, 5:04 p.m.
On Tue, Oct 16, 2012 at 9:44 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>
> Hmm, I was not aware of these bits (and yes, I agree it is non-sence this being
> duplicated everywhere).  I will add UNREACHABLE there.  What about rest of the
> change (i.e. adding the proper bits)?

I suppose it's basically fine but add add set_call_expr_flags first.
Please don't commit any changes to gcc/go/gofrontend/gogo-tree.cc, as
that file is copied from an upstream repository.

Ian
Jan Hubicka - Oct. 16, 2012, 5:08 p.m.
> On Tue, Oct 16, 2012 at 9:44 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> >
> > Hmm, I was not aware of these bits (and yes, I agree it is non-sence this being
> > duplicated everywhere).  I will add UNREACHABLE there.  What about rest of the
> > change (i.e. adding the proper bits)?
> 
> I suppose it's basically fine but add add set_call_expr_flags first.
> Please don't commit any changes to gcc/go/gofrontend/gogo-tree.cc, as
> that file is copied from an upstream repository.

OK, I noticed that similar code already exists in the tree.c builtin creation
so I will get the generic bits done first.
Thanks!
Honza

Patch

Index: go/gofrontend/gogo-tree.cc
===================================================================
--- go/gofrontend/gogo-tree.cc	(revision 192483)
+++ go/gofrontend/gogo-tree.cc	(working copy)
@@ -50,24 +50,22 @@  static std::map<std::string, tree> built
 // defined by builtins.def.  NAME is the name of the builtin function.
 // LIBNAME is the name of the corresponding library function, and is
 // NULL if there isn't one.  FNTYPE is the type of the function.
-// CONST_P is true if the function has the const attribute.
+// FLAGS specify fnction attributes.
 
 static void
 define_builtin(built_in_function bcode, const char* name, const char* libname,
-	       tree fntype, bool const_p)
+	       tree fntype, int flags)
 {
   tree decl = add_builtin_function(name, fntype, bcode, BUILT_IN_NORMAL,
 				   libname, NULL_TREE);
-  if (const_p)
-    TREE_READONLY(decl) = 1;
   set_builtin_decl(bcode, decl, true);
+  set_call_expr_flags (decl, flags);
   builtin_functions[name] = decl;
   if (libname != NULL)
     {
       decl = add_builtin_function(libname, fntype, bcode, BUILT_IN_NORMAL,
 				  NULL, NULL_TREE);
-      if (const_p)
-	TREE_READONLY(decl) = 1;
+      set_call_expr_flags (decl, flags);
       builtin_functions[libname] = decl;
     }
 }
@@ -82,22 +80,22 @@  Gogo::define_builtin_function_trees()
   tree t = go_type_for_size(BITS_PER_UNIT, 1);
   tree p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
   define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", NULL,
-		 build_function_type_list(t, p, t, NULL_TREE), false);
+		 build_function_type_list(t, p, t, NULL_TREE), ECF_LEAF | ECF_NOTHROW);
 
   t = go_type_for_size(BITS_PER_UNIT * 2, 1);
   p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
   define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", NULL,
-		  build_function_type_list(t, p, t, NULL_TREE), false);
+		  build_function_type_list(t, p, t, NULL_TREE), ECF_LEAF | ECF_NOTHROW);
 
   t = go_type_for_size(BITS_PER_UNIT * 4, 1);
   p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
   define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", NULL,
-		 build_function_type_list(t, p, t, NULL_TREE), false);
+		 build_function_type_list(t, p, t, NULL_TREE), ECF_LEAF | ECF_NOTHROW);
 
   t = go_type_for_size(BITS_PER_UNIT * 8, 1);
   p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE));
   define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", NULL,
-		 build_function_type_list(t, p, t, NULL_TREE), false);
+		 build_function_type_list(t, p, t, NULL_TREE), ECF_LEAF | ECF_NOTHROW);
 
   // We use __builtin_expect for magic import functions.
   define_builtin(BUILT_IN_EXPECT, "__builtin_expect", NULL,
@@ -105,7 +103,13 @@  Gogo::define_builtin_function_trees()
 					  long_integer_type_node,
 					  long_integer_type_node,
 					  NULL_TREE),
-		 true);
+		 ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+
+  // Middle-end use __builtin_unreachable
+  define_builtin(BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL,
+		 build_function_type(void_type_node,
+				     void_list_node),
+		 ECF_NOTHROW | ECF_LEAF | ECF_NORETURN);
 
   // We use __builtin_memcmp for struct comparisons.
   define_builtin(BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp",
@@ -114,7 +118,8 @@  Gogo::define_builtin_function_trees()
 					  const_ptr_type_node,
 					  size_type_node,
 					  NULL_TREE),
-		 false);
+		 ECF_LEAF | ECF_NOTHROW | ECF_PURE);
+  /* TODO: add non-null attribute.  */
 
   // We provide some functions for the math library.
   tree math_function_type = build_function_type_list(double_type_node,
@@ -131,93 +136,93 @@  Gogo::define_builtin_function_trees()
     build_function_type_list(long_double_type_node, long_double_type_node,
 			     long_double_type_node, NULL_TREE);
   define_builtin(BUILT_IN_ACOS, "__builtin_acos", "acos",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_ACOSL, "__builtin_acosl", "acosl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_ASIN, "__builtin_asin", "asin",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_ASINL, "__builtin_asinl", "asinl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_ATAN, "__builtin_atan", "atan",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_ATANL, "__builtin_atanl", "atanl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_ATAN2, "__builtin_atan2", "atan2",
-		 math_function_type_two, true);
+		 math_function_type_two, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l",
-		 math_function_type_long_two, true);
+		 math_function_type_long_two, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_CEIL, "__builtin_ceil", "ceil",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_CEILL, "__builtin_ceill", "ceill",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_COS, "__builtin_cos", "cos",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_COSL, "__builtin_cosl", "cosl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_EXP, "__builtin_exp", "exp",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_EXPL, "__builtin_expl", "expl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_EXPM1, "__builtin_expm1", "expm1",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_FABS, "__builtin_fabs", "fabs",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_FABSL, "__builtin_fabsl", "fabsl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_FLOOR, "__builtin_floor", "floor",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_FLOORL, "__builtin_floorl", "floorl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_FMOD, "__builtin_fmod", "fmod",
-		 math_function_type_two, true);
+		 math_function_type_two, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_FMODL, "__builtin_fmodl", "fmodl",
-		 math_function_type_long_two, true);
+		 math_function_type_long_two, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp",
 		 build_function_type_list(double_type_node,
 					  double_type_node,
 					  integer_type_node,
 					  NULL_TREE),
-		 true);
+		 ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl",
 		 build_function_type_list(long_double_type_node,
 					  long_double_type_node,
 					  integer_type_node,
 					  NULL_TREE),
-		 true);
+		 ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOG, "__builtin_log", "log",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOGL, "__builtin_logl", "logl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOG1P, "__builtin_log1p", "log1p",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOG10, "__builtin_log10", "log10",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOG10L, "__builtin_log10l", "log10l",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOG2, "__builtin_log2", "log2",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_LOG2L, "__builtin_log2l", "log2l",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_SIN, "__builtin_sin", "sin",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_SINL, "__builtin_sinl", "sinl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_SQRT, "__builtin_sqrt", "sqrt",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_TAN, "__builtin_tan", "tan",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_TANL, "__builtin_tanl", "tanl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_TRUNC, "__builtin_trunc", "trunc",
-		 math_function_type, true);
+		 math_function_type, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
   define_builtin(BUILT_IN_TRUNCL, "__builtin_truncl", "truncl",
-		 math_function_type_long, true);
+		 math_function_type_long, ECF_CONST | ECF_NOTHROW | ECF_LEAF);
 
   // We use __builtin_return_address in the thunk we build for
   // functions which call recover.
@@ -225,13 +230,13 @@  Gogo::define_builtin_function_trees()
 		 build_function_type_list(ptr_type_node,
 					  unsigned_type_node,
 					  NULL_TREE),
-		 false);
+		 ECF_LEAF);
 
   // The compiler uses __builtin_trap for some exception handling
   // cases.
   define_builtin(BUILT_IN_TRAP, "__builtin_trap", NULL,
 		 build_function_type(void_type_node, void_list_node),
-		 false);
+		 ECF_NOTHROW | ECF_LEAF | ECF_NORETURN);
 }
 
 // Get the name to use for the import control function.  If there is a
Index: calls.c
===================================================================
--- calls.c	(revision 192483)
+++ calls.c	(working copy)
@@ -802,6 +802,36 @@  call_expr_flags (const_tree t)
   return flags;
 }
 
+/* Modify DECL for given flags.  */
+void
+set_call_expr_flags (tree decl, int flags)
+{
+  if (flags & ECF_NOTHROW)
+    TREE_NOTHROW (decl) = 1;
+  if (flags & ECF_CONST)
+    TREE_READONLY (decl) = 1;
+  if (flags & ECF_PURE)
+    DECL_PURE_P (decl) = 1;
+  if (flags & ECF_NOVOPS)
+    DECL_IS_NOVOPS (decl) = 1;
+  if (flags & ECF_NORETURN)
+    TREE_THIS_VOLATILE (decl) = 1;
+  if (flags & ECF_MALLOC)
+    DECL_IS_MALLOC (decl) = 1;
+  if (flags & ECF_RETURNS_TWICE)
+    DECL_IS_RETURNS_TWICE (decl) = 1;
+  if (flags & ECF_LEAF)
+    DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
+					NULL, DECL_ATTRIBUTES (decl));
+  if (flags & ECF_TM_PURE)
+    DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("transaction_pure"),
+					NULL, DECL_ATTRIBUTES (decl));
+  /* Looping const or pure is imlpies by noreturn.
+     There is currently no way to declare looping const or looping pure alone.  */
+  gcc_assert (!(flags & ECF_LOOPING_CONST_OR_PURE)
+	      || ((flags & ECF_NORETURN) && (flags & (ECF_CONST | ECF_PURE))));
+}
+
 /* Precompute all register parameters as described by ARGS, storing values
    into fields within the ARGS array.
 
Index: tree.h
===================================================================
--- tree.h	(revision 192483)
+++ tree.h	(working copy)
@@ -6025,6 +6025,7 @@  extern tree build_duplicate_type (tree);
 
 extern int flags_from_decl_or_type (const_tree);
 extern int call_expr_flags (const_tree);
+extern void set_call_expr_flags (tree, int);
 
 /* Call argument flags.  */