1 //===- AArch64ExpandPseudoInsts.cpp - Expand pseudo instructions ----------===//
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 // This file contains a pass that expands pseudo instructions into target
10 // instructions to allow proper scheduling and other late optimizations.  This
11 // pass should be run after register allocation but before the post-regalloc
12 // scheduling pass.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "AArch64ExpandImm.h"
17 #include "AArch64InstrInfo.h"
18 #include "AArch64MachineFunctionInfo.h"
19 #include "AArch64Subtarget.h"
20 #include "MCTargetDesc/AArch64AddressingModes.h"
21 #include "Utils/AArch64BaseInfo.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/Triple.h"
24 #include "llvm/CodeGen/LivePhysRegs.h"
25 #include "llvm/CodeGen/MachineBasicBlock.h"
26 #include "llvm/CodeGen/MachineFunction.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/CodeGen/MachineInstrBuilder.h"
30 #include "llvm/CodeGen/MachineOperand.h"
31 #include "llvm/CodeGen/TargetSubtargetInfo.h"
32 #include "llvm/IR/DebugLoc.h"
33 #include "llvm/MC/MCInstrDesc.h"
34 #include "llvm/Pass.h"
35 #include "llvm/Support/CodeGen.h"
36 #include "llvm/Support/MathExtras.h"
37 #include "llvm/Target/TargetMachine.h"
38 #include <cassert>
39 #include <cstdint>
40 #include <iterator>
41 #include <limits>
42 #include <utility>
43 
44 using namespace llvm;
45 
46 #define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
47 
48 namespace {
49 
50 class AArch64ExpandPseudo : public MachineFunctionPass {
51 public:
52   const AArch64InstrInfo *TII;
53 
54   static char ID;
55 
AArch64ExpandPseudo()56   AArch64ExpandPseudo() : MachineFunctionPass(ID) {
57     initializeAArch64ExpandPseudoPass(*PassRegistry::getPassRegistry());
58   }
59 
60   bool runOnMachineFunction(MachineFunction &Fn) override;
61 
getPassName() const62   StringRef getPassName() const override { return AARCH64_EXPAND_PSEUDO_NAME; }
63 
64 private:
65   bool expandMBB(MachineBasicBlock &MBB);
66   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
67                 MachineBasicBlock::iterator &NextMBBI);
68   bool expandMOVImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
69                     unsigned BitSize);
70 
71   bool expand_DestructiveOp(MachineInstr &MI, MachineBasicBlock &MBB,
72                             MachineBasicBlock::iterator MBBI);
73   bool expandCMP_SWAP(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
74                       unsigned LdarOp, unsigned StlrOp, unsigned CmpOp,
75                       unsigned ExtendImm, unsigned ZeroReg,
76                       MachineBasicBlock::iterator &NextMBBI);
77   bool expandCMP_SWAP_128(MachineBasicBlock &MBB,
78                           MachineBasicBlock::iterator MBBI,
79                           MachineBasicBlock::iterator &NextMBBI);
80   bool expandSetTagLoop(MachineBasicBlock &MBB,
81                         MachineBasicBlock::iterator MBBI,
82                         MachineBasicBlock::iterator &NextMBBI);
83   bool expandSVESpillFill(MachineBasicBlock &MBB,
84                           MachineBasicBlock::iterator MBBI, unsigned Opc,
85                           unsigned N);
86   bool expandCALL_RVMARKER(MachineBasicBlock &MBB,
87                            MachineBasicBlock::iterator MBBI);
88 };
89 
90 } // end anonymous namespace
91 
92 char AArch64ExpandPseudo::ID = 0;
93 
94 INITIALIZE_PASS(AArch64ExpandPseudo, "aarch64-expand-pseudo",
95                 AARCH64_EXPAND_PSEUDO_NAME, false, false)
96 
97 /// Transfer implicit operands on the pseudo instruction to the
98 /// instructions created from the expansion.
transferImpOps(MachineInstr & OldMI,MachineInstrBuilder & UseMI,MachineInstrBuilder & DefMI)99 static void transferImpOps(MachineInstr &OldMI, MachineInstrBuilder &UseMI,
100                            MachineInstrBuilder &DefMI) {
101   const MCInstrDesc &Desc = OldMI.getDesc();
102   for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands(); i != e;
103        ++i) {
104     const MachineOperand &MO = OldMI.getOperand(i);
105     assert(MO.isReg() && MO.getReg());
106     if (MO.isUse())
107       UseMI.add(MO);
108     else
109       DefMI.add(MO);
110   }
111 }
112 
113 /// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more
114 /// real move-immediate instructions to synthesize the immediate.
expandMOVImm(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned BitSize)115 bool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock &MBB,
116                                        MachineBasicBlock::iterator MBBI,
117                                        unsigned BitSize) {
118   MachineInstr &MI = *MBBI;
119   Register DstReg = MI.getOperand(0).getReg();
120   uint64_t RenamableState =
121       MI.getOperand(0).isRenamable() ? RegState::Renamable : 0;
122   uint64_t Imm = MI.getOperand(1).getImm();
123 
124   if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
125     // Useless def, and we don't want to risk creating an invalid ORR (which
126     // would really write to sp).
127     MI.eraseFromParent();
128     return true;
129   }
130 
131   SmallVector<AArch64_IMM::ImmInsnModel, 4> Insn;
132   AArch64_IMM::expandMOVImm(Imm, BitSize, Insn);
133   assert(Insn.size() != 0);
134 
135   SmallVector<MachineInstrBuilder, 4> MIBS;
136   for (auto I = Insn.begin(), E = Insn.end(); I != E; ++I) {
137     bool LastItem = std::next(I) == E;
138     switch (I->Opcode)
139     {
140     default: llvm_unreachable("unhandled!"); break;
141 
142     case AArch64::ORRWri:
143     case AArch64::ORRXri:
144       MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
145         .add(MI.getOperand(0))
146         .addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
147         .addImm(I->Op2));
148       break;
149     case AArch64::MOVNWi:
150     case AArch64::MOVNXi:
151     case AArch64::MOVZWi:
152     case AArch64::MOVZXi: {
153       bool DstIsDead = MI.getOperand(0).isDead();
154       MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
155         .addReg(DstReg, RegState::Define |
156                 getDeadRegState(DstIsDead && LastItem) |
157                 RenamableState)
158         .addImm(I->Op1)
159         .addImm(I->Op2));
160       } break;
161     case AArch64::MOVKWi:
162     case AArch64::MOVKXi: {
163       Register DstReg = MI.getOperand(0).getReg();
164       bool DstIsDead = MI.getOperand(0).isDead();
165       MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
166         .addReg(DstReg,
167                 RegState::Define |
168                 getDeadRegState(DstIsDead && LastItem) |
169                 RenamableState)
170         .addReg(DstReg)
171         .addImm(I->Op1)
172         .addImm(I->Op2));
173       } break;
174     }
175   }
176   transferImpOps(MI, MIBS.front(), MIBS.back());
177   MI.eraseFromParent();
178   return true;
179 }
180 
expandCMP_SWAP(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned LdarOp,unsigned StlrOp,unsigned CmpOp,unsigned ExtendImm,unsigned ZeroReg,MachineBasicBlock::iterator & NextMBBI)181 bool AArch64ExpandPseudo::expandCMP_SWAP(
182     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned LdarOp,
183     unsigned StlrOp, unsigned CmpOp, unsigned ExtendImm, unsigned ZeroReg,
184     MachineBasicBlock::iterator &NextMBBI) {
185   MachineInstr &MI = *MBBI;
186   DebugLoc DL = MI.getDebugLoc();
187   const MachineOperand &Dest = MI.getOperand(0);
188   Register StatusReg = MI.getOperand(1).getReg();
189   bool StatusDead = MI.getOperand(1).isDead();
190   // Duplicating undef operands into 2 instructions does not guarantee the same
191   // value on both; However undef should be replaced by xzr anyway.
192   assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
193   Register AddrReg = MI.getOperand(2).getReg();
194   Register DesiredReg = MI.getOperand(3).getReg();
195   Register NewReg = MI.getOperand(4).getReg();
196 
197   MachineFunction *MF = MBB.getParent();
198   auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
199   auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
200   auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
201 
202   MF->insert(++MBB.getIterator(), LoadCmpBB);
203   MF->insert(++LoadCmpBB->getIterator(), StoreBB);
204   MF->insert(++StoreBB->getIterator(), DoneBB);
205 
206   // .Lloadcmp:
207   //     mov wStatus, 0
208   //     ldaxr xDest, [xAddr]
209   //     cmp xDest, xDesired
210   //     b.ne .Ldone
211   if (!StatusDead)
212     BuildMI(LoadCmpBB, DL, TII->get(AArch64::MOVZWi), StatusReg)
213       .addImm(0).addImm(0);
214   BuildMI(LoadCmpBB, DL, TII->get(LdarOp), Dest.getReg())
215       .addReg(AddrReg);
216   BuildMI(LoadCmpBB, DL, TII->get(CmpOp), ZeroReg)
217       .addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
218       .addReg(DesiredReg)
219       .addImm(ExtendImm);
220   BuildMI(LoadCmpBB, DL, TII->get(AArch64::Bcc))
221       .addImm(AArch64CC::NE)
222       .addMBB(DoneBB)
223       .addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
224   LoadCmpBB->addSuccessor(DoneBB);
225   LoadCmpBB->addSuccessor(StoreBB);
226 
227   // .Lstore:
228   //     stlxr wStatus, xNew, [xAddr]
229   //     cbnz wStatus, .Lloadcmp
230   BuildMI(StoreBB, DL, TII->get(StlrOp), StatusReg)
231       .addReg(NewReg)
232       .addReg(AddrReg);
233   BuildMI(StoreBB, DL, TII->get(AArch64::CBNZW))
234       .addReg(StatusReg, getKillRegState(StatusDead))
235       .addMBB(LoadCmpBB);
236   StoreBB->addSuccessor(LoadCmpBB);
237   StoreBB->addSuccessor(DoneBB);
238 
239   DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
240   DoneBB->transferSuccessors(&MBB);
241 
242   MBB.addSuccessor(LoadCmpBB);
243 
244   NextMBBI = MBB.end();
245   MI.eraseFromParent();
246 
247   // Recompute livein lists.
248   LivePhysRegs LiveRegs;
249   computeAndAddLiveIns(LiveRegs, *DoneBB);
250   computeAndAddLiveIns(LiveRegs, *StoreBB);
251   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
252   // Do an extra pass around the loop to get loop carried registers right.
253   StoreBB->clearLiveIns();
254   computeAndAddLiveIns(LiveRegs, *StoreBB);
255   LoadCmpBB->clearLiveIns();
256   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
257 
258   return true;
259 }
260 
expandCMP_SWAP_128(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)261 bool AArch64ExpandPseudo::expandCMP_SWAP_128(
262     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
263     MachineBasicBlock::iterator &NextMBBI) {
264   MachineInstr &MI = *MBBI;
265   DebugLoc DL = MI.getDebugLoc();
266   MachineOperand &DestLo = MI.getOperand(0);
267   MachineOperand &DestHi = MI.getOperand(1);
268   Register StatusReg = MI.getOperand(2).getReg();
269   bool StatusDead = MI.getOperand(2).isDead();
270   // Duplicating undef operands into 2 instructions does not guarantee the same
271   // value on both; However undef should be replaced by xzr anyway.
272   assert(!MI.getOperand(3).isUndef() && "cannot handle undef");
273   Register AddrReg = MI.getOperand(3).getReg();
274   Register DesiredLoReg = MI.getOperand(4).getReg();
275   Register DesiredHiReg = MI.getOperand(5).getReg();
276   Register NewLoReg = MI.getOperand(6).getReg();
277   Register NewHiReg = MI.getOperand(7).getReg();
278 
279   MachineFunction *MF = MBB.getParent();
280   auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
281   auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
282   auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
283 
284   MF->insert(++MBB.getIterator(), LoadCmpBB);
285   MF->insert(++LoadCmpBB->getIterator(), StoreBB);
286   MF->insert(++StoreBB->getIterator(), DoneBB);
287 
288   // .Lloadcmp:
289   //     ldaxp xDestLo, xDestHi, [xAddr]
290   //     cmp xDestLo, xDesiredLo
291   //     sbcs xDestHi, xDesiredHi
292   //     b.ne .Ldone
293   BuildMI(LoadCmpBB, DL, TII->get(AArch64::LDAXPX))
294       .addReg(DestLo.getReg(), RegState::Define)
295       .addReg(DestHi.getReg(), RegState::Define)
296       .addReg(AddrReg);
297   BuildMI(LoadCmpBB, DL, TII->get(AArch64::SUBSXrs), AArch64::XZR)
298       .addReg(DestLo.getReg(), getKillRegState(DestLo.isDead()))
299       .addReg(DesiredLoReg)
300       .addImm(0);
301   BuildMI(LoadCmpBB, DL, TII->get(AArch64::CSINCWr), StatusReg)
302     .addUse(AArch64::WZR)
303     .addUse(AArch64::WZR)
304     .addImm(AArch64CC::EQ);
305   BuildMI(LoadCmpBB, DL, TII->get(AArch64::SUBSXrs), AArch64::XZR)
306       .addReg(DestHi.getReg(), getKillRegState(DestHi.isDead()))
307       .addReg(DesiredHiReg)
308       .addImm(0);
309   BuildMI(LoadCmpBB, DL, TII->get(AArch64::CSINCWr), StatusReg)
310       .addUse(StatusReg, RegState::Kill)
311       .addUse(StatusReg, RegState::Kill)
312       .addImm(AArch64CC::EQ);
313   BuildMI(LoadCmpBB, DL, TII->get(AArch64::CBNZW))
314       .addUse(StatusReg, getKillRegState(StatusDead))
315       .addMBB(DoneBB);
316   LoadCmpBB->addSuccessor(DoneBB);
317   LoadCmpBB->addSuccessor(StoreBB);
318 
319   // .Lstore:
320   //     stlxp wStatus, xNewLo, xNewHi, [xAddr]
321   //     cbnz wStatus, .Lloadcmp
322   BuildMI(StoreBB, DL, TII->get(AArch64::STLXPX), StatusReg)
323       .addReg(NewLoReg)
324       .addReg(NewHiReg)
325       .addReg(AddrReg);
326   BuildMI(StoreBB, DL, TII->get(AArch64::CBNZW))
327       .addReg(StatusReg, getKillRegState(StatusDead))
328       .addMBB(LoadCmpBB);
329   StoreBB->addSuccessor(LoadCmpBB);
330   StoreBB->addSuccessor(DoneBB);
331 
332   DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
333   DoneBB->transferSuccessors(&MBB);
334 
335   MBB.addSuccessor(LoadCmpBB);
336 
337   NextMBBI = MBB.end();
338   MI.eraseFromParent();
339 
340   // Recompute liveness bottom up.
341   LivePhysRegs LiveRegs;
342   computeAndAddLiveIns(LiveRegs, *DoneBB);
343   computeAndAddLiveIns(LiveRegs, *StoreBB);
344   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
345   // Do an extra pass in the loop to get the loop carried dependencies right.
346   StoreBB->clearLiveIns();
347   computeAndAddLiveIns(LiveRegs, *StoreBB);
348   LoadCmpBB->clearLiveIns();
349   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
350 
351   return true;
352 }
353 
354 /// \brief Expand Pseudos to Instructions with destructive operands.
355 ///
356 /// This mechanism uses MOVPRFX instructions for zeroing the false lanes
357 /// or for fixing relaxed register allocation conditions to comply with
358 /// the instructions register constraints. The latter case may be cheaper
359 /// than setting the register constraints in the register allocator,
360 /// since that will insert regular MOV instructions rather than MOVPRFX.
361 ///
362 /// Example (after register allocation):
363 ///
364 ///   FSUB_ZPZZ_ZERO_B Z0, Pg, Z1, Z0
365 ///
366 /// * The Pseudo FSUB_ZPZZ_ZERO_B maps to FSUB_ZPmZ_B.
367 /// * We cannot map directly to FSUB_ZPmZ_B because the register
368 ///   constraints of the instruction are not met.
369 /// * Also the _ZERO specifies the false lanes need to be zeroed.
370 ///
371 /// We first try to see if the destructive operand == result operand,
372 /// if not, we try to swap the operands, e.g.
373 ///
374 ///   FSUB_ZPmZ_B  Z0, Pg/m, Z0, Z1
375 ///
376 /// But because FSUB_ZPmZ is not commutative, this is semantically
377 /// different, so we need a reverse instruction:
378 ///
379 ///   FSUBR_ZPmZ_B  Z0, Pg/m, Z0, Z1
380 ///
381 /// Then we implement the zeroing of the false lanes of Z0 by adding
382 /// a zeroing MOVPRFX instruction:
383 ///
384 ///   MOVPRFX_ZPzZ_B Z0, Pg/z, Z0
385 ///   FSUBR_ZPmZ_B   Z0, Pg/m, Z0, Z1
386 ///
387 /// Note that this can only be done for _ZERO or _UNDEF variants where
388 /// we can guarantee the false lanes to be zeroed (by implementing this)
389 /// or that they are undef (don't care / not used), otherwise the
390 /// swapping of operands is illegal because the operation is not
391 /// (or cannot be emulated to be) fully commutative.
expand_DestructiveOp(MachineInstr & MI,MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)392 bool AArch64ExpandPseudo::expand_DestructiveOp(
393                             MachineInstr &MI,
394                             MachineBasicBlock &MBB,
395                             MachineBasicBlock::iterator MBBI) {
396   unsigned Opcode = AArch64::getSVEPseudoMap(MI.getOpcode());
397   uint64_t DType = TII->get(Opcode).TSFlags & AArch64::DestructiveInstTypeMask;
398   uint64_t FalseLanes = MI.getDesc().TSFlags & AArch64::FalseLanesMask;
399   bool FalseZero = FalseLanes == AArch64::FalseLanesZero;
400 
401   unsigned DstReg = MI.getOperand(0).getReg();
402   bool DstIsDead = MI.getOperand(0).isDead();
403 
404   if (DType == AArch64::DestructiveBinary)
405     assert(DstReg != MI.getOperand(3).getReg());
406 
407   bool UseRev = false;
408   unsigned PredIdx, DOPIdx, SrcIdx;
409   switch (DType) {
410   case AArch64::DestructiveBinaryComm:
411   case AArch64::DestructiveBinaryCommWithRev:
412     if (DstReg == MI.getOperand(3).getReg()) {
413       // FSUB Zd, Pg, Zs1, Zd  ==> FSUBR   Zd, Pg/m, Zd, Zs1
414       std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
415       UseRev = true;
416       break;
417     }
418     LLVM_FALLTHROUGH;
419   case AArch64::DestructiveBinary:
420   case AArch64::DestructiveBinaryImm:
421     std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
422    break;
423   default:
424     llvm_unreachable("Unsupported Destructive Operand type");
425   }
426 
427 #ifndef NDEBUG
428   // MOVPRFX can only be used if the destination operand
429   // is the destructive operand, not as any other operand,
430   // so the Destructive Operand must be unique.
431   bool DOPRegIsUnique = false;
432   switch (DType) {
433   case AArch64::DestructiveBinaryComm:
434   case AArch64::DestructiveBinaryCommWithRev:
435     DOPRegIsUnique =
436       DstReg != MI.getOperand(DOPIdx).getReg() ||
437       MI.getOperand(DOPIdx).getReg() != MI.getOperand(SrcIdx).getReg();
438     break;
439   case AArch64::DestructiveBinaryImm:
440     DOPRegIsUnique = true;
441     break;
442   }
443 #endif
444 
445   // Resolve the reverse opcode
446   if (UseRev) {
447     int NewOpcode;
448     // e.g. DIV -> DIVR
449     if ((NewOpcode = AArch64::getSVERevInstr(Opcode)) != -1)
450       Opcode = NewOpcode;
451     // e.g. DIVR -> DIV
452     else if ((NewOpcode = AArch64::getSVENonRevInstr(Opcode)) != -1)
453       Opcode = NewOpcode;
454   }
455 
456   // Get the right MOVPRFX
457   uint64_t ElementSize = TII->getElementSizeForOpcode(Opcode);
458   unsigned MovPrfx, MovPrfxZero;
459   switch (ElementSize) {
460   case AArch64::ElementSizeNone:
461   case AArch64::ElementSizeB:
462     MovPrfx = AArch64::MOVPRFX_ZZ;
463     MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
464     break;
465   case AArch64::ElementSizeH:
466     MovPrfx = AArch64::MOVPRFX_ZZ;
467     MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
468     break;
469   case AArch64::ElementSizeS:
470     MovPrfx = AArch64::MOVPRFX_ZZ;
471     MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
472     break;
473   case AArch64::ElementSizeD:
474     MovPrfx = AArch64::MOVPRFX_ZZ;
475     MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
476     break;
477   default:
478     llvm_unreachable("Unsupported ElementSize");
479   }
480 
481   //
482   // Create the destructive operation (if required)
483   //
484   MachineInstrBuilder PRFX, DOP;
485   if (FalseZero) {
486 #ifndef NDEBUG
487     assert(DOPRegIsUnique && "The destructive operand should be unique");
488 #endif
489     assert(ElementSize != AArch64::ElementSizeNone &&
490            "This instruction is unpredicated");
491 
492     // Merge source operand into destination register
493     PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfxZero))
494                .addReg(DstReg, RegState::Define)
495                .addReg(MI.getOperand(PredIdx).getReg())
496                .addReg(MI.getOperand(DOPIdx).getReg());
497 
498     // After the movprfx, the destructive operand is same as Dst
499     DOPIdx = 0;
500   } else if (DstReg != MI.getOperand(DOPIdx).getReg()) {
501 #ifndef NDEBUG
502     assert(DOPRegIsUnique && "The destructive operand should be unique");
503 #endif
504     PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfx))
505                .addReg(DstReg, RegState::Define)
506                .addReg(MI.getOperand(DOPIdx).getReg());
507     DOPIdx = 0;
508   }
509 
510   //
511   // Create the destructive operation
512   //
513   DOP = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode))
514     .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead));
515 
516   switch (DType) {
517   case AArch64::DestructiveBinaryImm:
518   case AArch64::DestructiveBinaryComm:
519   case AArch64::DestructiveBinaryCommWithRev:
520     DOP.add(MI.getOperand(PredIdx))
521        .addReg(MI.getOperand(DOPIdx).getReg(), RegState::Kill)
522        .add(MI.getOperand(SrcIdx));
523     break;
524   }
525 
526   if (PRFX) {
527     finalizeBundle(MBB, PRFX->getIterator(), MBBI->getIterator());
528     transferImpOps(MI, PRFX, DOP);
529   } else
530     transferImpOps(MI, DOP, DOP);
531 
532   MI.eraseFromParent();
533   return true;
534 }
535 
expandSetTagLoop(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)536 bool AArch64ExpandPseudo::expandSetTagLoop(
537     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
538     MachineBasicBlock::iterator &NextMBBI) {
539   MachineInstr &MI = *MBBI;
540   DebugLoc DL = MI.getDebugLoc();
541   Register SizeReg = MI.getOperand(0).getReg();
542   Register AddressReg = MI.getOperand(1).getReg();
543 
544   MachineFunction *MF = MBB.getParent();
545 
546   bool ZeroData = MI.getOpcode() == AArch64::STZGloop_wback;
547   const unsigned OpCode1 =
548       ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
549   const unsigned OpCode2 =
550       ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
551 
552   unsigned Size = MI.getOperand(2).getImm();
553   assert(Size > 0 && Size % 16 == 0);
554   if (Size % (16 * 2) != 0) {
555     BuildMI(MBB, MBBI, DL, TII->get(OpCode1), AddressReg)
556         .addReg(AddressReg)
557         .addReg(AddressReg)
558         .addImm(1);
559     Size -= 16;
560   }
561   MachineBasicBlock::iterator I =
562       BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), SizeReg)
563           .addImm(Size);
564   expandMOVImm(MBB, I, 64);
565 
566   auto LoopBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
567   auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
568 
569   MF->insert(++MBB.getIterator(), LoopBB);
570   MF->insert(++LoopBB->getIterator(), DoneBB);
571 
572   BuildMI(LoopBB, DL, TII->get(OpCode2))
573       .addDef(AddressReg)
574       .addReg(AddressReg)
575       .addReg(AddressReg)
576       .addImm(2)
577       .cloneMemRefs(MI)
578       .setMIFlags(MI.getFlags());
579   BuildMI(LoopBB, DL, TII->get(AArch64::SUBXri))
580       .addDef(SizeReg)
581       .addReg(SizeReg)
582       .addImm(16 * 2)
583       .addImm(0);
584   BuildMI(LoopBB, DL, TII->get(AArch64::CBNZX)).addUse(SizeReg).addMBB(LoopBB);
585 
586   LoopBB->addSuccessor(LoopBB);
587   LoopBB->addSuccessor(DoneBB);
588 
589   DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
590   DoneBB->transferSuccessors(&MBB);
591 
592   MBB.addSuccessor(LoopBB);
593 
594   NextMBBI = MBB.end();
595   MI.eraseFromParent();
596   // Recompute liveness bottom up.
597   LivePhysRegs LiveRegs;
598   computeAndAddLiveIns(LiveRegs, *DoneBB);
599   computeAndAddLiveIns(LiveRegs, *LoopBB);
600   // Do an extra pass in the loop to get the loop carried dependencies right.
601   // FIXME: is this necessary?
602   LoopBB->clearLiveIns();
603   computeAndAddLiveIns(LiveRegs, *LoopBB);
604   DoneBB->clearLiveIns();
605   computeAndAddLiveIns(LiveRegs, *DoneBB);
606 
607   return true;
608 }
609 
expandSVESpillFill(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned Opc,unsigned N)610 bool AArch64ExpandPseudo::expandSVESpillFill(MachineBasicBlock &MBB,
611                                              MachineBasicBlock::iterator MBBI,
612                                              unsigned Opc, unsigned N) {
613   const TargetRegisterInfo *TRI =
614       MBB.getParent()->getSubtarget().getRegisterInfo();
615   MachineInstr &MI = *MBBI;
616   for (unsigned Offset = 0; Offset < N; ++Offset) {
617     int ImmOffset = MI.getOperand(2).getImm() + Offset;
618     bool Kill = (Offset + 1 == N) ? MI.getOperand(1).isKill() : false;
619     assert(ImmOffset >= -256 && ImmOffset < 256 &&
620            "Immediate spill offset out of range");
621     BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc))
622         .addReg(
623             TRI->getSubReg(MI.getOperand(0).getReg(), AArch64::zsub0 + Offset),
624             Opc == AArch64::LDR_ZXI ? RegState::Define : 0)
625         .addReg(MI.getOperand(1).getReg(), getKillRegState(Kill))
626         .addImm(ImmOffset);
627   }
628   MI.eraseFromParent();
629   return true;
630 }
631 
expandCALL_RVMARKER(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)632 bool AArch64ExpandPseudo::expandCALL_RVMARKER(
633     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
634   // Expand CALL_RVMARKER pseudo to a branch, followed by the special `mov x29,
635   // x29` marker. Mark the sequence as bundle, to avoid passes moving other code
636   // in between.
637   MachineInstr &MI = *MBBI;
638 
639   MachineInstr *OriginalCall;
640   MachineOperand &CallTarget = MI.getOperand(0);
641   assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
642          "invalid operand for regular call");
643   unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
644   OriginalCall = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)).getInstr();
645   OriginalCall->addOperand(CallTarget);
646 
647   unsigned RegMaskStartIdx = 1;
648   // Skip register arguments. Those are added during ISel, but are not
649   // needed for the concrete branch.
650   while (!MI.getOperand(RegMaskStartIdx).isRegMask()) {
651     assert(MI.getOperand(RegMaskStartIdx).isReg() &&
652            "should only skip register operands");
653     RegMaskStartIdx++;
654   }
655   for (; RegMaskStartIdx < MI.getNumOperands(); ++RegMaskStartIdx)
656     OriginalCall->addOperand(MI.getOperand(RegMaskStartIdx));
657 
658   auto *Marker = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXrs))
659                      .addReg(AArch64::FP, RegState::Define)
660                      .addReg(AArch64::XZR)
661                      .addReg(AArch64::FP)
662                      .addImm(0)
663                      .getInstr();
664   if (MI.shouldUpdateCallSiteInfo())
665     MBB.getParent()->moveCallSiteInfo(&MI, Marker);
666   MI.eraseFromParent();
667   finalizeBundle(MBB, OriginalCall->getIterator(),
668                  std::next(Marker->getIterator()));
669   return true;
670 }
671 
672 /// If MBBI references a pseudo instruction that should be expanded here,
673 /// do the expansion and return true.  Otherwise return false.
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)674 bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
675                                    MachineBasicBlock::iterator MBBI,
676                                    MachineBasicBlock::iterator &NextMBBI) {
677   MachineInstr &MI = *MBBI;
678   unsigned Opcode = MI.getOpcode();
679 
680   // Check if we can expand the destructive op
681   int OrigInstr = AArch64::getSVEPseudoMap(MI.getOpcode());
682   if (OrigInstr != -1) {
683     auto &Orig = TII->get(OrigInstr);
684     if ((Orig.TSFlags & AArch64::DestructiveInstTypeMask)
685            != AArch64::NotDestructive) {
686       return expand_DestructiveOp(MI, MBB, MBBI);
687     }
688   }
689 
690   switch (Opcode) {
691   default:
692     break;
693 
694   case AArch64::BSPv8i8:
695   case AArch64::BSPv16i8: {
696     Register DstReg = MI.getOperand(0).getReg();
697     if (DstReg == MI.getOperand(3).getReg()) {
698       // Expand to BIT
699       BuildMI(MBB, MBBI, MI.getDebugLoc(),
700               TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
701                                                   : AArch64::BITv16i8))
702           .add(MI.getOperand(0))
703           .add(MI.getOperand(3))
704           .add(MI.getOperand(2))
705           .add(MI.getOperand(1));
706     } else if (DstReg == MI.getOperand(2).getReg()) {
707       // Expand to BIF
708       BuildMI(MBB, MBBI, MI.getDebugLoc(),
709               TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
710                                                   : AArch64::BIFv16i8))
711           .add(MI.getOperand(0))
712           .add(MI.getOperand(2))
713           .add(MI.getOperand(3))
714           .add(MI.getOperand(1));
715     } else {
716       // Expand to BSL, use additional move if required
717       if (DstReg == MI.getOperand(1).getReg()) {
718         BuildMI(MBB, MBBI, MI.getDebugLoc(),
719                 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
720                                                     : AArch64::BSLv16i8))
721             .add(MI.getOperand(0))
722             .add(MI.getOperand(1))
723             .add(MI.getOperand(2))
724             .add(MI.getOperand(3));
725       } else {
726         BuildMI(MBB, MBBI, MI.getDebugLoc(),
727                 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
728                                                     : AArch64::ORRv16i8))
729             .addReg(DstReg,
730                     RegState::Define |
731                         getRenamableRegState(MI.getOperand(0).isRenamable()))
732             .add(MI.getOperand(1))
733             .add(MI.getOperand(1));
734         BuildMI(MBB, MBBI, MI.getDebugLoc(),
735                 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
736                                                     : AArch64::BSLv16i8))
737             .add(MI.getOperand(0))
738             .addReg(DstReg,
739                     RegState::Kill |
740                         getRenamableRegState(MI.getOperand(0).isRenamable()))
741             .add(MI.getOperand(2))
742             .add(MI.getOperand(3));
743       }
744     }
745     MI.eraseFromParent();
746     return true;
747   }
748 
749   case AArch64::ADDWrr:
750   case AArch64::SUBWrr:
751   case AArch64::ADDXrr:
752   case AArch64::SUBXrr:
753   case AArch64::ADDSWrr:
754   case AArch64::SUBSWrr:
755   case AArch64::ADDSXrr:
756   case AArch64::SUBSXrr:
757   case AArch64::ANDWrr:
758   case AArch64::ANDXrr:
759   case AArch64::BICWrr:
760   case AArch64::BICXrr:
761   case AArch64::ANDSWrr:
762   case AArch64::ANDSXrr:
763   case AArch64::BICSWrr:
764   case AArch64::BICSXrr:
765   case AArch64::EONWrr:
766   case AArch64::EONXrr:
767   case AArch64::EORWrr:
768   case AArch64::EORXrr:
769   case AArch64::ORNWrr:
770   case AArch64::ORNXrr:
771   case AArch64::ORRWrr:
772   case AArch64::ORRXrr: {
773     unsigned Opcode;
774     switch (MI.getOpcode()) {
775     default:
776       return false;
777     case AArch64::ADDWrr:      Opcode = AArch64::ADDWrs; break;
778     case AArch64::SUBWrr:      Opcode = AArch64::SUBWrs; break;
779     case AArch64::ADDXrr:      Opcode = AArch64::ADDXrs; break;
780     case AArch64::SUBXrr:      Opcode = AArch64::SUBXrs; break;
781     case AArch64::ADDSWrr:     Opcode = AArch64::ADDSWrs; break;
782     case AArch64::SUBSWrr:     Opcode = AArch64::SUBSWrs; break;
783     case AArch64::ADDSXrr:     Opcode = AArch64::ADDSXrs; break;
784     case AArch64::SUBSXrr:     Opcode = AArch64::SUBSXrs; break;
785     case AArch64::ANDWrr:      Opcode = AArch64::ANDWrs; break;
786     case AArch64::ANDXrr:      Opcode = AArch64::ANDXrs; break;
787     case AArch64::BICWrr:      Opcode = AArch64::BICWrs; break;
788     case AArch64::BICXrr:      Opcode = AArch64::BICXrs; break;
789     case AArch64::ANDSWrr:     Opcode = AArch64::ANDSWrs; break;
790     case AArch64::ANDSXrr:     Opcode = AArch64::ANDSXrs; break;
791     case AArch64::BICSWrr:     Opcode = AArch64::BICSWrs; break;
792     case AArch64::BICSXrr:     Opcode = AArch64::BICSXrs; break;
793     case AArch64::EONWrr:      Opcode = AArch64::EONWrs; break;
794     case AArch64::EONXrr:      Opcode = AArch64::EONXrs; break;
795     case AArch64::EORWrr:      Opcode = AArch64::EORWrs; break;
796     case AArch64::EORXrr:      Opcode = AArch64::EORXrs; break;
797     case AArch64::ORNWrr:      Opcode = AArch64::ORNWrs; break;
798     case AArch64::ORNXrr:      Opcode = AArch64::ORNXrs; break;
799     case AArch64::ORRWrr:      Opcode = AArch64::ORRWrs; break;
800     case AArch64::ORRXrr:      Opcode = AArch64::ORRXrs; break;
801     }
802     MachineInstrBuilder MIB1 =
803         BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode),
804                 MI.getOperand(0).getReg())
805             .add(MI.getOperand(1))
806             .add(MI.getOperand(2))
807             .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
808     transferImpOps(MI, MIB1, MIB1);
809     MI.eraseFromParent();
810     return true;
811   }
812 
813   case AArch64::LOADgot: {
814     MachineFunction *MF = MBB.getParent();
815     Register DstReg = MI.getOperand(0).getReg();
816     const MachineOperand &MO1 = MI.getOperand(1);
817     unsigned Flags = MO1.getTargetFlags();
818 
819     if (MF->getTarget().getCodeModel() == CodeModel::Tiny) {
820       // Tiny codemodel expand to LDR
821       MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
822                                         TII->get(AArch64::LDRXl), DstReg);
823 
824       if (MO1.isGlobal()) {
825         MIB.addGlobalAddress(MO1.getGlobal(), 0, Flags);
826       } else if (MO1.isSymbol()) {
827         MIB.addExternalSymbol(MO1.getSymbolName(), Flags);
828       } else {
829         assert(MO1.isCPI() &&
830                "Only expect globals, externalsymbols, or constant pools");
831         MIB.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(), Flags);
832       }
833     } else {
834       // Small codemodel expand into ADRP + LDR.
835       MachineFunction &MF = *MI.getParent()->getParent();
836       DebugLoc DL = MI.getDebugLoc();
837       MachineInstrBuilder MIB1 =
838           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
839 
840       MachineInstrBuilder MIB2;
841       if (MF.getSubtarget<AArch64Subtarget>().isTargetILP32()) {
842         auto TRI = MBB.getParent()->getSubtarget().getRegisterInfo();
843         unsigned Reg32 = TRI->getSubReg(DstReg, AArch64::sub_32);
844         unsigned DstFlags = MI.getOperand(0).getTargetFlags();
845         MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRWui))
846                    .addDef(Reg32)
847                    .addReg(DstReg, RegState::Kill)
848                    .addReg(DstReg, DstFlags | RegState::Implicit);
849       } else {
850         unsigned DstReg = MI.getOperand(0).getReg();
851         MIB2 = BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
852                    .add(MI.getOperand(0))
853                    .addUse(DstReg, RegState::Kill);
854       }
855 
856       if (MO1.isGlobal()) {
857         MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
858         MIB2.addGlobalAddress(MO1.getGlobal(), 0,
859                               Flags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
860       } else if (MO1.isSymbol()) {
861         MIB1.addExternalSymbol(MO1.getSymbolName(), Flags | AArch64II::MO_PAGE);
862         MIB2.addExternalSymbol(MO1.getSymbolName(), Flags |
863                                                         AArch64II::MO_PAGEOFF |
864                                                         AArch64II::MO_NC);
865       } else {
866         assert(MO1.isCPI() &&
867                "Only expect globals, externalsymbols, or constant pools");
868         MIB1.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
869                                   Flags | AArch64II::MO_PAGE);
870         MIB2.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
871                                   Flags | AArch64II::MO_PAGEOFF |
872                                       AArch64II::MO_NC);
873       }
874 
875       transferImpOps(MI, MIB1, MIB2);
876     }
877     MI.eraseFromParent();
878     return true;
879   }
880 
881   case AArch64::MOVaddr:
882   case AArch64::MOVaddrJT:
883   case AArch64::MOVaddrCP:
884   case AArch64::MOVaddrBA:
885   case AArch64::MOVaddrTLS:
886   case AArch64::MOVaddrEXT: {
887     // Expand into ADRP + ADD.
888     Register DstReg = MI.getOperand(0).getReg();
889     MachineInstrBuilder MIB1 =
890         BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
891             .add(MI.getOperand(1));
892 
893     if (MI.getOperand(1).getTargetFlags() & AArch64II::MO_TAGGED) {
894       // MO_TAGGED on the page indicates a tagged address. Set the tag now.
895       // We do so by creating a MOVK that sets bits 48-63 of the register to
896       // (global address + 0x100000000 - PC) >> 48. This assumes that we're in
897       // the small code model so we can assume a binary size of <= 4GB, which
898       // makes the untagged PC relative offset positive. The binary must also be
899       // loaded into address range [0, 2^48). Both of these properties need to
900       // be ensured at runtime when using tagged addresses.
901       auto Tag = MI.getOperand(1);
902       Tag.setTargetFlags(AArch64II::MO_PREL | AArch64II::MO_G3);
903       Tag.setOffset(0x100000000);
904       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi), DstReg)
905           .addReg(DstReg)
906           .add(Tag)
907           .addImm(48);
908     }
909 
910     MachineInstrBuilder MIB2 =
911         BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
912             .add(MI.getOperand(0))
913             .addReg(DstReg)
914             .add(MI.getOperand(2))
915             .addImm(0);
916 
917     transferImpOps(MI, MIB1, MIB2);
918     MI.eraseFromParent();
919     return true;
920   }
921   case AArch64::ADDlowTLS:
922     // Produce a plain ADD
923     BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
924         .add(MI.getOperand(0))
925         .add(MI.getOperand(1))
926         .add(MI.getOperand(2))
927         .addImm(0);
928     MI.eraseFromParent();
929     return true;
930 
931   case AArch64::MOVbaseTLS: {
932     Register DstReg = MI.getOperand(0).getReg();
933     auto SysReg = AArch64SysReg::TPIDR_EL0;
934     MachineFunction *MF = MBB.getParent();
935     if (MF->getSubtarget<AArch64Subtarget>().useEL3ForTP())
936       SysReg = AArch64SysReg::TPIDR_EL3;
937     else if (MF->getSubtarget<AArch64Subtarget>().useEL2ForTP())
938       SysReg = AArch64SysReg::TPIDR_EL2;
939     else if (MF->getSubtarget<AArch64Subtarget>().useEL1ForTP())
940       SysReg = AArch64SysReg::TPIDR_EL1;
941     BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MRS), DstReg)
942         .addImm(SysReg);
943     MI.eraseFromParent();
944     return true;
945   }
946 
947   case AArch64::MOVi32imm:
948     return expandMOVImm(MBB, MBBI, 32);
949   case AArch64::MOVi64imm:
950     return expandMOVImm(MBB, MBBI, 64);
951   case AArch64::RET_ReallyLR: {
952     // Hiding the LR use with RET_ReallyLR may lead to extra kills in the
953     // function and missing live-ins. We are fine in practice because callee
954     // saved register handling ensures the register value is restored before
955     // RET, but we need the undef flag here to appease the MachineVerifier
956     // liveness checks.
957     MachineInstrBuilder MIB =
958         BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::RET))
959           .addReg(AArch64::LR, RegState::Undef);
960     transferImpOps(MI, MIB, MIB);
961     MI.eraseFromParent();
962     return true;
963   }
964   case AArch64::CMP_SWAP_8:
965     return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRB, AArch64::STLXRB,
966                           AArch64::SUBSWrx,
967                           AArch64_AM::getArithExtendImm(AArch64_AM::UXTB, 0),
968                           AArch64::WZR, NextMBBI);
969   case AArch64::CMP_SWAP_16:
970     return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRH, AArch64::STLXRH,
971                           AArch64::SUBSWrx,
972                           AArch64_AM::getArithExtendImm(AArch64_AM::UXTH, 0),
973                           AArch64::WZR, NextMBBI);
974   case AArch64::CMP_SWAP_32:
975     return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRW, AArch64::STLXRW,
976                           AArch64::SUBSWrs,
977                           AArch64_AM::getShifterImm(AArch64_AM::LSL, 0),
978                           AArch64::WZR, NextMBBI);
979   case AArch64::CMP_SWAP_64:
980     return expandCMP_SWAP(MBB, MBBI,
981                           AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
982                           AArch64_AM::getShifterImm(AArch64_AM::LSL, 0),
983                           AArch64::XZR, NextMBBI);
984   case AArch64::CMP_SWAP_128:
985     return expandCMP_SWAP_128(MBB, MBBI, NextMBBI);
986 
987   case AArch64::AESMCrrTied:
988   case AArch64::AESIMCrrTied: {
989     MachineInstrBuilder MIB =
990     BuildMI(MBB, MBBI, MI.getDebugLoc(),
991             TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
992                                                       AArch64::AESIMCrr))
993       .add(MI.getOperand(0))
994       .add(MI.getOperand(1));
995     transferImpOps(MI, MIB, MIB);
996     MI.eraseFromParent();
997     return true;
998    }
999    case AArch64::IRGstack: {
1000      MachineFunction &MF = *MBB.getParent();
1001      const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1002      const AArch64FrameLowering *TFI =
1003          MF.getSubtarget<AArch64Subtarget>().getFrameLowering();
1004 
1005      // IRG does not allow immediate offset. getTaggedBasePointerOffset should
1006      // almost always point to SP-after-prologue; if not, emit a longer
1007      // instruction sequence.
1008      int BaseOffset = -AFI->getTaggedBasePointerOffset();
1009      Register FrameReg;
1010      StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1011          MF, BaseOffset, false /*isFixed*/, false /*isSVE*/, FrameReg,
1012          /*PreferFP=*/false,
1013          /*ForSimm=*/true);
1014      Register SrcReg = FrameReg;
1015      if (FrameRegOffset) {
1016        // Use output register as temporary.
1017        SrcReg = MI.getOperand(0).getReg();
1018        emitFrameOffset(MBB, &MI, MI.getDebugLoc(), SrcReg, FrameReg,
1019                        FrameRegOffset, TII);
1020      }
1021      BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::IRG))
1022          .add(MI.getOperand(0))
1023          .addUse(SrcReg)
1024          .add(MI.getOperand(2));
1025      MI.eraseFromParent();
1026      return true;
1027    }
1028    case AArch64::TAGPstack: {
1029      int64_t Offset = MI.getOperand(2).getImm();
1030      BuildMI(MBB, MBBI, MI.getDebugLoc(),
1031              TII->get(Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1032          .add(MI.getOperand(0))
1033          .add(MI.getOperand(1))
1034          .addImm(std::abs(Offset))
1035          .add(MI.getOperand(4));
1036      MI.eraseFromParent();
1037      return true;
1038    }
1039    case AArch64::STGloop_wback:
1040    case AArch64::STZGloop_wback:
1041      return expandSetTagLoop(MBB, MBBI, NextMBBI);
1042    case AArch64::STGloop:
1043    case AArch64::STZGloop:
1044      report_fatal_error(
1045          "Non-writeback variants of STGloop / STZGloop should not "
1046          "survive past PrologEpilogInserter.");
1047    case AArch64::STR_ZZZZXI:
1048      return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 4);
1049    case AArch64::STR_ZZZXI:
1050      return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 3);
1051    case AArch64::STR_ZZXI:
1052      return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 2);
1053    case AArch64::LDR_ZZZZXI:
1054      return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 4);
1055    case AArch64::LDR_ZZZXI:
1056      return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 3);
1057    case AArch64::LDR_ZZXI:
1058      return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 2);
1059    case AArch64::BLR_RVMARKER:
1060      return expandCALL_RVMARKER(MBB, MBBI);
1061   }
1062   return false;
1063 }
1064 
1065 /// Iterate over the instructions in basic block MBB and expand any
1066 /// pseudo instructions.  Return true if anything was modified.
expandMBB(MachineBasicBlock & MBB)1067 bool AArch64ExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
1068   bool Modified = false;
1069 
1070   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1071   while (MBBI != E) {
1072     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
1073     Modified |= expandMI(MBB, MBBI, NMBBI);
1074     MBBI = NMBBI;
1075   }
1076 
1077   return Modified;
1078 }
1079 
runOnMachineFunction(MachineFunction & MF)1080 bool AArch64ExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
1081   TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
1082 
1083   bool Modified = false;
1084   for (auto &MBB : MF)
1085     Modified |= expandMBB(MBB);
1086   return Modified;
1087 }
1088 
1089 /// Returns an instance of the pseudo instruction expansion pass.
createAArch64ExpandPseudoPass()1090 FunctionPass *llvm::createAArch64ExpandPseudoPass() {
1091   return new AArch64ExpandPseudo();
1092 }
1093