Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: prettier IR-show for line number and inlining information #28390

Merged
merged 4 commits into from
Sep 10, 2018

Conversation

vtjnash
Copy link
Sponsor Member

@vtjnash vtjnash commented Aug 1, 2018

As suggested by maleadt in the original LineNumber info PR, this uses box-drawing characters and indentation to improve readability of code_llvm (and should trigger detection in certain terminals of line number hyperlinking). As a second step, it uses the same line number formatting across all of code_lowered / code_typed / code_warntype / code_llvm / code_native, for a more consistent experience.

A sample example:
(note that in the terminal, there is additional usage of color to further improve visibility of various elements)

julia> function g(A)
           v = 0
           @simd for i = 1:length(A)
               @inbounds ai = A[i]
               if ai !== missing
                   v += ai
               end
           end
           return v
       end
g (generic function with 1 method)

julia> code_lowered(g, (typeof([1,missing]),))
1-element Array{Core.CodeInfo,1}:
 CodeInfo(
    @ REPL[1]:2 within `g'
1 ──       v = 0
│   @ REPL[1]:3 within `g'
│  ┌ @ simdloop.jl:65 within `macro expansion'
│    %2  = (Main.length)(A)
│          r#368 = 1:%2
│  │ @ simdloop.jl:66 within `macro expansion'
│    %4  = Base.simd_outer_range
│    %5  = (%4)(r#368)
│          #temp# = (Base.iterate)(%5)
│    %7  = #temp# === nothing
│    %8  = (Base.not_int)(%7)
└───       goto #11 if not %8
2 ┄─ %10 = #temp#
│          i#369 = (Core.getfield)(%10, 1)
│    %12 = (Core.getfield)(%10, 2)
│  │ @ simdloop.jl:67 within `macro expansion'
│          Core.NewvarNode(:(i@_7))
│    %14 = Base.simd_inner_length
│    %15 = r#368
│          n#370 = (%14)(%15, i#369)
│  │ @ simdloop.jl:68 within `macro expansion'
│    %17 = (Main.zero)(n#370)
│    %18 = %17 < n#370
└───       goto #9 if not %18
   │ @ simdloop.jl:70 within `macro expansion'
3 ──       i#371 = (Main.zero)(n#370)
   │ @ simdloop.jl:71 within `macro expansion'
4 ┄─ %21 = i#371 < n#370
└───       goto #8 if not %21
   │ @ simdloop.jl:72 within `macro expansion'
5 ── %23 = Base.simd_index
│    %24 = r#368
│    %25 = i#369
│          i@_12 = (%23)(%24, %25, i#371)
│  │ @ simdloop.jl:73 within `macro expansion'
│  │┌ @ REPL[1]:4 within `macro expansion'
│          $(Expr(:inbounds, true))
│    %28 = (Base.getindex)(A, i@_12)
│          ai = %28
│          val = %28
│          $(Expr(:inbounds, :pop))
│          val
│  ││ @ REPL[1]:5 within `macro expansion'
│    %33 = ai !== Main.missing
└───       goto #7 if not %33
   ││ @ REPL[1]:6 within `macro expansion'
6 ──       v = v + ai
   ││ @ REPL[1]:4 within `macro expansion'
7 ┄─       i#371 = i#371 + 1
│  ││ @ REPL[1]:5 within `macro expansion'
│          $(Expr(:simdloop, false))
└───       goto #4
   ││ @ REPL[1]:6 within `macro expansion'
8 ──       i@_7 = (Main.last)(r#368)
9 ┄─       #temp# = (Base.iterate)(%5, %12)
│    %41 = #temp# === nothing
│    %42 = (Base.not_int)(%41)
└───       goto #11 if not %42
10 ─       goto #2
   │┘
   │ @ simdloop.jl:74 within `macro expansion'
11 ┄       Main.nothing
│  │ @ simdloop.jl:65 within `macro expansion'
└───       return v
)

julia> code_typed(g, (typeof([1,missing]),))
1-element Array{Any,1}:
 CodeInfo(
    @ REPL[1]:3 within `g'
   ┌ @ simdloop.jl:65 within `macro expansion'
   │┌ @ array.jl:199 within `length'
1 ── %1  = (Base.arraylen)(A)::Int64
│  │┘
│  │┌ @ range.jl:5 within `Colon'
│  ││┌ @ range.jl:255 within `Type'
│  │││┌ @ range.jl:260 within `unitrange_last'
│  ││││┌ @ operators.jl:333 within `>='
│  │││││┌ @ int.jl:428 within `<='
│    %2  = (Base.sle_int)(1, %1)::Bool
│  ││││┘┘
│  ││││┌ @ int.jl:52 within `-'
│          (Base.sub_int)(%1, 1)::Int64
│  ││││┘
│    %4  = (Base.ifelse)(%2, %1, 0)::Int64
│  │││┘
│    %5  = %new(UnitRange{Int64}, 1, %4)::UnitRange{Int64}
│  │┘┘
│  │ @ simdloop.jl:66 within `macro expansion'
│  │┌ @ simdloop.jl:44 within `simd_outer_range'
│  ││┌ @ range.jl:5 within `Colon'
│  │││┌ @ range.jl:255 within `Type'
│  ││││┌ @ range.jl:260 within `unitrange_last'
│          (Base.ifelse)(true, 0, -1)::Int64
│  │┘┘┘┘
│  │┌ @ range.jl:571 within `iterate'
│  ││┌ @ range.jl:455 within `isempty'
│  │││┌ @ operators.jl:286 within `>'
│  ││││┌ @ int.jl:49 within `<'
│    %7  = (Base.slt_int)(0, 0)::Bool
│  ││┘┘┘
└───       goto #3 if not %7
2 ──       goto #4
3 ──       goto #4
   │┘
4 ┄─ %11 = φ (#2 => true, #3 => false)::Bool
│    %12 = φ (#3 => 0)::Int64
│    %13 = (Base.not_int)(%11)::Bool
└───       goto #36 if not %13
5 ┄─ %15 = φ (#4 => 0, #35 => %70)::Int64
│    %16 = φ (#4 => %12, #35 => %76)::Int64
│  │ @ simdloop.jl:67 within `macro expansion'
│  │┌ @ simdloop.jl:47 within `simd_inner_length'
│  ││┌ @ range.jl:521 within `length'
│  │││┌ @ checked.jl:226 within `checked_sub'
│  ││││┌ @ checked.jl:198 within `sub_with_overflow'
│    %17 = (Base.Checked.checked_ssub_int)(%4, 1)::Tuple{Int64,Bool}
│  ││││┘
│  ││││┌ @ tuple.jl:60 within `indexed_iterate'
│  │││││┌ @ tuple.jl:60 within `indexed_iterate'
│  ││││││┌ @ tuple.jl:24 within `getindex'
│    %18 = (Base.getfield)(%17, 1, true)::Int64
│  │││││┘┘
│  │││││┌ @ tuple.jl:24 within `getindex'
│    %19 = (Base.getfield)(%17, 2, true)::Bool
│  ││││┘┘
│  ││││ @ checked.jl:227 within `checked_sub'
└───       goto #7 if not %19
6 ──       invoke Base.Checked.throw_overflowerr_binaryop(:-::Symbol, %4::Int64, 1::Int64)::Union{}
└───       $(Expr(:unreachable))::Union{}
   ││││ @ checked.jl:228 within `checked_sub'
7 ┄─       goto #8
   │││┘
   │││┌ @ checked.jl:169 within `checked_add'
   ││││┌ @ checked.jl:136 within `add_with_overflow'
8 ── %24 = (Base.Checked.checked_sadd_int)(%18, 1)::Tuple{Int64,Bool}
│  ││││┘
│  ││││┌ @ tuple.jl:60 within `indexed_iterate'
│  │││││┌ @ tuple.jl:60 within `indexed_iterate'
│  ││││││┌ @ tuple.jl:24 within `getindex'
│    %25 = (Base.getfield)(%24, 1, true)::Int64
│  │││││┘┘
│  │││││┌ @ tuple.jl:24 within `getindex'
│    %26 = (Base.getfield)(%24, 2, true)::Bool
│  ││││┘┘
│  ││││ @ checked.jl:170 within `checked_add'
└───       goto #10 if not %26
9 ──       invoke Base.Checked.throw_overflowerr_binaryop(:+::Symbol, %18::Int64, 1::Int64)::Union{}
└───       $(Expr(:unreachable))::Union{}
   ││││ @ checked.jl:171 within `checked_add'
10 ┄       goto #11
   │││┘
11 ─       goto #12
   ││┘
12 ─       goto #13
   │┘
   │ @ simdloop.jl:68 within `macro expansion'
   │┌ @ int.jl:49 within `<'
13 ─ %33 = (Base.slt_int)(0, %25)::Bool
│  │┘
└───       goto #31 if not %33
14 ─       nothing::Nothing
   │ @ simdloop.jl:71 within `macro expansion'
15 ┄ %36 = φ (#14 => %15, #29 => %65)::Int64
│    %37 = φ (#14 => 0, #29 => %66)::Int64
│  │┌ @ int.jl:49 within `<'
│    %38 = (Base.slt_int)(%37, %25)::Bool
│  │┘
└───       goto #30 if not %38
   │ @ simdloop.jl:72 within `macro expansion'
   │┌ @ simdloop.jl:50 within `simd_index'
   ││┌ @ int.jl:53 within `+'
16 ─ %40 = (Base.add_int)(%37, 1)::Int64
│  ││┘
│  ││┌ @ range.jl:596 within `getindex'
│  │││┌ @ int.jl:53 within `+'
│    %41 = (Base.add_int)(1, %40)::Int64
│  │││┘
│  │││┌ @ int.jl:52 within `-'
│    %42 = (Base.sub_int)(%41, 1)::Int64
│  │││┘
│  │││ @ range.jl:597 within `getindex'
└───       goto #25 if not false
   │││┌ @ range.jl:582 within `_in_unit_range'
   ││││┌ @ operators.jl:286 within `>'
   │││││┌ @ int.jl:49 within `<'
17 ─ %44 = (Base.slt_int)(0, %40)::Bool
│  ││││┘┘
└───       goto #21 if not %44
   ││││┌ @ int.jl:428 within `<='
18 ─ %46 = (Base.sle_int)(%42, %4)::Bool
│  ││││┘
└───       goto #20 if not %46
   ││││┌ @ operators.jl:333 within `>='
   │││││┌ @ int.jl:428 within `<='
19 ─ %48 = (Base.sle_int)(1, %42)::Bool
│  ││││┘┘
└───       goto #22
20 ─       goto #22
21 ─       goto #22
   │││┘
22 ┄ %52 = φ (#19 => %48, #20 => false, #21 => false)::Bool
└───       goto #24 if not %52
23 ─       goto #25
24 ─       invoke Base.throw_boundserror(%5::UnitRange{Int64}, %40::Int64)::Union{}
└───       $(Expr(:unreachable))::Union{}
   │││ @ range.jl:598 within `getindex'
25 ┄       goto #26
   ││┘
26 ─       goto #27
   │┘
   │ @ simdloop.jl:73 within `macro expansion'
   │┌ @ REPL[1]:4 within `macro expansion'
   ││┌ @ array.jl:731 within `getindex'
27 ─ %59 = (Base.arrayref)(false, A, %42)::Union{Missing, Int64}
│  ││┘
│  ││ @ REPL[1]:5 within `macro expansion'
│    %60 = (%59 === Main.missing)::Bool
│    %61 = (Core.Intrinsics.not_int)(%60)::Bool
└───       goto #29 if not %61
   ││ @ REPL[1]:6 within `macro expansion'
28 ─ %63 = π (%59, Int64)
│  ││┌ @ int.jl:53 within `+'
└─── %64 = (Base.add_int)(%36, %63)::Int64
   ││┘
   ││ @ REPL[1]:4 within `macro expansion'
29 ┄ %65 = φ (#28 => %64, #27 => %36)::Int64
│  ││┌ @ int.jl:53 within `+'
│    %66 = (Base.add_int)(%37, 1)::Int64
│  ││┘
│  ││ @ REPL[1]:5 within `macro expansion'
│          $(Expr(:simdloop, false))::Any
└───       goto #15
30 ─       nothing::Nothing
   ││ @ REPL[1]:6 within `macro expansion'
31 ┄ %70 = φ (#30 => %36, #13 => %15)::Int64
│  ││┌ @ range.jl:575 within `iterate'
│  │││┌ @ promotion.jl:425 within `=='
│    %71 = (%16 === 0)::Bool
│  │││┘
└───       goto #33 if not %71
32 ─       goto #34
   │││ @ range.jl:576 within `iterate'
   │││┌ @ int.jl:53 within `+'
33 ─ %74 = (Base.add_int)(%16, 1)::Int64
│  │││┘
│  │││ @ range.jl:577 within `iterate'
└───       goto #34
   ││┘
34 ┄ %76 = φ (#33 => %74)::Int64
│    %77 = φ (#32 => true, #33 => false)::Bool
│    %78 = (Base.not_int)(%77)::Bool
└───       goto #36 if not %78
35 ─       goto #5
   │┘
   │ @ simdloop.jl:74 within `macro expansion'
36 ┄ %81 = φ (#34 => %70, #4 => 0)::Int64
│  │ @ simdloop.jl:65 within `macro expansion'
└───       return %81
) => Int64

julia> code_llvm(g, (typeof([1,missing]),))

;  @ REPL[1]:2 within `g'
define i64 @julia_g_33689(%jl_value_t addrspace(10)* nonnull align 16 dereferenceable(40)) {
top:
;  @ REPL[1]:3 within `g'
; ┌ @ simdloop.jl:65 within `macro expansion'
; │┌ @ array.jl:199 within `length'
    %1 = addrspacecast %jl_value_t addrspace(10)* %0 to %jl_value_t addrspace(11)*
    %2 = bitcast %jl_value_t addrspace(11)* %1 to %jl_array_t addrspace(11)*
    %3 = getelementptr inbounds %jl_array_t, %jl_array_t addrspace(11)* %2, i64 0, i32 1
    %4 = load i64, i64 addrspace(11)* %3, align 8
; │┘
; │┌ @ range.jl:5 within `Colon'
; ││┌ @ range.jl:255 within `Type'
; │││┌ @ range.jl:260 within `unitrange_last'
; ││││┌ @ operators.jl:333 within `>='
; │││││┌ @ int.jl:428 within `<='
        %5 = icmp sgt i64 %4, 0
; ││││┘┘
      %6 = select i1 %5, i64 %4, i64 0
; │┘┘┘
; │ @ simdloop.jl:67 within `macro expansion'
; │┌ @ simdloop.jl:47 within `simd_inner_length'
; ││┌ @ range.jl:521 within `length'
; │││┌ @ checked.jl:226 within `checked_sub'
; ││││┌ @ checked.jl:198 within `sub_with_overflow'
       %7 = add nsw i64 %6, -1
; │││┘┘
; │││┌ @ checked.jl:169 within `checked_add'
; ││││┌ @ checked.jl:136 within `add_with_overflow'
       %8 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %7, i64 1)
       %9 = extractvalue { i64, i1 } %8, 1
; ││││┘
; ││││ @ checked.jl:170 within `checked_add'
      br i1 %9, label %L28, label %L33.lr.ph

L33.lr.ph:                                        ; preds = %top
; ││││ @ checked.jl:169 within `checked_add'
; ││││┌ @ checked.jl:136 within `add_with_overflow'
       %10 = extractvalue { i64, i1 } %8, 0
       %11 = icmp slt i64 %10, 1
; ││││┘
; ││││ @ checked.jl:170 within `checked_add'
      br i1 %11, label %L81, label %L40.lr.ph.us33

L40.lr.ph.us33:                                   ; preds = %L33.lr.ph
      %12 = bitcast %jl_value_t addrspace(11)* %1 to [1 x i64] addrspace(13)* addrspace(11)*
      %13 = load [1 x i64] addrspace(13)*, [1 x i64] addrspace(13)* addrspace(11)* %12, align 8
      %14 = getelementptr inbounds %jl_array_t, %jl_array_t addrspace(11)* %2, i64 0, i32 4
      %15 = load i32, i32 addrspace(11)* %14, align 4
      %16 = zext i32 %15 to i64
      %17 = bitcast %jl_value_t addrspace(11)* %1 to %jl_value_t addrspace(10)* addrspace(11)*
      %18 = getelementptr inbounds %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)* addrspace(11)* %17, i64 4
      %19 = bitcast %jl_value_t addrspace(10)* addrspace(11)* %18 to i64 addrspace(11)*
      %20 = load i64, i64 addrspace(11)* %19, align 8
      %21 = sub i64 %20, %16
      %22 = getelementptr inbounds [1 x i64], [1 x i64] addrspace(13)* %13, i64 %21
      %23 = bitcast [1 x i64] addrspace(13)* %22 to i8 addrspace(13)*
      %24 = sext i32 %15 to i64
      %25 = getelementptr inbounds i8, i8 addrspace(13)* %23, i64 %24
; │┘┘┘
; │ @ simdloop.jl:71 within `macro expansion'
   %min.iters.check = icmp ult i64 %6, 32
   br i1 %min.iters.check, label %scalar.ph, label %vector.ph

vector.ph:                                        ; preds = %L40.lr.ph.us33
   %n.vec = and i64 %6, 9223372036854775776
   br label %vector.body

vector.body:                                      ; preds = %vector.body, %vector.ph
; │ @ simdloop.jl:73 within `macro expansion'
; │┌ @ REPL[1]:4 within `macro expansion'
; ││┌ @ int.jl:53 within `+'
     %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
     %vec.phi = phi <8 x i64> [ zeroinitializer, %vector.ph ], [ %50, %vector.body ]
     %vec.phi51 = phi <8 x i64> [ zeroinitializer, %vector.ph ], [ %51, %vector.body ]
     %vec.phi52 = phi <8 x i64> [ zeroinitializer, %vector.ph ], [ %52, %vector.body ]
     %vec.phi53 = phi <8 x i64> [ zeroinitializer, %vector.ph ], [ %53, %vector.body ]
; ││┘
; ││┌ @ array.jl:731 within `getindex'
     %26 = getelementptr inbounds i8, i8 addrspace(13)* %25, i64 %index
     %27 = bitcast i8 addrspace(13)* %26 to <8 x i8> addrspace(13)*
     %wide.load = load <8 x i8>, <8 x i8> addrspace(13)* %27, align 1
     %28 = getelementptr i8, i8 addrspace(13)* %26, i64 8
     %29 = bitcast i8 addrspace(13)* %28 to <8 x i8> addrspace(13)*
     %wide.load54 = load <8 x i8>, <8 x i8> addrspace(13)* %29, align 1
     %30 = getelementptr i8, i8 addrspace(13)* %26, i64 16
     %31 = bitcast i8 addrspace(13)* %30 to <8 x i8> addrspace(13)*
     %wide.load55 = load <8 x i8>, <8 x i8> addrspace(13)* %31, align 1
     %32 = getelementptr i8, i8 addrspace(13)* %26, i64 24
     %33 = bitcast i8 addrspace(13)* %32 to <8 x i8> addrspace(13)*
     %wide.load56 = load <8 x i8>, <8 x i8> addrspace(13)* %33, align 1
     %34 = getelementptr inbounds [1 x i64], [1 x i64] addrspace(13)* %13, i64 %index, i64 0
     %35 = bitcast i64 addrspace(13)* %34 to <8 x i64> addrspace(13)*
     %wide.load57 = load <8 x i64>, <8 x i64> addrspace(13)* %35, align 8
     %36 = getelementptr [1 x i64], [1 x i64] addrspace(13)* %13, i64 %index, i64 8
     %37 = bitcast i64 addrspace(13)* %36 to <8 x i64> addrspace(13)*
     %wide.load58 = load <8 x i64>, <8 x i64> addrspace(13)* %37, align 8
     %38 = getelementptr [1 x i64], [1 x i64] addrspace(13)* %13, i64 %index, i64 16
     %39 = bitcast i64 addrspace(13)* %38 to <8 x i64> addrspace(13)*
     %wide.load59 = load <8 x i64>, <8 x i64> addrspace(13)* %39, align 8
     %40 = getelementptr [1 x i64], [1 x i64] addrspace(13)* %13, i64 %index, i64 24
     %41 = bitcast i64 addrspace(13)* %40 to <8 x i64> addrspace(13)*
     %wide.load60 = load <8 x i64>, <8 x i64> addrspace(13)* %41, align 8
; ││┘
; ││ @ REPL[1]:5 within `macro expansion'
    %42 = icmp eq <8 x i8> %wide.load, zeroinitializer
    %43 = icmp eq <8 x i8> %wide.load54, zeroinitializer
    %44 = icmp eq <8 x i8> %wide.load55, zeroinitializer
    %45 = icmp eq <8 x i8> %wide.load56, zeroinitializer
    %46 = select <8 x i1> %42, <8 x i64> zeroinitializer, <8 x i64> %wide.load57
    %47 = select <8 x i1> %43, <8 x i64> zeroinitializer, <8 x i64> %wide.load58
    %48 = select <8 x i1> %44, <8 x i64> zeroinitializer, <8 x i64> %wide.load59
    %49 = select <8 x i1> %45, <8 x i64> zeroinitializer, <8 x i64> %wide.load60
    %50 = add <8 x i64> %46, %vec.phi
    %51 = add <8 x i64> %47, %vec.phi51
    %52 = add <8 x i64> %48, %vec.phi52
    %53 = add <8 x i64> %49, %vec.phi53
; ││ @ REPL[1]:4 within `macro expansion'
; ││┌ @ int.jl:53 within `+'
     %index.next = add i64 %index, 32
     %54 = icmp eq i64 %index.next, %n.vec
     br i1 %54, label %middle.block, label %vector.body

middle.block:                                     ; preds = %vector.body
; ││┘
; ││ @ REPL[1]:5 within `macro expansion'
    %bin.rdx = add <8 x i64> %51, %50
    %bin.rdx61 = add <8 x i64> %52, %bin.rdx
    %bin.rdx62 = add <8 x i64> %53, %bin.rdx61
    %rdx.shuf = shufflevector <8 x i64> %bin.rdx62, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
    %bin.rdx63 = add <8 x i64> %bin.rdx62, %rdx.shuf
    %rdx.shuf64 = shufflevector <8 x i64> %bin.rdx63, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
    %bin.rdx65 = add <8 x i64> %bin.rdx63, %rdx.shuf64
    %rdx.shuf66 = shufflevector <8 x i64> %bin.rdx65, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
    %bin.rdx67 = add <8 x i64> %bin.rdx65, %rdx.shuf66
    %55 = extractelement <8 x i64> %bin.rdx67, i32 0
    %cmp.n = icmp eq i64 %6, %n.vec
; │┘
; │ @ simdloop.jl:71 within `macro expansion'
   br i1 %cmp.n, label %L81, label %scalar.ph

scalar.ph:                                        ; preds = %middle.block, %L40.lr.ph.us33
   %bc.resume.val = phi i64 [ %n.vec, %middle.block ], [ 0, %L40.lr.ph.us33 ]
   %bc.merge.rdx = phi i64 [ %55, %middle.block ], [ 0, %L40.lr.ph.us33 ]
   br label %L40.us34

L40.us34:                                         ; preds = %L40.us34, %scalar.ph
   %value_phi625.us35 = phi i64 [ %bc.resume.val, %scalar.ph ], [ %62, %L40.us34 ]
   %value_phi524.us36 = phi i64 [ %bc.merge.rdx, %scalar.ph ], [ %value_phi8.us37, %L40.us34 ]
; │ @ simdloop.jl:73 within `macro expansion'
; │┌ @ REPL[1]:4 within `macro expansion'
; ││┌ @ array.jl:731 within `getindex'
     %56 = getelementptr inbounds i8, i8 addrspace(13)* %25, i64 %value_phi625.us35
     %57 = load i8, i8 addrspace(13)* %56, align 1
     %58 = getelementptr inbounds [1 x i64], [1 x i64] addrspace(13)* %13, i64 %value_phi625.us35, i64 0
     %59 = load i64, i64 addrspace(13)* %58, align 8
; ││┘
; ││ @ REPL[1]:5 within `macro expansion'
    %60 = icmp eq i8 %57, 0
    %61 = select i1 %60, i64 0, i64 %59
    %value_phi8.us37 = add i64 %61, %value_phi524.us36
; ││ @ REPL[1]:4 within `macro expansion'
; ││┌ @ int.jl:53 within `+'
     %62 = add nuw nsw i64 %value_phi625.us35, 1
; │┘┘
; │ @ simdloop.jl:71 within `macro expansion'
; │┌ @ int.jl:49 within `<'
    %63 = icmp ult i64 %62, %10
; │┘
   br i1 %63, label %L40.us34, label %L81

L28:                                              ; preds = %top
; │ @ simdloop.jl:67 within `macro expansion'
; │┌ @ simdloop.jl:47 within `simd_inner_length'
; ││┌ @ range.jl:521 within `length'
; │││┌ @ checked.jl:170 within `checked_add'
      call void @julia_throw_overflowerr_binaryop_22657(%jl_value_t addrspace(10)* addrspacecast (%jl_value_t* inttoptr (i64 140059004363544 to %jl_value_t*) to %jl_value_t addrspace(10)*), i64 %7, i64 1)
      call void @llvm.trap()
      unreachable

L81:                                              ; preds = %L40.us34, %middle.block, %L33.lr.ph
      %value_phi10.lcssa = phi i64 [ 0, %L33.lr.ph ], [ %value_phi8.us37, %L40.us34 ], [ %55, %middle.block ]
; │┘┘┘
; │ @ simdloop.jl:65 within `macro expansion'
   ret i64 %value_phi10.lcssa
; ┘
}

julia> code_native(g, (typeof([1,missing]),))
	.text
; ┌ @ REPL[1]:3 within `g'
; │┌ @ simdloop.jl:65 within `macro expansion'
; ││┌ @ REPL[1]:2 within `length'
	pushq	%rbx
	movq	8(%rdi), %rax
; │┘┘
; │┌ @ range.jl:260 within `macro expansion'
	movq	%rax, %rcx
	sarq	$63, %rcx
	andnq	%rax, %rcx, %r10
; │┘
; │┌ @ simdloop.jl:67 within `macro expansion'
; ││┌ @ simdloop.jl:47 within `simd_inner_length'
; │││┌ @ range.jl:521 within `length'
; ││││┌ @ checked.jl:226 within `checked_sub'
; │││││┌ @ checked.jl:198 within `sub_with_overflow'
	leaq	-1(%r10), %rsi
; ││││┘┘
; ││││┌ @ checked.jl:169 within `checked_add'
; │││││┌ @ checked.jl:136 within `add_with_overflow'
	movq	%rsi, %rcx
	incq	%rcx
; │││││┘
; │││││ @ checked.jl:170 within `checked_add'
	jo	L391
	testq	%rcx, %rcx
; │││││ @ checked.jl:170 within `checked_add'
	jle	L67
; │┘┘┘┘
; │┌ @ checked.jl within `macro expansion'
	movq	(%rdi), %rdx
	movq	32(%rdi), %r9
	movslq	20(%rdi), %r8
	movl	%r8d, %r11d
; │┘
; │┌ @ simdloop.jl:71 within `macro expansion'
	cmpq	$32, %r10
	jae	L71
	xorl	%esi, %esi
	xorl	%eax, %eax
	jmp	L326
L67:
	xorl	%eax, %eax
; ││ @ simdloop.jl:65 within `macro expansion'
	popq	%rbx
	retq
; ││ @ simdloop.jl:71 within `macro expansion'
L71:
	movabsq	$9223372036854775776, %rsi # imm = 0x7FFFFFFFFFFFFFE0
	andq	%r10, %rsi
	leaq	192(%rdx), %rax
	leaq	3(%r9), %rdi
	subq	%r11, %rdi
	leaq	(%rdx,%rdi,8), %rdi
	addq	%r8, %rdi
	vpxor	%xmm0, %xmm0, %xmm0
	vpxor	%xmm8, %xmm8, %xmm8
; ││ @ simdloop.jl:73 within `macro expansion'
; ││┌ @ REPL[1]:4 within `macro expansion'
; │││┌ @ int.jl:53 within `+'
	movq	%rsi, %rbx
	vpxor	%xmm2, %xmm2, %xmm2
	vpxor	%xmm3, %xmm3, %xmm3
	vpxor	%xmm4, %xmm4, %xmm4
	nopw	%cs:(%rax,%rax)
; ││┘┘
; ││┌ @ array.jl:731 within `macro expansion'
L144:
	vpmovzxbw	-24(%rdi), %xmm5 # xmm5 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
	vpmovzxbw	-16(%rdi), %xmm6 # xmm6 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
	vpmovzxbw	-8(%rdi), %xmm7 # xmm7 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
	vpmovzxbw	(%rdi), %xmm1   # xmm1 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero
; │┘┘
; │ @ REPL[1]:5 within `g'
	vpcmpneqw	%xmm8, %xmm5, %k1
	vpcmpneqw	%xmm8, %xmm6, %k2
	vpcmpneqw	%xmm8, %xmm7, %k3
	vpcmpneqw	%xmm8, %xmm1, %k4
	vmovdqu64	-192(%rax), %zmm1 {%k1} {z}
	vpaddq	%zmm0, %zmm1, %zmm0
	vmovdqu64	-128(%rax), %zmm1 {%k2} {z}
	vpaddq	%zmm2, %zmm1, %zmm2
	vmovdqu64	-64(%rax), %zmm1 {%k3} {z}
	vpaddq	%zmm3, %zmm1, %zmm3
	vmovdqu64	(%rax), %zmm1 {%k4} {z}
	vpaddq	%zmm4, %zmm1, %zmm4
; │ @ REPL[1]:3 within `g'
; │┌ @ simdloop.jl:73 within `macro expansion'
; ││┌ @ REPL[1]:4 within `macro expansion'
; │││┌ @ int.jl:53 within `+'
	addq	$256, %rax              # imm = 0x100
	addq	$32, %rdi
	addq	$-32, %rbx
	jne	L144
; │┘┘┘
; │ @ REPL[1]:5 within `g'
	vpaddq	%zmm0, %zmm2, %zmm0
	vpaddq	%zmm0, %zmm3, %zmm0
	vpaddq	%zmm0, %zmm4, %zmm0
	vextracti64x4	$1, %zmm0, %ymm1
	vpaddq	%zmm1, %zmm0, %zmm0
	vextracti128	$1, %ymm0, %xmm1
	vpaddq	%zmm1, %zmm0, %zmm0
	vpshufd	$78, %xmm0, %xmm1       # xmm1 = xmm0[2,3,0,1]
	vpaddq	%zmm1, %zmm0, %zmm0
	vmovq	%xmm0, %rax
	cmpq	%rsi, %r10
; │ @ REPL[1]:3 within `g'
; │┌ @ simdloop.jl:71 within `macro expansion'
	je	L386
L326:
	leaq	(%rsi,%r9,8), %rdi
	addq	%r8, %rdi
	shlq	$3, %r11
	subq	%r11, %rdi
	nopw	%cs:(%rax,%rax)
; ││ @ simdloop.jl:73 within `macro expansion'
; ││┌ @ REPL[1]:5 within `macro expansion'
L352:
	cmpb	$0, (%rdx,%rdi)
	je	L368
	movq	(%rdx,%rsi,8), %rbx
	jmp	L370
	nopl	(%rax)
; │││ @ REPL[1]:5 within `macro expansion'
L368:
	xorl	%ebx, %ebx
L370:
	addq	%rbx, %rax
; │││ @ REPL[1]:4 within `macro expansion'
; │││┌ @ int.jl:53 within `+'
	addq	$1, %rsi
; ││┘┘
; ││ @ simdloop.jl:71 within `macro expansion'
; ││┌ @ int.jl:49 within `<'
	addq	$1, %rdi
	cmpq	%rcx, %rsi
; ││┘
	jb	L352
; ││ @ simdloop.jl:65 within `macro expansion'
L386:
	popq	%rbx
	vzeroupper
	retq
; ││ @ simdloop.jl:67 within `macro expansion'
; ││┌ @ simdloop.jl:47 within `simd_inner_length'
; │││┌ @ range.jl:521 within `length'
; ││││┌ @ checked.jl:170 within `checked_add'
L391:
	movabsq	$throw_overflowerr_binaryop, %rax
	movabsq	$140059004363544, %rdi  # imm = 0x7F620733E318
	movl	$1, %edx
	callq	*%rax
	ud2
	nopw	%cs:(%rax,%rax)
; ┘┘┘┘┘

julia> 

fixes #27526

@Keno
Copy link
Member

Keno commented Aug 1, 2018

We already have a julia ir mode that shows the linetable in verbose mode. I really think printing all this line information by default is way too verbose.

@vchuravy
Copy link
Sponsor Member

vchuravy commented Aug 1, 2018

I love the assembly and llvm view.

@Keno
Copy link
Member

Keno commented Aug 1, 2018

E.g. compare the amount of information that fits on one screen with the full linetable information
screen shot 2018-08-01 at 12 17 09 pm

compared to the compressed representation we have right now

screen shot 2018-08-01 at 12 17 42 pm

I really think the full linetable cannot be the default. Sometimes it's useful,
but most often you don't really care.

@Keno
Copy link
Member

Keno commented Aug 1, 2018

and note that the full representation we have right now shorter than the representation suggested in this PR (because it doesn't use a line to end a scope).

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Aug 1, 2018

This PR restores the v0.6 capabilities for line-info printing that regressed when the new IR PR was merged. It then also adds additional formatting marks to coordinate it with the updates to the code_llvm format improvements also being made here. We can consider adding flags that hide metadata information, but the regression in quality shouldn't be a necessary side-effect of changing the IR format.

but most often you don't really care

I strongly disagree. Most of the time, it's pretty much the only anchor I have for figuring out why this code was generated. I find that first screenshot to be basically worthless, since it fails to represent most location information or represents it ambiguously. I agree it obscures somewhat the optimization information – but that's why I don't print this more accurate metadata for IRCode (or you can also do fill!(src.codelocs, 0) to recover the old behavior for CodeInfo). FWIW, this also essentially makes the line number printing pluggable too, since I think it's cleaner to have this factored into a separate function.

@Keno
Copy link
Member

Keno commented Aug 1, 2018

I strongly disagree. Most of the time, it's pretty much the only anchor I have for figuring out why this code was generated. I find that first screenshot to be basically worthless, since it fails to represent most location information or represents it ambiguously.

Well, I cut off the linetable information in that screenshot (here it is)

screen shot 2018-08-01 at 12 43 42 pm

When I designed that representation I tried pretty hard to make it maximally informative without taking up any extra lines. If you really, really feel that all the location information is necessary, I think the current verbose printing is better, because it at least doesn't need an extra line to close the scope and doesn't clutter up the LHS.

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Aug 1, 2018

because it at least doesn't need an extra line to close the scope

It's not necessary here either. I included it to give this the same layout as the code_llvm and code_native information. But we can skip it.

@Keno
Copy link
Member

Keno commented Aug 1, 2018

It's not necessary here either. I included it to give this the same layout as the code_llvm and code_native information. But we can skip it.

Sure, but I think putting the additional indicators on the LHS of the screen clutters up the control flow information, while there's plenty of space on the RHS. If you don't use lines for closing the scope, then you need some other way to indicate it, as the current verbose printing does. I really don't think consistency with the LLVM printing is all that valuable here, because that has other constraints (i.e. we can't put any formatting on content lines, because we want it to be copy-pasteable to a .ll file).

@Keno
Copy link
Member

Keno commented Aug 1, 2018

I guess what I'm saying is this.

  1. I prefer the compact printing, but if people really feel strongly, I'm fine with verbose printing for CodeInfo (I'd prefer to keep it compact for IRCode though, such that it doesn't clutter up everything when I dump it in the compiler).
  2. Don't delete the compact printing, it's very useful
  3. Everything should have a keyword argument to disable the verbose printing
  4. I like the current verbose printing we have better than the one in this PR, but we can debate that. Or you can leave that part out of this PR to get it merged quicker.

If you make those changes, I'll be ok.

@ararslan ararslan added the domain:display and printing Aesthetics and correctness of printed representations of objects. label Aug 1, 2018
@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Aug 1, 2018

I can do all of that except 1 (already not changed) and 3 (I think we should make this a Function argument – like LLVM – not just a boolean).

@StefanKarpinski
Copy link
Sponsor Member

Timing and priorities, folks.

@JeffBezanson
Copy link
Sponsor Member

Seriously, folks. Please do not spend time on pretty-printing when we have release-blocking bugs that need to be fixed yesterday.

Use box-drawing characters and indentation to make the output readable more rapidly.
…_native

For consistency of user experience, reduce the variance in our IR printing across formats.
This also now shows inlining and line number information even if the output device might not support color,
which was previously impossible (a regression since v0.6).
Here we make the observation that it's somewhat common to have chains
of methods of one function that recursively handle arguments in some
fashion (for example, map-tuple or +). However, since they all have the
same method name, it's possible to represent these on a single line.
@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Aug 31, 2018

Changes requested above by Keno have been made. Additionally, I now compress recursion to take a single line (the effect of which is most apparent with tailcall-like functions such as tuple-map and promotion of operators like *) to slightly further reduce the vertical space used in such cases across code_lowered/typed/llvm/native (all now share the same format output).

@vtjnash vtjnash merged commit 999bcc5 into master Sep 10, 2018
@vtjnash vtjnash deleted the jn/irshow3 branch September 10, 2018 13:44
@KristofferC
Copy link
Sponsor Member

I extremely much prefer the old printing. Please bring that back with an option or something. I can't use this at all.

@Keno
Copy link
Member

Keno commented Sep 10, 2018

Yeah, I'm sorry, but this printing just looks messy. It's great if I care about the line information, but near useless if I want to actually look at the code:

screen shot 2018-09-10 at 11 27 02 am

It loses the compactness of the previous printing as well as the alignment of the SSA values (which was useful to quickly be able to go to an operand). We also need verbosity controls on the macros themselves. Previous printing for comparison:

screen shot 2018-09-10 at 11 29 28 am

I'm also not convinced it's any better than the verbose printing we had before:

screen shot 2018-09-10 at 11 34 48 am

Lastly, I'm unhappy about the process by which this was merged (or rather the lack thereof), but I've already mentioned so offline, so I won't repeat that here.

@StefanKarpinski
Copy link
Sponsor Member

Agree. Just merging this despite all the objections is pretty antisocial behavior. This is yet another step in an apparent project that you've undertaken for unclear reasons to make the output of all the code introspection tools so verbose and illegible that no one will ever use them again. Please stop.

@vtjnash
Copy link
Sponsor Member Author

vtjnash commented Sep 10, 2018

I'm currently looking at an issue (#29117), where the inlining information is pretty much the only part of the IR that matters, so yes, it's useful.

as well as the alignment of the SSA values

There's a flag for this in the code. Right now, it's set on for code_typed and code_llvm, but off for code_native. I find it helps most with code_llvm readability, but we can toggle that off for the other two.

I'm also not convinced it's any better than the verbose printing we had before:

Is the thought just that we should indent it more heavily, so that the code is more visibly left-aligned? That's something we could change to be consistent across our tooling too.

@Keno
Copy link
Member

Keno commented Sep 10, 2018

I'm currently looking at an issue (#29117), where the inlining information is pretty much the only part of the IR that matters, so yes, it's useful.

I didn't say it was useless, I said it's near useless if I want to look at the code. There's clearly situations where you care about the line info, but I'd say in most cases you care about what the code is doing. That's why I've been requesting a simple macro flag here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:display and printing Aesthetics and correctness of printed representations of objects.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

new IR printing sometimes broken for non-stdout IO
7 participants