LCOV - code coverage report
Current view: top level - gcc - range-op-mixed.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 54 54
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 20 20
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.