Avoid NVHPC 25.5 fort2 ICE by expanding f_compute_multidim_cfl_terms - #1718
Avoid NVHPC 25.5 fort2 ICE by expanding f_compute_multidim_cfl_terms#1718sbryngelson wants to merge 2 commits into
Conversation
NVHPC 25.5's fort2 segfaults (SIGSEGV) during the -Minline pass of our two-pass IPO when it cross-file inlines a routine whose body contains a call to f_compute_multidim_cfl_terms. It manifests as: nvfortran-Fatal-.../25.5/compilers/bin/tools/fort2 TERMINATED by signal 11 gmake[3]: *** [.../simulation.dir/fypp/simulation/m_data_output.fpp.f90.o] The crash is at the call site, not in the callee: it reproduces with the helper's body emptied and with its array dummy replaced by a scalar, and it survives except:f_compute_multidim_cfl_terms (excluding the callee leaves the offending call inside the inlined caller). Excluding the caller -- s_compute_stability_from_dt -- is what avoids it. Because the helper was private with exactly two call sites, expanding it in place removes the pattern entirely. The resulting if (p > 0) / else if (n > 0) / else structure matches the viscous and capillary blocks already present in both routines. Not architecture specific: originally reported on GH200/aarch64, and reproduced here on x86_64 with the stock NVHPC 25.5 tarball. NVHPC 25.11 compiles the unmodified source cleanly, so this is a 25.5 codegen bug; this change simply avoids the construct that triggers it. Verified: - NVHPC 25.5, GPU+MPI, case-optimized: fails before, builds after - NVHPC 25.11, same config: builds before and after (no regression) - cfl_adap_dt golden-file tests: 7/7 pass
There was a problem hiding this comment.
Pull request overview
This pull request adjusts the simulation CFL/stability computations to avoid an NVHPC 25.5 fort2 internal compiler error triggered by cross-file inlining of a routine containing a call to f_compute_multidim_cfl_terms. The fix removes the helper function and expands its logic directly at the two call sites in m_sim_helpers, preserving the existing CFL selection behavior while eliminating the problematic call pattern.
Changes:
- Removed the private helper
f_compute_multidim_cfl_termsfromsrc/simulation/m_sim_helpers.fpp. - Inlined the 2D/3D inviscid CFL term selection logic directly into
s_compute_stability_from_dtands_compute_dt_from_cfl, including thegrid_geometry == 3(filtered dtheta) path. - Added an in-code comment documenting the NVHPC 25.5
-Minline/IPO inlining-triggered crash and why the logic is duplicated.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Local verification completeRan both full suites against the golden files, plus a GPU run on the compiler that actually has the bug. Full test suite
The two CPU "failures" were per-test timeouts, not golden-file mismatches, on The GPU run is the important one: it executes the modified Builds
On removing the inline exclusionsWith this fix, NVHPC 25.5 builds cleanly with both the Still not proposing that here, for two different reasons:
|
The NVHPC 25.5 fort2 ICE fixed in the previous commit was invisible to
CI, and would have stayed invisible. Two axes never intersect:
- The NVHPC version matrix (23.11 -> 26.3) builds gpu targets without
--case-optimization. An unmodified master builds cleanly on 25.5 in
that configuration, which is why those jobs are green today.
- The case-optimization jobs run only on self-hosted clusters:
Phoenix, pinned to nvhpc/24.5, and Frontier, which is CCE/AMD.
So "case-optimized x NVHPC 25.5" was never exercised. Case optimization
hard-codes case parameters into the generated sources, which sharply
increases cross-file inlining pressure in the -Mextract/-Minline pass --
precisely where NVHPC fort2 has repeatedly hit ICEs (see the -Mnoinline
list in cmake/MFCTargets.cmake).
This adds one extra build to the existing gpu matrix jobs. It is
build-only and a single case, because the failure is at compile time and
nothing needs to run.
- 3D specifically: m_sim_helpers.fpp guards its 3D block with
"#:if not MFC_CASE_OPTIMIZATION or num_dims > 2", so a case-optimized
2D build elides the code that crashed.
- OpenACC only: the two-pass IPO is disabled for OpenMP offload
(MFCTargets.cmake), so gpu-omp cannot hit this class of bug.
Verified with a local NVHPC 25.5 install, running this exact command:
- unmodified master: fort2 TERMINATED by signal 11 on m_data_output
- with the previous commit: builds cleanly
Added: CI guard (0410833)This bug was invisible to CI and would have stayed that way. I confirmed the gap rather than assuming it: Control experiment — unmodified master, NVHPC 25.5, GPU+MPI, without Two CI axes that never intersect:
So The guardOne extra build in the existing gpu matrix jobs — build-only, one case, since the failure is at compile time and nothing needs to run: Two deliberate constraints:
Guard validated in both directionsUsing a local NVHPC 25.5 install and this exact command:
Red before, green after — it actually catches the regression it claims to. I went with the matrix approach over bumping Phoenix off |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1718 +/- ##
==========================================
- Coverage 61.24% 61.24% -0.01%
==========================================
Files 83 83
Lines 20700 20702 +2
Branches 3072 3072
==========================================
+ Hits 12677 12678 +1
Misses 5969 5969
- Partials 2054 2055 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Problem
Building
simulationwith NVHPC 25.5 and our two-pass IPO crashes the compiler:Reported by OLCF on a GH200 (Grace + H100, NVHPC 25.5, CUDA 12.9) while running the
scaling benchmark. It is not architecture specific — it reproduces on x86_64 with
the stock NVHPC 25.5 tarball, same signal and same file.
Root cause
fort2segfaults during the-Minlinepass when it cross-file inlines a routine whosebody contains a call to
f_compute_multidim_cfl_terms.The crash belongs to the call site, not the callee. Bisected against a live reproducer:
s_compute_stability_from_dtf_compute_filtered_dtheta(scalar args)f_compute_multidim_cfl_termsThis also explains why
except:f_compute_multidim_cfl_termsdoes not help: excluding thecallee still leaves the offending call inside the inlined caller. Only excluding the
caller avoids it.
It also explains the second crash site.
m_time_stepperscallss_compute_dt_from_cfl,the sibling routine in the same module with the same call pattern — which is exactly where
the ICE relocates if
m_data_outputis added to the-Mnoinlinelist.Fix
f_compute_multidim_cfl_termswasprivatewith exactly two call sites, so it is expandedin place and removed. No
-Mnoinline, no macro, net −1 line. The resultingif (p > 0) / else if (n > 0) / elsestructure matches the viscous and capillary blocksalready present in both routines.
Semantics are unchanged: the original nested logic selected 3D for
p > 0and 2Dotherwise, guarded by
if (p > 0 .or. n > 0). Every read offltr_dthetain both routinesis still immediately preceded by its own assignment.
Verification
-Mnoinlineexclusions removedcfl_adap_dtgolden-file tests (CPU)Full CPU test suite is running locally and was clean through the first ~315/628 cases at
the time of opening; CI covers it here regardless.
Follow-up (not in this PR)
With this fix, NVHPC 25.5 builds cleanly with the existing
m_start_up/m_cbc-Mnoinlineexclusions incmake/MFCTargets.cmakeremoved entirely. Those were addedfor an NVHPC 25.x ICE and look like the same bug. I left them in place here to keep this
change minimal — worth removing separately once CI confirms across the matrix, since it
would restore full IPO to those files.
NVHPC 25.11 compiles the unmodified source fine, so the underlying defect is a 25.5 codegen
bug; this change avoids the construct that triggers it. Worth filing upstream with NVIDIA.