[llvm] [flang-rt] - Reduce ShallowCopy template instantiations to improve LTO time (PR #209915)

Pranav Bhandarkar via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 15:48:43 PDT 2026


https://github.com/bhandarkar-pranav created https://github.com/llvm/llvm-project/pull/209915

Limit `ShallowCopy` rank specializations from 1-15 to 1-4, using a generic fallback for higher ranks. This significantly reduces code size and LTO compile time when the Fortran runtime is linked into GPU offloading code.

Before: 15 ranks × 7 types × 3 scenarios = 315 template instantiations
After:  4 ranks × 7 types × 3 scenarios = 84 template instantiations + fallbacks

Trade-off: Arrays with rank > 4 use a generic runtime loop instead of compile-time specialized iteration. This is acceptable because:
- Most real-world Fortran arrays are rank 1-3
- Rank 5-15 arrays are rare in practice
- The generic loop is still efficient (just not unrollable)
## Results

### Compilation Time (from `time` command)

| Metric | Baseline (main) | Improvement | Delta |
|--------|----------------|-------------|-------|
| Wall clock time | ~27.6s | ~22.1s | **-5.5s (-20%)** |

### LTO Pass Timing (from `-mllvm -time-passes`)

| Pass | Baseline (main) | Improvement | Delta |
|------|----------------|-------------|-------|
| **Total LTO** | 27.64s | 22.10s | **-5.54s (-20.0%)** |
| OpenMPOptPass | 8.77s (31.7%) | 6.65s (30.1%) | **-2.12s (-24.2%)** |
| OpenMPOptCGSCCPass | 2.32s (8.4%) | 1.99s (9.0%) | **-0.33s (-14.2%)** |
| **Combined OpenMPOpt** | **11.09s** | **8.64s** | **-2.45s (-22.1%)** |

### Attributor Statistics (from `-mllvm -stats`)

| Metric | Baseline (main) | Improvement | Delta |
|--------|----------------|-------------|-------|
| Abstract Attributes Created | 1,119,860 | 813,947 | **-305,913 (-27.3%)** |
| Abstract Attributes in Valid Fixpoint | 491,995 | 359,149 | **-132,846 (-27.0%)** |
| Dead Basic Blocks Deleted | 6,522 | 2,168 | -4,354 (-66.8%) |



This is the first part of a multi-part fix for https://github.com/llvm/llvm-project/issues/203915

>From fff149ff22f21975f75518d857499e991d316813 Mon Sep 17 00:00:00 2001
From: Pranav Bhandarkar <pranav.bhandarkar at amd.com>
Date: Mon, 19 Jan 2026 15:50:55 -0600
Subject: [PATCH] Reduce ShallowCopy template instantiations to improve LTO
 compile time
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Limit ShallowCopy rank specializations from 1-15 to 1-4, using a generic
fallback for higher ranks. This significantly reduces code size and LTO
compile time when the Fortran runtime is linked into GPU offloading code.

Before: 15 ranks × 7 types × 3 scenarios = 315 template instantiations
After:  4 ranks × 7 types × 3 scenarios = 84 template instantiations + fallbacks

Impact on LTO compile time (measured with OpenMP offloading test case):
- LTO time: 17s → 13s (24% improvement)
- Abstract Attributes created: 396K → 276K (30% reduction)
- Attributor worklist entries: 1.36M → 929K (32% reduction)

Trade-off: Arrays with rank > 4 use a generic runtime loop instead of
compile-time specialized iteration. This is acceptable because:
- Most real-world Fortran arrays are rank 1-3
- Rank 5-15 arrays are rare in practice
- The generic loop is still efficient (just not unrollable)
---
 flang-rt/lib/runtime/tools.cpp | 49 +++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/flang-rt/lib/runtime/tools.cpp b/flang-rt/lib/runtime/tools.cpp
index 03ee982d913bb..a3b14203dccd9 100644
--- a/flang-rt/lib/runtime/tools.cpp
+++ b/flang-rt/lib/runtime/tools.cpp
@@ -201,37 +201,36 @@ RT_API_ATTRS void ShallowCopyInner(const Descriptor &to, const Descriptor &from,
   }
 }
 
-// Most arrays are much closer to rank-1 than to maxRank.
-// Doing the recursion upwards instead of downwards puts the more common
-// cases earlier in the if-chain and has a tangible impact on performance.
-template <typename P, int RANK> struct ShallowCopyRankSpecialize {
-  static RT_API_ATTRS bool execute(const Descriptor &to, const Descriptor &from,
-      bool toIsContiguous, bool fromIsContiguous) {
-    if (to.rank() == RANK && from.rank() == RANK) {
-      ShallowCopyInner<P, RANK>(to, from, toIsContiguous, fromIsContiguous);
-      return true;
-    }
-    return ShallowCopyRankSpecialize<P, RANK + 1>::execute(
-        to, from, toIsContiguous, fromIsContiguous);
-  }
-};
-
-template <typename P> struct ShallowCopyRankSpecialize<P, maxRank + 1> {
-  static RT_API_ATTRS bool execute(const Descriptor &to, const Descriptor &from,
-      bool toIsContiguous, bool fromIsContiguous) {
-    return false;
-  }
-};
+// Specialize only for common ranks (1-4) to reduce code size.
+// Higher ranks use the generic fallback which handles any rank at runtime.
+// Most real-world Fortran arrays are rank 1-3; rank 4+ is rare.
+// This trades a small amount of potential optimization for high-rank arrays
+// in exchange for significantly reduced code size (~60% reduction in
+// ShallowCopy template instantiations).
 
 // ShallowCopy helper for specialising the variants based on array rank
 template <typename P>
 RT_API_ATTRS void ShallowCopyRank(const Descriptor &to, const Descriptor &from,
     bool toIsContiguous, bool fromIsContiguous) {
-  // Try to call a specialised ShallowCopy variant from rank-1 up to maxRank
-  bool specialized{ShallowCopyRankSpecialize<P, 1>::execute(
-      to, from, toIsContiguous, fromIsContiguous)};
-  if (!specialized) {
+  // Specialize only common low ranks; use generic fallback for higher ranks
+  switch (to.rank()) {
+  case 1:
+    ShallowCopyInner<P, 1>(to, from, toIsContiguous, fromIsContiguous);
+    return;
+  case 2:
+    ShallowCopyInner<P, 2>(to, from, toIsContiguous, fromIsContiguous);
+    return;
+  case 3:
+    ShallowCopyInner<P, 3>(to, from, toIsContiguous, fromIsContiguous);
+    return;
+  case 4:
+    ShallowCopyInner<P, 4>(to, from, toIsContiguous, fromIsContiguous);
+    return;
+  default:
+    // Generic fallback for rank > 4 (and rank 0, though that's handled
+    // by the contiguous-to-contiguous case in ShallowCopyInner)
     ShallowCopyInner<P>(to, from, toIsContiguous, fromIsContiguous);
+    return;
   }
 }
 



More information about the llvm-commits mailing list