From aa6f3a39c6b1847f9dfe4b3584d4ce73a2a82f4e Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 16 Oct 2026 17:33:18 +0200 Subject: [PATCH] Use GPUToolbox's overrides of Base methods that use Int128. SPIR-V doesn't support 128-bit integers, which Base uses to compare `Rational`s by multiplying out their denominators. Stack GPUToolbox's `int128_overrides`, which compute these products as pairs of 64-bit words. --- Project.toml | 2 +- src/compiler/compilation.jl | 7 +++++-- test/device/intrinsics.jl | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 1c57f59a7..e39d47920 100644 --- a/Project.toml +++ b/Project.toml @@ -43,7 +43,7 @@ CEnum = "0.5, 1" ExprTools = "0.1" GPUArrays = "12.1" GPUCompiler = "2.13" -GPUToolbox = "3.3.1" +GPUToolbox = "3.4" KernelAbstractions = "0.10" KernelInterface = "0.4" LLVM = "10" diff --git a/src/compiler/compilation.jl b/src/compiler/compilation.jl index 7d2a95245..2bfff9c81 100644 --- a/src/compiler/compilation.jl +++ b/src/compiler/compilation.jl @@ -35,12 +35,15 @@ GPUCompiler.runtime_module(::oneAPICompilerJob) = oneAPI GPUCompiler.kernel_state_type(::oneAPICompilerJob) = KernelState +# SPIR-V doesn't support 128-bit integers, so keep 64-bit integer math (e.g. `Rational` +# comparisons) that Base computes with them out of Int128 function GPUCompiler.method_tables(job::oneAPICompilerJob) if job.config.target.supports_fp64 - (method_table, SPIRVIntrinsics.method_table) + (method_table, SPIRVIntrinsics.method_table, GPUToolbox.Overlays.int128_overrides) else # keep single-precision math that Base computes in Float64 out of double precision - (method_table, SPIRVIntrinsics.method_table, GPUToolbox.Overlays.float64_overrides) + (method_table, SPIRVIntrinsics.method_table, GPUToolbox.Overlays.float64_overrides, + GPUToolbox.Overlays.int128_overrides) end end diff --git a/test/device/intrinsics.jl b/test/device/intrinsics.jl index 6130a8794..ce377476f 100644 --- a/test/device/intrinsics.jl +++ b/test/device/intrinsics.jl @@ -44,6 +44,29 @@ end @test testf(a->exp.(a), Matrix{ComplexF32}([1.0 + 1.0im 1.0 - 1.0im; -1.0 + 1.0im -1.0 - 1.0im])) end + + # Base compares rationals using the 128-bit products of their numerators and + # denominators, which GPUToolbox computes in 64-bit words instead + @testset "rational comparisons" begin + # constructing the rational on the device needs `checked_neg`, which the SPIR-V + # translator can't compile (`llvm.ssub.with.overflow`) + r = 3 // 2 + xs = Float32[0, -1, 1.4, 1.5, 1.6, Inf, NaN] + @test Array(map(x -> x < r, oneArray(xs))) == (xs .< r) + + qs = [1//3, -5//7, 3//2, typemax(Int)//2, 2^40//3, -typemax(Int)//(2^40 + 1)] + ns = [0, -1, 2, 2^35, typemax(Int), typemin(Int)] + fs = Float32[0.3, -0.7, 1.5, 2f0^62, 3.6f11, -Inf] + for op in (<, <=, cmp) + @test Array(op.(oneArray(qs), oneArray(fs))) == op.(qs, fs) + @test Array(op.(oneArray(fs), oneArray(qs))) == op.(fs, qs) + end + for op in (<, <=) + @test Array(op.(oneArray(qs), oneArray(reverse(qs)))) == op.(qs, reverse(qs)) + @test Array(op.(oneArray(qs), oneArray(ns))) == op.(qs, ns) + @test Array(op.(oneArray(ns), oneArray(qs))) == op.(ns, qs) + end + end end