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