=== MBA Substitution Test ===
; ModuleID = 'mba_out.bc'
source_filename = "simple.ll"

define i32 @add(i32 %a, i32 %b) {
entry:
  %0 = sub i32 0, %a
  %1 = sub i32 0, %a
  %2 = xor i32 %b, -1
  %3 = and i32 %2, 0
  %4 = xor i32 %3, -1
  %5 = and i32 %b, -1
  %6 = xor i32 %5, -1
  %7 = and i32 %4, %6
  %8 = xor i32 %b, -1
  %9 = add i32 %1, %7
  %10 = add i32 %0, %9
  %11 = add i32 %a, %10
  %12 = xor i32 %11, -1
  %13 = and i32 %12, -1
  %14 = and i32 %11, 0
  %15 = add i32 %13, %14
  %16 = and i32 %13, %14
  %17 = sub i32 %15, %16
  %18 = or i32 %13, %14
  %19 = xor i32 %11, -1
  %sum = add i32 %a, %b
  ret i32 %17
}

define i32 @sub(i32 %a, i32 %b) {
entry:
  %0 = sub i32 0, %b
  %1 = xor i32 %a, -1
  %2 = xor i32 %0, -1
  %3 = and i32 %1, %2
  %4 = xor i32 %3, -1
  %5 = and i32 %a, %0
  %6 = xor i32 %5, -1
  %7 = and i32 %4, %6
  %8 = xor i32 %a, %0
  %9 = and i32 %a, %0
  %10 = add i32 2, %9
  %11 = and i32 2, %9
  %12 = sub i32 %10, %11
  %13 = or i32 2, %9
  %14 = and i32 2, %9
  %15 = mul i32 %12, %14
  %16 = xor i32 %9, -1
  %17 = and i32 2, %16
  %18 = and i32 %9, -3
  %19 = mul i32 %17, %18
  %20 = add i32 %15, %19
  %21 = mul i32 2, %9
  %22 = sub i32 0, %7
  %23 = sub i32 0, %7
  %24 = xor i32 %20, -1
  %25 = and i32 %24, -1
  %26 = and i32 %20, 0
  %27 = and i32 %25, %26
  %28 = xor i32 %26, %27
  %29 = xor i32 %25, %28
  %30 = or i32 %25, %26
  %31 = xor i32 %20, -1
  %32 = add i32 %23, %29
  %33 = add i32 %22, %32
  %34 = add i32 %7, %33
  %35 = xor i32 %34, -1
  %36 = and i32 %35, -1
  %37 = and i32 %34, 0
  %38 = add i32 %36, %37
  %39 = and i32 %36, %37
  %40 = sub i32 %38, %39
  %41 = or i32 %36, %37
  %42 = xor i32 %34, -1
  %43 = add i32 %7, %20
  %diff = sub i32 %a, %b
  ret i32 %40
}

define i32 @mul(i32 %a, i32 %b) {
entry:
  %0 = add i32 %a, %b
  %1 = and i32 %a, %b
  %2 = sub i32 %0, %1
  %3 = or i32 %a, %b
  %4 = and i32 %a, %b
  %5 = mul i32 %2, %4
  %6 = xor i32 %b, -1
  %7 = and i32 %a, %6
  %8 = xor i32 %a, -1
  %9 = and i32 %b, %8
  %10 = mul i32 %7, %9
  %11 = add i32 %5, %10
  %prod = mul i32 %a, %b
  ret i32 %11
}

define i32 @xor_func(i32 %a, i32 %b) {
entry:
  %0 = add i32 %a, %b
  %1 = and i32 %a, %b
  %2 = add i32 2, %1
  %3 = and i32 2, %1
  %4 = sub i32 %2, %3
  %5 = or i32 2, %1
  %6 = and i32 2, %1
  %7 = mul i32 %4, %6
  %8 = xor i32 %1, -1
  %9 = and i32 2, %8
  %10 = and i32 %1, -3
  %11 = mul i32 %9, %10
  %12 = add i32 %7, %11
  %13 = mul i32 2, %1
  %14 = sub i32 %0, %12
  %result = xor i32 %a, %b
  ret i32 %14
}

define i32 @or_func(i32 %a, i32 %b) {
entry:
  %0 = xor i32 %a, -1
  %1 = xor i32 %b, -1
  %2 = and i32 %0, %1
  %3 = xor i32 %2, -1
  %result = or i32 %a, %b
  ret i32 %3
}

define i32 @factorial(i32 %n) {
entry:
  %cmp = icmp sle i32 %n, 1
  br i1 %cmp, label %base, label %recurse

base:                                             ; preds = %entry
  ret i32 1

recurse:                                          ; preds = %entry
  %0 = add i32 %n, -1
  %1 = and i32 %n, -1
  %2 = and i32 2, %1
  %3 = xor i32 %1, %2
  %4 = xor i32 2, %3
  %5 = or i32 2, %1
  %6 = and i32 2, %1
  %7 = mul i32 %4, %6
  %8 = xor i32 %1, -1
  %9 = and i32 2, %8
  %10 = and i32 %1, -3
  %11 = mul i32 %9, %10
  %12 = add i32 %7, %11
  %13 = mul i32 2, %1
  %14 = sub i32 %0, %12
  %15 = xor i32 %n, -1
  %16 = and i32 %n, -1
  %17 = xor i32 %16, -1
  %18 = and i32 -3, %17
  %19 = xor i32 %18, -1
  %20 = or i32 2, %16
  %21 = and i32 2, %16
  %22 = mul i32 %19, %21
  %23 = xor i32 %16, -1
  %24 = and i32 2, %23
  %25 = and i32 %16, -3
  %26 = mul i32 %24, %25
  %27 = add i32 %22, %26
  %28 = mul i32 2, %16
  %29 = add i32 %27, -1253818729
  %30 = add i32 %14, %29
  %31 = sub i32 %30, -1253818729
  %32 = add i32 %14, %27
  %n_minus_1 = sub i32 %n, 1
  %fact_n_minus_1 = call i32 @factorial(i32 %31)
  %33 = and i32 %n, %fact_n_minus_1
  %34 = xor i32 %fact_n_minus_1, %33
  %35 = xor i32 %n, %34
  %36 = or i32 %n, %fact_n_minus_1
  %37 = and i32 %n, %fact_n_minus_1
  %38 = mul i32 %35, %37
  %39 = xor i32 %fact_n_minus_1, -1
  %40 = and i32 %n, %39
  %41 = xor i32 %n, -1
  %42 = and i32 %fact_n_minus_1, %41
  %43 = mul i32 %40, %42
  %44 = add i32 %38, %43
  %result = mul i32 %n, %fact_n_minus_1
  ret i32 %44
}

define i32 @max(i32 %a, i32 %b) {
entry:
  %cmp = icmp sgt i32 %a, %b
  br i1 %cmp, label %then, label %else

then:                                             ; preds = %entry
  br label %end

else:                                             ; preds = %entry
  br label %end

end:                                              ; preds = %else, %then
  %result = phi i32 [ %a, %then ], [ %b, %else ]
  ret i32 %result
}

=== Basic Block Splitter Test ===
; ModuleID = 'bb_out.bc'
source_filename = "large_blocks.ll"

define i32 @compute(i32 %a, i32 %b, i32 %c) {
entry:
  %t1 = add i32 %a, %b
  %t2 = mul i32 %t1, %c
  %t3 = sub i32 %t2, %a
  %t4 = xor i32 %t3, %b
  %t5 = or i32 %t4, %c
  %t6 = and i32 %t5, %a
  %t7 = shl i32 %t6, 2
  br label %0

0:                                                ; preds = %entry
  %t8 = lshr i32 %t7, 1
  %t9 = add i32 %t8, %t1
  %t10 = mul i32 %t9, %t2
  %t11 = sub i32 %t10, %t3
  %t12 = xor i32 %t11, %t4
  %t13 = or i32 %t12, %t5
  %t14 = and i32 %t13, %t6
  br label %1

1:                                                ; preds = %0
  %t15 = add i32 %t14, %t7
  ret i32 %t15
}

=== Indirect Branch Test ===
; ModuleID = 'ibr_out.bc'
source_filename = "simple.ll"

define i32 @add(i32 %a, i32 %b) {
entry:
  %sum = add i32 %a, %b
  ret i32 %sum
}

define i32 @sub(i32 %a, i32 %b) {
entry:
  %diff = sub i32 %a, %b
  ret i32 %diff
}

define i32 @mul(i32 %a, i32 %b) {
entry:
  %prod = mul i32 %a, %b
  ret i32 %prod
}

define i32 @xor_func(i32 %a, i32 %b) {
entry:
  %result = xor i32 %a, %b
  ret i32 %result
}

define i32 @or_func(i32 %a, i32 %b) {
entry:
  %result = or i32 %a, %b
  ret i32 %result
}

define i32 @factorial(i32 %n) {
entry:
  %ibr.blocks = alloca [2 x ptr], align 8
  %cmp = icmp sle i32 %n, 1
  %0 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 0
  store volatile ptr blockaddress(@factorial, %base), ptr %0, align 8
  %1 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 1
  store volatile ptr blockaddress(@factorial, %recurse), ptr %1, align 8
  %2 = xor i1 %cmp, true
  %3 = zext i1 %2 to i32
  %4 = xor i32 %3, -1
  %5 = and i32 %4, -211680420
  %6 = and i32 %3, 211680419
  %7 = or i32 %5, %6
  %8 = xor i32 %7, -1
  %9 = and i32 %8, -211680420
  %10 = and i32 %7, 211680419
  %11 = or i32 %9, %10
  %12 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 %11
  %13 = load volatile ptr, ptr %12, align 8
  indirectbr ptr %13, [label %recurse, label %base]

base:                                             ; preds = %entry
  ret i32 1

recurse:                                          ; preds = %entry
  %n_minus_1 = sub i32 %n, 1
  %fact_n_minus_1 = call i32 @factorial(i32 %n_minus_1)
  %result = mul i32 %n, %fact_n_minus_1
  ret i32 %result
}

define i32 @max(i32 %a, i32 %b) {
entry:
  %ibr.blocks = alloca [2 x ptr], align 8
  %cmp = icmp sgt i32 %a, %b
  %0 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 0
  store volatile ptr blockaddress(@max, %then), ptr %0, align 8
  %1 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 1
  store volatile ptr blockaddress(@max, %else), ptr %1, align 8
  %2 = xor i1 %cmp, true
  %3 = zext i1 %2 to i32
  %4 = xor i32 %3, -1
  %5 = and i32 %4, -1731515372
  %6 = and i32 %3, 1731515371
  %7 = or i32 %5, %6
  %8 = xor i32 %7, -1
  %9 = and i32 %8, -1731515372
  %10 = and i32 %7, 1731515371
  %11 = or i32 %9, %10
  %12 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 %11
  %13 = load volatile ptr, ptr %12, align 8
  indirectbr ptr %13, [label %else, label %then]

then:                                             ; preds = %entry
  %14 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 0
  store volatile ptr blockaddress(@max, %end), ptr %14, align 8
  %15 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 0
  %16 = load volatile ptr, ptr %15, align 8
  indirectbr ptr %16, [label %end]

else:                                             ; preds = %entry
  %17 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 0
  store volatile ptr blockaddress(@max, %end), ptr %17, align 8
  %18 = getelementptr [2 x ptr], ptr %ibr.blocks, i32 0, i32 0
  %19 = load volatile ptr, ptr %18, align 8
  indirectbr ptr %19, [label %end]

end:                                              ; preds = %else, %then
  %result = phi i32 [ %a, %then ], [ %b, %else ]
  ret i32 %result
}

=== Control Flow Flattening Test ===
; ModuleID = 'cff_out.bc'
source_filename = "simple.ll"

define i32 @add(i32 %a, i32 %b) {
entry:
  %sum = add i32 %a, %b
  ret i32 %sum
}

define i32 @sub(i32 %a, i32 %b) {
entry:
  %diff = sub i32 %a, %b
  ret i32 %diff
}

define i32 @mul(i32 %a, i32 %b) {
entry:
  %prod = mul i32 %a, %b
  ret i32 %prod
}

define i32 @xor_func(i32 %a, i32 %b) {
entry:
  %result = xor i32 %a, %b
  ret i32 %result
}

define i32 @or_func(i32 %a, i32 %b) {
entry:
  %result = or i32 %a, %b
  ret i32 %result
}

define i32 @factorial(i32 %n) {
entry:
  %state = alloca i64, align 8
  store volatile i64 0, ptr %state, align 4
  %cmp = icmp sle i32 %n, 1
  br i1 %cmp, label %cff.true_state, label %cff.false_state

recurse:                                          ; preds = %cond_check.1
  %n_minus_1 = sub i32 %n, 1
  %fact_n_minus_1 = call i32 @factorial(i32 %n_minus_1)
  %result = mul i32 %n, %fact_n_minus_1
  ret i32 %result

cond_check.1:                                     ; preds = %cond_check.0
  %state_val1 = load volatile i64, ptr %state, align 4
  %0 = icmp eq i64 %state_val1, -6658695496205073752
  br i1 %0, label %recurse, label %default

base:                                             ; preds = %cond_check.0
  ret i32 1

cff.false_state:                                  ; preds = %entry
  store volatile i64 -6658695496205073752, ptr %state, align 4
  br label %dispatch

cond_check.0:                                     ; preds = %dispatch
  %state_val = load volatile i64, ptr %state, align 4
  %1 = icmp eq i64 %state_val, -4516583221450448170
  br i1 %1, label %base, label %cond_check.1

default:                                          ; preds = %cond_check.1
  br label %dispatch

cff.true_state:                                   ; preds = %entry
  store volatile i64 -4516583221450448170, ptr %state, align 4
  br label %dispatch

dispatch:                                         ; preds = %cff.true_state, %default, %cff.false_state
  br label %cond_check.0
}

define i32 @max(i32 %a, i32 %b) {
entry:
  %result.reg2mem = alloca i32, align 4
  %state = alloca i64, align 8
  store volatile i64 0, ptr %state, align 4
  %cmp = icmp sgt i32 %a, %b
  br i1 %cmp, label %cff.true_state, label %cff.false_state

end:                                              ; preds = %cond_check.2
  %result.reload = load i32, ptr %result.reg2mem, align 4
  ret i32 %result.reload

cff.false_state:                                  ; preds = %entry
  store volatile i64 -5805720026476998184, ptr %state, align 4
  br label %dispatch

default:                                          ; preds = %cond_check.2
  br label %dispatch

cond_check.2:                                     ; preds = %cond_check.1
  %state_val2 = load volatile i64, ptr %state, align 4
  %0 = icmp eq i64 %state_val2, -6689930472466057170
  br i1 %0, label %end, label %default

dispatch:                                         ; preds = %then, %cff.true_state, %else, %default, %cff.false_state
  br label %cond_check.0

else:                                             ; preds = %cond_check.1
  store volatile i64 -6689930472466057170, ptr %state, align 4
  store i32 %b, ptr %result.reg2mem, align 4
  br label %dispatch

cond_check.0:                                     ; preds = %dispatch
  %state_val = load volatile i64, ptr %state, align 4
  %1 = icmp eq i64 %state_val, -8786081103927593914
  br i1 %1, label %then, label %cond_check.1

cond_check.1:                                     ; preds = %cond_check.0
  %state_val1 = load volatile i64, ptr %state, align 4
  %2 = icmp eq i64 %state_val1, -5805720026476998184
  br i1 %2, label %else, label %cond_check.2

cff.true_state:                                   ; preds = %entry
  store volatile i64 -8786081103927593914, ptr %state, align 4
  br label %dispatch

then:                                             ; preds = %cond_check.0
  store volatile i64 -6689930472466057170, ptr %state, align 4
  store i32 %a, ptr %result.reg2mem, align 4
  br label %dispatch
}

=== Control Flow Flattening with SipHash Test ===
; ModuleID = 'cff_siphash_out.bc'
source_filename = "simple.ll"

define i32 @add(i32 %a, i32 %b) {
entry:
  %sum = add i32 %a, %b
  ret i32 %sum
}

define i32 @sub(i32 %a, i32 %b) {
entry:
  %diff = sub i32 %a, %b
  ret i32 %diff
}

define i32 @mul(i32 %a, i32 %b) {
entry:
  %prod = mul i32 %a, %b
  ret i32 %prod
}

define i32 @xor_func(i32 %a, i32 %b) {
entry:
  %result = xor i32 %a, %b
  ret i32 %result
}

define i32 @or_func(i32 %a, i32 %b) {
entry:
  %result = or i32 %a, %b
  ret i32 %result
}

define i32 @factorial(i32 %n) {
entry:
  %state = alloca i64, align 8
  store volatile i64 0, ptr %state, align 4
  %cmp = icmp sle i32 %n, 1
  br i1 %cmp, label %cff.true_state, label %cff.false_state

cond_check.1:                                     ; preds = %cond_check.0
  %state_val1 = load volatile i64, ptr %state, align 4
  %0 = call i64 @___siphash(i64 %state_val1, i64 -1001686120458196184, i64 -4552314978985526218, i64 8281039959894235250, i64 863363284243311649, i64 1191558566433412391, i64 -4655910387916276917)
  %1 = icmp eq i64 %0, -7678121173678907418
  br i1 %1, label %recurse, label %default

recurse:                                          ; preds = %cond_check.1
  %n_minus_1 = sub i32 %n, 1
  %fact_n_minus_1 = call i32 @factorial(i32 %n_minus_1)
  %result = mul i32 %n, %fact_n_minus_1
  ret i32 %result

base:                                             ; preds = %cond_check.0
  ret i32 1

cff.false_state:                                  ; preds = %entry
  store volatile i64 -6658695496205073752, ptr %state, align 4
  br label %dispatch

cond_check.0:                                     ; preds = %dispatch
  %state_val = load volatile i64, ptr %state, align 4
  %2 = call i64 @___siphash(i64 %state_val, i64 -1784372620280129195, i64 1735254072535961468, i64 -7847792721469955040, i64 6878563960103549184, i64 5052085463163665590, i64 7199227068871507297)
  %3 = icmp eq i64 %2, -1647589385571961947
  br i1 %3, label %base, label %cond_check.1

dispatch:                                         ; preds = %cff.true_state, %default, %cff.false_state
  br label %cond_check.0

default:                                          ; preds = %cond_check.1
  br label %dispatch

cff.true_state:                                   ; preds = %entry
  store volatile i64 -4516583221450448170, ptr %state, align 4
  br label %dispatch
}

define i32 @max(i32 %a, i32 %b) {
entry:
  %result.reg2mem = alloca i32, align 4
  %state = alloca i64, align 8
  store volatile i64 0, ptr %state, align 4
  %cmp = icmp sgt i32 %a, %b
  br i1 %cmp, label %cff.true_state, label %cff.false_state

end:                                              ; preds = %cond_check.2
  %result.reload = load i32, ptr %result.reg2mem, align 4
  ret i32 %result.reload

cff.false_state:                                  ; preds = %entry
  store volatile i64 1737174442216388500, ptr %state, align 4
  br label %dispatch

then:                                             ; preds = %cond_check.0
  store volatile i64 -8666994371393720023, ptr %state, align 4
  store i32 %a, ptr %result.reg2mem, align 4
  br label %dispatch

dispatch:                                         ; preds = %cff.true_state, %default, %else, %then, %cff.false_state
  br label %cond_check.0

else:                                             ; preds = %cond_check.1
  store volatile i64 -8666994371393720023, ptr %state, align 4
  store i32 %b, ptr %result.reg2mem, align 4
  br label %dispatch

cond_check.2:                                     ; preds = %cond_check.1
  %state_val2 = load volatile i64, ptr %state, align 4
  %0 = call i64 @___siphash(i64 %state_val2, i64 1369488287976682948, i64 -3310888069592193895, i64 8808491887800875507, i64 8179950246259061590, i64 -83954985815497999, i64 -7472033593677238211)
  %1 = icmp eq i64 %0, 5066365912075046352
  br i1 %1, label %end, label %default

default:                                          ; preds = %cond_check.2
  br label %dispatch

cff.true_state:                                   ; preds = %entry
  store volatile i64 2654745661508165829, ptr %state, align 4
  br label %dispatch

cond_check.0:                                     ; preds = %dispatch
  %state_val = load volatile i64, ptr %state, align 4
  %2 = call i64 @___siphash(i64 %state_val, i64 -4700866653361741017, i64 5972285565580814423, i64 -4593804127888259574, i64 -3609429867050390788, i64 802755865933221356, i64 -1363168409009428409)
  %3 = icmp eq i64 %2, -497931193753214718
  br i1 %3, label %then, label %cond_check.1

cond_check.1:                                     ; preds = %cond_check.0
  %state_val1 = load volatile i64, ptr %state, align 4
  %4 = call i64 @___siphash(i64 %state_val1, i64 8475173802140507824, i64 -8542128088517601291, i64 9017917336913856761, i64 3905021596306121336, i64 -7246224461111609311, i64 9095644588463654702)
  %5 = icmp eq i64 %4, -661386383189456170
  br i1 %5, label %else, label %cond_check.2
}

define internal i64 @___siphash(i64 noundef %0, i64 noundef %1, i64 noundef %2, i64 noundef %3, i64 noundef %4, i64 noundef %5, i64 noundef %6) {
  %.reg2mem69 = alloca i64, align 8
  %.reg2mem67 = alloca i32, align 4
  %.reg2mem65 = alloca i64, align 8
  %.reg2mem63 = alloca i64, align 8
  %.reg2mem61 = alloca i64, align 8
  %.reg2mem59 = alloca i64, align 8
  %.reg2mem57 = alloca i1, align 1
  %.reg2mem55 = alloca i64, align 8
  %.reg2mem53 = alloca i64, align 8
  %.reg2mem51 = alloca i64, align 8
  %.reg2mem49 = alloca i64, align 8
  %.reg2mem47 = alloca i1, align 1
  %.reg2mem45 = alloca i64, align 8
  %.reg2mem43 = alloca i64, align 8
  %.reg2mem41 = alloca i64, align 8
  %.reg2mem38 = alloca i32, align 4
  %.reg2mem35 = alloca i64, align 8
  %.reg2mem32 = alloca i64, align 8
  %.reg2mem29 = alloca i64, align 8
  %.reg2mem25 = alloca i64, align 8
  %.reg2mem22 = alloca i64, align 8
  %.reg2mem19 = alloca i64, align 8
  %.reg2mem16 = alloca i64, align 8
  %.reg2mem12 = alloca i64, align 8
  %.reg2mem9 = alloca i64, align 8
  %.reg2mem6 = alloca i64, align 8
  %.reg2mem3 = alloca i64, align 8
  %.reg2mem = alloca i64, align 8
  %8 = xor i64 %6, %2
  %9 = xor i64 %5, %1
  %10 = xor i64 %4, %2
  %11 = xor i64 %3, %1
  %12 = xor i64 %8, %0
  store i64 %11, ptr %.reg2mem41, align 4
  store i64 %10, ptr %.reg2mem43, align 4
  store i64 %9, ptr %.reg2mem45, align 4
  store i1 true, ptr %.reg2mem47, align 1
  store i64 %12, ptr %.reg2mem49, align 4
  br label %33

13:                                               ; preds = %63, %13
  %.reload70 = load i64, ptr %.reg2mem69, align 4
  %.reload68 = load i32, ptr %.reg2mem67, align 4
  %.reload66 = load i64, ptr %.reg2mem65, align 4
  %.reload64 = load i64, ptr %.reg2mem63, align 4
  %.reload62 = load i64, ptr %.reg2mem61, align 4
  %14 = add i64 %.reload62, %.reload64
  %15 = tail call i64 @llvm.fshl.i64(i64 %.reload64, i64 %.reload64, i64 13)
  %16 = xor i64 %14, %15
  %17 = tail call i64 @llvm.fshl.i64(i64 %14, i64 %14, i64 32)
  %18 = add i64 %.reload66, %.reload70
  %19 = tail call i64 @llvm.fshl.i64(i64 %.reload70, i64 %.reload70, i64 16)
  %20 = xor i64 %18, %19
  %21 = add i64 %17, %20
  store i64 %21, ptr %.reg2mem25, align 4
  %22 = tail call i64 @llvm.fshl.i64(i64 %20, i64 %20, i64 21)
  %.reload27 = load i64, ptr %.reg2mem25, align 4
  %23 = xor i64 %.reload27, %22
  store i64 %23, ptr %.reg2mem29, align 4
  %24 = add i64 %16, %18
  %25 = tail call i64 @llvm.fshl.i64(i64 %16, i64 %16, i64 17)
  %26 = xor i64 %25, %24
  store i64 %26, ptr %.reg2mem32, align 4
  %27 = tail call i64 @llvm.fshl.i64(i64 %24, i64 %24, i64 32)
  store i64 %27, ptr %.reg2mem35, align 4
  %28 = add nuw nsw i32 %.reload68, 1
  store i32 %28, ptr %.reg2mem38, align 4
  %.reload39 = load i32, ptr %.reg2mem38, align 4
  %29 = icmp eq i32 %.reload39, 4
  %.reload28 = load i64, ptr %.reg2mem25, align 4
  %.reload31 = load i64, ptr %.reg2mem29, align 4
  %.reload34 = load i64, ptr %.reg2mem32, align 4
  %.reload37 = load i64, ptr %.reg2mem35, align 4
  %.reload40 = load i32, ptr %.reg2mem38, align 4
  store i64 %.reload28, ptr %.reg2mem61, align 4
  store i64 %.reload34, ptr %.reg2mem63, align 4
  store i64 %.reload37, ptr %.reg2mem65, align 4
  store i32 %.reload40, ptr %.reg2mem67, align 4
  store i64 %.reload31, ptr %.reg2mem69, align 4
  br i1 %29, label %66, label %13

30:                                               ; preds = %33
  %.reload = load i64, ptr %.reg2mem, align 4
  %31 = xor i64 %.reload, %0
  %.reload4 = load i64, ptr %.reg2mem3, align 4
  %32 = xor i64 %.reload4, 576460752303423488
  %.reload7 = load i64, ptr %.reg2mem6, align 4
  %.reload10 = load i64, ptr %.reg2mem9, align 4
  store i64 %31, ptr %.reg2mem51, align 4
  store i64 %.reload7, ptr %.reg2mem53, align 4
  store i64 %.reload10, ptr %.reg2mem55, align 4
  store i1 true, ptr %.reg2mem57, align 1
  store i64 %32, ptr %.reg2mem59, align 4
  br label %48

33:                                               ; preds = %33, %7
  %.reload50 = load i64, ptr %.reg2mem49, align 4
  %.reload48 = load i1, ptr %.reg2mem47, align 1
  %.reload46 = load i64, ptr %.reg2mem45, align 4
  %.reload44 = load i64, ptr %.reg2mem43, align 4
  %.reload42 = load i64, ptr %.reg2mem41, align 4
  %34 = add i64 %.reload42, %.reload44
  %35 = tail call i64 @llvm.fshl.i64(i64 %.reload44, i64 %.reload44, i64 13)
  %36 = xor i64 %34, %35
  %37 = tail call i64 @llvm.fshl.i64(i64 %34, i64 %34, i64 32)
  %38 = add i64 %.reload46, %.reload50
  %39 = tail call i64 @llvm.fshl.i64(i64 %.reload50, i64 %.reload50, i64 16)
  %40 = xor i64 %38, %39
  %41 = add i64 %37, %40
  store i64 %41, ptr %.reg2mem, align 4
  %42 = tail call i64 @llvm.fshl.i64(i64 %40, i64 %40, i64 21)
  %.reload1 = load i64, ptr %.reg2mem, align 4
  %43 = xor i64 %.reload1, %42
  store i64 %43, ptr %.reg2mem3, align 4
  %44 = add i64 %36, %38
  %45 = tail call i64 @llvm.fshl.i64(i64 %36, i64 %36, i64 17)
  %46 = xor i64 %45, %44
  store i64 %46, ptr %.reg2mem6, align 4
  %47 = tail call i64 @llvm.fshl.i64(i64 %44, i64 %44, i64 32)
  store i64 %47, ptr %.reg2mem9, align 4
  %.reload2 = load i64, ptr %.reg2mem, align 4
  %.reload5 = load i64, ptr %.reg2mem3, align 4
  %.reload8 = load i64, ptr %.reg2mem6, align 4
  %.reload11 = load i64, ptr %.reg2mem9, align 4
  store i64 %.reload2, ptr %.reg2mem41, align 4
  store i64 %.reload8, ptr %.reg2mem43, align 4
  store i64 %.reload11, ptr %.reg2mem45, align 4
  store i1 false, ptr %.reg2mem47, align 1
  store i64 %.reload5, ptr %.reg2mem49, align 4
  br i1 %.reload48, label %33, label %30

48:                                               ; preds = %48, %30
  %.reload60 = load i64, ptr %.reg2mem59, align 4
  %.reload58 = load i1, ptr %.reg2mem57, align 1
  %.reload56 = load i64, ptr %.reg2mem55, align 4
  %.reload54 = load i64, ptr %.reg2mem53, align 4
  %.reload52 = load i64, ptr %.reg2mem51, align 4
  %49 = add i64 %.reload52, %.reload54
  %50 = tail call i64 @llvm.fshl.i64(i64 %.reload54, i64 %.reload54, i64 13)
  %51 = xor i64 %49, %50
  %52 = tail call i64 @llvm.fshl.i64(i64 %49, i64 %49, i64 32)
  %53 = add i64 %.reload56, %.reload60
  %54 = tail call i64 @llvm.fshl.i64(i64 %.reload60, i64 %.reload60, i64 16)
  %55 = xor i64 %53, %54
  %56 = add i64 %52, %55
  store i64 %56, ptr %.reg2mem12, align 4
  %57 = tail call i64 @llvm.fshl.i64(i64 %55, i64 %55, i64 21)
  %.reload14 = load i64, ptr %.reg2mem12, align 4
  %58 = xor i64 %.reload14, %57
  store i64 %58, ptr %.reg2mem16, align 4
  %59 = add i64 %51, %53
  %60 = tail call i64 @llvm.fshl.i64(i64 %51, i64 %51, i64 17)
  %61 = xor i64 %60, %59
  store i64 %61, ptr %.reg2mem19, align 4
  %62 = tail call i64 @llvm.fshl.i64(i64 %59, i64 %59, i64 32)
  store i64 %62, ptr %.reg2mem22, align 4
  %.reload15 = load i64, ptr %.reg2mem12, align 4
  %.reload18 = load i64, ptr %.reg2mem16, align 4
  %.reload21 = load i64, ptr %.reg2mem19, align 4
  %.reload24 = load i64, ptr %.reg2mem22, align 4
  store i64 %.reload15, ptr %.reg2mem51, align 4
  store i64 %.reload21, ptr %.reg2mem53, align 4
  store i64 %.reload24, ptr %.reg2mem55, align 4
  store i1 false, ptr %.reg2mem57, align 1
  store i64 %.reload18, ptr %.reg2mem59, align 4
  br i1 %.reload58, label %48, label %63

63:                                               ; preds = %48
  %.reload13 = load i64, ptr %.reg2mem12, align 4
  %64 = xor i64 %.reload13, 576460752303423488
  %.reload23 = load i64, ptr %.reg2mem22, align 4
  %65 = xor i64 %.reload23, 255
  %.reload17 = load i64, ptr %.reg2mem16, align 4
  %.reload20 = load i64, ptr %.reg2mem19, align 4
  store i64 %64, ptr %.reg2mem61, align 4
  store i64 %.reload20, ptr %.reg2mem63, align 4
  store i64 %65, ptr %.reg2mem65, align 4
  store i32 0, ptr %.reg2mem67, align 4
  store i64 %.reload17, ptr %.reg2mem69, align 4
  br label %13

66:                                               ; preds = %13
  %.reload30 = load i64, ptr %.reg2mem29, align 4
  %.reload36 = load i64, ptr %.reg2mem35, align 4
  %67 = xor i64 %.reload36, %.reload30
  %.reload33 = load i64, ptr %.reg2mem32, align 4
  %68 = xor i64 %67, %.reload33
  %.reload26 = load i64, ptr %.reg2mem25, align 4
  %69 = xor i64 %68, %.reload26
  ret i64 %69
}

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

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

=== String Encryption Test ===
Encrypting 3 strings
; ModuleID = 'str_out.bc'
source_filename = "strings.ll"

@.str.hello = private unnamed_addr global [14 x i8] c"d\E0!C1es\98\C5\E7\9F\B8L\B7"
@.str.secret = private unnamed_addr global [17 x i8] c"L\9E\D1\D1\E6\C8|\81\C4\92\B4\E5\EB\C1\C9\7F\8E"
@.str.test = private unnamed_addr global [12 x i8] c"\F4Y(\BE\BC\FC;\CA\\\A4/t"
@__enc_ptr_table = internal global [3 x ptr] [ptr @.str.hello, ptr @.str.secret, ptr @.str.test]
@__enc_len_table = internal global [3 x i32] [i32 14, i32 17, i32 12]
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @__decrypt_strings_ctor, ptr null }]

declare i32 @puts(ptr)

define i32 @main() {
entry:
  %0 = call i32 @puts(ptr @.str.hello)
  %1 = call i32 @puts(ptr @.str.secret)
  %2 = call i32 @puts(ptr @.str.test)
  ret i32 0
}

define internal void @__decrypt_strings_ctor() {
entry:
  %0 = alloca i32, align 4
  %dec.offset = alloca i32, align 4
  %dec.state = alloca i32, align 4
  %dec.j = alloca i32, align 4
  store i32 0, ptr %0, align 4
  br label %loop.header

loop.header:                                      ; preds = %dec.after.off, %entry
  %1 = load i32, ptr %0, align 4
  %2 = icmp ult i32 %1, 3
  br i1 %2, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.header
  %3 = getelementptr inbounds [3 x ptr], ptr @__enc_ptr_table, i64 0, i32 %1
  %4 = load ptr, ptr %3, align 8
  %5 = getelementptr inbounds [3 x i32], ptr @__enc_len_table, i64 0, i32 %1
  %6 = load i32, ptr %5, align 4
  %7 = xor i32 1608637542, %1
  store volatile i32 0, ptr %dec.offset, align 4
  store volatile i32 %7, ptr %dec.state, align 4
  br label %dec.loop.off

loop.exit:                                        ; preds = %loop.header
  ret void

dec.loop.off:                                     ; preds = %dec.after.j, %loop.body
  %8 = load volatile i32, ptr %dec.offset, align 4
  %9 = load volatile i32, ptr %dec.state, align 4
  %10 = icmp ult i32 %8, %6
  br i1 %10, label %dec.body.off, label %dec.after.off

dec.body.off:                                     ; preds = %dec.loop.off
  %11 = add i32 %9, -1640531527
  %12 = lshr i32 %11, 16
  %13 = xor i32 %11, %12
  %14 = mul i32 %13, -2048144789
  %15 = lshr i32 %14, 13
  %16 = xor i32 %14, %15
  %17 = mul i32 %16, -1028477387
  %18 = lshr i32 %17, 16
  %19 = xor i32 %17, %18
  %20 = sub i32 %6, %8
  %21 = icmp ult i32 %20, 4
  %22 = select i1 %21, i32 %20, i32 4
  store volatile i32 0, ptr %dec.j, align 4
  br label %dec.loop.j

dec.after.off:                                    ; preds = %dec.loop.off
  %23 = add i32 %1, 1
  store i32 %23, ptr %0, align 4
  br label %loop.header

dec.loop.j:                                       ; preds = %dec.body.j, %dec.body.off
  %24 = load volatile i32, ptr %dec.j, align 4
  %25 = icmp ult i32 %24, %22
  br i1 %25, label %dec.body.j, label %dec.after.j

dec.body.j:                                       ; preds = %dec.loop.j
  %26 = add i32 %8, %24
  %27 = getelementptr inbounds i8, ptr %4, i32 %26
  %28 = load volatile i8, ptr %27, align 1
  %29 = mul i32 %24, 8
  %30 = lshr i32 %19, %29
  %31 = trunc i32 %30 to i8
  %32 = xor i8 %28, %31
  %33 = getelementptr inbounds i8, ptr %4, i32 %26
  store volatile i8 %32, ptr %33, align 1
  %34 = add i32 %24, 1
  store volatile i32 %34, ptr %dec.j, align 4
  br label %dec.loop.j

dec.after.j:                                      ; preds = %dec.loop.j
  %35 = add i32 %8, %22
  store volatile i32 %35, ptr %dec.offset, align 4
  store volatile i32 %11, ptr %dec.state, align 4
  br label %dec.loop.off
}

=== All tests passed ===
