1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -passes=gvn-sink -S %s | FileCheck %s 3 4declare i32 @foo() 5 6define void @loop1() { 7; CHECK-LABEL: define void @loop1() { 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[LOOP:%.*]] 10; CHECK: loop: 11; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 12; CHECK-NEXT: br label [[LOOP]] 13; 14entry: 15 %c1 = call i32 @foo() 16 br label %loop 17 18loop: 19 %c2 = call i32 @foo() 20 br label %loop 21} 22 23define void @uncond_succ_no_loop() { 24; CHECK-LABEL: define void @uncond_succ_no_loop() { 25; CHECK-NEXT: entry: 26; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 27; CHECK-NEXT: br label [[EXIT:%.*]] 28; CHECK: exit: 29; CHECK-NEXT: [[C2:%.*]] = call i32 @foo() 30; CHECK-NEXT: ret void 31; 32entry: 33 %c1 = call i32 @foo() 34 br label %exit 35 36exit: 37 %c2 = call i32 @foo() 38 ret void 39} 40 41define void @loop_with_store(ptr %a) { 42; CHECK-LABEL: define void @loop_with_store 43; CHECK-SAME: (ptr [[A:%.*]]) { 44; CHECK-NEXT: entry: 45; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 46; CHECK-NEXT: br label [[LOOP:%.*]] 47; CHECK: loop: 48; CHECK-NEXT: [[C2:%.*]] = call i32 @foo() 49; CHECK-NEXT: store i32 0, ptr [[A]], align 4 50; CHECK-NEXT: br label [[LOOP]] 51; 52entry: 53 %c1 = call i32 @foo() 54 br label %loop 55 56loop: 57 %c2 = call i32 @foo() 58 store i32 0, ptr %a 59 br label %loop 60} 61 62define void @loop_linked_latches() { 63; CHECK-LABEL: define void @loop_linked_latches() { 64; CHECK-NEXT: entry: 65; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 66; CHECK-NEXT: br label [[LOOP:%.*]] 67; CHECK: loop: 68; CHECK-NEXT: [[C2:%.*]] = call i32 @foo() 69; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[C2]], 100 70; CHECK-NEXT: br i1 [[C]], label [[LATCH_1:%.*]], label [[EXIT:%.*]] 71; CHECK: latch.1: 72; CHECK-NEXT: br label [[LATCH_2:%.*]] 73; CHECK: latch.2: 74; CHECK-NEXT: br label [[LOOP]] 75; CHECK: exit: 76; CHECK-NEXT: ret void 77; 78entry: 79 %c1 = call i32 @foo() 80 br label %loop 81 82loop: 83 %c2 = call i32 @foo() 84 %c = icmp eq i32 %c2, 100 85 br i1 %c, label %latch.1, label %exit 86 87latch.1: 88 br label %latch.2 89 90latch.2: 91 br label %loop 92 93 94exit: 95 ret void 96} 97 98define void @loop_with_branch(i32 %s) { 99; CHECK-LABEL: define void @loop_with_branch 100; CHECK-SAME: (i32 [[S:%.*]]) { 101; CHECK-NEXT: entry: 102; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 103; CHECK: loop.header: 104; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 105; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[S]], 100 106; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]] 107; CHECK: loop.latch: 108; CHECK-NEXT: br label [[LOOP_HEADER]] 109; CHECK: exit: 110; CHECK-NEXT: ret void 111; 112entry: 113 %c1 = call i32 @foo() 114 br label %loop.header 115 116loop.header: 117 %cmp = icmp eq i32 %s, 100 118 br i1 %cmp, label %loop.latch, label %exit 119 120loop.latch: 121 %c2 = call i32 @foo() 122 br label %loop.header 123 124exit: 125 ret void 126} 127 128define void @loop_with_switch(i32 %s) { 129; CHECK-LABEL: define void @loop_with_switch 130; CHECK-SAME: (i32 [[S:%.*]]) { 131; CHECK-NEXT: entry: 132; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 133; CHECK: loop.header: 134; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 135; CHECK-NEXT: switch i32 [[S]], label [[LOOP_LATCH:%.*]] [ 136; CHECK-NEXT: i32 0, label [[EXIT:%.*]] 137; CHECK-NEXT: ] 138; CHECK: loop.latch: 139; CHECK-NEXT: br label [[LOOP_HEADER]] 140; CHECK: exit: 141; CHECK-NEXT: ret void 142; 143entry: 144 %c1 = call i32 @foo() 145 br label %loop.header 146 147loop.header: 148 switch i32 %s, label %loop.latch [ 149 i32 0, label %exit 150 ] 151 152loop.latch: 153 %c2 = call i32 @foo() 154 br label %loop.header 155 156exit: 157 ret void 158} 159 160define void @cycle_latch_not_dominated_by_header_branch(i1 %c, i32 %s) { 161; CHECK-LABEL: define void @cycle_latch_not_dominated_by_header_branch 162; CHECK-SAME: (i1 [[C:%.*]], i32 [[S:%.*]]) { 163; CHECK-NEXT: entry: 164; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[CYCLE_2:%.*]] 165; CHECK: then: 166; CHECK-NEXT: br label [[CYCLE_1:%.*]] 167; CHECK: cycle.1: 168; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 169; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[S]], 100 170; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[CYCLE_2]] 171; CHECK: cycle.2: 172; CHECK-NEXT: br label [[CYCLE_1]] 173; CHECK: exit: 174; CHECK-NEXT: ret void 175; 176entry: 177 br i1 %c, label %then, label %cycle.2 178 179then: 180 %c1 = call i32 @foo() 181 br label %cycle.1 182 183cycle.1: 184 %cmp = icmp eq i32 %s, 100 185 br i1 %cmp, label %exit, label %cycle.2 186 187cycle.2: 188 %c2 = call i32 @foo() 189 br label %cycle.1 190 191exit: 192 ret void 193} 194 195define void @cycle_latch_not_dominated_by_header_switch(i1 %c, i32 %s) { 196; CHECK-LABEL: define void @cycle_latch_not_dominated_by_header_switch 197; CHECK-SAME: (i1 [[C:%.*]], i32 [[S:%.*]]) { 198; CHECK-NEXT: entry: 199; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[CYCLE_2:%.*]] 200; CHECK: then: 201; CHECK-NEXT: br label [[CYCLE_1:%.*]] 202; CHECK: cycle.1: 203; CHECK-NEXT: [[C1:%.*]] = call i32 @foo() 204; CHECK-NEXT: switch i32 [[S]], label [[EXIT:%.*]] [ 205; CHECK-NEXT: i32 0, label [[CYCLE_2]] 206; CHECK-NEXT: ] 207; CHECK: cycle.2: 208; CHECK-NEXT: br label [[CYCLE_1]] 209; CHECK: exit: 210; CHECK-NEXT: ret void 211; 212entry: 213 br i1 %c, label %then, label %cycle.2 214 215then: 216 %c1 = call i32 @foo() 217 br label %cycle.1 218 219cycle.1: 220 switch i32 %s, label %exit [ 221 i32 0, label %cycle.2 222 ] 223 224cycle.2: 225 %c2 = call i32 @foo() 226 br label %cycle.1 227 228exit: 229 ret void 230} 231 232