Home | History | Annotate | Line # | Download | only in gcc
      1 /* IPA predicates.
      2    Copyright (C) 2003-2022 Free Software Foundation, Inc.
      3    Contributed by Jan Hubicka
      4 
      5 This file is part of GCC.
      6 
      7 GCC is free software; you can redistribute it and/or modify it under
      8 the terms of the GNU General Public License as published by the Free
      9 Software Foundation; either version 3, or (at your option) any later
     10 version.
     11 
     12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15 for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with GCC; see the file COPYING3.  If not see
     19 <http://www.gnu.org/licenses/>.  */
     20 
     21 /* Representation of inline parameters that do depend on context function is
     22    inlined into (i.e. known constant values of function parameters.
     23 
     24    Conditions that are interesting for function body are collected into CONDS
     25    vector.  They are of simple as kind of a mathematical transformation on
     26    function parameter, T(function_param), in which the parameter occurs only
     27    once, and other operands are IPA invariant.  The conditions are then
     28    referred by predicates.  */
     29 
     30 
     31 /* A simplified representation of tree node, for unary, binary and ternary
     32    operation.  Computations on parameter are decomposed to a series of this
     33    kind of structure.  */
     34 struct GTY(()) expr_eval_op
     35 {
     36   /* Result type of expression.  */
     37   tree type;
     38   /* Constant operands in expression, there are at most two.  */
     39   tree val[2];
     40   /* Index of parameter operand in expression.  */
     41   unsigned index : 2;
     42   /* Operation code of expression.  */
     43   ENUM_BITFIELD(tree_code) code : 16;
     44 };
     45 
     46 typedef vec<expr_eval_op, va_gc> *expr_eval_ops;
     47 
     48 struct GTY(()) condition
     49 {
     50   /* If agg_contents is set, this is the offset from which the used data was
     51      loaded.  */
     52   HOST_WIDE_INT offset;
     53   /* Type of the access reading the data (or the PARM_DECL SSA_NAME).  */
     54   tree type;
     55   tree val;
     56   int operand_num;
     57   ENUM_BITFIELD(tree_code) code : 16;
     58   /* Set if the used data were loaded from an aggregate parameter or from
     59      data received by reference.  */
     60   unsigned agg_contents : 1;
     61   /* If agg_contents is set, this differentiates between loads from data
     62      passed by reference and by value.  */
     63   unsigned by_ref : 1;
     64   /* A set of sequential operations on the parameter, which can be seen as
     65      a mathematical function on the parameter.  */
     66   expr_eval_ops param_ops;
     67 };
     68 
     69 /* Information kept about parameter of call site.  */
     70 struct inline_param_summary
     71 {
     72   /* REG_BR_PROB_BASE based probability that parameter will change in between
     73      two invocation of the calls.
     74      I.e. loop invariant parameters
     75      REG_BR_PROB_BASE/estimated_iterations and regular
     76      parameters REG_BR_PROB_BASE.
     77 
     78      Value 0 is reserved for compile time invariants. */
     79   short change_prob;
     80   unsigned points_to_local_or_readonly_memory : 1;
     81   bool equal_to (const inline_param_summary &other) const
     82   {
     83     return change_prob == other.change_prob
     84 	   && points_to_local_or_readonly_memory
     85 	      == other.points_to_local_or_readonly_memory;
     86   }
     87   bool useless_p (void) const
     88   {
     89     return change_prob == REG_BR_PROB_BASE
     90 	   && !points_to_local_or_readonly_memory;
     91   }
     92 };
     93 
     94 typedef vec<condition, va_gc> *conditions;
     95 
     96 /* Predicates are used to represent function parameters (such as runtime)
     97    which depend on a context function is called in.
     98 
     99    Predicates are logical formulas in conjunctive-disjunctive form consisting
    100    of clauses which are bitmaps specifying a set of condition that must
    101    be true for a clause to be satisfied. Physically they are represented as
    102    array of clauses terminated by 0.
    103 
    104    In order to make predicate (possibly) true, all of its clauses must
    105    be (possibly) true. To make clause (possibly) true, one of conditions
    106    it mentions must be (possibly) true.
    107 
    108    There are fixed bounds on number of clauses and conditions and all the
    109    manipulation functions are conservative in positive direction. I.e. we
    110    may lose precision by thinking that predicate may be true even when it
    111    is not.  */
    112 
    113 typedef uint32_t clause_t;
    114 class ipa_predicate
    115 {
    116 public:
    117   enum predicate_conditions
    118     {
    119       false_condition = 0,
    120       not_inlined_condition = 1,
    121       first_dynamic_condition = 2
    122     };
    123 
    124   /* Maximal number of conditions predicate can refer to.  This is limited
    125      by using clause_t to be 32bit.  */
    126   static const int num_conditions = 32;
    127 
    128   /* Special condition code we use to represent test that operand is compile
    129      time constant.  */
    130   static const tree_code is_not_constant = ERROR_MARK;
    131 
    132   /* Special condition code we use to represent test that operand is not changed
    133      across invocation of the function.  When operand IS_NOT_CONSTANT it is
    134      always CHANGED, however i.e. loop invariants can be NOT_CHANGED given
    135      percentage of executions even when they are not compile time constants.  */
    136   static const tree_code changed = IDENTIFIER_NODE;
    137 
    138 
    139 
    140   /* Initialize predicate either to true of false depending on P.  */
    141   inline ipa_predicate (bool p = true)
    142     {
    143       if (p)
    144         /* True predicate.  */
    145         m_clause[0] = 0;
    146       else
    147         /* False predicate. */
    148         set_to_cond (false_condition);
    149     }
    150 
    151   /* Sanity check that we do not mix pointers to predicates with predicates.  */
    152   inline ipa_predicate (ipa_predicate *)
    153     {
    154       gcc_unreachable ();
    155     }
    156 
    157   /* Return predicate testing condition I.  */
    158   static inline ipa_predicate predicate_testing_cond (int i)
    159     {
    160       ipa_predicate p;
    161       p.set_to_cond (i + first_dynamic_condition);
    162       return p;
    163     }
    164 
    165   /* Return predicate testing that function was not inlined.  */
    166   static ipa_predicate not_inlined (void)
    167     {
    168       ipa_predicate p;
    169       p.set_to_cond (not_inlined_condition);
    170       return p;
    171     }
    172 
    173   /* Compute logical and of ipa_predicates.  */
    174   ipa_predicate & operator &= (const ipa_predicate &);
    175   inline ipa_predicate operator &(const ipa_predicate &p) const
    176     {
    177       ipa_predicate ret = *this;
    178       ret &= p;
    179       return ret;
    180     }
    181 
    182   /* Compute logical or of ipa_predicates.  This is not operator because
    183      extra parameter CONDITIONS is needed  */
    184   ipa_predicate or_with (conditions, const ipa_predicate &) const;
    185 
    186   /* Return true if ipa_predicates are known to be equal.  */
    187   inline bool operator==(const ipa_predicate &p2) const
    188     {
    189       int i;
    190       for (i = 0; m_clause[i]; i++)
    191 	{
    192 	  gcc_checking_assert (i < max_clauses);
    193 	  gcc_checking_assert (m_clause[i] > m_clause[i + 1]);
    194 	  gcc_checking_assert (!p2.m_clause[i]
    195 			       || p2.m_clause[i] > p2.m_clause[i + 1]);
    196 	  if (m_clause[i] != p2.m_clause[i])
    197 	    return false;
    198 	}
    199       return !p2.m_clause[i];
    200     }
    201 
    202   /* Return true if predicates are known to be true or false depending
    203      on COND.  */
    204   inline bool operator==(const bool cond) const
    205     {
    206       if (cond)
    207         return !m_clause[0];
    208       if (m_clause[0] == (1 << false_condition))
    209 	{
    210 	  gcc_checking_assert (!m_clause[1]
    211 			       && m_clause[0] == 1
    212 				  << false_condition);
    213 	  return true;
    214 	}
    215       return false;
    216     }
    217 
    218   inline bool operator!=(const ipa_predicate &p2) const
    219     {
    220       return !(*this == p2);
    221     }
    222 
    223   inline bool operator!=(const bool cond) const
    224     {
    225       return !(*this == cond);
    226     }
    227 
    228   /* Evaluate if predicate is known to be false given the clause of possible
    229      truths.  */
    230   bool evaluate (clause_t) const;
    231 
    232   /* Estimate probability that predicate will be true in a given context.  */
    233   int probability (conditions, clause_t, vec<inline_param_summary>) const;
    234 
    235   /* Dump predicate to F. Output newline if nl.  */
    236   void dump (FILE *f, conditions, bool nl=true) const;
    237   void DEBUG_FUNCTION debug (conditions) const;
    238 
    239   /* Return ipa_predicate equal to THIS after duplication.  */
    240   ipa_predicate remap_after_duplication (clause_t);
    241 
    242   /* Return ipa_predicate equal to THIS after inlining.  */
    243   ipa_predicate remap_after_inlining (class ipa_fn_summary *,
    244 				      ipa_node_params *params_summary,
    245 				      ipa_fn_summary *,
    246 				      const vec<int> &,
    247 				      const vec<HOST_WIDE_INT> &,
    248 				      clause_t, const ipa_predicate &);
    249 
    250   void stream_in (lto_input_block *);
    251   void stream_out (output_block *);
    252 
    253 private:
    254   static const int max_clauses = 8;
    255   clause_t m_clause[max_clauses + 1];
    256 
    257   /* Initialize predicate to one testing single condition number COND.  */
    258   inline void set_to_cond (int cond)
    259     {
    260       m_clause[0] = 1 << cond;
    261       m_clause[1] = 0;
    262     }
    263 
    264   void add_clause (conditions conditions, clause_t);
    265 };
    266 
    267 void dump_condition (FILE *f, conditions conditions, int cond);
    268 ipa_predicate add_condition (ipa_fn_summary *summary,
    269 			     ipa_node_params *params_summary,
    270 			     int operand_num,
    271 			     tree type, struct agg_position_info *aggpos,
    272 			     enum tree_code code, tree val,
    273 			     expr_eval_ops param_ops = NULL);
    274