1 /* Header file for the GIMPLE fold_using_range interface.
2 Copyright (C) 2019-2023 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 range 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 (vrange
&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 (vrange
&v
, 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 (vrange
&r
, gimple
*s
, vrange
&r1
, range_query
*q
= NULL
);
41 bool fold_range (vrange
&r
, gimple
*s
, vrange
&r1
, vrange
&r2
,
42 range_query
*q
= NULL
);
43 bool fold_range (vrange
&r
, gimple
*s
, unsigned num_elements
, vrange
**vector
,
44 range_query
*q
= NULL
);
46 // This routine will return a relation trio for stmt S.
47 relation_trio
fold_relations (gimple
*s
, range_query
*q
= NULL
);
49 // Return the type of range which statement S calculates. If the type is
50 // unsupported or no type can be determined, return NULL_TREE.
53 gimple_range_type (const gimple
*s
)
55 tree lhs
= gimple_get_lhs (s
);
56 tree type
= NULL_TREE
;
58 type
= TREE_TYPE (lhs
);
61 enum gimple_code code
= gimple_code (s
);
62 if (code
== GIMPLE_COND
)
63 type
= boolean_type_node
;
64 else if (code
== GIMPLE_PHI
)
65 type
= TREE_TYPE (gimple_phi_result (s
));
66 else if (code
== GIMPLE_CALL
)
68 type
= gimple_call_fntype (s
);
69 // If it has a type, get the return type.
71 type
= TREE_TYPE (type
);
74 if (type
&& Value_Range::supports_type_p (type
))
79 // Return EXP if it is an SSA_NAME with a type supported by gimple ranges.
82 gimple_range_ssa_p (tree exp
)
84 if (exp
&& TREE_CODE (exp
) == SSA_NAME
&&
85 !SSA_NAME_IS_VIRTUAL_OPERAND (exp
) &&
86 !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp
) &&
87 Value_Range::supports_type_p (TREE_TYPE (exp
)))
92 // Return true if TYPE1 and TYPE2 are compatible range types.
95 range_compatible_p (tree type1
, tree type2
)
97 // types_compatible_p requires conversion in both directions to be useless.
98 // GIMPLE only requires a cast one way in order to be compatible.
99 // Ranges really only need the sign and precision to be the same.
100 return (TYPE_PRECISION (type1
) == TYPE_PRECISION (type2
)
101 && TYPE_SIGN (type1
) == TYPE_SIGN (type2
));
104 // Source of all operands for fold_using_range and gori_compute.
105 // It abstracts out the source of an operand so it can come from a stmt or
106 // and edge or anywhere a derived class of fur_source wants.
107 // The default simply picks up ranges from the current range_query.
112 fur_source (range_query
*q
= NULL
);
113 inline range_query
*query () { return m_query
; }
114 inline class gori_compute
*gori () { return m_gori
; };
115 virtual bool get_operand (vrange
&r
, tree expr
);
116 virtual bool get_phi_operand (vrange
&r
, tree expr
, edge e
);
117 virtual relation_kind
query_relation (tree op1
, tree op2
);
118 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
120 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
122 void register_outgoing_edges (gcond
*, irange
&lhs_range
, edge e0
, edge e1
);
124 range_query
*m_query
;
125 gori_compute
*m_gori
;
128 // fur_stmt is the specification for drawing an operand from range_query Q
129 // via a range_of_Expr call on stmt S.
131 class fur_stmt
: public fur_source
134 fur_stmt (gimple
*s
, range_query
*q
= NULL
);
135 virtual bool get_operand (vrange
&r
, tree expr
) override
;
136 virtual bool get_phi_operand (vrange
&r
, tree expr
, edge e
) override
;
137 virtual relation_kind
query_relation (tree op1
, tree op2
) override
;
142 // This version of fur_source will pick a range from a stmt, and also register
143 // dependencies via a gori_compute object. This is mostly an internal API.
145 class fur_depend
: public fur_stmt
148 fur_depend (gimple
*s
, gori_compute
*gori
, range_query
*q
= NULL
);
149 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
151 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
154 relation_oracle
*m_oracle
;
157 // This class uses ranges to fold a gimple statement producing a range for
158 // the LHS. The source of all operands is supplied via the fur_source class
159 // which provides a range_query as well as a source location and any other
160 // required information.
162 class fold_using_range
165 bool fold_stmt (vrange
&r
, gimple
*s
, class fur_source
&src
,
166 tree name
= NULL_TREE
);
168 bool range_of_range_op (vrange
&r
, gimple_range_op_handler
&handler
,
170 bool range_of_call (vrange
&r
, gcall
*call
, fur_source
&src
);
171 bool range_of_cond_expr (vrange
&r
, gassign
* cond
, fur_source
&src
);
172 bool range_of_address (irange
&r
, gimple
*s
, fur_source
&src
);
173 bool range_of_phi (vrange
&r
, gphi
*phi
, fur_source
&src
);
174 void range_of_ssa_name_with_loop_info (vrange
&, tree
, class loop
*, gphi
*,
176 void relation_fold_and_or (irange
& lhs_range
, gimple
*s
, fur_source
&src
);
178 #endif // GCC_GIMPLE_RANGE_FOLD_H