2021-01-09 Jakub Jelinek <ja...@redhat.com>
PR tree-optimization/95867
* tree-ssa-math-opts.h: New header.
* tree-ssa-math-opts.c: Include tree-ssa-math-opts.h.
(powi_as_mults): No longer static. Use build_one_cst instead of
build_real. Formatting fix.
* tree-ssa-reassoc.c: Include tree-ssa-math-opts.h.
(attempt_builtin_powi): Handle multiplication reassociation without
powi_fndecl using powi_as_mults.
(reassociate_bb): For integral types don't require
-funsafe-math-optimizations to call attempt_builtin_powi.
* gcc.dg/tree-ssa/pr95867.c: New test.
--- gcc/tree-ssa-math-opts.h.jj 2021-01-09 16:54:58.301092357 +0100
+++ gcc/tree-ssa-math-opts.h 2021-01-09 16:56:32.098024806 +0100
@@ -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 */
--- gcc/tree-ssa-math-opts.c.jj 2021-01-09 10:47:18.000000000 +0100
+++ gcc/tree-ssa-math-opts.c 2021-01-09 16:58:59.442347773 +0100
@@ -115,6 +115,7 @@ along with GCC; see the file COPYING3.
#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 *g
/* 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
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);
--- gcc/tree-ssa-reassoc.c.jj 2021-01-05 16:37:36.254185194 +0100
+++ gcc/tree-ssa-reassoc.c 2021-01-09 17:20:48.205462550 +0100
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3.
#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<
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<
}
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<
/* 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);
}
--- gcc/testsuite/gcc.dg/tree-ssa/pr95867.c.jj 2021-01-09 17:49:53.935641884
+0100
+++ gcc/testsuite/gcc.dg/tree-ssa/pr95867.c 2021-01-09 17:49:36.896835332
+0100
@@ -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;
+}
Jakub