; LLVM IR from humz2k/sugaryc :: ext/bdwgc/extra (gc)

; Unoptimized IR (clang -disable-llvm-passes):
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%struct.GC_hblk_s = type { [4096 x i8] }
%struct.hblkhdr = type { ptr, ptr, ptr, i8, i8, i16, i64, i64, ptr, i64, [5 x i64] }

@GC_same_obj_print_proc = external dso_local global ptr, align 8
@GC_is_initialized = external hidden global i32, align 4

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #0

; Function Attrs: nounwind uwtable
define dso_local ptr @GC_same_obj(ptr noundef %0, ptr noundef %1) #1 {
  %3 = alloca ptr, align 8
  %4 = alloca ptr, align 8
  %5 = alloca ptr, align 8
  %6 = alloca ptr, align 8
  %7 = alloca ptr, align 8
  %8 = alloca ptr, align 8
  %9 = alloca ptr, align 8
  %10 = alloca i64, align 8
  %11 = alloca i32, align 4
  %12 = alloca i64, align 8
  %13 = alloca i64, align 8
  store ptr %0, ptr %4, align 8, !tbaa !5
  store ptr %1, ptr %5, align 8, !tbaa !5
  call void @llvm.lifetime.start.p0(i64 8, ptr %6) #3
  call void @llvm.lifetime.start.p0(i64 8, ptr %7) #3
  call void @llvm.lifetime.start.p0(i64 8, ptr %8) #3
  call void @llvm.lifetime.start.p0(i64 8, ptr %9) #3
  call void @llvm.lifetime.start.p0(i64 8, ptr %10) #3
  %14 = load i32, ptr @GC_is_initialized, align 4, !tbaa !9
  %15 = sext i32 %14 to i64
  %16 = call i64 @llvm.expect.i64(i64 %15, i64 1)
  %17 = icmp ne i64 %16, 0
  br i1 %17, label %19, label %18

18:                                               ; preds = %2
  call void @GC_init()
  br label %19

19:                                               ; preds = %18, %2
  %20 = load ptr, ptr %4, align 8, !tbaa !5
  %21 = ptrtoint ptr %20 to i64
  %22 = inttoptr i64 %21 to ptr
  %23 = call ptr @GC_find_header(ptr noundef %22)
  store ptr %23, ptr %7, align 8, !tbaa !5
  %24 = load ptr, ptr %7, align 8, !tbaa !5
  %25 = icmp eq ptr null, %24
  br i1 %25, label %26, label %43

26:                                               ; preds = %19
  %27 = load ptr, ptr %4, align 8, !tbaa !5
  %28 = ptrtoint ptr %27 to i64
  %29 = lshr i64 %28, 12
  %30 = load ptr, ptr %5, align 8, !tbaa !5
  %31 = ptrtoint ptr %30 to i64
  %32 = lshr i64 %31, 12
  %33 = icmp ne i64 %29, %32
  br i1 %33, label %34, label %41

34:                                               ; preds = %26
  %35 = load ptr, ptr %5, align 8, !tbaa !5
  %36 = ptrtoint ptr %35 to i64
  %37 = inttoptr i64 %36 to ptr
  %38 = call ptr @GC_find_header(ptr noundef %37)
  %39 = icmp ne ptr %38, null
  br i1 %39, label %40, label %41

40:                                               ; preds = %34
  br label %160

41:                                               ; preds = %34, %26
  %42 = load ptr, ptr %4, align 8, !tbaa !5
  store ptr %42, ptr %3, align 8
  store i32 1, ptr %11, align 4
  br label %165

43:                                               ; preds = %19
  %44 = load ptr, ptr %7, align 8, !tbaa !5
  %45 = ptrtoint ptr %44 to i64
  %46 = icmp ule i64 %45, 4095
  br i1 %46, label %47, label %96

47:                                               ; preds = %43
  %48 = load ptr, ptr %4, align 8, !tbaa !5
  %49 = ptrtoint ptr %48 to i64
  %50 = and i64 %49, -4096
  %51 = inttoptr i64 %50 to ptr
  %52 = load ptr, ptr %7, align 8, !tbaa !5
  %53 = ptrtoint ptr %52 to i64
  %54 = sub i64 0, %53
  %55 = getelementptr inbounds %struct.GC_hblk_s, ptr %51, i64 %54
  store ptr %55, ptr %6, align 8, !tbaa !5
  %56 = load ptr, ptr %6, align 8, !tbaa !5
  %57 = call ptr @GC_find_header(ptr noundef %56)
  store ptr %57, ptr %7, align 8, !tbaa !5
  br label %58

58:                                               ; preds = %62, %47
  %59 = load ptr, ptr %7, align 8, !tbaa !5
  %60 = ptrtoint ptr %59 to i64
  %61 = icmp ule i64 %60, 4095
  br i1 %61, label %62, label %70

62:                                               ; preds = %58
  %63 = load ptr, ptr %6, align 8, !tbaa !5
  %64 = load ptr, ptr %7, align 8, !tbaa !5
  %65 = ptrtoint ptr %64 to i64
  %66 = sub i64 0, %65
  %67 = getelementptr inbounds %struct.GC_hblk_s, ptr %63, i64 %66
  store ptr %67, ptr %6, align 8, !tbaa !5
  %68 = load ptr, ptr %6, align 8, !tbaa !5
  %69 = call ptr @GC_find_header(ptr noundef %68)
  store ptr %69, ptr %7, align 8, !tbaa !5
  br label %58, !llvm.loop !11

70:                                               ; preds = %58
  %71 = load ptr, ptr %6, align 8, !tbaa !5
  %72 = load ptr, ptr %7, align 8, !tbaa !5
  %73 = getelementptr inbounds %struct.hblkhdr, ptr %72, i32 0, i32 6
  %74 = load i64, ptr %73, align 8, !tbaa !13
  %75 = getelementptr inbounds i8, ptr %71, i64 %74
  store ptr %75, ptr %9, align 8, !tbaa !5
  %76 = load ptr, ptr %4, align 8, !tbaa !5
  %77 = ptrtoint ptr %76 to i64
  %78 = load ptr, ptr %9, align 8, !tbaa !5
  %79 = ptrtoint ptr %78 to i64
  %80 = icmp uge i64 %77, %79
  br i1 %80, label %93, label %81

81:                                               ; preds = %70
  %82 = load ptr, ptr %5, align 8, !tbaa !5
  %83 = ptrtoint ptr %82 to i64
  %84 = load ptr, ptr %9, align 8, !tbaa !5
  %85 = ptrtoint ptr %84 to i64
  %86 = icmp uge i64 %83, %85
  br i1 %86, label %93, label %87

87:                                               ; preds = %81
  %88 = load ptr, ptr %5, align 8, !tbaa !5
  %89 = ptrtoint ptr %88 to i64
  %90 = load ptr, ptr %6, align 8, !tbaa !5
  %91 = ptrtoint ptr %90 to i64
  %92 = icmp ult i64 %89, %91
  br i1 %92, label %93, label %94

93:                                               ; preds = %87, %81, %70
  br label %160

94:                                               ; preds = %87
  %95 = load ptr, ptr %4, align 8, !tbaa !5
  store ptr %95, ptr %3, align 8
  store i32 1, ptr %11, align 4
  br label %165

96:                                               ; preds = %43
  %97 = load ptr, ptr %7, align 8, !tbaa !5
  %98 = getelementptr inbounds %struct.hblkhdr, ptr %97, i32 0, i32 6
  %99 = load i64, ptr %98, align 8, !tbaa !13
  store i64 %99, ptr %10, align 8, !tbaa !17
  %100 = load i64, ptr %10, align 8, !tbaa !17
  %101 = icmp ugt i64 %100, 2048
  br i1 %101, label %102, label %117

102:                                              ; preds = %96
  %103 = load ptr, ptr %4, align 8, !tbaa !5
  %104 = ptrtoint ptr %103 to i64
  %105 = and i64 %104, -4096
  %106 = inttoptr i64 %105 to ptr
  store ptr %106, ptr %8, align 8, !tbaa !5
  %107 = load ptr, ptr %8, align 8, !tbaa !5
  %108 = load i64, ptr %10, align 8, !tbaa !17
  %109 = getelementptr inbounds i8, ptr %107, i64 %108
  store ptr %109, ptr %9, align 8, !tbaa !5
  %110 = load ptr, ptr %4, align 8, !tbaa !5
  %111 = ptrtoint ptr %110 to i64
  %112 = load ptr, ptr %9, align 8, !tbaa !5
  %113 = ptrtoint ptr %112 to i64
  %114 = icmp uge i64 %111, %113
  br i1 %114, label %115, label %116

115:                                              ; preds = %102
  br label %160

116:                                              ; preds = %102
  br label %145

117:                                              ; preds = %96
  call void @llvm.lifetime.start.p0(i64 8, ptr %12) #3
  call void @llvm.lifetime.start.p0(i64 8, ptr %13) #3
  %118 = load ptr, ptr %4, align 8, !tbaa !5
  %119 = ptrtoint ptr %118 to i64
  %120 = and i64 %119, 4095
  store i64 %120, ptr %13, align 8, !tbaa !17
  %121 = load i64, ptr %13, align 8, !tbaa !17
  %122 = load i64, ptr %10, align 8, !tbaa !17
  %123 = urem i64 %121, %122
  store i64 %123, ptr %12, align 8, !tbaa !17
  %124 = load ptr, ptr %4, align 8, !tbaa !5
  %125 = ptrtoint ptr %124 to i64
  %126 = and i64 %125, -4096
  %127 = inttoptr i64 %126 to ptr
  %128 = load ptr, ptr %5, align 8, !tbaa !5
  %129 = ptrtoint ptr %128 to i64
  %130 = and i64 %129, -4096
  %131 = inttoptr i64 %130 to ptr
  %132 = icmp ne ptr %127, %131
  br i1 %132, label %133, label %134

133:                                              ; preds = %117
  store i32 2, ptr %11, align 4
  br label %142

134:                                              ; preds = %117
  %135 = load ptr, ptr %4, align 8, !tbaa !5
  %136 = load i64, ptr %12, align 8, !tbaa !17
  %137 = sub i64 0, %136
  %138 = getelementptr inbounds i8, ptr %135, i64 %137
  store ptr %138, ptr %8, align 8, !tbaa !5
  %139 = load ptr, ptr %8, align 8, !tbaa !5
  %140 = load i64, ptr %10, align 8, !tbaa !17
  %141 = getelementptr inbounds i8, ptr %139, i64 %140
  store ptr %141, ptr %9, align 8, !tbaa !5
  store i32 0, ptr %11, align 4
  br label %142

142:                                              ; preds = %134, %133
  call void @llvm.lifetime.end.p0(i64 8, ptr %13) #3
  call void @llvm.lifetime.end.p0(i64 8, ptr %12) #3
  %143 = load i32, ptr %11, align 4
  switch i32 %143, label %165 [
    i32 0, label %144
    i32 2, label %160
  ]

144:                                              ; preds = %142
  br label %145

145:                                              ; preds = %144, %116
  %146 = load ptr, ptr %5, align 8, !tbaa !5
  %147 = ptrtoint ptr %146 to i64
  %148 = load ptr, ptr %9, align 8, !tbaa !5
  %149 = ptrtoint ptr %148 to i64
  %150 = icmp uge i64 %147, %149
  br i1 %150, label %157, label %151

151:                                              ; preds = %145
  %152 = load ptr, ptr %5, align 8, !tbaa !5
  %153 = ptrtoint ptr %152 to i64
  %154 = load ptr, ptr %8, align 8, !tbaa !5
  %155 = ptrtoint ptr %154 to i64
  %156 = icmp ult i64 %153, %155
  br i1 %156, label %157, label %158

157:                                              ; preds = %151, %145
  br label %160

158:                                              ; preds = %151
  %159 = load ptr, ptr %4, align 8, !tbaa !5
  store ptr %159, ptr %3, align 8
  store i32 1, ptr %11, align 4
  br label %165

160:                                              ; preds = %157, %142, %115, %93, %40
  %161 = load ptr, ptr @GC_same_obj_print_proc, align 8, !tbaa !5
  %162 = load ptr, ptr %4, align 8, !tbaa !5
  %163 = load ptr, ptr %5, align 8, !tbaa !5
  call void %161(ptr noundef %162, ptr noundef %163)
  %164 = load ptr, ptr %4, align 8, !tbaa !5
  store ptr %164, ptr %3, align 8
  store i32 1, ptr %11, align 4
  br label %165

165:                                              ; preds = %160, %158, %142, %94, %41
  call void @llvm.lifetime.end.p0(i64 8, ptr %10) #3
  call void @llvm.lifetime.end.p0(i64 8, ptr %9) #3
  call void @llvm.lifetime.end.p0(i64 8, ptr %8) #3
  call void @llvm.lifetime.end.p0(i64 8, ptr %7) #3
  call void @llvm.lifetime.end.p0(i64 8, ptr %6) #3
  %166 = load ptr, ptr %3, align 8
  ret ptr %166
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
declare i64 @llvm.expect.i64(i64, i64) #2

; Function Attrs: nounwind uwtable
declare dso_local void @GC_init() #1

; Function Attrs: nounwind uwtable
declare hidden ptr @GC_find_header(ptr noundef) #1

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #1 = { nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) }
attributes #3 = { nounwind }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{!"clang version 19.1.0 (git@github.com:llvm/llvm-project.git a4bf6cd7cfb1a1421ba92bca9d017b49936c55e4)"}
!5 = !{!6, !6, i64 0}
!6 = !{!"any pointer", !7, i64 0}
!7 = !{!"omnipotent char", !8, i64 0}
!8 = !{!"Simple C/C++ TBAA"}
!9 = !{!10, !10, i64 0}
!10 = !{!"int", !7, i64 0}
!11 = distinct !{!11, !12}
!12 = !{!"llvm.loop.mustprogress"}
!13 = !{!14, !16, i64 32}
!14 = !{!"hblkhdr", !6, i64 0, !6, i64 8, !6, i64 16, !7, i64 24, !7, i64 25, !15, i64 26, !16, i64 32, !16, i64 40, !6, i64 48, !16, i64 56, !7, i64 64}
!15 = !{!"short", !7, i64 0}
!16 = !{!"long", !7, i64 0}
!17 = !{!16, !16, i64 0}


; Optimized IR (opt -passes='default<O3>'):
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%struct.GC_hblk_s = type { [4096 x i8] }

@GC_same_obj_print_proc = external dso_local local_unnamed_addr global ptr, align 8
@GC_is_initialized = external hidden local_unnamed_addr global i32, align 4

; Function Attrs: nounwind uwtable
define dso_local noundef ptr @GC_same_obj(ptr noundef returned %0, ptr noundef %1) local_unnamed_addr #0 {
  %3 = load i32, ptr @GC_is_initialized, align 4, !tbaa !5
  %.not = icmp eq i32 %3, 0
  br i1 %.not, label %4, label %5, !prof !9

4:                                                ; preds = %2
  tail call void @GC_init()
  br label %5

5:                                                ; preds = %4, %2
  %6 = ptrtoint ptr %0 to i64
  %7 = tail call ptr @GC_find_header(ptr noundef %0)
  %8 = icmp eq ptr %7, null
  br i1 %8, label %9, label %13

9:                                                ; preds = %5
  %10 = ptrtoint ptr %1 to i64
  %.not66.unshifted = xor i64 %10, %6
  %.not66 = icmp ult i64 %.not66.unshifted, 4096
  br i1 %.not66, label %53, label %11

11:                                               ; preds = %9
  %12 = tail call ptr @GC_find_header(ptr noundef %1)
  %.not67 = icmp eq ptr %12, null
  br i1 %.not67, label %53, label %51

13:                                               ; preds = %5
  %14 = icmp ult ptr %7, inttoptr (i64 4096 to ptr)
  br i1 %14, label %15, label %32

15:                                               ; preds = %13
  %16 = ptrtoint ptr %7 to i64
  %17 = and i64 %6, -4096
  %18 = inttoptr i64 %17 to ptr
  %19 = sub nsw i64 0, %16
  %20 = getelementptr inbounds %struct.GC_hblk_s, ptr %18, i64 %19
  %21 = tail call ptr @GC_find_header(ptr noundef nonnull %20)
  %22 = icmp ult ptr %21, inttoptr (i64 4096 to ptr)
  br i1 %22, label %.lr.ph, label %._crit_edge

.lr.ph:                                           ; preds = %15, %.lr.ph
  %.04877 = phi ptr [ %25, %.lr.ph ], [ %20, %15 ]
  %.05076 = phi ptr [ %26, %.lr.ph ], [ %21, %15 ]
  %23 = ptrtoint ptr %.05076 to i64
  %24 = sub nsw i64 0, %23
  %25 = getelementptr inbounds %struct.GC_hblk_s, ptr %.04877, i64 %24
  %26 = tail call ptr @GC_find_header(ptr noundef %25)
  %27 = icmp ult ptr %26, inttoptr (i64 4096 to ptr)
  br i1 %27, label %.lr.ph, label %._crit_edge, !llvm.loop !10

._crit_edge:                                      ; preds = %.lr.ph, %15
  %.050.lcssa = phi ptr [ %21, %15 ], [ %26, %.lr.ph ]
  %.048.lcssa = phi ptr [ %20, %15 ], [ %25, %.lr.ph ]
  %28 = getelementptr inbounds i8, ptr %.050.lcssa, i64 32
  %29 = load i64, ptr %28, align 8, !tbaa !12
  %30 = getelementptr inbounds i8, ptr %.048.lcssa, i64 %29
  %.not64 = icmp ule ptr %30, %0
  %.not65 = icmp ule ptr %30, %1
  %or.cond.not75 = or i1 %.not64, %.not65
  %31 = icmp ugt ptr %.048.lcssa, %1
  %or.cond68 = or i1 %31, %or.cond.not75
  br i1 %or.cond68, label %51, label %53

32:                                               ; preds = %13
  %33 = getelementptr inbounds i8, ptr %7, i64 32
  %34 = load i64, ptr %33, align 8, !tbaa !12
  %35 = icmp ugt i64 %34, 2048
  %36 = and i64 %6, -4096
  %37 = inttoptr i64 %36 to ptr
  br i1 %35, label %38, label %40

38:                                               ; preds = %32
  %39 = getelementptr inbounds i8, ptr %37, i64 %34
  %.not62 = icmp ugt ptr %39, %0
  br i1 %.not62, label %49, label %51

40:                                               ; preds = %32
  %41 = ptrtoint ptr %1 to i64
  %42 = and i64 %41, -4096
  %43 = inttoptr i64 %42 to ptr
  %.not61 = icmp eq ptr %37, %43
  br i1 %.not61, label %.thread, label %51

.thread:                                          ; preds = %40
  %44 = trunc i64 %6 to i16
  %.lhs.trunc = and i16 %44, 4095
  %.rhs.trunc = trunc nuw i64 %34 to i16
  %45 = urem i16 %.lhs.trunc, %.rhs.trunc
  %.zext = zext nneg i16 %45 to i64
  %46 = sub nsw i64 0, %.zext
  %47 = getelementptr inbounds i8, ptr %0, i64 %46
  %48 = getelementptr inbounds i8, ptr %47, i64 %34
  br label %49

49:                                               ; preds = %.thread, %38
  %.153 = phi ptr [ %37, %38 ], [ %47, %.thread ]
  %.1 = phi ptr [ %39, %38 ], [ %48, %.thread ]
  %.not63 = icmp ule ptr %.1, %1
  %50 = icmp ugt ptr %.153, %1
  %or.cond70 = select i1 %.not63, i1 true, i1 %50
  br i1 %or.cond70, label %51, label %53

51:                                               ; preds = %40, %49, %38, %._crit_edge, %11
  %52 = load ptr, ptr @GC_same_obj_print_proc, align 8, !tbaa !17
  tail call void %52(ptr noundef %0, ptr noundef %1) #1
  br label %53

53:                                               ; preds = %49, %._crit_edge, %9, %11, %51
  ret ptr %0
}

; Function Attrs: nounwind uwtable
declare dso_local void @GC_init() local_unnamed_addr #0

; Function Attrs: nounwind uwtable
declare hidden ptr @GC_find_header(ptr noundef) local_unnamed_addr #0

attributes #0 = { nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { nounwind }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{!"clang version 19.1.0 (git@github.com:llvm/llvm-project.git a4bf6cd7cfb1a1421ba92bca9d017b49936c55e4)"}
!5 = !{!6, !6, i64 0}
!6 = !{!"int", !7, i64 0}
!7 = !{!"omnipotent char", !8, i64 0}
!8 = !{!"Simple C/C++ TBAA"}
!9 = !{!"branch_weights", !"expected", i32 1, i32 2000}
!10 = distinct !{!10, !11}
!11 = !{!"llvm.loop.mustprogress"}
!12 = !{!13, !16, i64 32}
!13 = !{!"hblkhdr", !14, i64 0, !14, i64 8, !14, i64 16, !7, i64 24, !7, i64 25, !15, i64 26, !16, i64 32, !16, i64 40, !14, i64 48, !16, i64 56, !7, i64 64}
!14 = !{!"any pointer", !7, i64 0}
!15 = !{!"short", !7, i64 0}
!16 = !{!"long", !7, i64 0}
!17 = !{!14, !14, i64 0}


; Effective O3 passes: CorrelatedValuePropagationPass,EarlyCSEPass,GVNPass,GlobalOptPass,IPSCCPPass,InferFunctionAttrsPass,InstCombinePass,InstSimplifyPass,JumpThreadingPass,LCSSAPass,LoopRotatePass,LoopSimplifyPass,LoopUnrollPass,LowerExpectIntrinsicPass,PostOrderFunctionAttrsPass,ReassociatePass,SROAPass,SimplifyCFGPass,TailCallElimPass