blob: f225ff824195b80f405d419d36e9a5886b926961 [file] [log] [blame]
Diana Picus22274932016-11-11 08:27:37 +00001//===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// This file implements the targeting of the InstructionSelector class for ARM.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
Diana Picus22274932016-11-11 08:27:37 +000014#include "ARMRegisterBankInfo.h"
15#include "ARMSubtarget.h"
16#include "ARMTargetMachine.h"
Diana Picus674888d2017-04-28 09:10:38 +000017#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
David Blaikie62651302017-10-26 23:39:54 +000018#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
Diana Picus930e6ec2017-08-03 09:14:59 +000019#include "llvm/CodeGen/MachineConstantPool.h"
Diana Picus812caee2016-12-16 12:54:46 +000020#include "llvm/CodeGen/MachineRegisterInfo.h"
Diana Picus22274932016-11-11 08:27:37 +000021#include "llvm/Support/Debug.h"
22
23#define DEBUG_TYPE "arm-isel"
24
25using namespace llvm;
26
Diana Picus674888d2017-04-28 09:10:38 +000027namespace {
Diana Picus8abcbbb2017-05-02 09:40:49 +000028
29#define GET_GLOBALISEL_PREDICATE_BITSET
30#include "ARMGenGlobalISel.inc"
31#undef GET_GLOBALISEL_PREDICATE_BITSET
32
Diana Picus674888d2017-04-28 09:10:38 +000033class ARMInstructionSelector : public InstructionSelector {
34public:
Diana Picus8abcbbb2017-05-02 09:40:49 +000035 ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000036 const ARMRegisterBankInfo &RBI);
37
Daniel Sandersf76f3152017-11-16 00:46:35 +000038 bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
David Blaikie62651302017-10-26 23:39:54 +000039 static const char *getName() { return DEBUG_TYPE; }
Diana Picus674888d2017-04-28 09:10:38 +000040
41private:
Daniel Sandersf76f3152017-11-16 00:46:35 +000042 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
Diana Picus8abcbbb2017-05-02 09:40:49 +000043
Diana Picus995746d2017-07-12 10:31:16 +000044 struct CmpConstants;
45 struct InsertInfo;
Diana Picus5b916532017-07-07 08:39:04 +000046
Diana Picus995746d2017-07-12 10:31:16 +000047 bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
48 MachineRegisterInfo &MRI) const;
Diana Picus621894a2017-06-19 09:40:51 +000049
Diana Picus995746d2017-07-12 10:31:16 +000050 // Helper for inserting a comparison sequence that sets \p ResReg to either 1
51 // if \p LHSReg and \p RHSReg are in the relationship defined by \p Cond, or
52 // \p PrevRes otherwise. In essence, it computes PrevRes OR (LHS Cond RHS).
53 bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
54 ARMCC::CondCodes Cond, unsigned LHSReg, unsigned RHSReg,
55 unsigned PrevRes) const;
56
57 // Set \p DestReg to \p Constant.
58 void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
59
Diana Picus930e6ec2017-08-03 09:14:59 +000060 bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
Diana Picus995746d2017-07-12 10:31:16 +000061 bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
Diana Picuse393bc72017-10-06 15:39:16 +000062 bool selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const;
Diana Picus995746d2017-07-12 10:31:16 +000063
64 // Check if the types match and both operands have the expected size and
65 // register bank.
66 bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
67 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
68
69 // Check if the register has the expected size and register bank.
70 bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
71 unsigned ExpectedRegBankID) const;
Diana Picus7145d222017-06-27 09:19:51 +000072
Diana Picus674888d2017-04-28 09:10:38 +000073 const ARMBaseInstrInfo &TII;
74 const ARMBaseRegisterInfo &TRI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000075 const ARMBaseTargetMachine &TM;
Diana Picus674888d2017-04-28 09:10:38 +000076 const ARMRegisterBankInfo &RBI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000077 const ARMSubtarget &STI;
78
79#define GET_GLOBALISEL_PREDICATES_DECL
80#include "ARMGenGlobalISel.inc"
81#undef GET_GLOBALISEL_PREDICATES_DECL
82
83// We declare the temporaries used by selectImpl() in the class to minimize the
84// cost of constructing placeholder values.
85#define GET_GLOBALISEL_TEMPORARIES_DECL
86#include "ARMGenGlobalISel.inc"
87#undef GET_GLOBALISEL_TEMPORARIES_DECL
Diana Picus674888d2017-04-28 09:10:38 +000088};
89} // end anonymous namespace
90
91namespace llvm {
92InstructionSelector *
Diana Picus8abcbbb2017-05-02 09:40:49 +000093createARMInstructionSelector(const ARMBaseTargetMachine &TM,
94 const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000095 const ARMRegisterBankInfo &RBI) {
Diana Picus8abcbbb2017-05-02 09:40:49 +000096 return new ARMInstructionSelector(TM, STI, RBI);
Diana Picus674888d2017-04-28 09:10:38 +000097}
98}
99
Daniel Sanders8e82af22017-07-27 11:03:45 +0000100const unsigned zero_reg = 0;
Diana Picus8abcbbb2017-05-02 09:40:49 +0000101
102#define GET_GLOBALISEL_IMPL
103#include "ARMGenGlobalISel.inc"
104#undef GET_GLOBALISEL_IMPL
105
106ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
107 const ARMSubtarget &STI,
Diana Picus22274932016-11-11 08:27:37 +0000108 const ARMRegisterBankInfo &RBI)
Diana Picus895c6aa2016-11-15 16:42:10 +0000109 : InstructionSelector(), TII(*STI.getInstrInfo()),
Diana Picus8abcbbb2017-05-02 09:40:49 +0000110 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
111#define GET_GLOBALISEL_PREDICATES_INIT
112#include "ARMGenGlobalISel.inc"
113#undef GET_GLOBALISEL_PREDICATES_INIT
114#define GET_GLOBALISEL_TEMPORARIES_INIT
115#include "ARMGenGlobalISel.inc"
116#undef GET_GLOBALISEL_TEMPORARIES_INIT
117{
118}
Diana Picus22274932016-11-11 08:27:37 +0000119
Diana Picus865f7fe2018-01-04 13:09:25 +0000120static const TargetRegisterClass *guessRegClass(unsigned Reg,
121 MachineRegisterInfo &MRI,
122 const TargetRegisterInfo &TRI,
123 const RegisterBankInfo &RBI) {
124 const RegisterBank *RegBank = RBI.getRegBank(Reg, MRI, TRI);
125 assert(RegBank && "Can't get reg bank for virtual register");
126
127 const unsigned Size = MRI.getType(Reg).getSizeInBits();
128 assert((RegBank->getID() == ARM::GPRRegBankID ||
129 RegBank->getID() == ARM::FPRRegBankID) &&
130 "Unsupported reg bank");
131
132 if (RegBank->getID() == ARM::FPRRegBankID) {
133 if (Size == 32)
134 return &ARM::SPRRegClass;
135 else if (Size == 64)
136 return &ARM::DPRRegClass;
137 else
138 llvm_unreachable("Unsupported destination size");
139 }
140
141 return &ARM::GPRRegClass;
142}
143
Diana Picus812caee2016-12-16 12:54:46 +0000144static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
145 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
146 const RegisterBankInfo &RBI) {
147 unsigned DstReg = I.getOperand(0).getReg();
148 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
149 return true;
150
Diana Picus865f7fe2018-01-04 13:09:25 +0000151 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
Diana Picus4fa83c02017-02-08 13:23:04 +0000152
Diana Picus812caee2016-12-16 12:54:46 +0000153 // No need to constrain SrcReg. It will get constrained when
154 // we hit another of its uses or its defs.
155 // Copies do not have constraints.
156 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
157 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
158 << " operand\n");
159 return false;
160 }
161 return true;
162}
163
Diana Picus0b4190a2017-06-07 12:35:05 +0000164static bool selectMergeValues(MachineInstrBuilder &MIB,
165 const ARMBaseInstrInfo &TII,
166 MachineRegisterInfo &MRI,
167 const TargetRegisterInfo &TRI,
168 const RegisterBankInfo &RBI) {
169 assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000170
Diana Picus0b4190a2017-06-07 12:35:05 +0000171 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
Diana Picusb1701e02017-02-16 12:19:57 +0000172 // into one DPR.
173 unsigned VReg0 = MIB->getOperand(0).getReg();
174 (void)VReg0;
175 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
176 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000177 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000178 unsigned VReg1 = MIB->getOperand(1).getReg();
179 (void)VReg1;
180 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
181 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000182 "Unsupported operand for G_MERGE_VALUES");
183 unsigned VReg2 = MIB->getOperand(2).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000184 (void)VReg2;
185 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
186 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000187 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000188
189 MIB->setDesc(TII.get(ARM::VMOVDRR));
190 MIB.add(predOps(ARMCC::AL));
191
192 return true;
193}
194
Diana Picus0b4190a2017-06-07 12:35:05 +0000195static bool selectUnmergeValues(MachineInstrBuilder &MIB,
196 const ARMBaseInstrInfo &TII,
197 MachineRegisterInfo &MRI,
198 const TargetRegisterInfo &TRI,
199 const RegisterBankInfo &RBI) {
200 assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000201
Diana Picus0b4190a2017-06-07 12:35:05 +0000202 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
203 // GPRs.
Diana Picusb1701e02017-02-16 12:19:57 +0000204 unsigned VReg0 = MIB->getOperand(0).getReg();
205 (void)VReg0;
206 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
207 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000208 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000209 unsigned VReg1 = MIB->getOperand(1).getReg();
210 (void)VReg1;
Diana Picus0b4190a2017-06-07 12:35:05 +0000211 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
212 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
213 "Unsupported operand for G_UNMERGE_VALUES");
214 unsigned VReg2 = MIB->getOperand(2).getReg();
215 (void)VReg2;
216 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
217 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
218 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000219
Diana Picus0b4190a2017-06-07 12:35:05 +0000220 MIB->setDesc(TII.get(ARM::VMOVRRD));
Diana Picusb1701e02017-02-16 12:19:57 +0000221 MIB.add(predOps(ARMCC::AL));
222
223 return true;
224}
225
Diana Picus8b6c6be2017-01-25 08:10:40 +0000226/// Select the opcode for simple extensions (that translate to a single SXT/UXT
227/// instruction). Extension operations more complicated than that should not
Diana Picuse8368782017-02-17 13:44:19 +0000228/// invoke this. Returns the original opcode if it doesn't know how to select a
229/// better one.
Diana Picus8b6c6be2017-01-25 08:10:40 +0000230static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) {
231 using namespace TargetOpcode;
232
Diana Picuse8368782017-02-17 13:44:19 +0000233 if (Size != 8 && Size != 16)
234 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000235
236 if (Opc == G_SEXT)
237 return Size == 8 ? ARM::SXTB : ARM::SXTH;
238
239 if (Opc == G_ZEXT)
240 return Size == 8 ? ARM::UXTB : ARM::UXTH;
241
Diana Picuse8368782017-02-17 13:44:19 +0000242 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000243}
244
Diana Picus3b99c642017-02-24 14:01:27 +0000245/// Select the opcode for simple loads and stores. For types smaller than 32
246/// bits, the value will be zero extended. Returns the original opcode if it
247/// doesn't know how to select a better one.
248static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
249 unsigned Size) {
250 bool isStore = Opc == TargetOpcode::G_STORE;
251
Diana Picus1540b062017-02-16 14:10:50 +0000252 if (RegBank == ARM::GPRRegBankID) {
253 switch (Size) {
254 case 1:
255 case 8:
Diana Picus3b99c642017-02-24 14:01:27 +0000256 return isStore ? ARM::STRBi12 : ARM::LDRBi12;
Diana Picus1540b062017-02-16 14:10:50 +0000257 case 16:
Diana Picus3b99c642017-02-24 14:01:27 +0000258 return isStore ? ARM::STRH : ARM::LDRH;
Diana Picus1540b062017-02-16 14:10:50 +0000259 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000260 return isStore ? ARM::STRi12 : ARM::LDRi12;
Diana Picuse8368782017-02-17 13:44:19 +0000261 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000262 return Opc;
Diana Picus1540b062017-02-16 14:10:50 +0000263 }
Diana Picus1540b062017-02-16 14:10:50 +0000264 }
265
Diana Picuse8368782017-02-17 13:44:19 +0000266 if (RegBank == ARM::FPRRegBankID) {
267 switch (Size) {
268 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000269 return isStore ? ARM::VSTRS : ARM::VLDRS;
Diana Picuse8368782017-02-17 13:44:19 +0000270 case 64:
Diana Picus3b99c642017-02-24 14:01:27 +0000271 return isStore ? ARM::VSTRD : ARM::VLDRD;
Diana Picuse8368782017-02-17 13:44:19 +0000272 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000273 return Opc;
Diana Picuse8368782017-02-17 13:44:19 +0000274 }
Diana Picus278c7222017-01-26 09:20:47 +0000275 }
276
Diana Picus3b99c642017-02-24 14:01:27 +0000277 return Opc;
Diana Picus278c7222017-01-26 09:20:47 +0000278}
279
Diana Picus5b916532017-07-07 08:39:04 +0000280// When lowering comparisons, we sometimes need to perform two compares instead
281// of just one. Get the condition codes for both comparisons. If only one is
282// needed, the second member of the pair is ARMCC::AL.
283static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
284getComparePreds(CmpInst::Predicate Pred) {
285 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
Diana Picus621894a2017-06-19 09:40:51 +0000286 switch (Pred) {
Diana Picus621894a2017-06-19 09:40:51 +0000287 case CmpInst::FCMP_ONE:
Diana Picus5b916532017-07-07 08:39:04 +0000288 Preds = {ARMCC::GT, ARMCC::MI};
289 break;
Diana Picus621894a2017-06-19 09:40:51 +0000290 case CmpInst::FCMP_UEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000291 Preds = {ARMCC::EQ, ARMCC::VS};
292 break;
Diana Picus621894a2017-06-19 09:40:51 +0000293 case CmpInst::ICMP_EQ:
294 case CmpInst::FCMP_OEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000295 Preds.first = ARMCC::EQ;
296 break;
Diana Picus621894a2017-06-19 09:40:51 +0000297 case CmpInst::ICMP_SGT:
298 case CmpInst::FCMP_OGT:
Diana Picus5b916532017-07-07 08:39:04 +0000299 Preds.first = ARMCC::GT;
300 break;
Diana Picus621894a2017-06-19 09:40:51 +0000301 case CmpInst::ICMP_SGE:
302 case CmpInst::FCMP_OGE:
Diana Picus5b916532017-07-07 08:39:04 +0000303 Preds.first = ARMCC::GE;
304 break;
Diana Picus621894a2017-06-19 09:40:51 +0000305 case CmpInst::ICMP_UGT:
306 case CmpInst::FCMP_UGT:
Diana Picus5b916532017-07-07 08:39:04 +0000307 Preds.first = ARMCC::HI;
308 break;
Diana Picus621894a2017-06-19 09:40:51 +0000309 case CmpInst::FCMP_OLT:
Diana Picus5b916532017-07-07 08:39:04 +0000310 Preds.first = ARMCC::MI;
311 break;
Diana Picus621894a2017-06-19 09:40:51 +0000312 case CmpInst::ICMP_ULE:
313 case CmpInst::FCMP_OLE:
Diana Picus5b916532017-07-07 08:39:04 +0000314 Preds.first = ARMCC::LS;
315 break;
Diana Picus621894a2017-06-19 09:40:51 +0000316 case CmpInst::FCMP_ORD:
Diana Picus5b916532017-07-07 08:39:04 +0000317 Preds.first = ARMCC::VC;
318 break;
Diana Picus621894a2017-06-19 09:40:51 +0000319 case CmpInst::FCMP_UNO:
Diana Picus5b916532017-07-07 08:39:04 +0000320 Preds.first = ARMCC::VS;
321 break;
Diana Picus621894a2017-06-19 09:40:51 +0000322 case CmpInst::FCMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000323 Preds.first = ARMCC::PL;
324 break;
Diana Picus621894a2017-06-19 09:40:51 +0000325 case CmpInst::ICMP_SLT:
326 case CmpInst::FCMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000327 Preds.first = ARMCC::LT;
328 break;
Diana Picus621894a2017-06-19 09:40:51 +0000329 case CmpInst::ICMP_SLE:
330 case CmpInst::FCMP_ULE:
Diana Picus5b916532017-07-07 08:39:04 +0000331 Preds.first = ARMCC::LE;
332 break;
Diana Picus621894a2017-06-19 09:40:51 +0000333 case CmpInst::FCMP_UNE:
334 case CmpInst::ICMP_NE:
Diana Picus5b916532017-07-07 08:39:04 +0000335 Preds.first = ARMCC::NE;
336 break;
Diana Picus621894a2017-06-19 09:40:51 +0000337 case CmpInst::ICMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000338 Preds.first = ARMCC::HS;
339 break;
Diana Picus621894a2017-06-19 09:40:51 +0000340 case CmpInst::ICMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000341 Preds.first = ARMCC::LO;
342 break;
343 default:
344 break;
Diana Picus621894a2017-06-19 09:40:51 +0000345 }
Diana Picus5b916532017-07-07 08:39:04 +0000346 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
347 return Preds;
Diana Picus621894a2017-06-19 09:40:51 +0000348}
349
Diana Picus995746d2017-07-12 10:31:16 +0000350struct ARMInstructionSelector::CmpConstants {
351 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned OpRegBank,
352 unsigned OpSize)
353 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
354 OperandRegBankID(OpRegBank), OperandSize(OpSize) {}
Diana Picus621894a2017-06-19 09:40:51 +0000355
Diana Picus5b916532017-07-07 08:39:04 +0000356 // The opcode used for performing the comparison.
Diana Picus995746d2017-07-12 10:31:16 +0000357 const unsigned ComparisonOpcode;
Diana Picus621894a2017-06-19 09:40:51 +0000358
Diana Picus5b916532017-07-07 08:39:04 +0000359 // The opcode used for reading the flags set by the comparison. May be
360 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
Diana Picus995746d2017-07-12 10:31:16 +0000361 const unsigned ReadFlagsOpcode;
Diana Picus5b916532017-07-07 08:39:04 +0000362
363 // The assumed register bank ID for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000364 const unsigned OperandRegBankID;
Diana Picus5b916532017-07-07 08:39:04 +0000365
Diana Picus21014df2017-07-12 09:01:54 +0000366 // The assumed size in bits for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000367 const unsigned OperandSize;
Diana Picus5b916532017-07-07 08:39:04 +0000368};
369
Diana Picus995746d2017-07-12 10:31:16 +0000370struct ARMInstructionSelector::InsertInfo {
371 InsertInfo(MachineInstrBuilder &MIB)
372 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
373 DbgLoc(MIB->getDebugLoc()) {}
Diana Picus5b916532017-07-07 08:39:04 +0000374
Diana Picus995746d2017-07-12 10:31:16 +0000375 MachineBasicBlock &MBB;
376 const MachineBasicBlock::instr_iterator InsertBefore;
377 const DebugLoc &DbgLoc;
378};
Diana Picus5b916532017-07-07 08:39:04 +0000379
Diana Picus995746d2017-07-12 10:31:16 +0000380void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
381 unsigned Constant) const {
382 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVi))
383 .addDef(DestReg)
384 .addImm(Constant)
385 .add(predOps(ARMCC::AL))
386 .add(condCodeOp());
387}
Diana Picus21014df2017-07-12 09:01:54 +0000388
Diana Picus995746d2017-07-12 10:31:16 +0000389bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
390 unsigned LHSReg, unsigned RHSReg,
391 unsigned ExpectedSize,
392 unsigned ExpectedRegBankID) const {
393 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
394 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
395 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
396}
Diana Picus5b916532017-07-07 08:39:04 +0000397
Diana Picus995746d2017-07-12 10:31:16 +0000398bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
399 unsigned ExpectedSize,
400 unsigned ExpectedRegBankID) const {
401 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
402 DEBUG(dbgs() << "Unexpected size for register");
403 return false;
404 }
405
406 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
407 DEBUG(dbgs() << "Unexpected register bank for register");
408 return false;
409 }
410
411 return true;
412}
413
414bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
415 MachineInstrBuilder &MIB,
416 MachineRegisterInfo &MRI) const {
417 const InsertInfo I(MIB);
Diana Picus5b916532017-07-07 08:39:04 +0000418
Diana Picus621894a2017-06-19 09:40:51 +0000419 auto ResReg = MIB->getOperand(0).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000420 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
Diana Picus5b916532017-07-07 08:39:04 +0000421 return false;
422
Diana Picus621894a2017-06-19 09:40:51 +0000423 auto Cond =
424 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
Diana Picus5b916532017-07-07 08:39:04 +0000425 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
Diana Picus995746d2017-07-12 10:31:16 +0000426 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
Diana Picus5b916532017-07-07 08:39:04 +0000427 MIB->eraseFromParent();
428 return true;
429 }
430
431 auto LHSReg = MIB->getOperand(2).getReg();
432 auto RHSReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000433 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
434 Helper.OperandRegBankID))
Diana Picus621894a2017-06-19 09:40:51 +0000435 return false;
436
Diana Picus5b916532017-07-07 08:39:04 +0000437 auto ARMConds = getComparePreds(Cond);
Diana Picus995746d2017-07-12 10:31:16 +0000438 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
439 putConstant(I, ZeroReg, 0);
Diana Picus5b916532017-07-07 08:39:04 +0000440
441 if (ARMConds.second == ARMCC::AL) {
442 // Simple case, we only need one comparison and we're done.
Diana Picus995746d2017-07-12 10:31:16 +0000443 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
444 ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000445 return false;
446 } else {
447 // Not so simple, we need two successive comparisons.
448 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picus995746d2017-07-12 10:31:16 +0000449 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
450 RHSReg, ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000451 return false;
Diana Picus995746d2017-07-12 10:31:16 +0000452 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
453 IntermediateRes))
Diana Picus5b916532017-07-07 08:39:04 +0000454 return false;
455 }
Diana Picus621894a2017-06-19 09:40:51 +0000456
457 MIB->eraseFromParent();
458 return true;
459}
460
Diana Picus995746d2017-07-12 10:31:16 +0000461bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
462 unsigned ResReg,
463 ARMCC::CondCodes Cond,
464 unsigned LHSReg, unsigned RHSReg,
465 unsigned PrevRes) const {
466 // Perform the comparison.
467 auto CmpI =
468 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
469 .addUse(LHSReg)
470 .addUse(RHSReg)
471 .add(predOps(ARMCC::AL));
472 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
473 return false;
474
475 // Read the comparison flags (if necessary).
476 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
477 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
478 TII.get(Helper.ReadFlagsOpcode))
479 .add(predOps(ARMCC::AL));
480 if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
481 return false;
482 }
483
484 // Select either 1 or the previous result based on the value of the flags.
485 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVCCi))
486 .addDef(ResReg)
487 .addUse(PrevRes)
488 .addImm(1)
489 .add(predOps(Cond, ARM::CPSR));
490 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
491 return false;
492
493 return true;
494}
495
Diana Picus930e6ec2017-08-03 09:14:59 +0000496bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
497 MachineRegisterInfo &MRI) const {
Diana Picusabb08862017-09-05 07:57:41 +0000498 if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
499 DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
Diana Picus930e6ec2017-08-03 09:14:59 +0000500 return false;
501 }
Diana Picus930e6ec2017-08-03 09:14:59 +0000502
503 auto GV = MIB->getOperand(1).getGlobal();
504 if (GV->isThreadLocal()) {
505 DEBUG(dbgs() << "TLS variables not supported yet\n");
506 return false;
507 }
508
509 auto &MBB = *MIB->getParent();
510 auto &MF = *MBB.getParent();
511
Diana Picusac154732017-09-05 08:22:47 +0000512 bool UseMovt = STI.useMovt(MF);
Diana Picus930e6ec2017-08-03 09:14:59 +0000513
Diana Picusabb08862017-09-05 07:57:41 +0000514 unsigned Size = TM.getPointerSize();
Diana Picusc9f29c62017-08-29 09:47:55 +0000515 unsigned Alignment = 4;
Diana Picusabb08862017-09-05 07:57:41 +0000516
517 auto addOpsForConstantPoolLoad = [&MF, Alignment,
518 Size](MachineInstrBuilder &MIB,
519 const GlobalValue *GV, bool IsSBREL) {
520 assert(MIB->getOpcode() == ARM::LDRi12 && "Unsupported instruction");
521 auto ConstPool = MF.getConstantPool();
522 auto CPIndex =
523 // For SB relative entries we need a target-specific constant pool.
524 // Otherwise, just use a regular constant pool entry.
525 IsSBREL
526 ? ConstPool->getConstantPoolIndex(
527 ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
528 : ConstPool->getConstantPoolIndex(GV, Alignment);
529 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
530 .addMemOperand(
531 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
532 MachineMemOperand::MOLoad, Size, Alignment))
533 .addImm(0)
534 .add(predOps(ARMCC::AL));
535 };
536
Diana Picusc9f29c62017-08-29 09:47:55 +0000537 if (TM.isPositionIndependent()) {
Diana Picusac154732017-09-05 08:22:47 +0000538 bool Indirect = STI.isGVIndirectSymbol(GV);
Diana Picusc9f29c62017-08-29 09:47:55 +0000539 // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
540 // support it yet. See PR28229.
541 unsigned Opc =
Diana Picusac154732017-09-05 08:22:47 +0000542 UseMovt && !STI.isTargetELF()
Diana Picusc9f29c62017-08-29 09:47:55 +0000543 ? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel)
544 : (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel);
545 MIB->setDesc(TII.get(Opc));
546
Evgeniy Stepanov76d5ac42017-11-13 20:45:38 +0000547 int TargetFlags = ARMII::MO_NO_FLAG;
Diana Picusac154732017-09-05 08:22:47 +0000548 if (STI.isTargetDarwin())
Evgeniy Stepanov76d5ac42017-11-13 20:45:38 +0000549 TargetFlags |= ARMII::MO_NONLAZY;
550 if (STI.isGVInGOT(GV))
551 TargetFlags |= ARMII::MO_GOT;
552 MIB->getOperand(1).setTargetFlags(TargetFlags);
Diana Picusc9f29c62017-08-29 09:47:55 +0000553
554 if (Indirect)
555 MIB.addMemOperand(MF.getMachineMemOperand(
556 MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
557 TM.getPointerSize(), Alignment));
558
Diana Picusac154732017-09-05 08:22:47 +0000559 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
Diana Picusc9f29c62017-08-29 09:47:55 +0000560 }
561
Diana Picusf95979112017-09-01 11:13:39 +0000562 bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
563 if (STI.isROPI() && isReadOnly) {
564 unsigned Opc = UseMovt ? ARM::MOV_ga_pcrel : ARM::LDRLIT_ga_pcrel;
565 MIB->setDesc(TII.get(Opc));
566 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
567 }
Diana Picusabb08862017-09-05 07:57:41 +0000568 if (STI.isRWPI() && !isReadOnly) {
569 auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
570 MachineInstrBuilder OffsetMIB;
571 if (UseMovt) {
572 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
573 TII.get(ARM::MOVi32imm), Offset);
574 OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
575 } else {
576 // Load the offset from the constant pool.
577 OffsetMIB =
578 BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::LDRi12), Offset);
579 addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
580 }
581 if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
582 return false;
583
584 // Add the offset to the SB register.
585 MIB->setDesc(TII.get(ARM::ADDrr));
586 MIB->RemoveOperand(1);
587 MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
588 .addReg(Offset)
589 .add(predOps(ARMCC::AL))
590 .add(condCodeOp());
591
592 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
593 }
Diana Picusf95979112017-09-01 11:13:39 +0000594
Diana Picusac154732017-09-05 08:22:47 +0000595 if (STI.isTargetELF()) {
Diana Picus930e6ec2017-08-03 09:14:59 +0000596 if (UseMovt) {
597 MIB->setDesc(TII.get(ARM::MOVi32imm));
598 } else {
599 // Load the global's address from the constant pool.
600 MIB->setDesc(TII.get(ARM::LDRi12));
601 MIB->RemoveOperand(1);
Diana Picusabb08862017-09-05 07:57:41 +0000602 addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
Diana Picus930e6ec2017-08-03 09:14:59 +0000603 }
Diana Picusac154732017-09-05 08:22:47 +0000604 } else if (STI.isTargetMachO()) {
Diana Picus930e6ec2017-08-03 09:14:59 +0000605 if (UseMovt)
606 MIB->setDesc(TII.get(ARM::MOVi32imm));
607 else
608 MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs));
609 } else {
610 DEBUG(dbgs() << "Object format not supported yet\n");
611 return false;
612 }
613
614 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
615}
616
Diana Picus7145d222017-06-27 09:19:51 +0000617bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
Diana Picus995746d2017-07-12 10:31:16 +0000618 MachineRegisterInfo &MRI) const {
Diana Picus7145d222017-06-27 09:19:51 +0000619 auto &MBB = *MIB->getParent();
620 auto InsertBefore = std::next(MIB->getIterator());
Diana Picus77367372017-07-07 08:53:27 +0000621 auto &DbgLoc = MIB->getDebugLoc();
Diana Picus7145d222017-06-27 09:19:51 +0000622
623 // Compare the condition to 0.
624 auto CondReg = MIB->getOperand(1).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000625 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000626 "Unsupported types for select operation");
Diana Picus77367372017-07-07 08:53:27 +0000627 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri))
Diana Picus7145d222017-06-27 09:19:51 +0000628 .addUse(CondReg)
629 .addImm(0)
630 .add(predOps(ARMCC::AL));
631 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
632 return false;
633
634 // Move a value into the result register based on the result of the
635 // comparison.
636 auto ResReg = MIB->getOperand(0).getReg();
637 auto TrueReg = MIB->getOperand(2).getReg();
638 auto FalseReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000639 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
640 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000641 "Unsupported types for select operation");
Diana Picus77367372017-07-07 08:53:27 +0000642 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr))
Diana Picus7145d222017-06-27 09:19:51 +0000643 .addDef(ResReg)
644 .addUse(TrueReg)
645 .addUse(FalseReg)
646 .add(predOps(ARMCC::EQ, ARM::CPSR));
647 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
648 return false;
649
650 MIB->eraseFromParent();
651 return true;
652}
653
Diana Picuse393bc72017-10-06 15:39:16 +0000654bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
655 MachineInstrBuilder &MIB) const {
656 MIB->setDesc(TII.get(ARM::MOVsr));
657 MIB.addImm(ShiftOpc);
658 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
659 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
660}
661
Daniel Sandersf76f3152017-11-16 00:46:35 +0000662bool ARMInstructionSelector::select(MachineInstr &I,
663 CodeGenCoverage &CoverageInfo) const {
Diana Picus812caee2016-12-16 12:54:46 +0000664 assert(I.getParent() && "Instruction should be in a basic block!");
665 assert(I.getParent()->getParent() && "Instruction should be in a function!");
666
667 auto &MBB = *I.getParent();
668 auto &MF = *MBB.getParent();
669 auto &MRI = MF.getRegInfo();
670
671 if (!isPreISelGenericOpcode(I.getOpcode())) {
672 if (I.isCopy())
673 return selectCopy(I, TII, MRI, TRI, RBI);
674
675 return true;
676 }
677
Diana Picus68773852017-12-22 11:09:18 +0000678 using namespace TargetOpcode;
Diana Picus68773852017-12-22 11:09:18 +0000679
Daniel Sandersf76f3152017-11-16 00:46:35 +0000680 if (selectImpl(I, CoverageInfo))
Diana Picus8abcbbb2017-05-02 09:40:49 +0000681 return true;
682
Diana Picus519807f2016-12-19 11:26:31 +0000683 MachineInstrBuilder MIB{MF, I};
Diana Picusd83df5d2017-01-25 08:47:40 +0000684 bool isSExt = false;
Diana Picus519807f2016-12-19 11:26:31 +0000685
Diana Picus519807f2016-12-19 11:26:31 +0000686 switch (I.getOpcode()) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000687 case G_SEXT:
Diana Picusd83df5d2017-01-25 08:47:40 +0000688 isSExt = true;
689 LLVM_FALLTHROUGH;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000690 case G_ZEXT: {
691 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
692 // FIXME: Smaller destination sizes coming soon!
693 if (DstTy.getSizeInBits() != 32) {
694 DEBUG(dbgs() << "Unsupported destination size for extension");
695 return false;
696 }
697
698 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
699 unsigned SrcSize = SrcTy.getSizeInBits();
700 switch (SrcSize) {
Diana Picusd83df5d2017-01-25 08:47:40 +0000701 case 1: {
702 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
703 I.setDesc(TII.get(ARM::ANDri));
704 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
705
706 if (isSExt) {
707 unsigned SExtResult = I.getOperand(0).getReg();
708
709 // Use a new virtual register for the result of the AND
710 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
711 I.getOperand(0).setReg(AndResult);
712
713 auto InsertBefore = std::next(I.getIterator());
Martin Bohme8396e142017-01-25 14:28:19 +0000714 auto SubI =
Diana Picusd83df5d2017-01-25 08:47:40 +0000715 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri))
716 .addDef(SExtResult)
717 .addUse(AndResult)
718 .addImm(0)
719 .add(predOps(ARMCC::AL))
720 .add(condCodeOp());
721 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
722 return false;
723 }
724 break;
725 }
Diana Picus8b6c6be2017-01-25 08:10:40 +0000726 case 8:
727 case 16: {
728 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
Diana Picuse8368782017-02-17 13:44:19 +0000729 if (NewOpc == I.getOpcode())
730 return false;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000731 I.setDesc(TII.get(NewOpc));
732 MIB.addImm(0).add(predOps(ARMCC::AL));
733 break;
734 }
735 default:
736 DEBUG(dbgs() << "Unsupported source size for extension");
737 return false;
738 }
739 break;
740 }
Diana Picus657bfd32017-05-11 08:28:31 +0000741 case G_ANYEXT:
Diana Picus64a33432017-04-21 13:16:50 +0000742 case G_TRUNC: {
743 // The high bits are undefined, so there's nothing special to do, just
744 // treat it as a copy.
745 auto SrcReg = I.getOperand(1).getReg();
746 auto DstReg = I.getOperand(0).getReg();
747
748 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
749 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
750
Diana Picus75ce8522017-12-20 11:27:10 +0000751 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
752 // This should only happen in the obscure case where we have put a 64-bit
753 // integer into a D register. Get it out of there and keep only the
754 // interesting part.
755 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
756 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
757 "Unsupported combination of register banks");
758 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
759 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
760
761 unsigned IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
762 auto InsertBefore = std::next(I.getIterator());
763 auto MovI =
764 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
765 .addDef(DstReg)
766 .addDef(IgnoredBits)
767 .addUse(SrcReg)
768 .add(predOps(ARMCC::AL));
769 if (!constrainSelectedInstRegOperands(*MovI, TII, TRI, RBI))
770 return false;
771
772 MIB->eraseFromParent();
773 return true;
774 }
775
Diana Picus64a33432017-04-21 13:16:50 +0000776 if (SrcRegBank.getID() != DstRegBank.getID()) {
Diana Picus657bfd32017-05-11 08:28:31 +0000777 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
Diana Picus64a33432017-04-21 13:16:50 +0000778 return false;
779 }
780
781 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Diana Picus657bfd32017-05-11 08:28:31 +0000782 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
Diana Picus64a33432017-04-21 13:16:50 +0000783 return false;
784 }
785
786 I.setDesc(TII.get(COPY));
787 return selectCopy(I, TII, MRI, TRI, RBI);
788 }
Diana Picus37ae9f62018-01-04 10:54:57 +0000789 case G_CONSTANT: {
790 if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
791 // Non-pointer constants should be handled by TableGen.
792 DEBUG(dbgs() << "Unsupported constant type\n");
793 return false;
794 }
795
796 auto &Val = I.getOperand(1);
797 if (Val.isCImm()) {
798 if (!Val.getCImm()->isZero()) {
799 DEBUG(dbgs() << "Unsupported pointer constant value\n");
800 return false;
801 }
802 Val.ChangeToImmediate(0);
803 } else {
804 assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
805 if (Val.getImm() != 0) {
806 DEBUG(dbgs() << "Unsupported pointer constant value\n");
807 return false;
808 }
809 }
810
811 I.setDesc(TII.get(ARM::MOVi));
812 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
813 break;
814 }
Diana Picus28a6d0e2017-12-22 13:05:51 +0000815 case G_INTTOPTR:
816 case G_PTRTOINT: {
817 auto SrcReg = I.getOperand(1).getReg();
818 auto DstReg = I.getOperand(0).getReg();
819
820 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
821 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
822
823 if (SrcRegBank.getID() != DstRegBank.getID()) {
824 DEBUG(dbgs()
825 << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
826 return false;
827 }
828
829 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
830 DEBUG(dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
831 return false;
832 }
833
834 I.setDesc(TII.get(COPY));
835 return selectCopy(I, TII, MRI, TRI, RBI);
836 }
Diana Picus7145d222017-06-27 09:19:51 +0000837 case G_SELECT:
Diana Picus995746d2017-07-12 10:31:16 +0000838 return selectSelect(MIB, MRI);
839 case G_ICMP: {
840 CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END,
841 ARM::GPRRegBankID, 32);
842 return selectCmp(Helper, MIB, MRI);
843 }
Diana Picus21014df2017-07-12 09:01:54 +0000844 case G_FCMP: {
Diana Picusac154732017-09-05 08:22:47 +0000845 assert(STI.hasVFP2() && "Can't select fcmp without VFP");
Diana Picus21014df2017-07-12 09:01:54 +0000846
847 unsigned OpReg = I.getOperand(2).getReg();
848 unsigned Size = MRI.getType(OpReg).getSizeInBits();
Diana Picus995746d2017-07-12 10:31:16 +0000849
Diana Picusac154732017-09-05 08:22:47 +0000850 if (Size == 64 && STI.isFPOnlySP()) {
Diana Picus995746d2017-07-12 10:31:16 +0000851 DEBUG(dbgs() << "Subtarget only supports single precision");
852 return false;
853 }
854 if (Size != 32 && Size != 64) {
855 DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
856 return false;
Diana Picus21014df2017-07-12 09:01:54 +0000857 }
858
Diana Picus995746d2017-07-12 10:31:16 +0000859 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
860 ARM::FPRRegBankID, Size);
861 return selectCmp(Helper, MIB, MRI);
Diana Picus21014df2017-07-12 09:01:54 +0000862 }
Diana Picuse393bc72017-10-06 15:39:16 +0000863 case G_LSHR:
864 return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
865 case G_ASHR:
866 return selectShift(ARM_AM::ShiftOpc::asr, MIB);
867 case G_SHL: {
868 return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
869 }
Diana Picus9d070942017-02-28 10:14:38 +0000870 case G_GEP:
Diana Picus812caee2016-12-16 12:54:46 +0000871 I.setDesc(TII.get(ARM::ADDrr));
Diana Picus8a73f552017-01-13 10:18:01 +0000872 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000873 break;
874 case G_FRAME_INDEX:
875 // Add 0 to the given frame index and hope it will eventually be folded into
876 // the user(s).
877 I.setDesc(TII.get(ARM::ADDri));
Diana Picus8a73f552017-01-13 10:18:01 +0000878 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000879 break;
Diana Picus930e6ec2017-08-03 09:14:59 +0000880 case G_GLOBAL_VALUE:
881 return selectGlobal(MIB, MRI);
Diana Picus3b99c642017-02-24 14:01:27 +0000882 case G_STORE:
Diana Picus278c7222017-01-26 09:20:47 +0000883 case G_LOAD: {
Daniel Sanders3c1c4c02017-12-05 05:52:07 +0000884 const auto &MemOp = **I.memoperands_begin();
885 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
886 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
887 return false;
888 }
889
Diana Picus1540b062017-02-16 14:10:50 +0000890 unsigned Reg = I.getOperand(0).getReg();
891 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
892
893 LLT ValTy = MRI.getType(Reg);
Diana Picus278c7222017-01-26 09:20:47 +0000894 const auto ValSize = ValTy.getSizeInBits();
895
Diana Picusac154732017-09-05 08:22:47 +0000896 assert((ValSize != 64 || STI.hasVFP2()) &&
Diana Picus3b99c642017-02-24 14:01:27 +0000897 "Don't know how to load/store 64-bit value without VFP");
Diana Picus1540b062017-02-16 14:10:50 +0000898
Diana Picus3b99c642017-02-24 14:01:27 +0000899 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
900 if (NewOpc == G_LOAD || NewOpc == G_STORE)
Diana Picuse8368782017-02-17 13:44:19 +0000901 return false;
902
Diana Picus278c7222017-01-26 09:20:47 +0000903 I.setDesc(TII.get(NewOpc));
904
Diana Picus3b99c642017-02-24 14:01:27 +0000905 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
Diana Picus278c7222017-01-26 09:20:47 +0000906 // LDRH has a funny addressing mode (there's already a FIXME for it).
907 MIB.addReg(0);
Diana Picus4f8c3e12017-01-13 09:37:56 +0000908 MIB.addImm(0).add(predOps(ARMCC::AL));
Diana Picus519807f2016-12-19 11:26:31 +0000909 break;
Diana Picus278c7222017-01-26 09:20:47 +0000910 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000911 case G_MERGE_VALUES: {
912 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000913 return false;
914 break;
915 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000916 case G_UNMERGE_VALUES: {
917 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000918 return false;
919 break;
920 }
Diana Picus87a70672017-07-14 09:46:06 +0000921 case G_BRCOND: {
922 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
923 DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
924 return false;
925 }
926
927 // Set the flags.
928 auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri))
929 .addReg(I.getOperand(0).getReg())
930 .addImm(1)
931 .add(predOps(ARMCC::AL));
932 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
933 return false;
934
935 // Branch conditionally.
936 auto Branch = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::Bcc))
937 .add(I.getOperand(1))
Diana Picus863b5b02017-11-29 14:20:06 +0000938 .add(predOps(ARMCC::NE, ARM::CPSR));
Diana Picus87a70672017-07-14 09:46:06 +0000939 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
940 return false;
941 I.eraseFromParent();
942 return true;
943 }
Diana Picus865f7fe2018-01-04 13:09:25 +0000944 case G_PHI: {
945 I.setDesc(TII.get(PHI));
946
947 unsigned DstReg = I.getOperand(0).getReg();
948 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
949 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
950 break;
951 }
952
953 return true;
954 }
Diana Picus519807f2016-12-19 11:26:31 +0000955 default:
956 return false;
Diana Picus812caee2016-12-16 12:54:46 +0000957 }
958
Diana Picus519807f2016-12-19 11:26:31 +0000959 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
Diana Picus22274932016-11-11 08:27:37 +0000960}