blob: c7f1d483bd46dd5c887389d7343f0d923b418901 [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"
Diana Picus812caee2016-12-16 12:54:46 +000018#include "llvm/CodeGen/MachineRegisterInfo.h"
Diana Picus22274932016-11-11 08:27:37 +000019#include "llvm/Support/Debug.h"
20
21#define DEBUG_TYPE "arm-isel"
22
Daniel Sanders6ab0daa2017-07-04 14:35:06 +000023#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
24
Diana Picus22274932016-11-11 08:27:37 +000025using namespace llvm;
26
27#ifndef LLVM_BUILD_GLOBAL_ISEL
28#error "You shouldn't build this"
29#endif
30
Diana Picus674888d2017-04-28 09:10:38 +000031namespace {
Diana Picus8abcbbb2017-05-02 09:40:49 +000032
33#define GET_GLOBALISEL_PREDICATE_BITSET
34#include "ARMGenGlobalISel.inc"
35#undef GET_GLOBALISEL_PREDICATE_BITSET
36
Diana Picus674888d2017-04-28 09:10:38 +000037class ARMInstructionSelector : public InstructionSelector {
38public:
Diana Picus8abcbbb2017-05-02 09:40:49 +000039 ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000040 const ARMRegisterBankInfo &RBI);
41
42 bool select(MachineInstr &I) const override;
43
44private:
Diana Picus8abcbbb2017-05-02 09:40:49 +000045 bool selectImpl(MachineInstr &I) const;
46
Diana Picus5b916532017-07-07 08:39:04 +000047 template <typename T> struct CmpHelper;
48
49 template <typename T>
50 bool selectCmp(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII,
51 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
52 const RegisterBankInfo &RBI) const;
Diana Picus621894a2017-06-19 09:40:51 +000053
Diana Picus7145d222017-06-27 09:19:51 +000054 bool selectSelect(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII,
55 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
56 const RegisterBankInfo &RBI) const;
57
Diana Picus674888d2017-04-28 09:10:38 +000058 const ARMBaseInstrInfo &TII;
59 const ARMBaseRegisterInfo &TRI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000060 const ARMBaseTargetMachine &TM;
Diana Picus674888d2017-04-28 09:10:38 +000061 const ARMRegisterBankInfo &RBI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000062 const ARMSubtarget &STI;
63
64#define GET_GLOBALISEL_PREDICATES_DECL
65#include "ARMGenGlobalISel.inc"
66#undef GET_GLOBALISEL_PREDICATES_DECL
67
68// We declare the temporaries used by selectImpl() in the class to minimize the
69// cost of constructing placeholder values.
70#define GET_GLOBALISEL_TEMPORARIES_DECL
71#include "ARMGenGlobalISel.inc"
72#undef GET_GLOBALISEL_TEMPORARIES_DECL
Diana Picus674888d2017-04-28 09:10:38 +000073};
74} // end anonymous namespace
75
76namespace llvm {
77InstructionSelector *
Diana Picus8abcbbb2017-05-02 09:40:49 +000078createARMInstructionSelector(const ARMBaseTargetMachine &TM,
79 const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000080 const ARMRegisterBankInfo &RBI) {
Diana Picus8abcbbb2017-05-02 09:40:49 +000081 return new ARMInstructionSelector(TM, STI, RBI);
Diana Picus674888d2017-04-28 09:10:38 +000082}
83}
84
Diana Picus8abcbbb2017-05-02 09:40:49 +000085unsigned zero_reg = 0;
86
87#define GET_GLOBALISEL_IMPL
88#include "ARMGenGlobalISel.inc"
89#undef GET_GLOBALISEL_IMPL
90
91ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
92 const ARMSubtarget &STI,
Diana Picus22274932016-11-11 08:27:37 +000093 const ARMRegisterBankInfo &RBI)
Diana Picus895c6aa2016-11-15 16:42:10 +000094 : InstructionSelector(), TII(*STI.getInstrInfo()),
Diana Picus8abcbbb2017-05-02 09:40:49 +000095 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
96#define GET_GLOBALISEL_PREDICATES_INIT
97#include "ARMGenGlobalISel.inc"
98#undef GET_GLOBALISEL_PREDICATES_INIT
99#define GET_GLOBALISEL_TEMPORARIES_INIT
100#include "ARMGenGlobalISel.inc"
101#undef GET_GLOBALISEL_TEMPORARIES_INIT
102{
103}
Diana Picus22274932016-11-11 08:27:37 +0000104
Diana Picus812caee2016-12-16 12:54:46 +0000105static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
106 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
107 const RegisterBankInfo &RBI) {
108 unsigned DstReg = I.getOperand(0).getReg();
109 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
110 return true;
111
112 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
Benjamin Kramer24bf8682016-12-16 13:13:03 +0000113 (void)RegBank;
Diana Picus812caee2016-12-16 12:54:46 +0000114 assert(RegBank && "Can't get reg bank for virtual register");
115
Diana Picus36aa09f2016-12-19 14:07:50 +0000116 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Diana Picus4fa83c02017-02-08 13:23:04 +0000117 assert((RegBank->getID() == ARM::GPRRegBankID ||
118 RegBank->getID() == ARM::FPRRegBankID) &&
119 "Unsupported reg bank");
120
Diana Picus812caee2016-12-16 12:54:46 +0000121 const TargetRegisterClass *RC = &ARM::GPRRegClass;
122
Diana Picus4fa83c02017-02-08 13:23:04 +0000123 if (RegBank->getID() == ARM::FPRRegBankID) {
Diana Picus6beef3c2017-02-16 12:19:52 +0000124 if (DstSize == 32)
125 RC = &ARM::SPRRegClass;
126 else if (DstSize == 64)
127 RC = &ARM::DPRRegClass;
128 else
129 llvm_unreachable("Unsupported destination size");
Diana Picus4fa83c02017-02-08 13:23:04 +0000130 }
131
Diana Picus812caee2016-12-16 12:54:46 +0000132 // No need to constrain SrcReg. It will get constrained when
133 // we hit another of its uses or its defs.
134 // Copies do not have constraints.
135 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
136 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
137 << " operand\n");
138 return false;
139 }
140 return true;
141}
142
Diana Picus0b4190a2017-06-07 12:35:05 +0000143static bool selectMergeValues(MachineInstrBuilder &MIB,
144 const ARMBaseInstrInfo &TII,
145 MachineRegisterInfo &MRI,
146 const TargetRegisterInfo &TRI,
147 const RegisterBankInfo &RBI) {
148 assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000149
Diana Picus0b4190a2017-06-07 12:35:05 +0000150 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
Diana Picusb1701e02017-02-16 12:19:57 +0000151 // into one DPR.
152 unsigned VReg0 = MIB->getOperand(0).getReg();
153 (void)VReg0;
154 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
155 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000156 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000157 unsigned VReg1 = MIB->getOperand(1).getReg();
158 (void)VReg1;
159 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
160 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000161 "Unsupported operand for G_MERGE_VALUES");
162 unsigned VReg2 = MIB->getOperand(2).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000163 (void)VReg2;
164 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
165 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000166 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000167
168 MIB->setDesc(TII.get(ARM::VMOVDRR));
169 MIB.add(predOps(ARMCC::AL));
170
171 return true;
172}
173
Diana Picus0b4190a2017-06-07 12:35:05 +0000174static bool selectUnmergeValues(MachineInstrBuilder &MIB,
175 const ARMBaseInstrInfo &TII,
176 MachineRegisterInfo &MRI,
177 const TargetRegisterInfo &TRI,
178 const RegisterBankInfo &RBI) {
179 assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000180
Diana Picus0b4190a2017-06-07 12:35:05 +0000181 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
182 // GPRs.
Diana Picusb1701e02017-02-16 12:19:57 +0000183 unsigned VReg0 = MIB->getOperand(0).getReg();
184 (void)VReg0;
185 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
186 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000187 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000188 unsigned VReg1 = MIB->getOperand(1).getReg();
189 (void)VReg1;
Diana Picus0b4190a2017-06-07 12:35:05 +0000190 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
191 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
192 "Unsupported operand for G_UNMERGE_VALUES");
193 unsigned VReg2 = MIB->getOperand(2).getReg();
194 (void)VReg2;
195 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
196 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
197 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000198
Diana Picus0b4190a2017-06-07 12:35:05 +0000199 MIB->setDesc(TII.get(ARM::VMOVRRD));
Diana Picusb1701e02017-02-16 12:19:57 +0000200 MIB.add(predOps(ARMCC::AL));
201
202 return true;
203}
204
Diana Picus8b6c6be2017-01-25 08:10:40 +0000205/// Select the opcode for simple extensions (that translate to a single SXT/UXT
206/// instruction). Extension operations more complicated than that should not
Diana Picuse8368782017-02-17 13:44:19 +0000207/// invoke this. Returns the original opcode if it doesn't know how to select a
208/// better one.
Diana Picus8b6c6be2017-01-25 08:10:40 +0000209static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) {
210 using namespace TargetOpcode;
211
Diana Picuse8368782017-02-17 13:44:19 +0000212 if (Size != 8 && Size != 16)
213 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000214
215 if (Opc == G_SEXT)
216 return Size == 8 ? ARM::SXTB : ARM::SXTH;
217
218 if (Opc == G_ZEXT)
219 return Size == 8 ? ARM::UXTB : ARM::UXTH;
220
Diana Picuse8368782017-02-17 13:44:19 +0000221 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000222}
223
Diana Picus3b99c642017-02-24 14:01:27 +0000224/// Select the opcode for simple loads and stores. For types smaller than 32
225/// bits, the value will be zero extended. Returns the original opcode if it
226/// doesn't know how to select a better one.
227static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
228 unsigned Size) {
229 bool isStore = Opc == TargetOpcode::G_STORE;
230
Diana Picus1540b062017-02-16 14:10:50 +0000231 if (RegBank == ARM::GPRRegBankID) {
232 switch (Size) {
233 case 1:
234 case 8:
Diana Picus3b99c642017-02-24 14:01:27 +0000235 return isStore ? ARM::STRBi12 : ARM::LDRBi12;
Diana Picus1540b062017-02-16 14:10:50 +0000236 case 16:
Diana Picus3b99c642017-02-24 14:01:27 +0000237 return isStore ? ARM::STRH : ARM::LDRH;
Diana Picus1540b062017-02-16 14:10:50 +0000238 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000239 return isStore ? ARM::STRi12 : ARM::LDRi12;
Diana Picuse8368782017-02-17 13:44:19 +0000240 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000241 return Opc;
Diana Picus1540b062017-02-16 14:10:50 +0000242 }
Diana Picus1540b062017-02-16 14:10:50 +0000243 }
244
Diana Picuse8368782017-02-17 13:44:19 +0000245 if (RegBank == ARM::FPRRegBankID) {
246 switch (Size) {
247 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000248 return isStore ? ARM::VSTRS : ARM::VLDRS;
Diana Picuse8368782017-02-17 13:44:19 +0000249 case 64:
Diana Picus3b99c642017-02-24 14:01:27 +0000250 return isStore ? ARM::VSTRD : ARM::VLDRD;
Diana Picuse8368782017-02-17 13:44:19 +0000251 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000252 return Opc;
Diana Picuse8368782017-02-17 13:44:19 +0000253 }
Diana Picus278c7222017-01-26 09:20:47 +0000254 }
255
Diana Picus3b99c642017-02-24 14:01:27 +0000256 return Opc;
Diana Picus278c7222017-01-26 09:20:47 +0000257}
258
Diana Picus5b916532017-07-07 08:39:04 +0000259// When lowering comparisons, we sometimes need to perform two compares instead
260// of just one. Get the condition codes for both comparisons. If only one is
261// needed, the second member of the pair is ARMCC::AL.
262static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
263getComparePreds(CmpInst::Predicate Pred) {
264 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
Diana Picus621894a2017-06-19 09:40:51 +0000265 switch (Pred) {
Diana Picus621894a2017-06-19 09:40:51 +0000266 case CmpInst::FCMP_ONE:
Diana Picus5b916532017-07-07 08:39:04 +0000267 Preds = {ARMCC::GT, ARMCC::MI};
268 break;
Diana Picus621894a2017-06-19 09:40:51 +0000269 case CmpInst::FCMP_UEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000270 Preds = {ARMCC::EQ, ARMCC::VS};
271 break;
Diana Picus621894a2017-06-19 09:40:51 +0000272 case CmpInst::ICMP_EQ:
273 case CmpInst::FCMP_OEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000274 Preds.first = ARMCC::EQ;
275 break;
Diana Picus621894a2017-06-19 09:40:51 +0000276 case CmpInst::ICMP_SGT:
277 case CmpInst::FCMP_OGT:
Diana Picus5b916532017-07-07 08:39:04 +0000278 Preds.first = ARMCC::GT;
279 break;
Diana Picus621894a2017-06-19 09:40:51 +0000280 case CmpInst::ICMP_SGE:
281 case CmpInst::FCMP_OGE:
Diana Picus5b916532017-07-07 08:39:04 +0000282 Preds.first = ARMCC::GE;
283 break;
Diana Picus621894a2017-06-19 09:40:51 +0000284 case CmpInst::ICMP_UGT:
285 case CmpInst::FCMP_UGT:
Diana Picus5b916532017-07-07 08:39:04 +0000286 Preds.first = ARMCC::HI;
287 break;
Diana Picus621894a2017-06-19 09:40:51 +0000288 case CmpInst::FCMP_OLT:
Diana Picus5b916532017-07-07 08:39:04 +0000289 Preds.first = ARMCC::MI;
290 break;
Diana Picus621894a2017-06-19 09:40:51 +0000291 case CmpInst::ICMP_ULE:
292 case CmpInst::FCMP_OLE:
Diana Picus5b916532017-07-07 08:39:04 +0000293 Preds.first = ARMCC::LS;
294 break;
Diana Picus621894a2017-06-19 09:40:51 +0000295 case CmpInst::FCMP_ORD:
Diana Picus5b916532017-07-07 08:39:04 +0000296 Preds.first = ARMCC::VC;
297 break;
Diana Picus621894a2017-06-19 09:40:51 +0000298 case CmpInst::FCMP_UNO:
Diana Picus5b916532017-07-07 08:39:04 +0000299 Preds.first = ARMCC::VS;
300 break;
Diana Picus621894a2017-06-19 09:40:51 +0000301 case CmpInst::FCMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000302 Preds.first = ARMCC::PL;
303 break;
Diana Picus621894a2017-06-19 09:40:51 +0000304 case CmpInst::ICMP_SLT:
305 case CmpInst::FCMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000306 Preds.first = ARMCC::LT;
307 break;
Diana Picus621894a2017-06-19 09:40:51 +0000308 case CmpInst::ICMP_SLE:
309 case CmpInst::FCMP_ULE:
Diana Picus5b916532017-07-07 08:39:04 +0000310 Preds.first = ARMCC::LE;
311 break;
Diana Picus621894a2017-06-19 09:40:51 +0000312 case CmpInst::FCMP_UNE:
313 case CmpInst::ICMP_NE:
Diana Picus5b916532017-07-07 08:39:04 +0000314 Preds.first = ARMCC::NE;
315 break;
Diana Picus621894a2017-06-19 09:40:51 +0000316 case CmpInst::ICMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000317 Preds.first = ARMCC::HS;
318 break;
Diana Picus621894a2017-06-19 09:40:51 +0000319 case CmpInst::ICMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000320 Preds.first = ARMCC::LO;
321 break;
322 default:
323 break;
Diana Picus621894a2017-06-19 09:40:51 +0000324 }
Diana Picus5b916532017-07-07 08:39:04 +0000325 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
326 return Preds;
Diana Picus621894a2017-06-19 09:40:51 +0000327}
328
Diana Picus5b916532017-07-07 08:39:04 +0000329template <typename T> struct ARMInstructionSelector::CmpHelper {
330 CmpHelper(const ARMInstructionSelector &Selector, MachineInstrBuilder &MIB,
331 const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI,
332 const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
333 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
334 DebugLoc(MIB->getDebugLoc()), TII(TII), MRI(MRI), TRI(TRI), RBI(RBI),
335 Selector(Selector) {}
Diana Picus621894a2017-06-19 09:40:51 +0000336
Diana Picus5b916532017-07-07 08:39:04 +0000337 // The opcode used for performing the comparison.
338 static const unsigned ComparisonOpcode;
Diana Picus621894a2017-06-19 09:40:51 +0000339
Diana Picus5b916532017-07-07 08:39:04 +0000340 // The opcode used for reading the flags set by the comparison. May be
341 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
342 static const unsigned ReadFlagsOpcode;
Diana Picus621894a2017-06-19 09:40:51 +0000343
Diana Picus5b916532017-07-07 08:39:04 +0000344 // The opcode used for selecting the result register, based on the value
345 // of the flags.
346 static const unsigned SetResultOpcode = ARM::MOVCCi;
347
348 // The assumed register bank ID for the operands.
349 static const unsigned OperandRegBankID;
350
351 // The assumed register bank ID for the result.
352 static const unsigned ResultRegBankID = ARM::GPRRegBankID;
353
354 unsigned getZeroRegister() {
355 unsigned Reg = MRI.createVirtualRegister(&ARM::GPRRegClass);
356 putConstant(Reg, 0);
357 return Reg;
358 }
359
360 void putConstant(unsigned DestReg, unsigned Constant) {
361 (void)BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::MOVi))
362 .addDef(DestReg)
363 .addImm(Constant)
364 .add(predOps(ARMCC::AL))
365 .add(condCodeOp());
366 }
367
368 bool insertComparison(unsigned ResReg, ARMCC::CondCodes Cond, unsigned LHSReg,
369 unsigned RHSReg, unsigned PrevRes) {
370
371 // Perform the comparison.
372 auto CmpI = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ComparisonOpcode))
373 .addUse(LHSReg)
374 .addUse(RHSReg)
375 .add(predOps(ARMCC::AL));
376 if (!Selector.constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
377 return false;
378
379 // Read the comparison flags (if necessary).
380 if (ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
381 auto ReadI =
382 BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ReadFlagsOpcode))
383 .add(predOps(ARMCC::AL));
384 if (!Selector.constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
385 return false;
386 }
387
388 // Select either 1 or the previous result based on the value of the flags.
389 auto Mov1I = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(SetResultOpcode))
390 .addDef(ResReg)
391 .addUse(PrevRes)
392 .addImm(1)
393 .add(predOps(Cond, ARM::CPSR));
394 if (!Selector.constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
395 return false;
396
397 return true;
398 }
399
400 bool validateOpRegs(unsigned LHSReg, unsigned RHSReg) {
401 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
402 validateOpReg(LHSReg, MRI, TRI, RBI) &&
403 validateOpReg(RHSReg, MRI, TRI, RBI);
404 }
405
406 bool validateResReg(unsigned ResReg) {
407 if (MRI.getType(ResReg).getSizeInBits() != 1) {
408 DEBUG(dbgs() << "Unsupported size for comparison operand");
409 return false;
410 }
411
412 if (RBI.getRegBank(ResReg, MRI, TRI)->getID() != ResultRegBankID) {
413 DEBUG(dbgs() << "Unsupported register bank for comparison operand");
414 return false;
415 }
416
417 return true;
418 }
419
420private:
421 bool validateOpReg(unsigned OpReg, MachineRegisterInfo &MRI,
422 const TargetRegisterInfo &TRI,
423 const RegisterBankInfo &RBI) {
424 if (MRI.getType(OpReg).getSizeInBits() != 32) {
425 DEBUG(dbgs() << "Unsupported size for comparison operand");
426 return false;
427 }
428
429 if (RBI.getRegBank(OpReg, MRI, TRI)->getID() != OperandRegBankID) {
430 DEBUG(dbgs() << "Unsupported register bank for comparison operand");
431 return false;
432 }
433
434 return true;
435 }
436
437 MachineBasicBlock &MBB;
438 MachineBasicBlock::instr_iterator InsertBefore;
439 const DebugLoc &DebugLoc;
440
441 const ARMBaseInstrInfo &TII;
442 MachineRegisterInfo &MRI;
443 const TargetRegisterInfo &TRI;
444 const RegisterBankInfo &RBI;
445
446 const ARMInstructionSelector &Selector;
447};
448
449// Specialize the opcode to be used for comparing different types of operands.
450template <>
451const unsigned ARMInstructionSelector::CmpHelper<int>::ComparisonOpcode =
452 ARM::CMPrr;
453template <>
454const unsigned ARMInstructionSelector::CmpHelper<float>::ComparisonOpcode =
455 ARM::VCMPS;
456
457// Specialize the opcode to be used for reading the comparison flags for
458// different types of operands.
459template <>
460const unsigned ARMInstructionSelector::CmpHelper<int>::ReadFlagsOpcode =
461 ARM::INSTRUCTION_LIST_END;
462template <>
463const unsigned ARMInstructionSelector::CmpHelper<float>::ReadFlagsOpcode =
464 ARM::FMSTAT;
465
466// Specialize the register bank where the operands of the comparison are assumed
467// to live.
468template <>
469const unsigned ARMInstructionSelector::CmpHelper<int>::OperandRegBankID =
470 ARM::GPRRegBankID;
471template <>
472const unsigned ARMInstructionSelector::CmpHelper<float>::OperandRegBankID =
473 ARM::FPRRegBankID;
474
475template <typename T>
476bool ARMInstructionSelector::selectCmp(MachineInstrBuilder &MIB,
477 const ARMBaseInstrInfo &TII,
478 MachineRegisterInfo &MRI,
479 const TargetRegisterInfo &TRI,
480 const RegisterBankInfo &RBI) const {
481 auto Helper = CmpHelper<T>(*this, MIB, TII, MRI, TRI, RBI);
482
Diana Picus621894a2017-06-19 09:40:51 +0000483 auto ResReg = MIB->getOperand(0).getReg();
Diana Picus5b916532017-07-07 08:39:04 +0000484 if (!Helper.validateResReg(ResReg))
485 return false;
486
Diana Picus621894a2017-06-19 09:40:51 +0000487 auto Cond =
488 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
Diana Picus5b916532017-07-07 08:39:04 +0000489 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
490 Helper.putConstant(ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
491 MIB->eraseFromParent();
492 return true;
493 }
494
495 auto LHSReg = MIB->getOperand(2).getReg();
496 auto RHSReg = MIB->getOperand(3).getReg();
497 if (!Helper.validateOpRegs(LHSReg, RHSReg))
Diana Picus621894a2017-06-19 09:40:51 +0000498 return false;
499
Diana Picus5b916532017-07-07 08:39:04 +0000500 auto ARMConds = getComparePreds(Cond);
501 auto ZeroReg = Helper.getZeroRegister();
502
503 if (ARMConds.second == ARMCC::AL) {
504 // Simple case, we only need one comparison and we're done.
505 if (!Helper.insertComparison(ResReg, ARMConds.first, LHSReg, RHSReg,
506 ZeroReg))
507 return false;
508 } else {
509 // Not so simple, we need two successive comparisons.
510 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
511 if (!Helper.insertComparison(IntermediateRes, ARMConds.first, LHSReg,
512 RHSReg, ZeroReg))
513 return false;
514 if (!Helper.insertComparison(ResReg, ARMConds.second, LHSReg, RHSReg,
515 IntermediateRes))
516 return false;
517 }
Diana Picus621894a2017-06-19 09:40:51 +0000518
519 MIB->eraseFromParent();
520 return true;
521}
522
Diana Picus7145d222017-06-27 09:19:51 +0000523bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
524 const ARMBaseInstrInfo &TII,
525 MachineRegisterInfo &MRI,
526 const TargetRegisterInfo &TRI,
527 const RegisterBankInfo &RBI) const {
528 auto &MBB = *MIB->getParent();
529 auto InsertBefore = std::next(MIB->getIterator());
530 auto &DebugLoc = MIB->getDebugLoc();
531
532 // Compare the condition to 0.
533 auto CondReg = MIB->getOperand(1).getReg();
534 assert(MRI.getType(CondReg).getSizeInBits() == 1 &&
535 RBI.getRegBank(CondReg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
536 "Unsupported types for select operation");
537 auto CmpI = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::CMPri))
538 .addUse(CondReg)
539 .addImm(0)
540 .add(predOps(ARMCC::AL));
541 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
542 return false;
543
544 // Move a value into the result register based on the result of the
545 // comparison.
546 auto ResReg = MIB->getOperand(0).getReg();
547 auto TrueReg = MIB->getOperand(2).getReg();
548 auto FalseReg = MIB->getOperand(3).getReg();
549 assert(MRI.getType(ResReg) == MRI.getType(TrueReg) &&
550 MRI.getType(TrueReg) == MRI.getType(FalseReg) &&
551 MRI.getType(FalseReg).getSizeInBits() == 32 &&
552 RBI.getRegBank(TrueReg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
553 RBI.getRegBank(FalseReg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
554 "Unsupported types for select operation");
555 auto Mov1I = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::MOVCCr))
556 .addDef(ResReg)
557 .addUse(TrueReg)
558 .addUse(FalseReg)
559 .add(predOps(ARMCC::EQ, ARM::CPSR));
560 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
561 return false;
562
563 MIB->eraseFromParent();
564 return true;
565}
566
Diana Picus812caee2016-12-16 12:54:46 +0000567bool ARMInstructionSelector::select(MachineInstr &I) const {
568 assert(I.getParent() && "Instruction should be in a basic block!");
569 assert(I.getParent()->getParent() && "Instruction should be in a function!");
570
571 auto &MBB = *I.getParent();
572 auto &MF = *MBB.getParent();
573 auto &MRI = MF.getRegInfo();
574
575 if (!isPreISelGenericOpcode(I.getOpcode())) {
576 if (I.isCopy())
577 return selectCopy(I, TII, MRI, TRI, RBI);
578
579 return true;
580 }
581
Diana Picus8abcbbb2017-05-02 09:40:49 +0000582 if (selectImpl(I))
583 return true;
584
Diana Picus519807f2016-12-19 11:26:31 +0000585 MachineInstrBuilder MIB{MF, I};
Diana Picusd83df5d2017-01-25 08:47:40 +0000586 bool isSExt = false;
Diana Picus519807f2016-12-19 11:26:31 +0000587
588 using namespace TargetOpcode;
589 switch (I.getOpcode()) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000590 case G_SEXT:
Diana Picusd83df5d2017-01-25 08:47:40 +0000591 isSExt = true;
592 LLVM_FALLTHROUGH;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000593 case G_ZEXT: {
594 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
595 // FIXME: Smaller destination sizes coming soon!
596 if (DstTy.getSizeInBits() != 32) {
597 DEBUG(dbgs() << "Unsupported destination size for extension");
598 return false;
599 }
600
601 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
602 unsigned SrcSize = SrcTy.getSizeInBits();
603 switch (SrcSize) {
Diana Picusd83df5d2017-01-25 08:47:40 +0000604 case 1: {
605 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
606 I.setDesc(TII.get(ARM::ANDri));
607 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
608
609 if (isSExt) {
610 unsigned SExtResult = I.getOperand(0).getReg();
611
612 // Use a new virtual register for the result of the AND
613 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
614 I.getOperand(0).setReg(AndResult);
615
616 auto InsertBefore = std::next(I.getIterator());
Martin Bohme8396e142017-01-25 14:28:19 +0000617 auto SubI =
Diana Picusd83df5d2017-01-25 08:47:40 +0000618 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri))
619 .addDef(SExtResult)
620 .addUse(AndResult)
621 .addImm(0)
622 .add(predOps(ARMCC::AL))
623 .add(condCodeOp());
624 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
625 return false;
626 }
627 break;
628 }
Diana Picus8b6c6be2017-01-25 08:10:40 +0000629 case 8:
630 case 16: {
631 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
Diana Picuse8368782017-02-17 13:44:19 +0000632 if (NewOpc == I.getOpcode())
633 return false;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000634 I.setDesc(TII.get(NewOpc));
635 MIB.addImm(0).add(predOps(ARMCC::AL));
636 break;
637 }
638 default:
639 DEBUG(dbgs() << "Unsupported source size for extension");
640 return false;
641 }
642 break;
643 }
Diana Picus657bfd32017-05-11 08:28:31 +0000644 case G_ANYEXT:
Diana Picus64a33432017-04-21 13:16:50 +0000645 case G_TRUNC: {
646 // The high bits are undefined, so there's nothing special to do, just
647 // treat it as a copy.
648 auto SrcReg = I.getOperand(1).getReg();
649 auto DstReg = I.getOperand(0).getReg();
650
651 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
652 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
653
654 if (SrcRegBank.getID() != DstRegBank.getID()) {
Diana Picus657bfd32017-05-11 08:28:31 +0000655 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
Diana Picus64a33432017-04-21 13:16:50 +0000656 return false;
657 }
658
659 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Diana Picus657bfd32017-05-11 08:28:31 +0000660 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
Diana Picus64a33432017-04-21 13:16:50 +0000661 return false;
662 }
663
664 I.setDesc(TII.get(COPY));
665 return selectCopy(I, TII, MRI, TRI, RBI);
666 }
Diana Picus7145d222017-06-27 09:19:51 +0000667 case G_SELECT:
668 return selectSelect(MIB, TII, MRI, TRI, RBI);
Diana Picus5b916532017-07-07 08:39:04 +0000669 case G_ICMP:
670 return selectCmp<int>(MIB, TII, MRI, TRI, RBI);
671 case G_FCMP:
672 assert(TII.getSubtarget().hasVFP2() && "Can't select fcmp without VFP");
673 return selectCmp<float>(MIB, TII, MRI, TRI, RBI);
Diana Picus9d070942017-02-28 10:14:38 +0000674 case G_GEP:
Diana Picus812caee2016-12-16 12:54:46 +0000675 I.setDesc(TII.get(ARM::ADDrr));
Diana Picus8a73f552017-01-13 10:18:01 +0000676 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000677 break;
678 case G_FRAME_INDEX:
679 // Add 0 to the given frame index and hope it will eventually be folded into
680 // the user(s).
681 I.setDesc(TII.get(ARM::ADDri));
Diana Picus8a73f552017-01-13 10:18:01 +0000682 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000683 break;
Diana Picus5a7203a2017-02-28 13:05:42 +0000684 case G_CONSTANT: {
685 unsigned Reg = I.getOperand(0).getReg();
686 if (MRI.getType(Reg).getSizeInBits() != 32)
687 return false;
688
689 assert(RBI.getRegBank(Reg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
690 "Expected constant to live in a GPR");
691 I.setDesc(TII.get(ARM::MOVi));
692 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus95a8aa92017-04-24 06:30:56 +0000693
694 auto &Val = I.getOperand(1);
695 if (Val.isCImm()) {
696 if (Val.getCImm()->getBitWidth() > 32)
697 return false;
698 Val.ChangeToImmediate(Val.getCImm()->getZExtValue());
699 }
700
701 if (!Val.isImm()) {
702 return false;
703 }
704
Diana Picus5a7203a2017-02-28 13:05:42 +0000705 break;
706 }
Diana Picus3b99c642017-02-24 14:01:27 +0000707 case G_STORE:
Diana Picus278c7222017-01-26 09:20:47 +0000708 case G_LOAD: {
Diana Picus1c33c9f2017-02-20 14:45:58 +0000709 const auto &MemOp = **I.memoperands_begin();
710 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
711 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
712 return false;
713 }
714
Diana Picus1540b062017-02-16 14:10:50 +0000715 unsigned Reg = I.getOperand(0).getReg();
716 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
717
718 LLT ValTy = MRI.getType(Reg);
Diana Picus278c7222017-01-26 09:20:47 +0000719 const auto ValSize = ValTy.getSizeInBits();
720
Diana Picus1540b062017-02-16 14:10:50 +0000721 assert((ValSize != 64 || TII.getSubtarget().hasVFP2()) &&
Diana Picus3b99c642017-02-24 14:01:27 +0000722 "Don't know how to load/store 64-bit value without VFP");
Diana Picus1540b062017-02-16 14:10:50 +0000723
Diana Picus3b99c642017-02-24 14:01:27 +0000724 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
725 if (NewOpc == G_LOAD || NewOpc == G_STORE)
Diana Picuse8368782017-02-17 13:44:19 +0000726 return false;
727
Diana Picus278c7222017-01-26 09:20:47 +0000728 I.setDesc(TII.get(NewOpc));
729
Diana Picus3b99c642017-02-24 14:01:27 +0000730 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
Diana Picus278c7222017-01-26 09:20:47 +0000731 // LDRH has a funny addressing mode (there's already a FIXME for it).
732 MIB.addReg(0);
Diana Picus4f8c3e12017-01-13 09:37:56 +0000733 MIB.addImm(0).add(predOps(ARMCC::AL));
Diana Picus519807f2016-12-19 11:26:31 +0000734 break;
Diana Picus278c7222017-01-26 09:20:47 +0000735 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000736 case G_MERGE_VALUES: {
737 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000738 return false;
739 break;
740 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000741 case G_UNMERGE_VALUES: {
742 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000743 return false;
744 break;
745 }
Diana Picus519807f2016-12-19 11:26:31 +0000746 default:
747 return false;
Diana Picus812caee2016-12-16 12:54:46 +0000748 }
749
Diana Picus519807f2016-12-19 11:26:31 +0000750 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
Diana Picus22274932016-11-11 08:27:37 +0000751}