1 /* Header file for the GIMPLE fold_using_range interface.
2 Copyright (C) 2019-2025 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 // Calculate op1 on stmt S.
47 bool op1_range (vrange
&, gimple
*s
, range_query
*q
= NULL
);
48 bool op1_range (vrange
&, gimple
*s
, const vrange
&lhs
, range_query
*q
= NULL
);
49 // Calculate op2 on stmt S.
50 bool op2_range (vrange
&, gimple
*s
, range_query
*q
= NULL
);
51 bool op2_range (vrange
&, gimple
*s
, const vrange
&lhs
, range_query
*q
= NULL
);
53 // This routine will return a relation trio for stmt S.
54 relation_trio
fold_relations (gimple
*s
, range_query
*q
= NULL
);
56 // Return the type of range which statement S calculates. If the type is
57 // unsupported or no type can be determined, return NULL_TREE.
60 gimple_range_type (const gimple
*s
)
62 tree lhs
= gimple_get_lhs (s
);
63 tree type
= NULL_TREE
;
65 type
= TREE_TYPE (lhs
);
68 enum gimple_code code
= gimple_code (s
);
69 if (code
== GIMPLE_COND
)
70 type
= boolean_type_node
;
71 else if (code
== GIMPLE_PHI
)
72 type
= TREE_TYPE (gimple_phi_result (s
));
73 else if (code
== GIMPLE_CALL
)
75 type
= gimple_call_fntype (s
);
76 // If it has a type, get the return type.
78 type
= TREE_TYPE (type
);
81 if (type
&& value_range::supports_type_p (type
))
86 // Return EXP if it is an SSA_NAME with a type supported by gimple ranges.
89 gimple_range_ssa_p (tree exp
)
91 if (exp
&& TREE_CODE (exp
) == SSA_NAME
&&
92 !SSA_NAME_IS_VIRTUAL_OPERAND (exp
) &&
93 !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp
) &&
94 value_range::supports_type_p (TREE_TYPE (exp
)))
99 // Source of all operands for fold_using_range and gori_compute.
100 // It abstracts out the source of an operand so it can come from a stmt or
101 // and edge or anywhere a derived class of fur_source wants.
102 // The default simply picks up ranges from the current range_query.
107 fur_source (range_query
*q
= NULL
);
108 inline range_query
*query () const { return m_query
; }
109 inline gori_map
*gori_ssa () const
110 { return (m_depend_p
&& m_query
) ? m_query
->gori_ssa () : NULL
; }
111 inline class gimple_outgoing_range
*gori ()
112 { return m_depend_p
? &(m_query
->gori ()) : NULL
; }
113 virtual bool get_operand (vrange
&r
, tree expr
);
114 virtual bool get_phi_operand (vrange
&r
, tree expr
, edge e
);
115 virtual relation_kind
query_relation (tree op1
, tree op2
);
116 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
118 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
120 void register_outgoing_edges (gcond
*, irange
&lhs_range
, edge e0
, edge e1
);
122 range_query
*m_query
;
126 // fur_stmt is the specification for drawing an operand from range_query Q
127 // via a range_of_Expr call on stmt S.
129 class fur_stmt
: public fur_source
132 fur_stmt (gimple
*s
, range_query
*q
= NULL
);
133 virtual bool get_operand (vrange
&r
, tree expr
) override
;
134 virtual bool get_phi_operand (vrange
&r
, tree expr
, edge e
) override
;
135 virtual relation_kind
query_relation (tree op1
, tree op2
) override
;
140 // This version of fur_source will pick a range from a stmt, and also register
141 // dependencies via a gori_compute object. This is mostly an internal API.
143 class fur_depend
: public fur_stmt
146 fur_depend (gimple
*s
, range_query
*q
= NULL
);
147 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
149 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
154 // This version of fur_source will pick a range up off an edge.
156 class fur_edge
: public fur_source
159 fur_edge (edge e
, range_query
*q
= NULL
) : fur_source (q
)
161 virtual bool get_operand (vrange
&r
, tree expr
) override
;
162 virtual bool get_phi_operand (vrange
&r
, tree expr
, edge e
) override
;
167 // This class uses ranges to fold a gimple statement producing a range for
168 // the LHS. The source of all operands is supplied via the fur_source class
169 // which provides a range_query as well as a source location and any other
170 // required information.
172 class fold_using_range
175 bool fold_stmt (vrange
&r
, gimple
*s
, class fur_source
&src
,
176 tree name
= NULL_TREE
);
178 bool range_of_range_op (vrange
&r
, gimple_range_op_handler
&handler
,
180 bool range_of_call (vrange
&r
, gcall
*call
, fur_source
&src
);
181 bool range_of_cond_expr (vrange
&r
, gassign
* cond
, fur_source
&src
);
182 bool range_of_address (prange
&r
, gimple
*s
, fur_source
&src
);
183 bool range_of_phi (vrange
&r
, gphi
*phi
, fur_source
&src
);
184 void range_of_ssa_name_with_loop_info (vrange
&, tree
, class loop
*, gphi
*,
186 void relation_fold_and_or (irange
& lhs_range
, gimple
*s
, fur_source
&src
,
187 vrange
&op1
, vrange
&op2
);
188 bool condexpr_adjust (vrange
&r1
, vrange
&r2
, gimple
*, tree cond
, tree op1
,
189 tree op2
, fur_source
&src
);
191 #endif // GCC_GIMPLE_RANGE_FOLD_H