re PR tree-optimization/17591 (Ada bootstrap SEGV in stage2 on osint.adb, no SEGV...
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Sun, 26 Sep 2004 08:32:40 +0000 (10:32 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Sun, 26 Sep 2004 08:32:40 +0000 (08:32 +0000)
PR bootstrap/17591
* tree-ssa-loop-im.c (for_each_index): Call callback for component_refs
with varying offset.
* tree-ssa-loop-ivopts.c (abnormal_ssa_name_p): New function.
(idx_contains_abnormal_ssa_name_p): Scan step and lower bound for
ARRAY_REFS.
(expr_invariant_in_loop_p): New function.
(idx_find_step): Handle step and lower bound for ARRAY_REFs.  Handle
component_ref_field_offset for COMPONENT_REFs.  Do not allow
ALIGN_INDIRECT_REFs and MISALIGNED_INDIRECT_REFs.
(add_address_candidates): Do not handle ALIGN_INDIRECT_REFs and
MISALIGNED_INDIRECT_REFs.
(idx_remove_ssa_names): Handle step and lower bound for ARRAY_REFs.
(rewrite_address_base): Do not handle ALIGN_INDIRECT_REFs and
MISALIGNED_INDIRECT_REFs.

From-SVN: r88123

gcc/ChangeLog
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-loop-ivopts.c

index 31f059cdd7ff687539a1f123981012fce85ae268..c89c8ed8520ba0f205e2209a5e1c5795654a9dd2 100644 (file)
@@ -1,3 +1,21 @@
+2004-09-26  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       PR bootstrap/17591
+       * tree-ssa-loop-im.c (for_each_index): Call callback for component_refs
+       with varying offset.
+       * tree-ssa-loop-ivopts.c (abnormal_ssa_name_p): New function.
+       (idx_contains_abnormal_ssa_name_p): Scan step and lower bound for
+       ARRAY_REFS.
+       (expr_invariant_in_loop_p): New function.
+       (idx_find_step): Handle step and lower bound for ARRAY_REFs.  Handle
+       component_ref_field_offset for COMPONENT_REFs.  Do not allow
+       ALIGN_INDIRECT_REFs and MISALIGNED_INDIRECT_REFs.
+       (add_address_candidates): Do not handle ALIGN_INDIRECT_REFs and
+       MISALIGNED_INDIRECT_REFs.
+       (idx_remove_ssa_names): Handle step and lower bound for ARRAY_REFs.
+       (rewrite_address_base): Do not handle ALIGN_INDIRECT_REFs and
+       MISALIGNED_INDIRECT_REFs.
+
 2004-09-26  Joseph S. Myers  <jsm@polyomino.org.uk>
 
        PR c/11459
index 4aafc815b84f19b7e12b2bba46a704bd0e91f562..0330a278009cfd361bd0e4f2e8dde2a9b2022efe 100644 (file)
@@ -128,7 +128,7 @@ get_stmt_uid (tree stmt)
 bool
 for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
 {
-  tree *nxt;
+  tree *nxt, *idx;
 
   for (; ; addr_p = nxt)
     {
@@ -144,7 +144,6 @@ for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
          return cbck (*addr_p, nxt, data);
 
        case BIT_FIELD_REF:
-       case COMPONENT_REF:
        case VIEW_CONVERT_EXPR:
        case ARRAY_RANGE_REF:
        case REALPART_EXPR:
@@ -152,6 +151,17 @@ for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
          nxt = &TREE_OPERAND (*addr_p, 0);
          break;
 
+       case COMPONENT_REF:
+         /* If the component has varying offset, it behaves like index
+            as well.  */
+         idx = &TREE_OPERAND (*addr_p, 2);
+         if (*idx
+             && !cbck (*addr_p, idx, data))
+           return false;
+
+         nxt = &TREE_OPERAND (*addr_p, 0);
+         break;
+
        case ARRAY_REF:
          nxt = &TREE_OPERAND (*addr_p, 0);
          if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
index 08a962d09325337845198aec2a98f202433520bc..d0b468f2c1c569af302c1e53b506ed59a1c79562 100644 (file)
@@ -701,17 +701,36 @@ determine_biv_step (tree phi)
   return step;
 }
 
-/* Returns false if INDEX is a ssa name that occurs in an
+/* Returns true if EXP is a ssa name that occurs in an abnormal phi node.  */
+
+static bool
+abnormal_ssa_name_p (tree exp)
+{
+  if (!exp)
+    return false;
+
+  if (TREE_CODE (exp) != SSA_NAME)
+    return false;
+
+  return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
+}
+
+/* Returns false if BASE or INDEX contains a ssa name that occurs in an
    abnormal phi node.  Callback for for_each_index.  */
 
 static bool
-idx_contains_abnormal_ssa_name_p (tree base ATTRIBUTE_UNUSED, tree *index,
+idx_contains_abnormal_ssa_name_p (tree base, tree *index,
                                  void *data ATTRIBUTE_UNUSED)
 {
-  if (TREE_CODE (*index) != SSA_NAME)
-    return true;
+  if (TREE_CODE (base) == ARRAY_REF)
+    {
+      if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
+       return false;
+      if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
+       return false;
+    }
 
-  return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*index) == 0;
+  return !abnormal_ssa_name_p (*index);
 }
 
 /* Returns true if EXPR contains a ssa name that occurs in an
@@ -1146,6 +1165,39 @@ find_interesting_uses_cond (struct ivopts_data *data, tree stmt, tree *cond_p)
   record_use (data, cond_p, civ, stmt, USE_COMPARE);
 }
 
+/* Returns true if expression EXPR is obviously invariant in LOOP,
+   i.e. if all its operands are defined outside of the LOOP.  */
+
+static bool
+expr_invariant_in_loop_p (struct loop *loop, tree expr)
+{
+  basic_block def_bb;
+  unsigned i, len;
+
+  if (is_gimple_min_invariant (expr))
+    return true;
+
+  if (TREE_CODE (expr) == SSA_NAME)
+    {
+      def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (expr));
+      if (def_bb
+         && flow_bb_inside_loop_p (loop, def_bb))
+       return false;
+
+      return true;
+    }
+
+  if (!EXPR_P (expr))
+    return false;
+
+  len = first_rtl_op (TREE_CODE (expr));
+  for (i = 0; i < len; i++)
+    if (!expr_invariant_in_loop_p (loop, TREE_OPERAND (expr, i)))
+      return false;
+
+  return true;
+}
+
 /* Cumulates the steps of indices into DATA and replaces their values with the
    initial ones.  Returns false when the value of the index cannot be determined.
    Callback for for_each_index.  */
@@ -1162,10 +1214,35 @@ idx_find_step (tree base, tree *idx, void *data)
 {
   struct ifs_ivopts_data *dta = data;
   struct iv *iv;
-  tree step, type, iv_type, iv_step, lbound;
-  basic_block def_bb;
+  tree step, type, iv_type, iv_step, lbound, off;
   struct loop *loop = dta->ivopts_data->current_loop;
-  
+
+  if (TREE_CODE (base) == MISALIGNED_INDIRECT_REF
+      || TREE_CODE (base) == ALIGN_INDIRECT_REF)
+    return false;
+
+  /* If base is a component ref, require that the offset of the reference
+     is invariant.  */
+  if (TREE_CODE (base) == COMPONENT_REF)
+    {
+      off = component_ref_field_offset (base);
+      return expr_invariant_in_loop_p (loop, off);
+    }
+
+  /* If base is array, first check whether we will be able to move the
+     reference out of the loop (in order to take its address in strength
+     reduction).  In order for this to work we need both lower bound
+     and step to be loop invariants.  */
+  if (TREE_CODE (base) == ARRAY_REF)
+    {
+      step = array_ref_element_size (base);
+      lbound = array_ref_low_bound (base);
+
+      if (!expr_invariant_in_loop_p (loop, step)
+         || !expr_invariant_in_loop_p (loop, lbound))
+       return false;
+    }
+
   if (TREE_CODE (*idx) != SSA_NAME)
     return true;
 
@@ -1183,27 +1260,10 @@ idx_find_step (tree base, tree *idx, void *data)
   if (TREE_CODE (base) == ARRAY_REF)
     {
       step = array_ref_element_size (base);
-      lbound = array_ref_low_bound (base);
 
       /* We only handle addresses whose step is an integer constant.  */
       if (TREE_CODE (step) != INTEGER_CST)
        return false;
-
-      /* We need the lower bound to be invariant in loop, since otherwise
-        we are unable to initialize a new induction variable created
-        in strength reduction -- we need to take the address of the
-        reference in front of the loop.  */
-      if (is_gimple_min_invariant (lbound))
-       ; /* Nothing to do.  */
-      else if (TREE_CODE (lbound) != SSA_NAME)
-       return false;
-      else
-       {
-         def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (lbound));
-         if (def_bb
-             && flow_bb_inside_loop_p (loop, def_bb))
-           return false;
-       }
     }
   else
     /* The step for pointer arithmetics already is 1 byte.  */
@@ -1269,9 +1329,10 @@ find_interesting_uses_address (struct ivopts_data *data, tree stmt, tree *op_p)
       || zero_p (step))
     goto fail;
 
-  if (TREE_CODE (base) == INDIRECT_REF
-      || TREE_CODE (base) == ALIGN_INDIRECT_REF
-      || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
+  gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
+  gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
+
+  if (TREE_CODE (base) == INDIRECT_REF)
     base = TREE_OPERAND (base, 0);
   else
     base = build_addr (base);
@@ -1701,9 +1762,10 @@ add_address_candidates (struct ivopts_data *data,
 
       if (base != TREE_OPERAND (iv->base, 0))
        { 
-         if (TREE_CODE (base) == INDIRECT_REF
-             || TREE_CODE (base) == ALIGN_INDIRECT_REF
-             || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
+         gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
+         gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
+
+         if (TREE_CODE (base) == INDIRECT_REF)
            base = TREE_OPERAND (base, 0);
          else
            base = build_addr (base);
@@ -3805,11 +3867,26 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
    for_each_index.  */
 
 static bool
-idx_remove_ssa_names (tree base ATTRIBUTE_UNUSED, tree *idx,
+idx_remove_ssa_names (tree base, tree *idx,
                      void *data ATTRIBUTE_UNUSED)
 {
+  tree *op;
+
   if (TREE_CODE (*idx) == SSA_NAME)
     *idx = SSA_NAME_VAR (*idx);
+
+  if (TREE_CODE (base) == ARRAY_REF)
+    {
+      op = &TREE_OPERAND (base, 2);
+      if (*op
+         && TREE_CODE (*op) == SSA_NAME)
+       *op = SSA_NAME_VAR (*op);
+      op = &TREE_OPERAND (base, 3);
+      if (*op
+         && TREE_CODE (*op) == SSA_NAME)
+       *op = SSA_NAME_VAR (*op);
+    }
+
   return true;
 }
 
@@ -3837,9 +3914,10 @@ rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
 
   if (!var || TREE_CODE (with) != SSA_NAME)
     goto do_rewrite;
-  if (TREE_CODE (var) == INDIRECT_REF
-      || TREE_CODE (var) == ALIGN_INDIRECT_REF
-      || TREE_CODE (var) == MISALIGNED_INDIRECT_REF)
+
+  gcc_assert (TREE_CODE (var) != ALIGN_INDIRECT_REF);
+  gcc_assert (TREE_CODE (var) != MISALIGNED_INDIRECT_REF);
+  if (TREE_CODE (var) == INDIRECT_REF)
     var = TREE_OPERAND (var, 0);
   if (TREE_CODE (var) == SSA_NAME)
     {
@@ -3876,19 +3954,15 @@ rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
 do_rewrite:
 
   orig = NULL_TREE;
-  if (TREE_CODE (*op) == INDIRECT_REF
-      || TREE_CODE (*op) == ALIGN_INDIRECT_REF
-      || TREE_CODE (*op) == MISALIGNED_INDIRECT_REF)
+  gcc_assert (TREE_CODE (*op) != ALIGN_INDIRECT_REF);
+  gcc_assert (TREE_CODE (*op) != MISALIGNED_INDIRECT_REF);
+
+  if (TREE_CODE (*op) == INDIRECT_REF)
     orig = REF_ORIGINAL (*op);
   if (!orig)
     orig = unshare_and_remove_ssa_names (*op);
 
-  if (TREE_CODE (bvar) == ALIGN_INDIRECT_REF)
-    *op = build1 (ALIGN_INDIRECT_REF, TREE_TYPE (*op), with);
-  else if (TREE_CODE (bvar) == MISALIGNED_INDIRECT_REF)
-    *op = build2 (MISALIGNED_INDIRECT_REF, TREE_TYPE (*op), with, TREE_OPERAND (*op, 1));
-  else
-    *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
+  *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
 
   /* Record the original reference, for purposes of alias analysis.  */
   REF_ORIGINAL (*op) = orig;