You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/lecture_06/lecture.md
+22-20Lines changed: 22 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -199,7 +199,28 @@ CodeInfo(
199
199
```
200
200
201
201
#### Code Typing
202
-
**Code typing** is the process in which the compiler attaches types to variables and tries to infer types of objects returned from called functions. If the compiler fails to infer the returned type, it will give the variable type `Any`, in which case a dynamic dispatch will be used in subsequent operations with the variable. Inspecting typed code is therefore important for detecting type instabilities (the process can be difficult and error prone, fortunately, new tools like `Jet.jl` may simplify this task). The output of typing can be inspected using`@code_typed`macro. If you know the types of function arguments, aka function signature, you can call directly function`InteractiveUtils.code_typed(nextfib, (typeof(3),))`.
202
+
**Code typing** is the process in which the compiler attaches types to variables and tries to infer types of objects returned from called functions. If the compiler fails to infer the returned type, it will give the variable type `Any`, in which case a dynamic dispatch will be used in subsequent operations with the variable. Inspecting typed code is therefore important for detecting type instabilities (the process can be difficult and error prone, fortunately, new tools like `Jet.jl` may simplify this task). The output of typing can be inspected using`@code_typed`macro. If you know the types of function arguments, aka function signature, you can call directly function`InteractiveUtils.code_typed(nextfib, (typeof(3),))`. By default, the `@code_typed` shows the output after **typing** and **optimization**. Turing off optimization to see the outcome of just typing, we get
203
+
```julia
204
+
julia> @code_typed optimize=false nextfib(3)
205
+
CodeInfo(
206
+
1 ─ %1 = Main.one(n)::Core.Const(1)
207
+
│ %2 = Main.one(n)::Core.Const(1)
208
+
│ (a = %1)::Core.Const(1)
209
+
└── (b = %2)::Core.Const(1)
210
+
2 ┄ %5 = (b < n)::Bool
211
+
└── goto #4 if not %5
212
+
3 ─ %7 = b::Int64
213
+
│ %8 = (a + b)::Int64
214
+
│ (a = %7)::Int64
215
+
│ (b = %8)::Int64
216
+
└── goto #2
217
+
4 ─ return b
218
+
) => Int64
219
+
```
220
+
Note that the same view of the code is offered by the `@code_warntype`macro, which we have seen in the previous [lecture](@ref perf_lecture). The main difference from `@code_typed` is that it highlights type instabilities with red color and shows only unoptimized view of the code.
221
+
222
+
Let's now look at the output after the optimization pass
223
+
203
224
```julia
204
225
julia> @code_typed nextfib(3)
205
226
CodeInfo(
@@ -223,25 +244,6 @@ We can see that
223
244
224
245
When we have called `@code_lower`, the role of types of arguments was in selecting - via multiple dispatch - the appropriate function body among different methods. Contrary in`@code_typed`, the types of parameters determine the choice of inner methods that need to be called (again with multiple dispatch). This process can trigger other optimization, such as inlining, as seen in the case of `one(n)` being replaced with `1` directly, though here this replacement is hidden in the `φ`function.
225
246
226
-
Note that the same view of the code is offered by the `@code_warntype`macro, which we have seen in the previous [lecture](@ref perf_lecture). The main difference from `@code_typed` is that it highlights type instabilities with red color and shows only unoptimized view of the code. You can view the unoptimized code with a keyword argument `optimize=false`:
227
-
```julia
228
-
julia> @code_typed optimize=false nextfib(3)
229
-
CodeInfo(
230
-
1 ─ %1 = Main.one(n)::Core.Const(1)
231
-
│ %2 = Main.one(n)::Core.Const(1)
232
-
│ (a = %1)::Core.Const(1)
233
-
└── (b = %2)::Core.Const(1)
234
-
2 ┄ %5 = (b < n)::Bool
235
-
└── goto #4 if not %5
236
-
3 ─ %7 = b::Int64
237
-
│ %8 = (a + b)::Int64
238
-
│ (a = %7)::Int64
239
-
│ (b = %8)::Int64
240
-
└── goto #2
241
-
4 ─ return b
242
-
) => Int64
243
-
```
244
-
245
247
#### Lowering to LLVM IR
246
248
Julia uses the LLVM compiler framework to generate machine code. LLVM stands for low-level virtual machine and it is basis of many modern compilers (see [wiki](https://en.wikipedia.org/wiki/LLVM)).
247
249
We can see the textual form of code lowered to LLVM IR by invoking
0 commit comments