111
|
1 /* Preamble and helpers for the autogenerated gimple-match.c file.
|
|
2 Copyright (C) 2014-2017 Free Software Foundation, Inc.
|
|
3
|
|
4 This file is part of GCC.
|
|
5
|
|
6 GCC is free software; you can redistribute it and/or modify it under
|
|
7 the terms of the GNU General Public License as published by the Free
|
|
8 Software Foundation; either version 3, or (at your option) any later
|
|
9 version.
|
|
10
|
|
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with GCC; see the file COPYING3. If not see
|
|
18 <http://www.gnu.org/licenses/>. */
|
|
19
|
|
20 #include "config.h"
|
|
21 #include "system.h"
|
|
22 #include "coretypes.h"
|
|
23 #include "backend.h"
|
|
24 #include "target.h"
|
|
25 #include "rtl.h"
|
|
26 #include "tree.h"
|
|
27 #include "gimple.h"
|
|
28 #include "ssa.h"
|
|
29 #include "cgraph.h"
|
|
30 #include "fold-const.h"
|
|
31 #include "fold-const-call.h"
|
|
32 #include "stor-layout.h"
|
|
33 #include "gimple-fold.h"
|
|
34 #include "calls.h"
|
|
35 #include "tree-dfa.h"
|
|
36 #include "builtins.h"
|
|
37 #include "gimple-match.h"
|
|
38 #include "tree-pass.h"
|
|
39 #include "internal-fn.h"
|
|
40 #include "case-cfn-macros.h"
|
|
41 #include "gimplify.h"
|
|
42 #include "optabs-tree.h"
|
|
43
|
|
44
|
|
45 /* Forward declarations of the private auto-generated matchers.
|
|
46 They expect valueized operands in canonical order and do not
|
|
47 perform simplification of all-constant operands. */
|
|
48 static bool gimple_simplify (code_helper *, tree *,
|
|
49 gimple_seq *, tree (*)(tree),
|
|
50 code_helper, tree, tree);
|
|
51 static bool gimple_simplify (code_helper *, tree *,
|
|
52 gimple_seq *, tree (*)(tree),
|
|
53 code_helper, tree, tree, tree);
|
|
54 static bool gimple_simplify (code_helper *, tree *,
|
|
55 gimple_seq *, tree (*)(tree),
|
|
56 code_helper, tree, tree, tree, tree);
|
|
57
|
|
58
|
|
59 /* Return whether T is a constant that we'll dispatch to fold to
|
|
60 evaluate fully constant expressions. */
|
|
61
|
|
62 static inline bool
|
|
63 constant_for_folding (tree t)
|
|
64 {
|
|
65 return (CONSTANT_CLASS_P (t)
|
|
66 /* The following is only interesting to string builtins. */
|
|
67 || (TREE_CODE (t) == ADDR_EXPR
|
|
68 && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST));
|
|
69 }
|
|
70
|
|
71
|
|
72 /* Helper that matches and simplifies the toplevel result from
|
|
73 a gimple_simplify run (where we don't want to build
|
|
74 a stmt in case it's used in in-place folding). Replaces
|
|
75 *RES_CODE and *RES_OPS with a simplified and/or canonicalized
|
|
76 result and returns whether any change was made. */
|
|
77
|
|
78 bool
|
|
79 gimple_resimplify1 (gimple_seq *seq,
|
|
80 code_helper *res_code, tree type, tree *res_ops,
|
|
81 tree (*valueize)(tree))
|
|
82 {
|
|
83 if (constant_for_folding (res_ops[0]))
|
|
84 {
|
|
85 tree tem = NULL_TREE;
|
|
86 if (res_code->is_tree_code ())
|
|
87 tem = const_unop (*res_code, type, res_ops[0]);
|
|
88 else
|
|
89 tem = fold_const_call (combined_fn (*res_code), type, res_ops[0]);
|
|
90 if (tem != NULL_TREE
|
|
91 && CONSTANT_CLASS_P (tem))
|
|
92 {
|
|
93 if (TREE_OVERFLOW_P (tem))
|
|
94 tem = drop_tree_overflow (tem);
|
|
95 res_ops[0] = tem;
|
|
96 res_ops[1] = NULL_TREE;
|
|
97 res_ops[2] = NULL_TREE;
|
|
98 *res_code = TREE_CODE (res_ops[0]);
|
|
99 return true;
|
|
100 }
|
|
101 }
|
|
102
|
|
103 code_helper res_code2;
|
|
104 tree res_ops2[3] = {};
|
|
105 if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
|
|
106 *res_code, type, res_ops[0]))
|
|
107 {
|
|
108 *res_code = res_code2;
|
|
109 res_ops[0] = res_ops2[0];
|
|
110 res_ops[1] = res_ops2[1];
|
|
111 res_ops[2] = res_ops2[2];
|
|
112 return true;
|
|
113 }
|
|
114
|
|
115 return false;
|
|
116 }
|
|
117
|
|
118 /* Helper that matches and simplifies the toplevel result from
|
|
119 a gimple_simplify run (where we don't want to build
|
|
120 a stmt in case it's used in in-place folding). Replaces
|
|
121 *RES_CODE and *RES_OPS with a simplified and/or canonicalized
|
|
122 result and returns whether any change was made. */
|
|
123
|
|
124 bool
|
|
125 gimple_resimplify2 (gimple_seq *seq,
|
|
126 code_helper *res_code, tree type, tree *res_ops,
|
|
127 tree (*valueize)(tree))
|
|
128 {
|
|
129 if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1]))
|
|
130 {
|
|
131 tree tem = NULL_TREE;
|
|
132 if (res_code->is_tree_code ())
|
|
133 tem = const_binop (*res_code, type, res_ops[0], res_ops[1]);
|
|
134 else
|
|
135 tem = fold_const_call (combined_fn (*res_code), type,
|
|
136 res_ops[0], res_ops[1]);
|
|
137 if (tem != NULL_TREE
|
|
138 && CONSTANT_CLASS_P (tem))
|
|
139 {
|
|
140 if (TREE_OVERFLOW_P (tem))
|
|
141 tem = drop_tree_overflow (tem);
|
|
142 res_ops[0] = tem;
|
|
143 res_ops[1] = NULL_TREE;
|
|
144 res_ops[2] = NULL_TREE;
|
|
145 *res_code = TREE_CODE (res_ops[0]);
|
|
146 return true;
|
|
147 }
|
|
148 }
|
|
149
|
|
150 /* Canonicalize operand order. */
|
|
151 bool canonicalized = false;
|
|
152 if (res_code->is_tree_code ()
|
|
153 && (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison
|
|
154 || commutative_tree_code (*res_code))
|
|
155 && tree_swap_operands_p (res_ops[0], res_ops[1]))
|
|
156 {
|
|
157 std::swap (res_ops[0], res_ops[1]);
|
|
158 if (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison)
|
|
159 *res_code = swap_tree_comparison (*res_code);
|
|
160 canonicalized = true;
|
|
161 }
|
|
162
|
|
163 code_helper res_code2;
|
|
164 tree res_ops2[3] = {};
|
|
165 if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
|
|
166 *res_code, type, res_ops[0], res_ops[1]))
|
|
167 {
|
|
168 *res_code = res_code2;
|
|
169 res_ops[0] = res_ops2[0];
|
|
170 res_ops[1] = res_ops2[1];
|
|
171 res_ops[2] = res_ops2[2];
|
|
172 return true;
|
|
173 }
|
|
174
|
|
175 return canonicalized;
|
|
176 }
|
|
177
|
|
178 /* Helper that matches and simplifies the toplevel result from
|
|
179 a gimple_simplify run (where we don't want to build
|
|
180 a stmt in case it's used in in-place folding). Replaces
|
|
181 *RES_CODE and *RES_OPS with a simplified and/or canonicalized
|
|
182 result and returns whether any change was made. */
|
|
183
|
|
184 bool
|
|
185 gimple_resimplify3 (gimple_seq *seq,
|
|
186 code_helper *res_code, tree type, tree *res_ops,
|
|
187 tree (*valueize)(tree))
|
|
188 {
|
|
189 if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1])
|
|
190 && constant_for_folding (res_ops[2]))
|
|
191 {
|
|
192 tree tem = NULL_TREE;
|
|
193 if (res_code->is_tree_code ())
|
|
194 tem = fold_ternary/*_to_constant*/ (*res_code, type, res_ops[0],
|
|
195 res_ops[1], res_ops[2]);
|
|
196 else
|
|
197 tem = fold_const_call (combined_fn (*res_code), type,
|
|
198 res_ops[0], res_ops[1], res_ops[2]);
|
|
199 if (tem != NULL_TREE
|
|
200 && CONSTANT_CLASS_P (tem))
|
|
201 {
|
|
202 if (TREE_OVERFLOW_P (tem))
|
|
203 tem = drop_tree_overflow (tem);
|
|
204 res_ops[0] = tem;
|
|
205 res_ops[1] = NULL_TREE;
|
|
206 res_ops[2] = NULL_TREE;
|
|
207 *res_code = TREE_CODE (res_ops[0]);
|
|
208 return true;
|
|
209 }
|
|
210 }
|
|
211
|
|
212 /* Canonicalize operand order. */
|
|
213 bool canonicalized = false;
|
|
214 if (res_code->is_tree_code ()
|
|
215 && commutative_ternary_tree_code (*res_code)
|
|
216 && tree_swap_operands_p (res_ops[0], res_ops[1]))
|
|
217 {
|
|
218 std::swap (res_ops[0], res_ops[1]);
|
|
219 canonicalized = true;
|
|
220 }
|
|
221
|
|
222 code_helper res_code2;
|
|
223 tree res_ops2[3] = {};
|
|
224 if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
|
|
225 *res_code, type,
|
|
226 res_ops[0], res_ops[1], res_ops[2]))
|
|
227 {
|
|
228 *res_code = res_code2;
|
|
229 res_ops[0] = res_ops2[0];
|
|
230 res_ops[1] = res_ops2[1];
|
|
231 res_ops[2] = res_ops2[2];
|
|
232 return true;
|
|
233 }
|
|
234
|
|
235 return canonicalized;
|
|
236 }
|
|
237
|
|
238
|
|
239 /* If in GIMPLE expressions with CODE go as single-rhs build
|
|
240 a GENERIC tree for that expression into *OP0. */
|
|
241
|
|
242 void
|
|
243 maybe_build_generic_op (enum tree_code code, tree type, tree *ops)
|
|
244 {
|
|
245 switch (code)
|
|
246 {
|
|
247 case REALPART_EXPR:
|
|
248 case IMAGPART_EXPR:
|
|
249 case VIEW_CONVERT_EXPR:
|
|
250 ops[0] = build1 (code, type, ops[0]);
|
|
251 break;
|
|
252 case BIT_FIELD_REF:
|
|
253 ops[0] = build3 (code, type, ops[0], ops[1], ops[2]);
|
|
254 ops[1] = ops[2] = NULL_TREE;
|
|
255 break;
|
|
256 default:;
|
|
257 }
|
|
258 }
|
|
259
|
|
260 tree (*mprts_hook) (code_helper, tree, tree *);
|
|
261
|
|
262 /* Try to build a call to FN with return type TYPE and the NARGS
|
|
263 arguments given in OPS. Return null if the target doesn't support
|
|
264 the function. */
|
|
265
|
|
266 static gcall *
|
|
267 build_call_internal (internal_fn fn, tree type, unsigned int nargs, tree *ops)
|
|
268 {
|
|
269 if (direct_internal_fn_p (fn))
|
|
270 {
|
|
271 tree_pair types = direct_internal_fn_types (fn, type, ops);
|
|
272 if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
|
|
273 return NULL;
|
|
274 }
|
|
275 return gimple_build_call_internal (fn, nargs, ops[0], ops[1], ops[2]);
|
|
276 }
|
|
277
|
|
278 /* Push the exploded expression described by RCODE, TYPE and OPS
|
|
279 as a statement to SEQ if necessary and return a gimple value
|
|
280 denoting the value of the expression. If RES is not NULL
|
|
281 then the result will be always RES and even gimple values are
|
|
282 pushed to SEQ. */
|
|
283
|
|
284 tree
|
|
285 maybe_push_res_to_seq (code_helper rcode, tree type, tree *ops,
|
|
286 gimple_seq *seq, tree res)
|
|
287 {
|
|
288 if (rcode.is_tree_code ())
|
|
289 {
|
|
290 if (!res
|
|
291 && gimple_simplified_result_is_gimple_val (rcode, ops))
|
|
292 return ops[0];
|
|
293 if (mprts_hook)
|
|
294 {
|
|
295 tree tem = mprts_hook (rcode, type, ops);
|
|
296 if (tem)
|
|
297 return tem;
|
|
298 }
|
|
299 if (!seq)
|
|
300 return NULL_TREE;
|
|
301 /* Play safe and do not allow abnormals to be mentioned in
|
|
302 newly created statements. */
|
|
303 if ((TREE_CODE (ops[0]) == SSA_NAME
|
|
304 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0]))
|
|
305 || (ops[1]
|
|
306 && TREE_CODE (ops[1]) == SSA_NAME
|
|
307 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1]))
|
|
308 || (ops[2]
|
|
309 && TREE_CODE (ops[2]) == SSA_NAME
|
|
310 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2]))
|
|
311 || (COMPARISON_CLASS_P (ops[0])
|
|
312 && ((TREE_CODE (TREE_OPERAND (ops[0], 0)) == SSA_NAME
|
|
313 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0],
|
|
314 0)))
|
|
315 || (TREE_CODE (TREE_OPERAND (ops[0], 1)) == SSA_NAME
|
|
316 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0],
|
|
317 1))))))
|
|
318 return NULL_TREE;
|
|
319 if (!res)
|
|
320 {
|
|
321 if (gimple_in_ssa_p (cfun))
|
|
322 res = make_ssa_name (type);
|
|
323 else
|
|
324 res = create_tmp_reg (type);
|
|
325 }
|
|
326 maybe_build_generic_op (rcode, type, ops);
|
|
327 gimple *new_stmt = gimple_build_assign (res, rcode,
|
|
328 ops[0], ops[1], ops[2]);
|
|
329 gimple_seq_add_stmt_without_update (seq, new_stmt);
|
|
330 return res;
|
|
331 }
|
|
332 else
|
|
333 {
|
|
334 if (!seq)
|
|
335 return NULL_TREE;
|
|
336 combined_fn fn = rcode;
|
|
337 /* Play safe and do not allow abnormals to be mentioned in
|
|
338 newly created statements. */
|
|
339 unsigned nargs;
|
|
340 for (nargs = 0; nargs < 3; ++nargs)
|
|
341 {
|
|
342 if (!ops[nargs])
|
|
343 break;
|
|
344 if (TREE_CODE (ops[nargs]) == SSA_NAME
|
|
345 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[nargs]))
|
|
346 return NULL_TREE;
|
|
347 }
|
|
348 gcc_assert (nargs != 0);
|
|
349 gcall *new_stmt = NULL;
|
|
350 if (internal_fn_p (fn))
|
|
351 {
|
|
352 /* Generate the given function if we can. */
|
|
353 internal_fn ifn = as_internal_fn (fn);
|
|
354 new_stmt = build_call_internal (ifn, type, nargs, ops);
|
|
355 if (!new_stmt)
|
|
356 return NULL_TREE;
|
|
357 }
|
|
358 else
|
|
359 {
|
|
360 /* Find the function we want to call. */
|
|
361 tree decl = builtin_decl_implicit (as_builtin_fn (fn));
|
|
362 if (!decl)
|
|
363 return NULL;
|
|
364
|
|
365 /* We can't and should not emit calls to non-const functions. */
|
|
366 if (!(flags_from_decl_or_type (decl) & ECF_CONST))
|
|
367 return NULL;
|
|
368
|
|
369 new_stmt = gimple_build_call (decl, nargs, ops[0], ops[1], ops[2]);
|
|
370 }
|
|
371 if (!res)
|
|
372 {
|
|
373 if (gimple_in_ssa_p (cfun))
|
|
374 res = make_ssa_name (type);
|
|
375 else
|
|
376 res = create_tmp_reg (type);
|
|
377 }
|
|
378 gimple_call_set_lhs (new_stmt, res);
|
|
379 gimple_seq_add_stmt_without_update (seq, new_stmt);
|
|
380 return res;
|
|
381 }
|
|
382 }
|
|
383
|
|
384
|
|
385 /* Public API overloads follow for operation being tree_code or
|
|
386 built_in_function and for one to three operands or arguments.
|
|
387 They return NULL_TREE if nothing could be simplified or
|
|
388 the resulting simplified value with parts pushed to SEQ.
|
|
389 If SEQ is NULL then if the simplification needs to create
|
|
390 new stmts it will fail. If VALUEIZE is non-NULL then all
|
|
391 SSA names will be valueized using that hook prior to
|
|
392 applying simplifications. */
|
|
393
|
|
394 /* Unary ops. */
|
|
395
|
|
396 tree
|
|
397 gimple_simplify (enum tree_code code, tree type,
|
|
398 tree op0,
|
|
399 gimple_seq *seq, tree (*valueize)(tree))
|
|
400 {
|
|
401 if (constant_for_folding (op0))
|
|
402 {
|
|
403 tree res = const_unop (code, type, op0);
|
|
404 if (res != NULL_TREE
|
|
405 && CONSTANT_CLASS_P (res))
|
|
406 return res;
|
|
407 }
|
|
408
|
|
409 code_helper rcode;
|
|
410 tree ops[3] = {};
|
|
411 if (!gimple_simplify (&rcode, ops, seq, valueize,
|
|
412 code, type, op0))
|
|
413 return NULL_TREE;
|
|
414 return maybe_push_res_to_seq (rcode, type, ops, seq);
|
|
415 }
|
|
416
|
|
417 /* Binary ops. */
|
|
418
|
|
419 tree
|
|
420 gimple_simplify (enum tree_code code, tree type,
|
|
421 tree op0, tree op1,
|
|
422 gimple_seq *seq, tree (*valueize)(tree))
|
|
423 {
|
|
424 if (constant_for_folding (op0) && constant_for_folding (op1))
|
|
425 {
|
|
426 tree res = const_binop (code, type, op0, op1);
|
|
427 if (res != NULL_TREE
|
|
428 && CONSTANT_CLASS_P (res))
|
|
429 return res;
|
|
430 }
|
|
431
|
|
432 /* Canonicalize operand order both for matching and fallback stmt
|
|
433 generation. */
|
|
434 if ((commutative_tree_code (code)
|
|
435 || TREE_CODE_CLASS (code) == tcc_comparison)
|
|
436 && tree_swap_operands_p (op0, op1))
|
|
437 {
|
|
438 std::swap (op0, op1);
|
|
439 if (TREE_CODE_CLASS (code) == tcc_comparison)
|
|
440 code = swap_tree_comparison (code);
|
|
441 }
|
|
442
|
|
443 code_helper rcode;
|
|
444 tree ops[3] = {};
|
|
445 if (!gimple_simplify (&rcode, ops, seq, valueize,
|
|
446 code, type, op0, op1))
|
|
447 return NULL_TREE;
|
|
448 return maybe_push_res_to_seq (rcode, type, ops, seq);
|
|
449 }
|
|
450
|
|
451 /* Ternary ops. */
|
|
452
|
|
453 tree
|
|
454 gimple_simplify (enum tree_code code, tree type,
|
|
455 tree op0, tree op1, tree op2,
|
|
456 gimple_seq *seq, tree (*valueize)(tree))
|
|
457 {
|
|
458 if (constant_for_folding (op0) && constant_for_folding (op1)
|
|
459 && constant_for_folding (op2))
|
|
460 {
|
|
461 tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
|
|
462 if (res != NULL_TREE
|
|
463 && CONSTANT_CLASS_P (res))
|
|
464 return res;
|
|
465 }
|
|
466
|
|
467 /* Canonicalize operand order both for matching and fallback stmt
|
|
468 generation. */
|
|
469 if (commutative_ternary_tree_code (code)
|
|
470 && tree_swap_operands_p (op0, op1))
|
|
471 std::swap (op0, op1);
|
|
472
|
|
473 code_helper rcode;
|
|
474 tree ops[3] = {};
|
|
475 if (!gimple_simplify (&rcode, ops, seq, valueize,
|
|
476 code, type, op0, op1, op2))
|
|
477 return NULL_TREE;
|
|
478 return maybe_push_res_to_seq (rcode, type, ops, seq);
|
|
479 }
|
|
480
|
|
481 /* Builtin function with one argument. */
|
|
482
|
|
483 tree
|
|
484 gimple_simplify (enum built_in_function fn, tree type,
|
|
485 tree arg0,
|
|
486 gimple_seq *seq, tree (*valueize)(tree))
|
|
487 {
|
|
488 if (constant_for_folding (arg0))
|
|
489 {
|
|
490 tree res = fold_const_call (as_combined_fn (fn), type, arg0);
|
|
491 if (res && CONSTANT_CLASS_P (res))
|
|
492 return res;
|
|
493 }
|
|
494
|
|
495 code_helper rcode;
|
|
496 tree ops[3] = {};
|
|
497 if (!gimple_simplify (&rcode, ops, seq, valueize,
|
|
498 as_combined_fn (fn), type, arg0))
|
|
499 return NULL_TREE;
|
|
500 return maybe_push_res_to_seq (rcode, type, ops, seq);
|
|
501 }
|
|
502
|
|
503 /* Builtin function with two arguments. */
|
|
504
|
|
505 tree
|
|
506 gimple_simplify (enum built_in_function fn, tree type,
|
|
507 tree arg0, tree arg1,
|
|
508 gimple_seq *seq, tree (*valueize)(tree))
|
|
509 {
|
|
510 if (constant_for_folding (arg0)
|
|
511 && constant_for_folding (arg1))
|
|
512 {
|
|
513 tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1);
|
|
514 if (res && CONSTANT_CLASS_P (res))
|
|
515 return res;
|
|
516 }
|
|
517
|
|
518 code_helper rcode;
|
|
519 tree ops[3] = {};
|
|
520 if (!gimple_simplify (&rcode, ops, seq, valueize,
|
|
521 as_combined_fn (fn), type, arg0, arg1))
|
|
522 return NULL_TREE;
|
|
523 return maybe_push_res_to_seq (rcode, type, ops, seq);
|
|
524 }
|
|
525
|
|
526 /* Builtin function with three arguments. */
|
|
527
|
|
528 tree
|
|
529 gimple_simplify (enum built_in_function fn, tree type,
|
|
530 tree arg0, tree arg1, tree arg2,
|
|
531 gimple_seq *seq, tree (*valueize)(tree))
|
|
532 {
|
|
533 if (constant_for_folding (arg0)
|
|
534 && constant_for_folding (arg1)
|
|
535 && constant_for_folding (arg2))
|
|
536 {
|
|
537 tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1, arg2);
|
|
538 if (res && CONSTANT_CLASS_P (res))
|
|
539 return res;
|
|
540 }
|
|
541
|
|
542 code_helper rcode;
|
|
543 tree ops[3] = {};
|
|
544 if (!gimple_simplify (&rcode, ops, seq, valueize,
|
|
545 as_combined_fn (fn), type, arg0, arg1, arg2))
|
|
546 return NULL_TREE;
|
|
547 return maybe_push_res_to_seq (rcode, type, ops, seq);
|
|
548 }
|
|
549
|
|
550 /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
|
|
551 VALUEIZED to true if valueization changed OP. */
|
|
552
|
|
553 static inline tree
|
|
554 do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
|
|
555 {
|
|
556 if (valueize && TREE_CODE (op) == SSA_NAME)
|
|
557 {
|
|
558 tree tem = valueize (op);
|
|
559 if (tem && tem != op)
|
|
560 {
|
|
561 op = tem;
|
|
562 valueized = true;
|
|
563 }
|
|
564 }
|
|
565 return op;
|
|
566 }
|
|
567
|
|
568 /* The main STMT based simplification entry. It is used by the fold_stmt
|
|
569 and the fold_stmt_to_constant APIs. */
|
|
570
|
|
571 bool
|
|
572 gimple_simplify (gimple *stmt,
|
|
573 code_helper *rcode, tree *ops,
|
|
574 gimple_seq *seq,
|
|
575 tree (*valueize)(tree), tree (*top_valueize)(tree))
|
|
576 {
|
|
577 switch (gimple_code (stmt))
|
|
578 {
|
|
579 case GIMPLE_ASSIGN:
|
|
580 {
|
|
581 enum tree_code code = gimple_assign_rhs_code (stmt);
|
|
582 tree type = TREE_TYPE (gimple_assign_lhs (stmt));
|
|
583 switch (gimple_assign_rhs_class (stmt))
|
|
584 {
|
|
585 case GIMPLE_SINGLE_RHS:
|
|
586 if (code == REALPART_EXPR
|
|
587 || code == IMAGPART_EXPR
|
|
588 || code == VIEW_CONVERT_EXPR)
|
|
589 {
|
|
590 tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
|
|
591 bool valueized = false;
|
|
592 op0 = do_valueize (op0, top_valueize, valueized);
|
|
593 *rcode = code;
|
|
594 ops[0] = op0;
|
|
595 return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
|
|
596 || valueized);
|
|
597 }
|
|
598 else if (code == BIT_FIELD_REF)
|
|
599 {
|
|
600 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
601 tree op0 = TREE_OPERAND (rhs1, 0);
|
|
602 bool valueized = false;
|
|
603 op0 = do_valueize (op0, top_valueize, valueized);
|
|
604 *rcode = code;
|
|
605 ops[0] = op0;
|
|
606 ops[1] = TREE_OPERAND (rhs1, 1);
|
|
607 ops[2] = TREE_OPERAND (rhs1, 2);
|
|
608 return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
|
|
609 || valueized);
|
|
610 }
|
|
611 else if (code == SSA_NAME
|
|
612 && top_valueize)
|
|
613 {
|
|
614 tree op0 = gimple_assign_rhs1 (stmt);
|
|
615 tree valueized = top_valueize (op0);
|
|
616 if (!valueized || op0 == valueized)
|
|
617 return false;
|
|
618 ops[0] = valueized;
|
|
619 *rcode = TREE_CODE (op0);
|
|
620 return true;
|
|
621 }
|
|
622 break;
|
|
623 case GIMPLE_UNARY_RHS:
|
|
624 {
|
|
625 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
626 bool valueized = false;
|
|
627 rhs1 = do_valueize (rhs1, top_valueize, valueized);
|
|
628 *rcode = code;
|
|
629 ops[0] = rhs1;
|
|
630 return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
|
|
631 || valueized);
|
|
632 }
|
|
633 case GIMPLE_BINARY_RHS:
|
|
634 {
|
|
635 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
636 tree rhs2 = gimple_assign_rhs2 (stmt);
|
|
637 bool valueized = false;
|
|
638 rhs1 = do_valueize (rhs1, top_valueize, valueized);
|
|
639 rhs2 = do_valueize (rhs2, top_valueize, valueized);
|
|
640 *rcode = code;
|
|
641 ops[0] = rhs1;
|
|
642 ops[1] = rhs2;
|
|
643 return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
|
|
644 || valueized);
|
|
645 }
|
|
646 case GIMPLE_TERNARY_RHS:
|
|
647 {
|
|
648 bool valueized = false;
|
|
649 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
650 /* If this is a [VEC_]COND_EXPR first try to simplify an
|
|
651 embedded GENERIC condition. */
|
|
652 if (code == COND_EXPR
|
|
653 || code == VEC_COND_EXPR)
|
|
654 {
|
|
655 if (COMPARISON_CLASS_P (rhs1))
|
|
656 {
|
|
657 tree lhs = TREE_OPERAND (rhs1, 0);
|
|
658 tree rhs = TREE_OPERAND (rhs1, 1);
|
|
659 lhs = do_valueize (lhs, top_valueize, valueized);
|
|
660 rhs = do_valueize (rhs, top_valueize, valueized);
|
|
661 code_helper rcode2 = TREE_CODE (rhs1);
|
|
662 tree ops2[3] = {};
|
|
663 ops2[0] = lhs;
|
|
664 ops2[1] = rhs;
|
|
665 if ((gimple_resimplify2 (seq, &rcode2, TREE_TYPE (rhs1),
|
|
666 ops2, valueize)
|
|
667 || valueized)
|
|
668 && rcode2.is_tree_code ())
|
|
669 {
|
|
670 valueized = true;
|
|
671 if (TREE_CODE_CLASS ((enum tree_code)rcode2)
|
|
672 == tcc_comparison)
|
|
673 rhs1 = build2 (rcode2, TREE_TYPE (rhs1),
|
|
674 ops2[0], ops2[1]);
|
|
675 else if (rcode2 == SSA_NAME
|
|
676 || rcode2 == INTEGER_CST
|
|
677 || rcode2 == VECTOR_CST)
|
|
678 rhs1 = ops2[0];
|
|
679 else
|
|
680 valueized = false;
|
|
681 }
|
|
682 }
|
|
683 }
|
|
684 tree rhs2 = gimple_assign_rhs2 (stmt);
|
|
685 tree rhs3 = gimple_assign_rhs3 (stmt);
|
|
686 rhs1 = do_valueize (rhs1, top_valueize, valueized);
|
|
687 rhs2 = do_valueize (rhs2, top_valueize, valueized);
|
|
688 rhs3 = do_valueize (rhs3, top_valueize, valueized);
|
|
689 *rcode = code;
|
|
690 ops[0] = rhs1;
|
|
691 ops[1] = rhs2;
|
|
692 ops[2] = rhs3;
|
|
693 return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
|
|
694 || valueized);
|
|
695 }
|
|
696 default:
|
|
697 gcc_unreachable ();
|
|
698 }
|
|
699 break;
|
|
700 }
|
|
701
|
|
702 case GIMPLE_CALL:
|
|
703 /* ??? This way we can't simplify calls with side-effects. */
|
|
704 if (gimple_call_lhs (stmt) != NULL_TREE
|
|
705 && gimple_call_num_args (stmt) >= 1
|
|
706 && gimple_call_num_args (stmt) <= 3)
|
|
707 {
|
|
708 bool valueized = false;
|
|
709 if (gimple_call_internal_p (stmt))
|
|
710 *rcode = as_combined_fn (gimple_call_internal_fn (stmt));
|
|
711 else
|
|
712 {
|
|
713 tree fn = gimple_call_fn (stmt);
|
|
714 if (!fn)
|
|
715 return false;
|
|
716
|
|
717 fn = do_valueize (fn, top_valueize, valueized);
|
|
718 if (TREE_CODE (fn) != ADDR_EXPR
|
|
719 || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
|
|
720 return false;
|
|
721
|
|
722 tree decl = TREE_OPERAND (fn, 0);
|
|
723 if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
|
|
724 || !gimple_builtin_call_types_compatible_p (stmt, decl))
|
|
725 return false;
|
|
726
|
|
727 *rcode = as_combined_fn (DECL_FUNCTION_CODE (decl));
|
|
728 }
|
|
729
|
|
730 tree type = TREE_TYPE (gimple_call_lhs (stmt));
|
|
731 for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
|
|
732 {
|
|
733 tree arg = gimple_call_arg (stmt, i);
|
|
734 ops[i] = do_valueize (arg, top_valueize, valueized);
|
|
735 }
|
|
736 switch (gimple_call_num_args (stmt))
|
|
737 {
|
|
738 case 1:
|
|
739 return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
|
|
740 || valueized);
|
|
741 case 2:
|
|
742 return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
|
|
743 || valueized);
|
|
744 case 3:
|
|
745 return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
|
|
746 || valueized);
|
|
747 default:
|
|
748 gcc_unreachable ();
|
|
749 }
|
|
750 }
|
|
751 break;
|
|
752
|
|
753 case GIMPLE_COND:
|
|
754 {
|
|
755 tree lhs = gimple_cond_lhs (stmt);
|
|
756 tree rhs = gimple_cond_rhs (stmt);
|
|
757 bool valueized = false;
|
|
758 lhs = do_valueize (lhs, top_valueize, valueized);
|
|
759 rhs = do_valueize (rhs, top_valueize, valueized);
|
|
760 *rcode = gimple_cond_code (stmt);
|
|
761 ops[0] = lhs;
|
|
762 ops[1] = rhs;
|
|
763 return (gimple_resimplify2 (seq, rcode,
|
|
764 boolean_type_node, ops, valueize)
|
|
765 || valueized);
|
|
766 }
|
|
767
|
|
768 default:
|
|
769 break;
|
|
770 }
|
|
771
|
|
772 return false;
|
|
773 }
|
|
774
|
|
775
|
|
776 /* Helper for the autogenerated code, valueize OP. */
|
|
777
|
|
778 inline tree
|
|
779 do_valueize (tree (*valueize)(tree), tree op)
|
|
780 {
|
|
781 if (valueize && TREE_CODE (op) == SSA_NAME)
|
|
782 {
|
|
783 tree tem = valueize (op);
|
|
784 if (tem)
|
|
785 return tem;
|
|
786 }
|
|
787 return op;
|
|
788 }
|
|
789
|
|
790 /* Helper for the autogenerated code, get at the definition of NAME when
|
|
791 VALUEIZE allows that. */
|
|
792
|
|
793 inline gimple *
|
|
794 get_def (tree (*valueize)(tree), tree name)
|
|
795 {
|
|
796 if (valueize && ! valueize (name))
|
|
797 return NULL;
|
|
798 return SSA_NAME_DEF_STMT (name);
|
|
799 }
|
|
800
|
|
801 /* Routine to determine if the types T1 and T2 are effectively
|
|
802 the same for GIMPLE. If T1 or T2 is not a type, the test
|
|
803 applies to their TREE_TYPE. */
|
|
804
|
|
805 static inline bool
|
|
806 types_match (tree t1, tree t2)
|
|
807 {
|
|
808 if (!TYPE_P (t1))
|
|
809 t1 = TREE_TYPE (t1);
|
|
810 if (!TYPE_P (t2))
|
|
811 t2 = TREE_TYPE (t2);
|
|
812
|
|
813 return types_compatible_p (t1, t2);
|
|
814 }
|
|
815
|
|
816 /* Return if T has a single use. For GIMPLE, we also allow any
|
|
817 non-SSA_NAME (ie constants) and zero uses to cope with uses
|
|
818 that aren't linked up yet. */
|
|
819
|
|
820 static inline bool
|
|
821 single_use (tree t)
|
|
822 {
|
|
823 return TREE_CODE (t) != SSA_NAME || has_zero_uses (t) || has_single_use (t);
|
|
824 }
|
|
825
|
|
826 /* Return true if math operations should be canonicalized,
|
|
827 e.g. sqrt(sqrt(x)) -> pow(x, 0.25). */
|
|
828
|
|
829 static inline bool
|
|
830 canonicalize_math_p ()
|
|
831 {
|
|
832 return !cfun || (cfun->curr_properties & PROP_gimple_opt_math) == 0;
|
|
833 }
|