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 irange::supports_type_p (TREE_TYPE (exp
)))
101 // Return true if TYPE1 and TYPE2 are compatible range types.
104 range_compatible_p (tree type1
, tree type2
)
106 // types_compatible_p requires conversion in both directions to be useless.
107 // GIMPLE only requires a cast one way in order to be compatible.
108 // Ranges really only need the sign and precision to be the same.
109 return (TYPE_PRECISION (type1
) == TYPE_PRECISION (type2
)
110 && TYPE_SIGN (type1
) == TYPE_SIGN (type2
));
114 // Source of all operands for fold_using_range and gori_compute.
115 // It abstracts out the source of an operand so it can come from a stmt or
116 // and edge or anywhere a derived class of fur_source wants.
117 // The default simply picks up ranges from the current range_query.
122 fur_source (range_query
*q
= NULL
);
123 inline range_query
*query () { return m_query
; }
124 inline class gori_compute
*gori () { return m_gori
; };
125 virtual bool get_operand (irange
&r
, tree expr
);
126 virtual bool get_phi_operand (irange
&r
, tree expr
, edge e
);
127 virtual relation_kind
query_relation (tree op1
, tree op2
);
128 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
130 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
132 void register_outgoing_edges (gcond
*, irange
&lhs_range
, edge e0
, edge e1
);
134 range_query
*m_query
;
135 gori_compute
*m_gori
;
138 // fur_stmt is the specification for drawing an operand from range_query Q
139 // via a range_of_Expr call on stmt S.
141 class fur_stmt
: public fur_source
144 fur_stmt (gimple
*s
, range_query
*q
= NULL
);
145 virtual bool get_operand (irange
&r
, tree expr
) OVERRIDE
;
146 virtual bool get_phi_operand (irange
&r
, tree expr
, edge e
) OVERRIDE
;
147 virtual relation_kind
query_relation (tree op1
, tree op2
) OVERRIDE
;
152 // This version of fur_source will pick a range from a stmt, and also register
153 // dependencies via a gori_compute object. This is mostly an internal API.
155 class fur_depend
: public fur_stmt
158 fur_depend (gimple
*s
, gori_compute
*gori
, range_query
*q
= NULL
);
159 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
161 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
164 relation_oracle
*m_oracle
;
167 extern tree
gimple_range_operand1 (const gimple
*s
);
168 extern tree
gimple_range_operand2 (const gimple
*s
);
170 // This class uses ranges to fold a gimple statement producinf a range for
171 // the LHS. The source of all operands is supplied via the fur_source class
172 // which provides a range_query as well as a source location and any other
173 // required information.
175 class fold_using_range
178 bool fold_stmt (irange
&r
, gimple
*s
, class fur_source
&src
,
179 tree name
= NULL_TREE
);
181 bool range_of_range_op (irange
&r
, gimple
*s
, fur_source
&src
);
182 bool range_of_call (irange
&r
, gcall
*call
, fur_source
&src
);
183 bool range_of_cond_expr (irange
&r
, gassign
* cond
, fur_source
&src
);
184 bool range_of_address (irange
&r
, gimple
*s
, fur_source
&src
);
185 bool range_of_builtin_call (irange
&r
, gcall
*call
, fur_source
&src
);
186 void range_of_builtin_ubsan_call (irange
&r
, gcall
*call
, tree_code code
,
188 bool range_of_phi (irange
&r
, gphi
*phi
, fur_source
&src
);
189 void range_of_ssa_name_with_loop_info (irange
&, tree
, class loop
*, gphi
*,
191 void relation_fold_and_or (irange
& lhs_range
, gimple
*s
, fur_source
&src
);
193 #endif // GCC_GIMPLE_RANGE_FOLD_H