1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -indvars -S | FileCheck %s
3
4@array = dso_local global [16777219 x i32] zeroinitializer, align 4
5
6define void @sitofp_fptosi_range() {
7; CHECK-LABEL: @sitofp_fptosi_range(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
10; CHECK:       for.body:
11; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ]
12; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[IV_INT]] to i64
13; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]]
14; CHECK-NEXT:    store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4
15; CHECK-NEXT:    [[DEC_INT]] = add nsw i32 [[IV_INT]], -1
16; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0
17; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]]
18; CHECK:       cleanup:
19; CHECK-NEXT:    ret void
20;
21entry:
22  br label %for.body
23
24for.body:                                         ; preds = %for.body, %entry
25  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
26  %indvar.conv = sitofp i32 %iv.int to float
27  %conv = fptosi float %indvar.conv to i32
28  %idxprom = sext i32 %conv to i64
29  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
30  store i32 %conv, i32* %arrayidx, align 4
31  %dec.int = add nsw i32 %iv.int, -1
32  %cmp = icmp ugt i32 %dec.int, 0
33  br i1 %cmp, label %for.body, label %cleanup
34
35cleanup:                                          ; preds = %for.body
36  ret void
37}
38
39; Negative test: The transform is *not* valid because there are too many significant bits
40define void @sitofp_fptosi_range_overflow() {
41; CHECK-LABEL: @sitofp_fptosi_range_overflow(
42; CHECK-NEXT:  entry:
43; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
44; CHECK:       for.body:
45; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 16777218, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ]
46; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to float
47; CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[INDVAR_CONV]] to i32
48; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[CONV]] to i64
49; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]]
50; CHECK-NEXT:    store i32 [[CONV]], i32* [[ARRAYIDX]], align 4
51; CHECK-NEXT:    [[DEC_INT]] = add nsw i32 [[IV_INT]], -1
52; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0
53; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]]
54; CHECK:       cleanup:
55; CHECK-NEXT:    ret void
56;
57entry:
58  br label %for.body
59
60for.body:                                         ; preds = %for.body, %entry
61  %iv.int = phi i32 [ 16777218, %entry ], [ %dec.int, %for.body ] ; intermediate 16777218 (= 1 << 24 + 2)
62  %indvar.conv = sitofp i32 %iv.int to float
63  %conv = fptosi float %indvar.conv to i32
64  %idxprom = sext i32 %conv to i64
65  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
66  store i32 %conv, i32* %arrayidx, align 4
67  %dec.int = add nsw i32 %iv.int, -1
68  %cmp = icmp ugt i32 %dec.int, 0
69  br i1 %cmp, label %for.body, label %cleanup
70
71cleanup:                                          ; preds = %for.body
72  ret void
73}
74
75; Negative test: Type mismatch between the integer IV and the fptosi result
76define void @sitofp_fptosi_range_mismatch_type() {
77;
78; CHECK-LABEL: @sitofp_fptosi_range_mismatch_type(
79; CHECK-NEXT:  entry:
80; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
81; CHECK:       for.body:
82; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ]
83; CHECK-NEXT:    [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to float
84; CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[INDVAR_CONV]] to i16
85; CHECK-NEXT:    [[IDXPROM32:%.*]] = sext i16 [[CONV]] to i32
86; CHECK-NEXT:    [[IDXPROM64:%.*]] = sext i16 [[CONV]] to i64
87; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM64]]
88; CHECK-NEXT:    store i32 [[IDXPROM32]], i32* [[ARRAYIDX]], align 4
89; CHECK-NEXT:    [[DEC_INT]] = add nsw i32 [[IV_INT]], -1
90; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0
91; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]]
92; CHECK:       cleanup:
93; CHECK-NEXT:    ret void
94;
95entry:
96  br label %for.body
97
98for.body:                                         ; preds = %for.body, %entry
99  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
100  %indvar.conv = sitofp i32 %iv.int to float
101  %conv = fptosi float %indvar.conv to i16
102  %idxprom32 = sext i16 %conv to i32
103  %idxprom64 = sext i16 %conv to i64
104  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom64
105  store i32 %idxprom32, i32* %arrayidx, align 4
106  %dec.int = add nsw i32 %iv.int, -1
107  %cmp = icmp ugt i32 %dec.int, 0
108  br i1 %cmp, label %for.body, label %cleanup
109
110cleanup:                                          ; preds = %for.body
111  ret void
112}
113
114define void @sitofp_fptoui_range() {
115; CHECK-LABEL: @sitofp_fptoui_range(
116; CHECK-NEXT:  entry:
117; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
118; CHECK:       for.body:
119; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ]
120; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64
121; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]]
122; CHECK-NEXT:    store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4
123; CHECK-NEXT:    [[DEC_INT]] = add nsw i32 [[IV_INT]], -1
124; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0
125; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]]
126; CHECK:       cleanup:
127; CHECK-NEXT:    ret void
128;
129entry:
130  br label %for.body
131
132for.body:                                         ; preds = %for.body, %entry
133  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
134  %indvar.conv = sitofp i32 %iv.int to float
135  %conv = fptoui float %indvar.conv to i32
136  %idxprom = zext i32 %conv to i64
137  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
138  store i32 %conv, i32* %arrayidx, align 4
139  %dec.int = add nsw i32 %iv.int, -1
140  %cmp = icmp sgt i32 %dec.int, 0
141  br i1 %cmp, label %for.body, label %cleanup
142
143cleanup:                                          ; preds = %for.body
144  ret void
145}
146
147; Range including negative value.
148define void @sitofp_fptoui_range_with_negative () {
149; CHECK-LABEL: @sitofp_fptoui_range_with_negative(
150; CHECK-NEXT:  entry:
151; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
152; CHECK:       for.body:
153; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ]
154; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64
155; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]]
156; CHECK-NEXT:    store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4
157; CHECK-NEXT:    [[DEC_INT]] = add nsw i32 [[IV_INT]], -1
158; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[DEC_INT]], -100
159; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]]
160; CHECK:       cleanup:
161; CHECK-NEXT:    ret void
162;
163entry:
164  br label %for.body
165
166for.body:                                         ; preds = %for.body, %entry
167  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
168  %indvar.conv = sitofp i32 %iv.int to float
169  %conv = fptoui float %indvar.conv to i32
170  %idxprom = zext i32 %conv to i64
171  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
172  store i32 %conv, i32* %arrayidx, align 4
173  %dec.int = add nsw i32 %iv.int, -1
174  %cmp = icmp sgt i32 %dec.int, -100
175  br i1 %cmp, label %for.body, label %cleanup
176
177cleanup:                                          ; preds = %for.body
178  ret void
179}
180
181; https://godbolt.org/z/51MrqYjEf
182define void @uitofp_fptoui_range () {
183; CHECK-LABEL: @uitofp_fptoui_range(
184; CHECK-NEXT:  entry:
185; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
186; CHECK:       for.body:
187; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ]
188; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64
189; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]]
190; CHECK-NEXT:    store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4
191; CHECK-NEXT:    [[DEC_INT]] = add nsw i32 [[IV_INT]], -1
192; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 3
193; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]]
194; CHECK:       cleanup:
195; CHECK-NEXT:    ret void
196;
197entry:
198  br label %for.body
199
200for.body:                                         ; preds = %for.body, %entry
201  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
202  %indvar.conv = uitofp i32 %iv.int to float
203  %conv = fptoui float %indvar.conv to i32
204  %idxprom = zext i32 %conv to i64
205  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
206  store i32 %conv, i32* %arrayidx, align 4
207  %dec.int = add nsw i32 %iv.int, -1
208  %cmp = icmp ugt i32 %dec.int, 3
209  br i1 %cmp, label %for.body, label %cleanup
210
211cleanup:                                          ; preds = %for.body
212  ret void
213}
214
215define void @uitofp_fptoui_range_with_negative() {
216; CHECK-LABEL: @uitofp_fptoui_range_with_negative(
217; CHECK-NEXT:  entry:
218; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
219; CHECK:       for.body:
220; CHECK-NEXT:    store i32 100, i32* getelementptr inbounds ([16777219 x i32], [16777219 x i32]* @array, i64 0, i64 100), align 4
221; CHECK-NEXT:    br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]]
222; CHECK:       cleanup:
223; CHECK-NEXT:    ret void
224;
225entry:
226  br label %for.body
227
228for.body:                                         ; preds = %for.body, %entry
229  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
230  %indvar.conv = uitofp i32 %iv.int to float
231  %conv = fptoui float %indvar.conv to i32
232  %idxprom = zext i32 %conv to i64
233  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
234  store i32 %conv, i32* %arrayidx, align 4
235  %dec.int = add nsw i32 %iv.int, -1
236  %cmp = icmp ugt i32 %dec.int, -100
237  br i1 %cmp, label %for.body, label %cleanup
238
239cleanup:                                          ; preds = %for.body
240  ret void
241}
242
243define void @uitofp_fptosi_range () {
244; CHECK-LABEL: @uitofp_fptosi_range(
245; CHECK-NEXT:  entry:
246; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
247; CHECK:       for.body:
248; CHECK-NEXT:    [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ]
249; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[IV_INT]] to i64
250; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]]
251; CHECK-NEXT:    store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4
252; CHECK-NEXT:    [[DEC_INT]] = add nsw i32 [[IV_INT]], -1
253; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 3
254; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]]
255; CHECK:       cleanup:
256; CHECK-NEXT:    ret void
257;
258entry:
259  br label %for.body
260
261for.body:                                         ; preds = %for.body, %entry
262  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
263  %indvar.conv = uitofp i32 %iv.int to float
264  %conv = fptosi float %indvar.conv to i32
265  %idxprom = sext i32 %conv to i64
266  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
267  store i32 %conv, i32* %arrayidx, align 4
268  %dec.int = add nsw i32 %iv.int, -1
269  %cmp = icmp ugt i32 %dec.int, 3
270  br i1 %cmp, label %for.body, label %cleanup
271
272cleanup:                                          ; preds = %for.body
273  ret void
274}
275
276define void @uitofp_fptosi_range_with_negative () {
277; CHECK-LABEL: @uitofp_fptosi_range_with_negative(
278; CHECK-NEXT:  entry:
279; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
280; CHECK:       for.body:
281; CHECK-NEXT:    store i32 100, i32* getelementptr inbounds ([16777219 x i32], [16777219 x i32]* @array, i64 0, i64 100), align 4
282; CHECK-NEXT:    br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]]
283; CHECK:       cleanup:
284; CHECK-NEXT:    ret void
285;
286entry:
287  br label %for.body
288
289for.body:                                         ; preds = %for.body, %entry
290  %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ]
291  %indvar.conv = uitofp i32 %iv.int to float
292  %conv = fptosi float %indvar.conv to i32
293  %idxprom = sext i32 %conv to i64
294  %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom
295  store i32 %conv, i32* %arrayidx, align 4
296  %dec.int = add nsw i32 %iv.int, -1
297  %cmp = icmp ugt i32 %dec.int, -100
298  br i1 %cmp, label %for.body, label %cleanup
299
300cleanup:                                          ; preds = %for.body
301  ret void
302}
303
304