internal-fn.c (expand_UNIQUE): New.
authorNathan Sidwell <nathan@gcc.gnu.org>
Tue, 27 Oct 2015 20:16:04 +0000 (20:16 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 27 Oct 2015 20:16:04 +0000 (20:16 +0000)
* internal-fn.c (expand_UNIQUE): New.
* internal-fn.h (enum ifn_unique_kind): New.
* internal-fn.def (IFN_UNIQUE): New.
* target-insns.def (unique): Define.
* gimple.h (gimple_call_internal_unique_p): New.
* gimple.c (gimple_call_same_target_p): Check internal fn
uniqueness.
* tracer.c (ignore_bb_p): Check for IFN_UNIQUE call.
* tree-ssa-threadedge.c
(record_temporary_equivalences_from_stmts): Likewise.
* tree-cfg.c (gmple_call_initialize_ctrl_altering): Likewise.

From-SVN: r229459

gcc/ChangeLog
gcc/gimple.c
gcc/gimple.h
gcc/internal-fn.c
gcc/internal-fn.def
gcc/internal-fn.h
gcc/target-insns.def
gcc/tracer.c
gcc/tree-cfg.c
gcc/tree-ssa-threadedge.c

index 369a5821fd1a1cbe969b0deb9b0644131cd7d39e..19a6809e8d49a789ce34cc27a9adda21a0e59104 100644 (file)
@@ -1,3 +1,17 @@
+2015-10-27  Nathan Sidwell  <nathan@codesourcery.com>
+       
+       * internal-fn.c (expand_UNIQUE): New.
+       * internal-fn.h (enum ifn_unique_kind): New.
+       * internal-fn.def (IFN_UNIQUE): New.
+       * target-insns.def (unique): Define.
+       * gimple.h (gimple_call_internal_unique_p): New.
+       * gimple.c (gimple_call_same_target_p): Check internal fn
+       uniqueness.
+       * tracer.c (ignore_bb_p): Check for IFN_UNIQUE call.
+       * tree-ssa-threadedge.c
+       (record_temporary_equivalences_from_stmts): Likewise.
+       * tree-cfg.c (gmple_call_initialize_ctrl_altering): Likewise.
+
 2015-10-27  Richard Henderson  <rth@redhat.com>
 
        PR rtl-opt/67609
 
        * graphite-optimize-isl.c (get_schedule_for_node_st): New callback
          function to schedule based on isl_schedule_node.
-       (get_schedule_map_st): New schedule optimizer based on isl_schedule_node.
-       (scop_get_domains): New. Return the isl_union_set containing the domains of all the pbbs.
+       (get_schedule_map_st): New schedule optimizer based on
+       isl_schedule_node.
+       (scop_get_domains): New. Return the isl_union_set containing the
+       domains of all the pbbs.
        (optimize_isl): Call the new function get_schedule_map_st for isl-0.15
 
 2015-10-27  H.J. Lu  <hongjiu.lu@intel.com>
index 5312d6e055dff8f0e3444cb20b6f0272896669f9..d7ce18749d23199fe71de144d85ef4a89540de58 100644 (file)
@@ -1346,7 +1346,8 @@ gimple_call_same_target_p (const gimple *c1, const gimple *c2)
 {
   if (gimple_call_internal_p (c1))
     return (gimple_call_internal_p (c2)
-           && gimple_call_internal_fn (c1) == gimple_call_internal_fn (c2));
+           && gimple_call_internal_fn (c1) == gimple_call_internal_fn (c2)
+           && !gimple_call_internal_unique_p (as_a <const gcall *> (c1)));
   else
     return (gimple_call_fn (c1) == gimple_call_fn (c2)
            || (gimple_call_fndecl (c1)
index 02d0db59752d7d75ab244db2e4db0905d7c22ee3..781801b7c4a7b95f5d7abe226fc8c7992bc5ffed 100644 (file)
@@ -2895,6 +2895,21 @@ gimple_call_internal_fn (const gimple *gs)
   return gimple_call_internal_fn (gc);
 }
 
+/* Return true, if this internal gimple call is unique.  */
+
+static inline bool
+gimple_call_internal_unique_p (const gcall *gs)
+{
+  return gimple_call_internal_fn (gs) == IFN_UNIQUE;
+}
+
+static inline bool
+gimple_call_internal_unique_p (const gimple *gs)
+{
+  const gcall *gc = GIMPLE_CHECK2<const gcall *> (gs);
+  return gimple_call_internal_unique_p (gc);
+}
+
 /* If CTRL_ALTERING_P is true, mark GIMPLE_CALL S to be a stmt
    that could alter control flow.  */
 
index f12d3aff96a9dbaf41c1edceb3c6b393fed65d29..ff5a90dc5028876eff245f6de174cb5bba3f521d 100644 (file)
@@ -1958,6 +1958,30 @@ expand_VA_ARG (gcall *stmt ATTRIBUTE_UNUSED)
   gcc_unreachable ();
 }
 
+/* Expand the IFN_UNIQUE function according to its first argument.  */
+
+static void
+expand_UNIQUE (gcall *stmt)
+{
+  rtx pattern = NULL_RTX;
+  enum ifn_unique_kind kind
+    = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
+
+  switch (kind)
+    {
+    default:
+      gcc_unreachable ();
+
+    case IFN_UNIQUE_UNSPEC:
+      if (targetm.have_unique ())
+       pattern = targetm.gen_unique ();
+      break;
+    }
+
+  if (pattern)
+    emit_insn (pattern);
+}
+
 /* Routines to expand each internal function, indexed by function number.
    Each routine has the prototype:
 
index 305cf1b858cb243dd77212b23a0cae57a9fe1727..e181bccf52d3ba8213814c7f7268b5d8b0228832 100644 (file)
@@ -65,3 +65,10 @@ DEF_INTERNAL_FN (SUB_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (MUL_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (TSAN_FUNC_EXIT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
+
+/* An unduplicable, uncombinable function.  Generally used to preserve
+   a CFG property in the face of jump threading, tail merging or
+   other such optimizations.  The first argument distinguishes
+   between uses.  See internal-fn.h for usage.  */
+DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+
index 2ff3347241fce8eed4848803657e6df4cf20b7d0..521e4af26479b936f5ab7a91ee704a4641fa8a47 100644 (file)
@@ -20,6 +20,11 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_INTERNAL_FN_H
 #define GCC_INTERNAL_FN_H
 
+/* INTEGER_CST values for IFN_UNIQUE function arg-0.  */
+enum ifn_unique_kind {
+  IFN_UNIQUE_UNSPEC   /* Undifferentiated UNIQUE.  */
+};
+
 /* Initialize internal function tables.  */
 
 extern void init_internal_fns ();
index 00e00273cd0132263df76c62421bc091fec604d7..d79fdf21db890ab341cddfb7e899dcf8bb816ced 100644 (file)
@@ -89,5 +89,6 @@ DEF_TARGET_INSN (stack_protect_test, (rtx x0, rtx x1, rtx x2))
 DEF_TARGET_INSN (store_multiple, (rtx x0, rtx x1, rtx x2))
 DEF_TARGET_INSN (tablejump, (rtx x0, rtx x1))
 DEF_TARGET_INSN (trap, (void))
+DEF_TARGET_INSN (unique, (void))
 DEF_TARGET_INSN (untyped_call, (rtx x0, rtx x1, rtx x2))
 DEF_TARGET_INSN (untyped_return, (rtx x0, rtx x1))
index 11d5f94ec6706589964d387e4e7e3688697f2f6c..074a96a39721033f03f87c61d8b17810f4690394 100644 (file)
@@ -93,18 +93,25 @@ bb_seen_p (basic_block bb)
 static bool
 ignore_bb_p (const_basic_block bb)
 {
-  gimple *g;
-
   if (bb->index < NUM_FIXED_BLOCKS)
     return true;
   if (optimize_bb_for_size_p (bb))
     return true;
 
-  /* A transaction is a single entry multiple exit region.  It must be
-     duplicated in its entirety or not at all.  */
-  g = last_stmt (CONST_CAST_BB (bb));
-  if (g && gimple_code (g) == GIMPLE_TRANSACTION)
-    return true;
+  if (gimple *g = last_stmt (CONST_CAST_BB (bb)))
+    {
+      /* A transaction is a single entry multiple exit region.  It
+        must be duplicated in its entirety or not at all.  */
+      if (gimple_code (g) == GIMPLE_TRANSACTION)
+       return true;
+
+      /* An IFN_UNIQUE call must be duplicated as part of its group,
+        or not at all.  */
+      if (is_gimple_call (g)
+         && gimple_call_internal_p (g)
+         && gimple_call_internal_unique_p (g))
+       return true;
+    }
 
   return false;
 }
index 40d5eb89ed759cf13d6efdf2f2e9761b3747caf8..970207d04d2af4fecb66ce68fb559c3251d2936b 100644 (file)
@@ -487,7 +487,11 @@ gimple_call_initialize_ctrl_altering (gimple *stmt)
       || ((flags & ECF_TM_BUILTIN)
          && is_tm_ending_fndecl (gimple_call_fndecl (stmt)))
       /* BUILT_IN_RETURN call is same as return statement.  */
-      || gimple_call_builtin_p (stmt, BUILT_IN_RETURN))
+      || gimple_call_builtin_p (stmt, BUILT_IN_RETURN)
+      /* IFN_UNIQUE should be the last insn, to make checking for it
+        as cheap as possible.  */
+      || (gimple_call_internal_p (stmt)
+         && gimple_call_internal_unique_p (stmt)))
     gimple_call_set_ctrl_altering (stmt, true);
   else
     gimple_call_set_ctrl_altering (stmt, false);
index 38f80ba14fc2dc3ee2478f66d7255680ecb88038..68fd4ef17ec45c03e5769bc7135931b6616e242b 100644 (file)
@@ -247,6 +247,13 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
          && gimple_asm_volatile_p (as_a <gasm *> (stmt)))
        return NULL;
 
+      /* If the statement is a unique builtin, we can not thread
+        through here.  */
+      if (gimple_code (stmt) == GIMPLE_CALL
+         && gimple_call_internal_p (stmt)
+         && gimple_call_internal_unique_p (stmt))
+       return NULL;
+
       /* If duplicating this block is going to cause too much code
         expansion, then do not thread through this block.  */
       stmt_count++;