-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Name LLVM variables from codegen #50094
Conversation
I wonder if we can get the julia level names as well? |
I don't see much point in grabbing the julia-level names here, if those are accessible they should go into proper debug info rather than instruction names. |
It would make the IR more legible just like this PR does? |
In the interest of not holding this up due to |
0c46b6a
to
fe39c22
Compare
fe39c22
to
3fb58c4
Compare
3fb58c4
to
203e645
Compare
Does the example still look the same after the changes? |
More or less, I added a handful of other names and named the arguments of the invoke stub, since those are pretty simple compared to the specsig function's arguments. Imaging mode results in poor IR output, so that's not turned on for New Examplejulia> @code_llvm dump_module=true f(100)
; ModuleID = 'f'
source_filename = "f"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@_j_const1 = private unnamed_addr constant i64 0
; @ REPL[1]:1 within `f`
define nonnull {}* @julia_f_153(i64 signext %0) #0 {
top:
%gcframe45 = alloca [3 x {}*], align 16
%gcframe45.sub = getelementptr inbounds [3 x {}*], [3 x {}*]* %gcframe45, i64 0, i64 0
%1 = bitcast [3 x {}*]* %gcframe45 to i8*
call void @llvm.memset.p0i8.i32(i8* noundef nonnull align 16 dereferenceable(24) %1, i8 0, i32 24, i1 false)
%thread_ptr = call i8* asm "movq %fs:0, $0", "=r"() #8
%ppgcstack_i8 = getelementptr i8, i8* %thread_ptr, i64 -8
%ppgcstack = bitcast i8* %ppgcstack_i8 to {}****
%pgcstack = load {}***, {}**** %ppgcstack, align 8
; @ REPL[1]:2 within `f`
; ┌ @ array.jl:630 within `zeros` @ array.jl:634
; │┌ @ boot.jl:484 within `Array` @ boot.jl:475
%2 = bitcast [3 x {}*]* %gcframe45 to i64*
store i64 4, i64* %2, align 16
%3 = getelementptr inbounds [3 x {}*], [3 x {}*]* %gcframe45, i64 0, i64 1
%4 = bitcast {}** %3 to {}***
%5 = load {}**, {}*** %pgcstack, align 8
store {}** %5, {}*** %4, align 8
%6 = bitcast {}*** %pgcstack to {}***
store {}** %gcframe45.sub, {}*** %6, align 8
%7 = call nonnull {}* inttoptr (i64 139653478707344 to {}* ({}*, i64)*)({}* inttoptr (i64 139653122672256 to {}*), i64 64)
; │└
; │ @ array.jl:630 within `zeros` @ array.jl:635
; │┌ @ array.jl:392 within `fill!`
; ││┌ @ abstractarray.jl:318 within `eachindex`
; │││┌ @ abstractarray.jl:134 within `axes1`
; ││││┌ @ abstractarray.jl:98 within `axes`
; │││││┌ @ array.jl:191 within `size`
%8 = bitcast {}* %7 to { i8*, i64, i16, i16, i32 }*
%arraylen_ptr = getelementptr inbounds { i8*, i64, i16, i16, i32 }, { i8*, i64, i16, i16, i32 }* %8, i64 0, i32 1
%arraylen = load i64, i64* %arraylen_ptr, align 8
; ││└└└└
; ││┌ @ range.jl:893 within `iterate`
; │││┌ @ range.jl:668 within `isempty`
; ││││┌ @ operators.jl:376 within `>`
; │││││┌ @ int.jl:83 within `<`
%.not.not = icmp eq i64 %arraylen, 0
; ││└└└└
br i1 %.not.not, label %L31, label %L14.preheader
L14.preheader: ; preds = %top
%9 = bitcast {}* %7 to i8**
%arrayptr3043 = load i8*, i8** %9, align 8
; ││ @ array.jl:394 within `fill!`
%10 = shl nuw i64 %arraylen, 3
; ││ @ array.jl:393 within `fill!`
; ││┌ @ array.jl:1019 within `setindex!`
call void @llvm.memset.p0i8.i64(i8* nonnull align 8 %arrayptr3043, i8 0, i64 %10, i1 false)
; └└└
br label %L31
L31: ; preds = %L14.preheader, %top
%11 = getelementptr inbounds [3 x {}*], [3 x {}*]* %gcframe45, i64 0, i64 2
store {}* %7, {}** %11, align 16
%12 = call nonnull {}* @j_Array_155({}* nonnull %7)
; @ REPL[1]:3 within `f`
; ┌ @ abstractarray.jl:318 within `eachindex`
; │┌ @ abstractarray.jl:134 within `axes1`
; ││┌ @ abstractarray.jl:98 within `axes`
; │││┌ @ array.jl:191 within `size`
%13 = bitcast {}* %12 to { i8*, i64, i16, i16, i32 }*
%arraylen_ptr8 = getelementptr inbounds { i8*, i64, i16, i16, i32 }, { i8*, i64, i16, i16, i32 }* %13, i64 0, i32 1
%arraylen9 = load i64, i64* %arraylen_ptr8, align 8
; └└└└
; ┌ @ range.jl:893 within `iterate`
; │┌ @ range.jl:668 within `isempty`
; ││┌ @ operators.jl:376 within `>`
; │││┌ @ int.jl:83 within `<`
%.not.not32 = icmp eq i64 %arraylen9, 0
; └└└└
br i1 %.not.not32, label %L58, label %L44.preheader37
L44.preheader37: ; preds = %L31
%14 = bitcast {}* %12 to [1 x i64]**
%arrayoffset_ptr = getelementptr inbounds { i8*, i64, i16, i16, i32 }, { i8*, i64, i16, i16, i32 }* %13, i64 0, i32 4
%15 = bitcast {}* %12 to {}**
%arraysize_ptr = getelementptr inbounds {}*, {}** %15, i64 4
%16 = bitcast {}** %arraysize_ptr to i64*
; @ REPL[1]:4 within `f`
; ┌ @ array.jl:1019 within `setindex!`
%arrayptr1933.pre = load [1 x i64]*, [1 x i64]** %14, align 8
%arrayoffset.pre = load i32, i32* %arrayoffset_ptr, align 4
%arraysize.pre = load i64, i64* %16, align 8
br label %idxend
L58: ; preds = %idxend, %L31
%17 = load {}*, {}** %3, align 8
%18 = bitcast {}*** %pgcstack to {}**
store {}* %17, {}** %18, align 8
; └
; @ REPL[1]:6 within `f`
ret {}* %12
idxend: ; preds = %idxend, %L44.preheader37
%value_phi14 = phi i64 [ %24, %idxend ], [ 1, %L44.preheader37 ]
; @ REPL[1]:4 within `f`
; ┌ @ array.jl:1019 within `setindex!`
%19 = add nsw i64 %value_phi14, -1
%20 = zext i32 %arrayoffset.pre to i64
%selidx_v = sub nsw i64 %arraysize.pre, %20
%ptindex = getelementptr inbounds [1 x i64], [1 x i64]* %arrayptr1933.pre, i64 %selidx_v
%21 = bitcast [1 x i64]* %ptindex to i8*
%22 = sext i32 %arrayoffset.pre to i64
%23 = getelementptr inbounds i8, i8* %21, i64 %22
%ptindex22 = getelementptr inbounds i8, i8* %23, i64 %19
store i8 1, i8* %ptindex22, align 1
%memcpy_refined_dst23 = getelementptr inbounds [1 x i64], [1 x i64]* %arrayptr1933.pre, i64 %19, i64 0
store i64 0, i64* %memcpy_refined_dst23, align 8
; └
; @ REPL[1]:5 within `f`
; ┌ @ range.jl:897 within `iterate`
%24 = add nuw nsw i64 %value_phi14, 1
; └
%25 = icmp ult i64 %value_phi14, %arraylen9
br i1 %25, label %idxend, label %L58
}
; Function Attrs: noinline optnone
define nonnull {}* @jfptr_f_154({}* %function, {}** noalias nocapture noundef readonly %args, i32 %nargs) #1 {
top:
%0 = getelementptr inbounds {}*, {}** %args, i32 0
%1 = load {}*, {}** %0, align 8
%2 = bitcast {}* %1 to i64*
%3 = load i64, i64* %2, align 8
%4 = call nonnull {}* @julia_f_153(i64 signext %3)
ret {}* %4
}
declare nonnull {}* @j_Array_155({}*) #0
; Function Attrs: noreturn
declare void @ijl_bounds_error_ints({}*, i64*, i64) #2
; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
declare i64 @llvm.umin.i64(i64, i64) #3
declare noalias nonnull {}** @julia.new_gc_frame(i32)
declare void @julia.push_gc_frame({}**, i32)
declare {}** @julia.get_gc_frame_slot({}**, i32)
declare void @julia.pop_gc_frame({}**)
; Function Attrs: inaccessiblemem_or_argmemonly
declare void @ijl_gc_queue_root({}*) #4
; Function Attrs: allocsize(2)
declare noalias nonnull {}* @ijl_gc_pool_alloc(i8*, i32, i32) #5
; Function Attrs: allocsize(1)
declare noalias nonnull {}* @ijl_gc_big_alloc(i8*, i64) #6
; Function Attrs: allocsize(1)
declare noalias nonnull {}* @ijl_gc_alloc_typed(i8*, i64, i8*) #6
; Function Attrs: argmemonly nocallback nofree nounwind willreturn writeonly
declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #7
; Function Attrs: argmemonly nocallback nofree nounwind willreturn writeonly
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #7
attributes #0 = { "frame-pointer"="all" "probe-stack"="inline-asm" }
attributes #1 = { noinline optnone "frame-pointer"="all" "probe-stack"="inline-asm" }
attributes #2 = { noreturn }
attributes #3 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
attributes #4 = { inaccessiblemem_or_argmemonly }
attributes #5 = { allocsize(2) }
attributes #6 = { allocsize(1) }
attributes #7 = { argmemonly nocallback nofree nounwind willreturn writeonly }
attributes #8 = { nounwind }
!llvm.module.flags = !{!0, !1}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3} |
I imagine this will be even more effective once we transition to opaque pointers and all of the unnamed bitcasts go away, since we'll have more instructions being operations on other named instructions. |
This makes it easier to identify where particular LLVM IR statements come from in codegen, without impacting the final generated code (note the array* and memcpy_refined statements in the example). Names are best-effort guesses.
Example