1 /* Gimple simplify definitions.
2
3 Copyright (C) 2011-2022 Free Software Foundation, Inc.
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:
code_helper()31 code_helper () {}
code_helper(tree_code code)32 code_helper (tree_code code) : rep ((int) code) {}
code_helper(combined_fn fn)33 code_helper (combined_fn fn) : rep (-(int) fn) {}
code_helper(internal_fn fn)34 code_helper (internal_fn fn) : rep (-(int) as_combined_fn (fn)) {}
tree_code()35 explicit operator tree_code () const { return (tree_code) rep; }
combined_fn()36 explicit operator combined_fn () const { return (combined_fn) -rep; }
37 explicit operator internal_fn () const;
38 explicit operator built_in_function () const;
is_tree_code()39 bool is_tree_code () const { return rep > 0; }
is_fn_code()40 bool is_fn_code () const { return rep < 0; }
41 bool is_internal_fn () const;
42 bool is_builtin_fn () const;
get_rep()43 int get_rep () const { return rep; }
44 bool operator== (const code_helper &other) { return rep == other.rep; }
45 bool operator!= (const code_helper &other) { return rep != other.rep; }
46 bool operator== (tree_code c) { return rep == code_helper (c).rep; }
47 bool operator!= (tree_code c) { return rep != code_helper (c).rep; }
48
49 private:
50 int rep;
51 };
52
internal_fn()53 inline code_helper::operator internal_fn () const
54 {
55 return as_internal_fn (combined_fn (*this));
56 }
57
built_in_function()58 inline code_helper::operator built_in_function () const
59 {
60 return as_builtin_fn (combined_fn (*this));
61 }
62
63 inline bool
is_internal_fn()64 code_helper::is_internal_fn () const
65 {
66 return is_fn_code () && internal_fn_p (combined_fn (*this));
67 }
68
69 inline bool
is_builtin_fn()70 code_helper::is_builtin_fn () const
71 {
72 return is_fn_code () && builtin_fn_p (combined_fn (*this));
73 }
74
75 /* Represents the condition under which an operation should happen,
76 and the value to use otherwise. The condition applies elementwise
77 (as for VEC_COND_EXPR) if the values are vectors. */
78 class gimple_match_cond
79 {
80 public:
81 enum uncond { UNCOND };
82
83 /* Build an unconditional op. */
gimple_match_cond(uncond)84 gimple_match_cond (uncond) : cond (NULL_TREE), else_value (NULL_TREE) {}
85 gimple_match_cond (tree, tree);
86
87 gimple_match_cond any_else () const;
88
89 /* The condition under which the operation occurs, or NULL_TREE
90 if the operation is unconditional. */
91 tree cond;
92
93 /* The value to use when the condition is false. This is NULL_TREE if
94 the operation is unconditional or if the value doesn't matter. */
95 tree else_value;
96 };
97
98 inline
gimple_match_cond(tree cond_in,tree else_value_in)99 gimple_match_cond::gimple_match_cond (tree cond_in, tree else_value_in)
100 : cond (cond_in), else_value (else_value_in)
101 {
102 }
103
104 /* Return a gimple_match_cond with the same condition but with an
105 arbitrary ELSE_VALUE. */
106
107 inline gimple_match_cond
any_else()108 gimple_match_cond::any_else () const
109 {
110 return gimple_match_cond (cond, NULL_TREE);
111 }
112
113 /* Represents an operation to be simplified, or the result of the
114 simplification. */
115 class gimple_match_op
116 {
117 public:
118 gimple_match_op ();
119 gimple_match_op (const gimple_match_cond &, code_helper, tree, unsigned int);
120 gimple_match_op (const gimple_match_cond &,
121 code_helper, tree, tree);
122 gimple_match_op (const gimple_match_cond &,
123 code_helper, tree, tree, tree);
124 gimple_match_op (const gimple_match_cond &,
125 code_helper, tree, tree, tree, tree);
126 gimple_match_op (const gimple_match_cond &,
127 code_helper, tree, tree, tree, tree, tree);
128 gimple_match_op (const gimple_match_cond &,
129 code_helper, tree, tree, tree, tree, tree, tree);
130
131 void set_op (code_helper, tree, unsigned int);
132 void set_op (code_helper, tree, tree);
133 void set_op (code_helper, tree, tree, tree);
134 void set_op (code_helper, tree, tree, tree, tree);
135 void set_op (code_helper, tree, tree, tree, tree, bool);
136 void set_op (code_helper, tree, tree, tree, tree, tree);
137 void set_op (code_helper, tree, tree, tree, tree, tree, tree);
138 void set_value (tree);
139
140 tree op_or_null (unsigned int) const;
141
142 bool resimplify (gimple_seq *, tree (*)(tree));
143
144 /* The maximum value of NUM_OPS. */
145 static const unsigned int MAX_NUM_OPS = 5;
146
147 /* The conditions under which the operation is performed, and the value to
148 use as a fallback. */
149 gimple_match_cond cond;
150
151 /* The operation being performed. */
152 code_helper code;
153
154 /* The type of the result. */
155 tree type;
156
157 /* For a BIT_FIELD_REF, whether the group of bits is stored in reverse order
158 from the target order. */
159 bool reverse;
160
161 /* The number of operands to CODE. */
162 unsigned int num_ops;
163
164 /* The operands to CODE. Only the first NUM_OPS entries are meaningful. */
165 tree ops[MAX_NUM_OPS];
166 };
167
168 inline
gimple_match_op()169 gimple_match_op::gimple_match_op ()
170 : cond (gimple_match_cond::UNCOND), type (NULL_TREE), reverse (false),
171 num_ops (0)
172 {
173 }
174
175 /* Constructor that takes the condition, code, type and number of
176 operands, but leaves the caller to fill in the operands. */
177
178 inline
gimple_match_op(const gimple_match_cond & cond_in,code_helper code_in,tree type_in,unsigned int num_ops_in)179 gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
180 code_helper code_in, tree type_in,
181 unsigned int num_ops_in)
182 : cond (cond_in), code (code_in), type (type_in), reverse (false),
183 num_ops (num_ops_in)
184 {
185 }
186
187 /* Constructors for various numbers of operands. */
188
189 inline
gimple_match_op(const gimple_match_cond & cond_in,code_helper code_in,tree type_in,tree op0)190 gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
191 code_helper code_in, tree type_in,
192 tree op0)
193 : cond (cond_in), code (code_in), type (type_in), reverse (false),
194 num_ops (1)
195 {
196 ops[0] = op0;
197 }
198
199 inline
gimple_match_op(const gimple_match_cond & cond_in,code_helper code_in,tree type_in,tree op0,tree op1)200 gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
201 code_helper code_in, tree type_in,
202 tree op0, tree op1)
203 : cond (cond_in), code (code_in), type (type_in), reverse (false),
204 num_ops (2)
205 {
206 ops[0] = op0;
207 ops[1] = op1;
208 }
209
210 inline
gimple_match_op(const gimple_match_cond & cond_in,code_helper code_in,tree type_in,tree op0,tree op1,tree op2)211 gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
212 code_helper code_in, tree type_in,
213 tree op0, tree op1, tree op2)
214 : cond (cond_in), code (code_in), type (type_in), reverse (false),
215 num_ops (3)
216 {
217 ops[0] = op0;
218 ops[1] = op1;
219 ops[2] = op2;
220 }
221
222 inline
gimple_match_op(const gimple_match_cond & cond_in,code_helper code_in,tree type_in,tree op0,tree op1,tree op2,tree op3)223 gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
224 code_helper code_in, tree type_in,
225 tree op0, tree op1, tree op2, tree op3)
226 : cond (cond_in), code (code_in), type (type_in), reverse (false),
227 num_ops (4)
228 {
229 ops[0] = op0;
230 ops[1] = op1;
231 ops[2] = op2;
232 ops[3] = op3;
233 }
234
235 inline
gimple_match_op(const gimple_match_cond & cond_in,code_helper code_in,tree type_in,tree op0,tree op1,tree op2,tree op3,tree op4)236 gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
237 code_helper code_in, tree type_in,
238 tree op0, tree op1, tree op2, tree op3,
239 tree op4)
240 : cond (cond_in), code (code_in), type (type_in), reverse (false),
241 num_ops (5)
242 {
243 ops[0] = op0;
244 ops[1] = op1;
245 ops[2] = op2;
246 ops[3] = op3;
247 ops[4] = op4;
248 }
249
250 /* Change the operation performed to CODE_IN, the type of the result to
251 TYPE_IN, and the number of operands to NUM_OPS_IN. The caller needs
252 to set the operands itself. */
253
254 inline void
set_op(code_helper code_in,tree type_in,unsigned int num_ops_in)255 gimple_match_op::set_op (code_helper code_in, tree type_in,
256 unsigned int num_ops_in)
257 {
258 code = code_in;
259 type = type_in;
260 num_ops = num_ops_in;
261 }
262
263 /* Functions for changing the operation performed, for various numbers
264 of operands. */
265
266 inline void
set_op(code_helper code_in,tree type_in,tree op0)267 gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0)
268 {
269 code = code_in;
270 type = type_in;
271 num_ops = 1;
272 ops[0] = op0;
273 }
274
275 inline void
set_op(code_helper code_in,tree type_in,tree op0,tree op1)276 gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0, tree op1)
277 {
278 code = code_in;
279 type = type_in;
280 num_ops = 2;
281 ops[0] = op0;
282 ops[1] = op1;
283 }
284
285 inline void
set_op(code_helper code_in,tree type_in,tree op0,tree op1,tree op2)286 gimple_match_op::set_op (code_helper code_in, tree type_in,
287 tree op0, tree op1, tree op2)
288 {
289 code = code_in;
290 type = type_in;
291 num_ops = 3;
292 ops[0] = op0;
293 ops[1] = op1;
294 ops[2] = op2;
295 }
296
297 inline void
set_op(code_helper code_in,tree type_in,tree op0,tree op1,tree op2,bool reverse_in)298 gimple_match_op::set_op (code_helper code_in, tree type_in,
299 tree op0, tree op1, tree op2, bool reverse_in)
300 {
301 code = code_in;
302 type = type_in;
303 reverse = reverse_in;
304 num_ops = 3;
305 ops[0] = op0;
306 ops[1] = op1;
307 ops[2] = op2;
308 }
309
310 inline void
set_op(code_helper code_in,tree type_in,tree op0,tree op1,tree op2,tree op3)311 gimple_match_op::set_op (code_helper code_in, tree type_in,
312 tree op0, tree op1, tree op2, tree op3)
313 {
314 code = code_in;
315 type = type_in;
316 num_ops = 4;
317 ops[0] = op0;
318 ops[1] = op1;
319 ops[2] = op2;
320 ops[3] = op3;
321 }
322
323 inline void
set_op(code_helper code_in,tree type_in,tree op0,tree op1,tree op2,tree op3,tree op4)324 gimple_match_op::set_op (code_helper code_in, tree type_in,
325 tree op0, tree op1, tree op2, tree op3, tree op4)
326 {
327 code = code_in;
328 type = type_in;
329 num_ops = 5;
330 ops[0] = op0;
331 ops[1] = op1;
332 ops[2] = op2;
333 ops[3] = op3;
334 ops[4] = op4;
335 }
336
337 /* Set the "operation" to be the single value VALUE, such as a constant
338 or SSA_NAME. */
339
340 inline void
set_value(tree value)341 gimple_match_op::set_value (tree value)
342 {
343 set_op (TREE_CODE (value), TREE_TYPE (value), value);
344 }
345
346 /* Return the value of operand I, or null if there aren't that many
347 operands. */
348
349 inline tree
op_or_null(unsigned int i)350 gimple_match_op::op_or_null (unsigned int i) const
351 {
352 return i < num_ops ? ops[i] : NULL_TREE;
353 }
354
355 /* Return whether OP is a non-expression result and a gimple value. */
356
357 inline bool
gimple_simplified_result_is_gimple_val(const gimple_match_op * op)358 gimple_simplified_result_is_gimple_val (const gimple_match_op *op)
359 {
360 return (op->code.is_tree_code ()
361 && (TREE_CODE_LENGTH ((tree_code) op->code) == 0
362 || ((tree_code) op->code) == ADDR_EXPR)
363 && is_gimple_val (op->ops[0]));
364 }
365
366 extern tree (*mprts_hook) (gimple_match_op *);
367
368 bool gimple_extract_op (gimple *, gimple_match_op *);
369 bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *,
370 tree (*)(tree), tree (*)(tree));
371 tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *,
372 tree res = NULL_TREE);
373 void maybe_build_generic_op (gimple_match_op *);
374
375 bool commutative_binary_op_p (code_helper, tree);
376 bool commutative_ternary_op_p (code_helper, tree);
377 int first_commutative_argument (code_helper, tree);
378 bool associative_binary_op_p (code_helper, tree);
379 code_helper canonicalize_code (code_helper, tree);
380
381 #ifdef GCC_OPTABS_TREE_H
382 bool directly_supported_p (code_helper, tree, optab_subtype = optab_default);
383 #endif
384
385 internal_fn get_conditional_internal_fn (code_helper, tree);
386
387 extern tree gimple_build (gimple_seq *, location_t,
388 code_helper, tree, tree);
389 inline tree
gimple_build(gimple_seq * seq,code_helper code,tree type,tree op0)390 gimple_build (gimple_seq *seq, code_helper code, tree type, tree op0)
391 {
392 return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0);
393 }
394
395 extern tree gimple_build (gimple_seq *, location_t,
396 code_helper, tree, tree, tree);
397 inline tree
gimple_build(gimple_seq * seq,code_helper code,tree type,tree op0,tree op1)398 gimple_build (gimple_seq *seq, code_helper code, tree type, tree op0,
399 tree op1)
400 {
401 return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0, op1);
402 }
403
404 extern tree gimple_build (gimple_seq *, location_t,
405 code_helper, tree, tree, tree, tree);
406 inline tree
gimple_build(gimple_seq * seq,code_helper code,tree type,tree op0,tree op1,tree op2)407 gimple_build (gimple_seq *seq, code_helper code, tree type, tree op0,
408 tree op1, tree op2)
409 {
410 return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0, op1, op2);
411 }
412
413 #endif /* GCC_GIMPLE_MATCH_H */
414