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