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