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