Hi,
To scheduler / global maintainers -- I've reviewed the scheduler part of this
(haifa-sched.cc (model_recompute)), and it looks good to me.
However, note that Patchwork detected a build failure [1] in insn-extract.cc:
| # 00:06:46 insn-extract.cc:21:24: error: cannot convert
‘operand_vec<rtx_def*>’ {aka ‘auto_vec<rtx_def*, 30>’} to
‘rtx_def**’ in initialization
| # 00:06:46 insn-extract.cc:22:29: error: cannot convert
‘operand_vec<rtx_def**>’ {aka ‘auto_vec<rtx_def**, 30>’} to
‘rtx_def***’ in initialization
| # 00:06:47 make[2]: *** [Makefile:1219: insn-extract.o] Error 1
| # 00:06:47 make[1]: *** [Makefile:4774: all-gcc] Error 2
| # 00:06:47 make: *** [Makefile:1099: all] Error 2
[1]
https://patchwork.sourceware.org/project/gcc/patch/bmm.hlnmhdo3u6.gcc.gcc.feedable.223....@forge-stage.sourceware.org/
--
Maxim Kuvyrkov
Garden City Compilers
> On Aug 25, 2026, at 11:24, feedable via Sourceware Forge
> <[email protected]> wrote:
>
> From: feedable <[email protected]>
>
> All of GCC's RTL machinery currently expects no instruction to exceed
> MAX_RECOG_OPERANDS (which is 30). This is fine for most targets, since
> they don't usually have more than 30 things of note anyway, and there
> are not many ways to run out of operands in an asm stmt. However, it may
> still happen, and there are targets now that will want an arbitrary
> amount of operands (e.g. wasm's call family of insns).
>
> For that reason, this patch seeks to remove this limit, primarily by
> replacing instances of static C arrays of bound MAX_RECOG_OPERANDS by
> small vectors of the same bound, but which can allocate more if there
> are more operands.
>
> This patch currently does not provide a way to actually define insn
> patterns with an arbitrary number of operands, nor does it touch the
> machine description infrastructure, so the only observable effect is
> asm_operands now having an arbitrary amount of operands.
>
> Many functions take in a pair of pointer+size to pass an array, this
> patch replaces that by array_slice parameters.
>
> LRA also makes use of -1-terminated arrays, mostly because it's more
> convenient than maintaining a separate array of sizes for its arrays
> of arrays. This is mostly redundant now, since the arrays-of-arrays
> are now handled by vectors-of-vectors. The relevant functions now
> accept array_slice parameters instead.
>
> IRA has a global bitmap for all insns and operands to mark scratches,
> and it relies on a fixed number of operands to avoid overlap. There
> isn't an easy way to convert that to support an arbitrary operand
> count, so a supplemental one is added to handle operands over the
> limit.
>
> gcc/ChangeLog:
>
...
> * haifa-sched.cc (model_recompute): Replace arrays by
> operand_vec.
>
...
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/pr61692.c: Mark >30 ops as allowed.
> ---
> gcc/cfgexpand.cc | 21 +--
> gcc/cse.cc | 44 ++---
> gcc/emit-rtl.cc | 28 ++-
> gcc/final.cc | 74 ++++----
> gcc/genattrtab.cc | 2 +-
> gcc/haifa-sched.cc | 18 +-
> gcc/ira-conflicts.cc | 4 +-
> gcc/ira-costs.cc | 77 +++++---
> gcc/ira-int.h | 6 +-
> gcc/ira.cc | 39 +++-
> gcc/ira.h | 5 +-
> gcc/loop-invariant.cc | 13 +-
> gcc/lra-constraints.cc | 315 ++++++++++++++++-----------------
> gcc/lra-eliminations.cc | 4 +-
> gcc/lra-int.h | 5 +-
> gcc/lra.cc | 46 ++---
> gcc/postreload.cc | 10 +-
> gcc/recog.cc | 86 ++++-----
> gcc/recog.h | 40 ++++-
> gcc/regrename.cc | 30 ++--
> gcc/reload.cc | 4 +-
> gcc/rtl.h | 7 +-
> gcc/testsuite/gcc.dg/pr61692.c | 10 +-
> gcc/varasm.cc | 8 +-
> 24 files changed, 466 insertions(+), 430 deletions(-)
>
>
...
> diff --git a/gcc/haifa-sched.cc b/gcc/haifa-sched.cc
> index 879749e9785d1..28d20bdc55999 100644
> --- a/gcc/haifa-sched.cc
> +++ b/gcc/haifa-sched.cc
> @@ -2116,15 +2116,16 @@ model_update_pressure (struct model_pressure_group
> *group,
> static void
> model_recompute (rtx_insn *insn)
> {
> - struct {
> + struct uses_t {
> int last_use;
> int regno;
> - } uses[FIRST_PSEUDO_REGISTER + MAX_RECOG_OPERANDS];
> + };
> + auto_vec<uses_t, FIRST_PSEUDO_REGISTER + MAX_RECOG_OPERANDS> uses;
> struct reg_use_data *use;
> struct reg_pressure_data *reg_pressure;
> int delta[N_REG_CLASSES];
> int pci, point, mix, new_last, cl, ref_pressure, queue;
> - unsigned int i, num_uses, num_pending_births;
> + unsigned int i, num_pending_births;
> bool print_p;
>
> /* The destinations of INSN were previously live from POINT onwards, but are
> @@ -2141,7 +2142,6 @@ model_recompute (rtx_insn *insn)
> before POINT. Adjust DELTA so that it represents the effect of
> this change after POINT - 1. Set NUM_PENDING_BIRTHS to the number of
> registers that will be born in the range [model_curr_point, POINT). */
> - num_uses = 0;
> num_pending_births = 0;
> bitmap_clear (tmp_bitmap);
> for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
> @@ -2155,12 +2155,9 @@ model_recompute (rtx_insn *insn)
> currently assumed to be live. */
> && bitmap_bit_p (curr_reg_live, use->regno))
> {
> - gcc_assert (num_uses < ARRAY_SIZE (uses));
> - uses[num_uses].last_use = new_last;
> - uses[num_uses].regno = use->regno;
> + uses.safe_push ({new_last, use->regno});
> /* This register is no longer live after POINT - 1. */
> mark_regno_birth_or_death (NULL, delta, use->regno, false);
> - num_uses++;
> if (new_last >= 0)
> num_pending_births++;
> }
> @@ -2190,7 +2187,7 @@ model_recompute (rtx_insn *insn)
> after POINT. Make it describe the effect on the pressure
> before POINT. */
> i = 0;
> - while (i < num_uses)
> + while (i < uses.length ())
> {
> if (uses[i].last_use == point)
> {
> @@ -2199,8 +2196,7 @@ model_recompute (rtx_insn *insn)
> uses[i].regno, true);
>
> /* Remove this use from the array. */
> - uses[i] = uses[num_uses - 1];
> - num_uses--;
> + uses.unordered_remove (i);
> num_pending_births--;
> }
> else