1*38fd1498Szrj /* IPA predicates.
2*38fd1498Szrj Copyright (C) 2003-2018 Free Software Foundation, Inc.
3*38fd1498Szrj Contributed by Jan Hubicka
4*38fd1498Szrj
5*38fd1498Szrj This file is part of GCC.
6*38fd1498Szrj
7*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
8*38fd1498Szrj the terms of the GNU General Public License as published by the Free
9*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
10*38fd1498Szrj version.
11*38fd1498Szrj
12*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15*38fd1498Szrj for more details.
16*38fd1498Szrj
17*38fd1498Szrj You should have received a copy of the GNU General Public License
18*38fd1498Szrj along with GCC; see the file COPYING3. If not see
19*38fd1498Szrj <http://www.gnu.org/licenses/>. */
20*38fd1498Szrj
21*38fd1498Szrj #include "config.h"
22*38fd1498Szrj #include "system.h"
23*38fd1498Szrj #include "coretypes.h"
24*38fd1498Szrj #include "backend.h"
25*38fd1498Szrj #include "tree.h"
26*38fd1498Szrj #include "cgraph.h"
27*38fd1498Szrj #include "tree-vrp.h"
28*38fd1498Szrj #include "symbol-summary.h"
29*38fd1498Szrj #include "alloc-pool.h"
30*38fd1498Szrj #include "ipa-prop.h"
31*38fd1498Szrj #include "ipa-fnsummary.h"
32*38fd1498Szrj #include "real.h"
33*38fd1498Szrj #include "fold-const.h"
34*38fd1498Szrj #include "tree-pretty-print.h"
35*38fd1498Szrj #include "gimple.h"
36*38fd1498Szrj #include "data-streamer.h"
37*38fd1498Szrj
38*38fd1498Szrj
39*38fd1498Szrj /* Add clause CLAUSE into the predicate P.
40*38fd1498Szrj When CONDITIONS is NULL do not perform checking whether NEW_CLAUSE
41*38fd1498Szrj is obviously true. This is useful only when NEW_CLAUSE is known to be
42*38fd1498Szrj sane. */
43*38fd1498Szrj
44*38fd1498Szrj void
add_clause(conditions conditions,clause_t new_clause)45*38fd1498Szrj predicate::add_clause (conditions conditions, clause_t new_clause)
46*38fd1498Szrj {
47*38fd1498Szrj int i;
48*38fd1498Szrj int i2;
49*38fd1498Szrj int insert_here = -1;
50*38fd1498Szrj int c1, c2;
51*38fd1498Szrj
52*38fd1498Szrj /* True clause. */
53*38fd1498Szrj if (!new_clause)
54*38fd1498Szrj return;
55*38fd1498Szrj
56*38fd1498Szrj /* False clause makes the whole predicate false. Kill the other variants. */
57*38fd1498Szrj if (new_clause == (1 << predicate::false_condition))
58*38fd1498Szrj {
59*38fd1498Szrj *this = false;
60*38fd1498Szrj return;
61*38fd1498Szrj }
62*38fd1498Szrj if (*this == false)
63*38fd1498Szrj return;
64*38fd1498Szrj
65*38fd1498Szrj /* No one should be silly enough to add false into nontrivial clauses. */
66*38fd1498Szrj gcc_checking_assert (!(new_clause & (1 << predicate::false_condition)));
67*38fd1498Szrj
68*38fd1498Szrj /* Look where to insert the new_clause. At the same time prune out
69*38fd1498Szrj new_clauses of P that are implied by the new new_clause and thus
70*38fd1498Szrj redundant. */
71*38fd1498Szrj for (i = 0, i2 = 0; i <= max_clauses; i++)
72*38fd1498Szrj {
73*38fd1498Szrj m_clause[i2] = m_clause[i];
74*38fd1498Szrj
75*38fd1498Szrj if (!m_clause[i])
76*38fd1498Szrj break;
77*38fd1498Szrj
78*38fd1498Szrj /* If m_clause[i] implies new_clause, there is nothing to add. */
79*38fd1498Szrj if ((m_clause[i] & new_clause) == m_clause[i])
80*38fd1498Szrj {
81*38fd1498Szrj /* We had nothing to add, none of clauses should've become
82*38fd1498Szrj redundant. */
83*38fd1498Szrj gcc_checking_assert (i == i2);
84*38fd1498Szrj return;
85*38fd1498Szrj }
86*38fd1498Szrj
87*38fd1498Szrj if (m_clause[i] < new_clause && insert_here < 0)
88*38fd1498Szrj insert_here = i2;
89*38fd1498Szrj
90*38fd1498Szrj /* If new_clause implies clause[i], then clause[i] becomes redundant.
91*38fd1498Szrj Otherwise the clause[i] has to stay. */
92*38fd1498Szrj if ((m_clause[i] & new_clause) != new_clause)
93*38fd1498Szrj i2++;
94*38fd1498Szrj }
95*38fd1498Szrj
96*38fd1498Szrj /* Look for clauses that are obviously true. I.e.
97*38fd1498Szrj op0 == 5 || op0 != 5. */
98*38fd1498Szrj if (conditions)
99*38fd1498Szrj for (c1 = predicate::first_dynamic_condition;
100*38fd1498Szrj c1 < num_conditions; c1++)
101*38fd1498Szrj {
102*38fd1498Szrj condition *cc1;
103*38fd1498Szrj if (!(new_clause & (1 << c1)))
104*38fd1498Szrj continue;
105*38fd1498Szrj cc1 = &(*conditions)[c1 - predicate::first_dynamic_condition];
106*38fd1498Szrj /* We have no way to represent !changed and !is_not_constant
107*38fd1498Szrj and thus there is no point for looking for them. */
108*38fd1498Szrj if (cc1->code == changed || cc1->code == is_not_constant)
109*38fd1498Szrj continue;
110*38fd1498Szrj for (c2 = c1 + 1; c2 < num_conditions; c2++)
111*38fd1498Szrj if (new_clause & (1 << c2))
112*38fd1498Szrj {
113*38fd1498Szrj condition *cc1 =
114*38fd1498Szrj &(*conditions)[c1 - predicate::first_dynamic_condition];
115*38fd1498Szrj condition *cc2 =
116*38fd1498Szrj &(*conditions)[c2 - predicate::first_dynamic_condition];
117*38fd1498Szrj if (cc1->operand_num == cc2->operand_num
118*38fd1498Szrj && cc1->val == cc2->val
119*38fd1498Szrj && cc2->code != is_not_constant
120*38fd1498Szrj && cc2->code != predicate::changed
121*38fd1498Szrj && cc1->code == invert_tree_comparison (cc2->code,
122*38fd1498Szrj HONOR_NANS (cc1->val)))
123*38fd1498Szrj return;
124*38fd1498Szrj }
125*38fd1498Szrj }
126*38fd1498Szrj
127*38fd1498Szrj
128*38fd1498Szrj /* We run out of variants. Be conservative in positive direction. */
129*38fd1498Szrj if (i2 == max_clauses)
130*38fd1498Szrj return;
131*38fd1498Szrj /* Keep clauses in decreasing order. This makes equivalence testing easy. */
132*38fd1498Szrj m_clause[i2 + 1] = 0;
133*38fd1498Szrj if (insert_here >= 0)
134*38fd1498Szrj for (; i2 > insert_here; i2--)
135*38fd1498Szrj m_clause[i2] = m_clause[i2 - 1];
136*38fd1498Szrj else
137*38fd1498Szrj insert_here = i2;
138*38fd1498Szrj m_clause[insert_here] = new_clause;
139*38fd1498Szrj }
140*38fd1498Szrj
141*38fd1498Szrj
142*38fd1498Szrj /* Do THIS &= P. */
143*38fd1498Szrj
144*38fd1498Szrj predicate &
145*38fd1498Szrj predicate::operator &= (const predicate &p)
146*38fd1498Szrj {
147*38fd1498Szrj /* Avoid busy work. */
148*38fd1498Szrj if (p == false || *this == true)
149*38fd1498Szrj {
150*38fd1498Szrj *this = p;
151*38fd1498Szrj return *this;
152*38fd1498Szrj }
153*38fd1498Szrj if (*this == false || p == true || this == &p)
154*38fd1498Szrj return *this;
155*38fd1498Szrj
156*38fd1498Szrj int i;
157*38fd1498Szrj
158*38fd1498Szrj /* See how far predicates match. */
159*38fd1498Szrj for (i = 0; m_clause[i] && m_clause[i] == p.m_clause[i]; i++)
160*38fd1498Szrj {
161*38fd1498Szrj gcc_checking_assert (i < max_clauses);
162*38fd1498Szrj }
163*38fd1498Szrj
164*38fd1498Szrj /* Combine the predicates rest. */
165*38fd1498Szrj for (; p.m_clause[i]; i++)
166*38fd1498Szrj {
167*38fd1498Szrj gcc_checking_assert (i < max_clauses);
168*38fd1498Szrj add_clause (NULL, p.m_clause[i]);
169*38fd1498Szrj }
170*38fd1498Szrj return *this;
171*38fd1498Szrj }
172*38fd1498Szrj
173*38fd1498Szrj
174*38fd1498Szrj
175*38fd1498Szrj /* Return THIS | P2. */
176*38fd1498Szrj
177*38fd1498Szrj predicate
or_with(conditions conditions,const predicate & p)178*38fd1498Szrj predicate::or_with (conditions conditions,
179*38fd1498Szrj const predicate &p) const
180*38fd1498Szrj {
181*38fd1498Szrj /* Avoid busy work. */
182*38fd1498Szrj if (p == false || *this == true || *this == p)
183*38fd1498Szrj return *this;
184*38fd1498Szrj if (*this == false || p == true)
185*38fd1498Szrj return p;
186*38fd1498Szrj
187*38fd1498Szrj /* OK, combine the predicates. */
188*38fd1498Szrj predicate out = true;
189*38fd1498Szrj
190*38fd1498Szrj for (int i = 0; m_clause[i]; i++)
191*38fd1498Szrj for (int j = 0; p.m_clause[j]; j++)
192*38fd1498Szrj {
193*38fd1498Szrj gcc_checking_assert (i < max_clauses && j < max_clauses);
194*38fd1498Szrj out.add_clause (conditions, m_clause[i] | p.m_clause[j]);
195*38fd1498Szrj }
196*38fd1498Szrj return out;
197*38fd1498Szrj }
198*38fd1498Szrj
199*38fd1498Szrj
200*38fd1498Szrj /* Having partial truth assignment in POSSIBLE_TRUTHS, return false
201*38fd1498Szrj if predicate P is known to be false. */
202*38fd1498Szrj
203*38fd1498Szrj bool
evaluate(clause_t possible_truths)204*38fd1498Szrj predicate::evaluate (clause_t possible_truths) const
205*38fd1498Szrj {
206*38fd1498Szrj int i;
207*38fd1498Szrj
208*38fd1498Szrj /* True remains true. */
209*38fd1498Szrj if (*this == true)
210*38fd1498Szrj return true;
211*38fd1498Szrj
212*38fd1498Szrj gcc_assert (!(possible_truths & (1 << predicate::false_condition)));
213*38fd1498Szrj
214*38fd1498Szrj /* See if we can find clause we can disprove. */
215*38fd1498Szrj for (i = 0; m_clause[i]; i++)
216*38fd1498Szrj {
217*38fd1498Szrj gcc_checking_assert (i < max_clauses);
218*38fd1498Szrj if (!(m_clause[i] & possible_truths))
219*38fd1498Szrj return false;
220*38fd1498Szrj }
221*38fd1498Szrj return true;
222*38fd1498Szrj }
223*38fd1498Szrj
224*38fd1498Szrj /* Return the probability in range 0...REG_BR_PROB_BASE that the predicated
225*38fd1498Szrj instruction will be recomputed per invocation of the inlined call. */
226*38fd1498Szrj
227*38fd1498Szrj int
probability(conditions conds,clause_t possible_truths,vec<inline_param_summary> inline_param_summary)228*38fd1498Szrj predicate::probability (conditions conds,
229*38fd1498Szrj clause_t possible_truths,
230*38fd1498Szrj vec<inline_param_summary> inline_param_summary) const
231*38fd1498Szrj {
232*38fd1498Szrj int i;
233*38fd1498Szrj int combined_prob = REG_BR_PROB_BASE;
234*38fd1498Szrj
235*38fd1498Szrj /* True remains true. */
236*38fd1498Szrj if (*this == true)
237*38fd1498Szrj return REG_BR_PROB_BASE;
238*38fd1498Szrj
239*38fd1498Szrj if (*this == false)
240*38fd1498Szrj return 0;
241*38fd1498Szrj
242*38fd1498Szrj gcc_assert (!(possible_truths & (1 << predicate::false_condition)));
243*38fd1498Szrj
244*38fd1498Szrj /* See if we can find clause we can disprove. */
245*38fd1498Szrj for (i = 0; m_clause[i]; i++)
246*38fd1498Szrj {
247*38fd1498Szrj gcc_checking_assert (i < max_clauses);
248*38fd1498Szrj if (!(m_clause[i] & possible_truths))
249*38fd1498Szrj return 0;
250*38fd1498Szrj else
251*38fd1498Szrj {
252*38fd1498Szrj int this_prob = 0;
253*38fd1498Szrj int i2;
254*38fd1498Szrj if (!inline_param_summary.exists ())
255*38fd1498Szrj return REG_BR_PROB_BASE;
256*38fd1498Szrj for (i2 = 0; i2 < num_conditions; i2++)
257*38fd1498Szrj if ((m_clause[i] & possible_truths) & (1 << i2))
258*38fd1498Szrj {
259*38fd1498Szrj if (i2 >= predicate::first_dynamic_condition)
260*38fd1498Szrj {
261*38fd1498Szrj condition *c =
262*38fd1498Szrj &(*conds)[i2 - predicate::first_dynamic_condition];
263*38fd1498Szrj if (c->code == predicate::changed
264*38fd1498Szrj && (c->operand_num <
265*38fd1498Szrj (int) inline_param_summary.length ()))
266*38fd1498Szrj {
267*38fd1498Szrj int iprob =
268*38fd1498Szrj inline_param_summary[c->operand_num].change_prob;
269*38fd1498Szrj this_prob = MAX (this_prob, iprob);
270*38fd1498Szrj }
271*38fd1498Szrj else
272*38fd1498Szrj this_prob = REG_BR_PROB_BASE;
273*38fd1498Szrj }
274*38fd1498Szrj else
275*38fd1498Szrj this_prob = REG_BR_PROB_BASE;
276*38fd1498Szrj }
277*38fd1498Szrj combined_prob = MIN (this_prob, combined_prob);
278*38fd1498Szrj if (!combined_prob)
279*38fd1498Szrj return 0;
280*38fd1498Szrj }
281*38fd1498Szrj }
282*38fd1498Szrj return combined_prob;
283*38fd1498Szrj }
284*38fd1498Szrj
285*38fd1498Szrj
286*38fd1498Szrj /* Dump conditional COND. */
287*38fd1498Szrj
288*38fd1498Szrj void
dump_condition(FILE * f,conditions conditions,int cond)289*38fd1498Szrj dump_condition (FILE *f, conditions conditions, int cond)
290*38fd1498Szrj {
291*38fd1498Szrj condition *c;
292*38fd1498Szrj if (cond == predicate::false_condition)
293*38fd1498Szrj fprintf (f, "false");
294*38fd1498Szrj else if (cond == predicate::not_inlined_condition)
295*38fd1498Szrj fprintf (f, "not inlined");
296*38fd1498Szrj else
297*38fd1498Szrj {
298*38fd1498Szrj c = &(*conditions)[cond - predicate::first_dynamic_condition];
299*38fd1498Szrj fprintf (f, "op%i", c->operand_num);
300*38fd1498Szrj if (c->agg_contents)
301*38fd1498Szrj fprintf (f, "[%soffset: " HOST_WIDE_INT_PRINT_DEC "]",
302*38fd1498Szrj c->by_ref ? "ref " : "", c->offset);
303*38fd1498Szrj if (c->code == predicate::is_not_constant)
304*38fd1498Szrj {
305*38fd1498Szrj fprintf (f, " not constant");
306*38fd1498Szrj return;
307*38fd1498Szrj }
308*38fd1498Szrj if (c->code == predicate::changed)
309*38fd1498Szrj {
310*38fd1498Szrj fprintf (f, " changed");
311*38fd1498Szrj return;
312*38fd1498Szrj }
313*38fd1498Szrj fprintf (f, " %s ", op_symbol_code (c->code));
314*38fd1498Szrj print_generic_expr (f, c->val);
315*38fd1498Szrj }
316*38fd1498Szrj }
317*38fd1498Szrj
318*38fd1498Szrj
319*38fd1498Szrj /* Dump clause CLAUSE. */
320*38fd1498Szrj
321*38fd1498Szrj static void
dump_clause(FILE * f,conditions conds,clause_t clause)322*38fd1498Szrj dump_clause (FILE *f, conditions conds, clause_t clause)
323*38fd1498Szrj {
324*38fd1498Szrj int i;
325*38fd1498Szrj bool found = false;
326*38fd1498Szrj fprintf (f, "(");
327*38fd1498Szrj if (!clause)
328*38fd1498Szrj fprintf (f, "true");
329*38fd1498Szrj for (i = 0; i < predicate::num_conditions; i++)
330*38fd1498Szrj if (clause & (1 << i))
331*38fd1498Szrj {
332*38fd1498Szrj if (found)
333*38fd1498Szrj fprintf (f, " || ");
334*38fd1498Szrj found = true;
335*38fd1498Szrj dump_condition (f, conds, i);
336*38fd1498Szrj }
337*38fd1498Szrj fprintf (f, ")");
338*38fd1498Szrj }
339*38fd1498Szrj
340*38fd1498Szrj
341*38fd1498Szrj /* Dump THIS to F. CONDS a vector of conditions used when evauating
342*38fd1498Szrj predicats. When NL is true new line is output at the end of dump. */
343*38fd1498Szrj
344*38fd1498Szrj void
dump(FILE * f,conditions conds,bool nl)345*38fd1498Szrj predicate::dump (FILE *f, conditions conds, bool nl) const
346*38fd1498Szrj {
347*38fd1498Szrj int i;
348*38fd1498Szrj if (*this == true)
349*38fd1498Szrj dump_clause (f, conds, 0);
350*38fd1498Szrj else
351*38fd1498Szrj for (i = 0; m_clause[i]; i++)
352*38fd1498Szrj {
353*38fd1498Szrj if (i)
354*38fd1498Szrj fprintf (f, " && ");
355*38fd1498Szrj dump_clause (f, conds, m_clause[i]);
356*38fd1498Szrj }
357*38fd1498Szrj if (nl)
358*38fd1498Szrj fprintf (f, "\n");
359*38fd1498Szrj }
360*38fd1498Szrj
361*38fd1498Szrj
362*38fd1498Szrj void
debug(conditions conds)363*38fd1498Szrj predicate::debug (conditions conds) const
364*38fd1498Szrj {
365*38fd1498Szrj dump (stderr, conds);
366*38fd1498Szrj }
367*38fd1498Szrj
368*38fd1498Szrj
369*38fd1498Szrj /* Remap predicate THIS of former function to be predicate of duplicated function.
370*38fd1498Szrj POSSIBLE_TRUTHS is clause of possible truths in the duplicated node,
371*38fd1498Szrj INFO is inline summary of the duplicated node. */
372*38fd1498Szrj
373*38fd1498Szrj predicate
remap_after_duplication(clause_t possible_truths)374*38fd1498Szrj predicate::remap_after_duplication (clause_t possible_truths)
375*38fd1498Szrj {
376*38fd1498Szrj int j;
377*38fd1498Szrj predicate out = true;
378*38fd1498Szrj for (j = 0; m_clause[j]; j++)
379*38fd1498Szrj if (!(possible_truths & m_clause[j]))
380*38fd1498Szrj return false;
381*38fd1498Szrj else
382*38fd1498Szrj out.add_clause (NULL, possible_truths & m_clause[j]);
383*38fd1498Szrj return out;
384*38fd1498Szrj }
385*38fd1498Szrj
386*38fd1498Szrj
387*38fd1498Szrj /* Translate all conditions from callee representation into caller
388*38fd1498Szrj representation and symbolically evaluate predicate THIS into new predicate.
389*38fd1498Szrj
390*38fd1498Szrj INFO is ipa_fn_summary of function we are adding predicate into, CALLEE_INFO
391*38fd1498Szrj is summary of function predicate P is from. OPERAND_MAP is array giving
392*38fd1498Szrj callee formal IDs the caller formal IDs. POSSSIBLE_TRUTHS is clausule of all
393*38fd1498Szrj callee conditions that may be true in caller context. TOPLEV_PREDICATE is
394*38fd1498Szrj predicate under which callee is executed. OFFSET_MAP is an array of of
395*38fd1498Szrj offsets that need to be added to conditions, negative offset means that
396*38fd1498Szrj conditions relying on values passed by reference have to be discarded
397*38fd1498Szrj because they might not be preserved (and should be considered offset zero
398*38fd1498Szrj for other purposes). */
399*38fd1498Szrj
400*38fd1498Szrj predicate
remap_after_inlining(struct ipa_fn_summary * info,struct ipa_fn_summary * callee_info,vec<int> operand_map,vec<int> offset_map,clause_t possible_truths,const predicate & toplev_predicate)401*38fd1498Szrj predicate::remap_after_inlining (struct ipa_fn_summary *info,
402*38fd1498Szrj struct ipa_fn_summary *callee_info,
403*38fd1498Szrj vec<int> operand_map,
404*38fd1498Szrj vec<int> offset_map,
405*38fd1498Szrj clause_t possible_truths,
406*38fd1498Szrj const predicate &toplev_predicate)
407*38fd1498Szrj {
408*38fd1498Szrj int i;
409*38fd1498Szrj predicate out = true;
410*38fd1498Szrj
411*38fd1498Szrj /* True predicate is easy. */
412*38fd1498Szrj if (*this == true)
413*38fd1498Szrj return toplev_predicate;
414*38fd1498Szrj for (i = 0; m_clause[i]; i++)
415*38fd1498Szrj {
416*38fd1498Szrj clause_t clause = m_clause[i];
417*38fd1498Szrj int cond;
418*38fd1498Szrj predicate clause_predicate = false;
419*38fd1498Szrj
420*38fd1498Szrj gcc_assert (i < max_clauses);
421*38fd1498Szrj
422*38fd1498Szrj for (cond = 0; cond < num_conditions; cond++)
423*38fd1498Szrj /* Do we have condition we can't disprove? */
424*38fd1498Szrj if (clause & possible_truths & (1 << cond))
425*38fd1498Szrj {
426*38fd1498Szrj predicate cond_predicate;
427*38fd1498Szrj /* Work out if the condition can translate to predicate in the
428*38fd1498Szrj inlined function. */
429*38fd1498Szrj if (cond >= predicate::first_dynamic_condition)
430*38fd1498Szrj {
431*38fd1498Szrj struct condition *c;
432*38fd1498Szrj
433*38fd1498Szrj c = &(*callee_info->conds)[cond
434*38fd1498Szrj -
435*38fd1498Szrj predicate::first_dynamic_condition];
436*38fd1498Szrj /* See if we can remap condition operand to caller's operand.
437*38fd1498Szrj Otherwise give up. */
438*38fd1498Szrj if (!operand_map.exists ()
439*38fd1498Szrj || (int) operand_map.length () <= c->operand_num
440*38fd1498Szrj || operand_map[c->operand_num] == -1
441*38fd1498Szrj /* TODO: For non-aggregate conditions, adding an offset is
442*38fd1498Szrj basically an arithmetic jump function processing which
443*38fd1498Szrj we should support in future. */
444*38fd1498Szrj || ((!c->agg_contents || !c->by_ref)
445*38fd1498Szrj && offset_map[c->operand_num] > 0)
446*38fd1498Szrj || (c->agg_contents && c->by_ref
447*38fd1498Szrj && offset_map[c->operand_num] < 0))
448*38fd1498Szrj cond_predicate = true;
449*38fd1498Szrj else
450*38fd1498Szrj {
451*38fd1498Szrj struct agg_position_info ap;
452*38fd1498Szrj HOST_WIDE_INT offset_delta = offset_map[c->operand_num];
453*38fd1498Szrj if (offset_delta < 0)
454*38fd1498Szrj {
455*38fd1498Szrj gcc_checking_assert (!c->agg_contents || !c->by_ref);
456*38fd1498Szrj offset_delta = 0;
457*38fd1498Szrj }
458*38fd1498Szrj gcc_assert (!c->agg_contents
459*38fd1498Szrj || c->by_ref || offset_delta == 0);
460*38fd1498Szrj ap.offset = c->offset + offset_delta;
461*38fd1498Szrj ap.agg_contents = c->agg_contents;
462*38fd1498Szrj ap.by_ref = c->by_ref;
463*38fd1498Szrj cond_predicate = add_condition (info,
464*38fd1498Szrj operand_map[c->operand_num],
465*38fd1498Szrj c->size, &ap, c->code,
466*38fd1498Szrj c->val);
467*38fd1498Szrj }
468*38fd1498Szrj }
469*38fd1498Szrj /* Fixed conditions remains same, construct single
470*38fd1498Szrj condition predicate. */
471*38fd1498Szrj else
472*38fd1498Szrj cond_predicate = predicate::predicate_testing_cond (cond);
473*38fd1498Szrj clause_predicate = clause_predicate.or_with (info->conds,
474*38fd1498Szrj cond_predicate);
475*38fd1498Szrj }
476*38fd1498Szrj out &= clause_predicate;
477*38fd1498Szrj }
478*38fd1498Szrj out &= toplev_predicate;
479*38fd1498Szrj return out;
480*38fd1498Szrj }
481*38fd1498Szrj
482*38fd1498Szrj
483*38fd1498Szrj /* Read predicate from IB. */
484*38fd1498Szrj
485*38fd1498Szrj void
stream_in(struct lto_input_block * ib)486*38fd1498Szrj predicate::stream_in (struct lto_input_block *ib)
487*38fd1498Szrj {
488*38fd1498Szrj clause_t clause;
489*38fd1498Szrj int k = 0;
490*38fd1498Szrj
491*38fd1498Szrj do
492*38fd1498Szrj {
493*38fd1498Szrj gcc_assert (k <= max_clauses);
494*38fd1498Szrj clause = m_clause[k++] = streamer_read_uhwi (ib);
495*38fd1498Szrj }
496*38fd1498Szrj while (clause);
497*38fd1498Szrj
498*38fd1498Szrj /* Zero-initialize the remaining clauses in OUT. */
499*38fd1498Szrj while (k <= max_clauses)
500*38fd1498Szrj m_clause[k++] = 0;
501*38fd1498Szrj }
502*38fd1498Szrj
503*38fd1498Szrj
504*38fd1498Szrj /* Write predicate P to OB. */
505*38fd1498Szrj
506*38fd1498Szrj void
stream_out(struct output_block * ob)507*38fd1498Szrj predicate::stream_out (struct output_block *ob)
508*38fd1498Szrj {
509*38fd1498Szrj int j;
510*38fd1498Szrj for (j = 0; m_clause[j]; j++)
511*38fd1498Szrj {
512*38fd1498Szrj gcc_assert (j < max_clauses);
513*38fd1498Szrj streamer_write_uhwi (ob, m_clause[j]);
514*38fd1498Szrj }
515*38fd1498Szrj streamer_write_uhwi (ob, 0);
516*38fd1498Szrj }
517*38fd1498Szrj
518*38fd1498Szrj
519*38fd1498Szrj /* Add condition to condition list SUMMARY. OPERAND_NUM, SIZE, CODE and VAL
520*38fd1498Szrj correspond to fields of condition structure. AGGPOS describes whether the
521*38fd1498Szrj used operand is loaded from an aggregate and where in the aggregate it is.
522*38fd1498Szrj It can be NULL, which means this not a load from an aggregate. */
523*38fd1498Szrj
524*38fd1498Szrj predicate
add_condition(struct ipa_fn_summary * summary,int operand_num,HOST_WIDE_INT size,struct agg_position_info * aggpos,enum tree_code code,tree val)525*38fd1498Szrj add_condition (struct ipa_fn_summary *summary, int operand_num,
526*38fd1498Szrj HOST_WIDE_INT size, struct agg_position_info *aggpos,
527*38fd1498Szrj enum tree_code code, tree val)
528*38fd1498Szrj {
529*38fd1498Szrj int i;
530*38fd1498Szrj struct condition *c;
531*38fd1498Szrj struct condition new_cond;
532*38fd1498Szrj HOST_WIDE_INT offset;
533*38fd1498Szrj bool agg_contents, by_ref;
534*38fd1498Szrj
535*38fd1498Szrj if (aggpos)
536*38fd1498Szrj {
537*38fd1498Szrj offset = aggpos->offset;
538*38fd1498Szrj agg_contents = aggpos->agg_contents;
539*38fd1498Szrj by_ref = aggpos->by_ref;
540*38fd1498Szrj }
541*38fd1498Szrj else
542*38fd1498Szrj {
543*38fd1498Szrj offset = 0;
544*38fd1498Szrj agg_contents = false;
545*38fd1498Szrj by_ref = false;
546*38fd1498Szrj }
547*38fd1498Szrj
548*38fd1498Szrj gcc_checking_assert (operand_num >= 0);
549*38fd1498Szrj for (i = 0; vec_safe_iterate (summary->conds, i, &c); i++)
550*38fd1498Szrj {
551*38fd1498Szrj if (c->operand_num == operand_num
552*38fd1498Szrj && c->size == size
553*38fd1498Szrj && c->code == code
554*38fd1498Szrj && c->val == val
555*38fd1498Szrj && c->agg_contents == agg_contents
556*38fd1498Szrj && (!agg_contents || (c->offset == offset && c->by_ref == by_ref)))
557*38fd1498Szrj return predicate::predicate_testing_cond (i);
558*38fd1498Szrj }
559*38fd1498Szrj /* Too many conditions. Give up and return constant true. */
560*38fd1498Szrj if (i == predicate::num_conditions - predicate::first_dynamic_condition)
561*38fd1498Szrj return true;
562*38fd1498Szrj
563*38fd1498Szrj new_cond.operand_num = operand_num;
564*38fd1498Szrj new_cond.code = code;
565*38fd1498Szrj new_cond.val = val;
566*38fd1498Szrj new_cond.agg_contents = agg_contents;
567*38fd1498Szrj new_cond.by_ref = by_ref;
568*38fd1498Szrj new_cond.offset = offset;
569*38fd1498Szrj new_cond.size = size;
570*38fd1498Szrj vec_safe_push (summary->conds, new_cond);
571*38fd1498Szrj
572*38fd1498Szrj return predicate::predicate_testing_cond (i);
573*38fd1498Szrj }
574