diff --git a/src/pocl/device/quirks.jl b/src/pocl/device/quirks.jl index a389d6aac..56359bf0c 100644 --- a/src/pocl/device/quirks.jl +++ b/src/pocl/device/quirks.jl @@ -46,6 +46,18 @@ end @gputhrow "BoundsError" "Out-of-bounds array access" end +# range.jl +# From Metal.jl to avoid widemul and Int128, which the SPIR-V back-end cannot lower. +# Unlike Metal.jl, this covers all the types Base's method does: `widemul` of a range of +# `Int32` and an `Int64` index widens to `Int128` as well. +@static if VERSION >= v"1.12.0-DEV.1736" # Partially reverts JuliaLang/julia PR #56750 + const BitInteger64 = Union{Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64} + @device_override function Base.checkbounds(::Type{Bool}, v::StepRange{<:BitInteger64, <:BitInteger64}, i::BitInteger64) + @inline + return checkindex(Bool, eachindex(IndexLinear(), v), i) + end +end + # trig.jl @device_override @noinline Base.Math.sincos_domain_error(x) = @gputhrow "DomainError" "sincos(x) is only defined for finite x" diff --git a/test/runtests.jl b/test/runtests.jl index 7e9c1b3ee..4508a0088 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -76,6 +76,34 @@ end @test config.target.extensions == "+SPV_KHR_expect_assume" end +# Julia 1.12 checks the bounds of a `StepRange` in 128-bit integers, which the SPIR-V back-end +# cannot lower; this is reached e.g. by indexing a strided view with `--check-bounds=yes` +@testset "POCL bounds checks of a StepRange" begin + @kernel function steprange_checkbounds!(out, r) + I = @index(Global, Linear) + @inbounds out[I] = checkbounds(Bool, r, I - 2) + end + @testset "$(typeof(r))" for r in (1:2:8, 9:-3:1, UInt64(1):UInt64(2):UInt64(8), Int32(1):Int32(2):Int32(8)) + n = Int(length(r)) + out = zeros(Bool, n + 3) + steprange_checkbounds!(CPU())(out, r; ndrange = length(out)) + synchronize(CPU()) + @test out == [checkbounds(Bool, r, i) for i in -1:(n + 1)] + end + + A = zeros(Int, 8, 10) + v = view(A, 1:2:8, 2:2:10) + @kernel function strided_view_fill!(v) + I = @index(Global, Cartesian) + v[I] = 1 + end + strided_view_fill!(CPU())(v; ndrange = size(v)) + synchronize(CPU()) + ref = zeros(Int, 8, 10) + ref[1:2:8, 2:2:10] .= 1 + @test A == ref +end + # `randn`/`randexp` for Float16 route through Random's table-free fallback, whose polar # transform overflows in Float16 and whose `log1p` isn't available for Float16 on the # device. The device overlays compute in Float32 and convert, so results stay finite.