]>
Commit | Line | Data |
---|---|---|
b679b55b | 1 | /* IPA predicates. |
a945c346 | 2 | Copyright (C) 2003-2024 Free Software Foundation, Inc. |
b679b55b JH |
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 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "backend.h" | |
25 | #include "tree.h" | |
26 | #include "cgraph.h" | |
27 | #include "tree-vrp.h" | |
b679b55b | 28 | #include "alloc-pool.h" |
a895e6d7 | 29 | #include "symbol-summary.h" |
c8742849 MJ |
30 | #include "sreal.h" |
31 | #include "ipa-cp.h" | |
b679b55b | 32 | #include "ipa-prop.h" |
27d020cf | 33 | #include "ipa-fnsummary.h" |
b679b55b JH |
34 | #include "real.h" |
35 | #include "fold-const.h" | |
36 | #include "tree-pretty-print.h" | |
37 | #include "gimple.h" | |
4307a485 | 38 | #include "gimplify.h" |
b679b55b JH |
39 | #include "data-streamer.h" |
40 | ||
41 | ||
4307a485 FX |
42 | /* Check whether two set of operations have same effects. */ |
43 | static bool | |
44 | expr_eval_ops_equal_p (expr_eval_ops ops1, expr_eval_ops ops2) | |
45 | { | |
46 | if (ops1) | |
47 | { | |
48 | if (!ops2 || ops1->length () != ops2->length ()) | |
49 | return false; | |
50 | ||
51 | for (unsigned i = 0; i < ops1->length (); i++) | |
52 | { | |
53 | expr_eval_op &op1 = (*ops1)[i]; | |
54 | expr_eval_op &op2 = (*ops2)[i]; | |
55 | ||
56 | if (op1.code != op2.code | |
57 | || op1.index != op2.index | |
58 | || !vrp_operand_equal_p (op1.val[0], op2.val[0]) | |
59 | || !vrp_operand_equal_p (op1.val[1], op2.val[1]) | |
60 | || !types_compatible_p (op1.type, op2.type)) | |
61 | return false; | |
62 | } | |
63 | return true; | |
64 | } | |
65 | return !ops2; | |
66 | } | |
67 | ||
b679b55b JH |
68 | /* Add clause CLAUSE into the predicate P. |
69 | When CONDITIONS is NULL do not perform checking whether NEW_CLAUSE | |
70 | is obviously true. This is useful only when NEW_CLAUSE is known to be | |
71 | sane. */ | |
72 | ||
73 | void | |
2d01bef2 | 74 | ipa_predicate::add_clause (conditions conditions, clause_t new_clause) |
b679b55b JH |
75 | { |
76 | int i; | |
77 | int i2; | |
78 | int insert_here = -1; | |
79 | int c1, c2; | |
80 | ||
81 | /* True clause. */ | |
82 | if (!new_clause) | |
83 | return; | |
84 | ||
85 | /* False clause makes the whole predicate false. Kill the other variants. */ | |
2d01bef2 | 86 | if (new_clause == (1 << ipa_predicate::false_condition)) |
b679b55b JH |
87 | { |
88 | *this = false; | |
89 | return; | |
90 | } | |
91 | if (*this == false) | |
92 | return; | |
93 | ||
94 | /* No one should be silly enough to add false into nontrivial clauses. */ | |
2d01bef2 | 95 | gcc_checking_assert (!(new_clause & (1 << ipa_predicate::false_condition))); |
b679b55b JH |
96 | |
97 | /* Look where to insert the new_clause. At the same time prune out | |
98 | new_clauses of P that are implied by the new new_clause and thus | |
99 | redundant. */ | |
100 | for (i = 0, i2 = 0; i <= max_clauses; i++) | |
101 | { | |
102 | m_clause[i2] = m_clause[i]; | |
103 | ||
104 | if (!m_clause[i]) | |
105 | break; | |
106 | ||
107 | /* If m_clause[i] implies new_clause, there is nothing to add. */ | |
108 | if ((m_clause[i] & new_clause) == m_clause[i]) | |
109 | { | |
110 | /* We had nothing to add, none of clauses should've become | |
111 | redundant. */ | |
112 | gcc_checking_assert (i == i2); | |
113 | return; | |
114 | } | |
115 | ||
116 | if (m_clause[i] < new_clause && insert_here < 0) | |
117 | insert_here = i2; | |
118 | ||
119 | /* If new_clause implies clause[i], then clause[i] becomes redundant. | |
120 | Otherwise the clause[i] has to stay. */ | |
121 | if ((m_clause[i] & new_clause) != new_clause) | |
122 | i2++; | |
123 | } | |
124 | ||
125 | /* Look for clauses that are obviously true. I.e. | |
126 | op0 == 5 || op0 != 5. */ | |
127 | if (conditions) | |
2d01bef2 | 128 | for (c1 = ipa_predicate::first_dynamic_condition; |
b679b55b JH |
129 | c1 < num_conditions; c1++) |
130 | { | |
131 | condition *cc1; | |
132 | if (!(new_clause & (1 << c1))) | |
133 | continue; | |
2d01bef2 | 134 | cc1 = &(*conditions)[c1 - ipa_predicate::first_dynamic_condition]; |
b679b55b JH |
135 | /* We have no way to represent !changed and !is_not_constant |
136 | and thus there is no point for looking for them. */ | |
5a1ef1cf | 137 | if (cc1->code == changed || cc1->code == is_not_constant || cc1->code == not_sra_candidate) |
b679b55b JH |
138 | continue; |
139 | for (c2 = c1 + 1; c2 < num_conditions; c2++) | |
140 | if (new_clause & (1 << c2)) | |
141 | { | |
b679b55b | 142 | condition *cc2 = |
2d01bef2 | 143 | &(*conditions)[c2 - ipa_predicate::first_dynamic_condition]; |
b679b55b | 144 | if (cc1->operand_num == cc2->operand_num |
4307a485 | 145 | && vrp_operand_equal_p (cc1->val, cc2->val) |
b679b55b | 146 | && cc2->code != is_not_constant |
5a1ef1cf | 147 | && cc2->code != not_sra_candidate |
4307a485 FX |
148 | && cc2->code != changed |
149 | && expr_eval_ops_equal_p (cc1->param_ops, cc2->param_ops) | |
150 | && cc2->agg_contents == cc1->agg_contents | |
151 | && cc2->by_ref == cc1->by_ref | |
152 | && types_compatible_p (cc2->type, cc1->type) | |
b679b55b JH |
153 | && cc1->code == invert_tree_comparison (cc2->code, |
154 | HONOR_NANS (cc1->val))) | |
155 | return; | |
156 | } | |
157 | } | |
158 | ||
159 | ||
160 | /* We run out of variants. Be conservative in positive direction. */ | |
161 | if (i2 == max_clauses) | |
162 | return; | |
163 | /* Keep clauses in decreasing order. This makes equivalence testing easy. */ | |
164 | m_clause[i2 + 1] = 0; | |
165 | if (insert_here >= 0) | |
166 | for (; i2 > insert_here; i2--) | |
167 | m_clause[i2] = m_clause[i2 - 1]; | |
168 | else | |
169 | insert_here = i2; | |
170 | m_clause[insert_here] = new_clause; | |
171 | } | |
172 | ||
173 | ||
174 | /* Do THIS &= P. */ | |
175 | ||
2d01bef2 ML |
176 | ipa_predicate & |
177 | ipa_predicate::operator &= (const ipa_predicate &p) | |
b679b55b JH |
178 | { |
179 | /* Avoid busy work. */ | |
180 | if (p == false || *this == true) | |
181 | { | |
182 | *this = p; | |
183 | return *this; | |
184 | } | |
185 | if (*this == false || p == true || this == &p) | |
186 | return *this; | |
187 | ||
188 | int i; | |
189 | ||
2d01bef2 | 190 | /* See how far ipa_predicates match. */ |
b679b55b JH |
191 | for (i = 0; m_clause[i] && m_clause[i] == p.m_clause[i]; i++) |
192 | { | |
193 | gcc_checking_assert (i < max_clauses); | |
194 | } | |
195 | ||
2d01bef2 | 196 | /* Combine the ipa_predicates rest. */ |
b679b55b JH |
197 | for (; p.m_clause[i]; i++) |
198 | { | |
199 | gcc_checking_assert (i < max_clauses); | |
200 | add_clause (NULL, p.m_clause[i]); | |
201 | } | |
202 | return *this; | |
203 | } | |
204 | ||
205 | ||
206 | ||
207 | /* Return THIS | P2. */ | |
208 | ||
2d01bef2 ML |
209 | ipa_predicate |
210 | ipa_predicate::or_with (conditions conditions, | |
211 | const ipa_predicate &p) const | |
b679b55b JH |
212 | { |
213 | /* Avoid busy work. */ | |
214 | if (p == false || *this == true || *this == p) | |
215 | return *this; | |
216 | if (*this == false || p == true) | |
217 | return p; | |
218 | ||
219 | /* OK, combine the predicates. */ | |
2d01bef2 | 220 | ipa_predicate out = true; |
b679b55b JH |
221 | |
222 | for (int i = 0; m_clause[i]; i++) | |
223 | for (int j = 0; p.m_clause[j]; j++) | |
224 | { | |
225 | gcc_checking_assert (i < max_clauses && j < max_clauses); | |
226 | out.add_clause (conditions, m_clause[i] | p.m_clause[j]); | |
227 | } | |
228 | return out; | |
229 | } | |
230 | ||
231 | ||
232 | /* Having partial truth assignment in POSSIBLE_TRUTHS, return false | |
233 | if predicate P is known to be false. */ | |
234 | ||
235 | bool | |
2d01bef2 | 236 | ipa_predicate::evaluate (clause_t possible_truths) const |
b679b55b JH |
237 | { |
238 | int i; | |
239 | ||
240 | /* True remains true. */ | |
241 | if (*this == true) | |
242 | return true; | |
243 | ||
2d01bef2 | 244 | gcc_assert (!(possible_truths & (1 << ipa_predicate::false_condition))); |
b679b55b JH |
245 | |
246 | /* See if we can find clause we can disprove. */ | |
247 | for (i = 0; m_clause[i]; i++) | |
248 | { | |
249 | gcc_checking_assert (i < max_clauses); | |
250 | if (!(m_clause[i] & possible_truths)) | |
251 | return false; | |
252 | } | |
253 | return true; | |
254 | } | |
255 | ||
256 | /* Return the probability in range 0...REG_BR_PROB_BASE that the predicated | |
257 | instruction will be recomputed per invocation of the inlined call. */ | |
258 | ||
259 | int | |
2d01bef2 | 260 | ipa_predicate::probability (conditions conds, |
b679b55b JH |
261 | clause_t possible_truths, |
262 | vec<inline_param_summary> inline_param_summary) const | |
263 | { | |
264 | int i; | |
265 | int combined_prob = REG_BR_PROB_BASE; | |
266 | ||
267 | /* True remains true. */ | |
268 | if (*this == true) | |
269 | return REG_BR_PROB_BASE; | |
270 | ||
271 | if (*this == false) | |
272 | return 0; | |
273 | ||
2d01bef2 | 274 | gcc_assert (!(possible_truths & (1 << ipa_predicate::false_condition))); |
b679b55b JH |
275 | |
276 | /* See if we can find clause we can disprove. */ | |
277 | for (i = 0; m_clause[i]; i++) | |
278 | { | |
279 | gcc_checking_assert (i < max_clauses); | |
280 | if (!(m_clause[i] & possible_truths)) | |
281 | return 0; | |
282 | else | |
283 | { | |
284 | int this_prob = 0; | |
285 | int i2; | |
286 | if (!inline_param_summary.exists ()) | |
287 | return REG_BR_PROB_BASE; | |
288 | for (i2 = 0; i2 < num_conditions; i2++) | |
289 | if ((m_clause[i] & possible_truths) & (1 << i2)) | |
290 | { | |
2d01bef2 | 291 | if (i2 >= ipa_predicate::first_dynamic_condition) |
b679b55b JH |
292 | { |
293 | condition *c = | |
2d01bef2 ML |
294 | &(*conds)[i2 - ipa_predicate::first_dynamic_condition]; |
295 | if (c->code == ipa_predicate::changed | |
b679b55b JH |
296 | && (c->operand_num < |
297 | (int) inline_param_summary.length ())) | |
298 | { | |
299 | int iprob = | |
300 | inline_param_summary[c->operand_num].change_prob; | |
301 | this_prob = MAX (this_prob, iprob); | |
302 | } | |
303 | else | |
304 | this_prob = REG_BR_PROB_BASE; | |
305 | } | |
306 | else | |
307 | this_prob = REG_BR_PROB_BASE; | |
308 | } | |
309 | combined_prob = MIN (this_prob, combined_prob); | |
310 | if (!combined_prob) | |
311 | return 0; | |
312 | } | |
313 | } | |
314 | return combined_prob; | |
315 | } | |
316 | ||
317 | ||
318 | /* Dump conditional COND. */ | |
319 | ||
320 | void | |
321 | dump_condition (FILE *f, conditions conditions, int cond) | |
322 | { | |
323 | condition *c; | |
2d01bef2 | 324 | if (cond == ipa_predicate::false_condition) |
b679b55b | 325 | fprintf (f, "false"); |
2d01bef2 | 326 | else if (cond == ipa_predicate::not_inlined_condition) |
b679b55b JH |
327 | fprintf (f, "not inlined"); |
328 | else | |
329 | { | |
2d01bef2 | 330 | c = &(*conditions)[cond - ipa_predicate::first_dynamic_condition]; |
b679b55b JH |
331 | fprintf (f, "op%i", c->operand_num); |
332 | if (c->agg_contents) | |
333 | fprintf (f, "[%soffset: " HOST_WIDE_INT_PRINT_DEC "]", | |
334 | c->by_ref ? "ref " : "", c->offset); | |
4307a485 FX |
335 | |
336 | for (unsigned i = 0; i < vec_safe_length (c->param_ops); i++) | |
337 | { | |
338 | expr_eval_op &op = (*(c->param_ops))[i]; | |
339 | const char *op_name = op_symbol_code (op.code); | |
340 | ||
341 | if (op_name == op_symbol_code (ERROR_MARK)) | |
342 | op_name = get_tree_code_name (op.code); | |
343 | ||
344 | fprintf (f, ",("); | |
345 | ||
346 | if (!op.val[0]) | |
347 | { | |
348 | switch (op.code) | |
349 | { | |
350 | case FLOAT_EXPR: | |
351 | case FIX_TRUNC_EXPR: | |
352 | case FIXED_CONVERT_EXPR: | |
353 | case VIEW_CONVERT_EXPR: | |
354 | CASE_CONVERT: | |
355 | if (op.code == VIEW_CONVERT_EXPR) | |
356 | fprintf (f, "VCE"); | |
357 | fprintf (f, "("); | |
358 | print_generic_expr (f, op.type); | |
359 | fprintf (f, ")" ); | |
360 | break; | |
361 | ||
362 | default: | |
363 | fprintf (f, "%s", op_name); | |
364 | } | |
365 | fprintf (f, " #"); | |
366 | } | |
367 | else if (!op.val[1]) | |
368 | { | |
369 | if (op.index) | |
370 | { | |
371 | print_generic_expr (f, op.val[0]); | |
372 | fprintf (f, " %s #", op_name); | |
373 | } | |
374 | else | |
375 | { | |
376 | fprintf (f, "# %s ", op_name); | |
377 | print_generic_expr (f, op.val[0]); | |
378 | } | |
379 | } | |
380 | else | |
381 | { | |
382 | fprintf (f, "%s ", op_name); | |
383 | switch (op.index) | |
384 | { | |
385 | case 0: | |
386 | fprintf (f, "#, "); | |
387 | print_generic_expr (f, op.val[0]); | |
388 | fprintf (f, ", "); | |
389 | print_generic_expr (f, op.val[1]); | |
390 | break; | |
391 | ||
392 | case 1: | |
393 | print_generic_expr (f, op.val[0]); | |
394 | fprintf (f, ", #, "); | |
395 | print_generic_expr (f, op.val[1]); | |
396 | break; | |
397 | ||
398 | case 2: | |
399 | print_generic_expr (f, op.val[0]); | |
400 | fprintf (f, ", "); | |
401 | print_generic_expr (f, op.val[1]); | |
402 | fprintf (f, ", #"); | |
403 | break; | |
404 | ||
405 | default: | |
406 | fprintf (f, "*, *, *"); | |
407 | } | |
408 | } | |
409 | fprintf (f, ")"); | |
410 | } | |
411 | ||
2d01bef2 | 412 | if (c->code == ipa_predicate::is_not_constant) |
b679b55b JH |
413 | { |
414 | fprintf (f, " not constant"); | |
415 | return; | |
416 | } | |
2d01bef2 | 417 | if (c->code == ipa_predicate::changed) |
b679b55b JH |
418 | { |
419 | fprintf (f, " changed"); | |
420 | return; | |
421 | } | |
5a1ef1cf H |
422 | if (c->code == ipa_predicate::not_sra_candidate) |
423 | { | |
424 | fprintf (f, " not sra candidate"); | |
425 | return; | |
426 | } | |
b679b55b JH |
427 | fprintf (f, " %s ", op_symbol_code (c->code)); |
428 | print_generic_expr (f, c->val); | |
429 | } | |
430 | } | |
431 | ||
432 | ||
433 | /* Dump clause CLAUSE. */ | |
434 | ||
435 | static void | |
436 | dump_clause (FILE *f, conditions conds, clause_t clause) | |
437 | { | |
438 | int i; | |
439 | bool found = false; | |
440 | fprintf (f, "("); | |
441 | if (!clause) | |
442 | fprintf (f, "true"); | |
2d01bef2 | 443 | for (i = 0; i < ipa_predicate::num_conditions; i++) |
b679b55b JH |
444 | if (clause & (1 << i)) |
445 | { | |
446 | if (found) | |
447 | fprintf (f, " || "); | |
448 | found = true; | |
449 | dump_condition (f, conds, i); | |
450 | } | |
451 | fprintf (f, ")"); | |
452 | } | |
453 | ||
454 | ||
956d615d | 455 | /* Dump THIS to F. CONDS a vector of conditions used when evaluating |
2d01bef2 | 456 | ipa_predicates. When NL is true new line is output at the end of dump. */ |
b679b55b JH |
457 | |
458 | void | |
2d01bef2 | 459 | ipa_predicate::dump (FILE *f, conditions conds, bool nl) const |
b679b55b JH |
460 | { |
461 | int i; | |
462 | if (*this == true) | |
463 | dump_clause (f, conds, 0); | |
464 | else | |
465 | for (i = 0; m_clause[i]; i++) | |
466 | { | |
467 | if (i) | |
468 | fprintf (f, " && "); | |
469 | dump_clause (f, conds, m_clause[i]); | |
470 | } | |
471 | if (nl) | |
472 | fprintf (f, "\n"); | |
473 | } | |
474 | ||
475 | ||
476 | void | |
2d01bef2 | 477 | ipa_predicate::debug (conditions conds) const |
b679b55b JH |
478 | { |
479 | dump (stderr, conds); | |
480 | } | |
481 | ||
482 | ||
483 | /* Remap predicate THIS of former function to be predicate of duplicated function. | |
484 | POSSIBLE_TRUTHS is clause of possible truths in the duplicated node, | |
485 | INFO is inline summary of the duplicated node. */ | |
486 | ||
2d01bef2 ML |
487 | ipa_predicate |
488 | ipa_predicate::remap_after_duplication (clause_t possible_truths) | |
b679b55b JH |
489 | { |
490 | int j; | |
2d01bef2 | 491 | ipa_predicate out = true; |
b679b55b JH |
492 | for (j = 0; m_clause[j]; j++) |
493 | if (!(possible_truths & m_clause[j])) | |
494 | return false; | |
495 | else | |
496 | out.add_clause (NULL, possible_truths & m_clause[j]); | |
497 | return out; | |
498 | } | |
499 | ||
500 | ||
501 | /* Translate all conditions from callee representation into caller | |
502 | representation and symbolically evaluate predicate THIS into new predicate. | |
503 | ||
0bceb671 | 504 | INFO is ipa_fn_summary of function we are adding predicate into, CALLEE_INFO |
b679b55b | 505 | is summary of function predicate P is from. OPERAND_MAP is array giving |
956d615d | 506 | callee formal IDs the caller formal IDs. POSSSIBLE_TRUTHS is clause of all |
b679b55b | 507 | callee conditions that may be true in caller context. TOPLEV_PREDICATE is |
d5029d45 | 508 | predicate under which callee is executed. OFFSET_MAP is an array of |
b679b55b JH |
509 | offsets that need to be added to conditions, negative offset means that |
510 | conditions relying on values passed by reference have to be discarded | |
511 | because they might not be preserved (and should be considered offset zero | |
512 | for other purposes). */ | |
513 | ||
2d01bef2 ML |
514 | ipa_predicate |
515 | ipa_predicate::remap_after_inlining (class ipa_fn_summary *info, | |
40a777e8 | 516 | class ipa_node_params *params_summary, |
99b1c316 | 517 | class ipa_fn_summary *callee_info, |
00dcc88a MS |
518 | const vec<int> &operand_map, |
519 | const vec<HOST_WIDE_INT> &offset_map, | |
b679b55b | 520 | clause_t possible_truths, |
2d01bef2 | 521 | const ipa_predicate &toplev_predicate) |
b679b55b JH |
522 | { |
523 | int i; | |
2d01bef2 | 524 | ipa_predicate out = true; |
b679b55b | 525 | |
2d01bef2 | 526 | /* True ipa_predicate is easy. */ |
b679b55b JH |
527 | if (*this == true) |
528 | return toplev_predicate; | |
529 | for (i = 0; m_clause[i]; i++) | |
530 | { | |
531 | clause_t clause = m_clause[i]; | |
532 | int cond; | |
2d01bef2 | 533 | ipa_predicate clause_predicate = false; |
b679b55b JH |
534 | |
535 | gcc_assert (i < max_clauses); | |
536 | ||
537 | for (cond = 0; cond < num_conditions; cond++) | |
538 | /* Do we have condition we can't disprove? */ | |
539 | if (clause & possible_truths & (1 << cond)) | |
540 | { | |
2d01bef2 | 541 | ipa_predicate cond_predicate; |
b679b55b JH |
542 | /* Work out if the condition can translate to predicate in the |
543 | inlined function. */ | |
2d01bef2 | 544 | if (cond >= ipa_predicate::first_dynamic_condition) |
b679b55b JH |
545 | { |
546 | struct condition *c; | |
547 | ||
2d01bef2 ML |
548 | int index = cond - ipa_predicate::first_dynamic_condition; |
549 | c = &(*callee_info->conds)[index]; | |
b679b55b JH |
550 | /* See if we can remap condition operand to caller's operand. |
551 | Otherwise give up. */ | |
552 | if (!operand_map.exists () | |
553 | || (int) operand_map.length () <= c->operand_num | |
554 | || operand_map[c->operand_num] == -1 | |
555 | /* TODO: For non-aggregate conditions, adding an offset is | |
556 | basically an arithmetic jump function processing which | |
557 | we should support in future. */ | |
558 | || ((!c->agg_contents || !c->by_ref) | |
559 | && offset_map[c->operand_num] > 0) | |
560 | || (c->agg_contents && c->by_ref | |
561 | && offset_map[c->operand_num] < 0)) | |
562 | cond_predicate = true; | |
563 | else | |
564 | { | |
565 | struct agg_position_info ap; | |
566 | HOST_WIDE_INT offset_delta = offset_map[c->operand_num]; | |
567 | if (offset_delta < 0) | |
568 | { | |
569 | gcc_checking_assert (!c->agg_contents || !c->by_ref); | |
570 | offset_delta = 0; | |
571 | } | |
572 | gcc_assert (!c->agg_contents | |
573 | || c->by_ref || offset_delta == 0); | |
574 | ap.offset = c->offset + offset_delta; | |
575 | ap.agg_contents = c->agg_contents; | |
576 | ap.by_ref = c->by_ref; | |
40a777e8 | 577 | cond_predicate = add_condition (info, params_summary, |
b679b55b | 578 | operand_map[c->operand_num], |
4307a485 FX |
579 | c->type, &ap, c->code, |
580 | c->val, c->param_ops); | |
b679b55b JH |
581 | } |
582 | } | |
583 | /* Fixed conditions remains same, construct single | |
584 | condition predicate. */ | |
585 | else | |
2d01bef2 | 586 | cond_predicate = ipa_predicate::predicate_testing_cond (cond); |
b679b55b JH |
587 | clause_predicate = clause_predicate.or_with (info->conds, |
588 | cond_predicate); | |
589 | } | |
590 | out &= clause_predicate; | |
591 | } | |
592 | out &= toplev_predicate; | |
593 | return out; | |
594 | } | |
595 | ||
596 | ||
597 | /* Read predicate from IB. */ | |
598 | ||
599 | void | |
2d01bef2 | 600 | ipa_predicate::stream_in (class lto_input_block *ib) |
b679b55b JH |
601 | { |
602 | clause_t clause; | |
603 | int k = 0; | |
604 | ||
605 | do | |
606 | { | |
607 | gcc_assert (k <= max_clauses); | |
608 | clause = m_clause[k++] = streamer_read_uhwi (ib); | |
609 | } | |
610 | while (clause); | |
611 | ||
612 | /* Zero-initialize the remaining clauses in OUT. */ | |
613 | while (k <= max_clauses) | |
614 | m_clause[k++] = 0; | |
615 | } | |
616 | ||
617 | ||
618 | /* Write predicate P to OB. */ | |
619 | ||
620 | void | |
2d01bef2 | 621 | ipa_predicate::stream_out (struct output_block *ob) |
b679b55b JH |
622 | { |
623 | int j; | |
624 | for (j = 0; m_clause[j]; j++) | |
625 | { | |
626 | gcc_assert (j < max_clauses); | |
627 | streamer_write_uhwi (ob, m_clause[j]); | |
628 | } | |
629 | streamer_write_uhwi (ob, 0); | |
630 | } | |
631 | ||
632 | ||
4307a485 FX |
633 | /* Add condition to condition list SUMMARY. OPERAND_NUM, TYPE, CODE, VAL and |
634 | PARAM_OPS correspond to fields of condition structure. AGGPOS describes | |
635 | whether the used operand is loaded from an aggregate and where in the | |
636 | aggregate it is. It can be NULL, which means this not a load from an | |
637 | aggregate. */ | |
b679b55b | 638 | |
2d01bef2 | 639 | ipa_predicate |
40a777e8 JH |
640 | add_condition (class ipa_fn_summary *summary, |
641 | class ipa_node_params *params_summary, | |
642 | int operand_num, | |
4307a485 FX |
643 | tree type, struct agg_position_info *aggpos, |
644 | enum tree_code code, tree val, expr_eval_ops param_ops) | |
b679b55b | 645 | { |
4307a485 | 646 | int i, j; |
b679b55b JH |
647 | struct condition *c; |
648 | struct condition new_cond; | |
649 | HOST_WIDE_INT offset; | |
650 | bool agg_contents, by_ref; | |
4307a485 | 651 | expr_eval_op *op; |
b679b55b | 652 | |
40a777e8 JH |
653 | if (params_summary) |
654 | ipa_set_param_used_by_ipa_predicates (params_summary, operand_num, true); | |
655 | ||
b679b55b JH |
656 | if (aggpos) |
657 | { | |
658 | offset = aggpos->offset; | |
659 | agg_contents = aggpos->agg_contents; | |
660 | by_ref = aggpos->by_ref; | |
661 | } | |
662 | else | |
663 | { | |
664 | offset = 0; | |
665 | agg_contents = false; | |
666 | by_ref = false; | |
667 | } | |
668 | ||
669 | gcc_checking_assert (operand_num >= 0); | |
670 | for (i = 0; vec_safe_iterate (summary->conds, i, &c); i++) | |
671 | { | |
672 | if (c->operand_num == operand_num | |
b679b55b | 673 | && c->code == code |
4307a485 FX |
674 | && types_compatible_p (c->type, type) |
675 | && vrp_operand_equal_p (c->val, val) | |
b679b55b | 676 | && c->agg_contents == agg_contents |
4307a485 | 677 | && expr_eval_ops_equal_p (c->param_ops, param_ops) |
b679b55b | 678 | && (!agg_contents || (c->offset == offset && c->by_ref == by_ref))) |
2d01bef2 | 679 | return ipa_predicate::predicate_testing_cond (i); |
b679b55b JH |
680 | } |
681 | /* Too many conditions. Give up and return constant true. */ | |
2d01bef2 | 682 | if (i == ipa_predicate::num_conditions - ipa_predicate::first_dynamic_condition) |
b679b55b JH |
683 | return true; |
684 | ||
685 | new_cond.operand_num = operand_num; | |
686 | new_cond.code = code; | |
4307a485 FX |
687 | new_cond.type = unshare_expr_without_location (type); |
688 | new_cond.val = val ? unshare_expr_without_location (val) : val; | |
b679b55b JH |
689 | new_cond.agg_contents = agg_contents; |
690 | new_cond.by_ref = by_ref; | |
691 | new_cond.offset = offset; | |
4307a485 FX |
692 | new_cond.param_ops = vec_safe_copy (param_ops); |
693 | ||
694 | for (j = 0; vec_safe_iterate (new_cond.param_ops, j, &op); j++) | |
695 | { | |
696 | if (op->val[0]) | |
697 | op->val[0] = unshare_expr_without_location (op->val[0]); | |
698 | if (op->val[1]) | |
699 | op->val[1] = unshare_expr_without_location (op->val[1]); | |
700 | } | |
701 | ||
b679b55b JH |
702 | vec_safe_push (summary->conds, new_cond); |
703 | ||
2d01bef2 | 704 | return ipa_predicate::predicate_testing_cond (i); |
b679b55b | 705 | } |