[ARM] Add extra MVE tests for various patches. NFC

This commit is contained in:
David Green 2020-11-01 16:24:23 +00:00
parent 1f852ba853
commit 44c1a56869
4 changed files with 2860 additions and 103 deletions

View File

@ -0,0 +1,278 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=thumbv8.1m.main-none-eabi -mattr=+mve.fp -o - %s | FileCheck --check-prefix=CHECK %s
define void @tailpred(half* nocapture readonly %pSrcA, half* nocapture readonly %pSrcB, half* nocapture %pDst, i32 %blockSize) {
; CHECK-LABEL: tailpred:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: .save {r4, r5, r7, lr}
; CHECK-NEXT: push {r4, r5, r7, lr}
; CHECK-NEXT: cmp r3, #0
; CHECK-NEXT: beq .LBB0_6
; CHECK-NEXT: @ %bb.1: @ %vector.memcheck
; CHECK-NEXT: add.w r4, r2, r3, lsl #1
; CHECK-NEXT: add.w r5, r1, r3, lsl #1
; CHECK-NEXT: cmp r4, r1
; CHECK-NEXT: cset r12, hi
; CHECK-NEXT: cmp r5, r2
; CHECK-NEXT: cset lr, hi
; CHECK-NEXT: cmp r4, r0
; CHECK-NEXT: add.w r5, r0, r3, lsl #1
; CHECK-NEXT: cset r4, hi
; CHECK-NEXT: cmp r5, r2
; CHECK-NEXT: cset r5, hi
; CHECK-NEXT: ands r4, r5
; CHECK-NEXT: lsls r4, r4, #31
; CHECK-NEXT: mov r4, r3
; CHECK-NEXT: itt eq
; CHECK-NEXT: andeq.w r3, lr, r12
; CHECK-NEXT: lslseq.w r3, r3, #31
; CHECK-NEXT: beq .LBB0_4
; CHECK-NEXT: @ %bb.2: @ %while.body.preheader
; CHECK-NEXT: dls lr, r4
; CHECK-NEXT: .LBB0_3: @ %while.body
; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-NEXT: vldr.16 s0, [r0]
; CHECK-NEXT: vldr.16 s2, [r1]
; CHECK-NEXT: adds r1, #2
; CHECK-NEXT: adds r0, #2
; CHECK-NEXT: vadd.f16 s0, s2, s0
; CHECK-NEXT: vstr.16 s0, [r2]
; CHECK-NEXT: adds r2, #2
; CHECK-NEXT: le lr, .LBB0_3
; CHECK-NEXT: b .LBB0_6
; CHECK-NEXT: .LBB0_4: @ %vector.ph
; CHECK-NEXT: adds r3, r4, #7
; CHECK-NEXT: movs r5, #1
; CHECK-NEXT: bic r3, r3, #7
; CHECK-NEXT: subs r3, #8
; CHECK-NEXT: add.w r5, r5, r3, lsr #3
; CHECK-NEXT: mov r3, r5
; CHECK-NEXT: mov r5, r4
; CHECK-NEXT: .LBB0_5: @ %vector.body
; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-NEXT: mov lr, r3
; CHECK-NEXT: vctp.16 r5
; CHECK-NEXT: sub.w lr, lr, #1
; CHECK-NEXT: subs r5, #8
; CHECK-NEXT: vpstt
; CHECK-NEXT: vldrht.u16 q0, [r0], #16
; CHECK-NEXT: vldrht.u16 q1, [r1], #16
; CHECK-NEXT: mov r3, lr
; CHECK-NEXT: vadd.f16 q0, q1, q0
; CHECK-NEXT: vpst
; CHECK-NEXT: vstrht.16 q0, [r2], #16
; CHECK-NEXT: cmp.w lr, #0
; CHECK-NEXT: bne .LBB0_5
; CHECK-NEXT: b .LBB0_6
; CHECK-NEXT: .LBB0_6: @ %while.end
; CHECK-NEXT: pop {r4, r5, r7, pc}
entry:
%cmp.not6 = icmp eq i32 %blockSize, 0
br i1 %cmp.not6, label %while.end, label %vector.memcheck
vector.memcheck: ; preds = %entry
%scevgep = getelementptr half, half* %pDst, i32 %blockSize
%scevgep14 = getelementptr half, half* %pSrcA, i32 %blockSize
%scevgep17 = getelementptr half, half* %pSrcB, i32 %blockSize
%bound0 = icmp ugt half* %scevgep14, %pDst
%bound1 = icmp ugt half* %scevgep, %pSrcA
%found.conflict = and i1 %bound0, %bound1
%bound019 = icmp ugt half* %scevgep17, %pDst
%bound120 = icmp ugt half* %scevgep, %pSrcB
%found.conflict21 = and i1 %bound019, %bound120
%conflict.rdx = or i1 %found.conflict, %found.conflict21
br i1 %conflict.rdx, label %while.body, label %vector.ph
vector.ph: ; preds = %vector.memcheck
%n.rnd.up = add i32 %blockSize, 7
%n.vec = and i32 %n.rnd.up, -8
br label %vector.body
vector.body: ; preds = %vector.body, %vector.ph
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%next.gep = getelementptr half, half* %pSrcA, i32 %index
%next.gep28 = getelementptr half, half* %pDst, i32 %index
%next.gep29 = getelementptr half, half* %pSrcB, i32 %index
%active.lane.mask = call <8 x i1> @llvm.get.active.lane.mask.v8i1.i32(i32 %index, i32 %blockSize)
%0 = bitcast half* %next.gep to <8 x half>*
%wide.masked.load = call <8 x half> @llvm.masked.load.v8f16.p0v8f16(<8 x half>* %0, i32 2, <8 x i1> %active.lane.mask, <8 x half> undef)
%1 = bitcast half* %next.gep29 to <8 x half>*
%wide.masked.load32 = call <8 x half> @llvm.masked.load.v8f16.p0v8f16(<8 x half>* %1, i32 2, <8 x i1> %active.lane.mask, <8 x half> undef)
%2 = fadd fast <8 x half> %wide.masked.load32, %wide.masked.load
%3 = bitcast half* %next.gep28 to <8 x half>*
call void @llvm.masked.store.v8f16.p0v8f16(<8 x half> %2, <8 x half>* %3, i32 2, <8 x i1> %active.lane.mask)
%index.next = add i32 %index, 8
%4 = icmp eq i32 %index.next, %n.vec
br i1 %4, label %while.end, label %vector.body
while.body: ; preds = %vector.memcheck, %while.body
%blkCnt.010 = phi i32 [ %dec, %while.body ], [ %blockSize, %vector.memcheck ]
%pSrcA.addr.09 = phi half* [ %incdec.ptr, %while.body ], [ %pSrcA, %vector.memcheck ]
%pDst.addr.08 = phi half* [ %incdec.ptr3, %while.body ], [ %pDst, %vector.memcheck ]
%pSrcB.addr.07 = phi half* [ %incdec.ptr1, %while.body ], [ %pSrcB, %vector.memcheck ]
%incdec.ptr = getelementptr inbounds half, half* %pSrcA.addr.09, i32 1
%5 = load half, half* %pSrcA.addr.09, align 2
%incdec.ptr1 = getelementptr inbounds half, half* %pSrcB.addr.07, i32 1
%6 = load half, half* %pSrcB.addr.07, align 2
%7 = fadd fast half %6, %5
%incdec.ptr3 = getelementptr inbounds half, half* %pDst.addr.08, i32 1
store half %7, half* %pDst.addr.08, align 2
%dec = add i32 %blkCnt.010, -1
%cmp.not = icmp eq i32 %dec, 0
br i1 %cmp.not, label %while.end, label %while.body
while.end: ; preds = %vector.body, %while.body, %entry
ret void
}
define void @notailpred(half* nocapture readonly %pSrcA, half* nocapture readonly %pSrcB, half* nocapture %pDst, i32 %blockSize) {
; CHECK-LABEL: notailpred:
; CHECK: @ %bb.0: @ %entry
; CHECK-NEXT: .save {r4, r5, r6, r8, r9, lr}
; CHECK-NEXT: push.w {r4, r5, r6, r8, r9, lr}
; CHECK-NEXT: cbz r3, .LBB1_6
; CHECK-NEXT: @ %bb.1: @ %while.body.preheader
; CHECK-NEXT: cmp r3, #8
; CHECK-NEXT: blo .LBB1_3
; CHECK-NEXT: @ %bb.2: @ %vector.memcheck
; CHECK-NEXT: add.w r4, r2, r3, lsl #1
; CHECK-NEXT: add.w r5, r1, r3, lsl #1
; CHECK-NEXT: cmp r4, r1
; CHECK-NEXT: add.w r6, r0, r3, lsl #1
; CHECK-NEXT: cset r12, hi
; CHECK-NEXT: cmp r5, r2
; CHECK-NEXT: cset r5, hi
; CHECK-NEXT: cmp r4, r0
; CHECK-NEXT: cset r4, hi
; CHECK-NEXT: cmp r6, r2
; CHECK-NEXT: cset r6, hi
; CHECK-NEXT: ands r6, r4
; CHECK-NEXT: lsls r6, r6, #31
; CHECK-NEXT: itt eq
; CHECK-NEXT: andeq.w r6, r5, r12
; CHECK-NEXT: lslseq.w r6, r6, #31
; CHECK-NEXT: beq .LBB1_7
; CHECK-NEXT: .LBB1_3:
; CHECK-NEXT: mov lr, r3
; CHECK-NEXT: mov r12, r0
; CHECK-NEXT: mov r4, r2
; CHECK-NEXT: mov r5, r1
; CHECK-NEXT: .LBB1_4: @ %while.body.preheader31
; CHECK-NEXT: dls lr, lr
; CHECK-NEXT: .LBB1_5: @ %while.body
; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-NEXT: vldr.16 s0, [r12]
; CHECK-NEXT: vldr.16 s2, [r5]
; CHECK-NEXT: adds r5, #2
; CHECK-NEXT: add.w r12, r12, #2
; CHECK-NEXT: vadd.f16 s0, s2, s0
; CHECK-NEXT: vstr.16 s0, [r4]
; CHECK-NEXT: adds r4, #2
; CHECK-NEXT: le lr, .LBB1_5
; CHECK-NEXT: .LBB1_6: @ %while.end
; CHECK-NEXT: pop.w {r4, r5, r6, r8, r9, pc}
; CHECK-NEXT: .LBB1_7: @ %vector.ph
; CHECK-NEXT: bic r8, r3, #7
; CHECK-NEXT: movs r4, #1
; CHECK-NEXT: sub.w r5, r8, #8
; CHECK-NEXT: and r9, r3, #7
; CHECK-NEXT: add.w r12, r0, r8, lsl #1
; CHECK-NEXT: add.w r5, r4, r5, lsr #3
; CHECK-NEXT: add.w r4, r2, r8, lsl #1
; CHECK-NEXT: mov r6, r5
; CHECK-NEXT: add.w r5, r1, r8, lsl #1
; CHECK-NEXT: .LBB1_8: @ %vector.body
; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-NEXT: vldrh.u16 q0, [r0], #16
; CHECK-NEXT: vldrh.u16 q1, [r1], #16
; CHECK-NEXT: mov lr, r6
; CHECK-NEXT: vadd.f16 q0, q1, q0
; CHECK-NEXT: subs.w lr, lr, #1
; CHECK-NEXT: vstrb.8 q0, [r2], #16
; CHECK-NEXT: mov r6, lr
; CHECK-NEXT: bne .LBB1_8
; CHECK-NEXT: b .LBB1_9
; CHECK-NEXT: .LBB1_9: @ %middle.block
; CHECK-NEXT: cmp r8, r3
; CHECK-NEXT: mov lr, r9
; CHECK-NEXT: bne .LBB1_4
; CHECK-NEXT: b .LBB1_6
entry:
%cmp.not6 = icmp eq i32 %blockSize, 0
br i1 %cmp.not6, label %while.end, label %while.body.preheader
while.body.preheader: ; preds = %entry
%min.iters.check = icmp ult i32 %blockSize, 8
br i1 %min.iters.check, label %while.body.preheader31, label %vector.memcheck
vector.memcheck: ; preds = %while.body.preheader
%scevgep = getelementptr half, half* %pDst, i32 %blockSize
%scevgep14 = getelementptr half, half* %pSrcA, i32 %blockSize
%scevgep17 = getelementptr half, half* %pSrcB, i32 %blockSize
%bound0 = icmp ugt half* %scevgep14, %pDst
%bound1 = icmp ugt half* %scevgep, %pSrcA
%found.conflict = and i1 %bound0, %bound1
%bound019 = icmp ugt half* %scevgep17, %pDst
%bound120 = icmp ugt half* %scevgep, %pSrcB
%found.conflict21 = and i1 %bound019, %bound120
%conflict.rdx = or i1 %found.conflict, %found.conflict21
br i1 %conflict.rdx, label %while.body.preheader31, label %vector.ph
vector.ph: ; preds = %vector.memcheck
%n.vec = and i32 %blockSize, -8
%ind.end = and i32 %blockSize, 7
%ind.end23 = getelementptr half, half* %pSrcA, i32 %n.vec
%ind.end25 = getelementptr half, half* %pDst, i32 %n.vec
%ind.end27 = getelementptr half, half* %pSrcB, i32 %n.vec
br label %vector.body
vector.body: ; preds = %vector.body, %vector.ph
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%next.gep = getelementptr half, half* %pSrcA, i32 %index
%next.gep28 = getelementptr half, half* %pDst, i32 %index
%next.gep29 = getelementptr half, half* %pSrcB, i32 %index
%0 = bitcast half* %next.gep to <8 x half>*
%wide.load = load <8 x half>, <8 x half>* %0, align 2
%1 = bitcast half* %next.gep29 to <8 x half>*
%wide.load30 = load <8 x half>, <8 x half>* %1, align 2
%2 = fadd fast <8 x half> %wide.load30, %wide.load
%3 = bitcast half* %next.gep28 to <8 x half>*
store <8 x half> %2, <8 x half>* %3, align 2
%index.next = add i32 %index, 8
%4 = icmp eq i32 %index.next, %n.vec
br i1 %4, label %middle.block, label %vector.body
middle.block: ; preds = %vector.body
%cmp.n = icmp eq i32 %n.vec, %blockSize
br i1 %cmp.n, label %while.end, label %while.body.preheader31
while.body.preheader31: ; preds = %middle.block, %vector.memcheck, %while.body.preheader
%blkCnt.010.ph = phi i32 [ %blockSize, %vector.memcheck ], [ %blockSize, %while.body.preheader ], [ %ind.end, %middle.block ]
%pSrcA.addr.09.ph = phi half* [ %pSrcA, %vector.memcheck ], [ %pSrcA, %while.body.preheader ], [ %ind.end23, %middle.block ]
%pDst.addr.08.ph = phi half* [ %pDst, %vector.memcheck ], [ %pDst, %while.body.preheader ], [ %ind.end25, %middle.block ]
%pSrcB.addr.07.ph = phi half* [ %pSrcB, %vector.memcheck ], [ %pSrcB, %while.body.preheader ], [ %ind.end27, %middle.block ]
br label %while.body
while.body: ; preds = %while.body.preheader31, %while.body
%blkCnt.010 = phi i32 [ %dec, %while.body ], [ %blkCnt.010.ph, %while.body.preheader31 ]
%pSrcA.addr.09 = phi half* [ %incdec.ptr, %while.body ], [ %pSrcA.addr.09.ph, %while.body.preheader31 ]
%pDst.addr.08 = phi half* [ %incdec.ptr3, %while.body ], [ %pDst.addr.08.ph, %while.body.preheader31 ]
%pSrcB.addr.07 = phi half* [ %incdec.ptr1, %while.body ], [ %pSrcB.addr.07.ph, %while.body.preheader31 ]
%incdec.ptr = getelementptr inbounds half, half* %pSrcA.addr.09, i32 1
%5 = load half, half* %pSrcA.addr.09, align 2
%incdec.ptr1 = getelementptr inbounds half, half* %pSrcB.addr.07, i32 1
%6 = load half, half* %pSrcB.addr.07, align 2
%7 = fadd fast half %6, %5
%incdec.ptr3 = getelementptr inbounds half, half* %pDst.addr.08, i32 1
store half %7, half* %pDst.addr.08, align 2
%dec = add i32 %blkCnt.010, -1
%cmp.not = icmp eq i32 %dec, 0
br i1 %cmp.not, label %while.end, label %while.body
while.end: ; preds = %while.body, %middle.block, %entry
ret void
}
declare <8 x i1> @llvm.get.active.lane.mask.v8i1.i32(i32, i32) #1
declare <8 x half> @llvm.masked.load.v8f16.p0v8f16(<8 x half>*, i32 immarg, <8 x i1>, <8 x half>) #2
declare void @llvm.masked.store.v8f16.p0v8f16(<8 x half>, <8 x half>*, i32 immarg, <8 x i1>) #3

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +1,128 @@
; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEC ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-hardware-loop-phi=true -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REGDEC ; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -S %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-DEC
; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-nested-hardware-loop=true -S %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEC --check-prefix=CHECK-NESTED ; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-hardware-loop-phi=true -S %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-PHI
; 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-GUARD ; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-nested-hardware-loop=true -S %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NESTED
; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-hardware-loop-phi=true -force-hardware-loop-guard=true -S %s -o - | FileCheck %s --check-prefix=CHECK-GUARD ; 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-prefixes=CHECK,CHECK-GUARD
; RUN: opt -hardware-loops -force-hardware-loops=true -hardware-loop-decrement=1 -hardware-loop-counter-bitwidth=32 -force-hardware-loop-phi=true -force-hardware-loop-guard=true -S %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-PHIGUARD
; CHECK-LABEL: while_lt
define void @while_lt(i32 %i, i32 %N, i32* nocapture %A) { define void @while_lt(i32 %i, i32 %N, i32* nocapture %A) {
; CHECK-DEC-LABEL: @while_lt(
; CHECK-DEC-NEXT: entry:
; CHECK-DEC-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]]
; CHECK-DEC-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-DEC: while.body.preheader:
; CHECK-DEC-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]]
; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-DEC: while.body:
; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-DEC-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-DEC: while.end:
; CHECK-DEC-NEXT: ret void
;
; CHECK-PHI-LABEL: @while_lt(
; CHECK-PHI-NEXT: entry:
; CHECK-PHI-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]]
; CHECK-PHI-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHI: while.body.preheader:
; CHECK-PHI-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]]
; CHECK-PHI-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHI: while.body:
; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHI-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHI-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-PHI-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-PHI-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHI: while.end:
; CHECK-PHI-NEXT: ret void
;
; CHECK-NESTED-LABEL: @while_lt(
; CHECK-NESTED-NEXT: entry:
; CHECK-NESTED-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]]
; CHECK-NESTED-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-NESTED: while.body.preheader:
; CHECK-NESTED-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]]
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-NESTED-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-NESTED: while.body:
; CHECK-NESTED-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-NESTED-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-NESTED-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-NESTED-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-NESTED-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-NESTED: while.end:
; CHECK-NESTED-NEXT: ret void
;
; CHECK-GUARD-LABEL: @while_lt(
; CHECK-GUARD-NEXT: entry:
; CHECK-GUARD-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]]
; CHECK-GUARD-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]]
; CHECK-GUARD-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-GUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-GUARD: while.body:
; CHECK-GUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-GUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-GUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-GUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-GUARD-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-GUARD-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-GUARD: while.end:
; CHECK-GUARD-NEXT: ret void
;
; CHECK-PHIGUARD-LABEL: @while_lt(
; CHECK-PHIGUARD-NEXT: entry:
; CHECK-PHIGUARD-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]]
; CHECK-PHIGUARD-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]]
; CHECK-PHIGUARD-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHIGUARD: while.body.preheader:
; CHECK-PHIGUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-PHIGUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHIGUARD: while.body:
; CHECK-PHIGUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHIGUARD-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-PHIGUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHIGUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHIGUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHIGUARD-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-PHIGUARD-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHIGUARD: while.end:
; CHECK-PHIGUARD-NEXT: ret void
;
; CHECK-REGDEC-LABEL: @while_lt(
; CHECK-REGDEC-NEXT: entry:
; CHECK-REGDEC-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]]
; CHECK-REGDEC-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-REGDEC: while.body.preheader:
; CHECK-REGDEC-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]]
; CHECK-REGDEC-NEXT: [[TMP1:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[TMP0]])
; CHECK-REGDEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-REGDEC: while.body:
; CHECK-REGDEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-REGDEC-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP3:%.*]], [[WHILE_BODY]] ]
; CHECK-REGDEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-REGDEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-REGDEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-REGDEC-NEXT: [[TMP3]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP2]], i32 1)
; CHECK-REGDEC-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0
; CHECK-REGDEC-NEXT: br i1 [[TMP4]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-REGDEC: while.end:
; CHECK-REGDEC-NEXT: ret void
entry: entry:
%cmp4 = icmp ult i32 %i, %N %cmp4 = icmp ult i32 %i, %N
br i1 %cmp4, label %while.body, label %while.end br i1 %cmp4, label %while.body, label %while.end
; CHECK-GUARD-LABEL: while_lt
; CHECK-GUARD: [[COUNT:%[^ ]+]] = sub i32 %N, %i
; CHECK-GUARD: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
; CHECK-GUARD: br label %while.body
; CHECK: while.body.preheader:
; CHECK: [[COUNT:%[^ ]+]] = sub i32 %N, %i
; CHECK: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
; CHECK: br label %while.body
; CHECK-REGDEC: [[REM:%[^ ]+]] = phi i32 [ [[COUNT]], %while.body.preheader ], [ [[LOOP_DEC:%[^ ]+]], %while.body ]
; CHECK-REGDEC: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1)
; CHECK-REGDEC: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0
; CHECK-REGDEC: br i1 [[CMP]], label %while.body, label %while.end
; CHECK-DEC: [[LOOP_DEC:%[^ ]+]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC: br i1 [[LOOP_DEC]], label %while.body, label %while.end
while.body: while.body:
%i.addr.05 = phi i32 [ %inc, %while.body ], [ %i, %entry ] %i.addr.05 = phi i32 [ %inc, %while.body ], [ %i, %entry ]
%arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.addr.05 %arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.addr.05
@ -40,21 +135,120 @@ while.end:
ret void ret void
} }
; CHECK-LABEL: while_gt
; CHECK: while.body.preheader:
; CHECK: [[COUNT:%[^ ]+]] = sub i32 %i, %N
; CHECK: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
; CHECK: br label %while.body
; CHECK-REGDEC: [[REM:%[^ ]+]] = phi i32 [ [[COUNT]], %while.body.preheader ], [ [[LOOP_DEC:%[^ ]+]], %while.body ]
; CHECK-REGDEC: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1)
; CHECK-REGDEC: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0
; CHECK-REGDEC: br i1 [[CMP]], label %while.body, label %while.end
; CHECK-DEC: [[LOOP_DEC:%[^ ]+]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC: br i1 [[LOOP_DEC]], label %while.body, label %while.end
define void @while_gt(i32 %i, i32 %N, i32* nocapture %A) { define void @while_gt(i32 %i, i32 %N, i32* nocapture %A) {
; CHECK-DEC-LABEL: @while_gt(
; CHECK-DEC-NEXT: entry:
; CHECK-DEC-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]]
; CHECK-DEC-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-DEC: while.body.preheader:
; CHECK-DEC-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]]
; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-DEC: while.body:
; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-DEC-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-DEC-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-DEC: while.end:
; CHECK-DEC-NEXT: ret void
;
; CHECK-PHI-LABEL: @while_gt(
; CHECK-PHI-NEXT: entry:
; CHECK-PHI-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]]
; CHECK-PHI-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHI: while.body.preheader:
; CHECK-PHI-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]]
; CHECK-PHI-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHI: while.body:
; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHI-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHI-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-PHI-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-PHI-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-PHI-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHI: while.end:
; CHECK-PHI-NEXT: ret void
;
; CHECK-NESTED-LABEL: @while_gt(
; CHECK-NESTED-NEXT: entry:
; CHECK-NESTED-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]]
; CHECK-NESTED-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-NESTED: while.body.preheader:
; CHECK-NESTED-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]]
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-NESTED-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-NESTED: while.body:
; CHECK-NESTED-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-NESTED-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-NESTED-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-NESTED-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-NESTED-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-NESTED: while.end:
; CHECK-NESTED-NEXT: ret void
;
; CHECK-GUARD-LABEL: @while_gt(
; CHECK-GUARD-NEXT: entry:
; CHECK-GUARD-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]]
; CHECK-GUARD-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]]
; CHECK-GUARD-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-GUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-GUARD: while.body:
; CHECK-GUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-GUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-GUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-GUARD-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-GUARD-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-GUARD-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-GUARD: while.end:
; CHECK-GUARD-NEXT: ret void
;
; CHECK-PHIGUARD-LABEL: @while_gt(
; CHECK-PHIGUARD-NEXT: entry:
; CHECK-PHIGUARD-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]]
; CHECK-PHIGUARD-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]]
; CHECK-PHIGUARD-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHIGUARD: while.body.preheader:
; CHECK-PHIGUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]])
; CHECK-PHIGUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHIGUARD: while.body:
; CHECK-PHIGUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHIGUARD-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-PHIGUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHIGUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHIGUARD-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-PHIGUARD-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-PHIGUARD-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHIGUARD: while.end:
; CHECK-PHIGUARD-NEXT: ret void
;
; CHECK-REGDEC-LABEL: @while_gt(
; CHECK-REGDEC-NEXT: entry:
; CHECK-REGDEC-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]]
; CHECK-REGDEC-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-REGDEC: while.body.preheader:
; CHECK-REGDEC-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]]
; CHECK-REGDEC-NEXT: [[TMP1:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[TMP0]])
; CHECK-REGDEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-REGDEC: while.body:
; CHECK-REGDEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-REGDEC-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP3:%.*]], [[WHILE_BODY]] ]
; CHECK-REGDEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-REGDEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-REGDEC-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-REGDEC-NEXT: [[TMP3]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP2]], i32 1)
; CHECK-REGDEC-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0
; CHECK-REGDEC-NEXT: br i1 [[TMP4]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-REGDEC: while.end:
; CHECK-REGDEC-NEXT: ret void
entry: entry:
%cmp4 = icmp sgt i32 %i, %N %cmp4 = icmp sgt i32 %i, %N
br i1 %cmp4, label %while.body, label %while.end br i1 %cmp4, label %while.body, label %while.end
@ -71,31 +265,126 @@ while.end:
ret void ret void
} }
; CHECK-GUARD-LABEL: while_gte
; CHECK-GUARD: entry:
; CHECK-GUARD: br i1 %cmp4, label %while.end, label %while.body.preheader
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD: [[ADD:%[^ ]+]] = add i32 %i, 1
; CHECK-GUARD: [[COUNT:%[^ ]+]] = sub i32 [[ADD]], %N
; CHECK-GUARD: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
; CHECK-GUARD: br label %while.body
; CHECK-LABEL: while_gte
; CHECK: while.body.preheader:
; CHECK: [[ADD:%[^ ]+]] = add i32 %i, 1
; CHECK: [[COUNT:%[^ ]+]] = sub i32 [[ADD]], %N
; CHECK: call void @llvm.set.loop.iterations.i32(i32 [[COUNT]])
; CHECK: br label %while.body
; CHECK-REGDEC: [[REM:%[^ ]+]] = phi i32 [ [[COUNT]], %while.body.preheader ], [ [[LOOP_DEC:%[^ ]+]], %while.body ]
; CHECK-REGDEC: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1)
; CHECK-REGDEC: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0
; CHECK-REGDEC: br i1 [[CMP]], label %while.body, label %while.end
; CHECK-DEC: [[LOOP_DEC:%[^ ]+]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC: br i1 [[LOOP_DEC]], label %while.body, label %while.end
define void @while_gte(i32 %i, i32 %N, i32* nocapture %A) { define void @while_gte(i32 %i, i32 %N, i32* nocapture %A) {
; CHECK-DEC-LABEL: @while_gte(
; CHECK-DEC-NEXT: entry:
; CHECK-DEC-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]]
; CHECK-DEC-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-DEC: while.body.preheader:
; CHECK-DEC-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1
; CHECK-DEC-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]]
; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP1]])
; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-DEC: while.body:
; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-DEC-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-DEC-NEXT: [[TMP2:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC-NEXT: br i1 [[TMP2]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-DEC: while.end:
; CHECK-DEC-NEXT: ret void
;
; CHECK-PHI-LABEL: @while_gte(
; CHECK-PHI-NEXT: entry:
; CHECK-PHI-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]]
; CHECK-PHI-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-PHI: while.body.preheader:
; CHECK-PHI-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1
; CHECK-PHI-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]]
; CHECK-PHI-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP1]])
; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHI: while.body:
; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHI-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP3:%.*]], [[WHILE_BODY]] ]
; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHI-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-PHI-NEXT: [[TMP3]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP2]], i32 1)
; CHECK-PHI-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0
; CHECK-PHI-NEXT: br i1 [[TMP4]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHI: while.end:
; CHECK-PHI-NEXT: ret void
;
; CHECK-NESTED-LABEL: @while_gte(
; CHECK-NESTED-NEXT: entry:
; CHECK-NESTED-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]]
; CHECK-NESTED-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-NESTED: while.body.preheader:
; CHECK-NESTED-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1
; CHECK-NESTED-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]]
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP1]])
; CHECK-NESTED-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-NESTED: while.body:
; CHECK-NESTED-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-NESTED-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-NESTED-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-NESTED-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-NESTED-NEXT: [[TMP2:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP2]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-NESTED: while.end:
; CHECK-NESTED-NEXT: ret void
;
; CHECK-GUARD-LABEL: @while_gte(
; CHECK-GUARD-NEXT: entry:
; CHECK-GUARD-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]]
; CHECK-GUARD-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1
; CHECK-GUARD-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]]
; CHECK-GUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP1]])
; CHECK-GUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-GUARD: while.body:
; CHECK-GUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-GUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-GUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-GUARD-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-GUARD-NEXT: [[TMP2:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-GUARD-NEXT: br i1 [[TMP2]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-GUARD: while.end:
; CHECK-GUARD-NEXT: ret void
;
; CHECK-PHIGUARD-LABEL: @while_gte(
; CHECK-PHIGUARD-NEXT: entry:
; CHECK-PHIGUARD-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]]
; CHECK-PHIGUARD-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-PHIGUARD: while.body.preheader:
; CHECK-PHIGUARD-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1
; CHECK-PHIGUARD-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]]
; CHECK-PHIGUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP1]])
; CHECK-PHIGUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHIGUARD: while.body:
; CHECK-PHIGUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHIGUARD-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP3:%.*]], [[WHILE_BODY]] ]
; CHECK-PHIGUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHIGUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHIGUARD-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-PHIGUARD-NEXT: [[TMP3]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP2]], i32 1)
; CHECK-PHIGUARD-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[TMP4]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHIGUARD: while.end:
; CHECK-PHIGUARD-NEXT: ret void
;
; CHECK-REGDEC-LABEL: @while_gte(
; CHECK-REGDEC-NEXT: entry:
; CHECK-REGDEC-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]]
; CHECK-REGDEC-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-REGDEC: while.body.preheader:
; CHECK-REGDEC-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1
; CHECK-REGDEC-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]]
; CHECK-REGDEC-NEXT: [[TMP2:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[TMP1]])
; CHECK-REGDEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-REGDEC: while.body:
; CHECK-REGDEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ]
; CHECK-REGDEC-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP2]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP4:%.*]], [[WHILE_BODY]] ]
; CHECK-REGDEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-REGDEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-REGDEC-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1
; CHECK-REGDEC-NEXT: [[TMP4]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP3]], i32 1)
; CHECK-REGDEC-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP4]], 0
; CHECK-REGDEC-NEXT: br i1 [[TMP5]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-REGDEC: while.end:
; CHECK-REGDEC-NEXT: ret void
entry: entry:
%cmp4 = icmp slt i32 %i, %N %cmp4 = icmp slt i32 %i, %N
br i1 %cmp4, label %while.end, label %while.body br i1 %cmp4, label %while.end, label %while.body
@ -112,13 +401,114 @@ while.end:
ret void ret void
} }
; CHECK-GUARD-LABEL: while_ne
; CHECK-GUARD: entry:
; CHECK-GUARD: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
; CHECK-GUARD: br i1 [[TEST]], label %while.body.preheader, label %while.end
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD: br label %while.body
define void @while_ne(i32 %N, i32* nocapture %A) { define void @while_ne(i32 %N, i32* nocapture %A) {
; CHECK-DEC-LABEL: @while_ne(
; CHECK-DEC-NEXT: entry:
; CHECK-DEC-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0
; CHECK-DEC-NEXT: br i1 [[CMP]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-DEC: while.body.preheader:
; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-DEC: while.body:
; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-DEC: while.end:
; CHECK-DEC-NEXT: ret void
;
; CHECK-PHI-LABEL: @while_ne(
; CHECK-PHI-NEXT: entry:
; CHECK-PHI-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0
; CHECK-PHI-NEXT: br i1 [[CMP]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHI: while.body.preheader:
; CHECK-PHI-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHI: while.body:
; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHI-NEXT: [[TMP0:%.*]] = phi i32 [ [[N]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP1:%.*]], [[WHILE_BODY]] ]
; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHI-NEXT: [[TMP1]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP0]], i32 1)
; CHECK-PHI-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-PHI-NEXT: br i1 [[TMP2]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHI: while.end:
; CHECK-PHI-NEXT: ret void
;
; CHECK-NESTED-LABEL: @while_ne(
; CHECK-NESTED-NEXT: entry:
; CHECK-NESTED-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0
; CHECK-NESTED-NEXT: br i1 [[CMP]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-NESTED: while.body.preheader:
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-NESTED-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-NESTED: while.body:
; CHECK-NESTED-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-NESTED-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-NESTED-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-NESTED-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-NESTED-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-NESTED: while.end:
; CHECK-NESTED-NEXT: ret void
;
; CHECK-GUARD-LABEL: @while_ne(
; CHECK-GUARD-NEXT: entry:
; CHECK-GUARD-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0
; CHECK-GUARD-NEXT: [[TMP0:%.*]] = call i1 @llvm.test.set.loop.iterations.i32(i32 [[N]])
; CHECK-GUARD-NEXT: br i1 [[TMP0]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-GUARD: while.body:
; CHECK-GUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-GUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-GUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-GUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-GUARD-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-GUARD-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-GUARD: while.end:
; CHECK-GUARD-NEXT: ret void
;
; CHECK-PHIGUARD-LABEL: @while_ne(
; CHECK-PHIGUARD-NEXT: entry:
; CHECK-PHIGUARD-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0
; CHECK-PHIGUARD-NEXT: [[TMP0:%.*]] = call i1 @llvm.test.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHIGUARD-NEXT: br i1 [[TMP0]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHIGUARD: while.body.preheader:
; CHECK-PHIGUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHIGUARD: while.body:
; CHECK-PHIGUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHIGUARD-NEXT: [[TMP1:%.*]] = phi i32 [ [[N]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-PHIGUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHIGUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHIGUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHIGUARD-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-PHIGUARD-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHIGUARD: while.end:
; CHECK-PHIGUARD-NEXT: ret void
;
; CHECK-REGDEC-LABEL: @while_ne(
; CHECK-REGDEC-NEXT: entry:
; CHECK-REGDEC-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0
; CHECK-REGDEC-NEXT: br i1 [[CMP]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-REGDEC: while.body.preheader:
; CHECK-REGDEC-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]])
; CHECK-REGDEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-REGDEC: while.body:
; CHECK-REGDEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-REGDEC-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-REGDEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-REGDEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-REGDEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-REGDEC-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-REGDEC-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-REGDEC-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-REGDEC: while.end:
; CHECK-REGDEC-NEXT: ret void
entry: entry:
%cmp = icmp ne i32 %N, 0 %cmp = icmp ne i32 %N, 0
br i1 %cmp, label %while.body, label %while.end br i1 %cmp, label %while.body, label %while.end
@ -135,13 +525,114 @@ while.end:
ret void ret void
} }
; CHECK-GUARD-LABEL: while_eq
; CHECK-GUARD: entry:
; CHECK-GUARD: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
; CHECK-GUARD: br i1 [[TEST]], label %while.body.preheader, label %while.end
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD: br label %while.body
define void @while_eq(i32 %N, i32* nocapture %A) { define void @while_eq(i32 %N, i32* nocapture %A) {
; CHECK-DEC-LABEL: @while_eq(
; CHECK-DEC-NEXT: entry:
; CHECK-DEC-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-DEC-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-DEC: while.body.preheader:
; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-DEC: while.body:
; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-DEC: while.end:
; CHECK-DEC-NEXT: ret void
;
; CHECK-PHI-LABEL: @while_eq(
; CHECK-PHI-NEXT: entry:
; CHECK-PHI-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-PHI-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-PHI: while.body.preheader:
; CHECK-PHI-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHI: while.body:
; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHI-NEXT: [[TMP0:%.*]] = phi i32 [ [[N]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP1:%.*]], [[WHILE_BODY]] ]
; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHI-NEXT: [[TMP1]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP0]], i32 1)
; CHECK-PHI-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-PHI-NEXT: br i1 [[TMP2]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHI: while.end:
; CHECK-PHI-NEXT: ret void
;
; CHECK-NESTED-LABEL: @while_eq(
; CHECK-NESTED-NEXT: entry:
; CHECK-NESTED-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NESTED-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-NESTED: while.body.preheader:
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-NESTED-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-NESTED: while.body:
; CHECK-NESTED-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-NESTED-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-NESTED-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-NESTED-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-NESTED-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-NESTED: while.end:
; CHECK-NESTED-NEXT: ret void
;
; CHECK-GUARD-LABEL: @while_eq(
; CHECK-GUARD-NEXT: entry:
; CHECK-GUARD-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-GUARD-NEXT: [[TMP0:%.*]] = call i1 @llvm.test.set.loop.iterations.i32(i32 [[N]])
; CHECK-GUARD-NEXT: br i1 [[TMP0]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-GUARD: while.body:
; CHECK-GUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-GUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-GUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-GUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-GUARD-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-GUARD-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-GUARD: while.end:
; CHECK-GUARD-NEXT: ret void
;
; CHECK-PHIGUARD-LABEL: @while_eq(
; CHECK-PHIGUARD-NEXT: entry:
; CHECK-PHIGUARD-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-PHIGUARD-NEXT: [[TMP0:%.*]] = call i1 @llvm.test.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHIGUARD-NEXT: br i1 [[TMP0]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHIGUARD: while.body.preheader:
; CHECK-PHIGUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHIGUARD: while.body:
; CHECK-PHIGUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHIGUARD-NEXT: [[TMP1:%.*]] = phi i32 [ [[N]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-PHIGUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHIGUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHIGUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHIGUARD-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-PHIGUARD-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHIGUARD: while.end:
; CHECK-PHIGUARD-NEXT: ret void
;
; CHECK-REGDEC-LABEL: @while_eq(
; CHECK-REGDEC-NEXT: entry:
; CHECK-REGDEC-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-REGDEC-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-REGDEC: while.body.preheader:
; CHECK-REGDEC-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]])
; CHECK-REGDEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-REGDEC: while.body:
; CHECK-REGDEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-REGDEC-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-REGDEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-REGDEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-REGDEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-REGDEC-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-REGDEC-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-REGDEC-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-REGDEC: while.end:
; CHECK-REGDEC-NEXT: ret void
entry: entry:
%cmp = icmp eq i32 %N, 0 %cmp = icmp eq i32 %N, 0
br i1 %cmp, label %while.end, label %while.body br i1 %cmp, label %while.end, label %while.body
@ -158,15 +649,126 @@ while.end:
ret void ret void
} }
; CHECK-GUARD-LABEL: while_preheader_eq
; CHECK-GUARD: entry:
; CHECK-GUARD: br label %preheader
; CHECK-GUARD: preheader:
; CHECK-GUARD: [[TEST:%[^ ]+]] = call i1 @llvm.test.set.loop.iterations.i32(i32 %N)
; CHECK-GUARD: br i1 [[TEST]], label %while.body.preheader, label %while.end
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD: br label %while.body
define void @while_preheader_eq(i32 %N, i32* nocapture %A) { define void @while_preheader_eq(i32 %N, i32* nocapture %A) {
; CHECK-DEC-LABEL: @while_preheader_eq(
; CHECK-DEC-NEXT: entry:
; CHECK-DEC-NEXT: br label [[PREHEADER:%.*]]
; CHECK-DEC: preheader:
; CHECK-DEC-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-DEC-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-DEC: while.body.preheader:
; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-DEC: while.body:
; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-DEC: while.end:
; CHECK-DEC-NEXT: ret void
;
; CHECK-PHI-LABEL: @while_preheader_eq(
; CHECK-PHI-NEXT: entry:
; CHECK-PHI-NEXT: br label [[PREHEADER:%.*]]
; CHECK-PHI: preheader:
; CHECK-PHI-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-PHI-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-PHI: while.body.preheader:
; CHECK-PHI-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHI: while.body:
; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHI-NEXT: [[TMP0:%.*]] = phi i32 [ [[N]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP1:%.*]], [[WHILE_BODY]] ]
; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHI-NEXT: [[TMP1]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP0]], i32 1)
; CHECK-PHI-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-PHI-NEXT: br i1 [[TMP2]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHI: while.end:
; CHECK-PHI-NEXT: ret void
;
; CHECK-NESTED-LABEL: @while_preheader_eq(
; CHECK-NESTED-NEXT: entry:
; CHECK-NESTED-NEXT: br label [[PREHEADER:%.*]]
; CHECK-NESTED: preheader:
; CHECK-NESTED-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NESTED-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-NESTED: while.body.preheader:
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-NESTED-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-NESTED: while.body:
; CHECK-NESTED-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-NESTED-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-NESTED-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-NESTED-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-NESTED-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-NESTED: while.end:
; CHECK-NESTED-NEXT: ret void
;
; CHECK-GUARD-LABEL: @while_preheader_eq(
; CHECK-GUARD-NEXT: entry:
; CHECK-GUARD-NEXT: br label [[PREHEADER:%.*]]
; CHECK-GUARD: preheader:
; CHECK-GUARD-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-GUARD-NEXT: [[TMP0:%.*]] = call i1 @llvm.test.set.loop.iterations.i32(i32 [[N]])
; CHECK-GUARD-NEXT: br i1 [[TMP0]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-GUARD: while.body.preheader:
; CHECK-GUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-GUARD: while.body:
; CHECK-GUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-GUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-GUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-GUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-GUARD-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-GUARD-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-GUARD: while.end:
; CHECK-GUARD-NEXT: ret void
;
; CHECK-PHIGUARD-LABEL: @while_preheader_eq(
; CHECK-PHIGUARD-NEXT: entry:
; CHECK-PHIGUARD-NEXT: br label [[PREHEADER:%.*]]
; CHECK-PHIGUARD: preheader:
; CHECK-PHIGUARD-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-PHIGUARD-NEXT: [[TMP0:%.*]] = call i1 @llvm.test.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHIGUARD-NEXT: br i1 [[TMP0]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]]
; CHECK-PHIGUARD: while.body.preheader:
; CHECK-PHIGUARD-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-PHIGUARD: while.body:
; CHECK-PHIGUARD-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-PHIGUARD-NEXT: [[TMP1:%.*]] = phi i32 [ [[N]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-PHIGUARD-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-PHIGUARD-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-PHIGUARD-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-PHIGUARD-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-PHIGUARD-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-PHIGUARD: while.end:
; CHECK-PHIGUARD-NEXT: ret void
;
; CHECK-REGDEC-LABEL: @while_preheader_eq(
; CHECK-REGDEC-NEXT: entry:
; CHECK-REGDEC-NEXT: br label [[PREHEADER:%.*]]
; CHECK-REGDEC: preheader:
; CHECK-REGDEC-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-REGDEC-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
; CHECK-REGDEC: while.body.preheader:
; CHECK-REGDEC-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]])
; CHECK-REGDEC-NEXT: br label [[WHILE_BODY:%.*]]
; CHECK-REGDEC: while.body:
; CHECK-REGDEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
; CHECK-REGDEC-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ]
; CHECK-REGDEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_ADDR_05]]
; CHECK-REGDEC-NEXT: store i32 [[I_ADDR_05]], i32* [[ARRAYIDX]], align 4
; CHECK-REGDEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1
; CHECK-REGDEC-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-REGDEC-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-REGDEC-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]]
; CHECK-REGDEC: while.end:
; CHECK-REGDEC-NEXT: ret void
entry: entry:
br label %preheader br label %preheader
@ -186,28 +788,159 @@ while.end:
ret void ret void
} }
; CHECK-LABEL: nested
; CHECK-NESTED: call void @llvm.set.loop.iterations.i32(i32 %N)
; CHECK-NESTED: br label %while.cond1.preheader.us
; CHECK: call void @llvm.set.loop.iterations.i32(i32 %N)
; CHECK: br label %while.body3.us
; CHECK-DEC: [[LOOP_DEC:%[^ ]+]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-REGDEC: [[REM:%[^ ]+]] = phi i32 [ %N, %while.cond1.preheader.us ], [ [[LOOP_DEC:%[^ ]+]], %while.body3.us ]
; CHECK-REGDEC: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1)
; CHECK-REGDEC: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0
; CHECK-REGDEC: br i1 [[CMP]], label %while.body3.us, label %while.cond1.while.end_crit_edge.us
; CHECK-NESTED: [[LOOP_DEC1:%[^ ]+]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED: br i1 [[LOOP_DEC1]], label %while.cond1.preheader.us, label %while.end7
; CHECK-GUARD: while.cond1.preheader.us:
; CHECK-GUARD: call void @llvm.set.loop.iterations.i32(i32 %N)
; CHECK-GUARD: br label %while.body3.us
define void @nested(i32* nocapture %A, i32 %N) { define void @nested(i32* nocapture %A, i32 %N) {
; CHECK-DEC-LABEL: @nested(
; CHECK-DEC-NEXT: entry:
; CHECK-DEC-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-DEC-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US:%.*]]
; CHECK-DEC: while.cond1.preheader.us:
; CHECK-DEC-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-DEC-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]]
; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-DEC-NEXT: br label [[WHILE_BODY3_US:%.*]]
; CHECK-DEC: while.body3.us:
; CHECK-DEC-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-DEC-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]]
; CHECK-DEC-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[ADD_US]]
; CHECK-DEC-NEXT: store i32 [[ADD_US]], i32* [[ARRAYIDX_US]], align 4
; CHECK-DEC-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1
; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]]
; CHECK-DEC: while.cond1.while.end_crit_edge.us:
; CHECK-DEC-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1
; CHECK-DEC-NEXT: [[EXITCOND23:%.*]] = icmp eq i32 [[INC6_US]], [[N]]
; CHECK-DEC-NEXT: br i1 [[EXITCOND23]], label [[WHILE_END7]], label [[WHILE_COND1_PREHEADER_US]]
; CHECK-DEC: while.end7:
; CHECK-DEC-NEXT: ret void
;
; CHECK-PHI-LABEL: @nested(
; CHECK-PHI-NEXT: entry:
; CHECK-PHI-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-PHI-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US:%.*]]
; CHECK-PHI: while.cond1.preheader.us:
; CHECK-PHI-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-PHI-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]]
; CHECK-PHI-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHI-NEXT: br label [[WHILE_BODY3_US:%.*]]
; CHECK-PHI: while.body3.us:
; CHECK-PHI-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-PHI-NEXT: [[TMP0:%.*]] = phi i32 [ [[N]], [[WHILE_COND1_PREHEADER_US]] ], [ [[TMP1:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-PHI-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]]
; CHECK-PHI-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[ADD_US]]
; CHECK-PHI-NEXT: store i32 [[ADD_US]], i32* [[ARRAYIDX_US]], align 4
; CHECK-PHI-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1
; CHECK-PHI-NEXT: [[TMP1]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP0]], i32 1)
; CHECK-PHI-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-PHI-NEXT: br i1 [[TMP2]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]]
; CHECK-PHI: while.cond1.while.end_crit_edge.us:
; CHECK-PHI-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1
; CHECK-PHI-NEXT: [[EXITCOND23:%.*]] = icmp eq i32 [[INC6_US]], [[N]]
; CHECK-PHI-NEXT: br i1 [[EXITCOND23]], label [[WHILE_END7]], label [[WHILE_COND1_PREHEADER_US]]
; CHECK-PHI: while.end7:
; CHECK-PHI-NEXT: ret void
;
; CHECK-NESTED-LABEL: @nested(
; CHECK-NESTED-NEXT: entry:
; CHECK-NESTED-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NESTED-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US_PREHEADER:%.*]]
; CHECK-NESTED: while.cond1.preheader.us.preheader:
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-NESTED-NEXT: br label [[WHILE_COND1_PREHEADER_US:%.*]]
; CHECK-NESTED: while.cond1.preheader.us:
; CHECK-NESTED-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[WHILE_COND1_PREHEADER_US_PREHEADER]] ]
; CHECK-NESTED-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]]
; CHECK-NESTED-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-NESTED-NEXT: br label [[WHILE_BODY3_US:%.*]]
; CHECK-NESTED: while.body3.us:
; CHECK-NESTED-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-NESTED-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]]
; CHECK-NESTED-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[ADD_US]]
; CHECK-NESTED-NEXT: store i32 [[ADD_US]], i32* [[ARRAYIDX_US]], align 4
; CHECK-NESTED-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1
; CHECK-NESTED-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP0]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]]
; CHECK-NESTED: while.cond1.while.end_crit_edge.us:
; CHECK-NESTED-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1
; CHECK-NESTED-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-NESTED-NEXT: br i1 [[TMP1]], label [[WHILE_COND1_PREHEADER_US]], label [[WHILE_END7]]
; CHECK-NESTED: while.end7:
; CHECK-NESTED-NEXT: ret void
;
; CHECK-GUARD-LABEL: @nested(
; CHECK-GUARD-NEXT: entry:
; CHECK-GUARD-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-GUARD-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US:%.*]]
; CHECK-GUARD: while.cond1.preheader.us:
; CHECK-GUARD-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-GUARD-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]]
; CHECK-GUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-GUARD-NEXT: br label [[WHILE_BODY3_US:%.*]]
; CHECK-GUARD: while.body3.us:
; CHECK-GUARD-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-GUARD-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]]
; CHECK-GUARD-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[ADD_US]]
; CHECK-GUARD-NEXT: store i32 [[ADD_US]], i32* [[ARRAYIDX_US]], align 4
; CHECK-GUARD-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1
; CHECK-GUARD-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1)
; CHECK-GUARD-NEXT: br i1 [[TMP0]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]]
; CHECK-GUARD: while.cond1.while.end_crit_edge.us:
; CHECK-GUARD-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1
; CHECK-GUARD-NEXT: [[EXITCOND23:%.*]] = icmp eq i32 [[INC6_US]], [[N]]
; CHECK-GUARD-NEXT: br i1 [[EXITCOND23]], label [[WHILE_END7]], label [[WHILE_COND1_PREHEADER_US]]
; CHECK-GUARD: while.end7:
; CHECK-GUARD-NEXT: ret void
;
; CHECK-PHIGUARD-LABEL: @nested(
; CHECK-PHIGUARD-NEXT: entry:
; CHECK-PHIGUARD-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US:%.*]]
; CHECK-PHIGUARD: while.cond1.preheader.us:
; CHECK-PHIGUARD-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-PHIGUARD-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]]
; CHECK-PHIGUARD-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]])
; CHECK-PHIGUARD-NEXT: br label [[WHILE_BODY3_US:%.*]]
; CHECK-PHIGUARD: while.body3.us:
; CHECK-PHIGUARD-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-PHIGUARD-NEXT: [[TMP0:%.*]] = phi i32 [ [[N]], [[WHILE_COND1_PREHEADER_US]] ], [ [[TMP1:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-PHIGUARD-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]]
; CHECK-PHIGUARD-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[ADD_US]]
; CHECK-PHIGUARD-NEXT: store i32 [[ADD_US]], i32* [[ARRAYIDX_US]], align 4
; CHECK-PHIGUARD-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1
; CHECK-PHIGUARD-NEXT: [[TMP1]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP0]], i32 1)
; CHECK-PHIGUARD-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-PHIGUARD-NEXT: br i1 [[TMP2]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]]
; CHECK-PHIGUARD: while.cond1.while.end_crit_edge.us:
; CHECK-PHIGUARD-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1
; CHECK-PHIGUARD-NEXT: [[EXITCOND23:%.*]] = icmp eq i32 [[INC6_US]], [[N]]
; CHECK-PHIGUARD-NEXT: br i1 [[EXITCOND23]], label [[WHILE_END7]], label [[WHILE_COND1_PREHEADER_US]]
; CHECK-PHIGUARD: while.end7:
; CHECK-PHIGUARD-NEXT: ret void
;
; CHECK-REGDEC-LABEL: @nested(
; CHECK-REGDEC-NEXT: entry:
; CHECK-REGDEC-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-REGDEC-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US:%.*]]
; CHECK-REGDEC: while.cond1.preheader.us:
; CHECK-REGDEC-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-REGDEC-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]]
; CHECK-REGDEC-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]])
; CHECK-REGDEC-NEXT: br label [[WHILE_BODY3_US:%.*]]
; CHECK-REGDEC: while.body3.us:
; CHECK-REGDEC-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-REGDEC-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_COND1_PREHEADER_US]] ], [ [[TMP2:%.*]], [[WHILE_BODY3_US]] ]
; CHECK-REGDEC-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]]
; CHECK-REGDEC-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[ADD_US]]
; CHECK-REGDEC-NEXT: store i32 [[ADD_US]], i32* [[ARRAYIDX_US]], align 4
; CHECK-REGDEC-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1
; CHECK-REGDEC-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1)
; CHECK-REGDEC-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-REGDEC-NEXT: br i1 [[TMP3]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]]
; CHECK-REGDEC: while.cond1.while.end_crit_edge.us:
; CHECK-REGDEC-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1
; CHECK-REGDEC-NEXT: [[EXITCOND23:%.*]] = icmp eq i32 [[INC6_US]], [[N]]
; CHECK-REGDEC-NEXT: br i1 [[EXITCOND23]], label [[WHILE_END7]], label [[WHILE_COND1_PREHEADER_US]]
; CHECK-REGDEC: while.end7:
; CHECK-REGDEC-NEXT: ret void
entry: entry:
%cmp20 = icmp eq i32 %N, 0 %cmp20 = icmp eq i32 %N, 0
br i1 %cmp20, label %while.end7, label %while.cond1.preheader.us br i1 %cmp20, label %while.end7, label %while.cond1.preheader.us

View File

@ -66,6 +66,78 @@ for.body: ; preds = %for.body.preheader1
} }
; Same as above but without the nounroll on the remainder loop. Neither loop should be unrolled.
; CHECK-LABEL: @remainder
; CHECK: vector.body:
; CHECK: br i1 %13, label %middle.block, label %vector.body, !llvm.loop !0
; CHECK: middle.block:
; CHECK: br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader13
; CHECK: for.body:
; CHECK: br i1 %exitcond.3, label %for.cond.cleanup.loopexit.unr-lcssa, label %for.body, !llvm.loop !0
; CHECK: for.body.prol.1:
; CHECK: br i1 %prol.iter.cmp.1, label %for.body.prol.2, label %for.body.prol.loopexit.unr-lcssa
; CHECK: for.body.prol.2:
; CHECK: br label %for.body.prol.loopexit.unr-lcssa
define void @remainder(float* %s1, float* %s2, float* %d, i32 %n) {
entry:
%cmp10 = icmp sgt i32 %n, 0
br i1 %cmp10, label %for.body.preheader, label %for.cond.cleanup
for.body.preheader: ; preds = %entry
%min.iters.check = icmp ult i32 %n, 4
br i1 %min.iters.check, label %for.body.preheader13, label %vector.ph
for.body.preheader13: ; preds = %middle.block, %for.body.preheader
%i.011.ph = phi i32 [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
br label %for.body
vector.ph: ; preds = %for.body.preheader
%n.vec = and i32 %n, -4
br label %vector.body
vector.body: ; preds = %vector.body, %vector.ph
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
%0 = getelementptr inbounds float, float* %s1, i32 %index
%1 = bitcast float* %0 to <4 x float>*
%wide.load = load <4 x float>, <4 x float>* %1, align 4
%2 = getelementptr inbounds float, float* %s2, i32 %index
%3 = bitcast float* %2 to <4 x float>*
%wide.load12 = load <4 x float>, <4 x float>* %3, align 4
%4 = fadd fast <4 x float> %wide.load12, %wide.load
%5 = getelementptr inbounds float, float* %d, i32 %index
%6 = bitcast float* %5 to <4 x float>*
store <4 x float> %4, <4 x float>* %6, align 4
%index.next = add i32 %index, 4
%7 = icmp eq i32 %index.next, %n.vec
br i1 %7, label %middle.block, label %vector.body, !llvm.loop !0
middle.block: ; preds = %vector.body
%cmp.n = icmp eq i32 %n.vec, %n
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader13
for.cond.cleanup.loopexit: ; preds = %for.body
br label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %middle.block, %entry
ret void
for.body: ; preds = %for.body.preheader13, %for.body
%i.011 = phi i32 [ %add3, %for.body ], [ %i.011.ph, %for.body.preheader13 ]
%arrayidx = getelementptr inbounds float, float* %s1, i32 %i.011
%8 = load float, float* %arrayidx, align 4
%arrayidx1 = getelementptr inbounds float, float* %s2, i32 %i.011
%9 = load float, float* %arrayidx1, align 4
%add = fadd fast float %9, %8
%arrayidx2 = getelementptr inbounds float, float* %d, i32 %i.011
store float %add, float* %arrayidx2, align 4
%add3 = add nuw nsw i32 %i.011, 1
%exitcond = icmp eq i32 %add3, %n
br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body, !llvm.loop !0
}
; CHECK-LABEL: @nested ; CHECK-LABEL: @nested
; CHECK: for.outer: ; CHECK: for.outer: