1 /* Header file for the GIMPLE fold_using_range interface.
2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
4 and Aldy Hernandez <aldyh@redhat.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
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
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #ifndef GCC_GIMPLE_RANGE_FOLD_H
23 #define GCC_GIMPLE_RANGE_FOLD_H
25 // This file is the main include point for gimple range folding.
26 // These routines will fold stmt S into the result irange R.
27 // Any ssa_names on the stmt will be calculated using the range_query
28 // parameter via a call to range_of_expr.
29 // If no range_query is provided, current global range info will be used.
30 // The second variation specifies an edge, and stmt S is recalculated as if
31 // it appeared on that edge.
33 // Fold stmt S into range R using range query Q.
34 bool fold_range (irange
&r
, gimple
*s
, range_query
*q
= NULL
);
35 // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE.
36 bool fold_range (irange
&r
, gimple
*s
, edge on_edge
, range_query
*q
= NULL
);
38 // These routines the operands to be specified when manually folding.
39 // Any excess queries will be drawn from the current range_query.
40 bool fold_range (irange
&r
, gimple
*s
, irange
&r1
);
41 bool fold_range (irange
&r
, gimple
*s
, irange
&r1
, irange
&r2
);
42 bool fold_range (irange
&r
, gimple
*s
, unsigned num_elements
, irange
*vector
);
44 // Return the range_operator pointer for this statement. This routine
45 // can also be used to gate whether a routine is range-ops enabled.
47 static inline range_operator
*
48 gimple_range_handler (const gimple
*s
)
50 if (const gassign
*ass
= dyn_cast
<const gassign
*> (s
))
51 return range_op_handler (gimple_assign_rhs_code (ass
),
52 TREE_TYPE (gimple_assign_lhs (ass
)));
53 if (const gcond
*cond
= dyn_cast
<const gcond
*> (s
))
54 return range_op_handler (gimple_cond_code (cond
),
55 TREE_TYPE (gimple_cond_lhs (cond
)));
59 // Return the type of range which statement S calculates. If the type is
60 // unsupported or no type can be determined, return NULL_TREE.
63 gimple_range_type (const gimple
*s
)
65 tree lhs
= gimple_get_lhs (s
);
66 tree type
= NULL_TREE
;
68 type
= TREE_TYPE (lhs
);
71 enum gimple_code code
= gimple_code (s
);
72 if (code
== GIMPLE_COND
)
73 type
= boolean_type_node
;
74 else if (code
== GIMPLE_PHI
)
75 type
= TREE_TYPE (gimple_phi_result (s
));
76 else if (code
== GIMPLE_CALL
)
78 type
= gimple_call_fntype (s
);
79 // If it has a type, get the return type.
81 type
= TREE_TYPE (type
);
84 if (irange::supports_type_p (type
))
89 // Return EXP if it is an SSA_NAME with a type supported by gimple ranges.
92 gimple_range_ssa_p (tree exp
)
94 if (exp
&& TREE_CODE (exp
) == SSA_NAME
&&
95 !SSA_NAME_IS_VIRTUAL_OPERAND (exp
) &&
96 !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp
) &&
97 irange::supports_type_p (TREE_TYPE (exp
)))
102 // Return true if TYPE1 and TYPE2 are compatible range types.
105 range_compatible_p (tree type1
, tree type2
)
107 // types_compatible_p requires conversion in both directions to be useless.
108 // GIMPLE only requires a cast one way in order to be compatible.
109 // Ranges really only need the sign and precision to be the same.
110 return (TYPE_PRECISION (type1
) == TYPE_PRECISION (type2
)
111 && TYPE_SIGN (type1
) == TYPE_SIGN (type2
));
115 // Source of all operands for fold_using_range and gori_compute.
116 // It abstracts out the source of an operand so it can come from a stmt or
117 // and edge or anywhere a derived class of fur_source wants.
118 // The default simply picks up ranges from the current range_query.
123 fur_source (range_query
*q
= NULL
);
124 inline range_query
*query () { return m_query
; }
125 inline class gori_compute
*gori () { return m_gori
; };
126 virtual bool get_operand (irange
&r
, tree expr
);
127 virtual bool get_phi_operand (irange
&r
, tree expr
, edge e
);
128 virtual relation_kind
query_relation (tree op1
, tree op2
);
129 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
131 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
133 void register_outgoing_edges (gcond
*, irange
&lhs_range
, edge e0
, edge e1
);
135 range_query
*m_query
;
136 gori_compute
*m_gori
;
139 // fur_stmt is the specification for drawing an operand from range_query Q
140 // via a range_of_Expr call on stmt S.
142 class fur_stmt
: public fur_source
145 fur_stmt (gimple
*s
, range_query
*q
= NULL
);
146 virtual bool get_operand (irange
&r
, tree expr
) OVERRIDE
;
147 virtual bool get_phi_operand (irange
&r
, tree expr
, edge e
) OVERRIDE
;
148 virtual relation_kind
query_relation (tree op1
, tree op2
) OVERRIDE
;
153 // This version of fur_source will pick a range from a stmt, and also register
154 // dependencies via a gori_compute object. This is mostly an internal API.
156 class fur_depend
: public fur_stmt
159 fur_depend (gimple
*s
, gori_compute
*gori
, range_query
*q
= NULL
);
160 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
162 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
165 relation_oracle
*m_oracle
;
168 extern tree
gimple_range_operand1 (const gimple
*s
);
169 extern tree
gimple_range_operand2 (const gimple
*s
);
171 // This class uses ranges to fold a gimple statement producinf a range for
172 // the LHS. The source of all operands is supplied via the fur_source class
173 // which provides a range_query as well as a source location and any other
174 // required information.
176 class fold_using_range
179 bool fold_stmt (irange
&r
, gimple
*s
, class fur_source
&src
,
180 tree name
= NULL_TREE
);
182 bool range_of_range_op (irange
&r
, gimple
*s
, fur_source
&src
);
183 bool range_of_call (irange
&r
, gcall
*call
, fur_source
&src
);
184 bool range_of_cond_expr (irange
&r
, gassign
* cond
, fur_source
&src
);
185 bool range_of_address (irange
&r
, gimple
*s
, fur_source
&src
);
186 bool range_of_builtin_call (irange
&r
, gcall
*call
, fur_source
&src
);
187 void range_of_builtin_ubsan_call (irange
&r
, gcall
*call
, tree_code code
,
189 bool range_of_phi (irange
&r
, gphi
*phi
, fur_source
&src
);
190 void range_of_ssa_name_with_loop_info (irange
&, tree
, class loop
*, gphi
*,
192 void relation_fold_and_or (irange
& lhs_range
, gimple
*s
, fur_source
&src
);
194 #endif // GCC_GIMPLE_RANGE_FOLD_H