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