]> gcc.gnu.org Git - gcc.git/commitdiff
re PR lto/60449 (Merging function DECLs discards leaf attribute which causes cfg...
authorMartin Jambor <mjambor@suse.cz>
Wed, 20 Aug 2014 16:47:12 +0000 (18:47 +0200)
committerWei Mi <wmi@gcc.gnu.org>
Wed, 20 Aug 2014 16:47:12 +0000 (16:47 +0000)
2014-08-20  Martin Jambor  <mjambor@suse.cz>
    Wei Mi  <wmi@google.com>

PR ipa/60449
PR middle-end/61776
* tree-ssa-operands.c (update_stmt_operands): Remove
MODIFIED_NORETURN_CALLS.
* tree-cfgcleanup.c (cleanup_call_ctrl_altering_flag): New func.
(cleanup_control_flow_bb): Use cleanup_call_ctrl_altering_flag.
(split_bb_on_noreturn_calls): Renamed from split_bbs_on_noreturn_calls.
(cleanup_tree_cfg_1): Use split_bb_on_noreturn_calls.
* tree-ssanames.h: Remove MODIFIED_NORETURN_CALLS.
* gimple.h (enum gf_mask): Add GF_CALL_CTRL_ALTERING.
(gimple_call_set_ctrl_altering): New func.
(gimple_call_ctrl_altering_p): Ditto.
* tree-cfg.c (gimple_call_initialize_ctrl_altering): Ditto.
(make_blocks): Use gimple_call_initialize_ctrl_altering.
(is_ctrl_altering_stmt): Use gimple_call_ctrl_altering_p.
(execute_fixup_cfg): Use gimple_call_ctrl_altering_p and
remove MODIFIED_NORETURN_CALLS.

2014-08-20  Martin Jambor  <mjambor@suse.cz>
    Wei Mi  <wmi@google.com>

PR ipa/60449
PR middle-end/61776
* testsuite/gcc.dg/lto/pr60449_1.c: New test.
* testsuite/gcc.dg/lto/pr60449_0.c: New test.
* testsuite/gcc.dg/pr61776.c: New test.

Co-Authored-By: Wei Mi <wmi@google.com>
From-SVN: r214233

gcc/ChangeLog
gcc/gimple.h
gcc/testsuite/ChangeLog
gcc/tree-cfg.c
gcc/tree-cfgcleanup.c
gcc/tree-ssa-operands.c
gcc/tree-ssanames.h

index 40c0a99a09d5a98327f49238d9561b966cd79d5f..8f9b113e4dab22e32f3b5cab1709fabc485a0a82 100644 (file)
@@ -1,3 +1,24 @@
+2014-08-20  Martin Jambor  <mjambor@suse.cz>
+           Wei Mi  <wmi@google.com>
+
+       PR ipa/60449
+       PR middle-end/61776
+       * tree-ssa-operands.c (update_stmt_operands): Remove
+       MODIFIED_NORETURN_CALLS.
+       * tree-cfgcleanup.c (cleanup_call_ctrl_altering_flag): New func.
+       (cleanup_control_flow_bb): Use cleanup_call_ctrl_altering_flag.
+       (split_bb_on_noreturn_calls): Renamed from split_bbs_on_noreturn_calls.
+       (cleanup_tree_cfg_1): Use split_bb_on_noreturn_calls.
+       * tree-ssanames.h: Remove MODIFIED_NORETURN_CALLS.
+       * gimple.h (enum gf_mask): Add GF_CALL_CTRL_ALTERING.
+       (gimple_call_set_ctrl_altering): New func.
+       (gimple_call_ctrl_altering_p): Ditto.
+       * tree-cfg.c (gimple_call_initialize_ctrl_altering): Ditto.
+       (make_blocks): Use gimple_call_initialize_ctrl_altering.
+       (is_ctrl_altering_stmt): Use gimple_call_ctrl_altering_p.
+       (execute_fixup_cfg): Use gimple_call_ctrl_altering_p and
+       remove MODIFIED_NORETURN_CALLS.
+
 2014-08-20  Jan Hubicka  <hubicka@ucw.cz>
 
        * coverage.c (coverage_compute_profile_id): Return non-0;
index a517dee65d533f7a1c822d45189df8b326185a98..51814baa65ab51c89a16309294b715fed7d26b12 100644 (file)
@@ -90,6 +90,7 @@ enum gf_mask {
     GF_CALL_NOTHROW            = 1 << 4,
     GF_CALL_ALLOCA_FOR_VAR     = 1 << 5,
     GF_CALL_INTERNAL           = 1 << 6,
+    GF_CALL_CTRL_ALTERING       = 1 << 7,
     GF_OMP_PARALLEL_COMBINED   = 1 << 0,
     GF_OMP_FOR_KIND_MASK       = (1 << 2) - 1,
     GF_OMP_FOR_KIND_FOR                = 0,
@@ -2459,6 +2460,29 @@ gimple_call_internal_fn (const_gimple gs)
   return static_cast <const gimple_statement_call *> (gs)->u.internal_fn;
 }
 
+/* If CTRL_ALTERING_P is true, mark GIMPLE_CALL S to be a stmt
+   that could alter control flow.  */
+
+static inline void
+gimple_call_set_ctrl_altering (gimple s, bool ctrl_altering_p)
+{
+  GIMPLE_CHECK (s, GIMPLE_CALL);
+  if (ctrl_altering_p)
+    s->subcode |= GF_CALL_CTRL_ALTERING;
+  else
+    s->subcode &= ~GF_CALL_CTRL_ALTERING;
+}
+
+/* Return true if call GS calls an func whose GF_CALL_CTRL_ALTERING
+   flag is set. Such call could not be a stmt in the middle of a bb.  */
+
+static inline bool
+gimple_call_ctrl_altering_p (const_gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  return (gs->subcode & GF_CALL_CTRL_ALTERING) != 0;
+}
+
 
 /* Return the function type of the function called by GS.  */
 
index ab39fd674db81e8517554030c90d2c0d99c77f15..0957925669bcf415297f6d6003ed774ceae4d321 100644 (file)
@@ -1,3 +1,12 @@
+2014-08-20  Martin Jambor  <mjambor@suse.cz>
+           Wei Mi  <wmi@google.com>
+
+       PR ipa/60449
+       PR middle-end/61776
+       * testsuite/gcc.dg/lto/pr60449_1.c: New test.
+       * testsuite/gcc.dg/lto/pr60449_0.c: New test.
+       * testsuite/gcc.dg/pr61776.c: New test.
+
 2014-08-20  Steve Ellcey  <sellcey@mips.com>
 
        PR middle-end/49191
index 9d1de01021cfda296c3fe53c9212c3aa6bd627c5..700a998555145942f4240839d3c76b7acd7587ca 100644 (file)
@@ -164,6 +164,7 @@ static int gimple_verify_flow_info (void);
 static void gimple_make_forwarder_block (edge);
 static gimple first_non_label_stmt (basic_block);
 static bool verify_gimple_transaction (gimple);
+static bool call_can_make_abnormal_goto (gimple);
 
 /* Flowgraph optimization and cleanup.  */
 static void gimple_merge_blocks (basic_block, basic_block);
@@ -437,6 +438,32 @@ assert_unreachable_fallthru_edge_p (edge e)
 }
 
 
+/* Initialize GF_CALL_CTRL_ALTERING flag, which indicates the call
+   could alter control flow except via eh. We initialize the flag at
+   CFG build time and only ever clear it later.  */
+
+static void
+gimple_call_initialize_ctrl_altering (gimple stmt)
+{
+  int flags = gimple_call_flags (stmt);
+
+  /* A call alters control flow if it can make an abnormal goto.  */
+  if (call_can_make_abnormal_goto (stmt)
+      /* A call also alters control flow if it does not return.  */
+      || flags & ECF_NORETURN
+      /* TM ending statements have backedges out of the transaction.
+        Return true so we split the basic block containing them.
+        Note that the TM_BUILTIN test is merely an optimization.  */
+      || ((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_set_ctrl_altering (stmt, true);
+  else
+    gimple_call_set_ctrl_altering (stmt, false);
+}
+
+
 /* Build a flowgraph for the sequence of stmts SEQ.  */
 
 static void
@@ -455,6 +482,9 @@ make_blocks (gimple_seq seq)
       prev_stmt = stmt;
       stmt = gsi_stmt (i);
 
+      if (stmt && is_gimple_call (stmt))
+       gimple_call_initialize_ctrl_altering (stmt);
+
       /* If the statement starts a new basic block or if we have determined
         in a previous pass that we need to create a new block for STMT, do
         so now.  */
@@ -2372,28 +2402,10 @@ is_ctrl_altering_stmt (gimple t)
   switch (gimple_code (t))
     {
     case GIMPLE_CALL:
-      {
-       int flags = gimple_call_flags (t);
-
-       /* A call alters control flow if it can make an abnormal goto.  */
-       if (call_can_make_abnormal_goto (t))
-         return true;
-
-       /* A call also alters control flow if it does not return.  */
-       if (flags & ECF_NORETURN)
-         return true;
-
-       /* TM ending statements have backedges out of the transaction.
-          Return true so we split the basic block containing them.
-          Note that the TM_BUILTIN test is merely an optimization.  */
-       if ((flags & ECF_TM_BUILTIN)
-           && is_tm_ending_fndecl (gimple_call_fndecl (t)))
-         return true;
-
-       /* BUILT_IN_RETURN call is same as return statement.  */
-       if (gimple_call_builtin_p (t, BUILT_IN_RETURN))
-         return true;
-      }
+      /* Per stmt call flag indicates whether the call could alter
+        controlflow.  */
+      if (gimple_call_ctrl_altering_p (t))
+       return true;
       break;
 
     case GIMPLE_EH_DISPATCH:
@@ -8533,6 +8545,8 @@ execute_fixup_cfg (void)
                  && (!is_gimple_call (stmt)
                      || (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
            {
+             if (stmt && is_gimple_call (stmt))
+               gimple_call_set_ctrl_altering (stmt, false);
              stmt = gimple_build_call
                  (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
              gimple_stmt_iterator gsi = gsi_last_bb (bb);
@@ -8543,10 +8557,6 @@ execute_fixup_cfg (void)
   if (count_scale != REG_BR_PROB_BASE)
     compute_function_frequency ();
 
-  /* We just processed all calls.  */
-  if (cfun->gimple_df)
-    vec_free (MODIFIED_NORETURN_CALLS (cfun));
-
   /* Dump a textual representation of the flowgraph.  */
   if (dump_file)
     gimple_dump_cfg (dump_file, dump_flags);
index 2b6927e0437030a0d405adcb268fb77cbcf571c6..a66ec6e75375a823f059f6d62d5b88ebf69fdfb3 100644 (file)
@@ -162,6 +162,23 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi)
   return retval;
 }
 
+/* Cleanup the GF_CALL_CTRL_ALTERING flag according to
+   to updated gimple_call_flags.  */
+
+static void
+cleanup_call_ctrl_altering_flag (gimple bb_end)
+{
+  if (!is_gimple_call (bb_end)
+      || !gimple_call_ctrl_altering_p (bb_end))
+    return;
+
+  int flags = gimple_call_flags (bb_end);
+  if (((flags & (ECF_CONST | ECF_PURE))
+       && !(flags & ECF_LOOPING_CONST_OR_PURE))
+      || (flags & ECF_LEAF))
+    gimple_call_set_ctrl_altering (bb_end, false);
+}
+
 /* Try to remove superfluous control structures in basic block BB.  Returns
    true if anything changes.  */
 
@@ -182,6 +199,9 @@ cleanup_control_flow_bb (basic_block bb)
 
   stmt = gsi_stmt (gsi);
 
+  /* Try to cleanup ctrl altering flag for call which ends bb.  */
+  cleanup_call_ctrl_altering_flag (stmt);
+
   if (gimple_code (stmt) == GIMPLE_COND
       || gimple_code (stmt) == GIMPLE_SWITCH)
     retval |= cleanup_control_expr_graph (bb, gsi);
@@ -594,30 +614,24 @@ fixup_noreturn_call (gimple stmt)
    known not to return, and remove the unreachable code.  */
 
 static bool
-split_bbs_on_noreturn_calls (void)
+split_bb_on_noreturn_calls (basic_block bb)
 {
   bool changed = false;
-  gimple stmt;
-  basic_block bb;
+  gimple_stmt_iterator gsi;
 
-  /* Detect cases where a mid-block call is now known not to return.  */
-  if (cfun->gimple_df)
-    while (vec_safe_length (MODIFIED_NORETURN_CALLS (cfun)))
-      {
-       stmt = MODIFIED_NORETURN_CALLS (cfun)->pop ();
-       bb = gimple_bb (stmt);
-       /* BB might be deleted at this point, so verify first
-          BB is present in the cfg.  */
-       if (bb == NULL
-           || bb->index < NUM_FIXED_BLOCKS
-           || bb->index >= last_basic_block_for_fn (cfun)
-           || BASIC_BLOCK_FOR_FN (cfun, bb->index) != bb
-           || !gimple_call_noreturn_p (stmt))
-         continue;
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple stmt = gsi_stmt (gsi);
 
+      if (!is_gimple_call (stmt))
+       continue;
+
+      if (gimple_call_noreturn_p (stmt))
        changed |= fixup_noreturn_call (stmt);
-      }
+    }
 
+  if (changed)
+    bitmap_set_bit (cfgcleanup_altered_bbs, bb->index);
   return changed;
 }
 
@@ -655,8 +669,6 @@ cleanup_tree_cfg_1 (void)
   basic_block bb;
   unsigned i, n;
 
-  retval |= split_bbs_on_noreturn_calls ();
-
   /* Prepare the worklists of altered blocks.  */
   cfgcleanup_altered_bbs = BITMAP_ALLOC (NULL);
 
@@ -672,7 +684,10 @@ cleanup_tree_cfg_1 (void)
     {
       bb = BASIC_BLOCK_FOR_FN (cfun, i);
       if (bb)
-       retval |= cleanup_tree_cfg_bb (bb);
+       {
+         retval |= cleanup_tree_cfg_bb (bb);
+         retval |= split_bb_on_noreturn_calls (bb);
+       }
     }
 
   /* Now process the altered blocks, as long as any are available.  */
@@ -689,9 +704,9 @@ cleanup_tree_cfg_1 (void)
 
       retval |= cleanup_tree_cfg_bb (bb);
 
-      /* Rerun split_bbs_on_noreturn_calls, in case we have altered any noreturn
+      /* Rerun split_bb_on_noreturn_calls, in case we have altered any noreturn
         calls.  */
-      retval |= split_bbs_on_noreturn_calls ();
+      retval |= split_bb_on_noreturn_calls (bb);
     }
 
   end_recording_case_labels ();
index a939d41b894f6385d9be440c076d3bc4e68d6b6a..a7ccf04bea94760a24e772e248cc7a97cfccd328 100644 (file)
@@ -1087,12 +1087,6 @@ update_stmt_operands (struct function *fn, gimple stmt)
 
   timevar_push (TV_TREE_OPS);
 
-  /* If the stmt is a noreturn call queue it to be processed by
-     split_bbs_on_noreturn_calls during cfg cleanup.  */
-  if (is_gimple_call (stmt)
-      && gimple_call_noreturn_p (stmt))
-    vec_safe_push (MODIFIED_NORETURN_CALLS (fn), stmt);
-
   gcc_assert (gimple_modified_p (stmt));
   build_ssa_operands (fn, stmt);
   gimple_set_modified (stmt, false);
index 4fc9f69e1af612657242b360bc2db8658e416345..22570cd0145dc8b214ed3b01e9019707fd9d2efe 100644 (file)
@@ -57,7 +57,6 @@ struct GTY ((variable_size)) range_info_def {
 
 
 #define SSANAMES(fun) (fun)->gimple_df->ssa_names
-#define MODIFIED_NORETURN_CALLS(fun) (fun)->gimple_df->modified_noreturn_calls
 #define DEFAULT_DEFS(fun) (fun)->gimple_df->default_defs
 
 #define num_ssa_names (vec_safe_length (cfun->gimple_df->ssa_names))
This page took 0.136437 seconds and 5 git commands to generate.