1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; (X < C1) ? C1 : MIN(X, C2)
5define float @clamp_float_fast_ordered_strict_maxmin(float %x) {
6;
7; CHECK-LABEL: @clamp_float_fast_ordered_strict_maxmin(
8; CHECK-NEXT:    [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02
9; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
10; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
11; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
12; CHECK-NEXT:    ret float [[R1]]
13;
14  %cmp2 = fcmp fast olt float %x, 255.0
15  %min = select i1 %cmp2, float %x, float 255.0
16  %cmp1 = fcmp fast olt float %x, 1.0
17  %r = select i1 %cmp1, float 1.0, float %min
18  ret float %r
19}
20
21; (X <= C1) ? C1 : MIN(X, C2)
22define float @clamp_float_fast_ordered_nonstrict_maxmin(float %x) {
23;
24; CHECK-LABEL: @clamp_float_fast_ordered_nonstrict_maxmin(
25; CHECK-NEXT:    [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02
26; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
27; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
28; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
29; CHECK-NEXT:    ret float [[R1]]
30;
31  %cmp2 = fcmp fast olt float %x, 255.0
32  %min = select i1 %cmp2, float %x, float 255.0
33  %cmp1 = fcmp fast ole float %x, 1.0
34  %r = select i1 %cmp1, float 1.0, float %min
35  ret float %r
36}
37
38; (X > C1) ? C1 : MAX(X, C2)
39define float @clamp_float_fast_ordered_strict_minmax(float %x) {
40;
41; CHECK-LABEL: @clamp_float_fast_ordered_strict_minmax(
42; CHECK-NEXT:    [[CMP2:%.*]] = fcmp fast ogt float [[X:%.*]], 1.000000e+00
43; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
44; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
45; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
46; CHECK-NEXT:    ret float [[R1]]
47;
48  %cmp2 = fcmp fast ogt float %x, 1.0
49  %max = select i1 %cmp2, float %x, float 1.0
50  %cmp1 = fcmp fast ogt float %x, 255.0
51  %r = select i1 %cmp1, float 255.0, float %max
52  ret float %r
53}
54
55; (X >= C1) ? C1 : MAX(X, C2)
56define float @clamp_float_fast_ordered_nonstrict_minmax(float %x) {
57;
58; CHECK-LABEL: @clamp_float_fast_ordered_nonstrict_minmax(
59; CHECK-NEXT:    [[CMP2:%.*]] = fcmp fast ogt float [[X:%.*]], 1.000000e+00
60; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
61; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
62; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
63; CHECK-NEXT:    ret float [[R1]]
64;
65  %cmp2 = fcmp fast ogt float %x, 1.0
66  %max = select i1 %cmp2, float %x, float 1.0
67  %cmp1 = fcmp fast oge float %x, 255.0
68  %r = select i1 %cmp1, float 255.0, float %max
69  ret float %r
70}
71
72
73; The same for unordered
74
75; (X < C1) ? C1 : MIN(X, C2)
76define float @clamp_float_fast_unordered_strict_maxmin(float %x) {
77;
78; CHECK-LABEL: @clamp_float_fast_unordered_strict_maxmin(
79; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
80; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
81; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
82; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
83; CHECK-NEXT:    ret float [[R1]]
84;
85  %cmp2 = fcmp fast ult float %x, 255.0
86  %min = select i1 %cmp2, float %x, float 255.0
87  %cmp1 = fcmp fast ult float %x, 1.0
88  %r = select i1 %cmp1, float 1.0, float %min
89  ret float %r
90}
91
92; (X <= C1) ? C1 : MIN(X, C2)
93define float @clamp_float_fast_unordered_nonstrict_maxmin(float %x) {
94;
95; CHECK-LABEL: @clamp_float_fast_unordered_nonstrict_maxmin(
96; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
97; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
98; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
99; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
100; CHECK-NEXT:    ret float [[R1]]
101;
102  %cmp2 = fcmp fast ult float %x, 255.0
103  %min = select i1 %cmp2, float %x, float 255.0
104  %cmp1 = fcmp fast ule float %x, 1.0
105  %r = select i1 %cmp1, float 1.0, float %min
106  ret float %r
107}
108
109; (X > C1) ? C1 : MAX(X, C2)
110define float @clamp_float_fast_unordered_strict_minmax(float %x) {
111;
112; CHECK-LABEL: @clamp_float_fast_unordered_strict_minmax(
113; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00
114; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
115; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
116; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
117; CHECK-NEXT:    ret float [[R1]]
118;
119  %cmp2 = fcmp fast ugt float %x, 1.0
120  %max = select i1 %cmp2, float %x, float 1.0
121  %cmp1 = fcmp fast ugt float %x, 255.0
122  %r = select i1 %cmp1, float 255.0, float %max
123  ret float %r
124}
125
126; (X >= C1) ? C1 : MAX(X, C2)
127define float @clamp_float_fast_unordered_nonstrict_minmax(float %x) {
128;
129; CHECK-LABEL: @clamp_float_fast_unordered_nonstrict_minmax(
130; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00
131; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
132; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
133; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
134; CHECK-NEXT:    ret float [[R1]]
135;
136  %cmp2 = fcmp fast ugt float %x, 1.0
137  %max = select i1 %cmp2, float %x, float 1.0
138  %cmp1 = fcmp fast uge float %x, 255.0
139  %r = select i1 %cmp1, float 255.0, float %max
140  ret float %r
141}
142
143; Some more checks with fast
144
145; (X > 1.0) ? min(x, 255.0) : 1.0
146; That did not match because select was in inverse order.
147define float @clamp_test_1(float %x) {
148; CHECK-LABEL: @clamp_test_1(
149; CHECK-NEXT:    [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
150; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
151; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp fast oge float [[INNER_SEL]], 1.000000e+00
152; CHECK-NEXT:    [[R1:%.*]] = select i1 [[DOTINV]], float [[INNER_SEL]], float 1.000000e+00
153; CHECK-NEXT:    ret float [[R1]]
154;
155  %inner_cmp = fcmp fast ult float %x, 255.0
156  %inner_sel = select i1 %inner_cmp, float %x, float 255.0
157  %outer_cmp = fcmp fast ugt float %x, 1.0
158  %r = select i1 %outer_cmp, float %inner_sel, float 1.0
159  ret float %r
160}
161
162; And something negative
163
164; Like @clamp_test_1 but HighConst < LowConst
165define float @clamp_negative_wrong_const(float %x) {
166; CHECK-LABEL: @clamp_negative_wrong_const(
167; CHECK-NEXT:    [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
168; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
169; CHECK-NEXT:    [[OUTER_CMP:%.*]] = fcmp fast ugt float [[X]], 5.120000e+02
170; CHECK-NEXT:    [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 5.120000e+02
171; CHECK-NEXT:    ret float [[R]]
172;
173  %inner_cmp = fcmp fast ult float %x, 255.0
174  %inner_sel = select i1 %inner_cmp, float %x, float 255.0
175  %outer_cmp = fcmp fast ugt float %x, 512.0
176  %r = select i1 %outer_cmp, float %inner_sel, float 512.0
177  ret float %r
178}
179
180; Like @clamp_test_1 but both are min
181define float @clamp_negative_same_op(float %x) {
182; CHECK-LABEL: @clamp_negative_same_op(
183; CHECK-NEXT:    [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
184; CHECK-NEXT:    [[INNER_SEL:%.*]] = select i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
185; CHECK-NEXT:    [[OUTER_CMP:%.*]] = fcmp fast ult float [[X]], 1.000000e+00
186; CHECK-NEXT:    [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 1.000000e+00
187; CHECK-NEXT:    ret float [[R]]
188;
189  %inner_cmp = fcmp fast ult float %x, 255.0
190  %inner_sel = select i1 %inner_cmp, float %x, float 255.0
191  %outer_cmp = fcmp fast ult float %x, 1.0
192  %r = select i1 %outer_cmp, float %inner_sel, float 1.0
193  ret float %r
194}
195
196
197; And now without fast.
198
199; First, check that we don't do bad things in the presence of signed zeros
200define float @clamp_float_with_zero1(float %x) {
201; CHECK-LABEL: @clamp_float_with_zero1(
202; CHECK-NEXT:    [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02
203; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
204; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ole float [[X]], 0.000000e+00
205; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 0.000000e+00, float [[MIN]]
206; CHECK-NEXT:    ret float [[R]]
207;
208  %cmp2 = fcmp fast olt float %x, 255.0
209  %min = select i1 %cmp2, float %x, float 255.0
210  %cmp1 = fcmp ole float %x, 0.0
211  %r = select i1 %cmp1, float 0.0, float %min
212  ret float %r
213}
214
215define float @clamp_float_with_zero2(float %x) {
216; CHECK-LABEL: @clamp_float_with_zero2(
217; CHECK-NEXT:    [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02
218; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
219; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[X]], 0.000000e+00
220; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 0.000000e+00, float [[MIN]]
221; CHECK-NEXT:    ret float [[R]]
222;
223  %cmp2 = fcmp fast olt float %x, 255.0
224  %min = select i1 %cmp2, float %x, float 255.0
225  %cmp1 = fcmp olt float %x, 0.0
226  %r = select i1 %cmp1, float 0.0, float %min
227  ret float %r
228}
229
230; Also, here we care more about the ordering of the inner min/max, so
231; two times more cases.
232; TODO: that is not implemented yet, so these checks are for the
233;       future. This means that checks below can just check that
234;       "fcmp.*%x" happens twice for each label.
235
236; (X < C1) ? C1 : MIN(X, C2)
237define float @clamp_float_ordered_strict_maxmin1(float %x) {
238;
239; CHECK-LABEL: @clamp_float_ordered_strict_maxmin1(
240; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02
241; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
242; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[X]], 1.000000e+00
243; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
244; CHECK-NEXT:    ret float [[R]]
245;
246  %cmp2 = fcmp olt float %x, 255.0                   ; X is NaN => false
247  %min = select i1 %cmp2, float %x, float 255.0      ;             255.0
248  %cmp1 = fcmp olt float %x, 1.0                     ;             false
249  %r = select i1 %cmp1, float 1.0, float %min        ;             min (255.0)
250  ret float %r
251}
252
253define float @clamp_float_ordered_strict_maxmin2(float %x) {
254;
255; CHECK-LABEL: @clamp_float_ordered_strict_maxmin2(
256; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02
257; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
258; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[X]], 1.000000e+00
259; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
260; CHECK-NEXT:    ret float [[R]]
261;
262  %cmp2 = fcmp ult float %x, 255.0                  ; X is NaN => true
263  %min = select i1 %cmp2, float %x, float 255.0     ;             NaN
264  %cmp1 = fcmp olt float %x, 1.0                    ;             false
265  %r = select i1 %cmp1, float 1.0, float %min       ;             min (NaN)
266  ret float %r
267}
268
269; (X <= C1) ? C1 : MIN(X, C2)
270define float @clamp_float_ordered_nonstrict_maxmin1(float %x) {
271;
272; CHECK-LABEL: @clamp_float_ordered_nonstrict_maxmin1(
273; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02
274; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
275; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ole float [[X]], 1.000000e+00
276; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
277; CHECK-NEXT:    ret float [[R]]
278;
279  %cmp2 = fcmp olt float %x, 255.0                  ; X is NaN => false
280  %min = select i1 %cmp2, float %x, float 255.0     ;             255.0
281  %cmp1 = fcmp ole float %x, 1.0                    ;             false
282  %r = select i1 %cmp1, float 1.0, float %min       ;             min (255.0)
283  ret float %r
284}
285
286define float @clamp_float_ordered_nonstrict_maxmin2(float %x) {
287;
288; CHECK-LABEL: @clamp_float_ordered_nonstrict_maxmin2(
289; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02
290; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
291; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ole float [[X]], 1.000000e+00
292; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
293; CHECK-NEXT:    ret float [[R]]
294;
295  %cmp2 = fcmp ult float %x, 255.0                  ; x is NaN => true
296  %min = select i1 %cmp2, float %x, float 255.0     ;             NaN
297  %cmp1 = fcmp ole float %x, 1.0                    ;             false
298  %r = select i1 %cmp1, float 1.0, float %min       ;             min (NaN)
299  ret float %r
300}
301
302; (X > C1) ? C1 : MAX(X, C2)
303define float @clamp_float_ordered_strict_minmax1(float %x) {
304;
305; CHECK-LABEL: @clamp_float_ordered_strict_minmax1(
306; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00
307; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
308; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ogt float [[X]], 2.550000e+02
309; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
310; CHECK-NEXT:    ret float [[R]]
311;
312  %cmp2 = fcmp ogt float %x, 1.0                    ; x is NaN => false
313  %max = select i1 %cmp2, float %x, float 1.0       ;             1.0
314  %cmp1 = fcmp ogt float %x, 255.0                  ;             false
315  %r = select i1 %cmp1, float 255.0, float %max     ;             max (1.0)
316  ret float %r
317}
318
319define float @clamp_float_ordered_strict_minmax2(float %x) {
320;
321; CHECK-LABEL: @clamp_float_ordered_strict_minmax2(
322; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00
323; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
324; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ogt float [[X]], 2.550000e+02
325; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
326; CHECK-NEXT:    ret float [[R]]
327;
328  %cmp2 = fcmp ugt float %x, 1.0                    ; x is NaN => true
329  %max = select i1 %cmp2, float %x, float 1.0       ;             NaN
330  %cmp1 = fcmp ogt float %x, 255.0                  ;             false
331  %r = select i1 %cmp1, float 255.0, float %max     ;             max (NaN)
332  ret float %r
333}
334
335; (X >= C1) ? C1 : MAX(X, C2)
336define float @clamp_float_ordered_nonstrict_minmax1(float %x) {
337;
338; CHECK-LABEL: @clamp_float_ordered_nonstrict_minmax1(
339; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00
340; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
341; CHECK-NEXT:    [[CMP1:%.*]] = fcmp oge float [[X]], 2.550000e+02
342; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
343; CHECK-NEXT:    ret float [[R]]
344;
345  %cmp2 = fcmp ogt float %x, 1.0                    ; x is NaN => false
346  %max = select i1 %cmp2, float %x, float 1.0       ;             1.0
347  %cmp1 = fcmp oge float %x, 255.0                  ;             false
348  %r = select i1 %cmp1, float 255.0, float %max     ;             max (1.0)
349  ret float %r
350}
351
352define float @clamp_float_ordered_nonstrict_minmax2(float %x) {
353;
354; CHECK-LABEL: @clamp_float_ordered_nonstrict_minmax2(
355; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00
356; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
357; CHECK-NEXT:    [[CMP1:%.*]] = fcmp oge float [[X]], 2.550000e+02
358; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
359; CHECK-NEXT:    ret float [[R]]
360;
361  %cmp2 = fcmp ugt float %x, 1.0                    ; x is NaN => true
362  %max = select i1 %cmp2, float %x, float 1.0       ;             NaN
363  %cmp1 = fcmp oge float %x, 255.0                  ;             false
364  %r = select i1 %cmp1, float 255.0, float %max     ;             max (NaN)
365  ret float %r
366}
367
368
369; The same for unordered
370
371; (X < C1) ? C1 : MIN(X, C2)
372define float @clamp_float_unordered_strict_maxmin1(float %x) {
373;
374; CHECK-LABEL: @clamp_float_unordered_strict_maxmin1(
375; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02
376; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
377; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ult float [[X]], 1.000000e+00
378; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
379; CHECK-NEXT:    ret float [[R]]
380;
381  %cmp2 = fcmp olt float %x, 255.0                  ; x is NaN => false
382  %min = select i1 %cmp2, float %x, float 255.0     ;             255.0
383  %cmp1 = fcmp ult float %x, 1.0                    ;             true
384  %r = select i1 %cmp1, float 1.0, float %min       ;             1.0
385  ret float %r
386}
387
388define float @clamp_float_unordered_strict_maxmin2(float %x) {
389;
390; CHECK-LABEL: @clamp_float_unordered_strict_maxmin2(
391; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02
392; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
393; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ult float [[X]], 1.000000e+00
394; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
395; CHECK-NEXT:    ret float [[R]]
396;
397  %cmp2 = fcmp ult float %x, 255.0                  ; x is NaN => true
398  %min = select i1 %cmp2, float %x, float 255.0     ;             NaN
399  %cmp1 = fcmp ult float %x, 1.0                    ;             true
400  %r = select i1 %cmp1, float 1.0, float %min       ;             1.0
401  ret float %r
402}
403
404; (X <= C1) ? C1 : MIN(X, C2)
405define float @clamp_float_unordered_nonstrict_maxmin1(float %x) {
406;
407; CHECK-LABEL: @clamp_float_unordered_nonstrict_maxmin1(
408; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02
409; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
410; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ule float [[X]], 1.000000e+00
411; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
412; CHECK-NEXT:    ret float [[R]]
413;
414  %cmp2 = fcmp olt float %x, 255.0                  ; x is NaN => false
415  %min = select i1 %cmp2, float %x, float 255.0     ;             255.0
416  %cmp1 = fcmp ule float %x, 1.0                    ;             true
417  %r = select i1 %cmp1, float 1.0, float %min       ;             1.0
418  ret float %r
419}
420
421define float @clamp_float_unordered_nonstrict_maxmin2(float %x) {
422;
423; CHECK-LABEL: @clamp_float_unordered_nonstrict_maxmin2(
424; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02
425; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
426; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ule float [[X]], 1.000000e+00
427; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
428; CHECK-NEXT:    ret float [[R]]
429;
430  %cmp2 = fcmp ult float %x, 255.0                  ; x is NaN => true
431  %min = select i1 %cmp2, float %x, float 255.0     ;             NaN
432  %cmp1 = fcmp ule float %x, 1.0                    ;             true
433  %r = select i1 %cmp1, float 1.0, float %min       ;             1.0
434  ret float %r
435}
436
437; (X > C1) ? C1 : MAX(X, C2)
438define float @clamp_float_unordered_strict_minmax1(float %x) {
439;
440; CHECK-LABEL: @clamp_float_unordered_strict_minmax1(
441; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00
442; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
443; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ugt float [[X]], 2.550000e+02
444; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
445; CHECK-NEXT:    ret float [[R]]
446;
447  %cmp2 = fcmp ogt float %x, 1.0                    ; x is NaN => false
448  %max = select i1 %cmp2, float %x, float 1.0       ;             1.0
449  %cmp1 = fcmp ugt float %x, 255.0                  ;             true
450  %r = select i1 %cmp1, float 255.0, float %max     ;             255.0
451  ret float %r
452}
453
454define float @clamp_float_unordered_strict_minmax2(float %x) {
455;
456; CHECK-LABEL: @clamp_float_unordered_strict_minmax2(
457; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00
458; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
459; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ugt float [[X]], 2.550000e+02
460; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
461; CHECK-NEXT:    ret float [[R]]
462;
463  %cmp2 = fcmp ugt float %x, 1.0                    ; x is NaN => true
464  %max = select i1 %cmp2, float %x, float 1.0       ;             NaN
465  %cmp1 = fcmp ugt float %x, 255.0                  ;             true
466  %r = select i1 %cmp1, float 255.0, float %max     ;             255.0
467  ret float %r
468}
469
470; (X >= C1) ? C1 : MAX(X, C2)
471define float @clamp_float_unordered_nonstrict_minmax1(float %x) {
472;
473; CHECK-LABEL: @clamp_float_unordered_nonstrict_minmax1(
474; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00
475; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
476; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uge float [[X]], 2.550000e+02
477; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
478; CHECK-NEXT:    ret float [[R]]
479;
480  %cmp2 = fcmp ogt float %x, 1.0                    ; x is NaN => false
481  %max = select i1 %cmp2, float %x, float 1.0       ;             1.0
482  %cmp1 = fcmp uge float %x, 255.0                  ;             true
483  %r = select i1 %cmp1, float 255.0, float %max     ;             255.0
484  ret float %r
485}
486
487define float @clamp_float_unordered_nonstrict_minmax2(float %x) {
488;
489; CHECK-LABEL: @clamp_float_unordered_nonstrict_minmax2(
490; CHECK-NEXT:    [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00
491; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
492; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uge float [[X]], 2.550000e+02
493; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
494; CHECK-NEXT:    ret float [[R]]
495;
496  %cmp2 = fcmp ugt float %x, 1.0                    ; x is NaN => true
497  %max = select i1 %cmp2, float %x, float 1.0       ;             NaN
498  %cmp1 = fcmp uge float %x, 255.0                  ;             true
499  %r = select i1 %cmp1, float 255.0, float %max     ;             255.0
500  ret float %r
501}
502
503;; Check casts behavior
504define float @ui32_clamp_and_cast_to_float(i32 %x) {
505; CHECK-LABEL: @ui32_clamp_and_cast_to_float(
506; CHECK-NEXT:    [[LO_CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
507; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X]], 255
508; CHECK-NEXT:    [[MIN1:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 255
509; CHECK-NEXT:    [[TMP2:%.*]] = uitofp i32 [[MIN1]] to float
510; CHECK-NEXT:    [[R:%.*]] = select i1 [[LO_CMP]], float 1.000000e+00, float [[TMP2]]
511; CHECK-NEXT:    ret float [[R]]
512;
513  %f_x = uitofp i32 %x to float
514  %up_cmp = icmp ugt i32 %x, 255
515  %lo_cmp = icmp ult i32 %x, 1
516  %min = select i1 %up_cmp, float 255.0, float %f_x
517  %r = select i1 %lo_cmp, float 1.0, float %min
518  ret float %r
519}
520
521define float @ui64_clamp_and_cast_to_float(i64 %x) {
522; CHECK-LABEL: @ui64_clamp_and_cast_to_float(
523; CHECK-NEXT:    [[LO_CMP:%.*]] = icmp eq i64 [[X:%.*]], 0
524; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[X]], 255
525; CHECK-NEXT:    [[MIN1:%.*]] = select i1 [[TMP1]], i64 [[X]], i64 255
526; CHECK-NEXT:    [[TMP2:%.*]] = uitofp i64 [[MIN1]] to float
527; CHECK-NEXT:    [[R:%.*]] = select i1 [[LO_CMP]], float 1.000000e+00, float [[TMP2]]
528; CHECK-NEXT:    ret float [[R]]
529;
530  %f_x = uitofp i64 %x to float
531  %up_cmp = icmp ugt i64 %x, 255
532  %lo_cmp = icmp ult i64 %x, 1
533  %min = select i1 %up_cmp, float 255.0, float %f_x
534  %r = select i1 %lo_cmp, float 1.0, float %min
535  ret float %r
536}
537
538define float @mixed_clamp_to_float_1(i32 %x) {
539; CHECK-LABEL: @mixed_clamp_to_float_1(
540; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 255
541; CHECK-NEXT:    [[SI_MIN:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 255
542; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[SI_MIN]], 1
543; CHECK-NEXT:    [[R1:%.*]] = select i1 [[TMP2]], i32 [[SI_MIN]], i32 1
544; CHECK-NEXT:    [[TMP3:%.*]] = sitofp i32 [[R1]] to float
545; CHECK-NEXT:    ret float [[TMP3]]
546;
547  %si_min_cmp = icmp sgt i32 %x, 255
548  %si_min = select i1 %si_min_cmp, i32 255, i32 %x
549  %f_min = sitofp i32 %si_min to float
550  %f_x = sitofp i32 %x to float
551  %lo_cmp = fcmp ult float %f_x, 1.0
552  %r = select i1 %lo_cmp, float 1.0, float %f_min
553  ret float %r
554}
555
556define i32 @mixed_clamp_to_i32_1(float %x) {
557; CHECK-LABEL: @mixed_clamp_to_i32_1(
558; CHECK-NEXT:    [[FLOAT_MIN_CMP:%.*]] = fcmp ogt float [[X:%.*]], 2.550000e+02
559; CHECK-NEXT:    [[FLOAT_MIN:%.*]] = select i1 [[FLOAT_MIN_CMP]], float 2.550000e+02, float [[X]]
560; CHECK-NEXT:    [[I32_MIN:%.*]] = fptosi float [[FLOAT_MIN]] to i32
561; CHECK-NEXT:    [[I32_X:%.*]] = fptosi float [[X]] to i32
562; CHECK-NEXT:    [[LO_CMP:%.*]] = icmp eq i32 [[I32_X]], 0
563; CHECK-NEXT:    [[R:%.*]] = select i1 [[LO_CMP]], i32 1, i32 [[I32_MIN]]
564; CHECK-NEXT:    ret i32 [[R]]
565;
566  %float_min_cmp = fcmp ogt float %x, 255.0
567  %float_min = select i1 %float_min_cmp, float 255.0, float %x
568  %i32_min = fptosi float %float_min to i32
569  %i32_x = fptosi float %x to i32
570  %lo_cmp = icmp ult i32 %i32_x, 1
571  %r = select i1 %lo_cmp, i32 1, i32 %i32_min
572  ret i32 %r
573}
574
575define float @mixed_clamp_to_float_2(i32 %x) {
576; CHECK-LABEL: @mixed_clamp_to_float_2(
577; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 255
578; CHECK-NEXT:    [[SI_MIN:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 255
579; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[SI_MIN]], 1
580; CHECK-NEXT:    [[R1:%.*]] = select i1 [[TMP2]], i32 [[SI_MIN]], i32 1
581; CHECK-NEXT:    [[TMP3:%.*]] = sitofp i32 [[R1]] to float
582; CHECK-NEXT:    ret float [[TMP3]]
583;
584  %si_min_cmp = icmp sgt i32 %x, 255
585  %si_min = select i1 %si_min_cmp, i32 255, i32 %x
586  %f_min = sitofp i32 %si_min to float
587  %lo_cmp = icmp slt i32 %x, 1
588  %r = select i1 %lo_cmp, float 1.0, float %f_min
589  ret float %r
590}
591
592define i32 @mixed_clamp_to_i32_2(float %x) {
593; CHECK-LABEL: @mixed_clamp_to_i32_2(
594; CHECK-NEXT:    [[FLOAT_MIN_CMP:%.*]] = fcmp ogt float [[X:%.*]], 2.550000e+02
595; CHECK-NEXT:    [[FLOAT_MIN:%.*]] = select i1 [[FLOAT_MIN_CMP]], float 2.550000e+02, float [[X]]
596; CHECK-NEXT:    [[I32_MIN:%.*]] = fptosi float [[FLOAT_MIN]] to i32
597; CHECK-NEXT:    [[LO_CMP:%.*]] = fcmp olt float [[X]], 1.000000e+00
598; CHECK-NEXT:    [[R:%.*]] = select i1 [[LO_CMP]], i32 1, i32 [[I32_MIN]]
599; CHECK-NEXT:    ret i32 [[R]]
600;
601  %float_min_cmp = fcmp ogt float %x, 255.0
602  %float_min = select i1 %float_min_cmp, float 255.0, float %x
603  %i32_min = fptosi float %float_min to i32
604  %lo_cmp = fcmp olt float %x, 1.0
605  %r = select i1 %lo_cmp, i32 1, i32 %i32_min
606  ret i32 %r
607}
608