From 3ca220e371ba65fd4be5710579c4891f57797b86 Mon Sep 17 00:00:00 2001 From: Dayuxiaoshui <792179245@qq.com> Date: Fri, 5 Dec 2025 10:54:43 +0000 Subject: [PATCH 1/3] [MetaSchedule] Fix tune_tir crash with ScheduleError in RewriteParallelVectorizeUnroll This patch fixes issue #18423 where meta_schedule.tune_tir crashes during initial population sampling when RewriteParallelVectorizeUnroll postprocessor encounters blocks that violate compact dataflow requirements. The crash occurred when: - A block reads and writes to the same buffer - RewriteParallelVectorizeUnroll tries to parallelize/vectorize these loops - ScheduleError is thrown and propagates through parallel_for_dynamic Solution: - Added exception handling in RewriteParallelVectorizeUnroll::Apply to catch ScheduleError and skip problematic blocks instead of crashing - Added exception handling in ThreadedTraceApply::Apply to catch exceptions from postprocessors and treat them as normal failures This makes the tuning process more robust by gracefully handling schedule errors instead of crashing the entire tuning session. --- .../rewrite_parallel_vectorize_unroll.cc | 39 +++++++++++-------- src/meta_schedule/utils.h | 12 +++++- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc b/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc index d833af614221..eda0fd82cadb 100644 --- a/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc +++ b/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc @@ -425,25 +425,30 @@ class RewriteParallelVectorizeUnrollNode : public PostprocNode { tir::ParsedAnnotation parsed = parsed_root; tir::AdjustParallelVectorize(sch, block_rv, loop_rvs, &parsed); const int loops_num = loop_rvs.size(); - if (parsed.num_parallel_loops == loops_num && parsed.num_vectorize_loops == loops_num) { - // Fuse, split, vectorize and parallelize - tir::RewriteFuseSplitParallelVectorize(sch, &loop_rvs, parsed.max_vectorize_extent); - } else { - // Parallel - if (parsed.num_parallel_loops > 0) { - tir::RewriteParallel(sch, parsed.num_parallel_loops, &loop_rvs); + try { + if (parsed.num_parallel_loops == loops_num && parsed.num_vectorize_loops == loops_num) { + // Fuse, split, vectorize and parallelize + tir::RewriteFuseSplitParallelVectorize(sch, &loop_rvs, parsed.max_vectorize_extent); + } else { + // Parallel + if (parsed.num_parallel_loops > 0) { + tir::RewriteParallel(sch, parsed.num_parallel_loops, &loop_rvs); + } + // Vectorize + if (parsed.num_vectorize_loops > 0) { + tir::RewriteVectorize(sch, parsed.num_vectorize_loops, &loop_rvs); + } } - // Vectorize - if (parsed.num_vectorize_loops > 0) { - tir::RewriteVectorize(sch, parsed.num_vectorize_loops, &loop_rvs); + // AutoUnroll + if (parsed.unroll_explicit != -1 || parsed.unroll_implicit != -1) { + ICHECK(parsed.unroll_explicit == -1 || parsed.unroll_implicit == -1); + int unroll_explicit = parsed.unroll_explicit != -1; + int max_step = parsed.unroll_explicit + parsed.unroll_implicit + 1; + tir::RewriteUnroll(sch, unroll_explicit, max_step, block_rv, loop_rvs[0]); } - } - // AutoUnroll - if (parsed.unroll_explicit != -1 || parsed.unroll_implicit != -1) { - ICHECK(parsed.unroll_explicit == -1 || parsed.unroll_implicit == -1); - int unroll_explicit = parsed.unroll_explicit != -1; - int max_step = parsed.unroll_explicit + parsed.unroll_implicit + 1; - tir::RewriteUnroll(sch, unroll_explicit, max_step, block_rv, loop_rvs[0]); + } catch (const tir::ScheduleError& e) { + DLOG(WARNING) << "Failed to apply parallelization/vectorization: " << e.what(); + continue; } } } diff --git a/src/meta_schedule/utils.h b/src/meta_schedule/utils.h index ee94b1d2ab5e..57c9d17c4f07 100644 --- a/src/meta_schedule/utils.h +++ b/src/meta_schedule/utils.h @@ -334,7 +334,17 @@ struct ThreadedTraceApply { for (int i = 0; i < n_; ++i) { Item& item = items_[i]; - if (!item.postproc->Apply(sch)) { + try { + if (!item.postproc->Apply(sch)) { + item.fail_counter++; + return std::nullopt; + } + } catch (const tir::ScheduleError& e) { + DLOG(WARNING) << "Postproc #" << i << " failed with ScheduleError: " << e.what(); + item.fail_counter++; + return std::nullopt; + } catch (const std::exception& e) { + DLOG(WARNING) << "Postproc #" << i << " failed with exception: " << e.what(); item.fail_counter++; return std::nullopt; } From 30df64bcdc46f14b7d6a9a84cc418420435f4f8f Mon Sep 17 00:00:00 2001 From: Dayuxiaoshui <792179245@qq.com> Date: Fri, 5 Dec 2025 11:03:33 +0000 Subject: [PATCH 2/3] Refactor: eliminate duplicate failure handling logic in ThreadedTraceApply --- src/meta_schedule/utils.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/meta_schedule/utils.h b/src/meta_schedule/utils.h index 57c9d17c4f07..96b18fb7e755 100644 --- a/src/meta_schedule/utils.h +++ b/src/meta_schedule/utils.h @@ -334,17 +334,19 @@ struct ThreadedTraceApply { for (int i = 0; i < n_; ++i) { Item& item = items_[i]; + bool success = true; try { if (!item.postproc->Apply(sch)) { - item.fail_counter++; - return std::nullopt; + success = false; } } catch (const tir::ScheduleError& e) { DLOG(WARNING) << "Postproc #" << i << " failed with ScheduleError: " << e.what(); - item.fail_counter++; - return std::nullopt; + success = false; } catch (const std::exception& e) { DLOG(WARNING) << "Postproc #" << i << " failed with exception: " << e.what(); + success = false; + } + if (!success) { item.fail_counter++; return std::nullopt; } From 85374d0a798067a0a537104188e4a03f173f93b4 Mon Sep 17 00:00:00 2001 From: Dayuxiaoshui <792179245@qq.com> Date: Sun, 14 Dec 2025 10:16:44 +0000 Subject: [PATCH 3/3] fix: Return false on ScheduleError in rewrite_parallel_vectorize_unroll Previously, catching ScheduleError and continuing could leave the schedule partially mutated if operations failed mid-sequence. This change ensures that when a ScheduleError occurs, the postprocessor returns false immediately, causing the candidate to be discarded safely rather than continuing with a potentially corrupted schedule state. This matches the error handling pattern used in ThreadedTraceApply::Apply and addresses the safety concern about partial mutations. --- src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc b/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc index eda0fd82cadb..5950ef742d49 100644 --- a/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc +++ b/src/meta_schedule/postproc/rewrite_parallel_vectorize_unroll.cc @@ -448,7 +448,7 @@ class RewriteParallelVectorizeUnrollNode : public PostprocNode { } } catch (const tir::ScheduleError& e) { DLOG(WARNING) << "Failed to apply parallelization/vectorization: " << e.what(); - continue; + return false; } } }