blob: 7176f5ef9ecfef77367d2d48283b46a313b8c1a9 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=indvars -S < %s | FileCheck %s
;
; The loop is not mustprogress and the stride is symbolic, so on its own SCEV
; cannot bound the trip count (a zero stride would loop forever) and
; IndVarSimplify leaves the loop intact. The dominating guard proves %s > 0,
; which makes the exit value computable and rewritten to a closed form.
define i32 @exit_value_guarded_positive_stride(i32 %s, i32 %n) {
; CHECK-LABEL: @exit_value_guarded_positive_stride(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[G:%.*]] = icmp sgt i32 [[S:%.*]], 0
; CHECK-NEXT: br i1 [[G]], label [[PH:%.*]], label [[BAIL:%.*]]
; CHECK: bail:
; CHECK-NEXT: ret i32 -1
; CHECK: ph:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 [[S]])
; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[SMAX]], [[S]]
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP0]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[UMIN]]
; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[S]], i32 1)
; CHECK-NEXT: [[TMP2:%.*]] = udiv i32 [[TMP1]], [[UMAX]]
; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[UMIN]], [[TMP2]]
; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 1
; CHECK-NEXT: ret i32 [[TMP4]]
;
entry:
%g = icmp sgt i32 %s, 0
br i1 %g, label %ph, label %bail
bail:
ret i32 -1
ph:
br label %loop
loop:
%i = phi i32 [ 0, %ph ], [ %i.next, %loop ]
%c = phi i32 [ 0, %ph ], [ %c.next, %loop ]
%c.next = add i32 %c, 1
%i.next = add nsw i32 %i, %s
%cmp = icmp slt i32 %i.next, %n
br i1 %cmp, label %loop, label %exit
exit:
%lcssa = phi i32 [ %c.next, %loop ]
ret i32 %lcssa
}