llvm.org GIT mirror llvm / c1a274e
[GISel][CombinerHelper] Add a combine turning shuffle_vector into concat_vectors Teach the CombinerHelper how to turn shuffle_vectors, that concatenate vectors, into concat_vectors and add this combine to the AArch64 pre-legalizer combiner. Differential Revision: https://reviews.llvm.org/D69149 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@375452 91177308-0d34-0410-b5e6-96231b3b80d8 Quentin Colombet 1 year, 1 month ago
4 changed file(s) with 459 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
111111 void applyCombineConcatVectors(MachineInstr &MI, bool IsUndef,
112112 const ArrayRef Ops);
113113
114 /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
115 /// Returns true if MI changed.
116 ///
117 /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
118 bool tryCombineShuffleVector(MachineInstr &MI);
119 /// Check if the G_SHUFFLE_VECTOR \p MI can be replaced by a
120 /// concat_vectors.
121 /// \p Ops will contain the operands needed to produce the flattened
122 /// concat_vectors.
123 ///
124 /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
125 bool matchCombineShuffleVector(MachineInstr &MI,
126 SmallVectorImpl &Ops);
127 /// Replace \p MI with a concat_vectors with \p Ops.
128 void applyCombineShuffleVector(MachineInstr &MI,
129 const ArrayRef Ops);
130
114131 /// Optimize memcpy intrinsics et al, e.g. constant len calls.
115132 /// /p MaxLen if non-zero specifies the max length of a mem libcall to inline.
116133 ///
168168 Builder.buildUndef(NewDstReg);
169169 else
170170 Builder.buildBuildVector(NewDstReg, Ops);
171 MI.eraseFromParent();
172 replaceRegWith(MRI, DstReg, NewDstReg);
173 }
174
175 bool CombinerHelper::tryCombineShuffleVector(MachineInstr &MI) {
176 SmallVector Ops;
177 if (matchCombineShuffleVector(MI, Ops)) {
178 applyCombineShuffleVector(MI, Ops);
179 return true;
180 }
181 return false;
182 }
183
184 bool CombinerHelper::matchCombineShuffleVector(MachineInstr &MI,
185 SmallVectorImpl &Ops) {
186 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
187 "Invalid instruction kind");
188 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
189 Register Src1 = MI.getOperand(1).getReg();
190 LLT SrcType = MRI.getType(Src1);
191 unsigned DstNumElts = DstType.getNumElements();
192 unsigned SrcNumElts = SrcType.getNumElements();
193
194 // If the resulting vector is smaller than the size of the source
195 // vectors being concatenated, we won't be able to replace the
196 // shuffle vector into a concat_vectors.
197 //
198 // Note: We may still be able to produce a concat_vectors fed by
199 // extract_vector_elt and so on. It is less clear that would
200 // be better though, so don't bother for now.
201 if (DstNumElts < 2 * SrcNumElts)
202 return false;
203
204 // Check that the shuffle mask can be broken evenly between the
205 // different sources.
206 if (DstNumElts % SrcNumElts != 0)
207 return false;
208
209 // Mask length is a multiple of the source vector length.
210 // Check if the shuffle is some kind of concatenation of the input
211 // vectors.
212 unsigned NumConcat = DstNumElts / SrcNumElts;
213 SmallVector ConcatSrcs(NumConcat, -1);
214 SmallVector Mask;
215 ShuffleVectorInst::getShuffleMask(MI.getOperand(3).getShuffleMask(), Mask);
216 for (unsigned i = 0; i != DstNumElts; ++i) {
217 int Idx = Mask[i];
218 // Undef value.
219 if (Idx < 0)
220 continue;
221 // Ensure the indices in each SrcType sized piece are sequential and that
222 // the same source is used for the whole piece.
223 if ((Idx % SrcNumElts != (i % SrcNumElts)) ||
224 (ConcatSrcs[i / SrcNumElts] >= 0 &&
225 ConcatSrcs[i / SrcNumElts] != (int)(Idx / SrcNumElts)))
226 return false;
227 // Remember which source this index came from.
228 ConcatSrcs[i / SrcNumElts] = Idx / SrcNumElts;
229 }
230
231 // The shuffle is concatenating multiple vectors together.
232 // Collect the different operands for that.
233 Register UndefReg;
234 Register Src2 = MI.getOperand(2).getReg();
235 for (auto Src : ConcatSrcs) {
236 if (Src < 0) {
237 if (!UndefReg) {
238 Builder.setInsertPt(*MI.getParent(), MI);
239 UndefReg = Builder.buildUndef(SrcType).getReg(0);
240 }
241 Ops.push_back(UndefReg);
242 } else if (Src == 0)
243 Ops.push_back(Src1);
244 else
245 Ops.push_back(Src2);
246 }
247 return true;
248 }
249
250 void CombinerHelper::applyCombineShuffleVector(MachineInstr &MI,
251 const ArrayRef Ops) {
252 Register DstReg = MI.getOperand(0).getReg();
253 Builder.setInsertPt(*MI.getParent(), MI);
254 Register NewDstReg = MRI.cloneVirtualRegister(DstReg);
255
256 Builder.buildConcatVectors(NewDstReg, Ops);
257
171258 MI.eraseFromParent();
172259 replaceRegWith(MRI, DstReg, NewDstReg);
173260 }
6363 switch (MI.getOpcode()) {
6464 case TargetOpcode::G_CONCAT_VECTORS:
6565 return Helper.tryCombineConcatVectors(MI);
66 case TargetOpcode::G_SHUFFLE_VECTOR:
67 return Helper.tryCombineShuffleVector(MI);
6668 case TargetOpcode::G_LOAD:
6769 case TargetOpcode::G_SEXTLOAD:
6870 case TargetOpcode::G_ZEXTLOAD: {
0 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
1 # RUN: llc -mtriple aarch64-apple-ios -run-pass=aarch64-prelegalizer-combiner %s -o - | FileCheck %s
2
3 # Check that we canonicalize shuffle_vector(Src1, Src2, mask(0,1,2,3))
4 # into concat_vector(Src1, Src2).
5 ---
6 name: shuffle_vector_to_concat_vector_0123
7 tracksRegLiveness: true
8 body: |
9 bb.1:
10 liveins: $d0, $d1
11
12 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_0123
13 ; CHECK: liveins: $d0, $d1
14 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
15 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
16 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s32>) = G_CONCAT_VECTORS [[COPY]](<2 x s32>), [[COPY1]](<2 x s32>)
17 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<4 x s32>)
18 %0:_(<2 x s32>) = COPY $d0
19 %1:_(<2 x s32>) = COPY $d1
20 %2:_(<4 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1(<2 x s32>), shufflemask(0, 1, 2, 3)
21 RET_ReallyLR implicit %2
22 ...
23 # Check that we canonicalize shuffle_vector(Src1, Src2, mask(2,3,0,1,2,3))
24 # into concat_vector(Src2, Src1, Src2).
25 ---
26 name: shuffle_vector_to_concat_vector_230123
27 tracksRegLiveness: true
28 body: |
29 bb.1:
30 liveins: $d0, $d1
31
32 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_230123
33 ; CHECK: liveins: $d0, $d1
34 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
35 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
36 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[COPY1]](<2 x s32>), [[COPY]](<2 x s32>), [[COPY1]](<2 x s32>)
37 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<6 x s32>)
38 %0:_(<2 x s32>) = COPY $d0
39 %1:_(<2 x s32>) = COPY $d1
40 %2:_(<6 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1(<2 x s32>), shufflemask(2,3,0,1,2,3)
41 RET_ReallyLR implicit %2
42 ...
43 # Check that we canonicalize shuffle_vector(Src1, Src2, mask(2,undef,0,1,undef,3))
44 # into concat_vector(Src2, Src1, Src2).
45 ---
46 name: shuffle_vector_to_concat_vector_2undef01undef3
47 tracksRegLiveness: true
48 body: |
49 bb.1:
50 liveins: $d0, $d1
51
52 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_2undef01undef3
53 ; CHECK: liveins: $d0, $d1
54 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
55 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
56 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[COPY1]](<2 x s32>), [[COPY]](<2 x s32>), [[COPY1]](<2 x s32>)
57 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<6 x s32>)
58 %0:_(<2 x s32>) = COPY $d0
59 %1:_(<2 x s32>) = COPY $d1
60 %2:_(<6 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1(<2 x s32>), shufflemask(2,-1,0,1,-1,3)
61 RET_ReallyLR implicit %2
62 ...
63 # Check that we don't canonicalize shuffle_vector into concat_vectors
64 # when the sources get half mixed.
65 ---
66 name: shuffle_vector_to_concat_vector_mixed_src_200123_neg
67 tracksRegLiveness: true
68 body: |
69 bb.1:
70 liveins: $d0, $d1
71
72 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_mixed_src_200123_neg
73 ; CHECK: liveins: $d0, $d1
74 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
75 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
76 ; CHECK: [[SHUF:%[0-9]+]]:_(<6 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<2 x s32>), [[COPY1]], shufflemask(2, 0, 0, 1, 2, 3)
77 ; CHECK: RET_ReallyLR implicit [[SHUF]](<6 x s32>)
78 %0:_(<2 x s32>) = COPY $d0
79 %1:_(<2 x s32>) = COPY $d1
80 %2:_(<6 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1(<2 x s32>), shufflemask(2,0,0,1,2,3)
81 RET_ReallyLR implicit %2
82 ...
83 # Check that we produce implicit_def while canonicalizing shuffle_vector(Src1, Src2, mask(2,undef,undef,undef,undef,1))
84 # into concat_vector(Src2, undef, Src1).
85 ---
86 name: shuffle_vector_to_concat_vector_2undef1
87 tracksRegLiveness: true
88 body: |
89 bb.1:
90 liveins: $d0, $d1
91
92 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_2undef1
93 ; CHECK: liveins: $d0, $d1
94 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
95 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
96 ; CHECK: [[DEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
97 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[COPY1]](<2 x s32>), [[DEF]](<2 x s32>), [[COPY]](<2 x s32>)
98 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<6 x s32>)
99 %0:_(<2 x s32>) = COPY $d0
100 %1:_(<2 x s32>) = COPY $d1
101 %2:_(<6 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1(<2 x s32>), shufflemask(2,-1,-1,-1,-1,1)
102 RET_ReallyLR implicit %2
103 ...
104 # Check that we don't canonicalize shuffle_vector into concat_vectors
105 # if a source is flipped.
106 ---
107 name: shuffle_vector_to_concat_vector_src_flipped_230132_neg
108 tracksRegLiveness: true
109 body: |
110 bb.1:
111 liveins: $d0, $d1
112
113 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_src_flipped_230132_neg
114 ; CHECK: liveins: $d0, $d1
115 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
116 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
117 ; CHECK: [[SHUF:%[0-9]+]]:_(<6 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<2 x s32>), [[COPY1]], shufflemask(2, 3, 0, 1, 3, 2)
118 ; CHECK: RET_ReallyLR implicit [[SHUF]](<6 x s32>)
119 %0:_(<2 x s32>) = COPY $d0
120 %1:_(<2 x s32>) = COPY $d1
121 %2:_(<6 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1(<2 x s32>), shufflemask(2,3,0,1,3,2)
122 RET_ReallyLR implicit %2
123 ...
124 # Check that we don't canonicalize shuffle_vector into concat_vectors
125 # if a source is flipped and the other half is undef.
126 ---
127 name: shuffle_vector_to_concat_vector_src_flipped_23013undef_neg
128 tracksRegLiveness: true
129 body: |
130 bb.1:
131 liveins: $d0, $d1
132
133 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_src_flipped_23013undef_neg
134 ; CHECK: liveins: $d0, $d1
135 ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
136 ; CHECK: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1
137 ; CHECK: [[SHUF:%[0-9]+]]:_(<6 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<2 x s32>), [[COPY1]], shufflemask(2, 3, 0, 1, 3, -1)
138 ; CHECK: RET_ReallyLR implicit [[SHUF]](<6 x s32>)
139 %0:_(<2 x s32>) = COPY $d0
140 %1:_(<2 x s32>) = COPY $d1
141 %2:_(<6 x s32>) = G_SHUFFLE_VECTOR %0(<2 x s32>), %1(<2 x s32>), shufflemask(2,3,0,1,3,-1)
142 RET_ReallyLR implicit %2
143 ...
144
145 # Check that we canonicalize shuffle_vector(Src1, Src2, mask(0,1,2,3,4,5,6,7))
146 # into concat_vector(Src1, Src2) with bigger vector type.
147 ---
148 name: shuffle_vector_to_concat_vector_01234567
149 tracksRegLiveness: true
150 body: |
151 bb.1:
152 liveins: $q0, $q1
153
154 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_01234567
155 ; CHECK: liveins: $q0, $q1
156 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
157 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1
158 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<8 x s32>) = G_CONCAT_VECTORS [[COPY]](<4 x s32>), [[COPY1]](<4 x s32>)
159 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<8 x s32>)
160 %0:_(<4 x s32>) = COPY $q0
161 %1:_(<4 x s32>) = COPY $q1
162 %2:_(<8 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1(<4 x s32>), shufflemask(0, 1, 2, 3, 4, 5, 6, 7)
163 RET_ReallyLR implicit %2
164 ...
165 # Check that we canonicalize shuffle_vector(Src1, Src2, mask(4,5,6,7,0,1,2,3))
166 # into concat_vector(Src2, Src1, Src2) with bigger vector type.
167 ---
168 name: shuffle_vector_to_concat_vector_45670123
169 tracksRegLiveness: true
170 body: |
171 bb.1:
172 liveins: $q0, $q1
173
174 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_45670123
175 ; CHECK: liveins: $q0, $q1
176 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
177 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1
178 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<12 x s32>) = G_CONCAT_VECTORS [[COPY1]](<4 x s32>), [[COPY]](<4 x s32>), [[COPY1]](<4 x s32>)
179 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<12 x s32>)
180 %0:_(<4 x s32>) = COPY $q0
181 %1:_(<4 x s32>) = COPY $q1
182 %2:_(<12 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1(<4 x s32>), shufflemask(4,5,6,7,0,1,2,3,4,5,6,7)
183 RET_ReallyLR implicit %2
184 ...
185 # Check that we canonicalize shuffle_vector(Src1, Src2, mask(4,5,undef,undef,0,1,2,3,undef,undef,6,7))
186 # into concat_vector(Src2, Src1, Src2) with bigger vector type.
187 ---
188 name: shuffle_vector_to_concat_vector_45undefundef0123undefundef67
189 tracksRegLiveness: true
190 body: |
191 bb.1:
192 liveins: $q0, $q1
193
194 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_45undefundef0123undefundef67
195 ; CHECK: liveins: $q0, $q1
196 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
197 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1
198 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<12 x s32>) = G_CONCAT_VECTORS [[COPY1]](<4 x s32>), [[COPY]](<4 x s32>), [[COPY1]](<4 x s32>)
199 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<12 x s32>)
200 %0:_(<4 x s32>) = COPY $q0
201 %1:_(<4 x s32>) = COPY $q1
202 %2:_(<12 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1(<4 x s32>), shufflemask(4,5,-1,-1,0,1,2,3,-1,-1,6,7)
203 RET_ReallyLR implicit %2
204 ...
205 # Check that we don't canonicalize shuffle_vector into concat_vectors
206 # when the sources get half mixed with bigger vector type.
207 ---
208 name: shuffle_vector_to_concat_vector_mixed_src_456000123_neg
209 tracksRegLiveness: true
210 body: |
211 bb.1:
212 liveins: $q0, $q1
213
214 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_mixed_src_456000123_neg
215 ; CHECK: liveins: $q0, $q1
216 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
217 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1
218 ; CHECK: [[SHUF:%[0-9]+]]:_(<8 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<4 x s32>), [[COPY1]], shufflemask(4, 5, 6, 0, 0, 1, 2, 3)
219 ; CHECK: RET_ReallyLR implicit [[SHUF]](<8 x s32>)
220 %0:_(<4 x s32>) = COPY $q0
221 %1:_(<4 x s32>) = COPY $q1
222 %2:_(<8 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1(<4 x s32>), shufflemask(4,5,6,0,0,1,2,3)
223 RET_ReallyLR implicit %2
224 ...
225 # Check that we produce implicit_def while canonicalizing shuffle_vector(Src1, Src2, mask(2,undef,undef,undef,undef,1))
226 # into concat_vector(Src2, undef, Src1) with bigger vector type.
227 ---
228 name: shuffle_vector_to_concat_vector_45undefundefundefundefundefundefundefundef23
229 tracksRegLiveness: true
230 body: |
231 bb.1:
232 liveins: $q0, $q1
233
234 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_45undefundefundefundefundefundefundefundef23
235 ; CHECK: liveins: $q0, $q1
236 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
237 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1
238 ; CHECK: [[DEF:%[0-9]+]]:_(<4 x s32>) = G_IMPLICIT_DEF
239 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<12 x s32>) = G_CONCAT_VECTORS [[COPY1]](<4 x s32>), [[DEF]](<4 x s32>), [[COPY]](<4 x s32>)
240 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<12 x s32>)
241 %0:_(<4 x s32>) = COPY $q0
242 %1:_(<4 x s32>) = COPY $q1
243 %2:_(<12 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1(<4 x s32>), shufflemask(4,5,-1,-1,-1,-1,-1,-1,-1,-1,2,3)
244 RET_ReallyLR implicit %2
245 ...
246 # Check that we don't canonicalize shuffle_vector into concat_vectors
247 # when we grab less than the full vectors.
248 ---
249 name: shuffle_vector_to_concat_vector_4501_neg
250 tracksRegLiveness: true
251 body: |
252 bb.1:
253 liveins: $q0, $q1
254
255 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_4501_neg
256 ; CHECK: liveins: $q0, $q1
257 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
258 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1
259 ; CHECK: [[SHUF:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<4 x s32>), [[COPY1]], shufflemask(4, 5, 0, 1)
260 ; CHECK: RET_ReallyLR implicit [[SHUF]](<4 x s32>)
261 %0:_(<4 x s32>) = COPY $q0
262 %1:_(<4 x s32>) = COPY $q1
263 %2:_(<4 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1(<4 x s32>), shufflemask(4,5,0,1)
264 RET_ReallyLR implicit %2
265 ...
266 # Check that we don't canonicalize shuffle_vector into concat_vectors
267 # if a source is flipped and the other half is undef with bigger vector.
268 ---
269 name: shuffle_vector_to_concat_vector_src_flipped_4567012367undefundef_neg
270 tracksRegLiveness: true
271 body: |
272 bb.1:
273 liveins: $q0, $q1
274
275 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_src_flipped_4567012367undefundef_neg
276 ; CHECK: liveins: $q0, $q1
277 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
278 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x s32>) = COPY $q1
279 ; CHECK: [[SHUF:%[0-9]+]]:_(<12 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<4 x s32>), [[COPY1]], shufflemask(4, 5, 6, 7, 0, 1, 2, 3, 6, 7, -1, -1)
280 ; CHECK: RET_ReallyLR implicit [[SHUF]](<12 x s32>)
281 %0:_(<4 x s32>) = COPY $q0
282 %1:_(<4 x s32>) = COPY $q1
283 %2:_(<12 x s32>) = G_SHUFFLE_VECTOR %0(<4 x s32>), %1(<4 x s32>), shufflemask(4,5,6,7,0,1,2,3,6,7,-1,-1)
284 RET_ReallyLR implicit %2
285 ...
286 # Check that we canonicalize shuffle_vector(Src1, Src2, mask(4,5,undef,undef,0,1,2,3,undef,undef,6,7))
287 # into concat_vector(Src2, Src1, Src2) with vector of pointers.
288 ---
289 name: shuffle_vector_to_concat_vector_45undefundef0123undefundef67_ptr
290 tracksRegLiveness: true
291 body: |
292 bb.1:
293 liveins: $q0_q1, $q2_q3
294
295 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_45undefundef0123undefundef67_ptr
296 ; CHECK: liveins: $q0_q1, $q2_q3
297 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x p0>) = COPY $q0_q1
298 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x p0>) = COPY $q2_q3
299 ; CHECK: [[CONCAT_VECTORS:%[0-9]+]]:_(<12 x p0>) = G_CONCAT_VECTORS [[COPY1]](<4 x p0>), [[COPY]](<4 x p0>), [[COPY1]](<4 x p0>)
300 ; CHECK: RET_ReallyLR implicit [[CONCAT_VECTORS]](<12 x p0>)
301 %0:_(<4 x p0>) = COPY $q0_q1
302 %1:_(<4 x p0>) = COPY $q2_q3
303 %2:_(<12 x p0>) = G_SHUFFLE_VECTOR %0(<4 x p0>), %1(<4 x p0>), shufflemask(4,5,-1,-1,0,1,2,3,-1,-1,6,7)
304 RET_ReallyLR implicit %2
305 ...
306 # Check that we don't canonicalize shuffle_vector into concat_vectors
307 # when the sources get half mixed with vector of pointers.
308 ---
309 name: shuffle_vector_to_concat_vector_mixed_src_456000123_neg_ptr
310 tracksRegLiveness: true
311 body: |
312 bb.1:
313 liveins: $q0_q1, $q2_q3
314
315 ; CHECK-LABEL: name: shuffle_vector_to_concat_vector_mixed_src_456000123_neg_ptr
316 ; CHECK: liveins: $q0_q1, $q2_q3
317 ; CHECK: [[COPY:%[0-9]+]]:_(<4 x p0>) = COPY $q0_q1
318 ; CHECK: [[COPY1:%[0-9]+]]:_(<4 x p0>) = COPY $q2_q3
319 ; CHECK: [[SHUF:%[0-9]+]]:_(<8 x p0>) = G_SHUFFLE_VECTOR [[COPY]](<4 x p0>), [[COPY1]], shufflemask(4, 5, 6, 0, 0, 1, 2, 3)
320 ; CHECK: RET_ReallyLR implicit [[SHUF]](<8 x p0>)
321 %0:_(<4 x p0>) = COPY $q0_q1
322 %1:_(<4 x p0>) = COPY $q2_q3
323 %2:_(<8 x p0>) = G_SHUFFLE_VECTOR %0(<4 x p0>), %1(<4 x p0>), shufflemask(4,5,6,0,0,1,2,3)
324 RET_ReallyLR implicit %2
325 ...
326
327 # Check that shuffle_vector gets combined into concat_vectors then the
328 # concat_vectors gets combined into build_vector.
329 ---
330 name: shuffle_vector_to_build_vector_ptr
331 tracksRegLiveness: true
332 body: |
333 bb.1:
334 liveins: $x0, $x1, $x2, $x3
335
336 ; CHECK-LABEL: name: shuffle_vector_to_build_vector_ptr
337 ; CHECK: liveins: $x0, $x1, $x2, $x3
338 ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
339 ; CHECK: [[COPY1:%[0-9]+]]:_(p0) = COPY $x1
340 ; CHECK: [[COPY2:%[0-9]+]]:_(p0) = COPY $x2
341 ; CHECK: [[COPY3:%[0-9]+]]:_(p0) = COPY $x3
342 ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x p0>) = G_BUILD_VECTOR [[COPY]](p0), [[COPY1]](p0), [[COPY2]](p0), [[COPY3]](p0)
343 ; CHECK: RET_ReallyLR implicit [[BUILD_VECTOR]](<4 x p0>)
344 %0:_(p0) = COPY $x0
345 %1:_(p0) = COPY $x1
346 %2:_(p0) = COPY $x2
347 %3:_(p0) = COPY $x3
348 %4:_(<2 x p0>) = G_BUILD_VECTOR %0(p0), %1
349 %5:_(<2 x p0>) = G_BUILD_VECTOR %2(p0), %3
350 %6:_(<4 x p0>) = G_SHUFFLE_VECTOR %4(<2 x p0>), %5(<2 x p0>), shufflemask(0,1,2,3)
351 RET_ReallyLR implicit %6
352 ...