Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temporary variable inferred as Union{Bool, Int64} when calling rand() #20062

Closed
pkofod opened this issue Jan 16, 2017 · 3 comments
Closed

Temporary variable inferred as Union{Bool, Int64} when calling rand() #20062

pkofod opened this issue Jan 16, 2017 · 3 comments
Labels
compiler:inference Type inference domain:randomness Random number generation and the Random stdlib

Comments

@pkofod
Copy link
Contributor

pkofod commented Jan 16, 2017

Witnesses this when trying to hunt down another inference related issue. Return type is inferred, but what is the #temp#@_2::union{Bool, Int64} about? Does not happen for rand(1) (see bottom). On v0.5.0 release.

julia> foo() = rand()
foo (generic function with 1 method)

julia> @code_warntype foo()
Variables:
  #self#::#foo
  #temp#@_2::Union{Bool,Int64}
  #temp#@_3::Float64

Body:
  begin 
      $(Expr(:inbounds, false))
      # meta: location random.jl rand 227
      $(Expr(:inbounds, false))
      # meta: location random.jl rand 122
      $(Expr(:inbounds, false))
      # meta: location random.jl reserve_1 111
      unless ((Core.getfield)(Base.Random.GLOBAL_RNG,:idx)::Int64 === (Base.box)(Int64,(Base.sext_int)(Int64,Base.Random.MTCacheLength)))::Bool goto 19
      # meta: location random.jl gen_rand 107
      SSAValue(1) = (Core.getfield)(Base.Random.GLOBAL_RNG,:state)::Base.dSFMT.DSFMT_state
      SSAValue(0) = (Core.getfield)(Base.Random.GLOBAL_RNG,:vals)::Array{Float64,1}
      $(Expr(:invoke, LambdaInfo for dsfmt_fill_array_close1_open2!(::Base.dSFMT.DSFMT_state, ::Ptr{Float64}, ::Int64), :(Base.Random.dsfmt_fill_array_close1_open2!), SSAValue(1), :((Core.ccall)(:jl_array_ptr,(Core.apply_type)(Base.Ptr,Float64)::Type{Ptr{Float64}},(Core.svec)(Base.Any)::SimpleVector,SSAValue(0),0)::Ptr{Float64}), :((Base.arraylen)((Core.getfield)(Base.Random.GLOBAL_RNG,:vals)::Array{Float64,1})::Int64))) # line 108:
      # meta: location random.jl mt_setfull! 102
      (Core.setfield!)(Base.Random.GLOBAL_RNG,:idx,0)::Int64
      # meta: pop location
      # meta: pop location
      #temp#@_2::Union{Bool,Int64} = 0
      goto 21
      19: 
      #temp#@_2::Union{Bool,Int64} = false
      21: 
      # meta: pop location
      $(Expr(:inbounds, :pop))
      #temp#@_2::Union{Bool,Int64}
      $(Expr(:inbounds, false))
      # meta: location random.jl rand_inbounds 118
      $(Expr(:inbounds, false))
      # meta: location random.jl rand_inbounds 117
      $(Expr(:inbounds, false))
      # meta: location random.jl mt_pop! 104
      $(Expr(:inbounds, true))
      SSAValue(2) = (Core.getfield)(Base.Random.GLOBAL_RNG,:vals)::Array{Float64,1}
      SSAValue(3) = (Base.box)(Int64,(Base.add_int)((Core.getfield)(Base.Random.GLOBAL_RNG,:idx)::Int64,1))
      (Core.setfield!)(Base.Random.GLOBAL_RNG,:idx,SSAValue(3))::Int64
      #temp#@_3::Float64 = (Base.arrayref)(SSAValue(2),SSAValue(3))::Float64
      goto 38
      $(Expr(:inbounds, :pop))
      38: 
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      return (Base.box)(Base.Float64,(Base.sub_float)(#temp#@_3::Float64,1.0))
  end::Float64
julia> workspace()
julia> foo() = rand(1)
foo (generic function with 1 method)

julia> @code_warntype foo()
Variables:
  #self#::#foo

Body:
  begin 
      # meta: location random.jl rand 230
      # meta: location random.jl rand 229
      # meta: location random.jl rand 297
      # meta: location random.jl rand 300
      SSAValue(0) = (Core.ccall)(:jl_new_array,(Core.apply_type)(Core.Array,Float64,1)::Type{Array{Float64,1}},(Core.svec)(Core.Any,Core.Any)::SimpleVector,Array{Float64,1},0,(Base.tuple)(1)::Tuple{Int64},0)::Array{Float64,1}
      # meta: pop location
      # meta: pop location
      # meta: pop location
      # meta: pop location
      return $(Expr(:invoke, LambdaInfo for rand!(::MersenneTwister, ::Array{Float64,1}, ::Int64, ::Type{Base.Random.CloseOpen}), :(Base.Random.rand!), :(Base.Random.GLOBAL_RNG), SSAValue(0), :((Base.arraylen)(SSAValue(0))::Int64), :(Base.Random.CloseOpen)))
  end::Array{Float64,1}
@pkofod pkofod changed the title Temporary variable inferred as Union{Bool, Int64} calling rand() Temporary variable inferred as Union{Bool, Int64} when calling rand() Jan 16, 2017
@yuyichao
Copy link
Contributor

It's in rand(1) too, just not inlined. I thought we already had an issue / pr for it but couldn't find it. This should not affect performance.

@pkofod
Copy link
Contributor Author

pkofod commented Jan 16, 2017

This should not affect performance.

sure, I just found it odd

@kshyatt kshyatt added the compiler:inference Type inference label Jan 17, 2017
@GregPlowman
Copy link
Contributor

I too have found that this pollutes @code_warntype output with red.
On v0.5.0, I think the offending code is in random.jl (lines 111-114)

@inline reserve_1(r::MersenneTwister) = mt_empty(r) && gen_rand(r)
# `reserve` allows one to call `rand_inbounds` n times
# precondition: n <= MTCacheLength
@inline reserve(r::MersenneTwister, n::Int) = mt_avail(r) < n && gen_rand(r)

gen_rand(r) always returns 0, so reserve() returns Union{Bool,Int}

Overwriting these seemed to fix the inference for me:

@inline reserve_1(r::MersenneTwister) = mt_empty(r) ? gen_rand(r) : 0
@inline reserve(r::MersenneTwister, n::Int) = (mt_avail(r) < n) ? gen_rand(r) : 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:inference Type inference domain:randomness Random number generation and the Random stdlib
Projects
None yet
Development

No branches or pull requests

5 participants