diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 58f9cd838cd3..a0b92c9af7e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2007-01-08 Roberto Costa + + * 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 * tree-ssa-forwprop.c (forward_propagate_into_cond, diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 7ae87d675398..a93464b22fa7 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -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; diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 493bdecedcde..0f02b8c86515 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -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) diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index a5267ae3970e..39653fcfc794 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -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 diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 1092d176dbd7..ed0a97c7533f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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))