LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMInstructionSelector.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 352 367 95.9 %
Date: 2017-09-14 15:23:50 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : /// \file
      10             : /// This file implements the targeting of the InstructionSelector class for ARM.
      11             : /// \todo This should be generated by TableGen.
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "ARMRegisterBankInfo.h"
      15             : #include "ARMSubtarget.h"
      16             : #include "ARMTargetMachine.h"
      17             : #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
      18             : #include "llvm/CodeGen/MachineConstantPool.h"
      19             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      20             : #include "llvm/Support/Debug.h"
      21             : 
      22             : #define DEBUG_TYPE "arm-isel"
      23             : 
      24             : #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
      25             : 
      26             : using namespace llvm;
      27             : 
      28             : namespace {
      29             : 
      30             : #define GET_GLOBALISEL_PREDICATE_BITSET
      31             : #include "ARMGenGlobalISel.inc"
      32             : #undef GET_GLOBALISEL_PREDICATE_BITSET
      33             : 
      34       13335 : class ARMInstructionSelector : public InstructionSelector {
      35             : public:
      36             :   ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
      37             :                          const ARMRegisterBankInfo &RBI);
      38             : 
      39             :   bool select(MachineInstr &I) const override;
      40             : 
      41             : private:
      42             :   bool selectImpl(MachineInstr &I) const;
      43             : 
      44             :   struct CmpConstants;
      45             :   struct InsertInfo;
      46             : 
      47             :   bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
      48             :                  MachineRegisterInfo &MRI) const;
      49             : 
      50             :   // Helper for inserting a comparison sequence that sets \p ResReg to either 1
      51             :   // if \p LHSReg and \p RHSReg are in the relationship defined by \p Cond, or
      52             :   // \p PrevRes otherwise. In essence, it computes PrevRes OR (LHS Cond RHS).
      53             :   bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
      54             :                         ARMCC::CondCodes Cond, unsigned LHSReg, unsigned RHSReg,
      55             :                         unsigned PrevRes) const;
      56             : 
      57             :   // Set \p DestReg to \p Constant.
      58             :   void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
      59             : 
      60             :   bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
      61             :   bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
      62             : 
      63             :   // Check if the types match and both operands have the expected size and
      64             :   // register bank.
      65             :   bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
      66             :                       unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
      67             : 
      68             :   // Check if the register has the expected size and register bank.
      69             :   bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
      70             :                 unsigned ExpectedRegBankID) const;
      71             : 
      72             :   const ARMBaseInstrInfo &TII;
      73             :   const ARMBaseRegisterInfo &TRI;
      74             :   const ARMBaseTargetMachine &TM;
      75             :   const ARMRegisterBankInfo &RBI;
      76             :   const ARMSubtarget &STI;
      77             : 
      78             : #define GET_GLOBALISEL_PREDICATES_DECL
      79             : #include "ARMGenGlobalISel.inc"
      80             : #undef GET_GLOBALISEL_PREDICATES_DECL
      81             : 
      82             : // We declare the temporaries used by selectImpl() in the class to minimize the
      83             : // cost of constructing placeholder values.
      84             : #define GET_GLOBALISEL_TEMPORARIES_DECL
      85             : #include "ARMGenGlobalISel.inc"
      86             : #undef GET_GLOBALISEL_TEMPORARIES_DECL
      87             : };
      88             : } // end anonymous namespace
      89             : 
      90             : namespace llvm {
      91             : InstructionSelector *
      92        4487 : createARMInstructionSelector(const ARMBaseTargetMachine &TM,
      93             :                              const ARMSubtarget &STI,
      94             :                              const ARMRegisterBankInfo &RBI) {
      95        4487 :   return new ARMInstructionSelector(TM, STI, RBI);
      96             : }
      97             : }
      98             : 
      99             : const unsigned zero_reg = 0;
     100             : 
     101             : #define GET_GLOBALISEL_IMPL
     102             : #include "ARMGenGlobalISel.inc"
     103             : #undef GET_GLOBALISEL_IMPL
     104             : 
     105        4487 : ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
     106             :                                                const ARMSubtarget &STI,
     107        4487 :                                                const ARMRegisterBankInfo &RBI)
     108        4487 :     : InstructionSelector(), TII(*STI.getInstrInfo()),
     109        4487 :       TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
     110             : #define GET_GLOBALISEL_PREDICATES_INIT
     111             : #include "ARMGenGlobalISel.inc"
     112             : #undef GET_GLOBALISEL_PREDICATES_INIT
     113             : #define GET_GLOBALISEL_TEMPORARIES_INIT
     114             : #include "ARMGenGlobalISel.inc"
     115             : #undef GET_GLOBALISEL_TEMPORARIES_INIT
     116             : {
     117        4487 : }
     118             : 
     119         958 : static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
     120             :                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
     121             :                        const RegisterBankInfo &RBI) {
     122         958 :   unsigned DstReg = I.getOperand(0).getReg();
     123         958 :   if (TargetRegisterInfo::isPhysicalRegister(DstReg))
     124             :     return true;
     125             : 
     126         550 :   const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
     127             :   (void)RegBank;
     128             :   assert(RegBank && "Can't get reg bank for virtual register");
     129             : 
     130         550 :   const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
     131             :   assert((RegBank->getID() == ARM::GPRRegBankID ||
     132             :           RegBank->getID() == ARM::FPRRegBankID) &&
     133             :          "Unsupported reg bank");
     134             : 
     135         550 :   const TargetRegisterClass *RC = &ARM::GPRRegClass;
     136             : 
     137         550 :   if (RegBank->getID() == ARM::FPRRegBankID) {
     138          86 :     if (DstSize == 32)
     139             :       RC = &ARM::SPRRegClass;
     140          35 :     else if (DstSize == 64)
     141             :       RC = &ARM::DPRRegClass;
     142             :     else
     143           0 :       llvm_unreachable("Unsupported destination size");
     144             :   }
     145             : 
     146             :   // No need to constrain SrcReg. It will get constrained when
     147             :   // we hit another of its uses or its defs.
     148             :   // Copies do not have constraints.
     149         550 :   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
     150             :     DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
     151             :                  << " operand\n");
     152             :     return false;
     153             :   }
     154             :   return true;
     155             : }
     156             : 
     157           9 : static bool selectMergeValues(MachineInstrBuilder &MIB,
     158             :                               const ARMBaseInstrInfo &TII,
     159             :                               MachineRegisterInfo &MRI,
     160             :                               const TargetRegisterInfo &TRI,
     161             :                               const RegisterBankInfo &RBI) {
     162             :   assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP");
     163             : 
     164             :   // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
     165             :   // into one DPR.
     166           9 :   unsigned VReg0 = MIB->getOperand(0).getReg();
     167             :   (void)VReg0;
     168             :   assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
     169             :          RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
     170             :          "Unsupported operand for G_MERGE_VALUES");
     171           9 :   unsigned VReg1 = MIB->getOperand(1).getReg();
     172             :   (void)VReg1;
     173             :   assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
     174             :          RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
     175             :          "Unsupported operand for G_MERGE_VALUES");
     176           9 :   unsigned VReg2 = MIB->getOperand(2).getReg();
     177             :   (void)VReg2;
     178             :   assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
     179             :          RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
     180             :          "Unsupported operand for G_MERGE_VALUES");
     181             : 
     182          27 :   MIB->setDesc(TII.get(ARM::VMOVDRR));
     183          27 :   MIB.add(predOps(ARMCC::AL));
     184             : 
     185           9 :   return true;
     186             : }
     187             : 
     188           5 : static bool selectUnmergeValues(MachineInstrBuilder &MIB,
     189             :                                 const ARMBaseInstrInfo &TII,
     190             :                                 MachineRegisterInfo &MRI,
     191             :                                 const TargetRegisterInfo &TRI,
     192             :                                 const RegisterBankInfo &RBI) {
     193             :   assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP");
     194             : 
     195             :   // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
     196             :   // GPRs.
     197           5 :   unsigned VReg0 = MIB->getOperand(0).getReg();
     198             :   (void)VReg0;
     199             :   assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
     200             :          RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
     201             :          "Unsupported operand for G_UNMERGE_VALUES");
     202           5 :   unsigned VReg1 = MIB->getOperand(1).getReg();
     203             :   (void)VReg1;
     204             :   assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
     205             :          RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
     206             :          "Unsupported operand for G_UNMERGE_VALUES");
     207           5 :   unsigned VReg2 = MIB->getOperand(2).getReg();
     208             :   (void)VReg2;
     209             :   assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
     210             :          RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
     211             :          "Unsupported operand for G_UNMERGE_VALUES");
     212             : 
     213          15 :   MIB->setDesc(TII.get(ARM::VMOVRRD));
     214          15 :   MIB.add(predOps(ARMCC::AL));
     215             : 
     216           5 :   return true;
     217             : }
     218             : 
     219             : /// Select the opcode for simple extensions (that translate to a single SXT/UXT
     220             : /// instruction). Extension operations more complicated than that should not
     221             : /// invoke this. Returns the original opcode if it doesn't know how to select a
     222             : /// better one.
     223             : static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) {
     224             :   using namespace TargetOpcode;
     225             : 
     226          70 :   if (Size != 8 && Size != 16)
     227             :     return Opc;
     228             : 
     229          70 :   if (Opc == G_SEXT)
     230          36 :     return Size == 8 ? ARM::SXTB : ARM::SXTH;
     231             : 
     232          34 :   if (Opc == G_ZEXT)
     233          34 :     return Size == 8 ? ARM::UXTB : ARM::UXTH;
     234             : 
     235             :   return Opc;
     236             : }
     237             : 
     238             : /// Select the opcode for simple loads and stores. For types smaller than 32
     239             : /// bits, the value will be zero extended. Returns the original opcode if it
     240             : /// doesn't know how to select a better one.
     241         121 : static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
     242             :                                       unsigned Size) {
     243         121 :   bool isStore = Opc == TargetOpcode::G_STORE;
     244             : 
     245         121 :   if (RegBank == ARM::GPRRegBankID) {
     246         117 :     switch (Size) {
     247           4 :     case 1:
     248             :     case 8:
     249           4 :       return isStore ? ARM::STRBi12 : ARM::LDRBi12;
     250           3 :     case 16:
     251           3 :       return isStore ? ARM::STRH : ARM::LDRH;
     252         110 :     case 32:
     253         110 :       return isStore ? ARM::STRi12 : ARM::LDRi12;
     254             :     default:
     255             :       return Opc;
     256             :     }
     257             :   }
     258             : 
     259           4 :   if (RegBank == ARM::FPRRegBankID) {
     260           4 :     switch (Size) {
     261           2 :     case 32:
     262           2 :       return isStore ? ARM::VSTRS : ARM::VLDRS;
     263           2 :     case 64:
     264           2 :       return isStore ? ARM::VSTRD : ARM::VLDRD;
     265             :     default:
     266             :       return Opc;
     267             :     }
     268             :   }
     269             : 
     270             :   return Opc;
     271             : }
     272             : 
     273             : // When lowering comparisons, we sometimes need to perform two compares instead
     274             : // of just one. Get the condition codes for both comparisons. If only one is
     275             : // needed, the second member of the pair is ARMCC::AL.
     276             : static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
     277          47 : getComparePreds(CmpInst::Predicate Pred) {
     278          47 :   std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
     279          47 :   switch (Pred) {
     280           3 :   case CmpInst::FCMP_ONE:
     281           9 :     Preds = {ARMCC::GT, ARMCC::MI};
     282           3 :     break;
     283           2 :   case CmpInst::FCMP_UEQ:
     284           6 :     Preds = {ARMCC::EQ, ARMCC::VS};
     285           2 :     break;
     286           4 :   case CmpInst::ICMP_EQ:
     287             :   case CmpInst::FCMP_OEQ:
     288           4 :     Preds.first = ARMCC::EQ;
     289           4 :     break;
     290           7 :   case CmpInst::ICMP_SGT:
     291             :   case CmpInst::FCMP_OGT:
     292           7 :     Preds.first = ARMCC::GT;
     293           7 :     break;
     294           3 :   case CmpInst::ICMP_SGE:
     295             :   case CmpInst::FCMP_OGE:
     296           3 :     Preds.first = ARMCC::GE;
     297           3 :     break;
     298           3 :   case CmpInst::ICMP_UGT:
     299             :   case CmpInst::FCMP_UGT:
     300           3 :     Preds.first = ARMCC::HI;
     301           3 :     break;
     302           2 :   case CmpInst::FCMP_OLT:
     303           2 :     Preds.first = ARMCC::MI;
     304           2 :     break;
     305           3 :   case CmpInst::ICMP_ULE:
     306             :   case CmpInst::FCMP_OLE:
     307           3 :     Preds.first = ARMCC::LS;
     308           3 :     break;
     309           2 :   case CmpInst::FCMP_ORD:
     310           2 :     Preds.first = ARMCC::VC;
     311           2 :     break;
     312           2 :   case CmpInst::FCMP_UNO:
     313           2 :     Preds.first = ARMCC::VS;
     314           2 :     break;
     315           2 :   case CmpInst::FCMP_UGE:
     316           2 :     Preds.first = ARMCC::PL;
     317           2 :     break;
     318           5 :   case CmpInst::ICMP_SLT:
     319             :   case CmpInst::FCMP_ULT:
     320           5 :     Preds.first = ARMCC::LT;
     321           5 :     break;
     322           3 :   case CmpInst::ICMP_SLE:
     323             :   case CmpInst::FCMP_ULE:
     324           3 :     Preds.first = ARMCC::LE;
     325           3 :     break;
     326           4 :   case CmpInst::FCMP_UNE:
     327             :   case CmpInst::ICMP_NE:
     328           4 :     Preds.first = ARMCC::NE;
     329           4 :     break;
     330           1 :   case CmpInst::ICMP_UGE:
     331           1 :     Preds.first = ARMCC::HS;
     332           1 :     break;
     333           1 :   case CmpInst::ICMP_ULT:
     334           1 :     Preds.first = ARMCC::LO;
     335           1 :     break;
     336             :   default:
     337             :     break;
     338             :   }
     339             :   assert(Preds.first != ARMCC::AL && "No comparisons needed?");
     340          47 :   return Preds;
     341             : }
     342             : 
     343             : struct ARMInstructionSelector::CmpConstants {
     344             :   CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned OpRegBank,
     345             :                unsigned OpSize)
     346          51 :       : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
     347          51 :         OperandRegBankID(OpRegBank), OperandSize(OpSize) {}
     348             : 
     349             :   // The opcode used for performing the comparison.
     350             :   const unsigned ComparisonOpcode;
     351             : 
     352             :   // The opcode used for reading the flags set by the comparison. May be
     353             :   // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
     354             :   const unsigned ReadFlagsOpcode;
     355             : 
     356             :   // The assumed register bank ID for the operands.
     357             :   const unsigned OperandRegBankID;
     358             : 
     359             :   // The assumed size in bits for the operands.
     360             :   const unsigned OperandSize;
     361             : };
     362             : 
     363             : struct ARMInstructionSelector::InsertInfo {
     364             :   InsertInfo(MachineInstrBuilder &MIB)
     365         153 :       : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
     366         153 :         DbgLoc(MIB->getDebugLoc()) {}
     367             : 
     368             :   MachineBasicBlock &MBB;
     369             :   const MachineBasicBlock::instr_iterator InsertBefore;
     370             :   const DebugLoc &DbgLoc;
     371             : };
     372             : 
     373          51 : void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
     374             :                                          unsigned Constant) const {
     375         204 :   (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVi))
     376          51 :       .addDef(DestReg)
     377         102 :       .addImm(Constant)
     378         204 :       .add(predOps(ARMCC::AL))
     379         102 :       .add(condCodeOp());
     380          51 : }
     381             : 
     382          47 : bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
     383             :                                             unsigned LHSReg, unsigned RHSReg,
     384             :                                             unsigned ExpectedSize,
     385             :                                             unsigned ExpectedRegBankID) const {
     386         188 :   return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
     387          94 :          validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
     388          94 :          validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
     389             : }
     390             : 
     391         147 : bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
     392             :                                       unsigned ExpectedSize,
     393             :                                       unsigned ExpectedRegBankID) const {
     394         147 :   if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
     395             :     DEBUG(dbgs() << "Unexpected size for register");
     396             :     return false;
     397             :   }
     398             : 
     399         147 :   if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
     400             :     DEBUG(dbgs() << "Unexpected register bank for register");
     401             :     return false;
     402             :   }
     403             : 
     404             :   return true;
     405             : }
     406             : 
     407          51 : bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
     408             :                                        MachineInstrBuilder &MIB,
     409             :                                        MachineRegisterInfo &MRI) const {
     410          51 :   const InsertInfo I(MIB);
     411             : 
     412          51 :   auto ResReg = MIB->getOperand(0).getReg();
     413          51 :   if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
     414             :     return false;
     415             : 
     416             :   auto Cond =
     417          51 :       static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
     418          51 :   if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
     419           4 :     putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
     420           4 :     MIB->eraseFromParent();
     421           4 :     return true;
     422             :   }
     423             : 
     424          47 :   auto LHSReg = MIB->getOperand(2).getReg();
     425          47 :   auto RHSReg = MIB->getOperand(3).getReg();
     426          47 :   if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
     427          47 :                       Helper.OperandRegBankID))
     428             :     return false;
     429             : 
     430          47 :   auto ARMConds = getComparePreds(Cond);
     431          47 :   auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
     432          47 :   putConstant(I, ZeroReg, 0);
     433             : 
     434          47 :   if (ARMConds.second == ARMCC::AL) {
     435             :     // Simple case, we only need one comparison and we're done.
     436          42 :     if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
     437             :                           ZeroReg))
     438             :       return false;
     439             :   } else {
     440             :     // Not so simple, we need two successive comparisons.
     441           5 :     auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
     442           5 :     if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
     443             :                           RHSReg, ZeroReg))
     444             :       return false;
     445           5 :     if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
     446             :                           IntermediateRes))
     447             :       return false;
     448             :   }
     449             : 
     450          47 :   MIB->eraseFromParent();
     451          47 :   return true;
     452             : }
     453             : 
     454          52 : bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
     455             :                                               unsigned ResReg,
     456             :                                               ARMCC::CondCodes Cond,
     457             :                                               unsigned LHSReg, unsigned RHSReg,
     458             :                                               unsigned PrevRes) const {
     459             :   // Perform the comparison.
     460             :   auto CmpI =
     461         156 :       BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
     462          52 :           .addUse(LHSReg)
     463          52 :           .addUse(RHSReg)
     464         156 :           .add(predOps(ARMCC::AL));
     465          52 :   if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
     466             :     return false;
     467             : 
     468             :   // Read the comparison flags (if necessary).
     469          52 :   if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
     470          35 :     auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
     471          70 :                          TII.get(Helper.ReadFlagsOpcode))
     472         105 :                      .add(predOps(ARMCC::AL));
     473          35 :     if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
     474           0 :       return false;
     475             :   }
     476             : 
     477             :   // Select either 1 or the previous result based on the value of the flags.
     478         156 :   auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVCCi))
     479          52 :                    .addDef(ResReg)
     480          52 :                    .addUse(PrevRes)
     481          52 :                    .addImm(1)
     482         156 :                    .add(predOps(Cond, ARM::CPSR));
     483          52 :   if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
     484             :     return false;
     485             : 
     486             :   return true;
     487             : }
     488             : 
     489         101 : bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
     490             :                                           MachineRegisterInfo &MRI) const {
     491         152 :   if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
     492             :     DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
     493             :     return false;
     494             :   }
     495             : 
     496         101 :   auto GV = MIB->getOperand(1).getGlobal();
     497         101 :   if (GV->isThreadLocal()) {
     498             :     DEBUG(dbgs() << "TLS variables not supported yet\n");
     499             :     return false;
     500             :   }
     501             : 
     502          96 :   auto &MBB = *MIB->getParent();
     503          96 :   auto &MF = *MBB.getParent();
     504             : 
     505          96 :   bool UseMovt = STI.useMovt(MF);
     506             : 
     507         192 :   unsigned Size = TM.getPointerSize();
     508          96 :   unsigned Alignment = 4;
     509             : 
     510             :   auto addOpsForConstantPoolLoad = [&MF, Alignment,
     511             :                                     Size](MachineInstrBuilder &MIB,
     512          80 :                                           const GlobalValue *GV, bool IsSBREL) {
     513             :     assert(MIB->getOpcode() == ARM::LDRi12 && "Unsupported instruction");
     514          20 :     auto ConstPool = MF.getConstantPool();
     515             :     auto CPIndex =
     516             :         // For SB relative entries we need a target-specific constant pool.
     517             :         // Otherwise, just use a regular constant pool entry.
     518             :         IsSBREL
     519          40 :             ? ConstPool->getConstantPoolIndex(
     520           8 :                   ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
     521          20 :             : ConstPool->getConstantPoolIndex(GV, Alignment);
     522          20 :     MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
     523             :         .addMemOperand(
     524             :             MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
     525          80 :                                     MachineMemOperand::MOLoad, Size, Alignment))
     526          20 :         .addImm(0)
     527          60 :         .add(predOps(ARMCC::AL));
     528         116 :   };
     529             : 
     530          96 :   if (TM.isPositionIndependent()) {
     531          32 :     bool Indirect = STI.isGVIndirectSymbol(GV);
     532             :     // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
     533             :     // support it yet. See PR28229.
     534             :     unsigned Opc =
     535          32 :         UseMovt && !STI.isTargetELF()
     536          40 :             ? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel)
     537          32 :             : (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel);
     538          96 :     MIB->setDesc(TII.get(Opc));
     539             : 
     540          32 :     if (STI.isTargetDarwin())
     541          16 :       MIB->getOperand(1).setTargetFlags(ARMII::MO_NONLAZY);
     542             : 
     543          32 :     if (Indirect)
     544          16 :       MIB.addMemOperand(MF.getMachineMemOperand(
     545             :           MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
     546          48 :           TM.getPointerSize(), Alignment));
     547             : 
     548          32 :     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
     549             :   }
     550             : 
     551          64 :   bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
     552          64 :   if (STI.isROPI() && isReadOnly) {
     553          16 :     unsigned Opc = UseMovt ? ARM::MOV_ga_pcrel : ARM::LDRLIT_ga_pcrel;
     554          48 :     MIB->setDesc(TII.get(Opc));
     555          16 :     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
     556             :   }
     557          72 :   if (STI.isRWPI() && !isReadOnly) {
     558          16 :     auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
     559          16 :     MachineInstrBuilder OffsetMIB;
     560          16 :     if (UseMovt) {
     561           8 :       OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
     562          24 :                           TII.get(ARM::MOVi32imm), Offset);
     563             :       OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
     564             :     } else {
     565             :       // Load the offset from the constant pool.
     566           8 :       OffsetMIB =
     567          24 :           BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::LDRi12), Offset);
     568           8 :       addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
     569             :     }
     570          16 :     if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
     571             :       return false;
     572             : 
     573             :     // Add the offset to the SB register.
     574          48 :     MIB->setDesc(TII.get(ARM::ADDrr));
     575          16 :     MIB->RemoveOperand(1);
     576          16 :     MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
     577          16 :         .addReg(Offset)
     578          64 :         .add(predOps(ARMCC::AL))
     579          32 :         .add(condCodeOp());
     580             : 
     581          16 :     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
     582             :   }
     583             : 
     584          64 :   if (STI.isTargetELF()) {
     585          24 :     if (UseMovt) {
     586          24 :       MIB->setDesc(TII.get(ARM::MOVi32imm));
     587             :     } else {
     588             :       // Load the global's address from the constant pool.
     589          36 :       MIB->setDesc(TII.get(ARM::LDRi12));
     590          12 :       MIB->RemoveOperand(1);
     591          12 :       addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
     592             :     }
     593          16 :   } else if (STI.isTargetMachO()) {
     594           8 :     if (UseMovt)
     595           8 :       MIB->setDesc(TII.get(ARM::MOVi32imm));
     596             :     else
     597           8 :       MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs));
     598             :   } else {
     599             :     DEBUG(dbgs() << "Object format not supported yet\n");
     600             :     return false;
     601             :   }
     602             : 
     603          32 :   return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
     604             : }
     605             : 
     606           4 : bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
     607             :                                           MachineRegisterInfo &MRI) const {
     608           4 :   auto &MBB = *MIB->getParent();
     609          12 :   auto InsertBefore = std::next(MIB->getIterator());
     610           8 :   auto &DbgLoc = MIB->getDebugLoc();
     611             : 
     612             :   // Compare the condition to 0.
     613           4 :   auto CondReg = MIB->getOperand(1).getReg();
     614             :   assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
     615             :          "Unsupported types for select operation");
     616          12 :   auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri))
     617           4 :                   .addUse(CondReg)
     618           4 :                   .addImm(0)
     619          12 :                   .add(predOps(ARMCC::AL));
     620           4 :   if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
     621             :     return false;
     622             : 
     623             :   // Move a value into the result register based on the result of the
     624             :   // comparison.
     625           4 :   auto ResReg = MIB->getOperand(0).getReg();
     626           4 :   auto TrueReg = MIB->getOperand(2).getReg();
     627           4 :   auto FalseReg = MIB->getOperand(3).getReg();
     628             :   assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
     629             :          validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
     630             :          "Unsupported types for select operation");
     631          12 :   auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr))
     632           4 :                    .addDef(ResReg)
     633           4 :                    .addUse(TrueReg)
     634           4 :                    .addUse(FalseReg)
     635          12 :                    .add(predOps(ARMCC::EQ, ARM::CPSR));
     636           4 :   if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
     637             :     return false;
     638             : 
     639           4 :   MIB->eraseFromParent();
     640             :   return true;
     641             : }
     642             : 
     643        1940 : bool ARMInstructionSelector::select(MachineInstr &I) const {
     644             :   assert(I.getParent() && "Instruction should be in a basic block!");
     645             :   assert(I.getParent()->getParent() && "Instruction should be in a function!");
     646             : 
     647        1940 :   auto &MBB = *I.getParent();
     648        1940 :   auto &MF = *MBB.getParent();
     649        1940 :   auto &MRI = MF.getRegInfo();
     650             : 
     651        5820 :   if (!isPreISelGenericOpcode(I.getOpcode())) {
     652        1294 :     if (I.isCopy())
     653         852 :       return selectCopy(I, TII, MRI, TRI, RBI);
     654             : 
     655             :     return true;
     656             :   }
     657             : 
     658         646 :   if (selectImpl(I))
     659             :     return true;
     660             : 
     661        1066 :   MachineInstrBuilder MIB{MF, I};
     662         533 :   bool isSExt = false;
     663             : 
     664             :   using namespace TargetOpcode;
     665        1066 :   switch (I.getOpcode()) {
     666          38 :   case G_SEXT:
     667          38 :     isSExt = true;
     668             :     LLVM_FALLTHROUGH;
     669         125 :   case G_ZEXT: {
     670         125 :     LLT DstTy = MRI.getType(I.getOperand(0).getReg());
     671             :     // FIXME: Smaller destination sizes coming soon!
     672         125 :     if (DstTy.getSizeInBits() != 32) {
     673             :       DEBUG(dbgs() << "Unsupported destination size for extension");
     674           0 :       return false;
     675             :     }
     676             : 
     677         125 :     LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
     678         125 :     unsigned SrcSize = SrcTy.getSizeInBits();
     679         125 :     switch (SrcSize) {
     680          55 :     case 1: {
     681             :       // ZExt boils down to & 0x1; for SExt we also subtract that from 0
     682         165 :       I.setDesc(TII.get(ARM::ANDri));
     683         330 :       MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
     684             : 
     685          55 :       if (isSExt) {
     686           2 :         unsigned SExtResult = I.getOperand(0).getReg();
     687             : 
     688             :         // Use a new virtual register for the result of the AND
     689           2 :         unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
     690           2 :         I.getOperand(0).setReg(AndResult);
     691             : 
     692           6 :         auto InsertBefore = std::next(I.getIterator());
     693             :         auto SubI =
     694           8 :             BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri))
     695           2 :                 .addDef(SExtResult)
     696           2 :                 .addUse(AndResult)
     697           2 :                 .addImm(0)
     698           8 :                 .add(predOps(ARMCC::AL))
     699           4 :                 .add(condCodeOp());
     700           2 :         if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
     701           0 :           return false;
     702             :       }
     703             :       break;
     704             :     }
     705          70 :     case 8:
     706             :     case 16: {
     707         210 :       unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
     708          70 :       if (NewOpc == I.getOpcode())
     709             :         return false;
     710         210 :       I.setDesc(TII.get(NewOpc));
     711         280 :       MIB.addImm(0).add(predOps(ARMCC::AL));
     712          70 :       break;
     713             :     }
     714             :     default:
     715             :       DEBUG(dbgs() << "Unsupported source size for extension");
     716             :       return false;
     717             :     }
     718         125 :     break;
     719             :   }
     720         106 :   case G_ANYEXT:
     721             :   case G_TRUNC: {
     722             :     // The high bits are undefined, so there's nothing special to do, just
     723             :     // treat it as a copy.
     724         106 :     auto SrcReg = I.getOperand(1).getReg();
     725         106 :     auto DstReg = I.getOperand(0).getReg();
     726             : 
     727         106 :     const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
     728         106 :     const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
     729             : 
     730         106 :     if (SrcRegBank.getID() != DstRegBank.getID()) {
     731             :       DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
     732             :       return false;
     733             :     }
     734             : 
     735         106 :     if (SrcRegBank.getID() != ARM::GPRRegBankID) {
     736             :       DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
     737             :       return false;
     738             :     }
     739             : 
     740         318 :     I.setDesc(TII.get(COPY));
     741         106 :     return selectCopy(I, TII, MRI, TRI, RBI);
     742             :   }
     743           4 :   case G_SELECT:
     744           4 :     return selectSelect(MIB, MRI);
     745          17 :   case G_ICMP: {
     746             :     CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END,
     747          17 :                         ARM::GPRRegBankID, 32);
     748          17 :     return selectCmp(Helper, MIB, MRI);
     749             :   }
     750          34 :   case G_FCMP: {
     751             :     assert(STI.hasVFP2() && "Can't select fcmp without VFP");
     752             : 
     753          34 :     unsigned OpReg = I.getOperand(2).getReg();
     754          34 :     unsigned Size = MRI.getType(OpReg).getSizeInBits();
     755             : 
     756          34 :     if (Size == 64 && STI.isFPOnlySP()) {
     757             :       DEBUG(dbgs() << "Subtarget only supports single precision");
     758             :       return false;
     759             :     }
     760          34 :     if (Size != 32 && Size != 64) {
     761             :       DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
     762             :       return false;
     763             :     }
     764             : 
     765             :     CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
     766          68 :                         ARM::FPRRegBankID, Size);
     767          34 :     return selectCmp(Helper, MIB, MRI);
     768             :   }
     769           1 :   case G_GEP:
     770           3 :     I.setDesc(TII.get(ARM::ADDrr));
     771           5 :     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
     772           1 :     break;
     773           8 :   case G_FRAME_INDEX:
     774             :     // Add 0 to the given frame index and hope it will eventually be folded into
     775             :     // the user(s).
     776          24 :     I.setDesc(TII.get(ARM::ADDri));
     777          48 :     MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
     778           8 :     break;
     779           0 :   case G_CONSTANT: {
     780           0 :     unsigned Reg = I.getOperand(0).getReg();
     781             : 
     782           0 :     if (!validReg(MRI, Reg, 32, ARM::GPRRegBankID))
     783             :       return false;
     784             : 
     785           0 :     I.setDesc(TII.get(ARM::MOVi));
     786           0 :     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
     787             : 
     788           0 :     auto &Val = I.getOperand(1);
     789           0 :     if (Val.isCImm()) {
     790           0 :       if (Val.getCImm()->getBitWidth() > 32)
     791             :         return false;
     792           0 :       Val.ChangeToImmediate(Val.getCImm()->getZExtValue());
     793             :     }
     794             : 
     795           0 :     if (!Val.isImm()) {
     796             :       return false;
     797             :     }
     798             : 
     799             :     break;
     800             :   }
     801         101 :   case G_GLOBAL_VALUE:
     802         101 :     return selectGlobal(MIB, MRI);
     803         121 :   case G_STORE:
     804             :   case G_LOAD: {
     805         121 :     const auto &MemOp = **I.memoperands_begin();
     806         121 :     if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
     807             :       DEBUG(dbgs() << "Atomic load/store not supported yet\n");
     808           0 :       return false;
     809             :     }
     810             : 
     811         121 :     unsigned Reg = I.getOperand(0).getReg();
     812         121 :     unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
     813             : 
     814         121 :     LLT ValTy = MRI.getType(Reg);
     815         121 :     const auto ValSize = ValTy.getSizeInBits();
     816             : 
     817             :     assert((ValSize != 64 || STI.hasVFP2()) &&
     818             :            "Don't know how to load/store 64-bit value without VFP");
     819             : 
     820         242 :     const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
     821         121 :     if (NewOpc == G_LOAD || NewOpc == G_STORE)
     822             :       return false;
     823             : 
     824         363 :     I.setDesc(TII.get(NewOpc));
     825             : 
     826         121 :     if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
     827             :       // LDRH has a funny addressing mode (there's already a FIXME for it).
     828           3 :       MIB.addReg(0);
     829         484 :     MIB.addImm(0).add(predOps(ARMCC::AL));
     830         121 :     break;
     831             :   }
     832           9 :   case G_MERGE_VALUES: {
     833           9 :     if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
     834             :       return false;
     835             :     break;
     836             :   }
     837           5 :   case G_UNMERGE_VALUES: {
     838           5 :     if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
     839             :       return false;
     840             :     break;
     841             :   }
     842           2 :   case G_BRCOND: {
     843           2 :     if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
     844             :       DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
     845             :       return false;
     846             :     }
     847             : 
     848             :     // Set the flags.
     849           8 :     auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri))
     850           2 :                     .addReg(I.getOperand(0).getReg())
     851           2 :                     .addImm(1)
     852           6 :                     .add(predOps(ARMCC::AL));
     853           2 :     if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
     854             :       return false;
     855             : 
     856             :     // Branch conditionally.
     857           4 :     auto Branch = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::Bcc))
     858           6 :                       .add(I.getOperand(1))
     859           6 :                       .add(predOps(ARMCC::EQ, ARM::CPSR));
     860           2 :     if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
     861             :       return false;
     862           2 :     I.eraseFromParent();
     863           2 :     return true;
     864             :   }
     865             :   default:
     866             :     return false;
     867             :   }
     868             : 
     869         269 :   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
     870      216918 : }

Generated by: LCOV version 1.13