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

; 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 }
%struct.anon = 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 }
%struct.tree = type { i16, i16, i32, i32, i32, i32, i32, i64, i64, i64 }
%struct.kvx = type { %struct.clc2, %struct.iovec }
%struct.clc2 = type { %struct.clc, %struct.clc }
%struct.clc = type { ptr, i64, i64 }
%struct.iovec = type { ptr, i64 }

@globals = external global %struct.libmdbx_globals, align 8
@__func__.tbl_setup = external hidden unnamed_addr constant [10 x i8], align 1
@.str = external hidden unnamed_addr constant [42 x i8], align 1
@.str.1 = external hidden unnamed_addr constant [55 x i8], align 1
@.str.2 = external hidden unnamed_addr constant [35 x i8], align 1
@.str.3 = external hidden unnamed_addr constant [35 x i8], align 1

; Function Attrs: nounwind uwtable
define dso_local i32 @tbl_setup(ptr noundef %0, ptr noundef %1, ptr noundef %2) #0 {
  %4 = alloca i32, align 4
  %5 = alloca ptr, align 8
  %6 = alloca ptr, align 8
  %7 = alloca ptr, align 8
  %8 = alloca i64, align 8
  %9 = alloca i64, align 8
  %10 = alloca i32, align 4
  store ptr %0, ptr %5, align 8, !tbaa !5
  store ptr %1, ptr %6, align 8, !tbaa !5
  store ptr %2, ptr %7, align 8, !tbaa !5
  fence acquire
  %11 = load ptr, ptr %7, align 8, !tbaa !5
  %12 = getelementptr inbounds %struct.tree, ptr %11, i32 0, i32 0
  %13 = load i16, ptr %12, align 4, !tbaa !9
  %14 = zext i16 %13 to i32
  %15 = call zeroext i1 @check_table_flags(i32 noundef %14)
  %16 = xor i1 %15, true
  %17 = xor i1 %16, true
  %18 = xor i1 %17, true
  %19 = zext i1 %18 to i32
  %20 = sext i32 %19 to i64
  %21 = call i64 @llvm.expect.i64(i64 %20, i64 0)
  %22 = icmp ne i64 %21, 0
  br i1 %22, label %23, label %41

23:                                               ; preds = %3
  br label %24

24:                                               ; preds = %23
  %25 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !14
  %26 = zext i8 %25 to i32
  %27 = icmp sle i32 1, %26
  %28 = xor i1 %27, true
  %29 = xor i1 %28, true
  %30 = zext i1 %29 to i32
  %31 = sext i32 %30 to i64
  %32 = call i64 @llvm.expect.i64(i64 %31, i64 0)
  %33 = icmp ne i64 %32, 0
  br i1 %33, label %34, label %39

34:                                               ; preds = %24
  %35 = load ptr, ptr %7, align 8, !tbaa !5
  %36 = getelementptr inbounds %struct.tree, ptr %35, i32 0, i32 0
  %37 = load i16, ptr %36, align 4, !tbaa !9
  %38 = zext i16 %37 to i32
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 1, ptr noundef @__func__.tbl_setup, i32 noundef 10, ptr noundef @.str, i32 noundef %38)
  br label %39

39:                                               ; preds = %34, %24
  br label %40

40:                                               ; preds = %39
  store i32 -30784, ptr %4, align 4
  br label %253

41:                                               ; preds = %3
  call void @llvm.lifetime.start.p0(i64 8, ptr %8) #7
  %42 = load ptr, ptr %7, align 8, !tbaa !5
  %43 = getelementptr inbounds %struct.tree, ptr %42, i32 0, i32 0
  %44 = load i16, ptr %43, align 4, !tbaa !9
  %45 = zext i16 %44 to i32
  %46 = call i64 @valsize_min(i32 noundef %45) #8
  store i64 %46, ptr %8, align 8, !tbaa !17
  call void @llvm.lifetime.start.p0(i64 8, ptr %9) #7
  %47 = load ptr, ptr %5, align 8, !tbaa !5
  %48 = load ptr, ptr %7, align 8, !tbaa !5
  %49 = getelementptr inbounds %struct.tree, ptr %48, i32 0, i32 0
  %50 = load i16, ptr %49, align 4, !tbaa !9
  %51 = zext i16 %50 to i32
  %52 = call i64 @env_valsize_max(ptr noundef %47, i32 noundef %51) #8
  store i64 %52, ptr %9, align 8, !tbaa !17
  %53 = load ptr, ptr %7, align 8, !tbaa !5
  %54 = getelementptr inbounds %struct.tree, ptr %53, i32 0, i32 0
  %55 = load i16, ptr %54, align 4, !tbaa !9
  %56 = zext i16 %55 to i32
  %57 = and i32 %56, 48
  %58 = icmp ne i32 %57, 0
  br i1 %58, label %59, label %111

59:                                               ; preds = %41
  %60 = load ptr, ptr %7, align 8, !tbaa !5
  %61 = getelementptr inbounds %struct.tree, ptr %60, i32 0, i32 2
  %62 = load i32, ptr %61, align 4, !tbaa !18
  %63 = icmp ne i32 %62, 0
  br i1 %63, label %64, label %111

64:                                               ; preds = %59
  %65 = load ptr, ptr %7, align 8, !tbaa !5
  %66 = getelementptr inbounds %struct.tree, ptr %65, i32 0, i32 2
  %67 = load i32, ptr %66, align 4, !tbaa !18
  %68 = zext i32 %67 to i64
  %69 = load i64, ptr %8, align 8, !tbaa !17
  %70 = icmp ult i64 %68, %69
  br i1 %70, label %78, label %71

71:                                               ; preds = %64
  %72 = load ptr, ptr %7, align 8, !tbaa !5
  %73 = getelementptr inbounds %struct.tree, ptr %72, i32 0, i32 2
  %74 = load i32, ptr %73, align 4, !tbaa !18
  %75 = zext i32 %74 to i64
  %76 = load i64, ptr %9, align 8, !tbaa !17
  %77 = icmp ugt i64 %75, %76
  br label %78

78:                                               ; preds = %71, %64
  %79 = phi i1 [ true, %64 ], [ %77, %71 ]
  %80 = xor i1 %79, true
  %81 = xor i1 %80, true
  %82 = zext i1 %81 to i32
  %83 = sext i32 %82 to i64
  %84 = call i64 @llvm.expect.i64(i64 %83, i64 0)
  %85 = icmp ne i64 %84, 0
  br i1 %85, label %86, label %106

86:                                               ; preds = %78
  br label %87

87:                                               ; preds = %86
  %88 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 5), align 2, !tbaa !14
  %89 = zext i8 %88 to i32
  %90 = icmp sle i32 1, %89
  %91 = xor i1 %90, true
  %92 = xor i1 %91, true
  %93 = zext i1 %92 to i32
  %94 = sext i32 %93 to i64
  %95 = call i64 @llvm.expect.i64(i64 %94, i64 0)
  %96 = icmp ne i64 %95, 0
  br i1 %96, label %97, label %103

97:                                               ; preds = %87
  %98 = load ptr, ptr %7, align 8, !tbaa !5
  %99 = getelementptr inbounds %struct.tree, ptr %98, i32 0, i32 2
  %100 = load i32, ptr %99, align 4, !tbaa !18
  %101 = load i64, ptr %8, align 8, !tbaa !17
  %102 = load i64, ptr %9, align 8, !tbaa !17
  call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 1, ptr noundef @__func__.tbl_setup, i32 noundef 18, ptr noundef @.str.1, i32 noundef %100, i64 noundef %101, i64 noundef %102)
  br label %103

103:                                              ; preds = %97, %87
  br label %104

104:                                              ; preds = %103
  br label %105

105:                                              ; preds = %104
  store i32 -30796, ptr %4, align 4
  store i32 1, ptr %10, align 4
  br label %252

106:                                              ; preds = %78
  %107 = load ptr, ptr %7, align 8, !tbaa !5
  %108 = getelementptr inbounds %struct.tree, ptr %107, i32 0, i32 2
  %109 = load i32, ptr %108, align 4, !tbaa !18
  %110 = zext i32 %109 to i64
  store i64 %110, ptr %9, align 8, !tbaa !17
  store i64 %110, ptr %8, align 8, !tbaa !17
  br label %111

111:                                              ; preds = %106, %59, %41
  %112 = load ptr, ptr %7, align 8, !tbaa !5
  %113 = getelementptr inbounds %struct.tree, ptr %112, i32 0, i32 0
  %114 = load i16, ptr %113, align 4, !tbaa !9
  %115 = zext i16 %114 to i32
  %116 = call i64 @keysize_min(i32 noundef %115) #8
  %117 = load ptr, ptr %6, align 8, !tbaa !5
  %118 = getelementptr inbounds %struct.kvx, ptr %117, i32 0, i32 0
  %119 = getelementptr inbounds %struct.clc2, ptr %118, i32 0, i32 0
  %120 = getelementptr inbounds %struct.clc, ptr %119, i32 0, i32 1
  store volatile i64 %116, ptr %120, align 8, !tbaa !19
  %121 = load ptr, ptr %5, align 8, !tbaa !5
  %122 = load ptr, ptr %7, align 8, !tbaa !5
  %123 = getelementptr inbounds %struct.tree, ptr %122, i32 0, i32 0
  %124 = load i16, ptr %123, align 4, !tbaa !9
  %125 = zext i16 %124 to i32
  %126 = call i64 @env_keysize_max(ptr noundef %121, i32 noundef %125) #8
  %127 = load ptr, ptr %6, align 8, !tbaa !5
  %128 = getelementptr inbounds %struct.kvx, ptr %127, i32 0, i32 0
  %129 = getelementptr inbounds %struct.clc2, ptr %128, i32 0, i32 0
  %130 = getelementptr inbounds %struct.clc, ptr %129, i32 0, i32 2
  store volatile i64 %126, ptr %130, align 8, !tbaa !24
  %131 = load ptr, ptr %6, align 8, !tbaa !5
  %132 = getelementptr inbounds %struct.kvx, ptr %131, i32 0, i32 0
  %133 = getelementptr inbounds %struct.clc2, ptr %132, i32 0, i32 0
  %134 = getelementptr inbounds %struct.clc, ptr %133, i32 0, i32 0
  %135 = load volatile ptr, ptr %134, align 8, !tbaa !25
  %136 = icmp ne ptr %135, null
  %137 = xor i1 %136, true
  %138 = xor i1 %137, true
  %139 = xor i1 %138, true
  %140 = zext i1 %139 to i32
  %141 = sext i32 %140 to i64
  %142 = call i64 @llvm.expect.i64(i64 %141, i64 0)
  %143 = icmp ne i64 %142, 0
  br i1 %143, label %144, label %163

144:                                              ; preds = %111
  %145 = load ptr, ptr %7, align 8, !tbaa !5
  %146 = getelementptr inbounds %struct.tree, ptr %145, i32 0, i32 0
  %147 = load i16, ptr %146, align 4, !tbaa !9
  %148 = zext i16 %147 to i32
  %149 = call ptr @builtin_datacmp(i32 noundef %148)
  %150 = load ptr, ptr %6, align 8, !tbaa !5
  %151 = getelementptr inbounds %struct.kvx, ptr %150, i32 0, i32 0
  %152 = getelementptr inbounds %struct.clc2, ptr %151, i32 0, i32 1
  %153 = getelementptr inbounds %struct.clc, ptr %152, i32 0, i32 0
  store volatile ptr %149, ptr %153, align 8, !tbaa !26
  %154 = load ptr, ptr %7, align 8, !tbaa !5
  %155 = getelementptr inbounds %struct.tree, ptr %154, i32 0, i32 0
  %156 = load i16, ptr %155, align 4, !tbaa !9
  %157 = zext i16 %156 to i32
  %158 = call ptr @builtin_keycmp(i32 noundef %157)
  %159 = load ptr, ptr %6, align 8, !tbaa !5
  %160 = getelementptr inbounds %struct.kvx, ptr %159, i32 0, i32 0
  %161 = getelementptr inbounds %struct.clc2, ptr %160, i32 0, i32 0
  %162 = getelementptr inbounds %struct.clc, ptr %161, i32 0, i32 0
  store volatile ptr %158, ptr %162, align 8, !tbaa !25
  br label %163

163:                                              ; preds = %144, %111
  %164 = load i64, ptr %8, align 8, !tbaa !17
  %165 = load ptr, ptr %6, align 8, !tbaa !5
  %166 = getelementptr inbounds %struct.kvx, ptr %165, i32 0, i32 0
  %167 = getelementptr inbounds %struct.clc2, ptr %166, i32 0, i32 1
  %168 = getelementptr inbounds %struct.clc, ptr %167, i32 0, i32 1
  store volatile i64 %164, ptr %168, align 8, !tbaa !27
  %169 = load i64, ptr %9, align 8, !tbaa !17
  %170 = load ptr, ptr %6, align 8, !tbaa !5
  %171 = getelementptr inbounds %struct.kvx, ptr %170, i32 0, i32 0
  %172 = getelementptr inbounds %struct.clc2, ptr %171, i32 0, i32 1
  %173 = getelementptr inbounds %struct.clc, ptr %172, i32 0, i32 2
  store volatile i64 %169, ptr %173, align 8, !tbaa !28
  fence release
  br label %174

174:                                              ; preds = %163
  %175 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 4), align 1, !tbaa !29
  %176 = zext i8 %175 to i32
  %177 = and i32 %176, 1
  %178 = icmp ne i32 %177, 0
  %179 = xor i1 %178, true
  %180 = xor i1 %179, true
  %181 = zext i1 %180 to i32
  %182 = sext i32 %181 to i64
  %183 = call i64 @llvm.expect.i64(i64 %182, i64 1)
  %184 = icmp ne i64 %183, 0
  br i1 %184, label %185, label %210

185:                                              ; preds = %174
  br label %186

186:                                              ; preds = %185
  %187 = load ptr, ptr %6, align 8, !tbaa !5
  %188 = getelementptr inbounds %struct.kvx, ptr %187, i32 0, i32 0
  %189 = getelementptr inbounds %struct.clc2, ptr %188, i32 0, i32 0
  %190 = getelementptr inbounds %struct.clc, ptr %189, i32 0, i32 2
  %191 = load volatile i64, ptr %190, align 8, !tbaa !24
  %192 = load ptr, ptr %6, align 8, !tbaa !5
  %193 = getelementptr inbounds %struct.kvx, ptr %192, i32 0, i32 0
  %194 = getelementptr inbounds %struct.clc2, ptr %193, i32 0, i32 0
  %195 = getelementptr inbounds %struct.clc, ptr %194, i32 0, i32 1
  %196 = load volatile i64, ptr %195, align 8, !tbaa !19
  %197 = icmp uge i64 %191, %196
  %198 = xor i1 %197, true
  %199 = xor i1 %198, true
  %200 = xor i1 %199, true
  %201 = zext i1 %200 to i32
  %202 = sext i32 %201 to i64
  %203 = call i64 @llvm.expect.i64(i64 %202, i64 0)
  %204 = icmp ne i64 %203, 0
  br i1 %204, label %205, label %207

205:                                              ; preds = %186
  %206 = load ptr, ptr %5, align 8, !tbaa !5
  call void @mdbx_assert_fail(ptr noundef %206, ptr noundef @.str.2, ptr noundef @__func__.tbl_setup, i32 noundef 35) #9
  unreachable

207:                                              ; preds = %186
  br label %208

208:                                              ; preds = %207
  br label %209

209:                                              ; preds = %208
  br label %210

210:                                              ; preds = %209, %174
  br label %211

211:                                              ; preds = %210
  br label %212

212:                                              ; preds = %211
  br label %213

213:                                              ; preds = %212
  %214 = load i8, ptr getelementptr inbounds (%struct.libmdbx_globals, ptr @globals, i32 0, i32 4), align 1, !tbaa !29
  %215 = zext i8 %214 to i32
  %216 = and i32 %215, 1
  %217 = icmp ne i32 %216, 0
  %218 = xor i1 %217, true
  %219 = xor i1 %218, true
  %220 = zext i1 %219 to i32
  %221 = sext i32 %220 to i64
  %222 = call i64 @llvm.expect.i64(i64 %221, i64 1)
  %223 = icmp ne i64 %222, 0
  br i1 %223, label %224, label %249

224:                                              ; preds = %213
  br label %225

225:                                              ; preds = %224
  %226 = load ptr, ptr %6, align 8, !tbaa !5
  %227 = getelementptr inbounds %struct.kvx, ptr %226, i32 0, i32 0
  %228 = getelementptr inbounds %struct.clc2, ptr %227, i32 0, i32 1
  %229 = getelementptr inbounds %struct.clc, ptr %228, i32 0, i32 2
  %230 = load volatile i64, ptr %229, align 8, !tbaa !28
  %231 = load ptr, ptr %6, align 8, !tbaa !5
  %232 = getelementptr inbounds %struct.kvx, ptr %231, i32 0, i32 0
  %233 = getelementptr inbounds %struct.clc2, ptr %232, i32 0, i32 1
  %234 = getelementptr inbounds %struct.clc, ptr %233, i32 0, i32 1
  %235 = load volatile i64, ptr %234, align 8, !tbaa !27
  %236 = icmp uge i64 %230, %235
  %237 = xor i1 %236, true
  %238 = xor i1 %237, true
  %239 = xor i1 %238, true
  %240 = zext i1 %239 to i32
  %241 = sext i32 %240 to i64
  %242 = call i64 @llvm.expect.i64(i64 %241, i64 0)
  %243 = icmp ne i64 %242, 0
  br i1 %243, label %244, label %246

244:                                              ; preds = %225
  %245 = load ptr, ptr %5, align 8, !tbaa !5
  call void @mdbx_assert_fail(ptr noundef %245, ptr noundef @.str.3, ptr noundef @__func__.tbl_setup, i32 noundef 36) #9
  unreachable

246:                                              ; preds = %225
  br label %247

247:                                              ; preds = %246
  br label %248

248:                                              ; preds = %247
  br label %249

249:                                              ; preds = %248, %213
  br label %250

250:                                              ; preds = %249
  br label %251

251:                                              ; preds = %250
  store i32 0, ptr %4, align 4
  store i32 1, ptr %10, align 4
  br label %252

252:                                              ; preds = %251, %105
  call void @llvm.lifetime.end.p0(i64 8, ptr %9) #7
  call void @llvm.lifetime.end.p0(i64 8, ptr %8) #7
  br label %253

253:                                              ; preds = %252, %40
  %254 = load i32, ptr %4, align 4
  ret i32 %254
}

; Function Attrs: inlinehint nounwind uwtable
declare hidden zeroext i1 @check_table_flags(i32 noundef) #1

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

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

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

; Function Attrs: inlinehint nounwind willreturn memory(none) uwtable
declare hidden i64 @valsize_min(i32 noundef) #5

; Function Attrs: inlinehint nounwind willreturn memory(none) uwtable
declare hidden i64 @env_valsize_max(ptr noundef, i32 noundef) #5

; Function Attrs: inlinehint nounwind willreturn memory(none) uwtable
declare hidden i64 @keysize_min(i32 noundef) #5

; Function Attrs: inlinehint nounwind willreturn memory(none) uwtable
declare hidden i64 @env_keysize_max(ptr noundef, i32 noundef) #5

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

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

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

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

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 = { 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 = { nocallback nofree nosync nounwind willreturn memory(none) }
attributes #3 = { "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 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #5 = { inlinehint nounwind willreturn memory(none) 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 = { 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 #7 = { nounwind }
attributes #8 = { nounwind willreturn memory(none) }
attributes #9 = { 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, !11, i64 0}
!10 = !{!"tree", !11, i64 0, !11, i64 2, !12, i64 4, !12, i64 8, !12, i64 12, !12, i64 16, !12, i64 20, !13, i64 24, !13, i64 32, !13, i64 40}
!11 = !{!"short", !7, i64 0}
!12 = !{!"int", !7, i64 0}
!13 = !{!"long", !7, i64 0}
!14 = !{!15, !7, i64 26}
!15 = !{!"libmdbx_globals", !7, i64 0, !12, i64 16, !12, i64 20, !7, i64 24, !7, i64 25, !7, i64 26, !16, i64 27, !12, i64 28, !7, i64 32, !7, i64 40, !13, i64 80, !6, i64 88}
!16 = !{!"_Bool", !7, i64 0}
!17 = !{!13, !13, i64 0}
!18 = !{!10, !12, i64 4}
!19 = !{!20, !13, i64 8}
!20 = !{!"kvx", !21, i64 0, !23, i64 48}
!21 = !{!"clc2", !22, i64 0, !22, i64 24}
!22 = !{!"clc", !6, i64 0, !13, i64 8, !13, i64 16}
!23 = !{!"iovec", !6, i64 0, !13, i64 8}
!24 = !{!20, !13, i64 16}
!25 = !{!20, !6, i64 0}
!26 = !{!20, !6, i64 24}
!27 = !{!20, !13, i64 32}
!28 = !{!20, !13, i64 40}
!29 = !{!15, !7, i64 25}


; 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 }
%struct.anon = 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 }

@globals = external local_unnamed_addr global %struct.libmdbx_globals, align 8
@__func__.tbl_setup = external hidden unnamed_addr constant [10 x i8], align 1
@.str = external hidden unnamed_addr constant [42 x i8], align 1
@.str.1 = external hidden unnamed_addr constant [55 x i8], align 1
@.str.2 = external hidden unnamed_addr constant [35 x i8], align 1
@.str.3 = external hidden unnamed_addr constant [35 x i8], align 1

; Function Attrs: nounwind uwtable
define dso_local range(i32 -30796, 1) i32 @tbl_setup(ptr noundef %0, ptr noundef %1, ptr nocapture noundef readonly %2) local_unnamed_addr #0 {
  fence acquire
  %4 = load i16, ptr %2, align 4, !tbaa !5
  %5 = zext i16 %4 to i32
  %6 = tail call zeroext i1 @check_table_flags(i32 noundef %5)
  br i1 %6, label %12, label %7, !prof !12

7:                                                ; preds = %3
  %8 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !13
  %.not46 = icmp eq i8 %8, 0
  br i1 %.not46, label %.thread, label %9, !prof !12

9:                                                ; preds = %7
  %10 = load i16, ptr %2, align 4, !tbaa !5
  %11 = zext i16 %10 to i32
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 1, ptr noundef nonnull @__func__.tbl_setup, i32 noundef 10, ptr noundef nonnull @.str, i32 noundef %11) #5
  br label %.thread

12:                                               ; preds = %3
  %13 = load i16, ptr %2, align 4, !tbaa !5
  %14 = zext i16 %13 to i32
  %15 = tail call i64 @valsize_min(i32 noundef %14) #6
  %16 = tail call i64 @env_valsize_max(ptr noundef %0, i32 noundef %14) #6
  %17 = and i32 %14, 48
  %.not = icmp eq i32 %17, 0
  br i1 %.not, label %28, label %18

18:                                               ; preds = %12
  %19 = getelementptr inbounds i8, ptr %2, i64 4
  %20 = load i32, ptr %19, align 4, !tbaa !17
  %.not39 = icmp eq i32 %20, 0
  br i1 %.not39, label %28, label %21

21:                                               ; preds = %18
  %22 = zext i32 %20 to i64
  %23 = icmp ugt i64 %15, %22
  %24 = icmp ult i64 %16, %22
  %spec.select = select i1 %23, i1 true, i1 %24, !prof !18
  br i1 %spec.select, label %25, label %28, !prof !18

25:                                               ; preds = %21
  %26 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 26), align 2, !tbaa !13
  %.not45 = icmp eq i8 %26, 0
  br i1 %.not45, label %.thread, label %27, !prof !12

27:                                               ; preds = %25
  tail call void (i32, ptr, i32, ptr, ...) @debug_log(i32 noundef 1, ptr noundef nonnull @__func__.tbl_setup, i32 noundef 18, ptr noundef nonnull @.str.1, i32 noundef %20, i64 noundef %15, i64 noundef %16) #5
  br label %.thread

28:                                               ; preds = %21, %18, %12
  %.035 = phi i64 [ %15, %18 ], [ %15, %12 ], [ %22, %21 ]
  %.0 = phi i64 [ %16, %18 ], [ %16, %12 ], [ %22, %21 ]
  %29 = tail call i64 @keysize_min(i32 noundef %14) #6
  %30 = getelementptr inbounds i8, ptr %1, i64 8
  store volatile i64 %29, ptr %30, align 8, !tbaa !19
  %31 = tail call i64 @env_keysize_max(ptr noundef %0, i32 noundef %14) #6
  %32 = getelementptr inbounds i8, ptr %1, i64 16
  store volatile i64 %31, ptr %32, align 8, !tbaa !24
  %33 = load volatile ptr, ptr %1, align 8, !tbaa !25
  %.not40 = icmp eq ptr %33, null
  br i1 %.not40, label %34, label %40, !prof !18

34:                                               ; preds = %28
  %35 = tail call ptr @builtin_datacmp(i32 noundef %14)
  %36 = getelementptr inbounds i8, ptr %1, i64 24
  store volatile ptr %35, ptr %36, align 8, !tbaa !26
  %37 = load i16, ptr %2, align 4, !tbaa !5
  %38 = zext i16 %37 to i32
  %39 = tail call ptr @builtin_keycmp(i32 noundef %38)
  store volatile ptr %39, ptr %1, align 8, !tbaa !25
  br label %40

40:                                               ; preds = %34, %28
  %41 = getelementptr inbounds i8, ptr %1, i64 32
  store volatile i64 %.035, ptr %41, align 8, !tbaa !27
  %42 = getelementptr inbounds i8, ptr %1, i64 40
  store volatile i64 %.0, ptr %42, align 8, !tbaa !28
  fence release
  %43 = load i8, ptr getelementptr inbounds (i8, ptr @globals, i64 25), align 1, !tbaa !29
  %44 = and i8 %43, 1
  %.not41 = icmp eq i8 %44, 0
  br i1 %.not41, label %.thread, label %45, !prof !18

45:                                               ; preds = %40
  %46 = load volatile i64, ptr %32, align 8, !tbaa !24
  %47 = load volatile i64, ptr %30, align 8, !tbaa !19
  %.not42 = icmp ult i64 %46, %47
  br i1 %.not42, label %48, label %49, !prof !18

48:                                               ; preds = %45
  tail call void @mdbx_assert_fail(ptr noundef %0, ptr noundef nonnull @.str.2, ptr noundef nonnull @__func__.tbl_setup, i32 noundef 35) #7
  unreachable

49:                                               ; preds = %45
  %50 = load volatile i64, ptr %42, align 8, !tbaa !28
  %51 = load volatile i64, ptr %41, align 8, !tbaa !27
  %.not44 = icmp ult i64 %50, %51
  br i1 %.not44, label %52, label %.thread, !prof !18

52:                                               ; preds = %49
  tail call void @mdbx_assert_fail(ptr noundef %0, ptr noundef nonnull @.str.3, ptr noundef nonnull @__func__.tbl_setup, i32 noundef 36) #7
  unreachable

.thread:                                          ; preds = %40, %27, %25, %49, %9, %7
  %.1 = phi i32 [ -30784, %7 ], [ -30784, %9 ], [ -30796, %27 ], [ -30796, %25 ], [ 0, %49 ], [ 0, %40 ]
  ret i32 %.1
}

; Function Attrs: inlinehint nounwind uwtable
declare hidden zeroext i1 @check_table_flags(i32 noundef) local_unnamed_addr #1

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

; Function Attrs: inlinehint mustprogress nofree nosync nounwind willreturn memory(none) uwtable
declare hidden i64 @valsize_min(i32 noundef) local_unnamed_addr #3

; Function Attrs: inlinehint mustprogress nofree nosync nounwind willreturn memory(none) uwtable
declare hidden i64 @env_valsize_max(ptr noundef, i32 noundef) local_unnamed_addr #3

; Function Attrs: inlinehint mustprogress nofree nosync nounwind willreturn memory(none) uwtable
declare hidden i64 @keysize_min(i32 noundef) local_unnamed_addr #3

; Function Attrs: inlinehint mustprogress nofree nosync nounwind willreturn memory(none) uwtable
declare hidden i64 @env_keysize_max(ptr noundef, i32 noundef) local_unnamed_addr #3

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

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

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

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 = { 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 = { "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 mustprogress nofree nosync nounwind willreturn memory(none) 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 = { 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 #5 = { nounwind }
attributes #6 = { nounwind willreturn memory(none) }
attributes #7 = { 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 0}
!6 = !{!"tree", !7, i64 0, !7, i64 2, !10, i64 4, !10, i64 8, !10, i64 12, !10, i64 16, !10, i64 20, !11, i64 24, !11, i64 32, !11, i64 40}
!7 = !{!"short", !8, i64 0}
!8 = !{!"omnipotent char", !9, i64 0}
!9 = !{!"Simple C/C++ TBAA"}
!10 = !{!"int", !8, i64 0}
!11 = !{!"long", !8, i64 0}
!12 = !{!"branch_weights", !"expected", i32 2000, i32 1}
!13 = !{!14, !8, i64 26}
!14 = !{!"libmdbx_globals", !8, i64 0, !10, i64 16, !10, i64 20, !8, i64 24, !8, i64 25, !8, i64 26, !15, i64 27, !10, i64 28, !8, i64 32, !8, i64 40, !11, i64 80, !16, i64 88}
!15 = !{!"_Bool", !8, i64 0}
!16 = !{!"any pointer", !8, i64 0}
!17 = !{!6, !10, i64 4}
!18 = !{!"branch_weights", !"expected", i32 1, i32 2000}
!19 = !{!20, !11, i64 8}
!20 = !{!"kvx", !21, i64 0, !23, i64 48}
!21 = !{!"clc2", !22, i64 0, !22, i64 24}
!22 = !{!"clc", !16, i64 0, !11, i64 8, !11, i64 16}
!23 = !{!"iovec", !16, i64 0, !11, i64 8}
!24 = !{!20, !11, i64 16}
!25 = !{!20, !16, i64 0}
!26 = !{!20, !16, i64 24}
!27 = !{!20, !11, i64 32}
!28 = !{!20, !11, i64 40}
!29 = !{!14, !8, i64 25}


; Effective O3 passes: EarlyCSEPass,GlobalOptPass,IPSCCPPass,InferFunctionAttrsPass,InstCombinePass,JumpThreadingPass,LowerExpectIntrinsicPass,PostOrderFunctionAttrsPass,SROAPass,SimplifyCFGPass,TailCallElimPass