1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s 3 4define i32 @test_unreachable_default(i32 noundef %num) { 5; CHECK-LABEL: define i32 @test_unreachable_default( 6; CHECK-SAME: i32 noundef [[NUM:%.*]]) { 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 9; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 10; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 11; CHECK-NEXT: switch i32 [[COND]], label [[DEFAULT_UNREACHABLE:%.*]] [ 12; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] 13; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] 14; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] 15; CHECK-NEXT: ] 16; CHECK: sw.bb: 17; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() 18; CHECK-NEXT: br label [[CLEANUP:%.*]] 19; CHECK: sw.bb2: 20; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() 21; CHECK-NEXT: br label [[CLEANUP]] 22; CHECK: sw.bb4: 23; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() 24; CHECK-NEXT: br label [[CLEANUP]] 25; CHECK: default.unreachable: 26; CHECK-NEXT: unreachable 27; CHECK: sw.default: 28; CHECK-NEXT: [[CALL6:%.*]] = call i32 @call3() 29; CHECK-NEXT: br label [[CLEANUP]] 30; CHECK: cleanup: 31; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT:%.*]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] 32; CHECK-NEXT: ret i32 [[RETVAL_0]] 33; 34entry: 35 %sub = add i32 %num, -120 36 %cmp = icmp ult i32 %sub, 3 37 %cond = select i1 %cmp, i32 %sub, i32 2 38 switch i32 %cond, label %sw.default [ 39 i32 0, label %sw.bb 40 i32 1, label %sw.bb2 41 i32 2, label %sw.bb4 42 ] 43 44sw.bb: 45 %call = call i32 @call0() 46 br label %cleanup 47 48sw.bb2: 49 %call3 = call i32 @call1() 50 br label %cleanup 51 52sw.bb4: 53 %call5 = call i32 @call2() 54 br label %cleanup 55 56sw.default: 57 %call6 = call i32 @call3() 58 br label %cleanup 59 60cleanup: 61 %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] 62 ret i32 %retval.0 63} 64 65define i32 @test_unreachable_default_shared_edge(i32 noundef %num) { 66; CHECK-LABEL: define i32 @test_unreachable_default_shared_edge( 67; CHECK-SAME: i32 noundef [[NUM:%.*]]) { 68; CHECK-NEXT: entry: 69; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 70; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 71; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 72; CHECK-NEXT: switch i32 [[COND]], label [[DEFAULT_UNREACHABLE:%.*]] [ 73; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] 74; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] 75; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] 76; CHECK-NEXT: ] 77; CHECK: sw.bb: 78; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() 79; CHECK-NEXT: br label [[CLEANUP:%.*]] 80; CHECK: sw.bb2: 81; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() 82; CHECK-NEXT: br label [[CLEANUP]] 83; CHECK: default.unreachable: 84; CHECK-NEXT: unreachable 85; CHECK: sw.bb4: 86; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call4(i32 [[SUB]]) 87; CHECK-NEXT: br label [[CLEANUP]] 88; CHECK: cleanup: 89; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] 90; CHECK-NEXT: ret i32 [[RETVAL_0]] 91; 92entry: 93 %sub = add i32 %num, -120 94 %cmp = icmp ult i32 %sub, 3 95 %cond = select i1 %cmp, i32 %sub, i32 2 96 switch i32 %cond, label %sw.bb4 [ 97 i32 0, label %sw.bb 98 i32 1, label %sw.bb2 99 i32 2, label %sw.bb4 100 ] 101 102sw.bb: 103 %call = call i32 @call0() 104 br label %cleanup 105 106sw.bb2: 107 %call3 = call i32 @call1() 108 br label %cleanup 109 110sw.bb4: 111 %val = phi i32 [ %sub, %entry ], [ %sub, %entry ] 112 %call5 = call i32 @call4(i32 %val) 113 br label %cleanup 114 115cleanup: 116 %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] 117 ret i32 %retval.0 118} 119 120; Negative tests 121 122define i32 @test_reachable_default(i32 noundef %num) { 123; CHECK-LABEL: define i32 @test_reachable_default( 124; CHECK-SAME: i32 noundef [[NUM:%.*]]) { 125; CHECK-NEXT: entry: 126; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 127; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 128; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 4 129; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ 130; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] 131; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] 132; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] 133; CHECK-NEXT: ] 134; CHECK: sw.bb: 135; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() 136; CHECK-NEXT: br label [[CLEANUP:%.*]] 137; CHECK: sw.bb2: 138; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() 139; CHECK-NEXT: br label [[CLEANUP]] 140; CHECK: sw.bb4: 141; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() 142; CHECK-NEXT: br label [[CLEANUP]] 143; CHECK: sw.default: 144; CHECK-NEXT: [[CALL6:%.*]] = call i32 @call3() 145; CHECK-NEXT: br label [[CLEANUP]] 146; CHECK: cleanup: 147; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] 148; CHECK-NEXT: ret i32 [[RETVAL_0]] 149; 150entry: 151 %sub = add i32 %num, -120 152 %cmp = icmp ult i32 %sub, 3 153 %cond = select i1 %cmp, i32 %sub, i32 4 154 switch i32 %cond, label %sw.default [ 155 i32 0, label %sw.bb 156 i32 1, label %sw.bb2 157 i32 2, label %sw.bb4 158 ] 159 160sw.bb: 161 %call = call i32 @call0() 162 br label %cleanup 163 164sw.bb2: 165 %call3 = call i32 @call1() 166 br label %cleanup 167 168sw.bb4: 169 %call5 = call i32 @call2() 170 br label %cleanup 171 172sw.default: 173 %call6 = call i32 @call3() 174 br label %cleanup 175 176cleanup: 177 %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] 178 ret i32 %retval.0 179} 180 181define i32 @test_unreachable_default_cond_may_be_undef(i32 %num) { 182; CHECK-LABEL: define i32 @test_unreachable_default_cond_may_be_undef( 183; CHECK-SAME: i32 [[NUM:%.*]]) { 184; CHECK-NEXT: entry: 185; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 186; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 187; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 188; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ 189; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] 190; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] 191; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] 192; CHECK-NEXT: ] 193; CHECK: sw.bb: 194; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() 195; CHECK-NEXT: br label [[CLEANUP:%.*]] 196; CHECK: sw.bb2: 197; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() 198; CHECK-NEXT: br label [[CLEANUP]] 199; CHECK: sw.bb4: 200; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() 201; CHECK-NEXT: br label [[CLEANUP]] 202; CHECK: sw.default: 203; CHECK-NEXT: [[CALL6:%.*]] = call i32 @call3() 204; CHECK-NEXT: br label [[CLEANUP]] 205; CHECK: cleanup: 206; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] 207; CHECK-NEXT: ret i32 [[RETVAL_0]] 208; 209entry: 210 %sub = add i32 %num, -120 211 %cmp = icmp ult i32 %sub, 3 212 %cond = select i1 %cmp, i32 %sub, i32 2 213 switch i32 %cond, label %sw.default [ 214 i32 0, label %sw.bb 215 i32 1, label %sw.bb2 216 i32 2, label %sw.bb4 217 ] 218 219sw.bb: 220 %call = call i32 @call0() 221 br label %cleanup 222 223sw.bb2: 224 %call3 = call i32 @call1() 225 br label %cleanup 226 227sw.bb4: 228 %call5 = call i32 @call2() 229 br label %cleanup 230 231sw.default: 232 %call6 = call i32 @call3() 233 br label %cleanup 234 235cleanup: 236 %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] 237 ret i32 %retval.0 238} 239 240define i32 @test_default_is_already_unreachable(i32 %num) { 241; CHECK-LABEL: define i32 @test_default_is_already_unreachable( 242; CHECK-SAME: i32 [[NUM:%.*]]) { 243; CHECK-NEXT: entry: 244; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 245; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 246; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 247; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ 248; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] 249; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] 250; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] 251; CHECK-NEXT: ] 252; CHECK: sw.bb: 253; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() 254; CHECK-NEXT: br label [[CLEANUP:%.*]] 255; CHECK: sw.bb2: 256; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() 257; CHECK-NEXT: br label [[CLEANUP]] 258; CHECK: sw.bb4: 259; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() 260; CHECK-NEXT: br label [[CLEANUP]] 261; CHECK: sw.default: 262; CHECK-NEXT: unreachable 263; CHECK: cleanup: 264; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] 265; CHECK-NEXT: ret i32 [[RETVAL_0]] 266; 267entry: 268 %sub = add i32 %num, -120 269 %cmp = icmp ult i32 %sub, 3 270 %cond = select i1 %cmp, i32 %sub, i32 2 271 switch i32 %cond, label %sw.default [ 272 i32 0, label %sw.bb 273 i32 1, label %sw.bb2 274 i32 2, label %sw.bb4 275 ] 276 277sw.bb: 278 %call = call i32 @call0() 279 br label %cleanup 280 281sw.bb2: 282 %call3 = call i32 @call1() 283 br label %cleanup 284 285sw.bb4: 286 %call5 = call i32 @call2() 287 br label %cleanup 288 289sw.default: 290 unreachable 291 292cleanup: 293 %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] 294 ret i32 %retval.0 295} 296 297declare i32 @call0() 298declare i32 @call1() 299declare i32 @call2() 300declare i32 @call3() 301declare i32 @call4(i32) 302