1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare void @may_unwind() 5 6define i1 @test_switch_in_block_with_assume(i8 %x) { 7; CHECK-LABEL: @test_switch_in_block_with_assume( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: call void @may_unwind() 10; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[X:%.*]], 10 11; CHECK-NEXT: call void @llvm.assume(i1 [[C_1]]) 12; CHECK-NEXT: switch i8 0, label [[EXIT_1:%.*]] [ 13; CHECK-NEXT: i8 1, label [[EXIT_2:%.*]] 14; CHECK-NEXT: ] 15; CHECK: exit.1: 16; CHECK-NEXT: [[C_2:%.*]] = icmp ult i8 [[X]], 9 17; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[C_2]] 18; CHECK-NEXT: ret i1 [[RES_1]] 19; CHECK: exit.2: 20; CHECK-NEXT: [[C_3:%.*]] = icmp ult i8 [[X]], 9 21; CHECK-NEXT: [[RES_2:%.*]] = xor i1 true, [[C_3]] 22; CHECK-NEXT: ret i1 [[RES_2]] 23; 24entry: 25 call void @may_unwind() 26 %c.1 = icmp ult i8 %x, 10 27 call void @llvm.assume(i1 %c.1) 28 switch i8 0, label %exit.1 [ 29 i8 1, label %exit.2 30 ] 31 32exit.1: 33 %t.1 = icmp ult i8 %x, 10 34 %c.2 = icmp ult i8 %x, 9 35 %res.1 = xor i1 %t.1, %c.2 36 ret i1 %res.1 37 38exit.2: 39 %t.2 = icmp ult i8 %x, 10 40 %c.3 = icmp ult i8 %x, 9 41 %res.2 = xor i1 %t.2, %c.3 42 ret i1 %res.2 43} 44 45declare void @llvm.assume(i1) 46 47define i1 @simplify_based_on_switch(i8 %x) { 48; CHECK-LABEL: @simplify_based_on_switch( 49; CHECK-NEXT: entry: 50; CHECK-NEXT: switch i8 [[X:%.*]], label [[EXIT_1:%.*]] [ 51; CHECK-NEXT: i8 6, label [[EXIT_2:%.*]] 52; CHECK-NEXT: i8 10, label [[EXIT_3:%.*]] 53; CHECK-NEXT: ] 54; CHECK: exit.1: 55; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[X]], 7 56; CHECK-NEXT: [[C_2:%.*]] = icmp ult i8 [[X]], 6 57; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]] 58; CHECK-NEXT: ret i1 [[RES_1]] 59; CHECK: exit.2: 60; CHECK-NEXT: [[RES_2:%.*]] = xor i1 true, false 61; CHECK-NEXT: ret i1 [[RES_2]] 62; CHECK: exit.3: 63; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, false 64; CHECK-NEXT: ret i1 [[RES_3]] 65; 66entry: 67 switch i8 %x, label %exit.1 [ 68 i8 6, label %exit.2 69 i8 10, label %exit.3 70 ] 71 72exit.1: 73 %c.1 = icmp ult i8 %x, 7 74 %c.2 = icmp ult i8 %x, 6 75 %res.1 = xor i1 %c.1, %c.2 76 ret i1 %res.1 77 78exit.2: 79 %t.1 = icmp ult i8 %x, 7 80 %f.1 = icmp ult i8 %x, 6 81 %res.2 = xor i1 %t.1, %f.1 82 ret i1 %res.2 83 84exit.3: 85 %t.2 = icmp ult i8 %x, 11 86 %f.2 = icmp ult i8 %x, 10 87 %res.3 = xor i1 %t.2, %f.2 88 ret i1 %res.3 89} 90 91define i1 @simplify_based_on_switch_successor_branches(i8 %x) { 92; CHECK-LABEL: @simplify_based_on_switch_successor_branches( 93; CHECK-NEXT: entry: 94; CHECK-NEXT: switch i8 [[X:%.*]], label [[EXIT_1:%.*]] [ 95; CHECK-NEXT: i8 6, label [[EXIT_2:%.*]] 96; CHECK-NEXT: i8 10, label [[EXIT_3:%.*]] 97; CHECK-NEXT: ] 98; CHECK: exit.1: 99; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[X]], 7 100; CHECK-NEXT: [[C_2:%.*]] = icmp ult i8 [[X]], 6 101; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]] 102; CHECK-NEXT: ret i1 [[RES_1]] 103; CHECK: exit.2: 104; CHECK-NEXT: [[RES_2:%.*]] = xor i1 true, false 105; CHECK-NEXT: call void @use(i1 [[RES_2]]) 106; CHECK-NEXT: br label [[EXIT_3]] 107; CHECK: exit.3: 108; CHECK-NEXT: [[C_3:%.*]] = icmp ult i8 [[X]], 11 109; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8 [[X]], 10 110; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[C_3]], [[C_4]] 111; CHECK-NEXT: ret i1 [[RES_3]] 112; 113entry: 114 switch i8 %x, label %exit.1 [ 115 i8 6, label %exit.2 116 i8 10, label %exit.3 117 ] 118 119exit.1: 120 %c.1 = icmp ult i8 %x, 7 121 %c.2 = icmp ult i8 %x, 6 122 %res.1 = xor i1 %c.1, %c.2 123 ret i1 %res.1 124 125exit.2: 126 %t.1 = icmp ult i8 %x, 7 127 %f.1 = icmp ult i8 %x, 6 128 %res.2 = xor i1 %t.1, %f.1 129 call void @use(i1 %res.2) 130 br label %exit.3 131 132exit.3: 133 %c.3 = icmp ult i8 %x, 11 134 %c.4 = icmp ult i8 %x, 10 135 %res.3 = xor i1 %c.3, %c.4 136 ret i1 %res.3 137} 138 139define i1 @switch_same_destination_for_different_cases(i8 %x) { 140; CHECK-LABEL: @switch_same_destination_for_different_cases( 141; CHECK-NEXT: entry: 142; CHECK-NEXT: switch i8 [[X:%.*]], label [[EXIT_1:%.*]] [ 143; CHECK-NEXT: i8 6, label [[EXIT_2:%.*]] 144; CHECK-NEXT: i8 10, label [[EXIT_2]] 145; CHECK-NEXT: ] 146; CHECK: exit.1: 147; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[X]], 7 148; CHECK-NEXT: [[C_2:%.*]] = icmp ult i8 [[X]], 6 149; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]] 150; CHECK-NEXT: ret i1 [[RES_1]] 151; CHECK: exit.2: 152; CHECK-NEXT: [[C_3:%.*]] = icmp ult i8 [[X]], 7 153; CHECK-NEXT: call void @use(i1 [[C_3]]) 154; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8 [[X]], 6 155; CHECK-NEXT: call void @use(i1 [[C_4]]) 156; CHECK-NEXT: [[C_5:%.*]] = icmp ult i8 [[X]], 11 157; CHECK-NEXT: call void @use(i1 [[C_5]]) 158; CHECK-NEXT: [[C_6:%.*]] = icmp ult i8 [[X]], 10 159; CHECK-NEXT: ret i1 [[C_6]] 160; 161entry: 162 switch i8 %x, label %exit.1 [ 163 i8 6, label %exit.2 164 i8 10, label %exit.2 165 ] 166 167exit.1: 168 %c.1 = icmp ult i8 %x, 7 169 %c.2 = icmp ult i8 %x, 6 170 %res.1 = xor i1 %c.1, %c.2 171 ret i1 %res.1 172 173exit.2: 174 %c.3 = icmp ult i8 %x, 7 175 call void @use(i1 %c.3) 176 %c.4 = icmp ult i8 %x, 6 177 call void @use(i1 %c.4) 178 %c.5 = icmp ult i8 %x, 11 179 call void @use(i1 %c.5) 180 %c.6 = icmp ult i8 %x, 10 181 ret i1 %c.6 182} 183 184declare void @use(i1) 185