https://gcc.gnu.org/g:d2cc7decabbd7bb28ed8b08e230c1303b9e1d8bc
commit d2cc7decabbd7bb28ed8b08e230c1303b9e1d8bc Author: Arsen Arsenović <[email protected]> Date: Fri Dec 19 10:33:05 2025 +0000 tree-ssa-math-opts: Fix ICE if vectorizer produces IFN_SIN/COS calls With the following testcase, on AMDGCN with -Ofast: void foo (float* output, float* input) { for (int i = 0; i < 1024 * 1024; i++) { output[i] = __builtin_sinf (input[i]) + __builtin_cosf (input[i]); } } ... the following ICE happens: during GIMPLE pass: sincos test.cpp: In function 'void foo(float*, float*)': test.cpp:2:1: internal compiler error: Segmentation fault 2 | foo (float* output, float* input) | ^~~ [... snipped ...] 0x17befb8 types_compatible_p(tree_node*, tree_node*) gcc/gimple-expr.h:67 0x17befb8 execute_cse_sincos_1 gcc/tree-ssa-math-opts.cc:1299 0x17befb8 execute gcc/tree-ssa-math-opts.cc:2248 This happens because the vect pass converted the testcase into: vect__4.6_40 = MEM <vector(64) float> [(float *)vectp_input.4_38]; vect__6.8_42 = .COS (vect__4.6_40); vect__5.7_41 = .SIN (vect__4.6_40); vect__8.9_43 = vect__5.7_41 + vect__6.8_42; Then, sincos attempts to find the type of the IFN_SIN/IFN_COS via mathfn_built_in_type. This fails, so the compiler crashes. For these IFNs, their input type is the same as their output type, so we can fall back to that. Note that, currently, GCC can't seem to handle vector sincos/cexpi operations, so any attempt to CSE these will fail quickly after. This patch does not fix that, only the ICE that happens in the attempt. gcc/ChangeLog: * tree-ssa-math-opts.cc (execute_cse_sincos_1): If mathfn_built_in_type fails to determine a type for our operation, presume that it is the same as the input type. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c: New test. * gcc.target/gcn/sincos-ice-on-ifn_sin-call-1.c: New test. (cherry picked from commit bce3ac1019c52c92ff39b4bf963c58fb7e8c4479) Diff: --- .../gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c | 19 +++++++++++++++++++ .../gcc.target/gcn/sincos-ice-on-ifn_sin-call-1.c | 14 ++++++++++++++ gcc/tree-ssa-math-opts.cc | 13 ++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c b/gcc/testsuite/gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c new file mode 100644 index 000000000000..3a8c047502e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O -fgimple" } */ +typedef float V __attribute__ ((vector_size (16))); + +void __GIMPLE (ssa, startwith ("sincos")) +foo (float * output, const float * input) +{ + V a; + V b; + V c; + V d; + + __BB(2): + a = __MEM <const V> (input); + b = .COS (a); + c = .SIN (a); + d = a + b; + return; +} diff --git a/gcc/testsuite/gcc.target/gcn/sincos-ice-on-ifn_sin-call-1.c b/gcc/testsuite/gcc.target/gcn/sincos-ice-on-ifn_sin-call-1.c new file mode 100644 index 000000000000..9a94de7b6aa5 --- /dev/null +++ b/gcc/testsuite/gcc.target/gcn/sincos-ice-on-ifn_sin-call-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Ofast" } */ +#include <math.h> + +/* This test is the original, platform-specific, version of + gcc.dg/tree-ssa/sincos-ice-on-ifn_sin-call.c. */ +void +foo (float output[1024 * 1024], const float input[1024 * 1024]) +{ + int i; + for (i = 0; i < 1024 * 1024; i++) { + output[i] = __builtin_sinf (input[i]) + __builtin_cosf (input[i]); + } +} diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index c3b2ac28e46e..839c5ccbaee4 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -1287,7 +1287,18 @@ execute_cse_sincos_1 (tree name) continue; } - tree t = mathfn_built_in_type (gimple_call_combined_fn (use_stmt)); + auto stmt_cfn = gimple_call_combined_fn (use_stmt); + tree t = mathfn_built_in_type (stmt_cfn); + if (!t) + { + /* It is possible to get IFN_{SIN,COS} calls, for which + mathfn_built_in_type will return NULL. Those are normally only + present for vector operations. We won't be able to CSE those + at the moment. */ + gcc_checking_assert (internal_fn_p (stmt_cfn)); + return false; + } + if (!type) { type = t;
