re PR tree-optimization/68619 (error: loop with header 6 not in loop tree)
authorJeff Law <law@redhat.com>
Thu, 10 Dec 2015 16:34:43 +0000 (09:34 -0700)
committerJeff Law <law@gcc.gnu.org>
Thu, 10 Dec 2015 16:34:43 +0000 (09:34 -0700)
2015-12-10  Jeff Law  <law@redhat.com>

PR tree-optimization/68619
* tree-ssa-dom.c (dom_opt_dom_walker::before_dom_children): Propgate
return value from optimize_stmt.
(dom_opt_dom_walker): Add new argument to dom_walker constructor.
(pass_dominator:execute): If a block has an unreachable edge,
remove all jump threads through any successor of the affected block.
(record_equivalences_from_phis): Ignore alternative if the edge
does not have EDGE_EXECUTABLE set.
(single_incoming_edge_ignoring_loop_edges): Similarly.
(optimize_stmt): If a gimple_code has a compile-time constant
condition, return the edge taken for that constant value.  Also
change the condition to true/false as necessary.
* domwalk.h (dom_walker::dom_walker): Add new argument
skip_unreachable_blocks.  Don't provide empty constructor body.
(dom_walker::before_dom_children): Change return type.
(dom_walker::bb_reachable): Declare new private method.
(dom_walker::propagate_unreachable_to_edges): Likewise.
(dom_walker::m_unreachable_dom): Declare new private data member.
(dom_walker::m_skip_unreachable_blocks): Likewise.
* domwalk.c: Include dumpfile.h.
(dom_walker::dom_walker): New constructor.  Initialize private data
members.  If needed, set EDGE_EXECUTABLE for all edges in the CFG,
extracted from tree-ssa-sccvn.c.
(dom_walker::bb_reachable): New method extracted from tree-ssa-sccvn.c
(dom_walker::propagate_unreachable_to_edges): Likewise.
(dom_walker::walk): Only call before_dom_children on reachable
blocks.  If before_dom_children returns an edge, then clear
EDGE_EXECUTABLE for all other outgoing edges from the same block.
For unreachable blocks, call propagate_unreachable_to_edges.
Similarly, only call after_dom_children on reachable blocks.  For
unreachable blocks, conditionally clear m_unreachable_dom.
* tree-ssa-sccvn.c (sccvn_dom_walker::unreachable_dom): Remove
private data member.
(sccvn_dom_walker::after_dom_children): Use methods from dom_walker
class.
(run_scc_vn): Likewise.
(sccvn_dom_walker::before_dom_children): Likewise.  Return the taken
outgoing edge if a COND, SWITCH, or GOTO are optimized.
* compare-elim.c (find_comparison_dom_walker::before_dom_children):
Change return type to an edge.  Always return NULL.
* fwprop.c (single_def_use_dom_walker::before_dom_children): Likewise.
* gimple-ssa-strength-reduction.c
(find_candidates_dom_walker::before_dom_children): Likewise.
* ipa-prop.c (analysis_dom_walker::before_dom_children): Likewise.
(ipcp_modif_dom_walker::before_dom_children): Likewise.
* tree-into-ssa.c (rewrite_dom_walker::before_dom_children): Likewise.
(rewrite_update_dom_walker::before_dom_children): Likewise.
(mark_def_dom_children::before_dom_children): Likewise.
* tree-ssa-dse.c (dse_dom_walker::before_dom_children): Likewise.
* tree-ssa-loop-im.c
(invariantness_dom_walker::before_dom_children): Likewise.
(move_computations_dom_walker::before_dom_walker): Likewise.
* tree-ssa-phiopt.c
(nontrapping_dom_walker::before_dom_children): Likewise.
* tree-ssa-pre.c
(eliminate_dom_walker::before_dom_children): Likewise.
* tree-ssa-propagate.c
(substitute_and_fold_dom_walker::before_dom_children): Likewise.
* tree-ssa-strlen.c
(strlen_dom_walker::before_dom_children): Likewise.
* tree-ssa-uncprop.c
(uncprop_dom_walker::before_dom_children): Likewise.

PR tree-optimization/68619
* gcc.dg/tree-ssa/pr68619-1.c: New test.
* gcc.dg/tree-ssa/pr68619-2.c: New test.
* gcc.dg/tree-ssa/pr68619-3.c: New test.
* gcc.dg/tree-ssa/pr68619-4.c: New test.
* gcc.dg/tree-ssa/pr68619-5.c: New test.

From-SVN: r231527

23 files changed:
gcc/ChangeLog
gcc/compare-elim.c
gcc/domwalk.c
gcc/domwalk.h
gcc/fwprop.c
gcc/gimple-ssa-strength-reduction.c
gcc/ipa-prop.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr68619-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr68619-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr68619-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr68619-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr68619-5.c [new file with mode: 0644]
gcc/tree-into-ssa.c
gcc/tree-ssa-dom.c
gcc/tree-ssa-dse.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-phiopt.c
gcc/tree-ssa-pre.c
gcc/tree-ssa-propagate.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-strlen.c
gcc/tree-ssa-uncprop.c

index 511fd020cfbbb6e060cf3a6dd3bd834c2afdcf29..0a77807efe4f149da192402f0eee27345b6f7503 100644 (file)
@@ -1,3 +1,68 @@
+2015-12-10  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/68619
+       * tree-ssa-dom.c (dom_opt_dom_walker::before_dom_children): Propgate
+       return value from optimize_stmt.
+       (dom_opt_dom_walker): Add new argument to dom_walker constructor.
+       (pass_dominator:execute): If a block has an unreachable edge,
+       remove all jump threads through any successor of the affected block.
+       (record_equivalences_from_phis): Ignore alternative if the edge
+       does not have EDGE_EXECUTABLE set.
+       (single_incoming_edge_ignoring_loop_edges): Similarly.
+       (optimize_stmt): If a gimple_code has a compile-time constant
+       condition, return the edge taken for that constant value.  Also
+       change the condition to true/false as necessary.
+       * domwalk.h (dom_walker::dom_walker): Add new argument
+       skip_unreachable_blocks.  Don't provide empty constructor body.
+       (dom_walker::before_dom_children): Change return type.
+       (dom_walker::bb_reachable): Declare new private method.
+       (dom_walker::propagate_unreachable_to_edges): Likewise.
+       (dom_walker::m_unreachable_dom): Declare new private data member.
+       (dom_walker::m_skip_unreachable_blocks): Likewise.
+       * domwalk.c: Include dumpfile.h.
+       (dom_walker::dom_walker): New constructor.  Initialize private data
+       members.  If needed, set EDGE_EXECUTABLE for all edges in the CFG,
+       extracted from tree-ssa-sccvn.c.
+       (dom_walker::bb_reachable): New method extracted from tree-ssa-sccvn.c
+       (dom_walker::propagate_unreachable_to_edges): Likewise.
+       (dom_walker::walk): Only call before_dom_children on reachable
+       blocks.  If before_dom_children returns an edge, then clear
+       EDGE_EXECUTABLE for all other outgoing edges from the same block.
+       For unreachable blocks, call propagate_unreachable_to_edges.
+       Similarly, only call after_dom_children on reachable blocks.  For
+       unreachable blocks, conditionally clear m_unreachable_dom.
+       * tree-ssa-sccvn.c (sccvn_dom_walker::unreachable_dom): Remove
+       private data member.
+       (sccvn_dom_walker::after_dom_children): Use methods from dom_walker
+       class.
+       (run_scc_vn): Likewise.
+       (sccvn_dom_walker::before_dom_children): Likewise.  Return the taken
+       outgoing edge if a COND, SWITCH, or GOTO are optimized.
+       * compare-elim.c (find_comparison_dom_walker::before_dom_children):
+       Change return type to an edge.  Always return NULL.
+       * fwprop.c (single_def_use_dom_walker::before_dom_children): Likewise.
+       * gimple-ssa-strength-reduction.c
+       (find_candidates_dom_walker::before_dom_children): Likewise.
+       * ipa-prop.c (analysis_dom_walker::before_dom_children): Likewise.
+       (ipcp_modif_dom_walker::before_dom_children): Likewise.
+       * tree-into-ssa.c (rewrite_dom_walker::before_dom_children): Likewise.
+       (rewrite_update_dom_walker::before_dom_children): Likewise.
+       (mark_def_dom_children::before_dom_children): Likewise.
+       * tree-ssa-dse.c (dse_dom_walker::before_dom_children): Likewise.
+       * tree-ssa-loop-im.c
+       (invariantness_dom_walker::before_dom_children): Likewise.
+       (move_computations_dom_walker::before_dom_walker): Likewise.
+       * tree-ssa-phiopt.c
+       (nontrapping_dom_walker::before_dom_children): Likewise.
+       * tree-ssa-pre.c
+       (eliminate_dom_walker::before_dom_children): Likewise.
+       * tree-ssa-propagate.c
+       (substitute_and_fold_dom_walker::before_dom_children): Likewise.
+       * tree-ssa-strlen.c
+       (strlen_dom_walker::before_dom_children): Likewise.
+       * tree-ssa-uncprop.c
+       (uncprop_dom_walker::before_dom_children): Likewise.
+
 2015-12-10  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/68376
index 54b26ba40297544f40b6d19bee5e0cc1d43854df..5f74db027dbf08333aa457d440143824e1b31552 100644 (file)
@@ -248,7 +248,7 @@ public:
   find_comparison_dom_walker (cdi_direction direction)
     : dom_walker (direction) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 };
 
 /* Return true if conforming COMPARE with EH_NOTE is redundant with comparison
@@ -294,7 +294,7 @@ can_eliminate_compare (rtx compare, rtx eh_note, struct comparison *cmp)
    compare in the BB is live at the end of the block, install the compare
    in BB->AUX.  Called via dom_walker.walk ().  */
 
-void
+edge
 find_comparison_dom_walker::before_dom_children (basic_block bb)
 {
   struct comparison *last_cmp;
@@ -426,6 +426,8 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
      remove EH edges.  */
   if (need_purge)
     purge_dead_edges (bb);
+
+  return NULL;
 }
 
 /* Find all comparisons in the function.  */
index 167fc384a5d3f0f291ae115af3a2d998ed771556..2481e34ea6e80e88d112ab038a6fff3c78415b40 100644 (file)
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "backend.h"
 #include "cfganal.h"
 #include "domwalk.h"
+#include "dumpfile.h"
 
 /* This file implements a generic walker for dominator trees.
 
@@ -142,6 +143,91 @@ cmp_bb_postorder (const void *a, const void *b)
   return 1;
 }
 
+/* Constructor for a dom walker.
+
+   If SKIP_UNREACHBLE_BLOCKS is true, then we need to set
+   EDGE_EXECUTABLE on every edge in the CFG. */
+dom_walker::dom_walker (cdi_direction direction,
+                       bool skip_unreachable_blocks)
+  : m_dom_direction (direction),
+    m_skip_unreachable_blocks (skip_unreachable_blocks),
+    m_unreachable_dom (NULL)
+{
+  /* If we are not skipping unreachable blocks, then there is nothing
+     to do.  */
+  if (!m_skip_unreachable_blocks)
+    return;
+
+  basic_block bb;
+  FOR_ALL_BB_FN (bb, cfun)
+    {
+      edge_iterator ei;
+      edge e;
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       e->flags |= EDGE_EXECUTABLE;
+    }
+}
+
+/* Return TRUE if BB is reachable, false otherwise.  */
+
+bool
+dom_walker::bb_reachable (struct function *fun, basic_block bb)
+{
+  /* If we're not skipping unreachable blocks, then assume everything
+     is reachable.  */
+  if (!m_skip_unreachable_blocks)
+    return true;
+
+  /* If any of the predecessor edges that do not come from blocks dominated
+     by us are still marked as possibly executable consider this block
+     reachable.  */
+  bool reachable = false;
+  if (!m_unreachable_dom)
+    {
+      reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (fun);
+      edge_iterator ei;
+      edge e;
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
+         reachable |= (e->flags & EDGE_EXECUTABLE);
+    }
+
+  return reachable;
+}
+
+/* BB has been determined to be unreachable.  Propagate that property
+   to incoming and outgoing edges of BB as appropriate.  */
+
+void
+dom_walker::propagate_unreachable_to_edges (basic_block bb,
+                                           FILE *dump_file,
+                                           int dump_flags)
+{
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "Marking all outgoing edges of unreachable "
+            "BB %d as not executable\n", bb->index);
+
+  edge_iterator ei;
+  edge e;
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    e->flags &= ~EDGE_EXECUTABLE;
+
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    {
+      if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file, "Marking backedge from BB %d into "
+                    "unreachable BB %d as not executable\n",
+                    e->src->index, bb->index);
+         e->flags &= ~EDGE_EXECUTABLE;
+       }
+    }
+
+  if (!m_unreachable_dom)
+    m_unreachable_dom = bb;
+}
+
 /* Recursively walk the dominator tree.
    BB is the basic block we are currently visiting.  */
 
@@ -171,9 +257,23 @@ dom_walker::walk (basic_block bb)
          || bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
          || bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
        {
+
          /* Callback for subclasses to do custom things before we have walked
             the dominator children, but before we walk statements.  */
-         before_dom_children (bb);
+         if (this->bb_reachable (cfun, bb))
+           {
+             edge taken_edge = before_dom_children (bb);
+             if (taken_edge)
+               {
+                 edge_iterator ei;
+                 edge e;
+                 FOR_EACH_EDGE (e, ei, bb->succs)
+                   if (e != taken_edge)
+                     e->flags &= ~EDGE_EXECUTABLE;
+               }
+           }
+         else
+           propagate_unreachable_to_edges (bb, dump_file, dump_flags);
 
          /* Mark the current BB to be popped out of the recursion stack
             once children are processed.  */
@@ -203,7 +303,10 @@ dom_walker::walk (basic_block bb)
 
          /* Callback allowing subclasses to do custom things after we have
             walked dominator children, but before we walk statements.  */
-         after_dom_children (bb);
+         if (bb_reachable (cfun, bb))
+           after_dom_children (bb);
+         else if (m_unreachable_dom == bb)
+           m_unreachable_dom = NULL;
        }
       if (sp)
        bb = worklist[--sp];
index 71a7c47b00aa0d5a7cb8fa8ce6cdfaf0d9ce444b..e631a675155abba967ba2f296fa1b7b58d1aee79 100644 (file)
@@ -30,13 +30,26 @@ along with GCC; see the file COPYING3.  If not see
 class dom_walker
 {
 public:
-  dom_walker (cdi_direction direction) : m_dom_direction (direction) {}
+  /* Use SKIP_UNREACHBLE_BLOCKS = true when your client can discover
+     that some edges are not executable.
+
+     If a client can discover that a COND, SWITCH or GOTO has a static
+     target in the before_dom_children callback, the taken edge should
+     be returned.  The generic walker will clear EDGE_EXECUTABLE on all
+     edges it can determine are not executable.  */
+  dom_walker (cdi_direction direction, bool skip_unreachable_blocks = false);
 
   /* Walk the dominator tree.  */
   void walk (basic_block);
 
-  /* Function to call before the recursive walk of the dominator children.  */
-  virtual void before_dom_children (basic_block) {}
+  /* Function to call before the recursive walk of the dominator children.
+
+     Return value is the always taken edge if the block has multiple outgoing
+     edges, NULL otherwise.  When skipping unreachable blocks, the walker
+     uses the taken edge information to clear EDGE_EXECUTABLE on the other
+     edges, exposing unreachable blocks.  A NULL return value means all
+     outgoing edges should still be considered executable.  */
+  virtual edge before_dom_children (basic_block) { return NULL; }
 
   /* Function to call after the recursive walk of the dominator children.  */
   virtual void after_dom_children (basic_block) {}
@@ -47,6 +60,18 @@ private:
      if it is set to CDI_POST_DOMINATORS, then we walk the post
      dominator tree.  */
   const ENUM_BITFIELD (cdi_direction) m_dom_direction : 2;
+  bool m_skip_unreachable_blocks;
+  basic_block m_unreachable_dom;
+
+  /* Query whether or not the given block is reachable or not.  */
+  bool bb_reachable (struct function *, basic_block);
+
+  /* Given an unreachable block, propagate that property to outgoing
+     and possibly incoming edges for the block.  Typically called after
+     determining a block is unreachable in the before_dom_children
+     callback.  */
+  void propagate_unreachable_to_edges (basic_block, FILE *, int);
+
 };
 
 #endif
index 863e35de6004640bb4810160469c8d2d2885e45e..5f61130af5245fe270e7af160fe42a168ec6bb29 100644 (file)
@@ -208,11 +208,11 @@ class single_def_use_dom_walker : public dom_walker
 public:
   single_def_use_dom_walker (cdi_direction direction)
     : dom_walker (direction) {}
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 };
 
-void
+edge
 single_def_use_dom_walker::before_dom_children (basic_block bb)
 {
   int bb_index = bb->index;
@@ -245,6 +245,8 @@ single_def_use_dom_walker::before_dom_children (basic_block bb)
 
   process_uses (df_get_artificial_uses (bb_index), 0);
   process_defs (df_get_artificial_defs (bb_index), 0);
+
+  return NULL;
 }
 
 /* Pop the definitions created in this basic block when leaving its
index b8078230f340241b030f48a6fade564a22859b40..e184a1bcd6eb4b87fa262a4aafe9210050718245 100644 (file)
@@ -1649,12 +1649,12 @@ class find_candidates_dom_walker : public dom_walker
 public:
   find_candidates_dom_walker (cdi_direction direction)
     : dom_walker (direction) {}
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 };
 
 /* Find strength-reduction candidates in block BB.  */
 
-void
+edge
 find_candidates_dom_walker::before_dom_children (basic_block bb)
 {
   bool speed = optimize_bb_for_speed_p (bb);
@@ -1737,6 +1737,7 @@ find_candidates_dom_walker::before_dom_children (basic_block bb)
            }
        }
     }
+  return NULL;
 }
 \f
 /* Dump a candidate for debug.  */
index f379ea73909e21edf89d3b7087c6dee650df548f..f96bf970ee10cfca3654751e83cb4d2cbe4b7e16 100644 (file)
@@ -2245,17 +2245,18 @@ public:
   analysis_dom_walker (struct ipa_func_body_info *fbi)
     : dom_walker (CDI_DOMINATORS), m_fbi (fbi) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 
 private:
   struct ipa_func_body_info *m_fbi;
 };
 
-void
+edge
 analysis_dom_walker::before_dom_children (basic_block bb)
 {
   ipa_analyze_params_uses_in_bb (m_fbi, bb);
   ipa_compute_jump_functions_for_bb (m_fbi, bb);
+  return NULL;
 }
 
 /* Release body info FBI.  */
@@ -5098,7 +5099,7 @@ public:
     : dom_walker (CDI_DOMINATORS), m_fbi (fbi), m_descriptors (descs),
       m_aggval (av), m_something_changed (sc), m_cfg_changed (cc) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 
 private:
   struct ipa_func_body_info *m_fbi;
@@ -5107,7 +5108,7 @@ private:
   bool *m_something_changed, *m_cfg_changed;
 };
 
-void
+edge
 ipcp_modif_dom_walker::before_dom_children (basic_block bb)
 {
   gimple_stmt_iterator gsi;
@@ -5198,7 +5199,7 @@ ipcp_modif_dom_walker::before_dom_children (basic_block bb)
          && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
        *m_cfg_changed = true;
     }
-
+  return NULL;
 }
 
 /* Update alignment of formal parameters as described in
index e076b6a65faf6d5d0c5ee09c03cf260f0492bbe4..6bcacab080e047bf92408960e8f53fda1b0ef7b8 100644 (file)
@@ -1,3 +1,12 @@
+2015-12-10  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/68619
+       * gcc.dg/tree-ssa/pr68619-1.c: New test.
+       * gcc.dg/tree-ssa/pr68619-2.c: New test.
+       * gcc.dg/tree-ssa/pr68619-3.c: New test.
+       * gcc.dg/tree-ssa/pr68619-4.c: New test.
+       * gcc.dg/tree-ssa/pr68619-5.c: New test.
+
 2015-12-10  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/68376
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68619-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68619-1.c
new file mode 100644 (file)
index 0000000..3e988de
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -w" } */
+
+extern void fn2(int);
+int a, b, c;
+void fn1() {
+  int d;
+  for (; b; b++) {
+    a = 7;
+    for (; a;) {
+    jump:
+      fn2(d ?: c);
+      d = 0;
+    }
+    d = c;
+    if (c)
+      goto jump;
+  }
+  goto jump;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68619-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68619-2.c
new file mode 100644 (file)
index 0000000..cca706e
--- /dev/null
@@ -0,0 +1,92 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
+
+typedef union tree_node *tree;
+struct gcc_options
+{
+  int x_flag_finite_math_only;
+};
+extern struct gcc_options global_options;
+enum mode_class
+{ MODE_RANDOM, MODE_CC, MODE_INT, MODE_PARTIAL_INT, MODE_FRACT, MODE_UFRACT,
+  MODE_ACCUM, MODE_UACCUM, MODE_FLOAT, MODE_DECIMAL_FLOAT, MODE_COMPLEX_INT,
+  MODE_COMPLEX_FLOAT, MODE_VECTOR_INT, MODE_VECTOR_FRACT,
+  MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM,
+  MODE_VECTOR_FLOAT, MAX_MODE_CLASS
+};
+extern const unsigned char mode_class[27];
+extern const unsigned char mode_inner[27];
+struct real_value
+{
+};
+struct real_format
+{
+  unsigned char has_inf;
+};
+extern const struct real_format *real_format_for_mode[5 -
+                                                     2 + 1 + 15 - 10 + 1];
+struct tree_type
+{
+};
+union tree_node
+{
+  int code;
+  int mode;
+  struct tree_type type;
+};
+tree
+omp_reduction_init (tree clause, tree type)
+{
+  if ((((type)->code) == 64))
+    {
+      struct real_value max;
+      if (((((mode_class[((((type))->code) ==
+                         32 ?
+                         vector_type_mode (type)
+                         : (type)->mode)]) ==
+            MODE_VECTOR_FLOAT)
+           &&
+           ((real_format_for_mode
+             [((mode_class[((mode_class[((((type))->code) ==
+                                         32 ?
+                                         vector_type_mode (type)
+                                         : (type)->mode)]) ==
+                            12) ? (((((type))->code)
+                                    ==
+                                    32 ?
+                                    vector_type_mode
+                                    (type)
+                                    : (type)->mode))
+                           : (mode_inner[((((type))->code) ==
+                                          32 ?
+                                          vector_type_mode (type)
+                                          : (type)->mode)])]) ==
+               12)
+              ? (((((mode_class[((((type))->code) ==
+                                 32 ? vector_type_mode (type)
+                                 : (type)->mode)]) ==
+                    12) ? (((((type))->code) ==
+                            32 ?
+                            vector_type_mode (type)
+                            : (type)->mode)) : (mode_inner
+                                                [((((type))->code) ==
+                                                  32 ?
+                                                  vector_type_mode (type)
+                                                  : (type)->mode)])) - 10) +
+                 (5 - 2 +
+                  1))
+              : ((((mode_class
+                    [((((type))->code) ==
+                      32 ? vector_type_mode (type) : (type)->mode)]) ==
+                   12) ? (((((type))->code) ==
+                           32 ? vector_type_mode (type) : (type)->
+                           mode)) : (mode_inner[((((type))->code) ==
+                                                 32 ? vector_type_mode (type)
+                                                 : (type)->mode)])) -
+                 2)]))->has_inf) && !global_options.x_flag_finite_math_only))
+       real_inf (&max);
+    }
+}
+
+/* { dg-final { scan-tree-dump "Marking all outgoing edges of unreachable" "dom2"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68619-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68619-3.c
new file mode 100644 (file)
index 0000000..3548725
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -w" } */
+typedef unsigned int hashval_t;
+enum ETYPE
+{
+  ETYPE_ARRAY, ETYPE_STRUCT, ETYPE_UNION,
+};
+struct entry
+{
+  enum ETYPE etype:8;
+  unsigned short len;
+  const char *attrib;
+};
+e_hash (const void *a)
+{
+  const struct entry *e = a;
+  hashval_t ret = 0;
+  int i;
+  if (e[0].etype != ETYPE_STRUCT && e[0].etype != ETYPE_UNION)
+    abort ();
+  for (i = 0; i <= e[0].len; ++i)
+    {
+      ret = iterative_hash (&e[i], __builtin_offsetof (struct entry, attrib), ret);
+    }
+  return ret;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68619-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68619-4.c
new file mode 100644 (file)
index 0000000..da3cdb9
--- /dev/null
@@ -0,0 +1,94 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -w" } */
+
+typedef struct rtx_def *rtx;
+enum rtx_code
+{
+  UNKNOWN, VALUE, DEBUG_EXPR, EXPR_LIST, INSN_LIST, SEQUENCE, ADDRESS,
+  DEBUG_INSN, INSN, JUMP_INSN, CALL_INSN, BARRIER, CODE_LABEL, NOTE,
+  COND_EXEC, PARALLEL, ASM_INPUT, ASM_OPERANDS, UNSPEC, UNSPEC_VOLATILE,
+  ADDR_VEC, ADDR_DIFF_VEC, PREFETCH, SET, USE, CLOBBER, CALL, RETURN,
+  EH_RETURN, TRAP_IF, CONST_INT, CONST_FIXED, CONST_DOUBLE, CONST_VECTOR,
+  CONST_STRING, CONST, PC, REG, SCRATCH, SUBREG, STRICT_LOW_PART, CONCAT,
+  CONCATN, MEM, LABEL_REF, SYMBOL_REF, CC0, IF_THEN_ELSE, COMPARE, PLUS,
+  MINUS, NEG, MULT, SS_MULT, US_MULT, DIV, SS_DIV, US_DIV, MOD, UDIV, UMOD,
+  AND, IOR, XOR, NOT, ASHIFT, ROTATE, ASHIFTRT, LSHIFTRT, ROTATERT, SMIN,
+  SMAX, UMIN, UMAX, PRE_DEC, PRE_INC, POST_DEC, POST_INC, PRE_MODIFY,
+  POST_MODIFY, NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU, UNORDERED,
+  ORDERED, UNEQ, UNGE, UNGT, UNLE, UNLT, LTGT, SIGN_EXTEND, ZERO_EXTEND,
+  TRUNCATE, FLOAT_EXTEND, FLOAT_TRUNCATE, FLOAT, FIX, UNSIGNED_FLOAT,
+  UNSIGNED_FIX, FRACT_CONVERT, UNSIGNED_FRACT_CONVERT, SAT_FRACT,
+  UNSIGNED_SAT_FRACT, ABS, SQRT, BSWAP, FFS, CLZ, CTZ, POPCOUNT, PARITY,
+  SIGN_EXTRACT, ZERO_EXTRACT, HIGH, LO_SUM, VEC_MERGE, VEC_SELECT,
+  VEC_CONCAT, VEC_DUPLICATE, SS_PLUS, US_PLUS, SS_MINUS, SS_NEG, US_NEG,
+  SS_ABS, SS_ASHIFT, US_ASHIFT, US_MINUS, SS_TRUNCATE, US_TRUNCATE, FMA,
+  VAR_LOCATION, DEBUG_IMPLICIT_PTR, ENTRY_VALUE, LAST_AND_UNUSED_RTX_CODE
+};
+enum rtx_class
+{
+  RTX_COMPARE, RTX_COMM_COMPARE, RTX_BIN_ARITH, RTX_COMM_ARITH, RTX_UNARY,
+  RTX_EXTRA, RTX_MATCH, RTX_INSN, RTX_OBJ, RTX_CONST_OBJ, RTX_TERNARY,
+  RTX_BITFIELD_OPS, RTX_AUTOINC
+};
+extern const unsigned char rtx_length[((int) LAST_AND_UNUSED_RTX_CODE)];
+extern const enum rtx_class rtx_class[((int) LAST_AND_UNUSED_RTX_CODE)];
+union rtunion_def
+{
+  rtx rt_rtx;
+};
+typedef union rtunion_def rtunion;
+struct rtx_def
+{
+  enum rtx_code code:16;
+  union u
+  {
+    rtunion fld[1];
+  }
+  u;
+};
+struct cse_reg_info
+{
+  unsigned int timestamp;
+  int reg_qty;
+  int reg_tick;
+  int reg_in_table;
+  unsigned int subreg_ticked;
+};
+static struct cse_reg_info *cse_reg_info_table;
+static unsigned int cse_reg_info_timestamp;
+
+static __inline__ struct cse_reg_info *
+get_cse_reg_info (unsigned int regno)
+{
+  struct cse_reg_info *p = &cse_reg_info_table[regno];
+  if (p->timestamp != cse_reg_info_timestamp)
+    cse_reg_info_table[regno].timestamp = cse_reg_info_timestamp;
+}
+
+int
+mention_regs (rtx x)
+{
+  enum rtx_code code;
+  int i, j;
+  const char *fmt;
+  int changed = 0;
+  code = ((x)->code);
+  if (code == SUBREG
+      && ((((((x)->u.fld[0]).rt_rtx))->code) == REG))
+    {
+      (get_cse_reg_info (i)->reg_in_table) = (get_cse_reg_info (i)->reg_tick);
+      (get_cse_reg_info (i)->subreg_ticked) =
+       (rhs_regno ((((x)->u.fld[0]).rt_rtx)));
+    }
+  if ((((rtx_class[(int) (((x)->code))]) & (~1)) == (RTX_COMPARE & (~1))))
+    {
+      if (((((((x)->u.fld[0]).rt_rtx))->code) == REG))
+       foop ();
+    }
+  for (i = (rtx_length[(int) (code)]) - 1; i >= 0; i--)
+       arf ();
+}
+
+/* Make sure the constant 39 gets propagated into the PHI at the join point.  */
+/* { dg-final { scan-tree-dump "PHI <.*, 39" "optimized"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68619-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68619-5.c
new file mode 100644 (file)
index 0000000..7eee1b8
--- /dev/null
@@ -0,0 +1,172 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -w" } */
+typedef union tree_node *tree;
+typedef union gimple_statement_d *gimple;
+enum machine_mode
+{ VOIDmode, BLKmode, CCmode, CCGCmode, CCGOCmode, CCNOmode, CCAmode, CCCmode,
+    CCOmode, CCSmode, CCZmode, CCFPmode, CCFPUmode, BImode, QImode, HImode,
+    SImode, DImode, TImode, OImode, QQmode, HQmode, SQmode, DQmode, TQmode,
+    UQQmode, UHQmode, USQmode, UDQmode, UTQmode, HAmode, SAmode, DAmode,
+    TAmode, UHAmode, USAmode, UDAmode, UTAmode, SFmode, DFmode, XFmode,
+    TFmode, SDmode, DDmode, TDmode, CQImode, CHImode, CSImode, CDImode,
+    CTImode, COImode, SCmode, DCmode, XCmode, TCmode, V2QImode, V4QImode,
+    V2HImode, V1SImode, V8QImode, V4HImode, V2SImode, V1DImode, V16QImode,
+    V8HImode, V4SImode, V2DImode, V1TImode, V32QImode, V16HImode, V8SImode,
+    V4DImode, V2TImode, V64QImode, V32HImode, V16SImode, V8DImode, V4TImode,
+    V2SFmode, V4SFmode, V2DFmode, V8SFmode, V4DFmode, V2TFmode, V16SFmode,
+    V8DFmode, V4TFmode, MAX_MACHINE_MODE, MIN_MODE_RANDOM =
+    VOIDmode, MAX_MODE_RANDOM = BLKmode, MIN_MODE_CC = CCmode, MAX_MODE_CC =
+    CCFPUmode, MIN_MODE_INT = QImode, MAX_MODE_INT =
+    OImode, MIN_MODE_PARTIAL_INT = VOIDmode, MAX_MODE_PARTIAL_INT =
+    VOIDmode, MIN_MODE_FRACT = QQmode, MAX_MODE_FRACT =
+    TQmode, MIN_MODE_UFRACT = UQQmode, MAX_MODE_UFRACT =
+    UTQmode, MIN_MODE_ACCUM = HAmode, MAX_MODE_ACCUM =
+    TAmode, MIN_MODE_UACCUM = UHAmode, MAX_MODE_UACCUM =
+    UTAmode, MIN_MODE_FLOAT = SFmode, MAX_MODE_FLOAT =
+    TFmode, MIN_MODE_DECIMAL_FLOAT = SDmode, MAX_MODE_DECIMAL_FLOAT =
+    TDmode, MIN_MODE_COMPLEX_INT = CQImode, MAX_MODE_COMPLEX_INT =
+    COImode, MIN_MODE_COMPLEX_FLOAT = SCmode, MAX_MODE_COMPLEX_FLOAT =
+    TCmode, MIN_MODE_VECTOR_INT = V2QImode, MAX_MODE_VECTOR_INT =
+    V4TImode, MIN_MODE_VECTOR_FRACT = VOIDmode, MAX_MODE_VECTOR_FRACT =
+    VOIDmode, MIN_MODE_VECTOR_UFRACT = VOIDmode, MAX_MODE_VECTOR_UFRACT =
+    VOIDmode, MIN_MODE_VECTOR_ACCUM = VOIDmode, MAX_MODE_VECTOR_ACCUM =
+    VOIDmode, MIN_MODE_VECTOR_UACCUM = VOIDmode, MAX_MODE_VECTOR_UACCUM =
+    VOIDmode, MIN_MODE_VECTOR_FLOAT = V2SFmode, MAX_MODE_VECTOR_FLOAT =
+    V4TFmode, NUM_MACHINE_MODES = MAX_MACHINE_MODE };
+enum mode_class
+{ MODE_RANDOM, MODE_CC, MODE_INT, MODE_PARTIAL_INT, MODE_FRACT, MODE_UFRACT,
+    MODE_ACCUM, MODE_UACCUM, MODE_FLOAT, MODE_DECIMAL_FLOAT, MODE_COMPLEX_INT,
+    MODE_COMPLEX_FLOAT, MODE_VECTOR_INT, MODE_VECTOR_FRACT,
+    MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM,
+    MODE_VECTOR_FLOAT, MAX_MODE_CLASS };
+extern const unsigned char mode_class[NUM_MACHINE_MODES];
+extern const unsigned char mode_inner[NUM_MACHINE_MODES];
+struct real_format
+{
+  unsigned char has_nans;
+};
+extern const struct real_format *real_format_for_mode[MAX_MODE_FLOAT -
+                                                     MIN_MODE_FLOAT + 1 +
+                                                     MAX_MODE_DECIMAL_FLOAT -
+                                                     MIN_MODE_DECIMAL_FLOAT +
+                                                     1];
+enum tree_code
+{ ERROR_MARK, IDENTIFIER_NODE, TREE_LIST, TREE_VEC, BLOCK, OFFSET_TYPE,
+    ENUMERAL_TYPE, BOOLEAN_TYPE, INTEGER_TYPE, REAL_TYPE, POINTER_TYPE,
+    REFERENCE_TYPE, NULLPTR_TYPE, FIXED_POINT_TYPE, COMPLEX_TYPE, VECTOR_TYPE,
+    ARRAY_TYPE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, VOID_TYPE,
+    FUNCTION_TYPE, METHOD_TYPE, LANG_TYPE, INTEGER_CST, REAL_CST, FIXED_CST,
+    COMPLEX_CST, VECTOR_CST, STRING_CST, FUNCTION_DECL, LABEL_DECL,
+    FIELD_DECL, VAR_DECL, CONST_DECL, PARM_DECL, TYPE_DECL, RESULT_DECL,
+    DEBUG_EXPR_DECL, NAMESPACE_DECL, IMPORTED_DECL, TRANSLATION_UNIT_DECL,
+    COMPONENT_REF, BIT_FIELD_REF, REALPART_EXPR, IMAGPART_EXPR, ARRAY_REF,
+    ARRAY_RANGE_REF, INDIRECT_REF, OBJ_TYPE_REF, CONSTRUCTOR, COMPOUND_EXPR,
+    MODIFY_EXPR, INIT_EXPR, TARGET_EXPR, COND_EXPR, VEC_COND_EXPR, BIND_EXPR,
+    CALL_EXPR, WITH_CLEANUP_EXPR, CLEANUP_POINT_EXPR, PLACEHOLDER_EXPR,
+    PLUS_EXPR, MINUS_EXPR, MULT_EXPR, POINTER_PLUS_EXPR, TRUNC_DIV_EXPR,
+    CEIL_DIV_EXPR, FLOOR_DIV_EXPR, ROUND_DIV_EXPR, TRUNC_MOD_EXPR,
+    CEIL_MOD_EXPR, FLOOR_MOD_EXPR, ROUND_MOD_EXPR, RDIV_EXPR, EXACT_DIV_EXPR,
+    FIX_TRUNC_EXPR, FLOAT_EXPR, NEGATE_EXPR, MIN_EXPR, MAX_EXPR, ABS_EXPR,
+    LSHIFT_EXPR, RSHIFT_EXPR, LROTATE_EXPR, RROTATE_EXPR, BIT_IOR_EXPR,
+    BIT_XOR_EXPR, BIT_AND_EXPR, BIT_NOT_EXPR, TRUTH_ANDIF_EXPR,
+    TRUTH_ORIF_EXPR, TRUTH_AND_EXPR, TRUTH_OR_EXPR, TRUTH_XOR_EXPR,
+    TRUTH_NOT_EXPR, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR, NE_EXPR,
+    UNORDERED_EXPR, ORDERED_EXPR, UNLT_EXPR, UNLE_EXPR, UNGT_EXPR, UNGE_EXPR,
+    UNEQ_EXPR, LTGT_EXPR, RANGE_EXPR, PAREN_EXPR, CONVERT_EXPR,
+    ADDR_SPACE_CONVERT_EXPR, FIXED_CONVERT_EXPR, NOP_EXPR, NON_LVALUE_EXPR,
+    VIEW_CONVERT_EXPR, COMPOUND_LITERAL_EXPR, SAVE_EXPR, ADDR_EXPR,
+    FDESC_EXPR, COMPLEX_EXPR, CONJ_EXPR, PREDECREMENT_EXPR, PREINCREMENT_EXPR,
+    POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, VA_ARG_EXPR, TRY_CATCH_EXPR,
+    TRY_FINALLY_EXPR, DECL_EXPR, LABEL_EXPR, GOTO_EXPR, RETURN_EXPR,
+    EXIT_EXPR, LOOP_EXPR, SWITCH_EXPR, CASE_LABEL_EXPR, ASM_EXPR, SSA_NAME,
+    CATCH_EXPR, EH_FILTER_EXPR, SCEV_KNOWN, SCEV_NOT_KNOWN, POLYNOMIAL_CHREC,
+    STATEMENT_LIST, ASSERT_EXPR, TREE_BINFO, WITH_SIZE_EXPR,
+    REALIGN_LOAD_EXPR, TARGET_MEM_REF, MEM_REF, OMP_PARALLEL, OMP_TASK,
+    OMP_FOR, OMP_SECTIONS, OMP_SINGLE, OMP_SECTION, OMP_MASTER, OMP_ORDERED,
+    OMP_CRITICAL, OMP_ATOMIC, OMP_CLAUSE, REDUC_MAX_EXPR, REDUC_MIN_EXPR,
+    REDUC_PLUS_EXPR, DOT_PROD_EXPR, WIDEN_SUM_EXPR, WIDEN_MULT_EXPR,
+    WIDEN_MULT_PLUS_EXPR, WIDEN_MULT_MINUS_EXPR, FMA_EXPR, VEC_LSHIFT_EXPR,
+    VEC_RSHIFT_EXPR, VEC_WIDEN_MULT_HI_EXPR, VEC_WIDEN_MULT_LO_EXPR,
+    VEC_UNPACK_HI_EXPR, VEC_UNPACK_LO_EXPR, VEC_UNPACK_FLOAT_HI_EXPR,
+    VEC_UNPACK_FLOAT_LO_EXPR, VEC_PACK_TRUNC_EXPR, VEC_PACK_SAT_EXPR,
+    VEC_PACK_FIX_TRUNC_EXPR, VEC_EXTRACT_EVEN_EXPR, VEC_EXTRACT_ODD_EXPR,
+    VEC_INTERLEAVE_HIGH_EXPR, VEC_INTERLEAVE_LOW_EXPR, PREDICT_EXPR,
+    OPTIMIZATION_NODE, TARGET_OPTION_NODE, LAST_AND_UNUSED_TREE_CODE,
+    C_MAYBE_CONST_EXPR, EXCESS_PRECISION_EXPR, UNCONSTRAINED_ARRAY_TYPE,
+    UNCONSTRAINED_ARRAY_REF, NULL_EXPR, PLUS_NOMOD_EXPR, MINUS_NOMOD_EXPR,
+    ATTR_ADDR_EXPR, STMT_STMT, LOOP_STMT, EXIT_STMT, OFFSET_REF, PTRMEM_CST,
+    NEW_EXPR, VEC_NEW_EXPR, DELETE_EXPR, VEC_DELETE_EXPR, SCOPE_REF,
+    MEMBER_REF, TYPE_EXPR, AGGR_INIT_EXPR, VEC_INIT_EXPR, THROW_EXPR,
+    EMPTY_CLASS_EXPR, BASELINK, TEMPLATE_DECL, TEMPLATE_PARM_INDEX,
+    TEMPLATE_TEMPLATE_PARM, TEMPLATE_TYPE_PARM, TYPENAME_TYPE, TYPEOF_TYPE,
+    BOUND_TEMPLATE_TEMPLATE_PARM, UNBOUND_CLASS_TEMPLATE, USING_DECL,
+    USING_STMT, DEFAULT_ARG, TEMPLATE_ID_EXPR, OVERLOAD, PSEUDO_DTOR_EXPR,
+    MODOP_EXPR, CAST_EXPR, REINTERPRET_CAST_EXPR, CONST_CAST_EXPR,
+    STATIC_CAST_EXPR, DYNAMIC_CAST_EXPR, DOTSTAR_EXPR, TYPEID_EXPR,
+    NOEXCEPT_EXPR, NON_DEPENDENT_EXPR, CTOR_INITIALIZER, TRY_BLOCK,
+    EH_SPEC_BLOCK, HANDLER, MUST_NOT_THROW_EXPR, CLEANUP_STMT, IF_STMT,
+    FOR_STMT, RANGE_FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT, CONTINUE_STMT,
+    SWITCH_STMT, EXPR_STMT, TAG_DEFN, OFFSETOF_EXPR, SIZEOF_EXPR, ARROW_EXPR,
+    ALIGNOF_EXPR, AT_ENCODE_EXPR, STMT_EXPR, UNARY_PLUS_EXPR, STATIC_ASSERT,
+    TYPE_ARGUMENT_PACK, NONTYPE_ARGUMENT_PACK, TYPE_PACK_EXPANSION,
+    EXPR_PACK_EXPANSION, ARGUMENT_PACK_SELECT, TRAIT_EXPR, LAMBDA_EXPR,
+    DECLTYPE_TYPE, TEMPLATE_INFO, URSHIFT_EXPR, COMPARE_EXPR, COMPARE_L_EXPR,
+    COMPARE_G_EXPR, CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
+    CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
+    PROTOCOL_INTERFACE_TYPE, KEYWORD_DECL, INSTANCE_METHOD_DECL,
+    CLASS_METHOD_DECL, PROPERTY_DECL, MESSAGE_SEND_EXPR, CLASS_REFERENCE_EXPR,
+    PROPERTY_REF, MAX_TREE_CODES };
+struct tree_base
+{
+  enum tree_code code:16;
+};
+struct tree_typed
+{
+  tree type;
+};
+struct tree_type
+{
+  enum machine_mode mode:8;
+};
+union tree_node
+{
+  struct tree_base base;
+  struct tree_typed typed;
+  struct tree_type type;
+};
+enum tree_code
+parse_predicate (tree cond, tree * op0, tree * op1)
+{
+  gimple s;
+  tree op;
+  tree type = (*(&op->typed.type));
+  enum tree_code code;
+  return invert_tree_comparison (code,
+                                ((((mode_class
+                                    [((((type))->base.code) ==
+                                      VECTOR_TYPE ? vector_type_mode (type)
+                                      : (type)->type.mode)]) ==
+                                   MODE_VECTOR_FLOAT)
+                                  &&
+                                  ((real_format_for_mode
+                                    [(((enum mode_class)
+                                       mode_class[(((enum mode_class)
+                                                    mode_class[((((type))->
+                                                                 base.
+                                                                 code) ==
+                                                                VECTOR_TYPE ?
+                                                                vector_type_mode
+                                                                (type)
+                                                                : (type)->
+                                                                type.
+                                                                mode)]) ==
+                                                   MODE_DECIMAL_FLOAT)
+                                                  ? (((((type))->base.
+                                                       code) ==
+                                                      VECTOR_TYPE ?
+                                                      vector_type_mode (type)
+                                                      : (type)->type.
+                                                      mode)) : ((enum
+                                                                 machine_mode)
+                                                                mode_inner[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)])]) == MODE_DECIMAL_FLOAT) ? ((((((enum mode_class) mode_class[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)]) == MODE_DECIMAL_FLOAT) ? (((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)) : ((enum machine_mode) mode_inner[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)])) - MIN_MODE_DECIMAL_FLOAT) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : (((((enum mode_class) mode_class[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)]) == MODE_DECIMAL_FLOAT) ? (((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)) : ((enum machine_mode) mode_inner[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)])) - MIN_MODE_FLOAT)]))->has_nans)  ));
+}
index 3086f8247cbda4939e75ba7ed9417b5edcc63b38..5486d5c8609c466f73189886b1d9b921a2b97559 100644 (file)
@@ -1391,7 +1391,7 @@ class rewrite_dom_walker : public dom_walker
 public:
   rewrite_dom_walker (cdi_direction direction) : dom_walker (direction) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 };
 
@@ -1400,7 +1400,7 @@ public:
    (BLOCK_DEFS).  Register new definitions for every PHI node in the
    block.  */
 
-void
+edge
 rewrite_dom_walker::before_dom_children (basic_block bb)
 {
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1432,6 +1432,8 @@ rewrite_dom_walker::before_dom_children (basic_block bb)
      reaching definition for the variable and the edge through which that
      definition is reaching the PHI node.  */
   rewrite_add_phi_arguments (bb);
+
+  return NULL;
 }
 
 
@@ -2055,7 +2057,7 @@ class rewrite_update_dom_walker : public dom_walker
 public:
   rewrite_update_dom_walker (cdi_direction direction) : dom_walker (direction) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 };
 
@@ -2064,7 +2066,7 @@ public:
    for new SSA names produced in this block (BLOCK_DEFS).  Register
    new definitions for every PHI node in the block.  */
 
-void
+edge
 rewrite_update_dom_walker::before_dom_children (basic_block bb)
 {
   bool is_abnormal_phi;
@@ -2077,7 +2079,7 @@ rewrite_update_dom_walker::before_dom_children (basic_block bb)
   block_defs_stack.safe_push (NULL_TREE);
 
   if (!bitmap_bit_p (blocks_to_update, bb->index))
-    return;
+    return NULL;
 
   /* Mark the LHS if any of the arguments flows through an abnormal
      edge.  */
@@ -2133,6 +2135,8 @@ rewrite_update_dom_walker::before_dom_children (basic_block bb)
 
   /* Step 3.  Update PHI nodes.  */
   rewrite_update_phi_arguments (bb);
+
+  return NULL;
 }
 
 /* Called after visiting block BB.  Unwind BLOCK_DEFS_STACK to restore
@@ -2210,7 +2214,7 @@ public:
   mark_def_dom_walker (cdi_direction direction);
   ~mark_def_dom_walker ();
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 
 private:
   /* Notice that this bitmap is indexed using variable UIDs, so it must be
@@ -2232,7 +2236,7 @@ mark_def_dom_walker::~mark_def_dom_walker ()
 /* Block processing routine for mark_def_sites.  Clear the KILLS bitmap
    at the start of each block, and call mark_def_sites for each statement.  */
 
-void
+edge
 mark_def_dom_walker::before_dom_children (basic_block bb)
 {
   gimple_stmt_iterator gsi;
@@ -2240,6 +2244,7 @@ mark_def_dom_walker::before_dom_children (basic_block bb)
   bitmap_clear (m_kills);
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     mark_def_sites (bb, gsi_stmt (gsi), m_kills);
+  return NULL;
 }
 
 /* Initialize internal data needed during renaming.  */
index aeb726c9bdbb6883e535694580a3865205cc20cb..88fc517900c5653a6174c2ea4c31fb07b78e4d87 100644 (file)
@@ -99,7 +99,7 @@ struct opt_stats_d
 static struct opt_stats_d opt_stats;
 
 /* Local functions.  */
-static void optimize_stmt (basic_block, gimple_stmt_iterator,
+static edge optimize_stmt (basic_block, gimple_stmt_iterator,
                           class const_and_copies *,
                           class avail_exprs_stack *);
 static tree lookup_avail_expr (gimple *, bool, class avail_exprs_stack *);
@@ -493,12 +493,12 @@ public:
   dom_opt_dom_walker (cdi_direction direction,
                      class const_and_copies *const_and_copies,
                      class avail_exprs_stack *avail_exprs_stack)
-    : dom_walker (direction),
+    : dom_walker (direction, true),
       m_const_and_copies (const_and_copies),
       m_avail_exprs_stack (avail_exprs_stack),
       m_dummy_cond (NULL) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
 private:
@@ -611,6 +611,36 @@ pass_dominator::execute (function *fun)
                             avail_exprs_stack);
   walker.walk (fun->cfg->x_entry_block_ptr);
 
+  /* Look for blocks where we cleared EDGE_EXECUTABLE on an outgoing
+     edge.  When found, remove jump threads which contain any outgoing
+     edge from the affected block.  */
+  if (cfg_altered)
+    {
+      FOR_EACH_BB_FN (bb, fun)
+       {
+         edge_iterator ei;
+         edge e;
+
+         /* First see if there are any edges without EDGE_EXECUTABLE
+            set.  */
+         bool found = false;
+         FOR_EACH_EDGE (e, ei, bb->succs)
+           {
+             if ((e->flags & EDGE_EXECUTABLE) == 0)
+               {
+                 found = true;
+                 break;
+               }
+           }
+
+         /* If there were any such edges found, then remove jump threads
+            containing any edge leaving BB.  */
+         if (found)
+           FOR_EACH_EDGE (e, ei, bb->succs)
+             remove_jump_threads_including (e);
+       }
+    }
+
   {
     gimple_stmt_iterator gsi;
     basic_block bb;
@@ -951,6 +981,11 @@ record_equivalences_from_phis (basic_block bb)
          if (lhs == t)
            continue;
 
+         /* If the associated edge is not marked as executable, then it
+            can be ignored.  */
+         if ((gimple_phi_arg_edge (phi, i)->flags & EDGE_EXECUTABLE) == 0)
+           continue;
+
          t = dom_valueize (t);
 
          /* If we have not processed an alternative yet, then set
@@ -997,6 +1032,10 @@ single_incoming_edge_ignoring_loop_edges (basic_block bb)
       if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
        continue;
 
+      /* We can safely ignore edges that are not executable.  */
+      if ((e->flags & EDGE_EXECUTABLE) == 0)
+       continue;
+
       /* If we have already seen a non-loop edge, then we must have
         multiple incoming non-loop edges and thus we return NULL.  */
       if (retval)
@@ -1294,7 +1333,7 @@ cprop_into_successor_phis (basic_block bb,
     }
 }
 
-void
+edge
 dom_opt_dom_walker::before_dom_children (basic_block bb)
 {
   gimple_stmt_iterator gsi;
@@ -1322,12 +1361,15 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
                                      m_avail_exprs_stack);
   m_avail_exprs_stack->pop_to_marker ();
 
+  edge taken_edge = NULL;
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-    optimize_stmt (bb, gsi, m_const_and_copies, m_avail_exprs_stack);
+    taken_edge
+      = optimize_stmt (bb, gsi, m_const_and_copies, m_avail_exprs_stack);
 
   /* Now prepare to process dominated blocks.  */
   record_edge_info (bb);
   cprop_into_successor_phis (bb, m_const_and_copies);
+  return taken_edge;
 }
 
 /* We have finished processing the dominator children of BB, perform
@@ -1694,7 +1736,7 @@ cprop_into_stmt (gimple *stmt)
       assignment is found, we map the value on the RHS of the assignment to
       the variable in the LHS in the CONST_AND_COPIES table.  */
 
-static void
+static edge
 optimize_stmt (basic_block bb, gimple_stmt_iterator si,
               class const_and_copies *const_and_copies,
               class avail_exprs_stack *avail_exprs_stack)
@@ -1703,6 +1745,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
   bool may_optimize_p;
   bool modified_p = false;
   bool was_noreturn;
+  edge retval = NULL;
 
   old_stmt = stmt = gsi_stmt (si);
   was_noreturn = is_gimple_call (stmt) && gimple_call_noreturn_p (stmt);
@@ -1823,7 +1866,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
                    fprintf (dump_file, "  Flagged to clear EH edges.\n");
                }
              release_defs (stmt);
-             return;
+             return retval;
            }
        }
     }
@@ -1849,25 +1892,19 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 
       if (val && TREE_CODE (val) == INTEGER_CST)
        {
-         edge taken_edge = find_taken_edge (bb, val);
-         if (taken_edge)
+         retval = find_taken_edge (bb, val);
+         if (retval)
            {
-
-             /* We need to remove any queued jump threads that
-                reference outgoing edges from this block.  */
-             edge_iterator ei;
-             edge e;
-             FOR_EACH_EDGE (e, ei, bb->succs)
-               remove_jump_threads_including (e);
-
-             /* Now clean up the control statement at the end of
-                BB and remove unexecutable edges.  */
-             remove_ctrl_stmt_and_useless_edges (bb, taken_edge->dest);
-
-             /* Fixup the flags on the single remaining edge.  */
-             taken_edge->flags
-               &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
-             taken_edge->flags |= EDGE_FALLTHRU;
+             /* Fix the condition to be either true or false.  */
+             if (gimple_code (stmt) == GIMPLE_COND)
+               {
+                 if (integer_zerop (val))
+                   gimple_cond_make_false (as_a <gcond *> (stmt));
+                 else if (integer_onep (val))
+                   gimple_cond_make_true (as_a <gcond *> (stmt));
+                 else
+                   gcc_unreachable ();
+               }
 
              /* Further simplifications may be possible.  */
              cfg_altered = true;
@@ -1887,6 +1924,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
          && is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
        need_noreturn_fixup.safe_push (stmt);
     }
+  return retval;
 }
 
 /* Helper for walk_non_aliased_vuses.  Determine if we arrived at
index 20a12b5ee889c1b0381b9bc19e6d4ce3815efe4b..0b05c5e2ab32651840715d5634d074d5bbb7707f 100644 (file)
@@ -316,10 +316,10 @@ class dse_dom_walker : public dom_walker
 public:
   dse_dom_walker (cdi_direction direction) : dom_walker (direction) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 };
 
-void
+edge
 dse_dom_walker::before_dom_children (basic_block bb)
 {
   gimple_stmt_iterator gsi;
@@ -332,6 +332,7 @@ dse_dom_walker::before_dom_children (basic_block bb)
       else
        gsi_prev (&gsi);
     }
+  return NULL;
 }
 
 namespace {
index 0d82d36af9340ffc7bed8878aa8be9e81016bcf8..9b1b8157b127f54f8b99b6727dffbac3e519d49c 100644 (file)
@@ -958,14 +958,14 @@ public:
   invariantness_dom_walker (cdi_direction direction)
     : dom_walker (direction) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 };
 
 /* Determine the outermost loops in that statements in basic block BB are
    invariant, and record them to the LIM_DATA associated with the statements.
    Callback for dom_walker.  */
 
-void
+edge
 invariantness_dom_walker::before_dom_children (basic_block bb)
 {
   enum move_pos pos;
@@ -976,7 +976,7 @@ invariantness_dom_walker::before_dom_children (basic_block bb)
   struct lim_aux_data *lim_data;
 
   if (!loop_outer (bb->loop_father))
-    return;
+    return NULL;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Basic block %d (loop %d -- depth %d):\n\n",
@@ -1094,6 +1094,7 @@ invariantness_dom_walker::before_dom_children (basic_block bb)
       if (lim_data->cost >= LIM_EXPENSIVE)
        set_profitable_level (stmt);
     }
+  return NULL;
 }
 
 class move_computations_dom_walker : public dom_walker
@@ -1102,7 +1103,7 @@ public:
   move_computations_dom_walker (cdi_direction direction)
     : dom_walker (direction), todo_ (0) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 
   unsigned int todo_;
 };
@@ -1111,7 +1112,7 @@ public:
    data stored in LIM_DATA structures associated with each statement.  Callback
    for walk_dominator_tree.  */
 
-void
+edge
 move_computations_dom_walker::before_dom_children (basic_block bb)
 {
   struct loop *level;
@@ -1119,7 +1120,7 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
   struct lim_aux_data *lim_data;
 
   if (!loop_outer (bb->loop_father))
-    return;
+    return NULL;
 
   for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); )
     {
@@ -1265,6 +1266,7 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
       else
        gsi_insert_on_edge (e, stmt);
     }
+  return NULL;
 }
 
 /* Hoist the statements out of the loops prescribed by data stored in
index e5e0a9a6ddb8621335203d4dd1a1dd07d48a7462..99ab23a62ddd248671d5abab062924ee362d7122 100644 (file)
@@ -1477,7 +1477,7 @@ public:
   nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
     : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
 private:
@@ -1496,7 +1496,7 @@ private:
 };
 
 /* Called by walk_dominator_tree, when entering the block BB.  */
-void
+edge
 nontrapping_dom_walker::before_dom_children (basic_block bb)
 {
   edge e;
@@ -1529,6 +1529,7 @@ nontrapping_dom_walker::before_dom_children (basic_block bb)
          add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), false);
        }
     }
+  return NULL;
 }
 
 /* Called by walk_dominator_tree, when basic block BB is exited.  */
index baafa34d40b08c8c7c8284a3cc37fce223adcfc2..21a3a2b41d257c2e2bd8f55358d25fada9aeb375 100644 (file)
@@ -3906,7 +3906,7 @@ public:
   eliminate_dom_walker (cdi_direction direction, bool do_pre_)
       : dom_walker (direction), do_pre (do_pre_) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
   bool do_pre;
@@ -3914,7 +3914,7 @@ public:
 
 /* Perform elimination for the basic-block B during the domwalk.  */
 
-void
+edge
 eliminate_dom_walker::before_dom_children (basic_block b)
 {
   /* Mark new bb.  */
@@ -4423,6 +4423,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
            }
        }
     }
+  return NULL;
 }
 
 /* Make no longer available leaders no longer available.  */
index e61cb482acf871d9014daeab4e67d59046ebe6df..c52b41c78e536e287e53400a44ad202e06373b5d 100644 (file)
@@ -1123,7 +1123,7 @@ public:
       BITMAP_FREE (need_eh_cleanup);
     }
 
-    virtual void before_dom_children (basic_block);
+    virtual edge before_dom_children (basic_block);
     virtual void after_dom_children (basic_block) {}
 
     ssa_prop_get_value_fn get_value_fn;
@@ -1135,7 +1135,7 @@ public:
     bitmap need_eh_cleanup;
 };
 
-void
+edge
 substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
 {
   /* Propagate known values into PHI nodes.  */
@@ -1293,6 +1293,7 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
            fprintf (dump_file, "Not folded\n");
        }
     }
+  return NULL;
 }
 
 
index 3086f84f39e7edd2ab0f687e8533391adfa211ae..84e95639824f7e1aac72331e43650a201dfd7ee5 100644 (file)
@@ -4208,11 +4208,10 @@ class sccvn_dom_walker : public dom_walker
 {
 public:
   sccvn_dom_walker ()
-    : dom_walker (CDI_DOMINATORS), fail (false), unreachable_dom (NULL),
-      cond_stack (vNULL) {}
+    : dom_walker (CDI_DOMINATORS, true), fail (false), cond_stack (vNULL) {}
   ~sccvn_dom_walker ();
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
   void record_cond (basic_block,
@@ -4221,7 +4220,6 @@ public:
                     enum tree_code code, tree lhs, tree rhs, bool value);
 
   bool fail;
-  basic_block unreachable_dom;
   vec<std::pair <basic_block, std::pair <vn_nary_op_t, vn_nary_op_t> > >
     cond_stack;
 };
@@ -4302,9 +4300,6 @@ sccvn_dom_walker::record_conds (basic_block bb,
 void
 sccvn_dom_walker::after_dom_children (basic_block bb)
 {
-  if (unreachable_dom == bb)
-    unreachable_dom = NULL;
-
   while (!cond_stack.is_empty ()
         && cond_stack.last ().first == bb)
     {
@@ -4319,56 +4314,14 @@ sccvn_dom_walker::after_dom_children (basic_block bb)
 
 /* Value number all statements in BB.  */
 
-void
+edge
 sccvn_dom_walker::before_dom_children (basic_block bb)
 {
   edge e;
   edge_iterator ei;
 
   if (fail)
-    return;
-
-  /* If any of the predecessor edges that do not come from blocks dominated
-     by us are still marked as possibly executable consider this block
-     reachable.  */
-  bool reachable = false;
-  if (!unreachable_dom)
-    {
-      reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun);
-      FOR_EACH_EDGE (e, ei, bb->preds)
-       if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
-         reachable |= (e->flags & EDGE_EXECUTABLE);
-    }
-
-  /* If the block is not reachable all outgoing edges are not
-     executable.  Neither are incoming edges with src dominated by us.  */
-  if (!reachable)
-    {
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       fprintf (dump_file, "Marking all outgoing edges of unreachable "
-                "BB %d as not executable\n", bb->index);
-
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       e->flags &= ~EDGE_EXECUTABLE;
-
-      FOR_EACH_EDGE (e, ei, bb->preds)
-       {
-         if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
-           {
-             if (dump_file && (dump_flags & TDF_DETAILS))
-               fprintf (dump_file, "Marking backedge from BB %d into "
-                        "unreachable BB %d as not executable\n",
-                        e->src->index, bb->index);
-             e->flags &= ~EDGE_EXECUTABLE;
-           }
-       }
-
-      /* Record the most dominating unreachable block.  */
-      if (!unreachable_dom)
-       unreachable_dom = bb;
-
-      return;
-    }
+    return NULL;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Visiting BB %d\n", bb->index);
@@ -4429,7 +4382,7 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
          && !DFS (res))
        {
          fail = true;
-         return;
+         return NULL;
        }
     }
   for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
@@ -4442,20 +4395,20 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
            && !DFS (op))
          {
            fail = true;
-           return;
+           return NULL;
          }
     }
 
   /* Finally look at the last stmt.  */
   gimple *stmt = last_stmt (bb);
   if (!stmt)
-    return;
+    return NULL;
 
   enum gimple_code code = gimple_code (stmt);
   if (code != GIMPLE_COND
       && code != GIMPLE_SWITCH
       && code != GIMPLE_GOTO)
-    return;
+    return NULL;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -4498,19 +4451,17 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
       gcc_unreachable ();
     }
   if (!val)
-    return;
+    return NULL;
 
   edge taken = find_taken_edge (bb, vn_valueize (val));
   if (!taken)
-    return;
+    return NULL;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Marking all edges out of BB %d but (%d -> %d) as "
             "not executable\n", bb->index, bb->index, taken->dest->index);
 
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    if (e != taken)
-      e->flags &= ~EDGE_EXECUTABLE;
+  return taken;
 }
 
 /* Do SCCVN.  Returns true if it finished, false if we bailed out
@@ -4520,7 +4471,6 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
 bool
 run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
 {
-  basic_block bb;
   size_t i;
 
   default_vn_walk_kind = default_vn_walk_kind_;
@@ -4550,15 +4500,6 @@ run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
        }
     }
 
-  /* Mark all edges as possibly executable.  */
-  FOR_ALL_BB_FN (bb, cfun)
-    {
-      edge_iterator ei;
-      edge e;
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       e->flags |= EDGE_EXECUTABLE;
-    }
-
   /* Walk all blocks in dominator order, value-numbering stmts
      SSA defs and decide whether outgoing edges are not executable.  */
   sccvn_dom_walker walker;
index 31732d75b48f974a65c8822dc8657df5fd787f2d..f98b8656d21ce26ee5effe91903233c1683664a7 100644 (file)
@@ -2196,14 +2196,14 @@ class strlen_dom_walker : public dom_walker
 public:
   strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 };
 
 /* Callback for walk_dominator_tree.  Attempt to optimize various
    string ops by remembering string lenths pointed by pointer SSA_NAMEs.  */
 
-void
+edge
 strlen_dom_walker::before_dom_children (basic_block bb)
 {
   basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
@@ -2283,6 +2283,7 @@ strlen_dom_walker::before_dom_children (basic_block bb)
   bb->aux = stridx_to_strinfo;
   if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
     (*stridx_to_strinfo)[0] = (strinfo *) bb;
+  return NULL;
 }
 
 /* Callback for walk_dominator_tree.  Free strinfo vector if it is
index a60184e31fe191557128535e9fcd4728d335c449..502614a37d605d5097d35e77d6640aa6a845a594 100644 (file)
@@ -303,7 +303,7 @@ class uncprop_dom_walker : public dom_walker
 public:
   uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
 private:
@@ -433,7 +433,7 @@ single_incoming_edge_ignoring_loop_edges (basic_block bb)
   return retval;
 }
 
-void
+edge
 uncprop_dom_walker::before_dom_children (basic_block bb)
 {
   basic_block parent;
@@ -462,6 +462,7 @@ uncprop_dom_walker::before_dom_children (basic_block bb)
     m_equiv_stack.safe_push (NULL_TREE);
 
   uncprop_into_successor_phis (bb);
+  return NULL;
 }
 
 namespace {