1 /* Preamble and helpers for the autogenerated gimple-match.c file.
2    Copyright (C) 2014-2018 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 }
834 
835 /* Return true if math operations that are beneficial only after
836    vectorization should be canonicalized.  */
837 
838 static inline bool
839 canonicalize_math_after_vectorization_p ()
840 {
841   return !cfun || (cfun->curr_properties & PROP_gimple_lvec) != 0;
842 }
843 
844 /* Return true if pow(cst, x) should be optimized into exp(log(cst) * x).
845    As a workaround for SPEC CPU2017 628.pop2_s, don't do it if arg0
846    is an exact integer, arg1 = phi_res +/- cst1 and phi_res = PHI <cst2, ...>
847    where cst2 +/- cst1 is an exact integer, because then pow (arg0, arg1)
848    will likely be exact, while exp (log (arg0) * arg1) might be not.
849    Also don't do it if arg1 is phi_res above and cst2 is an exact integer.  */
850 
851 static bool
852 optimize_pow_to_exp (tree arg0, tree arg1)
853 {
854   gcc_assert (TREE_CODE (arg0) == REAL_CST);
855   if (!real_isinteger (TREE_REAL_CST_PTR (arg0), TYPE_MODE (TREE_TYPE (arg0))))
856     return true;
857 
858   if (TREE_CODE (arg1) != SSA_NAME)
859     return true;
860 
861   gimple *def = SSA_NAME_DEF_STMT (arg1);
862   gphi *phi = dyn_cast <gphi *> (def);
863   tree cst1 = NULL_TREE;
864   enum tree_code code = ERROR_MARK;
865   if (!phi)
866     {
867       if (!is_gimple_assign (def))
868 	return true;
869       code = gimple_assign_rhs_code (def);
870       switch (code)
871 	{
872 	case PLUS_EXPR:
873 	case MINUS_EXPR:
874 	  break;
875 	default:
876 	  return true;
877 	}
878       if (TREE_CODE (gimple_assign_rhs1 (def)) != SSA_NAME
879 	  || TREE_CODE (gimple_assign_rhs2 (def)) != REAL_CST)
880 	return true;
881 
882       cst1 = gimple_assign_rhs2 (def);
883 
884       phi = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def)));
885       if (!phi)
886 	return true;
887     }
888 
889   tree cst2 = NULL_TREE;
890   int n = gimple_phi_num_args (phi);
891   for (int i = 0; i < n; i++)
892     {
893       tree arg = PHI_ARG_DEF (phi, i);
894       if (TREE_CODE (arg) != REAL_CST)
895 	continue;
896       else if (cst2 == NULL_TREE)
897 	cst2 = arg;
898       else if (!operand_equal_p (cst2, arg, 0))
899 	return true;
900     }
901 
902   if (cst1 && cst2)
903     cst2 = const_binop (code, TREE_TYPE (cst2), cst2, cst1);
904   if (cst2
905       && TREE_CODE (cst2) == REAL_CST
906       && real_isinteger (TREE_REAL_CST_PTR (cst2),
907 			 TYPE_MODE (TREE_TYPE (cst2))))
908     return false;
909   return true;
910 }
911