We'd been optimizing the case where the predicate was obviously true, do the same for the false case. Mostly just for completeness sake, but also may improve compile time in loops which will exit through the guard. Such loops are presumed rare in fastpath code, but may be present down untaken paths, so optimizing for them is still useful. llvm-svn: 357408
1596 lines
72 KiB
LLVM
1596 lines
72 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s
|
|
; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
|
|
|
|
declare void @llvm.experimental.guard(i1, ...)
|
|
|
|
define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check(
|
|
; 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:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check(
|
|
; 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:%.*]] = icmp ult i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ule i32 [[I_NEXT]], [[N]]
|
|
; 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ule i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check(
|
|
; 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:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ugt i32 %length, %i
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_ult_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %length.ptr, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle i32 %n, 0
|
|
%length = load i32, i32* %length.ptr, !range !{i32 1, i32 2147483648}
|
|
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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[I_NEXT]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp sgt i32 %i.next, %n
|
|
br i1 %continue, label %exit, label %loop
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp sle i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_preincrement_latch_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add i32 %i, 1
|
|
%continue = icmp slt i32 %i, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -2
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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 slt i32 [[I]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
|
|
%i.next = add 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 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 slt i32 %i, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_offset_ult_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[N]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%i.offset = add i32 %i, 1
|
|
%within.bounds = icmp ult i32 %i.offset, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add i32 %i, 1
|
|
%continue = icmp sle i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 1, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add i32 [[I]], 1
|
|
; CHECK-NEXT: [[I_NEXT_OFFSET:%.*]] = add i32 [[I_NEXT]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT_OFFSET]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%i.offset = add i32 %i, 1
|
|
%within.bounds = icmp ult i32 %i.offset, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add i32 %i, 1
|
|
%i.next.offset = add i32 %i.next, 1
|
|
%continue = icmp sle i32 %i.next.offset, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nsw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nsw i32 %i, 1
|
|
%continue = icmp ne i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nsw i32 [[I]], 2
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nsw i32 %i, 2
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[J_NEXT]] = add nsw i32 [[J]], 1
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
|
|
|
|
%within.bounds = icmp ult i32 %j, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%j.next = add nsw i32 %j, 1
|
|
%i.next = add nsw i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_start_to_n_offset_iv_range_check(i32* %array, i32 %start.i,
|
|
; CHECK-LABEL: @signed_loop_start_to_n_offset_iv_range_check(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
|
|
; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], [[START_I:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[START_J:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[N]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[START_J]], [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[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]] ], [ [[START_I]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ [[START_J]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[J_NEXT]] = add i32 [[J]], 1
|
|
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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]]
|
|
;
|
|
i32 %start.j, i32 %length,
|
|
i32 %n) {
|
|
entry:
|
|
%tmp5 = icmp sle 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 ], [ %start.i, %loop.preheader ]
|
|
%j = phi i32 [ %j.next, %loop ], [ %start.j, %loop.preheader ]
|
|
|
|
%within.bounds = icmp ult i32 %j, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%j.next = add i32 %j, 1
|
|
%i.next = add i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_different_iv_types(i32* %array, i16 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_different_iv_types(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[J:%.*]] = phi i16 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i16 [[J]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[J_NEXT]] = add i16 [[J]], 1
|
|
; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%j = phi i16 [ %j.next, %loop ], [ 0, %loop.preheader ]
|
|
|
|
%within.bounds = icmp ult i16 %j, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%j.next = add i16 %j, 1
|
|
%i.next = add i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_0_to_n_different_iv_strides(i32* %array, i32 %length, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_0_to_n_different_iv_strides(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[J_NEXT]] = add nsw i32 [[J]], 2
|
|
; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ 0, %loop.preheader ]
|
|
%j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
|
|
|
|
%within.bounds = icmp ult i32 %j, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%j.next = add nsw i32 %j, 2
|
|
%i.next = add nsw i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @two_range_checks(i32* %array.1, i32 %length.1,
|
|
; CHECK-LABEL: @two_range_checks(
|
|
; 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:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_2]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_1]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP2]], [[TMP5]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP6]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
|
|
; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
|
|
; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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]]
|
|
;
|
|
i32* %array.2, i32 %length.2, i32 %n) {
|
|
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 ], [ 0, %loop.preheader ]
|
|
%within.bounds.1 = icmp ult i32 %i, %length.1
|
|
%within.bounds.2 = icmp ult i32 %i, %length.2
|
|
%within.bounds = and i1 %within.bounds.1, %within.bounds.2
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i to i64
|
|
%array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
|
|
%array.1.i = load i32, i32* %array.1.i.ptr, align 4
|
|
%loop.acc.1 = add i32 %loop.acc, %array.1.i
|
|
|
|
%array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
|
|
%array.2.i = load i32, i32* %array.2.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc.1, %array.2.i
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @three_range_checks(i32* %array.1, i32 %length.1,
|
|
; CHECK-LABEL: @three_range_checks(
|
|
; 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:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_3]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
|
|
; CHECK-NEXT: [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
|
|
; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_1]]
|
|
; CHECK-NEXT: [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[TMP9:%.*]] = and i1 [[TMP2]], [[TMP5]]
|
|
; CHECK-NEXT: [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP10]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
|
|
; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
|
|
; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
|
|
; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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]]
|
|
;
|
|
i32* %array.2, i32 %length.2,
|
|
i32* %array.3, i32 %length.3, i32 %n) {
|
|
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 ], [ 0, %loop.preheader ]
|
|
%within.bounds.1 = icmp ult i32 %i, %length.1
|
|
%within.bounds.2 = icmp ult i32 %i, %length.2
|
|
%within.bounds.3 = icmp ult i32 %i, %length.3
|
|
%within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
|
|
%within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i to i64
|
|
%array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
|
|
%array.1.i = load i32, i32* %array.1.i.ptr, align 4
|
|
%loop.acc.1 = add i32 %loop.acc, %array.1.i
|
|
|
|
%array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
|
|
%array.2.i = load i32, i32* %array.2.i.ptr, align 4
|
|
%loop.acc.2 = add i32 %loop.acc.1, %array.2.i
|
|
|
|
%array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
|
|
%array.3.i = load i32, i32* %array.3.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc.2, %array.3.i
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @three_guards(i32* %array.1, i32 %length.1,
|
|
; CHECK-LABEL: @three_guards(
|
|
; 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:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_1]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
|
|
; CHECK-NEXT: [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
|
|
; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_3]]
|
|
; CHECK-NEXT: [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
|
|
; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP5]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP8]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
|
|
; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
|
|
; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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]]
|
|
;
|
|
i32* %array.2, i32 %length.2,
|
|
i32* %array.3, i32 %length.3, i32 %n) {
|
|
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 ], [ 0, %loop.preheader ]
|
|
|
|
%within.bounds.1 = icmp ult i32 %i, %length.1
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i to i64
|
|
%array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
|
|
%array.1.i = load i32, i32* %array.1.i.ptr, align 4
|
|
%loop.acc.1 = add i32 %loop.acc, %array.1.i
|
|
|
|
%within.bounds.2 = icmp ult i32 %i, %length.2
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
|
|
|
|
%array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
|
|
%array.2.i = load i32, i32* %array.2.i.ptr, align 4
|
|
%loop.acc.2 = add i32 %loop.acc.1, %array.2.i
|
|
|
|
%within.bounds.3 = icmp ult i32 %i, %length.3
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
|
|
|
|
%array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
|
|
%array.3.i = load i32, i32* %array.3.i.ptr, align 4
|
|
%loop.acc.next = add i32 %loop.acc.2, %array.3.i
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) {
|
|
; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition(
|
|
; 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:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[UNRELATED_COND]], [[TMP2]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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 ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
%unrelated.cond = icmp ult i32 %x, %length
|
|
%guard.cond = and i1 %within.bounds, %unrelated.cond
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
; Don't change the guard condition if there were no widened subconditions
|
|
define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
|
|
; CHECK-LABEL: @test_no_widened_conditions(
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[UNRELATED_COND_1:%.*]] = icmp eq i32 [[X1:%.*]], [[I]]
|
|
; CHECK-NEXT: [[UNRELATED_COND_2:%.*]] = icmp eq i32 [[X2:%.*]], [[I]]
|
|
; CHECK-NEXT: [[UNRELATED_COND_3:%.*]] = icmp eq i32 [[X3:%.*]], [[I]]
|
|
; CHECK-NEXT: [[UNRELATED_COND_AND_1:%.*]] = and i1 [[UNRELATED_COND_1]], [[UNRELATED_COND_2]]
|
|
; CHECK-NEXT: [[GUARD_COND:%.*]] = and i1 [[UNRELATED_COND_AND_1]], [[UNRELATED_COND_3]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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 ], [ 0, %loop.preheader ]
|
|
%unrelated.cond.1 = icmp eq i32 %x1, %i
|
|
%unrelated.cond.2 = icmp eq i32 %x2, %i
|
|
%unrelated.cond.3 = icmp eq i32 %x3, %i
|
|
%unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
|
|
%guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
|
|
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle 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]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[BOUND:%.*]] = add i32 [[I]], [[X:%.*]]
|
|
; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[BOUND]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nsw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ %start, %loop.preheader ]
|
|
%bound = add i32 %i, %x
|
|
%within.bounds = icmp ult i32 %i, %bound
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nsw i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) {
|
|
; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP5:%.*]] = icmp sle 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]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp eq i32 [[I]], [[X:%.*]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nsw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
|
|
; 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 sle 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 ], [ %start, %loop.preheader ]
|
|
%guard.cond = icmp eq i32 %i, %x
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nsw i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) {
|
|
; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length(
|
|
; 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:%.*]] = zext i16 [[LENGTH_I16:%.*]] to i32
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[TMP0]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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 ], [ 0, %loop.preheader ]
|
|
%length = zext i16 %length.i16 to i32
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) {
|
|
; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length(
|
|
; 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]]
|
|
; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH_UDIV]]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
|
|
; 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 ], [ 0, %loop.preheader ]
|
|
%length.udiv = udiv i32 %length, %divider
|
|
%within.bounds = icmp ult i32 %i, %length.udiv
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp ult i32 %i.next, %n
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|
|
|
|
|
|
; This is a case where the length information tells us that the guard
|
|
; must trigger on some iteration.
|
|
define i32 @provably_taken(i32* %array, i32* %length.ptr) {
|
|
; CHECK-LABEL: @provably_taken(
|
|
; CHECK-NEXT: loop.preheader:
|
|
; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !1
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 0, [[LENGTH]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], 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]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ]
|
|
; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] 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: [[I_NEXT]] = add nuw i32 [[I]], 1
|
|
; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], 200
|
|
; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: ret i32 [[RESULT]]
|
|
;
|
|
loop.preheader:
|
|
%length = load i32, i32* %length.ptr, !range !{i32 0, i32 50}
|
|
br label %loop
|
|
|
|
loop:
|
|
%loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
|
|
%within.bounds = icmp ult i32 %i, %length
|
|
call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
|
|
|
|
%i.i64 = zext i32 %i 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
|
|
|
|
%i.next = add nuw i32 %i, 1
|
|
%continue = icmp slt i32 %i.next, 200
|
|
br i1 %continue, label %loop, label %exit
|
|
|
|
exit:
|
|
%result = phi i32 [ %loop.acc.next, %loop ]
|
|
ret i32 %result
|
|
}
|