> -----Original Message-----
> From: Kyrylo Tkachov <[email protected]>
> Sent: Monday, September 21, 2026 5:16 PM
> To: Richard Biener <[email protected]>
> Cc: xiezhiheng <[email protected]>; Tamar Christina
> <[email protected]>; Richard Earnshaw
> <[email protected]>; [email protected]
> Subject: Re: [PATCH] sched: Cap max_lookahead_tries
>
>
>
> > On 21 Sep 2026, at 11:07, Richard Biener <[email protected]> wrote:
> >
> > On Sun, Sep 20, 2026 at 3:51 PM Kyrylo Tkachov <[email protected]> wrote:
> >>
> >>
> >>
> >>> On 20 Sep 2026, at 05:43, xiezhiheng <[email protected]> wrote:
> >>>
> >>>> -----Original Message-----
> >>>> From: Richard Biener <[email protected]>
> >>>> Sent: Thursday, September 10, 2026 8:36 PM
> >>>> To: xiezhiheng <[email protected]>
> >>>> Cc: [email protected]
> >>>> Subject: Re: [PATCH] sched: Cap max_lookahead_tries
> >>>>
> >>>> On Thu, Sep 10, 2026 at 2:28 PM xiezhiheng <[email protected]> wrote:
> >>>>>
> >>>>>> -----Original Message-----
> >>>>>> From: Richard Biener <[email protected]>
> >>>>>> Sent: Thursday, September 10, 2026 5:51 PM
> >>>>>> To: xiezhiheng <[email protected]>
> >>>>>> Cc: [email protected]
> >>>>>> Subject: Re: [PATCH] sched: Cap max_lookahead_tries
> >>>>>>
> >>>>>> On Thu, Sep 10, 2026 at 10:22 AM xiezhiheng <[email protected]>
> >>>>>> wrote:
> >>>>>>>
> >>>>>>> In the AArch64 backend, dfa_lookahead generally returns issue_rate,
> >>>>>>> so max_lookahead_tries is set to 100 * issue_rate ** issue_rate.
> >>>>>>> As issue_rate values for modern AArch64 cores increase, this can
> >>>>>>> become
> >>>>>>> very large. For example, the hip12 core has an issue_rate of 8, which
> >>>>>>> makes max_lookahead_tries 1,677,721,600 and causes very long compile
> >>>>>>> times.
> >>>>>>> Another example is Cortex-X925, whose issue_rate is 10,
> >>>>>>> this causes an overflow in the computation, and max_lookahead_tries
> >>>>>>> ends up
> >>>>>>> being 0. Therefore, this patch caps max_lookahead_tries at 1,000,000.
> >>>>>>> Not sure whether this value is appropriate, any comments?
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> With issue_rate values on modern cores continuing to increase,
> >>>>>>> max_lookahead_tries grows exponentially. Cap max_lookahead_tries
> >>>>>>> to avoid excessively long compile times.
> >>>>>>>
> >>>>>>> Bootstrapped and tested on aarch64-linux-gnu and x86_64-linux-gnu, no
> >>>>>>> regression.
> >>>>>>
> >>>>>> ISTR seeing similar things in a bugzilla when x86 bumped issue_rate
> >>>>>> for some cores.
> >>>>>> There's some analysis in the bug:
> >>>>>>
> >>>>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119010
> >>>>>
> >>>>> Thanks for the info! So maybe the root cause is that some instructions
> >>>>> are
> >>>>> missing reservations? I'll continue investigating in that direction.
> >>>
> >>> Hi aarch64 port maintainers,
> >>>
> >>> I have a few questions I'd like to ask. After some analysis, I found that
> >>> when the first loop in max_issue reaches max_lookahead_tries, the state
> >>> is as follows:
> >>>
> >>> ;; max_issue among 17 insns: 500:351:prio=0 499:350:prio=1
> >>> 345:333:prio=1 349:253:prio=1
> 341:251:prio=1 338:250:prio=1 253:262:prio=4 266:244:prio=4
> 264:243:prio=4 254:240:prio=4 249:236:prio=4
> 247:235:prio=4 238:258:prio=5 232:228:prio=5 234:225:prio=5
> 215:229:prio=5 221:217:prio=5
> >>>
> >>> ;; | 500 | 0 | x23=x23+0xa8 ca57_sx1|ca57_sx2
> >>> ;; | 499 | 1 | {cc=cmp(x26-0x1,0);x26=x26-0x1;} ca57_sx1|ca57_sx2
> >>> ;; | 345 | 1 | x3=x19+[176, 176] ca57_sx1|ca57_sx2
> >>> ;; | 349 | 1 | x1=x19+[208, 208] ca57_sx1|ca57_sx2
> >>> ;; | 341 | 1 | x5=x19+[144, 144] ca57_sx1|ca57_sx2
> >>> ;; | 338 | 1 | x6=x19+[128, 128] ca57_sx1|ca57_sx2
> >>> ;; | 253 | 4 | v1=v27 0>>const_vector nothing
> >>> ;; | 266 | 4 | v16=v29 0>>const_vector nothing
> >>> ;; | 264 | 4 | v17=v30 0>>const_vector nothing
> >>> ;; | 254 | 4 | v22=v26 0>>const_vector nothing
> >>> ;; | 249 | 4 | v5=v29 0>>const_vector nothing
> >>> ;; | 247 | 4 | v6=v30 0>>const_vector nothing
> >>> ;; | 238 | 5 | v19=v27 0>>const_vector nothing
> >>> ;; | 232 | 5 | v0=v30 0>>const_vector nothing
> >>> ;; | 234 | 5 | v21=v29 0>>const_vector nothing
> >>> ;; | 215 | 5 | x0=x20+[128, 128] ca57_sx1|ca57_sx2
> >>> ;; | 221 | 5 | x2=x20+[176, 176] ca57_sx1|ca57_sx2
> >>>
> >>> (insn 253 245 255 10 (set (reg:VNx2DI 33 v1)
> >>> (lshiftrt:VNx2DI (reg:VNx2DI 59 v27)
> >>> (const_vector:VNx2DI repeat [
> >>> (const_int 48 [0x30])
> >>> ]))) "test.c":11:24 discrim 102400 8708
> >>> {aarch64_vlshrvnx2di3_const}
> >>> (nil))
> >>>
> >>> I found that SVE as a whole does not seem to have any reservations set,
> >>> which leads to a large number of "nothing" entries. This may affect the
> >>> execution time of traditional DFA scheduling. Has this issue been noticed
> >>> before?
> >>> Also, I noticed that dispatch scheduling has been introduced in the
> >>> AArch64 backend. Is this a new solution to the missing SVE reservations?
> >>>
> >>
> >> Yes, this known and (sort of) deliberate. We didn’t want to create a
> >> fine-grained scheduling type classification for SVE types as there
> are a large amount of SVE instructions. For all aarch64 cores where SVE
> performance matters the CPUs are aggressively OoO so we
> don’t have evidence that DFA scheduling would be worth the effort and
> maintenance burden of creating a scheduling type scheme for
> SVE instructions. For some cores like Neoverse V2, Olympus we have taken the
> dispatch scheduling scheme that does not care about the
> DFA type, as you noticed. It uses a much more coarse-grained sve_type to help
> its classification.
> >>
> >> In theory, some of the smaller recent cores have SVE2 may want to do DFA
> >> scheduling, but I guess nobody has considered it valuable
> enough to be worth the effort I described above.
> >
> > But it causes compile-time blow-up for scheduling. So maybe the
> > schedulers behavior for insns w/o reservation
> > should be improved somehow, possibly by not re-scheduling those at all?
> >
>
> I think for aarch64 the simplest workaround would be to treat insns with an
> sve_type (i.e. only used for dispatch-scheduling) as a
> standard basic Neon instruction.
> This is what we did for the armv8.X SIMD instructions in
> config/arm/cortex-a57.md (which is the basis for most DFA aarch64
> descriptions):
> ;; If it doesn't match any of the above that we want to treat specially but is
> ;; still a NEON type, treat it as a basic NEON type. This is better than
> ;; dropping it on the floor and making no assumptions about it whatsoever.
>
> (eq_attr "is_neon_type" "yes”)
> (const_string "neon_arith_basic")]
>
Sorry for the late reply, I was on vacation. Treating all SVE instructions as
basic NEON instructions
should help me solve the problem. The patch would roughly be as follows,
Reuse sve_type, but only use it to identify whether an instruction is an SVE
instruction, and map
it to neon_arith_basic. How does this approach sound?
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 7c8915ec389..459bc7f212d 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -704,6 +704,26 @@ (define_attr "sve_type"
sve_crypto_sha3"
(const_string "none"))
+(define_attr "is_sve_type" "yes,no"
+ (if_then_else (eq_attr "sve_type"
+ "none,\
+ sve_pred_logical,sve_pred_cnt_ctrl,sve_pred_cnt_scalar,sve_pred_misc,\
+ sve_pred_vec,\
+ sve_fp_arith,sve_fp_mul,sve_fp_assoc_add,sve_fp_cmp,sve_fp_cvt,sve_fp_log,\
+ sve_fp_exp,sve_fp_div,sve_fp_sqrt,sve_fp_reduc,sve_fp_misc,\
+ sve_int_general,sve_int_shift,sve_int_mul,sve_int_dot,sve_int_cmp_set,\
+ sve_int_extend,sve_int_extract,sve_int_cvt,sve_int_div,sve_int_index,\
+ sve_int_match,sve_int_recip_est,sve_int_reduc,sve_int_accum,\
+ sve_int_pmul,sve_int_bit_perm,\
+ sve_load_pred,sve_load_1reg,sve_load_2reg,sve_load_3reg,sve_load_4reg,\
+ sve_gatherload_32,sve_gatherload_64,\
+ sve_store_pred,sve_store_1reg,sve_store_2reg,sve_store_3reg,sve_store_4reg,\
+ sve_scatterstore_32,sve_scatterstore_64,\
+ sve_ffr,\
+ sve_crypto_sha3")
+ (const_string "yes")
+ (const_string "no")))
+
;; -------------------------------------------------------------------
;; Pipeline descriptions and scheduling
;; -------------------------------------------------------------------
diff --git a/gcc/config/arm/cortex-a57.md b/gcc/config/arm/cortex-a57.md
index 07003422e01..ef3334a8e99 100644
--- a/gcc/config/arm/cortex-a57.md
+++ b/gcc/config/arm/cortex-a57.md
@@ -241,6 +241,9 @@ (define_attr "cortex_a57_neon_type"
;; still a NEON type, treat it as a basic NEON type. This is better than
;; dropping it on the floor and making no assumptions about it whatsoever.
(eq_attr "is_neon_type" "yes")
+ (const_string "neon_arith_basic")
+
+ (eq_attr "is_sve_type" "yes")
(const_string "neon_arith_basic")]
(const_string "unknown")))
One more thing: I will later submit the pipeline for the hip12 core.
Would you recommend doing this only in hip12.md, or enabling it
in the widely used cortex-a57.md/cortex-a53.md as well?
Thanks,
Xie Zhiheng
>
> >> Thanks,
> >> Kyrill
> >>
> >>
> >>> Many thanks!
> >>> Xie Zhiheng
> >>>
> >>>
> >>>>
> >>>> I think so.
> >>>>
> >>>>> Also, the overflow in the max_lookahead_tries calculation is still
> >>>>> there.
> >>>>> Maybe I should send a separate patch to change its type from int to
> >>>>> int64_t?
> >>>>
> >>>> Yes, I think that makes sense.
> >>>>
> >>>> Richard.
> >>>>
> >>>>>
> >>>>>
> >>>>>>
> >>>>>>> gcc/ChangeLog:
> >>>>>>>
> >>>>>>> * haifa-sched.cc (max_issue): cap max_lookahead_tries
> >>>>>>> ---
> >>>>>>> gcc/haifa-sched.cc | 5 +++--
> >>>>>>> 1 file changed, 3 insertions(+), 2 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/gcc/haifa-sched.cc b/gcc/haifa-sched.cc
> >>>>>>> index 879749e9785..7f3fd5b496a 100644
> >>>>>>> --- a/gcc/haifa-sched.cc
> >>>>>>> +++ b/gcc/haifa-sched.cc
> >>>>>>> @@ -5956,9 +5956,10 @@ max_issue (struct ready_list *ready, int
> >>>>>>> privileged_n, state_t state,
> >>>>>>> /* Init MAX_LOOKAHEAD_TRIES. */
> >>>>>>> if (max_lookahead_tries == 0)
> >>>>>>> {
> >>>>>>> - max_lookahead_tries = 100;
> >>>>>>> + int64_t max_tries = 100;
> >>>>>>> for (i = 0; i < issue_rate; i++)
> >>>>>>> - max_lookahead_tries *= dfa_lookahead;
> >>>>>>> + max_tries *= dfa_lookahead;
> >>>>>>> + max_lookahead_tries = MIN (max_tries, (int64_t) 1000000);
> >>>>>>> }
> >>>>>>>
> >>>>>>> /* Init max_points. */
>