1; RUN: opt -passes='hardware-loops<force-hardware-loops;force-hardware-loop-guard;hardware-loop-decrement=1;hardware-loop-counter-bitwidth=32>' -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EXIT 2; RUN: opt -passes='hardware-loops<force-hardware-loops;force-hardware-loop-guard;force-hardware-loop-phi;hardware-loop-decrement=1;hardware-loop-counter-bitwidth=32>' -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LATCH 3; RUN: opt -passes='hardware-loops<force-hardware-loops;hardware-loop-decrement=1;hardware-loop-counter-bitwidth=32>' -S %s -o - | FileCheck %s --check-prefix=NO-GUARD 4 5; NO-GUARD-NOT: @llvm.test.set.loop.iterations 6 7; CHECK-LABEL: test1 8; CHECK: entry: 9; CHECK: [[MAX:%[^ ]+]] = call i32 @llvm.umax.i32(i32 %N, i32 2) 10; CHECK: [[COUNT:%[^ ]+]] = add i32 [[MAX]], -1 11; CHECK: br i1 %t1, label %do.body.preheader 12; CHECK: do.body.preheader: 13; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]]) 14; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 [[COUNT]]) 15; CHECK: br label %do.body 16define void @test1(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 17entry: 18 br i1 %t1, label %do.body, label %if.end 19 20do.body: ; preds = %do.body, %entry 21 %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %entry ] 22 %a.addr.0 = phi ptr [ %incdec.ptr1, %do.body ], [ %a, %entry ] 23 %i.0 = phi i32 [ %inc, %do.body ], [ 1, %entry ] 24 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1 25 %tmp = load i32, ptr %b.addr.0, align 4 26 %incdec.ptr1 = getelementptr inbounds i32, ptr %a.addr.0, i32 1 27 store i32 %tmp, ptr %a.addr.0, align 4 28 %inc = add nuw i32 %i.0, 1 29 %cmp = icmp ult i32 %inc, %N 30 br i1 %cmp, label %do.body, label %if.end 31 32if.end: ; preds = %do.body, %entry 33 ret void 34} 35 36; CHECK-LABEL: test2 37; CHECK-NOT: call i1 @llvm.test.set.loop.iterations 38; CHECK-NOT: call void @llvm.set.loop.iterations 39; CHECK-NOT: call i32 @llvm.start.loop.iterations 40define void @test2(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 41entry: 42 br i1 %t1, label %do.body, label %if.end 43 44do.body: ; preds = %do.body, %entry 45 %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %entry ] 46 %a.addr.0 = phi ptr [ %incdec.ptr1, %do.body ], [ %a, %entry ] 47 %i.0 = phi i32 [ %add, %do.body ], [ 1, %entry ] 48 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1 49 %tmp = load i32, ptr %b.addr.0, align 4 50 %incdec.ptr1 = getelementptr inbounds i32, ptr %a.addr.0, i32 1 51 store i32 %tmp, ptr %a.addr.0, align 4 52 %add = add i32 %i.0, 2 53 %cmp = icmp ult i32 %add, %N 54 br i1 %cmp, label %do.body, label %if.end 55 56if.end: ; preds = %do.body, %entry 57 ret void 58} 59 60; CHECK-LABEL: test3 61; CHECK: entry: 62; CHECK: [[COUNT:%[^ ]+]] = call i32 @llvm.umax.i32(i32 %N, i32 1) 63; CHECK: br i1 %brmerge.demorgan, label %do.body.preheader 64; CHECK: do.body.preheader: 65; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]]) 66; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 [[COUNT]]) 67; CHECK: br label %do.body 68define void @test3(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 69entry: 70 %brmerge.demorgan = and i1 %t1, %t2 71 br i1 %brmerge.demorgan, label %do.body, label %if.end 72 73do.body: ; preds = %do.body, %entry 74 %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %entry ] 75 %a.addr.0 = phi ptr [ %incdec.ptr3, %do.body ], [ %a, %entry ] 76 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ] 77 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1 78 %tmp = load i32, ptr %b.addr.0, align 4 79 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1 80 store i32 %tmp, ptr %a.addr.0, align 4 81 %inc = add nuw i32 %i.0, 1 82 %cmp = icmp ult i32 %inc, %N 83 br i1 %cmp, label %do.body, label %if.end 84 85if.end: ; preds = %do.body, %entry 86 ret void 87} 88 89; CHECK-LABEL: test4 90; CHECK: entry: 91; CHECK-LATCH: br i1 %brmerge.demorgan, label %while.cond 92; CHECK-LATCH-NOT: @llvm{{.*}}loop.iterations 93; CHECK-EXIT: br i1 %brmerge.demorgan, label %while.cond.preheader 94; CHECK-EXIT: while.cond.preheader: 95; CHECK-EXIT: [[COUNT:%[^ ]+]] = add i32 %N, 1 96; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]]) 97; CHECK-EXIT: br label %while.cond 98define void @test4(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 99entry: 100 %brmerge.demorgan = and i1 %t1, %t2 101 br i1 %brmerge.demorgan, label %while.cond, label %if.end 102 103while.cond: ; preds = %while.body, %entry 104 %b.addr.0 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %entry ] 105 %a.addr.0 = phi ptr [ %incdec.ptr3, %while.body ], [ %a, %entry ] 106 %i.0 = phi i32 [ %inc, %while.body ], [ 0, %entry ] 107 %exitcond = icmp eq i32 %i.0, %N 108 br i1 %exitcond, label %if.end, label %while.body 109 110while.body: ; preds = %while.cond 111 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1 112 %tmp = load i32, ptr %b.addr.0, align 4 113 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1 114 store i32 %tmp, ptr %a.addr.0, align 4 115 %inc = add i32 %i.0, 1 116 br label %while.cond 117 118if.end: ; preds = %while.cond, %entry 119 ret void 120} 121 122; CHECK-LABEL: test5 123; CHECK: entry: 124; CHECK: br i1 %or.cond, label %while.body.preheader 125; CHECK: while.body.preheader: 126; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 %N) 127; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 %N) 128; CHECK: br label %while.body 129define void @test5(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 130entry: 131 %brmerge.demorgan = and i1 %t1, %t2 132 %cmp6 = icmp ne i32 %N, 0 133 %or.cond = and i1 %brmerge.demorgan, %cmp6 134 br i1 %or.cond, label %while.body, label %if.end 135 136while.body: ; preds = %while.body, %entry 137 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %entry ] 138 %a.addr.08 = phi ptr [ %incdec.ptr3, %while.body ], [ %a, %entry ] 139 %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %entry ] 140 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1 141 %tmp = load i32, ptr %b.addr.07, align 4 142 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1 143 store i32 %tmp, ptr %a.addr.08, align 4 144 %inc = add nuw i32 %i.09, 1 145 %exitcond = icmp eq i32 %inc, %N 146 br i1 %exitcond, label %if.end, label %while.body 147 148if.end: ; preds = %while.body, %entry 149 ret void 150} 151 152; CHECK-LABEL: test6 153; CHECK: entry: 154; CHECK: br i1 %brmerge.demorgan, label %while.preheader 155; CHECK: while.preheader: 156; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N) 157; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %N) 158; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1 159; CHECK: br i1 [[TEST]], label %while.body.preheader, label %if.end 160; CHECK: while.body.preheader: 161; CHECK: br label %while.body 162define void @test6(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 163entry: 164 %brmerge.demorgan = and i1 %t1, %t2 165 br i1 %brmerge.demorgan, label %while.preheader, label %if.end 166 167while.preheader: ; preds = %entry 168 %cmp = icmp ne i32 %N, 0 169 br i1 %cmp, label %while.body, label %if.end 170 171while.body: ; preds = %while.body, %while.preheader 172 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ] 173 %a.addr.08 = phi ptr [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ] 174 %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %while.preheader ] 175 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1 176 %tmp = load i32, ptr %b.addr.07, align 4 177 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1 178 store i32 %tmp, ptr %a.addr.08, align 4 179 %inc = add nuw i32 %i.09, 1 180 %exitcond = icmp eq i32 %inc, %N 181 br i1 %exitcond, label %if.end, label %while.body 182 183if.end: ; preds = %while.body, %while.preheader, %entry 184 ret void 185} 186 187; CHECK-LABEL: test7 188; CHECK: entry: 189; CHECK: br i1 %brmerge.demorgan, label %while.preheader 190; CHECK: while.preheader: 191; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N) 192; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %N) 193; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1 194; CHECK: br i1 [[TEST]], label %while.body.preheader, label %if.end 195; CHECK: while.body.preheader: 196; CHECK: br label %while.body 197define void @test7(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 198entry: 199 %brmerge.demorgan = and i1 %t1, %t2 200 br i1 %brmerge.demorgan, label %while.preheader, label %if.end 201 202while.preheader: ; preds = %entry 203 %cmp = icmp eq i32 %N, 0 204 br i1 %cmp, label %if.end, label %while.body 205 206while.body: ; preds = %while.body, %while.preheader 207 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ] 208 %a.addr.08 = phi ptr [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ] 209 %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %while.preheader ] 210 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1 211 %tmp = load i32, ptr %b.addr.07, align 4 212 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1 213 store i32 %tmp, ptr %a.addr.08, align 4 214 %inc = add nuw i32 %i.09, 1 215 %exitcond = icmp eq i32 %inc, %N 216 br i1 %exitcond, label %if.end, label %while.body 217 218if.end: ; preds = %while.body, %while.preheader, %entry 219 ret void 220} 221 222; TODO: Can we rearrange the conditional blocks so that we can use the test form? 223; CHECK-LABEL: test8 224; CHECK: entry: 225; CHECK: [[CMP:%[^ ]+]] = icmp ne i32 %N, 0 226; CHECK: br i1 [[CMP]], label %while.preheader 227; CHECK: while.preheader: 228; CHECK: br i1 %brmerge.demorgan, label %while.body.preheader 229; CHECK: while.body.preheader: 230; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 %N) 231; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 %N) 232; CHECK: br label %while.body 233define void @test8(i1 zeroext %t1, i1 zeroext %t2, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 234entry: 235 %cmp = icmp ne i32 %N, 0 236 br i1 %cmp, label %while.preheader, label %if.end 237 238while.preheader: ; preds = %entry 239 %brmerge.demorgan = and i1 %t1, %t2 240 br i1 %brmerge.demorgan, label %while.body, label %if.end 241 242while.body: ; preds = %while.body, %while.preheader 243 %i.09 = phi i32 [ %inc, %while.body ], [ 0, %while.preheader ] 244 %a.addr.08 = phi ptr [ %incdec.ptr3, %while.body ], [ %a, %while.preheader ] 245 %b.addr.07 = phi ptr [ %incdec.ptr, %while.body ], [ %b, %while.preheader ] 246 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.07, i32 1 247 %tmp = load i32, ptr %b.addr.07, align 4 248 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.08, i32 1 249 store i32 %tmp, ptr %a.addr.08, align 4 250 %inc = add nuw i32 %i.09, 1 251 %exitcond = icmp eq i32 %inc, %N 252 br i1 %exitcond, label %if.end, label %while.body 253 254if.end: ; preds = %while.body, %while.preheader, %entry 255 ret void 256} 257 258; CHECK-LABEL: test9 259; CHECK: entry: 260; CHECK: br i1 %brmerge.demorgan, label %do.body.preheader 261; CHECK: do.body.preheader: 262; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 %N) 263; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 %N) 264; CHECK: br label %do.body 265define void @test9(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 266entry: 267 %cmp = icmp ne i32 %N, 0 268 %brmerge.demorgan = and i1 %t1, %cmp 269 br i1 %brmerge.demorgan, label %do.body, label %if.end 270 271do.body: ; preds = %do.body, %entry 272 %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %entry ] 273 %a.addr.0 = phi ptr [ %incdec.ptr3, %do.body ], [ %a, %entry ] 274 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ] 275 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1 276 %tmp = load i32, ptr %b.addr.0, align 4 277 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1 278 store i32 %tmp, ptr %a.addr.0, align 4 279 %inc = add nuw i32 %i.0, 1 280 %cmp.1 = icmp ult i32 %inc, %N 281 br i1 %cmp.1, label %do.body, label %if.end 282 283if.end: ; preds = %do.body, %entry 284 ret void 285} 286 287; CHECK-LABEL: test10 288; CHECK: entry: 289; CHECK: br i1 %cmp.1, label %do.body.preheader 290; CHECK: do.body.preheader: 291; CHECK-EXIT: call void @llvm.set.loop.iterations.i32(i32 292; CHECK-LATCH: call i32 @llvm.start.loop.iterations.i32(i32 293; CHECK: br label %do.body 294define void @test10(ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 295entry: 296 %cmp = icmp ne i32 %N, 0 297 %sub = sub i32 %N, 1 298 %be = select i1 %cmp, i32 0, i32 %sub 299 %cmp.1 = icmp ne i32 %be, 0 300 br i1 %cmp.1, label %do.body, label %if.end 301 302do.body: ; preds = %do.body, %entry 303 %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %entry ] 304 %a.addr.0 = phi ptr [ %incdec.ptr3, %do.body ], [ %a, %entry ] 305 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %entry ] 306 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1 307 %tmp = load i32, ptr %b.addr.0, align 4 308 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1 309 store i32 %tmp, ptr %a.addr.0, align 4 310 %inc = add nuw i32 %i.0, 1 311 %cmp.2 = icmp ult i32 %inc, %N 312 br i1 %cmp.2, label %do.body, label %if.end 313 314if.end: ; preds = %do.body, %entry 315 ret void 316} 317 318; CHECK-LABEL: test11 319; CHECK: entry: 320; CHECK: br label %do.body.preheader 321; CHECK: do.body.preheader: 322; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N) 323; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %N) 324; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1 325; CHECK: br i1 [[TEST]], label %do.body.preheader1, label %if.end 326; CHECK: do.body.preheader1: 327; CHECK: br label %do.body 328define void @test11(i1 zeroext %t1, ptr nocapture %a, ptr nocapture readonly %b, i32 %N) { 329entry: 330 br label %do.body.preheader 331 332do.body.preheader: 333 %cmp = icmp ne i32 %N, 0 334 br i1 %cmp, label %do.body, label %if.end 335 336do.body: 337 %b.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %b, %do.body.preheader ] 338 %a.addr.0 = phi ptr [ %incdec.ptr3, %do.body ], [ %a, %do.body.preheader ] 339 %i.0 = phi i32 [ %inc, %do.body ], [ 0, %do.body.preheader ] 340 %incdec.ptr = getelementptr inbounds i32, ptr %b.addr.0, i32 1 341 %tmp = load i32, ptr %b.addr.0, align 4 342 %incdec.ptr3 = getelementptr inbounds i32, ptr %a.addr.0, i32 1 343 store i32 %tmp, ptr %a.addr.0, align 4 344 %inc = add nuw i32 %i.0, 1 345 %cmp.1 = icmp ult i32 %inc, %N 346 br i1 %cmp.1, label %do.body, label %if.end 347 348if.end: ; preds = %do.body, %entry 349 ret void 350} 351 352; CHECK-LABEL: test12 353; CHECK: entry: 354; CHECK-EXIT: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %conv) 355; CHECK-LATCH: [[TEST1:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %conv) 356; CHECK-LATCH: [[TEST:%[^ ]+]] = extractvalue { i32, i1 } [[TEST1]], 1 357; CHECK: br i1 [[TEST]], label %for.body.preheader, label %for.end 358; CHECK: for.body.preheader: 359; CHECK: br label %for.body 360 361define void @test12(ptr nocapture %a, ptr nocapture readonly %b, i16 zeroext %length) { 362entry: 363 %conv = zext i16 %length to i32 364 %cmp8.not = icmp eq i16 %length, 0 365 br i1 %cmp8.not, label %for.end, label %for.body 366 367for.body: ; preds = %entry, %for.body 368 %i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 369 %arrayidx = getelementptr inbounds i32, ptr %b, i32 %i.09 370 %0 = load i32, ptr %arrayidx, align 4 371 %arrayidx2 = getelementptr inbounds i32, ptr %a, i32 %i.09 372 store i32 %0, ptr %arrayidx2, align 4 373 %inc = add nuw nsw i32 %i.09, 1 374 %exitcond.not = icmp eq i32 %inc, %conv 375 br i1 %exitcond.not, label %for.end, label %for.body 376 377for.end: ; preds = %for.body, %entry 378 ret void 379} 380