Does this really require compiler work? We already have @noinline
which is sufficient for this as far as I’m aware:
my_sqrt(x::Real) = x >= 0.0 ? sqrt(x) : my_sqrt_error(x);
@noinline my_sqrt_error(x) = throw(DomainError("my_sqrt requires inputs greater than 0, you gave $x which is less than 0"));
julia> @benchmark my_sqrt(x) setup=(x= 100*rand())
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min … max): 2.159 ns … 20.240 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 2.160 ns ┊ GC (median): 0.00%
Time (mean ± σ): 2.168 ns ± 0.192 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
█ ▁
▂█▁▁▁▁▁▁▁▁▁▂█▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▂▃ ▂
2.16 ns Histogram: frequency by time 2.21 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
julia> @benchmark sqrt(x) setup=(x= 100*rand())
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min … max): 2.159 ns … 11.370 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 2.160 ns ┊ GC (median): 0.00%
Time (mean ± σ): 2.167 ns ± 0.107 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
█ ▆ ▁ ▃ ▁
██▁▁▁▁▁▁▁▁▁▆█▁▁▁▁▁▁▁▁▁▁▃▁▁▁▁▁▁▁▁▁▁▁▄▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▄█ █
2.16 ns Histogram: log(frequency) by time 2.21 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
In fact, now that I look, it appears that whoever wrote the sqrt(::Float64)
method in Base already knew and took advantage of this:
julia> @code_typed sqrt(1.0)
CodeInfo(
1 ─ %1 = Base.lt_float(x, 0.0)::Bool
└── goto #3 if not %1
2 ─ invoke Base.Math.throw_complex_domainerror(:sqrt::Symbol, x::Float64)::Union{}
└── unreachable
3 ─ %5 = Base.Math.sqrt_llvm(x)::Float64
└── return %5
) => Float64