]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/value-query.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / value-query.cc
1 /* Support routines for value queries.
2 Copyright (C) 2020-2021 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com> and
4 Andrew MacLeod <amacleod@redhat.com>.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
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/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "backend.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "ssa.h"
29 #include "tree-pretty-print.h"
30 #include "fold-const.h"
31 #include "value-range-equiv.h"
32 #include "value-query.h"
33 #include "alloc-pool.h"
34
35 // value_query default methods.
36
37 tree
38 value_query::value_on_edge (edge, tree name)
39 {
40 return value_of_expr (name);
41 }
42
43 tree
44 value_query::value_of_stmt (gimple *stmt, tree name)
45 {
46 if (!name)
47 name = gimple_get_lhs (stmt);
48
49 gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
50
51 if (name)
52 return value_of_expr (name);
53 return NULL_TREE;
54 }
55
56 // range_query default methods.
57
58 bool
59 range_query::range_on_edge (irange &r, edge, tree name)
60 {
61 return range_of_expr (r, name);
62 }
63
64 bool
65 range_query::range_of_stmt (irange &r, gimple *stmt, tree name)
66 {
67 if (!name)
68 name = gimple_get_lhs (stmt);
69
70 gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
71
72 if (name)
73 return range_of_expr (r, name);
74 return false;
75 }
76
77 tree
78 range_query::value_of_expr (tree name, gimple *stmt)
79 {
80 tree t;
81 int_range_max r;
82
83 if (!irange::supports_type_p (TREE_TYPE (name)))
84 return NULL_TREE;
85
86 if (range_of_expr (r, name, stmt))
87 {
88 // A constant used in an unreachable block oftens returns as UNDEFINED.
89 // If the result is undefined, check the global value for a constant.
90 if (r.undefined_p ())
91 range_of_expr (r, name);
92 if (r.singleton_p (&t))
93 return t;
94 }
95 return NULL_TREE;
96 }
97
98 tree
99 range_query::value_on_edge (edge e, tree name)
100 {
101 tree t;
102 int_range_max r;
103
104 if (!irange::supports_type_p (TREE_TYPE (name)))
105 return NULL_TREE;
106 if (range_on_edge (r, e, name))
107 {
108 // A constant used in an unreachable block oftens returns as UNDEFINED.
109 // If the result is undefined, check the global value for a constant.
110 if (r.undefined_p ())
111 range_of_expr (r, name);
112 if (r.singleton_p (&t))
113 return t;
114 }
115 return NULL_TREE;
116
117 }
118
119 tree
120 range_query::value_of_stmt (gimple *stmt, tree name)
121 {
122 tree t;
123 int_range_max r;
124
125 if (!name)
126 name = gimple_get_lhs (stmt);
127
128 gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
129
130 if (!name || !irange::supports_type_p (TREE_TYPE (name)))
131 return NULL_TREE;
132 if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
133 return t;
134 return NULL_TREE;
135
136 }
137
138 // valuation_query support routines for value_range_equiv's.
139
140 class equiv_allocator : public object_allocator<value_range_equiv>
141 {
142 public:
143 equiv_allocator ()
144 : object_allocator<value_range_equiv> ("equiv_allocator pool") { }
145 };
146
147 value_range_equiv *
148 range_query::allocate_value_range_equiv ()
149 {
150 return new (equiv_alloc->allocate ()) value_range_equiv;
151 }
152
153 void
154 range_query::free_value_range_equiv (value_range_equiv *v)
155 {
156 equiv_alloc->remove (v);
157 }
158
159 const class value_range_equiv *
160 range_query::get_value_range (const_tree expr, gimple *stmt)
161 {
162 int_range_max r;
163 if (range_of_expr (r, const_cast<tree> (expr), stmt))
164 return new (equiv_alloc->allocate ()) value_range_equiv (r);
165 return new (equiv_alloc->allocate ()) value_range_equiv (TREE_TYPE (expr));
166 }
167
168 range_query::range_query ()
169 {
170 equiv_alloc = new equiv_allocator;
171 }
172
173 range_query::~range_query ()
174 {
175 equiv_alloc->release ();
176 delete equiv_alloc;
177 }