1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=aggressive-instcombine -mtriple aarch64 -S | FileCheck %s --check-prefixes=CHECK,CHECK-FP
3 ; RUN: opt < %s -passes=aggressive-instcombine -mtriple aarch64 -mattr=+fullfp16 -S | FileCheck %s --check-prefixes=CHECK,CHECK-FP16
5 define i64 @f32_i32(float %in) {
6 ; CHECK-LABEL: @f32_i32(
7 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[IN:%.*]])
8 ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64
9 ; CHECK-NEXT: ret i64 [[TMP2]]
11 %conv = fptosi float %in to i64
12 %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
13 %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
17 define i64 @f32_i31(float %in) {
18 ; CHECK-LABEL: @f32_i31(
19 ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[IN:%.*]] to i64
20 ; CHECK-NEXT: [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 1073741823)
21 ; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -1073741824)
22 ; CHECK-NEXT: ret i64 [[MAX]]
24 %conv = fptosi float %in to i64
25 %min = call i64 @llvm.smin.i64(i64 %conv, i64 1073741823)
26 %max = call i64 @llvm.smax.i64(i64 %min, i64 -1073741824)
30 define i32 @f32_i16(float %in) {
31 ; CHECK-LABEL: @f32_i16(
32 ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[IN:%.*]] to i32
33 ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 32767)
34 ; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -32768)
35 ; CHECK-NEXT: ret i32 [[MAX]]
37 %conv = fptosi float %in to i32
38 %min = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
39 %max = call i32 @llvm.smax.i32(i32 %min, i32 -32768)
43 define i32 @f32_i8(float %in) {
44 ; CHECK-LABEL: @f32_i8(
45 ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[IN:%.*]] to i32
46 ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 127)
47 ; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -128)
48 ; CHECK-NEXT: ret i32 [[MAX]]
50 %conv = fptosi float %in to i32
51 %min = call i32 @llvm.smin.i32(i32 %conv, i32 127)
52 %max = call i32 @llvm.smax.i32(i32 %min, i32 -128)
56 define i64 @f64_i32(double %in) {
57 ; CHECK-LABEL: @f64_i32(
58 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fptosi.sat.i32.f64(double [[IN:%.*]])
59 ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64
60 ; CHECK-NEXT: ret i64 [[TMP2]]
62 %conv = fptosi double %in to i64
63 %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
64 %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
68 define i64 @f64_i31(double %in) {
69 ; CHECK-LABEL: @f64_i31(
70 ; CHECK-NEXT: [[CONV:%.*]] = fptosi double [[IN:%.*]] to i64
71 ; CHECK-NEXT: [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 1073741823)
72 ; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -1073741824)
73 ; CHECK-NEXT: ret i64 [[MAX]]
75 %conv = fptosi double %in to i64
76 %min = call i64 @llvm.smin.i64(i64 %conv, i64 1073741823)
77 %max = call i64 @llvm.smax.i64(i64 %min, i64 -1073741824)
81 define i32 @f64_i16(double %in) {
82 ; CHECK-LABEL: @f64_i16(
83 ; CHECK-NEXT: [[CONV:%.*]] = fptosi double [[IN:%.*]] to i32
84 ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 32767)
85 ; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -32768)
86 ; CHECK-NEXT: ret i32 [[MAX]]
88 %conv = fptosi double %in to i32
89 %min = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
90 %max = call i32 @llvm.smax.i32(i32 %min, i32 -32768)
94 define i64 @f16_i32(half %in) {
95 ; CHECK-LABEL: @f16_i32(
96 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fptosi.sat.i32.f16(half [[IN:%.*]])
97 ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64
98 ; CHECK-NEXT: ret i64 [[TMP2]]
100 %conv = fptosi half %in to i64
101 %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
102 %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
106 define i64 @f16_i31(half %in) {
107 ; CHECK-LABEL: @f16_i31(
108 ; CHECK-NEXT: [[CONV:%.*]] = fptosi half [[IN:%.*]] to i64
109 ; CHECK-NEXT: [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 1073741823)
110 ; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -1073741824)
111 ; CHECK-NEXT: ret i64 [[MAX]]
113 %conv = fptosi half %in to i64
114 %min = call i64 @llvm.smin.i64(i64 %conv, i64 1073741823)
115 %max = call i64 @llvm.smax.i64(i64 %min, i64 -1073741824)
119 define i32 @f16_i16(half %in) {
120 ; CHECK-LABEL: @f16_i16(
121 ; CHECK-NEXT: [[CONV:%.*]] = fptosi half [[IN:%.*]] to i32
122 ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 32767)
123 ; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -32768)
124 ; CHECK-NEXT: ret i32 [[MAX]]
126 %conv = fptosi half %in to i32
127 %min = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
128 %max = call i32 @llvm.smax.i32(i32 %min, i32 -32768)
132 define i32 @f16_i8(half %in) {
133 ; CHECK-LABEL: @f16_i8(
134 ; CHECK-NEXT: [[CONV:%.*]] = fptosi half [[IN:%.*]] to i32
135 ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 127)
136 ; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -128)
137 ; CHECK-NEXT: ret i32 [[MAX]]
139 %conv = fptosi half %in to i32
140 %min = call i32 @llvm.smin.i32(i32 %conv, i32 127)
141 %max = call i32 @llvm.smax.i32(i32 %min, i32 -128)
145 define <2 x i64> @v2f32_i32(<2 x float> %in) {
146 ; CHECK-LABEL: @v2f32_i32(
147 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float> [[IN:%.*]])
148 ; CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
149 ; CHECK-NEXT: ret <2 x i64> [[TMP2]]
151 %conv = fptosi <2 x float> %in to <2 x i64>
152 %min = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %conv, <2 x i64> <i64 2147483647, i64 2147483647>)
153 %max = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %min, <2 x i64> <i64 -2147483648, i64 -2147483648>)
157 define <4 x i64> @v4f32_i32(<4 x float> %in) {
158 ; CHECK-LABEL: @v4f32_i32(
159 ; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> [[IN:%.*]])
160 ; CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i32> [[TMP1]] to <4 x i64>
161 ; CHECK-NEXT: ret <4 x i64> [[TMP2]]
163 %conv = fptosi <4 x float> %in to <4 x i64>
164 %min = call <4 x i64> @llvm.smin.v4i64(<4 x i64> %conv, <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>)
165 %max = call <4 x i64> @llvm.smax.v4i64(<4 x i64> %min, <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>)
169 define <8 x i64> @v8f32_i32(<8 x float> %in) {
170 ; CHECK-LABEL: @v8f32_i32(
171 ; CHECK-NEXT: [[TMP1:%.*]] = call <8 x i32> @llvm.fptosi.sat.v8i32.v8f32(<8 x float> [[IN:%.*]])
172 ; CHECK-NEXT: [[TMP2:%.*]] = sext <8 x i32> [[TMP1]] to <8 x i64>
173 ; CHECK-NEXT: ret <8 x i64> [[TMP2]]
175 %conv = fptosi <8 x float> %in to <8 x i64>
176 %min = call <8 x i64> @llvm.smin.v8i64(<8 x i64> %conv, <8 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>)
177 %max = call <8 x i64> @llvm.smax.v8i64(<8 x i64> %min, <8 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>)
181 define <4 x i32> @v4f16_i16(<4 x half> %in) {
182 ; CHECK-LABEL: @v4f16_i16(
183 ; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i16> @llvm.fptosi.sat.v4i16.v4f16(<4 x half> [[IN:%.*]])
184 ; CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
185 ; CHECK-NEXT: ret <4 x i32> [[TMP2]]
187 %conv = fptosi <4 x half> %in to <4 x i32>
188 %min = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %conv, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>)
189 %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %min, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>)
193 define <8 x i32> @v8f16_i16(<8 x half> %in) {
194 ; CHECK-LABEL: @v8f16_i16(
195 ; CHECK-NEXT: [[TMP1:%.*]] = call <8 x i16> @llvm.fptosi.sat.v8i16.v8f16(<8 x half> [[IN:%.*]])
196 ; CHECK-NEXT: [[TMP2:%.*]] = sext <8 x i16> [[TMP1]] to <8 x i32>
197 ; CHECK-NEXT: ret <8 x i32> [[TMP2]]
199 %conv = fptosi <8 x half> %in to <8 x i32>
200 %min = call <8 x i32> @llvm.smin.v8i32(<8 x i32> %conv, <8 x i32> <i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767>)
201 %max = call <8 x i32> @llvm.smax.v8i32(<8 x i32> %min, <8 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768>)
206 define i64 @f32_i32_extrause1(float %in) {
207 ; CHECK-LABEL: @f32_i32_extrause1(
208 ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[IN:%.*]] to i64
209 ; CHECK-NEXT: [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 2147483647)
210 ; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -2147483648)
211 ; CHECK-NEXT: call void @use(i64 [[MIN]])
212 ; CHECK-NEXT: ret i64 [[MAX]]
214 %conv = fptosi float %in to i64
215 %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
216 %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
217 call void @use(i64 %min)
221 define i64 @f32_i32_extrause2(float %in) {
222 ; CHECK-LABEL: @f32_i32_extrause2(
223 ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[IN:%.*]] to i64
224 ; CHECK-NEXT: [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 2147483647)
225 ; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -2147483648)
226 ; CHECK-NEXT: call void @use(i64 [[CONV]])
227 ; CHECK-NEXT: ret i64 [[MAX]]
229 %conv = fptosi float %in to i64
230 %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
231 %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
232 call void @use(i64 %conv)
236 define i64 @f32_i32_invertedconsts(float %in) {
237 ; CHECK-LABEL: @f32_i32_invertedconsts(
238 ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[IN:%.*]] to i64
239 ; CHECK-NEXT: [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 -2147483648)
240 ; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 2147483647)
241 ; CHECK-NEXT: ret i64 [[MAX]]
243 %conv = fptosi float %in to i64
244 %min = call i64 @llvm.smin.i64(i64 %conv, i64 -2147483648)
245 %max = call i64 @llvm.smax.i64(i64 %min, i64 2147483647)
249 define i64 @f32_i32_maxmin(float %in) {
250 ; CHECK-LABEL: @f32_i32_maxmin(
251 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[IN:%.*]])
252 ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64
253 ; CHECK-NEXT: ret i64 [[TMP2]]
255 %conv = fptosi float %in to i64
256 %max = call i64 @llvm.smax.i64(i64 %conv, i64 -2147483648)
257 %min = call i64 @llvm.smin.i64(i64 %max, i64 2147483647)
262 declare void @use(i64)
263 declare i64 @llvm.smin.i64(i64, i64)
264 declare i64 @llvm.smax.i64(i64, i64)
265 declare i32 @llvm.smin.i32(i32, i32)
266 declare i32 @llvm.smax.i32(i32, i32)
267 declare <2 x i64> @llvm.smin.v2i64(<2 x i64>, <2 x i64>)
268 declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>)
269 declare <4 x i64> @llvm.smin.v4i64(<4 x i64>, <4 x i64>)
270 declare <4 x i64> @llvm.smax.v4i64(<4 x i64>, <4 x i64>)
271 declare <8 x i64> @llvm.smin.v8i64(<8 x i64>, <8 x i64>)
272 declare <8 x i64> @llvm.smax.v8i64(<8 x i64>, <8 x i64>)
273 declare <4 x i32> @llvm.smin.v4i32(<4 x i32>, <4 x i32>)
274 declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>)
275 declare <8 x i32> @llvm.smin.v8i32(<8 x i32>, <8 x i32>)
276 declare <8 x i32> @llvm.smax.v8i32(<8 x i32>, <8 x i32>)
277 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: