Branch data Line data Source code
1 : : /* Header file for mixed range operator class.
2 : : Copyright (C) 2017-2025 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 : 18502037 : wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
35 : : {
36 : 18502037 : signop sign = TYPE_SIGN (type);
37 : 18502037 : 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 : 1892917 : wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
44 : : {
45 : 1892917 : unsigned prec = TYPE_PRECISION (type);
46 : 2395313 : 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 : 276606948 : empty_range_varying (vrange &r, tree type,
60 : : const vrange &op1, const vrange & op2)
61 : : {
62 : 276519326 : if (op1.undefined_p () || op2.undefined_p ())
63 : : {
64 : 5453347 : r.set_varying (type);
65 : 5355645 : 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 : 82563836 : relop_early_resolve (irange &r, tree type, const vrange &op1,
78 : : const vrange &op2, relation_trio trio,
79 : : relation_kind my_rel)
80 : : {
81 : 82563836 : relation_kind rel = trio.op1_op2 ();
82 : : // If known relation is a complete subset of this relation, always true.
83 : 82563836 : if (relation_union (rel, my_rel) == my_rel)
84 : : {
85 : 48538 : r = range_true (type);
86 : 48538 : return true;
87 : : }
88 : :
89 : : // If known relation has no subset of this relation, always false.
90 : 82515298 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
91 : : {
92 : 48996 : r = range_false (type);
93 : 48996 : return true;
94 : : }
95 : :
96 : : // If either operand is undefined, return VARYING.
97 : 82466302 : if (empty_range_varying (r, type, op1, op2))
98 : 97702 : 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 : 39092563 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
155 : 39092563 : { 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 : 61576662 : bool operand_check_p (tree t0, tree t1, tree t2) const final override
206 : 61576662 : { 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 : 14508256 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
254 : 14508256 : { 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 : 11361641 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
305 : 11361641 : { 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 : 26008185 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
355 : 26008185 : { 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 : 7639555 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
406 : 7639555 : { 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 : : class operator_plus : public range_operator
531 : : {
532 : : public:
533 : : using range_operator::op1_range;
534 : : using range_operator::op2_range;
535 : : using range_operator::lhs_op1_relation;
536 : : using range_operator::lhs_op2_relation;
537 : : using range_operator::update_bitmask;
538 : : bool op1_range (irange &r, tree type,
539 : : const irange &lhs, const irange &op2,
540 : : relation_trio) const final override;
541 : : bool op1_range (frange &r, tree type,
542 : : const frange &lhs, const frange &op2,
543 : : relation_trio = TRIO_VARYING) const final override;
544 : :
545 : : bool op2_range (irange &r, tree type,
546 : : const irange &lhs, const irange &op1,
547 : : relation_trio) const final override;
548 : : bool op2_range (frange &r, tree type,
549 : : const frange &lhs, const frange &op1,
550 : : relation_trio = TRIO_VARYING) const final override;
551 : :
552 : : relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
553 : : const irange &op2,
554 : : relation_kind rel) const final override;
555 : : relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
556 : : const irange &op2,
557 : : relation_kind rel) const final override;
558 : : void update_bitmask (irange &r, const irange &lh,
559 : : const irange &rh) const final override;
560 : :
561 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
562 : : relation_trio = TRIO_VARYING) const;
563 : : // Check compatibility of all operands.
564 : 55176179 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
565 : 55176179 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
566 : : private:
567 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
568 : : const wide_int &lh_ub, const wide_int &rh_lb,
569 : : const wide_int &rh_ub) const final override;
570 : : void rv_fold (frange &r, tree type,
571 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
572 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
573 : : relation_kind) const final override;
574 : : };
575 : :
576 : : class operator_abs : public range_operator
577 : : {
578 : : public:
579 : : using range_operator::fold_range;
580 : : using range_operator::op1_range;
581 : : using range_operator::update_bitmask;
582 : : bool fold_range (frange &r, tree type,
583 : : const frange &op1, const frange &,
584 : : relation_trio = TRIO_VARYING) const final override;
585 : :
586 : : bool op1_range (irange &r, tree type, const irange &lhs,
587 : : const irange &op2, relation_trio) const final override;
588 : : bool op1_range (frange &r, tree type,
589 : : const frange &lhs, const frange &op2,
590 : : relation_trio rel = TRIO_VARYING) const final override;
591 : : void update_bitmask (irange &r, const irange &lh,
592 : : const irange &rh) const final override;
593 : : // Check compatibility of LHS and op1.
594 : 985359 : bool operand_check_p (tree t1, tree t2, tree) const final override
595 : 985359 : { return range_compatible_p (t1, t2); }
596 : : private:
597 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
598 : : const wide_int &lh_ub, const wide_int &rh_lb,
599 : : const wide_int &rh_ub) const final override;
600 : :
601 : : };
602 : :
603 : : class operator_minus : public range_operator
604 : : {
605 : : public:
606 : : using range_operator::fold_range;
607 : : using range_operator::op1_range;
608 : : using range_operator::op2_range;
609 : : using range_operator::lhs_op1_relation;
610 : : using range_operator::op1_op2_relation_effect;
611 : : using range_operator::update_bitmask;
612 : : bool op1_range (irange &r, tree type,
613 : : const irange &lhs, const irange &op2,
614 : : relation_trio) const final override;
615 : : bool op1_range (frange &r, tree type,
616 : : const frange &lhs, const frange &op2,
617 : : relation_trio = TRIO_VARYING) const final override;
618 : :
619 : : bool op2_range (irange &r, tree type,
620 : : const irange &lhs, const irange &op1,
621 : : relation_trio) const final override;
622 : : bool op2_range (frange &r, tree type,
623 : : const frange &lhs,
624 : : const frange &op1,
625 : : relation_trio = TRIO_VARYING) const final override;
626 : :
627 : : relation_kind lhs_op1_relation (const irange &lhs,
628 : : const irange &op1, const irange &op2,
629 : : relation_kind rel) const final override;
630 : : bool op1_op2_relation_effect (irange &lhs_range, tree type,
631 : : const irange &op1_range,
632 : : const irange &op2_range,
633 : : relation_kind rel) const final override;
634 : : void update_bitmask (irange &r, const irange &lh,
635 : : const irange &rh) const final override;
636 : :
637 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
638 : : relation_trio = TRIO_VARYING) const;
639 : : // Check compatibility of all operands.
640 : 17150537 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
641 : 17150537 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
642 : : private:
643 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
644 : : const wide_int &lh_ub, const wide_int &rh_lb,
645 : : const wide_int &rh_ub) const final override;
646 : : void rv_fold (frange &r, tree type,
647 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
648 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
649 : : relation_kind) const final override;
650 : : };
651 : :
652 : : class operator_negate : public range_operator
653 : : {
654 : : public:
655 : : using range_operator::fold_range;
656 : : using range_operator::op1_range;
657 : : bool fold_range (irange &r, tree type,
658 : : const irange &op1, const irange &op2,
659 : : relation_trio rel = TRIO_VARYING) const final override;
660 : : bool fold_range (frange &r, tree type,
661 : : const frange &op1, const frange &op2,
662 : : relation_trio = TRIO_VARYING) const final override;
663 : :
664 : : bool op1_range (irange &r, tree type,
665 : : const irange &lhs, const irange &op2,
666 : : relation_trio rel = TRIO_VARYING) const final override;
667 : : bool op1_range (frange &r, tree type,
668 : : const frange &lhs, const frange &op2,
669 : : relation_trio rel = TRIO_VARYING) const final override;
670 : : // Check compatibility of LHS and op1.
671 : 773369 : bool operand_check_p (tree t1, tree t2, tree) const final override
672 : 773369 : { return range_compatible_p (t1, t2); }
673 : : };
674 : :
675 : :
676 : : class cross_product_operator : public range_operator
677 : : {
678 : : public:
679 : : virtual bool wi_op_overflows (wide_int &r,
680 : : tree type,
681 : : const wide_int &,
682 : : const wide_int &) const = 0;
683 : : void wi_cross_product (irange &r, tree type,
684 : : const wide_int &lh_lb,
685 : : const wide_int &lh_ub,
686 : : const wide_int &rh_lb,
687 : : const wide_int &rh_ub) const;
688 : : };
689 : :
690 : : class operator_mult : public cross_product_operator
691 : : {
692 : : public:
693 : : using range_operator::op1_range;
694 : : using range_operator::op2_range;
695 : : using range_operator::update_bitmask;
696 : : bool op1_range (irange &r, tree type,
697 : : const irange &lhs, const irange &op2,
698 : : relation_trio) const final override;
699 : : bool op1_range (frange &r, tree type,
700 : : const frange &lhs, const frange &op2,
701 : : relation_trio = TRIO_VARYING) const final override;
702 : :
703 : : bool op2_range (irange &r, tree type,
704 : : const irange &lhs, const irange &op1,
705 : : relation_trio) const final override;
706 : : bool op2_range (frange &r, tree type,
707 : : const frange &lhs, const frange &op1,
708 : : relation_trio = TRIO_VARYING) const final override;
709 : :
710 : : void update_bitmask (irange &r, const irange &lh,
711 : : const irange &rh) const final override;
712 : :
713 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
714 : : const wide_int &lh_ub, const wide_int &rh_lb,
715 : : const wide_int &rh_ub) const final override;
716 : : bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
717 : : const wide_int &w1) const final override;
718 : :
719 : : void rv_fold (frange &r, tree type,
720 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
721 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
722 : : relation_kind kind) const final override;
723 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
724 : : relation_trio = TRIO_VARYING) const;
725 : : // Check compatibility of all operands.
726 : 13900958 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
727 : 13900958 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
728 : : };
729 : :
730 : : class operator_addr_expr : public range_operator
731 : : {
732 : : public:
733 : : using range_operator::fold_range;
734 : : using range_operator::op1_range;
735 : : bool fold_range (irange &r, tree type,
736 : : const irange &op1, const irange &op2,
737 : : relation_trio rel = TRIO_VARYING) const final override;
738 : : bool op1_range (irange &r, tree type,
739 : : const irange &lhs, const irange &op2,
740 : : relation_trio rel = TRIO_VARYING) const final override;
741 : : bool op1_range (prange &r, tree type,
742 : : const prange &lhs, const prange &op2,
743 : : relation_trio rel = TRIO_VARYING) const final override;
744 : : };
745 : :
746 : : class operator_bitwise_not : public range_operator
747 : : {
748 : : public:
749 : : using range_operator::fold_range;
750 : : using range_operator::op1_range;
751 : : using range_operator::update_bitmask;
752 : : bool fold_range (irange &r, tree type,
753 : : const irange &lh, const irange &rh,
754 : : relation_trio rel = TRIO_VARYING) const final override;
755 : : bool op1_range (irange &r, tree type,
756 : : const irange &lhs, const irange &op2,
757 : : relation_trio rel = TRIO_VARYING) const final override;
758 : : void update_bitmask (irange &r, const irange &lh,
759 : : const irange &rh) const final override;
760 : : // Check compatibility of all operands.
761 : 514246 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
762 : 514246 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
763 : : };
764 : :
765 : : class operator_bitwise_xor : public range_operator
766 : : {
767 : : public:
768 : : using range_operator::op1_range;
769 : : using range_operator::op2_range;
770 : : using range_operator::op1_op2_relation_effect;
771 : : using range_operator::update_bitmask;
772 : : bool op1_range (irange &r, tree type,
773 : : const irange &lhs, const irange &op2,
774 : : relation_trio rel = TRIO_VARYING) const final override;
775 : : bool op2_range (irange &r, tree type,
776 : : const irange &lhs, const irange &op1,
777 : : relation_trio rel = TRIO_VARYING) const final override;
778 : : bool op1_op2_relation_effect (irange &lhs_range,
779 : : tree type,
780 : : const irange &op1_range,
781 : : const irange &op2_range,
782 : : relation_kind rel) const final override;
783 : : void update_bitmask (irange &r, const irange &lh,
784 : : const irange &rh) const final override;
785 : : // Check compatibility of all operands.
786 : 312888 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
787 : 312888 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
788 : : private:
789 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
790 : : const wide_int &lh_ub, const wide_int &rh_lb,
791 : : const wide_int &rh_ub) const final override;
792 : : };
793 : :
794 : : class operator_bitwise_and : public range_operator
795 : : {
796 : : public:
797 : : using range_operator::fold_range;
798 : : using range_operator::op1_range;
799 : : using range_operator::op2_range;
800 : : using range_operator::lhs_op1_relation;
801 : : using range_operator::update_bitmask;
802 : : bool fold_range (prange &r, tree type,
803 : : const prange &op1,
804 : : const prange &op2,
805 : : relation_trio) const final override;
806 : : bool op1_range (irange &r, tree type,
807 : : const irange &lhs, const irange &op2,
808 : : relation_trio rel = TRIO_VARYING) const override;
809 : : bool op2_range (irange &r, tree type,
810 : : const irange &lhs, const irange &op1,
811 : : relation_trio rel = TRIO_VARYING) const override;
812 : : relation_kind lhs_op1_relation (const irange &lhs,
813 : : const irange &op1, const irange &op2,
814 : : relation_kind) const override;
815 : : void update_bitmask (irange &r, const irange &lh,
816 : : const irange &rh) const override;
817 : : // Check compatibility of all operands.
818 : 9840730 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
819 : 9840730 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
820 : : protected:
821 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
822 : : const wide_int &lh_ub, const wide_int &rh_lb,
823 : : const wide_int &rh_ub) const override;
824 : : void simple_op1_range_solver (irange &r, tree type,
825 : : const irange &lhs,
826 : : const irange &op2) const;
827 : : };
828 : :
829 : : class operator_bitwise_or : public range_operator
830 : : {
831 : : public:
832 : : using range_operator::fold_range;
833 : : using range_operator::op1_range;
834 : : using range_operator::op2_range;
835 : : using range_operator::update_bitmask;
836 : :
837 : : bool fold_range (prange &r, tree type,
838 : : const prange &op1,
839 : : const prange &op2,
840 : : relation_trio) const final override;
841 : : bool op1_range (irange &r, tree type,
842 : : const irange &lhs, const irange &op2,
843 : : relation_trio rel = TRIO_VARYING) const override;
844 : : bool op2_range (irange &r, tree type,
845 : : const irange &lhs, const irange &op1,
846 : : relation_trio rel = TRIO_VARYING) const override;
847 : : void update_bitmask (irange &r, const irange &lh,
848 : : const irange &rh) const override;
849 : : // Check compatibility of all operands.
850 : 2879740 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
851 : 2879740 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
852 : : protected:
853 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
854 : : const wide_int &lh_ub, const wide_int &rh_lb,
855 : : const wide_int &rh_ub) const override;
856 : : };
857 : :
858 : : class operator_min : public range_operator
859 : : {
860 : : public:
861 : : using range_operator::fold_range;
862 : : using range_operator::update_bitmask;
863 : : bool fold_range (prange &r, tree type,
864 : : const prange &op1,
865 : : const prange &op2,
866 : : relation_trio) const final override;
867 : : void update_bitmask (irange &r, const irange &lh,
868 : : const irange &rh) const override;
869 : : // Check compatibility of all operands.
870 : 1283545 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
871 : 1283545 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
872 : : protected:
873 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
874 : : const wide_int &lh_ub, const wide_int &rh_lb,
875 : : const wide_int &rh_ub) const override;
876 : : };
877 : :
878 : : class operator_max : public range_operator
879 : : {
880 : : public:
881 : : using range_operator::fold_range;
882 : : using range_operator::update_bitmask;
883 : : bool fold_range (prange &r, tree type,
884 : : const prange &op1,
885 : : const prange &op2,
886 : : relation_trio) const final override;
887 : : void update_bitmask (irange &r, const irange &lh,
888 : : const irange &rh) const override;
889 : : // Check compatibility of all operands.
890 : 673611 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
891 : 673611 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
892 : : protected:
893 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
894 : : const wide_int &lh_ub, const wide_int &rh_lb,
895 : : const wide_int &rh_ub) const override;
896 : : };
897 : : #endif // GCC_RANGE_OP_MIXED_H
|