xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARM/ARMInstructionSelector.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
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 /// \file
90b57cec5SDimitry Andric /// This file implements the targeting of the InstructionSelector class for ARM.
100b57cec5SDimitry Andric /// \todo This should be generated by TableGen.
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "ARMRegisterBankInfo.h"
140b57cec5SDimitry Andric #include "ARMSubtarget.h"
150b57cec5SDimitry Andric #include "ARMTargetMachine.h"
1606c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
20480093f4SDimitry Andric #include "llvm/IR/IntrinsicsARM.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #define DEBUG_TYPE "arm-isel"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define GET_GLOBALISEL_PREDICATE_BITSET
300b57cec5SDimitry Andric #include "ARMGenGlobalISel.inc"
310b57cec5SDimitry Andric #undef GET_GLOBALISEL_PREDICATE_BITSET
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric class ARMInstructionSelector : public InstructionSelector {
340b57cec5SDimitry Andric public:
350b57cec5SDimitry Andric   ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
360b57cec5SDimitry Andric                          const ARMRegisterBankInfo &RBI);
370b57cec5SDimitry Andric 
388bcb0991SDimitry Andric   bool select(MachineInstr &I) override;
390b57cec5SDimitry Andric   static const char *getName() { return DEBUG_TYPE; }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric private:
420b57cec5SDimitry Andric   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   struct CmpConstants;
450b57cec5SDimitry Andric   struct InsertInfo;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
480b57cec5SDimitry Andric                  MachineRegisterInfo &MRI) const;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   // Helper for inserting a comparison sequence that sets \p ResReg to either 1
510b57cec5SDimitry Andric   // if \p LHSReg and \p RHSReg are in the relationship defined by \p Cond, or
520b57cec5SDimitry Andric   // \p PrevRes otherwise. In essence, it computes PrevRes OR (LHS Cond RHS).
530b57cec5SDimitry Andric   bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
540b57cec5SDimitry Andric                         ARMCC::CondCodes Cond, unsigned LHSReg, unsigned RHSReg,
550b57cec5SDimitry Andric                         unsigned PrevRes) const;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   // Set \p DestReg to \p Constant.
580b57cec5SDimitry Andric   void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
610b57cec5SDimitry Andric   bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
620b57cec5SDimitry Andric   bool selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   // Check if the types match and both operands have the expected size and
650b57cec5SDimitry Andric   // register bank.
660b57cec5SDimitry Andric   bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
670b57cec5SDimitry Andric                       unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   // Check if the register has the expected size and register bank.
700b57cec5SDimitry Andric   bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
710b57cec5SDimitry Andric                 unsigned ExpectedRegBankID) const;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   const ARMBaseInstrInfo &TII;
740b57cec5SDimitry Andric   const ARMBaseRegisterInfo &TRI;
750b57cec5SDimitry Andric   const ARMBaseTargetMachine &TM;
760b57cec5SDimitry Andric   const ARMRegisterBankInfo &RBI;
770b57cec5SDimitry Andric   const ARMSubtarget &STI;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
800b57cec5SDimitry Andric   // uses "STI." in the code generated by TableGen. If we want to reuse some of
810b57cec5SDimitry Andric   // the custom C++ predicates written for DAGISel, we need to have both around.
820b57cec5SDimitry Andric   const ARMSubtarget *Subtarget = &STI;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   // Store the opcodes that we might need, so we don't have to check what kind
850b57cec5SDimitry Andric   // of subtarget (ARM vs Thumb) we have all the time.
860b57cec5SDimitry Andric   struct OpcodeCache {
870b57cec5SDimitry Andric     unsigned ZEXT16;
880b57cec5SDimitry Andric     unsigned SEXT16;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric     unsigned ZEXT8;
910b57cec5SDimitry Andric     unsigned SEXT8;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric     // Used for implementing ZEXT/SEXT from i1
940b57cec5SDimitry Andric     unsigned AND;
950b57cec5SDimitry Andric     unsigned RSB;
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric     unsigned STORE32;
980b57cec5SDimitry Andric     unsigned LOAD32;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric     unsigned STORE16;
1010b57cec5SDimitry Andric     unsigned LOAD16;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric     unsigned STORE8;
1040b57cec5SDimitry Andric     unsigned LOAD8;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric     unsigned ADDrr;
1070b57cec5SDimitry Andric     unsigned ADDri;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric     // Used for G_ICMP
1100b57cec5SDimitry Andric     unsigned CMPrr;
1110b57cec5SDimitry Andric     unsigned MOVi;
1120b57cec5SDimitry Andric     unsigned MOVCCi;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric     // Used for G_SELECT
1150b57cec5SDimitry Andric     unsigned MOVCCr;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric     unsigned TSTri;
1180b57cec5SDimitry Andric     unsigned Bcc;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric     // Used for G_GLOBAL_VALUE
1210b57cec5SDimitry Andric     unsigned MOVi32imm;
1220b57cec5SDimitry Andric     unsigned ConstPoolLoad;
1230b57cec5SDimitry Andric     unsigned MOV_ga_pcrel;
1240b57cec5SDimitry Andric     unsigned LDRLIT_ga_pcrel;
1250b57cec5SDimitry Andric     unsigned LDRLIT_ga_abs;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     OpcodeCache(const ARMSubtarget &STI);
1280b57cec5SDimitry Andric   } const Opcodes;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   // Select the opcode for simple extensions (that translate to a single SXT/UXT
1310b57cec5SDimitry Andric   // instruction). Extension operations more complicated than that should not
1320b57cec5SDimitry Andric   // invoke this. Returns the original opcode if it doesn't know how to select a
1330b57cec5SDimitry Andric   // better one.
1340b57cec5SDimitry Andric   unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) const;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   // Select the opcode for simple loads and stores. Returns the original opcode
1370b57cec5SDimitry Andric   // if it doesn't know how to select a better one.
1380b57cec5SDimitry Andric   unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
1390b57cec5SDimitry Andric                                  unsigned Size) const;
1400b57cec5SDimitry Andric 
141480093f4SDimitry Andric   void renderVFPF32Imm(MachineInstrBuilder &New, const MachineInstr &Old,
142480093f4SDimitry Andric                        int OpIdx = -1) const;
143480093f4SDimitry Andric   void renderVFPF64Imm(MachineInstrBuilder &New, const MachineInstr &Old,
144480093f4SDimitry Andric                        int OpIdx = -1) const;
145*0fca6ea1SDimitry Andric   void renderInvertedImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
146*0fca6ea1SDimitry Andric                          int OpIdx = -1) const;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric #define GET_GLOBALISEL_PREDICATES_DECL
1490b57cec5SDimitry Andric #include "ARMGenGlobalISel.inc"
1500b57cec5SDimitry Andric #undef GET_GLOBALISEL_PREDICATES_DECL
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric // We declare the temporaries used by selectImpl() in the class to minimize the
1530b57cec5SDimitry Andric // cost of constructing placeholder values.
1540b57cec5SDimitry Andric #define GET_GLOBALISEL_TEMPORARIES_DECL
1550b57cec5SDimitry Andric #include "ARMGenGlobalISel.inc"
1560b57cec5SDimitry Andric #undef GET_GLOBALISEL_TEMPORARIES_DECL
1570b57cec5SDimitry Andric };
1580b57cec5SDimitry Andric } // end anonymous namespace
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric namespace llvm {
1610b57cec5SDimitry Andric InstructionSelector *
1620b57cec5SDimitry Andric createARMInstructionSelector(const ARMBaseTargetMachine &TM,
1630b57cec5SDimitry Andric                              const ARMSubtarget &STI,
1640b57cec5SDimitry Andric                              const ARMRegisterBankInfo &RBI) {
1650b57cec5SDimitry Andric   return new ARMInstructionSelector(TM, STI, RBI);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric #define GET_GLOBALISEL_IMPL
1700b57cec5SDimitry Andric #include "ARMGenGlobalISel.inc"
1710b57cec5SDimitry Andric #undef GET_GLOBALISEL_IMPL
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
1740b57cec5SDimitry Andric                                                const ARMSubtarget &STI,
1750b57cec5SDimitry Andric                                                const ARMRegisterBankInfo &RBI)
17604eeddc0SDimitry Andric     : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI),
17704eeddc0SDimitry Andric       STI(STI), Opcodes(STI),
1780b57cec5SDimitry Andric #define GET_GLOBALISEL_PREDICATES_INIT
1790b57cec5SDimitry Andric #include "ARMGenGlobalISel.inc"
1800b57cec5SDimitry Andric #undef GET_GLOBALISEL_PREDICATES_INIT
1810b57cec5SDimitry Andric #define GET_GLOBALISEL_TEMPORARIES_INIT
1820b57cec5SDimitry Andric #include "ARMGenGlobalISel.inc"
1830b57cec5SDimitry Andric #undef GET_GLOBALISEL_TEMPORARIES_INIT
1840b57cec5SDimitry Andric {
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric static const TargetRegisterClass *guessRegClass(unsigned Reg,
1880b57cec5SDimitry Andric                                                 MachineRegisterInfo &MRI,
1890b57cec5SDimitry Andric                                                 const TargetRegisterInfo &TRI,
1900b57cec5SDimitry Andric                                                 const RegisterBankInfo &RBI) {
1910b57cec5SDimitry Andric   const RegisterBank *RegBank = RBI.getRegBank(Reg, MRI, TRI);
1920b57cec5SDimitry Andric   assert(RegBank && "Can't get reg bank for virtual register");
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   const unsigned Size = MRI.getType(Reg).getSizeInBits();
1950b57cec5SDimitry Andric   assert((RegBank->getID() == ARM::GPRRegBankID ||
1960b57cec5SDimitry Andric           RegBank->getID() == ARM::FPRRegBankID) &&
1970b57cec5SDimitry Andric          "Unsupported reg bank");
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   if (RegBank->getID() == ARM::FPRRegBankID) {
2000b57cec5SDimitry Andric     if (Size == 32)
2010b57cec5SDimitry Andric       return &ARM::SPRRegClass;
2020b57cec5SDimitry Andric     else if (Size == 64)
2030b57cec5SDimitry Andric       return &ARM::DPRRegClass;
2040b57cec5SDimitry Andric     else if (Size == 128)
2050b57cec5SDimitry Andric       return &ARM::QPRRegClass;
2060b57cec5SDimitry Andric     else
2070b57cec5SDimitry Andric       llvm_unreachable("Unsupported destination size");
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   return &ARM::GPRRegClass;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
2140b57cec5SDimitry Andric                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
2150b57cec5SDimitry Andric                        const RegisterBankInfo &RBI) {
2168bcb0991SDimitry Andric   Register DstReg = I.getOperand(0).getReg();
217bdd1243dSDimitry Andric   if (DstReg.isPhysical())
2180b57cec5SDimitry Andric     return true;
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   // No need to constrain SrcReg. It will get constrained when
2230b57cec5SDimitry Andric   // we hit another of its uses or its defs.
2240b57cec5SDimitry Andric   // Copies do not have constraints.
2250b57cec5SDimitry Andric   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
2260b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
2270b57cec5SDimitry Andric                       << " operand\n");
2280b57cec5SDimitry Andric     return false;
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric   return true;
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric static bool selectMergeValues(MachineInstrBuilder &MIB,
2340b57cec5SDimitry Andric                               const ARMBaseInstrInfo &TII,
2350b57cec5SDimitry Andric                               MachineRegisterInfo &MRI,
2360b57cec5SDimitry Andric                               const TargetRegisterInfo &TRI,
2370b57cec5SDimitry Andric                               const RegisterBankInfo &RBI) {
2380b57cec5SDimitry Andric   assert(TII.getSubtarget().hasVFP2Base() && "Can't select merge without VFP");
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
2410b57cec5SDimitry Andric   // into one DPR.
2425ffd83dbSDimitry Andric   Register VReg0 = MIB.getReg(0);
2430b57cec5SDimitry Andric   (void)VReg0;
2440b57cec5SDimitry Andric   assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
2450b57cec5SDimitry Andric          RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
2460b57cec5SDimitry Andric          "Unsupported operand for G_MERGE_VALUES");
2475ffd83dbSDimitry Andric   Register VReg1 = MIB.getReg(1);
2480b57cec5SDimitry Andric   (void)VReg1;
2490b57cec5SDimitry Andric   assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
2500b57cec5SDimitry Andric          RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2510b57cec5SDimitry Andric          "Unsupported operand for G_MERGE_VALUES");
2525ffd83dbSDimitry Andric   Register VReg2 = MIB.getReg(2);
2530b57cec5SDimitry Andric   (void)VReg2;
2540b57cec5SDimitry Andric   assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
2550b57cec5SDimitry Andric          RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2560b57cec5SDimitry Andric          "Unsupported operand for G_MERGE_VALUES");
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   MIB->setDesc(TII.get(ARM::VMOVDRR));
2590b57cec5SDimitry Andric   MIB.add(predOps(ARMCC::AL));
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   return true;
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric static bool selectUnmergeValues(MachineInstrBuilder &MIB,
2650b57cec5SDimitry Andric                                 const ARMBaseInstrInfo &TII,
2660b57cec5SDimitry Andric                                 MachineRegisterInfo &MRI,
2670b57cec5SDimitry Andric                                 const TargetRegisterInfo &TRI,
2680b57cec5SDimitry Andric                                 const RegisterBankInfo &RBI) {
2690b57cec5SDimitry Andric   assert(TII.getSubtarget().hasVFP2Base() &&
2700b57cec5SDimitry Andric          "Can't select unmerge without VFP");
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
2730b57cec5SDimitry Andric   // GPRs.
2745ffd83dbSDimitry Andric   Register VReg0 = MIB.getReg(0);
2750b57cec5SDimitry Andric   (void)VReg0;
2760b57cec5SDimitry Andric   assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
2770b57cec5SDimitry Andric          RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2780b57cec5SDimitry Andric          "Unsupported operand for G_UNMERGE_VALUES");
2795ffd83dbSDimitry Andric   Register VReg1 = MIB.getReg(1);
2800b57cec5SDimitry Andric   (void)VReg1;
2810b57cec5SDimitry Andric   assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
2820b57cec5SDimitry Andric          RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2830b57cec5SDimitry Andric          "Unsupported operand for G_UNMERGE_VALUES");
2845ffd83dbSDimitry Andric   Register VReg2 = MIB.getReg(2);
2850b57cec5SDimitry Andric   (void)VReg2;
2860b57cec5SDimitry Andric   assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
2870b57cec5SDimitry Andric          RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
2880b57cec5SDimitry Andric          "Unsupported operand for G_UNMERGE_VALUES");
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   MIB->setDesc(TII.get(ARM::VMOVRRD));
2910b57cec5SDimitry Andric   MIB.add(predOps(ARMCC::AL));
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   return true;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {
2970b57cec5SDimitry Andric   bool isThumb = STI.isThumb();
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   using namespace TargetOpcode;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric #define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC
3020b57cec5SDimitry Andric   STORE_OPCODE(SEXT16, SXTH);
3030b57cec5SDimitry Andric   STORE_OPCODE(ZEXT16, UXTH);
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   STORE_OPCODE(SEXT8, SXTB);
3060b57cec5SDimitry Andric   STORE_OPCODE(ZEXT8, UXTB);
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   STORE_OPCODE(AND, ANDri);
3090b57cec5SDimitry Andric   STORE_OPCODE(RSB, RSBri);
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   STORE_OPCODE(STORE32, STRi12);
3120b57cec5SDimitry Andric   STORE_OPCODE(LOAD32, LDRi12);
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric   // LDRH/STRH are special...
3150b57cec5SDimitry Andric   STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
3160b57cec5SDimitry Andric   LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   STORE_OPCODE(STORE8, STRBi12);
3190b57cec5SDimitry Andric   STORE_OPCODE(LOAD8, LDRBi12);
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   STORE_OPCODE(ADDrr, ADDrr);
3220b57cec5SDimitry Andric   STORE_OPCODE(ADDri, ADDri);
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   STORE_OPCODE(CMPrr, CMPrr);
3250b57cec5SDimitry Andric   STORE_OPCODE(MOVi, MOVi);
3260b57cec5SDimitry Andric   STORE_OPCODE(MOVCCi, MOVCCi);
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   STORE_OPCODE(MOVCCr, MOVCCr);
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   STORE_OPCODE(TSTri, TSTri);
3310b57cec5SDimitry Andric   STORE_OPCODE(Bcc, Bcc);
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   STORE_OPCODE(MOVi32imm, MOVi32imm);
3340b57cec5SDimitry Andric   ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;
3350b57cec5SDimitry Andric   STORE_OPCODE(MOV_ga_pcrel, MOV_ga_pcrel);
3360b57cec5SDimitry Andric   LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;
3370b57cec5SDimitry Andric   LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;
3380b57cec5SDimitry Andric #undef MAP_OPCODE
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric unsigned ARMInstructionSelector::selectSimpleExtOpc(unsigned Opc,
3420b57cec5SDimitry Andric                                                     unsigned Size) const {
3430b57cec5SDimitry Andric   using namespace TargetOpcode;
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric   if (Size != 8 && Size != 16)
3460b57cec5SDimitry Andric     return Opc;
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   if (Opc == G_SEXT)
3490b57cec5SDimitry Andric     return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   if (Opc == G_ZEXT)
3520b57cec5SDimitry Andric     return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   return Opc;
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric unsigned ARMInstructionSelector::selectLoadStoreOpCode(unsigned Opc,
3580b57cec5SDimitry Andric                                                        unsigned RegBank,
3590b57cec5SDimitry Andric                                                        unsigned Size) const {
3600b57cec5SDimitry Andric   bool isStore = Opc == TargetOpcode::G_STORE;
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   if (RegBank == ARM::GPRRegBankID) {
3630b57cec5SDimitry Andric     switch (Size) {
3640b57cec5SDimitry Andric     case 1:
3650b57cec5SDimitry Andric     case 8:
3660b57cec5SDimitry Andric       return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
3670b57cec5SDimitry Andric     case 16:
3680b57cec5SDimitry Andric       return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
3690b57cec5SDimitry Andric     case 32:
3700b57cec5SDimitry Andric       return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
3710b57cec5SDimitry Andric     default:
3720b57cec5SDimitry Andric       return Opc;
3730b57cec5SDimitry Andric     }
3740b57cec5SDimitry Andric   }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   if (RegBank == ARM::FPRRegBankID) {
3770b57cec5SDimitry Andric     switch (Size) {
3780b57cec5SDimitry Andric     case 32:
3790b57cec5SDimitry Andric       return isStore ? ARM::VSTRS : ARM::VLDRS;
3800b57cec5SDimitry Andric     case 64:
3810b57cec5SDimitry Andric       return isStore ? ARM::VSTRD : ARM::VLDRD;
3820b57cec5SDimitry Andric     default:
3830b57cec5SDimitry Andric       return Opc;
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   return Opc;
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric // When lowering comparisons, we sometimes need to perform two compares instead
3910b57cec5SDimitry Andric // of just one. Get the condition codes for both comparisons. If only one is
3920b57cec5SDimitry Andric // needed, the second member of the pair is ARMCC::AL.
3930b57cec5SDimitry Andric static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
3940b57cec5SDimitry Andric getComparePreds(CmpInst::Predicate Pred) {
3950b57cec5SDimitry Andric   std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
3960b57cec5SDimitry Andric   switch (Pred) {
3970b57cec5SDimitry Andric   case CmpInst::FCMP_ONE:
3980b57cec5SDimitry Andric     Preds = {ARMCC::GT, ARMCC::MI};
3990b57cec5SDimitry Andric     break;
4000b57cec5SDimitry Andric   case CmpInst::FCMP_UEQ:
4010b57cec5SDimitry Andric     Preds = {ARMCC::EQ, ARMCC::VS};
4020b57cec5SDimitry Andric     break;
4030b57cec5SDimitry Andric   case CmpInst::ICMP_EQ:
4040b57cec5SDimitry Andric   case CmpInst::FCMP_OEQ:
4050b57cec5SDimitry Andric     Preds.first = ARMCC::EQ;
4060b57cec5SDimitry Andric     break;
4070b57cec5SDimitry Andric   case CmpInst::ICMP_SGT:
4080b57cec5SDimitry Andric   case CmpInst::FCMP_OGT:
4090b57cec5SDimitry Andric     Preds.first = ARMCC::GT;
4100b57cec5SDimitry Andric     break;
4110b57cec5SDimitry Andric   case CmpInst::ICMP_SGE:
4120b57cec5SDimitry Andric   case CmpInst::FCMP_OGE:
4130b57cec5SDimitry Andric     Preds.first = ARMCC::GE;
4140b57cec5SDimitry Andric     break;
4150b57cec5SDimitry Andric   case CmpInst::ICMP_UGT:
4160b57cec5SDimitry Andric   case CmpInst::FCMP_UGT:
4170b57cec5SDimitry Andric     Preds.first = ARMCC::HI;
4180b57cec5SDimitry Andric     break;
4190b57cec5SDimitry Andric   case CmpInst::FCMP_OLT:
4200b57cec5SDimitry Andric     Preds.first = ARMCC::MI;
4210b57cec5SDimitry Andric     break;
4220b57cec5SDimitry Andric   case CmpInst::ICMP_ULE:
4230b57cec5SDimitry Andric   case CmpInst::FCMP_OLE:
4240b57cec5SDimitry Andric     Preds.first = ARMCC::LS;
4250b57cec5SDimitry Andric     break;
4260b57cec5SDimitry Andric   case CmpInst::FCMP_ORD:
4270b57cec5SDimitry Andric     Preds.first = ARMCC::VC;
4280b57cec5SDimitry Andric     break;
4290b57cec5SDimitry Andric   case CmpInst::FCMP_UNO:
4300b57cec5SDimitry Andric     Preds.first = ARMCC::VS;
4310b57cec5SDimitry Andric     break;
4320b57cec5SDimitry Andric   case CmpInst::FCMP_UGE:
4330b57cec5SDimitry Andric     Preds.first = ARMCC::PL;
4340b57cec5SDimitry Andric     break;
4350b57cec5SDimitry Andric   case CmpInst::ICMP_SLT:
4360b57cec5SDimitry Andric   case CmpInst::FCMP_ULT:
4370b57cec5SDimitry Andric     Preds.first = ARMCC::LT;
4380b57cec5SDimitry Andric     break;
4390b57cec5SDimitry Andric   case CmpInst::ICMP_SLE:
4400b57cec5SDimitry Andric   case CmpInst::FCMP_ULE:
4410b57cec5SDimitry Andric     Preds.first = ARMCC::LE;
4420b57cec5SDimitry Andric     break;
4430b57cec5SDimitry Andric   case CmpInst::FCMP_UNE:
4440b57cec5SDimitry Andric   case CmpInst::ICMP_NE:
4450b57cec5SDimitry Andric     Preds.first = ARMCC::NE;
4460b57cec5SDimitry Andric     break;
4470b57cec5SDimitry Andric   case CmpInst::ICMP_UGE:
4480b57cec5SDimitry Andric     Preds.first = ARMCC::HS;
4490b57cec5SDimitry Andric     break;
4500b57cec5SDimitry Andric   case CmpInst::ICMP_ULT:
4510b57cec5SDimitry Andric     Preds.first = ARMCC::LO;
4520b57cec5SDimitry Andric     break;
4530b57cec5SDimitry Andric   default:
4540b57cec5SDimitry Andric     break;
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric   assert(Preds.first != ARMCC::AL && "No comparisons needed?");
4570b57cec5SDimitry Andric   return Preds;
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric struct ARMInstructionSelector::CmpConstants {
4610b57cec5SDimitry Andric   CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,
4620b57cec5SDimitry Andric                unsigned OpRegBank, unsigned OpSize)
4630b57cec5SDimitry Andric       : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
4640b57cec5SDimitry Andric         SelectResultOpcode(SelectOpcode), OperandRegBankID(OpRegBank),
4650b57cec5SDimitry Andric         OperandSize(OpSize) {}
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   // The opcode used for performing the comparison.
4680b57cec5SDimitry Andric   const unsigned ComparisonOpcode;
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   // The opcode used for reading the flags set by the comparison. May be
4710b57cec5SDimitry Andric   // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
4720b57cec5SDimitry Andric   const unsigned ReadFlagsOpcode;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   // The opcode used for materializing the result of the comparison.
4750b57cec5SDimitry Andric   const unsigned SelectResultOpcode;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   // The assumed register bank ID for the operands.
4780b57cec5SDimitry Andric   const unsigned OperandRegBankID;
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric   // The assumed size in bits for the operands.
4810b57cec5SDimitry Andric   const unsigned OperandSize;
4820b57cec5SDimitry Andric };
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric struct ARMInstructionSelector::InsertInfo {
4850b57cec5SDimitry Andric   InsertInfo(MachineInstrBuilder &MIB)
4860b57cec5SDimitry Andric       : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
4870b57cec5SDimitry Andric         DbgLoc(MIB->getDebugLoc()) {}
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   MachineBasicBlock &MBB;
4900b57cec5SDimitry Andric   const MachineBasicBlock::instr_iterator InsertBefore;
4910b57cec5SDimitry Andric   const DebugLoc &DbgLoc;
4920b57cec5SDimitry Andric };
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
4950b57cec5SDimitry Andric                                          unsigned Constant) const {
4960b57cec5SDimitry Andric   (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
4970b57cec5SDimitry Andric       .addDef(DestReg)
4980b57cec5SDimitry Andric       .addImm(Constant)
4990b57cec5SDimitry Andric       .add(predOps(ARMCC::AL))
5000b57cec5SDimitry Andric       .add(condCodeOp());
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
5040b57cec5SDimitry Andric                                             unsigned LHSReg, unsigned RHSReg,
5050b57cec5SDimitry Andric                                             unsigned ExpectedSize,
5060b57cec5SDimitry Andric                                             unsigned ExpectedRegBankID) const {
5070b57cec5SDimitry Andric   return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
5080b57cec5SDimitry Andric          validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
5090b57cec5SDimitry Andric          validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
5130b57cec5SDimitry Andric                                       unsigned ExpectedSize,
5140b57cec5SDimitry Andric                                       unsigned ExpectedRegBankID) const {
5150b57cec5SDimitry Andric   if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
5160b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Unexpected size for register");
5170b57cec5SDimitry Andric     return false;
5180b57cec5SDimitry Andric   }
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
5210b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Unexpected register bank for register");
5220b57cec5SDimitry Andric     return false;
5230b57cec5SDimitry Andric   }
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   return true;
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
5290b57cec5SDimitry Andric                                        MachineInstrBuilder &MIB,
5300b57cec5SDimitry Andric                                        MachineRegisterInfo &MRI) const {
5310b57cec5SDimitry Andric   const InsertInfo I(MIB);
5320b57cec5SDimitry Andric 
5335ffd83dbSDimitry Andric   auto ResReg = MIB.getReg(0);
5340b57cec5SDimitry Andric   if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
5350b57cec5SDimitry Andric     return false;
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   auto Cond =
5380b57cec5SDimitry Andric       static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
5390b57cec5SDimitry Andric   if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
5400b57cec5SDimitry Andric     putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
5410b57cec5SDimitry Andric     MIB->eraseFromParent();
5420b57cec5SDimitry Andric     return true;
5430b57cec5SDimitry Andric   }
5440b57cec5SDimitry Andric 
5455ffd83dbSDimitry Andric   auto LHSReg = MIB.getReg(2);
5465ffd83dbSDimitry Andric   auto RHSReg = MIB.getReg(3);
5470b57cec5SDimitry Andric   if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
5480b57cec5SDimitry Andric                       Helper.OperandRegBankID))
5490b57cec5SDimitry Andric     return false;
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   auto ARMConds = getComparePreds(Cond);
5520b57cec5SDimitry Andric   auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
5530b57cec5SDimitry Andric   putConstant(I, ZeroReg, 0);
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   if (ARMConds.second == ARMCC::AL) {
5560b57cec5SDimitry Andric     // Simple case, we only need one comparison and we're done.
5570b57cec5SDimitry Andric     if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
5580b57cec5SDimitry Andric                           ZeroReg))
5590b57cec5SDimitry Andric       return false;
5600b57cec5SDimitry Andric   } else {
5610b57cec5SDimitry Andric     // Not so simple, we need two successive comparisons.
5620b57cec5SDimitry Andric     auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
5630b57cec5SDimitry Andric     if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
5640b57cec5SDimitry Andric                           RHSReg, ZeroReg))
5650b57cec5SDimitry Andric       return false;
5660b57cec5SDimitry Andric     if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
5670b57cec5SDimitry Andric                           IntermediateRes))
5680b57cec5SDimitry Andric       return false;
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   MIB->eraseFromParent();
5720b57cec5SDimitry Andric   return true;
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
5760b57cec5SDimitry Andric                                               unsigned ResReg,
5770b57cec5SDimitry Andric                                               ARMCC::CondCodes Cond,
5780b57cec5SDimitry Andric                                               unsigned LHSReg, unsigned RHSReg,
5790b57cec5SDimitry Andric                                               unsigned PrevRes) const {
5800b57cec5SDimitry Andric   // Perform the comparison.
5810b57cec5SDimitry Andric   auto CmpI =
5820b57cec5SDimitry Andric       BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
5830b57cec5SDimitry Andric           .addUse(LHSReg)
5840b57cec5SDimitry Andric           .addUse(RHSReg)
5850b57cec5SDimitry Andric           .add(predOps(ARMCC::AL));
5860b57cec5SDimitry Andric   if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
5870b57cec5SDimitry Andric     return false;
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   // Read the comparison flags (if necessary).
5900b57cec5SDimitry Andric   if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
5910b57cec5SDimitry Andric     auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
5920b57cec5SDimitry Andric                          TII.get(Helper.ReadFlagsOpcode))
5930b57cec5SDimitry Andric                      .add(predOps(ARMCC::AL));
5940b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
5950b57cec5SDimitry Andric       return false;
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   // Select either 1 or the previous result based on the value of the flags.
5990b57cec5SDimitry Andric   auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
6000b57cec5SDimitry Andric                        TII.get(Helper.SelectResultOpcode))
6010b57cec5SDimitry Andric                    .addDef(ResReg)
6020b57cec5SDimitry Andric                    .addUse(PrevRes)
6030b57cec5SDimitry Andric                    .addImm(1)
6040b57cec5SDimitry Andric                    .add(predOps(Cond, ARM::CPSR));
6050b57cec5SDimitry Andric   if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
6060b57cec5SDimitry Andric     return false;
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   return true;
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
6120b57cec5SDimitry Andric                                           MachineRegisterInfo &MRI) const {
6130b57cec5SDimitry Andric   if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
6140b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
6150b57cec5SDimitry Andric     return false;
6160b57cec5SDimitry Andric   }
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   auto GV = MIB->getOperand(1).getGlobal();
6190b57cec5SDimitry Andric   if (GV->isThreadLocal()) {
6200b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");
6210b57cec5SDimitry Andric     return false;
6220b57cec5SDimitry Andric   }
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric   auto &MBB = *MIB->getParent();
6250b57cec5SDimitry Andric   auto &MF = *MBB.getParent();
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric   bool UseMovt = STI.useMovt();
6280b57cec5SDimitry Andric 
62981ad6265SDimitry Andric   LLT PtrTy = MRI.getType(MIB->getOperand(0).getReg());
6305ffd83dbSDimitry Andric   const Align Alignment(4);
6310b57cec5SDimitry Andric 
63281ad6265SDimitry Andric   auto addOpsForConstantPoolLoad = [&MF, Alignment, PtrTy](
63381ad6265SDimitry Andric                                        MachineInstrBuilder &MIB,
6340b57cec5SDimitry Andric                                        const GlobalValue *GV, bool IsSBREL) {
6350b57cec5SDimitry Andric     assert((MIB->getOpcode() == ARM::LDRi12 ||
6360b57cec5SDimitry Andric             MIB->getOpcode() == ARM::t2LDRpci) &&
6370b57cec5SDimitry Andric            "Unsupported instruction");
6380b57cec5SDimitry Andric     auto ConstPool = MF.getConstantPool();
6390b57cec5SDimitry Andric     auto CPIndex =
6400b57cec5SDimitry Andric         // For SB relative entries we need a target-specific constant pool.
6410b57cec5SDimitry Andric         // Otherwise, just use a regular constant pool entry.
6420b57cec5SDimitry Andric         IsSBREL
6430b57cec5SDimitry Andric             ? ConstPool->getConstantPoolIndex(
6440b57cec5SDimitry Andric                   ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
6450b57cec5SDimitry Andric             : ConstPool->getConstantPoolIndex(GV, Alignment);
6460b57cec5SDimitry Andric     MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
6470b57cec5SDimitry Andric         .addMemOperand(MF.getMachineMemOperand(
6480b57cec5SDimitry Andric             MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
64981ad6265SDimitry Andric             PtrTy, Alignment));
6500b57cec5SDimitry Andric     if (MIB->getOpcode() == ARM::LDRi12)
6510b57cec5SDimitry Andric       MIB.addImm(0);
6520b57cec5SDimitry Andric     MIB.add(predOps(ARMCC::AL));
6530b57cec5SDimitry Andric   };
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) {
6560b57cec5SDimitry Andric     MIB.addMemOperand(MF.getMachineMemOperand(
6570b57cec5SDimitry Andric         MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
6580b57cec5SDimitry Andric         TM.getProgramPointerSize(), Alignment));
6590b57cec5SDimitry Andric   };
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   if (TM.isPositionIndependent()) {
6620b57cec5SDimitry Andric     bool Indirect = STI.isGVIndirectSymbol(GV);
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric     // For ARM mode, we have different pseudoinstructions for direct accesses
6650b57cec5SDimitry Andric     // and indirect accesses, and the ones for indirect accesses include the
6660b57cec5SDimitry Andric     // load from GOT. For Thumb mode, we use the same pseudoinstruction for both
6670b57cec5SDimitry Andric     // direct and indirect accesses, and we need to manually generate the load
6680b57cec5SDimitry Andric     // from GOT.
6690b57cec5SDimitry Andric     bool UseOpcodeThatLoads = Indirect && !STI.isThumb();
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric     // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
6720b57cec5SDimitry Andric     // support it yet. See PR28229.
6730b57cec5SDimitry Andric     unsigned Opc =
6740b57cec5SDimitry Andric         UseMovt && !STI.isTargetELF()
6750b57cec5SDimitry Andric             ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
6760b57cec5SDimitry Andric                                   : Opcodes.MOV_ga_pcrel)
6770b57cec5SDimitry Andric             : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
6780b57cec5SDimitry Andric                                   : Opcodes.LDRLIT_ga_pcrel);
6790b57cec5SDimitry Andric     MIB->setDesc(TII.get(Opc));
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric     int TargetFlags = ARMII::MO_NO_FLAG;
6820b57cec5SDimitry Andric     if (STI.isTargetDarwin())
6830b57cec5SDimitry Andric       TargetFlags |= ARMII::MO_NONLAZY;
6840b57cec5SDimitry Andric     if (STI.isGVInGOT(GV))
6850b57cec5SDimitry Andric       TargetFlags |= ARMII::MO_GOT;
6860b57cec5SDimitry Andric     MIB->getOperand(1).setTargetFlags(TargetFlags);
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric     if (Indirect) {
6890b57cec5SDimitry Andric       if (!UseOpcodeThatLoads) {
6905ffd83dbSDimitry Andric         auto ResultReg = MIB.getReg(0);
6910b57cec5SDimitry Andric         auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric         MIB->getOperand(0).setReg(AddressReg);
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric         auto InsertBefore = std::next(MIB->getIterator());
6960b57cec5SDimitry Andric         auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),
6970b57cec5SDimitry Andric                                TII.get(Opcodes.LOAD32))
6980b57cec5SDimitry Andric                            .addDef(ResultReg)
6990b57cec5SDimitry Andric                            .addReg(AddressReg)
7000b57cec5SDimitry Andric                            .addImm(0)
7010b57cec5SDimitry Andric                            .add(predOps(ARMCC::AL));
7020b57cec5SDimitry Andric         addGOTMemOperand(MIBLoad);
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric         if (!constrainSelectedInstRegOperands(*MIBLoad, TII, TRI, RBI))
7050b57cec5SDimitry Andric           return false;
7060b57cec5SDimitry Andric       } else {
7070b57cec5SDimitry Andric         addGOTMemOperand(MIB);
7080b57cec5SDimitry Andric       }
7090b57cec5SDimitry Andric     }
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
7120b57cec5SDimitry Andric   }
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
7150b57cec5SDimitry Andric   if (STI.isROPI() && isReadOnly) {
7160b57cec5SDimitry Andric     unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
7170b57cec5SDimitry Andric     MIB->setDesc(TII.get(Opc));
7180b57cec5SDimitry Andric     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
7190b57cec5SDimitry Andric   }
7200b57cec5SDimitry Andric   if (STI.isRWPI() && !isReadOnly) {
7210b57cec5SDimitry Andric     auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
7220b57cec5SDimitry Andric     MachineInstrBuilder OffsetMIB;
7230b57cec5SDimitry Andric     if (UseMovt) {
7240b57cec5SDimitry Andric       OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
7250b57cec5SDimitry Andric                           TII.get(Opcodes.MOVi32imm), Offset);
7260b57cec5SDimitry Andric       OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
7270b57cec5SDimitry Andric     } else {
7280b57cec5SDimitry Andric       // Load the offset from the constant pool.
7290b57cec5SDimitry Andric       OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
7300b57cec5SDimitry Andric                           TII.get(Opcodes.ConstPoolLoad), Offset);
7310b57cec5SDimitry Andric       addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
7320b57cec5SDimitry Andric     }
7330b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
7340b57cec5SDimitry Andric       return false;
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric     // Add the offset to the SB register.
7370b57cec5SDimitry Andric     MIB->setDesc(TII.get(Opcodes.ADDrr));
73881ad6265SDimitry Andric     MIB->removeOperand(1);
7390b57cec5SDimitry Andric     MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
7400b57cec5SDimitry Andric         .addReg(Offset)
7410b57cec5SDimitry Andric         .add(predOps(ARMCC::AL))
7420b57cec5SDimitry Andric         .add(condCodeOp());
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
7450b57cec5SDimitry Andric   }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   if (STI.isTargetELF()) {
7480b57cec5SDimitry Andric     if (UseMovt) {
7490b57cec5SDimitry Andric       MIB->setDesc(TII.get(Opcodes.MOVi32imm));
7500b57cec5SDimitry Andric     } else {
7510b57cec5SDimitry Andric       // Load the global's address from the constant pool.
7520b57cec5SDimitry Andric       MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
75381ad6265SDimitry Andric       MIB->removeOperand(1);
7540b57cec5SDimitry Andric       addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
7550b57cec5SDimitry Andric     }
7560b57cec5SDimitry Andric   } else if (STI.isTargetMachO()) {
7570b57cec5SDimitry Andric     if (UseMovt)
7580b57cec5SDimitry Andric       MIB->setDesc(TII.get(Opcodes.MOVi32imm));
7590b57cec5SDimitry Andric     else
7600b57cec5SDimitry Andric       MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));
7610b57cec5SDimitry Andric   } else {
7620b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
7630b57cec5SDimitry Andric     return false;
7640b57cec5SDimitry Andric   }
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric   return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
7670b57cec5SDimitry Andric }
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
7700b57cec5SDimitry Andric                                           MachineRegisterInfo &MRI) const {
7710b57cec5SDimitry Andric   auto &MBB = *MIB->getParent();
7720b57cec5SDimitry Andric   auto InsertBefore = std::next(MIB->getIterator());
7730b57cec5SDimitry Andric   auto &DbgLoc = MIB->getDebugLoc();
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric   // Compare the condition to 1.
7765ffd83dbSDimitry Andric   auto CondReg = MIB.getReg(1);
7770b57cec5SDimitry Andric   assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
7780b57cec5SDimitry Andric          "Unsupported types for select operation");
7790b57cec5SDimitry Andric   auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))
7800b57cec5SDimitry Andric                   .addUse(CondReg)
7810b57cec5SDimitry Andric                   .addImm(1)
7820b57cec5SDimitry Andric                   .add(predOps(ARMCC::AL));
7830b57cec5SDimitry Andric   if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
7840b57cec5SDimitry Andric     return false;
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric   // Move a value into the result register based on the result of the
7870b57cec5SDimitry Andric   // comparison.
7885ffd83dbSDimitry Andric   auto ResReg = MIB.getReg(0);
7895ffd83dbSDimitry Andric   auto TrueReg = MIB.getReg(2);
7905ffd83dbSDimitry Andric   auto FalseReg = MIB.getReg(3);
7910b57cec5SDimitry Andric   assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
7920b57cec5SDimitry Andric          validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
7930b57cec5SDimitry Andric          "Unsupported types for select operation");
7940b57cec5SDimitry Andric   auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.MOVCCr))
7950b57cec5SDimitry Andric                    .addDef(ResReg)
7960b57cec5SDimitry Andric                    .addUse(TrueReg)
7970b57cec5SDimitry Andric                    .addUse(FalseReg)
7980b57cec5SDimitry Andric                    .add(predOps(ARMCC::EQ, ARM::CPSR));
7990b57cec5SDimitry Andric   if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
8000b57cec5SDimitry Andric     return false;
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   MIB->eraseFromParent();
8030b57cec5SDimitry Andric   return true;
8040b57cec5SDimitry Andric }
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
8070b57cec5SDimitry Andric                                          MachineInstrBuilder &MIB) const {
8080b57cec5SDimitry Andric   assert(!STI.isThumb() && "Unsupported subtarget");
8090b57cec5SDimitry Andric   MIB->setDesc(TII.get(ARM::MOVsr));
8100b57cec5SDimitry Andric   MIB.addImm(ShiftOpc);
8110b57cec5SDimitry Andric   MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
8120b57cec5SDimitry Andric   return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
8130b57cec5SDimitry Andric }
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric void ARMInstructionSelector::renderVFPF32Imm(
816480093f4SDimitry Andric   MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst,
817480093f4SDimitry Andric   int OpIdx) const {
8180b57cec5SDimitry Andric   assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
819480093f4SDimitry Andric          OpIdx == -1 && "Expected G_FCONSTANT");
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric   APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
8220b57cec5SDimitry Andric   int FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue);
8230b57cec5SDimitry Andric   assert(FPImmEncoding != -1 && "Invalid immediate value");
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric   NewInstBuilder.addImm(FPImmEncoding);
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric void ARMInstructionSelector::renderVFPF64Imm(
829480093f4SDimitry Andric   MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst, int OpIdx) const {
8300b57cec5SDimitry Andric   assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
831480093f4SDimitry Andric          OpIdx == -1 && "Expected G_FCONSTANT");
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric   APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
8340b57cec5SDimitry Andric   int FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue);
8350b57cec5SDimitry Andric   assert(FPImmEncoding != -1 && "Invalid immediate value");
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   NewInstBuilder.addImm(FPImmEncoding);
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric 
840*0fca6ea1SDimitry Andric void ARMInstructionSelector::renderInvertedImm(MachineInstrBuilder &MIB,
841*0fca6ea1SDimitry Andric                                                const MachineInstr &MI,
842*0fca6ea1SDimitry Andric                                                int OpIdx) const {
843*0fca6ea1SDimitry Andric   assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
844*0fca6ea1SDimitry Andric          "Expected G_CONSTANT");
845*0fca6ea1SDimitry Andric   int64_t CVal = MI.getOperand(1).getCImm()->getSExtValue();
846*0fca6ea1SDimitry Andric   MIB.addImm(~CVal);
847*0fca6ea1SDimitry Andric }
848*0fca6ea1SDimitry Andric 
8498bcb0991SDimitry Andric bool ARMInstructionSelector::select(MachineInstr &I) {
8500b57cec5SDimitry Andric   assert(I.getParent() && "Instruction should be in a basic block!");
8510b57cec5SDimitry Andric   assert(I.getParent()->getParent() && "Instruction should be in a function!");
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   auto &MBB = *I.getParent();
8540b57cec5SDimitry Andric   auto &MF = *MBB.getParent();
8550b57cec5SDimitry Andric   auto &MRI = MF.getRegInfo();
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric   if (!isPreISelGenericOpcode(I.getOpcode())) {
8580b57cec5SDimitry Andric     if (I.isCopy())
8590b57cec5SDimitry Andric       return selectCopy(I, TII, MRI, TRI, RBI);
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric     return true;
8620b57cec5SDimitry Andric   }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   using namespace TargetOpcode;
8650b57cec5SDimitry Andric 
8668bcb0991SDimitry Andric   if (selectImpl(I, *CoverageInfo))
8670b57cec5SDimitry Andric     return true;
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   MachineInstrBuilder MIB{MF, I};
8700b57cec5SDimitry Andric   bool isSExt = false;
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   switch (I.getOpcode()) {
8730b57cec5SDimitry Andric   case G_SEXT:
8740b57cec5SDimitry Andric     isSExt = true;
875bdd1243dSDimitry Andric     [[fallthrough]];
8760b57cec5SDimitry Andric   case G_ZEXT: {
8770b57cec5SDimitry Andric     assert(MRI.getType(I.getOperand(0).getReg()).getSizeInBits() <= 32 &&
8780b57cec5SDimitry Andric            "Unsupported destination size for extension");
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric     LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
8810b57cec5SDimitry Andric     unsigned SrcSize = SrcTy.getSizeInBits();
8820b57cec5SDimitry Andric     switch (SrcSize) {
8830b57cec5SDimitry Andric     case 1: {
8840b57cec5SDimitry Andric       // ZExt boils down to & 0x1; for SExt we also subtract that from 0
8850b57cec5SDimitry Andric       I.setDesc(TII.get(Opcodes.AND));
8860b57cec5SDimitry Andric       MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric       if (isSExt) {
8898bcb0991SDimitry Andric         Register SExtResult = I.getOperand(0).getReg();
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric         // Use a new virtual register for the result of the AND
8928bcb0991SDimitry Andric         Register AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
8930b57cec5SDimitry Andric         I.getOperand(0).setReg(AndResult);
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric         auto InsertBefore = std::next(I.getIterator());
8960b57cec5SDimitry Andric         auto SubI =
8970b57cec5SDimitry Andric             BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))
8980b57cec5SDimitry Andric                 .addDef(SExtResult)
8990b57cec5SDimitry Andric                 .addUse(AndResult)
9000b57cec5SDimitry Andric                 .addImm(0)
9010b57cec5SDimitry Andric                 .add(predOps(ARMCC::AL))
9020b57cec5SDimitry Andric                 .add(condCodeOp());
9030b57cec5SDimitry Andric         if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
9040b57cec5SDimitry Andric           return false;
9050b57cec5SDimitry Andric       }
9060b57cec5SDimitry Andric       break;
9070b57cec5SDimitry Andric     }
9080b57cec5SDimitry Andric     case 8:
9090b57cec5SDimitry Andric     case 16: {
9100b57cec5SDimitry Andric       unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
9110b57cec5SDimitry Andric       if (NewOpc == I.getOpcode())
9120b57cec5SDimitry Andric         return false;
9130b57cec5SDimitry Andric       I.setDesc(TII.get(NewOpc));
9140b57cec5SDimitry Andric       MIB.addImm(0).add(predOps(ARMCC::AL));
9150b57cec5SDimitry Andric       break;
9160b57cec5SDimitry Andric     }
9170b57cec5SDimitry Andric     default:
9180b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Unsupported source size for extension");
9190b57cec5SDimitry Andric       return false;
9200b57cec5SDimitry Andric     }
9210b57cec5SDimitry Andric     break;
9220b57cec5SDimitry Andric   }
9230b57cec5SDimitry Andric   case G_ANYEXT:
9240b57cec5SDimitry Andric   case G_TRUNC: {
9250b57cec5SDimitry Andric     // The high bits are undefined, so there's nothing special to do, just
9260b57cec5SDimitry Andric     // treat it as a copy.
9270b57cec5SDimitry Andric     auto SrcReg = I.getOperand(1).getReg();
9280b57cec5SDimitry Andric     auto DstReg = I.getOperand(0).getReg();
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric     const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
9310b57cec5SDimitry Andric     const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric     if (SrcRegBank.getID() == ARM::FPRRegBankID) {
9340b57cec5SDimitry Andric       // This should only happen in the obscure case where we have put a 64-bit
9350b57cec5SDimitry Andric       // integer into a D register. Get it out of there and keep only the
9360b57cec5SDimitry Andric       // interesting part.
9370b57cec5SDimitry Andric       assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
9380b57cec5SDimitry Andric       assert(DstRegBank.getID() == ARM::GPRRegBankID &&
9390b57cec5SDimitry Andric              "Unsupported combination of register banks");
9400b57cec5SDimitry Andric       assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
9410b57cec5SDimitry Andric       assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
9420b57cec5SDimitry Andric 
9438bcb0991SDimitry Andric       Register IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
9440b57cec5SDimitry Andric       auto InsertBefore = std::next(I.getIterator());
9450b57cec5SDimitry Andric       auto MovI =
9460b57cec5SDimitry Andric           BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
9470b57cec5SDimitry Andric               .addDef(DstReg)
9480b57cec5SDimitry Andric               .addDef(IgnoredBits)
9490b57cec5SDimitry Andric               .addUse(SrcReg)
9500b57cec5SDimitry Andric               .add(predOps(ARMCC::AL));
9510b57cec5SDimitry Andric       if (!constrainSelectedInstRegOperands(*MovI, TII, TRI, RBI))
9520b57cec5SDimitry Andric         return false;
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric       MIB->eraseFromParent();
9550b57cec5SDimitry Andric       return true;
9560b57cec5SDimitry Andric     }
9570b57cec5SDimitry Andric 
9580b57cec5SDimitry Andric     if (SrcRegBank.getID() != DstRegBank.getID()) {
9590b57cec5SDimitry Andric       LLVM_DEBUG(
9600b57cec5SDimitry Andric           dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
9610b57cec5SDimitry Andric       return false;
9620b57cec5SDimitry Andric     }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric     if (SrcRegBank.getID() != ARM::GPRRegBankID) {
9650b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
9660b57cec5SDimitry Andric       return false;
9670b57cec5SDimitry Andric     }
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric     I.setDesc(TII.get(COPY));
9700b57cec5SDimitry Andric     return selectCopy(I, TII, MRI, TRI, RBI);
9710b57cec5SDimitry Andric   }
9720b57cec5SDimitry Andric   case G_CONSTANT: {
9730b57cec5SDimitry Andric     if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
9740b57cec5SDimitry Andric       // Non-pointer constants should be handled by TableGen.
9750b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
9760b57cec5SDimitry Andric       return false;
9770b57cec5SDimitry Andric     }
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric     auto &Val = I.getOperand(1);
9800b57cec5SDimitry Andric     if (Val.isCImm()) {
9810b57cec5SDimitry Andric       if (!Val.getCImm()->isZero()) {
9820b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
9830b57cec5SDimitry Andric         return false;
9840b57cec5SDimitry Andric       }
9850b57cec5SDimitry Andric       Val.ChangeToImmediate(0);
9860b57cec5SDimitry Andric     } else {
9870b57cec5SDimitry Andric       assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
9880b57cec5SDimitry Andric       if (Val.getImm() != 0) {
9890b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
9900b57cec5SDimitry Andric         return false;
9910b57cec5SDimitry Andric       }
9920b57cec5SDimitry Andric     }
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric     assert(!STI.isThumb() && "Unsupported subtarget");
9950b57cec5SDimitry Andric     I.setDesc(TII.get(ARM::MOVi));
9960b57cec5SDimitry Andric     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
9970b57cec5SDimitry Andric     break;
9980b57cec5SDimitry Andric   }
9990b57cec5SDimitry Andric   case G_FCONSTANT: {
10000b57cec5SDimitry Andric     // Load from constant pool
10010b57cec5SDimitry Andric     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
10025ffd83dbSDimitry Andric     Align Alignment(Size);
10030b57cec5SDimitry Andric 
10040b57cec5SDimitry Andric     assert((Size == 4 || Size == 8) && "Unsupported FP constant type");
10050b57cec5SDimitry Andric     auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric     auto ConstPool = MF.getConstantPool();
10080b57cec5SDimitry Andric     auto CPIndex =
10090b57cec5SDimitry Andric         ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);
10100b57cec5SDimitry Andric     MIB->setDesc(TII.get(LoadOpcode));
101181ad6265SDimitry Andric     MIB->removeOperand(1);
10120b57cec5SDimitry Andric     MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
10130b57cec5SDimitry Andric         .addMemOperand(
10140b57cec5SDimitry Andric             MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
10150b57cec5SDimitry Andric                                     MachineMemOperand::MOLoad, Size, Alignment))
10160b57cec5SDimitry Andric         .addImm(0)
10170b57cec5SDimitry Andric         .add(predOps(ARMCC::AL));
10180b57cec5SDimitry Andric     break;
10190b57cec5SDimitry Andric   }
10200b57cec5SDimitry Andric   case G_INTTOPTR:
10210b57cec5SDimitry Andric   case G_PTRTOINT: {
10220b57cec5SDimitry Andric     auto SrcReg = I.getOperand(1).getReg();
10230b57cec5SDimitry Andric     auto DstReg = I.getOperand(0).getReg();
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric     const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
10260b57cec5SDimitry Andric     const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric     if (SrcRegBank.getID() != DstRegBank.getID()) {
10290b57cec5SDimitry Andric       LLVM_DEBUG(
10300b57cec5SDimitry Andric           dbgs()
10310b57cec5SDimitry Andric           << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
10320b57cec5SDimitry Andric       return false;
10330b57cec5SDimitry Andric     }
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric     if (SrcRegBank.getID() != ARM::GPRRegBankID) {
10360b57cec5SDimitry Andric       LLVM_DEBUG(
10370b57cec5SDimitry Andric           dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
10380b57cec5SDimitry Andric       return false;
10390b57cec5SDimitry Andric     }
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric     I.setDesc(TII.get(COPY));
10420b57cec5SDimitry Andric     return selectCopy(I, TII, MRI, TRI, RBI);
10430b57cec5SDimitry Andric   }
10440b57cec5SDimitry Andric   case G_SELECT:
10450b57cec5SDimitry Andric     return selectSelect(MIB, MRI);
10460b57cec5SDimitry Andric   case G_ICMP: {
10470b57cec5SDimitry Andric     CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
10480b57cec5SDimitry Andric                         Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
10490b57cec5SDimitry Andric     return selectCmp(Helper, MIB, MRI);
10500b57cec5SDimitry Andric   }
10510b57cec5SDimitry Andric   case G_FCMP: {
10520b57cec5SDimitry Andric     assert(STI.hasVFP2Base() && "Can't select fcmp without VFP");
10530b57cec5SDimitry Andric 
10548bcb0991SDimitry Andric     Register OpReg = I.getOperand(2).getReg();
10550b57cec5SDimitry Andric     unsigned Size = MRI.getType(OpReg).getSizeInBits();
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric     if (Size == 64 && !STI.hasFP64()) {
10580b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");
10590b57cec5SDimitry Andric       return false;
10600b57cec5SDimitry Andric     }
10610b57cec5SDimitry Andric     if (Size != 32 && Size != 64) {
10620b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
10630b57cec5SDimitry Andric       return false;
10640b57cec5SDimitry Andric     }
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric     CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
10670b57cec5SDimitry Andric                         Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
10680b57cec5SDimitry Andric     return selectCmp(Helper, MIB, MRI);
10690b57cec5SDimitry Andric   }
10700b57cec5SDimitry Andric   case G_LSHR:
10710b57cec5SDimitry Andric     return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
10720b57cec5SDimitry Andric   case G_ASHR:
10730b57cec5SDimitry Andric     return selectShift(ARM_AM::ShiftOpc::asr, MIB);
10740b57cec5SDimitry Andric   case G_SHL: {
10750b57cec5SDimitry Andric     return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
10760b57cec5SDimitry Andric   }
1077480093f4SDimitry Andric   case G_PTR_ADD:
10780b57cec5SDimitry Andric     I.setDesc(TII.get(Opcodes.ADDrr));
10790b57cec5SDimitry Andric     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
10800b57cec5SDimitry Andric     break;
10810b57cec5SDimitry Andric   case G_FRAME_INDEX:
10820b57cec5SDimitry Andric     // Add 0 to the given frame index and hope it will eventually be folded into
10830b57cec5SDimitry Andric     // the user(s).
10840b57cec5SDimitry Andric     I.setDesc(TII.get(Opcodes.ADDri));
10850b57cec5SDimitry Andric     MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
10860b57cec5SDimitry Andric     break;
10870b57cec5SDimitry Andric   case G_GLOBAL_VALUE:
10880b57cec5SDimitry Andric     return selectGlobal(MIB, MRI);
10890b57cec5SDimitry Andric   case G_STORE:
10900b57cec5SDimitry Andric   case G_LOAD: {
10910b57cec5SDimitry Andric     const auto &MemOp = **I.memoperands_begin();
10928bcb0991SDimitry Andric     if (MemOp.isAtomic()) {
10930b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
10940b57cec5SDimitry Andric       return false;
10950b57cec5SDimitry Andric     }
10960b57cec5SDimitry Andric 
10978bcb0991SDimitry Andric     Register Reg = I.getOperand(0).getReg();
10980b57cec5SDimitry Andric     unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric     LLT ValTy = MRI.getType(Reg);
11010b57cec5SDimitry Andric     const auto ValSize = ValTy.getSizeInBits();
11020b57cec5SDimitry Andric 
11030b57cec5SDimitry Andric     assert((ValSize != 64 || STI.hasVFP2Base()) &&
11040b57cec5SDimitry Andric            "Don't know how to load/store 64-bit value without VFP");
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric     const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
11070b57cec5SDimitry Andric     if (NewOpc == G_LOAD || NewOpc == G_STORE)
11080b57cec5SDimitry Andric       return false;
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric     I.setDesc(TII.get(NewOpc));
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric     if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
11130b57cec5SDimitry Andric       // LDRH has a funny addressing mode (there's already a FIXME for it).
11140b57cec5SDimitry Andric       MIB.addReg(0);
11150b57cec5SDimitry Andric     MIB.addImm(0).add(predOps(ARMCC::AL));
11160b57cec5SDimitry Andric     break;
11170b57cec5SDimitry Andric   }
11180b57cec5SDimitry Andric   case G_MERGE_VALUES: {
11190b57cec5SDimitry Andric     if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
11200b57cec5SDimitry Andric       return false;
11210b57cec5SDimitry Andric     break;
11220b57cec5SDimitry Andric   }
11230b57cec5SDimitry Andric   case G_UNMERGE_VALUES: {
11240b57cec5SDimitry Andric     if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
11250b57cec5SDimitry Andric       return false;
11260b57cec5SDimitry Andric     break;
11270b57cec5SDimitry Andric   }
11280b57cec5SDimitry Andric   case G_BRCOND: {
11290b57cec5SDimitry Andric     if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
11300b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
11310b57cec5SDimitry Andric       return false;
11320b57cec5SDimitry Andric     }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric     // Set the flags.
11350b57cec5SDimitry Andric     auto Test =
11360b57cec5SDimitry Andric         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))
11370b57cec5SDimitry Andric             .addReg(I.getOperand(0).getReg())
11380b57cec5SDimitry Andric             .addImm(1)
11390b57cec5SDimitry Andric             .add(predOps(ARMCC::AL));
11400b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
11410b57cec5SDimitry Andric       return false;
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric     // Branch conditionally.
11440b57cec5SDimitry Andric     auto Branch =
11450b57cec5SDimitry Andric         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))
11460b57cec5SDimitry Andric             .add(I.getOperand(1))
11470b57cec5SDimitry Andric             .add(predOps(ARMCC::NE, ARM::CPSR));
11480b57cec5SDimitry Andric     if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
11490b57cec5SDimitry Andric       return false;
11500b57cec5SDimitry Andric     I.eraseFromParent();
11510b57cec5SDimitry Andric     return true;
11520b57cec5SDimitry Andric   }
11530b57cec5SDimitry Andric   case G_PHI: {
11540b57cec5SDimitry Andric     I.setDesc(TII.get(PHI));
11550b57cec5SDimitry Andric 
11568bcb0991SDimitry Andric     Register DstReg = I.getOperand(0).getReg();
11570b57cec5SDimitry Andric     const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
11580b57cec5SDimitry Andric     if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
11590b57cec5SDimitry Andric       break;
11600b57cec5SDimitry Andric     }
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric     return true;
11630b57cec5SDimitry Andric   }
11640b57cec5SDimitry Andric   default:
11650b57cec5SDimitry Andric     return false;
11660b57cec5SDimitry Andric   }
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
11690b57cec5SDimitry Andric }
1170