122274934SDiana Picus //===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
222274934SDiana Picus //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
622274934SDiana Picus //
722274934SDiana Picus //===----------------------------------------------------------------------===//
822274934SDiana Picus /// \file
922274934SDiana Picus /// This file implements the targeting of the InstructionSelector class for ARM.
1022274934SDiana Picus /// \todo This should be generated by TableGen.
1122274934SDiana Picus //===----------------------------------------------------------------------===//
1222274934SDiana Picus 
1322274934SDiana Picus #include "ARMRegisterBankInfo.h"
1422274934SDiana Picus #include "ARMSubtarget.h"
1522274934SDiana Picus #include "ARMTargetMachine.h"
16674888d8SDiana Picus #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
1762651300SDavid Blaikie #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
18930e6ec8SDiana Picus #include "llvm/CodeGen/MachineConstantPool.h"
19812caee6SDiana Picus #include "llvm/CodeGen/MachineRegisterInfo.h"
205d986953SReid Kleckner #include "llvm/IR/IntrinsicsARM.h"
2122274934SDiana Picus #include "llvm/Support/Debug.h"
2222274934SDiana Picus 
2322274934SDiana Picus #define DEBUG_TYPE "arm-isel"
2422274934SDiana Picus 
2522274934SDiana Picus using namespace llvm;
2622274934SDiana Picus 
27674888d8SDiana Picus namespace {
288abcbbb2SDiana Picus 
298abcbbb2SDiana Picus #define GET_GLOBALISEL_PREDICATE_BITSET
308abcbbb2SDiana Picus #include "ARMGenGlobalISel.inc"
318abcbbb2SDiana Picus #undef GET_GLOBALISEL_PREDICATE_BITSET
328abcbbb2SDiana Picus 
33674888d8SDiana Picus class ARMInstructionSelector : public InstructionSelector {
34674888d8SDiana Picus public:
358abcbbb2SDiana Picus   ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
36674888d8SDiana Picus                          const ARMRegisterBankInfo &RBI);
37674888d8SDiana Picus 
38e14c91b7SAmara Emerson   bool select(MachineInstr &I) override;
getName()3962651300SDavid Blaikie   static const char *getName() { return DEBUG_TYPE; }
40674888d8SDiana Picus 
41674888d8SDiana Picus private:
42f76f3154SDaniel Sanders   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
438abcbbb2SDiana Picus 
44995746daSDiana Picus   struct CmpConstants;
45995746daSDiana Picus   struct InsertInfo;
465b916538SDiana Picus 
47995746daSDiana Picus   bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
48995746daSDiana Picus                  MachineRegisterInfo &MRI) const;
49621894acSDiana Picus 
50995746daSDiana Picus   // Helper for inserting a comparison sequence that sets \p ResReg to either 1
51995746daSDiana Picus   // if \p LHSReg and \p RHSReg are in the relationship defined by \p Cond, or
52995746daSDiana Picus   // \p PrevRes otherwise. In essence, it computes PrevRes OR (LHS Cond RHS).
53995746daSDiana Picus   bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
54995746daSDiana Picus                         ARMCC::CondCodes Cond, unsigned LHSReg, unsigned RHSReg,
55995746daSDiana Picus                         unsigned PrevRes) const;
56995746daSDiana Picus 
57995746daSDiana Picus   // Set \p DestReg to \p Constant.
58995746daSDiana Picus   void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
59995746daSDiana Picus 
60930e6ec8SDiana Picus   bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
61995746daSDiana Picus   bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
62e393bc72SDiana Picus   bool selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const;
63995746daSDiana Picus 
64995746daSDiana Picus   // Check if the types match and both operands have the expected size and
65995746daSDiana Picus   // register bank.
66995746daSDiana Picus   bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
67995746daSDiana Picus                       unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
68995746daSDiana Picus 
69995746daSDiana Picus   // Check if the register has the expected size and register bank.
70995746daSDiana Picus   bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
71995746daSDiana Picus                 unsigned ExpectedRegBankID) const;
727145d22fSDiana Picus 
73674888d8SDiana Picus   const ARMBaseInstrInfo &TII;
74674888d8SDiana Picus   const ARMBaseRegisterInfo &TRI;
758abcbbb2SDiana Picus   const ARMBaseTargetMachine &TM;
76674888d8SDiana Picus   const ARMRegisterBankInfo &RBI;
778abcbbb2SDiana Picus   const ARMSubtarget &STI;
788abcbbb2SDiana Picus 
79cf0ff638SDiana Picus   // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
80cf0ff638SDiana Picus   // uses "STI." in the code generated by TableGen. If we want to reuse some of
81cf0ff638SDiana Picus   // the custom C++ predicates written for DAGISel, we need to have both around.
82cf0ff638SDiana Picus   const ARMSubtarget *Subtarget = &STI;
83cf0ff638SDiana Picus 
84813af0d2SDiana Picus   // Store the opcodes that we might need, so we don't have to check what kind
85813af0d2SDiana Picus   // of subtarget (ARM vs Thumb) we have all the time.
86813af0d2SDiana Picus   struct OpcodeCache {
87813af0d2SDiana Picus     unsigned ZEXT16;
88813af0d2SDiana Picus     unsigned SEXT16;
89813af0d2SDiana Picus 
90813af0d2SDiana Picus     unsigned ZEXT8;
91813af0d2SDiana Picus     unsigned SEXT8;
92813af0d2SDiana Picus 
93813af0d2SDiana Picus     // Used for implementing ZEXT/SEXT from i1
94813af0d2SDiana Picus     unsigned AND;
95813af0d2SDiana Picus     unsigned RSB;
96813af0d2SDiana Picus 
97813af0d2SDiana Picus     unsigned STORE32;
98813af0d2SDiana Picus     unsigned LOAD32;
99813af0d2SDiana Picus 
100813af0d2SDiana Picus     unsigned STORE16;
101813af0d2SDiana Picus     unsigned LOAD16;
102813af0d2SDiana Picus 
103813af0d2SDiana Picus     unsigned STORE8;
104813af0d2SDiana Picus     unsigned LOAD8;
105813af0d2SDiana Picus 
106c0f964ebSDiana Picus     unsigned ADDrr;
107dcaa939aSDiana Picus     unsigned ADDri;
108c0f964ebSDiana Picus 
109aa4118a8SDiana Picus     // Used for G_ICMP
11075a04e2aSDiana Picus     unsigned CMPrr;
11175a04e2aSDiana Picus     unsigned MOVi;
11275a04e2aSDiana Picus     unsigned MOVCCi;
11375a04e2aSDiana Picus 
114aa4118a8SDiana Picus     // Used for G_SELECT
115aa4118a8SDiana Picus     unsigned MOVCCr;
116aa4118a8SDiana Picus 
117a00425ffSDiana Picus     unsigned TSTri;
118a00425ffSDiana Picus     unsigned Bcc;
119a00425ffSDiana Picus 
1203b7beafcSDiana Picus     // Used for G_GLOBAL_VALUE
1213b7beafcSDiana Picus     unsigned MOVi32imm;
1223b7beafcSDiana Picus     unsigned ConstPoolLoad;
1233b7beafcSDiana Picus     unsigned MOV_ga_pcrel;
1243b7beafcSDiana Picus     unsigned LDRLIT_ga_pcrel;
1253b7beafcSDiana Picus     unsigned LDRLIT_ga_abs;
1263b7beafcSDiana Picus 
127813af0d2SDiana Picus     OpcodeCache(const ARMSubtarget &STI);
128813af0d2SDiana Picus   } const Opcodes;
129813af0d2SDiana Picus 
130813af0d2SDiana Picus   // Select the opcode for simple extensions (that translate to a single SXT/UXT
131813af0d2SDiana Picus   // instruction). Extension operations more complicated than that should not
132813af0d2SDiana Picus   // invoke this. Returns the original opcode if it doesn't know how to select a
133813af0d2SDiana Picus   // better one.
134813af0d2SDiana Picus   unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) const;
135813af0d2SDiana Picus 
136813af0d2SDiana Picus   // Select the opcode for simple loads and stores. Returns the original opcode
137813af0d2SDiana Picus   // if it doesn't know how to select a better one.
138813af0d2SDiana Picus   unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
139813af0d2SDiana Picus                                  unsigned Size) const;
140813af0d2SDiana Picus 
141b4a64744SMatt Arsenault   void renderVFPF32Imm(MachineInstrBuilder &New, const MachineInstr &Old,
142b4a64744SMatt Arsenault                        int OpIdx = -1) const;
143b4a64744SMatt Arsenault   void renderVFPF64Imm(MachineInstrBuilder &New, const MachineInstr &Old,
144b4a64744SMatt Arsenault                        int OpIdx = -1) const;
145b6e83b98SDiana Picus 
1468abcbbb2SDiana Picus #define GET_GLOBALISEL_PREDICATES_DECL
1478abcbbb2SDiana Picus #include "ARMGenGlobalISel.inc"
1488abcbbb2SDiana Picus #undef GET_GLOBALISEL_PREDICATES_DECL
1498abcbbb2SDiana Picus 
1508abcbbb2SDiana Picus // We declare the temporaries used by selectImpl() in the class to minimize the
1518abcbbb2SDiana Picus // cost of constructing placeholder values.
1528abcbbb2SDiana Picus #define GET_GLOBALISEL_TEMPORARIES_DECL
1538abcbbb2SDiana Picus #include "ARMGenGlobalISel.inc"
1548abcbbb2SDiana Picus #undef GET_GLOBALISEL_TEMPORARIES_DECL
155674888d8SDiana Picus };
156674888d8SDiana Picus } // end anonymous namespace
157674888d8SDiana Picus 
158674888d8SDiana Picus namespace llvm {
159674888d8SDiana Picus InstructionSelector *
createARMInstructionSelector(const ARMBaseTargetMachine & TM,const ARMSubtarget & STI,const ARMRegisterBankInfo & RBI)1608abcbbb2SDiana Picus createARMInstructionSelector(const ARMBaseTargetMachine &TM,
1618abcbbb2SDiana Picus                              const ARMSubtarget &STI,
162674888d8SDiana Picus                              const ARMRegisterBankInfo &RBI) {
1638abcbbb2SDiana Picus   return new ARMInstructionSelector(TM, STI, RBI);
164674888d8SDiana Picus }
165674888d8SDiana Picus }
166674888d8SDiana Picus 
1678abcbbb2SDiana Picus #define GET_GLOBALISEL_IMPL
1688abcbbb2SDiana Picus #include "ARMGenGlobalISel.inc"
1698abcbbb2SDiana Picus #undef GET_GLOBALISEL_IMPL
1708abcbbb2SDiana Picus 
ARMInstructionSelector(const ARMBaseTargetMachine & TM,const ARMSubtarget & STI,const ARMRegisterBankInfo & RBI)1718abcbbb2SDiana Picus ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
1728abcbbb2SDiana Picus                                                const ARMSubtarget &STI,
17322274934SDiana Picus                                                const ARMRegisterBankInfo &RBI)
174f3a344d2SKazu Hirata     : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI),
175f3a344d2SKazu Hirata       STI(STI), Opcodes(STI),
1768abcbbb2SDiana Picus #define GET_GLOBALISEL_PREDICATES_INIT
1778abcbbb2SDiana Picus #include "ARMGenGlobalISel.inc"
1788abcbbb2SDiana Picus #undef GET_GLOBALISEL_PREDICATES_INIT
1798abcbbb2SDiana Picus #define GET_GLOBALISEL_TEMPORARIES_INIT
1808abcbbb2SDiana Picus #include "ARMGenGlobalISel.inc"
1818abcbbb2SDiana Picus #undef GET_GLOBALISEL_TEMPORARIES_INIT
1828abcbbb2SDiana Picus {
1838abcbbb2SDiana Picus }
18422274934SDiana Picus 
guessRegClass(unsigned Reg,MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI,const RegisterBankInfo & RBI)185865f7fecSDiana Picus static const TargetRegisterClass *guessRegClass(unsigned Reg,
186865f7fecSDiana Picus                                                 MachineRegisterInfo &MRI,
187865f7fecSDiana Picus                                                 const TargetRegisterInfo &TRI,
188865f7fecSDiana Picus                                                 const RegisterBankInfo &RBI) {
189865f7fecSDiana Picus   const RegisterBank *RegBank = RBI.getRegBank(Reg, MRI, TRI);
190865f7fecSDiana Picus   assert(RegBank && "Can't get reg bank for virtual register");
191865f7fecSDiana Picus 
192865f7fecSDiana Picus   const unsigned Size = MRI.getType(Reg).getSizeInBits();
193865f7fecSDiana Picus   assert((RegBank->getID() == ARM::GPRRegBankID ||
194865f7fecSDiana Picus           RegBank->getID() == ARM::FPRRegBankID) &&
195865f7fecSDiana Picus          "Unsupported reg bank");
196865f7fecSDiana Picus 
197865f7fecSDiana Picus   if (RegBank->getID() == ARM::FPRRegBankID) {
198865f7fecSDiana Picus     if (Size == 32)
199865f7fecSDiana Picus       return &ARM::SPRRegClass;
200865f7fecSDiana Picus     else if (Size == 64)
201865f7fecSDiana Picus       return &ARM::DPRRegClass;
202e79d656cSRoman Tereshin     else if (Size == 128)
203e79d656cSRoman Tereshin       return &ARM::QPRRegClass;
204865f7fecSDiana Picus     else
205865f7fecSDiana Picus       llvm_unreachable("Unsupported destination size");
206865f7fecSDiana Picus   }
207865f7fecSDiana Picus 
208865f7fecSDiana Picus   return &ARM::GPRRegClass;
209865f7fecSDiana Picus }
210865f7fecSDiana Picus 
selectCopy(MachineInstr & I,const TargetInstrInfo & TII,MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI,const RegisterBankInfo & RBI)211812caee6SDiana Picus static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
212812caee6SDiana Picus                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
213812caee6SDiana Picus                        const RegisterBankInfo &RBI) {
2140c476111SDaniel Sanders   Register DstReg = I.getOperand(0).getReg();
2152bea69bfSDaniel Sanders   if (Register::isPhysicalRegister(DstReg))
216812caee6SDiana Picus     return true;
217812caee6SDiana Picus 
218865f7fecSDiana Picus   const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
2194fa83c03SDiana Picus 
220812caee6SDiana Picus   // No need to constrain SrcReg. It will get constrained when
221812caee6SDiana Picus   // we hit another of its uses or its defs.
222812caee6SDiana Picus   // Copies do not have constraints.
223812caee6SDiana Picus   if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
224d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
225812caee6SDiana Picus                       << " operand\n");
226812caee6SDiana Picus     return false;
227812caee6SDiana Picus   }
228812caee6SDiana Picus   return true;
229812caee6SDiana Picus }
230812caee6SDiana Picus 
selectMergeValues(MachineInstrBuilder & MIB,const ARMBaseInstrInfo & TII,MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI,const RegisterBankInfo & RBI)2310b4190a9SDiana Picus static bool selectMergeValues(MachineInstrBuilder &MIB,
232b1701e0bSDiana Picus                               const ARMBaseInstrInfo &TII,
233b1701e0bSDiana Picus                               MachineRegisterInfo &MRI,
234b1701e0bSDiana Picus                               const TargetRegisterInfo &TRI,
235b1701e0bSDiana Picus                               const RegisterBankInfo &RBI) {
236760df47bSSimon Tatham   assert(TII.getSubtarget().hasVFP2Base() && "Can't select merge without VFP");
237b1701e0bSDiana Picus 
2380b4190a9SDiana Picus   // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
239b1701e0bSDiana Picus   // into one DPR.
240b482e1bfSJay Foad   Register VReg0 = MIB.getReg(0);
241b1701e0bSDiana Picus   (void)VReg0;
242b1701e0bSDiana Picus   assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
243b1701e0bSDiana Picus          RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
2440b4190a9SDiana Picus          "Unsupported operand for G_MERGE_VALUES");
245b482e1bfSJay Foad   Register VReg1 = MIB.getReg(1);
246b1701e0bSDiana Picus   (void)VReg1;
247b1701e0bSDiana Picus   assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
248b1701e0bSDiana Picus          RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2490b4190a9SDiana Picus          "Unsupported operand for G_MERGE_VALUES");
250b482e1bfSJay Foad   Register VReg2 = MIB.getReg(2);
251b1701e0bSDiana Picus   (void)VReg2;
252b1701e0bSDiana Picus   assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
253b1701e0bSDiana Picus          RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2540b4190a9SDiana Picus          "Unsupported operand for G_MERGE_VALUES");
255b1701e0bSDiana Picus 
256b1701e0bSDiana Picus   MIB->setDesc(TII.get(ARM::VMOVDRR));
257b1701e0bSDiana Picus   MIB.add(predOps(ARMCC::AL));
258b1701e0bSDiana Picus 
259b1701e0bSDiana Picus   return true;
260b1701e0bSDiana Picus }
261b1701e0bSDiana Picus 
selectUnmergeValues(MachineInstrBuilder & MIB,const ARMBaseInstrInfo & TII,MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI,const RegisterBankInfo & RBI)2620b4190a9SDiana Picus static bool selectUnmergeValues(MachineInstrBuilder &MIB,
2630b4190a9SDiana Picus                                 const ARMBaseInstrInfo &TII,
264b1701e0bSDiana Picus                                 MachineRegisterInfo &MRI,
265b1701e0bSDiana Picus                                 const TargetRegisterInfo &TRI,
266b1701e0bSDiana Picus                                 const RegisterBankInfo &RBI) {
267760df47bSSimon Tatham   assert(TII.getSubtarget().hasVFP2Base() &&
268760df47bSSimon Tatham          "Can't select unmerge without VFP");
269b1701e0bSDiana Picus 
2700b4190a9SDiana Picus   // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
2710b4190a9SDiana Picus   // GPRs.
272b482e1bfSJay Foad   Register VReg0 = MIB.getReg(0);
273b1701e0bSDiana Picus   (void)VReg0;
274b1701e0bSDiana Picus   assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
275b1701e0bSDiana Picus          RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2760b4190a9SDiana Picus          "Unsupported operand for G_UNMERGE_VALUES");
277b482e1bfSJay Foad   Register VReg1 = MIB.getReg(1);
278b1701e0bSDiana Picus   (void)VReg1;
2790b4190a9SDiana Picus   assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
2800b4190a9SDiana Picus          RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
2810b4190a9SDiana Picus          "Unsupported operand for G_UNMERGE_VALUES");
282b482e1bfSJay Foad   Register VReg2 = MIB.getReg(2);
2830b4190a9SDiana Picus   (void)VReg2;
2840b4190a9SDiana Picus   assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
2850b4190a9SDiana Picus          RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
2860b4190a9SDiana Picus          "Unsupported operand for G_UNMERGE_VALUES");
287b1701e0bSDiana Picus 
2880b4190a9SDiana Picus   MIB->setDesc(TII.get(ARM::VMOVRRD));
289b1701e0bSDiana Picus   MIB.add(predOps(ARMCC::AL));
290b1701e0bSDiana Picus 
291b1701e0bSDiana Picus   return true;
292b1701e0bSDiana Picus }
293b1701e0bSDiana Picus 
OpcodeCache(const ARMSubtarget & STI)294813af0d2SDiana Picus ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {
295813af0d2SDiana Picus   bool isThumb = STI.isThumb();
296813af0d2SDiana Picus 
297813af0d2SDiana Picus   using namespace TargetOpcode;
298813af0d2SDiana Picus 
299813af0d2SDiana Picus #define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC
300813af0d2SDiana Picus   STORE_OPCODE(SEXT16, SXTH);
301813af0d2SDiana Picus   STORE_OPCODE(ZEXT16, UXTH);
302813af0d2SDiana Picus 
303813af0d2SDiana Picus   STORE_OPCODE(SEXT8, SXTB);
304813af0d2SDiana Picus   STORE_OPCODE(ZEXT8, UXTB);
305813af0d2SDiana Picus 
306813af0d2SDiana Picus   STORE_OPCODE(AND, ANDri);
307813af0d2SDiana Picus   STORE_OPCODE(RSB, RSBri);
308813af0d2SDiana Picus 
309813af0d2SDiana Picus   STORE_OPCODE(STORE32, STRi12);
310813af0d2SDiana Picus   STORE_OPCODE(LOAD32, LDRi12);
311813af0d2SDiana Picus 
312813af0d2SDiana Picus   // LDRH/STRH are special...
313813af0d2SDiana Picus   STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
314813af0d2SDiana Picus   LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
315813af0d2SDiana Picus 
316813af0d2SDiana Picus   STORE_OPCODE(STORE8, STRBi12);
317813af0d2SDiana Picus   STORE_OPCODE(LOAD8, LDRBi12);
31875a04e2aSDiana Picus 
319c0f964ebSDiana Picus   STORE_OPCODE(ADDrr, ADDrr);
320dcaa939aSDiana Picus   STORE_OPCODE(ADDri, ADDri);
321c0f964ebSDiana Picus 
32275a04e2aSDiana Picus   STORE_OPCODE(CMPrr, CMPrr);
32375a04e2aSDiana Picus   STORE_OPCODE(MOVi, MOVi);
32475a04e2aSDiana Picus   STORE_OPCODE(MOVCCi, MOVCCi);
325aa4118a8SDiana Picus 
326aa4118a8SDiana Picus   STORE_OPCODE(MOVCCr, MOVCCr);
327a00425ffSDiana Picus 
328a00425ffSDiana Picus   STORE_OPCODE(TSTri, TSTri);
329a00425ffSDiana Picus   STORE_OPCODE(Bcc, Bcc);
3303b7beafcSDiana Picus 
3313b7beafcSDiana Picus   STORE_OPCODE(MOVi32imm, MOVi32imm);
3323b7beafcSDiana Picus   ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;
3333b7beafcSDiana Picus   STORE_OPCODE(MOV_ga_pcrel, MOV_ga_pcrel);
3343b7beafcSDiana Picus   LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;
3353b7beafcSDiana Picus   LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;
336813af0d2SDiana Picus #undef MAP_OPCODE
337813af0d2SDiana Picus }
338813af0d2SDiana Picus 
selectSimpleExtOpc(unsigned Opc,unsigned Size) const339813af0d2SDiana Picus unsigned ARMInstructionSelector::selectSimpleExtOpc(unsigned Opc,
340813af0d2SDiana Picus                                                     unsigned Size) const {
3418b6c6bedSDiana Picus   using namespace TargetOpcode;
3428b6c6bedSDiana Picus 
343e836878bSDiana Picus   if (Size != 8 && Size != 16)
344e836878bSDiana Picus     return Opc;
3458b6c6bedSDiana Picus 
3468b6c6bedSDiana Picus   if (Opc == G_SEXT)
347813af0d2SDiana Picus     return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
3488b6c6bedSDiana Picus 
3498b6c6bedSDiana Picus   if (Opc == G_ZEXT)
350813af0d2SDiana Picus     return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
3518b6c6bedSDiana Picus 
352e836878bSDiana Picus   return Opc;
3538b6c6bedSDiana Picus }
3548b6c6bedSDiana Picus 
selectLoadStoreOpCode(unsigned Opc,unsigned RegBank,unsigned Size) const355813af0d2SDiana Picus unsigned ARMInstructionSelector::selectLoadStoreOpCode(unsigned Opc,
356813af0d2SDiana Picus                                                        unsigned RegBank,
357813af0d2SDiana Picus                                                        unsigned Size) const {
3583b99c64bSDiana Picus   bool isStore = Opc == TargetOpcode::G_STORE;
3593b99c64bSDiana Picus 
3601540b06eSDiana Picus   if (RegBank == ARM::GPRRegBankID) {
36159720b42SDiana Picus     switch (Size) {
36259720b42SDiana Picus     case 1:
36359720b42SDiana Picus     case 8:
364813af0d2SDiana Picus       return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
36559720b42SDiana Picus     case 16:
366813af0d2SDiana Picus       return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
36759720b42SDiana Picus     case 32:
368813af0d2SDiana Picus       return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
369e836878bSDiana Picus     default:
3703b99c64bSDiana Picus       return Opc;
371e836878bSDiana Picus     }
372278c722eSDiana Picus   }
373278c722eSDiana Picus 
374e836878bSDiana Picus   if (RegBank == ARM::FPRRegBankID) {
3751540b06eSDiana Picus     switch (Size) {
3761540b06eSDiana Picus     case 32:
3773b99c64bSDiana Picus       return isStore ? ARM::VSTRS : ARM::VLDRS;
3781540b06eSDiana Picus     case 64:
3793b99c64bSDiana Picus       return isStore ? ARM::VSTRD : ARM::VLDRD;
380e836878bSDiana Picus     default:
3813b99c64bSDiana Picus       return Opc;
382e836878bSDiana Picus     }
3831540b06eSDiana Picus   }
3841540b06eSDiana Picus 
3853b99c64bSDiana Picus   return Opc;
3861540b06eSDiana Picus }
3871540b06eSDiana Picus 
3885b916538SDiana Picus // When lowering comparisons, we sometimes need to perform two compares instead
3895b916538SDiana Picus // of just one. Get the condition codes for both comparisons. If only one is
3905b916538SDiana Picus // needed, the second member of the pair is ARMCC::AL.
3915b916538SDiana Picus static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
getComparePreds(CmpInst::Predicate Pred)3925b916538SDiana Picus getComparePreds(CmpInst::Predicate Pred) {
3935b916538SDiana Picus   std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
394621894acSDiana Picus   switch (Pred) {
395621894acSDiana Picus   case CmpInst::FCMP_ONE:
3965b916538SDiana Picus     Preds = {ARMCC::GT, ARMCC::MI};
3975b916538SDiana Picus     break;
398621894acSDiana Picus   case CmpInst::FCMP_UEQ:
3995b916538SDiana Picus     Preds = {ARMCC::EQ, ARMCC::VS};
4005b916538SDiana Picus     break;
401621894acSDiana Picus   case CmpInst::ICMP_EQ:
402621894acSDiana Picus   case CmpInst::FCMP_OEQ:
4035b916538SDiana Picus     Preds.first = ARMCC::EQ;
4045b916538SDiana Picus     break;
405621894acSDiana Picus   case CmpInst::ICMP_SGT:
406621894acSDiana Picus   case CmpInst::FCMP_OGT:
4075b916538SDiana Picus     Preds.first = ARMCC::GT;
4085b916538SDiana Picus     break;
409621894acSDiana Picus   case CmpInst::ICMP_SGE:
410621894acSDiana Picus   case CmpInst::FCMP_OGE:
4115b916538SDiana Picus     Preds.first = ARMCC::GE;
4125b916538SDiana Picus     break;
413621894acSDiana Picus   case CmpInst::ICMP_UGT:
414621894acSDiana Picus   case CmpInst::FCMP_UGT:
4155b916538SDiana Picus     Preds.first = ARMCC::HI;
4165b916538SDiana Picus     break;
417621894acSDiana Picus   case CmpInst::FCMP_OLT:
4185b916538SDiana Picus     Preds.first = ARMCC::MI;
4195b916538SDiana Picus     break;
420621894acSDiana Picus   case CmpInst::ICMP_ULE:
421621894acSDiana Picus   case CmpInst::FCMP_OLE:
4225b916538SDiana Picus     Preds.first = ARMCC::LS;
4235b916538SDiana Picus     break;
424621894acSDiana Picus   case CmpInst::FCMP_ORD:
4255b916538SDiana Picus     Preds.first = ARMCC::VC;
4265b916538SDiana Picus     break;
427621894acSDiana Picus   case CmpInst::FCMP_UNO:
4285b916538SDiana Picus     Preds.first = ARMCC::VS;
4295b916538SDiana Picus     break;
430621894acSDiana Picus   case CmpInst::FCMP_UGE:
4315b916538SDiana Picus     Preds.first = ARMCC::PL;
4325b916538SDiana Picus     break;
433621894acSDiana Picus   case CmpInst::ICMP_SLT:
434621894acSDiana Picus   case CmpInst::FCMP_ULT:
4355b916538SDiana Picus     Preds.first = ARMCC::LT;
4365b916538SDiana Picus     break;
437621894acSDiana Picus   case CmpInst::ICMP_SLE:
438621894acSDiana Picus   case CmpInst::FCMP_ULE:
4395b916538SDiana Picus     Preds.first = ARMCC::LE;
4405b916538SDiana Picus     break;
441621894acSDiana Picus   case CmpInst::FCMP_UNE:
442621894acSDiana Picus   case CmpInst::ICMP_NE:
4435b916538SDiana Picus     Preds.first = ARMCC::NE;
4445b916538SDiana Picus     break;
445621894acSDiana Picus   case CmpInst::ICMP_UGE:
4465b916538SDiana Picus     Preds.first = ARMCC::HS;
4475b916538SDiana Picus     break;
448621894acSDiana Picus   case CmpInst::ICMP_ULT:
4495b916538SDiana Picus     Preds.first = ARMCC::LO;
4505b916538SDiana Picus     break;
4515b916538SDiana Picus   default:
4525b916538SDiana Picus     break;
453621894acSDiana Picus   }
4545b916538SDiana Picus   assert(Preds.first != ARMCC::AL && "No comparisons needed?");
4555b916538SDiana Picus   return Preds;
456621894acSDiana Picus }
457621894acSDiana Picus 
458995746daSDiana Picus struct ARMInstructionSelector::CmpConstants {
CmpConstantsARMInstructionSelector::CmpConstants45975a04e2aSDiana Picus   CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,
46075a04e2aSDiana Picus                unsigned OpRegBank, unsigned OpSize)
461995746daSDiana Picus       : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
46275a04e2aSDiana Picus         SelectResultOpcode(SelectOpcode), OperandRegBankID(OpRegBank),
46375a04e2aSDiana Picus         OperandSize(OpSize) {}
4645b916538SDiana Picus 
4655b916538SDiana Picus   // The opcode used for performing the comparison.
466995746daSDiana Picus   const unsigned ComparisonOpcode;
4675b916538SDiana Picus 
4685b916538SDiana Picus   // The opcode used for reading the flags set by the comparison. May be
4695b916538SDiana Picus   // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
470995746daSDiana Picus   const unsigned ReadFlagsOpcode;
4715b916538SDiana Picus 
47275a04e2aSDiana Picus   // The opcode used for materializing the result of the comparison.
47375a04e2aSDiana Picus   const unsigned SelectResultOpcode;
47475a04e2aSDiana Picus 
4755b916538SDiana Picus   // The assumed register bank ID for the operands.
476995746daSDiana Picus   const unsigned OperandRegBankID;
4775b916538SDiana Picus 
47821014df5SDiana Picus   // The assumed size in bits for the operands.
479995746daSDiana Picus   const unsigned OperandSize;
480995746daSDiana Picus };
48121014df5SDiana Picus 
482995746daSDiana Picus struct ARMInstructionSelector::InsertInfo {
InsertInfoARMInstructionSelector::InsertInfo483995746daSDiana Picus   InsertInfo(MachineInstrBuilder &MIB)
484995746daSDiana Picus       : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
485995746daSDiana Picus         DbgLoc(MIB->getDebugLoc()) {}
4865b916538SDiana Picus 
487995746daSDiana Picus   MachineBasicBlock &MBB;
488995746daSDiana Picus   const MachineBasicBlock::instr_iterator InsertBefore;
489995746daSDiana Picus   const DebugLoc &DbgLoc;
490995746daSDiana Picus };
4915b916538SDiana Picus 
putConstant(InsertInfo I,unsigned DestReg,unsigned Constant) const492995746daSDiana Picus void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
493995746daSDiana Picus                                          unsigned Constant) const {
49475a04e2aSDiana Picus   (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
4955b916538SDiana Picus       .addDef(DestReg)
4965b916538SDiana Picus       .addImm(Constant)
4975b916538SDiana Picus       .add(predOps(ARMCC::AL))
4985b916538SDiana Picus       .add(condCodeOp());
4995b916538SDiana Picus }
5005b916538SDiana Picus 
validOpRegPair(MachineRegisterInfo & MRI,unsigned LHSReg,unsigned RHSReg,unsigned ExpectedSize,unsigned ExpectedRegBankID) const501995746daSDiana Picus bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
502995746daSDiana Picus                                             unsigned LHSReg, unsigned RHSReg,
503995746daSDiana Picus                                             unsigned ExpectedSize,
504995746daSDiana Picus                                             unsigned ExpectedRegBankID) const {
5055b916538SDiana Picus   return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
506995746daSDiana Picus          validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
507995746daSDiana Picus          validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
5085b916538SDiana Picus }
5095b916538SDiana Picus 
validReg(MachineRegisterInfo & MRI,unsigned Reg,unsigned ExpectedSize,unsigned ExpectedRegBankID) const510995746daSDiana Picus bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
511995746daSDiana Picus                                       unsigned ExpectedSize,
512995746daSDiana Picus                                       unsigned ExpectedRegBankID) const {
513995746daSDiana Picus   if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
514d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Unexpected size for register");
5155b916538SDiana Picus     return false;
5165b916538SDiana Picus   }
5175b916538SDiana Picus 
518995746daSDiana Picus   if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
519d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Unexpected register bank for register");
5205b916538SDiana Picus     return false;
5215b916538SDiana Picus   }
5225b916538SDiana Picus 
5235b916538SDiana Picus   return true;
5245b916538SDiana Picus }
5255b916538SDiana Picus 
selectCmp(CmpConstants Helper,MachineInstrBuilder & MIB,MachineRegisterInfo & MRI) const526995746daSDiana Picus bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
527995746daSDiana Picus                                        MachineInstrBuilder &MIB,
528995746daSDiana Picus                                        MachineRegisterInfo &MRI) const {
529995746daSDiana Picus   const InsertInfo I(MIB);
530621894acSDiana Picus 
531b482e1bfSJay Foad   auto ResReg = MIB.getReg(0);
532995746daSDiana Picus   if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
5335b916538SDiana Picus     return false;
5345b916538SDiana Picus 
535621894acSDiana Picus   auto Cond =
536621894acSDiana Picus       static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
5375b916538SDiana Picus   if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
538995746daSDiana Picus     putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
5395b916538SDiana Picus     MIB->eraseFromParent();
5405b916538SDiana Picus     return true;
5415b916538SDiana Picus   }
5425b916538SDiana Picus 
543b482e1bfSJay Foad   auto LHSReg = MIB.getReg(2);
544b482e1bfSJay Foad   auto RHSReg = MIB.getReg(3);
545995746daSDiana Picus   if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
546995746daSDiana Picus                       Helper.OperandRegBankID))
547621894acSDiana Picus     return false;
548621894acSDiana Picus 
5495b916538SDiana Picus   auto ARMConds = getComparePreds(Cond);
550995746daSDiana Picus   auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
551995746daSDiana Picus   putConstant(I, ZeroReg, 0);
5525b916538SDiana Picus 
5535b916538SDiana Picus   if (ARMConds.second == ARMCC::AL) {
5545b916538SDiana Picus     // Simple case, we only need one comparison and we're done.
555995746daSDiana Picus     if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
5565b916538SDiana Picus                           ZeroReg))
557621894acSDiana Picus       return false;
5585b916538SDiana Picus   } else {
5595b916538SDiana Picus     // Not so simple, we need two successive comparisons.
5605b916538SDiana Picus     auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
561995746daSDiana Picus     if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
5625b916538SDiana Picus                           RHSReg, ZeroReg))
5635b916538SDiana Picus       return false;
564995746daSDiana Picus     if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
5655b916538SDiana Picus                           IntermediateRes))
5665b916538SDiana Picus       return false;
5675b916538SDiana Picus   }
568621894acSDiana Picus 
569621894acSDiana Picus   MIB->eraseFromParent();
570621894acSDiana Picus   return true;
571621894acSDiana Picus }
572621894acSDiana Picus 
insertComparison(CmpConstants Helper,InsertInfo I,unsigned ResReg,ARMCC::CondCodes Cond,unsigned LHSReg,unsigned RHSReg,unsigned PrevRes) const573995746daSDiana Picus bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
574995746daSDiana Picus                                               unsigned ResReg,
575995746daSDiana Picus                                               ARMCC::CondCodes Cond,
576995746daSDiana Picus                                               unsigned LHSReg, unsigned RHSReg,
577995746daSDiana Picus                                               unsigned PrevRes) const {
578995746daSDiana Picus   // Perform the comparison.
579995746daSDiana Picus   auto CmpI =
580995746daSDiana Picus       BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
581995746daSDiana Picus           .addUse(LHSReg)
582995746daSDiana Picus           .addUse(RHSReg)
583995746daSDiana Picus           .add(predOps(ARMCC::AL));
584995746daSDiana Picus   if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
585995746daSDiana Picus     return false;
586995746daSDiana Picus 
587995746daSDiana Picus   // Read the comparison flags (if necessary).
588995746daSDiana Picus   if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
589995746daSDiana Picus     auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
590995746daSDiana Picus                          TII.get(Helper.ReadFlagsOpcode))
591995746daSDiana Picus                      .add(predOps(ARMCC::AL));
592995746daSDiana Picus     if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
593995746daSDiana Picus       return false;
594995746daSDiana Picus   }
595995746daSDiana Picus 
596995746daSDiana Picus   // Select either 1 or the previous result based on the value of the flags.
59775a04e2aSDiana Picus   auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
59875a04e2aSDiana Picus                        TII.get(Helper.SelectResultOpcode))
599995746daSDiana Picus                    .addDef(ResReg)
600995746daSDiana Picus                    .addUse(PrevRes)
601995746daSDiana Picus                    .addImm(1)
602995746daSDiana Picus                    .add(predOps(Cond, ARM::CPSR));
603995746daSDiana Picus   if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
604995746daSDiana Picus     return false;
605995746daSDiana Picus 
606995746daSDiana Picus   return true;
607995746daSDiana Picus }
608995746daSDiana Picus 
selectGlobal(MachineInstrBuilder & MIB,MachineRegisterInfo & MRI) const609930e6ec8SDiana Picus bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
610930e6ec8SDiana Picus                                           MachineRegisterInfo &MRI) const {
611abb08869SDiana Picus   if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
612d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
613930e6ec8SDiana Picus     return false;
614930e6ec8SDiana Picus   }
615930e6ec8SDiana Picus 
616930e6ec8SDiana Picus   auto GV = MIB->getOperand(1).getGlobal();
617930e6ec8SDiana Picus   if (GV->isThreadLocal()) {
618d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");
619930e6ec8SDiana Picus     return false;
620930e6ec8SDiana Picus   }
621930e6ec8SDiana Picus 
622930e6ec8SDiana Picus   auto &MBB = *MIB->getParent();
623930e6ec8SDiana Picus   auto &MF = *MBB.getParent();
624930e6ec8SDiana Picus 
6255b09834bSSam Parker   bool UseMovt = STI.useMovt();
626930e6ec8SDiana Picus 
627*0fb6856aSMatt Arsenault   LLT PtrTy = MRI.getType(MIB->getOperand(0).getReg());
628998118c3SGuillaume Chatelet   const Align Alignment(4);
629abb08869SDiana Picus 
630*0fb6856aSMatt Arsenault   auto addOpsForConstantPoolLoad = [&MF, Alignment, PtrTy](
631*0fb6856aSMatt Arsenault                                        MachineInstrBuilder &MIB,
632abb08869SDiana Picus                                        const GlobalValue *GV, bool IsSBREL) {
6333b7beafcSDiana Picus     assert((MIB->getOpcode() == ARM::LDRi12 ||
6343b7beafcSDiana Picus             MIB->getOpcode() == ARM::t2LDRpci) &&
6353b7beafcSDiana Picus            "Unsupported instruction");
636abb08869SDiana Picus     auto ConstPool = MF.getConstantPool();
637abb08869SDiana Picus     auto CPIndex =
638abb08869SDiana Picus         // For SB relative entries we need a target-specific constant pool.
639abb08869SDiana Picus         // Otherwise, just use a regular constant pool entry.
6408c72b027SCraig Topper         IsSBREL
6418c72b027SCraig Topper             ? ConstPool->getConstantPoolIndex(
6428c72b027SCraig Topper                   ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
6438c72b027SCraig Topper             : ConstPool->getConstantPoolIndex(GV, Alignment);
644abb08869SDiana Picus     MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
6453b7beafcSDiana Picus         .addMemOperand(MF.getMachineMemOperand(
6463b7beafcSDiana Picus             MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
647*0fb6856aSMatt Arsenault             PtrTy, Alignment));
6483b7beafcSDiana Picus     if (MIB->getOpcode() == ARM::LDRi12)
6493b7beafcSDiana Picus       MIB.addImm(0);
6503b7beafcSDiana Picus     MIB.add(predOps(ARMCC::AL));
6513b7beafcSDiana Picus   };
6523b7beafcSDiana Picus 
6533b7beafcSDiana Picus   auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) {
6543b7beafcSDiana Picus     MIB.addMemOperand(MF.getMachineMemOperand(
6553b7beafcSDiana Picus         MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
6563b7beafcSDiana Picus         TM.getProgramPointerSize(), Alignment));
657abb08869SDiana Picus   };
658abb08869SDiana Picus 
659c9f29c62SDiana Picus   if (TM.isPositionIndependent()) {
660ac15473cSDiana Picus     bool Indirect = STI.isGVIndirectSymbol(GV);
6613b7beafcSDiana Picus 
6623b7beafcSDiana Picus     // For ARM mode, we have different pseudoinstructions for direct accesses
6633b7beafcSDiana Picus     // and indirect accesses, and the ones for indirect accesses include the
6643b7beafcSDiana Picus     // load from GOT. For Thumb mode, we use the same pseudoinstruction for both
6653b7beafcSDiana Picus     // direct and indirect accesses, and we need to manually generate the load
6663b7beafcSDiana Picus     // from GOT.
6673b7beafcSDiana Picus     bool UseOpcodeThatLoads = Indirect && !STI.isThumb();
6683b7beafcSDiana Picus 
669c9f29c62SDiana Picus     // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
670c9f29c62SDiana Picus     // support it yet. See PR28229.
67165a401f6SJonas Hahnfeld     unsigned Opc =
67265a401f6SJonas Hahnfeld         UseMovt && !STI.isTargetELF()
67365a401f6SJonas Hahnfeld             ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
6743b7beafcSDiana Picus                                   : Opcodes.MOV_ga_pcrel)
67565a401f6SJonas Hahnfeld             : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
6763b7beafcSDiana Picus                                   : Opcodes.LDRLIT_ga_pcrel);
677c9f29c62SDiana Picus     MIB->setDesc(TII.get(Opc));
678c9f29c62SDiana Picus 
67976d5ac49SEvgeniy Stepanov     int TargetFlags = ARMII::MO_NO_FLAG;
680ac15473cSDiana Picus     if (STI.isTargetDarwin())
68176d5ac49SEvgeniy Stepanov       TargetFlags |= ARMII::MO_NONLAZY;
68276d5ac49SEvgeniy Stepanov     if (STI.isGVInGOT(GV))
68376d5ac49SEvgeniy Stepanov       TargetFlags |= ARMII::MO_GOT;
68476d5ac49SEvgeniy Stepanov     MIB->getOperand(1).setTargetFlags(TargetFlags);
685c9f29c62SDiana Picus 
6863b7beafcSDiana Picus     if (Indirect) {
6873b7beafcSDiana Picus       if (!UseOpcodeThatLoads) {
688b482e1bfSJay Foad         auto ResultReg = MIB.getReg(0);
6893b7beafcSDiana Picus         auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
6903b7beafcSDiana Picus 
6913b7beafcSDiana Picus         MIB->getOperand(0).setReg(AddressReg);
6923b7beafcSDiana Picus 
6933b7beafcSDiana Picus         auto InsertBefore = std::next(MIB->getIterator());
6943b7beafcSDiana Picus         auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),
6953b7beafcSDiana Picus                                TII.get(Opcodes.LOAD32))
6963b7beafcSDiana Picus                            .addDef(ResultReg)
6973b7beafcSDiana Picus                            .addReg(AddressReg)
6983b7beafcSDiana Picus                            .addImm(0)
6993b7beafcSDiana Picus                            .add(predOps(ARMCC::AL));
7003b7beafcSDiana Picus         addGOTMemOperand(MIBLoad);
7013b7beafcSDiana Picus 
7023b7beafcSDiana Picus         if (!constrainSelectedInstRegOperands(*MIBLoad, TII, TRI, RBI))
7033b7beafcSDiana Picus           return false;
7043b7beafcSDiana Picus       } else {
7053b7beafcSDiana Picus         addGOTMemOperand(MIB);
7063b7beafcSDiana Picus       }
7073b7beafcSDiana Picus     }
708c9f29c62SDiana Picus 
709ac15473cSDiana Picus     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
710c9f29c62SDiana Picus   }
711c9f29c62SDiana Picus 
712f9597911SDiana Picus   bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
713f9597911SDiana Picus   if (STI.isROPI() && isReadOnly) {
7143b7beafcSDiana Picus     unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
715f9597911SDiana Picus     MIB->setDesc(TII.get(Opc));
716f9597911SDiana Picus     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
717f9597911SDiana Picus   }
718abb08869SDiana Picus   if (STI.isRWPI() && !isReadOnly) {
719abb08869SDiana Picus     auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
720abb08869SDiana Picus     MachineInstrBuilder OffsetMIB;
721abb08869SDiana Picus     if (UseMovt) {
722abb08869SDiana Picus       OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
7233b7beafcSDiana Picus                           TII.get(Opcodes.MOVi32imm), Offset);
724abb08869SDiana Picus       OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
725abb08869SDiana Picus     } else {
726abb08869SDiana Picus       // Load the offset from the constant pool.
7273b7beafcSDiana Picus       OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
7283b7beafcSDiana Picus                           TII.get(Opcodes.ConstPoolLoad), Offset);
729abb08869SDiana Picus       addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
730abb08869SDiana Picus     }
731abb08869SDiana Picus     if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
732abb08869SDiana Picus       return false;
733abb08869SDiana Picus 
734abb08869SDiana Picus     // Add the offset to the SB register.
7353b7beafcSDiana Picus     MIB->setDesc(TII.get(Opcodes.ADDrr));
73637b37838SShengchen Kan     MIB->removeOperand(1);
737abb08869SDiana Picus     MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
738abb08869SDiana Picus         .addReg(Offset)
739abb08869SDiana Picus         .add(predOps(ARMCC::AL))
740abb08869SDiana Picus         .add(condCodeOp());
741abb08869SDiana Picus 
742abb08869SDiana Picus     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
743abb08869SDiana Picus   }
744f9597911SDiana Picus 
745ac15473cSDiana Picus   if (STI.isTargetELF()) {
746930e6ec8SDiana Picus     if (UseMovt) {
7473b7beafcSDiana Picus       MIB->setDesc(TII.get(Opcodes.MOVi32imm));
748930e6ec8SDiana Picus     } else {
749930e6ec8SDiana Picus       // Load the global's address from the constant pool.
7503b7beafcSDiana Picus       MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
75137b37838SShengchen Kan       MIB->removeOperand(1);
752abb08869SDiana Picus       addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
753930e6ec8SDiana Picus     }
754ac15473cSDiana Picus   } else if (STI.isTargetMachO()) {
755930e6ec8SDiana Picus     if (UseMovt)
7563b7beafcSDiana Picus       MIB->setDesc(TII.get(Opcodes.MOVi32imm));
757930e6ec8SDiana Picus     else
7583b7beafcSDiana Picus       MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));
759930e6ec8SDiana Picus   } else {
760d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
761930e6ec8SDiana Picus     return false;
762930e6ec8SDiana Picus   }
763930e6ec8SDiana Picus 
764930e6ec8SDiana Picus   return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
765930e6ec8SDiana Picus }
766930e6ec8SDiana Picus 
selectSelect(MachineInstrBuilder & MIB,MachineRegisterInfo & MRI) const7677145d22fSDiana Picus bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
768995746daSDiana Picus                                           MachineRegisterInfo &MRI) const {
7697145d22fSDiana Picus   auto &MBB = *MIB->getParent();
7707145d22fSDiana Picus   auto InsertBefore = std::next(MIB->getIterator());
77177367378SDiana Picus   auto &DbgLoc = MIB->getDebugLoc();
7727145d22fSDiana Picus 
7734d512df3SDiana Picus   // Compare the condition to 1.
774b482e1bfSJay Foad   auto CondReg = MIB.getReg(1);
775995746daSDiana Picus   assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
7767145d22fSDiana Picus          "Unsupported types for select operation");
7774d512df3SDiana Picus   auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))
7787145d22fSDiana Picus                   .addUse(CondReg)
7794d512df3SDiana Picus                   .addImm(1)
7807145d22fSDiana Picus                   .add(predOps(ARMCC::AL));
7817145d22fSDiana Picus   if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
7827145d22fSDiana Picus     return false;
7837145d22fSDiana Picus 
7847145d22fSDiana Picus   // Move a value into the result register based on the result of the
7857145d22fSDiana Picus   // comparison.
786b482e1bfSJay Foad   auto ResReg = MIB.getReg(0);
787b482e1bfSJay Foad   auto TrueReg = MIB.getReg(2);
788b482e1bfSJay Foad   auto FalseReg = MIB.getReg(3);
789995746daSDiana Picus   assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
790995746daSDiana Picus          validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
7917145d22fSDiana Picus          "Unsupported types for select operation");
792aa4118a8SDiana Picus   auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.MOVCCr))
7937145d22fSDiana Picus                    .addDef(ResReg)
7947145d22fSDiana Picus                    .addUse(TrueReg)
7957145d22fSDiana Picus                    .addUse(FalseReg)
7967145d22fSDiana Picus                    .add(predOps(ARMCC::EQ, ARM::CPSR));
7977145d22fSDiana Picus   if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
7987145d22fSDiana Picus     return false;
7997145d22fSDiana Picus 
8007145d22fSDiana Picus   MIB->eraseFromParent();
8017145d22fSDiana Picus   return true;
8027145d22fSDiana Picus }
8037145d22fSDiana Picus 
selectShift(unsigned ShiftOpc,MachineInstrBuilder & MIB) const804e393bc72SDiana Picus bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
805e393bc72SDiana Picus                                          MachineInstrBuilder &MIB) const {
8064a7f8d8dSDiana Picus   assert(!STI.isThumb() && "Unsupported subtarget");
807e393bc72SDiana Picus   MIB->setDesc(TII.get(ARM::MOVsr));
808e393bc72SDiana Picus   MIB.addImm(ShiftOpc);
809e393bc72SDiana Picus   MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
810e393bc72SDiana Picus   return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
811e393bc72SDiana Picus }
812e393bc72SDiana Picus 
renderVFPF32Imm(MachineInstrBuilder & NewInstBuilder,const MachineInstr & OldInst,int OpIdx) const813b6e83b98SDiana Picus void ARMInstructionSelector::renderVFPF32Imm(
814b4a64744SMatt Arsenault   MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst,
815b4a64744SMatt Arsenault   int OpIdx) const {
816b6e83b98SDiana Picus   assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
817b4a64744SMatt Arsenault          OpIdx == -1 && "Expected G_FCONSTANT");
818b6e83b98SDiana Picus 
819b6e83b98SDiana Picus   APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
8206bdade85SDiana Picus   int FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue);
821b6e83b98SDiana Picus   assert(FPImmEncoding != -1 && "Invalid immediate value");
822b6e83b98SDiana Picus 
823b6e83b98SDiana Picus   NewInstBuilder.addImm(FPImmEncoding);
824b6e83b98SDiana Picus }
825b6e83b98SDiana Picus 
renderVFPF64Imm(MachineInstrBuilder & NewInstBuilder,const MachineInstr & OldInst,int OpIdx) const826b6e83b98SDiana Picus void ARMInstructionSelector::renderVFPF64Imm(
827b4a64744SMatt Arsenault   MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst, int OpIdx) const {
828b6e83b98SDiana Picus   assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
829b4a64744SMatt Arsenault          OpIdx == -1 && "Expected G_FCONSTANT");
830b6e83b98SDiana Picus 
831b6e83b98SDiana Picus   APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
8326bdade85SDiana Picus   int FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue);
833b6e83b98SDiana Picus   assert(FPImmEncoding != -1 && "Invalid immediate value");
834b6e83b98SDiana Picus 
835b6e83b98SDiana Picus   NewInstBuilder.addImm(FPImmEncoding);
836b6e83b98SDiana Picus }
837b6e83b98SDiana Picus 
select(MachineInstr & I)838e14c91b7SAmara Emerson bool ARMInstructionSelector::select(MachineInstr &I) {
839812caee6SDiana Picus   assert(I.getParent() && "Instruction should be in a basic block!");
840812caee6SDiana Picus   assert(I.getParent()->getParent() && "Instruction should be in a function!");
841812caee6SDiana Picus 
842812caee6SDiana Picus   auto &MBB = *I.getParent();
843812caee6SDiana Picus   auto &MF = *MBB.getParent();
844812caee6SDiana Picus   auto &MRI = MF.getRegInfo();
845812caee6SDiana Picus 
846812caee6SDiana Picus   if (!isPreISelGenericOpcode(I.getOpcode())) {
847812caee6SDiana Picus     if (I.isCopy())
848812caee6SDiana Picus       return selectCopy(I, TII, MRI, TRI, RBI);
849812caee6SDiana Picus 
850812caee6SDiana Picus     return true;
851812caee6SDiana Picus   }
852812caee6SDiana Picus 
85368773859SDiana Picus   using namespace TargetOpcode;
85468773859SDiana Picus 
855e14c91b7SAmara Emerson   if (selectImpl(I, *CoverageInfo))
8568abcbbb2SDiana Picus     return true;
8578abcbbb2SDiana Picus 
858519807f7SDiana Picus   MachineInstrBuilder MIB{MF, I};
859d83df5d3SDiana Picus   bool isSExt = false;
860519807f7SDiana Picus 
861519807f7SDiana Picus   switch (I.getOpcode()) {
8628b6c6bedSDiana Picus   case G_SEXT:
863d83df5d3SDiana Picus     isSExt = true;
864d83df5d3SDiana Picus     LLVM_FALLTHROUGH;
8658b6c6bedSDiana Picus   case G_ZEXT: {
8661136ea2dSDiana Picus     assert(MRI.getType(I.getOperand(0).getReg()).getSizeInBits() <= 32 &&
86706a61cccSDiana Picus            "Unsupported destination size for extension");
8688b6c6bedSDiana Picus 
8698b6c6bedSDiana Picus     LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
8708b6c6bedSDiana Picus     unsigned SrcSize = SrcTy.getSizeInBits();
8718b6c6bedSDiana Picus     switch (SrcSize) {
872d83df5d3SDiana Picus     case 1: {
873d83df5d3SDiana Picus       // ZExt boils down to & 0x1; for SExt we also subtract that from 0
874813af0d2SDiana Picus       I.setDesc(TII.get(Opcodes.AND));
875d83df5d3SDiana Picus       MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
876d83df5d3SDiana Picus 
877d83df5d3SDiana Picus       if (isSExt) {
8780c476111SDaniel Sanders         Register SExtResult = I.getOperand(0).getReg();
879d83df5d3SDiana Picus 
880d83df5d3SDiana Picus         // Use a new virtual register for the result of the AND
8810c476111SDaniel Sanders         Register AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
882d83df5d3SDiana Picus         I.getOperand(0).setReg(AndResult);
883d83df5d3SDiana Picus 
884d83df5d3SDiana Picus         auto InsertBefore = std::next(I.getIterator());
885813af0d2SDiana Picus         auto SubI =
886813af0d2SDiana Picus             BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))
887d83df5d3SDiana Picus                 .addDef(SExtResult)
888d83df5d3SDiana Picus                 .addUse(AndResult)
889d83df5d3SDiana Picus                 .addImm(0)
890d83df5d3SDiana Picus                 .add(predOps(ARMCC::AL))
891d83df5d3SDiana Picus                 .add(condCodeOp());
892d83df5d3SDiana Picus         if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
893d83df5d3SDiana Picus           return false;
894d83df5d3SDiana Picus       }
895d83df5d3SDiana Picus       break;
896d83df5d3SDiana Picus     }
8978b6c6bedSDiana Picus     case 8:
8988b6c6bedSDiana Picus     case 16: {
899813af0d2SDiana Picus       unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
900e836878bSDiana Picus       if (NewOpc == I.getOpcode())
901e836878bSDiana Picus         return false;
9028b6c6bedSDiana Picus       I.setDesc(TII.get(NewOpc));
9038b6c6bedSDiana Picus       MIB.addImm(0).add(predOps(ARMCC::AL));
9048b6c6bedSDiana Picus       break;
9058b6c6bedSDiana Picus     }
9068b6c6bedSDiana Picus     default:
907d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "Unsupported source size for extension");
9088b6c6bedSDiana Picus       return false;
9098b6c6bedSDiana Picus     }
9108b6c6bedSDiana Picus     break;
9118b6c6bedSDiana Picus   }
912657bfd33SDiana Picus   case G_ANYEXT:
91364a33431SDiana Picus   case G_TRUNC: {
91464a33431SDiana Picus     // The high bits are undefined, so there's nothing special to do, just
91564a33431SDiana Picus     // treat it as a copy.
91664a33431SDiana Picus     auto SrcReg = I.getOperand(1).getReg();
91764a33431SDiana Picus     auto DstReg = I.getOperand(0).getReg();
91864a33431SDiana Picus 
91964a33431SDiana Picus     const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
92064a33431SDiana Picus     const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
92164a33431SDiana Picus 
92275ce852aSDiana Picus     if (SrcRegBank.getID() == ARM::FPRRegBankID) {
92375ce852aSDiana Picus       // This should only happen in the obscure case where we have put a 64-bit
92475ce852aSDiana Picus       // integer into a D register. Get it out of there and keep only the
92575ce852aSDiana Picus       // interesting part.
92675ce852aSDiana Picus       assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
92775ce852aSDiana Picus       assert(DstRegBank.getID() == ARM::GPRRegBankID &&
92875ce852aSDiana Picus              "Unsupported combination of register banks");
92975ce852aSDiana Picus       assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
93075ce852aSDiana Picus       assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
93175ce852aSDiana Picus 
9320c476111SDaniel Sanders       Register IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
93375ce852aSDiana Picus       auto InsertBefore = std::next(I.getIterator());
93475ce852aSDiana Picus       auto MovI =
93575ce852aSDiana Picus           BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
93675ce852aSDiana Picus               .addDef(DstReg)
93775ce852aSDiana Picus               .addDef(IgnoredBits)
93875ce852aSDiana Picus               .addUse(SrcReg)
93975ce852aSDiana Picus               .add(predOps(ARMCC::AL));
94075ce852aSDiana Picus       if (!constrainSelectedInstRegOperands(*MovI, TII, TRI, RBI))
94175ce852aSDiana Picus         return false;
94275ce852aSDiana Picus 
94375ce852aSDiana Picus       MIB->eraseFromParent();
94475ce852aSDiana Picus       return true;
94575ce852aSDiana Picus     }
94675ce852aSDiana Picus 
94764a33431SDiana Picus     if (SrcRegBank.getID() != DstRegBank.getID()) {
948d34e60caSNicola Zaghen       LLVM_DEBUG(
949d34e60caSNicola Zaghen           dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
95064a33431SDiana Picus       return false;
95164a33431SDiana Picus     }
95264a33431SDiana Picus 
95364a33431SDiana Picus     if (SrcRegBank.getID() != ARM::GPRRegBankID) {
954d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
95564a33431SDiana Picus       return false;
95664a33431SDiana Picus     }
95764a33431SDiana Picus 
95864a33431SDiana Picus     I.setDesc(TII.get(COPY));
95964a33431SDiana Picus     return selectCopy(I, TII, MRI, TRI, RBI);
96064a33431SDiana Picus   }
96137ae9f68SDiana Picus   case G_CONSTANT: {
96237ae9f68SDiana Picus     if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
96337ae9f68SDiana Picus       // Non-pointer constants should be handled by TableGen.
964d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
96537ae9f68SDiana Picus       return false;
96637ae9f68SDiana Picus     }
96737ae9f68SDiana Picus 
96837ae9f68SDiana Picus     auto &Val = I.getOperand(1);
96937ae9f68SDiana Picus     if (Val.isCImm()) {
97037ae9f68SDiana Picus       if (!Val.getCImm()->isZero()) {
971d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
97237ae9f68SDiana Picus         return false;
97337ae9f68SDiana Picus       }
97437ae9f68SDiana Picus       Val.ChangeToImmediate(0);
97537ae9f68SDiana Picus     } else {
97637ae9f68SDiana Picus       assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
97737ae9f68SDiana Picus       if (Val.getImm() != 0) {
978d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
97937ae9f68SDiana Picus         return false;
98037ae9f68SDiana Picus       }
98137ae9f68SDiana Picus     }
98237ae9f68SDiana Picus 
9834a7f8d8dSDiana Picus     assert(!STI.isThumb() && "Unsupported subtarget");
98437ae9f68SDiana Picus     I.setDesc(TII.get(ARM::MOVi));
98537ae9f68SDiana Picus     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
98637ae9f68SDiana Picus     break;
98737ae9f68SDiana Picus   }
9883533ad68SDiana Picus   case G_FCONSTANT: {
9893533ad68SDiana Picus     // Load from constant pool
9903533ad68SDiana Picus     unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
991998118c3SGuillaume Chatelet     Align Alignment(Size);
9923533ad68SDiana Picus 
9933533ad68SDiana Picus     assert((Size == 4 || Size == 8) && "Unsupported FP constant type");
9943533ad68SDiana Picus     auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;
9953533ad68SDiana Picus 
9963533ad68SDiana Picus     auto ConstPool = MF.getConstantPool();
9978c72b027SCraig Topper     auto CPIndex =
9988c72b027SCraig Topper         ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);
9993533ad68SDiana Picus     MIB->setDesc(TII.get(LoadOpcode));
100037b37838SShengchen Kan     MIB->removeOperand(1);
10013533ad68SDiana Picus     MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
10023533ad68SDiana Picus         .addMemOperand(
10033533ad68SDiana Picus             MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
10043533ad68SDiana Picus                                     MachineMemOperand::MOLoad, Size, Alignment))
10053533ad68SDiana Picus         .addImm(0)
10063533ad68SDiana Picus         .add(predOps(ARMCC::AL));
10073533ad68SDiana Picus     break;
10083533ad68SDiana Picus   }
100928a6d0e6SDiana Picus   case G_INTTOPTR:
101028a6d0e6SDiana Picus   case G_PTRTOINT: {
101128a6d0e6SDiana Picus     auto SrcReg = I.getOperand(1).getReg();
101228a6d0e6SDiana Picus     auto DstReg = I.getOperand(0).getReg();
101328a6d0e6SDiana Picus 
101428a6d0e6SDiana Picus     const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
101528a6d0e6SDiana Picus     const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
101628a6d0e6SDiana Picus 
101728a6d0e6SDiana Picus     if (SrcRegBank.getID() != DstRegBank.getID()) {
1018d34e60caSNicola Zaghen       LLVM_DEBUG(
1019d34e60caSNicola Zaghen           dbgs()
102028a6d0e6SDiana Picus           << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
102128a6d0e6SDiana Picus       return false;
102228a6d0e6SDiana Picus     }
102328a6d0e6SDiana Picus 
102428a6d0e6SDiana Picus     if (SrcRegBank.getID() != ARM::GPRRegBankID) {
1025d34e60caSNicola Zaghen       LLVM_DEBUG(
1026d34e60caSNicola Zaghen           dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
102728a6d0e6SDiana Picus       return false;
102828a6d0e6SDiana Picus     }
102928a6d0e6SDiana Picus 
103028a6d0e6SDiana Picus     I.setDesc(TII.get(COPY));
103128a6d0e6SDiana Picus     return selectCopy(I, TII, MRI, TRI, RBI);
103228a6d0e6SDiana Picus   }
10337145d22fSDiana Picus   case G_SELECT:
1034995746daSDiana Picus     return selectSelect(MIB, MRI);
1035995746daSDiana Picus   case G_ICMP: {
103675a04e2aSDiana Picus     CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
103775a04e2aSDiana Picus                         Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
1038995746daSDiana Picus     return selectCmp(Helper, MIB, MRI);
1039995746daSDiana Picus   }
104021014df5SDiana Picus   case G_FCMP: {
1041760df47bSSimon Tatham     assert(STI.hasVFP2Base() && "Can't select fcmp without VFP");
104221014df5SDiana Picus 
10430c476111SDaniel Sanders     Register OpReg = I.getOperand(2).getReg();
104421014df5SDiana Picus     unsigned Size = MRI.getType(OpReg).getSizeInBits();
1045995746daSDiana Picus 
1046760df47bSSimon Tatham     if (Size == 64 && !STI.hasFP64()) {
1047d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");
104821014df5SDiana Picus       return false;
104921014df5SDiana Picus     }
1050995746daSDiana Picus     if (Size != 32 && Size != 64) {
1051d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
105221014df5SDiana Picus       return false;
105321014df5SDiana Picus     }
1054995746daSDiana Picus 
1055995746daSDiana Picus     CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
105675a04e2aSDiana Picus                         Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
1057995746daSDiana Picus     return selectCmp(Helper, MIB, MRI);
1058995746daSDiana Picus   }
1059e393bc72SDiana Picus   case G_LSHR:
1060e393bc72SDiana Picus     return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
1061e393bc72SDiana Picus   case G_ASHR:
1062e393bc72SDiana Picus     return selectShift(ARM_AM::ShiftOpc::asr, MIB);
1063e393bc72SDiana Picus   case G_SHL: {
1064e393bc72SDiana Picus     return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
1065e393bc72SDiana Picus   }
1066e74c5b96SDaniel Sanders   case G_PTR_ADD:
1067c0f964ebSDiana Picus     I.setDesc(TII.get(Opcodes.ADDrr));
10688a73f556SDiana Picus     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
1069519807f7SDiana Picus     break;
1070519807f7SDiana Picus   case G_FRAME_INDEX:
1071519807f7SDiana Picus     // Add 0 to the given frame index and hope it will eventually be folded into
1072519807f7SDiana Picus     // the user(s).
1073dcaa939aSDiana Picus     I.setDesc(TII.get(Opcodes.ADDri));
10748a73f556SDiana Picus     MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
1075519807f7SDiana Picus     break;
1076930e6ec8SDiana Picus   case G_GLOBAL_VALUE:
1077930e6ec8SDiana Picus     return selectGlobal(MIB, MRI);
10783b99c64bSDiana Picus   case G_STORE:
1079278c722eSDiana Picus   case G_LOAD: {
10803c1c4c0eSDaniel Sanders     const auto &MemOp = **I.memoperands_begin();
10815c38ca35SPhilip Reames     if (MemOp.isAtomic()) {
1082d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
10833c1c4c0eSDaniel Sanders       return false;
10843c1c4c0eSDaniel Sanders     }
10853c1c4c0eSDaniel Sanders 
10860c476111SDaniel Sanders     Register Reg = I.getOperand(0).getReg();
10871540b06eSDiana Picus     unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
10881540b06eSDiana Picus 
10891540b06eSDiana Picus     LLT ValTy = MRI.getType(Reg);
1090278c722eSDiana Picus     const auto ValSize = ValTy.getSizeInBits();
1091278c722eSDiana Picus 
1092760df47bSSimon Tatham     assert((ValSize != 64 || STI.hasVFP2Base()) &&
10933b99c64bSDiana Picus            "Don't know how to load/store 64-bit value without VFP");
10941540b06eSDiana Picus 
1095813af0d2SDiana Picus     const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
10963b99c64bSDiana Picus     if (NewOpc == G_LOAD || NewOpc == G_STORE)
1097e836878bSDiana Picus       return false;
1098e836878bSDiana Picus 
1099278c722eSDiana Picus     I.setDesc(TII.get(NewOpc));
1100278c722eSDiana Picus 
11013b99c64bSDiana Picus     if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
1102278c722eSDiana Picus       // LDRH has a funny addressing mode (there's already a FIXME for it).
1103278c722eSDiana Picus       MIB.addReg(0);
11044f8c3e18SDiana Picus     MIB.addImm(0).add(predOps(ARMCC::AL));
1105519807f7SDiana Picus     break;
1106278c722eSDiana Picus   }
11070b4190a9SDiana Picus   case G_MERGE_VALUES: {
11080b4190a9SDiana Picus     if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
1109b1701e0bSDiana Picus       return false;
1110b1701e0bSDiana Picus     break;
1111b1701e0bSDiana Picus   }
11120b4190a9SDiana Picus   case G_UNMERGE_VALUES: {
11130b4190a9SDiana Picus     if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
1114b1701e0bSDiana Picus       return false;
1115b1701e0bSDiana Picus     break;
1116b1701e0bSDiana Picus   }
111787a70679SDiana Picus   case G_BRCOND: {
111887a70679SDiana Picus     if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
1119d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
112087a70679SDiana Picus       return false;
112187a70679SDiana Picus     }
112287a70679SDiana Picus 
112387a70679SDiana Picus     // Set the flags.
1124a00425ffSDiana Picus     auto Test =
1125a00425ffSDiana Picus         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))
112687a70679SDiana Picus             .addReg(I.getOperand(0).getReg())
112787a70679SDiana Picus             .addImm(1)
112887a70679SDiana Picus             .add(predOps(ARMCC::AL));
112987a70679SDiana Picus     if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
113087a70679SDiana Picus       return false;
113187a70679SDiana Picus 
113287a70679SDiana Picus     // Branch conditionally.
1133a00425ffSDiana Picus     auto Branch =
1134a00425ffSDiana Picus         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))
113587a70679SDiana Picus             .add(I.getOperand(1))
1136863b5b05SDiana Picus             .add(predOps(ARMCC::NE, ARM::CPSR));
113787a70679SDiana Picus     if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
113887a70679SDiana Picus       return false;
113987a70679SDiana Picus     I.eraseFromParent();
114087a70679SDiana Picus     return true;
114187a70679SDiana Picus   }
1142865f7fecSDiana Picus   case G_PHI: {
1143865f7fecSDiana Picus     I.setDesc(TII.get(PHI));
1144865f7fecSDiana Picus 
11450c476111SDaniel Sanders     Register DstReg = I.getOperand(0).getReg();
1146865f7fecSDiana Picus     const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
1147865f7fecSDiana Picus     if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1148865f7fecSDiana Picus       break;
1149865f7fecSDiana Picus     }
1150865f7fecSDiana Picus 
1151865f7fecSDiana Picus     return true;
1152865f7fecSDiana Picus   }
1153519807f7SDiana Picus   default:
1154519807f7SDiana Picus     return false;
1155812caee6SDiana Picus   }
1156812caee6SDiana Picus 
1157519807f7SDiana Picus   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
115822274934SDiana Picus }
1159