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