--emit=llvm-ir
I can't be bothered to clean unoptimized LLVM IR up, sorry
define { i32, i32 } @change_value1(i32 %0, i32 %1) unnamed_addr #0 !dbg !6 {
start:
%2 = alloca { i32, i32 }, align 4
%val = alloca { i32, i32 }, align 4
%3 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 0
store i32 %0, ptr %3, align 4
%4 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 1
store i32 %1, ptr %4, align 4
%5 = load i32, ptr %val, align 4, !dbg !11, !range !13, !noundef !10
%_2 = zext i32 %5 to i64, !dbg !11
%6 = icmp eq i64 %_2, 0, !dbg !11
br i1 %6, label %bb1, label %bb3, !dbg !11
bb1: ; preds = %start
%7 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 1, !dbg !14
%x = load i32, ptr %7, align 4, !dbg !14, !noundef !10
%8 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 2), !dbg !15
%_5.0 = extractvalue { i32, i1 } %8, 0, !dbg !15
%_5.1 = extractvalue { i32, i1 } %8, 1, !dbg !15
%9 = call i1 @llvm.expect.i1(i1 %_5.1, i1 false), !dbg !15
br i1 %9, label %panic, label %bb2, !dbg !15
bb3: ; preds = %start
store i32 1, ptr %2, align 4, !dbg !16
br label %bb4, !dbg !17
bb4: ; preds = %bb2, %bb3
%10 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 0, !dbg !18
%11 = load i32, ptr %10, align 4, !dbg !18, !range !13, !noundef !10
%12 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 1, !dbg !18
%13 = load i32, ptr %12, align 4, !dbg !18
%14 = insertvalue { i32, i32 } poison, i32 %11, 0, !dbg !18
%15 = insertvalue { i32, i32 } %14, i32 %13, 1, !dbg !18
ret { i32, i32 } %15, !dbg !18
bb2: ; preds = %bb1
%16 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 1, !dbg !19
store i32 %_5.0, ptr %16, align 4, !dbg !19
store i32 0, ptr %2, align 4, !dbg !19
br label %bb4, !dbg !17
panic: ; preds = %bb1
call void @_ZN4core9panicking5panic17h9fe598656394a2d2E(ptr align 1 @str.0, i64 33, ptr align 8 @alloc_be64bd1efd00f35dae1bd1422706659e) #4, !dbg !15
unreachable, !dbg !15
}
define { i32, i32 } @change_value2(i32 %0, i32 %1) unnamed_addr #0 !dbg !20 {
start:
%2 = alloca { i32, i32 }, align 4
%val = alloca { i32, i32 }, align 4
%3 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 0
store i32 %0, ptr %3, align 4
%4 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 1
store i32 %1, ptr %4, align 4
%5 = load i32, ptr %val, align 4, !dbg !21, !range !13, !noundef !10
%_2 = zext i32 %5 to i64, !dbg !21
%6 = icmp eq i64 %_2, 0, !dbg !22
br i1 %6, label %bb3, label %bb1, !dbg !22
bb3: ; preds = %start
%7 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 1, !dbg !23
%x = load i32, ptr %7, align 4, !dbg !23, !noundef !10
%8 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 2), !dbg !24
%_5.0 = extractvalue { i32, i1 } %8, 0, !dbg !24
%_5.1 = extractvalue { i32, i1 } %8, 1, !dbg !24
%9 = call i1 @llvm.expect.i1(i1 %_5.1, i1 false), !dbg !24
br i1 %9, label %panic, label %bb4, !dbg !24
bb1: ; preds = %start
store i32 1, ptr %2, align 4, !dbg !26
br label %bb5, !dbg !27
bb2: ; No predecessors!
unreachable, !dbg !21
bb5: ; preds = %bb4, %bb1
%10 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 0, !dbg !28
%11 = load i32, ptr %10, align 4, !dbg !28, !range !13, !noundef !10
%12 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 1, !dbg !28
%13 = load i32, ptr %12, align 4, !dbg !28
%14 = insertvalue { i32, i32 } poison, i32 %11, 0, !dbg !28
%15 = insertvalue { i32, i32 } %14, i32 %13, 1, !dbg !28
ret { i32, i32 } %15, !dbg !28
bb4: ; preds = %bb3
%16 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 1, !dbg !29
store i32 %_5.0, ptr %16, align 4, !dbg !29
store i32 0, ptr %2, align 4, !dbg !29
br label %bb5, !dbg !30
panic: ; preds = %bb3
call void @_ZN4core9panicking5panic17h9fe598656394a2d2E(ptr align 1 @str.0, i64 33, ptr align 8 @alloc_a2f1ab4ac39f1326c956f8b5fbb4e422) #4, !dbg !24
unreachable, !dbg !24
}
define { i32, i32 } @change_value3(i32 %0, i32 %1) unnamed_addr #0 !dbg !31 {
start:
%2 = alloca { i32, i32 }, align 4
%val = alloca { i32, i32 }, align 4
%3 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 0
store i32 %0, ptr %3, align 4
%4 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 1
store i32 %1, ptr %4, align 4
%5 = load i32, ptr %val, align 4, !dbg !32, !range !13, !noundef !10
%_2 = zext i32 %5 to i64, !dbg !32
%6 = icmp eq i64 %_2, 0, !dbg !33
br i1 %6, label %bb2, label %bb1, !dbg !33
bb2: ; preds = %start
%7 = getelementptr inbounds { i32, i32 }, ptr %val, i32 0, i32 1, !dbg !34
%x = load i32, ptr %7, align 4, !dbg !34, !noundef !10
%8 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 2), !dbg !35
%_5.0 = extractvalue { i32, i1 } %8, 0, !dbg !35
%_5.1 = extractvalue { i32, i1 } %8, 1, !dbg !35
%9 = call i1 @llvm.expect.i1(i1 %_5.1, i1 false), !dbg !35
br i1 %9, label %panic, label %bb3, !dbg !35
bb1: ; preds = %start
store i32 1, ptr %2, align 4, !dbg !37
br label %bb4, !dbg !38
bb4: ; preds = %bb3, %bb1
%10 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 0, !dbg !39
%11 = load i32, ptr %10, align 4, !dbg !39, !range !13, !noundef !10
%12 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 1, !dbg !39
%13 = load i32, ptr %12, align 4, !dbg !39
%14 = insertvalue { i32, i32 } poison, i32 %11, 0, !dbg !39
%15 = insertvalue { i32, i32 } %14, i32 %13, 1, !dbg !39
ret { i32, i32 } %15, !dbg !39
bb3: ; preds = %bb2
%16 = getelementptr inbounds { i32, i32 }, ptr %2, i32 0, i32 1, !dbg !40
store i32 %_5.0, ptr %16, align 4, !dbg !40
store i32 0, ptr %2, align 4, !dbg !40
br label %bb4, !dbg !41
panic: ; preds = %bb2
call void @_ZN4core9panicking5panic17h9fe598656394a2d2E(ptr align 1 @str.0, i64 33, ptr align 8 @alloc_0e586426b6f91c04bafde5cd1b168f27) #4, !dbg !35
unreachable, !dbg !35
}
define { i8, i32 } @change_value4(i1 zeroext %val.0, i32 %val.1) unnamed_addr #0 !dbg !42 {
start:
%0 = alloca i32, align 4
%_2.i = alloca i32, align 4
%1 = alloca i32, align 4
%2 = alloca { i8, i32 }, align 4
br i1 %val.0, label %bb1, label %bb3, !dbg !43
bb3: ; preds = %start
%3 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %val.1, i32 2), !dbg !44
%_8.0 = extractvalue { i32, i1 } %3, 0, !dbg !44
%_8.1 = extractvalue { i32, i1 } %3, 1, !dbg !44
%4 = call i1 @llvm.expect.i1(i1 %_8.1, i1 false), !dbg !44
br i1 %4, label %panic, label %bb5, !dbg !44
bb1: ; preds = %start
%5 = load i32, ptr %0, align 4, !dbg !45
store i8 1, ptr %2, align 4, !dbg !53
%6 = getelementptr inbounds { i8, i32 }, ptr %2, i32 0, i32 1, !dbg !53
store i32 %5, ptr %6, align 4, !dbg !53
br label %bb7, !dbg !54
bb7: ; preds = %bb5, %bb1
%7 = getelementptr inbounds { i8, i32 }, ptr %2, i32 0, i32 0, !dbg !55
%8 = load i8, ptr %7, align 4, !dbg !55, !range !56, !noundef !10
%9 = trunc i8 %8 to i1, !dbg !55
%10 = getelementptr inbounds { i8, i32 }, ptr %2, i32 0, i32 1, !dbg !55
%11 = load i32, ptr %10, align 4, !dbg !55
%12 = zext i1 %9 to i8, !dbg !55
%13 = insertvalue { i8, i32 } poison, i8 %12, 0, !dbg !55
%14 = insertvalue { i8, i32 } %13, i32 %11, 1, !dbg !55
ret { i8, i32 } %14, !dbg !55
bb5: ; preds = %bb3
store i32 %_8.0, ptr %_2.i, align 4, !dbg !57
%15 = load i32, ptr %_2.i, align 4, !dbg !65, !noundef !10
store i32 %15, ptr %1, align 4, !dbg !65
%16 = load i32, ptr %1, align 4, !dbg !66
store i8 0, ptr %2, align 4, !dbg !67
%17 = getelementptr inbounds { i8, i32 }, ptr %2, i32 0, i32 1, !dbg !67
store i32 %16, ptr %17, align 4, !dbg !67
br label %bb7, !dbg !54
panic: ; preds = %bb3
call void @_ZN4core9panicking5panic17h9fe598656394a2d2E(ptr align 1 @str.0, i64 33, ptr align 8 @alloc_73446bd2db1a380533fa7ccd1689a225) #4, !dbg !44
unreachable, !dbg !44
}
That patch is likely exactly what enabled this new optimization, since it extended some branch (two-arm switch) optimizations to (more-arm) switches. We want LLVM to know that the int switched over must be one of the taken arms (exactly what that patch was enabling).