1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S -passes="loop-mssa(loop-instsimplify,simple-loop-unswitch<nontrivial>)" < %s | FileCheck %s 3 4@vtable = constant ptr @foo 5 6declare void @foo() memory(none) 7declare void @bar() 8 9; The call becomes known readnone after simplification, but still have a 10; 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 void 30; 31 br label %loop 32 33loop: 34 %fn = load ptr, ptr @vtable, align 8 35 call void %fn() 36 br i1 %c, label %exit, label %loop 37 38exit: 39 ret void 40} 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 void 64; 65 br label %loop 66 67loop: 68 %fn = load ptr, ptr @vtable, align 8 69 call void %fn() 70 call void @bar() 71 br i1 %c, label %exit, label %loop 72 73exit: 74 ret void 75} 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 void 103; 104 br label %loop 105 106loop: 107 %fn = load ptr, ptr @vtable, align 8 108 br label %split 109 110split: 111 call void %fn() 112 call void @bar() 113 br i1 %c, label %exit, label %loop 114 115exit: 116 ret void 117} 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 void 139; 140start: 141 br label %loop 142 143loop: 144 %fn = load ptr, ptr @vtable, align 8 145 call void %fn() 146 br i1 %c, label %loop, label %exit 147 148exit: 149 ret void 150} 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 void 171; 172 br label %loop 173 174loop: 175 %fn = load ptr, ptr @vtable, align 8 176 call void %fn() 177 call void @bar() 178 br i1 %c, label %loop, label %exit 179 180exit: 181 ret void 182} 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 void 207; 208 br label %loop 209 210loop: 211 %fn = load ptr, ptr @vtable, align 8 212 br label %split 213 214split: 215 call void %fn() 216 call void @bar() 217 br i1 %c, label %loop, label %exit 218 219exit: 220 ret void 221} 222