Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -2148,15 +2148,11 @@ if (!C) continue; - // Ignore negative constants, as the code below doesn't handle them - // correctly. TODO: Remove this restriction. - if (!C->getValue().isStrictlyPositive()) continue; - /* Add new PHINode. */ PHINode *NewPH = PHINode::Create(DestTy, 2, "IV.S.", PH); /* create new increment. '++d' in above example. */ - Constant *CFP = ConstantFP::get(DestTy, C->getZExtValue()); + Constant *CFP = ConstantFP::get(DestTy, C->getSExtValue()); BinaryOperator *NewIncr = BinaryOperator::Create(Incr->getOpcode() == Instruction::Add ? Instruction::FAdd : Instruction::FSub, Index: llvm/test/CodeGen/X86/negative-stride-fptosi-user.ll =================================================================== --- llvm/test/CodeGen/X86/negative-stride-fptosi-user.ll +++ llvm/test/CodeGen/X86/negative-stride-fptosi-user.ll @@ -9,27 +9,28 @@ define void @foo(i32 %N) nounwind { ; CHECK-LABEL: foo: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: pushq %rbp ; CHECK-NEXT: pushq %rbx -; CHECK-NEXT: pushq %rax +; CHECK-NEXT: subq $16, %rsp ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: jns .LBB0_3 ; CHECK-NEXT: # %bb.1: # %bb.preheader ; CHECK-NEXT: movl %edi, %ebx -; CHECK-NEXT: xorl %ebp, %ebp +; CHECK-NEXT: xorpd %xmm0, %xmm0 ; CHECK-NEXT: .p2align 4, 0x90 ; CHECK-NEXT: .LBB0_2: # %bb ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: xorps %xmm0, %xmm0 -; CHECK-NEXT: cvtsi2sd %ebp, %xmm0 +; CHECK-NEXT: movsd %xmm0, 8(%rsp) # 8-byte Spill +; CHECK-NEXT: movsd 8(%rsp), %xmm0 # 8-byte Reload +; CHECK-NEXT: # xmm0 = mem[0],zero ; CHECK-NEXT: callq bar -; CHECK-NEXT: decl %ebp -; CHECK-NEXT: cmpl %ebp, %ebx +; CHECK-NEXT: movsd 8(%rsp), %xmm0 # 8-byte Reload +; CHECK-NEXT: # xmm0 = mem[0],zero +; CHECK-NEXT: addsd .LCPI0_0(%rip), %xmm0 +; CHECK-NEXT: incl %ebx ; CHECK-NEXT: jne .LBB0_2 ; CHECK-NEXT: .LBB0_3: # %return -; CHECK-NEXT: addq $8, %rsp +; CHECK-NEXT: addq $16, %rsp ; CHECK-NEXT: popq %rbx -; CHECK-NEXT: popq %rbp ; CHECK-NEXT: retq entry: %0 = icmp slt i32 %N, 0 ; [#uses=1] Index: llvm/test/Transforms/LoopStrengthReduce/X86/2008-08-14-ShadowIV.ll =================================================================== --- llvm/test/Transforms/LoopStrengthReduce/X86/2008-08-14-ShadowIV.ll +++ llvm/test/Transforms/LoopStrengthReduce/X86/2008-08-14-ShadowIV.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -loop-reduce -S -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s ; Provide legal integer types. @@ -5,122 +6,201 @@ define void @foobar(i32 %n) nounwind { - -; CHECK-LABEL: foobar( -; CHECK: phi double +; CHECK-LABEL: @foobar( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[COND]], label [[RETURN:%.*]], label [[BB_NPH:%.*]] +; CHECK: bb.nph: +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[IV_S_:%.*]] = phi double [ 0.000000e+00, [[BB_NPH]] ], [ [[IV_S_NEXT_:%.*]], [[BB]] ] +; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ 0, [[BB_NPH]] ], [ [[INDVAR_NEXT:%.*]], [[BB]] ] +; CHECK-NOT: uitofp +; CHECK-NEXT: tail call void @bar(i32 [[I_03]]) #0 +; CHECK-NEXT: tail call void @foo(double [[IV_S_]]) #0 +; CHECK-NEXT: [[IV_S_NEXT_]] = fadd double [[IV_S_]], 1.000000e+00 +; CHECK-NEXT: [[INDVAR_NEXT]] = add nuw nsw i32 [[I_03]], 1 +; CHECK-NEXT: [[SCMP:%.*]] = icmp uge i32 [[INDVAR_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[SCMP]], label [[RETURN_LOOPEXIT:%.*]], label [[BB]] +; CHECK: return.loopexit: +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: ret void +; entry: - %cond = icmp eq i32 %n, 0 ; :0 [#uses=2] - br i1 %cond, label %return, label %bb.nph + %cond = icmp eq i32 %n, 0 ; :0 [#uses=2] + br i1 %cond, label %return, label %bb.nph bb.nph: ; preds = %entry - %umax = select i1 %cond, i32 1, i32 %n ; [#uses=1] - br label %bb + %umax = select i1 %cond, i32 1, i32 %n ; [#uses=1] + br label %bb bb: ; preds = %bb, %bb.nph - %i.03 = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=3] - tail call void @bar( i32 %i.03 ) nounwind - %tmp1 = uitofp i32 %i.03 to double ; :1 [#uses=1] - tail call void @foo( double %tmp1 ) nounwind - %indvar.next = add nsw nuw i32 %i.03, 1 ; [#uses=2] - %exitcond = icmp eq i32 %indvar.next, %umax ; [#uses=1] - br i1 %exitcond, label %return, label %bb + %i.03 = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=3] + tail call void @bar( i32 %i.03 ) nounwind + %tmp1 = uitofp i32 %i.03 to double ; :1 [#uses=1] + tail call void @foo( double %tmp1 ) nounwind + %indvar.next = add nsw nuw i32 %i.03, 1 ; [#uses=2] + %exitcond = icmp eq i32 %indvar.next, %umax ; [#uses=1] + br i1 %exitcond, label %return, label %bb return: ; preds = %bb, %entry - ret void + ret void } ; Unable to eliminate cast because the mantissa bits for double are not enough ; to hold all of i64 IV bits. define void @foobar2(i64 %n) nounwind { - -; CHECK-LABEL: foobar2( -; CHECK-NOT: phi double -; CHECK-NOT: phi float +; CHECK-LABEL: @foobar2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[COND]], label [[RETURN:%.*]], label [[BB_NPH:%.*]] +; CHECK: bb.nph: +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[I_03:%.*]] = phi i64 [ 0, [[BB_NPH]] ], [ [[INDVAR_NEXT:%.*]], [[BB]] ] +; CHECK-NEXT: [[TMP:%.*]] = trunc i64 [[I_03]] to i32 +; CHECK-NEXT: tail call void @bar(i32 [[TMP]]) #0 +; CHECK-NEXT: [[TMP2:%.*]] = uitofp i64 [[I_03]] to double +; CHECK-NEXT: tail call void @foo(double [[TMP2]]) #0 +; CHECK-NEXT: [[INDVAR_NEXT]] = add nuw nsw i64 [[I_03]], 1 +; CHECK-NEXT: [[SCMP:%.*]] = icmp uge i64 [[INDVAR_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[SCMP]], label [[RETURN_LOOPEXIT:%.*]], label [[BB]] +; CHECK: return.loopexit: +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: ret void +; entry: - %cond = icmp eq i64 %n, 0 ; :0 [#uses=2] - br i1 %cond, label %return, label %bb.nph + %cond = icmp eq i64 %n, 0 ; :0 [#uses=2] + br i1 %cond, label %return, label %bb.nph bb.nph: ; preds = %entry - %umax = select i1 %cond, i64 1, i64 %n ; [#uses=1] - br label %bb + %umax = select i1 %cond, i64 1, i64 %n ; [#uses=1] + br label %bb bb: ; preds = %bb, %bb.nph - %i.03 = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=3] - %tmp1 = trunc i64 %i.03 to i32 ; :1 [#uses=1] - tail call void @bar( i32 %tmp1 ) nounwind - %tmp2 = uitofp i64 %i.03 to double ; :2 [#uses=1] - tail call void @foo( double %tmp2 ) nounwind - %indvar.next = add nsw nuw i64 %i.03, 1 ; [#uses=2] - %exitcond = icmp eq i64 %indvar.next, %umax ; [#uses=1] - br i1 %exitcond, label %return, label %bb + %i.03 = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=3] + %tmp1 = trunc i64 %i.03 to i32 ; :1 [#uses=1] + tail call void @bar( i32 %tmp1 ) nounwind + %tmp2 = uitofp i64 %i.03 to double ; :2 [#uses=1] + tail call void @foo( double %tmp2 ) nounwind + %indvar.next = add nsw nuw i64 %i.03, 1 ; [#uses=2] + %exitcond = icmp eq i64 %indvar.next, %umax ; [#uses=1] + br i1 %exitcond, label %return, label %bb return: ; preds = %bb, %entry - ret void + ret void } ; Unable to eliminate cast due to potentional overflow. define void @foobar3() nounwind { - -; CHECK-LABEL: foobar3( -; CHECK-NOT: phi double -; CHECK-NOT: phi float +; CHECK-LABEL: @foobar3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 (...) @nn() #0 +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[COND]], label [[RETURN:%.*]], label [[BB_PREHEADER:%.*]] +; CHECK: bb.preheader: +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ [[INDVAR_NEXT:%.*]], [[BB]] ], [ 0, [[BB_PREHEADER]] ] +; CHECK-NEXT: tail call void @bar(i32 [[I_03]]) #0 +; CHECK-NEXT: [[TMP2:%.*]] = uitofp i32 [[I_03]] to double +; CHECK-NEXT: tail call void @foo(double [[TMP2]]) #0 +; CHECK-NEXT: [[INDVAR_NEXT]] = add nuw nsw i32 [[I_03]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = tail call i32 (...) @nn() #0 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ugt i32 [[TMP4]], [[INDVAR_NEXT]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[BB]], label [[RETURN_LOOPEXIT:%.*]] +; CHECK: return.loopexit: +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: ret void +; entry: - %tmp0 = tail call i32 (...) @nn( ) nounwind ; :0 [#uses=1] - %cond = icmp eq i32 %tmp0, 0 ; :1 [#uses=1] - br i1 %cond, label %return, label %bb + %tmp0 = tail call i32 (...) @nn( ) nounwind ; :0 [#uses=1] + %cond = icmp eq i32 %tmp0, 0 ; :1 [#uses=1] + br i1 %cond, label %return, label %bb bb: ; preds = %bb, %entry - %i.03 = phi i32 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=3] - tail call void @bar( i32 %i.03 ) nounwind - %tmp2 = uitofp i32 %i.03 to double ; :2 [#uses=1] - tail call void @foo( double %tmp2 ) nounwind - %indvar.next = add nuw nsw i32 %i.03, 1 ; :3 [#uses=2] - %tmp4 = tail call i32 (...) @nn( ) nounwind ; :4 [#uses=1] - %exitcond = icmp ugt i32 %tmp4, %indvar.next ; :5 [#uses=1] - br i1 %exitcond, label %bb, label %return + %i.03 = phi i32 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=3] + tail call void @bar( i32 %i.03 ) nounwind + %tmp2 = uitofp i32 %i.03 to double ; :2 [#uses=1] + tail call void @foo( double %tmp2 ) nounwind + %indvar.next = add nuw nsw i32 %i.03, 1 ; :3 [#uses=2] + %tmp4 = tail call i32 (...) @nn( ) nounwind ; :4 [#uses=1] + %exitcond = icmp ugt i32 %tmp4, %indvar.next ; :5 [#uses=1] + br i1 %exitcond, label %bb, label %return return: ; preds = %bb, %entry - ret void + ret void } ; Unable to eliminate cast due to overflow. define void @foobar4() nounwind { - -; CHECK-LABEL: foobar4( -; CHECK-NOT: phi double -; CHECK-NOT: phi float +; CHECK-LABEL: @foobar4( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[BB_NPH:%.*]] +; CHECK: bb.nph: +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[BB]] ], [ 0, [[BB_NPH]] ] +; CHECK-NEXT: tail call void @bar(i32 [[LSR_IV]]) #0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[LSR_IV]] to i8 +; CHECK-NEXT: [[TMP3:%.*]] = uitofp i8 [[TMP4]] to double +; CHECK-NEXT: tail call void @foo(double [[TMP3]]) #0 +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8 +; CHECK-NEXT: [[TMP:%.*]] = sext i8 [[TMP1]] to i32 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[TMP]], 32767 +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw i32 [[LSR_IV]], 1 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[RETURN:%.*]], label [[BB]] +; CHECK: return: +; CHECK-NEXT: ret void +; entry: - br label %bb.nph + br label %bb.nph bb.nph: ; preds = %entry - br label %bb + br label %bb bb: ; preds = %bb, %bb.nph - %i.03 = phi i8 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=3] - %tmp2 = sext i8 %i.03 to i32 ; :0 [#uses=1] - tail call void @bar( i32 %tmp2 ) nounwind - %tmp3 = uitofp i8 %i.03 to double ; :1 [#uses=1] - tail call void @foo( double %tmp3 ) nounwind - %indvar.next = add nsw nuw i8 %i.03, 1 ; [#uses=2] - %tmp = sext i8 %indvar.next to i32 - %exitcond = icmp eq i32 %tmp, 32767 ; [#uses=1] - br i1 %exitcond, label %return, label %bb + %i.03 = phi i8 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=3] + %tmp2 = sext i8 %i.03 to i32 ; :0 [#uses=1] + tail call void @bar( i32 %tmp2 ) nounwind + %tmp3 = uitofp i8 %i.03 to double ; :1 [#uses=1] + tail call void @foo( double %tmp3 ) nounwind + %indvar.next = add nsw nuw i8 %i.03, 1 ; [#uses=2] + %tmp = sext i8 %indvar.next to i32 + %exitcond = icmp eq i32 %tmp, 32767 ; [#uses=1] + br i1 %exitcond, label %return, label %bb return: ; preds = %bb, %entry - ret void + ret void } ; Unable to eliminate cast because the integer IV overflows (accum exceeds ; SINT_MAX). define i32 @foobar5() { -; CHECK-LABEL: foobar5( -; CHECK-NOT: phi double -; CHECK-NOT: phi float +; CHECK-LABEL: @foobar5( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[LOOP]] ], [ 11, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ -3220, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[TMP1:%.*]] = sitofp i32 [[ACCUM]] to double +; CHECK-NEXT: tail call void @foo(double [[TMP1]]) #0 +; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], 9597741 +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ugt i32 [[LSR_IV_NEXT]], 235 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret i32 [[ACCUM_NEXT]] +; entry: br label %loop @@ -141,8 +221,23 @@ ; Can eliminate if we set nsw and, thus, think that we don't overflow SINT_MAX. define i32 @foobar6() { -; CHECK-LABEL: foobar6( -; CHECK: phi double +; CHECK-LABEL: @foobar6( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[LOOP]] ], [ 11, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[IV_S_:%.*]] = phi double [ -3.220000e+03, [[ENTRY]] ], [ [[IV_S_NEXT_:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ -3220, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP]] ] +; CHECK-NOT: sitofp +; CHECK-NEXT: tail call void @foo(double [[IV_S_]]) #0 +; CHECK-NEXT: [[IV_S_NEXT_]] = fadd double [[IV_S_]], 0x41624E65A0000000 +; CHECK-NEXT: [[ACCUM_NEXT]] = add nsw i32 [[ACCUM]], 9597741 +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ugt i32 [[LSR_IV_NEXT]], 235 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret i32 [[ACCUM_NEXT]] +; entry: br label %loop @@ -165,9 +260,21 @@ ; UINT_MAX). define i32 @foobar7() { -; CHECK-LABEL: foobar7( -; CHECK-NOT: phi double -; CHECK-NOT: phi float +; CHECK-LABEL: @foobar7( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[LOOP]] ], [ 11, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ -3220, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[TMP1:%.*]] = uitofp i32 [[ACCUM]] to double +; CHECK-NEXT: tail call void @foo(double [[TMP1]]) #0 +; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], 9597741 +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ugt i32 [[LSR_IV_NEXT]], 235 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret i32 [[ACCUM_NEXT]] +; entry: br label %loop @@ -188,8 +295,23 @@ ; Can eliminate if we set nuw and, thus, think that we don't overflow UINT_MAX. define i32 @foobar8() { -; CHECK-LABEL: foobar8( -; CHECK: phi double +; CHECK-LABEL: @foobar8( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[LOOP]] ], [ 11, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[IV_S_:%.*]] = phi double [ 0x41EFFFFE6D800000, [[ENTRY]] ], [ [[IV_S_NEXT_:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ -3220, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP]] ] +; CHECK-NOT: uitofp +; CHECK-NEXT: tail call void @foo(double [[IV_S_]]) #0 +; CHECK-NEXT: [[IV_S_NEXT_]] = fadd double [[IV_S_]], 0x41624E65A0000000 +; CHECK-NEXT: [[ACCUM_NEXT]] = add nuw i32 [[ACCUM]], 9597741 +; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ugt i32 [[LSR_IV_NEXT]], 235 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret i32 [[ACCUM_NEXT]] +; entry: br label %loop @@ -208,6 +330,59 @@ ret i32 %accum.next } +; void negative_step(int n) { +; for (int i = 10; i > n; i += -1) +; foo((double)i); +; } +; +; Transformed to: +; +; void negative_step(int n) { +; for (int i = 10, double d = 10.0; i > n; i += -1, d += -1.0) +; foo(d); +; } + +define void @negative_step(i32 %n) { +; CHECK-LABEL: @negative_step( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[WHILE_HEADER:%.*]] +; CHECK: while.header: +; CHECK-NEXT: [[IV_S_:%.*]] = phi double [ 1.000000e+01, [[ENTRY:%.*]] ], [ [[IV_S_NEXT_:%.*]], [[LATCH:%.*]] ] +; CHECK-NEXT: [[I:%.*]] = phi i32 [ 10, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LATCH:%.*]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[I]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[BODY:%.*]], label [[EXIT:%.*]] +; CHECK: body: +; CHECK-NOT: sitofp +; CHECK-NEXT: call void @foo(double [[IV_S_]]) +; CHECK-NEXT: br label [[LATCH]] +; CHECK: latch: +; CHECK-NEXT: [[IV_S_NEXT_]] = fadd double [[IV_S_]], -1.000000e+00 +; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 +; CHECK-NEXT: br label [[WHILE_HEADER]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %while.header + +while.header: + %i = phi i32 [ 10, %entry ], [ %i.next, %latch ] + %cond = icmp sgt i32 %i, %n + br i1 %cond, label %body, label %exit + +body: + %cast = sitofp i32 %i to double + call void @foo(double %cast) + br label %latch + +latch: + %i.next = add nsw i32 %i, -1 + br label %while.header + +exit: + ret void +} + declare void @bar(i32) declare void @foo(double)