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
5 define <2 x i32> @and_extract_zext_idx0(<4 x i16> %vec) nounwind {
6 ; CHECK-SD-LABEL: and_extract_zext_idx0:
8 ; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #0
9 ; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0
12 ; CHECK-GI-LABEL: and_extract_zext_idx0:
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
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>
24 define <4 x i16> @and_extract_sext_idx0(<8 x i8> %vec) nounwind {
25 ; CHECK-SD-LABEL: and_extract_sext_idx0:
27 ; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0
28 ; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0
31 ; CHECK-GI-LABEL: and_extract_sext_idx0:
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
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>
43 define <2 x i32> @and_extract_zext_idx2(<4 x i16> %vec) nounwind {
44 ; CHECK-SD-LABEL: and_extract_zext_idx2:
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
51 ; CHECK-GI-LABEL: and_extract_zext_idx2:
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
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>
64 define <4 x i16> @and_extract_sext_idx4(<8 x i8> %vec) nounwind {
65 ; CHECK-SD-LABEL: and_extract_sext_idx4:
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
72 ; CHECK-GI-LABEL: and_extract_sext_idx4:
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
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>
85 define <2 x i32> @sext_extract_zext_idx0(<4 x i16> %vec) nounwind {
86 ; CHECK-SD-LABEL: sext_extract_zext_idx0:
88 ; CHECK-SD-NEXT: sshll v0.4s, v0.4h, #0
89 ; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0
92 ; CHECK-GI-LABEL: sext_extract_zext_idx0:
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
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
105 ; Negative test, combine should not fire if sign extension is for a different width.
106 define <2 x i32> @sext_extract_zext_idx0_negtest(<4 x i16> %vec) nounwind {
107 ; CHECK-LABEL: sext_extract_zext_idx0_negtest:
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
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
120 define <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
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
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
140 define <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
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
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
162 define <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
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
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
184 define <8 x i8> @sext_extract_idx(<16 x i8> %vec) nounwind {
185 ; CHECK-LABEL: sext_extract_idx:
187 ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
189 %extract = call <8 x i8> @llvm.vector.extract.v8i8.v16i8(<16 x i8> %vec, i64 0)
190 ret <8 x i8> %extract
193 declare <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32>, i64)
194 declare <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16>, i64)
195 declare <8 x i8> @llvm.vector.extract.v8i8.v16i8(<16 x i8>, i64)