diff options
| -rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr95867.c | 14 | ||||
| -rw-r--r-- | gcc/tree-ssa-math-opts.c | 7 | ||||
| -rw-r--r-- | gcc/tree-ssa-math-opts.h | 26 | ||||
| -rw-r--r-- | gcc/tree-ssa-reassoc.c | 77 |
4 files changed, 102 insertions, 22 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr95867.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95867.c new file mode 100644 index 0000000..8ab3690 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95867.c @@ -0,0 +1,14 @@ +/* PR tree-optimization/95867 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times " \\* " 13 "optimized" } } */ + +#define A n * n * n * n * n * n * n * n +#define B A * A * A * A * A * A * A * A +#define C B * B * B * B * B * B * B * B + +unsigned +foo (unsigned n) +{ + return C * B * B * A * n * n * n * n * n; +} diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 91ec0f6..74a16b6 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -115,6 +115,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-eh.h" #include "targhooks.h" #include "domwalk.h" +#include "tree-ssa-math-opts.h" /* This structure represents one basic block that either computes a division, or is a common dominator for basic block that compute a @@ -1527,7 +1528,7 @@ powi_as_mults_1 (gimple_stmt_iterator *gsi, location_t loc, tree type, /* Convert ARG0**N to a tree of multiplications of ARG0 with itself. This function needs to be kept in sync with powi_cost above. */ -static tree +tree powi_as_mults (gimple_stmt_iterator *gsi, location_t loc, tree arg0, HOST_WIDE_INT n) { @@ -1536,9 +1537,9 @@ powi_as_mults (gimple_stmt_iterator *gsi, location_t loc, tree target; if (n == 0) - return build_real (type, dconst1); + return build_one_cst (type); - memset (cache, 0, sizeof (cache)); + memset (cache, 0, sizeof (cache)); cache[1] = arg0; result = powi_as_mults_1 (gsi, loc, type, (n < 0) ? -n : n, cache); diff --git a/gcc/tree-ssa-math-opts.h b/gcc/tree-ssa-math-opts.h new file mode 100644 index 0000000..37c666a --- /dev/null +++ b/gcc/tree-ssa-math-opts.h @@ -0,0 +1,26 @@ +/* Global, SSA-based optimizations using mathematical identities. + Copyright (C) 2021 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_TREE_SSA_MATH_OPTS_H +#define GCC_TREE_SSA_MATH_OPTS_H + +extern tree powi_as_mults (gimple_stmt_iterator *, location_t, + tree, HOST_WIDE_INT); + +#endif /* GCC_TREE_SSA_MATH_OPTS_H */ diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index fac74a3..b6a09e5 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "case-cfn-macros.h" #include "tree-ssa-reassoc.h" +#include "tree-ssa-math-opts.h" /* This is a simple global reassociation pass. It is, in part, based on the LLVM pass of the same name (They do some things more/less @@ -5976,8 +5977,8 @@ attempt_builtin_powi (gimple *stmt, vec<operand_entry *> *ops) gimple *mul_stmt, *pow_stmt; /* Nothing to do if BUILT_IN_POWI doesn't exist for this type and - target. */ - if (!powi_fndecl) + target, unless type is integral. */ + if (!powi_fndecl && !INTEGRAL_TYPE_P (type)) return NULL_TREE; /* Allocate the repeated factor vector. */ @@ -6086,14 +6087,33 @@ attempt_builtin_powi (gimple *stmt, vec<operand_entry *> *ops) } else { - iter_result = make_temp_ssa_name (type, NULL, "reassocpow"); - pow_stmt = gimple_build_call (powi_fndecl, 2, rf1->repr, - build_int_cst (integer_type_node, - power)); - gimple_call_set_lhs (pow_stmt, iter_result); - gimple_set_location (pow_stmt, gimple_location (stmt)); - gimple_set_uid (pow_stmt, gimple_uid (stmt)); - gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT); + if (INTEGRAL_TYPE_P (type)) + { + gcc_assert (power > 1); + gimple_stmt_iterator gsip = gsi; + gsi_prev (&gsip); + iter_result = powi_as_mults (&gsi, gimple_location (stmt), + rf1->repr, power); + gimple_stmt_iterator gsic = gsi; + while (gsi_stmt (gsic) != gsi_stmt (gsip)) + { + gimple_set_uid (gsi_stmt (gsic), gimple_uid (stmt)); + gimple_set_visited (gsi_stmt (gsic), true); + gsi_prev (&gsic); + } + } + else + { + iter_result = make_temp_ssa_name (type, NULL, "reassocpow"); + pow_stmt + = gimple_build_call (powi_fndecl, 2, rf1->repr, + build_int_cst (integer_type_node, + power)); + gimple_call_set_lhs (pow_stmt, iter_result); + gimple_set_location (pow_stmt, gimple_location (stmt)); + gimple_set_uid (pow_stmt, gimple_uid (stmt)); + gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT); + } if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -6188,14 +6208,32 @@ attempt_builtin_powi (gimple *stmt, vec<operand_entry *> *ops) /* Form a call to __builtin_powi for the maximum product just formed, raised to the power obtained earlier. */ rf1 = &repeat_factor_vec[j]; - iter_result = make_temp_ssa_name (type, NULL, "reassocpow"); - pow_stmt = gimple_build_call (powi_fndecl, 2, rf1->repr, - build_int_cst (integer_type_node, - power)); - gimple_call_set_lhs (pow_stmt, iter_result); - gimple_set_location (pow_stmt, gimple_location (stmt)); - gimple_set_uid (pow_stmt, gimple_uid (stmt)); - gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT); + if (INTEGRAL_TYPE_P (type)) + { + gcc_assert (power > 1); + gimple_stmt_iterator gsip = gsi; + gsi_prev (&gsip); + iter_result = powi_as_mults (&gsi, gimple_location (stmt), + rf1->repr, power); + gimple_stmt_iterator gsic = gsi; + while (gsi_stmt (gsic) != gsi_stmt (gsip)) + { + gimple_set_uid (gsi_stmt (gsic), gimple_uid (stmt)); + gimple_set_visited (gsi_stmt (gsic), true); + gsi_prev (&gsic); + } + } + else + { + iter_result = make_temp_ssa_name (type, NULL, "reassocpow"); + pow_stmt = gimple_build_call (powi_fndecl, 2, rf1->repr, + build_int_cst (integer_type_node, + power)); + gimple_call_set_lhs (pow_stmt, iter_result); + gimple_set_location (pow_stmt, gimple_location (stmt)); + gimple_set_uid (pow_stmt, gimple_uid (stmt)); + gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT); + } } /* If we previously formed at least one other builtin_powi call, @@ -6522,7 +6560,8 @@ reassociate_bb (basic_block bb) attempt_builtin_copysign (&ops); if (reassoc_insert_powi_p - && flag_unsafe_math_optimizations) + && (flag_unsafe_math_optimizations + || (INTEGRAL_TYPE_P (TREE_TYPE (lhs))))) powi_result = attempt_builtin_powi (stmt, &ops); } |
