xref: /llvm-project/clang/test/CodeGen/AArch64/sve-vls-shift-ops.c (revision 98e747ba56b2f8b51a7c797a3f379d02c545c42b)
1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
3 // RUN: -disable-O0-optnone -mvscale-min=4 -mvscale-max=4 \
4 // RUN:  -emit-llvm -o - %s | opt -S -passes=sroa | FileCheck %s
5 
6 // REQUIRES: aarch64-registered-target
7 
8 #include <arm_sve.h>
9 
10 #define N 512
11 
12 typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N)));
13 typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N)));
14 typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N)));
15 typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
16 
17 typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N)));
18 typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N)));
19 typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N)));
20 typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N)));
21 
22 typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N)));
23 typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N)));
24 typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N)));
25 
26 typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
27 
28 // CHECK-LABEL: @lshift_i8(
29 // CHECK-NEXT:  entry:
30 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
31 // CHECK-NEXT:    [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[B_COERCE:%.*]], i64 0)
32 // CHECK-NEXT:    [[SHL:%.*]] = shl <64 x i8> [[A]], [[B]]
33 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHL]], i64 0)
34 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
35 //
36 fixed_int8_t lshift_i8(fixed_int8_t a, fixed_int8_t b) {
37   return a << b;
38 }
39 
40 // CHECK-LABEL: @rshift_i8(
41 // CHECK-NEXT:  entry:
42 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
43 // CHECK-NEXT:    [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[B_COERCE:%.*]], i64 0)
44 // CHECK-NEXT:    [[SHR:%.*]] = ashr <64 x i8> [[A]], [[B]]
45 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHR]], i64 0)
46 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
47 //
48 fixed_int8_t rshift_i8(fixed_int8_t a, fixed_int8_t b) {
49   return a >> b;
50 }
51 
52 // CHECK-LABEL: @lshift_u8(
53 // CHECK-NEXT:  entry:
54 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
55 // CHECK-NEXT:    [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[B_COERCE:%.*]], i64 0)
56 // CHECK-NEXT:    [[SHL:%.*]] = shl <64 x i8> [[A]], [[B]]
57 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHL]], i64 0)
58 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
59 //
60 fixed_uint8_t lshift_u8(fixed_uint8_t a, fixed_uint8_t b) {
61   return a << b;
62 }
63 
64 // CHECK-LABEL: @rshift_u8(
65 // CHECK-NEXT:  entry:
66 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
67 // CHECK-NEXT:    [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[B_COERCE:%.*]], i64 0)
68 // CHECK-NEXT:    [[SHR:%.*]] = lshr <64 x i8> [[A]], [[B]]
69 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHR]], i64 0)
70 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
71 //
72 fixed_uint8_t rshift_u8(fixed_uint8_t a, fixed_uint8_t b) {
73   return a >> b;
74 }
75 
76 // CHECK-LABEL: @lshift_i16(
77 // CHECK-NEXT:  entry:
78 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
79 // CHECK-NEXT:    [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[B_COERCE:%.*]], i64 0)
80 // CHECK-NEXT:    [[SHL:%.*]] = shl <32 x i16> [[A]], [[B]]
81 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHL]], i64 0)
82 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
83 //
84 fixed_int16_t lshift_i16(fixed_int16_t a, fixed_int16_t b) {
85   return a << b;
86 }
87 
88 // CHECK-LABEL: @rshift_i16(
89 // CHECK-NEXT:  entry:
90 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
91 // CHECK-NEXT:    [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[B_COERCE:%.*]], i64 0)
92 // CHECK-NEXT:    [[SHR:%.*]] = ashr <32 x i16> [[A]], [[B]]
93 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHR]], i64 0)
94 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
95 //
96 fixed_int16_t rshift_i16(fixed_int16_t a, fixed_int16_t b) {
97   return a >> b;
98 }
99 
100 // CHECK-LABEL: @lshift_u16(
101 // CHECK-NEXT:  entry:
102 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
103 // CHECK-NEXT:    [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[B_COERCE:%.*]], i64 0)
104 // CHECK-NEXT:    [[SHL:%.*]] = shl <32 x i16> [[A]], [[B]]
105 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHL]], i64 0)
106 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
107 //
108 fixed_uint16_t lshift_u16(fixed_uint16_t a, fixed_uint16_t b) {
109   return a << b;
110 }
111 
112 // CHECK-LABEL: @rshift_u16(
113 // CHECK-NEXT:  entry:
114 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
115 // CHECK-NEXT:    [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[B_COERCE:%.*]], i64 0)
116 // CHECK-NEXT:    [[SHR:%.*]] = lshr <32 x i16> [[A]], [[B]]
117 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHR]], i64 0)
118 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
119 //
120 fixed_uint16_t rshift_u16(fixed_uint16_t a, fixed_uint16_t b) {
121   return a >> b;
122 }
123 
124 // CHECK-LABEL: @lshift_i32(
125 // CHECK-NEXT:  entry:
126 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
127 // CHECK-NEXT:    [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[B_COERCE:%.*]], i64 0)
128 // CHECK-NEXT:    [[SHL:%.*]] = shl <16 x i32> [[A]], [[B]]
129 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHL]], i64 0)
130 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
131 //
132 fixed_int32_t lshift_i32(fixed_int32_t a, fixed_int32_t b) {
133   return a << b;
134 }
135 
136 // CHECK-LABEL: @rshift_i32(
137 // CHECK-NEXT:  entry:
138 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
139 // CHECK-NEXT:    [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[B_COERCE:%.*]], i64 0)
140 // CHECK-NEXT:    [[SHR:%.*]] = ashr <16 x i32> [[A]], [[B]]
141 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHR]], i64 0)
142 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
143 //
144 fixed_int32_t rshift_i32(fixed_int32_t a, fixed_int32_t b) {
145   return a >> b;
146 }
147 
148 // CHECK-LABEL: @lshift_u32(
149 // CHECK-NEXT:  entry:
150 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
151 // CHECK-NEXT:    [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[B_COERCE:%.*]], i64 0)
152 // CHECK-NEXT:    [[SHL:%.*]] = shl <16 x i32> [[A]], [[B]]
153 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHL]], i64 0)
154 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
155 //
156 fixed_uint32_t lshift_u32(fixed_uint32_t a, fixed_uint32_t b) {
157   return a << b;
158 }
159 
160 // CHECK-LABEL: @rshift_u32(
161 // CHECK-NEXT:  entry:
162 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
163 // CHECK-NEXT:    [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[B_COERCE:%.*]], i64 0)
164 // CHECK-NEXT:    [[SHR:%.*]] = lshr <16 x i32> [[A]], [[B]]
165 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHR]], i64 0)
166 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
167 //
168 fixed_uint32_t rshift_u32(fixed_uint32_t a, fixed_uint32_t b) {
169   return a >> b;
170 }
171 
172 // CHECK-LABEL: @lshift_i64(
173 // CHECK-NEXT:  entry:
174 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
175 // CHECK-NEXT:    [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[B_COERCE:%.*]], i64 0)
176 // CHECK-NEXT:    [[SHL:%.*]] = shl <8 x i64> [[A]], [[B]]
177 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHL]], i64 0)
178 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
179 //
180 fixed_int64_t lshift_i64(fixed_int64_t a, fixed_int64_t b) {
181   return a << b;
182 }
183 
184 // CHECK-LABEL: @rshift_i64(
185 // CHECK-NEXT:  entry:
186 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
187 // CHECK-NEXT:    [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[B_COERCE:%.*]], i64 0)
188 // CHECK-NEXT:    [[SHR:%.*]] = ashr <8 x i64> [[A]], [[B]]
189 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHR]], i64 0)
190 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
191 //
192 fixed_int64_t rshift_i64(fixed_int64_t a, fixed_int64_t b) {
193   return a >> b;
194 }
195 
196 // CHECK-LABEL: @lshift_u64(
197 // CHECK-NEXT:  entry:
198 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
199 // CHECK-NEXT:    [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[B_COERCE:%.*]], i64 0)
200 // CHECK-NEXT:    [[SHL:%.*]] = shl <8 x i64> [[A]], [[B]]
201 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHL]], i64 0)
202 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
203 //
204 fixed_uint64_t lshift_u64(fixed_uint64_t a, fixed_uint64_t b) {
205   return a << b;
206 }
207 
208 // CHECK-LABEL: @rshift_u64(
209 // CHECK-NEXT:  entry:
210 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
211 // CHECK-NEXT:    [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[B_COERCE:%.*]], i64 0)
212 // CHECK-NEXT:    [[SHR:%.*]] = lshr <8 x i64> [[A]], [[B]]
213 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHR]], i64 0)
214 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
215 //
216 fixed_uint64_t rshift_u64(fixed_uint64_t a, fixed_uint64_t b) {
217   return a >> b;
218 }
219 
220 // CHECK-LABEL: @lshift_i8_rsplat(
221 // CHECK-NEXT:  entry:
222 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
223 // CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[B:%.*]] to i32
224 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i64 0
225 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer
226 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8>
227 // CHECK-NEXT:    [[SHL:%.*]] = shl <64 x i8> [[A]], [[SH_PROM]]
228 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHL]], i64 0)
229 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
230 //
231 fixed_int8_t lshift_i8_rsplat(fixed_int8_t a, int8_t b) {
232   return a << b;
233 }
234 
235 // CHECK-LABEL: @lshift_i8_lsplat(
236 // CHECK-NEXT:  entry:
237 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
238 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i64 0
239 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer
240 // CHECK-NEXT:    [[SHL:%.*]] = shl <64 x i8> [[SPLAT_SPLAT]], [[A]]
241 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHL]], i64 0)
242 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
243 //
244 fixed_int8_t lshift_i8_lsplat(fixed_int8_t a, int8_t b) {
245   return b << a;
246 }
247 
248 // CHECK-LABEL: @rshift_i8_rsplat(
249 // CHECK-NEXT:  entry:
250 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
251 // CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[B:%.*]] to i32
252 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i64 0
253 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer
254 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8>
255 // CHECK-NEXT:    [[SHR:%.*]] = ashr <64 x i8> [[A]], [[SH_PROM]]
256 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHR]], i64 0)
257 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
258 //
259 fixed_int8_t rshift_i8_rsplat(fixed_int8_t a, int8_t b) {
260   return a >> b;
261 }
262 
263 // CHECK-LABEL: @rshift_i8_lsplat(
264 // CHECK-NEXT:  entry:
265 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
266 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i64 0
267 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer
268 // CHECK-NEXT:    [[SHR:%.*]] = ashr <64 x i8> [[SPLAT_SPLAT]], [[A]]
269 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHR]], i64 0)
270 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
271 //
272 fixed_int8_t rshift_i8_lsplat(fixed_int8_t a, int8_t b) {
273   return b >> a;
274 }
275 
276 // CHECK-LABEL: @lshift_u8_rsplat(
277 // CHECK-NEXT:  entry:
278 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
279 // CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[B:%.*]] to i32
280 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i64 0
281 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer
282 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8>
283 // CHECK-NEXT:    [[SHL:%.*]] = shl <64 x i8> [[A]], [[SH_PROM]]
284 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHL]], i64 0)
285 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
286 //
287 fixed_uint8_t lshift_u8_rsplat(fixed_uint8_t a, uint8_t b) {
288   return a << b;
289 }
290 
291 // CHECK-LABEL: @lshift_u8_lsplat(
292 // CHECK-NEXT:  entry:
293 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
294 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i64 0
295 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer
296 // CHECK-NEXT:    [[SHL:%.*]] = shl <64 x i8> [[SPLAT_SPLAT]], [[A]]
297 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHL]], i64 0)
298 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
299 //
300 fixed_uint8_t lshift_u8_lsplat(fixed_uint8_t a, uint8_t b) {
301   return b << a;
302 }
303 
304 // CHECK-LABEL: @rshift_u8_rsplat(
305 // CHECK-NEXT:  entry:
306 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
307 // CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[B:%.*]] to i32
308 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i32> poison, i32 [[CONV]], i64 0
309 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i32> [[SPLAT_SPLATINSERT]], <64 x i32> poison, <64 x i32> zeroinitializer
310 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <64 x i32> [[SPLAT_SPLAT]] to <64 x i8>
311 // CHECK-NEXT:    [[SHR:%.*]] = lshr <64 x i8> [[A]], [[SH_PROM]]
312 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHR]], i64 0)
313 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
314 //
315 fixed_uint8_t rshift_u8_rsplat(fixed_uint8_t a, uint8_t b) {
316   return a >> b;
317 }
318 
319 // CHECK-LABEL: @rshift_u8_lsplat(
320 // CHECK-NEXT:  entry:
321 // CHECK-NEXT:    [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8(<vscale x 16 x i8> [[A_COERCE:%.*]], i64 0)
322 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <64 x i8> poison, i8 [[B:%.*]], i64 0
323 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <64 x i8> [[SPLAT_SPLATINSERT]], <64 x i8> poison, <64 x i32> zeroinitializer
324 // CHECK-NEXT:    [[SHR:%.*]] = lshr <64 x i8> [[SPLAT_SPLAT]], [[A]]
325 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 16 x i8> @llvm.vector.insert.nxv16i8.v64i8(<vscale x 16 x i8> poison, <64 x i8> [[SHR]], i64 0)
326 // CHECK-NEXT:    ret <vscale x 16 x i8> [[CASTSCALABLESVE]]
327 //
328 fixed_uint8_t rshift_u8_lsplat(fixed_uint8_t a, uint8_t b) {
329   return b >> a;
330 }
331 
332 // CHECK-LABEL: @lshift_i16_rsplat(
333 // CHECK-NEXT:  entry:
334 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
335 // CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[B:%.*]] to i32
336 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i64 0
337 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer
338 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16>
339 // CHECK-NEXT:    [[SHL:%.*]] = shl <32 x i16> [[A]], [[SH_PROM]]
340 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHL]], i64 0)
341 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
342 //
343 fixed_int16_t lshift_i16_rsplat(fixed_int16_t a, int16_t b) {
344   return a << b;
345 }
346 
347 // CHECK-LABEL: @lshift_i16_lsplat(
348 // CHECK-NEXT:  entry:
349 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
350 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i64 0
351 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer
352 // CHECK-NEXT:    [[SHL:%.*]] = shl <32 x i16> [[SPLAT_SPLAT]], [[A]]
353 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHL]], i64 0)
354 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
355 //
356 fixed_int16_t lshift_i16_lsplat(fixed_int16_t a, int16_t b) {
357   return b << a;
358 }
359 
360 // CHECK-LABEL: @rshift_i16_rsplat(
361 // CHECK-NEXT:  entry:
362 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
363 // CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[B:%.*]] to i32
364 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i64 0
365 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer
366 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16>
367 // CHECK-NEXT:    [[SHR:%.*]] = ashr <32 x i16> [[A]], [[SH_PROM]]
368 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHR]], i64 0)
369 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
370 //
371 fixed_int16_t rshift_i16_rsplat(fixed_int16_t a, int16_t b) {
372   return a >> b;
373 }
374 
375 // CHECK-LABEL: @rshift_i16_lsplat(
376 // CHECK-NEXT:  entry:
377 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
378 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i64 0
379 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer
380 // CHECK-NEXT:    [[SHR:%.*]] = ashr <32 x i16> [[SPLAT_SPLAT]], [[A]]
381 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHR]], i64 0)
382 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
383 //
384 fixed_int16_t rshift_i16_lsplat(fixed_int16_t a, int16_t b) {
385   return b >> a;
386 }
387 
388 // CHECK-LABEL: @lshift_u16_rsplat(
389 // CHECK-NEXT:  entry:
390 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
391 // CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[B:%.*]] to i32
392 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i64 0
393 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer
394 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16>
395 // CHECK-NEXT:    [[SHL:%.*]] = shl <32 x i16> [[A]], [[SH_PROM]]
396 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHL]], i64 0)
397 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
398 //
399 fixed_uint16_t lshift_u16_rsplat(fixed_uint16_t a, uint16_t b) {
400   return a << b;
401 }
402 
403 // CHECK-LABEL: @lshift_u16_lsplat(
404 // CHECK-NEXT:  entry:
405 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
406 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i64 0
407 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer
408 // CHECK-NEXT:    [[SHL:%.*]] = shl <32 x i16> [[SPLAT_SPLAT]], [[A]]
409 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHL]], i64 0)
410 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
411 //
412 fixed_uint16_t lshift_u16_lsplat(fixed_uint16_t a, uint16_t b) {
413   return b << a;
414 }
415 
416 // CHECK-LABEL: @rshift_u16_rsplat(
417 // CHECK-NEXT:  entry:
418 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
419 // CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[B:%.*]] to i32
420 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i32> poison, i32 [[CONV]], i64 0
421 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i32> [[SPLAT_SPLATINSERT]], <32 x i32> poison, <32 x i32> zeroinitializer
422 // CHECK-NEXT:    [[SH_PROM:%.*]] = trunc <32 x i32> [[SPLAT_SPLAT]] to <32 x i16>
423 // CHECK-NEXT:    [[SHR:%.*]] = lshr <32 x i16> [[A]], [[SH_PROM]]
424 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHR]], i64 0)
425 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
426 //
427 fixed_uint16_t rshift_u16_rsplat(fixed_uint16_t a, uint16_t b) {
428   return a >> b;
429 }
430 
431 // CHECK-LABEL: @rshift_u16_lsplat(
432 // CHECK-NEXT:  entry:
433 // CHECK-NEXT:    [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16(<vscale x 8 x i16> [[A_COERCE:%.*]], i64 0)
434 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <32 x i16> poison, i16 [[B:%.*]], i64 0
435 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <32 x i16> [[SPLAT_SPLATINSERT]], <32 x i16> poison, <32 x i32> zeroinitializer
436 // CHECK-NEXT:    [[SHR:%.*]] = lshr <32 x i16> [[SPLAT_SPLAT]], [[A]]
437 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 8 x i16> @llvm.vector.insert.nxv8i16.v32i16(<vscale x 8 x i16> poison, <32 x i16> [[SHR]], i64 0)
438 // CHECK-NEXT:    ret <vscale x 8 x i16> [[CASTSCALABLESVE]]
439 //
440 fixed_uint16_t rshift_u16_lsplat(fixed_uint16_t a, uint16_t b) {
441   return b >> a;
442 }
443 
444 // CHECK-LABEL: @lshift_i32_rsplat(
445 // CHECK-NEXT:  entry:
446 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
447 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
448 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
449 // CHECK-NEXT:    [[SHL:%.*]] = shl <16 x i32> [[A]], [[SPLAT_SPLAT]]
450 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHL]], i64 0)
451 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
452 //
453 fixed_int32_t lshift_i32_rsplat(fixed_int32_t a, int32_t b) {
454   return a << b;
455 }
456 
457 // CHECK-LABEL: @lshift_i32_lsplat(
458 // CHECK-NEXT:  entry:
459 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
460 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
461 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
462 // CHECK-NEXT:    [[SHL:%.*]] = shl <16 x i32> [[SPLAT_SPLAT]], [[A]]
463 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHL]], i64 0)
464 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
465 //
466 fixed_int32_t lshift_i32_lsplat(fixed_int32_t a, int32_t b) {
467   return b << a;
468 }
469 
470 // CHECK-LABEL: @rshift_i32_rsplat(
471 // CHECK-NEXT:  entry:
472 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
473 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
474 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
475 // CHECK-NEXT:    [[SHR:%.*]] = ashr <16 x i32> [[A]], [[SPLAT_SPLAT]]
476 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHR]], i64 0)
477 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
478 //
479 fixed_int32_t rshift_i32_rsplat(fixed_int32_t a, int32_t b) {
480   return a >> b;
481 }
482 
483 // CHECK-LABEL: @rshift_i32_lsplat(
484 // CHECK-NEXT:  entry:
485 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
486 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
487 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
488 // CHECK-NEXT:    [[SHR:%.*]] = ashr <16 x i32> [[SPLAT_SPLAT]], [[A]]
489 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHR]], i64 0)
490 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
491 //
492 fixed_int32_t rshift_i32_lsplat(fixed_int32_t a, int32_t b) {
493   return b >> a;
494 }
495 
496 // CHECK-LABEL: @lshift_u32_rsplat(
497 // CHECK-NEXT:  entry:
498 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
499 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
500 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
501 // CHECK-NEXT:    [[SHL:%.*]] = shl <16 x i32> [[A]], [[SPLAT_SPLAT]]
502 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHL]], i64 0)
503 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
504 //
505 fixed_uint32_t lshift_u32_rsplat(fixed_uint32_t a, uint32_t b) {
506   return a << b;
507 }
508 
509 // CHECK-LABEL: @lshift_u32_lsplat(
510 // CHECK-NEXT:  entry:
511 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
512 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
513 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
514 // CHECK-NEXT:    [[SHL:%.*]] = shl <16 x i32> [[SPLAT_SPLAT]], [[A]]
515 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHL]], i64 0)
516 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
517 //
518 fixed_uint32_t lshift_u32_lsplat(fixed_uint32_t a, uint32_t b) {
519   return b << a;
520 }
521 
522 // CHECK-LABEL: @rshift_u32_rsplat(
523 // CHECK-NEXT:  entry:
524 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
525 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
526 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
527 // CHECK-NEXT:    [[SHR:%.*]] = lshr <16 x i32> [[A]], [[SPLAT_SPLAT]]
528 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHR]], i64 0)
529 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
530 //
531 fixed_uint32_t rshift_u32_rsplat(fixed_uint32_t a, uint32_t b) {
532   return a >> b;
533 }
534 
535 // CHECK-LABEL: @rshift_u32_lsplat(
536 // CHECK-NEXT:  entry:
537 // CHECK-NEXT:    [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32(<vscale x 4 x i32> [[A_COERCE:%.*]], i64 0)
538 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[B:%.*]], i64 0
539 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer
540 // CHECK-NEXT:    [[SHR:%.*]] = lshr <16 x i32> [[SPLAT_SPLAT]], [[A]]
541 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[SHR]], i64 0)
542 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE]]
543 //
544 fixed_uint32_t rshift_u32_lsplat(fixed_uint32_t a, uint32_t b) {
545   return b >> a;
546 }
547 
548 // CHECK-LABEL: @lshift_i64_rsplat(
549 // CHECK-NEXT:  entry:
550 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
551 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
552 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
553 // CHECK-NEXT:    [[SHL:%.*]] = shl <8 x i64> [[A]], [[SPLAT_SPLAT]]
554 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHL]], i64 0)
555 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
556 //
557 fixed_int64_t lshift_i64_rsplat(fixed_int64_t a, int64_t b) {
558   return a << b;
559 }
560 
561 // CHECK-LABEL: @lshift_i64_lsplat(
562 // CHECK-NEXT:  entry:
563 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
564 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
565 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
566 // CHECK-NEXT:    [[SHL:%.*]] = shl <8 x i64> [[SPLAT_SPLAT]], [[A]]
567 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHL]], i64 0)
568 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
569 //
570 fixed_int64_t lshift_i64_lsplat(fixed_int64_t a, int64_t b) {
571   return b << a;
572 }
573 
574 // CHECK-LABEL: @rshift_i64_rsplat(
575 // CHECK-NEXT:  entry:
576 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
577 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
578 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
579 // CHECK-NEXT:    [[SHR:%.*]] = ashr <8 x i64> [[A]], [[SPLAT_SPLAT]]
580 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHR]], i64 0)
581 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
582 //
583 fixed_int64_t rshift_i64_rsplat(fixed_int64_t a, int64_t b) {
584   return a >> b;
585 }
586 
587 // CHECK-LABEL: @rshift_i64_lsplat(
588 // CHECK-NEXT:  entry:
589 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
590 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
591 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
592 // CHECK-NEXT:    [[SHR:%.*]] = ashr <8 x i64> [[SPLAT_SPLAT]], [[A]]
593 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHR]], i64 0)
594 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
595 //
596 fixed_int64_t rshift_i64_lsplat(fixed_int64_t a, int64_t b) {
597   return b >> a;
598 }
599 
600 // CHECK-LABEL: @lshift_u64_rsplat(
601 // CHECK-NEXT:  entry:
602 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
603 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
604 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
605 // CHECK-NEXT:    [[SHL:%.*]] = shl <8 x i64> [[A]], [[SPLAT_SPLAT]]
606 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHL]], i64 0)
607 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
608 //
609 fixed_uint64_t lshift_u64_rsplat(fixed_uint64_t a, uint64_t b) {
610   return a << b;
611 }
612 
613 // CHECK-LABEL: @lshift_u64_lsplat(
614 // CHECK-NEXT:  entry:
615 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
616 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
617 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
618 // CHECK-NEXT:    [[SHL:%.*]] = shl <8 x i64> [[SPLAT_SPLAT]], [[A]]
619 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHL]], i64 0)
620 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
621 //
622 fixed_uint64_t lshift_u64_lsplat(fixed_uint64_t a, uint64_t b) {
623   return b << a;
624 }
625 
626 // CHECK-LABEL: @rshift_u64_rsplat(
627 // CHECK-NEXT:  entry:
628 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
629 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
630 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
631 // CHECK-NEXT:    [[SHR:%.*]] = lshr <8 x i64> [[A]], [[SPLAT_SPLAT]]
632 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHR]], i64 0)
633 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
634 //
635 fixed_uint64_t rshift_u64_rsplat(fixed_uint64_t a, uint64_t b) {
636   return a >> b;
637 }
638 
639 // CHECK-LABEL: @rshift_u64_lsplat(
640 // CHECK-NEXT:  entry:
641 // CHECK-NEXT:    [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64(<vscale x 2 x i64> [[A_COERCE:%.*]], i64 0)
642 // CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[B:%.*]], i64 0
643 // CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <8 x i64> [[SPLAT_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
644 // CHECK-NEXT:    [[SHR:%.*]] = lshr <8 x i64> [[SPLAT_SPLAT]], [[A]]
645 // CHECK-NEXT:    [[CASTSCALABLESVE:%.*]] = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v8i64(<vscale x 2 x i64> poison, <8 x i64> [[SHR]], i64 0)
646 // CHECK-NEXT:    ret <vscale x 2 x i64> [[CASTSCALABLESVE]]
647 //
648 fixed_uint64_t rshift_u64_lsplat(fixed_uint64_t a, uint64_t b) {
649   return b >> a;
650 }
651