1/* Gimple simplify definitions.
2
3   Copyright (C) 2011-2020 Free Software Foundation, Inc.
4   Contributed by Richard Guenther <rguenther@suse.de>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along 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.  */
28class code_helper
29{
30public:
31  code_helper () {}
32  code_helper (tree_code code) : rep ((int) code) {}
33  code_helper (combined_fn fn) : rep (-(int) fn) {}
34  operator tree_code () const { return (tree_code) rep; }
35  operator combined_fn () const { return (combined_fn) -rep; }
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; }
39private:
40  int rep;
41};
42
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.  */
46class gimple_match_cond
47{
48public:
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
66inline
67gimple_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
75inline gimple_match_cond
76gimple_match_cond::any_else () const
77{
78  return gimple_match_cond (cond, NULL_TREE);
79}
80
81/* Represents an operation to be simplified, or the result of the
82   simplification.  */
83class gimple_match_op
84{
85public:
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);
96  gimple_match_op (const gimple_match_cond &,
97		   code_helper, tree, tree, tree, tree, tree, tree);
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);
103  void set_op (code_helper, tree, tree, tree, tree, bool);
104  void set_op (code_helper, tree, tree, tree, tree, tree);
105  void set_op (code_helper, tree, tree, tree, tree, tree, tree);
106  void set_value (tree);
107
108  tree op_or_null (unsigned int) const;
109
110  bool resimplify (gimple_seq *, tree (*)(tree));
111
112  /* The maximum value of NUM_OPS.  */
113  static const unsigned int MAX_NUM_OPS = 5;
114
115  /* The conditions under which the operation is performed, and the value to
116     use as a fallback.  */
117  gimple_match_cond cond;
118
119  /* The operation being performed.  */
120  code_helper code;
121
122  /* The type of the result.  */
123  tree type;
124
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
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
136inline
137gimple_match_op::gimple_match_op ()
138  : cond (gimple_match_cond::UNCOND), type (NULL_TREE), reverse (false),
139    num_ops (0)
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.  */
145
146inline
147gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
148				  code_helper code_in, tree type_in,
149				  unsigned int num_ops_in)
150  : cond (cond_in), code (code_in), type (type_in), reverse (false),
151    num_ops (num_ops_in)
152{
153}
154
155/* Constructors for various numbers of operands.  */
156
157inline
158gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
159				  code_helper code_in, tree type_in,
160				  tree op0)
161  : cond (cond_in), code (code_in), type (type_in), reverse (false),
162    num_ops (1)
163{
164  ops[0] = op0;
165}
166
167inline
168gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
169				  code_helper code_in, tree type_in,
170				  tree op0, tree op1)
171  : cond (cond_in), code (code_in), type (type_in), reverse (false),
172    num_ops (2)
173{
174  ops[0] = op0;
175  ops[1] = op1;
176}
177
178inline
179gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
180				  code_helper code_in, tree type_in,
181				  tree op0, tree op1, tree op2)
182  : cond (cond_in), code (code_in), type (type_in), reverse (false),
183    num_ops (3)
184{
185  ops[0] = op0;
186  ops[1] = op1;
187  ops[2] = op2;
188}
189
190inline
191gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
192				  code_helper code_in, tree type_in,
193				  tree op0, tree op1, tree op2, tree op3)
194  : cond (cond_in), code (code_in), type (type_in), reverse (false),
195    num_ops (4)
196{
197  ops[0] = op0;
198  ops[1] = op1;
199  ops[2] = op2;
200  ops[3] = op3;
201}
202
203inline
204gimple_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)
208  : cond (cond_in), code (code_in), type (type_in), reverse (false),
209    num_ops (5)
210{
211  ops[0] = op0;
212  ops[1] = op1;
213  ops[2] = op2;
214  ops[3] = op3;
215  ops[4] = op4;
216}
217
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
222inline void
223gimple_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
234inline void
235gimple_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
243inline void
244gimple_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
253inline void
254gimple_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
265inline void
266gimple_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
278inline void
279gimple_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
291inline void
292gimple_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
305/* Set the "operation" to be the single value VALUE, such as a constant
306   or SSA_NAME.  */
307
308inline void
309gimple_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
317inline tree
318gimple_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.  */
324
325inline bool
326gimple_simplified_result_is_gimple_val (const gimple_match_op *op)
327{
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]));
332}
333
334extern tree (*mprts_hook) (gimple_match_op *);
335
336bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *,
337		      tree (*)(tree), tree (*)(tree));
338tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *,
339			    tree res = NULL_TREE);
340void maybe_build_generic_op (gimple_match_op *);
341
342
343#endif  /* GCC_GIMPLE_MATCH_H */
344