; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s --check-prefixes=CHECK,DEFAULT_ITER ; RUN: opt -S -passes='instcombine' < %s | FileCheck %s --check-prefixes=CHECK,MAX1 declare void @dummy() declare void @llvm.assume(i1) define i32 @br_true(i1 %x) { ; CHECK-LABEL: define i32 @br_true ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 true, label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[JOIN:%.*]] ; CHECK: else: ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: ; CHECK-NEXT: ret i32 1 ; %c = or i1 %x, true br i1 %c, label %if, label %else if: call void @dummy() br label %join else: call void @dummy() br label %join join: %phi = phi i32 [ 1, %if ], [ 2, %else ] ret i32 %phi } define i32 @br_false(i1 %x) { ; CHECK-LABEL: define i32 @br_false ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 false, label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: ; CHECK-NEXT: br label [[JOIN:%.*]] ; CHECK: else: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: ; CHECK-NEXT: ret i32 2 ; %c = and i1 %x, false br i1 %c, label %if, label %else if: call void @dummy() br label %join else: call void @dummy() br label %join join: %phi = phi i32 [ 1, %if ], [ 2, %else ] ret i32 %phi } define i32 @br_undef(i1 %x) { ; CHECK-LABEL: define i32 @br_undef ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 undef, label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: ; CHECK-NEXT: br label [[JOIN:%.*]] ; CHECK: else: ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: ; CHECK-NEXT: ret i32 poison ; %c = xor i1 %x, undef br i1 %c, label %if, label %else if: call void @dummy() br label %join else: call void @dummy() br label %join join: %phi = phi i32 [ 1, %if ], [ 2, %else ] ret i32 %phi } define i32 @br_true_phi_with_repeated_preds(i1 %x) { ; CHECK-LABEL: define i32 @br_true_phi_with_repeated_preds ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 true, label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[JOIN:%.*]] ; CHECK: else: ; CHECK-NEXT: br i1 false, label [[JOIN]], label [[JOIN]] ; CHECK: join: ; CHECK-NEXT: ret i32 1 ; %c = or i1 %x, true br i1 %c, label %if, label %else if: call void @dummy() br label %join else: br i1 false, label %join, label %join join: %phi = phi i32 [ 1, %if ], [ 2, %else ], [ 2, %else ] ret i32 %phi } define i32 @br_true_const_phi_direct_edge(i1 %x) { ; CHECK-LABEL: define i32 @br_true_const_phi_direct_edge ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 true, label [[IF:%.*]], label [[JOIN:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: ; CHECK-NEXT: ret i32 2 ; entry: br i1 true, label %if, label %join if: call void @dummy() br label %join join: %phi = phi i32 [ 1, %entry ], [ 2, %if ] ret i32 %phi } define i32 @br_true_var_phi_direct_edge(i1 %x) { ; CHECK-LABEL: define i32 @br_true_var_phi_direct_edge ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 true, label [[IF:%.*]], label [[JOIN:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: ; CHECK-NEXT: ret i32 2 ; entry: %c = or i1 %x, true br i1 %c, label %if, label %join if: call void @dummy() br label %join join: %phi = phi i32 [ 1, %entry ], [ 2, %if ] ret i32 %phi } define void @switch_case(i32 %x) { ; CHECK-LABEL: define void @switch_case ; CHECK-SAME: (i32 [[X:%.*]]) { ; CHECK-NEXT: switch i32 0, label [[DEFAULT:%.*]] [ ; CHECK-NEXT: i32 0, label [[CASE0:%.*]] ; CHECK-NEXT: ] ; CHECK: case0: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; CHECK: default: ; CHECK-NEXT: ret void ; %v = and i32 %x, 0 switch i32 %v, label %default [ i32 0, label %case0 ] case0: call void @dummy() ret void default: call void @dummy() ret void } define void @switch_default(i32 %x) { ; CHECK-LABEL: define void @switch_default ; CHECK-SAME: (i32 [[X:%.*]]) { ; CHECK-NEXT: switch i32 -1, label [[DEFAULT:%.*]] [ ; CHECK-NEXT: i32 0, label [[CASE0:%.*]] ; CHECK-NEXT: ] ; CHECK: case0: ; CHECK-NEXT: ret void ; CHECK: default: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; %v = or i32 %x, -1 switch i32 %v, label %default [ i32 0, label %case0 ] case0: call void @dummy() ret void default: call void @dummy() ret void } define void @switch_undef(i32 %x) { ; CHECK-LABEL: define void @switch_undef ; CHECK-SAME: (i32 [[X:%.*]]) { ; CHECK-NEXT: switch i32 undef, label [[DEFAULT:%.*]] [ ; CHECK-NEXT: i32 0, label [[CASE0:%.*]] ; CHECK-NEXT: ] ; CHECK: case0: ; CHECK-NEXT: ret void ; CHECK: default: ; CHECK-NEXT: ret void ; %v = xor i32 %x, undef switch i32 %v, label %default [ i32 0, label %case0 ] case0: call void @dummy() ret void default: call void @dummy() ret void } define void @non_term_unreachable() { ; CHECK-LABEL: define void @non_term_unreachable() { ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: ret void ; call void @dummy() call void @dummy() nounwind willreturn store i1 true, ptr poison call void @dummy() ret void } define i32 @non_term_unreachable_phi(i1 %c) { ; CHECK-LABEL: define i32 @non_term_unreachable_phi ; CHECK-SAME: (i1 [[C:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]] ; CHECK: if: ; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: ; CHECK-NEXT: ret i32 2 ; entry: br i1 %c, label %if, label %join if: store i1 true, ptr poison call void @dummy() br label %join join: %phi = phi i32 [ 1, %if], [ 2, %entry ] ret i32 %phi } define void @non_term_unreachable_following_blocks() { ; CHECK-LABEL: define void @non_term_unreachable_following_blocks() { ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: br label [[SPLIT:%.*]] ; CHECK: split: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: br label [[LOOP]] ; call void @dummy() store i1 true, ptr poison call void @dummy() br label %split split: call void @dummy() br label %loop loop: call void @dummy() br label %loop } define void @br_not_into_loop(i1 %x) { ; CHECK-LABEL: define void @br_not_into_loop ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; %c = or i1 %x, true br i1 %c, label %exit, label %loop loop: call void @dummy() br label %loop exit: call void @dummy() ret void } define void @br_into_loop(i1 %x) { ; CHECK-LABEL: define void @br_into_loop ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 true, label [[LOOP:%.*]], label [[EXIT:%.*]] ; CHECK: loop: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: ret void ; %c = or i1 %x, true br i1 %c, label %loop, label %exit loop: call void @dummy() br label %loop exit: call void @dummy() ret void } define void @two_br_not_into_loop(i1 %x) { ; CHECK-LABEL: define void @two_br_not_into_loop ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[LOOP:%.*]] ; CHECK: bb2: ; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]] ; CHECK: loop: ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; %c = or i1 %x, true br i1 %c, label %bb2, label %loop bb2: %c2 = or i1 %x, true br i1 %c2, label %exit, label %loop loop: call void @dummy() br label %loop exit: call void @dummy() ret void } define void @one_br_into_loop_one_not(i1 %x, i1 %c2) { ; CHECK-LABEL: define void @one_br_into_loop_one_not ; CHECK-SAME: (i1 [[X:%.*]], i1 [[C2:%.*]]) { ; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[LOOP:%.*]] ; CHECK: bb2: ; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[LOOP]] ; CHECK: loop: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; %c = or i1 %x, true br i1 %c, label %bb2, label %loop bb2: br i1 %c2, label %exit, label %loop loop: call void @dummy() br label %loop exit: call void @dummy() ret void } define void @two_br_not_into_loop_with_split(i1 %x) { ; CHECK-LABEL: define void @two_br_not_into_loop_with_split ; CHECK-SAME: (i1 [[X:%.*]]) { ; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[SPLIT1:%.*]] ; CHECK: bb2: ; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SPLIT2:%.*]] ; CHECK: split1: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: split2: ; CHECK-NEXT: br label [[LOOP]] ; CHECK: loop: ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; %c = or i1 %x, true br i1 %c, label %bb2, label %split1 bb2: %c2 = or i1 %x, true br i1 %c2, label %exit, label %split2 split1: call void @dummy() br label %loop split2: call void @dummy() br label %loop loop: call void @dummy() br label %loop exit: call void @dummy() ret void } define void @irreducible() { ; CHECK-LABEL: define void @irreducible() { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 false, label [[LOOP2:%.*]], label [[LOOP1:%.*]] ; CHECK: loop1: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br label [[LOOP2]] ; CHECK: loop2: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP1]] ; CHECK: exit: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; entry: br i1 false, label %loop2, label %loop1 loop1: call void @dummy() br label %loop2 loop2: call void @dummy() br i1 true, label %exit, label %loop1 exit: call void @dummy() ret void } define void @really_unreachable() { ; CHECK-LABEL: define void @really_unreachable() { ; CHECK-NEXT: entry: ; CHECK-NEXT: ret void ; CHECK: unreachable: ; CHECK-NEXT: ret void ; entry: ret void unreachable: call void @dummy() ret void } define void @really_unreachable_predecessor() { ; CHECK-LABEL: define void @really_unreachable_predecessor() { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 false, label [[BB:%.*]], label [[EXIT:%.*]] ; CHECK: unreachable: ; CHECK-NEXT: br label [[BB]] ; CHECK: bb: ; CHECK-NEXT: ret void ; CHECK: exit: ; CHECK-NEXT: call void @dummy() ; CHECK-NEXT: ret void ; entry: br i1 false, label %bb, label %exit unreachable: call void @dummy() br label %bb bb: call void @dummy() ret void exit: call void @dummy() ret void } define i32 @pr64235() { ; CHECK-LABEL: define i32 @pr64235() { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 false, label [[BB:%.*]], label [[BB3:%.*]] ; CHECK: bb3: ; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: br label [[BB2:%.*]] ; CHECK: bb: ; CHECK-NEXT: br label [[BB2]] ; CHECK: bb2: ; CHECK-NEXT: br label [[BB]] ; entry: br i1 false, label %bb, label %bb3 bb3: call void @llvm.assume(i1 false) br label %bb2 bb: br label %bb2 bb2: call void @llvm.assume(i1 false) br label %bb } ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; DEFAULT_ITER: {{.*}} ; MAX1: {{.*}}