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.
This commit is contained in:
Arsen Arsenović
2025-12-19 10:33:05 +00:00
committed by Arsen Arsenović
parent c3824ad07a
commit bce3ac1019
3 changed files with 45 additions and 1 deletions

View File

@@ -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;
}

View File

@@ -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]);
}
}

View File

@@ -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;