xref: /llvm-project/llvm/test/Transforms/InstCombine/fneg-fabs-as-int.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -S -passes=instcombine %s | FileCheck %s
3
4define i32 @fneg_fabs_as_int_f32_noimplicitfloat(float %x) noimplicitfloat {
5; CHECK-LABEL: define i32 @fneg_fabs_as_int_f32_noimplicitfloat
6; CHECK-SAME: (float [[X:%.*]]) #[[ATTR0:[0-9]+]] {
7; CHECK-NEXT:    [[BC:%.*]] = bitcast float [[X]] to i32
8; CHECK-NEXT:    [[OR:%.*]] = or i32 [[BC]], -2147483648
9; CHECK-NEXT:    ret i32 [[OR]]
10;
11  %bc = bitcast float %x to i32
12  %or = or i32 %bc, -2147483648
13  ret i32 %or
14}
15
16define <2 x i32> @fneg_fabs_as_int_v2f32_noimplicitfloat(<2 x float> %x) noimplicitfloat {
17; CHECK-LABEL: define <2 x i32> @fneg_fabs_as_int_v2f32_noimplicitfloat
18; CHECK-SAME: (<2 x float> [[X:%.*]]) #[[ATTR0]] {
19; CHECK-NEXT:    [[BC:%.*]] = bitcast <2 x float> [[X]] to <2 x i32>
20; CHECK-NEXT:    [[OR:%.*]] = or <2 x i32> [[BC]], splat (i32 -2147483648)
21; CHECK-NEXT:    ret <2 x i32> [[OR]]
22;
23  %bc = bitcast <2 x float> %x to <2 x i32>
24  %or = or <2 x i32> %bc, <i32 -2147483648, i32 -2147483648>
25  ret <2 x i32> %or
26}
27
28define float @fneg_fabs_fabs_as_int_f32_and_or(float %val) {
29; CHECK-LABEL: define float @fneg_fabs_fabs_as_int_f32_and_or
30; CHECK-SAME: (float [[VAL:%.*]]) {
31; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[VAL]])
32; CHECK-NEXT:    [[TMP2:%.*]] = fneg float [[TMP1]]
33; CHECK-NEXT:    ret float [[TMP2]]
34;
35  %bitcast = bitcast float %val to i32
36  %and = and i32 %bitcast, 2147483647
37  %or = or i32 %and, -2147483648
38  %fneg.fabs = bitcast i32 %or to float
39  ret float %fneg.fabs
40}
41
42define float @fneg_fabs_as_int_f32_castback(float %val) {
43; CHECK-LABEL: define float @fneg_fabs_as_int_f32_castback
44; CHECK-SAME: (float [[VAL:%.*]]) {
45; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[VAL]])
46; CHECK-NEXT:    [[TMP2:%.*]] = fneg float [[TMP1]]
47; CHECK-NEXT:    ret float [[TMP2]]
48;
49  %bitcast = bitcast float %val to i32
50  %or = or i32 %bitcast, -2147483648
51  %fneg = bitcast i32 %or to float
52  ret float %fneg
53}
54
55define float @not_fneg_fabs_as_int_f32_castback_wrongconst(float %val) {
56; CHECK-LABEL: define float @not_fneg_fabs_as_int_f32_castback_wrongconst
57; CHECK-SAME: (float [[VAL:%.*]]) {
58; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast float [[VAL]] to i32
59; CHECK-NEXT:    [[OR:%.*]] = or i32 [[BITCAST]], -2147483647
60; CHECK-NEXT:    [[FNEG:%.*]] = bitcast i32 [[OR]] to float
61; CHECK-NEXT:    ret float [[FNEG]]
62;
63  %bitcast = bitcast float %val to i32
64  %or = or i32 %bitcast, -2147483647
65  %fneg = bitcast i32 %or to float
66  ret float %fneg
67}
68
69define float @fneg_fabs_as_int_f32_castback_multi_use(float %val, ptr %ptr) {
70; CHECK-LABEL: define float @fneg_fabs_as_int_f32_castback_multi_use
71; CHECK-SAME: (float [[VAL:%.*]], ptr [[PTR:%.*]]) {
72; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[VAL]])
73; CHECK-NEXT:    [[TMP2:%.*]] = fneg float [[TMP1]]
74; CHECK-NEXT:    store float [[TMP2]], ptr [[PTR]], align 4
75; CHECK-NEXT:    ret float [[TMP2]]
76;
77  %bitcast = bitcast float %val to i32
78  %or = or i32 %bitcast, -2147483648
79  store i32 %or, ptr %ptr
80  %fneg = bitcast i32 %or to float
81  ret float %fneg
82}
83
84define i64 @fneg_fabs_as_int_f64(double %x) {
85; CHECK-LABEL: define i64 @fneg_fabs_as_int_f64
86; CHECK-SAME: (double [[X:%.*]]) {
87; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X]])
88; CHECK-NEXT:    [[TMP2:%.*]] = fneg double [[TMP1]]
89; CHECK-NEXT:    [[OR:%.*]] = bitcast double [[TMP2]] to i64
90; CHECK-NEXT:    ret i64 [[OR]]
91;
92  %bc = bitcast double %x to i64
93  %or = or i64 %bc, -9223372036854775808
94  ret i64 %or
95}
96
97define <2 x i64> @fneg_fabs_as_int_v2f64(<2 x double> %x) {
98; CHECK-LABEL: define <2 x i64> @fneg_fabs_as_int_v2f64
99; CHECK-SAME: (<2 x double> [[X:%.*]]) {
100; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x double> @llvm.fabs.v2f64(<2 x double> [[X]])
101; CHECK-NEXT:    [[TMP2:%.*]] = fneg <2 x double> [[TMP1]]
102; CHECK-NEXT:    [[OR:%.*]] = bitcast <2 x double> [[TMP2]] to <2 x i64>
103; CHECK-NEXT:    ret <2 x i64> [[OR]]
104;
105  %bc = bitcast <2 x double> %x to <2 x i64>
106  %or = or <2 x i64> %bc, <i64 -9223372036854775808, i64 -9223372036854775808>
107  ret <2 x i64> %or
108}
109
110define i64 @fneg_fabs_as_int_f64_swap(double %x) {
111; CHECK-LABEL: define i64 @fneg_fabs_as_int_f64_swap
112; CHECK-SAME: (double [[X:%.*]]) {
113; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X]])
114; CHECK-NEXT:    [[TMP2:%.*]] = fneg double [[TMP1]]
115; CHECK-NEXT:    [[OR:%.*]] = bitcast double [[TMP2]] to i64
116; CHECK-NEXT:    ret i64 [[OR]]
117;
118  %bc = bitcast double %x to i64
119  %or = or i64 -9223372036854775808, %bc
120  ret i64 %or
121}
122
123define i32 @fneg_fabs_as_int_f32(float %x) {
124; CHECK-LABEL: define i32 @fneg_fabs_as_int_f32
125; CHECK-SAME: (float [[X:%.*]]) {
126; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
127; CHECK-NEXT:    [[TMP2:%.*]] = fneg float [[TMP1]]
128; CHECK-NEXT:    [[OR:%.*]] = bitcast float [[TMP2]] to i32
129; CHECK-NEXT:    ret i32 [[OR]]
130;
131  %bc = bitcast float %x to i32
132  %or = or i32 %bc, -2147483648
133  ret i32 %or
134}
135
136define <2 x i32> @fneg_fabs_as_int_v2f32(<2 x float> %x) {
137; CHECK-LABEL: define <2 x i32> @fneg_fabs_as_int_v2f32
138; CHECK-SAME: (<2 x float> [[X:%.*]]) {
139; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
140; CHECK-NEXT:    [[TMP2:%.*]] = fneg <2 x float> [[TMP1]]
141; CHECK-NEXT:    [[OR:%.*]] = bitcast <2 x float> [[TMP2]] to <2 x i32>
142; CHECK-NEXT:    ret <2 x i32> [[OR]]
143;
144  %bc = bitcast <2 x float> %x to <2 x i32>
145  %or = or <2 x i32> %bc, <i32 -2147483648, i32 -2147483648>
146  ret <2 x i32> %or
147}
148
149define <2 x i32> @not_fneg_fabs_as_int_v2f32_nonsplat(<2 x float> %x) {
150; CHECK-LABEL: define <2 x i32> @not_fneg_fabs_as_int_v2f32_nonsplat
151; CHECK-SAME: (<2 x float> [[X:%.*]]) {
152; CHECK-NEXT:    [[BC:%.*]] = bitcast <2 x float> [[X]] to <2 x i32>
153; CHECK-NEXT:    [[OR:%.*]] = or <2 x i32> [[BC]], <i32 -2147483648, i32 -2147483647>
154; CHECK-NEXT:    ret <2 x i32> [[OR]]
155;
156  %bc = bitcast <2 x float> %x to <2 x i32>
157  %or = or <2 x i32> %bc, <i32 -2147483648, i32 -2147483647>
158  ret <2 x i32> %or
159}
160
161define <3 x i32> @fneg_fabs_as_int_v3f32_poison(<3 x float> %x) {
162; CHECK-LABEL: define <3 x i32> @fneg_fabs_as_int_v3f32_poison
163; CHECK-SAME: (<3 x float> [[X:%.*]]) {
164; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x float> @llvm.fabs.v3f32(<3 x float> [[X]])
165; CHECK-NEXT:    [[TMP2:%.*]] = fneg <3 x float> [[TMP1]]
166; CHECK-NEXT:    [[OR:%.*]] = bitcast <3 x float> [[TMP2]] to <3 x i32>
167; CHECK-NEXT:    ret <3 x i32> [[OR]]
168;
169  %bc = bitcast <3 x float> %x to <3 x i32>
170  %or = or <3 x i32> %bc, <i32 -2147483648, i32 poison, i32 -2147483648>
171  ret <3 x i32> %or
172}
173
174; Make sure that only a bitcast is transformed.
175define i64 @fneg_fabs_as_int_f64_not_bitcast(double %x) {
176; CHECK-LABEL: define i64 @fneg_fabs_as_int_f64_not_bitcast
177; CHECK-SAME: (double [[X:%.*]]) {
178; CHECK-NEXT:    [[BC:%.*]] = fptoui double [[X]] to i64
179; CHECK-NEXT:    [[OR:%.*]] = or i64 [[BC]], -9223372036854775808
180; CHECK-NEXT:    ret i64 [[OR]]
181;
182  %bc = fptoui double %x to i64
183  %or = or i64 %bc, -9223372036854775808
184  ret i64 %or
185}
186
187define float @not_fneg_fabs_as_int_f32_bitcast_from_v2f16(<2 x half> %val) {
188; CHECK-LABEL: define float @not_fneg_fabs_as_int_f32_bitcast_from_v2f16
189; CHECK-SAME: (<2 x half> [[VAL:%.*]]) {
190; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast <2 x half> [[VAL]] to i32
191; CHECK-NEXT:    [[OR:%.*]] = or i32 [[BITCAST]], -2147483648
192; CHECK-NEXT:    [[FNEG:%.*]] = bitcast i32 [[OR]] to float
193; CHECK-NEXT:    ret float [[FNEG]]
194;
195  %bitcast = bitcast <2 x half> %val to i32
196  %or = or i32 %bitcast, -2147483648
197  %fneg = bitcast i32 %or to float
198  ret float %fneg
199}
200
201define float @not_fneg_fabs_as_int_f32_bitcast_from_v2i16(<2 x i16> %val) {
202; CHECK-LABEL: define float @not_fneg_fabs_as_int_f32_bitcast_from_v2i16
203; CHECK-SAME: (<2 x i16> [[VAL:%.*]]) {
204; CHECK-NEXT:    [[BITCAST:%.*]] = bitcast <2 x i16> [[VAL]] to i32
205; CHECK-NEXT:    [[OR:%.*]] = or i32 [[BITCAST]], -2147483648
206; CHECK-NEXT:    [[FNEG:%.*]] = bitcast i32 [[OR]] to float
207; CHECK-NEXT:    ret float [[FNEG]]
208;
209  %bitcast = bitcast <2 x i16> %val to i32
210  %or = or i32 %bitcast, -2147483648
211  %fneg = bitcast i32 %or to float
212  ret float %fneg
213}
214
215define i128 @fneg_fabs_as_int_fp128_f64_mask(fp128 %x) {
216; CHECK-LABEL: define i128 @fneg_fabs_as_int_fp128_f64_mask
217; CHECK-SAME: (fp128 [[X:%.*]]) {
218; CHECK-NEXT:    [[BC:%.*]] = bitcast fp128 [[X]] to i128
219; CHECK-NEXT:    [[OR:%.*]] = or i128 [[BC]], -9223372036854775808
220; CHECK-NEXT:    ret i128 [[OR]]
221;
222  %bc = bitcast fp128 %x to i128
223  %or = or i128 %bc, -9223372036854775808
224  ret i128 %or
225}
226
227define i128 @fneg_fabs_as_int_fp128_f128_mask(fp128 %x) {
228; CHECK-LABEL: define i128 @fneg_fabs_as_int_fp128_f128_mask
229; CHECK-SAME: (fp128 [[X:%.*]]) {
230; CHECK-NEXT:    [[TMP1:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X]])
231; CHECK-NEXT:    [[TMP2:%.*]] = fneg fp128 [[TMP1]]
232; CHECK-NEXT:    [[OR:%.*]] = bitcast fp128 [[TMP2]] to i128
233; CHECK-NEXT:    ret i128 [[OR]]
234;
235  %bc = bitcast fp128 %x to i128
236  %or = or i128 %bc, -170141183460469231731687303715884105728
237  ret i128 %or
238}
239
240define i16 @fneg_fabs_as_int_f16(half %x) {
241; CHECK-LABEL: define i16 @fneg_fabs_as_int_f16
242; CHECK-SAME: (half [[X:%.*]]) {
243; CHECK-NEXT:    [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X]])
244; CHECK-NEXT:    [[TMP2:%.*]] = fneg half [[TMP1]]
245; CHECK-NEXT:    [[OR:%.*]] = bitcast half [[TMP2]] to i16
246; CHECK-NEXT:    ret i16 [[OR]]
247;
248  %bc = bitcast half %x to i16
249  %or = or i16 %bc, -32768
250  ret i16 %or
251}
252
253define <2 x i16> @fneg_fabs_as_int_v2f16(<2 x half> %x) {
254; CHECK-LABEL: define <2 x i16> @fneg_fabs_as_int_v2f16
255; CHECK-SAME: (<2 x half> [[X:%.*]]) {
256; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X]])
257; CHECK-NEXT:    [[TMP2:%.*]] = fneg <2 x half> [[TMP1]]
258; CHECK-NEXT:    [[OR:%.*]] = bitcast <2 x half> [[TMP2]] to <2 x i16>
259; CHECK-NEXT:    ret <2 x i16> [[OR]]
260;
261  %bc = bitcast <2 x half> %x to <2 x i16>
262  %or = or <2 x i16> %bc, <i16 -32768, i16 -32768>
263  ret <2 x i16> %or
264}
265
266define i16 @fneg_fabs_as_int_bf16(bfloat %x) {
267; CHECK-LABEL: define i16 @fneg_fabs_as_int_bf16
268; CHECK-SAME: (bfloat [[X:%.*]]) {
269; CHECK-NEXT:    [[TMP1:%.*]] = call bfloat @llvm.fabs.bf16(bfloat [[X]])
270; CHECK-NEXT:    [[TMP2:%.*]] = fneg bfloat [[TMP1]]
271; CHECK-NEXT:    [[OR:%.*]] = bitcast bfloat [[TMP2]] to i16
272; CHECK-NEXT:    ret i16 [[OR]]
273;
274  %bc = bitcast bfloat %x to i16
275  %or = or i16 %bc, -32768
276  ret i16 %or
277}
278
279define <2 x i16> @fneg_fabs_as_int_v2bf16(<2 x bfloat> %x) {
280; CHECK-LABEL: define <2 x i16> @fneg_fabs_as_int_v2bf16
281; CHECK-SAME: (<2 x bfloat> [[X:%.*]]) {
282; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x bfloat> @llvm.fabs.v2bf16(<2 x bfloat> [[X]])
283; CHECK-NEXT:    [[TMP2:%.*]] = fneg <2 x bfloat> [[TMP1]]
284; CHECK-NEXT:    [[OR:%.*]] = bitcast <2 x bfloat> [[TMP2]] to <2 x i16>
285; CHECK-NEXT:    ret <2 x i16> [[OR]]
286;
287  %bc = bitcast <2 x bfloat> %x to <2 x i16>
288  %or = or <2 x i16> %bc, <i16 -32768, i16 -32768>
289  ret <2 x i16> %or
290}
291
292define i80 @fneg_fabs_as_int_x86_fp80_f64_mask(x86_fp80 %x) {
293; CHECK-LABEL: define i80 @fneg_fabs_as_int_x86_fp80_f64_mask
294; CHECK-SAME: (x86_fp80 [[X:%.*]]) {
295; CHECK-NEXT:    [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[X]])
296; CHECK-NEXT:    [[TMP2:%.*]] = fneg x86_fp80 [[TMP1]]
297; CHECK-NEXT:    [[OR:%.*]] = bitcast x86_fp80 [[TMP2]] to i80
298; CHECK-NEXT:    ret i80 [[OR]]
299;
300  %bc = bitcast x86_fp80 %x to i80
301  %or = or i80 %bc, -604462909807314587353088
302  ret i80 %or
303}
304
305define i128 @fneg_fabs_as_int_ppc_fp128_f64_mask(ppc_fp128 %x) {
306; CHECK-LABEL: define i128 @fneg_fabs_as_int_ppc_fp128_f64_mask
307; CHECK-SAME: (ppc_fp128 [[X:%.*]]) {
308; CHECK-NEXT:    [[BC:%.*]] = bitcast ppc_fp128 [[X]] to i128
309; CHECK-NEXT:    [[OR:%.*]] = or i128 [[BC]], -9223372036854775808
310; CHECK-NEXT:    ret i128 [[OR]]
311;
312  %bc = bitcast ppc_fp128 %x to i128
313  %or = or i128 %bc, -9223372036854775808
314  ret i128 %or
315}
316
317define i128 @fneg_fabs_as_int_ppc_fp128_f128_mask(ppc_fp128 %x) {
318; CHECK-LABEL: define i128 @fneg_fabs_as_int_ppc_fp128_f128_mask
319; CHECK-SAME: (ppc_fp128 [[X:%.*]]) {
320; CHECK-NEXT:    [[BC:%.*]] = bitcast ppc_fp128 [[X]] to i128
321; CHECK-NEXT:    [[OR:%.*]] = or i128 [[BC]], -170141183460469231731687303715884105728
322; CHECK-NEXT:    ret i128 [[OR]]
323;
324  %bc = bitcast ppc_fp128 %x to i128
325  %or = or i128 %bc, -170141183460469231731687303715884105728
326  ret i128 %or
327}
328