1 /* Header file for the GIMPLE fold_using_range interface.
2 Copyright (C) 2019-2024 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 // Source of all operands for fold_using_range and gori_compute.
93 // It abstracts out the source of an operand so it can come from a stmt or
94 // and edge or anywhere a derived class of fur_source wants.
95 // The default simply picks up ranges from the current range_query.
100 fur_source (range_query
*q
= NULL
);
101 inline range_query
*query () { return m_query
; }
102 inline class gori_compute
*gori () { return m_gori
; };
103 virtual bool get_operand (vrange
&r
, tree expr
);
104 virtual bool get_phi_operand (vrange
&r
, tree expr
, edge e
);
105 virtual relation_kind
query_relation (tree op1
, tree op2
);
106 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
108 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
110 void register_outgoing_edges (gcond
*, irange
&lhs_range
, edge e0
, edge e1
);
112 range_query
*m_query
;
113 gori_compute
*m_gori
;
116 // fur_stmt is the specification for drawing an operand from range_query Q
117 // via a range_of_Expr call on stmt S.
119 class fur_stmt
: public fur_source
122 fur_stmt (gimple
*s
, range_query
*q
= NULL
);
123 virtual bool get_operand (vrange
&r
, tree expr
) override
;
124 virtual bool get_phi_operand (vrange
&r
, tree expr
, edge e
) override
;
125 virtual relation_kind
query_relation (tree op1
, tree op2
) override
;
130 // This version of fur_source will pick a range from a stmt, and also register
131 // dependencies via a gori_compute object. This is mostly an internal API.
133 class fur_depend
: public fur_stmt
136 fur_depend (gimple
*s
, gori_compute
*gori
, range_query
*q
= NULL
);
137 virtual void register_relation (gimple
*stmt
, relation_kind k
, tree op1
,
139 virtual void register_relation (edge e
, relation_kind k
, tree op1
,
142 relation_oracle
*m_oracle
;
145 // This class uses ranges to fold a gimple statement producing a range for
146 // the LHS. The source of all operands is supplied via the fur_source class
147 // which provides a range_query as well as a source location and any other
148 // required information.
150 class fold_using_range
153 bool fold_stmt (vrange
&r
, gimple
*s
, class fur_source
&src
,
154 tree name
= NULL_TREE
);
156 bool range_of_range_op (vrange
&r
, gimple_range_op_handler
&handler
,
158 bool range_of_call (vrange
&r
, gcall
*call
, fur_source
&src
);
159 bool range_of_cond_expr (vrange
&r
, gassign
* cond
, fur_source
&src
);
160 bool range_of_address (irange
&r
, gimple
*s
, fur_source
&src
);
161 bool range_of_phi (vrange
&r
, gphi
*phi
, fur_source
&src
);
162 void range_of_ssa_name_with_loop_info (vrange
&, tree
, class loop
*, gphi
*,
164 void relation_fold_and_or (irange
& lhs_range
, gimple
*s
, fur_source
&src
,
165 vrange
&op1
, vrange
&op2
);
167 #endif // GCC_GIMPLE_RANGE_FOLD_H