1 //=== AArch64PostLegalizerLowering.cpp --------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// Post-legalization lowering for instructions.
11 ///
12 /// This is used to offload pattern matching from the selector.
13 ///
14 /// For example, this combiner will notice that a G_SHUFFLE_VECTOR is actually
15 /// a G_ZIP, G_UZP, etc.
16 ///
17 /// General optimization combines should be handled by either the
18 /// AArch64PostLegalizerCombiner or the AArch64PreLegalizerCombiner.
19 ///
20 //===----------------------------------------------------------------------===//
21 
22 #include "AArch64TargetMachine.h"
23 #include "AArch64GlobalISelUtils.h"
24 #include "MCTargetDesc/AArch64MCTargetDesc.h"
25 #include "llvm/CodeGen/GlobalISel/Combiner.h"
26 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
27 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
28 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
29 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
30 #include "llvm/CodeGen/GlobalISel/Utils.h"
31 #include "llvm/CodeGen/MachineFunctionPass.h"
32 #include "llvm/CodeGen/MachineInstrBuilder.h"
33 #include "llvm/CodeGen/MachineRegisterInfo.h"
34 #include "llvm/CodeGen/TargetOpcodes.h"
35 #include "llvm/CodeGen/TargetPassConfig.h"
36 #include "llvm/InitializePasses.h"
37 #include "llvm/Support/Debug.h"
38 
39 #define DEBUG_TYPE "aarch64-postlegalizer-lowering"
40 
41 using namespace llvm;
42 using namespace MIPatternMatch;
43 using namespace AArch64GISelUtils;
44 
45 /// Represents a pseudo instruction which replaces a G_SHUFFLE_VECTOR.
46 ///
47 /// Used for matching target-supported shuffles before codegen.
48 struct ShuffleVectorPseudo {
49   unsigned Opc; ///< Opcode for the instruction. (E.g. G_ZIP1)
50   Register Dst; ///< Destination register.
51   SmallVector<SrcOp, 2> SrcOps; ///< Source registers.
52   ShuffleVectorPseudo(unsigned Opc, Register Dst,
53                       std::initializer_list<SrcOp> SrcOps)
54       : Opc(Opc), Dst(Dst), SrcOps(SrcOps){};
55   ShuffleVectorPseudo() {}
56 };
57 
58 /// Check if a vector shuffle corresponds to a REV instruction with the
59 /// specified blocksize.
60 static bool isREVMask(ArrayRef<int> M, unsigned EltSize, unsigned NumElts,
61                       unsigned BlockSize) {
62   assert((BlockSize == 16 || BlockSize == 32 || BlockSize == 64) &&
63          "Only possible block sizes for REV are: 16, 32, 64");
64   assert(EltSize != 64 && "EltSize cannot be 64 for REV mask.");
65 
66   unsigned BlockElts = M[0] + 1;
67 
68   // If the first shuffle index is UNDEF, be optimistic.
69   if (M[0] < 0)
70     BlockElts = BlockSize / EltSize;
71 
72   if (BlockSize <= EltSize || BlockSize != BlockElts * EltSize)
73     return false;
74 
75   for (unsigned i = 0; i < NumElts; ++i) {
76     // Ignore undef indices.
77     if (M[i] < 0)
78       continue;
79     if (static_cast<unsigned>(M[i]) !=
80         (i - i % BlockElts) + (BlockElts - 1 - i % BlockElts))
81       return false;
82   }
83 
84   return true;
85 }
86 
87 /// Determines if \p M is a shuffle vector mask for a TRN of \p NumElts.
88 /// Whether or not G_TRN1 or G_TRN2 should be used is stored in \p WhichResult.
89 static bool isTRNMask(ArrayRef<int> M, unsigned NumElts,
90                       unsigned &WhichResult) {
91   if (NumElts % 2 != 0)
92     return false;
93   WhichResult = (M[0] == 0 ? 0 : 1);
94   for (unsigned i = 0; i < NumElts; i += 2) {
95     if ((M[i] >= 0 && static_cast<unsigned>(M[i]) != i + WhichResult) ||
96         (M[i + 1] >= 0 &&
97          static_cast<unsigned>(M[i + 1]) != i + NumElts + WhichResult))
98       return false;
99   }
100   return true;
101 }
102 
103 /// Check if a G_EXT instruction can handle a shuffle mask \p M when the vector
104 /// sources of the shuffle are different.
105 static Optional<std::pair<bool, uint64_t>> getExtMask(ArrayRef<int> M,
106                                                       unsigned NumElts) {
107   // Look for the first non-undef element.
108   auto FirstRealElt = find_if(M, [](int Elt) { return Elt >= 0; });
109   if (FirstRealElt == M.end())
110     return None;
111 
112   // Use APInt to handle overflow when calculating expected element.
113   unsigned MaskBits = APInt(32, NumElts * 2).logBase2();
114   APInt ExpectedElt = APInt(MaskBits, *FirstRealElt + 1);
115 
116   // The following shuffle indices must be the successive elements after the
117   // first real element.
118   if (any_of(
119           make_range(std::next(FirstRealElt), M.end()),
120           [&ExpectedElt](int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
121     return None;
122 
123   // The index of an EXT is the first element if it is not UNDEF.
124   // Watch out for the beginning UNDEFs. The EXT index should be the expected
125   // value of the first element.  E.g.
126   // <-1, -1, 3, ...> is treated as <1, 2, 3, ...>.
127   // <-1, -1, 0, 1, ...> is treated as <2*NumElts-2, 2*NumElts-1, 0, 1, ...>.
128   // ExpectedElt is the last mask index plus 1.
129   uint64_t Imm = ExpectedElt.getZExtValue();
130   bool ReverseExt = false;
131 
132   // There are two difference cases requiring to reverse input vectors.
133   // For example, for vector <4 x i32> we have the following cases,
134   // Case 1: shufflevector(<4 x i32>,<4 x i32>,<-1, -1, -1, 0>)
135   // Case 2: shufflevector(<4 x i32>,<4 x i32>,<-1, -1, 7, 0>)
136   // For both cases, we finally use mask <5, 6, 7, 0>, which requires
137   // to reverse two input vectors.
138   if (Imm < NumElts)
139     ReverseExt = true;
140   else
141     Imm -= NumElts;
142   return std::make_pair(ReverseExt, Imm);
143 }
144 
145 /// Determines if \p M is a shuffle vector mask for a UZP of \p NumElts.
146 /// Whether or not G_UZP1 or G_UZP2 should be used is stored in \p WhichResult.
147 static bool isUZPMask(ArrayRef<int> M, unsigned NumElts,
148                       unsigned &WhichResult) {
149   WhichResult = (M[0] == 0 ? 0 : 1);
150   for (unsigned i = 0; i != NumElts; ++i) {
151     // Skip undef indices.
152     if (M[i] < 0)
153       continue;
154     if (static_cast<unsigned>(M[i]) != 2 * i + WhichResult)
155       return false;
156   }
157   return true;
158 }
159 
160 /// \return true if \p M is a zip mask for a shuffle vector of \p NumElts.
161 /// Whether or not G_ZIP1 or G_ZIP2 should be used is stored in \p WhichResult.
162 static bool isZipMask(ArrayRef<int> M, unsigned NumElts,
163                       unsigned &WhichResult) {
164   if (NumElts % 2 != 0)
165     return false;
166 
167   // 0 means use ZIP1, 1 means use ZIP2.
168   WhichResult = (M[0] == 0 ? 0 : 1);
169   unsigned Idx = WhichResult * NumElts / 2;
170   for (unsigned i = 0; i != NumElts; i += 2) {
171       if ((M[i] >= 0 && static_cast<unsigned>(M[i]) != Idx) ||
172           (M[i + 1] >= 0 && static_cast<unsigned>(M[i + 1]) != Idx + NumElts))
173         return false;
174     Idx += 1;
175   }
176   return true;
177 }
178 
179 /// Helper function for matchINS.
180 ///
181 /// \returns a value when \p M is an ins mask for \p NumInputElements.
182 ///
183 /// First element of the returned pair is true when the produced
184 /// G_INSERT_VECTOR_ELT destination should be the LHS of the G_SHUFFLE_VECTOR.
185 ///
186 /// Second element is the destination lane for the G_INSERT_VECTOR_ELT.
187 static Optional<std::pair<bool, int>> isINSMask(ArrayRef<int> M,
188                                                 int NumInputElements) {
189   if (M.size() != static_cast<size_t>(NumInputElements))
190     return None;
191   int NumLHSMatch = 0, NumRHSMatch = 0;
192   int LastLHSMismatch = -1, LastRHSMismatch = -1;
193   for (int Idx = 0; Idx < NumInputElements; ++Idx) {
194     if (M[Idx] == -1) {
195       ++NumLHSMatch;
196       ++NumRHSMatch;
197       continue;
198     }
199     M[Idx] == Idx ? ++NumLHSMatch : LastLHSMismatch = Idx;
200     M[Idx] == Idx + NumInputElements ? ++NumRHSMatch : LastRHSMismatch = Idx;
201   }
202   const int NumNeededToMatch = NumInputElements - 1;
203   if (NumLHSMatch == NumNeededToMatch)
204     return std::make_pair(true, LastLHSMismatch);
205   if (NumRHSMatch == NumNeededToMatch)
206     return std::make_pair(false, LastRHSMismatch);
207   return None;
208 }
209 
210 /// \return true if a G_SHUFFLE_VECTOR instruction \p MI can be replaced with a
211 /// G_REV instruction. Returns the appropriate G_REV opcode in \p Opc.
212 static bool matchREV(MachineInstr &MI, MachineRegisterInfo &MRI,
213                      ShuffleVectorPseudo &MatchInfo) {
214   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
215   ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
216   Register Dst = MI.getOperand(0).getReg();
217   Register Src = MI.getOperand(1).getReg();
218   LLT Ty = MRI.getType(Dst);
219   unsigned EltSize = Ty.getScalarSizeInBits();
220 
221   // Element size for a rev cannot be 64.
222   if (EltSize == 64)
223     return false;
224 
225   unsigned NumElts = Ty.getNumElements();
226 
227   // Try to produce G_REV64
228   if (isREVMask(ShuffleMask, EltSize, NumElts, 64)) {
229     MatchInfo = ShuffleVectorPseudo(AArch64::G_REV64, Dst, {Src});
230     return true;
231   }
232 
233   // TODO: Produce G_REV32 and G_REV16 once we have proper legalization support.
234   // This should be identical to above, but with a constant 32 and constant
235   // 16.
236   return false;
237 }
238 
239 /// \return true if a G_SHUFFLE_VECTOR instruction \p MI can be replaced with
240 /// a G_TRN1 or G_TRN2 instruction.
241 static bool matchTRN(MachineInstr &MI, MachineRegisterInfo &MRI,
242                      ShuffleVectorPseudo &MatchInfo) {
243   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
244   unsigned WhichResult;
245   ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
246   Register Dst = MI.getOperand(0).getReg();
247   unsigned NumElts = MRI.getType(Dst).getNumElements();
248   if (!isTRNMask(ShuffleMask, NumElts, WhichResult))
249     return false;
250   unsigned Opc = (WhichResult == 0) ? AArch64::G_TRN1 : AArch64::G_TRN2;
251   Register V1 = MI.getOperand(1).getReg();
252   Register V2 = MI.getOperand(2).getReg();
253   MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1, V2});
254   return true;
255 }
256 
257 /// \return true if a G_SHUFFLE_VECTOR instruction \p MI can be replaced with
258 /// a G_UZP1 or G_UZP2 instruction.
259 ///
260 /// \param [in] MI - The shuffle vector instruction.
261 /// \param [out] MatchInfo - Either G_UZP1 or G_UZP2 on success.
262 static bool matchUZP(MachineInstr &MI, MachineRegisterInfo &MRI,
263                      ShuffleVectorPseudo &MatchInfo) {
264   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
265   unsigned WhichResult;
266   ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
267   Register Dst = MI.getOperand(0).getReg();
268   unsigned NumElts = MRI.getType(Dst).getNumElements();
269   if (!isUZPMask(ShuffleMask, NumElts, WhichResult))
270     return false;
271   unsigned Opc = (WhichResult == 0) ? AArch64::G_UZP1 : AArch64::G_UZP2;
272   Register V1 = MI.getOperand(1).getReg();
273   Register V2 = MI.getOperand(2).getReg();
274   MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1, V2});
275   return true;
276 }
277 
278 static bool matchZip(MachineInstr &MI, MachineRegisterInfo &MRI,
279                      ShuffleVectorPseudo &MatchInfo) {
280   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
281   unsigned WhichResult;
282   ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
283   Register Dst = MI.getOperand(0).getReg();
284   unsigned NumElts = MRI.getType(Dst).getNumElements();
285   if (!isZipMask(ShuffleMask, NumElts, WhichResult))
286     return false;
287   unsigned Opc = (WhichResult == 0) ? AArch64::G_ZIP1 : AArch64::G_ZIP2;
288   Register V1 = MI.getOperand(1).getReg();
289   Register V2 = MI.getOperand(2).getReg();
290   MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1, V2});
291   return true;
292 }
293 
294 /// Helper function for matchDup.
295 static bool matchDupFromInsertVectorElt(int Lane, MachineInstr &MI,
296                                         MachineRegisterInfo &MRI,
297                                         ShuffleVectorPseudo &MatchInfo) {
298   if (Lane != 0)
299     return false;
300 
301   // Try to match a vector splat operation into a dup instruction.
302   // We're looking for this pattern:
303   //
304   // %scalar:gpr(s64) = COPY $x0
305   // %undef:fpr(<2 x s64>) = G_IMPLICIT_DEF
306   // %cst0:gpr(s32) = G_CONSTANT i32 0
307   // %zerovec:fpr(<2 x s32>) = G_BUILD_VECTOR %cst0(s32), %cst0(s32)
308   // %ins:fpr(<2 x s64>) = G_INSERT_VECTOR_ELT %undef, %scalar(s64), %cst0(s32)
309   // %splat:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %ins(<2 x s64>), %undef, %zerovec(<2 x s32>)
310   //
311   // ...into:
312   // %splat = G_DUP %scalar
313 
314   // Begin matching the insert.
315   auto *InsMI = getOpcodeDef(TargetOpcode::G_INSERT_VECTOR_ELT,
316                              MI.getOperand(1).getReg(), MRI);
317   if (!InsMI)
318     return false;
319   // Match the undef vector operand.
320   if (!getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
321                     MRI))
322     return false;
323 
324   // Match the index constant 0.
325   if (!mi_match(InsMI->getOperand(3).getReg(), MRI, m_ZeroInt()))
326     return false;
327 
328   MatchInfo = ShuffleVectorPseudo(AArch64::G_DUP, MI.getOperand(0).getReg(),
329                                   {InsMI->getOperand(2).getReg()});
330   return true;
331 }
332 
333 /// Helper function for matchDup.
334 static bool matchDupFromBuildVector(int Lane, MachineInstr &MI,
335                                     MachineRegisterInfo &MRI,
336                                     ShuffleVectorPseudo &MatchInfo) {
337   assert(Lane >= 0 && "Expected positive lane?");
338   // Test if the LHS is a BUILD_VECTOR. If it is, then we can just reference the
339   // lane's definition directly.
340   auto *BuildVecMI = getOpcodeDef(TargetOpcode::G_BUILD_VECTOR,
341                                   MI.getOperand(1).getReg(), MRI);
342   if (!BuildVecMI)
343     return false;
344   Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
345   MatchInfo =
346       ShuffleVectorPseudo(AArch64::G_DUP, MI.getOperand(0).getReg(), {Reg});
347   return true;
348 }
349 
350 static bool matchDup(MachineInstr &MI, MachineRegisterInfo &MRI,
351                      ShuffleVectorPseudo &MatchInfo) {
352   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
353   auto MaybeLane = getSplatIndex(MI);
354   if (!MaybeLane)
355     return false;
356   int Lane = *MaybeLane;
357   // If this is undef splat, generate it via "just" vdup, if possible.
358   if (Lane < 0)
359     Lane = 0;
360   if (matchDupFromInsertVectorElt(Lane, MI, MRI, MatchInfo))
361     return true;
362   if (matchDupFromBuildVector(Lane, MI, MRI, MatchInfo))
363     return true;
364   return false;
365 }
366 
367 static bool matchEXT(MachineInstr &MI, MachineRegisterInfo &MRI,
368                      ShuffleVectorPseudo &MatchInfo) {
369   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
370   Register Dst = MI.getOperand(0).getReg();
371   auto ExtInfo = getExtMask(MI.getOperand(3).getShuffleMask(),
372                             MRI.getType(Dst).getNumElements());
373   if (!ExtInfo)
374     return false;
375   bool ReverseExt;
376   uint64_t Imm;
377   std::tie(ReverseExt, Imm) = *ExtInfo;
378   Register V1 = MI.getOperand(1).getReg();
379   Register V2 = MI.getOperand(2).getReg();
380   if (ReverseExt)
381     std::swap(V1, V2);
382   uint64_t ExtFactor = MRI.getType(V1).getScalarSizeInBits() / 8;
383   Imm *= ExtFactor;
384   MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1, V2, Imm});
385   return true;
386 }
387 
388 /// Replace a G_SHUFFLE_VECTOR instruction with a pseudo.
389 /// \p Opc is the opcode to use. \p MI is the G_SHUFFLE_VECTOR.
390 static bool applyShuffleVectorPseudo(MachineInstr &MI,
391                                      ShuffleVectorPseudo &MatchInfo) {
392   MachineIRBuilder MIRBuilder(MI);
393   MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst}, MatchInfo.SrcOps);
394   MI.eraseFromParent();
395   return true;
396 }
397 
398 /// Replace a G_SHUFFLE_VECTOR instruction with G_EXT.
399 /// Special-cased because the constant operand must be emitted as a G_CONSTANT
400 /// for the imported tablegen patterns to work.
401 static bool applyEXT(MachineInstr &MI, ShuffleVectorPseudo &MatchInfo) {
402   MachineIRBuilder MIRBuilder(MI);
403   // Tablegen patterns expect an i32 G_CONSTANT as the final op.
404   auto Cst =
405       MIRBuilder.buildConstant(LLT::scalar(32), MatchInfo.SrcOps[2].getImm());
406   MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst},
407                         {MatchInfo.SrcOps[0], MatchInfo.SrcOps[1], Cst});
408   MI.eraseFromParent();
409   return true;
410 }
411 
412 /// Match a G_SHUFFLE_VECTOR with a mask which corresponds to a
413 /// G_INSERT_VECTOR_ELT and G_EXTRACT_VECTOR_ELT pair.
414 ///
415 /// e.g.
416 ///   %shuf = G_SHUFFLE_VECTOR %left, %right, shufflemask(0, 0)
417 ///
418 /// Can be represented as
419 ///
420 ///   %extract = G_EXTRACT_VECTOR_ELT %left, 0
421 ///   %ins = G_INSERT_VECTOR_ELT %left, %extract, 1
422 ///
423 static bool matchINS(MachineInstr &MI, MachineRegisterInfo &MRI,
424                      std::tuple<Register, int, Register, int> &MatchInfo) {
425   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
426   ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
427   Register Dst = MI.getOperand(0).getReg();
428   int NumElts = MRI.getType(Dst).getNumElements();
429   auto DstIsLeftAndDstLane = isINSMask(ShuffleMask, NumElts);
430   if (!DstIsLeftAndDstLane)
431     return false;
432   bool DstIsLeft;
433   int DstLane;
434   std::tie(DstIsLeft, DstLane) = *DstIsLeftAndDstLane;
435   Register Left = MI.getOperand(1).getReg();
436   Register Right = MI.getOperand(2).getReg();
437   Register DstVec = DstIsLeft ? Left : Right;
438   Register SrcVec = Left;
439 
440   int SrcLane = ShuffleMask[DstLane];
441   if (SrcLane >= NumElts) {
442     SrcVec = Right;
443     SrcLane -= NumElts;
444   }
445 
446   MatchInfo = std::make_tuple(DstVec, DstLane, SrcVec, SrcLane);
447   return true;
448 }
449 
450 static bool applyINS(MachineInstr &MI, MachineRegisterInfo &MRI,
451                      MachineIRBuilder &Builder,
452                      std::tuple<Register, int, Register, int> &MatchInfo) {
453   Builder.setInstrAndDebugLoc(MI);
454   Register Dst = MI.getOperand(0).getReg();
455   auto ScalarTy = MRI.getType(Dst).getElementType();
456   Register DstVec, SrcVec;
457   int DstLane, SrcLane;
458   std::tie(DstVec, DstLane, SrcVec, SrcLane) = MatchInfo;
459   auto SrcCst = Builder.buildConstant(LLT::scalar(64), SrcLane);
460   auto Extract = Builder.buildExtractVectorElement(ScalarTy, SrcVec, SrcCst);
461   auto DstCst = Builder.buildConstant(LLT::scalar(64), DstLane);
462   Builder.buildInsertVectorElement(Dst, DstVec, Extract, DstCst);
463   MI.eraseFromParent();
464   return true;
465 }
466 
467 /// isVShiftRImm - Check if this is a valid vector for the immediate
468 /// operand of a vector shift right operation. The value must be in the range:
469 ///   1 <= Value <= ElementBits for a right shift.
470 static bool isVShiftRImm(Register Reg, MachineRegisterInfo &MRI, LLT Ty,
471                          int64_t &Cnt) {
472   assert(Ty.isVector() && "vector shift count is not a vector type");
473   MachineInstr *MI = MRI.getVRegDef(Reg);
474   auto Cst = getAArch64VectorSplatScalar(*MI, MRI);
475   if (!Cst)
476     return false;
477   Cnt = *Cst;
478   int64_t ElementBits = Ty.getScalarSizeInBits();
479   return Cnt >= 1 && Cnt <= ElementBits;
480 }
481 
482 /// Match a vector G_ASHR or G_LSHR with a valid immediate shift.
483 static bool matchVAshrLshrImm(MachineInstr &MI, MachineRegisterInfo &MRI,
484                               int64_t &Imm) {
485   assert(MI.getOpcode() == TargetOpcode::G_ASHR ||
486          MI.getOpcode() == TargetOpcode::G_LSHR);
487   LLT Ty = MRI.getType(MI.getOperand(1).getReg());
488   if (!Ty.isVector())
489     return false;
490   return isVShiftRImm(MI.getOperand(2).getReg(), MRI, Ty, Imm);
491 }
492 
493 static bool applyVAshrLshrImm(MachineInstr &MI, MachineRegisterInfo &MRI,
494                               int64_t &Imm) {
495   unsigned Opc = MI.getOpcode();
496   assert(Opc == TargetOpcode::G_ASHR || Opc == TargetOpcode::G_LSHR);
497   unsigned NewOpc =
498       Opc == TargetOpcode::G_ASHR ? AArch64::G_VASHR : AArch64::G_VLSHR;
499   MachineIRBuilder MIB(MI);
500   auto ImmDef = MIB.buildConstant(LLT::scalar(32), Imm);
501   MIB.buildInstr(NewOpc, {MI.getOperand(0)}, {MI.getOperand(1), ImmDef});
502   MI.eraseFromParent();
503   return true;
504 }
505 
506 /// Determine if it is possible to modify the \p RHS and predicate \p P of a
507 /// G_ICMP instruction such that the right-hand side is an arithmetic immediate.
508 ///
509 /// \returns A pair containing the updated immediate and predicate which may
510 /// be used to optimize the instruction.
511 ///
512 /// \note This assumes that the comparison has been legalized.
513 Optional<std::pair<uint64_t, CmpInst::Predicate>>
514 tryAdjustICmpImmAndPred(Register RHS, CmpInst::Predicate P,
515                           const MachineRegisterInfo &MRI) {
516   const auto &Ty = MRI.getType(RHS);
517   if (Ty.isVector())
518     return None;
519   unsigned Size = Ty.getSizeInBits();
520   assert((Size == 32 || Size == 64) && "Expected 32 or 64 bit compare only?");
521 
522   // If the RHS is not a constant, or the RHS is already a valid arithmetic
523   // immediate, then there is nothing to change.
524   auto ValAndVReg = getConstantVRegValWithLookThrough(RHS, MRI);
525   if (!ValAndVReg)
526     return None;
527   uint64_t C = ValAndVReg->Value.getZExtValue();
528   if (isLegalArithImmed(C))
529     return None;
530 
531   // We have a non-arithmetic immediate. Check if adjusting the immediate and
532   // adjusting the predicate will result in a legal arithmetic immediate.
533   switch (P) {
534   default:
535     return None;
536   case CmpInst::ICMP_SLT:
537   case CmpInst::ICMP_SGE:
538     // Check for
539     //
540     // x slt c => x sle c - 1
541     // x sge c => x sgt c - 1
542     //
543     // When c is not the smallest possible negative number.
544     if ((Size == 64 && static_cast<int64_t>(C) == INT64_MIN) ||
545         (Size == 32 && static_cast<int32_t>(C) == INT32_MIN))
546       return None;
547     P = (P == CmpInst::ICMP_SLT) ? CmpInst::ICMP_SLE : CmpInst::ICMP_SGT;
548     C -= 1;
549     break;
550   case CmpInst::ICMP_ULT:
551   case CmpInst::ICMP_UGE:
552     // Check for
553     //
554     // x ult c => x ule c - 1
555     // x uge c => x ugt c - 1
556     //
557     // When c is not zero.
558     if (C == 0)
559       return None;
560     P = (P == CmpInst::ICMP_ULT) ? CmpInst::ICMP_ULE : CmpInst::ICMP_UGT;
561     C -= 1;
562     break;
563   case CmpInst::ICMP_SLE:
564   case CmpInst::ICMP_SGT:
565     // Check for
566     //
567     // x sle c => x slt c + 1
568     // x sgt c => s sge c + 1
569     //
570     // When c is not the largest possible signed integer.
571     if ((Size == 32 && static_cast<int32_t>(C) == INT32_MAX) ||
572         (Size == 64 && static_cast<int64_t>(C) == INT64_MAX))
573       return None;
574     P = (P == CmpInst::ICMP_SLE) ? CmpInst::ICMP_SLT : CmpInst::ICMP_SGE;
575     C += 1;
576     break;
577   case CmpInst::ICMP_ULE:
578   case CmpInst::ICMP_UGT:
579     // Check for
580     //
581     // x ule c => x ult c + 1
582     // x ugt c => s uge c + 1
583     //
584     // When c is not the largest possible unsigned integer.
585     if ((Size == 32 && static_cast<uint32_t>(C) == UINT32_MAX) ||
586         (Size == 64 && C == UINT64_MAX))
587       return None;
588     P = (P == CmpInst::ICMP_ULE) ? CmpInst::ICMP_ULT : CmpInst::ICMP_UGE;
589     C += 1;
590     break;
591   }
592 
593   // Check if the new constant is valid, and return the updated constant and
594   // predicate if it is.
595   if (Size == 32)
596     C = static_cast<uint32_t>(C);
597   if (!isLegalArithImmed(C))
598     return None;
599   return {{C, P}};
600 }
601 
602 /// Determine whether or not it is possible to update the RHS and predicate of
603 /// a G_ICMP instruction such that the RHS will be selected as an arithmetic
604 /// immediate.
605 ///
606 /// \p MI - The G_ICMP instruction
607 /// \p MatchInfo - The new RHS immediate and predicate on success
608 ///
609 /// See tryAdjustICmpImmAndPred for valid transformations.
610 bool matchAdjustICmpImmAndPred(
611     MachineInstr &MI, const MachineRegisterInfo &MRI,
612     std::pair<uint64_t, CmpInst::Predicate> &MatchInfo) {
613   assert(MI.getOpcode() == TargetOpcode::G_ICMP);
614   Register RHS = MI.getOperand(3).getReg();
615   auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
616   if (auto MaybeNewImmAndPred = tryAdjustICmpImmAndPred(RHS, Pred, MRI)) {
617     MatchInfo = *MaybeNewImmAndPred;
618     return true;
619   }
620   return false;
621 }
622 
623 bool applyAdjustICmpImmAndPred(
624     MachineInstr &MI, std::pair<uint64_t, CmpInst::Predicate> &MatchInfo,
625     MachineIRBuilder &MIB, GISelChangeObserver &Observer) {
626   MIB.setInstrAndDebugLoc(MI);
627   MachineOperand &RHS = MI.getOperand(3);
628   MachineRegisterInfo &MRI = *MIB.getMRI();
629   auto Cst = MIB.buildConstant(MRI.cloneVirtualRegister(RHS.getReg()),
630                                MatchInfo.first);
631   Observer.changingInstr(MI);
632   RHS.setReg(Cst->getOperand(0).getReg());
633   MI.getOperand(1).setPredicate(MatchInfo.second);
634   Observer.changedInstr(MI);
635   return true;
636 }
637 
638 bool matchDupLane(MachineInstr &MI, MachineRegisterInfo &MRI,
639                   std::pair<unsigned, int> &MatchInfo) {
640   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
641   Register Src1Reg = MI.getOperand(1).getReg();
642   const LLT SrcTy = MRI.getType(Src1Reg);
643   const LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
644 
645   auto LaneIdx = getSplatIndex(MI);
646   if (!LaneIdx)
647     return false;
648 
649   // The lane idx should be within the first source vector.
650   if (*LaneIdx >= SrcTy.getNumElements())
651     return false;
652 
653   if (DstTy != SrcTy)
654     return false;
655 
656   LLT ScalarTy = SrcTy.getElementType();
657   unsigned ScalarSize = ScalarTy.getSizeInBits();
658 
659   unsigned Opc = 0;
660   switch (SrcTy.getNumElements()) {
661   case 2:
662     if (ScalarSize == 64)
663       Opc = AArch64::G_DUPLANE64;
664     else if (ScalarSize == 32)
665       Opc = AArch64::G_DUPLANE32;
666     break;
667   case 4:
668     if (ScalarSize == 32)
669       Opc = AArch64::G_DUPLANE32;
670     break;
671   case 8:
672     if (ScalarSize == 16)
673       Opc = AArch64::G_DUPLANE16;
674     break;
675   case 16:
676     if (ScalarSize == 8)
677       Opc = AArch64::G_DUPLANE8;
678     break;
679   default:
680     break;
681   }
682   if (!Opc)
683     return false;
684 
685   MatchInfo.first = Opc;
686   MatchInfo.second = *LaneIdx;
687   return true;
688 }
689 
690 bool applyDupLane(MachineInstr &MI, MachineRegisterInfo &MRI,
691                   MachineIRBuilder &B, std::pair<unsigned, int> &MatchInfo) {
692   assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
693   Register Src1Reg = MI.getOperand(1).getReg();
694   const LLT SrcTy = MRI.getType(Src1Reg);
695 
696   B.setInstrAndDebugLoc(MI);
697   auto Lane = B.buildConstant(LLT::scalar(64), MatchInfo.second);
698 
699   Register DupSrc = MI.getOperand(1).getReg();
700   // For types like <2 x s32>, we can use G_DUPLANE32, with a <4 x s32> source.
701   // To do this, we can use a G_CONCAT_VECTORS to do the widening.
702   if (SrcTy == LLT::vector(2, LLT::scalar(32))) {
703     assert(MRI.getType(MI.getOperand(0).getReg()).getNumElements() == 2 &&
704            "Unexpected dest elements");
705     auto Undef = B.buildUndef(SrcTy);
706     DupSrc = B.buildConcatVectors(SrcTy.changeNumElements(4),
707                                   {Src1Reg, Undef.getReg(0)})
708                  .getReg(0);
709   }
710   B.buildInstr(MatchInfo.first, {MI.getOperand(0).getReg()}, {DupSrc, Lane});
711   MI.eraseFromParent();
712   return true;
713 }
714 
715 static bool matchBuildVectorToDup(MachineInstr &MI, MachineRegisterInfo &MRI) {
716   assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
717   auto Splat = getAArch64VectorSplat(MI, MRI);
718   if (!Splat)
719     return false;
720   if (Splat->isReg())
721     return true;
722   // Later, during selection, we'll try to match imported patterns using
723   // immAllOnesV and immAllZerosV. These require G_BUILD_VECTOR. Don't lower
724   // G_BUILD_VECTORs which could match those patterns.
725   int64_t Cst = Splat->getCst();
726   return (Cst != 0 && Cst != -1);
727 }
728 
729 static bool applyBuildVectorToDup(MachineInstr &MI, MachineRegisterInfo &MRI,
730                                   MachineIRBuilder &B) {
731   B.setInstrAndDebugLoc(MI);
732   B.buildInstr(AArch64::G_DUP, {MI.getOperand(0).getReg()},
733                {MI.getOperand(1).getReg()});
734   MI.eraseFromParent();
735   return true;
736 }
737 
738 /// \returns how many instructions would be saved by folding a G_ICMP's shift
739 /// and/or extension operations.
740 static unsigned getCmpOperandFoldingProfit(Register CmpOp,
741                                            const MachineRegisterInfo &MRI) {
742   // No instructions to save if there's more than one use or no uses.
743   if (!MRI.hasOneNonDBGUse(CmpOp))
744     return 0;
745 
746   // FIXME: This is duplicated with the selector. (See: selectShiftedRegister)
747   auto IsSupportedExtend = [&](const MachineInstr &MI) {
748     if (MI.getOpcode() == TargetOpcode::G_SEXT_INREG)
749       return true;
750     if (MI.getOpcode() != TargetOpcode::G_AND)
751       return false;
752     auto ValAndVReg =
753         getConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
754     if (!ValAndVReg)
755       return false;
756     uint64_t Mask = ValAndVReg->Value.getZExtValue();
757     return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
758   };
759 
760   MachineInstr *Def = getDefIgnoringCopies(CmpOp, MRI);
761   if (IsSupportedExtend(*Def))
762     return 1;
763 
764   unsigned Opc = Def->getOpcode();
765   if (Opc != TargetOpcode::G_SHL && Opc != TargetOpcode::G_ASHR &&
766       Opc != TargetOpcode::G_LSHR)
767     return 0;
768 
769   auto MaybeShiftAmt =
770       getConstantVRegValWithLookThrough(Def->getOperand(2).getReg(), MRI);
771   if (!MaybeShiftAmt)
772     return 0;
773   uint64_t ShiftAmt = MaybeShiftAmt->Value.getZExtValue();
774   MachineInstr *ShiftLHS =
775       getDefIgnoringCopies(Def->getOperand(1).getReg(), MRI);
776 
777   // Check if we can fold an extend and a shift.
778   // FIXME: This is duplicated with the selector. (See:
779   // selectArithExtendedRegister)
780   if (IsSupportedExtend(*ShiftLHS))
781     return (ShiftAmt <= 4) ? 2 : 1;
782 
783   LLT Ty = MRI.getType(Def->getOperand(0).getReg());
784   if (Ty.isVector())
785     return 0;
786   unsigned ShiftSize = Ty.getSizeInBits();
787   if ((ShiftSize == 32 && ShiftAmt <= 31) ||
788       (ShiftSize == 64 && ShiftAmt <= 63))
789     return 1;
790   return 0;
791 }
792 
793 /// \returns true if it would be profitable to swap the LHS and RHS of a G_ICMP
794 /// instruction \p MI.
795 static bool trySwapICmpOperands(MachineInstr &MI,
796                                  const MachineRegisterInfo &MRI) {
797   assert(MI.getOpcode() == TargetOpcode::G_ICMP);
798   // Swap the operands if it would introduce a profitable folding opportunity.
799   // (e.g. a shift + extend).
800   //
801   //  For example:
802   //    lsl     w13, w11, #1
803   //    cmp     w13, w12
804   // can be turned into:
805   //    cmp     w12, w11, lsl #1
806 
807   // Don't swap if there's a constant on the RHS, because we know we can fold
808   // that.
809   Register RHS = MI.getOperand(3).getReg();
810   auto RHSCst = getConstantVRegValWithLookThrough(RHS, MRI);
811   if (RHSCst && isLegalArithImmed(RHSCst->Value.getSExtValue()))
812     return false;
813 
814   Register LHS = MI.getOperand(2).getReg();
815   auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
816   auto GetRegForProfit = [&](Register Reg) {
817     MachineInstr *Def = getDefIgnoringCopies(Reg, MRI);
818     return isCMN(Def, Pred, MRI) ? Def->getOperand(2).getReg() : Reg;
819   };
820 
821   // Don't have a constant on the RHS. If we swap the LHS and RHS of the
822   // compare, would we be able to fold more instructions?
823   Register TheLHS = GetRegForProfit(LHS);
824   Register TheRHS = GetRegForProfit(RHS);
825 
826   // If the LHS is more likely to give us a folding opportunity, then swap the
827   // LHS and RHS.
828   return (getCmpOperandFoldingProfit(TheLHS, MRI) >
829           getCmpOperandFoldingProfit(TheRHS, MRI));
830 }
831 
832 static bool applySwapICmpOperands(MachineInstr &MI,
833                                    GISelChangeObserver &Observer) {
834   auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
835   Register LHS = MI.getOperand(2).getReg();
836   Register RHS = MI.getOperand(3).getReg();
837   Observer.changedInstr(MI);
838   MI.getOperand(1).setPredicate(CmpInst::getSwappedPredicate(Pred));
839   MI.getOperand(2).setReg(RHS);
840   MI.getOperand(3).setReg(LHS);
841   Observer.changedInstr(MI);
842   return true;
843 }
844 
845 #define AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_DEPS
846 #include "AArch64GenPostLegalizeGILowering.inc"
847 #undef AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_DEPS
848 
849 namespace {
850 #define AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_H
851 #include "AArch64GenPostLegalizeGILowering.inc"
852 #undef AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_H
853 
854 class AArch64PostLegalizerLoweringInfo : public CombinerInfo {
855 public:
856   AArch64GenPostLegalizerLoweringHelperRuleConfig GeneratedRuleCfg;
857 
858   AArch64PostLegalizerLoweringInfo(bool OptSize, bool MinSize)
859       : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
860                      /*LegalizerInfo*/ nullptr, /*OptEnabled = */ true, OptSize,
861                      MinSize) {
862     if (!GeneratedRuleCfg.parseCommandLineOption())
863       report_fatal_error("Invalid rule identifier");
864   }
865 
866   virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
867                        MachineIRBuilder &B) const override;
868 };
869 
870 bool AArch64PostLegalizerLoweringInfo::combine(GISelChangeObserver &Observer,
871                                                MachineInstr &MI,
872                                                MachineIRBuilder &B) const {
873   CombinerHelper Helper(Observer, B);
874   AArch64GenPostLegalizerLoweringHelper Generated(GeneratedRuleCfg);
875   return Generated.tryCombineAll(Observer, MI, B, Helper);
876 }
877 
878 #define AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_CPP
879 #include "AArch64GenPostLegalizeGILowering.inc"
880 #undef AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_CPP
881 
882 class AArch64PostLegalizerLowering : public MachineFunctionPass {
883 public:
884   static char ID;
885 
886   AArch64PostLegalizerLowering();
887 
888   StringRef getPassName() const override {
889     return "AArch64PostLegalizerLowering";
890   }
891 
892   bool runOnMachineFunction(MachineFunction &MF) override;
893   void getAnalysisUsage(AnalysisUsage &AU) const override;
894 };
895 } // end anonymous namespace
896 
897 void AArch64PostLegalizerLowering::getAnalysisUsage(AnalysisUsage &AU) const {
898   AU.addRequired<TargetPassConfig>();
899   AU.setPreservesCFG();
900   getSelectionDAGFallbackAnalysisUsage(AU);
901   MachineFunctionPass::getAnalysisUsage(AU);
902 }
903 
904 AArch64PostLegalizerLowering::AArch64PostLegalizerLowering()
905     : MachineFunctionPass(ID) {
906   initializeAArch64PostLegalizerLoweringPass(*PassRegistry::getPassRegistry());
907 }
908 
909 bool AArch64PostLegalizerLowering::runOnMachineFunction(MachineFunction &MF) {
910   if (MF.getProperties().hasProperty(
911           MachineFunctionProperties::Property::FailedISel))
912     return false;
913   assert(MF.getProperties().hasProperty(
914              MachineFunctionProperties::Property::Legalized) &&
915          "Expected a legalized function?");
916   auto *TPC = &getAnalysis<TargetPassConfig>();
917   const Function &F = MF.getFunction();
918   AArch64PostLegalizerLoweringInfo PCInfo(F.hasOptSize(), F.hasMinSize());
919   Combiner C(PCInfo, TPC);
920   return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr);
921 }
922 
923 char AArch64PostLegalizerLowering::ID = 0;
924 INITIALIZE_PASS_BEGIN(AArch64PostLegalizerLowering, DEBUG_TYPE,
925                       "Lower AArch64 MachineInstrs after legalization", false,
926                       false)
927 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
928 INITIALIZE_PASS_END(AArch64PostLegalizerLowering, DEBUG_TYPE,
929                     "Lower AArch64 MachineInstrs after legalization", false,
930                     false)
931 
932 namespace llvm {
933 FunctionPass *createAArch64PostLegalizerLowering() {
934   return new AArch64PostLegalizerLowering();
935 }
936 } // end namespace llvm
937