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.
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.  */
 

Reply via email to