10b57cec5SDimitry Andric //===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a pass that expands pseudo instructions into target
100b57cec5SDimitry Andric // instructions to allow proper scheduling, if-conversion, and other late
110b57cec5SDimitry Andric // optimizations. This pass should be run after register allocation but before
120b57cec5SDimitry Andric // the post-regalloc scheduling pass.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "ARM.h"
170b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h"
180b57cec5SDimitry Andric #include "ARMBaseRegisterInfo.h"
190b57cec5SDimitry Andric #include "ARMConstantPoolValue.h"
200b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h"
210b57cec5SDimitry Andric #include "ARMSubtarget.h"
220b57cec5SDimitry Andric #include "MCTargetDesc/ARMAddressingModes.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
260b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #define DEBUG_TYPE "arm-pseudo"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric static cl::opt<bool>
330b57cec5SDimitry Andric VerifyARMPseudo("verify-arm-pseudo-expand", cl::Hidden,
340b57cec5SDimitry Andric                 cl::desc("Verify machine code after expanding ARM pseudos"));
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric #define ARM_EXPAND_PSEUDO_NAME "ARM pseudo instruction expansion pass"
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace {
390b57cec5SDimitry Andric   class ARMExpandPseudo : public MachineFunctionPass {
400b57cec5SDimitry Andric   public:
410b57cec5SDimitry Andric     static char ID;
420b57cec5SDimitry Andric     ARMExpandPseudo() : MachineFunctionPass(ID) {}
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric     const ARMBaseInstrInfo *TII;
450b57cec5SDimitry Andric     const TargetRegisterInfo *TRI;
460b57cec5SDimitry Andric     const ARMSubtarget *STI;
470b57cec5SDimitry Andric     ARMFunctionInfo *AFI;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &Fn) override;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric     MachineFunctionProperties getRequiredProperties() const override {
520b57cec5SDimitry Andric       return MachineFunctionProperties().set(
530b57cec5SDimitry Andric           MachineFunctionProperties::Property::NoVRegs);
540b57cec5SDimitry Andric     }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric     StringRef getPassName() const override {
570b57cec5SDimitry Andric       return ARM_EXPAND_PSEUDO_NAME;
580b57cec5SDimitry Andric     }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   private:
610b57cec5SDimitry Andric     void TransferImpOps(MachineInstr &OldMI,
620b57cec5SDimitry Andric                         MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI);
630b57cec5SDimitry Andric     bool ExpandMI(MachineBasicBlock &MBB,
640b57cec5SDimitry Andric                   MachineBasicBlock::iterator MBBI,
650b57cec5SDimitry Andric                   MachineBasicBlock::iterator &NextMBBI);
660b57cec5SDimitry Andric     bool ExpandMBB(MachineBasicBlock &MBB);
670b57cec5SDimitry Andric     void ExpandVLD(MachineBasicBlock::iterator &MBBI);
680b57cec5SDimitry Andric     void ExpandVST(MachineBasicBlock::iterator &MBBI);
690b57cec5SDimitry Andric     void ExpandLaneOp(MachineBasicBlock::iterator &MBBI);
700b57cec5SDimitry Andric     void ExpandVTBL(MachineBasicBlock::iterator &MBBI,
710b57cec5SDimitry Andric                     unsigned Opc, bool IsExt);
720b57cec5SDimitry Andric     void ExpandMOV32BitImm(MachineBasicBlock &MBB,
730b57cec5SDimitry Andric                            MachineBasicBlock::iterator &MBBI);
740b57cec5SDimitry Andric     bool ExpandCMP_SWAP(MachineBasicBlock &MBB,
750b57cec5SDimitry Andric                         MachineBasicBlock::iterator MBBI, unsigned LdrexOp,
760b57cec5SDimitry Andric                         unsigned StrexOp, unsigned UxtOp,
770b57cec5SDimitry Andric                         MachineBasicBlock::iterator &NextMBBI);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric     bool ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
800b57cec5SDimitry Andric                            MachineBasicBlock::iterator MBBI,
810b57cec5SDimitry Andric                            MachineBasicBlock::iterator &NextMBBI);
820b57cec5SDimitry Andric   };
830b57cec5SDimitry Andric   char ARMExpandPseudo::ID = 0;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric INITIALIZE_PASS(ARMExpandPseudo, DEBUG_TYPE, ARM_EXPAND_PSEUDO_NAME, false,
870b57cec5SDimitry Andric                 false)
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric /// TransferImpOps - Transfer implicit operands on the pseudo instruction to
900b57cec5SDimitry Andric /// the instructions created from the expansion.
910b57cec5SDimitry Andric void ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI,
920b57cec5SDimitry Andric                                      MachineInstrBuilder &UseMI,
930b57cec5SDimitry Andric                                      MachineInstrBuilder &DefMI) {
940b57cec5SDimitry Andric   const MCInstrDesc &Desc = OldMI.getDesc();
950b57cec5SDimitry Andric   for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands();
960b57cec5SDimitry Andric        i != e; ++i) {
970b57cec5SDimitry Andric     const MachineOperand &MO = OldMI.getOperand(i);
980b57cec5SDimitry Andric     assert(MO.isReg() && MO.getReg());
990b57cec5SDimitry Andric     if (MO.isUse())
1000b57cec5SDimitry Andric       UseMI.add(MO);
1010b57cec5SDimitry Andric     else
1020b57cec5SDimitry Andric       DefMI.add(MO);
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric namespace {
1070b57cec5SDimitry Andric   // Constants for register spacing in NEON load/store instructions.
1080b57cec5SDimitry Andric   // For quad-register load-lane and store-lane pseudo instructors, the
1090b57cec5SDimitry Andric   // spacing is initially assumed to be EvenDblSpc, and that is changed to
1100b57cec5SDimitry Andric   // OddDblSpc depending on the lane number operand.
1110b57cec5SDimitry Andric   enum NEONRegSpacing {
1120b57cec5SDimitry Andric     SingleSpc,
1130b57cec5SDimitry Andric     SingleLowSpc ,  // Single spacing, low registers, three and four vectors.
1140b57cec5SDimitry Andric     SingleHighQSpc, // Single spacing, high registers, four vectors.
1150b57cec5SDimitry Andric     SingleHighTSpc, // Single spacing, high registers, three vectors.
1160b57cec5SDimitry Andric     EvenDblSpc,
1170b57cec5SDimitry Andric     OddDblSpc
1180b57cec5SDimitry Andric   };
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   // Entries for NEON load/store information table.  The table is sorted by
1210b57cec5SDimitry Andric   // PseudoOpc for fast binary-search lookups.
1220b57cec5SDimitry Andric   struct NEONLdStTableEntry {
1230b57cec5SDimitry Andric     uint16_t PseudoOpc;
1240b57cec5SDimitry Andric     uint16_t RealOpc;
1250b57cec5SDimitry Andric     bool IsLoad;
1260b57cec5SDimitry Andric     bool isUpdating;
1270b57cec5SDimitry Andric     bool hasWritebackOperand;
1280b57cec5SDimitry Andric     uint8_t RegSpacing; // One of type NEONRegSpacing
1290b57cec5SDimitry Andric     uint8_t NumRegs; // D registers loaded or stored
1300b57cec5SDimitry Andric     uint8_t RegElts; // elements per D register; used for lane ops
1310b57cec5SDimitry Andric     // FIXME: Temporary flag to denote whether the real instruction takes
1320b57cec5SDimitry Andric     // a single register (like the encoding) or all of the registers in
1330b57cec5SDimitry Andric     // the list (like the asm syntax and the isel DAG). When all definitions
1340b57cec5SDimitry Andric     // are converted to take only the single encoded register, this will
1350b57cec5SDimitry Andric     // go away.
1360b57cec5SDimitry Andric     bool copyAllListRegs;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     // Comparison methods for binary search of the table.
1390b57cec5SDimitry Andric     bool operator<(const NEONLdStTableEntry &TE) const {
1400b57cec5SDimitry Andric       return PseudoOpc < TE.PseudoOpc;
1410b57cec5SDimitry Andric     }
1420b57cec5SDimitry Andric     friend bool operator<(const NEONLdStTableEntry &TE, unsigned PseudoOpc) {
1430b57cec5SDimitry Andric       return TE.PseudoOpc < PseudoOpc;
1440b57cec5SDimitry Andric     }
1450b57cec5SDimitry Andric     friend bool LLVM_ATTRIBUTE_UNUSED operator<(unsigned PseudoOpc,
1460b57cec5SDimitry Andric                                                 const NEONLdStTableEntry &TE) {
1470b57cec5SDimitry Andric       return PseudoOpc < TE.PseudoOpc;
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric   };
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric static const NEONLdStTableEntry NEONLdStTable[] = {
1530b57cec5SDimitry Andric { ARM::VLD1LNq16Pseudo,     ARM::VLD1LNd16,     true, false, false, EvenDblSpc, 1, 4 ,true},
1540b57cec5SDimitry Andric { ARM::VLD1LNq16Pseudo_UPD, ARM::VLD1LNd16_UPD, true, true, true,  EvenDblSpc, 1, 4 ,true},
1550b57cec5SDimitry Andric { ARM::VLD1LNq32Pseudo,     ARM::VLD1LNd32,     true, false, false, EvenDblSpc, 1, 2 ,true},
1560b57cec5SDimitry Andric { ARM::VLD1LNq32Pseudo_UPD, ARM::VLD1LNd32_UPD, true, true, true,  EvenDblSpc, 1, 2 ,true},
1570b57cec5SDimitry Andric { ARM::VLD1LNq8Pseudo,      ARM::VLD1LNd8,      true, false, false, EvenDblSpc, 1, 8 ,true},
1580b57cec5SDimitry Andric { ARM::VLD1LNq8Pseudo_UPD,  ARM::VLD1LNd8_UPD, true, true, true,  EvenDblSpc, 1, 8 ,true},
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric { ARM::VLD1d16QPseudo,      ARM::VLD1d16Q,     true,  false, false, SingleSpc,  4, 4 ,false},
1610b57cec5SDimitry Andric { ARM::VLD1d16TPseudo,      ARM::VLD1d16T,     true,  false, false, SingleSpc,  3, 4 ,false},
1620b57cec5SDimitry Andric { ARM::VLD1d32QPseudo,      ARM::VLD1d32Q,     true,  false, false, SingleSpc,  4, 2 ,false},
1630b57cec5SDimitry Andric { ARM::VLD1d32TPseudo,      ARM::VLD1d32T,     true,  false, false, SingleSpc,  3, 2 ,false},
1640b57cec5SDimitry Andric { ARM::VLD1d64QPseudo,      ARM::VLD1d64Q,     true,  false, false, SingleSpc,  4, 1 ,false},
1650b57cec5SDimitry Andric { ARM::VLD1d64QPseudoWB_fixed,  ARM::VLD1d64Qwb_fixed,   true,  true, false, SingleSpc,  4, 1 ,false},
1660b57cec5SDimitry Andric { ARM::VLD1d64QPseudoWB_register,  ARM::VLD1d64Qwb_register,   true,  true, true, SingleSpc,  4, 1 ,false},
1670b57cec5SDimitry Andric { ARM::VLD1d64TPseudo,      ARM::VLD1d64T,     true,  false, false, SingleSpc,  3, 1 ,false},
1680b57cec5SDimitry Andric { ARM::VLD1d64TPseudoWB_fixed,  ARM::VLD1d64Twb_fixed,   true,  true, false, SingleSpc,  3, 1 ,false},
1690b57cec5SDimitry Andric { ARM::VLD1d64TPseudoWB_register,  ARM::VLD1d64Twb_register, true, true, true,  SingleSpc,  3, 1 ,false},
1700b57cec5SDimitry Andric { ARM::VLD1d8QPseudo,       ARM::VLD1d8Q,      true,  false, false, SingleSpc,  4, 8 ,false},
1710b57cec5SDimitry Andric { ARM::VLD1d8TPseudo,       ARM::VLD1d8T,      true,  false, false, SingleSpc,  3, 8 ,false},
1720b57cec5SDimitry Andric { ARM::VLD1q16HighQPseudo,  ARM::VLD1d16Q,     true,  false, false, SingleHighQSpc,  4, 4 ,false},
1730b57cec5SDimitry Andric { ARM::VLD1q16HighTPseudo,  ARM::VLD1d16T,     true,  false, false, SingleHighTSpc,  3, 4 ,false},
1740b57cec5SDimitry Andric { ARM::VLD1q16LowQPseudo_UPD,  ARM::VLD1d16Qwb_fixed,   true,  true, true, SingleLowSpc,  4, 4 ,false},
1750b57cec5SDimitry Andric { ARM::VLD1q16LowTPseudo_UPD,  ARM::VLD1d16Twb_fixed,   true,  true, true, SingleLowSpc,  3, 4 ,false},
1760b57cec5SDimitry Andric { ARM::VLD1q32HighQPseudo,  ARM::VLD1d32Q,     true,  false, false, SingleHighQSpc,  4, 2 ,false},
1770b57cec5SDimitry Andric { ARM::VLD1q32HighTPseudo,  ARM::VLD1d32T,     true,  false, false, SingleHighTSpc,  3, 2 ,false},
1780b57cec5SDimitry Andric { ARM::VLD1q32LowQPseudo_UPD,  ARM::VLD1d32Qwb_fixed,   true,  true, true, SingleLowSpc,  4, 2 ,false},
1790b57cec5SDimitry Andric { ARM::VLD1q32LowTPseudo_UPD,  ARM::VLD1d32Twb_fixed,   true,  true, true, SingleLowSpc,  3, 2 ,false},
1800b57cec5SDimitry Andric { ARM::VLD1q64HighQPseudo,  ARM::VLD1d64Q,     true,  false, false, SingleHighQSpc,  4, 1 ,false},
1810b57cec5SDimitry Andric { ARM::VLD1q64HighTPseudo,  ARM::VLD1d64T,     true,  false, false, SingleHighTSpc,  3, 1 ,false},
1820b57cec5SDimitry Andric { ARM::VLD1q64LowQPseudo_UPD,  ARM::VLD1d64Qwb_fixed,   true,  true, true, SingleLowSpc,  4, 1 ,false},
1830b57cec5SDimitry Andric { ARM::VLD1q64LowTPseudo_UPD,  ARM::VLD1d64Twb_fixed,   true,  true, true, SingleLowSpc,  3, 1 ,false},
1840b57cec5SDimitry Andric { ARM::VLD1q8HighQPseudo,   ARM::VLD1d8Q,     true,  false, false, SingleHighQSpc,  4, 8 ,false},
1850b57cec5SDimitry Andric { ARM::VLD1q8HighTPseudo,   ARM::VLD1d8T,     true,  false, false, SingleHighTSpc,  3, 8 ,false},
1860b57cec5SDimitry Andric { ARM::VLD1q8LowQPseudo_UPD,  ARM::VLD1d8Qwb_fixed,   true,  true, true, SingleLowSpc,  4, 8 ,false},
1870b57cec5SDimitry Andric { ARM::VLD1q8LowTPseudo_UPD,  ARM::VLD1d8Twb_fixed,   true,  true, true, SingleLowSpc,  3, 8 ,false},
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric { ARM::VLD2DUPq16EvenPseudo,  ARM::VLD2DUPd16x2,  true, false, false, EvenDblSpc, 2, 4 ,false},
1900b57cec5SDimitry Andric { ARM::VLD2DUPq16OddPseudo,   ARM::VLD2DUPd16x2,  true, false, false, OddDblSpc,  2, 4 ,false},
1910b57cec5SDimitry Andric { ARM::VLD2DUPq32EvenPseudo,  ARM::VLD2DUPd32x2,  true, false, false, EvenDblSpc, 2, 2 ,false},
1920b57cec5SDimitry Andric { ARM::VLD2DUPq32OddPseudo,   ARM::VLD2DUPd32x2,  true, false, false, OddDblSpc,  2, 2 ,false},
1930b57cec5SDimitry Andric { ARM::VLD2DUPq8EvenPseudo,   ARM::VLD2DUPd8x2,   true, false, false, EvenDblSpc, 2, 8 ,false},
1940b57cec5SDimitry Andric { ARM::VLD2DUPq8OddPseudo,    ARM::VLD2DUPd8x2,   true, false, false, OddDblSpc,  2, 8 ,false},
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric { ARM::VLD2LNd16Pseudo,     ARM::VLD2LNd16,     true, false, false, SingleSpc,  2, 4 ,true},
1970b57cec5SDimitry Andric { ARM::VLD2LNd16Pseudo_UPD, ARM::VLD2LNd16_UPD, true, true, true,  SingleSpc,  2, 4 ,true},
1980b57cec5SDimitry Andric { ARM::VLD2LNd32Pseudo,     ARM::VLD2LNd32,     true, false, false, SingleSpc,  2, 2 ,true},
1990b57cec5SDimitry Andric { ARM::VLD2LNd32Pseudo_UPD, ARM::VLD2LNd32_UPD, true, true, true,  SingleSpc,  2, 2 ,true},
2000b57cec5SDimitry Andric { ARM::VLD2LNd8Pseudo,      ARM::VLD2LNd8,      true, false, false, SingleSpc,  2, 8 ,true},
2010b57cec5SDimitry Andric { ARM::VLD2LNd8Pseudo_UPD,  ARM::VLD2LNd8_UPD, true, true, true,  SingleSpc,  2, 8 ,true},
2020b57cec5SDimitry Andric { ARM::VLD2LNq16Pseudo,     ARM::VLD2LNq16,     true, false, false, EvenDblSpc, 2, 4 ,true},
2030b57cec5SDimitry Andric { ARM::VLD2LNq16Pseudo_UPD, ARM::VLD2LNq16_UPD, true, true, true,  EvenDblSpc, 2, 4 ,true},
2040b57cec5SDimitry Andric { ARM::VLD2LNq32Pseudo,     ARM::VLD2LNq32,     true, false, false, EvenDblSpc, 2, 2 ,true},
2050b57cec5SDimitry Andric { ARM::VLD2LNq32Pseudo_UPD, ARM::VLD2LNq32_UPD, true, true, true,  EvenDblSpc, 2, 2 ,true},
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric { ARM::VLD2q16Pseudo,       ARM::VLD2q16,      true,  false, false, SingleSpc,  4, 4 ,false},
2080b57cec5SDimitry Andric { ARM::VLD2q16PseudoWB_fixed,   ARM::VLD2q16wb_fixed, true, true, false,  SingleSpc,  4, 4 ,false},
2090b57cec5SDimitry Andric { ARM::VLD2q16PseudoWB_register,   ARM::VLD2q16wb_register, true, true, true,  SingleSpc,  4, 4 ,false},
2100b57cec5SDimitry Andric { ARM::VLD2q32Pseudo,       ARM::VLD2q32,      true,  false, false, SingleSpc,  4, 2 ,false},
2110b57cec5SDimitry Andric { ARM::VLD2q32PseudoWB_fixed,   ARM::VLD2q32wb_fixed, true, true, false,  SingleSpc,  4, 2 ,false},
2120b57cec5SDimitry Andric { ARM::VLD2q32PseudoWB_register,   ARM::VLD2q32wb_register, true, true, true,  SingleSpc,  4, 2 ,false},
2130b57cec5SDimitry Andric { ARM::VLD2q8Pseudo,        ARM::VLD2q8,       true,  false, false, SingleSpc,  4, 8 ,false},
2140b57cec5SDimitry Andric { ARM::VLD2q8PseudoWB_fixed,    ARM::VLD2q8wb_fixed, true, true, false,  SingleSpc,  4, 8 ,false},
2150b57cec5SDimitry Andric { ARM::VLD2q8PseudoWB_register,    ARM::VLD2q8wb_register, true, true, true,  SingleSpc,  4, 8 ,false},
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric { ARM::VLD3DUPd16Pseudo,     ARM::VLD3DUPd16,     true, false, false, SingleSpc, 3, 4,true},
2180b57cec5SDimitry Andric { ARM::VLD3DUPd16Pseudo_UPD, ARM::VLD3DUPd16_UPD, true, true, true,  SingleSpc, 3, 4,true},
2190b57cec5SDimitry Andric { ARM::VLD3DUPd32Pseudo,     ARM::VLD3DUPd32,     true, false, false, SingleSpc, 3, 2,true},
2200b57cec5SDimitry Andric { ARM::VLD3DUPd32Pseudo_UPD, ARM::VLD3DUPd32_UPD, true, true, true,  SingleSpc, 3, 2,true},
2210b57cec5SDimitry Andric { ARM::VLD3DUPd8Pseudo,      ARM::VLD3DUPd8,      true, false, false, SingleSpc, 3, 8,true},
2220b57cec5SDimitry Andric { ARM::VLD3DUPd8Pseudo_UPD,  ARM::VLD3DUPd8_UPD, true, true, true,  SingleSpc, 3, 8,true},
2230b57cec5SDimitry Andric { ARM::VLD3DUPq16EvenPseudo, ARM::VLD3DUPq16,     true, false, false, EvenDblSpc, 3, 4 ,true},
2240b57cec5SDimitry Andric { ARM::VLD3DUPq16OddPseudo,  ARM::VLD3DUPq16,     true, false, false, OddDblSpc,  3, 4 ,true},
2250b57cec5SDimitry Andric { ARM::VLD3DUPq32EvenPseudo, ARM::VLD3DUPq32,     true, false, false, EvenDblSpc, 3, 2 ,true},
2260b57cec5SDimitry Andric { ARM::VLD3DUPq32OddPseudo,  ARM::VLD3DUPq32,     true, false, false, OddDblSpc,  3, 2 ,true},
2270b57cec5SDimitry Andric { ARM::VLD3DUPq8EvenPseudo,  ARM::VLD3DUPq8,      true, false, false, EvenDblSpc, 3, 8 ,true},
2280b57cec5SDimitry Andric { ARM::VLD3DUPq8OddPseudo,   ARM::VLD3DUPq8,      true, false, false, OddDblSpc,  3, 8 ,true},
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric { ARM::VLD3LNd16Pseudo,     ARM::VLD3LNd16,     true, false, false, SingleSpc,  3, 4 ,true},
2310b57cec5SDimitry Andric { ARM::VLD3LNd16Pseudo_UPD, ARM::VLD3LNd16_UPD, true, true, true,  SingleSpc,  3, 4 ,true},
2320b57cec5SDimitry Andric { ARM::VLD3LNd32Pseudo,     ARM::VLD3LNd32,     true, false, false, SingleSpc,  3, 2 ,true},
2330b57cec5SDimitry Andric { ARM::VLD3LNd32Pseudo_UPD, ARM::VLD3LNd32_UPD, true, true, true,  SingleSpc,  3, 2 ,true},
2340b57cec5SDimitry Andric { ARM::VLD3LNd8Pseudo,      ARM::VLD3LNd8,      true, false, false, SingleSpc,  3, 8 ,true},
2350b57cec5SDimitry Andric { ARM::VLD3LNd8Pseudo_UPD,  ARM::VLD3LNd8_UPD, true, true, true,  SingleSpc,  3, 8 ,true},
2360b57cec5SDimitry Andric { ARM::VLD3LNq16Pseudo,     ARM::VLD3LNq16,     true, false, false, EvenDblSpc, 3, 4 ,true},
2370b57cec5SDimitry Andric { ARM::VLD3LNq16Pseudo_UPD, ARM::VLD3LNq16_UPD, true, true, true,  EvenDblSpc, 3, 4 ,true},
2380b57cec5SDimitry Andric { ARM::VLD3LNq32Pseudo,     ARM::VLD3LNq32,     true, false, false, EvenDblSpc, 3, 2 ,true},
2390b57cec5SDimitry Andric { ARM::VLD3LNq32Pseudo_UPD, ARM::VLD3LNq32_UPD, true, true, true,  EvenDblSpc, 3, 2 ,true},
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric { ARM::VLD3d16Pseudo,       ARM::VLD3d16,      true,  false, false, SingleSpc,  3, 4 ,true},
2420b57cec5SDimitry Andric { ARM::VLD3d16Pseudo_UPD,   ARM::VLD3d16_UPD, true, true, true,  SingleSpc,  3, 4 ,true},
2430b57cec5SDimitry Andric { ARM::VLD3d32Pseudo,       ARM::VLD3d32,      true,  false, false, SingleSpc,  3, 2 ,true},
2440b57cec5SDimitry Andric { ARM::VLD3d32Pseudo_UPD,   ARM::VLD3d32_UPD, true, true, true,  SingleSpc,  3, 2 ,true},
2450b57cec5SDimitry Andric { ARM::VLD3d8Pseudo,        ARM::VLD3d8,       true,  false, false, SingleSpc,  3, 8 ,true},
2460b57cec5SDimitry Andric { ARM::VLD3d8Pseudo_UPD,    ARM::VLD3d8_UPD, true, true, true,  SingleSpc,  3, 8 ,true},
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric { ARM::VLD3q16Pseudo_UPD,    ARM::VLD3q16_UPD, true, true, true,  EvenDblSpc, 3, 4 ,true},
2490b57cec5SDimitry Andric { ARM::VLD3q16oddPseudo,     ARM::VLD3q16,     true,  false, false, OddDblSpc,  3, 4 ,true},
2500b57cec5SDimitry Andric { ARM::VLD3q16oddPseudo_UPD, ARM::VLD3q16_UPD, true, true, true,  OddDblSpc,  3, 4 ,true},
2510b57cec5SDimitry Andric { ARM::VLD3q32Pseudo_UPD,    ARM::VLD3q32_UPD, true, true, true,  EvenDblSpc, 3, 2 ,true},
2520b57cec5SDimitry Andric { ARM::VLD3q32oddPseudo,     ARM::VLD3q32,     true,  false, false, OddDblSpc,  3, 2 ,true},
2530b57cec5SDimitry Andric { ARM::VLD3q32oddPseudo_UPD, ARM::VLD3q32_UPD, true, true, true,  OddDblSpc,  3, 2 ,true},
2540b57cec5SDimitry Andric { ARM::VLD3q8Pseudo_UPD,     ARM::VLD3q8_UPD, true, true, true,  EvenDblSpc, 3, 8 ,true},
2550b57cec5SDimitry Andric { ARM::VLD3q8oddPseudo,      ARM::VLD3q8,      true,  false, false, OddDblSpc,  3, 8 ,true},
2560b57cec5SDimitry Andric { ARM::VLD3q8oddPseudo_UPD,  ARM::VLD3q8_UPD, true, true, true,  OddDblSpc,  3, 8 ,true},
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric { ARM::VLD4DUPd16Pseudo,     ARM::VLD4DUPd16,     true, false, false, SingleSpc, 4, 4,true},
2590b57cec5SDimitry Andric { ARM::VLD4DUPd16Pseudo_UPD, ARM::VLD4DUPd16_UPD, true, true, true,  SingleSpc, 4, 4,true},
2600b57cec5SDimitry Andric { ARM::VLD4DUPd32Pseudo,     ARM::VLD4DUPd32,     true, false, false, SingleSpc, 4, 2,true},
2610b57cec5SDimitry Andric { ARM::VLD4DUPd32Pseudo_UPD, ARM::VLD4DUPd32_UPD, true, true, true,  SingleSpc, 4, 2,true},
2620b57cec5SDimitry Andric { ARM::VLD4DUPd8Pseudo,      ARM::VLD4DUPd8,      true, false, false, SingleSpc, 4, 8,true},
2630b57cec5SDimitry Andric { ARM::VLD4DUPd8Pseudo_UPD,  ARM::VLD4DUPd8_UPD, true, true, true,  SingleSpc, 4, 8,true},
2640b57cec5SDimitry Andric { ARM::VLD4DUPq16EvenPseudo, ARM::VLD4DUPq16,     true, false, false, EvenDblSpc, 4, 4 ,true},
2650b57cec5SDimitry Andric { ARM::VLD4DUPq16OddPseudo,  ARM::VLD4DUPq16,     true, false, false, OddDblSpc,  4, 4 ,true},
2660b57cec5SDimitry Andric { ARM::VLD4DUPq32EvenPseudo, ARM::VLD4DUPq32,     true, false, false, EvenDblSpc, 4, 2 ,true},
2670b57cec5SDimitry Andric { ARM::VLD4DUPq32OddPseudo,  ARM::VLD4DUPq32,     true, false, false, OddDblSpc,  4, 2 ,true},
2680b57cec5SDimitry Andric { ARM::VLD4DUPq8EvenPseudo,  ARM::VLD4DUPq8,      true, false, false, EvenDblSpc, 4, 8 ,true},
2690b57cec5SDimitry Andric { ARM::VLD4DUPq8OddPseudo,   ARM::VLD4DUPq8,      true, false, false, OddDblSpc,  4, 8 ,true},
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric { ARM::VLD4LNd16Pseudo,     ARM::VLD4LNd16,     true, false, false, SingleSpc,  4, 4 ,true},
2720b57cec5SDimitry Andric { ARM::VLD4LNd16Pseudo_UPD, ARM::VLD4LNd16_UPD, true, true, true,  SingleSpc,  4, 4 ,true},
2730b57cec5SDimitry Andric { ARM::VLD4LNd32Pseudo,     ARM::VLD4LNd32,     true, false, false, SingleSpc,  4, 2 ,true},
2740b57cec5SDimitry Andric { ARM::VLD4LNd32Pseudo_UPD, ARM::VLD4LNd32_UPD, true, true, true,  SingleSpc,  4, 2 ,true},
2750b57cec5SDimitry Andric { ARM::VLD4LNd8Pseudo,      ARM::VLD4LNd8,      true, false, false, SingleSpc,  4, 8 ,true},
2760b57cec5SDimitry Andric { ARM::VLD4LNd8Pseudo_UPD,  ARM::VLD4LNd8_UPD, true, true, true,  SingleSpc,  4, 8 ,true},
2770b57cec5SDimitry Andric { ARM::VLD4LNq16Pseudo,     ARM::VLD4LNq16,     true, false, false, EvenDblSpc, 4, 4 ,true},
2780b57cec5SDimitry Andric { ARM::VLD4LNq16Pseudo_UPD, ARM::VLD4LNq16_UPD, true, true, true,  EvenDblSpc, 4, 4 ,true},
2790b57cec5SDimitry Andric { ARM::VLD4LNq32Pseudo,     ARM::VLD4LNq32,     true, false, false, EvenDblSpc, 4, 2 ,true},
2800b57cec5SDimitry Andric { ARM::VLD4LNq32Pseudo_UPD, ARM::VLD4LNq32_UPD, true, true, true,  EvenDblSpc, 4, 2 ,true},
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric { ARM::VLD4d16Pseudo,       ARM::VLD4d16,      true,  false, false, SingleSpc,  4, 4 ,true},
2830b57cec5SDimitry Andric { ARM::VLD4d16Pseudo_UPD,   ARM::VLD4d16_UPD, true, true, true,  SingleSpc,  4, 4 ,true},
2840b57cec5SDimitry Andric { ARM::VLD4d32Pseudo,       ARM::VLD4d32,      true,  false, false, SingleSpc,  4, 2 ,true},
2850b57cec5SDimitry Andric { ARM::VLD4d32Pseudo_UPD,   ARM::VLD4d32_UPD, true, true, true,  SingleSpc,  4, 2 ,true},
2860b57cec5SDimitry Andric { ARM::VLD4d8Pseudo,        ARM::VLD4d8,       true,  false, false, SingleSpc,  4, 8 ,true},
2870b57cec5SDimitry Andric { ARM::VLD4d8Pseudo_UPD,    ARM::VLD4d8_UPD, true, true, true,  SingleSpc,  4, 8 ,true},
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric { ARM::VLD4q16Pseudo_UPD,    ARM::VLD4q16_UPD, true, true, true,  EvenDblSpc, 4, 4 ,true},
2900b57cec5SDimitry Andric { ARM::VLD4q16oddPseudo,     ARM::VLD4q16,     true,  false, false, OddDblSpc,  4, 4 ,true},
2910b57cec5SDimitry Andric { ARM::VLD4q16oddPseudo_UPD, ARM::VLD4q16_UPD, true, true, true,  OddDblSpc,  4, 4 ,true},
2920b57cec5SDimitry Andric { ARM::VLD4q32Pseudo_UPD,    ARM::VLD4q32_UPD, true, true, true,  EvenDblSpc, 4, 2 ,true},
2930b57cec5SDimitry Andric { ARM::VLD4q32oddPseudo,     ARM::VLD4q32,     true,  false, false, OddDblSpc,  4, 2 ,true},
2940b57cec5SDimitry Andric { ARM::VLD4q32oddPseudo_UPD, ARM::VLD4q32_UPD, true, true, true,  OddDblSpc,  4, 2 ,true},
2950b57cec5SDimitry Andric { ARM::VLD4q8Pseudo_UPD,     ARM::VLD4q8_UPD, true, true, true,  EvenDblSpc, 4, 8 ,true},
2960b57cec5SDimitry Andric { ARM::VLD4q8oddPseudo,      ARM::VLD4q8,      true,  false, false, OddDblSpc,  4, 8 ,true},
2970b57cec5SDimitry Andric { ARM::VLD4q8oddPseudo_UPD,  ARM::VLD4q8_UPD, true, true, true,  OddDblSpc,  4, 8 ,true},
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric { ARM::VST1LNq16Pseudo,     ARM::VST1LNd16,    false, false, false, EvenDblSpc, 1, 4 ,true},
3000b57cec5SDimitry Andric { ARM::VST1LNq16Pseudo_UPD, ARM::VST1LNd16_UPD, false, true, true,  EvenDblSpc, 1, 4 ,true},
3010b57cec5SDimitry Andric { ARM::VST1LNq32Pseudo,     ARM::VST1LNd32,    false, false, false, EvenDblSpc, 1, 2 ,true},
3020b57cec5SDimitry Andric { ARM::VST1LNq32Pseudo_UPD, ARM::VST1LNd32_UPD, false, true, true,  EvenDblSpc, 1, 2 ,true},
3030b57cec5SDimitry Andric { ARM::VST1LNq8Pseudo,      ARM::VST1LNd8,     false, false, false, EvenDblSpc, 1, 8 ,true},
3040b57cec5SDimitry Andric { ARM::VST1LNq8Pseudo_UPD,  ARM::VST1LNd8_UPD, false, true, true,  EvenDblSpc, 1, 8 ,true},
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric { ARM::VST1d16QPseudo,      ARM::VST1d16Q,     false, false, false, SingleSpc,  4, 4 ,false},
3070b57cec5SDimitry Andric { ARM::VST1d16TPseudo,      ARM::VST1d16T,     false, false, false, SingleSpc,  3, 4 ,false},
3080b57cec5SDimitry Andric { ARM::VST1d32QPseudo,      ARM::VST1d32Q,     false, false, false, SingleSpc,  4, 2 ,false},
3090b57cec5SDimitry Andric { ARM::VST1d32TPseudo,      ARM::VST1d32T,     false, false, false, SingleSpc,  3, 2 ,false},
3100b57cec5SDimitry Andric { ARM::VST1d64QPseudo,      ARM::VST1d64Q,     false, false, false, SingleSpc,  4, 1 ,false},
3110b57cec5SDimitry Andric { ARM::VST1d64QPseudoWB_fixed,  ARM::VST1d64Qwb_fixed, false, true, false,  SingleSpc,  4, 1 ,false},
3120b57cec5SDimitry Andric { ARM::VST1d64QPseudoWB_register, ARM::VST1d64Qwb_register, false, true, true,  SingleSpc,  4, 1 ,false},
3130b57cec5SDimitry Andric { ARM::VST1d64TPseudo,      ARM::VST1d64T,     false, false, false, SingleSpc,  3, 1 ,false},
3140b57cec5SDimitry Andric { ARM::VST1d64TPseudoWB_fixed,  ARM::VST1d64Twb_fixed, false, true, false,  SingleSpc,  3, 1 ,false},
3150b57cec5SDimitry Andric { ARM::VST1d64TPseudoWB_register,  ARM::VST1d64Twb_register, false, true, true,  SingleSpc,  3, 1 ,false},
3160b57cec5SDimitry Andric { ARM::VST1d8QPseudo,       ARM::VST1d8Q,      false, false, false, SingleSpc,  4, 8 ,false},
3170b57cec5SDimitry Andric { ARM::VST1d8TPseudo,       ARM::VST1d8T,      false, false, false, SingleSpc,  3, 8 ,false},
3180b57cec5SDimitry Andric { ARM::VST1q16HighQPseudo,  ARM::VST1d16Q,      false, false, false, SingleHighQSpc,   4, 4 ,false},
3190b57cec5SDimitry Andric { ARM::VST1q16HighTPseudo,  ARM::VST1d16T,      false, false, false, SingleHighTSpc,   3, 4 ,false},
3200b57cec5SDimitry Andric { ARM::VST1q16LowQPseudo_UPD,   ARM::VST1d16Qwb_fixed,  false, true, true, SingleLowSpc,   4, 4 ,false},
3210b57cec5SDimitry Andric { ARM::VST1q16LowTPseudo_UPD,   ARM::VST1d16Twb_fixed,  false, true, true, SingleLowSpc,   3, 4 ,false},
3220b57cec5SDimitry Andric { ARM::VST1q32HighQPseudo,  ARM::VST1d32Q,      false, false, false, SingleHighQSpc,   4, 2 ,false},
3230b57cec5SDimitry Andric { ARM::VST1q32HighTPseudo,  ARM::VST1d32T,      false, false, false, SingleHighTSpc,   3, 2 ,false},
3240b57cec5SDimitry Andric { ARM::VST1q32LowQPseudo_UPD,   ARM::VST1d32Qwb_fixed,  false, true, true, SingleLowSpc,   4, 2 ,false},
3250b57cec5SDimitry Andric { ARM::VST1q32LowTPseudo_UPD,   ARM::VST1d32Twb_fixed,  false, true, true, SingleLowSpc,   3, 2 ,false},
3260b57cec5SDimitry Andric { ARM::VST1q64HighQPseudo,  ARM::VST1d64Q,      false, false, false, SingleHighQSpc,   4, 1 ,false},
3270b57cec5SDimitry Andric { ARM::VST1q64HighTPseudo,  ARM::VST1d64T,      false, false, false, SingleHighTSpc,   3, 1 ,false},
3280b57cec5SDimitry Andric { ARM::VST1q64LowQPseudo_UPD,   ARM::VST1d64Qwb_fixed,  false, true, true, SingleLowSpc,   4, 1 ,false},
3290b57cec5SDimitry Andric { ARM::VST1q64LowTPseudo_UPD,   ARM::VST1d64Twb_fixed,  false, true, true, SingleLowSpc,   3, 1 ,false},
3300b57cec5SDimitry Andric { ARM::VST1q8HighQPseudo,   ARM::VST1d8Q,      false, false, false, SingleHighQSpc,   4, 8 ,false},
3310b57cec5SDimitry Andric { ARM::VST1q8HighTPseudo,   ARM::VST1d8T,      false, false, false, SingleHighTSpc,   3, 8 ,false},
3320b57cec5SDimitry Andric { ARM::VST1q8LowQPseudo_UPD,   ARM::VST1d8Qwb_fixed,  false, true, true, SingleLowSpc,   4, 8 ,false},
3330b57cec5SDimitry Andric { ARM::VST1q8LowTPseudo_UPD,   ARM::VST1d8Twb_fixed,  false, true, true, SingleLowSpc,   3, 8 ,false},
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric { ARM::VST2LNd16Pseudo,     ARM::VST2LNd16,     false, false, false, SingleSpc, 2, 4 ,true},
3360b57cec5SDimitry Andric { ARM::VST2LNd16Pseudo_UPD, ARM::VST2LNd16_UPD, false, true, true,  SingleSpc, 2, 4 ,true},
3370b57cec5SDimitry Andric { ARM::VST2LNd32Pseudo,     ARM::VST2LNd32,     false, false, false, SingleSpc, 2, 2 ,true},
3380b57cec5SDimitry Andric { ARM::VST2LNd32Pseudo_UPD, ARM::VST2LNd32_UPD, false, true, true,  SingleSpc, 2, 2 ,true},
3390b57cec5SDimitry Andric { ARM::VST2LNd8Pseudo,      ARM::VST2LNd8,      false, false, false, SingleSpc, 2, 8 ,true},
3400b57cec5SDimitry Andric { ARM::VST2LNd8Pseudo_UPD,  ARM::VST2LNd8_UPD, false, true, true,  SingleSpc, 2, 8 ,true},
3410b57cec5SDimitry Andric { ARM::VST2LNq16Pseudo,     ARM::VST2LNq16,     false, false, false, EvenDblSpc, 2, 4,true},
3420b57cec5SDimitry Andric { ARM::VST2LNq16Pseudo_UPD, ARM::VST2LNq16_UPD, false, true, true,  EvenDblSpc, 2, 4,true},
3430b57cec5SDimitry Andric { ARM::VST2LNq32Pseudo,     ARM::VST2LNq32,     false, false, false, EvenDblSpc, 2, 2,true},
3440b57cec5SDimitry Andric { ARM::VST2LNq32Pseudo_UPD, ARM::VST2LNq32_UPD, false, true, true,  EvenDblSpc, 2, 2,true},
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric { ARM::VST2q16Pseudo,       ARM::VST2q16,      false, false, false, SingleSpc,  4, 4 ,false},
3470b57cec5SDimitry Andric { ARM::VST2q16PseudoWB_fixed,   ARM::VST2q16wb_fixed, false, true, false,  SingleSpc,  4, 4 ,false},
3480b57cec5SDimitry Andric { ARM::VST2q16PseudoWB_register,   ARM::VST2q16wb_register, false, true, true,  SingleSpc,  4, 4 ,false},
3490b57cec5SDimitry Andric { ARM::VST2q32Pseudo,       ARM::VST2q32,      false, false, false, SingleSpc,  4, 2 ,false},
3500b57cec5SDimitry Andric { ARM::VST2q32PseudoWB_fixed,   ARM::VST2q32wb_fixed, false, true, false,  SingleSpc,  4, 2 ,false},
3510b57cec5SDimitry Andric { ARM::VST2q32PseudoWB_register,   ARM::VST2q32wb_register, false, true, true,  SingleSpc,  4, 2 ,false},
3520b57cec5SDimitry Andric { ARM::VST2q8Pseudo,        ARM::VST2q8,       false, false, false, SingleSpc,  4, 8 ,false},
3530b57cec5SDimitry Andric { ARM::VST2q8PseudoWB_fixed,    ARM::VST2q8wb_fixed, false, true, false,  SingleSpc,  4, 8 ,false},
3540b57cec5SDimitry Andric { ARM::VST2q8PseudoWB_register,    ARM::VST2q8wb_register, false, true, true,  SingleSpc,  4, 8 ,false},
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric { ARM::VST3LNd16Pseudo,     ARM::VST3LNd16,     false, false, false, SingleSpc, 3, 4 ,true},
3570b57cec5SDimitry Andric { ARM::VST3LNd16Pseudo_UPD, ARM::VST3LNd16_UPD, false, true, true,  SingleSpc, 3, 4 ,true},
3580b57cec5SDimitry Andric { ARM::VST3LNd32Pseudo,     ARM::VST3LNd32,     false, false, false, SingleSpc, 3, 2 ,true},
3590b57cec5SDimitry Andric { ARM::VST3LNd32Pseudo_UPD, ARM::VST3LNd32_UPD, false, true, true,  SingleSpc, 3, 2 ,true},
3600b57cec5SDimitry Andric { ARM::VST3LNd8Pseudo,      ARM::VST3LNd8,      false, false, false, SingleSpc, 3, 8 ,true},
3610b57cec5SDimitry Andric { ARM::VST3LNd8Pseudo_UPD,  ARM::VST3LNd8_UPD, false, true, true,  SingleSpc, 3, 8 ,true},
3620b57cec5SDimitry Andric { ARM::VST3LNq16Pseudo,     ARM::VST3LNq16,     false, false, false, EvenDblSpc, 3, 4,true},
3630b57cec5SDimitry Andric { ARM::VST3LNq16Pseudo_UPD, ARM::VST3LNq16_UPD, false, true, true,  EvenDblSpc, 3, 4,true},
3640b57cec5SDimitry Andric { ARM::VST3LNq32Pseudo,     ARM::VST3LNq32,     false, false, false, EvenDblSpc, 3, 2,true},
3650b57cec5SDimitry Andric { ARM::VST3LNq32Pseudo_UPD, ARM::VST3LNq32_UPD, false, true, true,  EvenDblSpc, 3, 2,true},
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric { ARM::VST3d16Pseudo,       ARM::VST3d16,      false, false, false, SingleSpc,  3, 4 ,true},
3680b57cec5SDimitry Andric { ARM::VST3d16Pseudo_UPD,   ARM::VST3d16_UPD, false, true, true,  SingleSpc,  3, 4 ,true},
3690b57cec5SDimitry Andric { ARM::VST3d32Pseudo,       ARM::VST3d32,      false, false, false, SingleSpc,  3, 2 ,true},
3700b57cec5SDimitry Andric { ARM::VST3d32Pseudo_UPD,   ARM::VST3d32_UPD, false, true, true,  SingleSpc,  3, 2 ,true},
3710b57cec5SDimitry Andric { ARM::VST3d8Pseudo,        ARM::VST3d8,       false, false, false, SingleSpc,  3, 8 ,true},
3720b57cec5SDimitry Andric { ARM::VST3d8Pseudo_UPD,    ARM::VST3d8_UPD, false, true, true,  SingleSpc,  3, 8 ,true},
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric { ARM::VST3q16Pseudo_UPD,    ARM::VST3q16_UPD, false, true, true,  EvenDblSpc, 3, 4 ,true},
3750b57cec5SDimitry Andric { ARM::VST3q16oddPseudo,     ARM::VST3q16,     false, false, false, OddDblSpc,  3, 4 ,true},
3760b57cec5SDimitry Andric { ARM::VST3q16oddPseudo_UPD, ARM::VST3q16_UPD, false, true, true,  OddDblSpc,  3, 4 ,true},
3770b57cec5SDimitry Andric { ARM::VST3q32Pseudo_UPD,    ARM::VST3q32_UPD, false, true, true,  EvenDblSpc, 3, 2 ,true},
3780b57cec5SDimitry Andric { ARM::VST3q32oddPseudo,     ARM::VST3q32,     false, false, false, OddDblSpc,  3, 2 ,true},
3790b57cec5SDimitry Andric { ARM::VST3q32oddPseudo_UPD, ARM::VST3q32_UPD, false, true, true,  OddDblSpc,  3, 2 ,true},
3800b57cec5SDimitry Andric { ARM::VST3q8Pseudo_UPD,     ARM::VST3q8_UPD, false, true, true,  EvenDblSpc, 3, 8 ,true},
3810b57cec5SDimitry Andric { ARM::VST3q8oddPseudo,      ARM::VST3q8,      false, false, false, OddDblSpc,  3, 8 ,true},
3820b57cec5SDimitry Andric { ARM::VST3q8oddPseudo_UPD,  ARM::VST3q8_UPD, false, true, true,  OddDblSpc,  3, 8 ,true},
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric { ARM::VST4LNd16Pseudo,     ARM::VST4LNd16,     false, false, false, SingleSpc, 4, 4 ,true},
3850b57cec5SDimitry Andric { ARM::VST4LNd16Pseudo_UPD, ARM::VST4LNd16_UPD, false, true, true,  SingleSpc, 4, 4 ,true},
3860b57cec5SDimitry Andric { ARM::VST4LNd32Pseudo,     ARM::VST4LNd32,     false, false, false, SingleSpc, 4, 2 ,true},
3870b57cec5SDimitry Andric { ARM::VST4LNd32Pseudo_UPD, ARM::VST4LNd32_UPD, false, true, true,  SingleSpc, 4, 2 ,true},
3880b57cec5SDimitry Andric { ARM::VST4LNd8Pseudo,      ARM::VST4LNd8,      false, false, false, SingleSpc, 4, 8 ,true},
3890b57cec5SDimitry Andric { ARM::VST4LNd8Pseudo_UPD,  ARM::VST4LNd8_UPD, false, true, true,  SingleSpc, 4, 8 ,true},
3900b57cec5SDimitry Andric { ARM::VST4LNq16Pseudo,     ARM::VST4LNq16,     false, false, false, EvenDblSpc, 4, 4,true},
3910b57cec5SDimitry Andric { ARM::VST4LNq16Pseudo_UPD, ARM::VST4LNq16_UPD, false, true, true,  EvenDblSpc, 4, 4,true},
3920b57cec5SDimitry Andric { ARM::VST4LNq32Pseudo,     ARM::VST4LNq32,     false, false, false, EvenDblSpc, 4, 2,true},
3930b57cec5SDimitry Andric { ARM::VST4LNq32Pseudo_UPD, ARM::VST4LNq32_UPD, false, true, true,  EvenDblSpc, 4, 2,true},
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric { ARM::VST4d16Pseudo,       ARM::VST4d16,      false, false, false, SingleSpc,  4, 4 ,true},
3960b57cec5SDimitry Andric { ARM::VST4d16Pseudo_UPD,   ARM::VST4d16_UPD, false, true, true,  SingleSpc,  4, 4 ,true},
3970b57cec5SDimitry Andric { ARM::VST4d32Pseudo,       ARM::VST4d32,      false, false, false, SingleSpc,  4, 2 ,true},
3980b57cec5SDimitry Andric { ARM::VST4d32Pseudo_UPD,   ARM::VST4d32_UPD, false, true, true,  SingleSpc,  4, 2 ,true},
3990b57cec5SDimitry Andric { ARM::VST4d8Pseudo,        ARM::VST4d8,       false, false, false, SingleSpc,  4, 8 ,true},
4000b57cec5SDimitry Andric { ARM::VST4d8Pseudo_UPD,    ARM::VST4d8_UPD, false, true, true,  SingleSpc,  4, 8 ,true},
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric { ARM::VST4q16Pseudo_UPD,    ARM::VST4q16_UPD, false, true, true,  EvenDblSpc, 4, 4 ,true},
4030b57cec5SDimitry Andric { ARM::VST4q16oddPseudo,     ARM::VST4q16,     false, false, false, OddDblSpc,  4, 4 ,true},
4040b57cec5SDimitry Andric { ARM::VST4q16oddPseudo_UPD, ARM::VST4q16_UPD, false, true, true,  OddDblSpc,  4, 4 ,true},
4050b57cec5SDimitry Andric { ARM::VST4q32Pseudo_UPD,    ARM::VST4q32_UPD, false, true, true,  EvenDblSpc, 4, 2 ,true},
4060b57cec5SDimitry Andric { ARM::VST4q32oddPseudo,     ARM::VST4q32,     false, false, false, OddDblSpc,  4, 2 ,true},
4070b57cec5SDimitry Andric { ARM::VST4q32oddPseudo_UPD, ARM::VST4q32_UPD, false, true, true,  OddDblSpc,  4, 2 ,true},
4080b57cec5SDimitry Andric { ARM::VST4q8Pseudo_UPD,     ARM::VST4q8_UPD, false, true, true,  EvenDblSpc, 4, 8 ,true},
4090b57cec5SDimitry Andric { ARM::VST4q8oddPseudo,      ARM::VST4q8,      false, false, false, OddDblSpc,  4, 8 ,true},
4100b57cec5SDimitry Andric { ARM::VST4q8oddPseudo_UPD,  ARM::VST4q8_UPD, false, true, true,  OddDblSpc,  4, 8 ,true}
4110b57cec5SDimitry Andric };
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric /// LookupNEONLdSt - Search the NEONLdStTable for information about a NEON
4140b57cec5SDimitry Andric /// load or store pseudo instruction.
4150b57cec5SDimitry Andric static const NEONLdStTableEntry *LookupNEONLdSt(unsigned Opcode) {
4160b57cec5SDimitry Andric #ifndef NDEBUG
4170b57cec5SDimitry Andric   // Make sure the table is sorted.
4180b57cec5SDimitry Andric   static std::atomic<bool> TableChecked(false);
4190b57cec5SDimitry Andric   if (!TableChecked.load(std::memory_order_relaxed)) {
4200b57cec5SDimitry Andric     assert(std::is_sorted(std::begin(NEONLdStTable), std::end(NEONLdStTable)) &&
4210b57cec5SDimitry Andric            "NEONLdStTable is not sorted!");
4220b57cec5SDimitry Andric     TableChecked.store(true, std::memory_order_relaxed);
4230b57cec5SDimitry Andric   }
4240b57cec5SDimitry Andric #endif
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   auto I = llvm::lower_bound(NEONLdStTable, Opcode);
4270b57cec5SDimitry Andric   if (I != std::end(NEONLdStTable) && I->PseudoOpc == Opcode)
4280b57cec5SDimitry Andric     return I;
4290b57cec5SDimitry Andric   return nullptr;
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric /// GetDSubRegs - Get 4 D subregisters of a Q, QQ, or QQQQ register,
4330b57cec5SDimitry Andric /// corresponding to the specified register spacing.  Not all of the results
4340b57cec5SDimitry Andric /// are necessarily valid, e.g., a Q register only has 2 D subregisters.
4350b57cec5SDimitry Andric static void GetDSubRegs(unsigned Reg, NEONRegSpacing RegSpc,
4360b57cec5SDimitry Andric                         const TargetRegisterInfo *TRI, unsigned &D0,
4370b57cec5SDimitry Andric                         unsigned &D1, unsigned &D2, unsigned &D3) {
4380b57cec5SDimitry Andric   if (RegSpc == SingleSpc || RegSpc == SingleLowSpc) {
4390b57cec5SDimitry Andric     D0 = TRI->getSubReg(Reg, ARM::dsub_0);
4400b57cec5SDimitry Andric     D1 = TRI->getSubReg(Reg, ARM::dsub_1);
4410b57cec5SDimitry Andric     D2 = TRI->getSubReg(Reg, ARM::dsub_2);
4420b57cec5SDimitry Andric     D3 = TRI->getSubReg(Reg, ARM::dsub_3);
4430b57cec5SDimitry Andric   } else if (RegSpc == SingleHighQSpc) {
4440b57cec5SDimitry Andric     D0 = TRI->getSubReg(Reg, ARM::dsub_4);
4450b57cec5SDimitry Andric     D1 = TRI->getSubReg(Reg, ARM::dsub_5);
4460b57cec5SDimitry Andric     D2 = TRI->getSubReg(Reg, ARM::dsub_6);
4470b57cec5SDimitry Andric     D3 = TRI->getSubReg(Reg, ARM::dsub_7);
4480b57cec5SDimitry Andric   } else if (RegSpc == SingleHighTSpc) {
4490b57cec5SDimitry Andric     D0 = TRI->getSubReg(Reg, ARM::dsub_3);
4500b57cec5SDimitry Andric     D1 = TRI->getSubReg(Reg, ARM::dsub_4);
4510b57cec5SDimitry Andric     D2 = TRI->getSubReg(Reg, ARM::dsub_5);
4520b57cec5SDimitry Andric     D3 = TRI->getSubReg(Reg, ARM::dsub_6);
4530b57cec5SDimitry Andric   } else if (RegSpc == EvenDblSpc) {
4540b57cec5SDimitry Andric     D0 = TRI->getSubReg(Reg, ARM::dsub_0);
4550b57cec5SDimitry Andric     D1 = TRI->getSubReg(Reg, ARM::dsub_2);
4560b57cec5SDimitry Andric     D2 = TRI->getSubReg(Reg, ARM::dsub_4);
4570b57cec5SDimitry Andric     D3 = TRI->getSubReg(Reg, ARM::dsub_6);
4580b57cec5SDimitry Andric   } else {
4590b57cec5SDimitry Andric     assert(RegSpc == OddDblSpc && "unknown register spacing");
4600b57cec5SDimitry Andric     D0 = TRI->getSubReg(Reg, ARM::dsub_1);
4610b57cec5SDimitry Andric     D1 = TRI->getSubReg(Reg, ARM::dsub_3);
4620b57cec5SDimitry Andric     D2 = TRI->getSubReg(Reg, ARM::dsub_5);
4630b57cec5SDimitry Andric     D3 = TRI->getSubReg(Reg, ARM::dsub_7);
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric /// ExpandVLD - Translate VLD pseudo instructions with Q, QQ or QQQQ register
4680b57cec5SDimitry Andric /// operands to real VLD instructions with D register operands.
4690b57cec5SDimitry Andric void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) {
4700b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
4710b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
4720b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
4750b57cec5SDimitry Andric   assert(TableEntry && TableEntry->IsLoad && "NEONLdStTable lookup failed");
4760b57cec5SDimitry Andric   NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
4770b57cec5SDimitry Andric   unsigned NumRegs = TableEntry->NumRegs;
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
4800b57cec5SDimitry Andric                                     TII->get(TableEntry->RealOpc));
4810b57cec5SDimitry Andric   unsigned OpIdx = 0;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(OpIdx).isDead();
4840b57cec5SDimitry Andric   unsigned DstReg = MI.getOperand(OpIdx++).getReg();
4850b57cec5SDimitry Andric   if(TableEntry->RealOpc == ARM::VLD2DUPd8x2 ||
4860b57cec5SDimitry Andric      TableEntry->RealOpc == ARM::VLD2DUPd16x2 ||
4870b57cec5SDimitry Andric      TableEntry->RealOpc == ARM::VLD2DUPd32x2) {
4880b57cec5SDimitry Andric     unsigned SubRegIndex;
4890b57cec5SDimitry Andric     if (RegSpc == EvenDblSpc) {
4900b57cec5SDimitry Andric       SubRegIndex = ARM::dsub_0;
4910b57cec5SDimitry Andric     } else {
4920b57cec5SDimitry Andric       assert(RegSpc == OddDblSpc && "Unexpected spacing!");
4930b57cec5SDimitry Andric       SubRegIndex = ARM::dsub_1;
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric     unsigned SubReg = TRI->getSubReg(DstReg, SubRegIndex);
4960b57cec5SDimitry Andric     unsigned DstRegPair = TRI->getMatchingSuperReg(SubReg, ARM::dsub_0,
4970b57cec5SDimitry Andric                                                    &ARM::DPairSpcRegClass);
4980b57cec5SDimitry Andric     MIB.addReg(DstRegPair, RegState::Define | getDeadRegState(DstIsDead));
4990b57cec5SDimitry Andric   } else {
5000b57cec5SDimitry Andric     unsigned D0, D1, D2, D3;
5010b57cec5SDimitry Andric     GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);
5020b57cec5SDimitry Andric     MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead));
5030b57cec5SDimitry Andric     if (NumRegs > 1 && TableEntry->copyAllListRegs)
5040b57cec5SDimitry Andric       MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
5050b57cec5SDimitry Andric     if (NumRegs > 2 && TableEntry->copyAllListRegs)
5060b57cec5SDimitry Andric       MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));
5070b57cec5SDimitry Andric     if (NumRegs > 3 && TableEntry->copyAllListRegs)
5080b57cec5SDimitry Andric       MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));
5090b57cec5SDimitry Andric   }
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   if (TableEntry->isUpdating)
5120b57cec5SDimitry Andric     MIB.add(MI.getOperand(OpIdx++));
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   // Copy the addrmode6 operands.
5150b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
5160b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric   // Copy the am6offset operand.
5190b57cec5SDimitry Andric   if (TableEntry->hasWritebackOperand) {
5200b57cec5SDimitry Andric     // TODO: The writing-back pseudo instructions we translate here are all
5210b57cec5SDimitry Andric     // defined to take am6offset nodes that are capable to represent both fixed
5220b57cec5SDimitry Andric     // and register forms. Some real instructions, however, do not rely on
5230b57cec5SDimitry Andric     // am6offset and have separate definitions for such forms. When this is the
5240b57cec5SDimitry Andric     // case, fixed forms do not take any offset nodes, so here we skip them for
5250b57cec5SDimitry Andric     // such instructions. Once all real and pseudo writing-back instructions are
5260b57cec5SDimitry Andric     // rewritten without use of am6offset nodes, this code will go away.
5270b57cec5SDimitry Andric     const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);
5280b57cec5SDimitry Andric     if (TableEntry->RealOpc == ARM::VLD1d8Qwb_fixed ||
5290b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VLD1d16Qwb_fixed ||
5300b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VLD1d32Qwb_fixed ||
5310b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VLD1d64Qwb_fixed ||
5320b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VLD1d8Twb_fixed ||
5330b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VLD1d16Twb_fixed ||
5340b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VLD1d32Twb_fixed ||
5350b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VLD1d64Twb_fixed) {
5360b57cec5SDimitry Andric       assert(AM6Offset.getReg() == 0 &&
5370b57cec5SDimitry Andric              "A fixed writing-back pseudo instruction provides an offset "
5380b57cec5SDimitry Andric              "register!");
5390b57cec5SDimitry Andric     } else {
5400b57cec5SDimitry Andric       MIB.add(AM6Offset);
5410b57cec5SDimitry Andric     }
5420b57cec5SDimitry Andric   }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   // For an instruction writing double-spaced subregs, the pseudo instruction
5450b57cec5SDimitry Andric   // has an extra operand that is a use of the super-register.  Record the
5460b57cec5SDimitry Andric   // operand index and skip over it.
5470b57cec5SDimitry Andric   unsigned SrcOpIdx = 0;
5480b57cec5SDimitry Andric   if(TableEntry->RealOpc != ARM::VLD2DUPd8x2 &&
5490b57cec5SDimitry Andric      TableEntry->RealOpc != ARM::VLD2DUPd16x2 &&
5500b57cec5SDimitry Andric      TableEntry->RealOpc != ARM::VLD2DUPd32x2) {
5510b57cec5SDimitry Andric     if (RegSpc == EvenDblSpc || RegSpc == OddDblSpc ||
5520b57cec5SDimitry Andric         RegSpc == SingleLowSpc || RegSpc == SingleHighQSpc ||
5530b57cec5SDimitry Andric         RegSpc == SingleHighTSpc)
5540b57cec5SDimitry Andric       SrcOpIdx = OpIdx++;
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   // Copy the predicate operands.
5580b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
5590b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   // Copy the super-register source operand used for double-spaced subregs over
5620b57cec5SDimitry Andric   // to the new instruction as an implicit operand.
5630b57cec5SDimitry Andric   if (SrcOpIdx != 0) {
5640b57cec5SDimitry Andric     MachineOperand MO = MI.getOperand(SrcOpIdx);
5650b57cec5SDimitry Andric     MO.setImplicit(true);
5660b57cec5SDimitry Andric     MIB.add(MO);
5670b57cec5SDimitry Andric   }
5680b57cec5SDimitry Andric   // Add an implicit def for the super-register.
5690b57cec5SDimitry Andric   MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
5700b57cec5SDimitry Andric   TransferImpOps(MI, MIB, MIB);
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   // Transfer memoperands.
5730b57cec5SDimitry Andric   MIB.cloneMemRefs(MI);
5740b57cec5SDimitry Andric   MI.eraseFromParent();
5750b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "To:        "; MIB.getInstr()->dump(););
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric /// ExpandVST - Translate VST pseudo instructions with Q, QQ or QQQQ register
5790b57cec5SDimitry Andric /// operands to real VST instructions with D register operands.
5800b57cec5SDimitry Andric void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) {
5810b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
5820b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
5830b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
5860b57cec5SDimitry Andric   assert(TableEntry && !TableEntry->IsLoad && "NEONLdStTable lookup failed");
5870b57cec5SDimitry Andric   NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
5880b57cec5SDimitry Andric   unsigned NumRegs = TableEntry->NumRegs;
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
5910b57cec5SDimitry Andric                                     TII->get(TableEntry->RealOpc));
5920b57cec5SDimitry Andric   unsigned OpIdx = 0;
5930b57cec5SDimitry Andric   if (TableEntry->isUpdating)
5940b57cec5SDimitry Andric     MIB.add(MI.getOperand(OpIdx++));
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   // Copy the addrmode6 operands.
5970b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
5980b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   if (TableEntry->hasWritebackOperand) {
6010b57cec5SDimitry Andric     // TODO: The writing-back pseudo instructions we translate here are all
6020b57cec5SDimitry Andric     // defined to take am6offset nodes that are capable to represent both fixed
6030b57cec5SDimitry Andric     // and register forms. Some real instructions, however, do not rely on
6040b57cec5SDimitry Andric     // am6offset and have separate definitions for such forms. When this is the
6050b57cec5SDimitry Andric     // case, fixed forms do not take any offset nodes, so here we skip them for
6060b57cec5SDimitry Andric     // such instructions. Once all real and pseudo writing-back instructions are
6070b57cec5SDimitry Andric     // rewritten without use of am6offset nodes, this code will go away.
6080b57cec5SDimitry Andric     const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);
6090b57cec5SDimitry Andric     if (TableEntry->RealOpc == ARM::VST1d8Qwb_fixed ||
6100b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VST1d16Qwb_fixed ||
6110b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VST1d32Qwb_fixed ||
6120b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VST1d64Qwb_fixed ||
6130b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VST1d8Twb_fixed ||
6140b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VST1d16Twb_fixed ||
6150b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VST1d32Twb_fixed ||
6160b57cec5SDimitry Andric         TableEntry->RealOpc == ARM::VST1d64Twb_fixed) {
6170b57cec5SDimitry Andric       assert(AM6Offset.getReg() == 0 &&
6180b57cec5SDimitry Andric              "A fixed writing-back pseudo instruction provides an offset "
6190b57cec5SDimitry Andric              "register!");
6200b57cec5SDimitry Andric     } else {
6210b57cec5SDimitry Andric       MIB.add(AM6Offset);
6220b57cec5SDimitry Andric     }
6230b57cec5SDimitry Andric   }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(OpIdx).isKill();
6260b57cec5SDimitry Andric   bool SrcIsUndef = MI.getOperand(OpIdx).isUndef();
6270b57cec5SDimitry Andric   unsigned SrcReg = MI.getOperand(OpIdx++).getReg();
6280b57cec5SDimitry Andric   unsigned D0, D1, D2, D3;
6290b57cec5SDimitry Andric   GetDSubRegs(SrcReg, RegSpc, TRI, D0, D1, D2, D3);
6300b57cec5SDimitry Andric   MIB.addReg(D0, getUndefRegState(SrcIsUndef));
6310b57cec5SDimitry Andric   if (NumRegs > 1 && TableEntry->copyAllListRegs)
6320b57cec5SDimitry Andric     MIB.addReg(D1, getUndefRegState(SrcIsUndef));
6330b57cec5SDimitry Andric   if (NumRegs > 2 && TableEntry->copyAllListRegs)
6340b57cec5SDimitry Andric     MIB.addReg(D2, getUndefRegState(SrcIsUndef));
6350b57cec5SDimitry Andric   if (NumRegs > 3 && TableEntry->copyAllListRegs)
6360b57cec5SDimitry Andric     MIB.addReg(D3, getUndefRegState(SrcIsUndef));
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   // Copy the predicate operands.
6390b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
6400b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   if (SrcIsKill && !SrcIsUndef) // Add an implicit kill for the super-reg.
6430b57cec5SDimitry Andric     MIB->addRegisterKilled(SrcReg, TRI, true);
6440b57cec5SDimitry Andric   else if (!SrcIsUndef)
6450b57cec5SDimitry Andric     MIB.addReg(SrcReg, RegState::Implicit); // Add implicit uses for src reg.
6460b57cec5SDimitry Andric   TransferImpOps(MI, MIB, MIB);
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   // Transfer memoperands.
6490b57cec5SDimitry Andric   MIB.cloneMemRefs(MI);
6500b57cec5SDimitry Andric   MI.eraseFromParent();
6510b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "To:        "; MIB.getInstr()->dump(););
6520b57cec5SDimitry Andric }
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric /// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ
6550b57cec5SDimitry Andric /// register operands to real instructions with D register operands.
6560b57cec5SDimitry Andric void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) {
6570b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
6580b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
6590b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
6620b57cec5SDimitry Andric   assert(TableEntry && "NEONLdStTable lookup failed");
6630b57cec5SDimitry Andric   NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
6640b57cec5SDimitry Andric   unsigned NumRegs = TableEntry->NumRegs;
6650b57cec5SDimitry Andric   unsigned RegElts = TableEntry->RegElts;
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
6680b57cec5SDimitry Andric                                     TII->get(TableEntry->RealOpc));
6690b57cec5SDimitry Andric   unsigned OpIdx = 0;
6700b57cec5SDimitry Andric   // The lane operand is always the 3rd from last operand, before the 2
6710b57cec5SDimitry Andric   // predicate operands.
6720b57cec5SDimitry Andric   unsigned Lane = MI.getOperand(MI.getDesc().getNumOperands() - 3).getImm();
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   // Adjust the lane and spacing as needed for Q registers.
6750b57cec5SDimitry Andric   assert(RegSpc != OddDblSpc && "unexpected register spacing for VLD/VST-lane");
6760b57cec5SDimitry Andric   if (RegSpc == EvenDblSpc && Lane >= RegElts) {
6770b57cec5SDimitry Andric     RegSpc = OddDblSpc;
6780b57cec5SDimitry Andric     Lane -= RegElts;
6790b57cec5SDimitry Andric   }
6800b57cec5SDimitry Andric   assert(Lane < RegElts && "out of range lane for VLD/VST-lane");
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   unsigned D0 = 0, D1 = 0, D2 = 0, D3 = 0;
6830b57cec5SDimitry Andric   unsigned DstReg = 0;
6840b57cec5SDimitry Andric   bool DstIsDead = false;
6850b57cec5SDimitry Andric   if (TableEntry->IsLoad) {
6860b57cec5SDimitry Andric     DstIsDead = MI.getOperand(OpIdx).isDead();
6870b57cec5SDimitry Andric     DstReg = MI.getOperand(OpIdx++).getReg();
6880b57cec5SDimitry Andric     GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);
6890b57cec5SDimitry Andric     MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead));
6900b57cec5SDimitry Andric     if (NumRegs > 1)
6910b57cec5SDimitry Andric       MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
6920b57cec5SDimitry Andric     if (NumRegs > 2)
6930b57cec5SDimitry Andric       MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));
6940b57cec5SDimitry Andric     if (NumRegs > 3)
6950b57cec5SDimitry Andric       MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));
6960b57cec5SDimitry Andric   }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric   if (TableEntry->isUpdating)
6990b57cec5SDimitry Andric     MIB.add(MI.getOperand(OpIdx++));
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric   // Copy the addrmode6 operands.
7020b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
7030b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
7040b57cec5SDimitry Andric   // Copy the am6offset operand.
7050b57cec5SDimitry Andric   if (TableEntry->hasWritebackOperand)
7060b57cec5SDimitry Andric     MIB.add(MI.getOperand(OpIdx++));
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   // Grab the super-register source.
7090b57cec5SDimitry Andric   MachineOperand MO = MI.getOperand(OpIdx++);
7100b57cec5SDimitry Andric   if (!TableEntry->IsLoad)
7110b57cec5SDimitry Andric     GetDSubRegs(MO.getReg(), RegSpc, TRI, D0, D1, D2, D3);
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric   // Add the subregs as sources of the new instruction.
7140b57cec5SDimitry Andric   unsigned SrcFlags = (getUndefRegState(MO.isUndef()) |
7150b57cec5SDimitry Andric                        getKillRegState(MO.isKill()));
7160b57cec5SDimitry Andric   MIB.addReg(D0, SrcFlags);
7170b57cec5SDimitry Andric   if (NumRegs > 1)
7180b57cec5SDimitry Andric     MIB.addReg(D1, SrcFlags);
7190b57cec5SDimitry Andric   if (NumRegs > 2)
7200b57cec5SDimitry Andric     MIB.addReg(D2, SrcFlags);
7210b57cec5SDimitry Andric   if (NumRegs > 3)
7220b57cec5SDimitry Andric     MIB.addReg(D3, SrcFlags);
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric   // Add the lane number operand.
7250b57cec5SDimitry Andric   MIB.addImm(Lane);
7260b57cec5SDimitry Andric   OpIdx += 1;
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   // Copy the predicate operands.
7290b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
7300b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   // Copy the super-register source to be an implicit source.
7330b57cec5SDimitry Andric   MO.setImplicit(true);
7340b57cec5SDimitry Andric   MIB.add(MO);
7350b57cec5SDimitry Andric   if (TableEntry->IsLoad)
7360b57cec5SDimitry Andric     // Add an implicit def for the super-register.
7370b57cec5SDimitry Andric     MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
7380b57cec5SDimitry Andric   TransferImpOps(MI, MIB, MIB);
7390b57cec5SDimitry Andric   // Transfer memoperands.
7400b57cec5SDimitry Andric   MIB.cloneMemRefs(MI);
7410b57cec5SDimitry Andric   MI.eraseFromParent();
7420b57cec5SDimitry Andric }
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric /// ExpandVTBL - Translate VTBL and VTBX pseudo instructions with Q or QQ
7450b57cec5SDimitry Andric /// register operands to real instructions with D register operands.
7460b57cec5SDimitry Andric void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI,
7470b57cec5SDimitry Andric                                  unsigned Opc, bool IsExt) {
7480b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
7490b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
7500b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc));
7530b57cec5SDimitry Andric   unsigned OpIdx = 0;
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric   // Transfer the destination register operand.
7560b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
7570b57cec5SDimitry Andric   if (IsExt) {
7580b57cec5SDimitry Andric     MachineOperand VdSrc(MI.getOperand(OpIdx++));
7590b57cec5SDimitry Andric     MIB.add(VdSrc);
7600b57cec5SDimitry Andric   }
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   bool SrcIsKill = MI.getOperand(OpIdx).isKill();
7630b57cec5SDimitry Andric   unsigned SrcReg = MI.getOperand(OpIdx++).getReg();
7640b57cec5SDimitry Andric   unsigned D0, D1, D2, D3;
7650b57cec5SDimitry Andric   GetDSubRegs(SrcReg, SingleSpc, TRI, D0, D1, D2, D3);
7660b57cec5SDimitry Andric   MIB.addReg(D0);
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   // Copy the other source register operand.
7690b57cec5SDimitry Andric   MachineOperand VmSrc(MI.getOperand(OpIdx++));
7700b57cec5SDimitry Andric   MIB.add(VmSrc);
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric   // Copy the predicate operands.
7730b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
7740b57cec5SDimitry Andric   MIB.add(MI.getOperand(OpIdx++));
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric   // Add an implicit kill and use for the super-reg.
7770b57cec5SDimitry Andric   MIB.addReg(SrcReg, RegState::Implicit | getKillRegState(SrcIsKill));
7780b57cec5SDimitry Andric   TransferImpOps(MI, MIB, MIB);
7790b57cec5SDimitry Andric   MI.eraseFromParent();
7800b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "To:        "; MIB.getInstr()->dump(););
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric static bool IsAnAddressOperand(const MachineOperand &MO) {
7840b57cec5SDimitry Andric   // This check is overly conservative.  Unless we are certain that the machine
7850b57cec5SDimitry Andric   // operand is not a symbol reference, we return that it is a symbol reference.
7860b57cec5SDimitry Andric   // This is important as the load pair may not be split up Windows.
7870b57cec5SDimitry Andric   switch (MO.getType()) {
7880b57cec5SDimitry Andric   case MachineOperand::MO_Register:
7890b57cec5SDimitry Andric   case MachineOperand::MO_Immediate:
7900b57cec5SDimitry Andric   case MachineOperand::MO_CImmediate:
7910b57cec5SDimitry Andric   case MachineOperand::MO_FPImmediate:
7920b57cec5SDimitry Andric     return false;
7930b57cec5SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
7940b57cec5SDimitry Andric     return true;
7950b57cec5SDimitry Andric   case MachineOperand::MO_FrameIndex:
7960b57cec5SDimitry Andric     return false;
7970b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
7980b57cec5SDimitry Andric   case MachineOperand::MO_TargetIndex:
7990b57cec5SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
8000b57cec5SDimitry Andric   case MachineOperand::MO_ExternalSymbol:
8010b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
8020b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress:
8030b57cec5SDimitry Andric     return true;
8040b57cec5SDimitry Andric   case MachineOperand::MO_RegisterMask:
8050b57cec5SDimitry Andric   case MachineOperand::MO_RegisterLiveOut:
8060b57cec5SDimitry Andric     return false;
8070b57cec5SDimitry Andric   case MachineOperand::MO_Metadata:
8080b57cec5SDimitry Andric   case MachineOperand::MO_MCSymbol:
8090b57cec5SDimitry Andric     return true;
8100b57cec5SDimitry Andric   case MachineOperand::MO_CFIIndex:
8110b57cec5SDimitry Andric     return false;
8120b57cec5SDimitry Andric   case MachineOperand::MO_IntrinsicID:
8130b57cec5SDimitry Andric   case MachineOperand::MO_Predicate:
8140b57cec5SDimitry Andric     llvm_unreachable("should not exist post-isel");
8150b57cec5SDimitry Andric   }
8160b57cec5SDimitry Andric   llvm_unreachable("unhandled machine operand type");
8170b57cec5SDimitry Andric }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric static MachineOperand makeImplicit(const MachineOperand &MO) {
8200b57cec5SDimitry Andric   MachineOperand NewMO = MO;
8210b57cec5SDimitry Andric   NewMO.setImplicit();
8220b57cec5SDimitry Andric   return NewMO;
8230b57cec5SDimitry Andric }
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB,
8260b57cec5SDimitry Andric                                         MachineBasicBlock::iterator &MBBI) {
8270b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
8280b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
8290b57cec5SDimitry Andric   unsigned PredReg = 0;
8300b57cec5SDimitry Andric   ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
8310b57cec5SDimitry Andric   unsigned DstReg = MI.getOperand(0).getReg();
8320b57cec5SDimitry Andric   bool DstIsDead = MI.getOperand(0).isDead();
8330b57cec5SDimitry Andric   bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm;
8340b57cec5SDimitry Andric   const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1);
8350b57cec5SDimitry Andric   bool RequiresBundling = STI->isTargetWindows() && IsAnAddressOperand(MO);
8360b57cec5SDimitry Andric   MachineInstrBuilder LO16, HI16;
8370b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric   if (!STI->hasV6T2Ops() &&
8400b57cec5SDimitry Andric       (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) {
8410b57cec5SDimitry Andric     // FIXME Windows CE supports older ARM CPUs
8420b57cec5SDimitry Andric     assert(!STI->isTargetWindows() && "Windows on ARM requires ARMv7+");
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric     // Expand into a movi + orr.
8450b57cec5SDimitry Andric     LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg);
8460b57cec5SDimitry Andric     HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri))
8470b57cec5SDimitry Andric       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
8480b57cec5SDimitry Andric       .addReg(DstReg);
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric     assert (MO.isImm() && "MOVi32imm w/ non-immediate source operand!");
8510b57cec5SDimitry Andric     unsigned ImmVal = (unsigned)MO.getImm();
8520b57cec5SDimitry Andric     unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);
8530b57cec5SDimitry Andric     unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);
8540b57cec5SDimitry Andric     LO16 = LO16.addImm(SOImmValV1);
8550b57cec5SDimitry Andric     HI16 = HI16.addImm(SOImmValV2);
8560b57cec5SDimitry Andric     LO16.cloneMemRefs(MI);
8570b57cec5SDimitry Andric     HI16.cloneMemRefs(MI);
8580b57cec5SDimitry Andric     LO16.addImm(Pred).addReg(PredReg).add(condCodeOp());
8590b57cec5SDimitry Andric     HI16.addImm(Pred).addReg(PredReg).add(condCodeOp());
8600b57cec5SDimitry Andric     if (isCC)
8610b57cec5SDimitry Andric       LO16.add(makeImplicit(MI.getOperand(1)));
8620b57cec5SDimitry Andric     TransferImpOps(MI, LO16, HI16);
8630b57cec5SDimitry Andric     MI.eraseFromParent();
8640b57cec5SDimitry Andric     return;
8650b57cec5SDimitry Andric   }
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric   unsigned LO16Opc = 0;
8680b57cec5SDimitry Andric   unsigned HI16Opc = 0;
8690b57cec5SDimitry Andric   if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) {
8700b57cec5SDimitry Andric     LO16Opc = ARM::t2MOVi16;
8710b57cec5SDimitry Andric     HI16Opc = ARM::t2MOVTi16;
8720b57cec5SDimitry Andric   } else {
8730b57cec5SDimitry Andric     LO16Opc = ARM::MOVi16;
8740b57cec5SDimitry Andric     HI16Opc = ARM::MOVTi16;
8750b57cec5SDimitry Andric   }
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric   LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg);
8780b57cec5SDimitry Andric   HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc))
8790b57cec5SDimitry Andric     .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
8800b57cec5SDimitry Andric     .addReg(DstReg);
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric   switch (MO.getType()) {
8830b57cec5SDimitry Andric   case MachineOperand::MO_Immediate: {
8840b57cec5SDimitry Andric     unsigned Imm = MO.getImm();
8850b57cec5SDimitry Andric     unsigned Lo16 = Imm & 0xffff;
8860b57cec5SDimitry Andric     unsigned Hi16 = (Imm >> 16) & 0xffff;
8870b57cec5SDimitry Andric     LO16 = LO16.addImm(Lo16);
8880b57cec5SDimitry Andric     HI16 = HI16.addImm(Hi16);
8890b57cec5SDimitry Andric     break;
8900b57cec5SDimitry Andric   }
8910b57cec5SDimitry Andric   case MachineOperand::MO_ExternalSymbol: {
8920b57cec5SDimitry Andric     const char *ES = MO.getSymbolName();
8930b57cec5SDimitry Andric     unsigned TF = MO.getTargetFlags();
8940b57cec5SDimitry Andric     LO16 = LO16.addExternalSymbol(ES, TF | ARMII::MO_LO16);
8950b57cec5SDimitry Andric     HI16 = HI16.addExternalSymbol(ES, TF | ARMII::MO_HI16);
8960b57cec5SDimitry Andric     break;
8970b57cec5SDimitry Andric   }
8980b57cec5SDimitry Andric   default: {
8990b57cec5SDimitry Andric     const GlobalValue *GV = MO.getGlobal();
9000b57cec5SDimitry Andric     unsigned TF = MO.getTargetFlags();
9010b57cec5SDimitry Andric     LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16);
9020b57cec5SDimitry Andric     HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16);
9030b57cec5SDimitry Andric     break;
9040b57cec5SDimitry Andric   }
9050b57cec5SDimitry Andric   }
9060b57cec5SDimitry Andric 
9070b57cec5SDimitry Andric   LO16.cloneMemRefs(MI);
9080b57cec5SDimitry Andric   HI16.cloneMemRefs(MI);
9090b57cec5SDimitry Andric   LO16.addImm(Pred).addReg(PredReg);
9100b57cec5SDimitry Andric   HI16.addImm(Pred).addReg(PredReg);
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   if (RequiresBundling)
9130b57cec5SDimitry Andric     finalizeBundle(MBB, LO16->getIterator(), MBBI->getIterator());
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric   if (isCC)
9160b57cec5SDimitry Andric     LO16.add(makeImplicit(MI.getOperand(1)));
9170b57cec5SDimitry Andric   TransferImpOps(MI, LO16, HI16);
9180b57cec5SDimitry Andric   MI.eraseFromParent();
9190b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "To:        "; LO16.getInstr()->dump(););
9200b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "And:       "; HI16.getInstr()->dump(););
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric /// Expand a CMP_SWAP pseudo-inst to an ldrex/strex loop as simply as
9240b57cec5SDimitry Andric /// possible. This only gets used at -O0 so we don't care about efficiency of
9250b57cec5SDimitry Andric /// the generated code.
9260b57cec5SDimitry Andric bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
9270b57cec5SDimitry Andric                                      MachineBasicBlock::iterator MBBI,
9280b57cec5SDimitry Andric                                      unsigned LdrexOp, unsigned StrexOp,
9290b57cec5SDimitry Andric                                      unsigned UxtOp,
9300b57cec5SDimitry Andric                                      MachineBasicBlock::iterator &NextMBBI) {
9310b57cec5SDimitry Andric   bool IsThumb = STI->isThumb();
9320b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
9330b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
9340b57cec5SDimitry Andric   const MachineOperand &Dest = MI.getOperand(0);
9350b57cec5SDimitry Andric   unsigned TempReg = MI.getOperand(1).getReg();
9360b57cec5SDimitry Andric   // Duplicating undef operands into 2 instructions does not guarantee the same
9370b57cec5SDimitry Andric   // value on both; However undef should be replaced by xzr anyway.
9380b57cec5SDimitry Andric   assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
9390b57cec5SDimitry Andric   unsigned AddrReg = MI.getOperand(2).getReg();
9400b57cec5SDimitry Andric   unsigned DesiredReg = MI.getOperand(3).getReg();
9410b57cec5SDimitry Andric   unsigned NewReg = MI.getOperand(4).getReg();
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric   MachineFunction *MF = MBB.getParent();
9440b57cec5SDimitry Andric   auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
9450b57cec5SDimitry Andric   auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
9460b57cec5SDimitry Andric   auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric   MF->insert(++MBB.getIterator(), LoadCmpBB);
9490b57cec5SDimitry Andric   MF->insert(++LoadCmpBB->getIterator(), StoreBB);
9500b57cec5SDimitry Andric   MF->insert(++StoreBB->getIterator(), DoneBB);
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric   if (UxtOp) {
9530b57cec5SDimitry Andric     MachineInstrBuilder MIB =
9540b57cec5SDimitry Andric         BuildMI(MBB, MBBI, DL, TII->get(UxtOp), DesiredReg)
9550b57cec5SDimitry Andric             .addReg(DesiredReg, RegState::Kill);
9560b57cec5SDimitry Andric     if (!IsThumb)
9570b57cec5SDimitry Andric       MIB.addImm(0);
9580b57cec5SDimitry Andric     MIB.add(predOps(ARMCC::AL));
9590b57cec5SDimitry Andric   }
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   // .Lloadcmp:
9620b57cec5SDimitry Andric   //     ldrex rDest, [rAddr]
9630b57cec5SDimitry Andric   //     cmp rDest, rDesired
9640b57cec5SDimitry Andric   //     bne .Ldone
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric   MachineInstrBuilder MIB;
9670b57cec5SDimitry Andric   MIB = BuildMI(LoadCmpBB, DL, TII->get(LdrexOp), Dest.getReg());
9680b57cec5SDimitry Andric   MIB.addReg(AddrReg);
9690b57cec5SDimitry Andric   if (LdrexOp == ARM::t2LDREX)
9700b57cec5SDimitry Andric     MIB.addImm(0); // a 32-bit Thumb ldrex (only) allows an offset.
9710b57cec5SDimitry Andric   MIB.add(predOps(ARMCC::AL));
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric   unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
9740b57cec5SDimitry Andric   BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
9750b57cec5SDimitry Andric       .addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
9760b57cec5SDimitry Andric       .addReg(DesiredReg)
9770b57cec5SDimitry Andric       .add(predOps(ARMCC::AL));
9780b57cec5SDimitry Andric   unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
9790b57cec5SDimitry Andric   BuildMI(LoadCmpBB, DL, TII->get(Bcc))
9800b57cec5SDimitry Andric       .addMBB(DoneBB)
9810b57cec5SDimitry Andric       .addImm(ARMCC::NE)
9820b57cec5SDimitry Andric       .addReg(ARM::CPSR, RegState::Kill);
9830b57cec5SDimitry Andric   LoadCmpBB->addSuccessor(DoneBB);
9840b57cec5SDimitry Andric   LoadCmpBB->addSuccessor(StoreBB);
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric   // .Lstore:
9870b57cec5SDimitry Andric   //     strex rTempReg, rNew, [rAddr]
9880b57cec5SDimitry Andric   //     cmp rTempReg, #0
9890b57cec5SDimitry Andric   //     bne .Lloadcmp
9900b57cec5SDimitry Andric   MIB = BuildMI(StoreBB, DL, TII->get(StrexOp), TempReg)
9910b57cec5SDimitry Andric     .addReg(NewReg)
9920b57cec5SDimitry Andric     .addReg(AddrReg);
9930b57cec5SDimitry Andric   if (StrexOp == ARM::t2STREX)
9940b57cec5SDimitry Andric     MIB.addImm(0); // a 32-bit Thumb strex (only) allows an offset.
9950b57cec5SDimitry Andric   MIB.add(predOps(ARMCC::AL));
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;
9980b57cec5SDimitry Andric   BuildMI(StoreBB, DL, TII->get(CMPri))
9990b57cec5SDimitry Andric       .addReg(TempReg, RegState::Kill)
10000b57cec5SDimitry Andric       .addImm(0)
10010b57cec5SDimitry Andric       .add(predOps(ARMCC::AL));
10020b57cec5SDimitry Andric   BuildMI(StoreBB, DL, TII->get(Bcc))
10030b57cec5SDimitry Andric       .addMBB(LoadCmpBB)
10040b57cec5SDimitry Andric       .addImm(ARMCC::NE)
10050b57cec5SDimitry Andric       .addReg(ARM::CPSR, RegState::Kill);
10060b57cec5SDimitry Andric   StoreBB->addSuccessor(LoadCmpBB);
10070b57cec5SDimitry Andric   StoreBB->addSuccessor(DoneBB);
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
10100b57cec5SDimitry Andric   DoneBB->transferSuccessors(&MBB);
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric   MBB.addSuccessor(LoadCmpBB);
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   NextMBBI = MBB.end();
10150b57cec5SDimitry Andric   MI.eraseFromParent();
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   // Recompute livein lists.
10180b57cec5SDimitry Andric   LivePhysRegs LiveRegs;
10190b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *DoneBB);
10200b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *StoreBB);
10210b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
10220b57cec5SDimitry Andric   // Do an extra pass around the loop to get loop carried registers right.
10230b57cec5SDimitry Andric   StoreBB->clearLiveIns();
10240b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *StoreBB);
10250b57cec5SDimitry Andric   LoadCmpBB->clearLiveIns();
10260b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric   return true;
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric /// ARM's ldrexd/strexd take a consecutive register pair (represented as a
10320b57cec5SDimitry Andric /// single GPRPair register), Thumb's take two separate registers so we need to
10330b57cec5SDimitry Andric /// extract the subregs from the pair.
10340b57cec5SDimitry Andric static void addExclusiveRegPair(MachineInstrBuilder &MIB, MachineOperand &Reg,
10350b57cec5SDimitry Andric                                 unsigned Flags, bool IsThumb,
10360b57cec5SDimitry Andric                                 const TargetRegisterInfo *TRI) {
10370b57cec5SDimitry Andric   if (IsThumb) {
10380b57cec5SDimitry Andric     unsigned RegLo = TRI->getSubReg(Reg.getReg(), ARM::gsub_0);
10390b57cec5SDimitry Andric     unsigned RegHi = TRI->getSubReg(Reg.getReg(), ARM::gsub_1);
10400b57cec5SDimitry Andric     MIB.addReg(RegLo, Flags);
10410b57cec5SDimitry Andric     MIB.addReg(RegHi, Flags);
10420b57cec5SDimitry Andric   } else
10430b57cec5SDimitry Andric     MIB.addReg(Reg.getReg(), Flags);
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric /// Expand a 64-bit CMP_SWAP to an ldrexd/strexd loop.
10470b57cec5SDimitry Andric bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
10480b57cec5SDimitry Andric                                         MachineBasicBlock::iterator MBBI,
10490b57cec5SDimitry Andric                                         MachineBasicBlock::iterator &NextMBBI) {
10500b57cec5SDimitry Andric   bool IsThumb = STI->isThumb();
10510b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
10520b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
10530b57cec5SDimitry Andric   MachineOperand &Dest = MI.getOperand(0);
10540b57cec5SDimitry Andric   unsigned TempReg = MI.getOperand(1).getReg();
10550b57cec5SDimitry Andric   // Duplicating undef operands into 2 instructions does not guarantee the same
10560b57cec5SDimitry Andric   // value on both; However undef should be replaced by xzr anyway.
10570b57cec5SDimitry Andric   assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
10580b57cec5SDimitry Andric   unsigned AddrReg = MI.getOperand(2).getReg();
10590b57cec5SDimitry Andric   unsigned DesiredReg = MI.getOperand(3).getReg();
10600b57cec5SDimitry Andric   MachineOperand New = MI.getOperand(4);
10610b57cec5SDimitry Andric   New.setIsKill(false);
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   unsigned DestLo = TRI->getSubReg(Dest.getReg(), ARM::gsub_0);
10640b57cec5SDimitry Andric   unsigned DestHi = TRI->getSubReg(Dest.getReg(), ARM::gsub_1);
10650b57cec5SDimitry Andric   unsigned DesiredLo = TRI->getSubReg(DesiredReg, ARM::gsub_0);
10660b57cec5SDimitry Andric   unsigned DesiredHi = TRI->getSubReg(DesiredReg, ARM::gsub_1);
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   MachineFunction *MF = MBB.getParent();
10690b57cec5SDimitry Andric   auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
10700b57cec5SDimitry Andric   auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
10710b57cec5SDimitry Andric   auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   MF->insert(++MBB.getIterator(), LoadCmpBB);
10740b57cec5SDimitry Andric   MF->insert(++LoadCmpBB->getIterator(), StoreBB);
10750b57cec5SDimitry Andric   MF->insert(++StoreBB->getIterator(), DoneBB);
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric   // .Lloadcmp:
10780b57cec5SDimitry Andric   //     ldrexd rDestLo, rDestHi, [rAddr]
10790b57cec5SDimitry Andric   //     cmp rDestLo, rDesiredLo
10800b57cec5SDimitry Andric   //     sbcs dead rTempReg, rDestHi, rDesiredHi
10810b57cec5SDimitry Andric   //     bne .Ldone
10820b57cec5SDimitry Andric   unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;
10830b57cec5SDimitry Andric   MachineInstrBuilder MIB;
10840b57cec5SDimitry Andric   MIB = BuildMI(LoadCmpBB, DL, TII->get(LDREXD));
10850b57cec5SDimitry Andric   addExclusiveRegPair(MIB, Dest, RegState::Define, IsThumb, TRI);
10860b57cec5SDimitry Andric   MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
10890b57cec5SDimitry Andric   BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
10900b57cec5SDimitry Andric       .addReg(DestLo, getKillRegState(Dest.isDead()))
10910b57cec5SDimitry Andric       .addReg(DesiredLo)
10920b57cec5SDimitry Andric       .add(predOps(ARMCC::AL));
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric   BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
10950b57cec5SDimitry Andric       .addReg(DestHi, getKillRegState(Dest.isDead()))
10960b57cec5SDimitry Andric       .addReg(DesiredHi)
10970b57cec5SDimitry Andric       .addImm(ARMCC::EQ).addReg(ARM::CPSR, RegState::Kill);
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
11000b57cec5SDimitry Andric   BuildMI(LoadCmpBB, DL, TII->get(Bcc))
11010b57cec5SDimitry Andric       .addMBB(DoneBB)
11020b57cec5SDimitry Andric       .addImm(ARMCC::NE)
11030b57cec5SDimitry Andric       .addReg(ARM::CPSR, RegState::Kill);
11040b57cec5SDimitry Andric   LoadCmpBB->addSuccessor(DoneBB);
11050b57cec5SDimitry Andric   LoadCmpBB->addSuccessor(StoreBB);
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   // .Lstore:
11080b57cec5SDimitry Andric   //     strexd rTempReg, rNewLo, rNewHi, [rAddr]
11090b57cec5SDimitry Andric   //     cmp rTempReg, #0
11100b57cec5SDimitry Andric   //     bne .Lloadcmp
11110b57cec5SDimitry Andric   unsigned STREXD = IsThumb ? ARM::t2STREXD : ARM::STREXD;
11120b57cec5SDimitry Andric   MIB = BuildMI(StoreBB, DL, TII->get(STREXD), TempReg);
11130b57cec5SDimitry Andric   unsigned Flags = getKillRegState(New.isDead());
11140b57cec5SDimitry Andric   addExclusiveRegPair(MIB, New, Flags, IsThumb, TRI);
11150b57cec5SDimitry Andric   MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric   unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;
11180b57cec5SDimitry Andric   BuildMI(StoreBB, DL, TII->get(CMPri))
11190b57cec5SDimitry Andric       .addReg(TempReg, RegState::Kill)
11200b57cec5SDimitry Andric       .addImm(0)
11210b57cec5SDimitry Andric       .add(predOps(ARMCC::AL));
11220b57cec5SDimitry Andric   BuildMI(StoreBB, DL, TII->get(Bcc))
11230b57cec5SDimitry Andric       .addMBB(LoadCmpBB)
11240b57cec5SDimitry Andric       .addImm(ARMCC::NE)
11250b57cec5SDimitry Andric       .addReg(ARM::CPSR, RegState::Kill);
11260b57cec5SDimitry Andric   StoreBB->addSuccessor(LoadCmpBB);
11270b57cec5SDimitry Andric   StoreBB->addSuccessor(DoneBB);
11280b57cec5SDimitry Andric 
11290b57cec5SDimitry Andric   DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
11300b57cec5SDimitry Andric   DoneBB->transferSuccessors(&MBB);
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   MBB.addSuccessor(LoadCmpBB);
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   NextMBBI = MBB.end();
11350b57cec5SDimitry Andric   MI.eraseFromParent();
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric   // Recompute livein lists.
11380b57cec5SDimitry Andric   LivePhysRegs LiveRegs;
11390b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *DoneBB);
11400b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *StoreBB);
11410b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
11420b57cec5SDimitry Andric   // Do an extra pass around the loop to get loop carried registers right.
11430b57cec5SDimitry Andric   StoreBB->clearLiveIns();
11440b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *StoreBB);
11450b57cec5SDimitry Andric   LoadCmpBB->clearLiveIns();
11460b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric   return true;
11490b57cec5SDimitry Andric }
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric 
11520b57cec5SDimitry Andric bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
11530b57cec5SDimitry Andric                                MachineBasicBlock::iterator MBBI,
11540b57cec5SDimitry Andric                                MachineBasicBlock::iterator &NextMBBI) {
11550b57cec5SDimitry Andric   MachineInstr &MI = *MBBI;
11560b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
11570b57cec5SDimitry Andric   switch (Opcode) {
11580b57cec5SDimitry Andric     default:
11590b57cec5SDimitry Andric       return false;
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric     case ARM::TCRETURNdi:
11620b57cec5SDimitry Andric     case ARM::TCRETURNri: {
11630b57cec5SDimitry Andric       MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
11640b57cec5SDimitry Andric       assert(MBBI->isReturn() &&
11650b57cec5SDimitry Andric              "Can only insert epilog into returning blocks");
11660b57cec5SDimitry Andric       unsigned RetOpcode = MBBI->getOpcode();
11670b57cec5SDimitry Andric       DebugLoc dl = MBBI->getDebugLoc();
11680b57cec5SDimitry Andric       const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>(
11690b57cec5SDimitry Andric           MBB.getParent()->getSubtarget().getInstrInfo());
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric       // Tail call return: adjust the stack pointer and jump to callee.
11720b57cec5SDimitry Andric       MBBI = MBB.getLastNonDebugInstr();
11730b57cec5SDimitry Andric       MachineOperand &JumpTarget = MBBI->getOperand(0);
11740b57cec5SDimitry Andric 
11750b57cec5SDimitry Andric       // Jump to label or value in register.
11760b57cec5SDimitry Andric       if (RetOpcode == ARM::TCRETURNdi) {
11770b57cec5SDimitry Andric         unsigned TCOpcode =
11780b57cec5SDimitry Andric             STI->isThumb()
11790b57cec5SDimitry Andric                 ? (STI->isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND)
11800b57cec5SDimitry Andric                 : ARM::TAILJMPd;
11810b57cec5SDimitry Andric         MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
11820b57cec5SDimitry Andric         if (JumpTarget.isGlobal())
11830b57cec5SDimitry Andric           MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
11840b57cec5SDimitry Andric                                JumpTarget.getTargetFlags());
11850b57cec5SDimitry Andric         else {
11860b57cec5SDimitry Andric           assert(JumpTarget.isSymbol());
11870b57cec5SDimitry Andric           MIB.addExternalSymbol(JumpTarget.getSymbolName(),
11880b57cec5SDimitry Andric                                 JumpTarget.getTargetFlags());
11890b57cec5SDimitry Andric         }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric         // Add the default predicate in Thumb mode.
11920b57cec5SDimitry Andric         if (STI->isThumb())
11930b57cec5SDimitry Andric           MIB.add(predOps(ARMCC::AL));
11940b57cec5SDimitry Andric       } else if (RetOpcode == ARM::TCRETURNri) {
11950b57cec5SDimitry Andric         unsigned Opcode =
11960b57cec5SDimitry Andric           STI->isThumb() ? ARM::tTAILJMPr
11970b57cec5SDimitry Andric                          : (STI->hasV4TOps() ? ARM::TAILJMPr : ARM::TAILJMPr4);
11980b57cec5SDimitry Andric         BuildMI(MBB, MBBI, dl,
11990b57cec5SDimitry Andric                 TII.get(Opcode))
12000b57cec5SDimitry Andric             .addReg(JumpTarget.getReg(), RegState::Kill);
12010b57cec5SDimitry Andric       }
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric       auto NewMI = std::prev(MBBI);
12040b57cec5SDimitry Andric       for (unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i)
12050b57cec5SDimitry Andric         NewMI->addOperand(MBBI->getOperand(i));
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric       // Delete the pseudo instruction TCRETURN.
12080b57cec5SDimitry Andric       MBB.erase(MBBI);
12090b57cec5SDimitry Andric       MBBI = NewMI;
12100b57cec5SDimitry Andric       return true;
12110b57cec5SDimitry Andric     }
12120b57cec5SDimitry Andric     case ARM::VMOVScc:
12130b57cec5SDimitry Andric     case ARM::VMOVDcc: {
12140b57cec5SDimitry Andric       unsigned newOpc = Opcode == ARM::VMOVScc ? ARM::VMOVS : ARM::VMOVD;
12150b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(newOpc),
12160b57cec5SDimitry Andric               MI.getOperand(1).getReg())
12170b57cec5SDimitry Andric           .add(MI.getOperand(2))
12180b57cec5SDimitry Andric           .addImm(MI.getOperand(3).getImm()) // 'pred'
12190b57cec5SDimitry Andric           .add(MI.getOperand(4))
12200b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric       MI.eraseFromParent();
12230b57cec5SDimitry Andric       return true;
12240b57cec5SDimitry Andric     }
12250b57cec5SDimitry Andric     case ARM::t2MOVCCr:
12260b57cec5SDimitry Andric     case ARM::MOVCCr: {
12270b57cec5SDimitry Andric       unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVr : ARM::MOVr;
12280b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
12290b57cec5SDimitry Andric               MI.getOperand(1).getReg())
12300b57cec5SDimitry Andric           .add(MI.getOperand(2))
12310b57cec5SDimitry Andric           .addImm(MI.getOperand(3).getImm()) // 'pred'
12320b57cec5SDimitry Andric           .add(MI.getOperand(4))
12330b57cec5SDimitry Andric           .add(condCodeOp()) // 's' bit
12340b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric       MI.eraseFromParent();
12370b57cec5SDimitry Andric       return true;
12380b57cec5SDimitry Andric     }
12390b57cec5SDimitry Andric     case ARM::MOVCCsi: {
12400b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
12410b57cec5SDimitry Andric               (MI.getOperand(1).getReg()))
12420b57cec5SDimitry Andric           .add(MI.getOperand(2))
12430b57cec5SDimitry Andric           .addImm(MI.getOperand(3).getImm())
12440b57cec5SDimitry Andric           .addImm(MI.getOperand(4).getImm()) // 'pred'
12450b57cec5SDimitry Andric           .add(MI.getOperand(5))
12460b57cec5SDimitry Andric           .add(condCodeOp()) // 's' bit
12470b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric       MI.eraseFromParent();
12500b57cec5SDimitry Andric       return true;
12510b57cec5SDimitry Andric     }
12520b57cec5SDimitry Andric     case ARM::MOVCCsr: {
12530b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsr),
12540b57cec5SDimitry Andric               (MI.getOperand(1).getReg()))
12550b57cec5SDimitry Andric           .add(MI.getOperand(2))
12560b57cec5SDimitry Andric           .add(MI.getOperand(3))
12570b57cec5SDimitry Andric           .addImm(MI.getOperand(4).getImm())
12580b57cec5SDimitry Andric           .addImm(MI.getOperand(5).getImm()) // 'pred'
12590b57cec5SDimitry Andric           .add(MI.getOperand(6))
12600b57cec5SDimitry Andric           .add(condCodeOp()) // 's' bit
12610b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric       MI.eraseFromParent();
12640b57cec5SDimitry Andric       return true;
12650b57cec5SDimitry Andric     }
12660b57cec5SDimitry Andric     case ARM::t2MOVCCi16:
12670b57cec5SDimitry Andric     case ARM::MOVCCi16: {
12680b57cec5SDimitry Andric       unsigned NewOpc = AFI->isThumbFunction() ? ARM::t2MOVi16 : ARM::MOVi16;
12690b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),
12700b57cec5SDimitry Andric               MI.getOperand(1).getReg())
12710b57cec5SDimitry Andric           .addImm(MI.getOperand(2).getImm())
12720b57cec5SDimitry Andric           .addImm(MI.getOperand(3).getImm()) // 'pred'
12730b57cec5SDimitry Andric           .add(MI.getOperand(4))
12740b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
12750b57cec5SDimitry Andric       MI.eraseFromParent();
12760b57cec5SDimitry Andric       return true;
12770b57cec5SDimitry Andric     }
12780b57cec5SDimitry Andric     case ARM::t2MOVCCi:
12790b57cec5SDimitry Andric     case ARM::MOVCCi: {
12800b57cec5SDimitry Andric       unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVi : ARM::MOVi;
12810b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
12820b57cec5SDimitry Andric               MI.getOperand(1).getReg())
12830b57cec5SDimitry Andric           .addImm(MI.getOperand(2).getImm())
12840b57cec5SDimitry Andric           .addImm(MI.getOperand(3).getImm()) // 'pred'
12850b57cec5SDimitry Andric           .add(MI.getOperand(4))
12860b57cec5SDimitry Andric           .add(condCodeOp()) // 's' bit
12870b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric       MI.eraseFromParent();
12900b57cec5SDimitry Andric       return true;
12910b57cec5SDimitry Andric     }
12920b57cec5SDimitry Andric     case ARM::t2MVNCCi:
12930b57cec5SDimitry Andric     case ARM::MVNCCi: {
12940b57cec5SDimitry Andric       unsigned Opc = AFI->isThumbFunction() ? ARM::t2MVNi : ARM::MVNi;
12950b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
12960b57cec5SDimitry Andric               MI.getOperand(1).getReg())
12970b57cec5SDimitry Andric           .addImm(MI.getOperand(2).getImm())
12980b57cec5SDimitry Andric           .addImm(MI.getOperand(3).getImm()) // 'pred'
12990b57cec5SDimitry Andric           .add(MI.getOperand(4))
13000b57cec5SDimitry Andric           .add(condCodeOp()) // 's' bit
13010b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric       MI.eraseFromParent();
13040b57cec5SDimitry Andric       return true;
13050b57cec5SDimitry Andric     }
13060b57cec5SDimitry Andric     case ARM::t2MOVCClsl:
13070b57cec5SDimitry Andric     case ARM::t2MOVCClsr:
13080b57cec5SDimitry Andric     case ARM::t2MOVCCasr:
13090b57cec5SDimitry Andric     case ARM::t2MOVCCror: {
13100b57cec5SDimitry Andric       unsigned NewOpc;
13110b57cec5SDimitry Andric       switch (Opcode) {
13120b57cec5SDimitry Andric       case ARM::t2MOVCClsl: NewOpc = ARM::t2LSLri; break;
13130b57cec5SDimitry Andric       case ARM::t2MOVCClsr: NewOpc = ARM::t2LSRri; break;
13140b57cec5SDimitry Andric       case ARM::t2MOVCCasr: NewOpc = ARM::t2ASRri; break;
13150b57cec5SDimitry Andric       case ARM::t2MOVCCror: NewOpc = ARM::t2RORri; break;
13160b57cec5SDimitry Andric       default: llvm_unreachable("unexpeced conditional move");
13170b57cec5SDimitry Andric       }
13180b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),
13190b57cec5SDimitry Andric               MI.getOperand(1).getReg())
13200b57cec5SDimitry Andric           .add(MI.getOperand(2))
13210b57cec5SDimitry Andric           .addImm(MI.getOperand(3).getImm())
13220b57cec5SDimitry Andric           .addImm(MI.getOperand(4).getImm()) // 'pred'
13230b57cec5SDimitry Andric           .add(MI.getOperand(5))
13240b57cec5SDimitry Andric           .add(condCodeOp()) // 's' bit
13250b57cec5SDimitry Andric           .add(makeImplicit(MI.getOperand(1)));
13260b57cec5SDimitry Andric       MI.eraseFromParent();
13270b57cec5SDimitry Andric       return true;
13280b57cec5SDimitry Andric     }
13290b57cec5SDimitry Andric     case ARM::Int_eh_sjlj_dispatchsetup: {
13300b57cec5SDimitry Andric       MachineFunction &MF = *MI.getParent()->getParent();
13310b57cec5SDimitry Andric       const ARMBaseInstrInfo *AII =
13320b57cec5SDimitry Andric         static_cast<const ARMBaseInstrInfo*>(TII);
13330b57cec5SDimitry Andric       const ARMBaseRegisterInfo &RI = AII->getRegisterInfo();
13340b57cec5SDimitry Andric       // For functions using a base pointer, we rematerialize it (via the frame
13350b57cec5SDimitry Andric       // pointer) here since eh.sjlj.setjmp and eh.sjlj.longjmp don't do it
13360b57cec5SDimitry Andric       // for us. Otherwise, expand to nothing.
13370b57cec5SDimitry Andric       if (RI.hasBasePointer(MF)) {
13380b57cec5SDimitry Andric         int32_t NumBytes = AFI->getFramePtrSpillOffset();
13390b57cec5SDimitry Andric         unsigned FramePtr = RI.getFrameRegister(MF);
13400b57cec5SDimitry Andric         assert(MF.getSubtarget().getFrameLowering()->hasFP(MF) &&
13410b57cec5SDimitry Andric                "base pointer without frame pointer?");
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric         if (AFI->isThumb2Function()) {
13440b57cec5SDimitry Andric           emitT2RegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
13450b57cec5SDimitry Andric                                  FramePtr, -NumBytes, ARMCC::AL, 0, *TII);
13460b57cec5SDimitry Andric         } else if (AFI->isThumbFunction()) {
13470b57cec5SDimitry Andric           emitThumbRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
13480b57cec5SDimitry Andric                                     FramePtr, -NumBytes, *TII, RI);
13490b57cec5SDimitry Andric         } else {
13500b57cec5SDimitry Andric           emitARMRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
13510b57cec5SDimitry Andric                                   FramePtr, -NumBytes, ARMCC::AL, 0,
13520b57cec5SDimitry Andric                                   *TII);
13530b57cec5SDimitry Andric         }
13540b57cec5SDimitry Andric         // If there's dynamic realignment, adjust for it.
13550b57cec5SDimitry Andric         if (RI.needsStackRealignment(MF)) {
13560b57cec5SDimitry Andric           MachineFrameInfo &MFI = MF.getFrameInfo();
13570b57cec5SDimitry Andric           unsigned MaxAlign = MFI.getMaxAlignment();
13580b57cec5SDimitry Andric           assert (!AFI->isThumb1OnlyFunction());
13590b57cec5SDimitry Andric           // Emit bic r6, r6, MaxAlign
13600b57cec5SDimitry Andric           assert(MaxAlign <= 256 && "The BIC instruction cannot encode "
13610b57cec5SDimitry Andric                                     "immediates larger than 256 with all lower "
13620b57cec5SDimitry Andric                                     "bits set.");
13630b57cec5SDimitry Andric           unsigned bicOpc = AFI->isThumbFunction() ?
13640b57cec5SDimitry Andric             ARM::t2BICri : ARM::BICri;
13650b57cec5SDimitry Andric           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(bicOpc), ARM::R6)
13660b57cec5SDimitry Andric               .addReg(ARM::R6, RegState::Kill)
13670b57cec5SDimitry Andric               .addImm(MaxAlign - 1)
13680b57cec5SDimitry Andric               .add(predOps(ARMCC::AL))
13690b57cec5SDimitry Andric               .add(condCodeOp());
13700b57cec5SDimitry Andric         }
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric       }
13730b57cec5SDimitry Andric       MI.eraseFromParent();
13740b57cec5SDimitry Andric       return true;
13750b57cec5SDimitry Andric     }
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric     case ARM::MOVsrl_flag:
13780b57cec5SDimitry Andric     case ARM::MOVsra_flag: {
13790b57cec5SDimitry Andric       // These are just fancy MOVs instructions.
13800b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
13810b57cec5SDimitry Andric               MI.getOperand(0).getReg())
13820b57cec5SDimitry Andric           .add(MI.getOperand(1))
13830b57cec5SDimitry Andric           .addImm(ARM_AM::getSORegOpc(
13840b57cec5SDimitry Andric               (Opcode == ARM::MOVsrl_flag ? ARM_AM::lsr : ARM_AM::asr), 1))
13850b57cec5SDimitry Andric           .add(predOps(ARMCC::AL))
13860b57cec5SDimitry Andric           .addReg(ARM::CPSR, RegState::Define);
13870b57cec5SDimitry Andric       MI.eraseFromParent();
13880b57cec5SDimitry Andric       return true;
13890b57cec5SDimitry Andric     }
13900b57cec5SDimitry Andric     case ARM::RRX: {
13910b57cec5SDimitry Andric       // This encodes as "MOVs Rd, Rm, rrx
13920b57cec5SDimitry Andric       MachineInstrBuilder MIB =
13930b57cec5SDimitry Andric           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
13940b57cec5SDimitry Andric                   MI.getOperand(0).getReg())
13950b57cec5SDimitry Andric               .add(MI.getOperand(1))
13960b57cec5SDimitry Andric               .addImm(ARM_AM::getSORegOpc(ARM_AM::rrx, 0))
13970b57cec5SDimitry Andric               .add(predOps(ARMCC::AL))
13980b57cec5SDimitry Andric               .add(condCodeOp());
13990b57cec5SDimitry Andric       TransferImpOps(MI, MIB, MIB);
14000b57cec5SDimitry Andric       MI.eraseFromParent();
14010b57cec5SDimitry Andric       return true;
14020b57cec5SDimitry Andric     }
14030b57cec5SDimitry Andric     case ARM::tTPsoft:
14040b57cec5SDimitry Andric     case ARM::TPsoft: {
14050b57cec5SDimitry Andric       const bool Thumb = Opcode == ARM::tTPsoft;
14060b57cec5SDimitry Andric 
14070b57cec5SDimitry Andric       MachineInstrBuilder MIB;
14080b57cec5SDimitry Andric       if (STI->genLongCalls()) {
14090b57cec5SDimitry Andric         MachineFunction *MF = MBB.getParent();
14100b57cec5SDimitry Andric         MachineConstantPool *MCP = MF->getConstantPool();
14110b57cec5SDimitry Andric         unsigned PCLabelID = AFI->createPICLabelUId();
14120b57cec5SDimitry Andric         MachineConstantPoolValue *CPV =
14130b57cec5SDimitry Andric             ARMConstantPoolSymbol::Create(MF->getFunction().getContext(),
14140b57cec5SDimitry Andric                                           "__aeabi_read_tp", PCLabelID, 0);
14150b57cec5SDimitry Andric         unsigned Reg = MI.getOperand(0).getReg();
14160b57cec5SDimitry Andric         MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
14170b57cec5SDimitry Andric                       TII->get(Thumb ? ARM::tLDRpci : ARM::LDRi12), Reg)
14180b57cec5SDimitry Andric                   .addConstantPoolIndex(MCP->getConstantPoolIndex(CPV, 4));
14190b57cec5SDimitry Andric         if (!Thumb)
14200b57cec5SDimitry Andric           MIB.addImm(0);
14210b57cec5SDimitry Andric         MIB.add(predOps(ARMCC::AL));
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric         MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
14240b57cec5SDimitry Andric                       TII->get(Thumb ? ARM::tBLXr : ARM::BLX));
14250b57cec5SDimitry Andric         if (Thumb)
14260b57cec5SDimitry Andric           MIB.add(predOps(ARMCC::AL));
14270b57cec5SDimitry Andric         MIB.addReg(Reg, RegState::Kill);
14280b57cec5SDimitry Andric       } else {
14290b57cec5SDimitry Andric         MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
14300b57cec5SDimitry Andric                       TII->get(Thumb ? ARM::tBL : ARM::BL));
14310b57cec5SDimitry Andric         if (Thumb)
14320b57cec5SDimitry Andric           MIB.add(predOps(ARMCC::AL));
14330b57cec5SDimitry Andric         MIB.addExternalSymbol("__aeabi_read_tp", 0);
14340b57cec5SDimitry Andric       }
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric       MIB.cloneMemRefs(MI);
14370b57cec5SDimitry Andric       TransferImpOps(MI, MIB, MIB);
14380b57cec5SDimitry Andric       MI.eraseFromParent();
14390b57cec5SDimitry Andric       return true;
14400b57cec5SDimitry Andric     }
14410b57cec5SDimitry Andric     case ARM::tLDRpci_pic:
14420b57cec5SDimitry Andric     case ARM::t2LDRpci_pic: {
14430b57cec5SDimitry Andric       unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
14440b57cec5SDimitry Andric         ? ARM::tLDRpci : ARM::t2LDRpci;
14450b57cec5SDimitry Andric       unsigned DstReg = MI.getOperand(0).getReg();
14460b57cec5SDimitry Andric       bool DstIsDead = MI.getOperand(0).isDead();
14470b57cec5SDimitry Andric       MachineInstrBuilder MIB1 =
14480b57cec5SDimitry Andric           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewLdOpc), DstReg)
14490b57cec5SDimitry Andric               .add(MI.getOperand(1))
14500b57cec5SDimitry Andric               .add(predOps(ARMCC::AL));
14510b57cec5SDimitry Andric       MIB1.cloneMemRefs(MI);
14520b57cec5SDimitry Andric       MachineInstrBuilder MIB2 =
14530b57cec5SDimitry Andric           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD))
14540b57cec5SDimitry Andric               .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
14550b57cec5SDimitry Andric               .addReg(DstReg)
14560b57cec5SDimitry Andric               .add(MI.getOperand(2));
14570b57cec5SDimitry Andric       TransferImpOps(MI, MIB1, MIB2);
14580b57cec5SDimitry Andric       MI.eraseFromParent();
14590b57cec5SDimitry Andric       return true;
14600b57cec5SDimitry Andric     }
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric     case ARM::LDRLIT_ga_abs:
14630b57cec5SDimitry Andric     case ARM::LDRLIT_ga_pcrel:
14640b57cec5SDimitry Andric     case ARM::LDRLIT_ga_pcrel_ldr:
14650b57cec5SDimitry Andric     case ARM::tLDRLIT_ga_abs:
14660b57cec5SDimitry Andric     case ARM::tLDRLIT_ga_pcrel: {
14670b57cec5SDimitry Andric       unsigned DstReg = MI.getOperand(0).getReg();
14680b57cec5SDimitry Andric       bool DstIsDead = MI.getOperand(0).isDead();
14690b57cec5SDimitry Andric       const MachineOperand &MO1 = MI.getOperand(1);
14700b57cec5SDimitry Andric       auto Flags = MO1.getTargetFlags();
14710b57cec5SDimitry Andric       const GlobalValue *GV = MO1.getGlobal();
14720b57cec5SDimitry Andric       bool IsARM =
14730b57cec5SDimitry Andric           Opcode != ARM::tLDRLIT_ga_pcrel && Opcode != ARM::tLDRLIT_ga_abs;
14740b57cec5SDimitry Andric       bool IsPIC =
14750b57cec5SDimitry Andric           Opcode != ARM::LDRLIT_ga_abs && Opcode != ARM::tLDRLIT_ga_abs;
14760b57cec5SDimitry Andric       unsigned LDRLITOpc = IsARM ? ARM::LDRi12 : ARM::tLDRpci;
14770b57cec5SDimitry Andric       unsigned PICAddOpc =
14780b57cec5SDimitry Andric           IsARM
14790b57cec5SDimitry Andric               ? (Opcode == ARM::LDRLIT_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)
14800b57cec5SDimitry Andric               : ARM::tPICADD;
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric       // We need a new const-pool entry to load from.
14830b57cec5SDimitry Andric       MachineConstantPool *MCP = MBB.getParent()->getConstantPool();
14840b57cec5SDimitry Andric       unsigned ARMPCLabelIndex = 0;
14850b57cec5SDimitry Andric       MachineConstantPoolValue *CPV;
14860b57cec5SDimitry Andric 
14870b57cec5SDimitry Andric       if (IsPIC) {
14880b57cec5SDimitry Andric         unsigned PCAdj = IsARM ? 8 : 4;
14890b57cec5SDimitry Andric         auto Modifier = (Flags & ARMII::MO_GOT)
14900b57cec5SDimitry Andric                             ? ARMCP::GOT_PREL
14910b57cec5SDimitry Andric                             : ARMCP::no_modifier;
14920b57cec5SDimitry Andric         ARMPCLabelIndex = AFI->createPICLabelUId();
14930b57cec5SDimitry Andric         CPV = ARMConstantPoolConstant::Create(
14940b57cec5SDimitry Andric             GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj, Modifier,
14950b57cec5SDimitry Andric             /*AddCurrentAddr*/ Modifier == ARMCP::GOT_PREL);
14960b57cec5SDimitry Andric       } else
14970b57cec5SDimitry Andric         CPV = ARMConstantPoolConstant::Create(GV, ARMCP::no_modifier);
14980b57cec5SDimitry Andric 
14990b57cec5SDimitry Andric       MachineInstrBuilder MIB =
15000b57cec5SDimitry Andric           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LDRLITOpc), DstReg)
15010b57cec5SDimitry Andric             .addConstantPoolIndex(MCP->getConstantPoolIndex(CPV, 4));
15020b57cec5SDimitry Andric       if (IsARM)
15030b57cec5SDimitry Andric         MIB.addImm(0);
15040b57cec5SDimitry Andric       MIB.add(predOps(ARMCC::AL));
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric       if (IsPIC) {
15070b57cec5SDimitry Andric         MachineInstrBuilder MIB =
15080b57cec5SDimitry Andric           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(PICAddOpc))
15090b57cec5SDimitry Andric             .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
15100b57cec5SDimitry Andric             .addReg(DstReg)
15110b57cec5SDimitry Andric             .addImm(ARMPCLabelIndex);
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric         if (IsARM)
15140b57cec5SDimitry Andric           MIB.add(predOps(ARMCC::AL));
15150b57cec5SDimitry Andric       }
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric       MI.eraseFromParent();
15180b57cec5SDimitry Andric       return true;
15190b57cec5SDimitry Andric     }
15200b57cec5SDimitry Andric     case ARM::MOV_ga_pcrel:
15210b57cec5SDimitry Andric     case ARM::MOV_ga_pcrel_ldr:
15220b57cec5SDimitry Andric     case ARM::t2MOV_ga_pcrel: {
15230b57cec5SDimitry Andric       // Expand into movw + movw. Also "add pc" / ldr [pc] in PIC mode.
15240b57cec5SDimitry Andric       unsigned LabelId = AFI->createPICLabelUId();
15250b57cec5SDimitry Andric       unsigned DstReg = MI.getOperand(0).getReg();
15260b57cec5SDimitry Andric       bool DstIsDead = MI.getOperand(0).isDead();
15270b57cec5SDimitry Andric       const MachineOperand &MO1 = MI.getOperand(1);
15280b57cec5SDimitry Andric       const GlobalValue *GV = MO1.getGlobal();
15290b57cec5SDimitry Andric       unsigned TF = MO1.getTargetFlags();
15300b57cec5SDimitry Andric       bool isARM = Opcode != ARM::t2MOV_ga_pcrel;
15310b57cec5SDimitry Andric       unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel;
15320b57cec5SDimitry Andric       unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel;
15330b57cec5SDimitry Andric       unsigned LO16TF = TF | ARMII::MO_LO16;
15340b57cec5SDimitry Andric       unsigned HI16TF = TF | ARMII::MO_HI16;
15350b57cec5SDimitry Andric       unsigned PICAddOpc = isARM
15360b57cec5SDimitry Andric         ? (Opcode == ARM::MOV_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)
15370b57cec5SDimitry Andric         : ARM::tPICADD;
15380b57cec5SDimitry Andric       MachineInstrBuilder MIB1 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
15390b57cec5SDimitry Andric                                          TII->get(LO16Opc), DstReg)
15400b57cec5SDimitry Andric         .addGlobalAddress(GV, MO1.getOffset(), TF | LO16TF)
15410b57cec5SDimitry Andric         .addImm(LabelId);
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric       BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc), DstReg)
15440b57cec5SDimitry Andric         .addReg(DstReg)
15450b57cec5SDimitry Andric         .addGlobalAddress(GV, MO1.getOffset(), TF | HI16TF)
15460b57cec5SDimitry Andric         .addImm(LabelId);
15470b57cec5SDimitry Andric 
15480b57cec5SDimitry Andric       MachineInstrBuilder MIB3 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
15490b57cec5SDimitry Andric                                          TII->get(PICAddOpc))
15500b57cec5SDimitry Andric         .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
15510b57cec5SDimitry Andric         .addReg(DstReg).addImm(LabelId);
15520b57cec5SDimitry Andric       if (isARM) {
15530b57cec5SDimitry Andric         MIB3.add(predOps(ARMCC::AL));
15540b57cec5SDimitry Andric         if (Opcode == ARM::MOV_ga_pcrel_ldr)
15550b57cec5SDimitry Andric           MIB3.cloneMemRefs(MI);
15560b57cec5SDimitry Andric       }
15570b57cec5SDimitry Andric       TransferImpOps(MI, MIB1, MIB3);
15580b57cec5SDimitry Andric       MI.eraseFromParent();
15590b57cec5SDimitry Andric       return true;
15600b57cec5SDimitry Andric     }
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric     case ARM::MOVi32imm:
15630b57cec5SDimitry Andric     case ARM::MOVCCi32imm:
15640b57cec5SDimitry Andric     case ARM::t2MOVi32imm:
15650b57cec5SDimitry Andric     case ARM::t2MOVCCi32imm:
15660b57cec5SDimitry Andric       ExpandMOV32BitImm(MBB, MBBI);
15670b57cec5SDimitry Andric       return true;
15680b57cec5SDimitry Andric 
15690b57cec5SDimitry Andric     case ARM::SUBS_PC_LR: {
15700b57cec5SDimitry Andric       MachineInstrBuilder MIB =
15710b57cec5SDimitry Andric           BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri), ARM::PC)
15720b57cec5SDimitry Andric               .addReg(ARM::LR)
15730b57cec5SDimitry Andric               .add(MI.getOperand(0))
15740b57cec5SDimitry Andric               .add(MI.getOperand(1))
15750b57cec5SDimitry Andric               .add(MI.getOperand(2))
15760b57cec5SDimitry Andric               .addReg(ARM::CPSR, RegState::Undef);
15770b57cec5SDimitry Andric       TransferImpOps(MI, MIB, MIB);
15780b57cec5SDimitry Andric       MI.eraseFromParent();
15790b57cec5SDimitry Andric       return true;
15800b57cec5SDimitry Andric     }
15810b57cec5SDimitry Andric     case ARM::VLDMQIA: {
15820b57cec5SDimitry Andric       unsigned NewOpc = ARM::VLDMDIA;
15830b57cec5SDimitry Andric       MachineInstrBuilder MIB =
15840b57cec5SDimitry Andric         BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
15850b57cec5SDimitry Andric       unsigned OpIdx = 0;
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric       // Grab the Q register destination.
15880b57cec5SDimitry Andric       bool DstIsDead = MI.getOperand(OpIdx).isDead();
15890b57cec5SDimitry Andric       unsigned DstReg = MI.getOperand(OpIdx++).getReg();
15900b57cec5SDimitry Andric 
15910b57cec5SDimitry Andric       // Copy the source register.
15920b57cec5SDimitry Andric       MIB.add(MI.getOperand(OpIdx++));
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric       // Copy the predicate operands.
15950b57cec5SDimitry Andric       MIB.add(MI.getOperand(OpIdx++));
15960b57cec5SDimitry Andric       MIB.add(MI.getOperand(OpIdx++));
15970b57cec5SDimitry Andric 
15980b57cec5SDimitry Andric       // Add the destination operands (D subregs).
15990b57cec5SDimitry Andric       unsigned D0 = TRI->getSubReg(DstReg, ARM::dsub_0);
16000b57cec5SDimitry Andric       unsigned D1 = TRI->getSubReg(DstReg, ARM::dsub_1);
16010b57cec5SDimitry Andric       MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))
16020b57cec5SDimitry Andric         .addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric       // Add an implicit def for the super-register.
16050b57cec5SDimitry Andric       MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
16060b57cec5SDimitry Andric       TransferImpOps(MI, MIB, MIB);
16070b57cec5SDimitry Andric       MIB.cloneMemRefs(MI);
16080b57cec5SDimitry Andric       MI.eraseFromParent();
16090b57cec5SDimitry Andric       return true;
16100b57cec5SDimitry Andric     }
16110b57cec5SDimitry Andric 
16120b57cec5SDimitry Andric     case ARM::VSTMQIA: {
16130b57cec5SDimitry Andric       unsigned NewOpc = ARM::VSTMDIA;
16140b57cec5SDimitry Andric       MachineInstrBuilder MIB =
16150b57cec5SDimitry Andric         BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
16160b57cec5SDimitry Andric       unsigned OpIdx = 0;
16170b57cec5SDimitry Andric 
16180b57cec5SDimitry Andric       // Grab the Q register source.
16190b57cec5SDimitry Andric       bool SrcIsKill = MI.getOperand(OpIdx).isKill();
16200b57cec5SDimitry Andric       unsigned SrcReg = MI.getOperand(OpIdx++).getReg();
16210b57cec5SDimitry Andric 
16220b57cec5SDimitry Andric       // Copy the destination register.
16230b57cec5SDimitry Andric       MachineOperand Dst(MI.getOperand(OpIdx++));
16240b57cec5SDimitry Andric       MIB.add(Dst);
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric       // Copy the predicate operands.
16270b57cec5SDimitry Andric       MIB.add(MI.getOperand(OpIdx++));
16280b57cec5SDimitry Andric       MIB.add(MI.getOperand(OpIdx++));
16290b57cec5SDimitry Andric 
16300b57cec5SDimitry Andric       // Add the source operands (D subregs).
16310b57cec5SDimitry Andric       unsigned D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);
16320b57cec5SDimitry Andric       unsigned D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);
16330b57cec5SDimitry Andric       MIB.addReg(D0, SrcIsKill ? RegState::Kill : 0)
16340b57cec5SDimitry Andric          .addReg(D1, SrcIsKill ? RegState::Kill : 0);
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric       if (SrcIsKill)      // Add an implicit kill for the Q register.
16370b57cec5SDimitry Andric         MIB->addRegisterKilled(SrcReg, TRI, true);
16380b57cec5SDimitry Andric 
16390b57cec5SDimitry Andric       TransferImpOps(MI, MIB, MIB);
16400b57cec5SDimitry Andric       MIB.cloneMemRefs(MI);
16410b57cec5SDimitry Andric       MI.eraseFromParent();
16420b57cec5SDimitry Andric       return true;
16430b57cec5SDimitry Andric     }
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric     case ARM::VLD2q8Pseudo:
16460b57cec5SDimitry Andric     case ARM::VLD2q16Pseudo:
16470b57cec5SDimitry Andric     case ARM::VLD2q32Pseudo:
16480b57cec5SDimitry Andric     case ARM::VLD2q8PseudoWB_fixed:
16490b57cec5SDimitry Andric     case ARM::VLD2q16PseudoWB_fixed:
16500b57cec5SDimitry Andric     case ARM::VLD2q32PseudoWB_fixed:
16510b57cec5SDimitry Andric     case ARM::VLD2q8PseudoWB_register:
16520b57cec5SDimitry Andric     case ARM::VLD2q16PseudoWB_register:
16530b57cec5SDimitry Andric     case ARM::VLD2q32PseudoWB_register:
16540b57cec5SDimitry Andric     case ARM::VLD3d8Pseudo:
16550b57cec5SDimitry Andric     case ARM::VLD3d16Pseudo:
16560b57cec5SDimitry Andric     case ARM::VLD3d32Pseudo:
16570b57cec5SDimitry Andric     case ARM::VLD1d8TPseudo:
16580b57cec5SDimitry Andric     case ARM::VLD1d16TPseudo:
16590b57cec5SDimitry Andric     case ARM::VLD1d32TPseudo:
16600b57cec5SDimitry Andric     case ARM::VLD1d64TPseudo:
16610b57cec5SDimitry Andric     case ARM::VLD1d64TPseudoWB_fixed:
16620b57cec5SDimitry Andric     case ARM::VLD1d64TPseudoWB_register:
16630b57cec5SDimitry Andric     case ARM::VLD3d8Pseudo_UPD:
16640b57cec5SDimitry Andric     case ARM::VLD3d16Pseudo_UPD:
16650b57cec5SDimitry Andric     case ARM::VLD3d32Pseudo_UPD:
16660b57cec5SDimitry Andric     case ARM::VLD3q8Pseudo_UPD:
16670b57cec5SDimitry Andric     case ARM::VLD3q16Pseudo_UPD:
16680b57cec5SDimitry Andric     case ARM::VLD3q32Pseudo_UPD:
16690b57cec5SDimitry Andric     case ARM::VLD3q8oddPseudo:
16700b57cec5SDimitry Andric     case ARM::VLD3q16oddPseudo:
16710b57cec5SDimitry Andric     case ARM::VLD3q32oddPseudo:
16720b57cec5SDimitry Andric     case ARM::VLD3q8oddPseudo_UPD:
16730b57cec5SDimitry Andric     case ARM::VLD3q16oddPseudo_UPD:
16740b57cec5SDimitry Andric     case ARM::VLD3q32oddPseudo_UPD:
16750b57cec5SDimitry Andric     case ARM::VLD4d8Pseudo:
16760b57cec5SDimitry Andric     case ARM::VLD4d16Pseudo:
16770b57cec5SDimitry Andric     case ARM::VLD4d32Pseudo:
16780b57cec5SDimitry Andric     case ARM::VLD1d8QPseudo:
16790b57cec5SDimitry Andric     case ARM::VLD1d16QPseudo:
16800b57cec5SDimitry Andric     case ARM::VLD1d32QPseudo:
16810b57cec5SDimitry Andric     case ARM::VLD1d64QPseudo:
16820b57cec5SDimitry Andric     case ARM::VLD1d64QPseudoWB_fixed:
16830b57cec5SDimitry Andric     case ARM::VLD1d64QPseudoWB_register:
16840b57cec5SDimitry Andric     case ARM::VLD1q8HighQPseudo:
16850b57cec5SDimitry Andric     case ARM::VLD1q8LowQPseudo_UPD:
16860b57cec5SDimitry Andric     case ARM::VLD1q8HighTPseudo:
16870b57cec5SDimitry Andric     case ARM::VLD1q8LowTPseudo_UPD:
16880b57cec5SDimitry Andric     case ARM::VLD1q16HighQPseudo:
16890b57cec5SDimitry Andric     case ARM::VLD1q16LowQPseudo_UPD:
16900b57cec5SDimitry Andric     case ARM::VLD1q16HighTPseudo:
16910b57cec5SDimitry Andric     case ARM::VLD1q16LowTPseudo_UPD:
16920b57cec5SDimitry Andric     case ARM::VLD1q32HighQPseudo:
16930b57cec5SDimitry Andric     case ARM::VLD1q32LowQPseudo_UPD:
16940b57cec5SDimitry Andric     case ARM::VLD1q32HighTPseudo:
16950b57cec5SDimitry Andric     case ARM::VLD1q32LowTPseudo_UPD:
16960b57cec5SDimitry Andric     case ARM::VLD1q64HighQPseudo:
16970b57cec5SDimitry Andric     case ARM::VLD1q64LowQPseudo_UPD:
16980b57cec5SDimitry Andric     case ARM::VLD1q64HighTPseudo:
16990b57cec5SDimitry Andric     case ARM::VLD1q64LowTPseudo_UPD:
17000b57cec5SDimitry Andric     case ARM::VLD4d8Pseudo_UPD:
17010b57cec5SDimitry Andric     case ARM::VLD4d16Pseudo_UPD:
17020b57cec5SDimitry Andric     case ARM::VLD4d32Pseudo_UPD:
17030b57cec5SDimitry Andric     case ARM::VLD4q8Pseudo_UPD:
17040b57cec5SDimitry Andric     case ARM::VLD4q16Pseudo_UPD:
17050b57cec5SDimitry Andric     case ARM::VLD4q32Pseudo_UPD:
17060b57cec5SDimitry Andric     case ARM::VLD4q8oddPseudo:
17070b57cec5SDimitry Andric     case ARM::VLD4q16oddPseudo:
17080b57cec5SDimitry Andric     case ARM::VLD4q32oddPseudo:
17090b57cec5SDimitry Andric     case ARM::VLD4q8oddPseudo_UPD:
17100b57cec5SDimitry Andric     case ARM::VLD4q16oddPseudo_UPD:
17110b57cec5SDimitry Andric     case ARM::VLD4q32oddPseudo_UPD:
17120b57cec5SDimitry Andric     case ARM::VLD3DUPd8Pseudo:
17130b57cec5SDimitry Andric     case ARM::VLD3DUPd16Pseudo:
17140b57cec5SDimitry Andric     case ARM::VLD3DUPd32Pseudo:
17150b57cec5SDimitry Andric     case ARM::VLD3DUPd8Pseudo_UPD:
17160b57cec5SDimitry Andric     case ARM::VLD3DUPd16Pseudo_UPD:
17170b57cec5SDimitry Andric     case ARM::VLD3DUPd32Pseudo_UPD:
17180b57cec5SDimitry Andric     case ARM::VLD4DUPd8Pseudo:
17190b57cec5SDimitry Andric     case ARM::VLD4DUPd16Pseudo:
17200b57cec5SDimitry Andric     case ARM::VLD4DUPd32Pseudo:
17210b57cec5SDimitry Andric     case ARM::VLD4DUPd8Pseudo_UPD:
17220b57cec5SDimitry Andric     case ARM::VLD4DUPd16Pseudo_UPD:
17230b57cec5SDimitry Andric     case ARM::VLD4DUPd32Pseudo_UPD:
17240b57cec5SDimitry Andric     case ARM::VLD2DUPq8EvenPseudo:
17250b57cec5SDimitry Andric     case ARM::VLD2DUPq8OddPseudo:
17260b57cec5SDimitry Andric     case ARM::VLD2DUPq16EvenPseudo:
17270b57cec5SDimitry Andric     case ARM::VLD2DUPq16OddPseudo:
17280b57cec5SDimitry Andric     case ARM::VLD2DUPq32EvenPseudo:
17290b57cec5SDimitry Andric     case ARM::VLD2DUPq32OddPseudo:
17300b57cec5SDimitry Andric     case ARM::VLD3DUPq8EvenPseudo:
17310b57cec5SDimitry Andric     case ARM::VLD3DUPq8OddPseudo:
17320b57cec5SDimitry Andric     case ARM::VLD3DUPq16EvenPseudo:
17330b57cec5SDimitry Andric     case ARM::VLD3DUPq16OddPseudo:
17340b57cec5SDimitry Andric     case ARM::VLD3DUPq32EvenPseudo:
17350b57cec5SDimitry Andric     case ARM::VLD3DUPq32OddPseudo:
17360b57cec5SDimitry Andric     case ARM::VLD4DUPq8EvenPseudo:
17370b57cec5SDimitry Andric     case ARM::VLD4DUPq8OddPseudo:
17380b57cec5SDimitry Andric     case ARM::VLD4DUPq16EvenPseudo:
17390b57cec5SDimitry Andric     case ARM::VLD4DUPq16OddPseudo:
17400b57cec5SDimitry Andric     case ARM::VLD4DUPq32EvenPseudo:
17410b57cec5SDimitry Andric     case ARM::VLD4DUPq32OddPseudo:
17420b57cec5SDimitry Andric       ExpandVLD(MBBI);
17430b57cec5SDimitry Andric       return true;
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric     case ARM::VST2q8Pseudo:
17460b57cec5SDimitry Andric     case ARM::VST2q16Pseudo:
17470b57cec5SDimitry Andric     case ARM::VST2q32Pseudo:
17480b57cec5SDimitry Andric     case ARM::VST2q8PseudoWB_fixed:
17490b57cec5SDimitry Andric     case ARM::VST2q16PseudoWB_fixed:
17500b57cec5SDimitry Andric     case ARM::VST2q32PseudoWB_fixed:
17510b57cec5SDimitry Andric     case ARM::VST2q8PseudoWB_register:
17520b57cec5SDimitry Andric     case ARM::VST2q16PseudoWB_register:
17530b57cec5SDimitry Andric     case ARM::VST2q32PseudoWB_register:
17540b57cec5SDimitry Andric     case ARM::VST3d8Pseudo:
17550b57cec5SDimitry Andric     case ARM::VST3d16Pseudo:
17560b57cec5SDimitry Andric     case ARM::VST3d32Pseudo:
17570b57cec5SDimitry Andric     case ARM::VST1d8TPseudo:
17580b57cec5SDimitry Andric     case ARM::VST1d16TPseudo:
17590b57cec5SDimitry Andric     case ARM::VST1d32TPseudo:
17600b57cec5SDimitry Andric     case ARM::VST1d64TPseudo:
17610b57cec5SDimitry Andric     case ARM::VST3d8Pseudo_UPD:
17620b57cec5SDimitry Andric     case ARM::VST3d16Pseudo_UPD:
17630b57cec5SDimitry Andric     case ARM::VST3d32Pseudo_UPD:
17640b57cec5SDimitry Andric     case ARM::VST1d64TPseudoWB_fixed:
17650b57cec5SDimitry Andric     case ARM::VST1d64TPseudoWB_register:
17660b57cec5SDimitry Andric     case ARM::VST3q8Pseudo_UPD:
17670b57cec5SDimitry Andric     case ARM::VST3q16Pseudo_UPD:
17680b57cec5SDimitry Andric     case ARM::VST3q32Pseudo_UPD:
17690b57cec5SDimitry Andric     case ARM::VST3q8oddPseudo:
17700b57cec5SDimitry Andric     case ARM::VST3q16oddPseudo:
17710b57cec5SDimitry Andric     case ARM::VST3q32oddPseudo:
17720b57cec5SDimitry Andric     case ARM::VST3q8oddPseudo_UPD:
17730b57cec5SDimitry Andric     case ARM::VST3q16oddPseudo_UPD:
17740b57cec5SDimitry Andric     case ARM::VST3q32oddPseudo_UPD:
17750b57cec5SDimitry Andric     case ARM::VST4d8Pseudo:
17760b57cec5SDimitry Andric     case ARM::VST4d16Pseudo:
17770b57cec5SDimitry Andric     case ARM::VST4d32Pseudo:
17780b57cec5SDimitry Andric     case ARM::VST1d8QPseudo:
17790b57cec5SDimitry Andric     case ARM::VST1d16QPseudo:
17800b57cec5SDimitry Andric     case ARM::VST1d32QPseudo:
17810b57cec5SDimitry Andric     case ARM::VST1d64QPseudo:
17820b57cec5SDimitry Andric     case ARM::VST4d8Pseudo_UPD:
17830b57cec5SDimitry Andric     case ARM::VST4d16Pseudo_UPD:
17840b57cec5SDimitry Andric     case ARM::VST4d32Pseudo_UPD:
17850b57cec5SDimitry Andric     case ARM::VST1d64QPseudoWB_fixed:
17860b57cec5SDimitry Andric     case ARM::VST1d64QPseudoWB_register:
17870b57cec5SDimitry Andric     case ARM::VST1q8HighQPseudo:
17880b57cec5SDimitry Andric     case ARM::VST1q8LowQPseudo_UPD:
17890b57cec5SDimitry Andric     case ARM::VST1q8HighTPseudo:
17900b57cec5SDimitry Andric     case ARM::VST1q8LowTPseudo_UPD:
17910b57cec5SDimitry Andric     case ARM::VST1q16HighQPseudo:
17920b57cec5SDimitry Andric     case ARM::VST1q16LowQPseudo_UPD:
17930b57cec5SDimitry Andric     case ARM::VST1q16HighTPseudo:
17940b57cec5SDimitry Andric     case ARM::VST1q16LowTPseudo_UPD:
17950b57cec5SDimitry Andric     case ARM::VST1q32HighQPseudo:
17960b57cec5SDimitry Andric     case ARM::VST1q32LowQPseudo_UPD:
17970b57cec5SDimitry Andric     case ARM::VST1q32HighTPseudo:
17980b57cec5SDimitry Andric     case ARM::VST1q32LowTPseudo_UPD:
17990b57cec5SDimitry Andric     case ARM::VST1q64HighQPseudo:
18000b57cec5SDimitry Andric     case ARM::VST1q64LowQPseudo_UPD:
18010b57cec5SDimitry Andric     case ARM::VST1q64HighTPseudo:
18020b57cec5SDimitry Andric     case ARM::VST1q64LowTPseudo_UPD:
18030b57cec5SDimitry Andric     case ARM::VST4q8Pseudo_UPD:
18040b57cec5SDimitry Andric     case ARM::VST4q16Pseudo_UPD:
18050b57cec5SDimitry Andric     case ARM::VST4q32Pseudo_UPD:
18060b57cec5SDimitry Andric     case ARM::VST4q8oddPseudo:
18070b57cec5SDimitry Andric     case ARM::VST4q16oddPseudo:
18080b57cec5SDimitry Andric     case ARM::VST4q32oddPseudo:
18090b57cec5SDimitry Andric     case ARM::VST4q8oddPseudo_UPD:
18100b57cec5SDimitry Andric     case ARM::VST4q16oddPseudo_UPD:
18110b57cec5SDimitry Andric     case ARM::VST4q32oddPseudo_UPD:
18120b57cec5SDimitry Andric       ExpandVST(MBBI);
18130b57cec5SDimitry Andric       return true;
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric     case ARM::VLD1LNq8Pseudo:
18160b57cec5SDimitry Andric     case ARM::VLD1LNq16Pseudo:
18170b57cec5SDimitry Andric     case ARM::VLD1LNq32Pseudo:
18180b57cec5SDimitry Andric     case ARM::VLD1LNq8Pseudo_UPD:
18190b57cec5SDimitry Andric     case ARM::VLD1LNq16Pseudo_UPD:
18200b57cec5SDimitry Andric     case ARM::VLD1LNq32Pseudo_UPD:
18210b57cec5SDimitry Andric     case ARM::VLD2LNd8Pseudo:
18220b57cec5SDimitry Andric     case ARM::VLD2LNd16Pseudo:
18230b57cec5SDimitry Andric     case ARM::VLD2LNd32Pseudo:
18240b57cec5SDimitry Andric     case ARM::VLD2LNq16Pseudo:
18250b57cec5SDimitry Andric     case ARM::VLD2LNq32Pseudo:
18260b57cec5SDimitry Andric     case ARM::VLD2LNd8Pseudo_UPD:
18270b57cec5SDimitry Andric     case ARM::VLD2LNd16Pseudo_UPD:
18280b57cec5SDimitry Andric     case ARM::VLD2LNd32Pseudo_UPD:
18290b57cec5SDimitry Andric     case ARM::VLD2LNq16Pseudo_UPD:
18300b57cec5SDimitry Andric     case ARM::VLD2LNq32Pseudo_UPD:
18310b57cec5SDimitry Andric     case ARM::VLD3LNd8Pseudo:
18320b57cec5SDimitry Andric     case ARM::VLD3LNd16Pseudo:
18330b57cec5SDimitry Andric     case ARM::VLD3LNd32Pseudo:
18340b57cec5SDimitry Andric     case ARM::VLD3LNq16Pseudo:
18350b57cec5SDimitry Andric     case ARM::VLD3LNq32Pseudo:
18360b57cec5SDimitry Andric     case ARM::VLD3LNd8Pseudo_UPD:
18370b57cec5SDimitry Andric     case ARM::VLD3LNd16Pseudo_UPD:
18380b57cec5SDimitry Andric     case ARM::VLD3LNd32Pseudo_UPD:
18390b57cec5SDimitry Andric     case ARM::VLD3LNq16Pseudo_UPD:
18400b57cec5SDimitry Andric     case ARM::VLD3LNq32Pseudo_UPD:
18410b57cec5SDimitry Andric     case ARM::VLD4LNd8Pseudo:
18420b57cec5SDimitry Andric     case ARM::VLD4LNd16Pseudo:
18430b57cec5SDimitry Andric     case ARM::VLD4LNd32Pseudo:
18440b57cec5SDimitry Andric     case ARM::VLD4LNq16Pseudo:
18450b57cec5SDimitry Andric     case ARM::VLD4LNq32Pseudo:
18460b57cec5SDimitry Andric     case ARM::VLD4LNd8Pseudo_UPD:
18470b57cec5SDimitry Andric     case ARM::VLD4LNd16Pseudo_UPD:
18480b57cec5SDimitry Andric     case ARM::VLD4LNd32Pseudo_UPD:
18490b57cec5SDimitry Andric     case ARM::VLD4LNq16Pseudo_UPD:
18500b57cec5SDimitry Andric     case ARM::VLD4LNq32Pseudo_UPD:
18510b57cec5SDimitry Andric     case ARM::VST1LNq8Pseudo:
18520b57cec5SDimitry Andric     case ARM::VST1LNq16Pseudo:
18530b57cec5SDimitry Andric     case ARM::VST1LNq32Pseudo:
18540b57cec5SDimitry Andric     case ARM::VST1LNq8Pseudo_UPD:
18550b57cec5SDimitry Andric     case ARM::VST1LNq16Pseudo_UPD:
18560b57cec5SDimitry Andric     case ARM::VST1LNq32Pseudo_UPD:
18570b57cec5SDimitry Andric     case ARM::VST2LNd8Pseudo:
18580b57cec5SDimitry Andric     case ARM::VST2LNd16Pseudo:
18590b57cec5SDimitry Andric     case ARM::VST2LNd32Pseudo:
18600b57cec5SDimitry Andric     case ARM::VST2LNq16Pseudo:
18610b57cec5SDimitry Andric     case ARM::VST2LNq32Pseudo:
18620b57cec5SDimitry Andric     case ARM::VST2LNd8Pseudo_UPD:
18630b57cec5SDimitry Andric     case ARM::VST2LNd16Pseudo_UPD:
18640b57cec5SDimitry Andric     case ARM::VST2LNd32Pseudo_UPD:
18650b57cec5SDimitry Andric     case ARM::VST2LNq16Pseudo_UPD:
18660b57cec5SDimitry Andric     case ARM::VST2LNq32Pseudo_UPD:
18670b57cec5SDimitry Andric     case ARM::VST3LNd8Pseudo:
18680b57cec5SDimitry Andric     case ARM::VST3LNd16Pseudo:
18690b57cec5SDimitry Andric     case ARM::VST3LNd32Pseudo:
18700b57cec5SDimitry Andric     case ARM::VST3LNq16Pseudo:
18710b57cec5SDimitry Andric     case ARM::VST3LNq32Pseudo:
18720b57cec5SDimitry Andric     case ARM::VST3LNd8Pseudo_UPD:
18730b57cec5SDimitry Andric     case ARM::VST3LNd16Pseudo_UPD:
18740b57cec5SDimitry Andric     case ARM::VST3LNd32Pseudo_UPD:
18750b57cec5SDimitry Andric     case ARM::VST3LNq16Pseudo_UPD:
18760b57cec5SDimitry Andric     case ARM::VST3LNq32Pseudo_UPD:
18770b57cec5SDimitry Andric     case ARM::VST4LNd8Pseudo:
18780b57cec5SDimitry Andric     case ARM::VST4LNd16Pseudo:
18790b57cec5SDimitry Andric     case ARM::VST4LNd32Pseudo:
18800b57cec5SDimitry Andric     case ARM::VST4LNq16Pseudo:
18810b57cec5SDimitry Andric     case ARM::VST4LNq32Pseudo:
18820b57cec5SDimitry Andric     case ARM::VST4LNd8Pseudo_UPD:
18830b57cec5SDimitry Andric     case ARM::VST4LNd16Pseudo_UPD:
18840b57cec5SDimitry Andric     case ARM::VST4LNd32Pseudo_UPD:
18850b57cec5SDimitry Andric     case ARM::VST4LNq16Pseudo_UPD:
18860b57cec5SDimitry Andric     case ARM::VST4LNq32Pseudo_UPD:
18870b57cec5SDimitry Andric       ExpandLaneOp(MBBI);
18880b57cec5SDimitry Andric       return true;
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric     case ARM::VTBL3Pseudo: ExpandVTBL(MBBI, ARM::VTBL3, false); return true;
18910b57cec5SDimitry Andric     case ARM::VTBL4Pseudo: ExpandVTBL(MBBI, ARM::VTBL4, false); return true;
18920b57cec5SDimitry Andric     case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true); return true;
18930b57cec5SDimitry Andric     case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true); return true;
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric     case ARM::CMP_SWAP_8:
18960b57cec5SDimitry Andric       if (STI->isThumb())
18970b57cec5SDimitry Andric         return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB,
18980b57cec5SDimitry Andric                               ARM::tUXTB, NextMBBI);
18990b57cec5SDimitry Andric       else
19000b57cec5SDimitry Andric         return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXB, ARM::STREXB,
19010b57cec5SDimitry Andric                               ARM::UXTB, NextMBBI);
19020b57cec5SDimitry Andric     case ARM::CMP_SWAP_16:
19030b57cec5SDimitry Andric       if (STI->isThumb())
19040b57cec5SDimitry Andric         return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXH, ARM::t2STREXH,
19050b57cec5SDimitry Andric                               ARM::tUXTH, NextMBBI);
19060b57cec5SDimitry Andric       else
19070b57cec5SDimitry Andric         return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH,
19080b57cec5SDimitry Andric                               ARM::UXTH, NextMBBI);
19090b57cec5SDimitry Andric     case ARM::CMP_SWAP_32:
19100b57cec5SDimitry Andric       if (STI->isThumb())
19110b57cec5SDimitry Andric         return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREX, ARM::t2STREX, 0,
19120b57cec5SDimitry Andric                               NextMBBI);
19130b57cec5SDimitry Andric       else
19140b57cec5SDimitry Andric         return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREX, ARM::STREX, 0, NextMBBI);
19150b57cec5SDimitry Andric 
19160b57cec5SDimitry Andric     case ARM::CMP_SWAP_64:
19170b57cec5SDimitry Andric       return ExpandCMP_SWAP_64(MBB, MBBI, NextMBBI);
19180b57cec5SDimitry Andric   }
19190b57cec5SDimitry Andric }
19200b57cec5SDimitry Andric 
19210b57cec5SDimitry Andric bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
19220b57cec5SDimitry Andric   bool Modified = false;
19230b57cec5SDimitry Andric 
19240b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
19250b57cec5SDimitry Andric   while (MBBI != E) {
19260b57cec5SDimitry Andric     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
19270b57cec5SDimitry Andric     Modified |= ExpandMI(MBB, MBBI, NMBBI);
19280b57cec5SDimitry Andric     MBBI = NMBBI;
19290b57cec5SDimitry Andric   }
19300b57cec5SDimitry Andric 
19310b57cec5SDimitry Andric   return Modified;
19320b57cec5SDimitry Andric }
19330b57cec5SDimitry Andric 
19340b57cec5SDimitry Andric bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
19350b57cec5SDimitry Andric   STI = &static_cast<const ARMSubtarget &>(MF.getSubtarget());
19360b57cec5SDimitry Andric   TII = STI->getInstrInfo();
19370b57cec5SDimitry Andric   TRI = STI->getRegisterInfo();
19380b57cec5SDimitry Andric   AFI = MF.getInfo<ARMFunctionInfo>();
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "********** ARM EXPAND PSEUDO INSTRUCTIONS **********\n"
19410b57cec5SDimitry Andric                     << "********** Function: " << MF.getName() << '\n');
19420b57cec5SDimitry Andric 
19430b57cec5SDimitry Andric   bool Modified = false;
19440b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF)
19450b57cec5SDimitry Andric     Modified |= ExpandMBB(MBB);
19460b57cec5SDimitry Andric   if (VerifyARMPseudo)
19470b57cec5SDimitry Andric     MF.verify(this, "After expanding ARM pseudo instructions.");
19480b57cec5SDimitry Andric 
19490b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "***************************************************\n");
19500b57cec5SDimitry Andric   return Modified;
19510b57cec5SDimitry Andric }
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric /// createARMExpandPseudoPass - returns an instance of the pseudo instruction
19540b57cec5SDimitry Andric /// expansion pass.
19550b57cec5SDimitry Andric FunctionPass *llvm::createARMExpandPseudoPass() {
19560b57cec5SDimitry Andric   return new ARMExpandPseudo();
19570b57cec5SDimitry Andric }
1958