; LLVM IR from erthink/libmdbx :: src (tls)

; 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.libmdbx_globals = type { %union.bin128, i32, i32, i8, i8, i8, i8, i32, %union.logger_union, %union.pthread_mutex_t, i64, ptr }
%union.bin128 = type { %struct.anon.9 }
%struct.anon.9 = type { i64, i64 }
%union.logger_union = type { ptr }
%union.pthread_mutex_t = type { %struct.__pthread_mutex_s }
%struct.__pthread_mutex_s = type { i32, i32, i32, i32, i32, i16, i16, %struct.__pthread_internal_list }
%struct.__pthread_internal_list = type { ptr, ptr }
%union.mdbx_atomic_uint32_t = type { i32 }
%union.pthread_cond_t = type { %struct.__pthread_cond_s }
%struct.__pthread_cond_s = type { %union.__atomic_wide_counter, %union.__atomic_wide_counter, [2 x i32], [2 x i32], i32, i32, [2 x i32] }
%union.__atomic_wide_counter = type { i64 }
%struct.rthc_entry = type { ptr }
%struct.MDBX_env = type { %union.mdbx_atomic_uint32_t, i32, i32, %struct.osal_mmap, i32, i32, %struct.osal_mmap, ptr, i16, i16, i16, i16, i16, i16, %union.mdbx_atomic_uint32_t, i8, i8, i16, i32, i32, i32, i32, %struct.anon, ptr, ptr, ptr, ptr, ptr, i32, i32, i32, ptr, ptr, i64, %struct.anon.0, %struct.anon.4, i8, ptr, ptr, ptr, %struct.anon.5, %union.pthread_mutex_t, i32, i32, ptr, %struct.osal_ioring, %union.pthread_mutex_t, [71 x %union.mdbx_atomic_uint64_t] }
%struct.osal_mmap = type { %union.anon, i32, i64, i64, i64 }
%union.anon = type { ptr }
%struct.anon = type { ptr, ptr, ptr, ptr }
%struct.anon.0 = type { i32, i32, i32, i32, i64, i8, i8, i8, i8, i32, i32, i8, i8, i8, %struct.anon.1, %union.anon.2 }
%struct.anon.1 = type { i16, i16, i16, i16 }
%union.anon.2 = type { i32 }
%struct.anon.4 = type { i64, i64, i64, i64, i64 }
%struct.anon.5 = type { i64 }
%struct.osal_ioring = type { i32, i32, i32, ptr, ptr, ptr }
%union.mdbx_atomic_uint64_t = type { i64 }
%struct.shared_lck = type { i64, i32, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, [2 x %union.mdbx_atomic_uint32_t], [16 x i8], %struct.pgops, [16 x i8], %union.pthread_mutex_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint32_t, i32, %struct.anon.8, %union.pthread_mutex_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint32_t, [16 x i8], [0 x %struct.reader_slot] }
%struct.pgops = type { %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint32_t, %struct.anon.6 }
%struct.anon.6 = type { %struct.gc_prof_stat, %struct.gc_prof_stat, i32, i32, i32, i32, i32 }
%struct.gc_prof_stat = type { i64, i64, i32, i32, i32, i32, %struct.anon.7 }
%struct.anon.7 = type { i64, i64, i32 }
%struct.anon.8 = type { [4 x i32], [4 x i64] }
%struct.reader_slot = type { %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint64_t }

@rthc_count = external hidden global i32, align 4
@rthc_table = external hidden global ptr, align 8
@globals = external global %struct.libmdbx_globals, align 8
@rthc_mutex = external hidden global %union.pthread_mutex_t, align 8
@rthc_pending = external hidden global %union.mdbx_atomic_uint32_t, align 4
@__func__.rthc_thread_dtor = external hidden unnamed_addr constant [17 x i8], align 1
@.str.12 = external hidden unnamed_addr constant [34 x i8], align 1
@.str.13 = external hidden unnamed_addr constant [61 x i8], align 1
@.str.14 = external hidden unnamed_addr constant [79 x i8], align 1
@.str.15 = external hidden unnamed_addr constant [37 x i8], align 1
@.str.16 = external hidden unnamed_addr constant [60 x i8], align 1
@.str.17 = external hidden unnamed_addr constant [11 x i8], align 1
@.str.18 = external hidden unnamed_addr constant [8 x i8], align 1
@.str.19 = external hidden unnamed_addr constant [35 x i8], align 1
@.str.20 = external hidden unnamed_addr constant [57 x i8], align 1
@.str.21 = external hidden unnamed_addr constant [6 x i8], align 1
@.str.22 = external hidden unnamed_addr constant [40 x i8], align 1
@rthc_cond = external hidden global %union.pthread_cond_t, align 8
@.str.23 = external hidden unnamed_addr constant [40 x i8], align 1
@.str.24 = external hidden unnamed_addr constant [26 x i8], align 1

; 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(none)
declare i64 @llvm.expect.i64(i64, i64) #1

declare void @debug_log(i32 noundef, ptr noundef, i32 noundef, ptr noundef, ...) #2

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

; Function Attrs: inlinehint nounwind uwtable
declare hidden ptr @__Wpedantic_format_voidptr(ptr noundef) #3

; Function Attrs: nounwind uwtable
declare dso_local void @rthc_lock() #4

; Function Attrs: noreturn
declare void @mdbx_assert_fail(ptr noundef, ptr noundef, ptr noundef, i32 noundef) #5

; Function Attrs: nounwind
declare i32 @pthread_mutex_unlock(ptr noundef) #6

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @rthc_signature(ptr noundef, i8 noundef zeroext) #3

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @osal_thread_self() #3

; Function Attrs: cold nounwind optsize uwtable
define dso_local void @rthc_thread_dtor(ptr noundef %0) #7 {
  %2 = alloca ptr, align 8
  %3 = alloca i32, align 4
  %4 = alloca i64, align 8
  %5 = alloca i32, align 4
  %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 i64, align 8
  %12 = alloca i64, align 8
  store ptr %0, ptr %2, align 8, !tbaa !5
  call void @rthc_lock()
  call void @llvm.lifetime.start.p0(i64 4, ptr %3) #9
  %13 = call i32 @osal_getpid()
  store i32 %13, ptr %3, align 4, !tbaa !9
  br label %14

14:                                               ; preds = %1
  %15 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %16 = zext i8 %15 to i32
  %17 = icmp sle i32 6, %16
  %18 = xor i1 %17, true
  %19 = xor i1 %18, true
  %20 = zext i1 %19 to i32
  %21 = sext i32 %20 to i64
  %22 = call i64 @llvm.expect.i64(i64 %21, i64 0)
  %23 = icmp ne i64 %22, 0
  br i1 %23, label %24, label %28

24:                                               ; preds = %14
  %25 = load i32, ptr %3, align 4, !tbaa !9
  %26 = call i64 @osal_thread_self()
  %27 = load ptr, ptr %2, align 8, !tbaa !5
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 264, ptr noundef @.str.12, i32 noundef %25, i64 noundef %26, ptr noundef %27)
  br label %28

28:                                               ; preds = %24, %14
  br label %29

29:                                               ; preds = %28
  br label %30

30:                                               ; preds = %29
  call void @llvm.lifetime.start.p0(i64 8, ptr %4) #9
  store i64 0, ptr %4, align 8, !tbaa !15
  br label %31

31:                                               ; preds = %180, %30
  %32 = load i64, ptr %4, align 8, !tbaa !15
  %33 = load i32, ptr @rthc_count, align 4, !tbaa !9
  %34 = zext i32 %33 to i64
  %35 = icmp ult i64 %32, %34
  br i1 %35, label %37, label %36

36:                                               ; preds = %31
  store i32 4, ptr %5, align 4
  call void @llvm.lifetime.end.p0(i64 8, ptr %4) #9
  br label %183

37:                                               ; preds = %31
  call void @llvm.lifetime.start.p0(i64 8, ptr %6) #9
  %38 = load ptr, ptr @rthc_table, align 8, !tbaa !5
  %39 = load i64, ptr %4, align 8, !tbaa !15
  %40 = getelementptr inbounds %struct.rthc_entry, ptr %38, i64 %39
  %41 = getelementptr inbounds %struct.rthc_entry, ptr %40, i32 0, i32 0
  %42 = load ptr, ptr %41, align 8, !tbaa !16
  store ptr %42, ptr %6, align 8, !tbaa !5
  %43 = load ptr, ptr %6, align 8, !tbaa !5
  %44 = getelementptr inbounds %struct.MDBX_env, ptr %43, i32 0, i32 20
  %45 = load i32, ptr %44, align 4, !tbaa !18
  %46 = load i32, ptr %3, align 4, !tbaa !9
  %47 = icmp ne i32 %45, %46
  br i1 %47, label %48, label %49

48:                                               ; preds = %37
  store i32 6, ptr %5, align 4
  br label %177

49:                                               ; preds = %37
  %50 = load ptr, ptr %6, align 8, !tbaa !5
  %51 = getelementptr inbounds %struct.MDBX_env, ptr %50, i32 0, i32 1
  %52 = load i32, ptr %51, align 4, !tbaa !28
  %53 = and i32 %52, 268435456
  %54 = icmp ne i32 %53, 0
  br i1 %54, label %56, label %55

55:                                               ; preds = %49
  store i32 6, ptr %5, align 4
  br label %177

56:                                               ; preds = %49
  call void @llvm.lifetime.start.p0(i64 8, ptr %7) #9
  %57 = load ptr, ptr %6, align 8, !tbaa !5
  %58 = getelementptr inbounds %struct.MDBX_env, ptr %57, i32 0, i32 21
  %59 = load i32, ptr %58, align 8, !tbaa !29
  %60 = call ptr @thread_rthc_get(i32 noundef %59)
  store ptr %60, ptr %7, align 8, !tbaa !5
  call void @llvm.lifetime.start.p0(i64 8, ptr %8) #9
  %61 = load ptr, ptr %6, align 8, !tbaa !5
  %62 = getelementptr inbounds %struct.MDBX_env, ptr %61, i32 0, i32 6
  %63 = getelementptr inbounds %struct.osal_mmap, ptr %62, i32 0, i32 0
  %64 = load ptr, ptr %63, align 8, !tbaa !30
  %65 = getelementptr inbounds %struct.shared_lck, ptr %64, i32 0, i32 23
  %66 = getelementptr inbounds [0 x %struct.reader_slot], ptr %65, i64 0, i64 0
  store ptr %66, ptr %8, align 8, !tbaa !5
  call void @llvm.lifetime.start.p0(i64 8, ptr %9) #9
  %67 = load ptr, ptr %6, align 8, !tbaa !5
  %68 = getelementptr inbounds %struct.MDBX_env, ptr %67, i32 0, i32 6
  %69 = getelementptr inbounds %struct.osal_mmap, ptr %68, i32 0, i32 0
  %70 = load ptr, ptr %69, align 8, !tbaa !30
  %71 = getelementptr inbounds %struct.shared_lck, ptr %70, i32 0, i32 23
  %72 = load ptr, ptr %6, align 8, !tbaa !5
  %73 = getelementptr inbounds %struct.MDBX_env, ptr %72, i32 0, i32 18
  %74 = load i32, ptr %73, align 4, !tbaa !31
  %75 = zext i32 %74 to i64
  %76 = getelementptr inbounds [0 x %struct.reader_slot], ptr %71, i64 0, i64 %75
  store ptr %76, ptr %9, align 8, !tbaa !5
  %77 = load ptr, ptr %7, align 8, !tbaa !5
  %78 = load ptr, ptr %8, align 8, !tbaa !5
  %79 = icmp ult ptr %77, %78
  br i1 %79, label %84, label %80

80:                                               ; preds = %56
  %81 = load ptr, ptr %7, align 8, !tbaa !5
  %82 = load ptr, ptr %9, align 8, !tbaa !5
  %83 = icmp uge ptr %81, %82
  br i1 %83, label %84, label %85

84:                                               ; preds = %80, %56
  store i32 6, ptr %5, align 4
  br label %176

85:                                               ; preds = %80
  %86 = load ptr, ptr %6, align 8, !tbaa !5
  %87 = getelementptr inbounds %struct.MDBX_env, ptr %86, i32 0, i32 21
  %88 = load i32, ptr %87, align 8, !tbaa !29
  %89 = call i32 @pthread_setspecific(i32 noundef %88, ptr noundef null) #9
  %90 = icmp ne i32 %89, 0
  br i1 %90, label %91, label %109

91:                                               ; preds = %85
  br label %92

92:                                               ; preds = %91
  %93 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %94 = zext i8 %93 to i32
  %95 = icmp sle i32 6, %94
  %96 = xor i1 %95, true
  %97 = xor i1 %96, true
  %98 = zext i1 %97 to i32
  %99 = sext i32 %98 to i64
  %100 = call i64 @llvm.expect.i64(i64 %99, i64 0)
  %101 = icmp ne i64 %100, 0
  br i1 %101, label %102, label %106

102:                                              ; preds = %92
  %103 = call i64 @osal_thread_self()
  %104 = load ptr, ptr %7, align 8, !tbaa !5
  %105 = call ptr @__Wpedantic_format_voidptr(ptr noundef %104)
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 281, ptr noundef @.str.13, i64 noundef %103, ptr noundef %105)
  br label %106

106:                                              ; preds = %102, %92
  br label %107

107:                                              ; preds = %106
  br label %108

108:                                              ; preds = %107
  store i32 6, ptr %5, align 4
  br label %176

109:                                              ; preds = %85
  br label %110

110:                                              ; preds = %109
  %111 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %112 = zext i8 %111 to i32
  %113 = icmp sle i32 6, %112
  %114 = xor i1 %113, true
  %115 = xor i1 %114, true
  %116 = zext i1 %115 to i32
  %117 = sext i32 %116 to i64
  %118 = call i64 @llvm.expect.i64(i64 %117, i64 0)
  %119 = icmp ne i64 %118, 0
  br i1 %119, label %120, label %140

120:                                              ; preds = %110
  %121 = call i64 @osal_thread_self()
  %122 = load ptr, ptr %7, align 8, !tbaa !5
  %123 = call ptr @__Wpedantic_format_voidptr(ptr noundef %122)
  %124 = load i64, ptr %4, align 8, !tbaa !15
  %125 = load ptr, ptr %8, align 8, !tbaa !5
  %126 = call ptr @__Wpedantic_format_voidptr(ptr noundef %125)
  %127 = load ptr, ptr %9, align 8, !tbaa !5
  %128 = call ptr @__Wpedantic_format_voidptr(ptr noundef %127)
  %129 = load ptr, ptr %7, align 8, !tbaa !5
  %130 = load ptr, ptr %8, align 8, !tbaa !5
  %131 = ptrtoint ptr %129 to i64
  %132 = ptrtoint ptr %130 to i64
  %133 = sub i64 %131, %132
  %134 = sdiv exact i64 %133, 32
  %135 = trunc i64 %134 to i32
  %136 = load ptr, ptr %7, align 8, !tbaa !5
  %137 = getelementptr inbounds %struct.reader_slot, ptr %136, i32 0, i32 2
  %138 = load volatile i32, ptr %137, align 8, !tbaa !30
  %139 = load i32, ptr %3, align 4, !tbaa !9
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 289, ptr noundef @.str.14, i64 noundef %121, ptr noundef %123, i64 noundef %124, ptr noundef %126, ptr noundef %128, i32 noundef %135, i32 noundef %138, i32 noundef %139)
  br label %140

140:                                              ; preds = %120, %110
  br label %141

141:                                              ; preds = %140
  br label %142

142:                                              ; preds = %141
  %143 = load ptr, ptr %7, align 8, !tbaa !5
  %144 = getelementptr inbounds %struct.reader_slot, ptr %143, i32 0, i32 2
  %145 = call i32 @atomic_load32(ptr noundef %144, i32 noundef 0)
  %146 = load i32, ptr %3, align 4, !tbaa !9
  %147 = icmp eq i32 %145, %146
  br i1 %147, label %148, label %175

148:                                              ; preds = %142
  br label %149

149:                                              ; preds = %148
  %150 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %151 = zext i8 %150 to i32
  %152 = icmp sle i32 6, %151
  %153 = xor i1 %152, true
  %154 = xor i1 %153, true
  %155 = zext i1 %154 to i32
  %156 = sext i32 %155 to i64
  %157 = call i64 @llvm.expect.i64(i64 %156, i64 0)
  %158 = icmp ne i64 %157, 0
  br i1 %158, label %159, label %163

159:                                              ; preds = %149
  %160 = call i64 @osal_thread_self()
  %161 = load ptr, ptr %7, align 8, !tbaa !5
  %162 = call ptr @__Wpedantic_format_voidptr(ptr noundef %161)
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 291, ptr noundef @.str.15, i64 noundef %160, ptr noundef %162)
  br label %163

163:                                              ; preds = %159, %149
  br label %164

164:                                              ; preds = %163
  br label %165

165:                                              ; preds = %164
  %166 = load ptr, ptr %7, align 8, !tbaa !5
  %167 = getelementptr inbounds %struct.reader_slot, ptr %166, i32 0, i32 2
  %168 = load i32, ptr %3, align 4, !tbaa !9
  %169 = call zeroext i1 @atomic_cas32(ptr noundef %167, i32 noundef %168, i32 noundef 0)
  %170 = load ptr, ptr %6, align 8, !tbaa !5
  %171 = getelementptr inbounds %struct.MDBX_env, ptr %170, i32 0, i32 7
  %172 = load ptr, ptr %171, align 8, !tbaa !32
  %173 = getelementptr inbounds %struct.shared_lck, ptr %172, i32 0, i32 21
  %174 = call i32 @atomic_store32(ptr noundef %173, i32 noundef 1, i32 noundef 0)
  br label %175

175:                                              ; preds = %165, %142
  store i32 0, ptr %5, align 4
  br label %176

176:                                              ; preds = %175, %108, %84
  call void @llvm.lifetime.end.p0(i64 8, ptr %9) #9
  call void @llvm.lifetime.end.p0(i64 8, ptr %8) #9
  call void @llvm.lifetime.end.p0(i64 8, ptr %7) #9
  br label %177

177:                                              ; preds = %176, %55, %48
  call void @llvm.lifetime.end.p0(i64 8, ptr %6) #9
  %178 = load i32, ptr %5, align 4
  switch i32 %178, label %332 [
    i32 0, label %179
    i32 6, label %180
  ]

179:                                              ; preds = %177
  br label %180

180:                                              ; preds = %179, %177
  %181 = load i64, ptr %4, align 8, !tbaa !15
  %182 = add i64 %181, 1
  store i64 %182, ptr %4, align 8, !tbaa !15
  br label %31, !llvm.loop !33

183:                                              ; preds = %36
  call void @llvm.lifetime.start.p0(i64 8, ptr %10) #9
  %184 = load ptr, ptr %2, align 8, !tbaa !5
  %185 = call i64 @rthc_signature(ptr noundef %184, i8 noundef zeroext 13)
  store i64 %185, ptr %10, align 8, !tbaa !15
  call void @llvm.lifetime.start.p0(i64 8, ptr %11) #9
  %186 = load ptr, ptr %2, align 8, !tbaa !5
  %187 = call i64 @rthc_signature(ptr noundef %186, i8 noundef zeroext -64)
  store i64 %187, ptr %11, align 8, !tbaa !15
  call void @llvm.lifetime.start.p0(i64 8, ptr %12) #9
  %188 = load ptr, ptr %2, align 8, !tbaa !5
  %189 = call i64 @rthc_read(ptr noundef %188)
  store i64 %189, ptr %12, align 8, !tbaa !15
  %190 = load i64, ptr %12, align 8, !tbaa !15
  %191 = load i64, ptr %10, align 8, !tbaa !15
  %192 = icmp eq i64 %190, %191
  br i1 %192, label %193, label %217

193:                                              ; preds = %183
  %194 = load ptr, ptr %2, align 8, !tbaa !5
  %195 = load i64, ptr %10, align 8, !tbaa !15
  %196 = call i64 @rthc_compare_and_clean(ptr noundef %194, i64 noundef %195)
  %197 = icmp ne i64 %196, 0
  br i1 %197, label %198, label %217

198:                                              ; preds = %193
  br label %199

199:                                              ; preds = %198
  %200 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %201 = zext i8 %200 to i32
  %202 = icmp sle i32 6, %201
  %203 = xor i1 %202, true
  %204 = xor i1 %203, true
  %205 = zext i1 %204 to i32
  %206 = sext i32 %205 to i64
  %207 = call i64 @llvm.expect.i64(i64 %206, i64 0)
  %208 = icmp ne i64 %207, 0
  br i1 %208, label %209, label %214

209:                                              ; preds = %199
  %210 = call i64 @osal_thread_self()
  %211 = load ptr, ptr %2, align 8, !tbaa !5
  %212 = call i32 @osal_getpid()
  %213 = load i64, ptr %12, align 8, !tbaa !15
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 306, ptr noundef @.str.16, i64 noundef %210, ptr noundef %211, i32 noundef %212, ptr noundef @.str.17, i64 noundef %213)
  br label %214

214:                                              ; preds = %209, %199
  br label %215

215:                                              ; preds = %214
  br label %216

216:                                              ; preds = %215
  br label %279

217:                                              ; preds = %193, %183
  %218 = load i64, ptr %12, align 8, !tbaa !15
  %219 = load i64, ptr %11, align 8, !tbaa !15
  %220 = icmp eq i64 %218, %219
  br i1 %220, label %221, label %259

221:                                              ; preds = %217
  %222 = load ptr, ptr %2, align 8, !tbaa !5
  %223 = load i64, ptr %11, align 8, !tbaa !15
  %224 = call i64 @rthc_compare_and_clean(ptr noundef %222, i64 noundef %223)
  %225 = icmp ne i64 %224, 0
  br i1 %225, label %226, label %259

226:                                              ; preds = %221
  br label %227

227:                                              ; preds = %226
  %228 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %229 = zext i8 %228 to i32
  %230 = icmp sle i32 6, %229
  %231 = xor i1 %230, true
  %232 = xor i1 %231, true
  %233 = zext i1 %232 to i32
  %234 = sext i32 %233 to i64
  %235 = call i64 @llvm.expect.i64(i64 %234, i64 0)
  %236 = icmp ne i64 %235, 0
  br i1 %236, label %237, label %242

237:                                              ; preds = %227
  %238 = call i64 @osal_thread_self()
  %239 = load ptr, ptr %2, align 8, !tbaa !5
  %240 = call i32 @osal_getpid()
  %241 = load i64, ptr %12, align 8, !tbaa !15
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 309, ptr noundef @.str.16, i64 noundef %238, ptr noundef %239, i32 noundef %240, ptr noundef @.str.18, i64 noundef %241)
  br label %242

242:                                              ; preds = %237, %227
  br label %243

243:                                              ; preds = %242
  br label %244

244:                                              ; preds = %243
  br label %245

245:                                              ; preds = %244
  %246 = call i32 @atomic_add32(ptr noundef @rthc_pending, i32 noundef -1)
  %247 = icmp ugt i32 %246, 0
  %248 = xor i1 %247, true
  %249 = xor i1 %248, true
  %250 = xor i1 %249, true
  %251 = zext i1 %250 to i32
  %252 = sext i32 %251 to i64
  %253 = call i64 @llvm.expect.i64(i64 %252, i64 0)
  %254 = icmp ne i64 %253, 0
  br i1 %254, label %255, label %256

255:                                              ; preds = %245
  call void @mdbx_assert_fail(ptr noundef null, ptr noundef @.str.19, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 310) #10
  unreachable

256:                                              ; preds = %245
  br label %257

257:                                              ; preds = %256
  br label %258

258:                                              ; preds = %257
  br label %278

259:                                              ; preds = %221, %217
  br label %260

260:                                              ; preds = %259
  %261 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %262 = zext i8 %261 to i32
  %263 = icmp sle i32 2, %262
  %264 = xor i1 %263, true
  %265 = xor i1 %264, true
  %266 = zext i1 %265 to i32
  %267 = sext i32 %266 to i64
  %268 = call i64 @llvm.expect.i64(i64 %267, i64 0)
  %269 = icmp ne i64 %268, 0
  br i1 %269, label %270, label %275

270:                                              ; preds = %260
  %271 = call i64 @osal_thread_self()
  %272 = load ptr, ptr %2, align 8, !tbaa !5
  %273 = call i32 @osal_getpid()
  %274 = load i64, ptr %12, align 8, !tbaa !15
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 2, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 313, ptr noundef @.str.20, i64 noundef %271, ptr noundef %272, i32 noundef %273, ptr noundef @.str.21, i64 noundef %274)
  br label %275

275:                                              ; preds = %270, %260
  br label %276

276:                                              ; preds = %275
  br label %277

277:                                              ; preds = %276
  br label %278

278:                                              ; preds = %277, %258
  br label %279

279:                                              ; preds = %278, %216
  %280 = call i32 @atomic_load32(ptr noundef @rthc_pending, i32 noundef 1)
  %281 = icmp eq i32 %280, 0
  br i1 %281, label %282, label %314

282:                                              ; preds = %279
  br label %283

283:                                              ; preds = %282
  %284 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %285 = zext i8 %284 to i32
  %286 = icmp sle i32 6, %285
  %287 = xor i1 %286, true
  %288 = xor i1 %287, true
  %289 = zext i1 %288 to i32
  %290 = sext i32 %289 to i64
  %291 = call i64 @llvm.expect.i64(i64 %290, i64 0)
  %292 = icmp ne i64 %291, 0
  br i1 %292, label %293, label %297

293:                                              ; preds = %283
  %294 = call i64 @osal_thread_self()
  %295 = load ptr, ptr %2, align 8, !tbaa !5
  %296 = call i32 @osal_getpid()
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 317, ptr noundef @.str.22, i64 noundef %294, ptr noundef %295, i32 noundef %296)
  br label %297

297:                                              ; preds = %293, %283
  br label %298

298:                                              ; preds = %297
  br label %299

299:                                              ; preds = %298
  br label %300

300:                                              ; preds = %299
  %301 = call i32 @pthread_cond_broadcast(ptr noundef @rthc_cond) #9
  %302 = icmp eq i32 %301, 0
  %303 = xor i1 %302, true
  %304 = xor i1 %303, true
  %305 = xor i1 %304, true
  %306 = zext i1 %305 to i32
  %307 = sext i32 %306 to i64
  %308 = call i64 @llvm.expect.i64(i64 %307, i64 0)
  %309 = icmp ne i64 %308, 0
  br i1 %309, label %310, label %311

310:                                              ; preds = %300
  call void @mdbx_assert_fail(ptr noundef null, ptr noundef @.str.23, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 318) #10
  unreachable

311:                                              ; preds = %300
  br label %312

312:                                              ; preds = %311
  br label %313

313:                                              ; preds = %312
  br label %314

314:                                              ; preds = %313, %279
  br label %315

315:                                              ; preds = %314
  %316 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !11
  %317 = zext i8 %316 to i32
  %318 = icmp sle i32 6, %317
  %319 = xor i1 %318, true
  %320 = xor i1 %319, true
  %321 = zext i1 %320 to i32
  %322 = sext i32 %321 to i64
  %323 = call i64 @llvm.expect.i64(i64 %322, i64 0)
  %324 = icmp ne i64 %323, 0
  br i1 %324, label %325, label %328

325:                                              ; preds = %315
  %326 = call i64 @osal_thread_self()
  %327 = load ptr, ptr %2, align 8, !tbaa !5
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef @__func__.rthc_thread_dtor, i32 noundef 321, ptr noundef @.str.24, i64 noundef %326, ptr noundef %327)
  br label %328

328:                                              ; preds = %325, %315
  br label %329

329:                                              ; preds = %328
  br label %330

330:                                              ; preds = %329
  %331 = call i32 @pthread_mutex_unlock(ptr noundef @rthc_mutex) #9
  call void @llvm.lifetime.end.p0(i64 8, ptr %12) #9
  call void @llvm.lifetime.end.p0(i64 8, ptr %11) #9
  call void @llvm.lifetime.end.p0(i64 8, ptr %10) #9
  call void @llvm.lifetime.end.p0(i64 4, ptr %3) #9
  ret void

332:                                              ; preds = %177
  unreachable
}

; Function Attrs: nounwind
declare i32 @pthread_setspecific(i32 noundef, ptr noundef) #6

; Function Attrs: alwaysinline nounwind uwtable
declare hidden i32 @atomic_add32(ptr noundef, i32 noundef) #8

; Function Attrs: inlinehint nounwind uwtable
declare hidden i32 @osal_getpid() #3

; Function Attrs: inlinehint nounwind uwtable
declare hidden ptr @thread_rthc_get(i32 noundef) #3

; Function Attrs: alwaysinline nounwind uwtable
declare hidden i32 @atomic_load32(ptr noundef, i32 noundef) #8

; Function Attrs: alwaysinline nounwind uwtable
declare hidden zeroext i1 @atomic_cas32(ptr noundef, i32 noundef, i32 noundef) #8

; Function Attrs: alwaysinline nounwind uwtable
declare hidden i32 @atomic_store32(ptr noundef, i32 noundef, i32 noundef) #8

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @rthc_read(ptr noundef) #3

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @rthc_compare_and_clean(ptr noundef, i64 noundef) #3

; Function Attrs: nounwind
declare i32 @pthread_cond_broadcast(ptr noundef) #6

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(none) }
attributes #2 = { "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 #3 = { inlinehint 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 #4 = { 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 #5 = { noreturn "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 #6 = { nounwind "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 #7 = { cold nounwind optsize 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 #8 = { alwaysinline 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 #9 = { nounwind }
attributes #10 = { noreturn }

!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 = !{!12, !7, i64 26}
!12 = !{!"libmdbx_globals", !7, i64 0, !10, i64 16, !10, i64 20, !7, i64 24, !7, i64 25, !7, i64 26, !13, i64 27, !10, i64 28, !7, i64 32, !7, i64 40, !14, i64 80, !6, i64 88}
!13 = !{!"_Bool", !7, i64 0}
!14 = !{!"long", !7, i64 0}
!15 = !{!14, !14, i64 0}
!16 = !{!17, !6, i64 0}
!17 = !{!"rthc_entry", !6, i64 0}
!18 = !{!19, !10, i64 140}
!19 = !{!"MDBX_env", !7, i64 0, !10, i64 4, !10, i64 8, !20, i64 16, !10, i64 56, !10, i64 60, !20, i64 64, !6, i64 104, !21, i64 112, !21, i64 114, !21, i64 116, !21, i64 118, !21, i64 120, !21, i64 122, !7, i64 124, !7, i64 128, !7, i64 129, !21, i64 130, !10, i64 132, !10, i64 136, !10, i64 140, !10, i64 144, !22, i64 152, !6, i64 184, !6, i64 192, !6, i64 200, !6, i64 208, !6, i64 216, !10, i64 224, !10, i64 228, !10, i64 232, !6, i64 240, !6, i64 248, !14, i64 256, !23, i64 264, !25, i64 320, !13, i64 360, !6, i64 368, !6, i64 376, !6, i64 384, !26, i64 392, !7, i64 400, !10, i64 440, !10, i64 444, !6, i64 448, !27, i64 456, !7, i64 496, !7, i64 536}
!20 = !{!"osal_mmap", !7, i64 0, !10, i64 8, !14, i64 16, !14, i64 24, !14, i64 32}
!21 = !{!"short", !7, i64 0}
!22 = !{!"", !6, i64 0, !6, i64 8, !6, i64 16, !6, i64 24}
!23 = !{!"", !10, i64 0, !10, i64 4, !10, i64 8, !10, i64 12, !14, i64 16, !7, i64 24, !7, i64 25, !7, i64 26, !7, i64 27, !10, i64 28, !10, i64 32, !13, i64 36, !13, i64 37, !13, i64 38, !24, i64 40, !7, i64 48}
!24 = !{!"", !21, i64 0, !21, i64 2, !21, i64 4, !21, i64 6}
!25 = !{!"", !14, i64 0, !14, i64 8, !14, i64 16, !14, i64 24, !14, i64 32}
!26 = !{!"", !14, i64 0}
!27 = !{!"osal_ioring", !10, i64 0, !10, i64 4, !10, i64 8, !6, i64 16, !6, i64 24, !6, i64 32}
!28 = !{!19, !10, i64 4}
!29 = !{!19, !10, i64 144}
!30 = !{!7, !7, i64 0}
!31 = !{!19, !10, i64 132}
!32 = !{!19, !6, i64 104}
!33 = distinct !{!33, !34}
!34 = !{!"llvm.loop.mustprogress"}


; 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.libmdbx_globals = type { %union.bin128, i32, i32, i8, i8, i8, i8, i32, %union.logger_union, %union.pthread_mutex_t, i64, ptr }
%union.bin128 = type { %struct.anon.9 }
%struct.anon.9 = type { i64, i64 }
%union.logger_union = type { ptr }
%union.pthread_mutex_t = type { %struct.__pthread_mutex_s }
%struct.__pthread_mutex_s = type { i32, i32, i32, i32, i32, i16, i16, %struct.__pthread_internal_list }
%struct.__pthread_internal_list = type { ptr, ptr }
%union.mdbx_atomic_uint32_t = type { i32 }
%union.pthread_cond_t = type { %struct.__pthread_cond_s }
%struct.__pthread_cond_s = type { %union.__atomic_wide_counter, %union.__atomic_wide_counter, [2 x i32], [2 x i32], i32, i32, [2 x i32] }
%union.__atomic_wide_counter = type { i64 }
%struct.rthc_entry = type { ptr }
%struct.reader_slot = type { %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint64_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint32_t, %union.mdbx_atomic_uint64_t }
%union.mdbx_atomic_uint64_t = type { i64 }

@rthc_count = external hidden local_unnamed_addr global i32, align 4
@rthc_table = external hidden local_unnamed_addr global ptr, align 8
@globals = external local_unnamed_addr global %struct.libmdbx_globals, align 8
@rthc_mutex = external hidden global %union.pthread_mutex_t, align 8
@rthc_pending = external hidden global %union.mdbx_atomic_uint32_t, align 4
@__func__.rthc_thread_dtor = external hidden unnamed_addr constant [17 x i8], align 1
@.str.12 = external hidden unnamed_addr constant [34 x i8], align 1
@.str.13 = external hidden unnamed_addr constant [61 x i8], align 1
@.str.14 = external hidden unnamed_addr constant [79 x i8], align 1
@.str.15 = external hidden unnamed_addr constant [37 x i8], align 1
@.str.16 = external hidden unnamed_addr constant [60 x i8], align 1
@.str.17 = external hidden unnamed_addr constant [11 x i8], align 1
@.str.18 = external hidden unnamed_addr constant [8 x i8], align 1
@.str.19 = external hidden unnamed_addr constant [35 x i8], align 1
@.str.20 = external hidden unnamed_addr constant [57 x i8], align 1
@.str.21 = external hidden unnamed_addr constant [6 x i8], align 1
@.str.22 = external hidden unnamed_addr constant [40 x i8], align 1
@rthc_cond = external hidden global %union.pthread_cond_t, align 8
@.str.23 = external hidden unnamed_addr constant [40 x i8], align 1
@.str.24 = external hidden unnamed_addr constant [26 x i8], align 1

declare void @debug_log(i32 noundef, ptr noundef, i32 noundef, ptr noundef, ...) local_unnamed_addr #0

; Function Attrs: inlinehint nounwind uwtable
declare hidden ptr @__Wpedantic_format_voidptr(ptr noundef) local_unnamed_addr #1

; Function Attrs: nounwind uwtable
declare dso_local void @rthc_lock() local_unnamed_addr #2

; Function Attrs: noreturn
declare void @mdbx_assert_fail(ptr noundef, ptr noundef, ptr noundef, i32 noundef) local_unnamed_addr #3

; Function Attrs: nounwind
declare i32 @pthread_mutex_unlock(ptr noundef) local_unnamed_addr #4

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @rthc_signature(ptr noundef, i8 noundef zeroext) local_unnamed_addr #1

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @osal_thread_self() local_unnamed_addr #1

; Function Attrs: cold nounwind optsize uwtable
define dso_local void @rthc_thread_dtor(ptr noundef %0) local_unnamed_addr #5 {
  tail call void @rthc_lock()
  %2 = tail call i32 @osal_getpid()
  %3 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %4 = icmp ugt i8 %3, 5
  br i1 %4, label %5, label %7, !prof !13

5:                                                ; preds = %1
  %6 = tail call i64 @osal_thread_self()
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 264, ptr noundef nonnull @.str.12, i32 noundef %2, i64 noundef %6, ptr noundef %0) #7
  br label %7

7:                                                ; preds = %5, %1
  %8 = load i32, ptr @rthc_count, align 4, !tbaa !14
  %.not65 = icmp eq i32 %8, 0
  br i1 %.not65, label %._crit_edge, label %.lr.ph

._crit_edge:                                      ; preds = %72, %7
  %9 = tail call i64 @rthc_signature(ptr noundef %0, i8 noundef zeroext 13)
  %10 = tail call i64 @rthc_signature(ptr noundef %0, i8 noundef zeroext -64)
  %11 = tail call i64 @rthc_read(ptr noundef %0)
  %12 = icmp eq i64 %11, %9
  br i1 %12, label %77, label %85

.lr.ph:                                           ; preds = %7, %72
  %.064 = phi i64 [ %73, %72 ], [ 0, %7 ]
  %13 = load ptr, ptr @rthc_table, align 8, !tbaa !15
  %14 = getelementptr inbounds %struct.rthc_entry, ptr %13, i64 %.064
  %15 = load ptr, ptr %14, align 8, !tbaa !16
  %16 = getelementptr inbounds i8, ptr %15, i64 140
  %17 = load i32, ptr %16, align 4, !tbaa !18
  %.not60 = icmp eq i32 %17, %2
  br i1 %.not60, label %18, label %72

18:                                               ; preds = %.lr.ph
  %19 = getelementptr inbounds i8, ptr %15, i64 4
  %20 = load i32, ptr %19, align 4, !tbaa !28
  %21 = and i32 %20, 268435456
  %.not61 = icmp eq i32 %21, 0
  br i1 %.not61, label %72, label %22

22:                                               ; preds = %18
  %23 = getelementptr inbounds i8, ptr %15, i64 144
  %24 = load i32, ptr %23, align 8, !tbaa !29
  %25 = tail call ptr @thread_rthc_get(i32 noundef %24)
  %26 = getelementptr inbounds i8, ptr %15, i64 64
  %27 = load ptr, ptr %26, align 8, !tbaa !30
  %28 = getelementptr inbounds i8, ptr %27, i64 512
  %29 = getelementptr inbounds i8, ptr %15, i64 132
  %30 = load i32, ptr %29, align 4, !tbaa !31
  %31 = zext i32 %30 to i64
  %32 = getelementptr inbounds [0 x %struct.reader_slot], ptr %28, i64 0, i64 %31
  %33 = icmp uge ptr %25, %28
  %.not62 = icmp ult ptr %25, %32
  %or.cond = select i1 %33, i1 %.not62, i1 false
  br i1 %or.cond, label %34, label %72

34:                                               ; preds = %22
  %35 = load i32, ptr %23, align 8, !tbaa !29
  %36 = tail call i32 @pthread_setspecific(i32 noundef %35, ptr noundef null) #7
  %.not63 = icmp eq i32 %36, 0
  %37 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %38 = icmp ugt i8 %37, 5
  br i1 %.not63, label %43, label %39

39:                                               ; preds = %34
  br i1 %38, label %40, label %72, !prof !13

40:                                               ; preds = %39
  %41 = tail call i64 @osal_thread_self()
  %42 = tail call ptr @__Wpedantic_format_voidptr(ptr noundef %25)
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 281, ptr noundef nonnull @.str.13, i64 noundef %41, ptr noundef %42) #7
  br label %72

43:                                               ; preds = %34
  br i1 %38, label %44, label %56, !prof !13

44:                                               ; preds = %43
  %45 = tail call i64 @osal_thread_self()
  %46 = tail call ptr @__Wpedantic_format_voidptr(ptr noundef %25)
  %47 = tail call ptr @__Wpedantic_format_voidptr(ptr noundef nonnull %28)
  %48 = tail call ptr @__Wpedantic_format_voidptr(ptr noundef nonnull %32)
  %49 = ptrtoint ptr %25 to i64
  %50 = ptrtoint ptr %28 to i64
  %51 = sub i64 %49, %50
  %52 = lshr exact i64 %51, 5
  %53 = trunc i64 %52 to i32
  %54 = getelementptr inbounds i8, ptr %25, i64 16
  %55 = load volatile i32, ptr %54, align 8, !tbaa !30
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 289, ptr noundef nonnull @.str.14, i64 noundef %45, ptr noundef %46, i64 noundef %.064, ptr noundef %47, ptr noundef %48, i32 noundef %53, i32 noundef %55, i32 noundef %2) #7
  br label %56

56:                                               ; preds = %44, %43
  %57 = getelementptr inbounds i8, ptr %25, i64 16
  %58 = tail call i32 @atomic_load32(ptr noundef nonnull %57, i32 noundef 0)
  %59 = icmp eq i32 %58, %2
  br i1 %59, label %60, label %72

60:                                               ; preds = %56
  %61 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %62 = icmp ugt i8 %61, 5
  br i1 %62, label %63, label %66, !prof !13

63:                                               ; preds = %60
  %64 = tail call i64 @osal_thread_self()
  %65 = tail call ptr @__Wpedantic_format_voidptr(ptr noundef %25)
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 291, ptr noundef nonnull @.str.15, i64 noundef %64, ptr noundef %65) #7
  br label %66

66:                                               ; preds = %63, %60
  %67 = tail call zeroext i1 @atomic_cas32(ptr noundef nonnull %57, i32 noundef %2, i32 noundef 0)
  %68 = getelementptr inbounds i8, ptr %15, i64 104
  %69 = load ptr, ptr %68, align 8, !tbaa !32
  %70 = getelementptr inbounds i8, ptr %69, i64 492
  %71 = tail call i32 @atomic_store32(ptr noundef nonnull %70, i32 noundef 1, i32 noundef 0)
  br label %72

72:                                               ; preds = %22, %40, %39, %66, %56, %18, %.lr.ph
  %73 = add nuw nsw i64 %.064, 1
  %74 = load i32, ptr @rthc_count, align 4, !tbaa !14
  %75 = zext i32 %74 to i64
  %76 = icmp ult i64 %73, %75
  br i1 %76, label %.lr.ph, label %._crit_edge, !llvm.loop !33

77:                                               ; preds = %._crit_edge
  %78 = tail call i64 @rthc_compare_and_clean(ptr noundef %0, i64 noundef %9)
  %.not = icmp eq i64 %78, 0
  br i1 %.not, label %85, label %79

79:                                               ; preds = %77
  %80 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %81 = icmp ugt i8 %80, 5
  br i1 %81, label %82, label %104, !prof !13

82:                                               ; preds = %79
  %83 = tail call i64 @osal_thread_self()
  %84 = tail call i32 @osal_getpid()
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 306, ptr noundef nonnull @.str.16, i64 noundef %83, ptr noundef %0, i32 noundef %84, ptr noundef nonnull @.str.17, i64 noundef %9) #7
  br label %104

85:                                               ; preds = %77, %._crit_edge
  %86 = icmp eq i64 %11, %10
  br i1 %86, label %87, label %98

87:                                               ; preds = %85
  %88 = tail call i64 @rthc_compare_and_clean(ptr noundef %0, i64 noundef %10)
  %.not57 = icmp eq i64 %88, 0
  br i1 %.not57, label %98, label %89

89:                                               ; preds = %87
  %90 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %91 = icmp ugt i8 %90, 5
  br i1 %91, label %92, label %95, !prof !13

92:                                               ; preds = %89
  %93 = tail call i64 @osal_thread_self()
  %94 = tail call i32 @osal_getpid()
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 309, ptr noundef nonnull @.str.16, i64 noundef %93, ptr noundef %0, i32 noundef %94, ptr noundef nonnull @.str.18, i64 noundef %10) #7
  br label %95

95:                                               ; preds = %89, %92
  %96 = tail call i32 @atomic_add32(ptr noundef nonnull @rthc_pending, i32 noundef -1)
  %.not58 = icmp eq i32 %96, 0
  br i1 %.not58, label %97, label %104, !prof !13

97:                                               ; preds = %95
  tail call void @mdbx_assert_fail(ptr noundef null, ptr noundef nonnull @.str.19, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 310) #8
  unreachable

98:                                               ; preds = %85, %87
  %99 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %100 = icmp ugt i8 %99, 1
  br i1 %100, label %101, label %104, !prof !13

101:                                              ; preds = %98
  %102 = tail call i64 @osal_thread_self()
  %103 = tail call i32 @osal_getpid()
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 2, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 313, ptr noundef nonnull @.str.20, i64 noundef %102, ptr noundef %0, i32 noundef %103, ptr noundef nonnull @.str.21, i64 noundef %11) #7
  br label %104

104:                                              ; preds = %95, %101, %98, %79, %82
  %105 = tail call i32 @atomic_load32(ptr noundef nonnull @rthc_pending, i32 noundef 1)
  %106 = icmp eq i32 %105, 0
  br i1 %106, label %107, label %116

107:                                              ; preds = %104
  %108 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %109 = icmp ugt i8 %108, 5
  br i1 %109, label %110, label %113, !prof !13

110:                                              ; preds = %107
  %111 = tail call i64 @osal_thread_self()
  %112 = tail call i32 @osal_getpid()
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 317, ptr noundef nonnull @.str.22, i64 noundef %111, ptr noundef %0, i32 noundef %112) #7
  br label %113

113:                                              ; preds = %107, %110
  %114 = tail call i32 @pthread_cond_broadcast(ptr noundef nonnull @rthc_cond) #7
  %.not59 = icmp eq i32 %114, 0
  br i1 %.not59, label %116, label %115, !prof !35

115:                                              ; preds = %113
  tail call void @mdbx_assert_fail(ptr noundef null, ptr noundef nonnull @.str.23, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 318) #8
  unreachable

116:                                              ; preds = %104, %113
  %117 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !5
  %118 = icmp ugt i8 %117, 5
  br i1 %118, label %119, label %121, !prof !13

119:                                              ; preds = %116
  %120 = tail call i64 @osal_thread_self()
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 6, ptr noundef nonnull @__func__.rthc_thread_dtor, i32 noundef 321, ptr noundef nonnull @.str.24, i64 noundef %120, ptr noundef %0) #7
  br label %121

121:                                              ; preds = %119, %116
  %122 = tail call i32 @pthread_mutex_unlock(ptr noundef nonnull @rthc_mutex) #7
  ret void
}

; Function Attrs: nounwind
declare i32 @pthread_setspecific(i32 noundef, ptr noundef) local_unnamed_addr #4

; Function Attrs: alwaysinline nounwind uwtable
declare hidden i32 @atomic_add32(ptr noundef, i32 noundef) local_unnamed_addr #6

; Function Attrs: inlinehint nounwind uwtable
declare hidden i32 @osal_getpid() local_unnamed_addr #1

; Function Attrs: inlinehint nounwind uwtable
declare hidden ptr @thread_rthc_get(i32 noundef) local_unnamed_addr #1

; Function Attrs: alwaysinline nounwind uwtable
declare hidden i32 @atomic_load32(ptr noundef, i32 noundef) local_unnamed_addr #6

; Function Attrs: alwaysinline nounwind uwtable
declare hidden zeroext i1 @atomic_cas32(ptr noundef, i32 noundef, i32 noundef) local_unnamed_addr #6

; Function Attrs: alwaysinline nounwind uwtable
declare hidden i32 @atomic_store32(ptr noundef, i32 noundef, i32 noundef) local_unnamed_addr #6

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @rthc_read(ptr noundef) local_unnamed_addr #1

; Function Attrs: inlinehint nounwind uwtable
declare hidden i64 @rthc_compare_and_clean(ptr noundef, i64 noundef) local_unnamed_addr #1

; Function Attrs: nounwind
declare i32 @pthread_cond_broadcast(ptr noundef) local_unnamed_addr #4

attributes #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 = { inlinehint 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 = { 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 #3 = { noreturn "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 #4 = { nounwind "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 #5 = { cold nounwind optsize 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 #6 = { alwaysinline 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 #7 = { nounwind }
attributes #8 = { noreturn 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, !7, i64 26}
!6 = !{!"libmdbx_globals", !7, i64 0, !9, i64 16, !9, i64 20, !7, i64 24, !7, i64 25, !7, i64 26, !10, i64 27, !9, i64 28, !7, i64 32, !7, i64 40, !11, i64 80, !12, i64 88}
!7 = !{!"omnipotent char", !8, i64 0}
!8 = !{!"Simple C/C++ TBAA"}
!9 = !{!"int", !7, i64 0}
!10 = !{!"_Bool", !7, i64 0}
!11 = !{!"long", !7, i64 0}
!12 = !{!"any pointer", !7, i64 0}
!13 = !{!"branch_weights", !"expected", i32 1, i32 2000}
!14 = !{!9, !9, i64 0}
!15 = !{!12, !12, i64 0}
!16 = !{!17, !12, i64 0}
!17 = !{!"rthc_entry", !12, i64 0}
!18 = !{!19, !9, i64 140}
!19 = !{!"MDBX_env", !7, i64 0, !9, i64 4, !9, i64 8, !20, i64 16, !9, i64 56, !9, i64 60, !20, i64 64, !12, i64 104, !21, i64 112, !21, i64 114, !21, i64 116, !21, i64 118, !21, i64 120, !21, i64 122, !7, i64 124, !7, i64 128, !7, i64 129, !21, i64 130, !9, i64 132, !9, i64 136, !9, i64 140, !9, i64 144, !22, i64 152, !12, i64 184, !12, i64 192, !12, i64 200, !12, i64 208, !12, i64 216, !9, i64 224, !9, i64 228, !9, i64 232, !12, i64 240, !12, i64 248, !11, i64 256, !23, i64 264, !25, i64 320, !10, i64 360, !12, i64 368, !12, i64 376, !12, i64 384, !26, i64 392, !7, i64 400, !9, i64 440, !9, i64 444, !12, i64 448, !27, i64 456, !7, i64 496, !7, i64 536}
!20 = !{!"osal_mmap", !7, i64 0, !9, i64 8, !11, i64 16, !11, i64 24, !11, i64 32}
!21 = !{!"short", !7, i64 0}
!22 = !{!"", !12, i64 0, !12, i64 8, !12, i64 16, !12, i64 24}
!23 = !{!"", !9, i64 0, !9, i64 4, !9, i64 8, !9, i64 12, !11, i64 16, !7, i64 24, !7, i64 25, !7, i64 26, !7, i64 27, !9, i64 28, !9, i64 32, !10, i64 36, !10, i64 37, !10, i64 38, !24, i64 40, !7, i64 48}
!24 = !{!"", !21, i64 0, !21, i64 2, !21, i64 4, !21, i64 6}
!25 = !{!"", !11, i64 0, !11, i64 8, !11, i64 16, !11, i64 24, !11, i64 32}
!26 = !{!"", !11, i64 0}
!27 = !{!"osal_ioring", !9, i64 0, !9, i64 4, !9, i64 8, !12, i64 16, !12, i64 24, !12, i64 32}
!28 = !{!19, !9, i64 4}
!29 = !{!19, !9, i64 144}
!30 = !{!7, !7, i64 0}
!31 = !{!19, !9, i64 132}
!32 = !{!19, !12, i64 104}
!33 = distinct !{!33, !34}
!34 = !{!"llvm.loop.mustprogress"}
!35 = !{!"branch_weights", !"expected", i32 2000, i32 1}


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