xref: /dflybsd-src/contrib/gcc-8.0/gcc/gimple-match-head.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Preamble and helpers for the autogenerated gimple-match.c file.
238fd1498Szrj    Copyright (C) 2014-2018 Free Software Foundation, Inc.
338fd1498Szrj 
438fd1498Szrj This file is part of GCC.
538fd1498Szrj 
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
738fd1498Szrj the terms of the GNU General Public License as published by the Free
838fd1498Szrj Software Foundation; either version 3, or (at your option) any later
938fd1498Szrj version.
1038fd1498Szrj 
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1238fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1338fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1438fd1498Szrj for more details.
1538fd1498Szrj 
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3.  If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>.  */
1938fd1498Szrj 
2038fd1498Szrj #include "config.h"
2138fd1498Szrj #include "system.h"
2238fd1498Szrj #include "coretypes.h"
2338fd1498Szrj #include "backend.h"
2438fd1498Szrj #include "target.h"
2538fd1498Szrj #include "rtl.h"
2638fd1498Szrj #include "tree.h"
2738fd1498Szrj #include "gimple.h"
2838fd1498Szrj #include "ssa.h"
2938fd1498Szrj #include "cgraph.h"
3038fd1498Szrj #include "fold-const.h"
3138fd1498Szrj #include "fold-const-call.h"
3238fd1498Szrj #include "stor-layout.h"
3338fd1498Szrj #include "gimple-fold.h"
3438fd1498Szrj #include "calls.h"
3538fd1498Szrj #include "tree-dfa.h"
3638fd1498Szrj #include "builtins.h"
3738fd1498Szrj #include "gimple-match.h"
3838fd1498Szrj #include "tree-pass.h"
3938fd1498Szrj #include "internal-fn.h"
4038fd1498Szrj #include "case-cfn-macros.h"
4138fd1498Szrj #include "gimplify.h"
4238fd1498Szrj #include "optabs-tree.h"
4338fd1498Szrj 
4438fd1498Szrj 
4538fd1498Szrj /* Forward declarations of the private auto-generated matchers.
4638fd1498Szrj    They expect valueized operands in canonical order and do not
4738fd1498Szrj    perform simplification of all-constant operands.  */
4838fd1498Szrj static bool gimple_simplify (code_helper *, tree *,
4938fd1498Szrj 			     gimple_seq *, tree (*)(tree),
5038fd1498Szrj 			     code_helper, tree, tree);
5138fd1498Szrj static bool gimple_simplify (code_helper *, tree *,
5238fd1498Szrj 			     gimple_seq *, tree (*)(tree),
5338fd1498Szrj 			     code_helper, tree, tree, tree);
5438fd1498Szrj static bool gimple_simplify (code_helper *, tree *,
5538fd1498Szrj 			     gimple_seq *, tree (*)(tree),
5638fd1498Szrj 			     code_helper, tree, tree, tree, tree);
5738fd1498Szrj 
5838fd1498Szrj 
5938fd1498Szrj /* Return whether T is a constant that we'll dispatch to fold to
6038fd1498Szrj    evaluate fully constant expressions.  */
6138fd1498Szrj 
6238fd1498Szrj static inline bool
constant_for_folding(tree t)6338fd1498Szrj constant_for_folding (tree t)
6438fd1498Szrj {
6538fd1498Szrj   return (CONSTANT_CLASS_P (t)
6638fd1498Szrj 	  /* The following is only interesting to string builtins.  */
6738fd1498Szrj 	  || (TREE_CODE (t) == ADDR_EXPR
6838fd1498Szrj 	      && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST));
6938fd1498Szrj }
7038fd1498Szrj 
7138fd1498Szrj 
7238fd1498Szrj /* Helper that matches and simplifies the toplevel result from
7338fd1498Szrj    a gimple_simplify run (where we don't want to build
7438fd1498Szrj    a stmt in case it's used in in-place folding).  Replaces
7538fd1498Szrj    *RES_CODE and *RES_OPS with a simplified and/or canonicalized
7638fd1498Szrj    result and returns whether any change was made.  */
7738fd1498Szrj 
7838fd1498Szrj bool
gimple_resimplify1(gimple_seq * seq,code_helper * res_code,tree type,tree * res_ops,tree (* valueize)(tree))7938fd1498Szrj gimple_resimplify1 (gimple_seq *seq,
8038fd1498Szrj 		    code_helper *res_code, tree type, tree *res_ops,
8138fd1498Szrj 		    tree (*valueize)(tree))
8238fd1498Szrj {
8338fd1498Szrj   if (constant_for_folding (res_ops[0]))
8438fd1498Szrj     {
8538fd1498Szrj       tree tem = NULL_TREE;
8638fd1498Szrj       if (res_code->is_tree_code ())
8738fd1498Szrj 	tem = const_unop (*res_code, type, res_ops[0]);
8838fd1498Szrj       else
8938fd1498Szrj 	tem = fold_const_call (combined_fn (*res_code), type, res_ops[0]);
9038fd1498Szrj       if (tem != NULL_TREE
9138fd1498Szrj 	  && CONSTANT_CLASS_P (tem))
9238fd1498Szrj 	{
9338fd1498Szrj 	  if (TREE_OVERFLOW_P (tem))
9438fd1498Szrj 	    tem = drop_tree_overflow (tem);
9538fd1498Szrj 	  res_ops[0] = tem;
9638fd1498Szrj 	  res_ops[1] = NULL_TREE;
9738fd1498Szrj 	  res_ops[2] = NULL_TREE;
9838fd1498Szrj 	  *res_code = TREE_CODE (res_ops[0]);
9938fd1498Szrj 	  return true;
10038fd1498Szrj 	}
10138fd1498Szrj     }
10238fd1498Szrj 
103*58e805e6Szrj   /* Limit recursion, there are cases like PR80887 and others, for
104*58e805e6Szrj      example when value-numbering presents us with unfolded expressions
105*58e805e6Szrj      that we are really not prepared to handle without eventual
106*58e805e6Szrj      oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50
107*58e805e6Szrj      itself as available expression.  */
108*58e805e6Szrj   static unsigned depth;
109*58e805e6Szrj   if (depth > 10)
110*58e805e6Szrj     {
111*58e805e6Szrj       if (dump_file && (dump_flags & TDF_FOLDING))
112*58e805e6Szrj 	fprintf (dump_file, "Aborting expression simplification due to "
113*58e805e6Szrj 		 "deep recursion\n");
114*58e805e6Szrj       return false;
115*58e805e6Szrj     }
116*58e805e6Szrj 
117*58e805e6Szrj   ++depth;
11838fd1498Szrj   code_helper res_code2;
11938fd1498Szrj   tree res_ops2[3] = {};
12038fd1498Szrj   if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
12138fd1498Szrj 		       *res_code, type, res_ops[0]))
12238fd1498Szrj     {
123*58e805e6Szrj       --depth;
12438fd1498Szrj       *res_code = res_code2;
12538fd1498Szrj       res_ops[0] = res_ops2[0];
12638fd1498Szrj       res_ops[1] = res_ops2[1];
12738fd1498Szrj       res_ops[2] = res_ops2[2];
12838fd1498Szrj       return true;
12938fd1498Szrj     }
130*58e805e6Szrj   --depth;
13138fd1498Szrj 
13238fd1498Szrj   return false;
13338fd1498Szrj }
13438fd1498Szrj 
13538fd1498Szrj /* Helper that matches and simplifies the toplevel result from
13638fd1498Szrj    a gimple_simplify run (where we don't want to build
13738fd1498Szrj    a stmt in case it's used in in-place folding).  Replaces
13838fd1498Szrj    *RES_CODE and *RES_OPS with a simplified and/or canonicalized
13938fd1498Szrj    result and returns whether any change was made.  */
14038fd1498Szrj 
14138fd1498Szrj bool
gimple_resimplify2(gimple_seq * seq,code_helper * res_code,tree type,tree * res_ops,tree (* valueize)(tree))14238fd1498Szrj gimple_resimplify2 (gimple_seq *seq,
14338fd1498Szrj 		    code_helper *res_code, tree type, tree *res_ops,
14438fd1498Szrj 		    tree (*valueize)(tree))
14538fd1498Szrj {
14638fd1498Szrj   if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1]))
14738fd1498Szrj     {
14838fd1498Szrj       tree tem = NULL_TREE;
14938fd1498Szrj       if (res_code->is_tree_code ())
15038fd1498Szrj 	tem = const_binop (*res_code, type, res_ops[0], res_ops[1]);
15138fd1498Szrj       else
15238fd1498Szrj 	tem = fold_const_call (combined_fn (*res_code), type,
15338fd1498Szrj 			       res_ops[0], res_ops[1]);
15438fd1498Szrj       if (tem != NULL_TREE
15538fd1498Szrj 	  && CONSTANT_CLASS_P (tem))
15638fd1498Szrj 	{
15738fd1498Szrj 	  if (TREE_OVERFLOW_P (tem))
15838fd1498Szrj 	    tem = drop_tree_overflow (tem);
15938fd1498Szrj 	  res_ops[0] = tem;
16038fd1498Szrj 	  res_ops[1] = NULL_TREE;
16138fd1498Szrj 	  res_ops[2] = NULL_TREE;
16238fd1498Szrj 	  *res_code = TREE_CODE (res_ops[0]);
16338fd1498Szrj 	  return true;
16438fd1498Szrj 	}
16538fd1498Szrj     }
16638fd1498Szrj 
16738fd1498Szrj   /* Canonicalize operand order.  */
16838fd1498Szrj   bool canonicalized = false;
16938fd1498Szrj   if (res_code->is_tree_code ()
17038fd1498Szrj       && (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison
17138fd1498Szrj 	  || commutative_tree_code (*res_code))
17238fd1498Szrj       && tree_swap_operands_p (res_ops[0], res_ops[1]))
17338fd1498Szrj     {
17438fd1498Szrj       std::swap (res_ops[0], res_ops[1]);
17538fd1498Szrj       if (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison)
17638fd1498Szrj 	*res_code = swap_tree_comparison (*res_code);
17738fd1498Szrj       canonicalized = true;
17838fd1498Szrj     }
17938fd1498Szrj 
180*58e805e6Szrj   /* Limit recursion, see gimple_resimplify1.  */
181*58e805e6Szrj   static unsigned depth;
182*58e805e6Szrj   if (depth > 10)
183*58e805e6Szrj     {
184*58e805e6Szrj       if (dump_file && (dump_flags & TDF_FOLDING))
185*58e805e6Szrj 	fprintf (dump_file, "Aborting expression simplification due to "
186*58e805e6Szrj 		 "deep recursion\n");
187*58e805e6Szrj       return false;
188*58e805e6Szrj     }
189*58e805e6Szrj 
190*58e805e6Szrj   ++depth;
19138fd1498Szrj   code_helper res_code2;
19238fd1498Szrj   tree res_ops2[3] = {};
19338fd1498Szrj   if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
19438fd1498Szrj 		       *res_code, type, res_ops[0], res_ops[1]))
19538fd1498Szrj     {
196*58e805e6Szrj       --depth;
19738fd1498Szrj       *res_code = res_code2;
19838fd1498Szrj       res_ops[0] = res_ops2[0];
19938fd1498Szrj       res_ops[1] = res_ops2[1];
20038fd1498Szrj       res_ops[2] = res_ops2[2];
20138fd1498Szrj       return true;
20238fd1498Szrj     }
203*58e805e6Szrj   --depth;
20438fd1498Szrj 
20538fd1498Szrj   return canonicalized;
20638fd1498Szrj }
20738fd1498Szrj 
20838fd1498Szrj /* Helper that matches and simplifies the toplevel result from
20938fd1498Szrj    a gimple_simplify run (where we don't want to build
21038fd1498Szrj    a stmt in case it's used in in-place folding).  Replaces
21138fd1498Szrj    *RES_CODE and *RES_OPS with a simplified and/or canonicalized
21238fd1498Szrj    result and returns whether any change was made.  */
21338fd1498Szrj 
21438fd1498Szrj bool
gimple_resimplify3(gimple_seq * seq,code_helper * res_code,tree type,tree * res_ops,tree (* valueize)(tree))21538fd1498Szrj gimple_resimplify3 (gimple_seq *seq,
21638fd1498Szrj 		    code_helper *res_code, tree type, tree *res_ops,
21738fd1498Szrj 		    tree (*valueize)(tree))
21838fd1498Szrj {
21938fd1498Szrj   if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1])
22038fd1498Szrj       && constant_for_folding (res_ops[2]))
22138fd1498Szrj     {
22238fd1498Szrj       tree tem = NULL_TREE;
22338fd1498Szrj       if (res_code->is_tree_code ())
22438fd1498Szrj 	tem = fold_ternary/*_to_constant*/ (*res_code, type, res_ops[0],
22538fd1498Szrj 					    res_ops[1], res_ops[2]);
22638fd1498Szrj       else
22738fd1498Szrj 	tem = fold_const_call (combined_fn (*res_code), type,
22838fd1498Szrj 			       res_ops[0], res_ops[1], res_ops[2]);
22938fd1498Szrj       if (tem != NULL_TREE
23038fd1498Szrj 	  && CONSTANT_CLASS_P (tem))
23138fd1498Szrj 	{
23238fd1498Szrj 	  if (TREE_OVERFLOW_P (tem))
23338fd1498Szrj 	    tem = drop_tree_overflow (tem);
23438fd1498Szrj 	  res_ops[0] = tem;
23538fd1498Szrj 	  res_ops[1] = NULL_TREE;
23638fd1498Szrj 	  res_ops[2] = NULL_TREE;
23738fd1498Szrj 	  *res_code = TREE_CODE (res_ops[0]);
23838fd1498Szrj 	  return true;
23938fd1498Szrj 	}
24038fd1498Szrj     }
24138fd1498Szrj 
24238fd1498Szrj   /* Canonicalize operand order.  */
24338fd1498Szrj   bool canonicalized = false;
24438fd1498Szrj   if (res_code->is_tree_code ()
24538fd1498Szrj       && commutative_ternary_tree_code (*res_code)
24638fd1498Szrj       && tree_swap_operands_p (res_ops[0], res_ops[1]))
24738fd1498Szrj     {
24838fd1498Szrj       std::swap (res_ops[0], res_ops[1]);
24938fd1498Szrj       canonicalized = true;
25038fd1498Szrj     }
25138fd1498Szrj 
252*58e805e6Szrj   /* Limit recursion, see gimple_resimplify1.  */
253*58e805e6Szrj   static unsigned depth;
254*58e805e6Szrj   if (depth > 10)
255*58e805e6Szrj     {
256*58e805e6Szrj       if (dump_file && (dump_flags & TDF_FOLDING))
257*58e805e6Szrj 	fprintf (dump_file, "Aborting expression simplification due to "
258*58e805e6Szrj 		 "deep recursion\n");
259*58e805e6Szrj       return false;
260*58e805e6Szrj     }
261*58e805e6Szrj 
262*58e805e6Szrj   ++depth;
26338fd1498Szrj   code_helper res_code2;
26438fd1498Szrj   tree res_ops2[3] = {};
26538fd1498Szrj   if (gimple_simplify (&res_code2, res_ops2, seq, valueize,
26638fd1498Szrj 		       *res_code, type,
26738fd1498Szrj 		       res_ops[0], res_ops[1], res_ops[2]))
26838fd1498Szrj     {
269*58e805e6Szrj       --depth;
27038fd1498Szrj       *res_code = res_code2;
27138fd1498Szrj       res_ops[0] = res_ops2[0];
27238fd1498Szrj       res_ops[1] = res_ops2[1];
27338fd1498Szrj       res_ops[2] = res_ops2[2];
27438fd1498Szrj       return true;
27538fd1498Szrj     }
276*58e805e6Szrj   --depth;
27738fd1498Szrj 
27838fd1498Szrj   return canonicalized;
27938fd1498Szrj }
28038fd1498Szrj 
28138fd1498Szrj 
28238fd1498Szrj /* If in GIMPLE expressions with CODE go as single-rhs build
28338fd1498Szrj    a GENERIC tree for that expression into *OP0.  */
28438fd1498Szrj 
28538fd1498Szrj void
maybe_build_generic_op(enum tree_code code,tree type,tree * ops)28638fd1498Szrj maybe_build_generic_op (enum tree_code code, tree type, tree *ops)
28738fd1498Szrj {
28838fd1498Szrj   switch (code)
28938fd1498Szrj     {
29038fd1498Szrj     case REALPART_EXPR:
29138fd1498Szrj     case IMAGPART_EXPR:
29238fd1498Szrj     case VIEW_CONVERT_EXPR:
29338fd1498Szrj       ops[0] = build1 (code, type, ops[0]);
29438fd1498Szrj       break;
29538fd1498Szrj     case BIT_FIELD_REF:
29638fd1498Szrj       ops[0] = build3 (code, type, ops[0], ops[1], ops[2]);
29738fd1498Szrj       ops[1] = ops[2] = NULL_TREE;
29838fd1498Szrj       break;
29938fd1498Szrj     default:;
30038fd1498Szrj     }
30138fd1498Szrj }
30238fd1498Szrj 
30338fd1498Szrj tree (*mprts_hook) (code_helper, tree, tree *);
30438fd1498Szrj 
30538fd1498Szrj /* Try to build a call to FN with return type TYPE and the NARGS
30638fd1498Szrj    arguments given in OPS.  Return null if the target doesn't support
30738fd1498Szrj    the function.  */
30838fd1498Szrj 
30938fd1498Szrj static gcall *
build_call_internal(internal_fn fn,tree type,unsigned int nargs,tree * ops)31038fd1498Szrj build_call_internal (internal_fn fn, tree type, unsigned int nargs, tree *ops)
31138fd1498Szrj {
31238fd1498Szrj   if (direct_internal_fn_p (fn))
31338fd1498Szrj     {
31438fd1498Szrj       tree_pair types = direct_internal_fn_types (fn, type, ops);
31538fd1498Szrj       if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
31638fd1498Szrj 	return NULL;
31738fd1498Szrj     }
31838fd1498Szrj   return gimple_build_call_internal (fn, nargs, ops[0], ops[1], ops[2]);
31938fd1498Szrj }
32038fd1498Szrj 
32138fd1498Szrj /* Push the exploded expression described by RCODE, TYPE and OPS
32238fd1498Szrj    as a statement to SEQ if necessary and return a gimple value
32338fd1498Szrj    denoting the value of the expression.  If RES is not NULL
32438fd1498Szrj    then the result will be always RES and even gimple values are
32538fd1498Szrj    pushed to SEQ.  */
32638fd1498Szrj 
32738fd1498Szrj tree
maybe_push_res_to_seq(code_helper rcode,tree type,tree * ops,gimple_seq * seq,tree res)32838fd1498Szrj maybe_push_res_to_seq (code_helper rcode, tree type, tree *ops,
32938fd1498Szrj 		       gimple_seq *seq, tree res)
33038fd1498Szrj {
33138fd1498Szrj   if (rcode.is_tree_code ())
33238fd1498Szrj     {
33338fd1498Szrj       if (!res
33438fd1498Szrj 	  && gimple_simplified_result_is_gimple_val (rcode, ops))
33538fd1498Szrj 	return ops[0];
33638fd1498Szrj       if (mprts_hook)
33738fd1498Szrj 	{
33838fd1498Szrj 	  tree tem = mprts_hook (rcode, type, ops);
33938fd1498Szrj 	  if (tem)
34038fd1498Szrj 	    return tem;
34138fd1498Szrj 	}
34238fd1498Szrj       if (!seq)
34338fd1498Szrj 	return NULL_TREE;
34438fd1498Szrj       /* Play safe and do not allow abnormals to be mentioned in
34538fd1498Szrj          newly created statements.  */
34638fd1498Szrj       if ((TREE_CODE (ops[0]) == SSA_NAME
34738fd1498Szrj 	   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0]))
34838fd1498Szrj 	  || (ops[1]
34938fd1498Szrj 	      && TREE_CODE (ops[1]) == SSA_NAME
35038fd1498Szrj 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1]))
35138fd1498Szrj 	  || (ops[2]
35238fd1498Szrj 	      && TREE_CODE (ops[2]) == SSA_NAME
35338fd1498Szrj 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2]))
35438fd1498Szrj 	  || (COMPARISON_CLASS_P (ops[0])
35538fd1498Szrj 	      && ((TREE_CODE (TREE_OPERAND (ops[0], 0)) == SSA_NAME
35638fd1498Szrj 		   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0],
35738fd1498Szrj 								     0)))
35838fd1498Szrj 		  || (TREE_CODE (TREE_OPERAND (ops[0], 1)) == SSA_NAME
35938fd1498Szrj 		      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0],
36038fd1498Szrj 									1))))))
36138fd1498Szrj 	return NULL_TREE;
36238fd1498Szrj       if (!res)
36338fd1498Szrj 	{
36438fd1498Szrj 	  if (gimple_in_ssa_p (cfun))
36538fd1498Szrj 	    res = make_ssa_name (type);
36638fd1498Szrj 	  else
36738fd1498Szrj 	    res = create_tmp_reg (type);
36838fd1498Szrj 	}
36938fd1498Szrj       maybe_build_generic_op (rcode, type, ops);
37038fd1498Szrj       gimple *new_stmt = gimple_build_assign (res, rcode,
37138fd1498Szrj 					     ops[0], ops[1], ops[2]);
37238fd1498Szrj       gimple_seq_add_stmt_without_update (seq, new_stmt);
37338fd1498Szrj       return res;
37438fd1498Szrj     }
37538fd1498Szrj   else
37638fd1498Szrj     {
37738fd1498Szrj       if (!seq)
37838fd1498Szrj 	return NULL_TREE;
37938fd1498Szrj       combined_fn fn = rcode;
38038fd1498Szrj       /* Play safe and do not allow abnormals to be mentioned in
38138fd1498Szrj          newly created statements.  */
38238fd1498Szrj       unsigned nargs;
38338fd1498Szrj       for (nargs = 0; nargs < 3; ++nargs)
38438fd1498Szrj 	{
38538fd1498Szrj 	  if (!ops[nargs])
38638fd1498Szrj 	    break;
38738fd1498Szrj 	  if (TREE_CODE (ops[nargs]) == SSA_NAME
38838fd1498Szrj 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[nargs]))
38938fd1498Szrj 	    return NULL_TREE;
39038fd1498Szrj 	}
39138fd1498Szrj       gcc_assert (nargs != 0);
39238fd1498Szrj       gcall *new_stmt = NULL;
39338fd1498Szrj       if (internal_fn_p (fn))
39438fd1498Szrj 	{
39538fd1498Szrj 	  /* Generate the given function if we can.  */
39638fd1498Szrj 	  internal_fn ifn = as_internal_fn (fn);
39738fd1498Szrj 	  new_stmt = build_call_internal (ifn, type, nargs, ops);
39838fd1498Szrj 	  if (!new_stmt)
39938fd1498Szrj 	    return NULL_TREE;
40038fd1498Szrj 	}
40138fd1498Szrj       else
40238fd1498Szrj 	{
40338fd1498Szrj 	  /* Find the function we want to call.  */
40438fd1498Szrj 	  tree decl = builtin_decl_implicit (as_builtin_fn (fn));
40538fd1498Szrj 	  if (!decl)
40638fd1498Szrj 	    return NULL;
40738fd1498Szrj 
40838fd1498Szrj 	  /* We can't and should not emit calls to non-const functions.  */
40938fd1498Szrj 	  if (!(flags_from_decl_or_type (decl) & ECF_CONST))
41038fd1498Szrj 	    return NULL;
41138fd1498Szrj 
41238fd1498Szrj 	  new_stmt = gimple_build_call (decl, nargs, ops[0], ops[1], ops[2]);
41338fd1498Szrj 	}
41438fd1498Szrj       if (!res)
41538fd1498Szrj 	{
41638fd1498Szrj 	  if (gimple_in_ssa_p (cfun))
41738fd1498Szrj 	    res = make_ssa_name (type);
41838fd1498Szrj 	  else
41938fd1498Szrj 	    res = create_tmp_reg (type);
42038fd1498Szrj 	}
42138fd1498Szrj       gimple_call_set_lhs (new_stmt, res);
42238fd1498Szrj       gimple_seq_add_stmt_without_update (seq, new_stmt);
42338fd1498Szrj       return res;
42438fd1498Szrj     }
42538fd1498Szrj }
42638fd1498Szrj 
42738fd1498Szrj 
42838fd1498Szrj /* Public API overloads follow for operation being tree_code or
42938fd1498Szrj    built_in_function and for one to three operands or arguments.
43038fd1498Szrj    They return NULL_TREE if nothing could be simplified or
43138fd1498Szrj    the resulting simplified value with parts pushed to SEQ.
43238fd1498Szrj    If SEQ is NULL then if the simplification needs to create
43338fd1498Szrj    new stmts it will fail.  If VALUEIZE is non-NULL then all
43438fd1498Szrj    SSA names will be valueized using that hook prior to
43538fd1498Szrj    applying simplifications.  */
43638fd1498Szrj 
43738fd1498Szrj /* Unary ops.  */
43838fd1498Szrj 
43938fd1498Szrj tree
gimple_simplify(enum tree_code code,tree type,tree op0,gimple_seq * seq,tree (* valueize)(tree))44038fd1498Szrj gimple_simplify (enum tree_code code, tree type,
44138fd1498Szrj 		 tree op0,
44238fd1498Szrj 		 gimple_seq *seq, tree (*valueize)(tree))
44338fd1498Szrj {
44438fd1498Szrj   if (constant_for_folding (op0))
44538fd1498Szrj     {
44638fd1498Szrj       tree res = const_unop (code, type, op0);
44738fd1498Szrj       if (res != NULL_TREE
44838fd1498Szrj 	  && CONSTANT_CLASS_P (res))
44938fd1498Szrj 	return res;
45038fd1498Szrj     }
45138fd1498Szrj 
45238fd1498Szrj   code_helper rcode;
45338fd1498Szrj   tree ops[3] = {};
45438fd1498Szrj   if (!gimple_simplify (&rcode, ops, seq, valueize,
45538fd1498Szrj 			code, type, op0))
45638fd1498Szrj     return NULL_TREE;
45738fd1498Szrj   return maybe_push_res_to_seq (rcode, type, ops, seq);
45838fd1498Szrj }
45938fd1498Szrj 
46038fd1498Szrj /* Binary ops.  */
46138fd1498Szrj 
46238fd1498Szrj tree
gimple_simplify(enum tree_code code,tree type,tree op0,tree op1,gimple_seq * seq,tree (* valueize)(tree))46338fd1498Szrj gimple_simplify (enum tree_code code, tree type,
46438fd1498Szrj 		 tree op0, tree op1,
46538fd1498Szrj 		 gimple_seq *seq, tree (*valueize)(tree))
46638fd1498Szrj {
46738fd1498Szrj   if (constant_for_folding (op0) && constant_for_folding (op1))
46838fd1498Szrj     {
46938fd1498Szrj       tree res = const_binop (code, type, op0, op1);
47038fd1498Szrj       if (res != NULL_TREE
47138fd1498Szrj 	  && CONSTANT_CLASS_P (res))
47238fd1498Szrj 	return res;
47338fd1498Szrj     }
47438fd1498Szrj 
47538fd1498Szrj   /* Canonicalize operand order both for matching and fallback stmt
47638fd1498Szrj      generation.  */
47738fd1498Szrj   if ((commutative_tree_code (code)
47838fd1498Szrj        || TREE_CODE_CLASS (code) == tcc_comparison)
47938fd1498Szrj       && tree_swap_operands_p (op0, op1))
48038fd1498Szrj     {
48138fd1498Szrj       std::swap (op0, op1);
48238fd1498Szrj       if (TREE_CODE_CLASS (code) == tcc_comparison)
48338fd1498Szrj 	code = swap_tree_comparison (code);
48438fd1498Szrj     }
48538fd1498Szrj 
48638fd1498Szrj   code_helper rcode;
48738fd1498Szrj   tree ops[3] = {};
48838fd1498Szrj   if (!gimple_simplify (&rcode, ops, seq, valueize,
48938fd1498Szrj 			code, type, op0, op1))
49038fd1498Szrj     return NULL_TREE;
49138fd1498Szrj   return maybe_push_res_to_seq (rcode, type, ops, seq);
49238fd1498Szrj }
49338fd1498Szrj 
49438fd1498Szrj /* Ternary ops.  */
49538fd1498Szrj 
49638fd1498Szrj tree
gimple_simplify(enum tree_code code,tree type,tree op0,tree op1,tree op2,gimple_seq * seq,tree (* valueize)(tree))49738fd1498Szrj gimple_simplify (enum tree_code code, tree type,
49838fd1498Szrj 		 tree op0, tree op1, tree op2,
49938fd1498Szrj 		 gimple_seq *seq, tree (*valueize)(tree))
50038fd1498Szrj {
50138fd1498Szrj   if (constant_for_folding (op0) && constant_for_folding (op1)
50238fd1498Szrj       && constant_for_folding (op2))
50338fd1498Szrj     {
50438fd1498Szrj       tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
50538fd1498Szrj       if (res != NULL_TREE
50638fd1498Szrj 	  && CONSTANT_CLASS_P (res))
50738fd1498Szrj 	return res;
50838fd1498Szrj     }
50938fd1498Szrj 
51038fd1498Szrj   /* Canonicalize operand order both for matching and fallback stmt
51138fd1498Szrj      generation.  */
51238fd1498Szrj   if (commutative_ternary_tree_code (code)
51338fd1498Szrj       && tree_swap_operands_p (op0, op1))
51438fd1498Szrj     std::swap (op0, op1);
51538fd1498Szrj 
51638fd1498Szrj   code_helper rcode;
51738fd1498Szrj   tree ops[3] = {};
51838fd1498Szrj   if (!gimple_simplify (&rcode, ops, seq, valueize,
51938fd1498Szrj 			code, type, op0, op1, op2))
52038fd1498Szrj     return NULL_TREE;
52138fd1498Szrj   return maybe_push_res_to_seq (rcode, type, ops, seq);
52238fd1498Szrj }
52338fd1498Szrj 
52438fd1498Szrj /* Builtin function with one argument.  */
52538fd1498Szrj 
52638fd1498Szrj tree
gimple_simplify(enum built_in_function fn,tree type,tree arg0,gimple_seq * seq,tree (* valueize)(tree))52738fd1498Szrj gimple_simplify (enum built_in_function fn, tree type,
52838fd1498Szrj 		 tree arg0,
52938fd1498Szrj 		 gimple_seq *seq, tree (*valueize)(tree))
53038fd1498Szrj {
53138fd1498Szrj   if (constant_for_folding (arg0))
53238fd1498Szrj     {
53338fd1498Szrj       tree res = fold_const_call (as_combined_fn (fn), type, arg0);
53438fd1498Szrj       if (res && CONSTANT_CLASS_P (res))
53538fd1498Szrj 	return res;
53638fd1498Szrj     }
53738fd1498Szrj 
53838fd1498Szrj   code_helper rcode;
53938fd1498Szrj   tree ops[3] = {};
54038fd1498Szrj   if (!gimple_simplify (&rcode, ops, seq, valueize,
54138fd1498Szrj 			as_combined_fn (fn), type, arg0))
54238fd1498Szrj     return NULL_TREE;
54338fd1498Szrj   return maybe_push_res_to_seq (rcode, type, ops, seq);
54438fd1498Szrj }
54538fd1498Szrj 
54638fd1498Szrj /* Builtin function with two arguments.  */
54738fd1498Szrj 
54838fd1498Szrj tree
gimple_simplify(enum built_in_function fn,tree type,tree arg0,tree arg1,gimple_seq * seq,tree (* valueize)(tree))54938fd1498Szrj gimple_simplify (enum built_in_function fn, tree type,
55038fd1498Szrj 		 tree arg0, tree arg1,
55138fd1498Szrj 		 gimple_seq *seq, tree (*valueize)(tree))
55238fd1498Szrj {
55338fd1498Szrj   if (constant_for_folding (arg0)
55438fd1498Szrj       && constant_for_folding (arg1))
55538fd1498Szrj     {
55638fd1498Szrj       tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1);
55738fd1498Szrj       if (res && CONSTANT_CLASS_P (res))
55838fd1498Szrj 	return res;
55938fd1498Szrj     }
56038fd1498Szrj 
56138fd1498Szrj   code_helper rcode;
56238fd1498Szrj   tree ops[3] = {};
56338fd1498Szrj   if (!gimple_simplify (&rcode, ops, seq, valueize,
56438fd1498Szrj 			as_combined_fn (fn), type, arg0, arg1))
56538fd1498Szrj     return NULL_TREE;
56638fd1498Szrj   return maybe_push_res_to_seq (rcode, type, ops, seq);
56738fd1498Szrj }
56838fd1498Szrj 
56938fd1498Szrj /* Builtin function with three arguments.  */
57038fd1498Szrj 
57138fd1498Szrj tree
gimple_simplify(enum built_in_function fn,tree type,tree arg0,tree arg1,tree arg2,gimple_seq * seq,tree (* valueize)(tree))57238fd1498Szrj gimple_simplify (enum built_in_function fn, tree type,
57338fd1498Szrj 		 tree arg0, tree arg1, tree arg2,
57438fd1498Szrj 		 gimple_seq *seq, tree (*valueize)(tree))
57538fd1498Szrj {
57638fd1498Szrj   if (constant_for_folding (arg0)
57738fd1498Szrj       && constant_for_folding (arg1)
57838fd1498Szrj       && constant_for_folding (arg2))
57938fd1498Szrj     {
58038fd1498Szrj       tree res = fold_const_call (as_combined_fn (fn), type, arg0, arg1, arg2);
58138fd1498Szrj       if (res && CONSTANT_CLASS_P (res))
58238fd1498Szrj 	return res;
58338fd1498Szrj     }
58438fd1498Szrj 
58538fd1498Szrj   code_helper rcode;
58638fd1498Szrj   tree ops[3] = {};
58738fd1498Szrj   if (!gimple_simplify (&rcode, ops, seq, valueize,
58838fd1498Szrj 			as_combined_fn (fn), type, arg0, arg1, arg2))
58938fd1498Szrj     return NULL_TREE;
59038fd1498Szrj   return maybe_push_res_to_seq (rcode, type, ops, seq);
59138fd1498Szrj }
59238fd1498Szrj 
59338fd1498Szrj /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
59438fd1498Szrj    VALUEIZED to true if valueization changed OP.  */
59538fd1498Szrj 
59638fd1498Szrj static inline tree
do_valueize(tree op,tree (* valueize)(tree),bool & valueized)59738fd1498Szrj do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
59838fd1498Szrj {
59938fd1498Szrj   if (valueize && TREE_CODE (op) == SSA_NAME)
60038fd1498Szrj     {
60138fd1498Szrj       tree tem = valueize (op);
60238fd1498Szrj       if (tem && tem != op)
60338fd1498Szrj 	{
60438fd1498Szrj 	  op = tem;
60538fd1498Szrj 	  valueized = true;
60638fd1498Szrj 	}
60738fd1498Szrj     }
60838fd1498Szrj   return op;
60938fd1498Szrj }
61038fd1498Szrj 
61138fd1498Szrj /* The main STMT based simplification entry.  It is used by the fold_stmt
61238fd1498Szrj    and the fold_stmt_to_constant APIs.  */
61338fd1498Szrj 
61438fd1498Szrj bool
gimple_simplify(gimple * stmt,code_helper * rcode,tree * ops,gimple_seq * seq,tree (* valueize)(tree),tree (* top_valueize)(tree))61538fd1498Szrj gimple_simplify (gimple *stmt,
61638fd1498Szrj 		 code_helper *rcode, tree *ops,
61738fd1498Szrj 		 gimple_seq *seq,
61838fd1498Szrj 		 tree (*valueize)(tree), tree (*top_valueize)(tree))
61938fd1498Szrj {
62038fd1498Szrj   switch (gimple_code (stmt))
62138fd1498Szrj     {
62238fd1498Szrj     case GIMPLE_ASSIGN:
62338fd1498Szrj       {
62438fd1498Szrj 	enum tree_code code = gimple_assign_rhs_code (stmt);
62538fd1498Szrj 	tree type = TREE_TYPE (gimple_assign_lhs (stmt));
62638fd1498Szrj 	switch (gimple_assign_rhs_class (stmt))
62738fd1498Szrj 	  {
62838fd1498Szrj 	  case GIMPLE_SINGLE_RHS:
62938fd1498Szrj 	    if (code == REALPART_EXPR
63038fd1498Szrj 		|| code == IMAGPART_EXPR
63138fd1498Szrj 		|| code == VIEW_CONVERT_EXPR)
63238fd1498Szrj 	      {
63338fd1498Szrj 		tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
63438fd1498Szrj 		bool valueized = false;
63538fd1498Szrj 		op0 = do_valueize (op0, top_valueize, valueized);
63638fd1498Szrj 		*rcode = code;
63738fd1498Szrj 		ops[0] = op0;
63838fd1498Szrj 		return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
63938fd1498Szrj 			|| valueized);
64038fd1498Szrj 	      }
64138fd1498Szrj 	    else if (code == BIT_FIELD_REF)
64238fd1498Szrj 	      {
64338fd1498Szrj 		tree rhs1 = gimple_assign_rhs1 (stmt);
64438fd1498Szrj 		tree op0 = TREE_OPERAND (rhs1, 0);
64538fd1498Szrj 		bool valueized = false;
64638fd1498Szrj 		op0 = do_valueize (op0, top_valueize, valueized);
64738fd1498Szrj 		*rcode = code;
64838fd1498Szrj 		ops[0] = op0;
64938fd1498Szrj 		ops[1] = TREE_OPERAND (rhs1, 1);
65038fd1498Szrj 		ops[2] = TREE_OPERAND (rhs1, 2);
65138fd1498Szrj 		return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
65238fd1498Szrj 			|| valueized);
65338fd1498Szrj 	      }
65438fd1498Szrj 	    else if (code == SSA_NAME
65538fd1498Szrj 		     && top_valueize)
65638fd1498Szrj 	      {
65738fd1498Szrj 		tree op0 = gimple_assign_rhs1 (stmt);
65838fd1498Szrj 		tree valueized = top_valueize (op0);
65938fd1498Szrj 		if (!valueized || op0 == valueized)
66038fd1498Szrj 		  return false;
66138fd1498Szrj 		ops[0] = valueized;
66238fd1498Szrj 		*rcode = TREE_CODE (op0);
66338fd1498Szrj 		return true;
66438fd1498Szrj 	      }
66538fd1498Szrj 	    break;
66638fd1498Szrj 	  case GIMPLE_UNARY_RHS:
66738fd1498Szrj 	    {
66838fd1498Szrj 	      tree rhs1 = gimple_assign_rhs1 (stmt);
66938fd1498Szrj 	      bool valueized = false;
67038fd1498Szrj 	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
67138fd1498Szrj 	      *rcode = code;
67238fd1498Szrj 	      ops[0] = rhs1;
67338fd1498Szrj 	      return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
67438fd1498Szrj 		      || valueized);
67538fd1498Szrj 	    }
67638fd1498Szrj 	  case GIMPLE_BINARY_RHS:
67738fd1498Szrj 	    {
67838fd1498Szrj 	      tree rhs1 = gimple_assign_rhs1 (stmt);
67938fd1498Szrj 	      tree rhs2 = gimple_assign_rhs2 (stmt);
68038fd1498Szrj 	      bool valueized = false;
68138fd1498Szrj 	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
68238fd1498Szrj 	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
68338fd1498Szrj 	      *rcode = code;
68438fd1498Szrj 	      ops[0] = rhs1;
68538fd1498Szrj 	      ops[1] = rhs2;
68638fd1498Szrj 	      return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
68738fd1498Szrj 		      || valueized);
68838fd1498Szrj 	    }
68938fd1498Szrj 	  case GIMPLE_TERNARY_RHS:
69038fd1498Szrj 	    {
69138fd1498Szrj 	      bool valueized = false;
69238fd1498Szrj 	      tree rhs1 = gimple_assign_rhs1 (stmt);
69338fd1498Szrj 	      /* If this is a [VEC_]COND_EXPR first try to simplify an
69438fd1498Szrj 		 embedded GENERIC condition.  */
69538fd1498Szrj 	      if (code == COND_EXPR
69638fd1498Szrj 		  || code == VEC_COND_EXPR)
69738fd1498Szrj 		{
69838fd1498Szrj 		  if (COMPARISON_CLASS_P (rhs1))
69938fd1498Szrj 		    {
70038fd1498Szrj 		      tree lhs = TREE_OPERAND (rhs1, 0);
70138fd1498Szrj 		      tree rhs = TREE_OPERAND (rhs1, 1);
70238fd1498Szrj 		      lhs = do_valueize (lhs, top_valueize, valueized);
70338fd1498Szrj 		      rhs = do_valueize (rhs, top_valueize, valueized);
70438fd1498Szrj 		      code_helper rcode2 = TREE_CODE (rhs1);
70538fd1498Szrj 		      tree ops2[3] = {};
70638fd1498Szrj 		      ops2[0] = lhs;
70738fd1498Szrj 		      ops2[1] = rhs;
70838fd1498Szrj 		      if ((gimple_resimplify2 (seq, &rcode2, TREE_TYPE (rhs1),
70938fd1498Szrj 					       ops2, valueize)
71038fd1498Szrj 			   || valueized)
71138fd1498Szrj 			  && rcode2.is_tree_code ())
71238fd1498Szrj 			{
71338fd1498Szrj 			  valueized = true;
71438fd1498Szrj 			  if (TREE_CODE_CLASS ((enum tree_code)rcode2)
71538fd1498Szrj 			      == tcc_comparison)
71638fd1498Szrj 			    rhs1 = build2 (rcode2, TREE_TYPE (rhs1),
71738fd1498Szrj 					   ops2[0], ops2[1]);
71838fd1498Szrj 			  else if (rcode2 == SSA_NAME
71938fd1498Szrj 				   || rcode2 == INTEGER_CST
72038fd1498Szrj 				   || rcode2 == VECTOR_CST)
72138fd1498Szrj 			    rhs1 = ops2[0];
72238fd1498Szrj 			  else
72338fd1498Szrj 			    valueized = false;
72438fd1498Szrj 			}
72538fd1498Szrj 		    }
72638fd1498Szrj 		}
72738fd1498Szrj 	      tree rhs2 = gimple_assign_rhs2 (stmt);
72838fd1498Szrj 	      tree rhs3 = gimple_assign_rhs3 (stmt);
72938fd1498Szrj 	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
73038fd1498Szrj 	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
73138fd1498Szrj 	      rhs3 = do_valueize (rhs3, top_valueize, valueized);
73238fd1498Szrj 	      *rcode = code;
73338fd1498Szrj 	      ops[0] = rhs1;
73438fd1498Szrj 	      ops[1] = rhs2;
73538fd1498Szrj 	      ops[2] = rhs3;
73638fd1498Szrj 	      return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
73738fd1498Szrj 		      || valueized);
73838fd1498Szrj 	    }
73938fd1498Szrj 	  default:
74038fd1498Szrj 	    gcc_unreachable ();
74138fd1498Szrj 	  }
74238fd1498Szrj 	break;
74338fd1498Szrj       }
74438fd1498Szrj 
74538fd1498Szrj     case GIMPLE_CALL:
74638fd1498Szrj       /* ???  This way we can't simplify calls with side-effects.  */
74738fd1498Szrj       if (gimple_call_lhs (stmt) != NULL_TREE
74838fd1498Szrj 	  && gimple_call_num_args (stmt) >= 1
74938fd1498Szrj 	  && gimple_call_num_args (stmt) <= 3)
75038fd1498Szrj 	{
75138fd1498Szrj 	  bool valueized = false;
75238fd1498Szrj 	  if (gimple_call_internal_p (stmt))
75338fd1498Szrj 	    *rcode = as_combined_fn (gimple_call_internal_fn (stmt));
75438fd1498Szrj 	  else
75538fd1498Szrj 	    {
75638fd1498Szrj 	      tree fn = gimple_call_fn (stmt);
75738fd1498Szrj 	      if (!fn)
75838fd1498Szrj 		return false;
75938fd1498Szrj 
76038fd1498Szrj 	      fn = do_valueize (fn, top_valueize, valueized);
76138fd1498Szrj 	      if (TREE_CODE (fn) != ADDR_EXPR
76238fd1498Szrj 		  || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
76338fd1498Szrj 		return false;
76438fd1498Szrj 
76538fd1498Szrj 	      tree decl = TREE_OPERAND (fn, 0);
76638fd1498Szrj 	      if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
76738fd1498Szrj 		  || !gimple_builtin_call_types_compatible_p (stmt, decl))
76838fd1498Szrj 		return false;
76938fd1498Szrj 
77038fd1498Szrj 	      *rcode = as_combined_fn (DECL_FUNCTION_CODE (decl));
77138fd1498Szrj 	    }
77238fd1498Szrj 
77338fd1498Szrj 	  tree type = TREE_TYPE (gimple_call_lhs (stmt));
77438fd1498Szrj 	  for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
77538fd1498Szrj 	    {
77638fd1498Szrj 	      tree arg = gimple_call_arg (stmt, i);
77738fd1498Szrj 	      ops[i] = do_valueize (arg, top_valueize, valueized);
77838fd1498Szrj 	    }
77938fd1498Szrj 	  switch (gimple_call_num_args (stmt))
78038fd1498Szrj 	    {
78138fd1498Szrj 	    case 1:
78238fd1498Szrj 	      return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
78338fd1498Szrj 		      || valueized);
78438fd1498Szrj 	    case 2:
78538fd1498Szrj 	      return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
78638fd1498Szrj 		      || valueized);
78738fd1498Szrj 	    case 3:
78838fd1498Szrj 	      return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
78938fd1498Szrj 		      || valueized);
79038fd1498Szrj 	    default:
79138fd1498Szrj 	     gcc_unreachable ();
79238fd1498Szrj 	    }
79338fd1498Szrj 	}
79438fd1498Szrj       break;
79538fd1498Szrj 
79638fd1498Szrj     case GIMPLE_COND:
79738fd1498Szrj       {
79838fd1498Szrj 	tree lhs = gimple_cond_lhs (stmt);
79938fd1498Szrj 	tree rhs = gimple_cond_rhs (stmt);
80038fd1498Szrj 	bool valueized = false;
80138fd1498Szrj 	lhs = do_valueize (lhs, top_valueize, valueized);
80238fd1498Szrj 	rhs = do_valueize (rhs, top_valueize, valueized);
80338fd1498Szrj 	*rcode = gimple_cond_code (stmt);
80438fd1498Szrj 	ops[0] = lhs;
80538fd1498Szrj 	ops[1] = rhs;
80638fd1498Szrj         return (gimple_resimplify2 (seq, rcode,
80738fd1498Szrj 				    boolean_type_node, ops, valueize)
80838fd1498Szrj 		|| valueized);
80938fd1498Szrj       }
81038fd1498Szrj 
81138fd1498Szrj     default:
81238fd1498Szrj       break;
81338fd1498Szrj     }
81438fd1498Szrj 
81538fd1498Szrj   return false;
81638fd1498Szrj }
81738fd1498Szrj 
81838fd1498Szrj 
81938fd1498Szrj /* Helper for the autogenerated code, valueize OP.  */
82038fd1498Szrj 
82138fd1498Szrj inline tree
do_valueize(tree (* valueize)(tree),tree op)82238fd1498Szrj do_valueize (tree (*valueize)(tree), tree op)
82338fd1498Szrj {
82438fd1498Szrj   if (valueize && TREE_CODE (op) == SSA_NAME)
82538fd1498Szrj     {
82638fd1498Szrj       tree tem = valueize (op);
82738fd1498Szrj       if (tem)
82838fd1498Szrj 	return tem;
82938fd1498Szrj     }
83038fd1498Szrj   return op;
83138fd1498Szrj }
83238fd1498Szrj 
83338fd1498Szrj /* Helper for the autogenerated code, get at the definition of NAME when
83438fd1498Szrj    VALUEIZE allows that.  */
83538fd1498Szrj 
83638fd1498Szrj inline gimple *
get_def(tree (* valueize)(tree),tree name)83738fd1498Szrj get_def (tree (*valueize)(tree), tree name)
83838fd1498Szrj {
83938fd1498Szrj   if (valueize && ! valueize (name))
84038fd1498Szrj     return NULL;
84138fd1498Szrj   return SSA_NAME_DEF_STMT (name);
84238fd1498Szrj }
84338fd1498Szrj 
84438fd1498Szrj /* Routine to determine if the types T1 and T2 are effectively
84538fd1498Szrj    the same for GIMPLE.  If T1 or T2 is not a type, the test
84638fd1498Szrj    applies to their TREE_TYPE.  */
84738fd1498Szrj 
84838fd1498Szrj static inline bool
types_match(tree t1,tree t2)84938fd1498Szrj types_match (tree t1, tree t2)
85038fd1498Szrj {
85138fd1498Szrj   if (!TYPE_P (t1))
85238fd1498Szrj     t1 = TREE_TYPE (t1);
85338fd1498Szrj   if (!TYPE_P (t2))
85438fd1498Szrj     t2 = TREE_TYPE (t2);
85538fd1498Szrj 
85638fd1498Szrj   return types_compatible_p (t1, t2);
85738fd1498Szrj }
85838fd1498Szrj 
85938fd1498Szrj /* Return if T has a single use.  For GIMPLE, we also allow any
86038fd1498Szrj    non-SSA_NAME (ie constants) and zero uses to cope with uses
86138fd1498Szrj    that aren't linked up yet.  */
86238fd1498Szrj 
86338fd1498Szrj static inline bool
single_use(tree t)86438fd1498Szrj single_use (tree t)
86538fd1498Szrj {
86638fd1498Szrj   return TREE_CODE (t) != SSA_NAME || has_zero_uses (t) || has_single_use (t);
86738fd1498Szrj }
86838fd1498Szrj 
86938fd1498Szrj /* Return true if math operations should be canonicalized,
87038fd1498Szrj    e.g. sqrt(sqrt(x)) -> pow(x, 0.25).  */
87138fd1498Szrj 
87238fd1498Szrj static inline bool
canonicalize_math_p()87338fd1498Szrj canonicalize_math_p ()
87438fd1498Szrj {
87538fd1498Szrj   return !cfun || (cfun->curr_properties & PROP_gimple_opt_math) == 0;
87638fd1498Szrj }
87738fd1498Szrj 
87838fd1498Szrj /* Return true if math operations that are beneficial only after
87938fd1498Szrj    vectorization should be canonicalized.  */
88038fd1498Szrj 
88138fd1498Szrj static inline bool
canonicalize_math_after_vectorization_p()88238fd1498Szrj canonicalize_math_after_vectorization_p ()
88338fd1498Szrj {
88438fd1498Szrj   return !cfun || (cfun->curr_properties & PROP_gimple_lvec) != 0;
88538fd1498Szrj }
88638fd1498Szrj 
88738fd1498Szrj /* Return true if pow(cst, x) should be optimized into exp(log(cst) * x).
88838fd1498Szrj    As a workaround for SPEC CPU2017 628.pop2_s, don't do it if arg0
88938fd1498Szrj    is an exact integer, arg1 = phi_res +/- cst1 and phi_res = PHI <cst2, ...>
89038fd1498Szrj    where cst2 +/- cst1 is an exact integer, because then pow (arg0, arg1)
89138fd1498Szrj    will likely be exact, while exp (log (arg0) * arg1) might be not.
89238fd1498Szrj    Also don't do it if arg1 is phi_res above and cst2 is an exact integer.  */
89338fd1498Szrj 
89438fd1498Szrj static bool
optimize_pow_to_exp(tree arg0,tree arg1)89538fd1498Szrj optimize_pow_to_exp (tree arg0, tree arg1)
89638fd1498Szrj {
89738fd1498Szrj   gcc_assert (TREE_CODE (arg0) == REAL_CST);
89838fd1498Szrj   if (!real_isinteger (TREE_REAL_CST_PTR (arg0), TYPE_MODE (TREE_TYPE (arg0))))
89938fd1498Szrj     return true;
90038fd1498Szrj 
90138fd1498Szrj   if (TREE_CODE (arg1) != SSA_NAME)
90238fd1498Szrj     return true;
90338fd1498Szrj 
90438fd1498Szrj   gimple *def = SSA_NAME_DEF_STMT (arg1);
90538fd1498Szrj   gphi *phi = dyn_cast <gphi *> (def);
90638fd1498Szrj   tree cst1 = NULL_TREE;
90738fd1498Szrj   enum tree_code code = ERROR_MARK;
90838fd1498Szrj   if (!phi)
90938fd1498Szrj     {
91038fd1498Szrj       if (!is_gimple_assign (def))
91138fd1498Szrj 	return true;
91238fd1498Szrj       code = gimple_assign_rhs_code (def);
91338fd1498Szrj       switch (code)
91438fd1498Szrj 	{
91538fd1498Szrj 	case PLUS_EXPR:
91638fd1498Szrj 	case MINUS_EXPR:
91738fd1498Szrj 	  break;
91838fd1498Szrj 	default:
91938fd1498Szrj 	  return true;
92038fd1498Szrj 	}
92138fd1498Szrj       if (TREE_CODE (gimple_assign_rhs1 (def)) != SSA_NAME
92238fd1498Szrj 	  || TREE_CODE (gimple_assign_rhs2 (def)) != REAL_CST)
92338fd1498Szrj 	return true;
92438fd1498Szrj 
92538fd1498Szrj       cst1 = gimple_assign_rhs2 (def);
92638fd1498Szrj 
92738fd1498Szrj       phi = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def)));
92838fd1498Szrj       if (!phi)
92938fd1498Szrj 	return true;
93038fd1498Szrj     }
93138fd1498Szrj 
93238fd1498Szrj   tree cst2 = NULL_TREE;
93338fd1498Szrj   int n = gimple_phi_num_args (phi);
93438fd1498Szrj   for (int i = 0; i < n; i++)
93538fd1498Szrj     {
93638fd1498Szrj       tree arg = PHI_ARG_DEF (phi, i);
93738fd1498Szrj       if (TREE_CODE (arg) != REAL_CST)
93838fd1498Szrj 	continue;
93938fd1498Szrj       else if (cst2 == NULL_TREE)
94038fd1498Szrj 	cst2 = arg;
94138fd1498Szrj       else if (!operand_equal_p (cst2, arg, 0))
94238fd1498Szrj 	return true;
94338fd1498Szrj     }
94438fd1498Szrj 
94538fd1498Szrj   if (cst1 && cst2)
94638fd1498Szrj     cst2 = const_binop (code, TREE_TYPE (cst2), cst2, cst1);
94738fd1498Szrj   if (cst2
94838fd1498Szrj       && TREE_CODE (cst2) == REAL_CST
94938fd1498Szrj       && real_isinteger (TREE_REAL_CST_PTR (cst2),
95038fd1498Szrj 			 TYPE_MODE (TREE_TYPE (cst2))))
95138fd1498Szrj     return false;
95238fd1498Szrj   return true;
95338fd1498Szrj }
954