]>
Commit | Line | Data |
---|---|---|
3d2cf79f RB |
1 | /* Gimple simplify definitions. |
2 | ||
8d9254fc | 3 | Copyright (C) 2011-2020 Free Software Foundation, Inc. |
3d2cf79f RB |
4 | Contributed by Richard Guenther <rguenther@suse.de> |
5 | ||
6 | This file is part of GCC. | |
7 | ||
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 | |
11 | version. | |
12 | ||
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 | |
16 | 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 | #ifndef GCC_GIMPLE_MATCH_H | |
23 | #define GCC_GIMPLE_MATCH_H | |
24 | ||
25 | ||
26 | /* Helper to transparently allow tree codes and builtin function codes | |
27 | exist in one storage entity. */ | |
28 | class code_helper | |
29 | { | |
30 | public: | |
31 | code_helper () {} | |
32 | code_helper (tree_code code) : rep ((int) code) {} | |
c9e926ce | 33 | code_helper (combined_fn fn) : rep (-(int) fn) {} |
3d2cf79f | 34 | operator tree_code () const { return (tree_code) rep; } |
c9e926ce | 35 | operator combined_fn () const { return (combined_fn) -rep; } |
3d2cf79f RB |
36 | bool is_tree_code () const { return rep > 0; } |
37 | bool is_fn_code () const { return rep < 0; } | |
38 | int get_rep () const { return rep; } | |
39 | private: | |
40 | int rep; | |
41 | }; | |
42 | ||
6a86928d RS |
43 | /* Represents the condition under which an operation should happen, |
44 | and the value to use otherwise. The condition applies elementwise | |
45 | (as for VEC_COND_EXPR) if the values are vectors. */ | |
6c1dae73 | 46 | class gimple_match_cond |
6a86928d | 47 | { |
6c1dae73 | 48 | public: |
6a86928d RS |
49 | enum uncond { UNCOND }; |
50 | ||
51 | /* Build an unconditional op. */ | |
52 | gimple_match_cond (uncond) : cond (NULL_TREE), else_value (NULL_TREE) {} | |
53 | gimple_match_cond (tree, tree); | |
54 | ||
55 | gimple_match_cond any_else () const; | |
56 | ||
57 | /* The condition under which the operation occurs, or NULL_TREE | |
58 | if the operation is unconditional. */ | |
59 | tree cond; | |
60 | ||
61 | /* The value to use when the condition is false. This is NULL_TREE if | |
62 | the operation is unconditional or if the value doesn't matter. */ | |
63 | tree else_value; | |
64 | }; | |
65 | ||
66 | inline | |
67 | gimple_match_cond::gimple_match_cond (tree cond_in, tree else_value_in) | |
68 | : cond (cond_in), else_value (else_value_in) | |
69 | { | |
70 | } | |
71 | ||
72 | /* Return a gimple_match_cond with the same condition but with an | |
73 | arbitrary ELSE_VALUE. */ | |
74 | ||
75 | inline gimple_match_cond | |
76 | gimple_match_cond::any_else () const | |
77 | { | |
78 | return gimple_match_cond (cond, NULL_TREE); | |
79 | } | |
80 | ||
5d75ad95 RS |
81 | /* Represents an operation to be simplified, or the result of the |
82 | simplification. */ | |
6c1dae73 | 83 | class gimple_match_op |
5d75ad95 | 84 | { |
6c1dae73 | 85 | public: |
6a86928d RS |
86 | gimple_match_op (); |
87 | gimple_match_op (const gimple_match_cond &, code_helper, tree, unsigned int); | |
88 | gimple_match_op (const gimple_match_cond &, | |
89 | code_helper, tree, tree); | |
90 | gimple_match_op (const gimple_match_cond &, | |
91 | code_helper, tree, tree, tree); | |
92 | gimple_match_op (const gimple_match_cond &, | |
93 | code_helper, tree, tree, tree, tree); | |
94 | gimple_match_op (const gimple_match_cond &, | |
95 | code_helper, tree, tree, tree, tree, tree); | |
b41d1f6e RS |
96 | gimple_match_op (const gimple_match_cond &, |
97 | code_helper, tree, tree, tree, tree, tree, tree); | |
5d75ad95 RS |
98 | |
99 | void set_op (code_helper, tree, unsigned int); | |
100 | void set_op (code_helper, tree, tree); | |
101 | void set_op (code_helper, tree, tree, tree); | |
102 | void set_op (code_helper, tree, tree, tree, tree); | |
de310193 | 103 | void set_op (code_helper, tree, tree, tree, tree, bool); |
0d2b3bca | 104 | void set_op (code_helper, tree, tree, tree, tree, tree); |
b41d1f6e | 105 | void set_op (code_helper, tree, tree, tree, tree, tree, tree); |
5d75ad95 RS |
106 | void set_value (tree); |
107 | ||
108 | tree op_or_null (unsigned int) const; | |
109 | ||
b7fe158a RB |
110 | bool resimplify (gimple_seq *, tree (*)(tree)); |
111 | ||
5d75ad95 | 112 | /* The maximum value of NUM_OPS. */ |
b41d1f6e | 113 | static const unsigned int MAX_NUM_OPS = 5; |
5d75ad95 | 114 | |
6a86928d RS |
115 | /* The conditions under which the operation is performed, and the value to |
116 | use as a fallback. */ | |
117 | gimple_match_cond cond; | |
118 | ||
5d75ad95 RS |
119 | /* The operation being performed. */ |
120 | code_helper code; | |
121 | ||
122 | /* The type of the result. */ | |
123 | tree type; | |
124 | ||
de310193 EB |
125 | /* For a BIT_FIELD_REF, whether the group of bits is stored in reverse order |
126 | from the target order. */ | |
127 | bool reverse; | |
128 | ||
5d75ad95 RS |
129 | /* The number of operands to CODE. */ |
130 | unsigned int num_ops; | |
131 | ||
132 | /* The operands to CODE. Only the first NUM_OPS entries are meaningful. */ | |
133 | tree ops[MAX_NUM_OPS]; | |
134 | }; | |
135 | ||
6a86928d RS |
136 | inline |
137 | gimple_match_op::gimple_match_op () | |
6fd8679f EB |
138 | : cond (gimple_match_cond::UNCOND), type (NULL_TREE), reverse (false), |
139 | num_ops (0) | |
6a86928d RS |
140 | { |
141 | } | |
142 | ||
143 | /* Constructor that takes the condition, code, type and number of | |
144 | operands, but leaves the caller to fill in the operands. */ | |
5d75ad95 RS |
145 | |
146 | inline | |
6a86928d RS |
147 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
148 | code_helper code_in, tree type_in, | |
5d75ad95 | 149 | unsigned int num_ops_in) |
6fd8679f EB |
150 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
151 | num_ops (num_ops_in) | |
5d75ad95 RS |
152 | { |
153 | } | |
154 | ||
155 | /* Constructors for various numbers of operands. */ | |
156 | ||
157 | inline | |
6a86928d RS |
158 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
159 | code_helper code_in, tree type_in, | |
5d75ad95 | 160 | tree op0) |
6fd8679f EB |
161 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
162 | num_ops (1) | |
5d75ad95 RS |
163 | { |
164 | ops[0] = op0; | |
165 | } | |
166 | ||
167 | inline | |
6a86928d RS |
168 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
169 | code_helper code_in, tree type_in, | |
5d75ad95 | 170 | tree op0, tree op1) |
6fd8679f EB |
171 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
172 | num_ops (2) | |
5d75ad95 RS |
173 | { |
174 | ops[0] = op0; | |
175 | ops[1] = op1; | |
176 | } | |
177 | ||
178 | inline | |
6a86928d RS |
179 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
180 | code_helper code_in, tree type_in, | |
5d75ad95 | 181 | tree op0, tree op1, tree op2) |
6fd8679f EB |
182 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
183 | num_ops (3) | |
5d75ad95 RS |
184 | { |
185 | ops[0] = op0; | |
186 | ops[1] = op1; | |
187 | ops[2] = op2; | |
188 | } | |
189 | ||
0d2b3bca | 190 | inline |
6a86928d RS |
191 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
192 | code_helper code_in, tree type_in, | |
0d2b3bca | 193 | tree op0, tree op1, tree op2, tree op3) |
6fd8679f EB |
194 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
195 | num_ops (4) | |
0d2b3bca RS |
196 | { |
197 | ops[0] = op0; | |
198 | ops[1] = op1; | |
199 | ops[2] = op2; | |
200 | ops[3] = op3; | |
201 | } | |
202 | ||
b41d1f6e RS |
203 | inline |
204 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, | |
205 | code_helper code_in, tree type_in, | |
206 | tree op0, tree op1, tree op2, tree op3, | |
207 | tree op4) | |
6fd8679f EB |
208 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
209 | num_ops (5) | |
b41d1f6e RS |
210 | { |
211 | ops[0] = op0; | |
212 | ops[1] = op1; | |
213 | ops[2] = op2; | |
214 | ops[3] = op3; | |
215 | ops[4] = op4; | |
216 | } | |
217 | ||
5d75ad95 RS |
218 | /* Change the operation performed to CODE_IN, the type of the result to |
219 | TYPE_IN, and the number of operands to NUM_OPS_IN. The caller needs | |
220 | to set the operands itself. */ | |
221 | ||
222 | inline void | |
223 | gimple_match_op::set_op (code_helper code_in, tree type_in, | |
224 | unsigned int num_ops_in) | |
225 | { | |
226 | code = code_in; | |
227 | type = type_in; | |
228 | num_ops = num_ops_in; | |
229 | } | |
230 | ||
231 | /* Functions for changing the operation performed, for various numbers | |
232 | of operands. */ | |
233 | ||
234 | inline void | |
235 | gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0) | |
236 | { | |
237 | code = code_in; | |
238 | type = type_in; | |
239 | num_ops = 1; | |
240 | ops[0] = op0; | |
241 | } | |
242 | ||
243 | inline void | |
244 | gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0, tree op1) | |
245 | { | |
246 | code = code_in; | |
247 | type = type_in; | |
248 | num_ops = 2; | |
249 | ops[0] = op0; | |
250 | ops[1] = op1; | |
251 | } | |
252 | ||
253 | inline void | |
254 | gimple_match_op::set_op (code_helper code_in, tree type_in, | |
255 | tree op0, tree op1, tree op2) | |
256 | { | |
257 | code = code_in; | |
258 | type = type_in; | |
259 | num_ops = 3; | |
260 | ops[0] = op0; | |
261 | ops[1] = op1; | |
262 | ops[2] = op2; | |
263 | } | |
264 | ||
de310193 EB |
265 | inline void |
266 | gimple_match_op::set_op (code_helper code_in, tree type_in, | |
267 | tree op0, tree op1, tree op2, bool reverse_in) | |
268 | { | |
269 | code = code_in; | |
270 | type = type_in; | |
271 | reverse = reverse_in; | |
272 | num_ops = 3; | |
273 | ops[0] = op0; | |
274 | ops[1] = op1; | |
275 | ops[2] = op2; | |
276 | } | |
277 | ||
0d2b3bca RS |
278 | inline void |
279 | gimple_match_op::set_op (code_helper code_in, tree type_in, | |
280 | tree op0, tree op1, tree op2, tree op3) | |
281 | { | |
282 | code = code_in; | |
283 | type = type_in; | |
284 | num_ops = 4; | |
285 | ops[0] = op0; | |
286 | ops[1] = op1; | |
287 | ops[2] = op2; | |
288 | ops[3] = op3; | |
289 | } | |
290 | ||
b41d1f6e RS |
291 | inline void |
292 | gimple_match_op::set_op (code_helper code_in, tree type_in, | |
293 | tree op0, tree op1, tree op2, tree op3, tree op4) | |
294 | { | |
295 | code = code_in; | |
296 | type = type_in; | |
297 | num_ops = 5; | |
298 | ops[0] = op0; | |
299 | ops[1] = op1; | |
300 | ops[2] = op2; | |
301 | ops[3] = op3; | |
302 | ops[4] = op4; | |
303 | } | |
304 | ||
5d75ad95 RS |
305 | /* Set the "operation" to be the single value VALUE, such as a constant |
306 | or SSA_NAME. */ | |
307 | ||
308 | inline void | |
309 | gimple_match_op::set_value (tree value) | |
310 | { | |
311 | set_op (TREE_CODE (value), TREE_TYPE (value), value); | |
312 | } | |
313 | ||
314 | /* Return the value of operand I, or null if there aren't that many | |
315 | operands. */ | |
316 | ||
317 | inline tree | |
318 | gimple_match_op::op_or_null (unsigned int i) const | |
319 | { | |
320 | return i < num_ops ? ops[i] : NULL_TREE; | |
321 | } | |
322 | ||
323 | /* Return whether OP is a non-expression result and a gimple value. */ | |
c0f62740 RB |
324 | |
325 | inline bool | |
5d75ad95 | 326 | gimple_simplified_result_is_gimple_val (const gimple_match_op *op) |
c0f62740 | 327 | { |
5d75ad95 RS |
328 | return (op->code.is_tree_code () |
329 | && (TREE_CODE_LENGTH ((tree_code) op->code) == 0 | |
330 | || ((tree_code) op->code) == ADDR_EXPR) | |
331 | && is_gimple_val (op->ops[0])); | |
c0f62740 RB |
332 | } |
333 | ||
5d75ad95 | 334 | extern tree (*mprts_hook) (gimple_match_op *); |
34050b6b | 335 | |
5d75ad95 | 336 | bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *, |
0ff093d8 | 337 | tree (*)(tree), tree (*)(tree)); |
5d75ad95 RS |
338 | tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *, |
339 | tree res = NULL_TREE); | |
340 | void maybe_build_generic_op (gimple_match_op *); | |
3d2cf79f RB |
341 | |
342 | ||
343 | #endif /* GCC_GIMPLE_MATCH_H */ |