This patch doesn't work. But the first one is okay, despite that it pessimizes sin and cos calls by skipping the optimization pass.
Sep 18, 2025 11:04:16 PM Peter Damianov <peter0...@disroot.org>: > In my previous patch, I disabled pass_cse_sincos for -fmath-errno. This was > because it was causing ICEs when trying to replace sin/cos calls, and more > importantly, the pass was transforming sin+cos to cexpi which doesn't set > errno like sin/cos do. The optimization is valid when either: > 1. We don't care about errno (-fno-math-errno), or > 2. We can use sincos() which does set errno like sin/cos do > > This patch fixes the ICE and implements a different optimization strategy > that preserves errno semantics by directly calling sincos when available, > and only falling back to cexpi when errno doesn't matter. The ICEs are > resolved by properly unlinking VDEFs before statement replacement. > > gcc/ChangeLog: > > PR tree-optimization/80042 > * tree-ssa-math-opts.cc (execute_cse_sincos_1): Optimize to sincos > for -fmath-errno. Fix ICE with unlink_stmt_vdef before gsi_replace. > (pass_cse_sincos::execute): Remove errno check to allow proper > optimization in execute_cse_sincos_1. > > gcc/testsuite/ChangeLog: > > PR tree-optimization/80042 > * gcc.dg/pr80042.c: New test. > --- > gcc/testsuite/gcc.dg/pr80042.c | 71 +++++++++++++++++++++ > gcc/tree-ssa-math-opts.cc | 110 ++++++++++++++++++++++++++------- > 2 files changed, 159 insertions(+), 22 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/pr80042.c > > diff --git a/gcc/testsuite/gcc.dg/pr80042.c b/gcc/testsuite/gcc.dg/pr80042.c > new file mode 100644 > index 00000000000..7843604d23c > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr80042.c > @@ -0,0 +1,71 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -lm -fmath-errno" } */ > + > +#include <errno.h> > + > +void test_double(void) > +{ > + double s, c; > + > + errno = 0; > + s = __builtin_sin(__builtin_inf()); > + if (errno != EDOM) > + __builtin_abort(); > + > + errno = 0; > + c = __builtin_cos(__builtin_inf()); > + if (errno != EDOM) > + __builtin_abort(); > + > + errno = 0; > + __builtin_sincos(__builtin_inf(), &s, &c); > + if (errno != EDOM) > + __builtin_abort(); > +} > + > +void test_float(void) > +{ > + float s, c; > + > + errno = 0; > + s = __builtin_sinf(__builtin_inff()); > + if (errno != EDOM) > + __builtin_abort(); > + > + errno = 0; > + c = __builtin_cosf(__builtin_inff()); > + if (errno != EDOM) > + __builtin_abort(); > + > + errno = 0; > + __builtin_sincosf(__builtin_inff(), &s, &c); > + if (errno != EDOM) > + __builtin_abort(); > +} > + > +void test_longdouble(void) > +{ > + long double s, c; > + > + errno = 0; > + s = __builtin_sinl(__builtin_infl()); > + if (errno != EDOM) > + __builtin_abort(); > + > + errno = 0; > + c = __builtin_cosl(__builtin_infl()); > + if (errno != EDOM) > + __builtin_abort(); > + > + errno = 0; > + __builtin_sincosl(__builtin_infl(), &s, &c); > + if (errno != EDOM) > + __builtin_abort(); > +} > + > +int main(void) > +{ > + test_double(); > + test_float(); > + test_longdouble(); > +} > \ No newline at end of file > diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc > index c736709158f..4076bcf55d5 100644 > --- a/gcc/tree-ssa-math-opts.cc > +++ b/gcc/tree-ssa-math-opts.cc > @@ -1253,7 +1253,7 @@ execute_cse_sincos_1 (tree name) > { > gimple_stmt_iterator gsi; > imm_use_iterator use_iter; > - tree fndecl, res, type = NULL_TREE; > + tree res, type = NULL_TREE; > gimple *def_stmt, *use_stmt, *stmt; > int seen_cos = 0, seen_sin = 0, seen_cexpi = 0; > auto_vec<gimple *> stmts; > @@ -1302,27 +1302,97 @@ execute_cse_sincos_1 (tree name) > if (seen_cos + seen_sin + seen_cexpi <= 1) > return false; > > - /* Simply insert cexpi at the beginning of top_bb but not earlier than > - the name def statement. */ > - fndecl = mathfn_built_in (type, BUILT_IN_CEXPI); > - if (!fndecl) > - return false; > - stmt = gimple_build_call (fndecl, 1, name); > - res = make_temp_ssa_name (TREE_TYPE (TREE_TYPE (fndecl)), stmt, > "sincostmp"); > - gimple_call_set_lhs (stmt, res); > + machine_mode mode = TYPE_MODE (type); > + tree sincos_fndecl = builtin_decl_explicit (BUILT_IN_SINCOS); > + bool can_use_sincos = sincos_fndecl > + && (optab_handler (sincos_optab, mode) > + != CODE_FOR_nothing > + || targetm.libc_has_function (function_sincos, > + type)); > > - def_stmt = SSA_NAME_DEF_STMT (name); > - if (!SSA_NAME_IS_DEFAULT_DEF (name) > - && gimple_code (def_stmt) != GIMPLE_PHI > - && gimple_bb (def_stmt) == top_bb) > + if (flag_errno_math && (seen_sin || seen_cos) && !can_use_sincos) > { > - gsi = gsi_for_stmt (def_stmt); > - gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); > + /* We cannot rewrite sin and cos calls to cexpi if we have > + flag_errno_math because cexpi does not set errno. */ > + return false; > + } > + > + if (can_use_sincos) > + { > + /* Generate sincos call if sincos is available. */ > + > + tree complex_type = build_complex_type (type); > + > + /* Create temporary variables for sin and cos results. */ > + tree sin_result = create_tmp_var (type, "sincos_sin"); > + tree cos_result = create_tmp_var (type, "sincos_cos"); > + > + /* Create addresses to the temporary variables. */ > + tree sin_addr = build_fold_addr_expr (sin_result); > + tree cos_addr = build_fold_addr_expr (cos_result); > + > + /* Generate sincos (angle, &sin_result, &cos_result) call. */ > + stmt = gimple_build_call (sincos_fndecl, 3, name, sin_addr, cos_addr); > + > + /* Insert the sincos call. */ > + def_stmt = SSA_NAME_DEF_STMT (name); > + 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); > + gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); > + } > + else > + { > + gsi = gsi_after_labels (top_bb); > + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); > + } > + > + /* Create SSA names for the results and load them from temporaries. */ > + tree sin_ssa = make_ssa_name (type); > + tree cos_ssa = make_ssa_name (type); > + > + gimple *sin_load = gimple_build_assign (sin_ssa, sin_result); > + gimple *cos_load = gimple_build_assign (cos_ssa, cos_result); > + > + gsi_insert_after (&gsi, sin_load, GSI_NEW_STMT); > + gsi_insert_after (&gsi, cos_load, GSI_NEW_STMT); > + > + /* Create a complex number from sin and cos results so the replacement > + logic can extract them using REALPART_EXPR (cos) and > + IMAGPART_EXPR (sin). */ > + res = make_temp_ssa_name (complex_type, NULL, "sincostmp"); > + gimple *complex_stmt = gimple_build_assign (res, COMPLEX_EXPR, cos_ssa, > + sin_ssa); > + gsi_insert_after (&gsi, complex_stmt, GSI_NEW_STMT); > } > else > { > - gsi = gsi_after_labels (top_bb); > - gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); > + cexpi_fndecl = mathfn_built_in (type, BUILT_IN_CEXPI); > + if (!cexpi_fndecl) > + return false; > + > + /* Generate a call to cexpi instead - this is fine if we don't care > + about errno. */ > + stmt = gimple_build_call (cexpi_fndecl, 1, name); > + res = make_temp_ssa_name (TREE_TYPE (TREE_TYPE (cexpi_fndecl)), stmt, > + "sincostmp"); > + gimple_call_set_lhs (stmt, res); > + > + def_stmt = SSA_NAME_DEF_STMT (name); > + 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); > + gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); > + } > + else > + { > + gsi = gsi_after_labels (top_bb); > + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); > + } > } > sincos_stats.inserted++; > > @@ -1353,6 +1423,7 @@ execute_cse_sincos_1 (tree name) > stmt = gimple_build_assign (gimple_call_lhs (use_stmt), rhs); > > gsi = gsi_for_stmt (use_stmt); > + unlink_stmt_vdef (use_stmt); > gsi_replace (&gsi, stmt, true); > if (gimple_purge_dead_eh_edges (gimple_bb (stmt))) > cfg_changed = true; > @@ -2239,11 +2310,6 @@ pass_cse_sincos::execute (function *fun) > { > CASE_CFN_COS: > CASE_CFN_SIN: > - /* Don't optimize sin/cos to cexpi if errno semantics matter, > - since cexpi doesn't set errno like sin/cos can. */ > - if (flag_errno_math) > - break; > - gcc_fallthrough (); > CASE_CFN_CEXPI: > arg = gimple_call_arg (stmt, 0); > /* Make sure we have either sincos or cexp. */ > -- > 2.39.5