Line data Source code
1 : /* Header file for mixed range operator class.
2 : Copyright (C) 2017-2026 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 (vrange &, tree_code, const vrange &, const vrange &);
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 19340780 : wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
35 : {
36 19340780 : signop sign = TYPE_SIGN (type);
37 19340780 : 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 1957028 : wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
44 : {
45 1957028 : unsigned prec = TYPE_PRECISION (type);
46 2326967 : 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 300990444 : empty_range_varying (vrange &r, tree type,
60 : const vrange &op1, const vrange & op2)
61 : {
62 300898959 : if (op1.undefined_p () || op2.undefined_p ())
63 : {
64 5460488 : r.set_varying (type);
65 5357913 : 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 86923549 : relop_early_resolve (irange &r, tree type, const vrange &op1,
78 : const vrange &op2, relation_trio trio,
79 : relation_kind my_rel)
80 : {
81 86923549 : relation_kind rel = trio.op1_op2 ();
82 : // If known relation is a complete subset of this relation, always true.
83 86923549 : if (relation_union (rel, my_rel) == my_rel)
84 : {
85 48484 : r = range_true (type);
86 48484 : return true;
87 : }
88 :
89 : // If known relation has no subset of this relation, always false.
90 86875065 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
91 : {
92 46428 : r = range_false (type);
93 46428 : return true;
94 : }
95 :
96 : // If either operand is undefined, return VARYING.
97 86828637 : if (empty_range_varying (r, type, op1, op2))
98 102575 : 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 : using range_operator::update_bitmask;
115 : bool fold_range (irange &r, tree type,
116 : const irange &op1, const irange &op2,
117 : relation_trio = TRIO_VARYING) const final override;
118 : bool fold_range (irange &r, tree type,
119 : const prange &op1, const prange &op2,
120 : relation_trio = TRIO_VARYING) const final override;
121 : bool fold_range (irange &r, tree type,
122 : const frange &op1, const frange &op2,
123 : relation_trio = TRIO_VARYING) const final override;
124 :
125 : bool op1_range (irange &r, tree type,
126 : const irange &lhs, const irange &val,
127 : relation_trio = TRIO_VARYING) const final override;
128 : bool op1_range (prange &r, tree type,
129 : const irange &lhs, const prange &val,
130 : relation_trio = TRIO_VARYING) const final override;
131 : bool op1_range (frange &r, tree type,
132 : const irange &lhs, const frange &op2,
133 : relation_trio = TRIO_VARYING) const final override;
134 :
135 : bool op2_range (irange &r, tree type,
136 : const irange &lhs, const irange &val,
137 : relation_trio = TRIO_VARYING) const final override;
138 : bool op2_range (prange &r, tree type,
139 : const irange &lhs, const prange &val,
140 : relation_trio = TRIO_VARYING) const final override;
141 : bool op2_range (frange &r, tree type,
142 : const irange &lhs, const frange &op1,
143 : relation_trio rel = TRIO_VARYING) const final override;
144 :
145 : relation_kind op1_op2_relation (const irange &lhs, const irange &,
146 : const irange &) const final override;
147 : relation_kind op1_op2_relation (const irange &lhs, const prange &,
148 : const prange &) const final override;
149 : relation_kind op1_op2_relation (const irange &lhs, const frange &,
150 : const frange &) const final override;
151 : void update_bitmask (irange &r, const irange &lh,
152 : const irange &rh) const final override;
153 : // Check op1 and op2 for compatibility.
154 41209793 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
155 41209793 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
156 : };
157 :
158 : class operator_not_equal : public range_operator
159 : {
160 : public:
161 : using range_operator::fold_range;
162 : using range_operator::op1_range;
163 : using range_operator::op2_range;
164 : using range_operator::op1_op2_relation;
165 : using range_operator::update_bitmask;
166 : bool fold_range (irange &r, tree type,
167 : const irange &op1, const irange &op2,
168 : relation_trio = TRIO_VARYING) const final override;
169 : bool fold_range (irange &r, tree type,
170 : const prange &op1, const prange &op2,
171 : relation_trio rel = TRIO_VARYING) const final override;
172 : bool fold_range (irange &r, tree type,
173 : const frange &op1, const frange &op2,
174 : relation_trio rel = TRIO_VARYING) const final override;
175 :
176 : bool op1_range (irange &r, tree type,
177 : const irange &lhs, const irange &op2,
178 : relation_trio = TRIO_VARYING) const final override;
179 : bool op1_range (prange &r, tree type,
180 : const irange &lhs, const prange &op2,
181 : relation_trio = TRIO_VARYING) const final override;
182 : bool op1_range (frange &r, tree type,
183 : const irange &lhs, const frange &op2,
184 : relation_trio = TRIO_VARYING) const final override;
185 :
186 : bool op2_range (irange &r, tree type,
187 : const irange &lhs, const irange &op1,
188 : relation_trio = TRIO_VARYING) const final override;
189 : bool op2_range (prange &r, tree type,
190 : const irange &lhs, const prange &op1,
191 : relation_trio = TRIO_VARYING) const final override;
192 : bool op2_range (frange &r, tree type,
193 : const irange &lhs, const frange &op1,
194 : relation_trio = TRIO_VARYING) const final override;
195 :
196 : relation_kind op1_op2_relation (const irange &lhs, const irange &,
197 : const irange &) const final override;
198 : relation_kind op1_op2_relation (const irange &lhs, const prange &,
199 : const prange &) const final override;
200 : relation_kind op1_op2_relation (const irange &lhs, const frange &,
201 : const frange &) const final override;
202 : void update_bitmask (irange &r, const irange &lh,
203 : const irange &rh) const final override;
204 : // Check op1 and op2 for compatibility.
205 63496015 : bool operand_check_p (tree t0, tree t1, tree t2) const final override
206 63496015 : { return range_compatible_p (t1, t2) && INTEGRAL_TYPE_P (t0); }
207 : };
208 :
209 : class operator_lt : public range_operator
210 : {
211 : public:
212 : using range_operator::fold_range;
213 : using range_operator::op1_range;
214 : using range_operator::op2_range;
215 : using range_operator::op1_op2_relation;
216 : using range_operator::update_bitmask;
217 : bool fold_range (irange &r, tree type,
218 : const irange &op1, const irange &op2,
219 : relation_trio = TRIO_VARYING) const final override;
220 : bool fold_range (irange &r, tree type,
221 : const prange &op1, const prange &op2,
222 : relation_trio = TRIO_VARYING) const final override;
223 : bool fold_range (irange &r, tree type,
224 : const frange &op1, const frange &op2,
225 : relation_trio = TRIO_VARYING) const final override;
226 : bool op1_range (irange &r, tree type,
227 : const irange &lhs, const irange &op2,
228 : relation_trio = TRIO_VARYING) const final override;
229 : bool op1_range (prange &r, tree type,
230 : const irange &lhs, const prange &op2,
231 : relation_trio = TRIO_VARYING) const final override;
232 : bool op1_range (frange &r, tree type,
233 : const irange &lhs, const frange &op2,
234 : relation_trio = TRIO_VARYING) const final override;
235 : bool op2_range (irange &r, tree type,
236 : const irange &lhs, const irange &op1,
237 : relation_trio = TRIO_VARYING) const final override;
238 : bool op2_range (prange &r, tree type,
239 : const irange &lhs, const prange &op1,
240 : relation_trio = TRIO_VARYING) const final override;
241 : bool op2_range (frange &r, tree type,
242 : const irange &lhs, const frange &op1,
243 : relation_trio = TRIO_VARYING) const final override;
244 : relation_kind op1_op2_relation (const irange &lhs, const irange &,
245 : const irange &) const final override;
246 : relation_kind op1_op2_relation (const irange &lhs, const prange &,
247 : const prange &) const final override;
248 : relation_kind op1_op2_relation (const irange &lhs, const frange &,
249 : const frange &) const final override;
250 : void update_bitmask (irange &r, const irange &lh,
251 : const irange &rh) const final override;
252 : // Check op1 and op2 for compatibility.
253 17740098 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
254 17740098 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
255 : };
256 :
257 : class operator_le : public range_operator
258 : {
259 : public:
260 : using range_operator::fold_range;
261 : using range_operator::op1_range;
262 : using range_operator::op2_range;
263 : using range_operator::op1_op2_relation;
264 : using range_operator::update_bitmask;
265 : bool fold_range (irange &r, tree type,
266 : const irange &op1, const irange &op2,
267 : relation_trio = TRIO_VARYING) const final override;
268 : bool fold_range (irange &r, tree type,
269 : const prange &op1, const prange &op2,
270 : relation_trio = TRIO_VARYING) const final override;
271 : bool fold_range (irange &r, tree type,
272 : const frange &op1, const frange &op2,
273 : relation_trio rel = TRIO_VARYING) const final override;
274 :
275 : bool op1_range (irange &r, tree type,
276 : const irange &lhs, const irange &op2,
277 : relation_trio = TRIO_VARYING) const final override;
278 : bool op1_range (prange &r, tree type,
279 : const irange &lhs, const prange &op2,
280 : relation_trio = TRIO_VARYING) const final override;
281 : bool op1_range (frange &r, tree type,
282 : const irange &lhs, const frange &op2,
283 : relation_trio rel = TRIO_VARYING) const final override;
284 :
285 : bool op2_range (irange &r, tree type,
286 : const irange &lhs, const irange &op1,
287 : relation_trio = TRIO_VARYING) const final override;
288 : bool op2_range (prange &r, tree type,
289 : const irange &lhs, const prange &op1,
290 : relation_trio = TRIO_VARYING) const final override;
291 : bool op2_range (frange &r, tree type,
292 : const irange &lhs, const frange &op1,
293 : relation_trio rel = TRIO_VARYING) const final override;
294 :
295 : relation_kind op1_op2_relation (const irange &lhs, const irange &,
296 : const irange &) const final override;
297 : relation_kind op1_op2_relation (const irange &lhs, const prange &,
298 : const prange &) const final override;
299 : relation_kind op1_op2_relation (const irange &lhs, const frange &,
300 : const frange &) const final override;
301 : void update_bitmask (irange &r, const irange &lh,
302 : const irange &rh) const final override;
303 : // Check op1 and op2 for compatibility.
304 13071247 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
305 13071247 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
306 : };
307 :
308 : class operator_gt : public range_operator
309 : {
310 : public:
311 : using range_operator::fold_range;
312 : using range_operator::op1_range;
313 : using range_operator::op2_range;
314 : using range_operator::op1_op2_relation;
315 : using range_operator::update_bitmask;
316 : bool fold_range (irange &r, tree type,
317 : const irange &op1, const irange &op2,
318 : relation_trio = TRIO_VARYING) const final override;
319 : bool fold_range (irange &r, tree type,
320 : const prange &op1, const prange &op2,
321 : relation_trio = TRIO_VARYING) const final override;
322 : bool fold_range (irange &r, tree type,
323 : const frange &op1, const frange &op2,
324 : relation_trio = TRIO_VARYING) const final override;
325 :
326 : bool op1_range (irange &r, tree type,
327 : const irange &lhs, const irange &op2,
328 : relation_trio = TRIO_VARYING) const final override;
329 : bool op1_range (prange &r, tree type,
330 : const irange &lhs, const prange &op2,
331 : relation_trio = TRIO_VARYING) const final override;
332 : bool op1_range (frange &r, tree type,
333 : const irange &lhs, const frange &op2,
334 : relation_trio = TRIO_VARYING) const final override;
335 :
336 : bool op2_range (irange &r, tree type,
337 : const irange &lhs, const irange &op1,
338 : relation_trio = TRIO_VARYING) const final override;
339 : bool op2_range (prange &r, tree type,
340 : const irange &lhs, const prange &op1,
341 : relation_trio = TRIO_VARYING) const final override;
342 : bool op2_range (frange &r, tree type,
343 : const irange &lhs, const frange &op1,
344 : relation_trio = TRIO_VARYING) const final override;
345 : relation_kind op1_op2_relation (const irange &lhs, const irange &,
346 : const irange &) const final override;
347 : relation_kind op1_op2_relation (const irange &lhs, const prange &,
348 : const prange &) const final override;
349 : relation_kind op1_op2_relation (const irange &lhs, const frange &,
350 : const frange &) const final override;
351 : void update_bitmask (irange &r, const irange &lh,
352 : const irange &rh) const final override;
353 : // Check op1 and op2 for compatibility.
354 29085060 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
355 29085060 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
356 : };
357 :
358 : class operator_ge : public range_operator
359 : {
360 : public:
361 : using range_operator::fold_range;
362 : using range_operator::op1_range;
363 : using range_operator::op2_range;
364 : using range_operator::op1_op2_relation;
365 : using range_operator::update_bitmask;
366 : bool fold_range (irange &r, tree type,
367 : const irange &op1, const irange &op2,
368 : relation_trio = TRIO_VARYING) const final override;
369 : bool fold_range (irange &r, tree type,
370 : const prange &op1, const prange &op2,
371 : relation_trio = TRIO_VARYING) const final override;
372 : bool fold_range (irange &r, tree type,
373 : const frange &op1, const frange &op2,
374 : relation_trio = TRIO_VARYING) const final override;
375 :
376 : bool op1_range (irange &r, tree type,
377 : const irange &lhs, const irange &op2,
378 : relation_trio = TRIO_VARYING) const final override;
379 : bool op1_range (prange &r, tree type,
380 : const irange &lhs, const prange &op2,
381 : relation_trio = TRIO_VARYING) const final override;
382 : bool op1_range (frange &r, tree type,
383 : const irange &lhs, const frange &op2,
384 : relation_trio = TRIO_VARYING) const final override;
385 :
386 : bool op2_range (irange &r, tree type,
387 : const irange &lhs, const irange &op1,
388 : relation_trio = TRIO_VARYING) const final override;
389 : bool op2_range (prange &r, tree type,
390 : const irange &lhs, const prange &op1,
391 : relation_trio = TRIO_VARYING) const final override;
392 : bool op2_range (frange &r, tree type,
393 : const irange &lhs, const frange &op1,
394 : relation_trio = TRIO_VARYING) const final override;
395 :
396 : relation_kind op1_op2_relation (const irange &lhs, const irange &,
397 : const irange &) const final override;
398 : relation_kind op1_op2_relation (const irange &lhs, const prange &,
399 : const prange &) const final override;
400 : relation_kind op1_op2_relation (const irange &lhs, const frange &,
401 : const frange &) const final override;
402 : void update_bitmask (irange &r, const irange &lh,
403 : const irange &rh) const final override;
404 : // Check op1 and op2 for compatibility.
405 8144590 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
406 8144590 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
407 : };
408 :
409 : class operator_identity : public range_operator
410 : {
411 : public:
412 : using range_operator::fold_range;
413 : using range_operator::op1_range;
414 : using range_operator::lhs_op1_relation;
415 : bool fold_range (irange &r, tree type,
416 : const irange &op1, const irange &op2,
417 : relation_trio rel = TRIO_VARYING) const final override;
418 : bool fold_range (prange &r, tree type,
419 : const prange &op1, const prange &op2,
420 : relation_trio rel = TRIO_VARYING) const final override;
421 : bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
422 : const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
423 : relation_trio = TRIO_VARYING) const final override;
424 : bool op1_range (irange &r, tree type,
425 : const irange &lhs, const irange &op2,
426 : relation_trio rel = TRIO_VARYING) const final override;
427 : bool op1_range (prange &r, tree type,
428 : const prange &lhs, const prange &op2,
429 : relation_trio rel = TRIO_VARYING) const final override;
430 : bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
431 : const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
432 : relation_trio = TRIO_VARYING) const final override;
433 : relation_kind lhs_op1_relation (const irange &lhs,
434 : const irange &op1, const irange &op2,
435 : relation_kind rel) const final override;
436 : relation_kind lhs_op1_relation (const prange &lhs,
437 : const prange &op1, const prange &op2,
438 : relation_kind rel) const final override;
439 : };
440 :
441 : class operator_cst : public range_operator
442 : {
443 : public:
444 : using range_operator::fold_range;
445 : bool fold_range (irange &r, tree type,
446 : const irange &op1, const irange &op2,
447 : relation_trio rel = TRIO_VARYING) const final override;
448 : bool fold_range (prange &r, tree type,
449 : const prange &op1, const prange &op2,
450 : relation_trio rel = TRIO_VARYING) const final override;
451 : bool fold_range (frange &r, tree type,
452 : const frange &op1, const frange &op2,
453 : relation_trio = TRIO_VARYING) const final override;
454 : };
455 :
456 :
457 : class operator_cast: public range_operator
458 : {
459 : public:
460 : using range_operator::fold_range;
461 : using range_operator::op1_range;
462 : using range_operator::lhs_op1_relation;
463 : using range_operator::update_bitmask;
464 : bool fold_range (irange &r, tree type,
465 : const irange &op1, const irange &op2,
466 : relation_trio rel = TRIO_VARYING) const final override;
467 : bool fold_range (prange &r, tree type,
468 : const prange &op1, const prange &op2,
469 : relation_trio rel = TRIO_VARYING) const final override;
470 : bool fold_range (irange &r, tree type,
471 : const prange &op1, const irange &op2,
472 : relation_trio rel = TRIO_VARYING) const final override;
473 : bool fold_range (prange &r, tree type,
474 : const irange &op1, const prange &op2,
475 : relation_trio rel = TRIO_VARYING) const final override;
476 : bool fold_range (frange &r, tree type,
477 : const frange &op1, const frange &op2,
478 : relation_trio = TRIO_VARYING) const final override;
479 : bool fold_range (irange &r, tree type,
480 : const frange &op1, const irange &op2,
481 : relation_trio = TRIO_VARYING) const final override;
482 : bool fold_range (frange &r, tree type,
483 : const irange &op1, const frange &op2,
484 : relation_trio = TRIO_VARYING) const final override;
485 :
486 : bool op1_range (irange &r, tree type,
487 : const irange &lhs, const irange &op2,
488 : relation_trio rel = TRIO_VARYING) const final override;
489 : bool op1_range (prange &r, tree type,
490 : const prange &lhs, const prange &op2,
491 : relation_trio rel = TRIO_VARYING) const final override;
492 : bool op1_range (irange &r, tree type,
493 : const prange &lhs, const irange &op2,
494 : relation_trio rel = TRIO_VARYING) const final override;
495 : bool op1_range (prange &r, tree type,
496 : const irange &lhs, const prange &op2,
497 : relation_trio rel = TRIO_VARYING) const final override;
498 : bool op1_range (frange &r, tree type,
499 : const frange &lhs, const frange &op2,
500 : relation_trio = TRIO_VARYING) const final override;
501 : bool op1_range (frange &r, tree type,
502 : const irange &lhs, const frange &op2,
503 : relation_trio = TRIO_VARYING) const final override;
504 : bool op1_range (irange &r, tree type,
505 : const frange &lhs, const irange &op2,
506 : relation_trio = TRIO_VARYING) const final override;
507 :
508 : relation_kind lhs_op1_relation (const irange &lhs,
509 : const irange &op1, const irange &op2,
510 : relation_kind) const final override;
511 : relation_kind lhs_op1_relation (const prange &lhs,
512 : const prange &op1, const prange &op2,
513 : relation_kind) const final override;
514 : relation_kind lhs_op1_relation (const prange &lhs,
515 : const irange &op1, const irange &op2,
516 : relation_kind) const final override;
517 : relation_kind lhs_op1_relation (const irange &lhs,
518 : const prange &op1, const prange &op2,
519 : relation_kind) const final override;
520 : void update_bitmask (irange &r, const irange &lh,
521 : const irange &rh) const final override;
522 : private:
523 : bool truncating_cast_p (const irange &inner, const irange &outer) const;
524 : bool inside_domain_p (const wide_int &min, const wide_int &max,
525 : const irange &outer) const;
526 : void fold_pair (irange &r, unsigned index, const irange &inner,
527 : const irange &outer) const;
528 : };
529 :
530 :
531 : class operator_view : public range_operator
532 : {
533 : public:
534 : using range_operator::fold_range;
535 : using range_operator::op1_range;
536 : using range_operator::update_bitmask;
537 : bool fold_range (irange &r, tree type,
538 : const irange &op1, const irange &op2,
539 : relation_trio rel = TRIO_VARYING) const override;
540 : bool fold_range (prange &r, tree type,
541 : const prange &op1, const prange &op2,
542 : relation_trio rel = TRIO_VARYING) const final override;
543 : bool fold_range (irange &r, tree type,
544 : const prange &op1, const irange &op2,
545 : relation_trio rel = TRIO_VARYING) const final override;
546 : bool fold_range (prange &r, tree type,
547 : const irange &op1, const prange &op2,
548 : relation_trio rel = TRIO_VARYING) const final override;
549 :
550 : bool op1_range (irange &r, tree type,
551 : const irange &lhs, const irange &op2,
552 : relation_trio rel = TRIO_VARYING) const override;
553 : bool op1_range (prange &r, tree type,
554 : const prange &lhs, const prange &op2,
555 : relation_trio rel = TRIO_VARYING) const final override;
556 : bool op1_range (irange &r, tree type,
557 : const prange &lhs, const irange &op2,
558 : relation_trio rel = TRIO_VARYING) const final override;
559 : bool op1_range (prange &r, tree type,
560 : const irange &lhs, const prange &op2,
561 : relation_trio rel = TRIO_VARYING) const final override;
562 :
563 : void update_bitmask (irange &r, const irange &lh,
564 : const irange &) const final override;
565 : private:
566 : // VIEW_CONVERT_EXPR works much like a cast between integral values, so use
567 : // the cast operator. Non-integrals are not handled as yet.
568 : operator_cast m_cast;
569 : };
570 :
571 : class operator_plus : public range_operator
572 : {
573 : public:
574 : using range_operator::op1_range;
575 : using range_operator::op2_range;
576 : using range_operator::lhs_op1_relation;
577 : using range_operator::lhs_op2_relation;
578 : using range_operator::update_bitmask;
579 : bool op1_range (irange &r, tree type,
580 : const irange &lhs, const irange &op2,
581 : relation_trio) const final override;
582 : bool op1_range (frange &r, tree type,
583 : const frange &lhs, const frange &op2,
584 : relation_trio = TRIO_VARYING) const final override;
585 :
586 : bool op2_range (irange &r, tree type,
587 : const irange &lhs, const irange &op1,
588 : relation_trio) const final override;
589 : bool op2_range (frange &r, tree type,
590 : const frange &lhs, const frange &op1,
591 : relation_trio = TRIO_VARYING) const final override;
592 :
593 : relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
594 : const irange &op2,
595 : relation_kind rel) const final override;
596 : relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
597 : const irange &op2,
598 : relation_kind rel) const final override;
599 : void update_bitmask (irange &r, const irange &lh,
600 : const irange &rh) const final override;
601 :
602 : bool overflow_free_p (const irange &lh, const irange &rh,
603 : relation_trio = TRIO_VARYING) const final override;
604 : // Check compatibility of all operands.
605 63226572 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
606 63226572 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
607 : private:
608 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
609 : const wide_int &lh_ub, const wide_int &rh_lb,
610 : const wide_int &rh_ub) const final override;
611 : void rv_fold (frange &r, tree type,
612 : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
613 : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
614 : relation_kind) const final override;
615 : };
616 :
617 : class operator_abs : public range_operator
618 : {
619 : public:
620 : using range_operator::fold_range;
621 : using range_operator::op1_range;
622 : using range_operator::update_bitmask;
623 : bool fold_range (frange &r, tree type,
624 : const frange &op1, const frange &,
625 : relation_trio = TRIO_VARYING) const final override;
626 :
627 : bool op1_range (irange &r, tree type, const irange &lhs,
628 : const irange &op2, relation_trio) const final override;
629 : bool op1_range (frange &r, tree type,
630 : const frange &lhs, const frange &op2,
631 : relation_trio rel = TRIO_VARYING) const final override;
632 : void update_bitmask (irange &r, const irange &lh,
633 : const irange &rh) const final override;
634 : // Check compatibility of LHS and op1.
635 1029443 : bool operand_check_p (tree t1, tree t2, tree) const final override
636 1029443 : { return range_compatible_p (t1, t2); }
637 : private:
638 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
639 : const wide_int &lh_ub, const wide_int &rh_lb,
640 : const wide_int &rh_ub) const final override;
641 :
642 : };
643 :
644 : class operator_minus : public range_operator
645 : {
646 : public:
647 : using range_operator::fold_range;
648 : using range_operator::op1_range;
649 : using range_operator::op2_range;
650 : using range_operator::lhs_op1_relation;
651 : using range_operator::op1_op2_relation_effect;
652 : using range_operator::update_bitmask;
653 : bool op1_range (irange &r, tree type,
654 : const irange &lhs, const irange &op2,
655 : relation_trio) const final override;
656 : bool op1_range (frange &r, tree type,
657 : const frange &lhs, const frange &op2,
658 : relation_trio = TRIO_VARYING) const final override;
659 :
660 : bool op2_range (irange &r, tree type,
661 : const irange &lhs, const irange &op1,
662 : relation_trio) const final override;
663 : bool op2_range (frange &r, tree type,
664 : const frange &lhs,
665 : const frange &op1,
666 : relation_trio = TRIO_VARYING) const final override;
667 :
668 : relation_kind lhs_op1_relation (const irange &lhs,
669 : const irange &op1, const irange &op2,
670 : relation_kind rel) const final override;
671 : bool op1_op2_relation_effect (irange &lhs_range, tree type,
672 : const irange &op1_range,
673 : const irange &op2_range,
674 : relation_kind rel) const final override;
675 : void update_bitmask (irange &r, const irange &lh,
676 : const irange &rh) const final override;
677 :
678 : bool overflow_free_p (const irange &lh, const irange &rh,
679 : relation_trio = TRIO_VARYING) const final override;
680 : // Check compatibility of all operands.
681 20840709 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
682 20840709 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
683 : private:
684 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
685 : const wide_int &lh_ub, const wide_int &rh_lb,
686 : const wide_int &rh_ub) const final override;
687 : void rv_fold (frange &r, tree type,
688 : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
689 : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
690 : relation_kind) const final override;
691 : };
692 :
693 : class operator_negate : public range_operator
694 : {
695 : public:
696 : using range_operator::fold_range;
697 : using range_operator::op1_range;
698 : bool fold_range (irange &r, tree type,
699 : const irange &op1, const irange &op2,
700 : relation_trio rel = TRIO_VARYING) const final override;
701 : bool fold_range (frange &r, tree type,
702 : const frange &op1, const frange &op2,
703 : relation_trio = TRIO_VARYING) const final override;
704 :
705 : bool op1_range (irange &r, tree type,
706 : const irange &lhs, const irange &op2,
707 : relation_trio rel = TRIO_VARYING) const final override;
708 : bool op1_range (frange &r, tree type,
709 : const frange &lhs, const frange &op2,
710 : relation_trio rel = TRIO_VARYING) const final override;
711 : // Check compatibility of LHS and op1.
712 822012 : bool operand_check_p (tree t1, tree t2, tree) const final override
713 822012 : { return range_compatible_p (t1, t2); }
714 : };
715 :
716 :
717 : class cross_product_operator : public range_operator
718 : {
719 : public:
720 : virtual bool wi_op_overflows (wide_int &r,
721 : tree type,
722 : const wide_int &,
723 : const wide_int &) const = 0;
724 : void wi_cross_product (irange &r, tree type,
725 : const wide_int &lh_lb,
726 : const wide_int &lh_ub,
727 : const wide_int &rh_lb,
728 : const wide_int &rh_ub) const;
729 : };
730 :
731 : class operator_mult : public cross_product_operator
732 : {
733 : public:
734 : using range_operator::op1_range;
735 : using range_operator::op2_range;
736 : using range_operator::update_bitmask;
737 : bool op1_range (irange &r, tree type,
738 : const irange &lhs, const irange &op2,
739 : relation_trio) const final override;
740 : bool op1_range (frange &r, tree type,
741 : const frange &lhs, const frange &op2,
742 : relation_trio = TRIO_VARYING) const final override;
743 :
744 : bool op2_range (irange &r, tree type,
745 : const irange &lhs, const irange &op1,
746 : relation_trio) const final override;
747 : bool op2_range (frange &r, tree type,
748 : const frange &lhs, const frange &op1,
749 : relation_trio = TRIO_VARYING) const final override;
750 :
751 : void update_bitmask (irange &r, const irange &lh,
752 : const irange &rh) const final override;
753 :
754 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
755 : const wide_int &lh_ub, const wide_int &rh_lb,
756 : const wide_int &rh_ub) const final override;
757 : bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
758 : const wide_int &w1) const final override;
759 :
760 : void rv_fold (frange &r, tree type,
761 : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
762 : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
763 : relation_kind kind) const final override;
764 : bool overflow_free_p (const irange &lh, const irange &rh,
765 : relation_trio = TRIO_VARYING) const final override;
766 : // Check compatibility of all operands.
767 15607656 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
768 15607656 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
769 : };
770 :
771 : class operator_addr_expr : public range_operator
772 : {
773 : public:
774 : using range_operator::fold_range;
775 : using range_operator::op1_range;
776 : bool fold_range (irange &r, tree type,
777 : const irange &op1, const irange &op2,
778 : relation_trio rel = TRIO_VARYING) const final override;
779 : bool op1_range (irange &r, tree type,
780 : const irange &lhs, const irange &op2,
781 : relation_trio rel = TRIO_VARYING) const final override;
782 : bool op1_range (prange &r, tree type,
783 : const prange &lhs, const prange &op2,
784 : relation_trio rel = TRIO_VARYING) const final override;
785 : };
786 :
787 : class operator_bitwise_not : public range_operator
788 : {
789 : public:
790 : using range_operator::fold_range;
791 : using range_operator::op1_range;
792 : using range_operator::update_bitmask;
793 : bool fold_range (irange &r, tree type,
794 : const irange &lh, const irange &rh,
795 : relation_trio rel = TRIO_VARYING) const final override;
796 : bool op1_range (irange &r, tree type,
797 : const irange &lhs, const irange &op2,
798 : relation_trio rel = TRIO_VARYING) const final override;
799 : void update_bitmask (irange &r, const irange &lh,
800 : const irange &rh) const final override;
801 : // Check compatibility of all operands.
802 543588 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
803 543588 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
804 : };
805 :
806 : class operator_bitwise_and : public range_operator
807 : {
808 : public:
809 : using range_operator::fold_range;
810 : using range_operator::op1_range;
811 : using range_operator::op2_range;
812 : using range_operator::lhs_op1_relation;
813 : using range_operator::update_bitmask;
814 : bool fold_range (prange &r, tree type,
815 : const prange &op1,
816 : const prange &op2,
817 : relation_trio) const final override;
818 : bool op1_range (irange &r, tree type,
819 : const irange &lhs, const irange &op2,
820 : relation_trio rel = TRIO_VARYING) const override;
821 : bool op2_range (irange &r, tree type,
822 : const irange &lhs, const irange &op1,
823 : relation_trio rel = TRIO_VARYING) const override;
824 : relation_kind lhs_op1_relation (const irange &lhs,
825 : const irange &op1, const irange &op2,
826 : relation_kind) const override;
827 : void update_bitmask (irange &r, const irange &lh,
828 : const irange &rh) const override;
829 : // Check compatibility of all operands.
830 10606355 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
831 10606355 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
832 : protected:
833 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
834 : const wide_int &lh_ub, const wide_int &rh_lb,
835 : const wide_int &rh_ub) const override;
836 : void simple_op1_range_solver (irange &r, tree type,
837 : const irange &lhs,
838 : const irange &op2) const;
839 : };
840 :
841 : class operator_bitwise_or : public range_operator
842 : {
843 : public:
844 : using range_operator::fold_range;
845 : using range_operator::op1_range;
846 : using range_operator::op2_range;
847 : using range_operator::update_bitmask;
848 :
849 : bool fold_range (prange &r, tree type,
850 : const prange &op1,
851 : const prange &op2,
852 : relation_trio) const final override;
853 : bool op1_range (irange &r, tree type,
854 : const irange &lhs, const irange &op2,
855 : relation_trio rel = TRIO_VARYING) const override;
856 : bool op2_range (irange &r, tree type,
857 : const irange &lhs, const irange &op1,
858 : relation_trio rel = TRIO_VARYING) const override;
859 : void update_bitmask (irange &r, const irange &lh,
860 : const irange &rh) const override;
861 : // Check compatibility of all operands.
862 2826253 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
863 2826253 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
864 : protected:
865 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
866 : const wide_int &lh_ub, const wide_int &rh_lb,
867 : const wide_int &rh_ub) const override;
868 : };
869 :
870 : class operator_bitwise_xor : public range_operator
871 : {
872 : public:
873 : using range_operator::fold_range;
874 : using range_operator::op1_range;
875 : using range_operator::op2_range;
876 : using range_operator::op1_op2_relation_effect;
877 : using range_operator::update_bitmask;
878 : bool fold_range (irange &r, tree type,
879 : const irange &lh, const irange &rh,
880 : relation_trio rel = TRIO_VARYING) const final override;
881 : bool op1_range (irange &r, tree type,
882 : const irange &lhs, const irange &op2,
883 : relation_trio rel = TRIO_VARYING) const final override;
884 : bool op2_range (irange &r, tree type,
885 : const irange &lhs, const irange &op1,
886 : relation_trio rel = TRIO_VARYING) const final override;
887 : bool op1_op2_relation_effect (irange &lhs_range,
888 : tree type,
889 : const irange &op1_range,
890 : const irange &op2_range,
891 : relation_kind rel) const final override;
892 : void update_bitmask (irange &r, const irange &lh,
893 : const irange &rh) const final override;
894 : // Check compatibility of all operands.
895 358514 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
896 358514 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
897 : private:
898 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
899 : const wide_int &lh_ub, const wide_int &rh_lb,
900 : const wide_int &rh_ub) const final override;
901 : class operator_bitwise_and m_and;
902 : class operator_bitwise_or m_or;
903 : class operator_bitwise_not m_not;
904 : };
905 :
906 :
907 : class operator_min : public range_operator
908 : {
909 : public:
910 : using range_operator::fold_range;
911 : using range_operator::update_bitmask;
912 : bool fold_range (prange &r, tree type,
913 : const prange &op1,
914 : const prange &op2,
915 : relation_trio) const final override;
916 : void update_bitmask (irange &r, const irange &lh,
917 : const irange &rh) const override;
918 : // Check compatibility of all operands.
919 1595812 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
920 1595812 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
921 : protected:
922 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
923 : const wide_int &lh_ub, const wide_int &rh_lb,
924 : const wide_int &rh_ub) const override;
925 : };
926 :
927 : class operator_max : public range_operator
928 : {
929 : public:
930 : using range_operator::fold_range;
931 : using range_operator::update_bitmask;
932 : bool fold_range (prange &r, tree type,
933 : const prange &op1,
934 : const prange &op2,
935 : relation_trio) const final override;
936 : void update_bitmask (irange &r, const irange &lh,
937 : const irange &rh) const override;
938 : // Check compatibility of all operands.
939 830248 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
940 830248 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
941 : protected:
942 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
943 : const wide_int &lh_ub, const wide_int &rh_lb,
944 : const wide_int &rh_ub) const override;
945 : };
946 : #endif // GCC_RANGE_OP_MIXED_H
|