10ffa2763Smrg /* IPA predicates.
2*dd083157Smrg Copyright (C) 2003-2020 Free Software Foundation, Inc.
30ffa2763Smrg Contributed by Jan Hubicka
40ffa2763Smrg
50ffa2763Smrg This file is part of GCC.
60ffa2763Smrg
70ffa2763Smrg GCC is free software; you can redistribute it and/or modify it under
80ffa2763Smrg the terms of the GNU General Public License as published by the Free
90ffa2763Smrg Software Foundation; either version 3, or (at your option) any later
100ffa2763Smrg version.
110ffa2763Smrg
120ffa2763Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
130ffa2763Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
140ffa2763Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
150ffa2763Smrg for more details.
160ffa2763Smrg
170ffa2763Smrg You should have received a copy of the GNU General Public License
180ffa2763Smrg along with GCC; see the file COPYING3. If not see
190ffa2763Smrg <http://www.gnu.org/licenses/>. */
200ffa2763Smrg
210ffa2763Smrg #include "config.h"
220ffa2763Smrg #include "system.h"
230ffa2763Smrg #include "coretypes.h"
240ffa2763Smrg #include "backend.h"
250ffa2763Smrg #include "tree.h"
260ffa2763Smrg #include "cgraph.h"
270ffa2763Smrg #include "tree-vrp.h"
280ffa2763Smrg #include "alloc-pool.h"
29*dd083157Smrg #include "symbol-summary.h"
300ffa2763Smrg #include "ipa-prop.h"
310ffa2763Smrg #include "ipa-fnsummary.h"
320ffa2763Smrg #include "real.h"
330ffa2763Smrg #include "fold-const.h"
340ffa2763Smrg #include "tree-pretty-print.h"
350ffa2763Smrg #include "gimple.h"
36*dd083157Smrg #include "gimplify.h"
370ffa2763Smrg #include "data-streamer.h"
380ffa2763Smrg
390ffa2763Smrg
40*dd083157Smrg /* Check whether two set of operations have same effects. */
41*dd083157Smrg static bool
expr_eval_ops_equal_p(expr_eval_ops ops1,expr_eval_ops ops2)42*dd083157Smrg expr_eval_ops_equal_p (expr_eval_ops ops1, expr_eval_ops ops2)
43*dd083157Smrg {
44*dd083157Smrg if (ops1)
45*dd083157Smrg {
46*dd083157Smrg if (!ops2 || ops1->length () != ops2->length ())
47*dd083157Smrg return false;
48*dd083157Smrg
49*dd083157Smrg for (unsigned i = 0; i < ops1->length (); i++)
50*dd083157Smrg {
51*dd083157Smrg expr_eval_op &op1 = (*ops1)[i];
52*dd083157Smrg expr_eval_op &op2 = (*ops2)[i];
53*dd083157Smrg
54*dd083157Smrg if (op1.code != op2.code
55*dd083157Smrg || op1.index != op2.index
56*dd083157Smrg || !vrp_operand_equal_p (op1.val[0], op2.val[0])
57*dd083157Smrg || !vrp_operand_equal_p (op1.val[1], op2.val[1])
58*dd083157Smrg || !types_compatible_p (op1.type, op2.type))
59*dd083157Smrg return false;
60*dd083157Smrg }
61*dd083157Smrg return true;
62*dd083157Smrg }
63*dd083157Smrg return !ops2;
64*dd083157Smrg }
65*dd083157Smrg
660ffa2763Smrg /* Add clause CLAUSE into the predicate P.
670ffa2763Smrg When CONDITIONS is NULL do not perform checking whether NEW_CLAUSE
680ffa2763Smrg is obviously true. This is useful only when NEW_CLAUSE is known to be
690ffa2763Smrg sane. */
700ffa2763Smrg
710ffa2763Smrg void
add_clause(conditions conditions,clause_t new_clause)720ffa2763Smrg predicate::add_clause (conditions conditions, clause_t new_clause)
730ffa2763Smrg {
740ffa2763Smrg int i;
750ffa2763Smrg int i2;
760ffa2763Smrg int insert_here = -1;
770ffa2763Smrg int c1, c2;
780ffa2763Smrg
790ffa2763Smrg /* True clause. */
800ffa2763Smrg if (!new_clause)
810ffa2763Smrg return;
820ffa2763Smrg
830ffa2763Smrg /* False clause makes the whole predicate false. Kill the other variants. */
840ffa2763Smrg if (new_clause == (1 << predicate::false_condition))
850ffa2763Smrg {
860ffa2763Smrg *this = false;
870ffa2763Smrg return;
880ffa2763Smrg }
890ffa2763Smrg if (*this == false)
900ffa2763Smrg return;
910ffa2763Smrg
920ffa2763Smrg /* No one should be silly enough to add false into nontrivial clauses. */
930ffa2763Smrg gcc_checking_assert (!(new_clause & (1 << predicate::false_condition)));
940ffa2763Smrg
950ffa2763Smrg /* Look where to insert the new_clause. At the same time prune out
960ffa2763Smrg new_clauses of P that are implied by the new new_clause and thus
970ffa2763Smrg redundant. */
980ffa2763Smrg for (i = 0, i2 = 0; i <= max_clauses; i++)
990ffa2763Smrg {
1000ffa2763Smrg m_clause[i2] = m_clause[i];
1010ffa2763Smrg
1020ffa2763Smrg if (!m_clause[i])
1030ffa2763Smrg break;
1040ffa2763Smrg
1050ffa2763Smrg /* If m_clause[i] implies new_clause, there is nothing to add. */
1060ffa2763Smrg if ((m_clause[i] & new_clause) == m_clause[i])
1070ffa2763Smrg {
1080ffa2763Smrg /* We had nothing to add, none of clauses should've become
1090ffa2763Smrg redundant. */
1100ffa2763Smrg gcc_checking_assert (i == i2);
1110ffa2763Smrg return;
1120ffa2763Smrg }
1130ffa2763Smrg
1140ffa2763Smrg if (m_clause[i] < new_clause && insert_here < 0)
1150ffa2763Smrg insert_here = i2;
1160ffa2763Smrg
1170ffa2763Smrg /* If new_clause implies clause[i], then clause[i] becomes redundant.
1180ffa2763Smrg Otherwise the clause[i] has to stay. */
1190ffa2763Smrg if ((m_clause[i] & new_clause) != new_clause)
1200ffa2763Smrg i2++;
1210ffa2763Smrg }
1220ffa2763Smrg
1230ffa2763Smrg /* Look for clauses that are obviously true. I.e.
1240ffa2763Smrg op0 == 5 || op0 != 5. */
1250ffa2763Smrg if (conditions)
1260ffa2763Smrg for (c1 = predicate::first_dynamic_condition;
1270ffa2763Smrg c1 < num_conditions; c1++)
1280ffa2763Smrg {
1290ffa2763Smrg condition *cc1;
1300ffa2763Smrg if (!(new_clause & (1 << c1)))
1310ffa2763Smrg continue;
1320ffa2763Smrg cc1 = &(*conditions)[c1 - predicate::first_dynamic_condition];
1330ffa2763Smrg /* We have no way to represent !changed and !is_not_constant
1340ffa2763Smrg and thus there is no point for looking for them. */
1350ffa2763Smrg if (cc1->code == changed || cc1->code == is_not_constant)
1360ffa2763Smrg continue;
1370ffa2763Smrg for (c2 = c1 + 1; c2 < num_conditions; c2++)
1380ffa2763Smrg if (new_clause & (1 << c2))
1390ffa2763Smrg {
1400ffa2763Smrg condition *cc2 =
1410ffa2763Smrg &(*conditions)[c2 - predicate::first_dynamic_condition];
1420ffa2763Smrg if (cc1->operand_num == cc2->operand_num
143*dd083157Smrg && vrp_operand_equal_p (cc1->val, cc2->val)
1440ffa2763Smrg && cc2->code != is_not_constant
145*dd083157Smrg && cc2->code != changed
146*dd083157Smrg && expr_eval_ops_equal_p (cc1->param_ops, cc2->param_ops)
147*dd083157Smrg && cc2->agg_contents == cc1->agg_contents
148*dd083157Smrg && cc2->by_ref == cc1->by_ref
149*dd083157Smrg && types_compatible_p (cc2->type, cc1->type)
1500ffa2763Smrg && cc1->code == invert_tree_comparison (cc2->code,
1510ffa2763Smrg HONOR_NANS (cc1->val)))
1520ffa2763Smrg return;
1530ffa2763Smrg }
1540ffa2763Smrg }
1550ffa2763Smrg
1560ffa2763Smrg
1570ffa2763Smrg /* We run out of variants. Be conservative in positive direction. */
1580ffa2763Smrg if (i2 == max_clauses)
1590ffa2763Smrg return;
1600ffa2763Smrg /* Keep clauses in decreasing order. This makes equivalence testing easy. */
1610ffa2763Smrg m_clause[i2 + 1] = 0;
1620ffa2763Smrg if (insert_here >= 0)
1630ffa2763Smrg for (; i2 > insert_here; i2--)
1640ffa2763Smrg m_clause[i2] = m_clause[i2 - 1];
1650ffa2763Smrg else
1660ffa2763Smrg insert_here = i2;
1670ffa2763Smrg m_clause[insert_here] = new_clause;
1680ffa2763Smrg }
1690ffa2763Smrg
1700ffa2763Smrg
1710ffa2763Smrg /* Do THIS &= P. */
1720ffa2763Smrg
1730ffa2763Smrg predicate &
1740ffa2763Smrg predicate::operator &= (const predicate &p)
1750ffa2763Smrg {
1760ffa2763Smrg /* Avoid busy work. */
1770ffa2763Smrg if (p == false || *this == true)
1780ffa2763Smrg {
1790ffa2763Smrg *this = p;
1800ffa2763Smrg return *this;
1810ffa2763Smrg }
1820ffa2763Smrg if (*this == false || p == true || this == &p)
1830ffa2763Smrg return *this;
1840ffa2763Smrg
1850ffa2763Smrg int i;
1860ffa2763Smrg
1870ffa2763Smrg /* See how far predicates match. */
1880ffa2763Smrg for (i = 0; m_clause[i] && m_clause[i] == p.m_clause[i]; i++)
1890ffa2763Smrg {
1900ffa2763Smrg gcc_checking_assert (i < max_clauses);
1910ffa2763Smrg }
1920ffa2763Smrg
1930ffa2763Smrg /* Combine the predicates rest. */
1940ffa2763Smrg for (; p.m_clause[i]; i++)
1950ffa2763Smrg {
1960ffa2763Smrg gcc_checking_assert (i < max_clauses);
1970ffa2763Smrg add_clause (NULL, p.m_clause[i]);
1980ffa2763Smrg }
1990ffa2763Smrg return *this;
2000ffa2763Smrg }
2010ffa2763Smrg
2020ffa2763Smrg
2030ffa2763Smrg
2040ffa2763Smrg /* Return THIS | P2. */
2050ffa2763Smrg
2060ffa2763Smrg predicate
or_with(conditions conditions,const predicate & p)2070ffa2763Smrg predicate::or_with (conditions conditions,
2080ffa2763Smrg const predicate &p) const
2090ffa2763Smrg {
2100ffa2763Smrg /* Avoid busy work. */
2110ffa2763Smrg if (p == false || *this == true || *this == p)
2120ffa2763Smrg return *this;
2130ffa2763Smrg if (*this == false || p == true)
2140ffa2763Smrg return p;
2150ffa2763Smrg
2160ffa2763Smrg /* OK, combine the predicates. */
2170ffa2763Smrg predicate out = true;
2180ffa2763Smrg
2190ffa2763Smrg for (int i = 0; m_clause[i]; i++)
2200ffa2763Smrg for (int j = 0; p.m_clause[j]; j++)
2210ffa2763Smrg {
2220ffa2763Smrg gcc_checking_assert (i < max_clauses && j < max_clauses);
2230ffa2763Smrg out.add_clause (conditions, m_clause[i] | p.m_clause[j]);
2240ffa2763Smrg }
2250ffa2763Smrg return out;
2260ffa2763Smrg }
2270ffa2763Smrg
2280ffa2763Smrg
2290ffa2763Smrg /* Having partial truth assignment in POSSIBLE_TRUTHS, return false
2300ffa2763Smrg if predicate P is known to be false. */
2310ffa2763Smrg
2320ffa2763Smrg bool
evaluate(clause_t possible_truths)2330ffa2763Smrg predicate::evaluate (clause_t possible_truths) const
2340ffa2763Smrg {
2350ffa2763Smrg int i;
2360ffa2763Smrg
2370ffa2763Smrg /* True remains true. */
2380ffa2763Smrg if (*this == true)
2390ffa2763Smrg return true;
2400ffa2763Smrg
2410ffa2763Smrg gcc_assert (!(possible_truths & (1 << predicate::false_condition)));
2420ffa2763Smrg
2430ffa2763Smrg /* See if we can find clause we can disprove. */
2440ffa2763Smrg for (i = 0; m_clause[i]; i++)
2450ffa2763Smrg {
2460ffa2763Smrg gcc_checking_assert (i < max_clauses);
2470ffa2763Smrg if (!(m_clause[i] & possible_truths))
2480ffa2763Smrg return false;
2490ffa2763Smrg }
2500ffa2763Smrg return true;
2510ffa2763Smrg }
2520ffa2763Smrg
2530ffa2763Smrg /* Return the probability in range 0...REG_BR_PROB_BASE that the predicated
2540ffa2763Smrg instruction will be recomputed per invocation of the inlined call. */
2550ffa2763Smrg
2560ffa2763Smrg int
probability(conditions conds,clause_t possible_truths,vec<inline_param_summary> inline_param_summary)2570ffa2763Smrg predicate::probability (conditions conds,
2580ffa2763Smrg clause_t possible_truths,
2590ffa2763Smrg vec<inline_param_summary> inline_param_summary) const
2600ffa2763Smrg {
2610ffa2763Smrg int i;
2620ffa2763Smrg int combined_prob = REG_BR_PROB_BASE;
2630ffa2763Smrg
2640ffa2763Smrg /* True remains true. */
2650ffa2763Smrg if (*this == true)
2660ffa2763Smrg return REG_BR_PROB_BASE;
2670ffa2763Smrg
2680ffa2763Smrg if (*this == false)
2690ffa2763Smrg return 0;
2700ffa2763Smrg
2710ffa2763Smrg gcc_assert (!(possible_truths & (1 << predicate::false_condition)));
2720ffa2763Smrg
2730ffa2763Smrg /* See if we can find clause we can disprove. */
2740ffa2763Smrg for (i = 0; m_clause[i]; i++)
2750ffa2763Smrg {
2760ffa2763Smrg gcc_checking_assert (i < max_clauses);
2770ffa2763Smrg if (!(m_clause[i] & possible_truths))
2780ffa2763Smrg return 0;
2790ffa2763Smrg else
2800ffa2763Smrg {
2810ffa2763Smrg int this_prob = 0;
2820ffa2763Smrg int i2;
2830ffa2763Smrg if (!inline_param_summary.exists ())
2840ffa2763Smrg return REG_BR_PROB_BASE;
2850ffa2763Smrg for (i2 = 0; i2 < num_conditions; i2++)
2860ffa2763Smrg if ((m_clause[i] & possible_truths) & (1 << i2))
2870ffa2763Smrg {
2880ffa2763Smrg if (i2 >= predicate::first_dynamic_condition)
2890ffa2763Smrg {
2900ffa2763Smrg condition *c =
2910ffa2763Smrg &(*conds)[i2 - predicate::first_dynamic_condition];
2920ffa2763Smrg if (c->code == predicate::changed
2930ffa2763Smrg && (c->operand_num <
2940ffa2763Smrg (int) inline_param_summary.length ()))
2950ffa2763Smrg {
2960ffa2763Smrg int iprob =
2970ffa2763Smrg inline_param_summary[c->operand_num].change_prob;
2980ffa2763Smrg this_prob = MAX (this_prob, iprob);
2990ffa2763Smrg }
3000ffa2763Smrg else
3010ffa2763Smrg this_prob = REG_BR_PROB_BASE;
3020ffa2763Smrg }
3030ffa2763Smrg else
3040ffa2763Smrg this_prob = REG_BR_PROB_BASE;
3050ffa2763Smrg }
3060ffa2763Smrg combined_prob = MIN (this_prob, combined_prob);
3070ffa2763Smrg if (!combined_prob)
3080ffa2763Smrg return 0;
3090ffa2763Smrg }
3100ffa2763Smrg }
3110ffa2763Smrg return combined_prob;
3120ffa2763Smrg }
3130ffa2763Smrg
3140ffa2763Smrg
3150ffa2763Smrg /* Dump conditional COND. */
3160ffa2763Smrg
3170ffa2763Smrg void
dump_condition(FILE * f,conditions conditions,int cond)3180ffa2763Smrg dump_condition (FILE *f, conditions conditions, int cond)
3190ffa2763Smrg {
3200ffa2763Smrg condition *c;
3210ffa2763Smrg if (cond == predicate::false_condition)
3220ffa2763Smrg fprintf (f, "false");
3230ffa2763Smrg else if (cond == predicate::not_inlined_condition)
3240ffa2763Smrg fprintf (f, "not inlined");
3250ffa2763Smrg else
3260ffa2763Smrg {
3270ffa2763Smrg c = &(*conditions)[cond - predicate::first_dynamic_condition];
3280ffa2763Smrg fprintf (f, "op%i", c->operand_num);
3290ffa2763Smrg if (c->agg_contents)
3300ffa2763Smrg fprintf (f, "[%soffset: " HOST_WIDE_INT_PRINT_DEC "]",
3310ffa2763Smrg c->by_ref ? "ref " : "", c->offset);
332*dd083157Smrg
333*dd083157Smrg for (unsigned i = 0; i < vec_safe_length (c->param_ops); i++)
334*dd083157Smrg {
335*dd083157Smrg expr_eval_op &op = (*(c->param_ops))[i];
336*dd083157Smrg const char *op_name = op_symbol_code (op.code);
337*dd083157Smrg
338*dd083157Smrg if (op_name == op_symbol_code (ERROR_MARK))
339*dd083157Smrg op_name = get_tree_code_name (op.code);
340*dd083157Smrg
341*dd083157Smrg fprintf (f, ",(");
342*dd083157Smrg
343*dd083157Smrg if (!op.val[0])
344*dd083157Smrg {
345*dd083157Smrg switch (op.code)
346*dd083157Smrg {
347*dd083157Smrg case FLOAT_EXPR:
348*dd083157Smrg case FIX_TRUNC_EXPR:
349*dd083157Smrg case FIXED_CONVERT_EXPR:
350*dd083157Smrg case VIEW_CONVERT_EXPR:
351*dd083157Smrg CASE_CONVERT:
352*dd083157Smrg if (op.code == VIEW_CONVERT_EXPR)
353*dd083157Smrg fprintf (f, "VCE");
354*dd083157Smrg fprintf (f, "(");
355*dd083157Smrg print_generic_expr (f, op.type);
356*dd083157Smrg fprintf (f, ")" );
357*dd083157Smrg break;
358*dd083157Smrg
359*dd083157Smrg default:
360*dd083157Smrg fprintf (f, "%s", op_name);
361*dd083157Smrg }
362*dd083157Smrg fprintf (f, " #");
363*dd083157Smrg }
364*dd083157Smrg else if (!op.val[1])
365*dd083157Smrg {
366*dd083157Smrg if (op.index)
367*dd083157Smrg {
368*dd083157Smrg print_generic_expr (f, op.val[0]);
369*dd083157Smrg fprintf (f, " %s #", op_name);
370*dd083157Smrg }
371*dd083157Smrg else
372*dd083157Smrg {
373*dd083157Smrg fprintf (f, "# %s ", op_name);
374*dd083157Smrg print_generic_expr (f, op.val[0]);
375*dd083157Smrg }
376*dd083157Smrg }
377*dd083157Smrg else
378*dd083157Smrg {
379*dd083157Smrg fprintf (f, "%s ", op_name);
380*dd083157Smrg switch (op.index)
381*dd083157Smrg {
382*dd083157Smrg case 0:
383*dd083157Smrg fprintf (f, "#, ");
384*dd083157Smrg print_generic_expr (f, op.val[0]);
385*dd083157Smrg fprintf (f, ", ");
386*dd083157Smrg print_generic_expr (f, op.val[1]);
387*dd083157Smrg break;
388*dd083157Smrg
389*dd083157Smrg case 1:
390*dd083157Smrg print_generic_expr (f, op.val[0]);
391*dd083157Smrg fprintf (f, ", #, ");
392*dd083157Smrg print_generic_expr (f, op.val[1]);
393*dd083157Smrg break;
394*dd083157Smrg
395*dd083157Smrg case 2:
396*dd083157Smrg print_generic_expr (f, op.val[0]);
397*dd083157Smrg fprintf (f, ", ");
398*dd083157Smrg print_generic_expr (f, op.val[1]);
399*dd083157Smrg fprintf (f, ", #");
400*dd083157Smrg break;
401*dd083157Smrg
402*dd083157Smrg default:
403*dd083157Smrg fprintf (f, "*, *, *");
404*dd083157Smrg }
405*dd083157Smrg }
406*dd083157Smrg fprintf (f, ")");
407*dd083157Smrg }
408*dd083157Smrg
4090ffa2763Smrg if (c->code == predicate::is_not_constant)
4100ffa2763Smrg {
4110ffa2763Smrg fprintf (f, " not constant");
4120ffa2763Smrg return;
4130ffa2763Smrg }
4140ffa2763Smrg if (c->code == predicate::changed)
4150ffa2763Smrg {
4160ffa2763Smrg fprintf (f, " changed");
4170ffa2763Smrg return;
4180ffa2763Smrg }
4190ffa2763Smrg fprintf (f, " %s ", op_symbol_code (c->code));
4200ffa2763Smrg print_generic_expr (f, c->val);
4210ffa2763Smrg }
4220ffa2763Smrg }
4230ffa2763Smrg
4240ffa2763Smrg
4250ffa2763Smrg /* Dump clause CLAUSE. */
4260ffa2763Smrg
4270ffa2763Smrg static void
dump_clause(FILE * f,conditions conds,clause_t clause)4280ffa2763Smrg dump_clause (FILE *f, conditions conds, clause_t clause)
4290ffa2763Smrg {
4300ffa2763Smrg int i;
4310ffa2763Smrg bool found = false;
4320ffa2763Smrg fprintf (f, "(");
4330ffa2763Smrg if (!clause)
4340ffa2763Smrg fprintf (f, "true");
4350ffa2763Smrg for (i = 0; i < predicate::num_conditions; i++)
4360ffa2763Smrg if (clause & (1 << i))
4370ffa2763Smrg {
4380ffa2763Smrg if (found)
4390ffa2763Smrg fprintf (f, " || ");
4400ffa2763Smrg found = true;
4410ffa2763Smrg dump_condition (f, conds, i);
4420ffa2763Smrg }
4430ffa2763Smrg fprintf (f, ")");
4440ffa2763Smrg }
4450ffa2763Smrg
4460ffa2763Smrg
447*dd083157Smrg /* Dump THIS to F. CONDS a vector of conditions used when evaluating
448*dd083157Smrg predicates. When NL is true new line is output at the end of dump. */
4490ffa2763Smrg
4500ffa2763Smrg void
dump(FILE * f,conditions conds,bool nl)4510ffa2763Smrg predicate::dump (FILE *f, conditions conds, bool nl) const
4520ffa2763Smrg {
4530ffa2763Smrg int i;
4540ffa2763Smrg if (*this == true)
4550ffa2763Smrg dump_clause (f, conds, 0);
4560ffa2763Smrg else
4570ffa2763Smrg for (i = 0; m_clause[i]; i++)
4580ffa2763Smrg {
4590ffa2763Smrg if (i)
4600ffa2763Smrg fprintf (f, " && ");
4610ffa2763Smrg dump_clause (f, conds, m_clause[i]);
4620ffa2763Smrg }
4630ffa2763Smrg if (nl)
4640ffa2763Smrg fprintf (f, "\n");
4650ffa2763Smrg }
4660ffa2763Smrg
4670ffa2763Smrg
4680ffa2763Smrg void
debug(conditions conds)4690ffa2763Smrg predicate::debug (conditions conds) const
4700ffa2763Smrg {
4710ffa2763Smrg dump (stderr, conds);
4720ffa2763Smrg }
4730ffa2763Smrg
4740ffa2763Smrg
4750ffa2763Smrg /* Remap predicate THIS of former function to be predicate of duplicated function.
4760ffa2763Smrg POSSIBLE_TRUTHS is clause of possible truths in the duplicated node,
4770ffa2763Smrg INFO is inline summary of the duplicated node. */
4780ffa2763Smrg
4790ffa2763Smrg predicate
remap_after_duplication(clause_t possible_truths)4800ffa2763Smrg predicate::remap_after_duplication (clause_t possible_truths)
4810ffa2763Smrg {
4820ffa2763Smrg int j;
4830ffa2763Smrg predicate out = true;
4840ffa2763Smrg for (j = 0; m_clause[j]; j++)
4850ffa2763Smrg if (!(possible_truths & m_clause[j]))
4860ffa2763Smrg return false;
4870ffa2763Smrg else
4880ffa2763Smrg out.add_clause (NULL, possible_truths & m_clause[j]);
4890ffa2763Smrg return out;
4900ffa2763Smrg }
4910ffa2763Smrg
4920ffa2763Smrg
4930ffa2763Smrg /* Translate all conditions from callee representation into caller
4940ffa2763Smrg representation and symbolically evaluate predicate THIS into new predicate.
4950ffa2763Smrg
4960ffa2763Smrg INFO is ipa_fn_summary of function we are adding predicate into, CALLEE_INFO
4970ffa2763Smrg is summary of function predicate P is from. OPERAND_MAP is array giving
498*dd083157Smrg callee formal IDs the caller formal IDs. POSSSIBLE_TRUTHS is clause of all
4990ffa2763Smrg callee conditions that may be true in caller context. TOPLEV_PREDICATE is
500*dd083157Smrg predicate under which callee is executed. OFFSET_MAP is an array of
5010ffa2763Smrg offsets that need to be added to conditions, negative offset means that
5020ffa2763Smrg conditions relying on values passed by reference have to be discarded
5030ffa2763Smrg because they might not be preserved (and should be considered offset zero
5040ffa2763Smrg for other purposes). */
5050ffa2763Smrg
5060ffa2763Smrg predicate
remap_after_inlining(class ipa_fn_summary * info,class ipa_node_params * params_summary,class ipa_fn_summary * callee_info,vec<int> operand_map,vec<int> offset_map,clause_t possible_truths,const predicate & toplev_predicate)507*dd083157Smrg predicate::remap_after_inlining (class ipa_fn_summary *info,
508*dd083157Smrg class ipa_node_params *params_summary,
509*dd083157Smrg class ipa_fn_summary *callee_info,
5100ffa2763Smrg vec<int> operand_map,
5110ffa2763Smrg vec<int> offset_map,
5120ffa2763Smrg clause_t possible_truths,
5130ffa2763Smrg const predicate &toplev_predicate)
5140ffa2763Smrg {
5150ffa2763Smrg int i;
5160ffa2763Smrg predicate out = true;
5170ffa2763Smrg
5180ffa2763Smrg /* True predicate is easy. */
5190ffa2763Smrg if (*this == true)
5200ffa2763Smrg return toplev_predicate;
5210ffa2763Smrg for (i = 0; m_clause[i]; i++)
5220ffa2763Smrg {
5230ffa2763Smrg clause_t clause = m_clause[i];
5240ffa2763Smrg int cond;
5250ffa2763Smrg predicate clause_predicate = false;
5260ffa2763Smrg
5270ffa2763Smrg gcc_assert (i < max_clauses);
5280ffa2763Smrg
5290ffa2763Smrg for (cond = 0; cond < num_conditions; cond++)
5300ffa2763Smrg /* Do we have condition we can't disprove? */
5310ffa2763Smrg if (clause & possible_truths & (1 << cond))
5320ffa2763Smrg {
5330ffa2763Smrg predicate cond_predicate;
5340ffa2763Smrg /* Work out if the condition can translate to predicate in the
5350ffa2763Smrg inlined function. */
5360ffa2763Smrg if (cond >= predicate::first_dynamic_condition)
5370ffa2763Smrg {
5380ffa2763Smrg struct condition *c;
5390ffa2763Smrg
5400ffa2763Smrg c = &(*callee_info->conds)[cond
5410ffa2763Smrg -
5420ffa2763Smrg predicate::first_dynamic_condition];
5430ffa2763Smrg /* See if we can remap condition operand to caller's operand.
5440ffa2763Smrg Otherwise give up. */
5450ffa2763Smrg if (!operand_map.exists ()
5460ffa2763Smrg || (int) operand_map.length () <= c->operand_num
5470ffa2763Smrg || operand_map[c->operand_num] == -1
5480ffa2763Smrg /* TODO: For non-aggregate conditions, adding an offset is
5490ffa2763Smrg basically an arithmetic jump function processing which
5500ffa2763Smrg we should support in future. */
5510ffa2763Smrg || ((!c->agg_contents || !c->by_ref)
5520ffa2763Smrg && offset_map[c->operand_num] > 0)
5530ffa2763Smrg || (c->agg_contents && c->by_ref
5540ffa2763Smrg && offset_map[c->operand_num] < 0))
5550ffa2763Smrg cond_predicate = true;
5560ffa2763Smrg else
5570ffa2763Smrg {
5580ffa2763Smrg struct agg_position_info ap;
5590ffa2763Smrg HOST_WIDE_INT offset_delta = offset_map[c->operand_num];
5600ffa2763Smrg if (offset_delta < 0)
5610ffa2763Smrg {
5620ffa2763Smrg gcc_checking_assert (!c->agg_contents || !c->by_ref);
5630ffa2763Smrg offset_delta = 0;
5640ffa2763Smrg }
5650ffa2763Smrg gcc_assert (!c->agg_contents
5660ffa2763Smrg || c->by_ref || offset_delta == 0);
5670ffa2763Smrg ap.offset = c->offset + offset_delta;
5680ffa2763Smrg ap.agg_contents = c->agg_contents;
5690ffa2763Smrg ap.by_ref = c->by_ref;
570*dd083157Smrg cond_predicate = add_condition (info, params_summary,
5710ffa2763Smrg operand_map[c->operand_num],
572*dd083157Smrg c->type, &ap, c->code,
573*dd083157Smrg c->val, c->param_ops);
5740ffa2763Smrg }
5750ffa2763Smrg }
5760ffa2763Smrg /* Fixed conditions remains same, construct single
5770ffa2763Smrg condition predicate. */
5780ffa2763Smrg else
5790ffa2763Smrg cond_predicate = predicate::predicate_testing_cond (cond);
5800ffa2763Smrg clause_predicate = clause_predicate.or_with (info->conds,
5810ffa2763Smrg cond_predicate);
5820ffa2763Smrg }
5830ffa2763Smrg out &= clause_predicate;
5840ffa2763Smrg }
5850ffa2763Smrg out &= toplev_predicate;
5860ffa2763Smrg return out;
5870ffa2763Smrg }
5880ffa2763Smrg
5890ffa2763Smrg
5900ffa2763Smrg /* Read predicate from IB. */
5910ffa2763Smrg
5920ffa2763Smrg void
stream_in(class lto_input_block * ib)593*dd083157Smrg predicate::stream_in (class lto_input_block *ib)
5940ffa2763Smrg {
5950ffa2763Smrg clause_t clause;
5960ffa2763Smrg int k = 0;
5970ffa2763Smrg
5980ffa2763Smrg do
5990ffa2763Smrg {
6000ffa2763Smrg gcc_assert (k <= max_clauses);
6010ffa2763Smrg clause = m_clause[k++] = streamer_read_uhwi (ib);
6020ffa2763Smrg }
6030ffa2763Smrg while (clause);
6040ffa2763Smrg
6050ffa2763Smrg /* Zero-initialize the remaining clauses in OUT. */
6060ffa2763Smrg while (k <= max_clauses)
6070ffa2763Smrg m_clause[k++] = 0;
6080ffa2763Smrg }
6090ffa2763Smrg
6100ffa2763Smrg
6110ffa2763Smrg /* Write predicate P to OB. */
6120ffa2763Smrg
6130ffa2763Smrg void
stream_out(struct output_block * ob)6140ffa2763Smrg predicate::stream_out (struct output_block *ob)
6150ffa2763Smrg {
6160ffa2763Smrg int j;
6170ffa2763Smrg for (j = 0; m_clause[j]; j++)
6180ffa2763Smrg {
6190ffa2763Smrg gcc_assert (j < max_clauses);
6200ffa2763Smrg streamer_write_uhwi (ob, m_clause[j]);
6210ffa2763Smrg }
6220ffa2763Smrg streamer_write_uhwi (ob, 0);
6230ffa2763Smrg }
6240ffa2763Smrg
6250ffa2763Smrg
626*dd083157Smrg /* Add condition to condition list SUMMARY. OPERAND_NUM, TYPE, CODE, VAL and
627*dd083157Smrg PARAM_OPS correspond to fields of condition structure. AGGPOS describes
628*dd083157Smrg whether the used operand is loaded from an aggregate and where in the
629*dd083157Smrg aggregate it is. It can be NULL, which means this not a load from an
630*dd083157Smrg aggregate. */
6310ffa2763Smrg
6320ffa2763Smrg predicate
add_condition(class ipa_fn_summary * summary,class ipa_node_params * params_summary,int operand_num,tree type,struct agg_position_info * aggpos,enum tree_code code,tree val,expr_eval_ops param_ops)633*dd083157Smrg add_condition (class ipa_fn_summary *summary,
634*dd083157Smrg class ipa_node_params *params_summary,
635*dd083157Smrg int operand_num,
636*dd083157Smrg tree type, struct agg_position_info *aggpos,
637*dd083157Smrg enum tree_code code, tree val, expr_eval_ops param_ops)
6380ffa2763Smrg {
639*dd083157Smrg int i, j;
6400ffa2763Smrg struct condition *c;
6410ffa2763Smrg struct condition new_cond;
6420ffa2763Smrg HOST_WIDE_INT offset;
6430ffa2763Smrg bool agg_contents, by_ref;
644*dd083157Smrg expr_eval_op *op;
645*dd083157Smrg
646*dd083157Smrg if (params_summary)
647*dd083157Smrg ipa_set_param_used_by_ipa_predicates (params_summary, operand_num, true);
6480ffa2763Smrg
6490ffa2763Smrg if (aggpos)
6500ffa2763Smrg {
6510ffa2763Smrg offset = aggpos->offset;
6520ffa2763Smrg agg_contents = aggpos->agg_contents;
6530ffa2763Smrg by_ref = aggpos->by_ref;
6540ffa2763Smrg }
6550ffa2763Smrg else
6560ffa2763Smrg {
6570ffa2763Smrg offset = 0;
6580ffa2763Smrg agg_contents = false;
6590ffa2763Smrg by_ref = false;
6600ffa2763Smrg }
6610ffa2763Smrg
6620ffa2763Smrg gcc_checking_assert (operand_num >= 0);
6630ffa2763Smrg for (i = 0; vec_safe_iterate (summary->conds, i, &c); i++)
6640ffa2763Smrg {
6650ffa2763Smrg if (c->operand_num == operand_num
6660ffa2763Smrg && c->code == code
667*dd083157Smrg && types_compatible_p (c->type, type)
668*dd083157Smrg && vrp_operand_equal_p (c->val, val)
6690ffa2763Smrg && c->agg_contents == agg_contents
670*dd083157Smrg && expr_eval_ops_equal_p (c->param_ops, param_ops)
6710ffa2763Smrg && (!agg_contents || (c->offset == offset && c->by_ref == by_ref)))
6720ffa2763Smrg return predicate::predicate_testing_cond (i);
6730ffa2763Smrg }
6740ffa2763Smrg /* Too many conditions. Give up and return constant true. */
6750ffa2763Smrg if (i == predicate::num_conditions - predicate::first_dynamic_condition)
6760ffa2763Smrg return true;
6770ffa2763Smrg
6780ffa2763Smrg new_cond.operand_num = operand_num;
6790ffa2763Smrg new_cond.code = code;
680*dd083157Smrg new_cond.type = unshare_expr_without_location (type);
681*dd083157Smrg new_cond.val = val ? unshare_expr_without_location (val) : val;
6820ffa2763Smrg new_cond.agg_contents = agg_contents;
6830ffa2763Smrg new_cond.by_ref = by_ref;
6840ffa2763Smrg new_cond.offset = offset;
685*dd083157Smrg new_cond.param_ops = vec_safe_copy (param_ops);
686*dd083157Smrg
687*dd083157Smrg for (j = 0; vec_safe_iterate (new_cond.param_ops, j, &op); j++)
688*dd083157Smrg {
689*dd083157Smrg if (op->val[0])
690*dd083157Smrg op->val[0] = unshare_expr_without_location (op->val[0]);
691*dd083157Smrg if (op->val[1])
692*dd083157Smrg op->val[1] = unshare_expr_without_location (op->val[1]);
693*dd083157Smrg }
694*dd083157Smrg
6950ffa2763Smrg vec_safe_push (summary->conds, new_cond);
6960ffa2763Smrg
6970ffa2763Smrg return predicate::predicate_testing_cond (i);
6980ffa2763Smrg }
699