Try to update dominance info in tree-call-cdce.c
authorRichard Sandiford <richard.sandiford@arm.com>
Sat, 7 Nov 2015 09:56:04 +0000 (09:56 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 7 Nov 2015 09:56:04 +0000 (09:56 +0000)
The pass would free the dominance info after making a change, but it
should be pretty easy to keep the information up-to-date when the call
has no EH edges.

Tested on x86_64-linux-gnu, arm-linux-gnueabi and aarch64-linux-gnu.

gcc/
* tree-call-cdce.c (shrink_wrap_one_built_in_call): Try to update
the dominance info; free it if we can't.
(pass_call_cdce::execute): Don't free the dominance info here.

From-SVN: r229916

gcc/ChangeLog
gcc/tree-call-cdce.c

index 78dc3f04bdc9ed53daf673505ff2b3937289947b..6e7ab8e048fc03547c5e62e68ceea3aa85fcc883 100644 (file)
@@ -1,3 +1,9 @@
+2015-11-07  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * tree-call-cdce.c (shrink_wrap_one_built_in_call): Try to update
+       the dominance info; free it if we can't.
+       (pass_call_cdce::execute): Don't free the dominance info here.
+
 2015-11-06  Jeff Law <jeff@redhat.com>
 
        * tree-ssa-threadedge.c (dummy_simplify): Remove.
index ffc1c4ecc4f6e8d11a71ecde07105b280839a4fb..a5f38ce1331454fbfb3a0081b6e6a2f05122fa0b 100644 (file)
@@ -731,6 +731,32 @@ shrink_wrap_one_built_in_call (gcall *bi_call)
   if (nconds == 0)
     return false;
 
+  /* The cfg we want to create looks like this:
+
+          [guard n-1]         <- guard_bb (old block)
+            |    \
+            | [guard n-2]                   }
+            |    / \                        }
+            |   /  ...                      } new blocks
+            |  /  [guard 0]                 }
+            | /    /   |                    }
+           [ call ]    |     <- bi_call_bb  }
+            | \        |
+            |  \       |
+            |   [ join ]     <- join_tgt_bb (old iff call must end bb)
+            |
+        possible EH edges (only if [join] is old)
+
+     When [join] is new, the immediate dominators for these blocks are:
+
+     1. [guard n-1]: unchanged
+     2. [call]: [guard n-1]
+     3. [guard m]: [guard m+1] for 0 <= m <= n-2
+     4. [join]: [guard n-1]
+
+     We punt for the more complex case case of [join] being old and
+     simply free the dominance info.  We also punt on postdominators,
+     which aren't expected to be available at this point anyway.  */
   bi_call_bb = gimple_bb (bi_call);
 
   /* Now find the join target bb -- split bi_call_bb if needed.  */
@@ -741,6 +767,7 @@ shrink_wrap_one_built_in_call (gcall *bi_call)
       join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
       if (join_tgt_in_edge_from_call == NULL)
         return false;
+      free_dominance_info (CDI_DOMINATORS);
     }
   else
     join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
@@ -820,6 +847,15 @@ shrink_wrap_one_built_in_call (gcall *bi_call)
       guard_bb_in_edge->count = guard_bb->count - bi_call_in_edge->count;
     }
 
+  if (dom_info_available_p (CDI_DOMINATORS))
+    {
+      /* The split_blocks leave [guard 0] as the immediate dominator
+        of [call] and [call] as the immediate dominator of [join].
+        Fix them up.  */
+      set_immediate_dominator (CDI_DOMINATORS, bi_call_bb, guard_bb);
+      set_immediate_dominator (CDI_DOMINATORS, join_tgt_bb, guard_bb);
+    }
+
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       location_t loc;
@@ -927,7 +963,6 @@ pass_call_cdce::execute (function *fun)
 
   if (something_changed)
     {
-      free_dominance_info (CDI_DOMINATORS);
       free_dominance_info (CDI_POST_DOMINATORS);
       /* As we introduced new control-flow we need to insert PHI-nodes
          for the call-clobbers of the remaining call.  */