Skip to content

Commit 0bdb927

Browse files
Gate lu_refactorization wrapper-elision ceilings on Julia 1.12
The zero-allocation assertions introduced in SciML#1082 assume the returned LinearSolution wrapper is elided at testset scope, which holds on 1.12+ but not on 1.11 (which CI never runs: lts/1/pre = 1.10/1.12/pre). The failure reproduces identically on unmodified main under 1.11 (48 bytes there; 32 with the 5.0 lightweight solution). Allow the boxed wrapper (<= 48 bytes) on 1.11 only; a leaked pivot vector would add >= n * sizeof(Int) on top, so the reuse assertions remain meaningful. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
1 parent af74ae5 commit 0bdb927

1 file changed

Lines changed: 20 additions & 4 deletions

File tree

test/Core/lu_refactorization.jl

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ using LinearSolve, LinearAlgebra, StableRNGs, Test
77
# non-BLAS eltypes) is allocation-free on every supported version.
88
const BLAS_IPIV_REUSE = VERSION >= v"1.11"
99

10+
# On Julia 1.11 exactly, `@allocated refactor_solve!(...)` at testset scope
11+
# still counts one boxed `LinearSolution` return (<= 48 bytes): 1.11 has the
12+
# `getrf!(A, ipiv)` reuse API but its escape analysis does not elide the
13+
# returned solution wrapper here; 1.12+ elides it fully. A leaked pivot vector
14+
# would add >= n * sizeof(Int) bytes on top, so the reuse assertion stays
15+
# meaningful under this ceiling. (CI runs lts/1/pre = 1.10/1.12+/pre, so this
16+
# only shows up on local 1.11 runs; the ceilings were introduced in #1082
17+
# assuming the 1.12 elision behavior.)
18+
const WRAPPER_CEILING = VERSION >= v"1.12" ? 0 : 48
19+
1020
rng = StableRNG(42)
1121

1222
function refactor_solve!(cache, Awork, A)
@@ -28,12 +38,18 @@ end
2838
# 1.10's compiler does not always elide the small `LU`/solution wrapper
2939
# constructions that 1.11+ removes, hence the small nonzero ceiling.
3040
@testset "$(name)" for (name, alg, maxalloc) in (
31-
("LUFactorization RowMaximum", LUFactorization(), BLAS_IPIV_REUSE ? 0 : nothing),
41+
(
42+
"LUFactorization RowMaximum", LUFactorization(),
43+
BLAS_IPIV_REUSE ? WRAPPER_CEILING : nothing,
44+
),
3245
(
3346
"LUFactorization NoPivot", LUFactorization(pivot = NoPivot()),
34-
VERSION >= v"1.11" ? 0 : 64,
47+
VERSION >= v"1.11" ? WRAPPER_CEILING : 64,
48+
),
49+
(
50+
"default algorithm", nothing,
51+
BLAS_IPIV_REUSE ? WRAPPER_CEILING : nothing,
3552
),
36-
("default algorithm", nothing, BLAS_IPIV_REUSE ? 0 : nothing),
3753
)
3854
cache = init(
3955
LinearProblem(copy(A1), copy(b)), alg;
@@ -163,7 +179,7 @@ end
163179
refactor_solve!(cache, Awork, A2)
164180
alloc = @allocated refactor_solve!(cache, Awork, A2)
165181
if BLAS_IPIV_REUSE
166-
@test alloc == 0
182+
@test alloc <= WRAPPER_CEILING
167183
end
168184
@test cache.u A2 \ b2
169185
end

0 commit comments

Comments
 (0)