222 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 42; RUN: opt -S -passes="loop-mssa(loop-instsimplify,simple-loop-unswitch<nontrivial>)" < %s | FileCheck %s3 4@vtable = constant ptr @foo5 6declare void @foo() memory(none)7declare void @bar()8 9; The call becomes known readnone after simplification, but still have a10; MemoryAccess. Make sure this does not lead to an assertion failure.11define void @test(i1 %c) {12; CHECK-LABEL: define void @test(13; CHECK-SAME: i1 [[C:%.*]]) {14; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]15; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]16; CHECK: .split.us:17; CHECK-NEXT: br label [[LOOP_US:%.*]]18; CHECK: loop.us:19; CHECK-NEXT: call void @foo()20; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]21; CHECK: exit.split.us:22; CHECK-NEXT: br label [[EXIT:%.*]]23; CHECK: .split:24; CHECK-NEXT: br label [[LOOP:%.*]]25; CHECK: loop:26; CHECK-NEXT: call void @foo()27; CHECK-NEXT: br label [[LOOP]]28; CHECK: exit:29; CHECK-NEXT: ret void30;31 br label %loop32 33loop:34 %fn = load ptr, ptr @vtable, align 835 call void %fn()36 br i1 %c, label %exit, label %loop37 38exit:39 ret void40}41 42; Variant with another access after the call.43define void @test2(i1 %c, ptr %p) {44; CHECK-LABEL: define void @test2(45; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {46; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]47; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]48; CHECK: .split.us:49; CHECK-NEXT: br label [[LOOP_US:%.*]]50; CHECK: loop.us:51; CHECK-NEXT: call void @foo()52; CHECK-NEXT: call void @bar()53; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]54; CHECK: exit.split.us:55; CHECK-NEXT: br label [[EXIT:%.*]]56; CHECK: .split:57; CHECK-NEXT: br label [[LOOP:%.*]]58; CHECK: loop:59; CHECK-NEXT: call void @foo()60; CHECK-NEXT: call void @bar()61; CHECK-NEXT: br label [[LOOP]]62; CHECK: exit:63; CHECK-NEXT: ret void64;65 br label %loop66 67loop:68 %fn = load ptr, ptr @vtable, align 869 call void %fn()70 call void @bar()71 br i1 %c, label %exit, label %loop72 73exit:74 ret void75}76 77; Variant with another access after the call and no access before the call.78define void @test3(i1 %c, ptr %p) {79; CHECK-LABEL: define void @test3(80; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {81; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]82; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]83; CHECK: .split.us:84; CHECK-NEXT: br label [[LOOP_US:%.*]]85; CHECK: loop.us:86; CHECK-NEXT: br label [[SPLIT_US:%.*]]87; CHECK: split.us:88; CHECK-NEXT: call void @foo()89; CHECK-NEXT: call void @bar()90; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]91; CHECK: exit.split.us:92; CHECK-NEXT: br label [[EXIT:%.*]]93; CHECK: .split:94; CHECK-NEXT: br label [[LOOP:%.*]]95; CHECK: loop:96; CHECK-NEXT: br label [[SPLIT:%.*]]97; CHECK: split:98; CHECK-NEXT: call void @foo()99; CHECK-NEXT: call void @bar()100; CHECK-NEXT: br label [[LOOP]]101; CHECK: exit:102; CHECK-NEXT: ret void103;104 br label %loop105 106loop:107 %fn = load ptr, ptr @vtable, align 8108 br label %split109 110split:111 call void %fn()112 call void @bar()113 br i1 %c, label %exit, label %loop114 115exit:116 ret void117}118 119; Variants of the above test with swapped branch destinations.120 121define void @test1_swapped(i1 %c) {122; CHECK-LABEL: define void @test1_swapped(123; CHECK-SAME: i1 [[C:%.*]]) {124; CHECK-NEXT: start:125; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]126; CHECK-NEXT: br i1 [[C_FR]], label [[START_SPLIT_US:%.*]], label [[START_SPLIT:%.*]]127; CHECK: start.split.us:128; CHECK-NEXT: br label [[LOOP_US:%.*]]129; CHECK: loop.us:130; CHECK-NEXT: call void @foo()131; CHECK-NEXT: br label [[LOOP_US]]132; CHECK: start.split:133; CHECK-NEXT: br label [[LOOP:%.*]]134; CHECK: loop:135; CHECK-NEXT: call void @foo()136; CHECK-NEXT: br label [[EXIT:%.*]]137; CHECK: exit:138; CHECK-NEXT: ret void139;140start:141 br label %loop142 143loop:144 %fn = load ptr, ptr @vtable, align 8145 call void %fn()146 br i1 %c, label %loop, label %exit147 148exit:149 ret void150}151 152define void @test2_swapped(i1 %c, ptr %p) {153; CHECK-LABEL: define void @test2_swapped(154; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {155; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]156; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]157; CHECK: .split.us:158; CHECK-NEXT: br label [[LOOP_US:%.*]]159; CHECK: loop.us:160; CHECK-NEXT: call void @foo()161; CHECK-NEXT: call void @bar()162; CHECK-NEXT: br label [[LOOP_US]]163; CHECK: .split:164; CHECK-NEXT: br label [[LOOP:%.*]]165; CHECK: loop:166; CHECK-NEXT: call void @foo()167; CHECK-NEXT: call void @bar()168; CHECK-NEXT: br label [[EXIT:%.*]]169; CHECK: exit:170; CHECK-NEXT: ret void171;172 br label %loop173 174loop:175 %fn = load ptr, ptr @vtable, align 8176 call void %fn()177 call void @bar()178 br i1 %c, label %loop, label %exit179 180exit:181 ret void182}183 184define void @test3_swapped(i1 %c, ptr %p) {185; CHECK-LABEL: define void @test3_swapped(186; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {187; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]]188; CHECK-NEXT: br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]189; CHECK: .split.us:190; CHECK-NEXT: br label [[LOOP_US:%.*]]191; CHECK: loop.us:192; CHECK-NEXT: br label [[SPLIT_US:%.*]]193; CHECK: split.us:194; CHECK-NEXT: call void @foo()195; CHECK-NEXT: call void @bar()196; CHECK-NEXT: br label [[LOOP_US]]197; CHECK: .split:198; CHECK-NEXT: br label [[LOOP:%.*]]199; CHECK: loop:200; CHECK-NEXT: br label [[SPLIT:%.*]]201; CHECK: split:202; CHECK-NEXT: call void @foo()203; CHECK-NEXT: call void @bar()204; CHECK-NEXT: br label [[EXIT:%.*]]205; CHECK: exit:206; CHECK-NEXT: ret void207;208 br label %loop209 210loop:211 %fn = load ptr, ptr @vtable, align 8212 br label %split213 214split:215 call void %fn()216 call void @bar()217 br i1 %c, label %loop, label %exit218 219exit:220 ret void221}222