• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37632

26 Sep 2023 06:44AM UTC coverage: 86.999% (-0.9%) from 87.914%
#37632

push

local

web-flow
inference: make `throw` block deoptimization concrete-eval friendly (#49235)

The deoptimization can sometimes destroy the effects analysis and
disable [semi-]concrete evaluation that is otherwise possible. This is
because the deoptimization was designed with the type domain
profitability in mind (#35982), and hasn't been adequately considering
the effects domain.

This commit makes the deoptimization aware of the effects domain more
and enables the `throw` block deoptimization only when the effects
already known to be ineligible for concrete-evaluation.

In our current effect system, `ALWAYS_FALSE`/`false` means that the
effect can not be refined to `ALWAYS_TRUE`/`true` anymore (unless given
user annotation later). Therefore we can enable the `throw` block
deoptimization without hindering the chance of concrete-evaluation when
any of the following conditions are met:
- `effects.consistent === ALWAYS_FALSE`
- `effects.effect_free === ALWAYS_FALSE`
- `effects.terminates === false`
- `effects.nonoverlayed === false`

Here are some numbers:

| Metric | master | this commit | #35982 reverted (set
`unoptimize_throw_blocks=false`) |

|-------------------------|-----------|-------------|--------------------------------------------|
| Base (seconds) | 15.579300 | 15.206645 | 15.296319 |
| Stdlibs (seconds) | 17.919013 | 17.667094 | 17.738128 |
| Total (seconds) | 33.499279 | 32.874737 | 33.035448 |
| Precompilation (seconds) | 49.967516 | 49.421121 | 49.999998 |
| First time `plot(rand(10,3))` [^1] | `2.476678 seconds (11.74 M
allocations)` | `2.430355 seconds (11.77 M allocations)` | `2.514874
seconds (11.64 M allocations)` |
| First time `solve(prob, QNDF())(5.0)` [^2] | `4.469492 seconds (15.32
M allocations)` | `4.499217 seconds (15.41 M allocations)` | `4.470772
seconds (15.38 M allocations)` |

[^1]: With disabling precompilation of Plots.jl.
[^2]: With disabling precompilation of OrdinaryDiffEq.

These numbers ma... (continued)

7 of 7 new or added lines in 1 file covered. (100.0%)

73407 of 84377 relevant lines covered (87.0%)

11275130.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.26
/base/ryu/Ryu.jl
1
module Ryu
2

3
using .Base.Libc
4
import .Base: significand_bits, significand_mask, exponent_bits, exponent_mask, exponent_bias, exponent_max, uinttype
5

6
include("utils.jl")
7
include("shortest.jl")
8
include("fixed.jl")
9
include("exp.jl")
10

11
"""
12
    Ryu.neededdigits(T)
13

14
Number of digits necessary to represent type `T` in fixed-precision decimal.
15
"""
16
neededdigits(::Type{Float64}) = 309 + 17
×
17
neededdigits(::Type{Float32}) = 39 + 9 + 2
×
18
neededdigits(::Type{Float16}) = 9 + 5 + 9
×
19

20
"""
21
    Ryu.writeshortest(x, plus=false, space=false, hash=true, precision=-1, expchar=UInt8('e'), padexp=false, decchar=UInt8('.'), typed=false, compact=false)
22
    Ryu.writeshortest(buf::Vector{UInt8}, pos::Int, x, args...)
23

24
Convert a float value `x` into its "shortest" decimal string, which can be parsed back to the same value.
25
This function allows achieving the `%g` printf format.
26
Note the 2nd method allows passing in a byte buffer and position directly; callers must ensure the buffer has sufficient room to hold the entire decimal string.
27

28
Various options for the output format include:
29
  * `plus`: for positive `x`, prefix decimal string with a `'+'` character
30
  * `space`: for positive `x`, prefix decimal string with a `' '` character; overridden if `plus=true`
31
  * `hash`: whether the decimal point should be written, even if no additional digits are needed for precision
32
  * `precision`: minimum number of digits to be included in the decimal string; extra `'0'` characters will be added for padding if necessary
33
  * `expchar`: character to use exponent component in scientific notation
34
  * `padexp`: whether two digits should always be written, even for single-digit exponents (e.g. `e+1` becomes `e+01`)
35
  * `decchar`: decimal point character to be used
36
  * `typed`: whether additional type information should be printed for `Float16` / `Float32`
37
  * `compact`: output will be limited to 6 significant digits
38
"""
39
function writeshortest(x::T,
×
40
        plus::Bool=false,
41
        space::Bool=false,
42
        hash::Bool=true,
43
        precision::Integer=-1,
44
        expchar::UInt8=UInt8('e'),
45
        padexp::Bool=false,
46
        decchar::UInt8=UInt8('.'),
47
        typed::Bool=false,
48
        compact::Bool=false) where {T <: Base.IEEEFloat}
49
    buf = Base.StringVector(neededdigits(T))
×
50
    pos = writeshortest(buf, 1, x, plus, space, hash, precision, expchar, padexp, decchar, typed, compact)
×
51
    return String(resize!(buf, pos - 1))
×
52
end
53

54
"""
55
    Ryu.writefixed(x, precision, plus=false, space=false, hash=false, decchar=UInt8('.'), trimtrailingzeros=false)
56
    Ryu.writefixed(buf::Vector{UInt8}, pos::Int, x, args...)
57

58
Convert a float value `x` into a "fixed" size decimal string of the provided precision.
59
This function allows achieving the `%f` printf format.
60
Note the 2nd method allows passing in a byte buffer and position directly; callers must ensure the buffer has sufficient room to hold the entire decimal string.
61

62
Various options for the output format include:
63
  * `plus`: for positive `x`, prefix decimal string with a `'+'` character
64
  * `space`: for positive `x`, prefix decimal string with a `' '` character; overridden if `plus=true`
65
  * `hash`: whether the decimal point should be written, even if no additional digits are needed for precision
66
  * `precision`: minimum number of significant digits to be included in the decimal string; extra `'0'` characters will be added for padding if necessary
67
  * `decchar`: decimal point character to be used
68
  * `trimtrailingzeros`: whether trailing zeros of fractional part should be removed
69
"""
70
function writefixed(x::T,
39✔
71
    precision::Integer,
72
    plus::Bool=false,
73
    space::Bool=false,
74
    hash::Bool=false,
75
    decchar::UInt8=UInt8('.'),
76
    trimtrailingzeros::Bool=false) where {T <: Base.IEEEFloat}
77
    buf = Base.StringVector(precision + neededdigits(T))
124✔
78
    pos = writefixed(buf, 1, x, precision, plus, space, hash, decchar, trimtrailingzeros)
19✔
79
    return String(resize!(buf, pos - 1))
19✔
80
end
81

82
"""
83
    Ryu.writeexp(x, precision, plus=false, space=false, hash=false, expchar=UInt8('e'), decchar=UInt8('.'), trimtrailingzeros=false)
84
    Ryu.writeexp(buf::Vector{UInt8}, pos::Int, x, args...)
85

86
Convert a float value `x` into a scientific notation decimal string.
87
This function allows achieving the `%e` printf format.
88
Note the 2nd method allows passing in a byte buffer and position directly; callers must ensure the buffer has sufficient room to hold the entire decimal string.
89

90
Various options for the output format include:
91
  * `plus`: for positive `x`, prefix decimal string with a `'+'` character
92
  * `space`: for positive `x`, prefix decimal string with a `' '` character; overridden if `plus=true`
93
  * `hash`: whether the decimal point should be written, even if no additional digits are needed for precision
94
  * `precision`: minimum number of significant digits to be included in the decimal string; extra `'0'` characters will be added for padding if necessary
95
  * `expchar`: character to use exponent component in scientific notation
96
  * `decchar`: decimal point character to be used
97
  * `trimtrailingzeros`: whether trailing zeros should be removed
98
"""
99
function writeexp(x::T,
×
100
    precision::Integer,
101
    plus::Bool=false,
102
    space::Bool=false,
103
    hash::Bool=false,
104
    expchar::UInt8=UInt8('e'),
105
    decchar::UInt8=UInt8('.'),
106
    trimtrailingzeros::Bool=false) where {T <: Base.IEEEFloat}
107
    buf = Base.StringVector(precision + neededdigits(T))
×
108
    pos = writeexp(buf, 1, x, precision, plus, space, hash, expchar, decchar, trimtrailingzeros)
×
109
    return String(resize!(buf, pos - 1))
×
110
end
111

112
function Base.show(io::IO, x::T, forceuntyped::Bool=false, fromprint::Bool=false) where {T <: Base.IEEEFloat}
904,021✔
113
    compact = get(io, :compact, false)::Bool
2,056,600✔
114
    buf = Base.StringVector(neededdigits(T))
465,066✔
115
    typed = !forceuntyped && !compact && get(io, :typeinfo, Any) != typeof(x)
473,853✔
116
    pos = writeshortest(buf, 1, x, false, false, true, -1,
465,066✔
117
        (x isa Float32 && !fromprint) ? UInt8('f') : UInt8('e'), false, UInt8('.'), typed, compact)
118
    write(io, resize!(buf, pos - 1))
930,132✔
119
    return
465,066✔
120
end
121

122
function Base.string(x::T) where {T <: Base.IEEEFloat}
860✔
123
    buf = Base.StringVector(neededdigits(T))
860✔
124
    pos = writeshortest(buf, 1, x, false, false, true, -1,
860✔
125
        UInt8('e'), false, UInt8('.'), false, false)
126
    return String(resize!(buf, pos - 1))
860✔
127
end
128

129
Base.print(io::IO, x::Union{Float16, Float32}) = show(io, x, true, true)
10✔
130

131
end # module
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc