-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
AllocOpt incorrectly lowers a julia object created by a gc.alloc which itself contains several sub objects into a stack allocation of [i8 x 8000]
, instead of either nothing, or a stack allocation of julia objects.
This appears to be the case because the use of the object for storing/loading julia objects occurs through a gep of unknown offset (say %i49 = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %_malloccache.i, i64 %"iv'ac.i.0"
). As a result, addMemOp will never run for the load or store (https://github.com/wsmoses/julia/blob/6a1ba090901cd15378acec12c4f172fb7d4c9e6b/src/llvm-alloc-helpers.cpp#L235). That will prevent the allocation from being marked as having an objref (https://github.com/wsmoses/julia/blob/6a1ba090901cd15378acec12c4f172fb7d4c9e6b/src/llvm-alloc-helpers.cpp#L93) and as a result when iterating through all memops (
Line 234 in 92e68c8
bool has_ref = false; |
cc @vchuravy
Tested on 1.8.1 (and seemingly remains from the code linked above)
; wmoses@beast:~/git/Enzyme.jl/julia8 ((HEAD detached at v1.8.1)) $ /home/wmoses/.julia/artifacts/d9fd2d4dac2bf9a3007c9d4c979ed0e4f9c923e2/tools/opt --enable-new-pm=0 -load ./usr/lib/libjulia-codegen-debug.so min.ll -S -AllocOpt
; ModuleID = 'min.ll'
source_filename = "text"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12:13"
target triple = "x86_64-linux-gnu"
; Function Attrs: nofree readnone
declare {}*** @julia.get_pgcstack() local_unnamed_addr #0
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
; Function Attrs: noreturn
declare void @ijl_bounds_error_ints({} addrspace(12)*, i64*, i64) local_unnamed_addr #2
; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #3
; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #3
; Function Attrs: nofree nosync nounwind willreturn
declare i8* @llvm.stacksave() #4
; Function Attrs: nofree nosync nounwind willreturn
declare void @llvm.stackrestore(i8*) #4
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
; Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
declare void @llvm.memset.p13i8.i64(i8 addrspace(13)* nocapture writeonly, i8, i64, i1 immarg) #5
declare {} addrspace(10)* @ijl_box_int64(i64)
declare {} addrspace(10)* @jl_f_apply_type({} addrspace(10)*, {} addrspace(10)**, i32)
declare {} addrspace(10)* @jl_gc_alloc_typed(i8*, i64, {} addrspace(10)*)
declare {} addrspace(10)* @julia.gc_alloc_obj({}**, i64, {} addrspace(10)*)
declare void @julia.write_barrier({} addrspace(10)*, ...)
; Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #5
declare void @free(i8*)
; Function Attrs: alwaysinline
define void @diffejulia_objective__1864_inner_1wrap({} addrspace(10)* %arg, {} addrspace(10)* %arg1, {} addrspace(10)* %arg2, {} addrspace(10)* %arg3, {} addrspace(10)* %arg4) #6 !dbg !5 {
entry:
%i = call {}*** @julia.get_pgcstack()
%savedstack = call i8* @llvm.stacksave()
%i5 = call {}*** @julia.get_pgcstack()
%i6 = bitcast {} addrspace(10)* %arg4 to double addrspace(13)* addrspace(10)*
%i7 = addrspacecast double addrspace(13)* addrspace(10)* %i6 to double addrspace(13)* addrspace(11)*
%i8 = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %i7, align 16
%"'ipc.i" = bitcast {} addrspace(10)* %arg1 to double addrspace(13)* addrspace(10)*
%i9 = bitcast {} addrspace(10)* %arg to double addrspace(13)* addrspace(10)*
%"'ipc4.i" = addrspacecast double addrspace(13)* addrspace(10)* %"'ipc.i" to double addrspace(13)* addrspace(11)*
%i10 = addrspacecast double addrspace(13)* addrspace(10)* %i9 to double addrspace(13)* addrspace(11)*
%"'ipl.i" = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %"'ipc4.i", align 16
%i11 = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %i10, align 16
%"'ipc7.i" = bitcast {} addrspace(10)* %arg3 to double addrspace(10)*
%i12 = bitcast {} addrspace(10)* %arg2 to double addrspace(10)*
%i13 = bitcast {}*** %i5 to {}**, !dbg !23
%i14 = getelementptr inbounds {}*, {}** %i13, i64 -12, !dbg !23
%i15 = getelementptr inbounds {}*, {}** %i14, i64 14, !dbg !23
%i16 = bitcast {}** %i15 to i8**, !dbg !23
%i17 = load i8*, i8** %i16, align 8, !dbg !23
%i18 = call noalias nonnull dereferenceable(8000) dereferenceable_or_null(8000) {} addrspace(10)* @julia.gc_alloc_obj({}** %i14, i64 8000, {} addrspace(10)* addrspacecast ({}* inttoptr (i64 139756155247504 to {}*) to {} addrspace(10)*)), !dbg !23
%_malloccache.i = bitcast {} addrspace(10)* %i18 to {} addrspace(10)* addrspace(10)*, !dbg !23
%i19 = call noalias nonnull dereferenceable(8000) dereferenceable_or_null(8000) i8* inttoptr (i64 139765672698144 to i8* (i64)*)(i64 8000), !dbg !23
call void @llvm.memset.p0i8.i64(i8* %i19, i8 0, i64 8000, i1 false), !dbg !23
%_malloccache12.i = bitcast i8* %i19 to double*, !dbg !23
%i20 = call noalias nonnull dereferenceable(8000) dereferenceable_or_null(8000) i8* inttoptr (i64 139765672698144 to i8* (i64)*)(i64 8000), !dbg !23
call void @llvm.memset.p0i8.i64(i8* %i20, i8 0, i64 8000, i1 false), !dbg !23
%_malloccache18.i = bitcast i8* %i20 to i64*, !dbg !23
br label %L2.i.i, !dbg !23
L2.i.i: ; preds = %idxend.i.i, %entry
%iv.i = phi i64 [ %iv.next.i, %idxend.i.i ], [ 0, %entry ]
%iv.next.i = add nuw nsw i64 %iv.i, 1, !dbg !25
%i21 = call noalias nonnull {} addrspace(10)* inttoptr (i64 139765662535552 to {} addrspace(10)* ({} addrspace(10)*, i64)*)({} addrspace(10)* noundef addrspacecast ({}* inttoptr (i64 139765316605056 to {}*) to {} addrspace(10)*), i64 noundef 3) #7, !dbg !25
%i22 = call {} addrspace(10)* inttoptr (i64 139765662535552 to {} addrspace(10)* ({} addrspace(10)*, i64)*)({} addrspace(10)* addrspacecast ({}* inttoptr (i64 139765316605056 to {}*) to {} addrspace(10)*), i64 3), !dbg !25
%i23 = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %_malloccache.i, i64 %iv.i, !dbg !25
store {} addrspace(10)* %i22, {} addrspace(10)* addrspace(10)* %i23, align 8, !dbg !25, !invariant.group !36
%i24 = bitcast {} addrspace(10)* addrspace(10)* %_malloccache.i to {} addrspace(10)*, !dbg !25
call void ({} addrspace(10)*, ...) @julia.write_barrier({} addrspace(10)* %i24, {} addrspace(10)* %i22), !dbg !25
%i25 = bitcast {} addrspace(10)* %i22 to i8 addrspace(13)* addrspace(10)*, !dbg !25
%i26 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(10)* %i25, align 8, !dbg !25
call void @llvm.memset.p13i8.i64(i8 addrspace(13)* align 1 %i26, i8 0, i64 24, i1 false), !dbg !25
%i27 = bitcast {} addrspace(10)* %i21 to { i8 addrspace(13)*, i64, i16, i16, i32 } addrspace(10)*, !dbg !37
%i28 = addrspacecast { i8 addrspace(13)*, i64, i16, i16, i32 } addrspace(10)* %i27 to { i8 addrspace(13)*, i64, i16, i16, i32 } addrspace(11)*, !dbg !37
%i29 = getelementptr inbounds { i8 addrspace(13)*, i64, i16, i16, i32 }, { i8 addrspace(13)*, i64, i16, i16, i32 } addrspace(11)* %i28, i64 0, i32 1, !dbg !37
%i30 = load i64, i64 addrspace(11)* %i29, align 8, !dbg !37, !tbaa !49, !range !54
%.not.not.i = icmp eq i64 %i30, 0, !dbg !55
br i1 %.not.not.i, label %oob.i.i, label %idxend.i.i, !dbg !66
oob.i.i: ; preds = %L2.i.i
%.phi.trans.insert.i = bitcast {} addrspace(10)* %i21 to double addrspace(13)* addrspace(10)*
%.phi.trans.insert8.i = addrspacecast double addrspace(13)* addrspace(10)* %.phi.trans.insert.i to double addrspace(13)* addrspace(11)*
%.pre.i = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %.phi.trans.insert8.i, align 8, !dbg !67, !tbaa !70
%i31 = load double, double addrspace(13)* %i8, align 8, !dbg !72, !tbaa !74
%i32 = load double, double addrspace(13)* %i11, align 8, !dbg !77, !tbaa !74
%i33 = fmul double %i31, %i32, !dbg !78
store double %i33, double addrspace(13)* %.pre.i, align 8, !dbg !67, !tbaa !74
%i34 = alloca i64, align 8, !dbg !81
store i64 1, i64* %i34, align 8, !dbg !81
%i35 = addrspacecast {} addrspace(10)* %i21 to {} addrspace(12)*, !dbg !81
call void @ijl_bounds_error_ints({} addrspace(12)* %i35, i64* noundef nonnull align 8 %i34, i64 noundef 1) #8, !dbg !81
unreachable
idxend.i.i: ; preds = %L2.i.i
%"'ipc8.i" = bitcast {} addrspace(10)* %i22 to double addrspace(13)* addrspace(10)*
%i36 = bitcast {} addrspace(10)* %i21 to double addrspace(13)* addrspace(10)*
%"'ipc9.i" = addrspacecast double addrspace(13)* addrspace(10)* %"'ipc8.i" to double addrspace(13)* addrspace(11)*
%i37 = addrspacecast double addrspace(13)* addrspace(10)* %i36 to double addrspace(13)* addrspace(11)*
%"'ipl20.i" = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %"'ipc9.i", align 8, !tbaa !70, !nonnull !4
%i38 = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %i37, align 8, !tbaa !70, !nonnull !4
%"'ipc15.i" = bitcast double addrspace(13)* %"'ipl20.i" to i8 addrspace(13)*, !dbg !83
%i39 = bitcast double addrspace(13)* %i38 to i8 addrspace(13)*, !dbg !83
%i40 = shl nuw i64 %i30, 3, !dbg !83
call void @llvm.memset.p13i8.i64(i8 addrspace(13)* noundef nonnull align 8 %i39, i8 noundef 0, i64 %i40, i1 noundef false) #7, !dbg !84
%i41 = load double, double addrspace(13)* %i8, align 8, !dbg !72, !tbaa !74
%i42 = load double, double addrspace(13)* %i11, align 8, !dbg !77, !tbaa !74
%i43 = fmul double %i41, %i42, !dbg !78
store double %i43, double addrspace(13)* %i38, align 8, !dbg !67, !tbaa !74, !alias.scope !86, !noalias !89
%i44 = getelementptr inbounds i64, i64* %_malloccache18.i, i64 %iv.i, !dbg !91
store i64 %i40, i64* %i44, align 8, !dbg !91, !invariant.group !97
%i45 = getelementptr inbounds double, double* %_malloccache12.i, i64 %iv.i, !dbg !91
store double %i41, double* %i45, align 8, !dbg !91, !tbaa !74, !invariant.group !98
store double %i43, double addrspace(10)* %i12, align 8, !dbg !91, !tbaa !99, !alias.scope !86, !noalias !89
%.not5.i = icmp eq i64 %iv.next.i, 1000, !dbg !102
br i1 %.not5.i, label %julia_objective__1864_inner.exit.i, label %L2.i.i, !dbg !107
julia_objective__1864_inner.exit.i: ; preds = %idxend.i.i
br label %invertidxend.i.i
incinvertL2.i.i: ; preds = %invertidxend.i.i
%i46 = add nsw i64 %"iv'ac.i.0", -1
br label %invertidxend.i.i
invertidxend.i.i: ; preds = %incinvertL2.i.i, %julia_objective__1864_inner.exit.i
%"iv'ac.i.0" = phi i64 [ 999, %julia_objective__1864_inner.exit.i ], [ %i46, %incinvertL2.i.i ]
%i47 = load double, double addrspace(10)* %"'ipc7.i", align 8
store double 0.000000e+00, double addrspace(10)* %"'ipc7.i", align 8, !dbg !91, !tbaa !99, !alias.scope !89, !noalias !86
%i48 = fadd fast double 0.000000e+00, %i47
%i49 = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %_malloccache.i, i64 %"iv'ac.i.0"
%i50 = load {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %i49, align 8, !invariant.group !36
%"'ipc8_unwrap.i" = bitcast {} addrspace(10)* %i50 to double addrspace(13)* addrspace(10)*
%"'ipc9_unwrap.i" = addrspacecast double addrspace(13)* addrspace(10)* %"'ipc8_unwrap.i" to double addrspace(13)* addrspace(11)*
%"'il_phi3_unwrap.i" = load double addrspace(13)*, double addrspace(13)* addrspace(11)* %"'ipc9_unwrap.i", align 8, !tbaa !70
%i51 = load double, double addrspace(13)* %"'il_phi3_unwrap.i", align 8
store double 0.000000e+00, double addrspace(13)* %"'il_phi3_unwrap.i", align 8, !dbg !67, !tbaa !74, !alias.scope !89, !noalias !86
%i52 = fadd fast double %i48, %i51
%i53 = getelementptr inbounds double, double* %_malloccache12.i, i64 %"iv'ac.i.0"
%i54 = load double, double* %i53, align 8, !dbg !72, !tbaa !74, !invariant.group !98
%m1diffe.i = fmul fast double %i52, %i54
%i55 = fadd fast double 0.000000e+00, %m1diffe.i
%i56 = load double, double addrspace(13)* %"'ipl.i", align 8, !dbg !77, !tbaa !74, !alias.scope !89, !noalias !86
%i57 = fadd fast double %i56, %i55
store double %i57, double addrspace(13)* %"'ipl.i", align 8, !dbg !77, !tbaa !74, !alias.scope !89, !noalias !86
%i58 = getelementptr inbounds i64, i64* %_malloccache18.i, i64 %"iv'ac.i.0", !dbg !84
%i59 = load i64, i64* %i58, align 8, !dbg !84, !invariant.group !97
%"'ipc15_unwrap.i" = bitcast double addrspace(13)* %"'il_phi3_unwrap.i" to i8 addrspace(13)*, !dbg !84
call void @llvm.memset.p13i8.i64(i8 addrspace(13)* noundef nonnull align 8 %"'ipc15_unwrap.i", i8 noundef 0, i64 %i59, i1 noundef false) #7, !dbg !84
%i60 = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %_malloccache.i, i64 %"iv'ac.i.0"
%i61 = load {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %i60, align 8, !invariant.group !36
%i62 = icmp eq i64 %"iv'ac.i.0", 0
%i63 = xor i1 %i62, true
br i1 %i62, label %diffejulia_objective__1864_inner.1.exit, label %incinvertL2.i.i
diffejulia_objective__1864_inner.1.exit: ; preds = %invertidxend.i.i
%i64 = bitcast double* %_malloccache12.i to i8*
call void @free(i8* nonnull %i64), !dbg !108
%i65 = bitcast i64* %_malloccache18.i to i8*
call void @free(i8* nonnull %i65), !dbg !108
call void @llvm.stackrestore(i8* %savedstack)
ret void
}
attributes #0 = { nofree readnone "enzyme_inactive" "enzyme_shouldrecompute" }
attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
attributes #2 = { noreturn }
attributes #3 = { argmemonly nofree nosync nounwind willreturn }
attributes #4 = { nofree nosync nounwind willreturn }
attributes #5 = { argmemonly nofree nosync nounwind willreturn writeonly }
attributes #6 = { alwaysinline "probe-stack"="inline-asm" }
attributes #7 = { willreturn mustprogress }
attributes #8 = { noreturn willreturn mustprogress }
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Julia, file: !3, producer: "julia", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, nameTableKind: None)
!3 = !DIFile(filename: "/home/wmoses/git/Enzyme.jl/s.jl", directory: ".")
!4 = !{}
!5 = distinct !DISubprogram(name: "objective!", linkageName: "julia_objective!_1864", scope: null, file: !3, line: 5, type: !6, scopeLine: 5, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !18)
!6 = !DISubroutineType(types: !7)
!7 = !{!8, !9, !10, !15, !10}
!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nothing", align: 8, elements: !4, runtimeLang: DW_LANG_Julia, identifier: "139765312559776")
!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "#objective!", align: 8, elements: !4, runtimeLang: DW_LANG_Julia, identifier: "139765534525648")
!10 = !DIDerivedType(tag: DW_TAG_typedef, name: "Array", baseType: !11)
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64, align: 64)
!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "jl_value_t", file: !13, line: 71, align: 64, elements: !14)
!13 = !DIFile(filename: "julia.h", directory: "")
!14 = !{!11}
!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "RefValue", size: 64, align: 64, elements: !16, runtimeLang: DW_LANG_Julia, identifier: "139765319170656")
!16 = !{!17}
!17 = !DIBasicType(name: "Float64", size: 64, encoding: DW_ATE_unsigned)
!18 = !{!19, !20, !21, !22}
!19 = !DILocalVariable(name: "#self#", arg: 1, scope: !5, file: !3, line: 5, type: !9)
!20 = !DILocalVariable(name: "x", arg: 2, scope: !5, file: !3, line: 5, type: !10)
!21 = !DILocalVariable(name: "loss", arg: 3, scope: !5, file: !3, line: 5, type: !15)
!22 = !DILocalVariable(name: "R", arg: 4, scope: !5, file: !3, line: 5, type: !10)
!23 = !DILocation(line: 6, scope: !5, inlinedAt: !24)
!24 = distinct !DILocation(line: 0, scope: !5)
!25 = !DILocation(line: 459, scope: !26, inlinedAt: !29)
!26 = distinct !DISubprogram(name: "Array;", linkageName: "Array", scope: !27, file: !27, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!27 = !DIFile(filename: "boot.jl", directory: ".")
!28 = !DISubroutineType(types: !4)
!29 = distinct !DILocation(line: 468, scope: !26, inlinedAt: !30)
!30 = distinct !DILocation(line: 588, scope: !31, inlinedAt: !33)
!31 = distinct !DISubprogram(name: "zeros;", linkageName: "zeros", scope: !32, file: !32, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!32 = !DIFile(filename: "array.jl", directory: ".")
!33 = distinct !DILocation(line: 585, scope: !31, inlinedAt: !34)
!34 = distinct !DILocation(line: 583, scope: !31, inlinedAt: !35)
!35 = distinct !DILocation(line: 8, scope: !5, inlinedAt: !24)
!36 = distinct !{}
!37 = !DILocation(line: 151, scope: !38, inlinedAt: !39)
!38 = distinct !DISubprogram(name: "size;", linkageName: "size", scope: !32, file: !32, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!39 = distinct !DILocation(line: 95, scope: !40, inlinedAt: !42)
!40 = distinct !DISubprogram(name: "axes;", linkageName: "axes", scope: !41, file: !41, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!41 = !DIFile(filename: "abstractarray.jl", directory: ".")
!42 = distinct !DILocation(line: 116, scope: !43, inlinedAt: !44)
!43 = distinct !DISubprogram(name: "axes1;", linkageName: "axes1", scope: !41, file: !41, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!44 = distinct !DILocation(line: 285, scope: !45, inlinedAt: !46)
!45 = distinct !DISubprogram(name: "eachindex;", linkageName: "eachindex", scope: !41, file: !41, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!46 = distinct !DILocation(line: 352, scope: !47, inlinedAt: !48)
!47 = distinct !DISubprogram(name: "fill!;", linkageName: "fill!", scope: !32, file: !32, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!48 = distinct !DILocation(line: 589, scope: !31, inlinedAt: !33)
!49 = !{!50, !50, i64 0}
!50 = !{!"jtbaa_arraylen", !51, i64 0}
!51 = !{!"jtbaa_array", !52, i64 0}
!52 = !{!"jtbaa", !53, i64 0}
!53 = !{!"jtbaa"}
!54 = !{i64 0, i64 9223372036854775807}
!55 = !DILocation(line: 83, scope: !56, inlinedAt: !58)
!56 = distinct !DISubprogram(name: "<;", linkageName: "<", scope: !57, file: !57, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!57 = !DIFile(filename: "int.jl", directory: ".")
!58 = distinct !DILocation(line: 382, scope: !59, inlinedAt: !61)
!59 = distinct !DISubprogram(name: ">;", linkageName: ">", scope: !60, file: !60, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!60 = !DIFile(filename: "operators.jl", directory: ".")
!61 = distinct !DILocation(line: 654, scope: !62, inlinedAt: !64)
!62 = distinct !DISubprogram(name: "isempty;", linkageName: "isempty", scope: !63, file: !63, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!63 = !DIFile(filename: "range.jl", directory: ".")
!64 = distinct !DILocation(line: 879, scope: !65, inlinedAt: !46)
!65 = distinct !DISubprogram(name: "iterate;", linkageName: "iterate", scope: !63, file: !63, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!66 = !DILocation(line: 352, scope: !47, inlinedAt: !48)
!67 = !DILocation(line: 966, scope: !68, inlinedAt: !69)
!68 = distinct !DISubprogram(name: "setindex!;", linkageName: "setindex!", scope: !32, file: !32, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!69 = distinct !DILocation(line: 9, scope: !5, inlinedAt: !24)
!70 = !{!71, !71, i64 0}
!71 = !{!"jtbaa_arrayptr", !51, i64 0}
!72 = !DILocation(line: 925, scope: !73, inlinedAt: !69)
!73 = distinct !DISubprogram(name: "getindex;", linkageName: "getindex", scope: !32, file: !32, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!74 = !{!75, !75, i64 0}
!75 = !{!"jtbaa_arraybuf", !76, i64 0}
!76 = !{!"jtbaa_data", !52, i64 0}
!77 = !DILocation(line: 924, scope: !73, inlinedAt: !69)
!78 = !DILocation(line: 385, scope: !79, inlinedAt: !69)
!79 = distinct !DISubprogram(name: "*;", linkageName: "*", scope: !80, file: !80, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!80 = !DIFile(filename: "float.jl", directory: ".")
!81 = !DILocation(line: 924, scope: !73, inlinedAt: !82)
!82 = distinct !DILocation(line: 10, scope: !5, inlinedAt: !24)
!83 = !DILocation(line: 354, scope: !47, inlinedAt: !48)
!84 = !DILocation(line: 966, scope: !68, inlinedAt: !85)
!85 = distinct !DILocation(line: 353, scope: !47, inlinedAt: !48)
!86 = !{!87}
!87 = distinct !{!87, !88, !"primal"}
!88 = distinct !{!88, !" diff: %"}
!89 = !{!90}
!90 = distinct !{!90, !88, !"shadow_0"}
!91 = !DILocation(line: 39, scope: !92, inlinedAt: !94)
!92 = distinct !DISubprogram(name: "setproperty!;", linkageName: "setproperty!", scope: !93, file: !93, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!93 = !DIFile(filename: "Base.jl", directory: ".")
!94 = distinct !DILocation(line: 57, scope: !95, inlinedAt: !82)
!95 = distinct !DISubprogram(name: "setindex!;", linkageName: "setindex!", scope: !96, file: !96, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!96 = !DIFile(filename: "refvalue.jl", directory: ".")
!97 = distinct !{}
!98 = distinct !{}
!99 = !{!100, !100, i64 0}
!100 = !{!"jtbaa_mutab", !101, i64 0}
!101 = !{!"jtbaa_value", !76, i64 0}
!102 = !DILocation(line: 477, scope: !103, inlinedAt: !105)
!103 = distinct !DISubprogram(name: "==;", linkageName: "==", scope: !104, file: !104, type: !28, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!104 = !DIFile(filename: "promotion.jl", directory: ".")
!105 = distinct !DILocation(line: 883, scope: !65, inlinedAt: !106)
!106 = distinct !DILocation(line: 11, scope: !5, inlinedAt: !24)
!107 = !DILocation(line: 11, scope: !5, inlinedAt: !24)
!108 = !DILocation(line: 0, scope: !5)