1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt %s -S -passes='simplify-cfg<switch-to-lookup>' | FileCheck %s 3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 4declare void @foo(i32) 5 6define void @test(i1 %a) { 7; CHECK-LABEL: @test( 8; CHECK-NEXT: [[A_OFF:%.*]] = add i1 [[A:%.*]], true 9; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i1 [[A_OFF]], true 10; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] 11; CHECK: true: 12; CHECK-NEXT: call void @foo(i32 1) 13; CHECK-NEXT: ret void 14; CHECK: false: 15; CHECK-NEXT: call void @foo(i32 3) 16; CHECK-NEXT: ret void 17; 18 switch i1 %a, label %default [i1 1, label %true 19 i1 0, label %false] 20true: 21 call void @foo(i32 1) 22 ret void 23false: 24 call void @foo(i32 3) 25 ret void 26default: 27 call void @foo(i32 2) 28 ret void 29} 30 31define void @test2(i2 %a) { 32; CHECK-LABEL: @test2( 33; CHECK-NEXT: switch i2 [[A:%.*]], label [[DEFAULT1:%.*]] [ 34; CHECK-NEXT: i2 0, label [[CASE0:%.*]] 35; CHECK-NEXT: i2 1, label [[CASE1:%.*]] 36; CHECK-NEXT: i2 -2, label [[CASE2:%.*]] 37; CHECK-NEXT: i2 -1, label [[CASE3:%.*]] 38; CHECK-NEXT: ] 39; CHECK: case0: 40; CHECK-NEXT: call void @foo(i32 0) 41; CHECK-NEXT: ret void 42; CHECK: case1: 43; CHECK-NEXT: call void @foo(i32 1) 44; CHECK-NEXT: ret void 45; CHECK: case2: 46; CHECK-NEXT: call void @foo(i32 2) 47; CHECK-NEXT: ret void 48; CHECK: case3: 49; CHECK-NEXT: call void @foo(i32 3) 50; CHECK-NEXT: ret void 51; CHECK: default1: 52; CHECK-NEXT: unreachable 53; 54 switch i2 %a, label %default [i2 0, label %case0 55 i2 1, label %case1 56 i2 2, label %case2 57 i2 3, label %case3] 58case0: 59 call void @foo(i32 0) 60 ret void 61case1: 62 call void @foo(i32 1) 63 ret void 64case2: 65 call void @foo(i32 2) 66 ret void 67case3: 68 call void @foo(i32 3) 69 ret void 70default: 71 call void @foo(i32 4) 72 ret void 73} 74 75; This one is a negative test - we know the value of the default, 76; but that's about it 77define void @test3(i2 %a) { 78; CHECK-LABEL: @test3( 79; CHECK-NEXT: switch i2 [[A:%.*]], label [[DEFAULT:%.*]] [ 80; CHECK-NEXT: i2 0, label [[CASE0:%.*]] 81; CHECK-NEXT: i2 1, label [[CASE1:%.*]] 82; CHECK-NEXT: i2 -2, label [[CASE2:%.*]] 83; CHECK-NEXT: ] 84; CHECK: case0: 85; CHECK-NEXT: call void @foo(i32 0) 86; CHECK-NEXT: ret void 87; CHECK: case1: 88; CHECK-NEXT: call void @foo(i32 1) 89; CHECK-NEXT: ret void 90; CHECK: case2: 91; CHECK-NEXT: call void @foo(i32 2) 92; CHECK-NEXT: ret void 93; CHECK: default: 94; CHECK-NEXT: call void @foo(i32 3) 95; CHECK-NEXT: ret void 96; 97 switch i2 %a, label %default [i2 0, label %case0 98 i2 1, label %case1 99 i2 2, label %case2] 100 101case0: 102 call void @foo(i32 0) 103 ret void 104case1: 105 call void @foo(i32 1) 106 ret void 107case2: 108 call void @foo(i32 2) 109 ret void 110default: 111 call void @foo(i32 3) 112 ret void 113} 114 115; Negative test - check for possible overflow when computing 116; number of possible cases. 117define void @test4(i128 %a) { 118; CHECK-LABEL: @test4( 119; CHECK-NEXT: switch i128 [[A:%.*]], label [[DEFAULT:%.*]] [ 120; CHECK-NEXT: i128 0, label [[CASE0:%.*]] 121; CHECK-NEXT: i128 1, label [[CASE1:%.*]] 122; CHECK-NEXT: ] 123; CHECK: case0: 124; CHECK-NEXT: call void @foo(i32 0) 125; CHECK-NEXT: ret void 126; CHECK: case1: 127; CHECK-NEXT: call void @foo(i32 1) 128; CHECK-NEXT: ret void 129; CHECK: default: 130; CHECK-NEXT: call void @foo(i32 2) 131; CHECK-NEXT: ret void 132; 133 switch i128 %a, label %default [i128 0, label %case0 134 i128 1, label %case1] 135 136case0: 137 call void @foo(i32 0) 138 ret void 139case1: 140 call void @foo(i32 1) 141 ret void 142default: 143 call void @foo(i32 2) 144 ret void 145} 146 147; All but one bit known zero 148define void @test5(i8 %a) { 149; CHECK-LABEL: @test5( 150; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[A:%.*]], 2 151; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 152; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], -1 153; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 154; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] 155; CHECK: true: 156; CHECK-NEXT: call void @foo(i32 1) 157; CHECK-NEXT: ret void 158; CHECK: false: 159; CHECK-NEXT: call void @foo(i32 3) 160; CHECK-NEXT: ret void 161; 162 %cmp = icmp ult i8 %a, 2 163 call void @llvm.assume(i1 %cmp) 164 switch i8 %a, label %default [i8 1, label %true 165 i8 0, label %false] 166true: 167 call void @foo(i32 1) 168 ret void 169false: 170 call void @foo(i32 3) 171 ret void 172default: 173 call void @foo(i32 2) 174 ret void 175} 176 177;; All but one bit known one 178define void @test6(i8 %a) { 179; CHECK-LABEL: @test6( 180; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], -2 181; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], -2 182; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 183; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], 1 184; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 185; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] 186; CHECK: true: 187; CHECK-NEXT: call void @foo(i32 1) 188; CHECK-NEXT: ret void 189; CHECK: false: 190; CHECK-NEXT: call void @foo(i32 3) 191; CHECK-NEXT: ret void 192; 193 %and = and i8 %a, 254 194 %cmp = icmp eq i8 %and, 254 195 call void @llvm.assume(i1 %cmp) 196 switch i8 %a, label %default [i8 255, label %true 197 i8 254, label %false] 198true: 199 call void @foo(i32 1) 200 ret void 201false: 202 call void @foo(i32 3) 203 ret void 204default: 205 call void @foo(i32 2) 206 ret void 207} 208 209; Check that we can eliminate both dead cases and dead defaults 210; within a single run of simplify-cfg 211define void @test7(i8 %a) { 212; CHECK-LABEL: @test7( 213; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], -2 214; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], -2 215; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 216; CHECK-NEXT: [[A_OFF:%.*]] = add i8 [[A]], 1 217; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1 218; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] 219; CHECK: true: 220; CHECK-NEXT: call void @foo(i32 1) 221; CHECK-NEXT: ret void 222; CHECK: false: 223; CHECK-NEXT: call void @foo(i32 3) 224; CHECK-NEXT: ret void 225; 226 %and = and i8 %a, 254 227 %cmp = icmp eq i8 %and, 254 228 call void @llvm.assume(i1 %cmp) 229 switch i8 %a, label %default [i8 255, label %true 230 i8 254, label %false 231 i8 0, label %also_dead] 232true: 233 call void @foo(i32 1) 234 ret void 235false: 236 call void @foo(i32 3) 237 ret void 238also_dead: 239 call void @foo(i32 5) 240 ret void 241default: 242 call void @foo(i32 2) 243 ret void 244} 245 246declare void @llvm.assume(i1) 247 248