xref: /llvm-project/llvm/test/Transforms/Scalarizer/intrinsics.ll (revision 2302e4c32703b0fa368140dbebc78cc8b17ad42c)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes='function(scalarizer)' %s | FileCheck %s
3
4; Unary fp
5declare <2 x float> @llvm.sqrt.v2f32(<2 x float>)
6
7; Binary fp
8declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>)
9declare <2 x float> @llvm.minimum.v2f32(<2 x float>, <2 x float>)
10declare <2 x float> @llvm.maximum.v2f32(<2 x float>, <2 x float>)
11
12; Ternary fp
13declare <2 x float> @llvm.fma.v2f32(<2 x float>, <2 x float>, <2 x float>)
14
15; Unary int
16declare <2 x i32> @llvm.bswap.v2i32(<2 x i32>)
17
18; Unary int plus constant scalar operand
19declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1)
20
21; Unary fp plus any scalar operand
22declare <2 x float> @llvm.powi.v2f32.i32(<2 x float>, i32)
23
24; Binary int plus constant scalar operand
25declare <2 x i32> @llvm.smul.fix.sat.v2i32(<2 x i32>, <2 x i32>, i32)
26declare <2 x i32> @llvm.umul.fix.sat.v2i32(<2 x i32>, <2 x i32>, i32)
27
28; Unary fp operand, int return type
29declare <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float>)
30declare <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float>)
31
32; Unary fp operand, int return type
33declare <2 x i32> @llvm.lrint.v2i32.v2f32(<2 x float>)
34declare <2 x i32> @llvm.llrint.v2i32.v2f32(<2 x float>)
35
36; Bool return type, overloaded on fp operand type
37declare <2 x i1> @llvm.is.fpclass(<2 x float>, i32)
38
39
40define <2 x float> @scalarize_sqrt_v2f32(<2 x float> %x) #0 {
41; CHECK-LABEL: @scalarize_sqrt_v2f32(
42; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
43; CHECK-NEXT:    [[SQRT_I0:%.*]] = call float @llvm.sqrt.f32(float [[X_I0]])
44; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
45; CHECK-NEXT:    [[SQRT_I1:%.*]] = call float @llvm.sqrt.f32(float [[X_I1]])
46; CHECK-NEXT:    [[SQRT_UPTO0:%.*]] = insertelement <2 x float> poison, float [[SQRT_I0]], i64 0
47; CHECK-NEXT:    [[SQRT:%.*]] = insertelement <2 x float> [[SQRT_UPTO0]], float [[SQRT_I1]], i64 1
48; CHECK-NEXT:    ret <2 x float> [[SQRT]]
49;
50  %sqrt = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x)
51  ret <2 x float> %sqrt
52}
53
54define <2 x float> @scalarize_minnum_v2f32(<2 x float> %x, <2 x float> %y) #0 {
55; CHECK-LABEL: @scalarize_minnum_v2f32(
56; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
57; CHECK-NEXT:    [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0
58; CHECK-NEXT:    [[MINNUM_I0:%.*]] = call float @llvm.minnum.f32(float [[X_I0]], float [[Y_I0]])
59; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
60; CHECK-NEXT:    [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1
61; CHECK-NEXT:    [[MINNUM_I1:%.*]] = call float @llvm.minnum.f32(float [[X_I1]], float [[Y_I1]])
62; CHECK-NEXT:    [[MINNUM_UPTO0:%.*]] = insertelement <2 x float> poison, float [[MINNUM_I0]], i64 0
63; CHECK-NEXT:    [[MINNUM:%.*]] = insertelement <2 x float> [[MINNUM_UPTO0]], float [[MINNUM_I1]], i64 1
64; CHECK-NEXT:    ret <2 x float> [[MINNUM]]
65;
66  %minnum = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> %y)
67  ret <2 x float> %minnum
68}
69
70define <2 x float> @scalarize_minimum_v2f32(<2 x float> %x, <2 x float> %y) #0 {
71; CHECK-LABEL: @scalarize_minimum_v2f32(
72; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
73; CHECK-NEXT:    [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0
74; CHECK-NEXT:    [[MINIMUM_I0:%.*]] = call float @llvm.minimum.f32(float [[X_I0]], float [[Y_I0]])
75; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
76; CHECK-NEXT:    [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1
77; CHECK-NEXT:    [[MINIMUM_I1:%.*]] = call float @llvm.minimum.f32(float [[X_I1]], float [[Y_I1]])
78; CHECK-NEXT:    [[MINIMUM_UPTO0:%.*]] = insertelement <2 x float> poison, float [[MINIMUM_I0]], i64 0
79; CHECK-NEXT:    [[MINIMUM:%.*]] = insertelement <2 x float> [[MINIMUM_UPTO0]], float [[MINIMUM_I1]], i64 1
80; CHECK-NEXT:    ret <2 x float> [[MINIMUM]]
81;
82  %minimum = call <2 x float> @llvm.minimum.v2f32(<2 x float> %x, <2 x float> %y)
83  ret <2 x float> %minimum
84}
85
86define <2 x float> @scalarize_maximum_v2f32(<2 x float> %x, <2 x float> %y) #0 {
87; CHECK-LABEL: @scalarize_maximum_v2f32(
88; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
89; CHECK-NEXT:    [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0
90; CHECK-NEXT:    [[MAXIMUM_I0:%.*]] = call float @llvm.maximum.f32(float [[X_I0]], float [[Y_I0]])
91; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
92; CHECK-NEXT:    [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1
93; CHECK-NEXT:    [[MAXIMUM_I1:%.*]] = call float @llvm.maximum.f32(float [[X_I1]], float [[Y_I1]])
94; CHECK-NEXT:    [[MAXIMUM_UPTO0:%.*]] = insertelement <2 x float> poison, float [[MAXIMUM_I0]], i64 0
95; CHECK-NEXT:    [[MAXIMUM:%.*]] = insertelement <2 x float> [[MAXIMUM_UPTO0]], float [[MAXIMUM_I1]], i64 1
96; CHECK-NEXT:    ret <2 x float> [[MAXIMUM]]
97;
98  %maximum = call <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> %y)
99  ret <2 x float> %maximum
100}
101
102define <2 x float> @scalarize_fma_v2f32(<2 x float> %x, <2 x float> %y, <2 x float> %z) #0 {
103; CHECK-LABEL: @scalarize_fma_v2f32(
104; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
105; CHECK-NEXT:    [[Y_I0:%.*]] = extractelement <2 x float> [[Y:%.*]], i64 0
106; CHECK-NEXT:    [[Z_I0:%.*]] = extractelement <2 x float> [[Z:%.*]], i64 0
107; CHECK-NEXT:    [[FMA_I0:%.*]] = call float @llvm.fma.f32(float [[X_I0]], float [[Y_I0]], float [[Z_I0]])
108; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
109; CHECK-NEXT:    [[Y_I1:%.*]] = extractelement <2 x float> [[Y]], i64 1
110; CHECK-NEXT:    [[Z_I1:%.*]] = extractelement <2 x float> [[Z]], i64 1
111; CHECK-NEXT:    [[FMA_I1:%.*]] = call float @llvm.fma.f32(float [[X_I1]], float [[Y_I1]], float [[Z_I1]])
112; CHECK-NEXT:    [[FMA_UPTO0:%.*]] = insertelement <2 x float> poison, float [[FMA_I0]], i64 0
113; CHECK-NEXT:    [[FMA:%.*]] = insertelement <2 x float> [[FMA_UPTO0]], float [[FMA_I1]], i64 1
114; CHECK-NEXT:    ret <2 x float> [[FMA]]
115;
116  %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %x, <2 x float> %y, <2 x float> %z)
117  ret <2 x float> %fma
118}
119
120define <2 x i32> @scalarize_bswap_v2i32(<2 x i32> %x) #0 {
121; CHECK-LABEL: @scalarize_bswap_v2i32(
122; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0
123; CHECK-NEXT:    [[BSWAP_I0:%.*]] = call i32 @llvm.bswap.i32(i32 [[X_I0]])
124; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1
125; CHECK-NEXT:    [[BSWAP_I1:%.*]] = call i32 @llvm.bswap.i32(i32 [[X_I1]])
126; CHECK-NEXT:    [[BSWAP_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[BSWAP_I0]], i64 0
127; CHECK-NEXT:    [[BSWAP:%.*]] = insertelement <2 x i32> [[BSWAP_UPTO0]], i32 [[BSWAP_I1]], i64 1
128; CHECK-NEXT:    ret <2 x i32> [[BSWAP]]
129;
130  %bswap = call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %x)
131  ret <2 x i32> %bswap
132}
133
134define <2 x i32> @scalarize_ctlz_v2i32(<2 x i32> %x) #0 {
135; CHECK-LABEL: @scalarize_ctlz_v2i32(
136; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0
137; CHECK-NEXT:    [[CTLZ_I0:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X_I0]], i1 true)
138; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1
139; CHECK-NEXT:    [[CTLZ_I1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X_I1]], i1 true)
140; CHECK-NEXT:    [[CTLZ_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[CTLZ_I0]], i64 0
141; CHECK-NEXT:    [[CTLZ:%.*]] = insertelement <2 x i32> [[CTLZ_UPTO0]], i32 [[CTLZ_I1]], i64 1
142; CHECK-NEXT:    ret <2 x i32> [[CTLZ]]
143;
144  %ctlz = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %x, i1 true)
145  ret <2 x i32> %ctlz
146}
147
148define <2 x float> @scalarize_powi_v2f32(<2 x float> %x, i32 %y) #0 {
149; CHECK-LABEL: @scalarize_powi_v2f32(
150; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
151; CHECK-NEXT:    [[POWI_I0:%.*]] = call float @llvm.powi.f32.i32(float [[X_I0]], i32 [[Y:%.*]])
152; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
153; CHECK-NEXT:    [[POWI_I1:%.*]] = call float @llvm.powi.f32.i32(float [[X_I1]], i32 [[Y]])
154; CHECK-NEXT:    [[POWI_UPTO0:%.*]] = insertelement <2 x float> poison, float [[POWI_I0]], i64 0
155; CHECK-NEXT:    [[POWI:%.*]] = insertelement <2 x float> [[POWI_UPTO0]], float [[POWI_I1]], i64 1
156; CHECK-NEXT:    ret <2 x float> [[POWI]]
157;
158  %powi = call <2 x float> @llvm.powi.v2f32.i32(<2 x float> %x, i32 %y)
159  ret <2 x float> %powi
160}
161
162define <2 x i32> @scalarize_smul_fix_sat_v2i32(<2 x i32> %x) #0 {
163; CHECK-LABEL: @scalarize_smul_fix_sat_v2i32(
164; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0
165; CHECK-NEXT:    [[SMULFIXSAT_I0:%.*]] = call i32 @llvm.smul.fix.sat.i32(i32 [[X_I0]], i32 5, i32 31)
166; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1
167; CHECK-NEXT:    [[SMULFIXSAT_I1:%.*]] = call i32 @llvm.smul.fix.sat.i32(i32 [[X_I1]], i32 19, i32 31)
168; CHECK-NEXT:    [[SMULFIXSAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[SMULFIXSAT_I0]], i64 0
169; CHECK-NEXT:    [[SMULFIXSAT:%.*]] = insertelement <2 x i32> [[SMULFIXSAT_UPTO0]], i32 [[SMULFIXSAT_I1]], i64 1
170; CHECK-NEXT:    ret <2 x i32> [[SMULFIXSAT]]
171;
172  %smulfixsat = call <2 x i32> @llvm.smul.fix.sat.v2i32(<2 x i32> %x, <2 x i32> <i32 5, i32 19>, i32 31)
173  ret <2 x i32> %smulfixsat
174}
175
176define <2 x i32> @scalarize_umul_fix_sat_v2i32(<2 x i32> %x) #0 {
177; CHECK-LABEL: @scalarize_umul_fix_sat_v2i32(
178; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0
179; CHECK-NEXT:    [[UMULFIXSAT_I0:%.*]] = call i32 @llvm.umul.fix.sat.i32(i32 [[X_I0]], i32 5, i32 31)
180; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x i32> [[X]], i64 1
181; CHECK-NEXT:    [[UMULFIXSAT_I1:%.*]] = call i32 @llvm.umul.fix.sat.i32(i32 [[X_I1]], i32 19, i32 31)
182; CHECK-NEXT:    [[UMULFIXSAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[UMULFIXSAT_I0]], i64 0
183; CHECK-NEXT:    [[UMULFIXSAT:%.*]] = insertelement <2 x i32> [[UMULFIXSAT_UPTO0]], i32 [[UMULFIXSAT_I1]], i64 1
184; CHECK-NEXT:    ret <2 x i32> [[UMULFIXSAT]]
185;
186  %umulfixsat = call <2 x i32> @llvm.umul.fix.sat.v2i32(<2 x i32> %x, <2 x i32> <i32 5, i32 19>, i32 31)
187  ret <2 x i32> %umulfixsat
188}
189
190define <2 x i32> @scalarize_fptosi_sat(<2 x float> %x) #0 {
191; CHECK-LABEL: @scalarize_fptosi_sat(
192; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
193; CHECK-NEXT:    [[SAT_I0:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[X_I0]])
194; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
195; CHECK-NEXT:    [[SAT_I1:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[X_I1]])
196; CHECK-NEXT:    [[SAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[SAT_I0]], i64 0
197; CHECK-NEXT:    [[SAT:%.*]] = insertelement <2 x i32> [[SAT_UPTO0]], i32 [[SAT_I1]], i64 1
198; CHECK-NEXT:    ret <2 x i32> [[SAT]]
199;
200  %sat = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f32(<2 x float> %x)
201  ret <2 x i32> %sat
202}
203
204define <2 x i32> @scalarize_fptoui_sat(<2 x float> %x) #0 {
205; CHECK-LABEL: @scalarize_fptoui_sat(
206; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
207; CHECK-NEXT:    [[SAT_I0:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[X_I0]])
208; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
209; CHECK-NEXT:    [[SAT_I1:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[X_I1]])
210; CHECK-NEXT:    [[SAT_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[SAT_I0]], i64 0
211; CHECK-NEXT:    [[SAT:%.*]] = insertelement <2 x i32> [[SAT_UPTO0]], i32 [[SAT_I1]], i64 1
212; CHECK-NEXT:    ret <2 x i32> [[SAT]]
213;
214  %sat = call <2 x i32> @llvm.fptoui.sat.v2i32.v2f32(<2 x float> %x)
215  ret <2 x i32> %sat
216}
217
218define <2 x i32> @scalarize_lrint(<2 x float> %x) #0 {
219; CHECK-LABEL: @scalarize_lrint(
220; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
221; CHECK-NEXT:    [[RND_I0:%.*]] = call i32 @llvm.lrint.i32.f32(float [[X_I0]])
222; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
223; CHECK-NEXT:    [[RND_I1:%.*]] = call i32 @llvm.lrint.i32.f32(float [[X_I1]])
224; CHECK-NEXT:    [[RND_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[RND_I0]], i64 0
225; CHECK-NEXT:    [[RND:%.*]] = insertelement <2 x i32> [[RND_UPTO0]], i32 [[RND_I1]], i64 1
226; CHECK-NEXT:    ret <2 x i32> [[RND]]
227;
228  %rnd = call <2 x i32> @llvm.lrint.v2i32.v2f32(<2 x float> %x)
229  ret <2 x i32> %rnd
230}
231
232define <2 x i32> @scalarize_llrint(<2 x float> %x) #0 {
233; CHECK-LABEL: @scalarize_llrint(
234; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
235; CHECK-NEXT:    [[RND_I0:%.*]] = call i32 @llvm.llrint.i32.f32(float [[X_I0]])
236; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
237; CHECK-NEXT:    [[RND_I1:%.*]] = call i32 @llvm.llrint.i32.f32(float [[X_I1]])
238; CHECK-NEXT:    [[RND_UPTO0:%.*]] = insertelement <2 x i32> poison, i32 [[RND_I0]], i64 0
239; CHECK-NEXT:    [[RND:%.*]] = insertelement <2 x i32> [[RND_UPTO0]], i32 [[RND_I1]], i64 1
240; CHECK-NEXT:    ret <2 x i32> [[RND]]
241;
242  %rnd = call <2 x i32> @llvm.llrint.v2i32.v2f32(<2 x float> %x)
243  ret <2 x i32> %rnd
244}
245
246define <2 x i1> @scalarize_is_fpclass(<2 x float> %x) #0 {
247; CHECK-LABEL: @scalarize_is_fpclass(
248; CHECK-NEXT:    [[X_I0:%.*]] = extractelement <2 x float> [[X:%.*]], i64 0
249; CHECK-NEXT:    [[ISFPCLASS_I0:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X_I0]], i32 123)
250; CHECK-NEXT:    [[X_I1:%.*]] = extractelement <2 x float> [[X]], i64 1
251; CHECK-NEXT:    [[ISFPCLASS_I1:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X_I1]], i32 123)
252; CHECK-NEXT:    [[ISFPCLASS_UPTO0:%.*]] = insertelement <2 x i1> poison, i1 [[ISFPCLASS_I0]], i64 0
253; CHECK-NEXT:    [[ISFPCLASS:%.*]] = insertelement <2 x i1> [[ISFPCLASS_UPTO0]], i1 [[ISFPCLASS_I1]], i64 1
254; CHECK-NEXT:    ret <2 x i1> [[ISFPCLASS]]
255;
256  %isfpclass = call <2 x i1> @llvm.is.fpclass(<2 x float> %x, i32 123)
257  ret <2 x i1> %isfpclass
258}
259