I am trying to compare the output of @code_lowered
from two methods of a function. It struck me that displaying them side by side would make it easier to compare them line-by-line. However something like this doesn’t seem to work:
julia> a = @code_lowered sin(1)
CodeInfo(
1 ─ %1 = Base.Math.float(x)
│ %2 = Base.Math.sin(%1)
└── return %2
)
julia> hcat(a, a)
1×2 Array{Core.CodeInfo,2}:
CodeInfo(
1 ─ %1 = Base.Math.float(x)
│ %2 = Base.Math.sin(%1)
└── return %2
) … CodeInfo(
1 ─ %1 = Base.Math.float(x)
│ %2 = Base.Math.sin(%1)
└── return %2
)
I wonder if there’s a way to get them to display next to each other?
It appears that working with a.code
is one way to proceed:
julia> a = @code_lowered sin(1);
julia> [a.code a.code]
3×2 Array{Expr,2}:
:(Base.Math.float(_2)) :(Base.Math.float(_2))
:(Base.Math.sin(%1)) :(Base.Math.sin(%1))
:(return %2) :(return %2)
Sukera
October 17, 2020, 9:36am
3
That won’t work if the functions have different lengths:
julia> a = @code_lowered sin(1)
CodeInfo(
1 ─ %1 = Base.Math.float(x)
│ %2 = Base.Math.sin(%1)
└── return %2
)
julia> b = @code_lowered 1*2*5*4*6 + 3*4*2*3
CodeInfo(
1 ─ %1 = Base.add_int(x, y)
└── return %1
)
julia> [a.code b.code]
ERROR: DimensionMismatch("vectors must have same lengths")
Stacktrace:
[1] hcat(::Array{Any,1}, ::Array{Any,1}) at ./array.jl:1665
[2] top-level scope at REPL[5]:1
Printing differing texts side by side is, in general, a very hard problem - you might be interested in the diff program or various layouting algorithms .
Here is one way to do it using bash
and diff
:
julia> a = @code_lowered sin(1.);
julia> b = @code_lowered cos(1.);
shell> bash -c "diff --color <(echo '$a') <(echo '$b') --side-by-side"
CodeInfo( CodeInfo(
1 ── Core.NewvarNode(:(@_4)) 1 ── Core.NewvarNode(:(@_4))
│ Core.NewvarNode(:(y)) │ Core.NewvarNode(:(y))
│ Core.NewvarNode(:(n)) │ Core.NewvarNode(:(n))
│ absx = Base.Math.abs(x) │ absx = Base.Math.abs(x)
│ %5 = absx │ %5 = absx
│ %6 = ($(Expr(:static_parameter, 1)))(Base.Math.pi) │ %6 = ($(Expr(:static_parameter, 1)))(Base.Math.pi)
│ %7 = %6 / 4 │ %7 = %6 / 4
│ %8 = %5 < %7 │ %8 = %5 < %7
└─── goto #5 if not %8 └─── goto #5 if not %8
2 ── %10 = absx 2 ── %10 = absx
│ %11 = Base.Math.eps($(Expr(:static_parameter, 1))) │ %11 = Base.Math.eps($(Expr(:static_parameter, 1)))
│ %12 = Base.Math.sqrt(%11) | │ %12 = ($(Expr(:static_parameter, 1)))(2.0)
│ %13 = %10 < %12 | │ %13 = %11 / %12
└─── goto #4 if not %13 | │ %14 = Base.Math.sqrt(%13)
3 ── return x | │ %15 = %10 < %14
4 ── %16 = Base.Math.sin_kernel(x) | └─── goto #4 if not %15
└─── return %16 | 3 ── %17 = ($(Expr(:static_parameter, 1)))(1.0)
5 ── %18 = Base.Math.isnan(x) | └─── return %17
└─── goto #7 if not %18 | 4 ── %19 = Base.Math.cos_kernel(x)
6 ── %20 = ($(Expr(:static_parameter, 1)))(Base.Math.NaN) | └─── return %19
└─── return %20 | 5 ── %21 = Base.Math.isnan(x)
7 ── %22 = Base.Math.isinf(x) | └─── goto #7 if not %21
└─── goto #9 if not %22 | 6 ── %23 = ($(Expr(:static_parameter, 1)))(Base.Math.NaN)
8 ── Base.Math.sin_domain_error(x) | └─── return %23
9 ┄─ %25 = Base.Math.rem_pio2_kernel(x) | 7 ── %25 = Base.Math.isinf(x)
│ %26 = Base.indexed_iterate(%25, 1) | └─── goto #9 if not %25
│ n = Core.getfield(%26, 1) | 8 ── %27 = Base.Math.cos_domain_error(x)
│ @_4 = Core.getfield(%26, 2) | └─── return %27
│ %29 = Base.indexed_iterate(%25, 2, @_4) | 9 ── %29 = Base.Math.rem_pio2_kernel(x)
│ y = Core.getfield(%29, 1) | │ %30 = Base.indexed_iterate(%29, 1)
> │ n = Core.getfield(%30, 1)
> │ @_4 = Core.getfield(%30, 2)
> │ %33 = Base.indexed_iterate(%29, 2, @_4)
> │ y = Core.getfield(%33, 1)
│ n = n & 3 │ n = n & 3
│ %32 = n == 0 | │ %36 = n == 0
└─── goto #11 if not %32 | └─── goto #11 if not %36
10 ─ %34 = Base.Math.sin_kernel(y) | 10 ─ %38 = Base.Math.cos_kernel(y)
└─── return %34 <
11 ─ %36 = n == 1 <
└─── goto #13 if not %36 <
12 ─ %38 = Base.Math.cos_kernel(y) <
└─── return %38 └─── return %38
13 ─ %40 = n == 2 | 11 ─ %40 = n == 1
└─── goto #15 if not %40 | └─── goto #13 if not %40
14 ─ %42 = Base.Math.sin_kernel(y) | 12 ─ %42 = Base.Math.sin_kernel(y)
│ %43 = -%42 │ %43 = -%42
└─── return %43 └─── return %43
15 ─ %45 = Base.Math.cos_kernel(y) | 13 ─ %45 = n == 2
│ %46 = -%45 | └─── goto #15 if not %45
└─── return %46 | 14 ─ %47 = Base.Math.cos_kernel(y)
> │ %48 = -%47
> └─── return %48
> 15 ─ %50 = Base.Math.sin_kernel(y)
> └─── return %50
) )
This likely won’t work on Windows though, since you need to have bash
and diff
installed.
3 Likes