338 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 42; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s3 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]], -1209; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 310; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 211; 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: unreachable27; 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, -12036 %cmp = icmp ult i32 %sub, 337 %cond = select i1 %cmp, i32 %sub, i32 238 switch i32 %cond, label %sw.default [39 i32 0, label %sw.bb40 i32 1, label %sw.bb241 i32 2, label %sw.bb442 ]43 44sw.bb:45 %call = call i32 @call0()46 br label %cleanup47 48sw.bb2:49 %call3 = call i32 @call1()50 br label %cleanup51 52sw.bb4:53 %call5 = call i32 @call2()54 br label %cleanup55 56sw.default:57 %call6 = call i32 @call3()58 br label %cleanup59 60cleanup:61 %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]62 ret i32 %retval.063}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]], -12070; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 371; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 272; 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: unreachable85; 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, -12094 %cmp = icmp ult i32 %sub, 395 %cond = select i1 %cmp, i32 %sub, i32 296 switch i32 %cond, label %sw.bb4 [97 i32 0, label %sw.bb98 i32 1, label %sw.bb299 i32 2, label %sw.bb4100 ]101 102sw.bb:103 %call = call i32 @call0()104 br label %cleanup105 106sw.bb2:107 %call3 = call i32 @call1()108 br label %cleanup109 110sw.bb4:111 %val = phi i32 [ %sub, %entry ], [ %sub, %entry ]112 %call5 = call i32 @call4(i32 %val)113 br label %cleanup114 115cleanup:116 %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]117 ret i32 %retval.0118}119 120; Negative tests121 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]], -120127; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3128; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 4129; 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, -120152 %cmp = icmp ult i32 %sub, 3153 %cond = select i1 %cmp, i32 %sub, i32 4154 switch i32 %cond, label %sw.default [155 i32 0, label %sw.bb156 i32 1, label %sw.bb2157 i32 2, label %sw.bb4158 ]159 160sw.bb:161 %call = call i32 @call0()162 br label %cleanup163 164sw.bb2:165 %call3 = call i32 @call1()166 br label %cleanup167 168sw.bb4:169 %call5 = call i32 @call2()170 br label %cleanup171 172sw.default:173 %call6 = call i32 @call3()174 br label %cleanup175 176cleanup:177 %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]178 ret i32 %retval.0179}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]], -120186; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3187; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2188; 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, -120211 %cmp = icmp ult i32 %sub, 3212 %cond = select i1 %cmp, i32 %sub, i32 2213 switch i32 %cond, label %sw.default [214 i32 0, label %sw.bb215 i32 1, label %sw.bb2216 i32 2, label %sw.bb4217 ]218 219sw.bb:220 %call = call i32 @call0()221 br label %cleanup222 223sw.bb2:224 %call3 = call i32 @call1()225 br label %cleanup226 227sw.bb4:228 %call5 = call i32 @call2()229 br label %cleanup230 231sw.default:232 %call6 = call i32 @call3()233 br label %cleanup234 235cleanup:236 %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]237 ret i32 %retval.0238}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]], -120245; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3246; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2247; 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: unreachable263; 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, -120269 %cmp = icmp ult i32 %sub, 3270 %cond = select i1 %cmp, i32 %sub, i32 2271 switch i32 %cond, label %sw.default [272 i32 0, label %sw.bb273 i32 1, label %sw.bb2274 i32 2, label %sw.bb4275 ]276 277sw.bb:278 %call = call i32 @call0()279 br label %cleanup280 281sw.bb2:282 %call3 = call i32 @call1()283 br label %cleanup284 285sw.bb4:286 %call5 = call i32 @call2()287 br label %cleanup288 289sw.default:290 unreachable291 292cleanup:293 %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]294 ret i32 %retval.0295}296 297; Make sure that we don't branch into unreachable.298 299define void @pr142286() {300; CHECK-LABEL: define void @pr142286() {301; CHECK-NEXT: start:302; CHECK-NEXT: br label [[LOOP:%.*]]303; CHECK: loop:304; CHECK-NEXT: br label [[LOOP2:%.*]]305; CHECK: loop2:306; CHECK-NEXT: br label [[LOOP3:%.*]]307; CHECK: loop3:308; CHECK-NEXT: br label [[EXIT:%.*]]309; CHECK: exit:310; CHECK-NEXT: ret void311;312start:313 br label %loop314 315loop:316 %phi = phi i8 [ -1, %start ], [ 0, %loop3 ]317 br label %loop2318 319loop2:320 br label %loop3321 322loop3:323 switch i8 %phi, label %exit [324 i8 0, label %loop3325 i8 1, label %loop2326 i8 2, label %loop327 ]328 329exit:330 ret void331}332 333declare i32 @call0()334declare i32 @call1()335declare i32 @call2()336declare i32 @call3()337declare i32 @call4(i32)338