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