]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Better handling of COND_EXPRs in rhs
authorrobc <robc@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jan 2007 13:52:42 +0000 (13:52 +0000)
committerrobc <robc@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jan 2007 13:52:42 +0000 (13:52 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120581 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/tree-object-size.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-forwprop.c
gcc/tree-vrp.c

index 58f9cd838cd389ecd6bb6ccfe822122553d368a8..a0b92c9af7e65f428af0b379bb3351263e3b0b2a 100644 (file)
@@ -1,3 +1,16 @@
+2007-01-08  Roberto Costa  <roberto.costa@st.com>
+
+       * tree-vrp.c (extract_range_from_cond_expr): New.
+       (extract_range_from_expr): Handle COND_EXPR nodes used as expressions.
+       * tree-ssa-ccp.c (get_maxval_strlen): Handle COND_EXPR nodes used
+       as expressions.
+       (fold_stmt): Bug fix, avoid infinite recursion when folding COND_EXPRs.
+       * tree-ssa-forwprop.c (simplify_cond, forward_propagate_into_cond,
+       tree_ssa_forward_propagate_single_use_vars): Handle COND_EXPR nodes
+       used as expressions.
+       * tree-object-size.c (cond_expr_object_size): New.
+       (collect_object_sizes_for): Handle COND_EXPR nodes used as expressions.
+
 2007-01-08  Jan Hubicka  <jh@suse.cz>
 
        * tree-ssa-forwprop.c (forward_propagate_into_cond,
index 7ae87d67539810bb2bab2a297d79a0d7a960d691..a93464b22fa73f0cc4fbc9bc6542ddfa466484ad 100644 (file)
@@ -50,6 +50,7 @@ static void expr_object_size (struct object_size_info *, tree, tree);
 static bool merge_object_sizes (struct object_size_info *, tree, tree,
                                unsigned HOST_WIDE_INT);
 static bool plus_expr_object_size (struct object_size_info *, tree, tree);
+static bool cond_expr_object_size (struct object_size_info *, tree, tree);
 static unsigned int compute_object_sizes (void);
 static void init_offset_limit (void);
 static void check_for_plus_in_loops (struct object_size_info *, tree);
@@ -621,6 +622,40 @@ plus_expr_object_size (struct object_size_info *osi, tree var, tree value)
 }
 
 
+/* Compute object_sizes for PTR, defined to VALUE, which is
+   a COND_EXPR.  Return true if the object size might need reexamination
+   later.  */
+
+static bool
+cond_expr_object_size (struct object_size_info *osi, tree var, tree value)
+{
+  tree then_, else_;
+  int object_size_type = osi->object_size_type;
+  unsigned int varno = SSA_NAME_VERSION (var);
+  bool reexamine = false;
+
+  gcc_assert (TREE_CODE (value) == COND_EXPR);
+
+  if (object_sizes[object_size_type][varno] == unknown[object_size_type])
+    return false;
+
+  then_ = COND_EXPR_THEN (value);
+  else_ = COND_EXPR_ELSE (value);
+
+  if (TREE_CODE (then_) == SSA_NAME)
+    reexamine |= merge_object_sizes (osi, var, then_, 0);
+  else
+    expr_object_size (osi, var, then_);
+
+  if (TREE_CODE (else_) == SSA_NAME)
+    reexamine |= merge_object_sizes (osi, var, else_, 0);
+  else
+    expr_object_size (osi, var, else_);
+
+  return reexamine;
+}
+
+
 /* Compute object sizes for VAR.
    For ADDR_EXPR an object size is the number of remaining bytes
    to the end of the object (where what is considered an object depends on
@@ -711,6 +746,9 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
        else if (TREE_CODE (rhs) == PLUS_EXPR)
          reexamine = plus_expr_object_size (osi, var, rhs);
 
+        else if (TREE_CODE (rhs) == COND_EXPR)
+         reexamine = cond_expr_object_size (osi, var, rhs);
+
        else
          expr_object_size (osi, var, rhs);
        break;
index 493bdecedcde6a00fbad1949ca945a693cb2683a..0f02b8c865155b6302859e29cd152ac5cf7fba5f 100644 (file)
@@ -2109,6 +2109,10 @@ get_maxval_strlen (tree arg, tree *length, bitmap visited, int type)
   
   if (TREE_CODE (arg) != SSA_NAME)
     {
+      if (TREE_CODE (arg) == COND_EXPR)
+        return get_maxval_strlen (COND_EXPR_THEN (arg), length, visited, type)
+               && get_maxval_strlen (COND_EXPR_ELSE (arg), length, visited, type);
+
       if (type == 2)
        {
          val = arg;
@@ -2438,6 +2442,13 @@ fold_stmt (tree *stmt_p)
            }
        }
     }
+  else if (TREE_CODE (rhs) == COND_EXPR)
+    {
+      tree temp = fold (COND_EXPR_COND (rhs));
+      if (temp != COND_EXPR_COND (rhs))
+        result = fold_build3 (COND_EXPR, TREE_TYPE (rhs), temp,
+                              COND_EXPR_THEN (rhs), COND_EXPR_ELSE (rhs));
+    }
 
   /* If we couldn't fold the RHS, hand over to the generic fold routines.  */
   if (result == NULL_TREE)
index a5267ae3970ea01ed38772961619cc26f3ded327..39653fcfc794dfe1811d00c1bcae209568bb4418 100644 (file)
@@ -490,15 +490,16 @@ find_equivalent_equality_comparison (tree cond)
   return NULL;
 }
 
-/* STMT is a COND_EXPR
+/* EXPR is a COND_EXPR
+   STMT is the statement containing EXPR.
 
    This routine attempts to find equivalent forms of the condition
    which we may be able to optimize better.  */
 
 static void
-simplify_cond (tree stmt)
+simplify_cond (tree cond_expr, tree stmt)
 {
-  tree cond = COND_EXPR_COND (stmt);
+  tree cond = COND_EXPR_COND (cond_expr);
 
   if (COMPARISON_CLASS_P (cond))
     {
@@ -517,7 +518,7 @@ simplify_cond (tree stmt)
 
              if (new_cond)
                {
-                 COND_EXPR_COND (stmt) = new_cond;
+                 COND_EXPR_COND (cond_expr) = new_cond;
                  update_stmt (stmt);
                }
            }
@@ -529,7 +530,7 @@ simplify_cond (tree stmt)
    times as possible.  */
 
 static void
-forward_propagate_into_cond (tree cond_expr)
+forward_propagate_into_cond (tree cond_expr, tree stmt)
 {
   gcc_assert (TREE_CODE (cond_expr) == COND_EXPR);
 
@@ -554,7 +555,7 @@ forward_propagate_into_cond (tree cond_expr)
        }
 
       COND_EXPR_COND (cond_expr) = new_cond;
-      update_stmt (cond_expr);
+      update_stmt (stmt);
 
       if (has_zero_uses (test_var))
        {
@@ -570,7 +571,7 @@ forward_propagate_into_cond (tree cond_expr)
      against a constant where the SSA_NAME is the result of a
      conversion.  Perhaps this should be folded into the rest
      of the COND_EXPR simplification code.  */
-  simplify_cond (cond_expr);
+  simplify_cond (cond_expr, stmt);
 }
 
 /* We've just substituted an ADDR_EXPR into stmt.  Update all the 
@@ -1016,6 +1017,11 @@ tree_ssa_forward_propagate_single_use_vars (void)
                  simplify_not_neg_expr (stmt);
                  bsi_next (&bsi);
                }
+              else if (TREE_CODE (rhs) == COND_EXPR)
+                {
+                  forward_propagate_into_cond (rhs, stmt);
+                 bsi_next (&bsi);
+                }
              else
                bsi_next (&bsi);
            }
@@ -1026,7 +1032,7 @@ tree_ssa_forward_propagate_single_use_vars (void)
            }
          else if (TREE_CODE (stmt) == COND_EXPR)
            {
-             forward_propagate_into_cond (stmt);
+             forward_propagate_into_cond (stmt, stmt);
              bsi_next (&bsi);
            }
          else
index 1092d176dbd73c51f2893411e11668973a1ef3e5..ed0a97c7533f468206508e3be00c48f2e3398697 100644 (file)
@@ -43,6 +43,7 @@ static sbitmap found_in_subgraph;
 
 /* Local functions.  */
 static int compare_values (tree val1, tree val2);
+static void vrp_meet (value_range_t *, value_range_t *);
 
 /* Location information for ASSERT_EXPRs.  Each instance of this
    structure describes an ASSERT_EXPR for an SSA name.  Since a single
@@ -1919,6 +1920,40 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
 }
 
 
+/* Extract range information from a conditional expression EXPR based on
+   the ranges of each of its operands and the expression code.  */
+
+static void
+extract_range_from_cond_expr (value_range_t *vr, tree expr)
+{
+  tree op0, op1;
+  value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+  value_range_t vr1 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+
+  /* Get value ranges for each operand.  For constant operands, create
+     a new value range with the operand to simplify processing.  */
+  op0 = COND_EXPR_THEN (expr);
+  if (TREE_CODE (op0) == SSA_NAME)
+    vr0 = *(get_value_range (op0));
+  else if (is_gimple_min_invariant (op0))
+    set_value_range (&vr0, VR_RANGE, op0, op0, NULL);
+  else
+    set_value_range_to_varying (&vr0);
+
+  op1 = COND_EXPR_ELSE (expr);
+  if (TREE_CODE (op1) == SSA_NAME)
+    vr1 = *(get_value_range (op1));
+  else if (is_gimple_min_invariant (op1))
+    set_value_range (&vr1, VR_RANGE, op1, op1, NULL);
+  else
+    set_value_range_to_varying (&vr1);
+
+  /* The resulting value range is the union of the operand ranges */
+  vrp_meet (&vr0, &vr1);
+  copy_value_range (vr, &vr0);
+}
+
+
 /* Extract range information from a comparison expression EXPR based
    on the range of its operand and the expression code.  */
 
@@ -1961,6 +1996,8 @@ extract_range_from_expr (value_range_t *vr, tree expr)
     extract_range_from_binary_expr (vr, expr);
   else if (TREE_CODE_CLASS (code) == tcc_unary)
     extract_range_from_unary_expr (vr, expr);
+  else if (code == COND_EXPR)
+    extract_range_from_cond_expr (vr, expr);
   else if (TREE_CODE_CLASS (code) == tcc_comparison)
     extract_range_from_comparison (vr, expr);
   else if (is_gimple_min_invariant (expr))