xref: /netbsd-src/external/gpl3/gcc/dist/gcc/gimple-match.h (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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