1 /* IPA predicates. 2 Copyright (C) 2003-2018 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 for function_param OP VAL, where VAL is 26 IPA invariant. The conditions are then referred by predicates. */ 27 28 struct GTY(()) condition 29 { 30 /* If agg_contents is set, this is the offset from which the used data was 31 loaded. */ 32 HOST_WIDE_INT offset; 33 /* Size of the access reading the data (or the PARM_DECL SSA_NAME). */ 34 HOST_WIDE_INT size; 35 tree val; 36 int operand_num; 37 ENUM_BITFIELD(tree_code) code : 16; 38 /* Set if the used data were loaded from an aggregate parameter or from 39 data received by reference. */ 40 unsigned agg_contents : 1; 41 /* If agg_contents is set, this differentiates between loads from data 42 passed by reference and by value. */ 43 unsigned by_ref : 1; 44 }; 45 46 /* Information kept about parameter of call site. */ 47 struct inline_param_summary 48 { 49 /* REG_BR_PROB_BASE based probability that parameter will change in between 50 two invocation of the calls. 51 I.e. loop invariant parameters 52 REG_BR_PROB_BASE/estimated_iterations and regular 53 parameters REG_BR_PROB_BASE. 54 55 Value 0 is reserved for compile time invariants. */ 56 int change_prob; 57 }; 58 59 typedef vec<condition, va_gc> *conditions; 60 61 /* Predicates are used to repesent function parameters (such as runtime) 62 which depend on a context function is called in. 63 64 Predicates are logical formulas in conjunctive-disjunctive form consisting 65 of clauses which are bitmaps specifying a set of condition that must 66 be true for a clause to be satisfied. Physically they are represented as 67 array of clauses terminated by 0. 68 69 In order to make predicate (possibly) true, all of its clauses must 70 be (possibly) true. To make clause (possibly) true, one of conditions 71 it mentions must be (possibly) true. 72 73 There are fixed bounds on number of clauses and conditions and all the 74 manipulation functions are conservative in positive direction. I.e. we 75 may lose precision by thinking that predicate may be true even when it 76 is not. */ 77 78 typedef uint32_t clause_t; 79 class predicate 80 { 81 public: 82 enum predicate_conditions 83 { 84 false_condition = 0, 85 not_inlined_condition = 1, 86 first_dynamic_condition = 2 87 }; 88 89 /* Maximal number of conditions predicate can reffer to. This is limited 90 by using clause_t to be 32bit. */ 91 static const int num_conditions = 32; 92 93 /* Special condition code we use to represent test that operand is compile 94 time constant. */ 95 static const tree_code is_not_constant = ERROR_MARK; 96 97 /* Special condition code we use to represent test that operand is not changed 98 across invocation of the function. When operand IS_NOT_CONSTANT it is 99 always CHANGED, however i.e. loop invariants can be NOT_CHANGED given 100 percentage of executions even when they are not compile time constants. */ 101 static const tree_code changed = IDENTIFIER_NODE; 102 103 104 105 /* Initialize predicate either to true of false depending on P. */ 106 inline predicate (bool p = true) 107 { 108 if (p) 109 /* True predicate. */ 110 m_clause[0] = 0; 111 else 112 /* False predicate. */ 113 set_to_cond (false_condition); 114 } 115 116 /* Sanity check that we do not mix pointers to predicates with predicates. */ predicate(predicate *)117 inline predicate (predicate *) 118 { 119 gcc_unreachable (); 120 } 121 122 /* Return predicate testing condition I. */ predicate_testing_cond(int i)123 static inline predicate predicate_testing_cond (int i) 124 { 125 class predicate p; 126 p.set_to_cond (i + first_dynamic_condition); 127 return p; 128 } 129 130 /* Return predicate testing that function was not inlined. */ not_inlined(void)131 static predicate not_inlined (void) 132 { 133 class predicate p; 134 p.set_to_cond (not_inlined_condition); 135 return p; 136 } 137 138 /* Compute logical and of predicates. */ 139 predicate & operator &= (const predicate &); 140 inline predicate operator &(const predicate &p) const 141 { 142 predicate ret = *this; 143 ret &= p; 144 return ret; 145 } 146 147 /* Compute logical or of predicates. This is not operator because 148 extra parameter CONDITIONS is needed */ 149 predicate or_with (conditions, const predicate &) const; 150 151 /* Return true if predicates are known to be equal. */ 152 inline bool operator==(const predicate &p2) const 153 { 154 int i; 155 for (i = 0; m_clause[i]; i++) 156 { 157 gcc_checking_assert (i < max_clauses); 158 gcc_checking_assert (m_clause[i] > m_clause[i + 1]); 159 gcc_checking_assert (!p2.m_clause[i] 160 || p2.m_clause[i] > p2.m_clause[i + 1]); 161 if (m_clause[i] != p2.m_clause[i]) 162 return false; 163 } 164 return !p2.m_clause[i]; 165 } 166 167 /* Return true if predicates are known to be true or false depending 168 on COND. */ 169 inline bool operator==(const bool cond) const 170 { 171 if (cond) 172 return !m_clause[0]; 173 if (m_clause[0] == (1 << false_condition)) 174 { 175 gcc_checking_assert (!m_clause[1] 176 && m_clause[0] == 1 177 << false_condition); 178 return true; 179 } 180 return false; 181 } 182 183 inline bool operator!=(const predicate &p2) const 184 { 185 return !(*this == p2); 186 } 187 188 inline bool operator!=(const bool cond) const 189 { 190 return !(*this == cond); 191 } 192 193 /* Evaluate if predicate is known to be false given the clause of possible 194 truths. */ 195 bool evaluate (clause_t) const; 196 197 /* Estimate probability that predicate will be true in a given context. */ 198 int probability (conditions, clause_t, vec<inline_param_summary>) const; 199 200 /* Dump predicate to F. Output newline if nl. */ 201 void dump (FILE *f, conditions, bool nl=true) const; 202 void DEBUG_FUNCTION debug (conditions) const; 203 204 /* Return predicate equal to THIS after duplication. */ 205 predicate remap_after_duplication (clause_t); 206 207 /* Return predicate equal to THIS after inlining. */ 208 predicate remap_after_inlining (struct ipa_fn_summary *, 209 struct ipa_fn_summary *, 210 vec<int>, vec<int>, clause_t, const predicate &); 211 212 void stream_in (struct lto_input_block *); 213 void stream_out (struct output_block *); 214 215 private: 216 static const int max_clauses = 8; 217 clause_t m_clause[max_clauses + 1]; 218 219 /* Initialize predicate to one testing single condition number COND. */ set_to_cond(int cond)220 inline void set_to_cond (int cond) 221 { 222 m_clause[0] = 1 << cond; 223 m_clause[1] = 0; 224 } 225 226 void add_clause (conditions conditions, clause_t); 227 }; 228 229 void dump_condition (FILE *f, conditions conditions, int cond); 230 predicate add_condition (struct ipa_fn_summary *summary, int operand_num, 231 HOST_WIDE_INT size, struct agg_position_info *aggpos, 232 enum tree_code code, tree val); 233