Skip to content

Commit db511f0

Browse files
kasuga-fjaokblast
authored andcommitted
[DA] Add tests where dependencies are missed due to overflow (NFC) (llvm#164246)
This patch adds test cases that demonstrate missing dependencies in DA caused by the lack of overflow handling. These issues will be addressed by properly inserting overflow checks and bailing out when one is detected. It covers the following dependence test functions: - Strong SIV - Weak-Crossing SIV - Weak-Zero SIV - Symbolic RDIV - GCD MIV It does NOT cover: - Exact SIV - Exact RDIV - Banerjee MIV
1 parent beeae13 commit db511f0

File tree

5 files changed

+518
-0
lines changed

5 files changed

+518
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 \
3+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
4+
; RUN: opt < %s -disable-output "-passes=print<da>" -da-enable-dependence-test=gcd-miv 2>&1 \
5+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-GCD-MIV
6+
7+
; offset0 = 4;
8+
; offset1 = 0;
9+
; for (i = 0; i < 100; i++) {
10+
; A[offset0] = 1;
11+
; A[offset1] = 2;
12+
; offset0 += 3*m;
13+
; offset1 += 3;
14+
; }
15+
;
16+
; FIXME: DependenceAnalysis currently detects no dependency between the two
17+
; stores, but it does exist. E.g., consider `m` is 12297829382473034411, which
18+
; is a modular multiplicative inverse of 3 under modulo 2^64. Then `offset0` is
19+
; effectively `i + 4`, so accesses will be as follows:
20+
;
21+
; - A[offset0] : A[4], A[5], A[6], ...
22+
; - A[offset1] : A[0], A[3], A[6], ...
23+
;
24+
; The root cause is that DA interprets `3*m` in non-modular arithmetic, which
25+
; isn't necessarily true due to overflow.
26+
;
27+
define void @gcdmiv_coef_ovfl(ptr %A, i64 %m) {
28+
; CHECK-ALL-LABEL: 'gcdmiv_coef_ovfl'
29+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
30+
; CHECK-ALL-NEXT: da analyze - none!
31+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
32+
; CHECK-ALL-NEXT: da analyze - none!
33+
; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
34+
; CHECK-ALL-NEXT: da analyze - none!
35+
;
36+
; CHECK-GCD-MIV-LABEL: 'gcdmiv_coef_ovfl'
37+
; CHECK-GCD-MIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
38+
; CHECK-GCD-MIV-NEXT: da analyze - consistent output [*]!
39+
; CHECK-GCD-MIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
40+
; CHECK-GCD-MIV-NEXT: da analyze - none!
41+
; CHECK-GCD-MIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
42+
; CHECK-GCD-MIV-NEXT: da analyze - consistent output [*]!
43+
;
44+
entry:
45+
%step = mul i64 3, %m
46+
br label %loop
47+
48+
loop:
49+
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop ]
50+
%offset.0 = phi i64 [ 4, %entry ] , [ %offset.0.next, %loop ]
51+
%offset.1 = phi i64 [ 0, %entry ] , [ %offset.1.next, %loop ]
52+
%gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset.0
53+
%gep.1 = getelementptr inbounds i8, ptr %A, i64 %offset.1
54+
store i8 1, ptr %gep.0
55+
store i8 2, ptr %gep.1
56+
%i.inc = add nuw nsw i64 %i, 1
57+
%offset.0.next = add nsw i64 %offset.0, %step
58+
%offset.1.next = add nsw i64 %offset.1, 3
59+
%ec = icmp eq i64 %i.inc, 100
60+
br i1 %ec, label %exit, label %loop
61+
62+
exit:
63+
ret void
64+
}
65+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
66+
; CHECK: {{.*}}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 \
3+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
4+
; RUN: opt < %s -disable-output "-passes=print<da>" -da-enable-dependence-test=strong-siv 2>&1 \
5+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-STRONG-SIV
6+
7+
; for (i = 0; i < (1LL << 62); i++) {
8+
; if (0 <= 2*i - 2)
9+
; A[2*i - 2] = 1;
10+
;
11+
; if (0 <= 2*i - 4)
12+
; A[2*i - 4] = 2;
13+
; }
14+
;
15+
; FIXME: DependenceAnalysis currently detects no dependency between the two
16+
; stores, but it does exist. For example, each store will access A[0] when i
17+
; is 1 and 2 respectively.
18+
; The root cause is that the product of the BTC and the coefficient
19+
; ((1LL << 62) - 1 and 2) overflows in a signed sense.
20+
define void @strongsiv_const_ovfl(ptr %A) {
21+
; CHECK-LABEL: 'strongsiv_const_ovfl'
22+
; CHECK-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
23+
; CHECK-NEXT: da analyze - none!
24+
; CHECK-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
25+
; CHECK-NEXT: da analyze - none!
26+
; CHECK-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
27+
; CHECK-NEXT: da analyze - none!
28+
;
29+
entry:
30+
br label %loop.header
31+
32+
loop.header:
33+
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
34+
%offset.0 = phi i64 [ -2, %entry ], [ %offset.0.next, %loop.latch ]
35+
%offset.1 = phi i64 [ -4, %entry ], [ %offset.1.next, %loop.latch ]
36+
%ec = icmp eq i64 %i, 4611686018427387904
37+
br i1 %ec, label %exit, label %loop.body
38+
39+
loop.body:
40+
%cond.0 = icmp sge i64 %offset.0, 0
41+
%cond.1 = icmp sge i64 %offset.1, 0
42+
br i1 %cond.0, label %if.then.0, label %loop.middle
43+
44+
if.then.0:
45+
%gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset.0
46+
store i8 1, ptr %gep.0
47+
br label %loop.middle
48+
49+
loop.middle:
50+
br i1 %cond.1, label %if.then.1, label %loop.latch
51+
52+
if.then.1:
53+
%gep.1 = getelementptr inbounds i8, ptr %A, i64 %offset.1
54+
store i8 2, ptr %gep.1
55+
br label %loop.latch
56+
57+
loop.latch:
58+
%i.inc = add nuw nsw i64 %i, 1
59+
%offset.0.next = add nsw i64 %offset.0, 2
60+
%offset.1.next = add nsw i64 %offset.1, 2
61+
br label %loop.header
62+
63+
exit:
64+
ret void
65+
}
66+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
67+
; CHECK-ALL: {{.*}}
68+
; CHECK-STRONG-SIV: {{.*}}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 \
3+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
4+
; RUN: opt < %s -disable-output "-passes=print<da>" -da-enable-dependence-test=symbolic-rdiv 2>&1 \
5+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-SYMBOLIC-RDIV
6+
7+
; for (i = 0; i < (1LL << 62); i++) {
8+
; if (0 <= 2*i - 2)
9+
; A[2*i - 2] = 1;
10+
; A[i] = 2;
11+
; }
12+
;
13+
; FIXME: DependenceAnalysis currently detects no dependency between the two
14+
; stores, but it does exist. For example, each store will access A[0] when i
15+
; is 1 and 0 respectively.
16+
; The root cause is that the product of the BTC and the coefficient
17+
; ((1LL << 62) - 1 and 2) overflows in a signed sense.
18+
define void @symbolicrdiv_prod_ovfl(ptr %A) {
19+
; CHECK-ALL-LABEL: 'symbolicrdiv_prod_ovfl'
20+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
21+
; CHECK-ALL-NEXT: da analyze - none!
22+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
23+
; CHECK-ALL-NEXT: da analyze - none!
24+
; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
25+
; CHECK-ALL-NEXT: da analyze - none!
26+
;
27+
; CHECK-SYMBOLIC-RDIV-LABEL: 'symbolicrdiv_prod_ovfl'
28+
; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
29+
; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - none!
30+
; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
31+
; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - none!
32+
; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
33+
; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - consistent output [*]!
34+
;
35+
entry:
36+
br label %loop.header
37+
38+
loop.header:
39+
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
40+
%offset = phi i64 [ -2, %entry ], [ %offset.next, %loop.latch ]
41+
%ec = icmp eq i64 %i, 4611686018427387904
42+
br i1 %ec, label %exit, label %loop.body
43+
44+
loop.body:
45+
%cond = icmp sge i64 %offset, 0
46+
br i1 %cond, label %if.then, label %loop.latch
47+
48+
if.then:
49+
%gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset
50+
store i8 1, ptr %gep.0
51+
br label %loop.latch
52+
53+
loop.latch:
54+
%gep.1 = getelementptr inbounds i8, ptr %A, i64 %i
55+
store i8 2, ptr %gep.1
56+
%i.inc = add nuw nsw i64 %i, 1
57+
%offset.next = add nsw i64 %offset, 2
58+
br label %loop.header
59+
60+
exit:
61+
ret void
62+
}
63+
64+
; offset0 = -4611686018427387904; // -2^62
65+
; offset1 = 4611686018427387904; // 2^62
66+
; for (i = 0; i < (1LL << 62) - 100; i++) {
67+
; if (0 <= offset0)
68+
; A[offset0] = 1;
69+
; if (0 <= offset1)
70+
; A[offset1] = 2;
71+
; offset0 += 2;
72+
; offset1 -= 1;
73+
; }
74+
;
75+
; FIXME: DependenceAnalysis currently detects no dependency between the two
76+
; stores, but it does exist. For example,
77+
;
78+
; memory access | i == 2^61 | i == 2^61 + 2^59 | i == 2^61 + 2^60
79+
; -------------------------|-----------|------------------|-------------------
80+
; A[2*i - 2^62] (offset0) | | A[2^60] | A[2^61]
81+
; A[-i + 2^62] (offset1) | A[2^61] | | A[2^60]
82+
;
83+
; The root cause is that the calculation of the differenct between the two
84+
; constants (-2^62 and 2^62) overflows in a signed sense.
85+
define void @symbolicrdiv_delta_ovfl(ptr %A) {
86+
; CHECK-ALL-LABEL: 'symbolicrdiv_delta_ovfl'
87+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
88+
; CHECK-ALL-NEXT: da analyze - none!
89+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
90+
; CHECK-ALL-NEXT: da analyze - none!
91+
; CHECK-ALL-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
92+
; CHECK-ALL-NEXT: da analyze - none!
93+
;
94+
; CHECK-SYMBOLIC-RDIV-LABEL: 'symbolicrdiv_delta_ovfl'
95+
; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
96+
; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - consistent output [*]!
97+
; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
98+
; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - none!
99+
; CHECK-SYMBOLIC-RDIV-NEXT: Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
100+
; CHECK-SYMBOLIC-RDIV-NEXT: da analyze - consistent output [*]!
101+
;
102+
entry:
103+
br label %loop.header
104+
105+
loop.header:
106+
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
107+
%offset.0 = phi i64 [ -4611686018427387904, %entry ], [ %offset.0.next, %loop.latch ]
108+
%offset.1 = phi i64 [ 4611686018427387904, %entry ], [ %offset.1.next, %loop.latch ]
109+
%cond.0 = icmp sge i64 %offset.0, 0
110+
%cond.1 = icmp sge i64 %offset.1, 0
111+
br i1 %cond.0, label %if.then.0, label %loop.middle
112+
113+
if.then.0:
114+
%gep.0 = getelementptr inbounds i8, ptr %A, i64 %offset.0
115+
store i8 1, ptr %gep.0
116+
br label %loop.middle
117+
118+
loop.middle:
119+
br i1 %cond.1, label %if.then.1, label %loop.latch
120+
121+
if.then.1:
122+
%gep.1 = getelementptr inbounds i8, ptr %A, i64 %offset.1
123+
store i8 2, ptr %gep.1
124+
br label %loop.latch
125+
126+
loop.latch:
127+
%i.inc = add nuw nsw i64 %i, 1
128+
%offset.0.next = add nsw i64 %offset.0, 2
129+
%offset.1.next = sub nsw i64 %offset.1, 1
130+
%ec = icmp eq i64 %i.inc, 4611686018427387804 ; 2^62 - 100
131+
br i1 %ec, label %exit, label %loop.header
132+
133+
exit:
134+
ret void
135+
}
136+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
137+
; CHECK: {{.*}}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 \
3+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ALL
4+
; RUN: opt < %s -disable-output "-passes=print<da>" -da-enable-dependence-test=weak-crossing-siv 2>&1 \
5+
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-WEAK-CROSSING-SIV
6+
7+
; max_i = INT64_MAX/3 // 3074457345618258602
8+
; for (long long i = 0; i <= max_i; i++) {
9+
; A[-3*i + INT64_MAX] = 0;
10+
; if (i)
11+
; A[3*i - 2] = 1;
12+
; }
13+
;
14+
; FIXME: DependenceAnalysis currently detects no dependency between
15+
; `A[-3*i + INT64_MAX]` and `A[3*i - 2]`, but it does exist. For example,
16+
;
17+
; memory access | i == 1 | i == max_i
18+
; ---------------------|------------------|------------------
19+
; A[-3*i + INT64_MAX] | A[INT64_MAX - 3] | A[1]
20+
; A[3*i - 2] | A[1] | A[INT64_MAX - 3]
21+
;
22+
; The root cause is that the calculation of the differenct between the two
23+
; constants (INT64_MAX and -2) triggers an overflow.
24+
25+
define void @weakcorssing_delta_ovfl(ptr %A) {
26+
; CHECK-ALL-LABEL: 'weakcorssing_delta_ovfl'
27+
; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
28+
; CHECK-ALL-NEXT: da analyze - none!
29+
; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
30+
; CHECK-ALL-NEXT: da analyze - none!
31+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
32+
; CHECK-ALL-NEXT: da analyze - none!
33+
;
34+
; CHECK-WEAK-CROSSING-SIV-LABEL: 'weakcorssing_delta_ovfl'
35+
; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
36+
; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
37+
; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
38+
; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - none!
39+
; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
40+
; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
41+
;
42+
entry:
43+
br label %loop.header
44+
45+
loop.header:
46+
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ]
47+
%subscript.0 = phi i64 [ 9223372036854775807, %entry ], [ %subscript.0.next, %loop.latch ]
48+
%subscript.1 = phi i64 [ -2, %entry ], [ %subscript.1.next, %loop.latch ]
49+
%idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0
50+
store i8 0, ptr %idx.0
51+
%cond.store = icmp ne i64 %i, 0
52+
br i1 %cond.store, label %if.store, label %loop.latch
53+
54+
if.store:
55+
%idx.1 = getelementptr inbounds i8, ptr %A, i64 %subscript.1
56+
store i8 1, ptr %idx.1
57+
br label %loop.latch
58+
59+
loop.latch:
60+
%i.inc = add nuw nsw i64 %i, 1
61+
%subscript.0.next = add nsw i64 %subscript.0, -3
62+
%subscript.1.next = add nsw i64 %subscript.1, 3
63+
%ec = icmp sgt i64 %i.inc, 3074457345618258602
64+
br i1 %ec, label %exit, label %loop.header
65+
66+
exit:
67+
ret void
68+
}
69+
70+
; max_i = INT64_MAX/3 // 3074457345618258602
71+
; for (long long i = 0; i <= max_i; i++) {
72+
; A[-3*i + INT64_MAX] = 0;
73+
; A[3*i + 1] = 1;
74+
; }
75+
;
76+
; FIXME: DependenceAnalysis currently detects no dependency between
77+
; `A[-3*i + INT64_MAX]` and `A[3*i - 2]`, but it does exist. For example,
78+
;
79+
; memory access | i == 0 | i == 1 | i == max_i - 1 | i == max_i
80+
; ---------------------|--------|------------------|----------------|------------------
81+
; A[-3*i + INT64_MAX] | | A[INT64_MAX - 3] | A[1] |
82+
; A[3*i + 1] | A[1] | | | A[INT64_MAX - 3]
83+
;
84+
; The root cause is that the product of the BTC, the coefficient, and 2
85+
; triggers an overflow.
86+
;
87+
define void @weakcorssing_prod_ovfl(ptr %A) {
88+
; CHECK-ALL-LABEL: 'weakcorssing_prod_ovfl'
89+
; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
90+
; CHECK-ALL-NEXT: da analyze - none!
91+
; CHECK-ALL-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
92+
; CHECK-ALL-NEXT: da analyze - none!
93+
; CHECK-ALL-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
94+
; CHECK-ALL-NEXT: da analyze - none!
95+
;
96+
; CHECK-WEAK-CROSSING-SIV-LABEL: 'weakcorssing_prod_ovfl'
97+
; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
98+
; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
99+
; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
100+
; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - none!
101+
; CHECK-WEAK-CROSSING-SIV-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
102+
; CHECK-WEAK-CROSSING-SIV-NEXT: da analyze - consistent output [*]!
103+
;
104+
entry:
105+
br label %loop
106+
107+
loop:
108+
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop ]
109+
%subscript.0 = phi i64 [ 9223372036854775807, %entry ], [ %subscript.0.next, %loop ]
110+
%subscript.1 = phi i64 [ 1, %entry ], [ %subscript.1.next, %loop ]
111+
%idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0
112+
%idx.1 = getelementptr inbounds i8, ptr %A, i64 %subscript.1
113+
store i8 0, ptr %idx.0
114+
store i8 1, ptr %idx.1
115+
%i.inc = add nuw nsw i64 %i, 1
116+
%subscript.0.next = add nsw i64 %subscript.0, -3
117+
%subscript.1.next = add nsw i64 %subscript.1, 3
118+
%ec = icmp sgt i64 %i.inc, 3074457345618258602
119+
br i1 %ec, label %exit, label %loop
120+
121+
exit:
122+
ret void
123+
}
124+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
125+
; CHECK: {{.*}}

0 commit comments

Comments
 (0)