Home | History | Annotate | Line # | Download | only in gcc
gimple-range-fold.h revision 1.1
      1  1.1  mrg /* Header file for the GIMPLE fold_using_range interface.
      2  1.1  mrg    Copyright (C) 2019-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Andrew MacLeod <amacleod (at) redhat.com>
      4  1.1  mrg    and Aldy Hernandez <aldyh (at) redhat.com>.
      5  1.1  mrg 
      6  1.1  mrg This file is part of GCC.
      7  1.1  mrg 
      8  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      9  1.1  mrg the terms of the GNU General Public License as published by the Free
     10  1.1  mrg Software Foundation; either version 3, or (at your option) any later
     11  1.1  mrg version.
     12  1.1  mrg 
     13  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16  1.1  mrg  for more details.
     17  1.1  mrg 
     18  1.1  mrg You should have received a copy of the GNU General Public License
     19  1.1  mrg along with GCC; see the file COPYING3.  If not see
     20  1.1  mrg <http://www.gnu.org/licenses/>.  */
     21  1.1  mrg 
     22  1.1  mrg #ifndef GCC_GIMPLE_RANGE_FOLD_H
     23  1.1  mrg #define GCC_GIMPLE_RANGE_FOLD_H
     24  1.1  mrg 
     25  1.1  mrg // This file is the main include point for gimple range folding.
     26  1.1  mrg // These routines will fold stmt S into the result irange R.
     27  1.1  mrg // Any ssa_names on the stmt will be calculated using the range_query
     28  1.1  mrg // parameter via a call to range_of_expr.
     29  1.1  mrg // If no range_query is provided, current global range info will be used.
     30  1.1  mrg // The second variation specifies an edge, and stmt S is recalculated as if
     31  1.1  mrg // it appeared on that edge.
     32  1.1  mrg 
     33  1.1  mrg // Fold stmt S into range R using range query Q.
     34  1.1  mrg bool fold_range (irange &r, gimple *s, range_query *q = NULL);
     35  1.1  mrg // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE.
     36  1.1  mrg bool fold_range (irange &r, gimple *s, edge on_edge, range_query *q = NULL);
     37  1.1  mrg 
     38  1.1  mrg // These routines the operands to be specified when manually folding.
     39  1.1  mrg // Any excess queries will be drawn from the current range_query.
     40  1.1  mrg bool fold_range (irange &r, gimple *s, irange &r1);
     41  1.1  mrg bool fold_range (irange &r, gimple *s, irange &r1, irange &r2);
     42  1.1  mrg bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector);
     43  1.1  mrg 
     44  1.1  mrg // Return the range_operator pointer for this statement.  This routine
     45  1.1  mrg // can also be used to gate whether a routine is range-ops enabled.
     46  1.1  mrg 
     47  1.1  mrg static inline range_operator *
     48  1.1  mrg gimple_range_handler (const gimple *s)
     49  1.1  mrg {
     50  1.1  mrg   if (const gassign *ass = dyn_cast<const gassign *> (s))
     51  1.1  mrg     return range_op_handler (gimple_assign_rhs_code (ass),
     52  1.1  mrg 			     TREE_TYPE (gimple_assign_lhs (ass)));
     53  1.1  mrg   if (const gcond *cond = dyn_cast<const gcond *> (s))
     54  1.1  mrg     return range_op_handler (gimple_cond_code (cond),
     55  1.1  mrg 			     TREE_TYPE (gimple_cond_lhs (cond)));
     56  1.1  mrg   return NULL;
     57  1.1  mrg }
     58  1.1  mrg 
     59  1.1  mrg // Return the type of range which statement S calculates.  If the type is
     60  1.1  mrg // unsupported or no type can be determined, return NULL_TREE.
     61  1.1  mrg 
     62  1.1  mrg static inline tree
     63  1.1  mrg gimple_range_type (const gimple *s)
     64  1.1  mrg {
     65  1.1  mrg   tree lhs = gimple_get_lhs (s);
     66  1.1  mrg   tree type = NULL_TREE;
     67  1.1  mrg   if (lhs)
     68  1.1  mrg     type = TREE_TYPE (lhs);
     69  1.1  mrg   else
     70  1.1  mrg     {
     71  1.1  mrg       enum gimple_code code = gimple_code (s);
     72  1.1  mrg       if (code == GIMPLE_COND)
     73  1.1  mrg 	type = boolean_type_node;
     74  1.1  mrg       else if (code == GIMPLE_PHI)
     75  1.1  mrg 	type = TREE_TYPE (gimple_phi_result (s));
     76  1.1  mrg       else if (code == GIMPLE_CALL)
     77  1.1  mrg 	{
     78  1.1  mrg 	  type = gimple_call_fntype (s);
     79  1.1  mrg 	  // If it has a type, get the return type.
     80  1.1  mrg 	  if (type)
     81  1.1  mrg 	    type = TREE_TYPE (type);
     82  1.1  mrg 	}
     83  1.1  mrg     }
     84  1.1  mrg   if (irange::supports_type_p (type))
     85  1.1  mrg     return type;
     86  1.1  mrg   return NULL_TREE;
     87  1.1  mrg }
     88  1.1  mrg 
     89  1.1  mrg // Return EXP if it is an SSA_NAME with a type supported by gimple ranges.
     90  1.1  mrg 
     91  1.1  mrg static inline tree
     92  1.1  mrg gimple_range_ssa_p (tree exp)
     93  1.1  mrg {
     94  1.1  mrg   if (exp && TREE_CODE (exp) == SSA_NAME &&
     95  1.1  mrg       !SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
     96  1.1  mrg       !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
     97  1.1  mrg       irange::supports_type_p (TREE_TYPE (exp)))
     98  1.1  mrg     return exp;
     99  1.1  mrg   return NULL_TREE;
    100  1.1  mrg }
    101  1.1  mrg 
    102  1.1  mrg // Return true if TYPE1 and TYPE2 are compatible range types.
    103  1.1  mrg 
    104  1.1  mrg static inline bool
    105  1.1  mrg range_compatible_p (tree type1, tree type2)
    106  1.1  mrg {
    107  1.1  mrg   // types_compatible_p requires conversion in both directions to be useless.
    108  1.1  mrg   // GIMPLE only requires a cast one way in order to be compatible.
    109  1.1  mrg   // Ranges really only need the sign and precision to be the same.
    110  1.1  mrg   return (TYPE_PRECISION (type1) == TYPE_PRECISION (type2)
    111  1.1  mrg 	  && TYPE_SIGN (type1) == TYPE_SIGN (type2));
    112  1.1  mrg }
    113  1.1  mrg 
    114  1.1  mrg 
    115  1.1  mrg // Source of all operands for fold_using_range and gori_compute.
    116  1.1  mrg // It abstracts out the source of an operand so it can come from a stmt or
    117  1.1  mrg // and edge or anywhere a derived class of fur_source wants.
    118  1.1  mrg // The default simply picks up ranges from the current range_query.
    119  1.1  mrg 
    120  1.1  mrg class fur_source
    121  1.1  mrg {
    122  1.1  mrg public:
    123  1.1  mrg   fur_source (range_query *q = NULL);
    124  1.1  mrg   inline range_query *query () { return m_query; }
    125  1.1  mrg   inline class gori_compute *gori () { return m_gori; };
    126  1.1  mrg   virtual bool get_operand (irange &r, tree expr);
    127  1.1  mrg   virtual bool get_phi_operand (irange &r, tree expr, edge e);
    128  1.1  mrg   virtual relation_kind query_relation (tree op1, tree op2);
    129  1.1  mrg   virtual void register_relation (gimple *stmt, relation_kind k, tree op1,
    130  1.1  mrg 				  tree op2);
    131  1.1  mrg   virtual void register_relation (edge e, relation_kind k, tree op1,
    132  1.1  mrg 				  tree op2);
    133  1.1  mrg   void register_outgoing_edges (gcond *, irange &lhs_range, edge e0, edge e1);
    134  1.1  mrg protected:
    135  1.1  mrg   range_query *m_query;
    136  1.1  mrg   gori_compute *m_gori;
    137  1.1  mrg };
    138  1.1  mrg 
    139  1.1  mrg // fur_stmt is the specification for drawing an operand from range_query Q
    140  1.1  mrg // via a range_of_Expr call on stmt S.
    141  1.1  mrg 
    142  1.1  mrg class fur_stmt : public fur_source
    143  1.1  mrg {
    144  1.1  mrg public:
    145  1.1  mrg   fur_stmt (gimple *s, range_query *q = NULL);
    146  1.1  mrg   virtual bool get_operand (irange &r, tree expr) OVERRIDE;
    147  1.1  mrg   virtual bool get_phi_operand (irange &r, tree expr, edge e) OVERRIDE;
    148  1.1  mrg   virtual relation_kind query_relation (tree op1, tree op2) OVERRIDE;
    149  1.1  mrg private:
    150  1.1  mrg   gimple *m_stmt;
    151  1.1  mrg };
    152  1.1  mrg 
    153  1.1  mrg // This version of fur_source will pick a range from a stmt, and also register
    154  1.1  mrg // dependencies via a gori_compute object.  This is mostly an internal API.
    155  1.1  mrg 
    156  1.1  mrg class fur_depend : public fur_stmt
    157  1.1  mrg {
    158  1.1  mrg public:
    159  1.1  mrg   fur_depend (gimple *s, gori_compute *gori, range_query *q = NULL);
    160  1.1  mrg   virtual void register_relation (gimple *stmt, relation_kind k, tree op1,
    161  1.1  mrg 				  tree op2) OVERRIDE;
    162  1.1  mrg   virtual void register_relation (edge e, relation_kind k, tree op1,
    163  1.1  mrg 				  tree op2) OVERRIDE;
    164  1.1  mrg protected:
    165  1.1  mrg   relation_oracle *m_oracle;
    166  1.1  mrg };
    167  1.1  mrg 
    168  1.1  mrg extern tree gimple_range_operand1 (const gimple *s);
    169  1.1  mrg extern tree gimple_range_operand2 (const gimple *s);
    170  1.1  mrg 
    171  1.1  mrg // This class uses ranges to fold a gimple statement producinf a range for
    172  1.1  mrg // the LHS.  The source of all operands is supplied via the fur_source class
    173  1.1  mrg // which provides a range_query as well as a source location and any other
    174  1.1  mrg // required information.
    175  1.1  mrg 
    176  1.1  mrg class fold_using_range
    177  1.1  mrg {
    178  1.1  mrg public:
    179  1.1  mrg   bool fold_stmt (irange &r, gimple *s, class fur_source &src,
    180  1.1  mrg 		  tree name = NULL_TREE);
    181  1.1  mrg protected:
    182  1.1  mrg   bool range_of_range_op (irange &r, gimple *s, fur_source &src);
    183  1.1  mrg   bool range_of_call (irange &r, gcall *call, fur_source &src);
    184  1.1  mrg   bool range_of_cond_expr (irange &r, gassign* cond, fur_source &src);
    185  1.1  mrg   bool range_of_address (irange &r, gimple *s, fur_source &src);
    186  1.1  mrg   bool range_of_builtin_call (irange &r, gcall *call, fur_source &src);
    187  1.1  mrg   void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code,
    188  1.1  mrg 				    fur_source &src);
    189  1.1  mrg   bool range_of_phi (irange &r, gphi *phi, fur_source &src);
    190  1.1  mrg   void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, gphi *,
    191  1.1  mrg 					 fur_source &src);
    192  1.1  mrg   void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src);
    193  1.1  mrg };
    194  1.1  mrg #endif // GCC_GIMPLE_RANGE_FOLD_H
    195