Commit 02c46d7
committed
introduce
This commit introduces new compiler annotation named `@noinfer`, which
requests the compiler to avoid excess inference.
In order to discuss `@noinfer`, it would help a lot to understand the
behavior of `@nospecialize`.
Its docstring says simply:
> This is only a hint for the compiler to avoid excess code generation.
More specifically, it works by _suppressing dispatches_ with complex
runtime types of the annotated arguments. This could be understood with
the example below:
```julia
julia> function invokef(f, itr)
local r = 0
r += f(itr[1])
r += f(itr[2])
r += f(itr[3])
r
end;
julia> _isa = isa; # just for the sake of explanation, global variable to prevent inling
julia> f(a) = _isa(a, Function);
julia> g(@nospecialize a) = _isa(a, Function);
julia> dispatchonly = Any[sin, muladd, nothing]; # untyped container can cause excessive runtime dispatch
julia> @code_typed invokef(f, dispatchonly)
CodeInfo(
1 ─ %1 = π (0, Int64)
│ %2 = Base.arrayref(true, itr, 1)::Any
│ %3 = (f)(%2)::Any
│ %4 = (%1 + %3)::Any
│ %5 = Base.arrayref(true, itr, 2)::Any
│ %6 = (f)(%5)::Any
│ %7 = (%4 + %6)::Any
│ %8 = Base.arrayref(true, itr, 3)::Any
│ %9 = (f)(%8)::Any
│ %10 = (%7 + %9)::Any
└── return %10
) => Any
julia> @code_typed invokef(g, dispatchonly)
CodeInfo(
1 ─ %1 = π (0, Int64)
│ %2 = Base.arrayref(true, itr, 1)::Any
│ %3 = invoke f(%2::Any)::Any
│ %4 = (%1 + %3)::Any
│ %5 = Base.arrayref(true, itr, 2)::Any
│ %6 = invoke f(%5::Any)::Any
│ %7 = (%4 + %6)::Any
│ %8 = Base.arrayref(true, itr, 3)::Any
│ %9 = invoke f(%8::Any)::Any
│ %10 = (%7 + %9)::Any
└── return %10
) => Any
```
The calls of `f` remain to be `:call` expression (thus dispatched and
compiled at runtime) while the calls of `g` are resolved as `:invoke`
expressions. This is because `@nospecialize` requests the compiler to
give up compiling `g` with concrete argument types but with precisely
declared argument types, and in this way `invokef(g, dispatchonly)` will
avoid runtime dispatches and accompanying JIT compilations (i.e. "excess
code generation").
The problem here is, it influences dispatch only, does not intervene
into inference in anyway. So there is still a possibility of "excess
inference" when the compiler sees a considerable complexity of argument
types during inference:
```julia
julia> withinfernce = tuple(sin, muladd, "foo"); # typed container can cause excessive inference
julia> @time @code_typed invokef(f, withinfernce);
0.000812 seconds (3.77 k allocations: 217.938 KiB, 94.34% compilation time)
julia> @time @code_typed invokef(g, withinfernce);
0.000753 seconds (3.77 k allocations: 218.047 KiB, 92.42% compilation time)
```
The purpose of this PR is basically to provide a more drastic way to
avoid excess compilation.
Here are some ideas to implement the functionality:
1. make `@nospecialize` avoid inference also
2. add noinfer effect when `@nospecialize`d method is annotated as `@noinline` also
3. implement as `@pure`-like boolean annotation to request noinfer effect on top of `@nospecialize`
4. implement as annotation that is orthogonal to `@nospecialize`
After trying 1 ~ 3., I decided to submit 3. for now, because I think the
interface is ready to be experimented.
This is almost same as what Jameson has done at <vtjnash@8ab7b6b>.
It turned out that this approach performs very badly because some of
`@nospecialize`'d arguments still need inference to perform reasonably.
For example, it's obvious that the following definition of
`getindex(@nospecialize(t::Tuple), i::Int)` would perform very badly if
`@nospecialize` blocks inference, because of a lack of useful type
information for succeeding optimizations:
<https://github.com/JuliaLang/julia/blob/12d364e8249a07097a233ce7ea2886002459cc50/base/tuple.jl#L29-L30>
The important observation is that we often use `@nospecialize` even when
we expect inference to forward type and constant information.
Adversely, we may be able to exploit the fact that we usually don't
expect inference to forward information to a callee when we annotate it
as `@noinline`.
So the idea is to enable the inference suppression when `@nospecialize`'d
method is annotated as `@noinline` also.
It's a reasonable choice, and could be implemented efficiently after <#41922>.
But it sounds a bit weird to me to associate no infer effect with
`@noinline`, and I also think there may be some cases we want to inline
a method while _partially_ avoiding inference, e.g.:
```julia
@noinline function twof(@nospecialize(f), n) # we really want not to
inline this method body ?
if occursin('+', string(typeof(f).name.name::Symbol))
2 + n
elseif occursin('*', string(typeof(f).name.name::Symbol))
2n
else
zero(n)
end
end
```
So this is what this commit implements. It basically replaces the previous
`@noinline` flag with newly-introduced annotation named `@noinfer`. It's
still associated with `@nospecialize` and it only has effect when used
together with `@nospecialize`, but now it's not associated to `@noinline`
at least, and it would help us reason about the behavior of `@noinfer`
and experiment its effect more reliably:
```julia
Base.@noinfer function twof(@nospecialize(f), n) # the compiler may or not inline this method
if occursin('+', string(typeof(f).name.name::Symbol))
2 + n
elseif occursin('*', string(typeof(f).name.name::Symbol))
2n
else
zero(n)
end
end
```
Actually, we can have `@nospecialize` and `@noinfer` separately, and it
would allow us to configure compilation strategies in a more
fine-grained way.
```julia
function noinfspec(Base.@noinfer(f), @nospecialize(g))
...
end
```
I'm fine with this approach, if initial experiments show `@noinfer` is
useful.@noinfer macro to tell the compiler to avoid excess inference1 parent 1843201 commit 02c46d7
File tree
15 files changed
+250
-32
lines changed- base
- compiler
- ssair
- doc/src/base
- src
- stdlib/Serialization/src
- test/compiler
15 files changed
+250
-32
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
347 | 347 | | |
348 | 348 | | |
349 | 349 | | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
350 | 353 | | |
351 | 354 | | |
352 | 355 | | |
| |||
593 | 596 | | |
594 | 597 | | |
595 | 598 | | |
596 | | - | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
597 | 604 | | |
598 | 605 | | |
599 | 606 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
803 | 803 | | |
804 | 804 | | |
805 | 805 | | |
806 | | - | |
| 806 | + | |
807 | 807 | | |
808 | 808 | | |
809 | 809 | | |
| |||
818 | 818 | | |
819 | 819 | | |
820 | 820 | | |
821 | | - | |
| 821 | + | |
822 | 822 | | |
823 | 823 | | |
824 | 824 | | |
| |||
827 | 827 | | |
828 | 828 | | |
829 | 829 | | |
830 | | - | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
831 | 835 | | |
832 | 836 | | |
833 | 837 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
99 | 104 | | |
100 | 105 | | |
101 | 106 | | |
| |||
144 | 149 | | |
145 | 150 | | |
146 | 151 | | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
147 | 166 | | |
148 | 167 | | |
149 | 168 | | |
| |||
196 | 215 | | |
197 | 216 | | |
198 | 217 | | |
199 | | - | |
| 218 | + | |
200 | 219 | | |
201 | 220 | | |
202 | 221 | | |
| |||
205 | 224 | | |
206 | 225 | | |
207 | 226 | | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
208 | 232 | | |
209 | 233 | | |
210 | 234 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
61 | 60 | | |
62 | | - | |
| 61 | + | |
| 62 | + | |
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
90 | 123 | | |
91 | 124 | | |
92 | 125 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
336 | 336 | | |
337 | 337 | | |
338 | 338 | | |
339 | | - | |
340 | | - | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
341 | 343 | | |
342 | | - | |
| 344 | + | |
343 | 345 | | |
344 | 346 | | |
345 | 347 | | |
| |||
349 | 351 | | |
350 | 352 | | |
351 | 353 | | |
352 | | - | |
353 | | - | |
| 354 | + | |
| 355 | + | |
354 | 356 | | |
355 | | - | |
| 357 | + | |
356 | 358 | | |
357 | 359 | | |
358 | | - | |
| 360 | + | |
359 | 361 | | |
360 | 362 | | |
361 | | - | |
| 363 | + | |
362 | 364 | | |
363 | 365 | | |
364 | 366 | | |
| |||
371 | 373 | | |
372 | 374 | | |
373 | 375 | | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
374 | 409 | | |
375 | 410 | | |
376 | 411 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
273 | 273 | | |
274 | 274 | | |
275 | 275 | | |
| 276 | + | |
| 277 | + | |
276 | 278 | | |
277 | 279 | | |
278 | 280 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| 62 | + | |
62 | 63 | | |
63 | | - | |
| 64 | + | |
64 | 65 | | |
65 | 66 | | |
66 | 67 | | |
| |||
403 | 404 | | |
404 | 405 | | |
405 | 406 | | |
| 407 | + | |
406 | 408 | | |
407 | 409 | | |
408 | 410 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
671 | 671 | | |
672 | 672 | | |
673 | 673 | | |
| 674 | + | |
674 | 675 | | |
675 | 676 | | |
676 | 677 | | |
| |||
1526 | 1527 | | |
1527 | 1528 | | |
1528 | 1529 | | |
| 1530 | + | |
1529 | 1531 | | |
1530 | 1532 | | |
1531 | 1533 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2053 | 2053 | | |
2054 | 2054 | | |
2055 | 2055 | | |
2056 | | - | |
2057 | | - | |
2058 | 2056 | | |
2059 | | - | |
| 2057 | + | |
2060 | 2058 | | |
2061 | 2059 | | |
2062 | 2060 | | |
| |||
2100 | 2098 | | |
2101 | 2099 | | |
2102 | 2100 | | |
2103 | | - | |
2104 | | - | |
2105 | | - | |
| 2101 | + | |
2106 | 2102 | | |
2107 | 2103 | | |
2108 | 2104 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2329 | 2329 | | |
2330 | 2330 | | |
2331 | 2331 | | |
2332 | | - | |
| 2332 | + | |
2333 | 2333 | | |
2334 | 2334 | | |
2335 | 2335 | | |
| |||
2348 | 2348 | | |
2349 | 2349 | | |
2350 | 2350 | | |
| 2351 | + | |
2351 | 2352 | | |
2352 | | - | |
| 2353 | + | |
2353 | 2354 | | |
2354 | 2355 | | |
2355 | 2356 | | |
| |||
2368 | 2369 | | |
2369 | 2370 | | |
2370 | 2371 | | |
| 2372 | + | |
2371 | 2373 | | |
2372 | 2374 | | |
2373 | | - | |
| 2375 | + | |
2374 | 2376 | | |
2375 | 2377 | | |
2376 | 2378 | | |
2377 | 2379 | | |
2378 | | - | |
| 2380 | + | |
2379 | 2381 | | |
2380 | 2382 | | |
2381 | 2383 | | |
| |||
2401 | 2403 | | |
2402 | 2404 | | |
2403 | 2405 | | |
| 2406 | + | |
2404 | 2407 | | |
2405 | | - | |
| 2408 | + | |
2406 | 2409 | | |
2407 | 2410 | | |
2408 | 2411 | | |
| |||
2428 | 2431 | | |
2429 | 2432 | | |
2430 | 2433 | | |
| 2434 | + | |
2431 | 2435 | | |
2432 | 2436 | | |
2433 | 2437 | | |
| |||
0 commit comments