[PATCH] widening_mul: Fix up ICE in maybe_optimize_guarding_check [PR126601]
Jakub Jelinek <[email protected]> Tue, 4 Aug 2026 09:54:08 +0200
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <anGaoDP2vWR6ynsl@tucnak> |
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 <[email protected]> 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