1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes='loop-mssa(licm)' < %s | FileCheck %s 3 4declare i1 @cond(i32 %v) readnone 5declare void @capture(ptr %p) readnone 6 7define void @test_captured_after_loop(i32 %len) { 8; CHECK-LABEL: @test_captured_after_loop( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 11; CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4 12; CHECK-NEXT: [[COUNT_PROMOTED:%.*]] = load i32, ptr [[COUNT]], align 4 13; CHECK-NEXT: br label [[LOOP:%.*]] 14; CHECK: loop: 15; CHECK-NEXT: [[C_INC2:%.*]] = phi i32 [ [[COUNT_PROMOTED]], [[ENTRY:%.*]] ], [ [[C_INC1:%.*]], [[LATCH:%.*]] ] 16; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I_NEXT:%.*]], [[LATCH]] ] 17; CHECK-NEXT: [[COND:%.*]] = call i1 @cond(i32 [[I]]) 18; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[LATCH]] 19; CHECK: if: 20; CHECK-NEXT: [[C_INC:%.*]] = add i32 [[C_INC2]], 1 21; CHECK-NEXT: br label [[LATCH]] 22; CHECK: latch: 23; CHECK-NEXT: [[C_INC1]] = phi i32 [ [[C_INC]], [[IF]] ], [ [[C_INC2]], [[LOOP]] ] 24; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 25; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[LEN:%.*]] 26; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 27; CHECK: exit: 28; CHECK-NEXT: [[C_INC1_LCSSA:%.*]] = phi i32 [ [[C_INC1]], [[LATCH]] ] 29; CHECK-NEXT: store i32 [[C_INC1_LCSSA]], ptr [[COUNT]], align 4 30; CHECK-NEXT: call void @capture(ptr [[COUNT]]) 31; CHECK-NEXT: ret void 32; 33entry: 34 %count = alloca i32 35 store i32 0, ptr %count 36 br label %loop 37 38loop: 39 %i = phi i32 [ 0, %entry ], [ %i.next, %latch ] 40 %cond = call i1 @cond(i32 %i) 41 br i1 %cond, label %if, label %latch 42 43if: 44 %c = load i32, ptr %count 45 %c.inc = add i32 %c, 1 46 store i32 %c.inc, ptr %count 47 br label %latch 48 49latch: 50 %i.next = add nuw i32 %i, 1 51 %cmp = icmp eq i32 %i.next, %len 52 br i1 %cmp, label %exit, label %loop 53 54exit: 55 call void @capture(ptr %count) 56 ret void 57} 58 59define void @test_captured_in_loop(i32 %len) { 60; CHECK-LABEL: @test_captured_in_loop( 61; CHECK-NEXT: entry: 62; CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 63; CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4 64; CHECK-NEXT: [[COUNT_PROMOTED:%.*]] = load i32, ptr [[COUNT]], align 4 65; CHECK-NEXT: br label [[LOOP:%.*]] 66; CHECK: loop: 67; CHECK-NEXT: [[C_INC2:%.*]] = phi i32 [ [[COUNT_PROMOTED]], [[ENTRY:%.*]] ], [ [[C_INC1:%.*]], [[LATCH:%.*]] ] 68; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I_NEXT:%.*]], [[LATCH]] ] 69; CHECK-NEXT: [[COND:%.*]] = call i1 @cond(i32 [[I]]) 70; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[LATCH]] 71; CHECK: if: 72; CHECK-NEXT: [[C_INC:%.*]] = add i32 [[C_INC2]], 1 73; CHECK-NEXT: store i32 [[C_INC]], ptr [[COUNT]], align 4 74; CHECK-NEXT: call void @capture(ptr [[COUNT]]) 75; CHECK-NEXT: br label [[LATCH]] 76; CHECK: latch: 77; CHECK-NEXT: [[C_INC1]] = phi i32 [ [[C_INC]], [[IF]] ], [ [[C_INC2]], [[LOOP]] ] 78; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 79; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[LEN:%.*]] 80; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 81; CHECK: exit: 82; CHECK-NEXT: ret void 83; 84entry: 85 %count = alloca i32 86 store i32 0, ptr %count 87 br label %loop 88 89loop: 90 %i = phi i32 [ 0, %entry ], [ %i.next, %latch ] 91 %cond = call i1 @cond(i32 %i) 92 br i1 %cond, label %if, label %latch 93 94if: 95 %c = load i32, ptr %count 96 %c.inc = add i32 %c, 1 97 store i32 %c.inc, ptr %count 98 call void @capture(ptr %count) 99 br label %latch 100 101latch: 102 %i.next = add nuw i32 %i, 1 103 %cmp = icmp eq i32 %i.next, %len 104 br i1 %cmp, label %exit, label %loop 105 106exit: 107 ret void 108} 109 110define void @test_captured_before_loop(i32 %len) { 111; CHECK-LABEL: @test_captured_before_loop( 112; CHECK-NEXT: entry: 113; CHECK-NEXT: [[COUNT:%.*]] = alloca i32, align 4 114; CHECK-NEXT: store i32 0, ptr [[COUNT]], align 4 115; CHECK-NEXT: call void @capture(ptr [[COUNT]]) 116; CHECK-NEXT: [[COUNT_PROMOTED:%.*]] = load i32, ptr [[COUNT]], align 4 117; CHECK-NEXT: br label [[LOOP:%.*]] 118; CHECK: loop: 119; CHECK-NEXT: [[C_INC2:%.*]] = phi i32 [ [[COUNT_PROMOTED]], [[ENTRY:%.*]] ], [ [[C_INC1:%.*]], [[LATCH:%.*]] ] 120; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I_NEXT:%.*]], [[LATCH]] ] 121; CHECK-NEXT: [[COND:%.*]] = call i1 @cond(i32 [[I]]) 122; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[LATCH]] 123; CHECK: if: 124; CHECK-NEXT: [[C_INC:%.*]] = add i32 [[C_INC2]], 1 125; CHECK-NEXT: store i32 [[C_INC]], ptr [[COUNT]], align 4 126; CHECK-NEXT: br label [[LATCH]] 127; CHECK: latch: 128; CHECK-NEXT: [[C_INC1]] = phi i32 [ [[C_INC]], [[IF]] ], [ [[C_INC2]], [[LOOP]] ] 129; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 130; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[LEN:%.*]] 131; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 132; CHECK: exit: 133; CHECK-NEXT: ret void 134; 135entry: 136 %count = alloca i32 137 store i32 0, ptr %count 138 call void @capture(ptr %count) 139 br label %loop 140 141loop: 142 %i = phi i32 [ 0, %entry ], [ %i.next, %latch ] 143 %cond = call i1 @cond(i32 %i) 144 br i1 %cond, label %if, label %latch 145 146if: 147 %c = load i32, ptr %count 148 %c.inc = add i32 %c, 1 149 store i32 %c.inc, ptr %count 150 br label %latch 151 152latch: 153 %i.next = add nuw i32 %i, 1 154 %cmp = icmp eq i32 %i.next, %len 155 br i1 %cmp, label %exit, label %loop 156 157exit: 158 ret void 159} 160 161; Should not get promoted, because the pointer is captured and may not 162; be thread-local. 163define void @test_captured_before_loop_byval(ptr byval(i32) align 4 %count, i32 %len) { 164; CHECK-LABEL: @test_captured_before_loop_byval( 165; CHECK-NEXT: entry: 166; CHECK-NEXT: store i32 0, ptr [[COUNT:%.*]], align 4 167; CHECK-NEXT: call void @capture(ptr [[COUNT]]) 168; CHECK-NEXT: [[COUNT_PROMOTED:%.*]] = load i32, ptr [[COUNT]], align 4 169; CHECK-NEXT: br label [[LOOP:%.*]] 170; CHECK: loop: 171; CHECK-NEXT: [[C_INC2:%.*]] = phi i32 [ [[COUNT_PROMOTED]], [[ENTRY:%.*]] ], [ [[C_INC1:%.*]], [[LATCH:%.*]] ] 172; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I_NEXT:%.*]], [[LATCH]] ] 173; CHECK-NEXT: [[COND:%.*]] = call i1 @cond(i32 [[I]]) 174; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[LATCH]] 175; CHECK: if: 176; CHECK-NEXT: [[C_INC:%.*]] = add i32 [[C_INC2]], 1 177; CHECK-NEXT: store i32 [[C_INC]], ptr [[COUNT]], align 4 178; CHECK-NEXT: br label [[LATCH]] 179; CHECK: latch: 180; CHECK-NEXT: [[C_INC1]] = phi i32 [ [[C_INC]], [[IF]] ], [ [[C_INC2]], [[LOOP]] ] 181; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 182; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[LEN:%.*]] 183; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 184; CHECK: exit: 185; CHECK-NEXT: ret void 186; 187entry: 188 store i32 0, ptr %count 189 call void @capture(ptr %count) 190 br label %loop 191 192loop: 193 %i = phi i32 [ 0, %entry ], [ %i.next, %latch ] 194 %cond = call i1 @cond(i32 %i) 195 br i1 %cond, label %if, label %latch 196 197if: 198 %c = load i32, ptr %count 199 %c.inc = add i32 %c, 1 200 store i32 %c.inc, ptr %count 201 br label %latch 202 203latch: 204 %i.next = add nuw i32 %i, 1 205 %cmp = icmp eq i32 %i.next, %len 206 br i1 %cmp, label %exit, label %loop 207 208exit: 209 ret void 210} 211 212define void @test_captured_after_loop_byval(ptr byval(i32) align 4 %count, i32 %len) { 213; CHECK-LABEL: @test_captured_after_loop_byval( 214; CHECK-NEXT: entry: 215; CHECK-NEXT: store i32 0, ptr [[COUNT:%.*]], align 4 216; CHECK-NEXT: [[COUNT_PROMOTED:%.*]] = load i32, ptr [[COUNT]], align 4 217; CHECK-NEXT: br label [[LOOP:%.*]] 218; CHECK: loop: 219; CHECK-NEXT: [[C_INC2:%.*]] = phi i32 [ [[COUNT_PROMOTED]], [[ENTRY:%.*]] ], [ [[C_INC1:%.*]], [[LATCH:%.*]] ] 220; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I_NEXT:%.*]], [[LATCH]] ] 221; CHECK-NEXT: [[COND:%.*]] = call i1 @cond(i32 [[I]]) 222; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[LATCH]] 223; CHECK: if: 224; CHECK-NEXT: [[C_INC:%.*]] = add i32 [[C_INC2]], 1 225; CHECK-NEXT: br label [[LATCH]] 226; CHECK: latch: 227; CHECK-NEXT: [[C_INC1]] = phi i32 [ [[C_INC]], [[IF]] ], [ [[C_INC2]], [[LOOP]] ] 228; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 229; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[LEN:%.*]] 230; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 231; CHECK: exit: 232; CHECK-NEXT: [[C_INC1_LCSSA:%.*]] = phi i32 [ [[C_INC1]], [[LATCH]] ] 233; CHECK-NEXT: store i32 [[C_INC1_LCSSA]], ptr [[COUNT]], align 4 234; CHECK-NEXT: call void @capture(ptr [[COUNT]]) 235; CHECK-NEXT: ret void 236; 237entry: 238 store i32 0, ptr %count 239 br label %loop 240 241loop: 242 %i = phi i32 [ 0, %entry ], [ %i.next, %latch ] 243 %cond = call i1 @cond(i32 %i) 244 br i1 %cond, label %if, label %latch 245 246if: 247 %c = load i32, ptr %count 248 %c.inc = add i32 %c, 1 249 store i32 %c.inc, ptr %count 250 br label %latch 251 252latch: 253 %i.next = add nuw i32 %i, 1 254 %cmp = icmp eq i32 %i.next, %len 255 br i1 %cmp, label %exit, label %loop 256 257exit: 258 call void @capture(ptr %count) 259 ret void 260} 261