blob: df42c757a3b63687979ec9822441025002b2649a [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -disable-output -passes="print<da>" -da-dump-monotonicity-report \
; RUN: -da-enable-monotonicity-check 2>&1 | FileCheck %s
; for (int i = 0; i < n; i++)
; a[i] = 0;
;
define void @single_loop_nsw(ptr %a, i64 %n) {
; CHECK-LABEL: 'single_loop_nsw'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {0,+,1}<nuw><nsw><%loop>
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - none!
;
entry:
%guard = icmp sgt i64 %n, 0
br i1 %guard, label %loop, label %exit
loop:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop ]
%idx = getelementptr inbounds i8, ptr %a, i64 %i
store i8 0, ptr %idx
%i.inc = add nsw i64 %i, 1
%exitcond = icmp eq i64 %i.inc, %n
br i1 %exitcond, label %exit, label %loop
exit:
ret void
}
; The purpose of the variable `begin` is to avoid violating the size limitation
; of the allocated object in LLVM IR, which would cause UB.
;
; for (unsigned long long i = begin; i < end; i++)
; a[i] = 0;
;
define void @single_loop_nuw(ptr %a, i64 %begin, i64 %end) {
; CHECK-LABEL: 'single_loop_nuw'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {%begin,+,1}<nuw><%loop>
; CHECK-NEXT: Monotonicity: Unknown
; CHECK-NEXT: Reason: {%begin,+,1}<nuw><%loop>
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - confused!
;
entry:
%guard = icmp ult i64 %begin, %end
br i1 %guard, label %loop, label %exit
loop:
%i = phi i64 [ %begin, %entry ], [ %i.inc, %loop ]
%idx = getelementptr i8, ptr %a, i64 %i
store i8 0, ptr %idx
%i.inc = add nuw i64 %i, 1
%exitcond = icmp eq i64 %i.inc, %end
br i1 %exitcond, label %exit, label %loop
exit:
ret void
}
; for (int i = 0; i < n; i++)
; for (int j = 0; j < m; j++)
; a[i + j] = 0;
;
define void @nested_loop_nsw0(ptr %a, i64 %n, i64 %m) {
; CHECK-LABEL: 'nested_loop_nsw0'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nuw><nsw><%loop.j>
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - output [* *]!
;
entry:
%guard.i = icmp sgt i64 %n, 0
br i1 %guard.i, label %loop.i.header, label %exit
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
br label %loop.j.preheader
loop.j.preheader:
%gurard.j = icmp sgt i64 %m, 0
br i1 %gurard.j, label %loop.j, label %loop.i.latch
loop.j:
%j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j ]
%offset = add nsw i64 %i, %j
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
%j.inc = add nsw i64 %j, 1
%exitcond.j = icmp eq i64 %j.inc, %m
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%exitcond.i = icmp eq i64 %i.inc, %n
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; for (int i = n - 1; i >= 0; i--)
; for (int j = 0; j < m; j++)
; a[i + j] = 0;
;
define void @nested_loop_nsw1(ptr %a, i64 %n, i64 %m) {
; CHECK-LABEL: 'nested_loop_nsw1'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {{\{\{}}(-1 + %n),+,-1}<nsw><%loop.i.header>,+,1}<nsw><%loop.j>
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - output [* *]!
;
entry:
%guard.i = icmp sgt i64 %n, 0
br i1 %guard.i, label %loop.i.header, label %exit
loop.i.header:
%i = phi i64 [ %n, %entry ], [ %i.dec, %loop.i.latch ]
%i.dec = add nsw i64 %i, -1
br label %loop.j.preheader
loop.j.preheader:
%gurard.j = icmp sgt i64 %m, 0
br i1 %gurard.j, label %loop.j, label %loop.i.latch
loop.j:
%j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j ]
%offset = add nsw i64 %i.dec, %j
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
%j.inc = add nsw i64 %j, 1
%exitcond.j = icmp eq i64 %j.inc, %m
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
loop.i.latch:
%exitcond.i = icmp eq i64 %i.dec, 0
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; for (int i = 0; i < n; i--)
; for (int j = 0; j < m; j++)
; a[i - j] = 0;
;
define void @nested_loop_nsw2(ptr %a, i64 %n, i64 %m) {
; CHECK-LABEL: 'nested_loop_nsw2'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,-1}<nsw><%loop.j>
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - output [* *]!
;
entry:
%guard.i = icmp sgt i64 %n, 0
br i1 %guard.i, label %loop.i.header, label %exit
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
br label %loop.j.preheader
loop.j.preheader:
%gurard.j = icmp sgt i64 %m, 0
br i1 %gurard.j, label %loop.j, label %loop.i.latch
loop.j:
%j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j ]
%offset = sub nsw i64 %i, %j
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
%j.inc = add nsw i64 %j, 1
%exitcond.j = icmp eq i64 %j.inc, %m
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%exitcond.i = icmp eq i64 %i.inc, %n
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; for (int i = begin0; i < end0; i++)
; for (int j = begin1; j < end1; j++) {
; unsigned long long offset = (unsigned long long)i + (unsigned long long)j;
; a[offset] = 0;
; }
;
define void @nested_loop_nuw(ptr %a, i64 %begin0, i64 %end0, i64 %begin1, i64 %end1) {
; CHECK-LABEL: 'nested_loop_nuw'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {{\{\{}}(%begin0 + %begin1),+,1}<nw><%loop.i.header>,+,1}<nw><%loop.j>
; CHECK-NEXT: Monotonicity: Unknown
; CHECK-NEXT: Reason: {{\{\{}}(%begin0 + %begin1),+,1}<nw><%loop.i.header>,+,1}<nw><%loop.j>
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - confused!
;
entry:
%guard.i.0 = icmp slt i64 0, %begin0
%guard.i.1 = icmp slt i64 %begin0, %end0
%guard.i.2 = icmp slt i64 0, %end0
%and.i.0 = and i1 %guard.i.0, %guard.i.1
%and.i.1 = and i1 %and.i.0, %guard.i.2
br i1 %and.i.1, label %loop.i.header, label %exit
loop.i.header:
%i = phi i64 [ %begin0, %entry ], [ %i.inc, %loop.i.latch ]
br label %loop.j.preheader
loop.j.preheader:
%guard.j.0 = icmp slt i64 0, %begin1
%guard.j.1 = icmp slt i64 %begin1, %end1
%guard.j.2 = icmp slt i64 0, %end1
%and.j.0 = and i1 %guard.j.0, %guard.j.1
%and.j.1 = and i1 %and.j.0, %guard.j.2
br i1 %and.j.1, label %loop.j, label %loop.i.latch
loop.j:
%j = phi i64 [ %begin1, %loop.j.preheader ], [ %j.inc, %loop.j ]
%offset = add nuw i64 %i, %j
%idx = getelementptr i8, ptr %a, i64 %offset
store i8 0, ptr %idx
%j.inc = add nsw i64 %j, 1
%exitcond.j = icmp eq i64 %j.inc, %end1
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%exitcond.i = icmp eq i64 %i.inc, %end0
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; for (int i = 0; i < n; i++)
; for (int j = 0; j < m; j++)
; a[i + step*j] = 0;
;
define void @nested_loop_step(ptr %a, i64 %n, i64 %m, i64 %step) {
; CHECK-LABEL: 'nested_loop_step'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,%step}<nsw><%loop.j>
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - output [* *]!
;
entry:
%guard.i = icmp sgt i64 %n, 0
br i1 %guard.i, label %loop.i.header, label %exit
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
br label %loop.j.preheader
loop.j.preheader:
%gurard.j = icmp sgt i64 %m, 0
br i1 %gurard.j, label %loop.j, label %loop.i.latch
loop.j:
%j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j ]
%offset.j = phi i64 [ 0, %loop.j.preheader ], [ %offset.j.next, %loop.j ]
%offset = add nsw i64 %i, %offset.j
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
%j.inc = add nsw i64 %j, 1
%offset.j.next = add nsw i64 %offset.j, %step
%exitcond.j = icmp eq i64 %j.inc, %m
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%exitcond.i = icmp eq i64 %i.inc, %n
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; The value of step reccurence is not invariant with respect to the outer most
; loop (the i-loop). It is theoretically multivariate monotonic by definition,
; but we cannot handle non-affine addrec for now.
;
; offset_i = 0;
; for (int i = 0; i < 100; i++) {
; for (int j = 0; j < 100; j++)
; a[offset_i + j] = 0;
; offset_i += (i % 2 == 0) ? 0 : 3;
; }
;
define void @step_is_variant(ptr %a) {
; CHECK-LABEL: 'step_is_variant'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {%offset.i,+,1}<nuw><nsw><%loop.j>
; CHECK-NEXT: Monotonicity: Unknown
; CHECK-NEXT: Reason: %offset.i
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - confused!
;
entry:
br label %loop.i.header
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
%offset.i = phi i64 [ 0, %entry ], [ %offset.i.next, %loop.i.latch ]
%step.i.0 = phi i64 [ 0, %entry ], [ %step.i.1, %loop.i.latch ]
%step.i.1 = phi i64 [ 3, %entry ], [ %step.i.0, %loop.i.latch ]
br label %loop.j
loop.j:
%j = phi i64 [ 0, %loop.i.header ], [ %j.inc, %loop.j ]
%offset = add nsw i64 %offset.i, %j
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
%j.inc = add nsw i64 %j, 1
%exitcond.j = icmp eq i64 %j.inc, 100
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%offset.i.next = add nsw i64 %offset.i, %step.i.0
%exitcond.i = icmp eq i64 %i.inc, 100
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; The value of step reccurence is not invariant with respect to the outer most
; loop (the i-loop). Actually, `offset_i` is not monotonic.
;
; offset_i = 0;
; for (int i = 0; i < 100; i++) {
; for (int j = 0; j < 100; j++)
; a[offset_i + j] = 0;
; offset_i += (i % 2 == 0) ? -1 : 3;
; }
;
define void @step_is_variant2(ptr %a) {
; CHECK-LABEL: 'step_is_variant2'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {%offset.i,+,1}<nsw><%loop.j>
; CHECK-NEXT: Monotonicity: Unknown
; CHECK-NEXT: Reason: %offset.i
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - confused!
;
entry:
br label %loop.i.header
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
%offset.i = phi i64 [ 0, %entry ], [ %offset.i.next, %loop.i.latch ]
%step.i.0 = phi i64 [ -1, %entry ], [ %step.i.1, %loop.i.latch ]
%step.i.1 = phi i64 [ 3, %entry ], [ %step.i.0, %loop.i.latch ]
br label %loop.j
loop.j:
%j = phi i64 [ 0, %loop.i.header ], [ %j.inc, %loop.j ]
%offset = add nsw i64 %offset.i, %j
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
%j.inc = add nsw i64 %j, 1
%exitcond.j = icmp eq i64 %j.inc, 100
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%offset.i.next = add nsw i64 %offset.i, %step.i.0
%exitcond.i = icmp eq i64 %i.inc, 100
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; The AddRec doesn't have nsw flag for the j-loop, since the store may not be
; executed.
;
; for (int i = 0; i < n; i++)
; for (int j = 0; j < m; j++)
; if (cond)
; a[i + j] = 0;
;
define void @conditional_store0(ptr %a, i64 %n, i64 %m) {
; CHECK-LABEL: 'conditional_store0'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nw><%loop.j.header>
; CHECK-NEXT: Monotonicity: Unknown
; CHECK-NEXT: Reason: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nw><%loop.j.header>
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - confused!
;
entry:
%guard.i = icmp sgt i64 %n, 0
br i1 %guard.i, label %loop.i.header, label %exit
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
br label %loop.j.preheader
loop.j.preheader:
%gurard.j = icmp sgt i64 %m, 0
br i1 %gurard.j, label %loop.j.header, label %loop.i.latch
loop.j.header:
%j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j.latch ]
%offset = add nsw i64 %i, %j
%cond = freeze i1 poison
br i1 %cond, label %if.then, label %loop.j.latch
if.then:
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
br label %loop.j.latch
loop.j.latch:
%j.inc = add nsw i64 %j, 1
%exitcond.j = icmp eq i64 %j.inc, %m
br i1 %exitcond.j, label %loop.i.latch, label %loop.j.header
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%exitcond.i = icmp eq i64 %i.inc, %n
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; Similar to the @conditional_store0, but the definition of the `%offset` is
; different from it and we can infer `nsw` in this case.
;
; for (int i = 0; i < n; i++)
; for (int j = 0; j < m; j++)
; if (cond)
; a[i + j] = 0;
;
define void @conditional_store1(ptr %a, i64 %n, i64 %m) {
; CHECK-LABEL: 'conditional_store1'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nuw><nsw><%loop.j.header>
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
; CHECK-NEXT: da analyze - output [* *]!
;
entry:
%guard.i = icmp sgt i64 %n, 0
br i1 %guard.i, label %loop.i.header, label %exit
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
br label %loop.j.preheader
loop.j.preheader:
%gurard.j = icmp sgt i64 %m, 0
br i1 %gurard.j, label %loop.j.header, label %loop.i.latch
loop.j.header:
%j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j.latch ]
%offset = phi i64 [ %i, %loop.j.preheader ], [ %offset.next, %loop.j.latch ]
%cond = freeze i1 poison
br i1 %cond, label %if.then, label %loop.j.latch
if.then:
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
store i8 0, ptr %idx
br label %loop.j.latch
loop.j.latch:
%j.inc = add nsw i64 %j, 1
%offset.next = add nsw i64 %offset, 1
%exitcond.j = icmp eq i64 %j.inc, %m
br i1 %exitcond.j, label %loop.i.latch, label %loop.j.header
loop.i.latch:
%i.inc = add nsw i64 %i, 1
%exitcond.i = icmp eq i64 %i.inc, %n
br i1 %exitcond.i, label %exit, label %loop.i.header
exit:
ret void
}
; In the following case, the computation `offset = offset_i + j` will not wrap,
; but `offset_i += 1024` will wrap both in a signed sense and an unsigned
; sense. We cannot prove the monotonicity in this case.
;
; offset_i = (1ULL << 63) - 256;
; for (i = 0; i < (1ULL << 62); i++, offset_i += 1024)
; for (j = 0; j < 32; j++) {
; offset = offset_i + j;
;
; // The value of `offset` is positive in a signed sense.
; if (offset < (1ULL << 63))
; a[offset] = 0;
; }
;
define void @outer_loop_may_wrap(ptr %a) {
; CHECK-LABEL: 'outer_loop_may_wrap'
; CHECK-NEXT: Monotonicity check:
; CHECK-NEXT: Inst: store i8 0, ptr %gep, align 1
; CHECK-NEXT: Expr: {{\{\{}}9223372036854775552,+,1024}<%loop.i.header>,+,1}<nuw><nsw><%loop.j.header>
; CHECK-NEXT: Monotonicity: Unknown
; CHECK-NEXT: Reason: {9223372036854775552,+,1024}<%loop.i.header>
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %gep, align 1 --> Dst: store i8 0, ptr %gep, align 1
; CHECK-NEXT: da analyze - confused!
;
entry:
br label %loop.i.header
loop.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
%subscript.i = phi i64 [ 9223372036854775552, %entry ], [ %subscript.i.next, %loop.i.latch ] ; The initial value is 2^63 - 256
br label %loop.j.header
loop.j.header:
%j = phi i64 [ 0, %loop.i.header ], [ %j.inc, %loop.j.latch ]
%subscript = phi i64 [ %subscript.i, %loop.i.header ], [ %subscript.next, %loop.j.latch ]
%cond = icmp sge i64 %subscript, 0
br i1 %cond, label %if.then, label %loop.j.latch
if.then:
%gep = getelementptr inbounds i8, ptr %a, i64 %subscript
store i8 0, ptr %gep
br label %loop.j.latch
loop.j.latch:
%j.inc = add nuw nsw i64 %j, 1
%subscript.next = add nuw nsw i64 %subscript, 1
%ec.j = icmp eq i64 %j.inc, 32
br i1 %ec.j, label %loop.i.latch, label %loop.j.header
loop.i.latch:
%i.inc = add nuw nsw i64 %i, 1
%subscript.i.next = add i64 %subscript.i, 1024
%ec.i = icmp eq i64 %i.inc, 4611686018427387904 ; 2^62
br i1 %ec.i, label %exit, label %loop.i.header
exit:
ret void
}