Require target lra in gcc.c-torture/compile/asmgoto-6.c
[official-gcc.git] / gcc / range-op-mixed.h
blob6944742ecbc1015fbdb12ffec575382fb788faae
1 /* Header file for mixed range operator class.
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
4 and Aldy Hernandez <aldyh@redhat.com>.
6 This file is part of GCC.
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.
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.
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/>. */
22 #ifndef GCC_RANGE_OP_MIXED_H
23 #define GCC_RANGE_OP_MIXED_H
25 void update_known_bitmask (irange &, tree_code, const irange &, const irange &);
26 bool minus_op1_op2_relation_effect (irange &lhs_range, tree type,
27 const irange &, const irange &,
28 relation_kind rel);
31 // Return TRUE if 0 is within [WMIN, WMAX].
33 inline bool
34 wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
36 signop sign = TYPE_SIGN (type);
37 return wi::le_p (wmin, 0, sign) && wi::ge_p (wmax, 0, sign);
40 // Return TRUE if [WMIN, WMAX] is the singleton 0.
42 inline bool
43 wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
45 unsigned prec = TYPE_PRECISION (type);
46 return wmin == wmax && wi::eq_p (wmin, wi::zero (prec));
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);
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.
58 inline bool
59 empty_range_varying (vrange &r, tree type,
60 const vrange &op1, const vrange & op2)
62 if (op1.undefined_p () || op2.undefined_p ())
64 r.set_varying (type);
65 return true;
67 else
68 return false;
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.
76 inline bool
77 relop_early_resolve (irange &r, tree type, const vrange &op1,
78 const vrange &op2, relation_trio trio,
79 relation_kind my_rel)
81 relation_kind rel = trio.op1_op2 ();
82 // If known relation is a complete subset of this relation, always true.
83 if (relation_union (rel, my_rel) == my_rel)
85 r = range_true (type);
86 return true;
89 // If known relation has no subset of this relation, always false.
90 if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
92 r = range_false (type);
93 return true;
96 // If either operand is undefined, return VARYING.
97 if (empty_range_varying (r, type, op1, op2))
98 return true;
100 return false;
103 // ----------------------------------------------------------------------
104 // Mixed Mode Operators.
105 // ----------------------------------------------------------------------
107 class operator_equal : public range_operator
109 public:
110 using range_operator::fold_range;
111 using range_operator::op1_range;
112 using range_operator::op2_range;
113 using range_operator::op1_op2_relation;
114 bool fold_range (irange &r, tree type,
115 const irange &op1, const irange &op2,
116 relation_trio = TRIO_VARYING) const final override;
117 bool fold_range (irange &r, tree type,
118 const frange &op1, const frange &op2,
119 relation_trio = TRIO_VARYING) const final override;
121 bool op1_range (irange &r, tree type,
122 const irange &lhs, const irange &val,
123 relation_trio = TRIO_VARYING) const final override;
124 bool op1_range (frange &r, tree type,
125 const irange &lhs, const frange &op2,
126 relation_trio = TRIO_VARYING) const final override;
128 bool op2_range (irange &r, tree type,
129 const irange &lhs, const irange &val,
130 relation_trio = TRIO_VARYING) const final override;
131 bool op2_range (frange &r, tree type,
132 const irange &lhs, const frange &op1,
133 relation_trio rel = TRIO_VARYING) const final override;
135 relation_kind op1_op2_relation (const irange &lhs) const final override;
136 void update_bitmask (irange &r, const irange &lh,
137 const irange &rh) const final override;
140 class operator_not_equal : public range_operator
142 public:
143 using range_operator::fold_range;
144 using range_operator::op1_range;
145 using range_operator::op2_range;
146 using range_operator::op1_op2_relation;
147 bool fold_range (irange &r, tree type,
148 const irange &op1, const irange &op2,
149 relation_trio = TRIO_VARYING) const final override;
150 bool fold_range (irange &r, tree type,
151 const frange &op1, const frange &op2,
152 relation_trio rel = TRIO_VARYING) const final override;
154 bool op1_range (irange &r, tree type,
155 const irange &lhs, const irange &op2,
156 relation_trio = TRIO_VARYING) const final override;
157 bool op1_range (frange &r, tree type,
158 const irange &lhs, const frange &op2,
159 relation_trio = TRIO_VARYING) const final override;
161 bool op2_range (irange &r, tree type,
162 const irange &lhs, const irange &op1,
163 relation_trio = TRIO_VARYING) const final override;
165 relation_kind op1_op2_relation (const irange &lhs) const final override;
166 void update_bitmask (irange &r, const irange &lh,
167 const irange &rh) const final override;
170 class operator_lt : public range_operator
172 public:
173 using range_operator::fold_range;
174 using range_operator::op1_range;
175 using range_operator::op2_range;
176 using range_operator::op1_op2_relation;
177 bool fold_range (irange &r, tree type,
178 const irange &op1, const irange &op2,
179 relation_trio = TRIO_VARYING) const final override;
180 bool fold_range (irange &r, tree type,
181 const frange &op1, const frange &op2,
182 relation_trio = TRIO_VARYING) const final override;
183 bool op1_range (irange &r, tree type,
184 const irange &lhs, const irange &op2,
185 relation_trio = TRIO_VARYING) const final override;
186 bool op1_range (frange &r, tree type,
187 const irange &lhs, const frange &op2,
188 relation_trio = TRIO_VARYING) const final override;
189 bool op2_range (irange &r, tree type,
190 const irange &lhs, const irange &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 relation_kind op1_op2_relation (const irange &lhs) const final override;
196 void update_bitmask (irange &r, const irange &lh,
197 const irange &rh) const final override;
200 class operator_le : public range_operator
202 public:
203 using range_operator::fold_range;
204 using range_operator::op1_range;
205 using range_operator::op2_range;
206 using range_operator::op1_op2_relation;
207 bool fold_range (irange &r, tree type,
208 const irange &op1, const irange &op2,
209 relation_trio = TRIO_VARYING) const final override;
210 bool fold_range (irange &r, tree type,
211 const frange &op1, const frange &op2,
212 relation_trio rel = TRIO_VARYING) const final override;
214 bool op1_range (irange &r, tree type,
215 const irange &lhs, const irange &op2,
216 relation_trio = TRIO_VARYING) const final override;
217 bool op1_range (frange &r, tree type,
218 const irange &lhs, const frange &op2,
219 relation_trio rel = TRIO_VARYING) const final override;
221 bool op2_range (irange &r, tree type,
222 const irange &lhs, const irange &op1,
223 relation_trio = TRIO_VARYING) const final override;
224 bool op2_range (frange &r, tree type,
225 const irange &lhs, const frange &op1,
226 relation_trio rel = TRIO_VARYING) const final override;
228 relation_kind op1_op2_relation (const irange &lhs) const final override;
229 void update_bitmask (irange &r, const irange &lh,
230 const irange &rh) const final override;
233 class operator_gt : public range_operator
235 public:
236 using range_operator::fold_range;
237 using range_operator::op1_range;
238 using range_operator::op2_range;
239 using range_operator::op1_op2_relation;
240 bool fold_range (irange &r, tree type,
241 const irange &op1, const irange &op2,
242 relation_trio = TRIO_VARYING) const final override;
243 bool fold_range (irange &r, tree type,
244 const frange &op1, const frange &op2,
245 relation_trio = TRIO_VARYING) const final override;
247 bool op1_range (irange &r, tree type,
248 const irange &lhs, const irange &op2,
249 relation_trio = TRIO_VARYING) const final override;
250 bool op1_range (frange &r, tree type,
251 const irange &lhs, const frange &op2,
252 relation_trio = TRIO_VARYING) const final override;
254 bool op2_range (irange &r, tree type,
255 const irange &lhs, const irange &op1,
256 relation_trio = TRIO_VARYING) const final override;
257 bool op2_range (frange &r, tree type,
258 const irange &lhs, const frange &op1,
259 relation_trio = TRIO_VARYING) const final override;
260 relation_kind op1_op2_relation (const irange &lhs) const final override;
261 void update_bitmask (irange &r, const irange &lh,
262 const irange &rh) const final override;
265 class operator_ge : public range_operator
267 public:
268 using range_operator::fold_range;
269 using range_operator::op1_range;
270 using range_operator::op2_range;
271 using range_operator::op1_op2_relation;
272 bool fold_range (irange &r, tree type,
273 const irange &op1, const irange &op2,
274 relation_trio = TRIO_VARYING) const final override;
275 bool fold_range (irange &r, tree type,
276 const frange &op1, const frange &op2,
277 relation_trio = TRIO_VARYING) const final override;
279 bool op1_range (irange &r, tree type,
280 const irange &lhs, const irange &op2,
281 relation_trio = TRIO_VARYING) const final override;
282 bool op1_range (frange &r, tree type,
283 const irange &lhs, const frange &op2,
284 relation_trio = TRIO_VARYING) const final override;
286 bool op2_range (irange &r, tree type,
287 const irange &lhs, const irange &op1,
288 relation_trio = TRIO_VARYING) const final override;
289 bool op2_range (frange &r, tree type,
290 const irange &lhs, const frange &op1,
291 relation_trio = TRIO_VARYING) const final override;
293 relation_kind op1_op2_relation (const irange &lhs) const final override;
294 void update_bitmask (irange &r, const irange &lh,
295 const irange &rh) const final override;
298 class operator_identity : public range_operator
300 public:
301 using range_operator::fold_range;
302 using range_operator::op1_range;
303 using range_operator::lhs_op1_relation;
304 bool fold_range (irange &r, tree type,
305 const irange &op1, const irange &op2,
306 relation_trio rel = TRIO_VARYING) const final override;
307 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
308 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
309 relation_trio = TRIO_VARYING) const final override;
310 bool op1_range (irange &r, tree type,
311 const irange &lhs, const irange &op2,
312 relation_trio rel = TRIO_VARYING) const final override;
313 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
314 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
315 relation_trio = TRIO_VARYING) const final override;
316 relation_kind lhs_op1_relation (const irange &lhs,
317 const irange &op1, const irange &op2,
318 relation_kind rel) const final override;
321 class operator_cst : public range_operator
323 public:
324 using range_operator::fold_range;
325 bool fold_range (irange &r, tree type,
326 const irange &op1, const irange &op2,
327 relation_trio rel = TRIO_VARYING) const final override;
328 bool fold_range (frange &r, tree type,
329 const frange &op1, const frange &op2,
330 relation_trio = TRIO_VARYING) const final override;
334 class operator_cast: public range_operator
336 public:
337 using range_operator::fold_range;
338 using range_operator::op1_range;
339 using range_operator::lhs_op1_relation;
340 bool fold_range (irange &r, tree type,
341 const irange &op1, const irange &op2,
342 relation_trio rel = TRIO_VARYING) const final override;
343 bool op1_range (irange &r, tree type,
344 const irange &lhs, const irange &op2,
345 relation_trio rel = TRIO_VARYING) const final override;
346 relation_kind lhs_op1_relation (const irange &lhs,
347 const irange &op1, const irange &op2,
348 relation_kind) const final override;
349 private:
350 bool truncating_cast_p (const irange &inner, const irange &outer) const;
351 bool inside_domain_p (const wide_int &min, const wide_int &max,
352 const irange &outer) const;
353 void fold_pair (irange &r, unsigned index, const irange &inner,
354 const irange &outer) const;
357 class operator_plus : public range_operator
359 public:
360 using range_operator::op1_range;
361 using range_operator::op2_range;
362 using range_operator::lhs_op1_relation;
363 using range_operator::lhs_op2_relation;
364 bool op1_range (irange &r, tree type,
365 const irange &lhs, const irange &op2,
366 relation_trio) const final override;
367 bool op1_range (frange &r, tree type,
368 const frange &lhs, const frange &op2,
369 relation_trio = TRIO_VARYING) const final override;
371 bool op2_range (irange &r, tree type,
372 const irange &lhs, const irange &op1,
373 relation_trio) const final override;
374 bool op2_range (frange &r, tree type,
375 const frange &lhs, const frange &op1,
376 relation_trio = TRIO_VARYING) const final override;
378 relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
379 const irange &op2,
380 relation_kind rel) const final override;
381 relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
382 const irange &op2,
383 relation_kind rel) const final override;
384 void update_bitmask (irange &r, const irange &lh,
385 const irange &rh) const final override;
386 private:
387 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
388 const wide_int &lh_ub, const wide_int &rh_lb,
389 const wide_int &rh_ub) const final override;
390 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
391 bool &maybe_nan, tree type,
392 const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
393 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
394 relation_kind) const final override;
397 class operator_abs : public range_operator
399 public:
400 using range_operator::fold_range;
401 using range_operator::op1_range;
402 bool fold_range (frange &r, tree type,
403 const frange &op1, const frange &,
404 relation_trio = TRIO_VARYING) const final override;
406 bool op1_range (irange &r, tree type, const irange &lhs,
407 const irange &op2, relation_trio) const final override;
408 bool op1_range (frange &r, tree type,
409 const frange &lhs, const frange &op2,
410 relation_trio rel = TRIO_VARYING) const final override;
411 private:
412 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
413 const wide_int &lh_ub, const wide_int &rh_lb,
414 const wide_int &rh_ub) const final override;
418 class operator_minus : public range_operator
420 public:
421 using range_operator::fold_range;
422 using range_operator::op1_range;
423 using range_operator::op2_range;
424 using range_operator::lhs_op1_relation;
425 bool op1_range (irange &r, tree type,
426 const irange &lhs, const irange &op2,
427 relation_trio) const final override;
428 bool op1_range (frange &r, tree type,
429 const frange &lhs, const frange &op2,
430 relation_trio = TRIO_VARYING) const final override;
432 bool op2_range (irange &r, tree type,
433 const irange &lhs, const irange &op1,
434 relation_trio) const final override;
435 bool op2_range (frange &r, tree type,
436 const frange &lhs,
437 const frange &op1,
438 relation_trio = TRIO_VARYING) const final override;
440 relation_kind lhs_op1_relation (const irange &lhs,
441 const irange &op1, const irange &op2,
442 relation_kind rel) const final override;
443 bool op1_op2_relation_effect (irange &lhs_range, tree type,
444 const irange &op1_range,
445 const irange &op2_range,
446 relation_kind rel) const final override;
447 void update_bitmask (irange &r, const irange &lh,
448 const irange &rh) const final override;
449 private:
450 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
451 const wide_int &lh_ub, const wide_int &rh_lb,
452 const wide_int &rh_ub) const final override;
453 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
454 bool &maybe_nan, tree type,
455 const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
456 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
457 relation_kind) const final override;
460 class operator_negate : public range_operator
462 public:
463 using range_operator::fold_range;
464 using range_operator::op1_range;
465 bool fold_range (irange &r, tree type,
466 const irange &op1, const irange &op2,
467 relation_trio rel = TRIO_VARYING) const final override;
468 bool fold_range (frange &r, tree type,
469 const frange &op1, const frange &op2,
470 relation_trio = TRIO_VARYING) const final override;
472 bool op1_range (irange &r, tree type,
473 const irange &lhs, const irange &op2,
474 relation_trio rel = TRIO_VARYING) const final override;
475 bool op1_range (frange &r, tree type,
476 const frange &lhs, const frange &op2,
477 relation_trio rel = TRIO_VARYING) const final override;
481 class cross_product_operator : public range_operator
483 public:
484 virtual bool wi_op_overflows (wide_int &r,
485 tree type,
486 const wide_int &,
487 const wide_int &) const = 0;
488 void wi_cross_product (irange &r, tree type,
489 const wide_int &lh_lb,
490 const wide_int &lh_ub,
491 const wide_int &rh_lb,
492 const wide_int &rh_ub) const;
495 class operator_mult : public cross_product_operator
497 public:
498 using range_operator::op1_range;
499 using range_operator::op2_range;
500 bool op1_range (irange &r, tree type,
501 const irange &lhs, const irange &op2,
502 relation_trio) const final override;
503 bool op1_range (frange &r, tree type,
504 const frange &lhs, const frange &op2,
505 relation_trio = TRIO_VARYING) const final override;
507 bool op2_range (irange &r, tree type,
508 const irange &lhs, const irange &op1,
509 relation_trio) const final override;
510 bool op2_range (frange &r, tree type,
511 const frange &lhs, const frange &op1,
512 relation_trio = TRIO_VARYING) const final override;
514 void update_bitmask (irange &r, const irange &lh,
515 const irange &rh) const final override;
517 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
518 const wide_int &lh_ub, const wide_int &rh_lb,
519 const wide_int &rh_ub) const final override;
520 bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
521 const wide_int &w1) const final override;
523 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
524 bool &maybe_nan, tree type,
525 const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
526 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
527 relation_kind kind) const final override;
530 class operator_addr_expr : public range_operator
532 public:
533 using range_operator::fold_range;
534 using range_operator::op1_range;
535 bool fold_range (irange &r, tree type,
536 const irange &op1, const irange &op2,
537 relation_trio rel = TRIO_VARYING) const final override;
538 bool op1_range (irange &r, tree type,
539 const irange &lhs, const irange &op2,
540 relation_trio rel = TRIO_VARYING) const final override;
543 class operator_bitwise_not : public range_operator
545 public:
546 using range_operator::fold_range;
547 using range_operator::op1_range;
548 bool fold_range (irange &r, tree type,
549 const irange &lh, const irange &rh,
550 relation_trio rel = TRIO_VARYING) const final override;
551 bool op1_range (irange &r, tree type,
552 const irange &lhs, const irange &op2,
553 relation_trio rel = TRIO_VARYING) const final override;
556 class operator_bitwise_xor : public range_operator
558 public:
559 using range_operator::op1_range;
560 using range_operator::op2_range;
561 bool op1_range (irange &r, tree type,
562 const irange &lhs, const irange &op2,
563 relation_trio rel = TRIO_VARYING) const final override;
564 bool op2_range (irange &r, tree type,
565 const irange &lhs, const irange &op1,
566 relation_trio rel = TRIO_VARYING) const final override;
567 bool op1_op2_relation_effect (irange &lhs_range,
568 tree type,
569 const irange &op1_range,
570 const irange &op2_range,
571 relation_kind rel) const;
572 void update_bitmask (irange &r, const irange &lh,
573 const irange &rh) const final override;
574 private:
575 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
576 const wide_int &lh_ub, const wide_int &rh_lb,
577 const wide_int &rh_ub) const final override;
580 class operator_bitwise_and : public range_operator
582 public:
583 using range_operator::op1_range;
584 using range_operator::op2_range;
585 using range_operator::lhs_op1_relation;
586 bool op1_range (irange &r, tree type,
587 const irange &lhs, const irange &op2,
588 relation_trio rel = TRIO_VARYING) const override;
589 bool op2_range (irange &r, tree type,
590 const irange &lhs, const irange &op1,
591 relation_trio rel = TRIO_VARYING) const override;
592 relation_kind lhs_op1_relation (const irange &lhs,
593 const irange &op1, const irange &op2,
594 relation_kind) const override;
595 void update_bitmask (irange &r, const irange &lh,
596 const irange &rh) const override;
597 protected:
598 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
599 const wide_int &lh_ub, const wide_int &rh_lb,
600 const wide_int &rh_ub) const override;
601 void simple_op1_range_solver (irange &r, tree type,
602 const irange &lhs,
603 const irange &op2) const;
606 class operator_bitwise_or : public range_operator
608 public:
609 using range_operator::op1_range;
610 using range_operator::op2_range;
611 bool op1_range (irange &r, tree type,
612 const irange &lhs, const irange &op2,
613 relation_trio rel = TRIO_VARYING) const override;
614 bool op2_range (irange &r, tree type,
615 const irange &lhs, const irange &op1,
616 relation_trio rel = TRIO_VARYING) const override;
617 void update_bitmask (irange &r, const irange &lh,
618 const irange &rh) const override;
619 protected:
620 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
621 const wide_int &lh_ub, const wide_int &rh_lb,
622 const wide_int &rh_ub) const override;
625 class operator_min : public range_operator
627 public:
628 void update_bitmask (irange &r, const irange &lh,
629 const irange &rh) const override;
630 protected:
631 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
632 const wide_int &lh_ub, const wide_int &rh_lb,
633 const wide_int &rh_ub) const override;
636 class operator_max : public range_operator
638 public:
639 void update_bitmask (irange &r, const irange &lh,
640 const irange &rh) const override;
641 protected:
642 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
643 const wide_int &lh_ub, const wide_int &rh_lb,
644 const wide_int &rh_ub) const override;
646 #endif // GCC_RANGE_OP_MIXED_H