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 (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 : 15638575 : wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
35 : : {
36 : 15638575 : signop sign = TYPE_SIGN (type);
37 : 15638575 : 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 : 1568115 : wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
44 : : {
45 : 1568115 : unsigned prec = TYPE_PRECISION (type);
46 : 1905317 : 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 : 241292706 : empty_range_varying (vrange &r, tree type,
60 : : const vrange &op1, const vrange & op2)
61 : : {
62 : 241220057 : if (op1.undefined_p () || op2.undefined_p ())
63 : : {
64 : 3819286 : r.set_varying (type);
65 : 3737107 : 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 : 73613435 : relop_early_resolve (irange &r, tree type, const vrange &op1,
78 : : const vrange &op2, relation_trio trio,
79 : : relation_kind my_rel)
80 : : {
81 : 73613435 : relation_kind rel = trio.op1_op2 ();
82 : : // If known relation is a complete subset of this relation, always true.
83 : 73613435 : if (relation_union (rel, my_rel) == my_rel)
84 : : {
85 : 34775 : r = range_true (type);
86 : 34775 : return true;
87 : : }
88 : :
89 : : // If known relation has no subset of this relation, always false.
90 : 73578660 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
91 : : {
92 : 43155 : r = range_false (type);
93 : 43155 : return true;
94 : : }
95 : :
96 : : // If either operand is undefined, return VARYING.
97 : 73535505 : if (empty_range_varying (r, type, op1, op2))
98 : 82179 : 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 : 33774512 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
155 : 33774512 : { 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 : 53305149 : bool operand_check_p (tree t0, tree t1, tree t2) const final override
206 : 53305149 : { 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 : 12832088 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
254 : 12832088 : { 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 : 10331900 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
305 : 10331900 : { 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 : 22610644 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
355 : 22610644 : { 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 : 6547213 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
406 : 6547213 : { 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 op1_range (irange &r, tree type,
477 : : const irange &lhs, const irange &op2,
478 : : relation_trio rel = TRIO_VARYING) const final override;
479 : : bool op1_range (prange &r, tree type,
480 : : const prange &lhs, const prange &op2,
481 : : relation_trio rel = TRIO_VARYING) const final override;
482 : : bool op1_range (irange &r, tree type,
483 : : const prange &lhs, const irange &op2,
484 : : relation_trio rel = TRIO_VARYING) const final override;
485 : : bool op1_range (prange &r, tree type,
486 : : const irange &lhs, const prange &op2,
487 : : relation_trio rel = TRIO_VARYING) const final override;
488 : : relation_kind lhs_op1_relation (const irange &lhs,
489 : : const irange &op1, const irange &op2,
490 : : relation_kind) const final override;
491 : : relation_kind lhs_op1_relation (const prange &lhs,
492 : : const prange &op1, const prange &op2,
493 : : relation_kind) const final override;
494 : : relation_kind lhs_op1_relation (const prange &lhs,
495 : : const irange &op1, const irange &op2,
496 : : relation_kind) const final override;
497 : : relation_kind lhs_op1_relation (const irange &lhs,
498 : : const prange &op1, const prange &op2,
499 : : relation_kind) const final override;
500 : : void update_bitmask (irange &r, const irange &lh,
501 : : const irange &rh) const final override;
502 : : private:
503 : : bool truncating_cast_p (const irange &inner, const irange &outer) const;
504 : : bool inside_domain_p (const wide_int &min, const wide_int &max,
505 : : const irange &outer) const;
506 : : void fold_pair (irange &r, unsigned index, const irange &inner,
507 : : const irange &outer) const;
508 : : };
509 : :
510 : : class operator_plus : public range_operator
511 : : {
512 : : public:
513 : : using range_operator::op1_range;
514 : : using range_operator::op2_range;
515 : : using range_operator::lhs_op1_relation;
516 : : using range_operator::lhs_op2_relation;
517 : : using range_operator::update_bitmask;
518 : : bool op1_range (irange &r, tree type,
519 : : const irange &lhs, const irange &op2,
520 : : relation_trio) const final override;
521 : : bool op1_range (frange &r, tree type,
522 : : const frange &lhs, const frange &op2,
523 : : relation_trio = TRIO_VARYING) const final override;
524 : :
525 : : bool op2_range (irange &r, tree type,
526 : : const irange &lhs, const irange &op1,
527 : : relation_trio) const final override;
528 : : bool op2_range (frange &r, tree type,
529 : : const frange &lhs, const frange &op1,
530 : : relation_trio = TRIO_VARYING) const final override;
531 : :
532 : : relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
533 : : const irange &op2,
534 : : relation_kind rel) const final override;
535 : : relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
536 : : const irange &op2,
537 : : relation_kind rel) const final override;
538 : : void update_bitmask (irange &r, const irange &lh,
539 : : const irange &rh) const final override;
540 : :
541 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
542 : : relation_trio = TRIO_VARYING) const;
543 : : // Check compatibility of all operands.
544 : 47574188 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
545 : 47574188 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
546 : : private:
547 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
548 : : const wide_int &lh_ub, const wide_int &rh_lb,
549 : : const wide_int &rh_ub) const final override;
550 : : void rv_fold (frange &r, tree type,
551 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
552 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
553 : : relation_kind) const final override;
554 : : };
555 : :
556 : : class operator_abs : public range_operator
557 : : {
558 : : public:
559 : : using range_operator::fold_range;
560 : : using range_operator::op1_range;
561 : : using range_operator::update_bitmask;
562 : : bool fold_range (frange &r, tree type,
563 : : const frange &op1, const frange &,
564 : : relation_trio = TRIO_VARYING) const final override;
565 : :
566 : : bool op1_range (irange &r, tree type, const irange &lhs,
567 : : const irange &op2, relation_trio) const final override;
568 : : bool op1_range (frange &r, tree type,
569 : : const frange &lhs, const frange &op2,
570 : : relation_trio rel = TRIO_VARYING) const final override;
571 : : void update_bitmask (irange &r, const irange &lh,
572 : : const irange &rh) const final override;
573 : : // Check compatibility of LHS and op1.
574 : 848506 : bool operand_check_p (tree t1, tree t2, tree) const final override
575 : 848506 : { return range_compatible_p (t1, t2); }
576 : : private:
577 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
578 : : const wide_int &lh_ub, const wide_int &rh_lb,
579 : : const wide_int &rh_ub) const final override;
580 : :
581 : : };
582 : :
583 : : class operator_minus : public range_operator
584 : : {
585 : : public:
586 : : using range_operator::fold_range;
587 : : using range_operator::op1_range;
588 : : using range_operator::op2_range;
589 : : using range_operator::lhs_op1_relation;
590 : : using range_operator::op1_op2_relation_effect;
591 : : using range_operator::update_bitmask;
592 : : bool op1_range (irange &r, tree type,
593 : : const irange &lhs, const irange &op2,
594 : : relation_trio) const final override;
595 : : bool op1_range (frange &r, tree type,
596 : : const frange &lhs, const frange &op2,
597 : : relation_trio = TRIO_VARYING) const final override;
598 : :
599 : : bool op2_range (irange &r, tree type,
600 : : const irange &lhs, const irange &op1,
601 : : relation_trio) const final override;
602 : : bool op2_range (frange &r, tree type,
603 : : const frange &lhs,
604 : : const frange &op1,
605 : : relation_trio = TRIO_VARYING) const final override;
606 : :
607 : : relation_kind lhs_op1_relation (const irange &lhs,
608 : : const irange &op1, const irange &op2,
609 : : relation_kind rel) const final override;
610 : : bool op1_op2_relation_effect (irange &lhs_range, tree type,
611 : : const irange &op1_range,
612 : : const irange &op2_range,
613 : : relation_kind rel) const final override;
614 : : void update_bitmask (irange &r, const irange &lh,
615 : : const irange &rh) const final override;
616 : :
617 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
618 : : relation_trio = TRIO_VARYING) const;
619 : : // Check compatibility of all operands.
620 : 13625033 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
621 : 13625033 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
622 : : private:
623 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
624 : : const wide_int &lh_ub, const wide_int &rh_lb,
625 : : const wide_int &rh_ub) const final override;
626 : : void rv_fold (frange &r, tree type,
627 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
628 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
629 : : relation_kind) const final override;
630 : : };
631 : :
632 : : class operator_negate : public range_operator
633 : : {
634 : : public:
635 : : using range_operator::fold_range;
636 : : using range_operator::op1_range;
637 : : bool fold_range (irange &r, tree type,
638 : : const irange &op1, const irange &op2,
639 : : relation_trio rel = TRIO_VARYING) const final override;
640 : : bool fold_range (frange &r, tree type,
641 : : const frange &op1, const frange &op2,
642 : : relation_trio = TRIO_VARYING) const final override;
643 : :
644 : : bool op1_range (irange &r, tree type,
645 : : const irange &lhs, const irange &op2,
646 : : relation_trio rel = TRIO_VARYING) const final override;
647 : : bool op1_range (frange &r, tree type,
648 : : const frange &lhs, const frange &op2,
649 : : relation_trio rel = TRIO_VARYING) const final override;
650 : : // Check compatibility of LHS and op1.
651 : 714225 : bool operand_check_p (tree t1, tree t2, tree) const final override
652 : 714225 : { return range_compatible_p (t1, t2); }
653 : : };
654 : :
655 : :
656 : : class cross_product_operator : public range_operator
657 : : {
658 : : public:
659 : : virtual bool wi_op_overflows (wide_int &r,
660 : : tree type,
661 : : const wide_int &,
662 : : const wide_int &) const = 0;
663 : : void wi_cross_product (irange &r, tree type,
664 : : const wide_int &lh_lb,
665 : : const wide_int &lh_ub,
666 : : const wide_int &rh_lb,
667 : : const wide_int &rh_ub) const;
668 : : };
669 : :
670 : : class operator_mult : public cross_product_operator
671 : : {
672 : : public:
673 : : using range_operator::op1_range;
674 : : using range_operator::op2_range;
675 : : using range_operator::update_bitmask;
676 : : bool op1_range (irange &r, tree type,
677 : : const irange &lhs, const irange &op2,
678 : : relation_trio) const final override;
679 : : bool op1_range (frange &r, tree type,
680 : : const frange &lhs, const frange &op2,
681 : : relation_trio = TRIO_VARYING) const final override;
682 : :
683 : : bool op2_range (irange &r, tree type,
684 : : const irange &lhs, const irange &op1,
685 : : relation_trio) const final override;
686 : : bool op2_range (frange &r, tree type,
687 : : const frange &lhs, const frange &op1,
688 : : relation_trio = TRIO_VARYING) const final override;
689 : :
690 : : void update_bitmask (irange &r, const irange &lh,
691 : : const irange &rh) const final override;
692 : :
693 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
694 : : const wide_int &lh_ub, const wide_int &rh_lb,
695 : : const wide_int &rh_ub) const final override;
696 : : bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
697 : : const wide_int &w1) const final override;
698 : :
699 : : void rv_fold (frange &r, tree type,
700 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
701 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
702 : : relation_kind kind) const final override;
703 : : virtual bool overflow_free_p (const irange &lh, const irange &rh,
704 : : relation_trio = TRIO_VARYING) const;
705 : : // Check compatibility of all operands.
706 : 12192775 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
707 : 12192775 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
708 : : };
709 : :
710 : : class operator_addr_expr : public range_operator
711 : : {
712 : : public:
713 : : using range_operator::fold_range;
714 : : using range_operator::op1_range;
715 : : bool fold_range (irange &r, tree type,
716 : : const irange &op1, const irange &op2,
717 : : relation_trio rel = TRIO_VARYING) const final override;
718 : : bool op1_range (irange &r, tree type,
719 : : const irange &lhs, const irange &op2,
720 : : relation_trio rel = TRIO_VARYING) const final override;
721 : : bool op1_range (prange &r, tree type,
722 : : const prange &lhs, const prange &op2,
723 : : relation_trio rel = TRIO_VARYING) const final override;
724 : : };
725 : :
726 : : class operator_bitwise_not : public range_operator
727 : : {
728 : : public:
729 : : using range_operator::fold_range;
730 : : using range_operator::op1_range;
731 : : using range_operator::update_bitmask;
732 : : bool fold_range (irange &r, tree type,
733 : : const irange &lh, const irange &rh,
734 : : relation_trio rel = TRIO_VARYING) const final override;
735 : : bool op1_range (irange &r, tree type,
736 : : const irange &lhs, const irange &op2,
737 : : relation_trio rel = TRIO_VARYING) const final override;
738 : : void update_bitmask (irange &r, const irange &lh,
739 : : const irange &rh) const final override;
740 : : // Check compatibility of all operands.
741 : 475678 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
742 : 475678 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
743 : : };
744 : :
745 : : class operator_bitwise_xor : public range_operator
746 : : {
747 : : public:
748 : : using range_operator::op1_range;
749 : : using range_operator::op2_range;
750 : : using range_operator::op1_op2_relation_effect;
751 : : using range_operator::update_bitmask;
752 : : bool op1_range (irange &r, tree type,
753 : : const irange &lhs, const irange &op2,
754 : : relation_trio rel = TRIO_VARYING) const final override;
755 : : bool op2_range (irange &r, tree type,
756 : : const irange &lhs, const irange &op1,
757 : : relation_trio rel = TRIO_VARYING) const final override;
758 : : bool op1_op2_relation_effect (irange &lhs_range,
759 : : tree type,
760 : : const irange &op1_range,
761 : : const irange &op2_range,
762 : : relation_kind rel) const final override;
763 : : void update_bitmask (irange &r, const irange &lh,
764 : : const irange &rh) const final override;
765 : : // Check compatibility of all operands.
766 : 294462 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
767 : 294462 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
768 : : private:
769 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
770 : : const wide_int &lh_ub, const wide_int &rh_lb,
771 : : const wide_int &rh_ub) const final override;
772 : : };
773 : :
774 : : class operator_bitwise_and : public range_operator
775 : : {
776 : : public:
777 : : using range_operator::fold_range;
778 : : using range_operator::op1_range;
779 : : using range_operator::op2_range;
780 : : using range_operator::lhs_op1_relation;
781 : : using range_operator::update_bitmask;
782 : : bool fold_range (prange &r, tree type,
783 : : const prange &op1,
784 : : const prange &op2,
785 : : relation_trio) const final override;
786 : : bool op1_range (irange &r, tree type,
787 : : const irange &lhs, const irange &op2,
788 : : relation_trio rel = TRIO_VARYING) const override;
789 : : bool op2_range (irange &r, tree type,
790 : : const irange &lhs, const irange &op1,
791 : : relation_trio rel = TRIO_VARYING) const override;
792 : : relation_kind lhs_op1_relation (const irange &lhs,
793 : : const irange &op1, const irange &op2,
794 : : relation_kind) const override;
795 : : void update_bitmask (irange &r, const irange &lh,
796 : : const irange &rh) const override;
797 : : // Check compatibility of all operands.
798 : 8875365 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
799 : 8875365 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
800 : : protected:
801 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
802 : : const wide_int &lh_ub, const wide_int &rh_lb,
803 : : const wide_int &rh_ub) const override;
804 : : void simple_op1_range_solver (irange &r, tree type,
805 : : const irange &lhs,
806 : : const irange &op2) const;
807 : : };
808 : :
809 : : class operator_bitwise_or : public range_operator
810 : : {
811 : : public:
812 : : using range_operator::fold_range;
813 : : using range_operator::op1_range;
814 : : using range_operator::op2_range;
815 : : using range_operator::update_bitmask;
816 : :
817 : : bool fold_range (prange &r, tree type,
818 : : const prange &op1,
819 : : const prange &op2,
820 : : relation_trio) const final override;
821 : : bool op1_range (irange &r, tree type,
822 : : const irange &lhs, const irange &op2,
823 : : relation_trio rel = TRIO_VARYING) const override;
824 : : bool op2_range (irange &r, tree type,
825 : : const irange &lhs, const irange &op1,
826 : : relation_trio rel = TRIO_VARYING) const override;
827 : : void update_bitmask (irange &r, const irange &lh,
828 : : const irange &rh) const override;
829 : : // Check compatibility of all operands.
830 : 2655862 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
831 : 2655862 : { 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 : : };
837 : :
838 : : class operator_min : public range_operator
839 : : {
840 : : public:
841 : : using range_operator::fold_range;
842 : : using range_operator::update_bitmask;
843 : : bool fold_range (prange &r, tree type,
844 : : const prange &op1,
845 : : const prange &op2,
846 : : relation_trio) const final override;
847 : : void update_bitmask (irange &r, const irange &lh,
848 : : const irange &rh) const override;
849 : : // Check compatibility of all operands.
850 : 1209623 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
851 : 1209623 : { 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_max : 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 : 619203 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
871 : 619203 : { 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 : : #endif // GCC_RANGE_OP_MIXED_H
|