From: Jan Hubicka Date: Thu, 18 May 2017 14:18:08 +0000 (+0200) Subject: ipa-inline-analysis.c (predicate_conditions): Move to ipa-inline.h (true_predicate... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dbcb3c7446c4c9f8f491db6a71bbab318918c874;p=gcc.git ipa-inline-analysis.c (predicate_conditions): Move to ipa-inline.h (true_predicate... * ipa-inline-analysis.c (predicate_conditions): Move to ipa-inline.h (true_predicate, false_predicate, true_predicate_p, false_predicate_p): Remove. (single_cond_predicate, not_inlined_predicate): Turn to member function in ipa-inline.h (add_condition): Update. (add_clause): Turn to... (predicate::add_clause): ... this one; update; allow passing NULL as parameter. (and_predicates): Turn to ... (predicate::operator &=): ... this one. (predicates_equal_p): Move to predicate::operator == in ipa-inline.h (or_predicates): Turn to ... (predicate::or_with): ... this one. (evaluate_predicate): Turn to ... (predicate::evaluate): ... this one. (predicate_probability): Turn to ... (predicate::probability): ... this one. (dump_condition): Update. (dump_predicate): Turn to ... (predicate::dump): ... this one. (account_size_time): Update. (edge_set_predicate): Update. (set_hint_predicate): UPdate. (evaluate_conditions_for_known_args): Update. (evaluate_properties_for_edge): Update. (remap_predicate_after_duplication): Turn to... (predicate::remap_after_duplication): ... this one. (remap_hint_predicate_after_duplication): Update. (inline_summary_t::duplicate): UPdate. (dump_inline_edge_summary): Update. (dump_inline_summary): Update. (set_cond_stmt_execution_predicate): Update. (set_switch_stmt_execution_predicate): Update. (compute_bb_predicates): Update. (will_be_nonconstant_expr_predicate): Update. (will_be_nonconstant_predicate): Update. (phi_result_unknown_predicate): Update. (predicate_for_phi_result): Update. (array_index_predicate): Update. (estimate_function_body_sizes): Update. (estimate_node_size_and_time): Update. (estimate_ipcp_clone_size_and_time): Update. (remap_predicate): Rename to ... (predicate::remap_after_inlining): ... this one. (remap_hint_predicate): Update. (inline_merge_summary): Update. (inline_update_overall_summary): Update. (estimate_size_after_inlining): Update. (read_predicate): Rename to ... (predicate::stream_in): ... this one. (read_inline_edge_summary): Update. (write_predicate): Rename to ... (predicate::stream_out): ... this one. (write_inline_edge_summary): Update. * ipa-inline.h (MAX_CLAUSES): Turn to predicate::max_clauses. (clause_t): Turn to uint32_t (predicate): Turn to class; implement constructor and operators ==, !=, & (size_time_entry): Update. (inline_summary): Update. (inline_edge_summary): Update. From-SVN: r248204 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee04a860680..3ced7226cc9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,68 @@ +2017-05-18 Jan Hubicka + + * ipa-inline-analysis.c (predicate_conditions): Move to ipa-inline.h + (true_predicate, false_predicate, true_predicate_p, + false_predicate_p): Remove. + (single_cond_predicate, not_inlined_predicate): Turn to member function + in ipa-inline.h + (add_condition): Update. + (add_clause): Turn to... + (predicate::add_clause): ... this one; update; allow passing NULL + as parameter. + (and_predicates): Turn to ... + (predicate::operator &=): ... this one. + (predicates_equal_p): Move to predicate::operator == in ipa-inline.h + (or_predicates): Turn to ... + (predicate::or_with): ... this one. + (evaluate_predicate): Turn to ... + (predicate::evaluate): ... this one. + (predicate_probability): Turn to ... + (predicate::probability): ... this one. + (dump_condition): Update. + (dump_predicate): Turn to ... + (predicate::dump): ... this one. + (account_size_time): Update. + (edge_set_predicate): Update. + (set_hint_predicate): UPdate. + (evaluate_conditions_for_known_args): Update. + (evaluate_properties_for_edge): Update. + (remap_predicate_after_duplication): Turn to... + (predicate::remap_after_duplication): ... this one. + (remap_hint_predicate_after_duplication): Update. + (inline_summary_t::duplicate): UPdate. + (dump_inline_edge_summary): Update. + (dump_inline_summary): Update. + (set_cond_stmt_execution_predicate): Update. + (set_switch_stmt_execution_predicate): Update. + (compute_bb_predicates): Update. + (will_be_nonconstant_expr_predicate): Update. + (will_be_nonconstant_predicate): Update. + (phi_result_unknown_predicate): Update. + (predicate_for_phi_result): Update. + (array_index_predicate): Update. + (estimate_function_body_sizes): Update. + (estimate_node_size_and_time): Update. + (estimate_ipcp_clone_size_and_time): Update. + (remap_predicate): Rename to ... + (predicate::remap_after_inlining): ... this one. + (remap_hint_predicate): Update. + (inline_merge_summary): Update. + (inline_update_overall_summary): Update. + (estimate_size_after_inlining): Update. + (read_predicate): Rename to ... + (predicate::stream_in): ... this one. + (read_inline_edge_summary): Update. + (write_predicate): Rename to ... + (predicate::stream_out): ... this one. + (write_inline_edge_summary): Update. + * ipa-inline.h (MAX_CLAUSES): Turn to predicate::max_clauses. + (clause_t): Turn to uint32_t + (predicate): Turn to class; implement constructor and operators + ==, !=, & + (size_time_entry): Update. + (inline_summary): Update. + (inline_edge_summary): Update. + 2017-05-18 Marc Glisse * fold-const.c (fold_binary_loc): Move transformation... diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index dcfed9e4c4c..ee8744449a0 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -44,17 +44,7 @@ along with GCC; see the file COPYING3. If not see It is easy to add more variants. To represent function size and time that depends on context (i.e. it is known to be optimized away when context is known either by inlining or from IP-CP and cloning), - we use predicates. Predicates are logical formulas in - conjunctive-disjunctive form consisting of clauses. Clauses are bitmaps - specifying what conditions must be true. Conditions are simple test - of the form described above. - - In order to make predicate (possibly) true, all of its clauses must - be (possibly) true. To make clause (possibly) true, one of conditions - it mentions must be (possibly) true. There are fixed bounds on - number of clauses and conditions and all the manipulation functions - are conservative in positive direction. I.e. we may lose precision - by thinking that predicate may be true even when it is not. + we use predicates. estimate_edge_size and estimate_edge_growth can be used to query function size/time in the given context. inline_merge_summary merges @@ -100,13 +90,6 @@ along with GCC; see the file COPYING3. If not see hosts. */ #define NUM_CONDITIONS 32 -enum predicate_conditions -{ - predicate_false_condition = 0, - predicate_not_inlined_condition = 1, - predicate_first_dynamic_condition = 2 -}; - /* Special condition code we use to represent test that operand is compile time constant. */ #define IS_NOT_CONSTANT ERROR_MARK @@ -134,71 +117,6 @@ vec edge_growth_cache; /* Edge predicates goes here. */ static object_allocator edge_predicate_pool ("edge predicates"); -/* Return true predicate (tautology). - We represent it by empty list of clauses. */ - -static inline struct predicate -true_predicate (void) -{ - struct predicate p; - p.clause[0] = 0; - return p; -} - - -/* Return predicate testing single condition number COND. */ - -static inline struct predicate -single_cond_predicate (int cond) -{ - struct predicate p; - p.clause[0] = 1 << cond; - p.clause[1] = 0; - return p; -} - - -/* Return false predicate. First clause require false condition. */ - -static inline struct predicate -false_predicate (void) -{ - return single_cond_predicate (predicate_false_condition); -} - - -/* Return true if P is (true). */ - -static inline bool -true_predicate_p (struct predicate *p) -{ - return !p->clause[0]; -} - - -/* Return true if P is (false). */ - -static inline bool -false_predicate_p (struct predicate *p) -{ - if (p->clause[0] == (1 << predicate_false_condition)) - { - gcc_checking_assert (!p->clause[1] - && p->clause[0] == 1 << predicate_false_condition); - return true; - } - return false; -} - - -/* Return predicate that is set true when function is not inlined. */ - -static inline struct predicate -not_inlined_predicate (void) -{ - return single_cond_predicate (predicate_not_inlined_condition); -} - /* Simple description of whether a memory load or a condition refers to a load from an aggregate and if so, how and where from in the aggregate. Individual fields have the same meaning like fields with the same name in @@ -216,7 +134,7 @@ struct agg_position_info used operand is loaded from an aggregate and where in the aggregate it is. It can be NULL, which means this not a load from an aggregate. */ -static struct predicate +static predicate add_condition (struct inline_summary *summary, int operand_num, HOST_WIDE_INT size, struct agg_position_info *aggpos, enum tree_code code, tree val) @@ -249,11 +167,11 @@ add_condition (struct inline_summary *summary, int operand_num, && c->val == val && c->agg_contents == agg_contents && (!agg_contents || (c->offset == offset && c->by_ref == by_ref))) - return single_cond_predicate (i + predicate_first_dynamic_condition); + return predicate::predicate_testing_cond (i); } /* Too many conditions. Give up and return constant true. */ - if (i == NUM_CONDITIONS - predicate_first_dynamic_condition) - return true_predicate (); + if (i == NUM_CONDITIONS - predicate::first_dynamic_condition) + return true; new_cond.operand_num = operand_num; new_cond.code = code; @@ -263,14 +181,18 @@ add_condition (struct inline_summary *summary, int operand_num, new_cond.offset = offset; new_cond.size = size; vec_safe_push (summary->conds, new_cond); - return single_cond_predicate (i + predicate_first_dynamic_condition); + + return predicate::predicate_testing_cond (i); } -/* Add clause CLAUSE into the predicate P. */ +/* Add clause CLAUSE into the predicate P. + When CONDITIONS is NULL do not perform checking whether NEW_CLAUSE + is obviously true. This is useful only when NEW_CLAUSE is known to be + sane. */ -static inline void -add_clause (conditions conditions, struct predicate *p, clause_t clause) +void +predicate::add_clause (conditions conditions, clause_t new_clause) { int i; int i2; @@ -278,34 +200,33 @@ add_clause (conditions conditions, struct predicate *p, clause_t clause) int c1, c2; /* True clause. */ - if (!clause) + if (!new_clause) return; /* False clause makes the whole predicate false. Kill the other variants. */ - if (clause == (1 << predicate_false_condition)) + if (new_clause == (1 << predicate::false_condition)) { - p->clause[0] = (1 << predicate_false_condition); - p->clause[1] = 0; + *this = false; return; } - if (false_predicate_p (p)) + if (*this == false) return; /* No one should be silly enough to add false into nontrivial clauses. */ - gcc_checking_assert (!(clause & (1 << predicate_false_condition))); + gcc_checking_assert (!(new_clause & (1 << predicate::false_condition))); - /* Look where to insert the clause. At the same time prune out - clauses of P that are implied by the new clause and thus + /* Look where to insert the new_clause. At the same time prune out + new_clauses of P that are implied by the new new_clause and thus redundant. */ - for (i = 0, i2 = 0; i <= MAX_CLAUSES; i++) + for (i = 0, i2 = 0; i <= max_clauses; i++) { - p->clause[i2] = p->clause[i]; + m_clause[i2] = m_clause[i]; - if (!p->clause[i]) + if (!m_clause[i]) break; - /* If p->clause[i] implies clause, there is nothing to add. */ - if ((p->clause[i] & clause) == p->clause[i]) + /* If m_clause[i] implies new_clause, there is nothing to add. */ + if ((m_clause[i] & new_clause) == m_clause[i]) { /* We had nothing to add, none of clauses should've become redundant. */ @@ -313,132 +234,113 @@ add_clause (conditions conditions, struct predicate *p, clause_t clause) return; } - if (p->clause[i] < clause && insert_here < 0) + if (m_clause[i] < new_clause && insert_here < 0) insert_here = i2; - /* If clause implies p->clause[i], then p->clause[i] becomes redundant. - Otherwise the p->clause[i] has to stay. */ - if ((p->clause[i] & clause) != clause) + /* If new_clause implies clause[i], then clause[i] becomes redundant. + Otherwise the clause[i] has to stay. */ + if ((m_clause[i] & new_clause) != new_clause) i2++; } /* Look for clauses that are obviously true. I.e. op0 == 5 || op0 != 5. */ - for (c1 = predicate_first_dynamic_condition; c1 < NUM_CONDITIONS; c1++) - { - condition *cc1; - if (!(clause & (1 << c1))) - continue; - cc1 = &(*conditions)[c1 - predicate_first_dynamic_condition]; - /* We have no way to represent !CHANGED and !IS_NOT_CONSTANT - and thus there is no point for looking for them. */ - if (cc1->code == CHANGED || cc1->code == IS_NOT_CONSTANT) - continue; - for (c2 = c1 + 1; c2 < NUM_CONDITIONS; c2++) - if (clause & (1 << c2)) - { - condition *cc1 = - &(*conditions)[c1 - predicate_first_dynamic_condition]; - condition *cc2 = - &(*conditions)[c2 - predicate_first_dynamic_condition]; - if (cc1->operand_num == cc2->operand_num - && cc1->val == cc2->val - && cc2->code != IS_NOT_CONSTANT - && cc2->code != CHANGED - && cc1->code == invert_tree_comparison (cc2->code, - HONOR_NANS (cc1->val))) - return; - } - } + if (conditions) + for (c1 = predicate::first_dynamic_condition; c1 < NUM_CONDITIONS; c1++) + { + condition *cc1; + if (!(new_clause & (1 << c1))) + continue; + cc1 = &(*conditions)[c1 - predicate::first_dynamic_condition]; + /* We have no way to represent !CHANGED and !IS_NOT_CONSTANT + and thus there is no point for looking for them. */ + if (cc1->code == CHANGED || cc1->code == IS_NOT_CONSTANT) + continue; + for (c2 = c1 + 1; c2 < NUM_CONDITIONS; c2++) + if (new_clause & (1 << c2)) + { + condition *cc1 = + &(*conditions)[c1 - predicate::first_dynamic_condition]; + condition *cc2 = + &(*conditions)[c2 - predicate::first_dynamic_condition]; + if (cc1->operand_num == cc2->operand_num + && cc1->val == cc2->val + && cc2->code != IS_NOT_CONSTANT + && cc2->code != CHANGED + && cc1->code == invert_tree_comparison (cc2->code, + HONOR_NANS (cc1->val))) + return; + } + } /* We run out of variants. Be conservative in positive direction. */ - if (i2 == MAX_CLAUSES) + if (i2 == max_clauses) return; /* Keep clauses in decreasing order. This makes equivalence testing easy. */ - p->clause[i2 + 1] = 0; + m_clause[i2 + 1] = 0; if (insert_here >= 0) for (; i2 > insert_here; i2--) - p->clause[i2] = p->clause[i2 - 1]; + m_clause[i2] = m_clause[i2 - 1]; else insert_here = i2; - p->clause[insert_here] = clause; + m_clause[insert_here] = new_clause; } -/* Return P & P2. */ +/* Do THIS &= P. */ -static struct predicate -and_predicates (conditions conditions, - struct predicate *p, struct predicate *p2) +predicate & +predicate::operator &= (const predicate &p) { - struct predicate out = *p; - int i; - /* Avoid busy work. */ - if (false_predicate_p (p2) || true_predicate_p (p)) - return *p2; - if (false_predicate_p (p) || true_predicate_p (p2)) - return *p; + if (p == false || *this == true) + { + *this = p; + return *this; + } + if (*this == false || p == true || this == &p) + return *this; + + int i; /* See how far predicates match. */ - for (i = 0; p->clause[i] && p->clause[i] == p2->clause[i]; i++) + for (i = 0; m_clause[i] && m_clause[i] == p.m_clause[i]; i++) { - gcc_checking_assert (i < MAX_CLAUSES); + gcc_checking_assert (i < max_clauses); } /* Combine the predicates rest. */ - for (; p2->clause[i]; i++) + for (; p.m_clause[i]; i++) { - gcc_checking_assert (i < MAX_CLAUSES); - add_clause (conditions, &out, p2->clause[i]); + gcc_checking_assert (i < max_clauses); + add_clause (NULL, p.m_clause[i]); } - return out; + return *this; } -/* Return true if predicates are obviously equal. */ - -static inline bool -predicates_equal_p (struct predicate *p, struct predicate *p2) -{ - int i; - for (i = 0; p->clause[i]; i++) - { - gcc_checking_assert (i < MAX_CLAUSES); - gcc_checking_assert (p->clause[i] > p->clause[i + 1]); - gcc_checking_assert (!p2->clause[i] - || p2->clause[i] > p2->clause[i + 1]); - if (p->clause[i] != p2->clause[i]) - return false; - } - return !p2->clause[i]; -} - -/* Return P | P2. */ +/* Return THIS | P2. */ -static struct predicate -or_predicates (conditions conditions, - struct predicate *p, struct predicate *p2) +predicate +predicate::or_with (conditions conditions, + const predicate &p) const { - struct predicate out = true_predicate (); - int i, j; - /* Avoid busy work. */ - if (false_predicate_p (p2) || true_predicate_p (p)) - return *p; - if (false_predicate_p (p) || true_predicate_p (p2)) - return *p2; - if (predicates_equal_p (p, p2)) - return *p; + if (p == false || *this == true || *this == p) + return *this; + if (*this == false || p == true) + return p; /* OK, combine the predicates. */ - for (i = 0; p->clause[i]; i++) - for (j = 0; p2->clause[j]; j++) + predicate out = true; + + for (int i = 0; m_clause[i]; i++) + for (int j = 0; p.m_clause[j]; j++) { - gcc_checking_assert (i < MAX_CLAUSES && j < MAX_CLAUSES); - add_clause (conditions, &out, p->clause[i] | p2->clause[j]); + gcc_checking_assert (i < max_clauses && j < max_clauses); + out.add_clause (conditions, m_clause[i] | p.m_clause[j]); } return out; } @@ -447,22 +349,22 @@ or_predicates (conditions conditions, /* Having partial truth assignment in POSSIBLE_TRUTHS, return false if predicate P is known to be false. */ -static bool -evaluate_predicate (struct predicate *p, clause_t possible_truths) +bool +predicate::evaluate (clause_t possible_truths) const { int i; /* True remains true. */ - if (true_predicate_p (p)) + if (*this == true) return true; - gcc_assert (!(possible_truths & (1 << predicate_false_condition))); + gcc_assert (!(possible_truths & (1 << predicate::false_condition))); /* See if we can find clause we can disprove. */ - for (i = 0; p->clause[i]; i++) + for (i = 0; m_clause[i]; i++) { - gcc_checking_assert (i < MAX_CLAUSES); - if (!(p->clause[i] & possible_truths)) + gcc_checking_assert (i < max_clauses); + if (!(m_clause[i] & possible_truths)) return false; } return true; @@ -471,28 +373,28 @@ evaluate_predicate (struct predicate *p, clause_t possible_truths) /* Return the probability in range 0...REG_BR_PROB_BASE that the predicated instruction will be recomputed per invocation of the inlined call. */ -static int -predicate_probability (conditions conds, - struct predicate *p, clause_t possible_truths, - vec inline_param_summary) +int +predicate::probability (conditions conds, + clause_t possible_truths, + vec inline_param_summary) const { int i; int combined_prob = REG_BR_PROB_BASE; /* True remains true. */ - if (true_predicate_p (p)) + if (*this == true) return REG_BR_PROB_BASE; - if (false_predicate_p (p)) + if (*this == false) return 0; - gcc_assert (!(possible_truths & (1 << predicate_false_condition))); + gcc_assert (!(possible_truths & (1 << predicate::false_condition))); /* See if we can find clause we can disprove. */ - for (i = 0; p->clause[i]; i++) + for (i = 0; m_clause[i]; i++) { - gcc_checking_assert (i < MAX_CLAUSES); - if (!(p->clause[i] & possible_truths)) + gcc_checking_assert (i < max_clauses); + if (!(m_clause[i] & possible_truths)) return 0; else { @@ -501,12 +403,12 @@ predicate_probability (conditions conds, if (!inline_param_summary.exists ()) return REG_BR_PROB_BASE; for (i2 = 0; i2 < NUM_CONDITIONS; i2++) - if ((p->clause[i] & possible_truths) & (1 << i2)) + if ((m_clause[i] & possible_truths) & (1 << i2)) { - if (i2 >= predicate_first_dynamic_condition) + if (i2 >= predicate::first_dynamic_condition) { condition *c = - &(*conds)[i2 - predicate_first_dynamic_condition]; + &(*conds)[i2 - predicate::first_dynamic_condition]; if (c->code == CHANGED && (c->operand_num < (int) inline_param_summary.length ())) @@ -536,13 +438,13 @@ static void dump_condition (FILE *f, conditions conditions, int cond) { condition *c; - if (cond == predicate_false_condition) + if (cond == predicate::false_condition) fprintf (f, "false"); - else if (cond == predicate_not_inlined_condition) + else if (cond == predicate::not_inlined_condition) fprintf (f, "not inlined"); else { - c = &(*conditions)[cond - predicate_first_dynamic_condition]; + c = &(*conditions)[cond - predicate::first_dynamic_condition]; fprintf (f, "op%i", c->operand_num); if (c->agg_contents) fprintf (f, "[%soffset: " HOST_WIDE_INT_PRINT_DEC "]", @@ -585,22 +487,21 @@ dump_clause (FILE *f, conditions conds, clause_t clause) } -/* Dump PREDICATE to F. CONDS a vector of conditions used when evauating +/* Dump THIS to F. CONDS a vector of conditions used when evauating predicats. When NL is true new line is output at the end of dump. */ -static void -dump_predicate (FILE *f, conditions conds, struct predicate *pred, - bool nl = true) +void +predicate::dump (FILE *f, conditions conds, bool nl) const { int i; - if (true_predicate_p (pred)) + if (*this == true) dump_clause (f, conds, 0); else - for (i = 0; pred->clause[i]; i++) + for (i = 0; m_clause[i]; i++) { if (i) fprintf (f, " && "); - dump_clause (f, conds, pred->clause[i]); + dump_clause (f, conds, m_clause[i]); } if (nl) fprintf (f, "\n"); @@ -670,20 +571,20 @@ dump_inline_hints (FILE *f, inline_hints hints) static void account_size_time (struct inline_summary *summary, int size, sreal time, - struct predicate *exec_pred, - struct predicate *nonconst_pred_ptr) + predicate *exec_pred, + predicate *nonconst_pred_ptr) { size_time_entry *e; bool found = false; int i; - struct predicate nonconst_pred; + predicate nonconst_pred; - if (false_predicate_p (exec_pred)) + if (*exec_pred == false) return; - nonconst_pred = and_predicates (summary->conds, nonconst_pred_ptr, exec_pred); + nonconst_pred = *nonconst_pred_ptr & *exec_pred; - if (false_predicate_p (&nonconst_pred)) + if (nonconst_pred == false) return; /* We need to create initial empty unconitional clause, but otherwie @@ -694,8 +595,8 @@ account_size_time (struct inline_summary *summary, int size, sreal time, gcc_assert (time >= 0); for (i = 0; vec_safe_iterate (summary->entry, i, &e); i++) - if (predicates_equal_p (&e->exec_predicate, exec_pred) - && predicates_equal_p (&e->nonconst_predicate, &nonconst_pred)) + if (e->exec_predicate == *exec_pred + && e->nonconst_predicate == nonconst_pred) { found = true; break; @@ -705,7 +606,6 @@ account_size_time (struct inline_summary *summary, int size, sreal time, i = 0; found = true; e = &(*summary->entry)[0]; - gcc_assert (!e->exec_predicate.clause[0]); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "\t\tReached limit on number of entries, " @@ -717,11 +617,11 @@ account_size_time (struct inline_summary *summary, int size, sreal time, "\t\tAccounting size:%3.2f, time:%3.2f on %spredicate exec:", ((double) size) / INLINE_SIZE_SCALE, (time.to_double ()), found ? "" : "new "); - dump_predicate (dump_file, summary->conds, exec_pred, 0); - if (!predicates_equal_p (exec_pred, &nonconst_pred)) + exec_pred->dump (dump_file, summary->conds, 0); + if (*exec_pred != nonconst_pred) { fprintf (dump_file, " nonconst:"); - dump_predicate (dump_file, summary->conds, &nonconst_pred); + nonconst_pred.dump (dump_file, summary->conds); } else fprintf (dump_file, "\n"); @@ -771,11 +671,11 @@ redirect_to_unreachable (struct cgraph_edge *e) /* Set predicate for edge E. */ static void -edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate) +edge_set_predicate (struct cgraph_edge *e, predicate *predicate) { /* If the edge is determined to be never executed, redirect it to BUILTIN_UNREACHABLE to save inliner from inlining into it. */ - if (predicate && false_predicate_p (predicate) + if (predicate && *predicate == false /* When handling speculative edges, we need to do the redirection just once. Do it always on the direct edge, so we do not attempt to resolve speculation while duplicating the edge. */ @@ -783,7 +683,7 @@ edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate) e = redirect_to_unreachable (e); struct inline_edge_summary *es = inline_edge_summary (e); - if (predicate && !true_predicate_p (predicate)) + if (predicate && *predicate != true) { if (!es->predicate) es->predicate = edge_predicate_pool.allocate (); @@ -800,9 +700,9 @@ edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate) /* Set predicate for hint *P. */ static void -set_hint_predicate (struct predicate **p, struct predicate new_predicate) +set_hint_predicate (predicate **p, predicate new_predicate) { - if (false_predicate_p (&new_predicate) || true_predicate_p (&new_predicate)) + if (new_predicate == false || new_predicate == true) { if (*p) edge_predicate_pool.remove (*p); @@ -842,8 +742,8 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, clause_t *ret_clause, clause_t *ret_nonspec_clause) { - clause_t clause = inline_p ? 0 : 1 << predicate_not_inlined_condition; - clause_t nonspec_clause = 1 << predicate_not_inlined_condition; + clause_t clause = inline_p ? 0 : 1 << predicate::not_inlined_condition; + clause_t nonspec_clause = 1 << predicate::not_inlined_condition; struct inline_summary *info = inline_summaries->get (node); int i; struct condition *c; @@ -861,8 +761,8 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, || (known_vals.length () == known_aggs.length ())); if (c->operand_num >= (int) known_vals.length ()) { - clause |= 1 << (i + predicate_first_dynamic_condition); - nonspec_clause |= 1 << (i + predicate_first_dynamic_condition); + clause |= 1 << (i + predicate::first_dynamic_condition); + nonspec_clause |= 1 << (i + predicate::first_dynamic_condition); continue; } @@ -893,25 +793,25 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, if (!val) { - clause |= 1 << (i + predicate_first_dynamic_condition); - nonspec_clause |= 1 << (i + predicate_first_dynamic_condition); + clause |= 1 << (i + predicate::first_dynamic_condition); + nonspec_clause |= 1 << (i + predicate::first_dynamic_condition); continue; } if (c->code == CHANGED) { - nonspec_clause |= 1 << (i + predicate_first_dynamic_condition); + nonspec_clause |= 1 << (i + predicate::first_dynamic_condition); continue; } if (tree_to_shwi (TYPE_SIZE (TREE_TYPE (val))) != c->size) { - clause |= 1 << (i + predicate_first_dynamic_condition); - nonspec_clause |= 1 << (i + predicate_first_dynamic_condition); + clause |= 1 << (i + predicate::first_dynamic_condition); + nonspec_clause |= 1 << (i + predicate::first_dynamic_condition); continue; } if (c->code == IS_NOT_CONSTANT) { - nonspec_clause |= 1 << (i + predicate_first_dynamic_condition); + nonspec_clause |= 1 << (i + predicate::first_dynamic_condition); continue; } @@ -923,8 +823,8 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, if (res && integer_zerop (res)) continue; - clause |= 1 << (i + predicate_first_dynamic_condition); - nonspec_clause |= 1 << (i + predicate_first_dynamic_condition); + clause |= 1 << (i + predicate::first_dynamic_condition); + nonspec_clause |= 1 << (i + predicate::first_dynamic_condition); } *ret_clause = clause; if (ret_nonspec_clause) @@ -948,7 +848,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, vec known_aggs = vNULL; if (clause_ptr) - *clause_ptr = inline_p ? 0 : 1 << predicate_not_inlined_condition; + *clause_ptr = inline_p ? 0 : 1 << predicate::not_inlined_condition; if (known_vals_ptr) known_vals_ptr->create (0); if (known_contexts_ptr) @@ -1125,27 +1025,21 @@ inline_summary_t::remove (cgraph_node *node, inline_summary *info) reset_inline_summary (node, info); } -/* Remap predicate P of former function to be predicate of duplicated function. +/* Remap predicate THIS of former function to be predicate of duplicated function. POSSIBLE_TRUTHS is clause of possible truths in the duplicated node, INFO is inline summary of the duplicated node. */ -static struct predicate -remap_predicate_after_duplication (struct predicate *p, - clause_t possible_truths, - struct inline_summary *info) +predicate +predicate::remap_after_duplication (clause_t possible_truths) { - struct predicate new_predicate = true_predicate (); int j; - for (j = 0; p->clause[j]; j++) - if (!(possible_truths & p->clause[j])) - { - new_predicate = false_predicate (); - break; - } + predicate out = true; + for (j = 0; m_clause[j]; j++) + if (!(possible_truths & m_clause[j])) + return false; else - add_clause (info->conds, &new_predicate, - possible_truths & p->clause[j]); - return new_predicate; + out.add_clause (NULL, possible_truths & m_clause[j]); + return out; } /* Same as remap_predicate_after_duplication but handle hint predicate *P. @@ -1154,17 +1048,15 @@ remap_predicate_after_duplication (struct predicate *p, */ static void -remap_hint_predicate_after_duplication (struct predicate **p, - clause_t possible_truths, - struct inline_summary *info) +remap_hint_predicate_after_duplication (predicate **p, + clause_t possible_truths) { - struct predicate new_predicate; + predicate new_predicate; if (!*p) return; - new_predicate = remap_predicate_after_duplication (*p, - possible_truths, info); + new_predicate = (*p)->remap_after_duplication (possible_truths); /* We do not want to free previous predicate; it is used by node origin. */ *p = NULL; set_hint_predicate (p, new_predicate); @@ -1195,7 +1087,7 @@ inline_summary_t::duplicate (cgraph_node *src, int count = ipa_get_param_count (parms_info); int i, j; clause_t possible_truths; - struct predicate true_pred = true_predicate (); + predicate true_pred = true; size_time_entry *e; int optimized_out_size = 0; bool inlined_to_p = false; @@ -1236,17 +1128,13 @@ inline_summary_t::duplicate (cgraph_node *src, to be true. */ for (i = 0; vec_safe_iterate (entry, i, &e); i++) { - struct predicate new_exec_pred; - struct predicate new_nonconst_pred; - new_exec_pred = remap_predicate_after_duplication (&e->exec_predicate, - possible_truths, - info); - new_nonconst_pred - = remap_predicate_after_duplication (&e->nonconst_predicate, - possible_truths, - info); - if (false_predicate_p (&new_exec_pred) - || false_predicate_p (&new_nonconst_pred)) + predicate new_exec_pred; + predicate new_nonconst_pred; + new_exec_pred = e->exec_predicate.remap_after_duplication + (possible_truths); + new_nonconst_pred = e->nonconst_predicate.remap_after_duplication + (possible_truths); + if (new_exec_pred == false || new_nonconst_pred == false) optimized_out_size += e->size; else account_size_time (info, e->size, e->time, &new_exec_pred, @@ -1257,7 +1145,7 @@ inline_summary_t::duplicate (cgraph_node *src, Also copy constantness arrays. */ for (edge = dst->callees; edge; edge = next) { - struct predicate new_predicate; + predicate new_predicate; struct inline_edge_summary *es = inline_edge_summary (edge); next = edge->next_callee; @@ -1265,11 +1153,9 @@ inline_summary_t::duplicate (cgraph_node *src, inlined_to_p = true; if (!es->predicate) continue; - new_predicate = remap_predicate_after_duplication (es->predicate, - possible_truths, - info); - if (false_predicate_p (&new_predicate) - && !false_predicate_p (es->predicate)) + new_predicate = es->predicate->remap_after_duplication + (possible_truths); + if (new_predicate == false && *es->predicate != false) optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE; edge_set_predicate (edge, &new_predicate); } @@ -1278,27 +1164,25 @@ inline_summary_t::duplicate (cgraph_node *src, Also copy constantness arrays. */ for (edge = dst->indirect_calls; edge; edge = next) { - struct predicate new_predicate; + predicate new_predicate; struct inline_edge_summary *es = inline_edge_summary (edge); next = edge->next_callee; gcc_checking_assert (edge->inline_failed); if (!es->predicate) continue; - new_predicate = remap_predicate_after_duplication (es->predicate, - possible_truths, - info); - if (false_predicate_p (&new_predicate) - && !false_predicate_p (es->predicate)) + new_predicate = es->predicate->remap_after_duplication + (possible_truths); + if (new_predicate == false && *es->predicate != false) optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE; edge_set_predicate (edge, &new_predicate); } remap_hint_predicate_after_duplication (&info->loop_iterations, - possible_truths, info); + possible_truths); remap_hint_predicate_after_duplication (&info->loop_stride, - possible_truths, info); + possible_truths); remap_hint_predicate_after_duplication (&info->array_index, - possible_truths, info); + possible_truths); /* If inliner or someone after inliner will ever start producing non-trivial clones, we will get trouble with lack of information @@ -1418,7 +1302,7 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node, if (es->predicate) { fprintf (f, " predicate: "); - dump_predicate (f, info->conds, es->predicate); + es->predicate->dump (f, info->conds); } else fprintf (f, "\n"); @@ -1456,7 +1340,7 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node, if (es->predicate) { fprintf (f, "predicate: "); - dump_predicate (f, info->conds, es->predicate); + es->predicate->dump (f, info->conds); } else fprintf (f, "\n"); @@ -1499,33 +1383,32 @@ dump_inline_summary (FILE *f, struct cgraph_node *node) fprintf (f, " size:%f, time:%f", (double) e->size / INLINE_SIZE_SCALE, e->time.to_double ()); - if (!true_predicate_p (&e->exec_predicate)) + if (e->exec_predicate != true) { fprintf (f, ", executed if:"); - dump_predicate (f, s->conds, &e->exec_predicate, 0); + e->exec_predicate.dump (f, s->conds, 0); } - if (!predicates_equal_p (&e->exec_predicate, - &e->nonconst_predicate)) + if (e->exec_predicate != e->nonconst_predicate) { fprintf (f, ", nonconst if:"); - dump_predicate (f, s->conds, &e->nonconst_predicate, 0); + e->nonconst_predicate.dump (f, s->conds, 0); } fprintf (f, "\n"); } if (s->loop_iterations) { fprintf (f, " loop iterations:"); - dump_predicate (f, s->conds, s->loop_iterations); + s->loop_iterations->dump (f, s->conds); } if (s->loop_stride) { fprintf (f, " loop stride:"); - dump_predicate (f, s->conds, s->loop_stride); + s->loop_stride->dump (f, s->conds); } if (s->array_index) { fprintf (f, " array index:"); - dump_predicate (f, s->conds, s->array_index); + s->array_index->dump (f, s->conds); } fprintf (f, " calls:\n"); dump_inline_edge_summary (f, 4, node, s); @@ -1859,12 +1742,12 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, unordered one. Be sure it is not confused with NON_CONSTANT. */ if (this_code != ERROR_MARK) { - struct predicate p + predicate p = add_condition (summary, index, size, &aggpos, this_code, unshare_expr_without_location (gimple_cond_rhs (last))); e->aux = edge_predicate_pool.allocate (); - *(struct predicate *) e->aux = p; + *(predicate *) e->aux = p; } } } @@ -1894,10 +1777,10 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, return; FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE) { - struct predicate p = add_condition (summary, index, size, &aggpos, + predicate p = add_condition (summary, index, size, &aggpos, IS_NOT_CONSTANT, NULL_TREE); e->aux = edge_predicate_pool.allocate (); - *(struct predicate *) e->aux = p; + *(predicate *) e->aux = p; } } @@ -1931,14 +1814,14 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, FOR_EACH_EDGE (e, ei, bb->succs) { e->aux = edge_predicate_pool.allocate (); - *(struct predicate *) e->aux = false_predicate (); + *(predicate *) e->aux = false; } n = gimple_switch_num_labels (last); for (case_idx = 0; case_idx < n; ++case_idx) { tree cl = gimple_switch_label (last, case_idx); tree min, max; - struct predicate p; + predicate p; e = find_edge (bb, label_to_block (CASE_LABEL (cl))); min = CASE_LOW (cl); @@ -1948,21 +1831,21 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, of cases is met, but it is bit hard to do not having negations of conditionals handy. */ if (!min && !max) - p = true_predicate (); + p = true; else if (!max) p = add_condition (summary, index, size, &aggpos, EQ_EXPR, unshare_expr_without_location (min)); else { - struct predicate p1, p2; + predicate p1, p2; p1 = add_condition (summary, index, size, &aggpos, GE_EXPR, unshare_expr_without_location (min)); p2 = add_condition (summary, index, size, &aggpos, LE_EXPR, unshare_expr_without_location (max)); - p = and_predicates (summary->conds, &p1, &p2); + p = p1 & p2; } *(struct predicate *) e->aux - = or_predicates (summary->conds, &p, (struct predicate *) e->aux); + = p.or_with (summary->conds, *(struct predicate *) e->aux); } } @@ -1988,8 +1871,7 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, /* Entry block is always executable. */ ENTRY_BLOCK_PTR_FOR_FN (my_function)->aux = edge_predicate_pool.allocate (); - *(struct predicate *) ENTRY_BLOCK_PTR_FOR_FN (my_function)->aux - = true_predicate (); + *(predicate *) ENTRY_BLOCK_PTR_FOR_FN (my_function)->aux = true; /* A simple dataflow propagation of predicates forward in the CFG. TODO: work in reverse postorder. */ @@ -1998,44 +1880,42 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, done = true; FOR_EACH_BB_FN (bb, my_function) { - struct predicate p = false_predicate (); + predicate p = false; edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, bb->preds) { if (e->src->aux) { - struct predicate this_bb_predicate - = *(struct predicate *) e->src->aux; + predicate this_bb_predicate + = *(predicate *) e->src->aux; if (e->aux) - this_bb_predicate - = and_predicates (summary->conds, &this_bb_predicate, - (struct predicate *) e->aux); - p = or_predicates (summary->conds, &p, &this_bb_predicate); - if (true_predicate_p (&p)) + this_bb_predicate &= (*(struct predicate *) e->aux); + p = p.or_with (summary->conds, this_bb_predicate); + if (p == true) break; } } - if (false_predicate_p (&p)) - gcc_assert (!bb->aux); + if (p == false) + gcc_checking_assert (!bb->aux); else { if (!bb->aux) { done = false; bb->aux = edge_predicate_pool.allocate (); - *((struct predicate *) bb->aux) = p; + *((predicate *) bb->aux) = p; } - else if (!predicates_equal_p (&p, (struct predicate *) bb->aux)) + else if (p != *(predicate *) bb->aux) { /* This OR operation is needed to ensure monotonous data flow in the case we hit the limit on number of clauses and the and/or operations above give approximate answers. */ - p = or_predicates (summary->conds, &p, (struct predicate *)bb->aux); - if (!predicates_equal_p (&p, (struct predicate *) bb->aux)) + p = p.or_with (summary->conds, *(predicate *)bb->aux); + if (p != *(predicate *) bb->aux) { done = false; - *((struct predicate *) bb->aux) = p; + *((predicate *) bb->aux) = p; } } } @@ -2046,11 +1926,11 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, /* We keep info about constantness of SSA names. */ -typedef struct predicate predicate_t; +typedef predicate predicate_t; /* Return predicate specifying when the STMT might have result that is not a compile time constant. */ -static struct predicate +static predicate will_be_nonconstant_expr_predicate (struct ipa_node_params *info, struct inline_summary *summary, tree expr, @@ -2067,63 +1947,65 @@ will_be_nonconstant_expr_predicate (struct ipa_node_params *info, if (parm && (index = ipa_get_param_decl_index (info, parm)) >= 0) return add_condition (summary, index, size, NULL, CHANGED, NULL_TREE); if (is_gimple_min_invariant (expr)) - return false_predicate (); + return false; if (TREE_CODE (expr) == SSA_NAME) return nonconstant_names[SSA_NAME_VERSION (expr)]; if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr)) { - struct predicate p1 = will_be_nonconstant_expr_predicate + predicate p1 = will_be_nonconstant_expr_predicate (info, summary, TREE_OPERAND (expr, 0), nonconstant_names); - struct predicate p2; - if (true_predicate_p (&p1)) + if (p1 == true) return p1; + + predicate p2; p2 = will_be_nonconstant_expr_predicate (info, summary, TREE_OPERAND (expr, 1), nonconstant_names); - return or_predicates (summary->conds, &p1, &p2); + return p1.or_with (summary->conds, p2); } else if (TREE_CODE (expr) == COND_EXPR) { - struct predicate p1 = will_be_nonconstant_expr_predicate + predicate p1 = will_be_nonconstant_expr_predicate (info, summary, TREE_OPERAND (expr, 0), nonconstant_names); - struct predicate p2; - if (true_predicate_p (&p1)) + if (p1 == true) return p1; + + predicate p2; p2 = will_be_nonconstant_expr_predicate (info, summary, TREE_OPERAND (expr, 1), nonconstant_names); - if (true_predicate_p (&p2)) + if (p2 == true) return p2; - p1 = or_predicates (summary->conds, &p1, &p2); + p1 = p1.or_with (summary->conds, p2); p2 = will_be_nonconstant_expr_predicate (info, summary, TREE_OPERAND (expr, 2), nonconstant_names); - return or_predicates (summary->conds, &p1, &p2); + return p2.or_with (summary->conds, p1); } else { debug_tree (expr); gcc_unreachable (); } - return false_predicate (); + return false; } /* Return predicate specifying when the STMT might have result that is not a compile time constant. */ -static struct predicate +static predicate will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, struct inline_summary *summary, gimple *stmt, vec nonconstant_names) { - struct predicate p = true_predicate (); + predicate p = true; ssa_op_iter iter; tree use; - struct predicate op_non_const; + predicate op_non_const; bool is_load; int base_index; HOST_WIDE_INT size; @@ -2169,7 +2051,7 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, return p; /* If we know when operand is constant, we still can say something useful. */ - if (!true_predicate_p (&nonconstant_names[SSA_NAME_VERSION (use)])) + if (nonconstant_names[SSA_NAME_VERSION (use)] != true) continue; return p; } @@ -2178,7 +2060,7 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, op_non_const = add_condition (summary, base_index, size, &aggpos, CHANGED, NULL); else - op_non_const = false_predicate (); + op_non_const = false; FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) { HOST_WIDE_INT size; @@ -2194,7 +2076,7 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, } else p = nonconstant_names[SSA_NAME_VERSION (use)]; - op_non_const = or_predicates (summary->conds, &p, &op_non_const); + op_non_const = p.or_with (summary->conds, op_non_const); } if ((gimple_code (stmt) == GIMPLE_ASSIGN || gimple_code (stmt) == GIMPLE_CALL) && gimple_op (stmt, 0) @@ -2345,7 +2227,7 @@ param_change_prob (gimple *stmt, int i) static bool phi_result_unknown_predicate (struct ipa_node_params *info, inline_summary *summary, basic_block bb, - struct predicate *p, + predicate *p, vec nonconstant_names) { edge e; @@ -2355,7 +2237,7 @@ phi_result_unknown_predicate (struct ipa_node_params *info, if (single_pred_p (bb)) { - *p = false_predicate (); + *p = false; return true; } @@ -2391,7 +2273,7 @@ phi_result_unknown_predicate (struct ipa_node_params *info, *p = will_be_nonconstant_expr_predicate (info, summary, gimple_cond_lhs (stmt), nonconstant_names); - if (true_predicate_p (p)) + if (*p == true) return false; else return true; @@ -2404,7 +2286,7 @@ phi_result_unknown_predicate (struct ipa_node_params *info, static void predicate_for_phi_result (struct inline_summary *summary, gphi *phi, - struct predicate *p, + predicate *p, vec nonconstant_names) { unsigned i; @@ -2415,9 +2297,9 @@ predicate_for_phi_result (struct inline_summary *summary, gphi *phi, if (!is_gimple_min_invariant (arg)) { gcc_assert (TREE_CODE (arg) == SSA_NAME); - *p = or_predicates (summary->conds, p, - &nonconstant_names[SSA_NAME_VERSION (arg)]); - if (true_predicate_p (p)) + *p = p->or_with (summary->conds, + nonconstant_names[SSA_NAME_VERSION (arg)]); + if (*p == true) return; } } @@ -2425,25 +2307,25 @@ predicate_for_phi_result (struct inline_summary *summary, gphi *phi, if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "\t\tphi predicate: "); - dump_predicate (dump_file, summary->conds, p); + p->dump (dump_file, summary->conds); } nonconstant_names[SSA_NAME_VERSION (gimple_phi_result (phi))] = *p; } /* Return predicate specifying when array index in access OP becomes non-constant. */ -static struct predicate +static predicate array_index_predicate (inline_summary *info, vec< predicate_t> nonconstant_names, tree op) { - struct predicate p = false_predicate (); + predicate p = false; while (handled_component_p (op)) { if (TREE_CODE (op) == ARRAY_REF || TREE_CODE (op) == ARRAY_RANGE_REF) { if (TREE_CODE (TREE_OPERAND (op, 1)) == SSA_NAME) - p = or_predicates (info->conds, &p, - &nonconstant_names[SSA_NAME_VERSION + p = p.or_with (info->conds, + nonconstant_names[SSA_NAME_VERSION (TREE_OPERAND (op, 1))]); } op = TREE_OPERAND (op, 0); @@ -2602,12 +2484,12 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); int freq; struct inline_summary *info = inline_summaries->get (node); - struct predicate bb_predicate; + predicate bb_predicate; struct ipa_func_body_info fbi; vec nonconstant_names = vNULL; int nblocks, n; int *order; - predicate array_index = true_predicate (); + predicate array_index = true; gimple *fix_builtin_expect_stmt; gcc_assert (my_function && my_function->cfg); @@ -2652,10 +2534,10 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) /* When we run into maximal number of entries, we assign everything to the constant truth case. Be sure to have it in list. */ - bb_predicate = true_predicate (); + bb_predicate = true; account_size_time (info, 0, 0, &bb_predicate, &bb_predicate); - bb_predicate = not_inlined_predicate (); + bb_predicate = predicate::not_inlined (); account_size_time (info, 2 * INLINE_SIZE_SCALE, 0, &bb_predicate, &bb_predicate); @@ -2680,22 +2562,22 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) if (fbi.info) { if (bb->aux) - bb_predicate = *(struct predicate *) bb->aux; + bb_predicate = *(predicate *) bb->aux; else - bb_predicate = false_predicate (); + bb_predicate = false; } else - bb_predicate = true_predicate (); + bb_predicate = true; if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "\n BB %i predicate:", bb->index); - dump_predicate (dump_file, info->conds, &bb_predicate); + bb_predicate.dump (dump_file, info->conds); } if (fbi.info && nonconstant_names.exists ()) { - struct predicate phi_predicate; + predicate phi_predicate; bool first_phi = true; for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); @@ -2726,7 +2608,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) int this_size = estimate_num_insns (stmt, &eni_size_weights); int this_time = estimate_num_insns (stmt, &eni_time_weights); int prob; - struct predicate will_be_nonconstant; + predicate will_be_nonconstant; /* This relation stmt should be folded after we remove buildin_expect call. Adjust the cost here. */ @@ -2747,25 +2629,21 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) if (gimple_assign_load_p (stmt) && nonconstant_names.exists ()) { - struct predicate this_array_index; + predicate this_array_index; this_array_index = array_index_predicate (info, nonconstant_names, gimple_assign_rhs1 (stmt)); - if (!false_predicate_p (&this_array_index)) - array_index = - and_predicates (info->conds, &array_index, - &this_array_index); + if (this_array_index != false) + array_index &= this_array_index; } if (gimple_store_p (stmt) && nonconstant_names.exists ()) { - struct predicate this_array_index; + predicate this_array_index; this_array_index = array_index_predicate (info, nonconstant_names, gimple_get_lhs (stmt)); - if (!false_predicate_p (&this_array_index)) - array_index = - and_predicates (info->conds, &array_index, - &this_array_index); + if (this_array_index != false) + array_index &= this_array_index; } @@ -2783,7 +2661,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) && gimple_call_lhs (stmt) && TREE_CODE (gimple_call_lhs (stmt)) == SSA_NAME) { - struct predicate false_p = false_predicate (); + predicate false_p = false; nonconstant_names[SSA_NAME_VERSION (gimple_call_lhs (stmt))] = false_p; } @@ -2816,7 +2694,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) = will_be_nonconstant_predicate (&fbi, info, stmt, nonconstant_names); else - will_be_nonconstant = true_predicate (); + will_be_nonconstant = true; if (this_time || this_size) { this_time *= freq; @@ -2828,15 +2706,13 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "\t\tWill be eliminated by inlining\n"); - struct predicate p = and_predicates (info->conds, &bb_predicate, - &will_be_nonconstant); + struct predicate p = bb_predicate & will_be_nonconstant; /* We can ignore statement when we proved it is never going to happen, but we can not do that for call statements because edges are accounted specially. */ - if (!false_predicate_p (is_gimple_call (stmt) - ? &bb_predicate : &p)) + if (*(is_gimple_call (stmt) ? &bb_predicate : &p) != false) { time += this_time; size += this_size; @@ -2849,8 +2725,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) { if (prob) { - struct predicate ip = not_inlined_predicate (); - ip = and_predicates (info->conds, &ip, &bb_predicate); + predicate ip = bb_predicate & predicate::not_inlined (); account_size_time (info, this_size * prob, (sreal)(this_time * prob) / (CGRAPH_FREQ_BASE * 2), &ip, @@ -2883,8 +2758,8 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) if (nonconstant_names.exists () && !early) { struct loop *loop; - predicate loop_iterations = true_predicate (); - predicate loop_stride = true_predicate (); + predicate loop_iterations = true; + predicate loop_stride = true; if (dump_file && (dump_flags & TDF_DETAILS)) flow_loops_dump (dump_file, NULL, 0); @@ -2895,7 +2770,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) edge ex; unsigned int j; struct tree_niter_desc niter_desc; - bb_predicate = *(struct predicate *) loop->header->aux; + bb_predicate = *(predicate *) loop->header->aux; exits = get_loop_exit_edges (loop); FOR_EACH_VEC_ELT (exits, j, ex) @@ -2906,17 +2781,13 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) = will_be_nonconstant_expr_predicate (fbi.info, info, niter_desc.niter, nonconstant_names); - if (!true_predicate_p (&will_be_nonconstant)) - will_be_nonconstant = and_predicates (info->conds, - &bb_predicate, - &will_be_nonconstant); - if (!true_predicate_p (&will_be_nonconstant) - && !false_predicate_p (&will_be_nonconstant)) + if (will_be_nonconstant != true) + will_be_nonconstant = bb_predicate & will_be_nonconstant; + if (will_be_nonconstant != true + && will_be_nonconstant != false) /* This is slightly inprecise. We may want to represent each loop with independent predicate. */ - loop_iterations = - and_predicates (info->conds, &loop_iterations, - &will_be_nonconstant); + loop_iterations &= will_be_nonconstant; } exits.release (); } @@ -2931,7 +2802,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) for (unsigned i = 0; i < loop->num_nodes; i++) { gimple_stmt_iterator gsi; - bb_predicate = *(struct predicate *) body[i]->aux; + bb_predicate = *(predicate *) body[i]->aux; for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -2955,16 +2826,13 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) = will_be_nonconstant_expr_predicate (fbi.info, info, iv.step, nonconstant_names); - if (!true_predicate_p (&will_be_nonconstant)) - will_be_nonconstant - = and_predicates (info->conds, &bb_predicate, - &will_be_nonconstant); - if (!true_predicate_p (&will_be_nonconstant) - && !false_predicate_p (&will_be_nonconstant)) + if (will_be_nonconstant != true) + will_be_nonconstant = bb_predicate & will_be_nonconstant; + if (will_be_nonconstant != true + && will_be_nonconstant != false) /* This is slightly inprecise. We may want to represent each loop with independent predicate. */ - loop_stride = and_predicates (info->conds, &loop_stride, - &will_be_nonconstant); + loop_stride = loop_stride & will_be_nonconstant; } } free (body); @@ -2994,7 +2862,6 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) inline_summaries->get (node)->self_size = size; nonconstant_names.release (); ipa_release_body_info (&fbi); - inline_update_overall_summary (node); if (opt_for_fn (node->decl, optimize)) { if (!early) @@ -3038,14 +2905,14 @@ compute_inline_parameters (struct cgraph_node *node, bool early) if (node->thunk.thunk_p) { struct inline_edge_summary *es = inline_edge_summary (node->callees); - struct predicate t = true_predicate (); + predicate t = true; node->local.can_change_signature = false; es->call_stmt_size = eni_size_weights.call_cost; es->call_stmt_time = eni_time_weights.call_cost; account_size_time (info, INLINE_SIZE_SCALE * 2, 2, &t, &t); - t = not_inlined_predicate (); + t = predicate::not_inlined (); account_size_time (info, 2 * INLINE_SIZE_SCALE, 0, &t, &t); inline_update_overall_summary (node); info->self_size = info->size; @@ -3287,7 +3154,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, continue; } if (!es->predicate - || evaluate_predicate (es->predicate, possible_truths)) + || es->predicate->evaluate (possible_truths)) { if (e->inline_failed) { @@ -3314,7 +3181,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, struct inline_edge_summary *es = inline_edge_summary (e); if (!es->predicate - || evaluate_predicate (es->predicate, possible_truths)) + || es->predicate->evaluate (possible_truths)) estimate_edge_size_and_time (e, size, es->predicate ? NULL : min_size, time, REG_BR_PROB_BASE, @@ -3362,8 +3229,8 @@ estimate_node_size_and_time (struct cgraph_node *node, " Known to be false: ", node->name (), node->order); - for (i = predicate_not_inlined_condition; - i < (predicate_first_dynamic_condition + for (i = predicate::not_inlined_condition; + i < (predicate::first_dynamic_condition + (int) vec_safe_length (info->conds)); i++) if (!(possible_truths & (1 << i))) { @@ -3380,10 +3247,8 @@ estimate_node_size_and_time (struct cgraph_node *node, for (i = 0; vec_safe_iterate (info->entry, i, &e); i++) { - bool nonconst = evaluate_predicate (&e->nonconst_predicate, - possible_truths); - bool exec = evaluate_predicate (&e->exec_predicate, - nonspec_possible_truths); + bool nonconst = e->nonconst_predicate.evaluate (possible_truths); + bool exec = e->exec_predicate.evaluate (nonspec_possible_truths); gcc_assert (!nonconst || exec); if (exec) { @@ -3408,9 +3273,8 @@ estimate_node_size_and_time (struct cgraph_node *node, } else { - int prob = predicate_probability (info->conds, - &e->nonconst_predicate, - possible_truths, + int prob = e->nonconst_predicate.probability + (info->conds, possible_truths, inline_param_summary); gcc_checking_assert (prob >= 0); gcc_checking_assert (prob <= REG_BR_PROB_BASE); @@ -3419,8 +3283,8 @@ estimate_node_size_and_time (struct cgraph_node *node, gcc_checking_assert (time >= 0); } } - gcc_checking_assert (true_predicate_p (&(*info->entry)[0].exec_predicate)); - gcc_checking_assert (true_predicate_p (&(*info->entry)[0].nonconst_predicate)); + gcc_checking_assert ((*info->entry)[0].exec_predicate == true); + gcc_checking_assert ((*info->entry)[0].nonconst_predicate == true); min_size = (*info->entry)[0].size; gcc_checking_assert (size >= 0); gcc_checking_assert (time >= 0); @@ -3435,13 +3299,13 @@ estimate_node_size_and_time (struct cgraph_node *node, time = nonspecialized_time; if (info->loop_iterations - && !evaluate_predicate (info->loop_iterations, possible_truths)) + && !info->loop_iterations->evaluate (possible_truths)) hints |= INLINE_HINT_loop_iterations; if (info->loop_stride - && !evaluate_predicate (info->loop_stride, possible_truths)) + && !info->loop_stride->evaluate (possible_truths)) hints |= INLINE_HINT_loop_stride; if (info->array_index - && !evaluate_predicate (info->array_index, possible_truths)) + && !info->array_index->evaluate (possible_truths)) hints |= INLINE_HINT_array_index; if (info->scc_no) hints |= INLINE_HINT_in_scc; @@ -3494,7 +3358,7 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node, } /* Translate all conditions from callee representation into caller - representation and symbolically evaluate predicate P into new predicate. + representation and symbolically evaluate predicate THIS into new predicate. INFO is inline_summary of function we are adding predicate into, CALLEE_INFO is summary of function predicate P is from. OPERAND_MAP is array giving @@ -3506,42 +3370,42 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node, because they might not be preserved (and should be considered offset zero for other purposes). */ -static struct predicate -remap_predicate (struct inline_summary *info, - struct inline_summary *callee_info, - struct predicate *p, - vec operand_map, - vec offset_map, - clause_t possible_truths, struct predicate *toplev_predicate) +predicate +predicate::remap_after_inlining (struct inline_summary *info, + struct inline_summary *callee_info, + vec operand_map, + vec offset_map, + clause_t possible_truths, + const predicate &toplev_predicate) { int i; - struct predicate out = true_predicate (); + predicate out = true; /* True predicate is easy. */ - if (true_predicate_p (p)) - return *toplev_predicate; - for (i = 0; p->clause[i]; i++) + if (*this == true) + return toplev_predicate; + for (i = 0; m_clause[i]; i++) { - clause_t clause = p->clause[i]; + clause_t clause = m_clause[i]; int cond; - struct predicate clause_predicate = false_predicate (); + predicate clause_predicate = false; - gcc_assert (i < MAX_CLAUSES); + gcc_assert (i < max_clauses); for (cond = 0; cond < NUM_CONDITIONS; cond++) /* Do we have condition we can't disprove? */ if (clause & possible_truths & (1 << cond)) { - struct predicate cond_predicate; + predicate cond_predicate; /* Work out if the condition can translate to predicate in the inlined function. */ - if (cond >= predicate_first_dynamic_condition) + if (cond >= predicate::first_dynamic_condition) { struct condition *c; c = &(*callee_info->conds)[cond - - predicate_first_dynamic_condition]; + predicate::first_dynamic_condition]; /* See if we can remap condition operand to caller's operand. Otherwise give up. */ if (!operand_map.exists () @@ -3554,7 +3418,7 @@ remap_predicate (struct inline_summary *info, && offset_map[c->operand_num] > 0) || (c->agg_contents && c->by_ref && offset_map[c->operand_num] < 0)) - cond_predicate = true_predicate (); + cond_predicate = true; else { struct agg_position_info ap; @@ -3578,16 +3442,14 @@ remap_predicate (struct inline_summary *info, /* Fixed conditions remains same, construct single condition predicate. */ else - { - cond_predicate.clause[0] = 1 << cond; - cond_predicate.clause[1] = 0; - } - clause_predicate = or_predicates (info->conds, &clause_predicate, - &cond_predicate); + cond_predicate = predicate::predicate_testing_cond (cond); + clause_predicate = clause_predicate.or_with (info->conds, + cond_predicate); } - out = and_predicates (info->conds, &out, &clause_predicate); + out &= clause_predicate; } - return and_predicates (info->conds, &out, toplev_predicate); + out &= toplev_predicate; + return out; } @@ -3678,13 +3540,13 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, vec operand_map, vec offset_map, clause_t possible_truths, - struct predicate *toplev_predicate) + predicate *toplev_predicate) { struct cgraph_edge *e, *next; for (e = node->callees; e; e = next) { struct inline_edge_summary *es = inline_edge_summary (e); - struct predicate p; + predicate p; next = e->next_callee; if (e->inline_failed) @@ -3693,9 +3555,10 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, if (es->predicate) { - p = remap_predicate (info, callee_info, - es->predicate, operand_map, offset_map, - possible_truths, toplev_predicate); + p = es->predicate->remap_after_inlining + (info, callee_info, operand_map, + offset_map, possible_truths, + *toplev_predicate); edge_set_predicate (e, &p); } else @@ -3709,15 +3572,15 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, for (e = node->indirect_calls; e; e = next) { struct inline_edge_summary *es = inline_edge_summary (e); - struct predicate p; + predicate p; next = e->next_callee; remap_edge_change_prob (inlined_edge, e); if (es->predicate) { - p = remap_predicate (info, callee_info, - es->predicate, operand_map, offset_map, - possible_truths, toplev_predicate); + p = es->predicate->remap_after_inlining + (info, callee_info, operand_map, offset_map, + possible_truths, *toplev_predicate); edge_set_predicate (e, &p); } else @@ -3730,26 +3593,26 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, static void remap_hint_predicate (struct inline_summary *info, struct inline_summary *callee_info, - struct predicate **hint, + predicate **hint, vec operand_map, vec offset_map, clause_t possible_truths, - struct predicate *toplev_predicate) + predicate *toplev_predicate) { predicate p; if (!*hint) return; - p = remap_predicate (info, callee_info, - *hint, - operand_map, offset_map, - possible_truths, toplev_predicate); - if (!false_predicate_p (&p) && !true_predicate_p (&p)) + p = (*hint)->remap_after_inlining + (info, callee_info, + operand_map, offset_map, + possible_truths, *toplev_predicate); + if (p != false && p != true) { if (!*hint) set_hint_predicate (hint, p); else - **hint = and_predicates (info->conds, *hint, &p); + **hint &= p; } } @@ -3767,14 +3630,14 @@ inline_merge_summary (struct cgraph_edge *edge) vec operand_map = vNULL; vec offset_map = vNULL; int i; - struct predicate toplev_predicate; - struct predicate true_p = true_predicate (); + predicate toplev_predicate; + predicate true_p = true; struct inline_edge_summary *es = inline_edge_summary (edge); if (es->predicate) toplev_predicate = *es->predicate; else - toplev_predicate = true_predicate (); + toplev_predicate = true; info->fp_expressions |= callee_info->fp_expressions; @@ -3821,21 +3684,21 @@ inline_merge_summary (struct cgraph_edge *edge) } for (i = 0; vec_safe_iterate (callee_info->entry, i, &e); i++) { - struct predicate p = remap_predicate (info, callee_info, - &e->exec_predicate, operand_map, - offset_map, clause, - &toplev_predicate); - struct predicate nonconstp - = remap_predicate (info, callee_info, - &e->nonconst_predicate, operand_map, - offset_map, clause, - &toplev_predicate); - if (!false_predicate_p (&p) && !false_predicate_p (&nonconstp)) + predicate p; + p = e->exec_predicate.remap_after_inlining + (info, callee_info, operand_map, + offset_map, clause, + toplev_predicate); + predicate nonconstp; + nonconstp = e->nonconst_predicate.remap_after_inlining + (info, callee_info, operand_map, + offset_map, clause, + toplev_predicate); + if (p != false && nonconstp != false) { sreal add_time = ((sreal)e->time * edge->frequency) / CGRAPH_FREQ_BASE; - int prob = predicate_probability (callee_info->conds, - &e->nonconst_predicate, - clause, es->param); + int prob = e->nonconst_predicate.probability (callee_info->conds, + clause, es->param); add_time = add_time * prob / REG_BR_PROB_BASE; if (prob != REG_BR_PROB_BASE && dump_file && (dump_flags & TDF_DETAILS)) @@ -3888,7 +3751,7 @@ inline_update_overall_summary (struct cgraph_node *node) } estimate_calls_size_and_time (node, &info->size, &info->min_size, &info->time, NULL, - ~(clause_t) (1 << predicate_false_condition), + ~(clause_t) (1 << predicate::false_condition), vNULL, vNULL, vNULL); info->size = (info->size + INLINE_SIZE_SCALE / 2) / INLINE_SIZE_SCALE; } @@ -4069,7 +3932,7 @@ estimate_size_after_inlining (struct cgraph_node *node, struct cgraph_edge *edge) { struct inline_edge_summary *es = inline_edge_summary (edge); - if (!es->predicate || !false_predicate_p (es->predicate)) + if (!es->predicate || *es->predicate != false) { int size = inline_summaries->get (node)->size + estimate_edge_growth (edge); gcc_assert (size >= 0); @@ -4314,25 +4177,22 @@ inline_generate_summary (void) /* Read predicate from IB. */ -static struct predicate -read_predicate (struct lto_input_block *ib) +void +predicate::stream_in (struct lto_input_block *ib) { - struct predicate out; clause_t clause; int k = 0; do { - gcc_assert (k <= MAX_CLAUSES); - clause = out.clause[k++] = streamer_read_uhwi (ib); + gcc_assert (k <= max_clauses); + clause = m_clause[k++] = streamer_read_uhwi (ib); } while (clause); /* Zero-initialize the remaining clauses in OUT. */ - while (k <= MAX_CLAUSES) - out.clause[k++] = 0; - - return out; + while (k <= max_clauses) + m_clause[k++] = 0; } @@ -4342,13 +4202,13 @@ static void read_inline_edge_summary (struct lto_input_block *ib, struct cgraph_edge *e) { struct inline_edge_summary *es = inline_edge_summary (e); - struct predicate p; + predicate p; int length, i; es->call_stmt_size = streamer_read_uhwi (ib); es->call_stmt_time = streamer_read_uhwi (ib); es->loop_depth = streamer_read_uhwi (ib); - p = read_predicate (ib); + p.stream_in (ib); edge_set_predicate (e, &p); length = streamer_read_uhwi (ib); if (length) @@ -4432,17 +4292,17 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, e.size = streamer_read_uhwi (&ib); e.time = sreal::stream_in (&ib); - e.exec_predicate = read_predicate (&ib); - e.nonconst_predicate = read_predicate (&ib); + e.exec_predicate.stream_in (&ib); + e.nonconst_predicate.stream_in (&ib); vec_safe_push (info->entry, e); } - p = read_predicate (&ib); + p.stream_in (&ib); set_hint_predicate (&info->loop_iterations, p); - p = read_predicate (&ib); + p.stream_in (&ib); set_hint_predicate (&info->loop_stride, p); - p = read_predicate (&ib); + p.stream_in (&ib); set_hint_predicate (&info->array_index, p); for (e = node->callees; e; e = e->next_callee) read_inline_edge_summary (&ib, e); @@ -4498,16 +4358,15 @@ inline_read_summary (void) /* Write predicate P to OB. */ -static void -write_predicate (struct output_block *ob, struct predicate *p) +void +predicate::stream_out (struct output_block *ob) { int j; - if (p) - for (j = 0; p->clause[j]; j++) - { - gcc_assert (j < MAX_CLAUSES); - streamer_write_uhwi (ob, p->clause[j]); - } + for (j = 0; m_clause[j]; j++) + { + gcc_assert (j < max_clauses); + streamer_write_uhwi (ob, m_clause[j]); + } streamer_write_uhwi (ob, 0); } @@ -4523,7 +4382,10 @@ write_inline_edge_summary (struct output_block *ob, struct cgraph_edge *e) streamer_write_uhwi (ob, es->call_stmt_size); streamer_write_uhwi (ob, es->call_stmt_time); streamer_write_uhwi (ob, es->loop_depth); - write_predicate (ob, es->predicate); + if (es->predicate) + es->predicate->stream_out (ob); + else + streamer_write_uhwi (ob, 0); streamer_write_uhwi (ob, es->param.length ()); for (i = 0; i < (int) es->param.length (); i++) streamer_write_uhwi (ob, es->param[i].change_prob); @@ -4592,12 +4454,21 @@ inline_write_summary (void) { streamer_write_uhwi (ob, e->size); e->time.stream_out (ob); - write_predicate (ob, &e->exec_predicate); - write_predicate (ob, &e->nonconst_predicate); + e->exec_predicate.stream_out (ob); + e->nonconst_predicate.stream_out (ob); } - write_predicate (ob, info->loop_iterations); - write_predicate (ob, info->loop_stride); - write_predicate (ob, info->array_index); + if (info->loop_iterations) + info->loop_iterations->stream_out (ob); + else + streamer_write_uhwi (ob, 0); + if (info->loop_stride) + info->loop_stride->stream_out (ob); + else + streamer_write_uhwi (ob, 0); + if (info->array_index) + info->array_index->stream_out (ob); + else + streamer_write_uhwi (ob, 0); for (edge = cnode->callees; edge; edge = edge->next_callee) write_inline_edge_summary (ob, edge); for (edge = cnode->indirect_calls; edge; edge = edge->next_callee) diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h index ef52ca2eac9..8a162e96898 100644 --- a/gcc/ipa-inline.h +++ b/gcc/ipa-inline.h @@ -80,23 +80,169 @@ enum inline_hints_vals { }; typedef int inline_hints; +/* Information kept about parameter of call site. */ +struct inline_param_summary +{ + /* REG_BR_PROB_BASE based probability that parameter will change in between + two invocation of the calls. + I.e. loop invariant parameters + REG_BR_PROB_BASE/estimated_iterations and regular + parameters REG_BR_PROB_BASE. + + Value 0 is reserved for compile time invariants. */ + int change_prob; +}; typedef vec *conditions; -/* Representation of predicates i.e. formulas using conditions defined - above. Predicates are simple logical formulas in conjunctive-disjunctive - form. +/* Predicates are used to repesent function parameters (such as runtime) + which depend on a context function is called in. + + Predicates are logical formulas in conjunctive-disjunctive form consisting + of clauses which are bitmaps specifying a set of condition that must + be true for a clause to be satisfied. Physically they are represented as + array of clauses terminated by 0. - Predicate is array of clauses terminated by 0. Every clause must be true - in order to make predicate true. - Clauses are represented as bitmaps of conditions. One of conditions - must be true in order for clause to be true. */ + In order to make predicate (possibly) true, all of its clauses must + be (possibly) true. To make clause (possibly) true, one of conditions + it mentions must be (possibly) true. -#define MAX_CLAUSES 8 -typedef unsigned int clause_t; -struct GTY(()) predicate + There are fixed bounds on number of clauses and conditions and all the + manipulation functions are conservative in positive direction. I.e. we + may lose precision by thinking that predicate may be true even when it + is not. */ + +typedef uint32_t clause_t; +class predicate { - clause_t clause[MAX_CLAUSES + 1]; +public: + enum predicate_conditions + { + false_condition = 0, + not_inlined_condition = 1, + first_dynamic_condition = 2 + }; + + /* Initialize predicate either to true of false depending on P. */ + inline predicate (bool p = true) + { + if (p) + /* True predicate. */ + m_clause[0] = 0; + else + /* False predicate. */ + set_to_cond (false_condition); + } + + /* Sanity check that we do not mix pointers to predicates with predicates. */ + inline predicate (predicate *) + { + gcc_unreachable (); + } + + /* Return predicate testing condition I. */ + static inline predicate predicate_testing_cond (int i) + { + class predicate p; + p.set_to_cond (i + first_dynamic_condition); + return p; + } + + /* Return predicate testing that function was not inlined. */ + static predicate not_inlined (void) + { + class predicate p; + p.set_to_cond (not_inlined_condition); + return p; + } + + /* Compute logical and of predicates. */ + predicate & operator &= (const predicate &); + inline predicate operator &(const predicate &p) + { + predicate ret = *this; + ret &= p; + return ret; + } + + /* Compute logical or of predicates. This is not operator because + extra parameter CONDITIONS is needed */ + predicate or_with (conditions, const predicate &) const; + + /* Return true if predicates are known to be equal. */ + inline bool operator==(const predicate &p2) const + { + int i; + for (i = 0; m_clause[i]; i++) + { + gcc_checking_assert (i < max_clauses); + gcc_checking_assert (m_clause[i] > m_clause[i + 1]); + gcc_checking_assert (!p2.m_clause[i] + || p2.m_clause[i] > p2.m_clause[i + 1]); + if (m_clause[i] != p2.m_clause[i]) + return false; + } + return !p2.m_clause[i]; + } + + /* Return true if predicates are known to be true or false depending + on COND. */ + inline bool operator==(const bool cond) const + { + if (cond) + return !m_clause[0]; + if (m_clause[0] == (1 << false_condition)) + { + gcc_checking_assert (!m_clause[1] + && m_clause[0] == 1 + << false_condition); + return true; + } + return false; + } + + inline bool operator!=(const predicate &p2) const + { + return !(*this == p2); + } + + inline bool operator!=(const bool cond) const + { + return !(*this == cond); + } + + /* Evaluate if predicate is known to be false given the clause of possible + truths. */ + bool evaluate (clause_t) const; + + /* Estimate probability that predicate will be true in a given context. */ + int probability (conditions, clause_t, vec) const; + + /* Dump predicate to F. Output newline if nl. */ + void dump (FILE *f, conditions, bool nl=true) const; + + /* Return predicate equal to THIS after duplication. */ + predicate remap_after_duplication (clause_t); + + /* Return predicate equal to THIS after inlining. */ + predicate remap_after_inlining (struct inline_summary *, + struct inline_summary *, + vec, vec, clause_t, const predicate &); + + void stream_in (struct lto_input_block *); + void stream_out (struct output_block *); +private: + static const int max_clauses = 8; + clause_t m_clause[max_clauses + 1]; + + /* Initialize predicate to one testing single condition number COND. */ + inline void set_to_cond (int cond) + { + m_clause[0] = 1 << cond; + m_clause[1] = 0; + } + + void add_clause (conditions conditions, clause_t); }; /* Represnetation of function body size and time depending on the inline @@ -108,11 +254,11 @@ struct GTY(()) predicate struct GTY(()) size_time_entry { /* Predicate for code to be executed. */ - struct predicate exec_predicate; + predicate exec_predicate; /* Predicate for value to be constant and optimized out in a specialized copy. When deciding on specialization this makes it possible to see how much the executed code paths will simplify. */ - struct predicate nonconst_predicate; + predicate nonconst_predicate; int size; sreal GTY((skip)) time; }; @@ -161,12 +307,12 @@ struct GTY(()) inline_summary /* Predicate on when some loop in the function becomes to have known bounds. */ - struct predicate * GTY((skip)) loop_iterations; + predicate * GTY((skip)) loop_iterations; /* Predicate on when some loop in the function becomes to have known stride. */ - struct predicate * GTY((skip)) loop_stride; + predicate * GTY((skip)) loop_stride; /* Predicate on when some array indexes become constants. */ - struct predicate * GTY((skip)) array_index; + predicate * GTY((skip)) array_index; /* Estimated growth for inlining all copies of the function before start of small functions inlining. This value will get out of date as the callers are duplicated, but @@ -212,19 +358,6 @@ public: extern GTY(()) function_summary *inline_summaries; -/* Information kept about parameter of call site. */ -struct inline_param_summary -{ - /* REG_BR_PROB_BASE based probability that parameter will change in between - two invocation of the calls. - I.e. loop invariant parameters - REG_BR_PROB_BASE/estimated_iterations and regular - parameters REG_BR_PROB_BASE. - - Value 0 is reserved for compile time invariants. */ - int change_prob; -}; - /* Information kept about callgraph edges. */ struct inline_edge_summary { @@ -233,7 +366,7 @@ struct inline_edge_summary int call_stmt_time; /* Depth of loop nest, 0 means no nesting. */ unsigned short int loop_depth; - struct predicate *predicate; + class predicate *predicate; /* Array indexed by parameters. 0 means that parameter change all the time, REG_BR_PROB_BASE means that parameter is constant. */