// #target: macos-x64
import std::io;

fn void res(int a)
{
	io::printn(a);
}
fn void test1(int a)
{
	switch (a) @jump
	{
		case 1: res(1);
		case 0:
		case 2: res(2);
	}
	res(0);
}

fn void test2(int a)
{
	switch (a) @jump
	{
		case 1: res(1);
		case 2: res(2);
	}
}

fn void test3(int a)
{
	switch (a) @jump
	{
		case 1: res(1);
		case 3: res(3);
	}
}

fn void test4(int a)
{
	switch (a) @jump
	{
		case 1: res(1);
		default: res(-1);
	}
}

fn void test5(int a)
{
	switch (a) @jump
	{
		case 1: res(1);
		case 4: res(4);
		default: res(-1);
	}
}

fn void test6(int a)
{
	switch (a) @jump
	{
		case 1: res(1);
		case 4: res(4);
		case 5: nextcase(a * 2);
		default: res(-1);
	}
}

/* #expect: simple_jump.ll

@jumptable = private unnamed_addr constant [3 x ptr] [ptr blockaddress(@simple_jump.test1, %switch.case1), ptr blockaddress(@simple_jump.test1, %switch.case), ptr blockaddress(@simple_jump.test1, %switch.case1)], align 8
@jumptable.1 = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@simple_jump.test2, %switch.case), ptr blockaddress(@simple_jump.test2, %switch.case1)], align 8
@jumptable.2 = private unnamed_addr constant [3 x ptr] [ptr blockaddress(@simple_jump.test3, %switch.case), ptr blockaddress(@simple_jump.test3, %switch.exit), ptr blockaddress(@simple_jump.test3, %switch.case1)], align 8
@jumptable.3 = private unnamed_addr constant [1 x ptr] [ptr blockaddress(@simple_jump.test4, %switch.case)], align 8
@jumptable.4 = private unnamed_addr constant [4 x ptr] [ptr blockaddress(@simple_jump.test5, %switch.case), ptr blockaddress(@simple_jump.test5, %switch.default), ptr blockaddress(@simple_jump.test5, %switch.default), ptr blockaddress(@simple_jump.test5, %switch.case1)], align 8
@jumptable.5 = private unnamed_addr constant [5 x ptr] [ptr blockaddress(@simple_jump.test6, %switch.case), ptr blockaddress(@simple_jump.test6, %switch.default), ptr blockaddress(@simple_jump.test6, %switch.default), ptr blockaddress(@simple_jump.test6, %switch.case1), ptr blockaddress(@simple_jump.test6, %switch.case2)], align 8

after_check12:                                    ; preds = %noerr_block8
  br label %noerr_block14

guard_block13:                                    ; preds = %assign_optional11
  br label %voiderr

noerr_block14:                                    ; preds = %after_check12
  %14 = load i64, ptr %len, align 8
  %add = add i64 %14, 1
  br label %voiderr

voiderr:                                          ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block
  ret void
}

define void @simple_jump.test1(i32 %0) #0 {
entry:
  %switch = alloca i32, align 4
  store i32 %0, ptr %switch, align 4
  br label %switch.entry

switch.entry:                                     ; preds = %entry
  %1 = load i32, ptr %switch, align 4
  %2 = icmp ugt i32 %1, 2
  br i1 %2, label %switch.exit, label %jumpblock

jumpblock:                                        ; preds = %switch.entry
  %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %1
  %target = load ptr, ptr %ptroffset, align 8
  indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.exit]

switch.case:                                      ; preds = %jumpblock
  call void @simple_jump.res(i32 1)
  br label %switch.exit

switch.case1:                                     ; preds = %jumpblock
  call void @simple_jump.res(i32 2)
  br label %switch.exit

switch.exit:                                      ; preds = %jumpblock, %switch.case1, %switch.case, %switch.entry
  call void @simple_jump.res(i32 0)
  ret void
}

define void @simple_jump.test2(i32 %0) #0 {
entry:
  %switch = alloca i32, align 4
  store i32 %0, ptr %switch, align 4
  br label %switch.entry

switch.entry:                                     ; preds = %entry
  %1 = load i32, ptr %switch, align 4
  %2 = sub i32 %1, 1
  %3 = icmp ugt i32 %2, 1
  br i1 %3, label %switch.exit, label %jumpblock

jumpblock:                                        ; preds = %switch.entry
  %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.1, i32 %2
  %target = load ptr, ptr %ptroffset, align 8
  indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.exit]

switch.case:                                      ; preds = %jumpblock
  call void @simple_jump.res(i32 1)
  br label %switch.exit

switch.case1:                                     ; preds = %jumpblock
  call void @simple_jump.res(i32 2)
  br label %switch.exit

switch.exit:                                      ; preds = %jumpblock, %switch.case1, %switch.case, %switch.entry
  ret void
}

define void @simple_jump.test3(i32 %0) #0 {
entry:
  %switch = alloca i32, align 4
  store i32 %0, ptr %switch, align 4
  br label %switch.entry

switch.entry:                                     ; preds = %entry
  %1 = load i32, ptr %switch, align 4
  %2 = sub i32 %1, 1
  %3 = icmp ugt i32 %2, 2
  br i1 %3, label %switch.exit, label %jumpblock

jumpblock:                                        ; preds = %switch.entry
  %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.2, i32 %2
  %target = load ptr, ptr %ptroffset, align 8
  indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.exit, label %switch.exit]

switch.case:                                      ; preds = %jumpblock
  call void @simple_jump.res(i32 1)
  br label %switch.exit

switch.case1:                                     ; preds = %jumpblock
  call void @simple_jump.res(i32 3)
  br label %switch.exit

switch.exit:                                      ; preds = %jumpblock, %jumpblock, %switch.case1, %switch.case, %switch.entry
  ret void
}

define void @simple_jump.test4(i32 %0) #0 {
entry:
  %switch = alloca i32, align 4
  store i32 %0, ptr %switch, align 4
  br label %switch.entry

switch.entry:                                     ; preds = %entry
  %1 = load i32, ptr %switch, align 4
  %2 = sub i32 %1, 1
  %3 = icmp ugt i32 %2, 0
  br i1 %3, label %switch.default, label %jumpblock

jumpblock:                                        ; preds = %switch.entry
  %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.3, i32 %2
  %target = load ptr, ptr %ptroffset, align 8
  indirectbr ptr %target, [label %switch.case, label %switch.default]

switch.case:                                      ; preds = %jumpblock
  call void @simple_jump.res(i32 1)
  br label %switch.exit

switch.default:                                   ; preds = %jumpblock, %switch.entry
  call void @simple_jump.res(i32 -1)
  br label %switch.exit

switch.exit:                                      ; preds = %switch.default, %switch.case
  ret void
}

define void @simple_jump.test5(i32 %0) #0 {
entry:
  %switch = alloca i32, align 4
  store i32 %0, ptr %switch, align 4
  br label %switch.entry

switch.entry:                                     ; preds = %entry
  %1 = load i32, ptr %switch, align 4
  %2 = sub i32 %1, 1
  %3 = icmp ugt i32 %2, 3
  br i1 %3, label %switch.default, label %jumpblock

jumpblock:                                        ; preds = %switch.entry
  %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.4, i32 %2
  %target = load ptr, ptr %ptroffset, align 8
  indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.default, label %switch.default]

switch.case:                                      ; preds = %jumpblock
  call void @simple_jump.res(i32 1)
  br label %switch.exit

switch.case1:                                     ; preds = %jumpblock
  call void @simple_jump.res(i32 4)
  br label %switch.exit

switch.default:                                   ; preds = %jumpblock, %jumpblock, %switch.entry
  call void @simple_jump.res(i32 -1)
  br label %switch.exit

switch.exit:                                      ; preds = %switch.default, %switch.case1, %switch.case
  ret void
}

; Function Attrs: nounwind uwtable
define void @simple_jump.test6(i32 %0) #0 {
entry:
  %switch = alloca i32, align 4
  store i32 %0, ptr %switch, align 4
  br label %switch.entry

switch.entry:                                     ; preds = %entry
  %1 = load i32, ptr %switch, align 4
  %2 = sub i32 %1, 1
  %3 = icmp ugt i32 %2, 4
  br i1 %3, label %switch.default, label %jumpblock

jumpblock:                                        ; preds = %switch.entry
  %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.5, i32 %2
  %target = load ptr, ptr %ptroffset, align 8
  indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.case2, label %switch.default, label %switch.default]

switch.case:                                      ; preds = %jumpblock, %jumpblock3
  call void @simple_jump.res(i32 1)
  br label %switch.exit

switch.case1:                                     ; preds = %jumpblock, %jumpblock3
  call void @simple_jump.res(i32 4)
  br label %switch.exit

switch.case2:                                     ; preds = %jumpblock, %jumpblock3
  %mul = mul i32 %0, 2
  %4 = sub i32 %mul, 1
  %5 = icmp ugt i32 %4, 4
  br i1 %5, label %switch.default, label %jumpblock3

jumpblock3:                                       ; preds = %switch.case2
  %ptroffset4 = getelementptr inbounds [8 x i8], ptr @jumptable.5, i32 %4
  %target5 = load ptr, ptr %ptroffset4, align 8
  indirectbr ptr %target5, [label %switch.case, label %switch.case1, label %switch.case2, label %switch.default]

switch.default:                                   ; preds = %jumpblock, %jumpblock, %jumpblock3, %switch.case2, %switch.entry
  call void @simple_jump.res(i32 -1)
  br label %switch.exit

switch.exit:                                      ; preds = %switch.default, %switch.case1, %switch.case
  ret void
}