xref: /llvm-project/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll (revision 61510b51c33464a6bc15e4cf5b1ee07e2e0ec1c9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
3; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
4
5define <2 x i32> @and_extract_zext_idx0(<4 x i16> %vec) nounwind {
6; CHECK-SD-LABEL: and_extract_zext_idx0:
7; CHECK-SD:       // %bb.0:
8; CHECK-SD-NEXT:    ushll v0.4s, v0.4h, #0
9; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
10; CHECK-SD-NEXT:    ret
11;
12; CHECK-GI-LABEL: and_extract_zext_idx0:
13; CHECK-GI:       // %bb.0:
14; CHECK-GI-NEXT:    movi d1, #0x00ffff0000ffff
15; CHECK-GI-NEXT:    ushll v0.4s, v0.4h, #0
16; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
17; CHECK-GI-NEXT:    ret
18  %zext = zext <4 x i16> %vec to <4 x i32>
19  %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 0)
20  %and = and <2 x i32> %extract, <i32 65535, i32 65535>
21  ret <2 x i32> %and
22}
23
24define <4 x i16> @and_extract_sext_idx0(<8 x i8> %vec) nounwind {
25; CHECK-SD-LABEL: and_extract_sext_idx0:
26; CHECK-SD:       // %bb.0:
27; CHECK-SD-NEXT:    ushll v0.8h, v0.8b, #0
28; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
29; CHECK-SD-NEXT:    ret
30;
31; CHECK-GI-LABEL: and_extract_sext_idx0:
32; CHECK-GI:       // %bb.0:
33; CHECK-GI-NEXT:    movi d1, #0xff00ff00ff00ff
34; CHECK-GI-NEXT:    sshll v0.8h, v0.8b, #0
35; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
36; CHECK-GI-NEXT:    ret
37  %sext = sext <8 x i8> %vec to <8 x i16>
38  %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 0)
39  %and = and <4 x i16> %extract, <i16 255, i16 255, i16 255, i16 255>
40  ret <4 x i16> %and
41}
42
43define <2 x i32> @and_extract_zext_idx2(<4 x i16> %vec) nounwind {
44; CHECK-SD-LABEL: and_extract_zext_idx2:
45; CHECK-SD:       // %bb.0:
46; CHECK-SD-NEXT:    ushll v0.4s, v0.4h, #0
47; CHECK-SD-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
48; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
49; CHECK-SD-NEXT:    ret
50;
51; CHECK-GI-LABEL: and_extract_zext_idx2:
52; CHECK-GI:       // %bb.0:
53; CHECK-GI-NEXT:    ushll v0.4s, v0.4h, #0
54; CHECK-GI-NEXT:    movi d1, #0x00ffff0000ffff
55; CHECK-GI-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
56; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
57; CHECK-GI-NEXT:    ret
58  %zext = zext <4 x i16> %vec to <4 x i32>
59  %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 2)
60  %and = and <2 x i32> %extract, <i32 65535, i32 65535>
61  ret <2 x i32> %and
62}
63
64define <4 x i16> @and_extract_sext_idx4(<8 x i8> %vec) nounwind {
65; CHECK-SD-LABEL: and_extract_sext_idx4:
66; CHECK-SD:       // %bb.0:
67; CHECK-SD-NEXT:    ushll v0.8h, v0.8b, #0
68; CHECK-SD-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
69; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
70; CHECK-SD-NEXT:    ret
71;
72; CHECK-GI-LABEL: and_extract_sext_idx4:
73; CHECK-GI:       // %bb.0:
74; CHECK-GI-NEXT:    sshll v0.8h, v0.8b, #0
75; CHECK-GI-NEXT:    movi d1, #0xff00ff00ff00ff
76; CHECK-GI-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
77; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
78; CHECK-GI-NEXT:    ret
79  %sext = sext <8 x i8> %vec to <8 x i16>
80  %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 4)
81  %and = and <4 x i16> %extract, <i16 255, i16 255, i16 255, i16 255>
82  ret <4 x i16> %and
83}
84
85define <2 x i32> @sext_extract_zext_idx0(<4 x i16> %vec) nounwind {
86; CHECK-SD-LABEL: sext_extract_zext_idx0:
87; CHECK-SD:       // %bb.0:
88; CHECK-SD-NEXT:    sshll v0.4s, v0.4h, #0
89; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
90; CHECK-SD-NEXT:    ret
91;
92; CHECK-GI-LABEL: sext_extract_zext_idx0:
93; CHECK-GI:       // %bb.0:
94; CHECK-GI-NEXT:    ushll v0.4s, v0.4h, #0
95; CHECK-GI-NEXT:    shl v0.2s, v0.2s, #16
96; CHECK-GI-NEXT:    sshr v0.2s, v0.2s, #16
97; CHECK-GI-NEXT:    ret
98  %zext = zext <4 x i16> %vec to <4 x i32>
99  %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 0)
100  %sext_inreg_step0 = shl <2 x i32> %extract, <i32 16, i32 16>
101  %sext_inreg = ashr <2 x i32> %sext_inreg_step0, <i32 16, i32 16>
102  ret <2 x i32> %sext_inreg
103}
104
105; Negative test, combine should not fire if sign extension is for a different width.
106define <2 x i32> @sext_extract_zext_idx0_negtest(<4 x i16> %vec) nounwind {
107; CHECK-LABEL: sext_extract_zext_idx0_negtest:
108; CHECK:       // %bb.0:
109; CHECK-NEXT:    ushll v0.4s, v0.4h, #0
110; CHECK-NEXT:    shl v0.2s, v0.2s, #17
111; CHECK-NEXT:    sshr v0.2s, v0.2s, #17
112; CHECK-NEXT:    ret
113  %zext = zext <4 x i16> %vec to <4 x i32>
114  %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 0)
115  %sext_inreg_step0 = shl <2 x i32> %extract, <i32 17, i32 17>
116  %sext_inreg = ashr <2 x i32> %sext_inreg_step0, <i32 17, i32 17>
117  ret <2 x i32> %sext_inreg
118}
119
120define <4 x i16> @sext_extract_sext_idx0(<8 x i8> %vec) nounwind {
121; CHECK-SD-LABEL: sext_extract_sext_idx0:
122; CHECK-SD:       // %bb.0:
123; CHECK-SD-NEXT:    sshll v0.8h, v0.8b, #0
124; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
125; CHECK-SD-NEXT:    ret
126;
127; CHECK-GI-LABEL: sext_extract_sext_idx0:
128; CHECK-GI:       // %bb.0:
129; CHECK-GI-NEXT:    sshll v0.8h, v0.8b, #0
130; CHECK-GI-NEXT:    shl v0.4h, v0.4h, #8
131; CHECK-GI-NEXT:    sshr v0.4h, v0.4h, #8
132; CHECK-GI-NEXT:    ret
133  %sext = sext <8 x i8> %vec to <8 x i16>
134  %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 0)
135  %sext_inreg_step0 = shl <4 x i16> %extract, <i16 8, i16 8, i16 8, i16 8>
136  %sext_inreg = ashr <4 x i16> %sext_inreg_step0, <i16 8, i16 8, i16 8, i16 8>
137  ret <4 x i16> %sext_inreg
138}
139
140define <2 x i32> @sext_extract_zext_idx2(<4 x i16> %vec) nounwind {
141; CHECK-SD-LABEL: sext_extract_zext_idx2:
142; CHECK-SD:       // %bb.0:
143; CHECK-SD-NEXT:    sshll v0.4s, v0.4h, #0
144; CHECK-SD-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
145; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
146; CHECK-SD-NEXT:    ret
147;
148; CHECK-GI-LABEL: sext_extract_zext_idx2:
149; CHECK-GI:       // %bb.0:
150; CHECK-GI-NEXT:    ushll v0.4s, v0.4h, #0
151; CHECK-GI-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
152; CHECK-GI-NEXT:    shl v0.2s, v0.2s, #16
153; CHECK-GI-NEXT:    sshr v0.2s, v0.2s, #16
154; CHECK-GI-NEXT:    ret
155  %zext = zext <4 x i16> %vec to <4 x i32>
156  %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 2)
157  %sext_inreg_step0 = shl <2 x i32> %extract, <i32 16, i32 16>
158  %sext_inreg = ashr <2 x i32> %sext_inreg_step0, <i32 16, i32 16>
159  ret <2 x i32> %sext_inreg
160}
161
162define <4 x i16> @sext_extract_sext_idx4(<8 x i8> %vec) nounwind {
163; CHECK-SD-LABEL: sext_extract_sext_idx4:
164; CHECK-SD:       // %bb.0:
165; CHECK-SD-NEXT:    sshll v0.8h, v0.8b, #0
166; CHECK-SD-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
167; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
168; CHECK-SD-NEXT:    ret
169;
170; CHECK-GI-LABEL: sext_extract_sext_idx4:
171; CHECK-GI:       // %bb.0:
172; CHECK-GI-NEXT:    sshll v0.8h, v0.8b, #0
173; CHECK-GI-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
174; CHECK-GI-NEXT:    shl v0.4h, v0.4h, #8
175; CHECK-GI-NEXT:    sshr v0.4h, v0.4h, #8
176; CHECK-GI-NEXT:    ret
177  %sext = sext <8 x i8> %vec to <8 x i16>
178  %extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 4)
179  %sext_inreg_step0 = shl <4 x i16> %extract, <i16 8, i16 8, i16 8, i16 8>
180  %sext_inreg = ashr <4 x i16> %sext_inreg_step0, <i16 8, i16 8, i16 8, i16 8>
181  ret <4 x i16> %sext_inreg
182}
183
184define <8 x i8> @sext_extract_idx(<16 x i8> %vec) nounwind {
185; CHECK-LABEL: sext_extract_idx:
186; CHECK:       // %bb.0:
187; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
188; CHECK-NEXT:    ret
189  %extract = call <8 x i8> @llvm.vector.extract.v8i8.v16i8(<16 x i8> %vec, i64 0)
190  ret <8 x i8> %extract
191}
192
193declare <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32>, i64)
194declare <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16>, i64)
195declare <8 x i8> @llvm.vector.extract.v8i8.v16i8(<16 x i8>, i64)
196