xref: /llvm-project/llvm/test/Transforms/SCCP/ipsccp-cycles.ll (revision 0991da36906bdb29b8f1030d5123bafb58fee79e)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=ipsccp -S | FileCheck %s
3
4define internal i32 @test1a(i32 %A, i32 %b) {
5; CHECK-LABEL: @test1a(
6; CHECK-NEXT:    [[X:%.*]] = add i32 [[A:%.*]], 1
7; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X]], [[B:%.*]]
8; CHECK-NEXT:    br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]]
9; CHECK:       bb.true:
10; CHECK-NEXT:    [[R:%.*]] = call i32 @test1a(i32 [[X]], i32 [[B]])
11; CHECK-NEXT:    ret i32 [[R]]
12; CHECK:       bb.false:
13; CHECK-NEXT:    ret i32 [[A]]
14;
15  %X = add i32 %A, 1
16  %c = icmp eq i32 %X, %b
17  br i1 %c, label %bb.true, label %bb.false
18
19bb.true:
20  %r = call i32 @test1a(i32 %X, i32 %b)
21  ret i32 %r
22
23bb.false:
24  ret i32 %A
25}
26
27define i32 @test1b(i32 %b) {
28; CHECK-LABEL: @test1b(
29; CHECK-NEXT:    [[X:%.*]] = call i32 @test1a(i32 17, i32 [[B:%.*]])
30; CHECK-NEXT:    ret i32 [[X]]
31;
32  %X = call i32 @test1a( i32 17, i32 %b)
33  ret i32 %X
34}
35
36@Getopt.optind = internal global i32 1, align 4
37
38define i32 @test2(i32 %a) {
39; CHECK-LABEL: @test2(
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    br label [[LOOP:%.*]]
42; CHECK:       loop:
43; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr @Getopt.optind, align 4
44; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LV]], 1
45; CHECK-NEXT:    store i32 [[ADD]], ptr @Getopt.optind, align 4
46; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[ADD]], [[A:%.*]]
47; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]]
48; CHECK:       exit:
49; CHECK-NEXT:    ret i32 [[ADD]]
50;
51entry:
52  br label %loop
53
54loop:
55  %lv = load i32, ptr @Getopt.optind, align 4
56  %add = add i32 %lv, 1
57  store i32 %add, ptr @Getopt.optind
58  %c = icmp eq i32 %add, %a
59  br i1 %c, label %exit, label %loop
60
61exit:
62  ret i32 %add
63}
64
65
66define internal i32 @test3a(i32 %a) {
67; CHECK-LABEL: @test3a(
68; CHECK-NEXT:  entry:
69; CHECK-NEXT:    [[RES:%.*]] = add i32 [[A:%.*]], 1
70; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[RES]], 1000
71; CHECK-NEXT:    br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]]
72; CHECK:       bb.true:
73; CHECK-NEXT:    ret i32 [[RES]]
74; CHECK:       bb.false:
75; CHECK-NEXT:    ret i32 0
76;
77entry:
78  %res = add i32 %a, 1
79  %c = icmp ult i32 %res, 1000
80  br i1 %c, label %bb.true, label %bb.false
81
82bb.true:
83  ret i32 %res
84
85bb.false:
86  ret i32 0
87}
88
89define i32 @test3b(i32 %a) {
90; CHECK-LABEL: @test3b(
91; CHECK-NEXT:  entry:
92; CHECK-NEXT:    [[V1:%.*]] = call i32 @test3a(i32 0)
93; CHECK-NEXT:    br label [[LOOP:%.*]]
94; CHECK:       loop:
95; CHECK-NEXT:    [[V2:%.*]] = call i32 @test3a(i32 [[V1]])
96; CHECK-NEXT:    [[V3:%.*]] = add i32 [[V2]], 1
97; CHECK-NEXT:    [[V4:%.*]] = call i32 @test3a(i32 [[V3]])
98; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[V4]], [[A:%.*]]
99; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]]
100; CHECK:       exit:
101; CHECK-NEXT:    ret i32 [[V4]]
102;
103entry:
104  %v1 = call i32 @test3a(i32 0)
105  br label %loop
106
107loop:
108  %v2 = call i32 @test3a(i32 %v1)
109  %v3 = add i32 %v2, 1
110  %v4 = call i32 @test3a(i32 %v3)
111  %c = icmp eq i32 %v4, %a
112  br i1 %c, label %exit, label %loop
113
114exit:
115  ret i32 %v4
116}
117
118%struct.S = type { i32, i32 }
119
120; Check for a range extension cycle through a  struct argument.
121define internal i32 @test4a(%struct.S %s) {
122; CHECK-LABEL: @test4a(
123; CHECK-NEXT:    [[A:%.*]] = extractvalue [[STRUCT_S:%.*]] %s, 0
124; CHECK-NEXT:    [[B:%.*]] = extractvalue [[STRUCT_S]] %s, 1
125; CHECK-NEXT:    [[X:%.*]] = add i32 [[A]], 1
126; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X]], [[B]]
127; CHECK-NEXT:    br i1 [[C]], label [[BB_TRUE:%.*]], label [[BB_FALSE:%.*]]
128; CHECK:       bb.true:
129; CHECK-NEXT:    [[S2:%.*]] = insertvalue [[STRUCT_S]] %s, i32 [[X]], 0
130; CHECK-NEXT:    [[R:%.*]] = call i32 @test4a(%struct.S [[S2]])
131; CHECK-NEXT:    ret i32 [[R]]
132; CHECK:       bb.false:
133; CHECK-NEXT:    ret i32 [[A]]
134;
135  %a = extractvalue %struct.S %s, 0
136  %b = extractvalue %struct.S %s, 1
137
138  %x = add i32 %a, 1
139  %c = icmp eq i32 %x, %b
140  br i1 %c, label %bb.true, label %bb.false
141
142bb.true:
143  %s2 = insertvalue %struct.S %s, i32 %x, 0
144  %r = call i32 @test4a(%struct.S %s2)
145  ret i32 %r
146
147bb.false:
148  ret i32 %a
149}
150
151define i32 @test4b(i32 %b) {
152; CHECK-LABEL: @test4b(
153; CHECK-NEXT:    [[S2:%.*]] = insertvalue [[STRUCT_S:%.*]] { i32 17, i32 undef }, i32 [[B:%.*]], 1
154; CHECK-NEXT:    [[X:%.*]] = call i32 @test4a(%struct.S [[S2]])
155; CHECK-NEXT:    ret i32 [[X]]
156;
157  %s1 = insertvalue %struct.S undef, i32 17, 0
158  %s2 = insertvalue %struct.S %s1, i32 %b, 1
159  %X = call i32 @test4a(%struct.S %s2)
160  ret i32 %X
161}
162
163; Check for a range extension cycle through a returned value.
164
165define internal i32 @test5a(ptr %arg, i32 %arg1, i32 %arg2) {
166; CHECK-LABEL: @test5a(
167; CHECK-NEXT:  bb:
168; CHECK-NEXT:    [[TMP:%.*]] = icmp eq ptr [[ARG:%.*]], null
169; CHECK-NEXT:    br i1 [[TMP]], label [[BB6:%.*]], label [[BB3:%.*]]
170; CHECK:       bb3:
171; CHECK-NEXT:    [[TMP4:%.*]] = tail call i32 @test5a(ptr [[ARG]], i32 0, i32 -1)
172; CHECK-NEXT:    [[TMP5:%.*]] = add nsw i32 [[TMP4]], -1
173; CHECK-NEXT:    ret i32 [[TMP5]]
174; CHECK:       bb6:
175; CHECK-NEXT:    ret i32 0
176;
177bb:
178  %tmp = icmp eq ptr %arg, null
179  br i1 %tmp, label %bb6, label %bb3
180
181bb3:                                              ; preds = %bb
182  %tmp4 = tail call i32 @test5a(ptr %arg, i32 %arg1, i32 %arg2)
183  %tmp5 = add nsw i32 %tmp4, %arg2
184  ret i32 %tmp5
185
186bb6:                                              ; preds = %bb
187  ret i32 %arg1
188}
189
190define void @test5b(ptr %ptr) {
191; CHECK-LABEL: @test5b(
192; CHECK-NEXT:  bb:
193; CHECK-NEXT:    [[TMP:%.*]] = tail call i32 @test5a(ptr [[PTR:%.*]], i32 0, i32 -1)
194; CHECK-NEXT:    ret void
195;
196bb:
197  %tmp = tail call i32 @test5a(ptr %ptr, i32 0, i32 -1)
198  ret void
199}
200
201%struct = type { i32, i32 }
202
203define internal %struct @test6a(ptr %arg, i32 %arg1, i32 %arg2) {
204; CHECK-LABEL: @test6a(
205; CHECK-NEXT:  bb:
206; CHECK-NEXT:    [[TMP:%.*]] = icmp eq ptr [[ARG:%.*]], null
207; CHECK-NEXT:    br i1 [[TMP]], label [[BB6:%.*]], label [[BB3:%.*]]
208; CHECK:       bb3:
209; CHECK-NEXT:    [[S1:%.*]] = tail call [[STRUCT:%.*]] @test6a(ptr [[ARG]], i32 0, i32 -1)
210; CHECK-NEXT:    [[TMP4:%.*]] = extractvalue [[STRUCT]] %s1, 0
211; CHECK-NEXT:    [[TMP5:%.*]] = add nsw i32 [[TMP4]], -1
212; CHECK-NEXT:    [[S2:%.*]] = insertvalue [[STRUCT]] %s1, i32 [[TMP5]], 0
213; CHECK-NEXT:    ret [[STRUCT]] %s2
214; CHECK:       bb6:
215; CHECK-NEXT:    ret [[STRUCT]] { i32 0, i32 undef }
216;
217bb:
218  %tmp = icmp eq ptr %arg, null
219  br i1 %tmp, label %bb6, label %bb3
220
221bb3:                                              ; preds = %bb
222  %s1 = tail call %struct @test6a(ptr %arg, i32 %arg1, i32 %arg2)
223  %tmp4 = extractvalue %struct %s1, 0
224  %tmp5 = add nsw i32 %tmp4, %arg2
225  %s2 = insertvalue %struct %s1, i32 %tmp5, 0
226  ret %struct %s2
227
228bb6:                                              ; preds = %bb
229  %s3 = insertvalue %struct undef, i32 %arg1, 0
230  ret %struct %s3
231}
232
233define void @test6b(ptr %ptr) {
234; CHECK-LABEL: @test6b(
235; CHECK-NEXT:  bb:
236; CHECK-NEXT:    [[TMP:%.*]] = tail call [[STRUCT:%.*]] @test6a(ptr [[PTR:%.*]], i32 0, i32 -1)
237; CHECK-NEXT:    ret void
238;
239bb:
240  %tmp = tail call %struct @test6a(ptr %ptr, i32 0, i32 -1)
241  ret void
242}
243