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