Branch data Line data Source code
1 : : /* Header file for mixed range operator class.
2 : : Copyright (C) 2017-2024 Free Software Foundation, Inc.
3 : : Contributed by Andrew MacLeod <amacleod@redhat.com>
4 : : and Aldy Hernandez <aldyh@redhat.com>.
5 : :
6 : : This file is part of GCC.
7 : :
8 : : GCC is free software; you can redistribute it and/or modify it under
9 : : the terms of the GNU General Public License as published by the Free
10 : : Software Foundation; either version 3, or (at your option) any later
11 : : version.
12 : :
13 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : : for more details.
17 : :
18 : : You should have received a copy of the GNU General Public License
19 : : along with GCC; see the file COPYING3. If not see
20 : : <http://www.gnu.org/licenses/>. */
21 : :
22 : : #ifndef GCC_RANGE_OP_MIXED_H
23 : : #define GCC_RANGE_OP_MIXED_H
24 : :
25 : : void update_known_bitmask (irange &, tree_code, const irange &, const irange &);
26 : : bool minus_op1_op2_relation_effect (irange &lhs_range, tree type,
27 : : const irange &, const irange &,
28 : : relation_kind rel);
29 : :
30 : :
31 : : // Return TRUE if 0 is within [WMIN, WMAX].
32 : :
33 : : inline bool
34 : 15133366 : wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
35 : : {
36 : 15133366 : signop sign = TYPE_SIGN (type);
37 : 15133366 : return wi::le_p (wmin, 0, sign) && wi::ge_p (wmax, 0, sign);
38 : : }
39 : :
40 : : // Return TRUE if [WMIN, WMAX] is the singleton 0.
41 : :
42 : : inline bool
43 : 1424825 : wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
44 : : {
45 : 1424825 : unsigned prec = TYPE_PRECISION (type);
46 : 1739093 : return wmin == wmax && wi::eq_p (wmin, wi::zero (prec));
47 : : }
48 : :
49 : :
50 : : enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
51 : : bool_range_state get_bool_state (vrange &r, const vrange &lhs, tree val_type);
52 : :
53 : : // If the range of either op1 or op2 is undefined, set the result to
54 : : // varying and return TRUE. If the caller truly cares about a result,
55 : : // they should pass in a varying if it has an undefined that it wants
56 : : // treated as a varying.
57 : :
58 : : inline bool
59 : 222198521 : empty_range_varying (vrange &r, tree type,
60 : : const vrange &op1, const vrange & op2)
61 : : {
62 : 222138130 : if (op1.undefined_p () || op2.undefined_p ())
63 : : {
64 : 147438 : r.set_varying (type);
65 : 77488 : return true;
66 : : }
67 : : else
68 : : return false;
69 : : }
70 : :
71 : : // For relation opcodes, first try to see if the supplied relation
72 : : // forces a true or false result, and return that.
73 : : // Then check for undefined operands. If none of this applies,
74 : : // return false.
75 : :
76 : : inline bool
77 : 70984996 : relop_early_resolve (irange &r, tree type, const vrange &op1,
78 : : const vrange &op2, relation_trio trio,
79 : : relation_kind my_rel)
80 : : {
81 : 70984996 : relation_kind rel = trio.op1_op2 ();
82 : : // If known relation is a complete subset of this relation, always true.
83 : 70984996 : if (relation_union (rel, my_rel) == my_rel)
84 : : {
85 : 35008 : r = range_true (type);
86 : 35008 : return true;
87 : : }
88 : :
89 : : // If known relation has no subset of this relation, always false.
90 : 70949988 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
91 : : {
92 : 42288 : r = range_false (type);
93 : 42288 : return true;
94 : : }
95 : :
96 : : // If either operand is undefined, return VARYING.
97 : 70907700 : if (empty_range_varying (r, type, op1, op2))
98 : 69950 : return true;
99 : :
100 : : return false;
101 : : }
102 : :
103 : : // ----------------------------------------------------------------------
104 : : // Mixed Mode Operators.
105 : : // ----------------------------------------------------------------------
106 : :
107 : : class operator_equal : public range_operator
108 : : {
109 : : public:
110 : : using range_operator::fold_range;
111 : : using range_operator::op1_range;
112 : : using range_operator::op2_range;
113 : : using range_operator::op1_op2_relation;
114 : : bool fold_range (irange &r, tree type,
115 : : const irange &op1, const irange &op2,
116 : : relation_trio = TRIO_VARYING) const final override;
117 : : bool fold_range (irange &r, tree type,
118 : : const frange &op1, const frange &op2,
119 : : relation_trio = TRIO_VARYING) const final override;
120 : :
121 : : bool op1_range (irange &r, tree type,
122 : : const irange &lhs, const irange &val,
123 : : relation_trio = TRIO_VARYING) const final override;
124 : : bool op1_range (frange &r, tree type,
125 : : const irange &lhs, const frange &op2,
126 : : relation_trio = TRIO_VARYING) const final override;
127 : :
128 : : bool op2_range (irange &r, tree type,
129 : : const irange &lhs, const irange &val,
130 : : relation_trio = TRIO_VARYING) const final override;
131 : : bool op2_range (frange &r, tree type,
132 : : const irange &lhs, const frange &op1,
133 : : relation_trio rel = TRIO_VARYING) const final override;
134 : :
135 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
136 : : const irange &) const final override;
137 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
138 : : const frange &) const final override;
139 : : void update_bitmask (irange &r, const irange &lh,
140 : : const irange &rh) const final override;
141 : : // Check op1 and op2 for compatibility.
142 : 32196302 : bool operand_check_p (tree, tree t1, tree t2) const final override
143 : 32196302 : { return range_compatible_p (t1, t2); }
144 : : };
145 : :
146 : : class operator_not_equal : public range_operator
147 : : {
148 : : public:
149 : : using range_operator::fold_range;
150 : : using range_operator::op1_range;
151 : : using range_operator::op2_range;
152 : : using range_operator::op1_op2_relation;
153 : : bool fold_range (irange &r, tree type,
154 : : const irange &op1, const irange &op2,
155 : : relation_trio = TRIO_VARYING) const final override;
156 : : bool fold_range (irange &r, tree type,
157 : : const frange &op1, const frange &op2,
158 : : relation_trio rel = TRIO_VARYING) const final override;
159 : :
160 : : bool op1_range (irange &r, tree type,
161 : : const irange &lhs, const irange &op2,
162 : : relation_trio = TRIO_VARYING) const final override;
163 : : bool op1_range (frange &r, tree type,
164 : : const irange &lhs, const frange &op2,
165 : : relation_trio = TRIO_VARYING) const final override;
166 : :
167 : : bool op2_range (irange &r, tree type,
168 : : const irange &lhs, const irange &op1,
169 : : relation_trio = TRIO_VARYING) const final override;
170 : : bool op2_range (frange &r, tree type,
171 : : const irange &lhs, const frange &op1,
172 : : relation_trio = TRIO_VARYING) const final override;
173 : :
174 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
175 : : const irange &) const final override;
176 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
177 : : const frange &) const final override;
178 : : void update_bitmask (irange &r, const irange &lh,
179 : : const irange &rh) const final override;
180 : : // Check op1 and op2 for compatibility.
181 : 51028037 : bool operand_check_p (tree, tree t1, tree t2) const final override
182 : 51028037 : { return range_compatible_p (t1, t2); }
183 : : };
184 : :
185 : : class operator_lt : public range_operator
186 : : {
187 : : public:
188 : : using range_operator::fold_range;
189 : : using range_operator::op1_range;
190 : : using range_operator::op2_range;
191 : : using range_operator::op1_op2_relation;
192 : : bool fold_range (irange &r, tree type,
193 : : const irange &op1, const irange &op2,
194 : : relation_trio = TRIO_VARYING) const final override;
195 : : bool fold_range (irange &r, tree type,
196 : : const frange &op1, const frange &op2,
197 : : relation_trio = TRIO_VARYING) const final override;
198 : : bool op1_range (irange &r, tree type,
199 : : const irange &lhs, const irange &op2,
200 : : relation_trio = TRIO_VARYING) const final override;
201 : : bool op1_range (frange &r, tree type,
202 : : const irange &lhs, const frange &op2,
203 : : relation_trio = TRIO_VARYING) const final override;
204 : : bool op2_range (irange &r, tree type,
205 : : const irange &lhs, const irange &op1,
206 : : relation_trio = TRIO_VARYING) const final override;
207 : : bool op2_range (frange &r, tree type,
208 : : const irange &lhs, const frange &op1,
209 : : relation_trio = TRIO_VARYING) const final override;
210 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
211 : : const irange &) const final override;
212 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
213 : : const frange &) const final override;
214 : : void update_bitmask (irange &r, const irange &lh,
215 : : const irange &rh) const final override;
216 : : // Check op1 and op2 for compatibility.
217 : 11178023 : bool operand_check_p (tree, tree t1, tree t2) const final override
218 : 11178023 : { return range_compatible_p (t1, t2); }
219 : : };
220 : :
221 : : class operator_le : public range_operator
222 : : {
223 : : public:
224 : : using range_operator::fold_range;
225 : : using range_operator::op1_range;
226 : : using range_operator::op2_range;
227 : : using range_operator::op1_op2_relation;
228 : : bool fold_range (irange &r, tree type,
229 : : const irange &op1, const irange &op2,
230 : : relation_trio = TRIO_VARYING) const final override;
231 : : bool fold_range (irange &r, tree type,
232 : : const frange &op1, const frange &op2,
233 : : relation_trio rel = TRIO_VARYING) const final override;
234 : :
235 : : bool op1_range (irange &r, tree type,
236 : : const irange &lhs, const irange &op2,
237 : : relation_trio = TRIO_VARYING) const final override;
238 : : bool op1_range (frange &r, tree type,
239 : : const irange &lhs, const frange &op2,
240 : : relation_trio rel = TRIO_VARYING) const final override;
241 : :
242 : : bool op2_range (irange &r, tree type,
243 : : const irange &lhs, const irange &op1,
244 : : relation_trio = TRIO_VARYING) const final override;
245 : : bool op2_range (frange &r, tree type,
246 : : const irange &lhs, const frange &op1,
247 : : relation_trio rel = TRIO_VARYING) const final override;
248 : :
249 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
250 : : const irange &) const final override;
251 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
252 : : const frange &) const final override;
253 : : void update_bitmask (irange &r, const irange &lh,
254 : : const irange &rh) const final override;
255 : : // Check op1 and op2 for compatibility.
256 : 9356068 : bool operand_check_p (tree, tree t1, tree t2) const final override
257 : 9356068 : { return range_compatible_p (t1, t2); }
258 : : };
259 : :
260 : : class operator_gt : public range_operator
261 : : {
262 : : public:
263 : : using range_operator::fold_range;
264 : : using range_operator::op1_range;
265 : : using range_operator::op2_range;
266 : : using range_operator::op1_op2_relation;
267 : : bool fold_range (irange &r, tree type,
268 : : const irange &op1, const irange &op2,
269 : : relation_trio = TRIO_VARYING) const final override;
270 : : bool fold_range (irange &r, tree type,
271 : : const frange &op1, const frange &op2,
272 : : relation_trio = TRIO_VARYING) const final override;
273 : :
274 : : bool op1_range (irange &r, tree type,
275 : : const irange &lhs, const irange &op2,
276 : : relation_trio = TRIO_VARYING) const final override;
277 : : bool op1_range (frange &r, tree type,
278 : : const irange &lhs, const frange &op2,
279 : : relation_trio = TRIO_VARYING) const final override;
280 : :
281 : : bool op2_range (irange &r, tree type,
282 : : const irange &lhs, const irange &op1,
283 : : relation_trio = TRIO_VARYING) const final override;
284 : : bool op2_range (frange &r, tree type,
285 : : const irange &lhs, const frange &op1,
286 : : relation_trio = TRIO_VARYING) const final override;
287 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
288 : : const irange &) const final override;
289 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
290 : : const frange &) const final override;
291 : : void update_bitmask (irange &r, const irange &lh,
292 : : const irange &rh) const final override;
293 : : // Check op1 and op2 for compatibility.
294 : 19435742 : bool operand_check_p (tree, tree t1, tree t2) const final override
295 : 19435742 : { return range_compatible_p (t1, t2); }
296 : : };
297 : :
298 : : class operator_ge : public range_operator
299 : : {
300 : : public:
301 : : using range_operator::fold_range;
302 : : using range_operator::op1_range;
303 : : using range_operator::op2_range;
304 : : using range_operator::op1_op2_relation;
305 : : bool fold_range (irange &r, tree type,
306 : : const irange &op1, const irange &op2,
307 : : relation_trio = TRIO_VARYING) const final override;
308 : : bool fold_range (irange &r, tree type,
309 : : const frange &op1, const frange &op2,
310 : : relation_trio = TRIO_VARYING) const final override;
311 : :
312 : : bool op1_range (irange &r, tree type,
313 : : const irange &lhs, const irange &op2,
314 : : relation_trio = TRIO_VARYING) const final override;
315 : : bool op1_range (frange &r, tree type,
316 : : const irange &lhs, const frange &op2,
317 : : relation_trio = TRIO_VARYING) const final override;
318 : :
319 : : bool op2_range (irange &r, tree type,
320 : : const irange &lhs, const irange &op1,
321 : : relation_trio = TRIO_VARYING) const final override;
322 : : bool op2_range (frange &r, tree type,
323 : : const irange &lhs, const frange &op1,
324 : : relation_trio = TRIO_VARYING) const final override;
325 : :
326 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
327 : : const irange &) const final override;
328 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
329 : : const frange &) const final override;
330 : : void update_bitmask (irange &r, const irange &lh,
331 : : const irange &rh) const final override;
332 : : // Check op1 and op2 for compatibility.
333 : 6495570 : bool operand_check_p (tree, tree t1, tree t2) const final override
334 : 6495570 : { return range_compatible_p (t1, t2); }
335 : : };
336 : :
337 : : class operator_identity : public range_operator
338 : : {
339 : : public:
340 : : using range_operator::fold_range;
341 : : using range_operator::op1_range;
342 : : using range_operator::lhs_op1_relation;
343 : : bool fold_range (irange &r, tree type,
344 : : const irange &op1, const irange &op2,
345 : : relation_trio rel = TRIO_VARYING) const final override;
346 : : bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
347 : : const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
348 : : relation_trio = TRIO_VARYING) const final override;
349 : : bool op1_range (irange &r, tree type,
350 : : const irange &lhs, const irange &op2,
351 : : relation_trio rel = TRIO_VARYING) const final override;
352 : : bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
353 : : const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
354 : : relation_trio = TRIO_VARYING) const final override;
355 : : relation_kind lhs_op1_relation (const irange &lhs,
356 : : const irange &op1, const irange &op2,
357 : : relation_kind rel) const final override;
358 : : };
359 : :
360 : : class operator_cst : public range_operator
361 : : {
362 : : public:
363 : : using range_operator::fold_range;
364 : : bool fold_range (irange &r, tree type,
365 : : const irange &op1, const irange &op2,
366 : : relation_trio rel = TRIO_VARYING) const final override;
367 : : bool fold_range (frange &r, tree type,
368 : : const frange &op1, const frange &op2,
369 : : relation_trio = TRIO_VARYING) const final override;
370 : : };
371 : :
372 : :
373 : : class operator_cast: public range_operator
374 : : {
375 : : public:
376 : : using range_operator::fold_range;
377 : : using range_operator::op1_range;
378 : : using range_operator::lhs_op1_relation;
379 : : bool fold_range (irange &r, tree type,
380 : : const irange &op1, const irange &op2,
381 : : relation_trio rel = TRIO_VARYING) const final override;
382 : : bool op1_range (irange &r, tree type,
383 : : const irange &lhs, const irange &op2,
384 : : relation_trio rel = TRIO_VARYING) const final override;
385 : : relation_kind lhs_op1_relation (const irange &lhs,
386 : : const irange &op1, const irange &op2,
387 : : relation_kind) const final override;
388 : : void update_bitmask (irange &r, const irange &lh,
389 : : const irange &rh) const final override;
390 : : private:
391 : : bool truncating_cast_p (const irange &inner, const irange &outer) const;
392 : : bool inside_domain_p (const wide_int &min, const wide_int &max,
393 : : const irange &outer) const;
394 : : void fold_pair (irange &r, unsigned index, const irange &inner,
395 : : const irange &outer) const;
396 : : };
397 : :
398 : : class operator_plus : public range_operator
399 : : {
400 : : public:
401 : : using range_operator::op1_range;
402 : : using range_operator::op2_range;
403 : : using range_operator::lhs_op1_relation;
404 : : using range_operator::lhs_op2_relation;
405 : : bool op1_range (irange &r, tree type,
406 : : const irange &lhs, const irange &op2,
407 : : relation_trio) const final override;
408 : : bool op1_range (frange &r, tree type,
409 : : const frange &lhs, const frange &op2,
410 : : relation_trio = TRIO_VARYING) const final override;
411 : :
412 : : bool op2_range (irange &r, tree type,
413 : : const irange &lhs, const irange &op1,
414 : : relation_trio) const final override;
415 : : bool op2_range (frange &r, tree type,
416 : : const frange &lhs, const frange &op1,
417 : : relation_trio = TRIO_VARYING) const final override;
418 : :
419 : : relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
420 : : const irange &op2,
421 : : relation_kind rel) const final override;
422 : : relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
423 : : const irange &op2,
424 : : relation_kind rel) const final override;
425 : : void update_bitmask (irange &r, const irange &lh,
426 : : const irange &rh) const final override;
427 : :
428 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
429 : : relation_trio = TRIO_VARYING) const;
430 : : // Check compatibility of all operands.
431 : 43502482 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
432 : 43502482 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
433 : : private:
434 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
435 : : const wide_int &lh_ub, const wide_int &rh_lb,
436 : : const wide_int &rh_ub) const final override;
437 : : void rv_fold (frange &r, tree type,
438 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
439 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
440 : : relation_kind) const final override;
441 : : };
442 : :
443 : : class operator_abs : public range_operator
444 : : {
445 : : public:
446 : : using range_operator::fold_range;
447 : : using range_operator::op1_range;
448 : : bool fold_range (frange &r, tree type,
449 : : const frange &op1, const frange &,
450 : : relation_trio = TRIO_VARYING) const final override;
451 : :
452 : : bool op1_range (irange &r, tree type, const irange &lhs,
453 : : const irange &op2, relation_trio) const final override;
454 : : bool op1_range (frange &r, tree type,
455 : : const frange &lhs, const frange &op2,
456 : : relation_trio rel = TRIO_VARYING) const final override;
457 : : void update_bitmask (irange &r, const irange &lh,
458 : : const irange &rh) const final override;
459 : : // Check compatibility of LHS and op1.
460 : 821401 : bool operand_check_p (tree t1, tree t2, tree) const final override
461 : 821401 : { return range_compatible_p (t1, t2); }
462 : : private:
463 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
464 : : const wide_int &lh_ub, const wide_int &rh_lb,
465 : : const wide_int &rh_ub) const final override;
466 : :
467 : : };
468 : :
469 : : class operator_minus : public range_operator
470 : : {
471 : : public:
472 : : using range_operator::fold_range;
473 : : using range_operator::op1_range;
474 : : using range_operator::op2_range;
475 : : using range_operator::lhs_op1_relation;
476 : : bool op1_range (irange &r, tree type,
477 : : const irange &lhs, const irange &op2,
478 : : relation_trio) const final override;
479 : : bool op1_range (frange &r, tree type,
480 : : const frange &lhs, const frange &op2,
481 : : relation_trio = TRIO_VARYING) const final override;
482 : :
483 : : bool op2_range (irange &r, tree type,
484 : : const irange &lhs, const irange &op1,
485 : : relation_trio) const final override;
486 : : bool op2_range (frange &r, tree type,
487 : : const frange &lhs,
488 : : const frange &op1,
489 : : relation_trio = TRIO_VARYING) const final override;
490 : :
491 : : relation_kind lhs_op1_relation (const irange &lhs,
492 : : const irange &op1, const irange &op2,
493 : : relation_kind rel) const final override;
494 : : bool op1_op2_relation_effect (irange &lhs_range, tree type,
495 : : const irange &op1_range,
496 : : const irange &op2_range,
497 : : relation_kind rel) const final override;
498 : : void update_bitmask (irange &r, const irange &lh,
499 : : const irange &rh) const final override;
500 : :
501 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
502 : : relation_trio = TRIO_VARYING) const;
503 : : // Check compatibility of all operands.
504 : 12288799 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
505 : 12288799 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
506 : : private:
507 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
508 : : const wide_int &lh_ub, const wide_int &rh_lb,
509 : : const wide_int &rh_ub) const final override;
510 : : void rv_fold (frange &r, tree type,
511 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
512 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
513 : : relation_kind) const final override;
514 : : };
515 : :
516 : : class operator_negate : public range_operator
517 : : {
518 : : public:
519 : : using range_operator::fold_range;
520 : : using range_operator::op1_range;
521 : : bool fold_range (irange &r, tree type,
522 : : const irange &op1, const irange &op2,
523 : : relation_trio rel = TRIO_VARYING) const final override;
524 : : bool fold_range (frange &r, tree type,
525 : : const frange &op1, const frange &op2,
526 : : relation_trio = TRIO_VARYING) const final override;
527 : :
528 : : bool op1_range (irange &r, tree type,
529 : : const irange &lhs, const irange &op2,
530 : : relation_trio rel = TRIO_VARYING) const final override;
531 : : bool op1_range (frange &r, tree type,
532 : : const frange &lhs, const frange &op2,
533 : : relation_trio rel = TRIO_VARYING) const final override;
534 : : // Check compatibility of LHS and op1.
535 : 677531 : bool operand_check_p (tree t1, tree t2, tree) const final override
536 : 677531 : { return range_compatible_p (t1, t2); }
537 : : };
538 : :
539 : :
540 : : class cross_product_operator : public range_operator
541 : : {
542 : : public:
543 : : virtual bool wi_op_overflows (wide_int &r,
544 : : tree type,
545 : : const wide_int &,
546 : : const wide_int &) const = 0;
547 : : void wi_cross_product (irange &r, tree type,
548 : : const wide_int &lh_lb,
549 : : const wide_int &lh_ub,
550 : : const wide_int &rh_lb,
551 : : const wide_int &rh_ub) const;
552 : : };
553 : :
554 : : class operator_mult : public cross_product_operator
555 : : {
556 : : public:
557 : : using range_operator::op1_range;
558 : : using range_operator::op2_range;
559 : : bool op1_range (irange &r, tree type,
560 : : const irange &lhs, const irange &op2,
561 : : relation_trio) const final override;
562 : : bool op1_range (frange &r, tree type,
563 : : const frange &lhs, const frange &op2,
564 : : relation_trio = TRIO_VARYING) const final override;
565 : :
566 : : bool op2_range (irange &r, tree type,
567 : : const irange &lhs, const irange &op1,
568 : : relation_trio) const final override;
569 : : bool op2_range (frange &r, tree type,
570 : : const frange &lhs, const frange &op1,
571 : : relation_trio = TRIO_VARYING) const final override;
572 : :
573 : : void update_bitmask (irange &r, const irange &lh,
574 : : const irange &rh) const final override;
575 : :
576 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
577 : : const wide_int &lh_ub, const wide_int &rh_lb,
578 : : const wide_int &rh_ub) const final override;
579 : : bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
580 : : const wide_int &w1) const final override;
581 : :
582 : : void rv_fold (frange &r, tree type,
583 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
584 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
585 : : relation_kind kind) const final override;
586 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
587 : : relation_trio = TRIO_VARYING) const;
588 : : // Check compatibility of all operands.
589 : 12457719 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
590 : 12457719 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
591 : : };
592 : :
593 : : class operator_addr_expr : public range_operator
594 : : {
595 : : public:
596 : : using range_operator::fold_range;
597 : : using range_operator::op1_range;
598 : : bool fold_range (irange &r, tree type,
599 : : const irange &op1, const irange &op2,
600 : : relation_trio rel = TRIO_VARYING) const final override;
601 : : bool op1_range (irange &r, tree type,
602 : : const irange &lhs, const irange &op2,
603 : : relation_trio rel = TRIO_VARYING) const final override;
604 : : };
605 : :
606 : : class operator_bitwise_not : public range_operator
607 : : {
608 : : public:
609 : : using range_operator::fold_range;
610 : : using range_operator::op1_range;
611 : : bool fold_range (irange &r, tree type,
612 : : const irange &lh, const irange &rh,
613 : : relation_trio rel = TRIO_VARYING) const final override;
614 : : bool op1_range (irange &r, tree type,
615 : : const irange &lhs, const irange &op2,
616 : : relation_trio rel = TRIO_VARYING) const final override;
617 : : void update_bitmask (irange &r, const irange &lh,
618 : : const irange &rh) const final override;
619 : : // Check compatibility of all operands.
620 : 508689 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
621 : 508689 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
622 : : };
623 : :
624 : : class operator_bitwise_xor : public range_operator
625 : : {
626 : : public:
627 : : using range_operator::op1_range;
628 : : using range_operator::op2_range;
629 : : bool op1_range (irange &r, tree type,
630 : : const irange &lhs, const irange &op2,
631 : : relation_trio rel = TRIO_VARYING) const final override;
632 : : bool op2_range (irange &r, tree type,
633 : : const irange &lhs, const irange &op1,
634 : : relation_trio rel = TRIO_VARYING) const final override;
635 : : bool op1_op2_relation_effect (irange &lhs_range,
636 : : tree type,
637 : : const irange &op1_range,
638 : : const irange &op2_range,
639 : : relation_kind rel) const final override;
640 : : void update_bitmask (irange &r, const irange &lh,
641 : : const irange &rh) const final override;
642 : : // Check compatibility of all operands.
643 : 227694 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
644 : 227694 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
645 : : private:
646 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
647 : : const wide_int &lh_ub, const wide_int &rh_lb,
648 : : const wide_int &rh_ub) const final override;
649 : : };
650 : :
651 : : class operator_bitwise_and : public range_operator
652 : : {
653 : : public:
654 : : using range_operator::op1_range;
655 : : using range_operator::op2_range;
656 : : using range_operator::lhs_op1_relation;
657 : : bool op1_range (irange &r, tree type,
658 : : const irange &lhs, const irange &op2,
659 : : relation_trio rel = TRIO_VARYING) const override;
660 : : bool op2_range (irange &r, tree type,
661 : : const irange &lhs, const irange &op1,
662 : : relation_trio rel = TRIO_VARYING) const override;
663 : : relation_kind lhs_op1_relation (const irange &lhs,
664 : : const irange &op1, const irange &op2,
665 : : relation_kind) const override;
666 : : void update_bitmask (irange &r, const irange &lh,
667 : : const irange &rh) const override;
668 : : // Check compatibility of all operands.
669 : 8572886 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
670 : 8572886 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
671 : : protected:
672 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
673 : : const wide_int &lh_ub, const wide_int &rh_lb,
674 : : const wide_int &rh_ub) const override;
675 : : void simple_op1_range_solver (irange &r, tree type,
676 : : const irange &lhs,
677 : : const irange &op2) const;
678 : : };
679 : :
680 : : class operator_bitwise_or : public range_operator
681 : : {
682 : : public:
683 : : using range_operator::op1_range;
684 : : using range_operator::op2_range;
685 : : bool op1_range (irange &r, tree type,
686 : : const irange &lhs, const irange &op2,
687 : : relation_trio rel = TRIO_VARYING) const override;
688 : : bool op2_range (irange &r, tree type,
689 : : const irange &lhs, const irange &op1,
690 : : relation_trio rel = TRIO_VARYING) const override;
691 : : void update_bitmask (irange &r, const irange &lh,
692 : : const irange &rh) const override;
693 : : // Check compatibility of all operands.
694 : 2636043 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
695 : 2636043 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
696 : : protected:
697 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
698 : : const wide_int &lh_ub, const wide_int &rh_lb,
699 : : const wide_int &rh_ub) const override;
700 : : };
701 : :
702 : : class operator_min : public range_operator
703 : : {
704 : : public:
705 : : void update_bitmask (irange &r, const irange &lh,
706 : : const irange &rh) const override;
707 : : // Check compatibility of all operands.
708 : 969892 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
709 : 969892 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
710 : : protected:
711 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
712 : : const wide_int &lh_ub, const wide_int &rh_lb,
713 : : const wide_int &rh_ub) const override;
714 : : };
715 : :
716 : : class operator_max : public range_operator
717 : : {
718 : : public:
719 : : void update_bitmask (irange &r, const irange &lh,
720 : : const irange &rh) const override;
721 : : // Check compatibility of all operands.
722 : 553503 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
723 : 553503 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
724 : : protected:
725 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
726 : : const wide_int &lh_ub, const wide_int &rh_lb,
727 : : const wide_int &rh_ub) const override;
728 : : };
729 : : #endif // GCC_RANGE_OP_MIXED_H
|