From: Alexandre Oliva <oliva@adacore.com>
To: Richard Biener <richard.guenther@gmail.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: move sincos after pre
Date: Tue, 27 Oct 2020 02:32:04 -0300 [thread overview]
Message-ID: <ora6w8xmi3.fsf@livre.home> (raw)
In-Reply-To: <B7698CF0-A5A2-4AE1-9620-2EEA313243EA@gmail.com> (Richard Biener's message of "Fri, 23 Oct 2020 17:05:49 +0200")
On Oct 23, 2020, Richard Biener <richard.guenther@gmail.com> wrote:
> Can you move it one pass further after sink please?
I did, but it didn't solve the recip regressions that my first attempt
brought about.
> Also I don't
> remember exactly but does pass_sincos only handle sin/cos unifying?
It rearranges some powi computations, and that's what breaks recip. It
adds a copy of y*y in extract_recip_[34], we'd need a forwprop or
similar to get rid of the trivial copy before recip could do its job
properly again.
So I figured I'd try to cse type conversions before sincos, and that
turned out to be pretty easy, and it didn't regress anything.
Regstrapped on x86_64-linux-gnu. Ok to install?
CSE conversions within sincos
From: Alexandre Oliva <oliva@adacore.com>
On platforms in which Aux_[Real_Type] involves non-NOP conversions
(e.g., between single- and double-precision, or between short float
and float), the conversions before the calls are CSEd too late for
sincos to combine calls.
This patch enables the sincos pass to CSE type casts used as arguments
to eligible calls before looking for other calls using the same
operand.
for gcc/ChangeLog
* tree-ssa-math-opts.c (sincos_stats): Rename inserted to
sincos_inserted. Add conv_inserted.
(maybe_record_sincos): Rename to...
(maybe_record_stmt): ... this.
(execute_cse_conv_1): New.
(execute_cse_sincos_1): Call it. Adjust.
(pass_cse_sincos::execute): Adjust. Report conv_inserted.
for gcc/testsuite/ChangeLog
* gnat.dg/sin_cos.ads: New.
* gnat.dg/sin_cos.adb: New.
* gcc.dg/sin_cos.c: New.
---
gcc/testsuite/gcc.dg/sin_cos.c | 41 +++++++++++++
gcc/testsuite/gnat.dg/sin_cos.adb | 14 ++++
gcc/testsuite/gnat.dg/sin_cos.ads | 4 +
gcc/tree-ssa-math-opts.c | 119 +++++++++++++++++++++++++++++++++++--
4 files changed, 171 insertions(+), 7 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/sin_cos.c
create mode 100644 gcc/testsuite/gnat.dg/sin_cos.adb
create mode 100644 gcc/testsuite/gnat.dg/sin_cos.ads
diff --git a/gcc/testsuite/gcc.dg/sin_cos.c b/gcc/testsuite/gcc.dg/sin_cos.c
new file mode 100644
index 00000000..aa71dca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sin_cos.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* This maps to essentially the same gimple that is generated for
+ gnat.dg/sin_cos.adb, on platforms that use the wraplf variant of
+ Ada.Numerics.Aux_Float. The value of EPSILON is not relevant to
+ the test, but the test must be there to keep the conversions in
+ different BBs long enough to trigger the problem that prevented the
+ sincos optimization, because the arguments passed to sin and cos
+ didn't get unified into a single SSA_NAME in time for sincos. */
+
+#include <math.h>
+
+#define EPSILON 3.4526697709225118160247802734375e-4
+
+static float my_sinf(float x) {
+ return (float) sin ((double) x);
+}
+
+static float wrap_sinf(float x) {
+ if (fabs (x) < EPSILON)
+ return 0;
+ return my_sinf (x);
+}
+
+static float my_cosf(float x) {
+ return (float) cos ((double) x);
+}
+
+static float wrap_cosf(float x) {
+ if (fabs (x) < EPSILON)
+ return 1;
+ return my_cosf (x);
+}
+
+float my_sin_cos(float x, float *s, float *c) {
+ *s = wrap_sinf (x);
+ *c = wrap_cosf (x);
+}
+
+/* { dg-final { scan-assembler "sincos\|cexp" { target *-linux-gnu* *-w64-mingw* *-*-vxworks* } } } */
diff --git a/gcc/testsuite/gnat.dg/sin_cos.adb b/gcc/testsuite/gnat.dg/sin_cos.adb
new file mode 100644
index 00000000..6e18df9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sin_cos.adb
@@ -0,0 +1,14 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -gnatn" }
+
+with Ada.Numerics.Elementary_Functions;
+use Ada.Numerics.Elementary_Functions;
+package body Sin_Cos is
+ procedure Sin_Cos (Angle : T; SinA, CosA : out T) is
+ begin
+ SinA := Sin (Angle);
+ CosA := Cos (Angle);
+ end;
+end Sin_Cos;
+
+-- { dg-final { scan-assembler "sincos\|cexp" { target *-linux-gnu* *-w64-mingw* *-*-vxworks* } } }
diff --git a/gcc/testsuite/gnat.dg/sin_cos.ads b/gcc/testsuite/gnat.dg/sin_cos.ads
new file mode 100644
index 00000000..a0eff3d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sin_cos.ads
@@ -0,0 +1,4 @@
+package Sin_Cos is
+ subtype T is Float;
+ procedure Sin_Cos (Angle : T; SinA, CosA : out T);
+end Sin_Cos;
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 90dfb98..a32f5ca 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -186,7 +186,11 @@ static struct
static struct
{
/* Number of cexpi calls inserted. */
- int inserted;
+ int sincos_inserted;
+
+ /* Number of conversions inserted. */
+ int conv_inserted;
+
} sincos_stats;
static struct
@@ -1106,7 +1110,7 @@ make_pass_cse_reciprocals (gcc::context *ctxt)
statements in the vector. */
static bool
-maybe_record_sincos (vec<gimple *> *stmts,
+maybe_record_stmt (vec<gimple *> *stmts,
basic_block *top_bb, gimple *use_stmt)
{
basic_block use_bb = gimple_bb (use_stmt);
@@ -1126,6 +1130,103 @@ maybe_record_sincos (vec<gimple *> *stmts,
return true;
}
+/* If NAME is the result of a type conversion, look for other
+ conversions from the same source to the same type and CSE them.
+ Replace results of conversions in sin, cos and cexpi calls with the
+ CSEd SSA_NAME. Return a SSA_NAME that holds the result of the
+ conversion to be used instead of NAME. */
+
+static tree
+execute_cse_conv_1 (tree name)
+{
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ return name;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+
+ if (!gimple_assign_cast_p (def_stmt))
+ return name;
+
+ tree src = gimple_assign_rhs1 (def_stmt);
+ int count = 0;
+ imm_use_iterator use_iter;
+ gimple *use_stmt;
+ auto_vec<gimple *> stmts;
+ basic_block top_bb = NULL;
+
+ /* Record equivalent conversions from the same source. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, src)
+ {
+ if (!gimple_assign_cast_p (use_stmt))
+ continue;
+
+ if (!types_compatible_p (TREE_TYPE (name),
+ TREE_TYPE (gimple_assign_lhs (use_stmt))))
+ continue;
+
+ gcc_checking_assert (gimple_assign_rhs1 (use_stmt)
+ == gimple_assign_rhs1 (def_stmt));
+
+ if (maybe_record_stmt (&stmts, &top_bb, use_stmt))
+ count++;
+ }
+
+ if (count <= 1)
+ return name;
+
+ /* Build and insert a new conversion. */
+ name = make_temp_ssa_name (TREE_TYPE (name), def_stmt, "convtmp");
+ gimple *stmt = gimple_build_assign (name,
+ gimple_assign_rhs_code (def_stmt),
+ gimple_assign_rhs1 (def_stmt));
+
+ gimple_stmt_iterator gsi;
+ if (!SSA_NAME_IS_DEFAULT_DEF (name)
+ && gimple_code (def_stmt) != GIMPLE_PHI
+ && gimple_bb (def_stmt) == top_bb)
+ gsi = gsi_for_stmt (def_stmt);
+ else
+ gsi = gsi_after_labels (top_bb);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ update_stmt (stmt);
+ sincos_stats.conv_inserted++;
+
+ /* And adjust the recorded old conversion sites. */
+ for (int i = 0; stmts.iterate (i, &use_stmt); ++i)
+ {
+ tree lhs = gimple_assign_lhs (use_stmt);
+ gimple_assign_set_rhs1 (use_stmt, name);
+ gimple_assign_set_rhs_code (use_stmt, SSA_NAME);
+ update_stmt (use_stmt);
+
+ /* Replace uses of LHS with NAME in sin, cos and cexpi calls
+ right away, so that we can recognize them as taking the same
+ arguments. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, lhs)
+ {
+ if (gimple_code (use_stmt) != GIMPLE_CALL
+ || !gimple_call_lhs (use_stmt))
+ continue;
+
+ switch (gimple_call_combined_fn (use_stmt))
+ {
+ CASE_CFN_COS:
+ CASE_CFN_SIN:
+ CASE_CFN_CEXPI:
+ gcc_checking_assert (gimple_call_arg (use_stmt, 0) == lhs);
+ gimple_call_set_arg (use_stmt, 0, name);
+ update_stmt (use_stmt);
+ break;
+
+ default:
+ continue;
+ }
+ }
+ }
+
+ return name;
+}
+
/* Look for sin, cos and cexpi calls with the same argument NAME and
create a single call to cexpi CSEing the result in this case.
We first walk over all immediate uses of the argument collecting
@@ -1147,6 +1248,8 @@ execute_cse_sincos_1 (tree name)
int i;
bool cfg_changed = false;
+ name = execute_cse_conv_1 (name);
+
FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, name)
{
if (gimple_code (use_stmt) != GIMPLE_CALL
@@ -1156,15 +1259,15 @@ execute_cse_sincos_1 (tree name)
switch (gimple_call_combined_fn (use_stmt))
{
CASE_CFN_COS:
- seen_cos |= maybe_record_sincos (&stmts, &top_bb, use_stmt) ? 1 : 0;
+ seen_cos |= maybe_record_stmt (&stmts, &top_bb, use_stmt) ? 1 : 0;
break;
CASE_CFN_SIN:
- seen_sin |= maybe_record_sincos (&stmts, &top_bb, use_stmt) ? 1 : 0;
+ seen_sin |= maybe_record_stmt (&stmts, &top_bb, use_stmt) ? 1 : 0;
break;
CASE_CFN_CEXPI:
- seen_cexpi |= maybe_record_sincos (&stmts, &top_bb, use_stmt) ? 1 : 0;
+ seen_cexpi |= maybe_record_stmt (&stmts, &top_bb, use_stmt) ? 1 : 0;
break;
default:;
@@ -1208,7 +1311,7 @@ execute_cse_sincos_1 (tree name)
gsi = gsi_after_labels (top_bb);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
}
- sincos_stats.inserted++;
+ sincos_stats.sincos_inserted++;
/* And adjust the recorded old call sites. */
for (i = 0; stmts.iterate (i, &use_stmt); ++i)
@@ -2295,7 +2398,9 @@ pass_cse_sincos::execute (function *fun)
}
statistics_counter_event (fun, "sincos statements inserted",
- sincos_stats.inserted);
+ sincos_stats.sincos_inserted);
+ statistics_counter_event (fun, "conv statements inserted",
+ sincos_stats.conv_inserted);
return cfg_changed ? TODO_cleanup_cfg : 0;
}
--
Alexandre Oliva, happy hacker
https://FSFLA.org/blogs/lxo/
Free Software Activist
GNU Toolchain Engineer
next prev parent reply other threads:[~2020-10-27 5:32 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-18 20:28 [Ada,FYI] revamp ada.numerics.aux Alexandre Oliva
2020-10-19 9:46 ` Andreas Schwab
2020-10-19 11:52 ` Alexandre Oliva
2020-10-20 8:26 ` Rainer Orth
2020-10-22 5:15 ` Alexandre Oliva
2020-10-23 7:24 ` Iain Sandoe
2020-10-22 5:13 ` Alexandre Oliva
2020-10-22 18:13 ` Eric Botcazou
2020-10-23 9:33 ` Alexandre Oliva
2021-01-13 6:37 ` Sebastian Huber
2021-01-13 16:45 ` Alexandre Oliva
2021-01-13 17:27 ` Sebastian Huber
2021-01-13 18:40 ` Alexandre Oliva
2021-01-21 5:24 ` Sebastian Huber
2021-01-21 9:57 ` Alexandre Oliva
2020-10-22 5:22 ` Alexandre Oliva
2020-10-22 12:04 ` Alexandre Oliva
2020-10-23 14:23 ` move sincos after pre (was: Re: [Ada,FYI] revamp ada.numerics.aux) Alexandre Oliva
2020-10-23 15:05 ` move sincos after pre (was: Re: [Ada, FYI] " Richard Biener
2020-10-27 5:32 ` Alexandre Oliva [this message]
2020-10-27 8:54 ` move sincos after pre Richard Biener
2020-10-28 3:17 ` Alexandre Oliva
2020-10-28 13:01 ` Richard Biener
2020-12-22 22:03 ` make FOR_EACH_IMM_USE_STMT safe for early exits (was: Re: move sincos after pre) Alexandre Oliva
2021-01-04 13:10 ` Richard Biener
2021-01-06 11:34 ` make FOR_EACH_IMM_USE_STMT safe for early exits Alexandre Oliva
2021-01-07 8:41 ` Richard Biener
2021-01-09 20:33 ` Alexandre Oliva
2021-01-11 8:42 ` Richard Biener
2021-01-12 14:29 ` Andrew MacLeod
2020-10-22 5:27 ` [Ada,FYI] revamp ada.numerics.aux Alexandre Oliva
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ora6w8xmi3.fsf@livre.home \
--to=oliva@adacore.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=richard.guenther@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).