Repository navigation
Conversation
Add an --address-bits option. With 32, size_t-typed builtin parameters and returns (vloadN/vstoreN, vload_half, async copies, prefetch, get_image_array_size) are mangled and typed as uint, and the module uses the spir triple. Selecting the 32-bit prefix through sys.argv had been dead since the switch to argparse. For cpu_x86, 32 address bits select the i386 System V ABI. Clang passes and returns every OpenCL vector directly there, except that <8 x i8>, <4 x i16> and <2 x i32> arguments are coerced to i64. This holds for every i686 kernel library variant, so the register size doesn't matter. The output for 64-bit targets is unchanged.
Use the generated wrapper with --address-bits 32 instead of the checked-in spir_wrapper32.ll, which only has scalar builtins. Like on RISC-V, generate it once per kernel library variant: the i386 ABI doesn't depend on the vector registers, and the variants without SSE2 never reach the generation in the SLEEF vector-size loop.
Before linking a SPIR module with the kernel library, its datalayout is replaced by the host's. Struct types from SPIR(-V) aren't padded explicitly, because the SPIR datalayout already aligns long and double to 8 bytes as OpenCL C requires. Where the host aligns them less (i386), field offsets, struct sizes and array strides silently changed, while sizeof and offsetof, folded by the SPIR compiler, still reported the SPIR layout. Before the swap, replace every struct type whose layout differs, wherever it describes memory, by a packed struct with explicit padding: GEPs (renumbering the field indices), allocas, globals and their initializers, and the byval/sret/byref/elementtype attributes. Aggregate SSA values have no layout and keep their type; aggregate loads and stores are split into per-element accesses at the SPIR offsets. This is what Clang does for OpenCL C on i386, and a no-op where the layouts agree (all 64-bit hosts). The test checks struct buffers, by-value struct arguments, nested structs, tail padding, private arrays of structs, constant initializers and aggregate loads and stores, from 32-bit and 64-bit SPIR-V.
A 32-bit device rightly rejects Physical64 modules, so the regression tests with 64-bit SPIR-V inputs now skip there, using the poclu helper for the device's address bits, and the compiler unit tests with .spirv inputs are only registered on 64-bit hosts. spirv/printf, the test that led to SPIR-V being disabled on 32-bit hosts (pocl#1880), and example1 get 32-bit SPIR-V twins built from the same sources.
Call the builtins whose SPIR wrappers depend on the address bits (size_t parameters of vloadN/vstoreN, vload_half/vstore_half, async copies and prefetch) or on the calling convention (64-bit vectors that i386 coerces to integers, wide vectors that x86-64 passes in memory, vec3), plus scoped atomics, work_group_barrier and sub-groups, from 32-bit and 64-bit SPIR-V built from the same sources. Double precision and sub-groups are in separate modules so that devices without them still run the rest.
SPIR-V was disabled on 32-bit hosts in pocl#1883 after spirv/printf crashed on Debian's i386, armel and armhf builds (pocl#1880), until the 32-bit support was finished. The crash itself (a double free on the error path for 64-bit modules) has since been fixed, and with the generated i386 SPIR wrapper and the preserved struct layouts, SPIR-V works on i386 System V hosts. ARM32, RISC-V32 and 32-bit Windows stay disabled: the wrapper generator doesn't know their ABIs.
The search for the static SVML and IRC libraries in the oneAPI compiler directory also ran on 32-bit x86 (I386 and X32 set X86 too), where it finds the x86-64 archives, as oneAPI no longer ships ia32 libraries. These were then linked into the 32-bit kernels, which crashed in vectorized math builtins.
Run the CPU tests in an i386 Debian container on a GitHub-hosted runner. Debian testing, because the CPU JIT needs LLVM 21 on i386 (R_386_GOT32X support in JITLink), and with -msse2 because Debian's i386 baseline lacks the SSE the FTZ handling needs (pocl#2097). The tests that fail on i686 regardless of SPIR-V are excluded.
maleadt
added a commit
to maleadt/Yggdrasil
that referenced
this pull request
Nov 5, 2026
…he patch series Add pocl/pocl#2375 and pocl/pocl#2430 to both tracks. They fold the local and sub-group sizes before the barrier passes and fully unroll short constant-trip loops with barriers, such as sub-group and work-group reductions, instead of running each iteration as separate work-item loops. Bring the other patches up to date with their sources: the merged versions of pocl/pocl#2190, JuliaPackaging#2339 and JuliaPackaging#2423, the latest revisions of JuliaPackaging#2359 and JuliaPackaging#2384, and on the v7.2 track also JuliaGPU/pocl#4, JuliaPackaging#2239, JuliaPackaging#2394 and JuliaPackaging#2410, with JuliaPackaging#2381 and its mingw32 follow-up as separate patches. The spirv32 series gains the SVML commit of JuliaGPU/pocl#3. The v7.2 series is renumbered without its gap.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SPIR-V on the CPU device has been disabled on 32-bit hosts since pocl#1883, as a stopgap for pocl#1880 ("until someone finishes it"). The crash in that issue, a double free when a 32-bit device rejected the 64-bit
spirv/printfmodule, has since been fixed. What remained were two real gaps, both fixed here for i386 System V hosts (e.g. i686 Linux):The SPIR builtin wrapper. 32-bit hosts used the checked-in
spir_wrapper32.llfrom 2019, which only has scalar builtins: no vectors, no atomics with a scope, nowork_group_barrier(flags, scope), and 38 wrappers with broken pointer parameters.generate_spir_wrapper.pynow takes--address-bits 32, which types and manglessize_tparameters as 32-bit and selects the i386 ABI: clang passes and returns every OpenCL vector directly there, except that<8 x i8>,<4 x i16>and<2 x i32>arguments are coerced toi64. That holds for every distro kernel library variant (i386 through AVX-512), so the wrapper is generated once per variant. Comparing every wrapper declaration with the kernel library definitions gives 0 mismatches on all 13 i686 variants, and the same missing builtins as the x86-64 wrappers. The output for 64-bit targets is unchanged.Struct layouts. Before linking a SPIR module with the kernel library, PoCL replaces its datalayout with the host's. SPIR struct types aren't padded explicitly, because the SPIR datalayout already aligns
longanddoubleto 8 bytes, as OpenCL C requires. i386 aligns them to 4, so the kernels silently accessed fields, struct arguments and arrays of structs at the wrong offsets, whilesizeof/offsetof(folded by the SPIR compiler) still reported the OpenCL layout. A new step before the datalayout swap replaces every struct type whose layout differs, wherever it describes memory, by a packed struct with explicit padding that keeps the SPIR offsets and size. That covers GEPs (with renumbered field indices), allocas, globals and their initializers, and thebyval/sret/byref/elementtypeattributes. Aggregate SSA values have no layout and keep their type; aggregate loads and stores are split into per-element accesses at the SPIR offsets. Clang does the equivalent for OpenCL C on i386 (explicitly padded struct types). Where the layouts agree, which is the case on all 64-bit hosts, the step changes nothing: on x86-64 every SPIR-V-builtprogram.bcof the test suite is byte-identical with and without it.ARM32 (AAPCS lowers vectors differently and needs its own wrapper ABI table), RISC-V32 and 32-bit Windows stay disabled.
Tests:
regression/test_spirv_struct_layout: struct buffers, by-value struct arguments, nested structs, tail padding, private arrays of structs, constant initializers, and aggregate loads, stores and SSA values (from a hand-written.ll). It has 38 wrong fields on i686 without the layout fix.regression/test_spirv_builtins: the builtins whose wrappers depend on the address bits or the calling convention, plus scoped atomics,work_group_barrierand sub-groups..spirvinputs are only registered on 64-bit hosts, andspirv/printf(the test from test spirv/printf segfaults on 32-bit architectures pocl/pocl#1880) andexample1get 32-bit twins.-msse2because of Build fails on i686:error: inlining failed in call to ‘always_inline’ ‘_mm_getcsr’: target specific option mismatchpocl/pocl#2097, and excludes the tests that fail on i686 regardless of SPIR-V (listed below). LLVM 21 is needed because before it, JITLink can't handleR_386_GOT32X. With Debian trixie's LLVM 19, the CPU JIT fails on i386 with "Unsupported i386 relocation:43", which breaks many OpenCL C tests too. That is independent of this PR and probably calls for gating the JIT on LLVM 21 for i386.Validation:
-DKERNELLIB_HOST_CPU_VARIANTS=distro): 346/357 pass. The 11 failures are identical with-DENABLE_SPIRV=OFF, so they're unrelated:kernel/test_printf(%ldofLONG_MIN);regression/test_signal_handlers*(the SIGFPE avoidance is x86-64 only);runtime/test_image_normalized_conv;runtime/test_event_freeandexamples/vecbuiltin*.regression/test_issue_2005(allocations beyond the 32-bit address space).