111
|
1 /* Preamble and helpers for the autogenerated gimple-match.c file.
|
145
|
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
111
|
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"
|
145
|
30 #include "vec-perm-indices.h"
|
111
|
31 #include "fold-const.h"
|
|
32 #include "fold-const-call.h"
|
|
33 #include "stor-layout.h"
|
|
34 #include "gimple-fold.h"
|
|
35 #include "calls.h"
|
|
36 #include "tree-dfa.h"
|
|
37 #include "builtins.h"
|
|
38 #include "gimple-match.h"
|
|
39 #include "tree-pass.h"
|
|
40 #include "internal-fn.h"
|
|
41 #include "case-cfn-macros.h"
|
|
42 #include "gimplify.h"
|
|
43 #include "optabs-tree.h"
|
131
|
44 #include "tree-eh.h"
|
145
|
45 #include "dbgcnt.h"
|
111
|
46
|
|
47 /* Forward declarations of the private auto-generated matchers.
|
|
48 They expect valueized operands in canonical order and do not
|
|
49 perform simplification of all-constant operands. */
|
131
|
50 static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
|
111
|
51 code_helper, tree, tree);
|
131
|
52 static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
|
111
|
53 code_helper, tree, tree, tree);
|
131
|
54 static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
|
111
|
55 code_helper, tree, tree, tree, tree);
|
131
|
56 static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
|
|
57 code_helper, tree, tree, tree, tree, tree);
|
|
58 static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
|
|
59 code_helper, tree, tree, tree, tree, tree, tree);
|
145
|
60 static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *,
|
|
61 tree (*)(tree));
|
|
62 static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *,
|
|
63 tree (*)(tree));
|
|
64 static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *,
|
|
65 tree (*)(tree));
|
|
66 static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *,
|
|
67 tree (*)(tree));
|
|
68 static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *,
|
|
69 tree (*)(tree));
|
111
|
70
|
131
|
71 const unsigned int gimple_match_op::MAX_NUM_OPS;
|
111
|
72
|
|
73 /* Return whether T is a constant that we'll dispatch to fold to
|
|
74 evaluate fully constant expressions. */
|
|
75
|
|
76 static inline bool
|
|
77 constant_for_folding (tree t)
|
|
78 {
|
|
79 return (CONSTANT_CLASS_P (t)
|
|
80 /* The following is only interesting to string builtins. */
|
|
81 || (TREE_CODE (t) == ADDR_EXPR
|
|
82 && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST));
|
|
83 }
|
|
84
|
131
|
85 /* Try to convert conditional operation ORIG_OP into an IFN_COND_*
|
|
86 operation. Return true on success, storing the new operation in NEW_OP. */
|
111
|
87
|
131
|
88 static bool
|
|
89 convert_conditional_op (gimple_match_op *orig_op,
|
|
90 gimple_match_op *new_op)
|
111
|
91 {
|
131
|
92 internal_fn ifn;
|
|
93 if (orig_op->code.is_tree_code ())
|
|
94 ifn = get_conditional_internal_fn ((tree_code) orig_op->code);
|
|
95 else
|
111
|
96 {
|
131
|
97 combined_fn cfn = orig_op->code;
|
|
98 if (!internal_fn_p (cfn))
|
|
99 return false;
|
|
100 ifn = get_conditional_internal_fn (as_internal_fn (cfn));
|
|
101 }
|
|
102 if (ifn == IFN_LAST)
|
|
103 return false;
|
|
104 unsigned int num_ops = orig_op->num_ops;
|
|
105 new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + 2);
|
|
106 new_op->ops[0] = orig_op->cond.cond;
|
|
107 for (unsigned int i = 0; i < num_ops; ++i)
|
|
108 new_op->ops[i + 1] = orig_op->ops[i];
|
|
109 tree else_value = orig_op->cond.else_value;
|
|
110 if (!else_value)
|
|
111 else_value = targetm.preferred_else_value (ifn, orig_op->type,
|
|
112 num_ops, orig_op->ops);
|
|
113 new_op->ops[num_ops + 1] = else_value;
|
|
114 return true;
|
|
115 }
|
|
116
|
|
117 /* RES_OP is the result of a simplification. If it is conditional,
|
|
118 try to replace it with the equivalent UNCOND form, such as an
|
|
119 IFN_COND_* call or a VEC_COND_EXPR. Also try to resimplify the
|
|
120 result of the replacement if appropriate, adding any new statements to
|
|
121 SEQ and using VALUEIZE as the valueization function. Return true if
|
|
122 this resimplification occurred and resulted in at least one change. */
|
|
123
|
|
124 static bool
|
|
125 maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
|
|
126 tree (*valueize) (tree))
|
|
127 {
|
|
128 if (!res_op->cond.cond)
|
|
129 return false;
|
|
130
|
|
131 if (!res_op->cond.else_value
|
|
132 && res_op->code.is_tree_code ())
|
|
133 {
|
|
134 /* The "else" value doesn't matter. If the "then" value is a
|
|
135 gimple value, just use it unconditionally. This isn't a
|
|
136 simplification in itself, since there was no operation to
|
|
137 build in the first place. */
|
|
138 if (gimple_simplified_result_is_gimple_val (res_op))
|
111
|
139 {
|
131
|
140 res_op->cond.cond = NULL_TREE;
|
|
141 return false;
|
|
142 }
|
|
143
|
|
144 /* Likewise if the operation would not trap. */
|
|
145 bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
|
|
146 && TYPE_OVERFLOW_TRAPS (res_op->type));
|
145
|
147 tree_code op_code = (tree_code) res_op->code;
|
|
148 bool op_could_trap;
|
|
149
|
|
150 /* COND_EXPR and VEC_COND_EXPR will trap if, and only if, the condition
|
|
151 traps and hence we have to check this. For all other operations, we
|
|
152 don't need to consider the operands. */
|
|
153 if (op_code == COND_EXPR || op_code == VEC_COND_EXPR)
|
|
154 op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
|
|
155 else
|
|
156 op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
|
|
157 FLOAT_TYPE_P (res_op->type),
|
|
158 honor_trapv,
|
|
159 res_op->op_or_null (1));
|
|
160
|
|
161 if (!op_could_trap)
|
131
|
162 {
|
|
163 res_op->cond.cond = NULL_TREE;
|
|
164 return false;
|
111
|
165 }
|
|
166 }
|
|
167
|
131
|
168 /* If the "then" value is a gimple value and the "else" value matters,
|
|
169 create a VEC_COND_EXPR between them, then see if it can be further
|
|
170 simplified. */
|
|
171 gimple_match_op new_op;
|
|
172 if (res_op->cond.else_value
|
|
173 && VECTOR_TYPE_P (res_op->type)
|
|
174 && gimple_simplified_result_is_gimple_val (res_op))
|
111
|
175 {
|
131
|
176 new_op.set_op (VEC_COND_EXPR, res_op->type,
|
|
177 res_op->cond.cond, res_op->ops[0],
|
|
178 res_op->cond.else_value);
|
|
179 *res_op = new_op;
|
|
180 return gimple_resimplify3 (seq, res_op, valueize);
|
111
|
181 }
|
|
182
|
131
|
183 /* Otherwise try rewriting the operation as an IFN_COND_* call.
|
|
184 Again, this isn't a simplification in itself, since it's what
|
|
185 RES_OP already described. */
|
|
186 if (convert_conditional_op (res_op, &new_op))
|
|
187 *res_op = new_op;
|
|
188
|
111
|
189 return false;
|
|
190 }
|
|
191
|
|
192 /* Helper that matches and simplifies the toplevel result from
|
|
193 a gimple_simplify run (where we don't want to build
|
|
194 a stmt in case it's used in in-place folding). Replaces
|
131
|
195 RES_OP with a simplified and/or canonicalized result and
|
|
196 returns whether any change was made. */
|
111
|
197
|
145
|
198 static bool
|
131
|
199 gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
|
111
|
200 tree (*valueize)(tree))
|
|
201 {
|
131
|
202 if (constant_for_folding (res_op->ops[0]))
|
111
|
203 {
|
|
204 tree tem = NULL_TREE;
|
131
|
205 if (res_op->code.is_tree_code ())
|
145
|
206 {
|
|
207 tree_code code = res_op->code;
|
|
208 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
|
|
209 && TREE_CODE_LENGTH (code) == 1)
|
|
210 tem = const_unop (res_op->code, res_op->type, res_op->ops[0]);
|
|
211 }
|
111
|
212 else
|
131
|
213 tem = fold_const_call (combined_fn (res_op->code), res_op->type,
|
|
214 res_op->ops[0]);
|
111
|
215 if (tem != NULL_TREE
|
|
216 && CONSTANT_CLASS_P (tem))
|
|
217 {
|
|
218 if (TREE_OVERFLOW_P (tem))
|
|
219 tem = drop_tree_overflow (tem);
|
131
|
220 res_op->set_value (tem);
|
|
221 maybe_resimplify_conditional_op (seq, res_op, valueize);
|
|
222 return true;
|
|
223 }
|
|
224 }
|
|
225
|
|
226 /* Limit recursion, there are cases like PR80887 and others, for
|
|
227 example when value-numbering presents us with unfolded expressions
|
|
228 that we are really not prepared to handle without eventual
|
|
229 oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50
|
|
230 itself as available expression. */
|
|
231 static unsigned depth;
|
|
232 if (depth > 10)
|
|
233 {
|
|
234 if (dump_file && (dump_flags & TDF_FOLDING))
|
|
235 fprintf (dump_file, "Aborting expression simplification due to "
|
|
236 "deep recursion\n");
|
|
237 return false;
|
|
238 }
|
|
239
|
|
240 ++depth;
|
|
241 gimple_match_op res_op2 (*res_op);
|
|
242 if (gimple_simplify (&res_op2, seq, valueize,
|
|
243 res_op->code, res_op->type, res_op->ops[0]))
|
|
244 {
|
|
245 --depth;
|
|
246 *res_op = res_op2;
|
|
247 return true;
|
|
248 }
|
|
249 --depth;
|
|
250
|
|
251 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
|
|
252 return true;
|
|
253
|
|
254 return false;
|
|
255 }
|
|
256
|
|
257 /* Helper that matches and simplifies the toplevel result from
|
|
258 a gimple_simplify run (where we don't want to build
|
|
259 a stmt in case it's used in in-place folding). Replaces
|
|
260 RES_OP with a simplified and/or canonicalized result and
|
|
261 returns whether any change was made. */
|
|
262
|
145
|
263 static bool
|
131
|
264 gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
|
|
265 tree (*valueize)(tree))
|
|
266 {
|
|
267 if (constant_for_folding (res_op->ops[0])
|
|
268 && constant_for_folding (res_op->ops[1]))
|
|
269 {
|
|
270 tree tem = NULL_TREE;
|
|
271 if (res_op->code.is_tree_code ())
|
145
|
272 {
|
|
273 tree_code code = res_op->code;
|
|
274 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
|
|
275 && TREE_CODE_LENGTH (code) == 2)
|
|
276 tem = const_binop (res_op->code, res_op->type,
|
|
277 res_op->ops[0], res_op->ops[1]);
|
|
278 }
|
131
|
279 else
|
|
280 tem = fold_const_call (combined_fn (res_op->code), res_op->type,
|
|
281 res_op->ops[0], res_op->ops[1]);
|
|
282 if (tem != NULL_TREE
|
|
283 && CONSTANT_CLASS_P (tem))
|
|
284 {
|
|
285 if (TREE_OVERFLOW_P (tem))
|
|
286 tem = drop_tree_overflow (tem);
|
|
287 res_op->set_value (tem);
|
|
288 maybe_resimplify_conditional_op (seq, res_op, valueize);
|
111
|
289 return true;
|
|
290 }
|
|
291 }
|
|
292
|
|
293 /* Canonicalize operand order. */
|
|
294 bool canonicalized = false;
|
131
|
295 if (res_op->code.is_tree_code ()
|
|
296 && (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison
|
|
297 || commutative_tree_code (res_op->code))
|
|
298 && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
|
111
|
299 {
|
131
|
300 std::swap (res_op->ops[0], res_op->ops[1]);
|
|
301 if (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison)
|
|
302 res_op->code = swap_tree_comparison (res_op->code);
|
111
|
303 canonicalized = true;
|
|
304 }
|
|
305
|
131
|
306 /* Limit recursion, see gimple_resimplify1. */
|
|
307 static unsigned depth;
|
|
308 if (depth > 10)
|
111
|
309 {
|
131
|
310 if (dump_file && (dump_flags & TDF_FOLDING))
|
|
311 fprintf (dump_file, "Aborting expression simplification due to "
|
|
312 "deep recursion\n");
|
|
313 return false;
|
|
314 }
|
|
315
|
|
316 ++depth;
|
|
317 gimple_match_op res_op2 (*res_op);
|
|
318 if (gimple_simplify (&res_op2, seq, valueize,
|
|
319 res_op->code, res_op->type,
|
|
320 res_op->ops[0], res_op->ops[1]))
|
|
321 {
|
|
322 --depth;
|
|
323 *res_op = res_op2;
|
111
|
324 return true;
|
|
325 }
|
131
|
326 --depth;
|
|
327
|
|
328 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
|
|
329 return true;
|
111
|
330
|
|
331 return canonicalized;
|
|
332 }
|
|
333
|
|
334 /* Helper that matches and simplifies the toplevel result from
|
|
335 a gimple_simplify run (where we don't want to build
|
|
336 a stmt in case it's used in in-place folding). Replaces
|
131
|
337 RES_OP with a simplified and/or canonicalized result and
|
|
338 returns whether any change was made. */
|
111
|
339
|
145
|
340 static bool
|
131
|
341 gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
|
111
|
342 tree (*valueize)(tree))
|
|
343 {
|
131
|
344 if (constant_for_folding (res_op->ops[0])
|
|
345 && constant_for_folding (res_op->ops[1])
|
|
346 && constant_for_folding (res_op->ops[2]))
|
111
|
347 {
|
|
348 tree tem = NULL_TREE;
|
131
|
349 if (res_op->code.is_tree_code ())
|
145
|
350 {
|
|
351 tree_code code = res_op->code;
|
|
352 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
|
|
353 && TREE_CODE_LENGTH (code) == 3)
|
|
354 tem = fold_ternary/*_to_constant*/ (res_op->code, res_op->type,
|
|
355 res_op->ops[0], res_op->ops[1],
|
|
356 res_op->ops[2]);
|
|
357 }
|
111
|
358 else
|
131
|
359 tem = fold_const_call (combined_fn (res_op->code), res_op->type,
|
|
360 res_op->ops[0], res_op->ops[1], res_op->ops[2]);
|
111
|
361 if (tem != NULL_TREE
|
|
362 && CONSTANT_CLASS_P (tem))
|
|
363 {
|
|
364 if (TREE_OVERFLOW_P (tem))
|
|
365 tem = drop_tree_overflow (tem);
|
131
|
366 res_op->set_value (tem);
|
|
367 maybe_resimplify_conditional_op (seq, res_op, valueize);
|
111
|
368 return true;
|
|
369 }
|
|
370 }
|
|
371
|
|
372 /* Canonicalize operand order. */
|
|
373 bool canonicalized = false;
|
131
|
374 if (res_op->code.is_tree_code ()
|
|
375 && commutative_ternary_tree_code (res_op->code)
|
|
376 && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
|
111
|
377 {
|
131
|
378 std::swap (res_op->ops[0], res_op->ops[1]);
|
111
|
379 canonicalized = true;
|
|
380 }
|
|
381
|
131
|
382 /* Limit recursion, see gimple_resimplify1. */
|
|
383 static unsigned depth;
|
|
384 if (depth > 10)
|
111
|
385 {
|
131
|
386 if (dump_file && (dump_flags & TDF_FOLDING))
|
|
387 fprintf (dump_file, "Aborting expression simplification due to "
|
|
388 "deep recursion\n");
|
|
389 return false;
|
|
390 }
|
|
391
|
|
392 ++depth;
|
|
393 gimple_match_op res_op2 (*res_op);
|
|
394 if (gimple_simplify (&res_op2, seq, valueize,
|
|
395 res_op->code, res_op->type,
|
|
396 res_op->ops[0], res_op->ops[1], res_op->ops[2]))
|
|
397 {
|
|
398 --depth;
|
|
399 *res_op = res_op2;
|
111
|
400 return true;
|
|
401 }
|
131
|
402 --depth;
|
|
403
|
|
404 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
|
|
405 return true;
|
111
|
406
|
|
407 return canonicalized;
|
|
408 }
|
|
409
|
131
|
410 /* Helper that matches and simplifies the toplevel result from
|
|
411 a gimple_simplify run (where we don't want to build
|
|
412 a stmt in case it's used in in-place folding). Replaces
|
|
413 RES_OP with a simplified and/or canonicalized result and
|
|
414 returns whether any change was made. */
|
111
|
415
|
145
|
416 static bool
|
131
|
417 gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
|
|
418 tree (*valueize)(tree))
|
|
419 {
|
|
420 /* No constant folding is defined for four-operand functions. */
|
|
421
|
|
422 /* Limit recursion, see gimple_resimplify1. */
|
|
423 static unsigned depth;
|
|
424 if (depth > 10)
|
|
425 {
|
|
426 if (dump_file && (dump_flags & TDF_FOLDING))
|
|
427 fprintf (dump_file, "Aborting expression simplification due to "
|
|
428 "deep recursion\n");
|
|
429 return false;
|
|
430 }
|
|
431
|
|
432 ++depth;
|
|
433 gimple_match_op res_op2 (*res_op);
|
|
434 if (gimple_simplify (&res_op2, seq, valueize,
|
|
435 res_op->code, res_op->type,
|
|
436 res_op->ops[0], res_op->ops[1], res_op->ops[2],
|
|
437 res_op->ops[3]))
|
|
438 {
|
|
439 --depth;
|
|
440 *res_op = res_op2;
|
|
441 return true;
|
|
442 }
|
|
443 --depth;
|
|
444
|
|
445 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
|
|
446 return true;
|
|
447
|
|
448 return false;
|
|
449 }
|
|
450
|
|
451 /* Helper that matches and simplifies the toplevel result from
|
|
452 a gimple_simplify run (where we don't want to build
|
|
453 a stmt in case it's used in in-place folding). Replaces
|
|
454 RES_OP with a simplified and/or canonicalized result and
|
|
455 returns whether any change was made. */
|
|
456
|
145
|
457 static bool
|
131
|
458 gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
|
|
459 tree (*valueize)(tree))
|
|
460 {
|
|
461 /* No constant folding is defined for five-operand functions. */
|
|
462
|
|
463 gimple_match_op res_op2 (*res_op);
|
|
464 if (gimple_simplify (&res_op2, seq, valueize,
|
|
465 res_op->code, res_op->type,
|
|
466 res_op->ops[0], res_op->ops[1], res_op->ops[2],
|
|
467 res_op->ops[3], res_op->ops[4]))
|
|
468 {
|
|
469 *res_op = res_op2;
|
|
470 return true;
|
|
471 }
|
|
472
|
|
473 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
|
|
474 return true;
|
|
475
|
|
476 return false;
|
|
477 }
|
|
478
|
145
|
479 /* Match and simplify the toplevel valueized operation THIS.
|
|
480 Replaces THIS with a simplified and/or canonicalized result and
|
|
481 returns whether any change was made. */
|
|
482
|
|
483 bool
|
|
484 gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
|
|
485 {
|
|
486 switch (num_ops)
|
|
487 {
|
|
488 case 1:
|
|
489 return gimple_resimplify1 (seq, this, valueize);
|
|
490 case 2:
|
|
491 return gimple_resimplify2 (seq, this, valueize);
|
|
492 case 3:
|
|
493 return gimple_resimplify3 (seq, this, valueize);
|
|
494 case 4:
|
|
495 return gimple_resimplify4 (seq, this, valueize);
|
|
496 case 5:
|
|
497 return gimple_resimplify5 (seq, this, valueize);
|
|
498 default:
|
|
499 gcc_unreachable ();
|
|
500 }
|
|
501 }
|
|
502
|
131
|
503 /* If in GIMPLE the operation described by RES_OP should be single-rhs,
|
|
504 build a GENERIC tree for that expression and update RES_OP accordingly. */
|
111
|
505
|
|
506 void
|
131
|
507 maybe_build_generic_op (gimple_match_op *res_op)
|
111
|
508 {
|
131
|
509 tree_code code = (tree_code) res_op->code;
|
|
510 tree val;
|
111
|
511 switch (code)
|
|
512 {
|
|
513 case REALPART_EXPR:
|
|
514 case IMAGPART_EXPR:
|
|
515 case VIEW_CONVERT_EXPR:
|
131
|
516 val = build1 (code, res_op->type, res_op->ops[0]);
|
|
517 res_op->set_value (val);
|
111
|
518 break;
|
|
519 case BIT_FIELD_REF:
|
131
|
520 val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
|
|
521 res_op->ops[2]);
|
|
522 REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
|
|
523 res_op->set_value (val);
|
111
|
524 break;
|
|
525 default:;
|
|
526 }
|
|
527 }
|
|
528
|
131
|
529 tree (*mprts_hook) (gimple_match_op *);
|
111
|
530
|
131
|
531 /* Try to build RES_OP, which is known to be a call to FN. Return null
|
|
532 if the target doesn't support the function. */
|
111
|
533
|
|
534 static gcall *
|
131
|
535 build_call_internal (internal_fn fn, gimple_match_op *res_op)
|
111
|
536 {
|
|
537 if (direct_internal_fn_p (fn))
|
|
538 {
|
131
|
539 tree_pair types = direct_internal_fn_types (fn, res_op->type,
|
|
540 res_op->ops);
|
111
|
541 if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
|
|
542 return NULL;
|
|
543 }
|
131
|
544 return gimple_build_call_internal (fn, res_op->num_ops,
|
|
545 res_op->op_or_null (0),
|
|
546 res_op->op_or_null (1),
|
|
547 res_op->op_or_null (2),
|
|
548 res_op->op_or_null (3),
|
|
549 res_op->op_or_null (4));
|
111
|
550 }
|
|
551
|
131
|
552 /* Push the exploded expression described by RES_OP as a statement to
|
|
553 SEQ if necessary and return a gimple value denoting the value of the
|
|
554 expression. If RES is not NULL then the result will be always RES
|
|
555 and even gimple values are pushed to SEQ. */
|
111
|
556
|
|
557 tree
|
131
|
558 maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
|
111
|
559 {
|
131
|
560 tree *ops = res_op->ops;
|
|
561 unsigned num_ops = res_op->num_ops;
|
|
562
|
|
563 /* The caller should have converted conditional operations into an UNCOND
|
|
564 form and resimplified as appropriate. The conditional form only
|
|
565 survives this far if that conversion failed. */
|
|
566 if (res_op->cond.cond)
|
|
567 return NULL_TREE;
|
|
568
|
|
569 if (res_op->code.is_tree_code ())
|
111
|
570 {
|
|
571 if (!res
|
131
|
572 && gimple_simplified_result_is_gimple_val (res_op))
|
111
|
573 return ops[0];
|
|
574 if (mprts_hook)
|
|
575 {
|
131
|
576 tree tem = mprts_hook (res_op);
|
111
|
577 if (tem)
|
|
578 return tem;
|
|
579 }
|
131
|
580 }
|
|
581
|
|
582 if (!seq)
|
|
583 return NULL_TREE;
|
|
584
|
|
585 /* Play safe and do not allow abnormals to be mentioned in
|
|
586 newly created statements. */
|
|
587 for (unsigned int i = 0; i < num_ops; ++i)
|
|
588 if (TREE_CODE (ops[i]) == SSA_NAME
|
|
589 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
|
|
590 return NULL_TREE;
|
|
591
|
|
592 if (num_ops > 0 && COMPARISON_CLASS_P (ops[0]))
|
|
593 for (unsigned int i = 0; i < 2; ++i)
|
|
594 if (TREE_CODE (TREE_OPERAND (ops[0], i)) == SSA_NAME
|
|
595 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0], i)))
|
111
|
596 return NULL_TREE;
|
131
|
597
|
|
598 if (res_op->code.is_tree_code ())
|
|
599 {
|
111
|
600 if (!res)
|
|
601 {
|
|
602 if (gimple_in_ssa_p (cfun))
|
131
|
603 res = make_ssa_name (res_op->type);
|
111
|
604 else
|
131
|
605 res = create_tmp_reg (res_op->type);
|
111
|
606 }
|
131
|
607 maybe_build_generic_op (res_op);
|
|
608 gimple *new_stmt = gimple_build_assign (res, res_op->code,
|
|
609 res_op->op_or_null (0),
|
|
610 res_op->op_or_null (1),
|
|
611 res_op->op_or_null (2));
|
111
|
612 gimple_seq_add_stmt_without_update (seq, new_stmt);
|
|
613 return res;
|
|
614 }
|
|
615 else
|
|
616 {
|
131
|
617 gcc_assert (num_ops != 0);
|
|
618 combined_fn fn = res_op->code;
|
111
|
619 gcall *new_stmt = NULL;
|
|
620 if (internal_fn_p (fn))
|
|
621 {
|
|
622 /* Generate the given function if we can. */
|
|
623 internal_fn ifn = as_internal_fn (fn);
|
131
|
624 new_stmt = build_call_internal (ifn, res_op);
|
111
|
625 if (!new_stmt)
|
|
626 return NULL_TREE;
|
|
627 }
|
|
628 else
|
|
629 {
|
|
630 /* Find the function we want to call. */
|
|
631 tree decl = builtin_decl_implicit (as_builtin_fn (fn));
|
|
632 if (!decl)
|
|
633 return NULL;
|
|
634
|
|
635 /* We can't and should not emit calls to non-const functions. */
|
|
636 if (!(flags_from_decl_or_type (decl) & ECF_CONST))
|
|
637 return NULL;
|
|
638
|
131
|
639 new_stmt = gimple_build_call (decl, num_ops,
|
|
640 res_op->op_or_null (0),
|
|
641 res_op->op_or_null (1),
|
|
642 res_op->op_or_null (2),
|
|
643 res_op->op_or_null (3),
|
|
644 res_op->op_or_null (4));
|
111
|
645 }
|
|
646 if (!res)
|
|
647 {
|
|
648 if (gimple_in_ssa_p (cfun))
|
131
|
649 res = make_ssa_name (res_op->type);
|
111
|
650 else
|
131
|
651 res = create_tmp_reg (res_op->type);
|
111
|
652 }
|
|
653 gimple_call_set_lhs (new_stmt, res);
|
|
654 gimple_seq_add_stmt_without_update (seq, new_stmt);
|
|
655 return res;
|
|
656 }
|
|
657 }
|
|
658
|
|
659
|
|
660 /* Public API overloads follow for operation being tree_code or
|
|
661 built_in_function and for one to three operands or arguments.
|
|
662 They return NULL_TREE if nothing could be simplified or
|
|
663 the resulting simplified value with parts pushed to SEQ.
|
|
664 If SEQ is NULL then if the simplification needs to create
|
|
665 new stmts it will fail. If VALUEIZE is non-NULL then all
|
|
666 SSA names will be valueized using that hook prior to
|
|
667 applying simplifications. */
|
|
668
|
|
669 /* Unary ops. */
|
|
670
|
|
671 tree
|
|
672 gimple_simplify (enum tree_code code, tree type,
|
|
673 tree op0,
|
|
674 gimple_seq *seq, tree (*valueize)(tree))
|
|
675 {
|
|
676 if (constant_for_folding (op0))
|
|
677 {
|
|
678 tree res = const_unop (code, type, op0);
|
|
679 if (res != NULL_TREE
|
|
680 && CONSTANT_CLASS_P (res))
|
|
681 return res;
|
|
682 }
|
|
683
|
131
|
684 gimple_match_op res_op;
|
|
685 if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
|
111
|
686 return NULL_TREE;
|
131
|
687 return maybe_push_res_to_seq (&res_op, seq);
|
111
|
688 }
|
|
689
|
|
690 /* Binary ops. */
|
|
691
|
|
692 tree
|
|
693 gimple_simplify (enum tree_code code, tree type,
|
|
694 tree op0, tree op1,
|
|
695 gimple_seq *seq, tree (*valueize)(tree))
|
|
696 {
|
|
697 if (constant_for_folding (op0) && constant_for_folding (op1))
|
|
698 {
|
|
699 tree res = const_binop (code, type, op0, op1);
|
|
700 if (res != NULL_TREE
|
|
701 && CONSTANT_CLASS_P (res))
|
|
702 return res;
|
|
703 }
|
|
704
|
|
705 /* Canonicalize operand order both for matching and fallback stmt
|
|
706 generation. */
|
|
707 if ((commutative_tree_code (code)
|
|
708 || TREE_CODE_CLASS (code) == tcc_comparison)
|
|
709 && tree_swap_operands_p (op0, op1))
|
|
710 {
|
|
711 std::swap (op0, op1);
|
|
712 if (TREE_CODE_CLASS (code) == tcc_comparison)
|
|
713 code = swap_tree_comparison (code);
|
|
714 }
|
|
715
|
131
|
716 gimple_match_op res_op;
|
|
717 if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
|
111
|
718 return NULL_TREE;
|
131
|
719 return maybe_push_res_to_seq (&res_op, seq);
|
111
|
720 }
|
|
721
|
|
722 /* Ternary ops. */
|
|
723
|
|
724 tree
|
|
725 gimple_simplify (enum tree_code code, tree type,
|
|
726 tree op0, tree op1, tree op2,
|
|
727 gimple_seq *seq, tree (*valueize)(tree))
|
|
728 {
|
|
729 if (constant_for_folding (op0) && constant_for_folding (op1)
|
|
730 && constant_for_folding (op2))
|
|
731 {
|
|
732 tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
|
|
733 if (res != NULL_TREE
|
|
734 && CONSTANT_CLASS_P (res))
|
|
735 return res;
|
|
736 }
|
|
737
|
|
738 /* Canonicalize operand order both for matching and fallback stmt
|
|
739 generation. */
|
|
740 if (commutative_ternary_tree_code (code)
|
|
741 && tree_swap_operands_p (op0, op1))
|
|
742 std::swap (op0, op1);
|
|
743
|
131
|
744 gimple_match_op res_op;
|
|
745 if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
|
111
|
746 return NULL_TREE;
|
131
|
747 return maybe_push_res_to_seq (&res_op, seq);
|
111
|
748 }
|
|
749
|
131
|
750 /* Builtin or internal function with one argument. */
|
111
|
751
|
|
752 tree
|
131
|
753 gimple_simplify (combined_fn fn, tree type,
|
111
|
754 tree arg0,
|
|
755 gimple_seq *seq, tree (*valueize)(tree))
|
|
756 {
|
|
757 if (constant_for_folding (arg0))
|
|
758 {
|
131
|
759 tree res = fold_const_call (fn, type, arg0);
|
111
|
760 if (res && CONSTANT_CLASS_P (res))
|
|
761 return res;
|
|
762 }
|
|
763
|
131
|
764 gimple_match_op res_op;
|
|
765 if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0))
|
111
|
766 return NULL_TREE;
|
131
|
767 return maybe_push_res_to_seq (&res_op, seq);
|
111
|
768 }
|
|
769
|
131
|
770 /* Builtin or internal function with two arguments. */
|
111
|
771
|
|
772 tree
|
131
|
773 gimple_simplify (combined_fn fn, tree type,
|
111
|
774 tree arg0, tree arg1,
|
|
775 gimple_seq *seq, tree (*valueize)(tree))
|
|
776 {
|
|
777 if (constant_for_folding (arg0)
|
|
778 && constant_for_folding (arg1))
|
|
779 {
|
131
|
780 tree res = fold_const_call (fn, type, arg0, arg1);
|
111
|
781 if (res && CONSTANT_CLASS_P (res))
|
|
782 return res;
|
|
783 }
|
|
784
|
131
|
785 gimple_match_op res_op;
|
|
786 if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1))
|
111
|
787 return NULL_TREE;
|
131
|
788 return maybe_push_res_to_seq (&res_op, seq);
|
111
|
789 }
|
|
790
|
131
|
791 /* Builtin or internal function with three arguments. */
|
111
|
792
|
|
793 tree
|
131
|
794 gimple_simplify (combined_fn fn, tree type,
|
111
|
795 tree arg0, tree arg1, tree arg2,
|
|
796 gimple_seq *seq, tree (*valueize)(tree))
|
|
797 {
|
|
798 if (constant_for_folding (arg0)
|
|
799 && constant_for_folding (arg1)
|
|
800 && constant_for_folding (arg2))
|
|
801 {
|
131
|
802 tree res = fold_const_call (fn, type, arg0, arg1, arg2);
|
111
|
803 if (res && CONSTANT_CLASS_P (res))
|
|
804 return res;
|
|
805 }
|
|
806
|
131
|
807 gimple_match_op res_op;
|
|
808 if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2))
|
111
|
809 return NULL_TREE;
|
131
|
810 return maybe_push_res_to_seq (&res_op, seq);
|
111
|
811 }
|
|
812
|
|
813 /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
|
|
814 VALUEIZED to true if valueization changed OP. */
|
|
815
|
|
816 static inline tree
|
|
817 do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
|
|
818 {
|
|
819 if (valueize && TREE_CODE (op) == SSA_NAME)
|
|
820 {
|
|
821 tree tem = valueize (op);
|
|
822 if (tem && tem != op)
|
|
823 {
|
|
824 op = tem;
|
|
825 valueized = true;
|
|
826 }
|
|
827 }
|
|
828 return op;
|
|
829 }
|
|
830
|
131
|
831 /* If RES_OP is a call to a conditional internal function, try simplifying
|
|
832 the associated unconditional operation and using the result to build
|
|
833 a new conditional operation. For example, if RES_OP is:
|
|
834
|
|
835 IFN_COND_ADD (COND, A, B, ELSE)
|
|
836
|
|
837 try simplifying (plus A B) and using the result to build a replacement
|
|
838 for the whole IFN_COND_ADD.
|
|
839
|
|
840 Return true if this approach led to a simplification, otherwise leave
|
|
841 RES_OP unchanged (and so suitable for other simplifications). When
|
|
842 returning true, add any new statements to SEQ and use VALUEIZE as the
|
|
843 valueization function.
|
|
844
|
|
845 RES_OP is known to be a call to IFN. */
|
|
846
|
|
847 static bool
|
|
848 try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
|
|
849 gimple_seq *seq, tree (*valueize) (tree))
|
|
850 {
|
|
851 code_helper op;
|
|
852 tree_code code = conditional_internal_fn_code (ifn);
|
|
853 if (code != ERROR_MARK)
|
|
854 op = code;
|
|
855 else
|
|
856 {
|
|
857 ifn = get_unconditional_internal_fn (ifn);
|
|
858 if (ifn == IFN_LAST)
|
|
859 return false;
|
|
860 op = as_combined_fn (ifn);
|
|
861 }
|
|
862
|
|
863 unsigned int num_ops = res_op->num_ops;
|
|
864 gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
|
|
865 res_op->ops[num_ops - 1]),
|
|
866 op, res_op->type, num_ops - 2);
|
145
|
867
|
|
868 memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
|
131
|
869 switch (num_ops - 2)
|
|
870 {
|
|
871 case 2:
|
|
872 if (!gimple_resimplify2 (seq, &cond_op, valueize))
|
|
873 return false;
|
|
874 break;
|
|
875 case 3:
|
|
876 if (!gimple_resimplify3 (seq, &cond_op, valueize))
|
|
877 return false;
|
|
878 break;
|
|
879 default:
|
|
880 gcc_unreachable ();
|
|
881 }
|
|
882 *res_op = cond_op;
|
|
883 maybe_resimplify_conditional_op (seq, res_op, valueize);
|
|
884 return true;
|
|
885 }
|
|
886
|
111
|
887 /* The main STMT based simplification entry. It is used by the fold_stmt
|
|
888 and the fold_stmt_to_constant APIs. */
|
|
889
|
|
890 bool
|
131
|
891 gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
|
111
|
892 tree (*valueize)(tree), tree (*top_valueize)(tree))
|
|
893 {
|
|
894 switch (gimple_code (stmt))
|
|
895 {
|
|
896 case GIMPLE_ASSIGN:
|
|
897 {
|
|
898 enum tree_code code = gimple_assign_rhs_code (stmt);
|
|
899 tree type = TREE_TYPE (gimple_assign_lhs (stmt));
|
|
900 switch (gimple_assign_rhs_class (stmt))
|
|
901 {
|
|
902 case GIMPLE_SINGLE_RHS:
|
|
903 if (code == REALPART_EXPR
|
|
904 || code == IMAGPART_EXPR
|
|
905 || code == VIEW_CONVERT_EXPR)
|
|
906 {
|
|
907 tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
|
|
908 bool valueized = false;
|
|
909 op0 = do_valueize (op0, top_valueize, valueized);
|
131
|
910 res_op->set_op (code, type, op0);
|
|
911 return (gimple_resimplify1 (seq, res_op, valueize)
|
111
|
912 || valueized);
|
|
913 }
|
|
914 else if (code == BIT_FIELD_REF)
|
|
915 {
|
|
916 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
917 tree op0 = TREE_OPERAND (rhs1, 0);
|
|
918 bool valueized = false;
|
|
919 op0 = do_valueize (op0, top_valueize, valueized);
|
131
|
920 res_op->set_op (code, type, op0,
|
|
921 TREE_OPERAND (rhs1, 1),
|
|
922 TREE_OPERAND (rhs1, 2),
|
|
923 REF_REVERSE_STORAGE_ORDER (rhs1));
|
|
924 if (res_op->reverse)
|
|
925 return valueized;
|
|
926 return (gimple_resimplify3 (seq, res_op, valueize)
|
111
|
927 || valueized);
|
|
928 }
|
|
929 else if (code == SSA_NAME
|
|
930 && top_valueize)
|
|
931 {
|
|
932 tree op0 = gimple_assign_rhs1 (stmt);
|
|
933 tree valueized = top_valueize (op0);
|
|
934 if (!valueized || op0 == valueized)
|
|
935 return false;
|
131
|
936 res_op->set_op (TREE_CODE (op0), type, valueized);
|
111
|
937 return true;
|
|
938 }
|
|
939 break;
|
|
940 case GIMPLE_UNARY_RHS:
|
|
941 {
|
|
942 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
943 bool valueized = false;
|
|
944 rhs1 = do_valueize (rhs1, top_valueize, valueized);
|
131
|
945 res_op->set_op (code, type, rhs1);
|
|
946 return (gimple_resimplify1 (seq, res_op, valueize)
|
111
|
947 || valueized);
|
|
948 }
|
|
949 case GIMPLE_BINARY_RHS:
|
|
950 {
|
|
951 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
952 tree rhs2 = gimple_assign_rhs2 (stmt);
|
|
953 bool valueized = false;
|
|
954 rhs1 = do_valueize (rhs1, top_valueize, valueized);
|
|
955 rhs2 = do_valueize (rhs2, top_valueize, valueized);
|
131
|
956 res_op->set_op (code, type, rhs1, rhs2);
|
|
957 return (gimple_resimplify2 (seq, res_op, valueize)
|
111
|
958 || valueized);
|
|
959 }
|
|
960 case GIMPLE_TERNARY_RHS:
|
|
961 {
|
|
962 bool valueized = false;
|
|
963 tree rhs1 = gimple_assign_rhs1 (stmt);
|
|
964 /* If this is a [VEC_]COND_EXPR first try to simplify an
|
|
965 embedded GENERIC condition. */
|
|
966 if (code == COND_EXPR
|
|
967 || code == VEC_COND_EXPR)
|
|
968 {
|
|
969 if (COMPARISON_CLASS_P (rhs1))
|
|
970 {
|
|
971 tree lhs = TREE_OPERAND (rhs1, 0);
|
|
972 tree rhs = TREE_OPERAND (rhs1, 1);
|
|
973 lhs = do_valueize (lhs, top_valueize, valueized);
|
|
974 rhs = do_valueize (rhs, top_valueize, valueized);
|
131
|
975 gimple_match_op res_op2 (res_op->cond, TREE_CODE (rhs1),
|
|
976 TREE_TYPE (rhs1), lhs, rhs);
|
|
977 if ((gimple_resimplify2 (seq, &res_op2, valueize)
|
111
|
978 || valueized)
|
131
|
979 && res_op2.code.is_tree_code ())
|
111
|
980 {
|
|
981 valueized = true;
|
131
|
982 if (TREE_CODE_CLASS ((enum tree_code) res_op2.code)
|
111
|
983 == tcc_comparison)
|
131
|
984 rhs1 = build2 (res_op2.code, TREE_TYPE (rhs1),
|
|
985 res_op2.ops[0], res_op2.ops[1]);
|
|
986 else if (res_op2.code == SSA_NAME
|
|
987 || res_op2.code == INTEGER_CST
|
|
988 || res_op2.code == VECTOR_CST)
|
|
989 rhs1 = res_op2.ops[0];
|
111
|
990 else
|
|
991 valueized = false;
|
|
992 }
|
|
993 }
|
|
994 }
|
|
995 tree rhs2 = gimple_assign_rhs2 (stmt);
|
|
996 tree rhs3 = gimple_assign_rhs3 (stmt);
|
|
997 rhs1 = do_valueize (rhs1, top_valueize, valueized);
|
|
998 rhs2 = do_valueize (rhs2, top_valueize, valueized);
|
|
999 rhs3 = do_valueize (rhs3, top_valueize, valueized);
|
131
|
1000 res_op->set_op (code, type, rhs1, rhs2, rhs3);
|
|
1001 return (gimple_resimplify3 (seq, res_op, valueize)
|
111
|
1002 || valueized);
|
|
1003 }
|
|
1004 default:
|
|
1005 gcc_unreachable ();
|
|
1006 }
|
|
1007 break;
|
|
1008 }
|
|
1009
|
|
1010 case GIMPLE_CALL:
|
|
1011 /* ??? This way we can't simplify calls with side-effects. */
|
|
1012 if (gimple_call_lhs (stmt) != NULL_TREE
|
|
1013 && gimple_call_num_args (stmt) >= 1
|
131
|
1014 && gimple_call_num_args (stmt) <= 5)
|
111
|
1015 {
|
|
1016 bool valueized = false;
|
131
|
1017 combined_fn cfn;
|
111
|
1018 if (gimple_call_internal_p (stmt))
|
131
|
1019 cfn = as_combined_fn (gimple_call_internal_fn (stmt));
|
111
|
1020 else
|
|
1021 {
|
|
1022 tree fn = gimple_call_fn (stmt);
|
|
1023 if (!fn)
|
|
1024 return false;
|
|
1025
|
|
1026 fn = do_valueize (fn, top_valueize, valueized);
|
|
1027 if (TREE_CODE (fn) != ADDR_EXPR
|
|
1028 || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
|
|
1029 return false;
|
|
1030
|
|
1031 tree decl = TREE_OPERAND (fn, 0);
|
|
1032 if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
|
|
1033 || !gimple_builtin_call_types_compatible_p (stmt, decl))
|
|
1034 return false;
|
|
1035
|
131
|
1036 cfn = as_combined_fn (DECL_FUNCTION_CODE (decl));
|
111
|
1037 }
|
|
1038
|
131
|
1039 unsigned int num_args = gimple_call_num_args (stmt);
|
|
1040 res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
|
|
1041 for (unsigned i = 0; i < num_args; ++i)
|
111
|
1042 {
|
|
1043 tree arg = gimple_call_arg (stmt, i);
|
131
|
1044 res_op->ops[i] = do_valueize (arg, top_valueize, valueized);
|
111
|
1045 }
|
131
|
1046 if (internal_fn_p (cfn)
|
|
1047 && try_conditional_simplification (as_internal_fn (cfn),
|
|
1048 res_op, seq, valueize))
|
|
1049 return true;
|
|
1050 switch (num_args)
|
111
|
1051 {
|
|
1052 case 1:
|
131
|
1053 return (gimple_resimplify1 (seq, res_op, valueize)
|
111
|
1054 || valueized);
|
|
1055 case 2:
|
131
|
1056 return (gimple_resimplify2 (seq, res_op, valueize)
|
111
|
1057 || valueized);
|
|
1058 case 3:
|
131
|
1059 return (gimple_resimplify3 (seq, res_op, valueize)
|
|
1060 || valueized);
|
|
1061 case 4:
|
|
1062 return (gimple_resimplify4 (seq, res_op, valueize)
|
|
1063 || valueized);
|
|
1064 case 5:
|
|
1065 return (gimple_resimplify5 (seq, res_op, valueize)
|
111
|
1066 || valueized);
|
|
1067 default:
|
|
1068 gcc_unreachable ();
|
|
1069 }
|
|
1070 }
|
|
1071 break;
|
|
1072
|
|
1073 case GIMPLE_COND:
|
|
1074 {
|
|
1075 tree lhs = gimple_cond_lhs (stmt);
|
|
1076 tree rhs = gimple_cond_rhs (stmt);
|
|
1077 bool valueized = false;
|
|
1078 lhs = do_valueize (lhs, top_valueize, valueized);
|
|
1079 rhs = do_valueize (rhs, top_valueize, valueized);
|
131
|
1080 res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
|
|
1081 return (gimple_resimplify2 (seq, res_op, valueize)
|
111
|
1082 || valueized);
|
|
1083 }
|
|
1084
|
|
1085 default:
|
|
1086 break;
|
|
1087 }
|
|
1088
|
|
1089 return false;
|
|
1090 }
|
|
1091
|
|
1092
|
|
1093 /* Helper for the autogenerated code, valueize OP. */
|
|
1094
|
|
1095 inline tree
|
|
1096 do_valueize (tree (*valueize)(tree), tree op)
|
|
1097 {
|
|
1098 if (valueize && TREE_CODE (op) == SSA_NAME)
|
|
1099 {
|
|
1100 tree tem = valueize (op);
|
|
1101 if (tem)
|
|
1102 return tem;
|
|
1103 }
|
|
1104 return op;
|
|
1105 }
|
|
1106
|
|
1107 /* Helper for the autogenerated code, get at the definition of NAME when
|
|
1108 VALUEIZE allows that. */
|
|
1109
|
|
1110 inline gimple *
|
|
1111 get_def (tree (*valueize)(tree), tree name)
|
|
1112 {
|
|
1113 if (valueize && ! valueize (name))
|
|
1114 return NULL;
|
|
1115 return SSA_NAME_DEF_STMT (name);
|
|
1116 }
|
|
1117
|
|
1118 /* Routine to determine if the types T1 and T2 are effectively
|
|
1119 the same for GIMPLE. If T1 or T2 is not a type, the test
|
|
1120 applies to their TREE_TYPE. */
|
|
1121
|
|
1122 static inline bool
|
|
1123 types_match (tree t1, tree t2)
|
|
1124 {
|
|
1125 if (!TYPE_P (t1))
|
|
1126 t1 = TREE_TYPE (t1);
|
|
1127 if (!TYPE_P (t2))
|
|
1128 t2 = TREE_TYPE (t2);
|
|
1129
|
|
1130 return types_compatible_p (t1, t2);
|
|
1131 }
|
|
1132
|
|
1133 /* Return if T has a single use. For GIMPLE, we also allow any
|
|
1134 non-SSA_NAME (ie constants) and zero uses to cope with uses
|
|
1135 that aren't linked up yet. */
|
|
1136
|
|
1137 static inline bool
|
|
1138 single_use (tree t)
|
|
1139 {
|
|
1140 return TREE_CODE (t) != SSA_NAME || has_zero_uses (t) || has_single_use (t);
|
|
1141 }
|
|
1142
|
|
1143 /* Return true if math operations should be canonicalized,
|
|
1144 e.g. sqrt(sqrt(x)) -> pow(x, 0.25). */
|
|
1145
|
|
1146 static inline bool
|
|
1147 canonicalize_math_p ()
|
|
1148 {
|
|
1149 return !cfun || (cfun->curr_properties & PROP_gimple_opt_math) == 0;
|
|
1150 }
|
131
|
1151
|
|
1152 /* Return true if math operations that are beneficial only after
|
|
1153 vectorization should be canonicalized. */
|
|
1154
|
|
1155 static inline bool
|
|
1156 canonicalize_math_after_vectorization_p ()
|
|
1157 {
|
|
1158 return !cfun || (cfun->curr_properties & PROP_gimple_lvec) != 0;
|
|
1159 }
|
|
1160
|
|
1161 /* Return true if pow(cst, x) should be optimized into exp(log(cst) * x).
|
|
1162 As a workaround for SPEC CPU2017 628.pop2_s, don't do it if arg0
|
|
1163 is an exact integer, arg1 = phi_res +/- cst1 and phi_res = PHI <cst2, ...>
|
|
1164 where cst2 +/- cst1 is an exact integer, because then pow (arg0, arg1)
|
|
1165 will likely be exact, while exp (log (arg0) * arg1) might be not.
|
|
1166 Also don't do it if arg1 is phi_res above and cst2 is an exact integer. */
|
|
1167
|
|
1168 static bool
|
|
1169 optimize_pow_to_exp (tree arg0, tree arg1)
|
|
1170 {
|
|
1171 gcc_assert (TREE_CODE (arg0) == REAL_CST);
|
|
1172 if (!real_isinteger (TREE_REAL_CST_PTR (arg0), TYPE_MODE (TREE_TYPE (arg0))))
|
|
1173 return true;
|
|
1174
|
|
1175 if (TREE_CODE (arg1) != SSA_NAME)
|
|
1176 return true;
|
|
1177
|
|
1178 gimple *def = SSA_NAME_DEF_STMT (arg1);
|
|
1179 gphi *phi = dyn_cast <gphi *> (def);
|
|
1180 tree cst1 = NULL_TREE;
|
|
1181 enum tree_code code = ERROR_MARK;
|
|
1182 if (!phi)
|
|
1183 {
|
|
1184 if (!is_gimple_assign (def))
|
|
1185 return true;
|
|
1186 code = gimple_assign_rhs_code (def);
|
|
1187 switch (code)
|
|
1188 {
|
|
1189 case PLUS_EXPR:
|
|
1190 case MINUS_EXPR:
|
|
1191 break;
|
|
1192 default:
|
|
1193 return true;
|
|
1194 }
|
|
1195 if (TREE_CODE (gimple_assign_rhs1 (def)) != SSA_NAME
|
|
1196 || TREE_CODE (gimple_assign_rhs2 (def)) != REAL_CST)
|
|
1197 return true;
|
|
1198
|
|
1199 cst1 = gimple_assign_rhs2 (def);
|
|
1200
|
|
1201 phi = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def)));
|
|
1202 if (!phi)
|
|
1203 return true;
|
|
1204 }
|
|
1205
|
|
1206 tree cst2 = NULL_TREE;
|
|
1207 int n = gimple_phi_num_args (phi);
|
|
1208 for (int i = 0; i < n; i++)
|
|
1209 {
|
|
1210 tree arg = PHI_ARG_DEF (phi, i);
|
|
1211 if (TREE_CODE (arg) != REAL_CST)
|
|
1212 continue;
|
|
1213 else if (cst2 == NULL_TREE)
|
|
1214 cst2 = arg;
|
|
1215 else if (!operand_equal_p (cst2, arg, 0))
|
|
1216 return true;
|
|
1217 }
|
|
1218
|
|
1219 if (cst1 && cst2)
|
|
1220 cst2 = const_binop (code, TREE_TYPE (cst2), cst2, cst1);
|
|
1221 if (cst2
|
|
1222 && TREE_CODE (cst2) == REAL_CST
|
|
1223 && real_isinteger (TREE_REAL_CST_PTR (cst2),
|
|
1224 TYPE_MODE (TREE_TYPE (cst2))))
|
|
1225 return false;
|
|
1226 return true;
|
|
1227 }
|
145
|
1228
|
|
1229 /* Return true if a division INNER_DIV / DIVISOR where INNER_DIV
|
|
1230 is another division can be optimized. Don't optimize if INNER_DIV
|
|
1231 is used in a TRUNC_MOD_EXPR with DIVISOR as second operand. */
|
|
1232
|
|
1233 static bool
|
|
1234 optimize_successive_divisions_p (tree divisor, tree inner_div)
|
|
1235 {
|
|
1236 if (!gimple_in_ssa_p (cfun))
|
|
1237 return false;
|
|
1238
|
|
1239 imm_use_iterator imm_iter;
|
|
1240 use_operand_p use_p;
|
|
1241 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, inner_div)
|
|
1242 {
|
|
1243 gimple *use_stmt = USE_STMT (use_p);
|
|
1244 if (!is_gimple_assign (use_stmt)
|
|
1245 || gimple_assign_rhs_code (use_stmt) != TRUNC_MOD_EXPR
|
|
1246 || !operand_equal_p (gimple_assign_rhs2 (use_stmt), divisor, 0))
|
|
1247 continue;
|
|
1248 return false;
|
|
1249 }
|
|
1250 return true;
|
|
1251 }
|