| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt -S -passes='loop(loop-reduce)' -mtriple=riscv64 < %s | FileCheck %s --check-prefix=BASE | |
| ; RUN: opt -S -passes='loop(loop-reduce)' -mtriple=riscv64 -mattr=+experimental-zibi < %s | FileCheck %s --check-prefix=ZIBI | |
| ; LSR only changes relational exits when the target prefers the exact exit | |
| ; value as an equality immediate. The BASE checks ensure the default target | |
| ; retains the relational form. | |
| define void @increment_to_17(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @increment_to_17( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp slt i32 [[START]], 17 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[IV]], 16 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @increment_to_17( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0:[0-9]+]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp slt i32 [[START]], 17 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp slt i32 %start, 17 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, 1 | |
| %continue = icmp slt i32 %iv, 16 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @decrement_to_17(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @decrement_to_17( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 18 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @decrement_to_17( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp sgt i32 %start, 17 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %continue = icmp sgt i32 %iv, 18 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @decrement_by_two_to_17(ptr %p) { | |
| ; BASE-LABEL: define void @decrement_by_two_to_17( | |
| ; BASE-SAME: ptr [[P:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ 1003, %[[ENTRY]] ] | |
| ; BASE-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV]], -2 | |
| ; BASE-NEXT: store volatile i32 [[TMP0]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], -2 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[LSR_IV_NEXT]], 19 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @decrement_by_two_to_17( | |
| ; ZIBI-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ 1001, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -2 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i32 [ 1001, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -2 | |
| %continue = icmp sgt i32 %iv, 19 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @outside_zibi_immediate_range(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @outside_zibi_immediate_range( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 32 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 33 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @outside_zibi_immediate_range( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 32 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 33 | |
| ; ZIBI-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp sgt i32 %start, 32 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %continue = icmp sgt i32 %iv, 33 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @dynamic_exit_value(ptr %p, i32 %start, i32 %limit) { | |
| ; BASE-LABEL: define void @dynamic_exit_value( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]], i32 [[LIMIT:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], [[LIMIT]] | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], [[LIMIT]] | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @dynamic_exit_value( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]], i32 [[LIMIT:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], [[LIMIT]] | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], [[LIMIT]] | |
| ; ZIBI-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp sgt i32 %start, %limit | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %continue = icmp sgt i32 %iv, %limit | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @poison_no_self_wrap(ptr %p) { | |
| ; BASE-LABEL: define void @poison_no_self_wrap( | |
| ; BASE-SAME: ptr [[P:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; BASE-NEXT: [[COUNT:%.*]] = phi i8 [ -56, %[[ENTRY]] ], [ [[COUNT_NEXT:%.*]], %[[LOOP]] ] | |
| ; BASE-NEXT: [[IV_FROZEN:%.*]] = freeze i8 [[IV]] | |
| ; BASE-NEXT: store volatile i8 [[IV_FROZEN]], ptr [[P]], align 1 | |
| ; BASE-NEXT: [[IV_NEXT]] = add nsw i8 [[IV]], 2 | |
| ; BASE-NEXT: [[COUNT_NEXT]] = add i8 [[COUNT]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp ugt i8 [[COUNT_NEXT]], 0 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @poison_no_self_wrap( | |
| ; ZIBI-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: [[COUNT:%.*]] = phi i8 [ -56, %[[ENTRY]] ], [ [[COUNT_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: [[IV_FROZEN:%.*]] = freeze i8 [[IV]] | |
| ; ZIBI-NEXT: store volatile i8 [[IV_FROZEN]], ptr [[P]], align 1 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add nsw i8 [[IV]], 2 | |
| ; ZIBI-NEXT: [[COUNT_NEXT]] = add i8 [[COUNT]], -1 | |
| ; ZIBI-NEXT: [[CONTINUE:%.*]] = icmp ugt i8 [[COUNT_NEXT]], 0 | |
| ; ZIBI-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ] | |
| %count = phi i8 [ -56, %entry ], [ %count.next, %loop ] | |
| %iv.frozen = freeze i8 %iv | |
| store volatile i8 %iv.frozen, ptr %p | |
| %iv.next = add nsw i8 %iv, 2 | |
| %count.next = add i8 %count, -1 | |
| %continue = icmp ugt i8 %count.next, 0 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| ; LSR may drop poison-generating flags when it rewrites the IV. Make sure the | |
| ; equality rewrite does not rely on nowrap flags derived from those flags. | |
| define void @drop_poison_on_postinc(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @drop_poison_on_postinc( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: [[IV_FROZEN:%.*]] = freeze i32 [[IV]] | |
| ; BASE-NEXT: store volatile i32 [[IV_FROZEN]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 18 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @drop_poison_on_postinc( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: [[IV_FROZEN:%.*]] = freeze i32 [[IV]] | |
| ; ZIBI-NEXT: store volatile i32 [[IV_FROZEN]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp sgt i32 %start, 17 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| %iv.frozen = freeze i32 %iv | |
| store volatile i32 %iv.frozen, ptr %p | |
| %iv.next = add nsw i32 %iv, -1 | |
| %continue = icmp sgt i32 %iv, 18 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @false_successor_continues(ptr %p) { | |
| ; BASE-LABEL: define void @false_successor_continues( | |
| ; BASE-SAME: ptr [[P:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ 32, %[[ENTRY]] ] | |
| ; BASE-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV]], -1 | |
| ; BASE-NEXT: store volatile i32 [[TMP0]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], -1 | |
| ; BASE-NEXT: [[EXIT_COND:%.*]] = icmp sle i32 [[LSR_IV_NEXT]], 18 | |
| ; BASE-NEXT: br i1 [[EXIT_COND]], label %[[EXIT:.*]], label %[[LOOP]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @false_successor_continues( | |
| ; ZIBI-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ 31, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp eq i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[EXIT:.*]], label %[[LOOP]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i32 [ 31, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %exit.cond = icmp sle i32 %iv, 18 | |
| br i1 %exit.cond, label %exit, label %loop | |
| exit: | |
| ret void | |
| } | |
| define void @zero_exit_value(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @zero_exit_value( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 0 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 0 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @zero_exit_value( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 0 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 0 | |
| ; ZIBI-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp sgt i32 %start, 0 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %continue = icmp sgt i32 %iv, 0 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @minus_one_exit_value(ptr %p) { | |
| ; BASE-LABEL: define void @minus_one_exit_value( | |
| ; BASE-SAME: ptr [[P:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ 33, %[[ENTRY]] ] | |
| ; BASE-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV]], -2 | |
| ; BASE-NEXT: store volatile i32 [[TMP0]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], -2 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[LSR_IV_NEXT]], 1 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @minus_one_exit_value( | |
| ; ZIBI-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ 31, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -2 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], -1 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i32 [ 31, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -2 | |
| %continue = icmp sgt i32 %iv, 1 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @minus_one_relational_exit(ptr %p) { | |
| ; BASE-LABEL: define void @minus_one_relational_exit( | |
| ; BASE-SAME: ptr [[P:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ 32, %[[ENTRY]] ] | |
| ; BASE-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV]], -1 | |
| ; BASE-NEXT: store volatile i32 [[TMP0]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[LSR_IV_NEXT]], -1 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @minus_one_relational_exit( | |
| ; ZIBI-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ 32, %[[ENTRY]] ] | |
| ; ZIBI-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV]], -1 | |
| ; ZIBI-NEXT: store volatile i32 [[TMP0]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], -1 | |
| ; ZIBI-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[LSR_IV_NEXT]], -1 | |
| ; ZIBI-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i32 [ 31, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %continue = icmp sgt i32 %iv, -1 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @shared_condition(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @shared_condition( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 18 | |
| ; BASE-NEXT: call void @use_condition(i1 [[CONTINUE]]) | |
| ; BASE-NEXT: [[LOOP_TERMCOND:%.*]] = icmp sgt i32 [[IV]], 18 | |
| ; BASE-NEXT: br i1 [[LOOP_TERMCOND]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @shared_condition( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[IV]], 18 | |
| ; ZIBI-NEXT: call void @use_condition(i1 [[CONTINUE]]) | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp sgt i32 %start, 17 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %continue = icmp sgt i32 %iv, 18 | |
| call void @use_condition(i1 %continue) | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @increment_to_17_samesign(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @increment_to_17_samesign( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp ult i32 [[START]], 17 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp samesign ult i32 [[IV]], 16 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @increment_to_17_samesign( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp ult i32 [[START]], 17 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp ult i32 %start, 17 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, 1 | |
| %continue = icmp samesign ult i32 %iv, 16 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @decrement_to_17_samesign(ptr %p, i32 %start) { | |
| ; BASE-LABEL: define void @decrement_to_17_samesign( | |
| ; BASE-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*:]] | |
| ; BASE-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; BASE-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; BASE: [[LOOP_PREHEADER]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp samesign ugt i32 [[IV]], 18 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; BASE: [[EXIT_LOOPEXIT]]: | |
| ; BASE-NEXT: br label %[[EXIT]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @decrement_to_17_samesign( | |
| ; ZIBI-SAME: ptr [[P:%.*]], i32 [[START:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*:]] | |
| ; ZIBI-NEXT: [[ENTER:%.*]] = icmp sgt i32 [[START]], 17 | |
| ; ZIBI-NEXT: br i1 [[ENTER]], label %[[LOOP_PREHEADER:.*]], label %[[EXIT:.*]] | |
| ; ZIBI: [[LOOP_PREHEADER]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ [[START]], %[[LOOP_PREHEADER]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT_LOOPEXIT:.*]] | |
| ; ZIBI: [[EXIT_LOOPEXIT]]: | |
| ; ZIBI-NEXT: br label %[[EXIT]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| %enter = icmp sgt i32 %start, 17 | |
| br i1 %enter, label %loop, label %exit | |
| loop: | |
| %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -1 | |
| %continue = icmp samesign ugt i32 %iv, 18 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| define void @decrement_by_two_to_17_samesign(ptr %p) { | |
| ; BASE-LABEL: define void @decrement_by_two_to_17_samesign( | |
| ; BASE-SAME: ptr [[P:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ 1003, %[[ENTRY]] ] | |
| ; BASE-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV]], -2 | |
| ; BASE-NEXT: store volatile i32 [[TMP0]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV]], -2 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp samesign ugt i32 [[LSR_IV_NEXT]], 19 | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @decrement_by_two_to_17_samesign( | |
| ; ZIBI-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ 1001, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add i32 [[IV]], -2 | |
| ; ZIBI-NEXT: [[LSR_EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 17 | |
| ; ZIBI-NEXT: br i1 [[LSR_EXITCOND]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i32 [ 1001, %entry ], [ %iv.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add i32 %iv, -2 | |
| %continue = icmp samesign ugt i32 %iv, 19 | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| ; The IV has period 8 and the exact exit count is also 8. Its exit value was | |
| ; already visited on the first iteration, so an equality exit would exit early. | |
| define void @exit_count_reaches_recurrence_period(ptr %p) { | |
| ; BASE-LABEL: define void @exit_count_reaches_recurrence_period( | |
| ; BASE-SAME: ptr [[P:%.*]]) { | |
| ; BASE-NEXT: [[ENTRY:.*]]: | |
| ; BASE-NEXT: br label %[[LOOP:.*]] | |
| ; BASE: [[LOOP]]: | |
| ; BASE-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ -536870912, %[[ENTRY]] ] | |
| ; BASE-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; BASE-NEXT: [[LIMIT:%.*]] = phi i32 [ -1, %[[ENTRY]] ], [ [[LIMIT_NEXT:%.*]], %[[LOOP]] ] | |
| ; BASE-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; BASE-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 536870912 | |
| ; BASE-NEXT: [[LIMIT_NEXT]] = add nuw i32 [[LIMIT]], -1 | |
| ; BASE-NEXT: [[LSR_IV_NEXT]] = add i32 [[LSR_IV]], 536870912 | |
| ; BASE-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[LSR_IV_NEXT]], [[LIMIT]] | |
| ; BASE-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; BASE: [[EXIT]]: | |
| ; BASE-NEXT: ret void | |
| ; | |
| ; ZIBI-LABEL: define void @exit_count_reaches_recurrence_period( | |
| ; ZIBI-SAME: ptr [[P:%.*]]) #[[ATTR0]] { | |
| ; ZIBI-NEXT: [[ENTRY:.*]]: | |
| ; ZIBI-NEXT: br label %[[LOOP:.*]] | |
| ; ZIBI: [[LOOP]]: | |
| ; ZIBI-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], %[[LOOP]] ], [ -536870912, %[[ENTRY]] ] | |
| ; ZIBI-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: [[LIMIT:%.*]] = phi i32 [ -1, %[[ENTRY]] ], [ [[LIMIT_NEXT:%.*]], %[[LOOP]] ] | |
| ; ZIBI-NEXT: store volatile i32 [[IV]], ptr [[P]], align 4 | |
| ; ZIBI-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 536870912 | |
| ; ZIBI-NEXT: [[LIMIT_NEXT]] = add nuw i32 [[LIMIT]], -1 | |
| ; ZIBI-NEXT: [[LSR_IV_NEXT]] = add i32 [[LSR_IV]], 536870912 | |
| ; ZIBI-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[LSR_IV_NEXT]], [[LIMIT]] | |
| ; ZIBI-NEXT: br i1 [[CONTINUE]], label %[[LOOP]], label %[[EXIT:.*]] | |
| ; ZIBI: [[EXIT]]: | |
| ; ZIBI-NEXT: ret void | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] | |
| %limit = phi i32 [ -1, %entry ], [ %limit.next, %loop ] | |
| store volatile i32 %iv, ptr %p | |
| %iv.next = add nuw i32 %iv, 536870912 | |
| %limit.next = add nuw i32 %limit, -1 | |
| %continue = icmp ult i32 %iv, %limit | |
| br i1 %continue, label %loop, label %exit | |
| exit: | |
| ret void | |
| } | |
| declare void @use_condition(i1) |