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