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