From 20e38fcf4ff4d96d4d12d2939a94495166811203 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Wed, 15 Apr 2015 12:51:49 -0600 Subject: [PATCH] re PR tree-optimization/47679 (Strange uninitialized warning after SRA) PR tree-optimization/47679 * tree-ssa-dom.c (build_and_record_new_cond): Moved to avoid need for forward declaration in upcoming changes. (record_conditions, record_edge_info): Likewise. From-SVN: r222130 --- gcc/ChangeLog | 5 + gcc/tree-ssa-dom.c | 691 +++++++++++++++++++++++---------------------- 2 files changed, 351 insertions(+), 345 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6fc26196636..afa9266d1f8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -12,6 +12,11 @@ 2015-04-15 Jeff Law + PR tree-optimization/47679 + * tree-ssa-dom.c (build_and_record_new_cond): Moved to avoid + need for forward declaration in upcoming changes. + (record_conditions, record_edge_info): Likewise. + PR rtl-optimization/42522 * cse.c (fold_rtx): Try to simplify a ZERO_EXTRACT or SIGN_EXTRACT as a whole object rather than simplifying diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index ea49eb7c3c7..907fa970775 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -827,6 +827,317 @@ free_all_edge_infos (void) } } +/* Build a cond_equivalence record indicating that the comparison + CODE holds between operands OP0 and OP1 and push it to **P. */ + +static void +build_and_record_new_cond (enum tree_code code, + tree op0, tree op1, + vec *p) +{ + cond_equivalence c; + struct hashable_expr *cond = &c.cond; + + gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison); + + cond->type = boolean_type_node; + cond->kind = EXPR_BINARY; + cond->ops.binary.op = code; + cond->ops.binary.opnd0 = op0; + cond->ops.binary.opnd1 = op1; + + c.value = boolean_true_node; + p->safe_push (c); +} + +/* Record that COND is true and INVERTED is false into the edge information + structure. Also record that any conditions dominated by COND are true + as well. + + For example, if a < b is true, then a <= b must also be true. */ + +static void +record_conditions (struct edge_info *edge_info, tree cond, tree inverted) +{ + tree op0, op1; + cond_equivalence c; + + if (!COMPARISON_CLASS_P (cond)) + return; + + op0 = TREE_OPERAND (cond, 0); + op1 = TREE_OPERAND (cond, 1); + + switch (TREE_CODE (cond)) + { + case LT_EXPR: + case GT_EXPR: + if (FLOAT_TYPE_P (TREE_TYPE (op0))) + { + build_and_record_new_cond (ORDERED_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (LTGT_EXPR, op0, op1, + &edge_info->cond_equivalences); + } + + build_and_record_new_cond ((TREE_CODE (cond) == LT_EXPR + ? LE_EXPR : GE_EXPR), + op0, op1, &edge_info->cond_equivalences); + build_and_record_new_cond (NE_EXPR, op0, op1, + &edge_info->cond_equivalences); + break; + + case GE_EXPR: + case LE_EXPR: + if (FLOAT_TYPE_P (TREE_TYPE (op0))) + { + build_and_record_new_cond (ORDERED_EXPR, op0, op1, + &edge_info->cond_equivalences); + } + break; + + case EQ_EXPR: + if (FLOAT_TYPE_P (TREE_TYPE (op0))) + { + build_and_record_new_cond (ORDERED_EXPR, op0, op1, + &edge_info->cond_equivalences); + } + build_and_record_new_cond (LE_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (GE_EXPR, op0, op1, + &edge_info->cond_equivalences); + break; + + case UNORDERED_EXPR: + build_and_record_new_cond (NE_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (UNLE_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (UNGE_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (UNEQ_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (UNLT_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (UNGT_EXPR, op0, op1, + &edge_info->cond_equivalences); + break; + + case UNLT_EXPR: + case UNGT_EXPR: + build_and_record_new_cond ((TREE_CODE (cond) == UNLT_EXPR + ? UNLE_EXPR : UNGE_EXPR), + op0, op1, &edge_info->cond_equivalences); + build_and_record_new_cond (NE_EXPR, op0, op1, + &edge_info->cond_equivalences); + break; + + case UNEQ_EXPR: + build_and_record_new_cond (UNLE_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (UNGE_EXPR, op0, op1, + &edge_info->cond_equivalences); + break; + + case LTGT_EXPR: + build_and_record_new_cond (NE_EXPR, op0, op1, + &edge_info->cond_equivalences); + build_and_record_new_cond (ORDERED_EXPR, op0, op1, + &edge_info->cond_equivalences); + break; + + default: + break; + } + + /* Now store the original true and false conditions into the first + two slots. */ + initialize_expr_from_cond (cond, &c.cond); + c.value = boolean_true_node; + edge_info->cond_equivalences.safe_push (c); + + /* It is possible for INVERTED to be the negation of a comparison, + and not a valid RHS or GIMPLE_COND condition. This happens because + invert_truthvalue may return such an expression when asked to invert + a floating-point comparison. These comparisons are not assumed to + obey the trichotomy law. */ + initialize_expr_from_cond (inverted, &c.cond); + c.value = boolean_false_node; + edge_info->cond_equivalences.safe_push (c); +} + +/* We have finished optimizing BB, record any information implied by + taking a specific outgoing edge from BB. */ + +static void +record_edge_info (basic_block bb) +{ + gimple_stmt_iterator gsi = gsi_last_bb (bb); + struct edge_info *edge_info; + + if (! gsi_end_p (gsi)) + { + gimple stmt = gsi_stmt (gsi); + location_t loc = gimple_location (stmt); + + if (gimple_code (stmt) == GIMPLE_SWITCH) + { + gswitch *switch_stmt = as_a (stmt); + tree index = gimple_switch_index (switch_stmt); + + if (TREE_CODE (index) == SSA_NAME) + { + int i; + int n_labels = gimple_switch_num_labels (switch_stmt); + tree *info = XCNEWVEC (tree, last_basic_block_for_fn (cfun)); + edge e; + edge_iterator ei; + + for (i = 0; i < n_labels; i++) + { + tree label = gimple_switch_label (switch_stmt, i); + basic_block target_bb = label_to_block (CASE_LABEL (label)); + if (CASE_HIGH (label) + || !CASE_LOW (label) + || info[target_bb->index]) + info[target_bb->index] = error_mark_node; + else + info[target_bb->index] = label; + } + + FOR_EACH_EDGE (e, ei, bb->succs) + { + basic_block target_bb = e->dest; + tree label = info[target_bb->index]; + + if (label != NULL && label != error_mark_node) + { + tree x = fold_convert_loc (loc, TREE_TYPE (index), + CASE_LOW (label)); + edge_info = allocate_edge_info (e); + edge_info->lhs = index; + edge_info->rhs = x; + } + } + free (info); + } + } + + /* A COND_EXPR may create equivalences too. */ + if (gimple_code (stmt) == GIMPLE_COND) + { + edge true_edge; + edge false_edge; + + tree op0 = gimple_cond_lhs (stmt); + tree op1 = gimple_cond_rhs (stmt); + enum tree_code code = gimple_cond_code (stmt); + + extract_true_false_edges_from_block (bb, &true_edge, &false_edge); + + /* Special case comparing booleans against a constant as we + know the value of OP0 on both arms of the branch. i.e., we + can record an equivalence for OP0 rather than COND. */ + if ((code == EQ_EXPR || code == NE_EXPR) + && TREE_CODE (op0) == SSA_NAME + && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE + && is_gimple_min_invariant (op1)) + { + if (code == EQ_EXPR) + { + edge_info = allocate_edge_info (true_edge); + edge_info->lhs = op0; + edge_info->rhs = (integer_zerop (op1) + ? boolean_false_node + : boolean_true_node); + + edge_info = allocate_edge_info (false_edge); + edge_info->lhs = op0; + edge_info->rhs = (integer_zerop (op1) + ? boolean_true_node + : boolean_false_node); + } + else + { + edge_info = allocate_edge_info (true_edge); + edge_info->lhs = op0; + edge_info->rhs = (integer_zerop (op1) + ? boolean_true_node + : boolean_false_node); + + edge_info = allocate_edge_info (false_edge); + edge_info->lhs = op0; + edge_info->rhs = (integer_zerop (op1) + ? boolean_false_node + : boolean_true_node); + } + } + else if (is_gimple_min_invariant (op0) + && (TREE_CODE (op1) == SSA_NAME + || is_gimple_min_invariant (op1))) + { + tree cond = build2 (code, boolean_type_node, op0, op1); + tree inverted = invert_truthvalue_loc (loc, cond); + bool can_infer_simple_equiv + = !(HONOR_SIGNED_ZEROS (op0) + && real_zerop (op0)); + struct edge_info *edge_info; + + edge_info = allocate_edge_info (true_edge); + record_conditions (edge_info, cond, inverted); + + if (can_infer_simple_equiv && code == EQ_EXPR) + { + edge_info->lhs = op1; + edge_info->rhs = op0; + } + + edge_info = allocate_edge_info (false_edge); + record_conditions (edge_info, inverted, cond); + + if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR) + { + edge_info->lhs = op1; + edge_info->rhs = op0; + } + } + + else if (TREE_CODE (op0) == SSA_NAME + && (TREE_CODE (op1) == SSA_NAME + || is_gimple_min_invariant (op1))) + { + tree cond = build2 (code, boolean_type_node, op0, op1); + tree inverted = invert_truthvalue_loc (loc, cond); + bool can_infer_simple_equiv + = !(HONOR_SIGNED_ZEROS (op1) + && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1))); + struct edge_info *edge_info; + + edge_info = allocate_edge_info (true_edge); + record_conditions (edge_info, cond, inverted); + + if (can_infer_simple_equiv && code == EQ_EXPR) + { + edge_info->lhs = op0; + edge_info->rhs = op1; + } + + edge_info = allocate_edge_info (false_edge); + record_conditions (edge_info, inverted, cond); + + if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR) + { + edge_info->lhs = op0; + edge_info->rhs = op1; + } + } + } + + /* ??? TRUTH_NOT_EXPR can create an equivalence too. */ + } +} + + class dom_opt_dom_walker : public dom_walker { public: @@ -1399,185 +1710,46 @@ debug_dominator_optimization_stats (void) } -/* Dump statistics for the hash table HTAB. */ - -static void -htab_statistics (FILE *file, const hash_table &htab) -{ - fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n", - (long) htab.size (), - (long) htab.elements (), - htab.collisions ()); -} - - -/* Enter condition equivalence into the expression hash table. - This indicates that a conditional expression has a known - boolean value. */ - -static void -record_cond (cond_equivalence *p) -{ - struct expr_hash_elt *element = XCNEW (struct expr_hash_elt); - expr_hash_elt **slot; - - initialize_hash_element_from_expr (&p->cond, p->value, element); - - slot = avail_exprs->find_slot_with_hash (element, element->hash, INSERT); - if (*slot == NULL) - { - *slot = element; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "1>>> "); - print_expr_hash_elt (dump_file, element); - } - - avail_exprs_stack.safe_push - (std::pair (element, NULL)); - } - else - free_expr_hash_elt (element); -} - -/* Build a cond_equivalence record indicating that the comparison - CODE holds between operands OP0 and OP1 and push it to **P. */ - -static void -build_and_record_new_cond (enum tree_code code, - tree op0, tree op1, - vec *p) -{ - cond_equivalence c; - struct hashable_expr *cond = &c.cond; - - gcc_assert (TREE_CODE_CLASS (code) == tcc_comparison); - - cond->type = boolean_type_node; - cond->kind = EXPR_BINARY; - cond->ops.binary.op = code; - cond->ops.binary.opnd0 = op0; - cond->ops.binary.opnd1 = op1; - - c.value = boolean_true_node; - p->safe_push (c); -} - -/* Record that COND is true and INVERTED is false into the edge information - structure. Also record that any conditions dominated by COND are true - as well. - - For example, if a < b is true, then a <= b must also be true. */ - -static void -record_conditions (struct edge_info *edge_info, tree cond, tree inverted) -{ - tree op0, op1; - cond_equivalence c; - - if (!COMPARISON_CLASS_P (cond)) - return; - - op0 = TREE_OPERAND (cond, 0); - op1 = TREE_OPERAND (cond, 1); - - switch (TREE_CODE (cond)) - { - case LT_EXPR: - case GT_EXPR: - if (FLOAT_TYPE_P (TREE_TYPE (op0))) - { - build_and_record_new_cond (ORDERED_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (LTGT_EXPR, op0, op1, - &edge_info->cond_equivalences); - } - - build_and_record_new_cond ((TREE_CODE (cond) == LT_EXPR - ? LE_EXPR : GE_EXPR), - op0, op1, &edge_info->cond_equivalences); - build_and_record_new_cond (NE_EXPR, op0, op1, - &edge_info->cond_equivalences); - break; - - case GE_EXPR: - case LE_EXPR: - if (FLOAT_TYPE_P (TREE_TYPE (op0))) - { - build_and_record_new_cond (ORDERED_EXPR, op0, op1, - &edge_info->cond_equivalences); - } - break; - - case EQ_EXPR: - if (FLOAT_TYPE_P (TREE_TYPE (op0))) - { - build_and_record_new_cond (ORDERED_EXPR, op0, op1, - &edge_info->cond_equivalences); - } - build_and_record_new_cond (LE_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (GE_EXPR, op0, op1, - &edge_info->cond_equivalences); - break; - - case UNORDERED_EXPR: - build_and_record_new_cond (NE_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (UNLE_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (UNGE_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (UNEQ_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (UNLT_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (UNGT_EXPR, op0, op1, - &edge_info->cond_equivalences); - break; - - case UNLT_EXPR: - case UNGT_EXPR: - build_and_record_new_cond ((TREE_CODE (cond) == UNLT_EXPR - ? UNLE_EXPR : UNGE_EXPR), - op0, op1, &edge_info->cond_equivalences); - build_and_record_new_cond (NE_EXPR, op0, op1, - &edge_info->cond_equivalences); - break; +/* Dump statistics for the hash table HTAB. */ - case UNEQ_EXPR: - build_and_record_new_cond (UNLE_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (UNGE_EXPR, op0, op1, - &edge_info->cond_equivalences); - break; +static void +htab_statistics (FILE *file, const hash_table &htab) +{ + fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n", + (long) htab.size (), + (long) htab.elements (), + htab.collisions ()); +} - case LTGT_EXPR: - build_and_record_new_cond (NE_EXPR, op0, op1, - &edge_info->cond_equivalences); - build_and_record_new_cond (ORDERED_EXPR, op0, op1, - &edge_info->cond_equivalences); - break; - default: - break; - } +/* Enter condition equivalence into the expression hash table. + This indicates that a conditional expression has a known + boolean value. */ - /* Now store the original true and false conditions into the first - two slots. */ - initialize_expr_from_cond (cond, &c.cond); - c.value = boolean_true_node; - edge_info->cond_equivalences.safe_push (c); +static void +record_cond (cond_equivalence *p) +{ + struct expr_hash_elt *element = XCNEW (struct expr_hash_elt); + expr_hash_elt **slot; - /* It is possible for INVERTED to be the negation of a comparison, - and not a valid RHS or GIMPLE_COND condition. This happens because - invert_truthvalue may return such an expression when asked to invert - a floating-point comparison. These comparisons are not assumed to - obey the trichotomy law. */ - initialize_expr_from_cond (inverted, &c.cond); - c.value = boolean_false_node; - edge_info->cond_equivalences.safe_push (c); + initialize_hash_element_from_expr (&p->cond, p->value, element); + + slot = avail_exprs->find_slot_with_hash (element, element->hash, INSERT); + if (*slot == NULL) + { + *slot = element; + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "1>>> "); + print_expr_hash_elt (dump_file, element); + } + + avail_exprs_stack.safe_push + (std::pair (element, NULL)); + } + else + free_expr_hash_elt (element); } /* A helper function for record_const_or_copy and record_equality. @@ -1814,177 +1986,6 @@ cprop_into_successor_phis (basic_block bb) } } -/* We have finished optimizing BB, record any information implied by - taking a specific outgoing edge from BB. */ - -static void -record_edge_info (basic_block bb) -{ - gimple_stmt_iterator gsi = gsi_last_bb (bb); - struct edge_info *edge_info; - - if (! gsi_end_p (gsi)) - { - gimple stmt = gsi_stmt (gsi); - location_t loc = gimple_location (stmt); - - if (gimple_code (stmt) == GIMPLE_SWITCH) - { - gswitch *switch_stmt = as_a (stmt); - tree index = gimple_switch_index (switch_stmt); - - if (TREE_CODE (index) == SSA_NAME) - { - int i; - int n_labels = gimple_switch_num_labels (switch_stmt); - tree *info = XCNEWVEC (tree, last_basic_block_for_fn (cfun)); - edge e; - edge_iterator ei; - - for (i = 0; i < n_labels; i++) - { - tree label = gimple_switch_label (switch_stmt, i); - basic_block target_bb = label_to_block (CASE_LABEL (label)); - if (CASE_HIGH (label) - || !CASE_LOW (label) - || info[target_bb->index]) - info[target_bb->index] = error_mark_node; - else - info[target_bb->index] = label; - } - - FOR_EACH_EDGE (e, ei, bb->succs) - { - basic_block target_bb = e->dest; - tree label = info[target_bb->index]; - - if (label != NULL && label != error_mark_node) - { - tree x = fold_convert_loc (loc, TREE_TYPE (index), - CASE_LOW (label)); - edge_info = allocate_edge_info (e); - edge_info->lhs = index; - edge_info->rhs = x; - } - } - free (info); - } - } - - /* A COND_EXPR may create equivalences too. */ - if (gimple_code (stmt) == GIMPLE_COND) - { - edge true_edge; - edge false_edge; - - tree op0 = gimple_cond_lhs (stmt); - tree op1 = gimple_cond_rhs (stmt); - enum tree_code code = gimple_cond_code (stmt); - - extract_true_false_edges_from_block (bb, &true_edge, &false_edge); - - /* Special case comparing booleans against a constant as we - know the value of OP0 on both arms of the branch. i.e., we - can record an equivalence for OP0 rather than COND. */ - if ((code == EQ_EXPR || code == NE_EXPR) - && TREE_CODE (op0) == SSA_NAME - && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE - && is_gimple_min_invariant (op1)) - { - if (code == EQ_EXPR) - { - edge_info = allocate_edge_info (true_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) - ? boolean_false_node - : boolean_true_node); - - edge_info = allocate_edge_info (false_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) - ? boolean_true_node - : boolean_false_node); - } - else - { - edge_info = allocate_edge_info (true_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) - ? boolean_true_node - : boolean_false_node); - - edge_info = allocate_edge_info (false_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) - ? boolean_false_node - : boolean_true_node); - } - } - else if (is_gimple_min_invariant (op0) - && (TREE_CODE (op1) == SSA_NAME - || is_gimple_min_invariant (op1))) - { - tree cond = build2 (code, boolean_type_node, op0, op1); - tree inverted = invert_truthvalue_loc (loc, cond); - bool can_infer_simple_equiv - = !(HONOR_SIGNED_ZEROS (op0) - && real_zerop (op0)); - struct edge_info *edge_info; - - edge_info = allocate_edge_info (true_edge); - record_conditions (edge_info, cond, inverted); - - if (can_infer_simple_equiv && code == EQ_EXPR) - { - edge_info->lhs = op1; - edge_info->rhs = op0; - } - - edge_info = allocate_edge_info (false_edge); - record_conditions (edge_info, inverted, cond); - - if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR) - { - edge_info->lhs = op1; - edge_info->rhs = op0; - } - } - - else if (TREE_CODE (op0) == SSA_NAME - && (TREE_CODE (op1) == SSA_NAME - || is_gimple_min_invariant (op1))) - { - tree cond = build2 (code, boolean_type_node, op0, op1); - tree inverted = invert_truthvalue_loc (loc, cond); - bool can_infer_simple_equiv - = !(HONOR_SIGNED_ZEROS (op1) - && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1))); - struct edge_info *edge_info; - - edge_info = allocate_edge_info (true_edge); - record_conditions (edge_info, cond, inverted); - - if (can_infer_simple_equiv && code == EQ_EXPR) - { - edge_info->lhs = op0; - edge_info->rhs = op1; - } - - edge_info = allocate_edge_info (false_edge); - record_conditions (edge_info, inverted, cond); - - if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR) - { - edge_info->lhs = op0; - edge_info->rhs = op1; - } - } - } - - /* ??? TRUTH_NOT_EXPR can create an equivalence too. */ - } -} - void dom_opt_dom_walker::before_dom_children (basic_block bb) { -- 2.30.2