Skip to content

Support 32-bit platforms#95

Merged
ChrisRackauckas merged 1 commit into
SciML:mainfrom
oschulz:support-32bit
Jul 12, 2026
Merged

Support 32-bit platforms#95
ChrisRackauckas merged 1 commit into
SciML:mainfrom
oschulz:support-32bit

Conversation

@oschulz

@oschulz oschulz commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

FindFirstFunctions v3 fails to precompile on 32-bit platforms, breaking downstream 32-bit CI (via SciMLBase → LinearSolve → …):

julia> using FindFirstFunctions   # Julia 1.12, 32-bit x86
ERROR: MethodError: no method matching _findfirstequal(::Int64, ::Ptr{Int64}, ::Int32)

The PrecompileTools workload calls findfirstequal, which passes length(v)::Int32 to _findfirstequal(::Int64, ::Ptr{Int64}, ::Int64). Beyond that dispatch failure, the llvmcall kernels themselves assume a 64-bit host: on Julia < 1.12 Ptr arguments lower to i32 on 32-bit targets, mismatching the declared i64 / inttoptr i64.

Changes:

  • Gate the SIMD IR constants and llvmcall wrappers behind Sys.WORD_SIZE == 64. On other platforms, bind the same nine primitives to _scalar_first, a portable scalar loop with the identical contract (0-based offset of the first element with pred(v[i], x), -1 if none).
  • Convert lengths to Int64 at the two _findfirstequal call sites in equality.jl (no-ops on 64-bit).
  • Add a testset checking _scalar_first against findfirst for all predicate/eltype combinations; it runs on every platform.

Verification: the Core group passes (123036 tests) both as-is and with the gate flipped to force the scalar path on x86-64, so the fallback is exercised by the entire existing suite; QA group passes. No 32-bit hardware was available to me — on a real 32-bit target the only code delta relative to the flipped-gate run is the Int64(length(v)) conversion.

No version bump included.

Code changes generated by Claude (Fable).

@oschulz

oschulz commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

I ran into this problem in the context of MGVI.jl improvements. Fix is AI-generated. Should I trim down the comments in the code changes?

@ChrisRackauckas

Copy link
Copy Markdown
Member

The comments and code changes here look completely reasonable.

@ChrisRackauckas

Copy link
Copy Markdown
Member

But 32-bit CI should be added here to catch this.

@oschulz

oschulz commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

But 32-bit CI should be added here to catch this.

Will do.

The SIMD llvmcall kernels assume a 64-bit host: length(v)::Int32 fails
to dispatch to the len::Int64 primitives, breaking precompilation with
a MethodError, and on Julia < 1.12 Ptr arguments lower to i32,
mismatching the declared i64. Gate the SIMD path behind
Sys.WORD_SIZE == 64 and bind the primitives to a portable scalar loop
with the identical contract elsewhere.

Add a 32-bit CI job (Core group) so regressions are caught.

Created by generative AI.
@oschulz

oschulz commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

@ChrisRackauckas 32-bit tests added - Ok like this? (needs approval to run)

@oschulz

oschulz commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

And should I add a version bump to the PR?

@ChrisRackauckas

Copy link
Copy Markdown
Member

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member

Superseded by #97, which keeps the same 32-bit source support but (a) declares the 32-bit run through test/test_groups.toml (a new arch axis + group alias added in SciML/.github#113) instead of a hand-added tests.yml job, and (b) fixes a gap this branch has: findfirstsortedequal had no generic fallback, so on 32-bit (native Int = Int32) it threw MethodError 8385 times — the suite here does not actually pass on i686 without that fix. Verified green on real 32-bit Julia 1.11 in #97.

@ChrisRackauckas

Copy link
Copy Markdown
Member

I'll handle the next step.

@ChrisRackauckas
ChrisRackauckas merged commit 012b92c into SciML:main Jul 12, 2026
33 of 36 checks passed
@ChrisRackauckas

Copy link
Copy Markdown
Member

Thanks!

ChrisRackauckas-Claude pushed a commit to ChrisRackauckas-Claude/FindFirstFunctions.jl that referenced this pull request Jul 12, 2026
…eric fallback

Builds on SciML#95 (now on master). Two follow-ups:

1. Replace the hand-added `tests-32bit` job in Tests.yml with a `"Core 32-bit"`
   section in test/test_groups.toml. It dispatches the Core body (group = "Core")
   on a single `arch = "x86"` ubuntu cell via the arch axis / group alias added
   to SciML/.github's grouped-tests generator (v1.24.0). Tests.yml goes back to
   a thin caller.

2. Add the generic `findfirstsortedequal(var, vars)` fallback that SciML#95 was
   missing. Unlike `findfirstequal`, `findfirstsortedequal` had only the
   `(Int64, DenseVector{Int64})` method, so on 32-bit — where native `Int` is
   `Int32` — `findfirstsortedequal(::Int32, ::Vector{Int32})` throws MethodError
   (8385 such errors in the suite). The master `tests-32bit` job is therefore
   currently red; this fixes it. The fallback is a generic `searchsortedfirst`
   + equality post-check, mirroring `findfirstequal`.

Add a generic-fallback test (Int32/Int16/Float32) so the path is covered on
64-bit CI too, and bump 3.0.3 -> 3.1.0 (new public behavior).

Verified locally: full Core suite passes on 32-bit i686 Julia 1.11 (0 errors)
and on x64 (171915 tests).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcQkauMQ4KSytnTpJpXUZu
@oschulz

oschulz commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @ChrisRackauckas !

ChrisRackauckas-Claude pushed a commit to ChrisRackauckas-Claude/FindFirstFunctions.jl that referenced this pull request Jul 12, 2026
… broken 32-bit CI job

Follow-up to SciML#95. Two things:

1. Fix a correctness gap SciML#95 shipped. Unlike `findfirstequal`,
   `findfirstsortedequal` had ONLY the `(Int64, DenseVector{Int64})` method
   and no generic fallback. On 32-bit platforms native `Int` is `Int32`, so
   `findfirstsortedequal(::Int32, ::Vector{Int32})` throws MethodError — 8385
   such errors in the suite, and a bare `Pkg.test()` / any `Int`-vector caller
   on 32-bit is broken. Add a generic `searchsortedfirst` + equality post-check
   fallback (mirroring `findfirstequal`), so it works for any sorted vector on
   any platform. Add a test covering the fallback on Int32/Int16/Float32.

2. Remove the `tests-32bit` job SciML#95 added to Tests.yml. Running 32-bit Julia on
   the 64-bit `ubuntu-latest` runner fails at `setup-julia` (the i686 binary
   can't exec without the 32-bit loader, which is not installed before Julia is
   invoked: `spawn .../x86/bin/julia ENOENT`), so that job is red regardless of
   this fix. A proper 32-bit CI lane needs runner/reusable-workflow changes and
   is deferred; Tests.yml goes back to a thin grouped-tests caller.

Minor bump 3.0.3 -> 3.1.0 (new public behavior: `findfirstsortedequal` now
accepts any sorted vector). Verified locally: full Core suite passes on 32-bit
i686 Julia 1.11 (0 errors) and on x64 (171915 tests); GROUP=All passes.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcQkauMQ4KSytnTpJpXUZu
ChrisRackauckas-Claude pushed a commit to ChrisRackauckas-Claude/FindFirstFunctions.jl that referenced this pull request Jul 12, 2026
Declare a `Core 32-bit` matrix-only alias that dispatches the Core body
(group = "Core") on a single x86 Julia cell, so the WORD_SIZE != 64 scalar
fallbacks in src/simd_ir.jl are exercised in CI — replacing SciML#95's hand-added
`tests-32bit` job (removed in the parent commit) with a declarative lane.

This uses the arch axis / group alias in SciML/.github v1 (v1.24.0) and the
i386 runtime-lib install before setup-julia (v1.24.1), so the x86 leg can
actually run on the 64-bit ubuntu runner.

Require `SciMLTesting = "2.2"`: the alias section is skipped by folder discovery
only in SciMLTesting >= 2.2 (SciMLTesting.jl#22), which GROUP=All (the Downgrade
job) and a bare `Pkg.test()` need. FindFirstFunctions runs unchanged on
SciMLTesting 2.x (verified: Core suite passes on 2.1.0).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcQkauMQ4KSytnTpJpXUZu
ChrisRackauckas-Claude pushed a commit to ChrisRackauckas-Claude/FindFirstFunctions.jl that referenced this pull request Jul 12, 2026
Declare a `Core 32-bit` matrix-only alias that dispatches the Core body
(group = "Core") on a single x86 Julia cell, so the WORD_SIZE != 64 scalar
fallbacks in src/simd_ir.jl are exercised in CI — replacing SciML#95's hand-added
`tests-32bit` job (removed in the parent commit) with a declarative lane.

This uses the arch axis / group alias in SciML/.github v1 (v1.24.0) and the
i386 runtime-lib install before setup-julia (v1.24.1), so the x86 leg can
actually run on the 64-bit ubuntu runner.

Require `SciMLTesting = "2.2"`: the alias section is skipped by folder discovery
only in SciMLTesting >= 2.2 (SciMLTesting.jl#22), which GROUP=All (the Downgrade
job) and a bare `Pkg.test()` need. FindFirstFunctions runs unchanged on
SciMLTesting 2.x (verified: Core suite passes on 2.1.0).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcQkauMQ4KSytnTpJpXUZu
ChrisRackauckas added a commit that referenced this pull request Jul 12, 2026
… broken 32-bit CI job (#97)

Follow-up to #95. Two things:

1. Fix a correctness gap #95 shipped. Unlike `findfirstequal`,
   `findfirstsortedequal` had ONLY the `(Int64, DenseVector{Int64})` method
   and no generic fallback. On 32-bit platforms native `Int` is `Int32`, so
   `findfirstsortedequal(::Int32, ::Vector{Int32})` throws MethodError — 8385
   such errors in the suite, and a bare `Pkg.test()` / any `Int`-vector caller
   on 32-bit is broken. Add a generic `searchsortedfirst` + equality post-check
   fallback (mirroring `findfirstequal`), so it works for any sorted vector on
   any platform. Add a test covering the fallback on Int32/Int16/Float32.

2. Remove the `tests-32bit` job #95 added to Tests.yml. Running 32-bit Julia on
   the 64-bit `ubuntu-latest` runner fails at `setup-julia` (the i686 binary
   can't exec without the 32-bit loader, which is not installed before Julia is
   invoked: `spawn .../x86/bin/julia ENOENT`), so that job is red regardless of
   this fix. A proper 32-bit CI lane needs runner/reusable-workflow changes and
   is deferred; Tests.yml goes back to a thin grouped-tests caller.

Minor bump 3.0.3 -> 3.1.0 (new public behavior: `findfirstsortedequal` now
accepts any sorted vector). Verified locally: full Core suite passes on 32-bit
i686 Julia 1.11 (0 errors) and on x64 (171915 tests); GROUP=All passes.



Claude-Session: https://claude.ai/code/session_01EcQkauMQ4KSytnTpJpXUZu

Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ChrisRackauckas added a commit that referenced this pull request Jul 12, 2026
* Add generic findfirstsortedequal fallback (fixes 32-bit) and drop the broken 32-bit CI job

Follow-up to #95. Two things:

1. Fix a correctness gap #95 shipped. Unlike `findfirstequal`,
   `findfirstsortedequal` had ONLY the `(Int64, DenseVector{Int64})` method
   and no generic fallback. On 32-bit platforms native `Int` is `Int32`, so
   `findfirstsortedequal(::Int32, ::Vector{Int32})` throws MethodError — 8385
   such errors in the suite, and a bare `Pkg.test()` / any `Int`-vector caller
   on 32-bit is broken. Add a generic `searchsortedfirst` + equality post-check
   fallback (mirroring `findfirstequal`), so it works for any sorted vector on
   any platform. Add a test covering the fallback on Int32/Int16/Float32.

2. Remove the `tests-32bit` job #95 added to Tests.yml. Running 32-bit Julia on
   the 64-bit `ubuntu-latest` runner fails at `setup-julia` (the i686 binary
   can't exec without the 32-bit loader, which is not installed before Julia is
   invoked: `spawn .../x86/bin/julia ENOENT`), so that job is red regardless of
   this fix. A proper 32-bit CI lane needs runner/reusable-workflow changes and
   is deferred; Tests.yml goes back to a thin grouped-tests caller.

Minor bump 3.0.3 -> 3.1.0 (new public behavior: `findfirstsortedequal` now
accepts any sorted vector). Verified locally: full Core suite passes on 32-bit
i686 Julia 1.11 (0 errors) and on x64 (171915 tests); GROUP=All passes.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcQkauMQ4KSytnTpJpXUZu

* Add the 32-bit CI lane via test_groups.toml

Declare a `Core 32-bit` matrix-only alias that dispatches the Core body
(group = "Core") on a single x86 Julia cell, so the WORD_SIZE != 64 scalar
fallbacks in src/simd_ir.jl are exercised in CI — replacing #95's hand-added
`tests-32bit` job (removed in the parent commit) with a declarative lane.

This uses the arch axis / group alias in SciML/.github v1 (v1.24.0) and the
i386 runtime-lib install before setup-julia (v1.24.1), so the x86 leg can
actually run on the 64-bit ubuntu runner.

Require `SciMLTesting = "2.2"`: the alias section is skipped by folder discovery
only in SciMLTesting >= 2.2 (SciMLTesting.jl#22), which GROUP=All (the Downgrade
job) and a bare `Pkg.test()` need. FindFirstFunctions runs unchanged on
SciMLTesting 2.x (verified: Core suite passes on 2.1.0).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcQkauMQ4KSytnTpJpXUZu

---------

Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants