Short-circuit deepcopy for bits types (#31822)
This allows the compiler to elide the entire deepcopy call
in these cases.
Example:
julia> struct Foo; i::Int; end
julia> @code_warntype deepcopy(Foo(1))
Variables
#self#::Core.Compiler.Const(deepcopy, false)
x::Foo
Body::Foo
1 ─ %1 = Base.IdDict()::IdDict{Any,Any}
│ %2 = Base.deepcopy_internal(x, %1)::Foo
│ %3 = Base.typeof(x)::Core.Compiler.Const(Foo, false)
│ %4 = Core.typeassert(%2, %3)::Foo
└── return %4
julia> function fastdeepcopy(a)
isbitstype(typeof(a)) && return a
return deepcopy(a)
end
fastdeepcopy (generic function with 1 method)
julia> @code_warntype fastdeepcopy(Foo(1))
Variables
#self#::Core.Compiler.Const(fastdeepcopy, false)
a::Foo
Body::Foo
1 ─ %1 = Main.typeof(a)::Core.Compiler.Const(Foo, false)
│ %2 = Main.isbitstype(%1)::Core.Compiler.Const(true, true)
│ %2
└── return a
2 ─ Core.Compiler.Const(:(goto %7), false)
│ Core.Compiler.Const(false, false)
│ Core.Compiler.Const(:(Main.deepcopy(a)), false)
└── Core.Compiler.Const(:(return %7), false)
julia> @code_native fastdeepcopy(Foo(1))
.text
; ┌ @ REPL[12]:2 within `fastdeepcopy'
movq (%rdi), %rax
retq
nopw %cs:(%rax,%rax)
; └