- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.7k
Labels
backport 1.10Change should be backported to the 1.10 releaseChange should be backported to the 1.10 releasebugIndicates an unexpected problem or unintended behaviorIndicates an unexpected problem or unintended behaviorcompiler:llvmFor issues that relate to LLVMFor issues that relate to LLVM
Description
Here is an MRE we tracked down from our real code:
julia> primitive type ByteString18 (18 * 8) end
julia> a = reinterpret(ByteString18, ntuple(_->0x0, 18))
ByteString18(0x000000000000000000000000000000000000)
julia> (a,) === (a,)
false
julia> (a,) === (a,)
true
julia> (a,) === (a,)
false
julia> (a,) === (a,)
false
julia> (a,) === (a,)
false
julia> (a,) === (a,)
trueThis is definitely wrong.
This reproduces for me on ARM Mac, x86 Linux, 1.10, and 1.12.
And it's not unique to reinterpret, it shows up with zext as well:
julia> primitive type ByteString18 (18 * 8) end
julia> a = Core.zext_int(ByteString18, 0x0)
ByteString18(0x000000000000000000000000000000000000)
julia> (a,) === (a,)  # should obviously be `true`
falseAnd also, it's not unique to being all 0s, it works for reinterpreting any values in there.
julia> a = reinterpret(ByteString18, ntuple(_->0xaf, 18)); C = 10000; sum(@eval ((a,) === (a,)) for _ in 1:C) / C
0.7306
So far, we've only ever seen this during constant-folding, but I'm not sure if that's 100% true or not.
Finally, as you'd expect, this issue doesn't seem to affect primitive types that have standard power-of-2 integer sizes: 1,2,4,8,16,32. But most of the rest are affected:
 ratio of times `(a,) === (a,)` returns `true` out of 3,000 iterations, for different primitive type byte-widths.
ratio of times `(a,) === (a,)` returns `true` out of 3,000 iterations, for different primitive type byte-widths.
Code to generate the above plot:
const MAX_PRIMITIVE_BYTE_STRING = 16 * 8
for BYTES in 1:MAX_PRIMITIVE_BYTE_STRING
    name = Symbol("ByteString$(BYTES)")
    BITS = BYTES * 8
    @eval begin
        primitive type $(name) $(BITS) end
    end
end
out = let iters = 3000, out = Float64[]
    for N in 1:32
        T = eval(Symbol("ByteString$(N)"))
        a = reinterpret(T, ntuple(_->0x0, N))
        push!(out, sum(@eval(($a,) === ($a,)) for _ in 1:iters) / iters)
    end
    out
end
using Plots
plot(out)
vline!([1,2,4,8,16,32])Seelengrab
Metadata
Metadata
Assignees
Labels
backport 1.10Change should be backported to the 1.10 releaseChange should be backported to the 1.10 releasebugIndicates an unexpected problem or unintended behaviorIndicates an unexpected problem or unintended behaviorcompiler:llvmFor issues that relate to LLVMFor issues that relate to LLVM