diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-01-11 10:35:10 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-01-11 10:36:24 +0100 |
commit | 9a6c37e6ae520534993ef76dd45d016c8c86db21 (patch) | |
tree | d0035483cb49261a3fcdf2b3122adb700f585f7d /gcc/tree-ssa-reassoc.c | |
parent | 9febe9e4be7812519258ea3ed4f38bbc1a61624b (diff) | |
download | gcc-9a6c37e6ae520534993ef76dd45d016c8c86db21.zip gcc-9a6c37e6ae520534993ef76dd45d016c8c86db21.tar.gz gcc-9a6c37e6ae520534993ef76dd45d016c8c86db21.tar.bz2 |
reassoc: Reassociate integral multiplies [PR95867]
For floating point multiply, we have nice code in reassoc to reassociate
multiplications to almost optimal sequence of as few multiplications as
possible (or library call), but for integral types we just give up
because there is no __builtin_powi* for those types.
As there is no library routine we could use, instead of adding new internal
call just to hold it temporarily and then lower to multiplications again,
this patch for the integral types calls into the sincos pass routine that
expands it into multiplications right away.
2021-01-11 Jakub Jelinek <jakub@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.
Diffstat (limited to 'gcc/tree-ssa-reassoc.c')
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 77 |
1 files changed, 58 insertions, 19 deletions
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); } |