Upon further investigation and discussion, this is actually the opposite direction from what we should be taking, and this direction wouldn't solve the motivational problem anyway. Additionally, some more (polly) tests have escaped being updated. So, let's just take a step back here. This reverts commitf3190dedee. This reverts commit749581d21f. This reverts commitf3df87d57e. This reverts commitab1dbcecd6.
391 lines
18 KiB
LLVM
391 lines
18 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -loop-predication -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
|
|
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
|
|
|
|
declare void @llvm.experimental.guard(i1, ...)
|
|
|
|
define i32 @signed_reverse_loop_n_to_lower_limit(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
|
|
; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[LOWERLIMIT:%.*]], 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
|
|
; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[I]], [[LOWERLIMIT]]
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
entry:
|
|
%tmp5 = icmp eq i32 %n, 0
|
|
br i1 %tmp5, label %exit, label %loop.preheader
|
|
|
|
loop.preheader:
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
|
|
%i.next = add nsw i32 %i, -1
|
|
%within.bounds = icmp ult i32 %i.next, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
%i.i64 = zext i32 %i.next to i64
|
|
%array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
|
|
%array.i = load i32, i32* %array.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc, %array.i
|
|
%continue = icmp sgt i32 %i, %lowerlimit
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsigned_reverse_loop_n_to_lower_limit(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
|
|
; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[LOWERLIMIT:%.*]], 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
|
|
; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], [[LOWERLIMIT]]
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
entry:
|
|
%tmp5 = icmp eq i32 %n, 0
|
|
br i1 %tmp5, label %exit, label %loop.preheader
|
|
|
|
loop.preheader:
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
|
|
%i.next = add nsw i32 %i, -1
|
|
%within.bounds = icmp ult i32 %i.next, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
%i.i64 = zext i32 %i.next to i64
|
|
%array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
|
|
%array.i = load i32, i32* %array.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc, %array.i
|
|
%continue = icmp ugt i32 %i, %lowerlimit
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
|
|
; if we predicated the loop, the guard will definitely fail and we will
|
|
; deoptimize early on.
|
|
define i32 @unsigned_reverse_loop_n_to_0(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
|
|
; CHECK-LABEL: @unsigned_reverse_loop_n_to_0(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], false
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
|
|
; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 0
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
entry:
|
|
%tmp5 = icmp eq i32 %n, 0
|
|
br i1 %tmp5, label %exit, label %loop.preheader
|
|
|
|
loop.preheader:
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
|
|
%i.next = add nsw i32 %i, -1
|
|
%within.bounds = icmp ult i32 %i.next, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
%i.i64 = zext i32 %i.next to i64
|
|
%array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
|
|
%array.i = load i32, i32* %array.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc, %array.i
|
|
%continue = icmp ugt i32 %i, 0
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
; do not loop predicate when the range has step -1 and latch has step 1.
|
|
define i32 @reverse_loop_range_step_increment(i32 %n, i32* %array, i32 %length) {
|
|
; CHECK-LABEL: @reverse_loop_range_step_increment(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IRC:%.*]] = phi i32 [ [[I_INC:%.*]], [[LOOP]] ], [ 1, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[IRC]], 1
|
|
; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[IRC]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[IRC]] to i64
|
|
; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 65534
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
entry:
|
|
%tmp5 = icmp eq i32 %n, 0
|
|
br i1 %tmp5, label %exit, label %loop.preheader
|
|
|
|
loop.preheader:
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
|
|
%irc = phi i32 [ %i.inc, %loop ], [ 1, %loop.preheader ]
|
|
%i.inc = add nuw nsw i32 %irc, 1
|
|
%within.bounds = icmp ult i32 %irc, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
%i.i64 = zext i32 %irc to i64
|
|
%array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
|
|
%array.i = load i32, i32* %array.i.ptr, align 4
|
|
%i.next = add nsw i32 %i, -1
|
|
%loop.acc.next = add i32 %loop.acc, %array.i
|
|
%continue = icmp ugt i32 %i, 65534
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
|
|
; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit_equal(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOWERLIMIT:%.*]], 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
|
|
; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sge i32 [[I]], [[LOWERLIMIT]]
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
entry:
|
|
%tmp5 = icmp eq i32 %n, 0
|
|
br i1 %tmp5, label %exit, label %loop.preheader
|
|
|
|
loop.preheader:
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
|
|
%i.next = add nsw i32 %i, -1
|
|
%within.bounds = icmp ult i32 %i.next, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
%i.i64 = zext i32 %i.next to i64
|
|
%array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
|
|
%array.i = load i32, i32* %array.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc, %array.i
|
|
%continue = icmp sge i32 %i, %lowerlimit
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsigned_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
|
|
; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit_equal(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOWERLIMIT:%.*]], 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]]
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
|
|
; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], [[LOWERLIMIT]]
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
entry:
|
|
%tmp5 = icmp eq i32 %n, 0
|
|
br i1 %tmp5, label %exit, label %loop.preheader
|
|
|
|
loop.preheader:
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
|
|
%i.next = add nsw i32 %i, -1
|
|
%within.bounds = icmp ult i32 %i.next, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
%i.i64 = zext i32 %i.next to i64
|
|
%array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
|
|
%array.i = load i32, i32* %array.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc, %array.i
|
|
%continue = icmp uge i32 %i, %lowerlimit
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
|
|
; if we predicated the loop, the guard will definitely fail and we will
|
|
; deoptimize early on.
|
|
define i32 @unsigned_reverse_loop_n_to_1(i32* %array, i32 %length, i32 %n, i32 %lowerlimit) {
|
|
; CHECK-LABEL: @unsigned_reverse_loop_n_to_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], false
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64
|
|
; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], 1
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
entry:
|
|
%tmp5 = icmp eq i32 %n, 0
|
|
br i1 %tmp5, label %exit, label %loop.preheader
|
|
|
|
loop.preheader:
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ]
|
|
%i.next = add nsw i32 %i, -1
|
|
%within.bounds = icmp ult i32 %i.next, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
%i.i64 = zext i32 %i.next to i64
|
|
%array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
|
|
%array.i = load i32, i32* %array.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc, %array.i
|
|
%continue = icmp uge i32 %i, 1
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|