widening_mul: Fix up ICE in maybe_optimize_guarding_check [PR126601]

Message ID anGaoDP2vWR6ynsl@tucnak
State New
Headers
Series widening_mul: Fix up ICE in maybe_optimize_guarding_check [PR126601] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply

Commit Message

Jakub Jelinek Aug. 4, 2026, 7:54 a.m. UTC
  Hi!

The following testcase ICEs, because we try to quick_push into an already
full vector.
The caller (match_arith_overflow) has
  auto_vec<gimple *, 8> mul_stmts;
and 0-6 mul_stmts.quick_push (...); calls (none of that in a loop), and then
call to that maybe_optimize_guarding_check function which does one
quick_push, but the function is called in a
  FOR_EACH_IMM_USE_STMT (use_stmt, iter, cast_lhs ? cast_lhs : lhs)
loop, so if we are unlucky  as on the attached testcase, it is called more
than twice and either triggers ICE, or worse with checking disabled buffer
overflow.

The following patch fixes that by using safe_push in that spot instead.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2026-08-04  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/126601
	* tree-ssa-math-opts.cc (maybe_optimize_guarding_check): Use safe_push
	on mul_stmts rather than quick_push.

	* gcc.dg/tree-ssa/pr126601.c: New test.


	Jakub
  

Comments

Richard Biener Aug. 4, 2026, 8:15 a.m. UTC | #1
> Am 04.08.2026 um 10:06 schrieb Jakub Jelinek <jakub@redhat.com>:
> 
> Hi!
> 
> The following testcase ICEs, because we try to quick_push into an already
> full vector.
> The caller (match_arith_overflow) has
>  auto_vec<gimple *, 8> mul_stmts;
> and 0-6 mul_stmts.quick_push (...); calls (none of that in a loop), and then
> call to that maybe_optimize_guarding_check function which does one
> quick_push, but the function is called in a
>  FOR_EACH_IMM_USE_STMT (use_stmt, iter, cast_lhs ? cast_lhs : lhs)
> loop, so if we are unlucky  as on the attached testcase, it is called more
> than twice and either triggers ICE, or worse with checking disabled buffer
> overflow.
> 
> The following patch fixes that by using safe_push in that spot instead.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Thanks,
Richard 

> 2026-08-04  Jakub Jelinek  <jakub@redhat.com>
> 
>    PR tree-optimization/126601
>    * tree-ssa-math-opts.cc (maybe_optimize_guarding_check): Use safe_push
>    on mul_stmts rather than quick_push.
> 
>    * gcc.dg/tree-ssa/pr126601.c: New test.
> 
> --- gcc/tree-ssa-math-opts.cc.jj    2026-07-10 08:56:56.539168444 +0200
> +++ gcc/tree-ssa-math-opts.cc    2026-08-03 19:12:11.521252398 +0200
> @@ -3761,7 +3761,7 @@ maybe_optimize_guarding_check (vec<gimpl
>    return;
>     }
>   gimple_stmt_iterator gsi = gsi_after_labels (bb);
> -  mul_stmts.quick_push (div_stmt);
> +  mul_stmts.safe_push (div_stmt);
>   if (is_gimple_debug (gsi_stmt (gsi)))
>     gsi_next_nondebug (&gsi);
>   unsigned cast_count = 0;
> --- gcc/testsuite/gcc.dg/tree-ssa/pr126601.c.jj    2026-08-03 19:19:15.410107311 +0200
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr126601.c    2026-08-03 19:11:56.848430491 +0200
> @@ -0,0 +1,29 @@
> +/* PR tree-optimization/126601 */
> +/* { dg-do compile } */
> +/* { dg-options "-Os" } */
> +
> +volatile int c[16];
> +
> +[[gnu::noipa]] int
> +foo (unsigned x, unsigned y)
> +{
> +  unsigned r = x * y;
> +  int t = 0;
> +  if (c[0]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[1]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[2]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[3]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[4]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[5]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[6]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[7]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[8]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[9]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[10]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[11]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[12]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[13]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[14]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  if (c[15]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
> +  return t;
> +}
> 
>    Jakub
>
  

Patch

--- gcc/tree-ssa-math-opts.cc.jj	2026-07-10 08:56:56.539168444 +0200
+++ gcc/tree-ssa-math-opts.cc	2026-08-03 19:12:11.521252398 +0200
@@ -3761,7 +3761,7 @@  maybe_optimize_guarding_check (vec<gimpl
 	return;
     }
   gimple_stmt_iterator gsi = gsi_after_labels (bb);
-  mul_stmts.quick_push (div_stmt);
+  mul_stmts.safe_push (div_stmt);
   if (is_gimple_debug (gsi_stmt (gsi)))
     gsi_next_nondebug (&gsi);
   unsigned cast_count = 0;
--- gcc/testsuite/gcc.dg/tree-ssa/pr126601.c.jj	2026-08-03 19:19:15.410107311 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/pr126601.c	2026-08-03 19:11:56.848430491 +0200
@@ -0,0 +1,29 @@ 
+/* PR tree-optimization/126601 */
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+volatile int c[16];
+
+[[gnu::noipa]] int
+foo (unsigned x, unsigned y)
+{
+  unsigned r = x * y;
+  int t = 0;
+  if (c[0]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[1]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[2]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[3]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[4]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[5]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[6]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[7]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[8]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[9]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[10]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[11]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[12]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[13]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[14]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  if (c[15]) { int u = 0; if (x != 0) u = (r / x != y); t += u; }
+  return t;
+}