blob: faed6b867e2bc7d40d916d7e126238555dad70fd [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 Picus995746d2017-07-12 10:31:16 +000047 struct CmpConstants;
48 struct InsertInfo;
Diana Picus5b916532017-07-07 08:39:04 +000049
Diana Picus995746d2017-07-12 10:31:16 +000050 bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
51 MachineRegisterInfo &MRI) const;
Diana Picus621894a2017-06-19 09:40:51 +000052
Diana Picus995746d2017-07-12 10:31:16 +000053 // Helper for inserting a comparison sequence that sets \p ResReg to either 1
54 // if \p LHSReg and \p RHSReg are in the relationship defined by \p Cond, or
55 // \p PrevRes otherwise. In essence, it computes PrevRes OR (LHS Cond RHS).
56 bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
57 ARMCC::CondCodes Cond, unsigned LHSReg, unsigned RHSReg,
58 unsigned PrevRes) const;
59
60 // Set \p DestReg to \p Constant.
61 void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
62
63 bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
64
65 // Check if the types match and both operands have the expected size and
66 // register bank.
67 bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
68 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
69
70 // Check if the register has the expected size and register bank.
71 bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
72 unsigned ExpectedRegBankID) const;
Diana Picus7145d222017-06-27 09:19:51 +000073
Diana Picus674888d2017-04-28 09:10:38 +000074 const ARMBaseInstrInfo &TII;
75 const ARMBaseRegisterInfo &TRI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000076 const ARMBaseTargetMachine &TM;
Diana Picus674888d2017-04-28 09:10:38 +000077 const ARMRegisterBankInfo &RBI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000078 const ARMSubtarget &STI;
79
80#define GET_GLOBALISEL_PREDICATES_DECL
81#include "ARMGenGlobalISel.inc"
82#undef GET_GLOBALISEL_PREDICATES_DECL
83
84// We declare the temporaries used by selectImpl() in the class to minimize the
85// cost of constructing placeholder values.
86#define GET_GLOBALISEL_TEMPORARIES_DECL
87#include "ARMGenGlobalISel.inc"
88#undef GET_GLOBALISEL_TEMPORARIES_DECL
Diana Picus674888d2017-04-28 09:10:38 +000089};
90} // end anonymous namespace
91
92namespace llvm {
93InstructionSelector *
Diana Picus8abcbbb2017-05-02 09:40:49 +000094createARMInstructionSelector(const ARMBaseTargetMachine &TM,
95 const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000096 const ARMRegisterBankInfo &RBI) {
Diana Picus8abcbbb2017-05-02 09:40:49 +000097 return new ARMInstructionSelector(TM, STI, RBI);
Diana Picus674888d2017-04-28 09:10:38 +000098}
99}
100
Diana Picus8abcbbb2017-05-02 09:40:49 +0000101unsigned zero_reg = 0;
102
103#define GET_GLOBALISEL_IMPL
104#include "ARMGenGlobalISel.inc"
105#undef GET_GLOBALISEL_IMPL
106
107ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
108 const ARMSubtarget &STI,
Diana Picus22274932016-11-11 08:27:37 +0000109 const ARMRegisterBankInfo &RBI)
Diana Picus895c6aa2016-11-15 16:42:10 +0000110 : InstructionSelector(), TII(*STI.getInstrInfo()),
Diana Picus8abcbbb2017-05-02 09:40:49 +0000111 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
112#define GET_GLOBALISEL_PREDICATES_INIT
113#include "ARMGenGlobalISel.inc"
114#undef GET_GLOBALISEL_PREDICATES_INIT
115#define GET_GLOBALISEL_TEMPORARIES_INIT
116#include "ARMGenGlobalISel.inc"
117#undef GET_GLOBALISEL_TEMPORARIES_INIT
118{
119}
Diana Picus22274932016-11-11 08:27:37 +0000120
Diana Picus812caee2016-12-16 12:54:46 +0000121static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
122 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
123 const RegisterBankInfo &RBI) {
124 unsigned DstReg = I.getOperand(0).getReg();
125 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
126 return true;
127
128 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
Benjamin Kramer24bf8682016-12-16 13:13:03 +0000129 (void)RegBank;
Diana Picus812caee2016-12-16 12:54:46 +0000130 assert(RegBank && "Can't get reg bank for virtual register");
131
Diana Picus36aa09f2016-12-19 14:07:50 +0000132 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Diana Picus4fa83c02017-02-08 13:23:04 +0000133 assert((RegBank->getID() == ARM::GPRRegBankID ||
134 RegBank->getID() == ARM::FPRRegBankID) &&
135 "Unsupported reg bank");
136
Diana Picus812caee2016-12-16 12:54:46 +0000137 const TargetRegisterClass *RC = &ARM::GPRRegClass;
138
Diana Picus4fa83c02017-02-08 13:23:04 +0000139 if (RegBank->getID() == ARM::FPRRegBankID) {
Diana Picus6beef3c2017-02-16 12:19:52 +0000140 if (DstSize == 32)
141 RC = &ARM::SPRRegClass;
142 else if (DstSize == 64)
143 RC = &ARM::DPRRegClass;
144 else
145 llvm_unreachable("Unsupported destination size");
Diana Picus4fa83c02017-02-08 13:23:04 +0000146 }
147
Diana Picus812caee2016-12-16 12:54:46 +0000148 // No need to constrain SrcReg. It will get constrained when
149 // we hit another of its uses or its defs.
150 // Copies do not have constraints.
151 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
152 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
153 << " operand\n");
154 return false;
155 }
156 return true;
157}
158
Diana Picus0b4190a2017-06-07 12:35:05 +0000159static bool selectMergeValues(MachineInstrBuilder &MIB,
160 const ARMBaseInstrInfo &TII,
161 MachineRegisterInfo &MRI,
162 const TargetRegisterInfo &TRI,
163 const RegisterBankInfo &RBI) {
164 assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000165
Diana Picus0b4190a2017-06-07 12:35:05 +0000166 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
Diana Picusb1701e02017-02-16 12:19:57 +0000167 // into one DPR.
168 unsigned VReg0 = MIB->getOperand(0).getReg();
169 (void)VReg0;
170 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
171 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000172 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000173 unsigned VReg1 = MIB->getOperand(1).getReg();
174 (void)VReg1;
175 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
176 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000177 "Unsupported operand for G_MERGE_VALUES");
178 unsigned VReg2 = MIB->getOperand(2).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000179 (void)VReg2;
180 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
181 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000182 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000183
184 MIB->setDesc(TII.get(ARM::VMOVDRR));
185 MIB.add(predOps(ARMCC::AL));
186
187 return true;
188}
189
Diana Picus0b4190a2017-06-07 12:35:05 +0000190static bool selectUnmergeValues(MachineInstrBuilder &MIB,
191 const ARMBaseInstrInfo &TII,
192 MachineRegisterInfo &MRI,
193 const TargetRegisterInfo &TRI,
194 const RegisterBankInfo &RBI) {
195 assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000196
Diana Picus0b4190a2017-06-07 12:35:05 +0000197 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
198 // GPRs.
Diana Picusb1701e02017-02-16 12:19:57 +0000199 unsigned VReg0 = MIB->getOperand(0).getReg();
200 (void)VReg0;
201 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
202 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000203 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000204 unsigned VReg1 = MIB->getOperand(1).getReg();
205 (void)VReg1;
Diana Picus0b4190a2017-06-07 12:35:05 +0000206 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
207 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
208 "Unsupported operand for G_UNMERGE_VALUES");
209 unsigned VReg2 = MIB->getOperand(2).getReg();
210 (void)VReg2;
211 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
212 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
213 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000214
Diana Picus0b4190a2017-06-07 12:35:05 +0000215 MIB->setDesc(TII.get(ARM::VMOVRRD));
Diana Picusb1701e02017-02-16 12:19:57 +0000216 MIB.add(predOps(ARMCC::AL));
217
218 return true;
219}
220
Diana Picus8b6c6be2017-01-25 08:10:40 +0000221/// Select the opcode for simple extensions (that translate to a single SXT/UXT
222/// instruction). Extension operations more complicated than that should not
Diana Picuse8368782017-02-17 13:44:19 +0000223/// invoke this. Returns the original opcode if it doesn't know how to select a
224/// better one.
Diana Picus8b6c6be2017-01-25 08:10:40 +0000225static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) {
226 using namespace TargetOpcode;
227
Diana Picuse8368782017-02-17 13:44:19 +0000228 if (Size != 8 && Size != 16)
229 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000230
231 if (Opc == G_SEXT)
232 return Size == 8 ? ARM::SXTB : ARM::SXTH;
233
234 if (Opc == G_ZEXT)
235 return Size == 8 ? ARM::UXTB : ARM::UXTH;
236
Diana Picuse8368782017-02-17 13:44:19 +0000237 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000238}
239
Diana Picus3b99c642017-02-24 14:01:27 +0000240/// Select the opcode for simple loads and stores. For types smaller than 32
241/// bits, the value will be zero extended. Returns the original opcode if it
242/// doesn't know how to select a better one.
243static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
244 unsigned Size) {
245 bool isStore = Opc == TargetOpcode::G_STORE;
246
Diana Picus1540b062017-02-16 14:10:50 +0000247 if (RegBank == ARM::GPRRegBankID) {
248 switch (Size) {
249 case 1:
250 case 8:
Diana Picus3b99c642017-02-24 14:01:27 +0000251 return isStore ? ARM::STRBi12 : ARM::LDRBi12;
Diana Picus1540b062017-02-16 14:10:50 +0000252 case 16:
Diana Picus3b99c642017-02-24 14:01:27 +0000253 return isStore ? ARM::STRH : ARM::LDRH;
Diana Picus1540b062017-02-16 14:10:50 +0000254 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000255 return isStore ? ARM::STRi12 : ARM::LDRi12;
Diana Picuse8368782017-02-17 13:44:19 +0000256 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000257 return Opc;
Diana Picus1540b062017-02-16 14:10:50 +0000258 }
Diana Picus1540b062017-02-16 14:10:50 +0000259 }
260
Diana Picuse8368782017-02-17 13:44:19 +0000261 if (RegBank == ARM::FPRRegBankID) {
262 switch (Size) {
263 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000264 return isStore ? ARM::VSTRS : ARM::VLDRS;
Diana Picuse8368782017-02-17 13:44:19 +0000265 case 64:
Diana Picus3b99c642017-02-24 14:01:27 +0000266 return isStore ? ARM::VSTRD : ARM::VLDRD;
Diana Picuse8368782017-02-17 13:44:19 +0000267 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000268 return Opc;
Diana Picuse8368782017-02-17 13:44:19 +0000269 }
Diana Picus278c7222017-01-26 09:20:47 +0000270 }
271
Diana Picus3b99c642017-02-24 14:01:27 +0000272 return Opc;
Diana Picus278c7222017-01-26 09:20:47 +0000273}
274
Diana Picus5b916532017-07-07 08:39:04 +0000275// When lowering comparisons, we sometimes need to perform two compares instead
276// of just one. Get the condition codes for both comparisons. If only one is
277// needed, the second member of the pair is ARMCC::AL.
278static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
279getComparePreds(CmpInst::Predicate Pred) {
280 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
Diana Picus621894a2017-06-19 09:40:51 +0000281 switch (Pred) {
Diana Picus621894a2017-06-19 09:40:51 +0000282 case CmpInst::FCMP_ONE:
Diana Picus5b916532017-07-07 08:39:04 +0000283 Preds = {ARMCC::GT, ARMCC::MI};
284 break;
Diana Picus621894a2017-06-19 09:40:51 +0000285 case CmpInst::FCMP_UEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000286 Preds = {ARMCC::EQ, ARMCC::VS};
287 break;
Diana Picus621894a2017-06-19 09:40:51 +0000288 case CmpInst::ICMP_EQ:
289 case CmpInst::FCMP_OEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000290 Preds.first = ARMCC::EQ;
291 break;
Diana Picus621894a2017-06-19 09:40:51 +0000292 case CmpInst::ICMP_SGT:
293 case CmpInst::FCMP_OGT:
Diana Picus5b916532017-07-07 08:39:04 +0000294 Preds.first = ARMCC::GT;
295 break;
Diana Picus621894a2017-06-19 09:40:51 +0000296 case CmpInst::ICMP_SGE:
297 case CmpInst::FCMP_OGE:
Diana Picus5b916532017-07-07 08:39:04 +0000298 Preds.first = ARMCC::GE;
299 break;
Diana Picus621894a2017-06-19 09:40:51 +0000300 case CmpInst::ICMP_UGT:
301 case CmpInst::FCMP_UGT:
Diana Picus5b916532017-07-07 08:39:04 +0000302 Preds.first = ARMCC::HI;
303 break;
Diana Picus621894a2017-06-19 09:40:51 +0000304 case CmpInst::FCMP_OLT:
Diana Picus5b916532017-07-07 08:39:04 +0000305 Preds.first = ARMCC::MI;
306 break;
Diana Picus621894a2017-06-19 09:40:51 +0000307 case CmpInst::ICMP_ULE:
308 case CmpInst::FCMP_OLE:
Diana Picus5b916532017-07-07 08:39:04 +0000309 Preds.first = ARMCC::LS;
310 break;
Diana Picus621894a2017-06-19 09:40:51 +0000311 case CmpInst::FCMP_ORD:
Diana Picus5b916532017-07-07 08:39:04 +0000312 Preds.first = ARMCC::VC;
313 break;
Diana Picus621894a2017-06-19 09:40:51 +0000314 case CmpInst::FCMP_UNO:
Diana Picus5b916532017-07-07 08:39:04 +0000315 Preds.first = ARMCC::VS;
316 break;
Diana Picus621894a2017-06-19 09:40:51 +0000317 case CmpInst::FCMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000318 Preds.first = ARMCC::PL;
319 break;
Diana Picus621894a2017-06-19 09:40:51 +0000320 case CmpInst::ICMP_SLT:
321 case CmpInst::FCMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000322 Preds.first = ARMCC::LT;
323 break;
Diana Picus621894a2017-06-19 09:40:51 +0000324 case CmpInst::ICMP_SLE:
325 case CmpInst::FCMP_ULE:
Diana Picus5b916532017-07-07 08:39:04 +0000326 Preds.first = ARMCC::LE;
327 break;
Diana Picus621894a2017-06-19 09:40:51 +0000328 case CmpInst::FCMP_UNE:
329 case CmpInst::ICMP_NE:
Diana Picus5b916532017-07-07 08:39:04 +0000330 Preds.first = ARMCC::NE;
331 break;
Diana Picus621894a2017-06-19 09:40:51 +0000332 case CmpInst::ICMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000333 Preds.first = ARMCC::HS;
334 break;
Diana Picus621894a2017-06-19 09:40:51 +0000335 case CmpInst::ICMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000336 Preds.first = ARMCC::LO;
337 break;
338 default:
339 break;
Diana Picus621894a2017-06-19 09:40:51 +0000340 }
Diana Picus5b916532017-07-07 08:39:04 +0000341 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
342 return Preds;
Diana Picus621894a2017-06-19 09:40:51 +0000343}
344
Diana Picus995746d2017-07-12 10:31:16 +0000345struct ARMInstructionSelector::CmpConstants {
346 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned OpRegBank,
347 unsigned OpSize)
348 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
349 OperandRegBankID(OpRegBank), OperandSize(OpSize) {}
Diana Picus621894a2017-06-19 09:40:51 +0000350
Diana Picus5b916532017-07-07 08:39:04 +0000351 // The opcode used for performing the comparison.
Diana Picus995746d2017-07-12 10:31:16 +0000352 const unsigned ComparisonOpcode;
Diana Picus621894a2017-06-19 09:40:51 +0000353
Diana Picus5b916532017-07-07 08:39:04 +0000354 // The opcode used for reading the flags set by the comparison. May be
355 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
Diana Picus995746d2017-07-12 10:31:16 +0000356 const unsigned ReadFlagsOpcode;
Diana Picus5b916532017-07-07 08:39:04 +0000357
358 // The assumed register bank ID for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000359 const unsigned OperandRegBankID;
Diana Picus5b916532017-07-07 08:39:04 +0000360
Diana Picus21014df2017-07-12 09:01:54 +0000361 // The assumed size in bits for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000362 const unsigned OperandSize;
Diana Picus5b916532017-07-07 08:39:04 +0000363};
364
Diana Picus995746d2017-07-12 10:31:16 +0000365struct ARMInstructionSelector::InsertInfo {
366 InsertInfo(MachineInstrBuilder &MIB)
367 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
368 DbgLoc(MIB->getDebugLoc()) {}
Diana Picus5b916532017-07-07 08:39:04 +0000369
Diana Picus995746d2017-07-12 10:31:16 +0000370 MachineBasicBlock &MBB;
371 const MachineBasicBlock::instr_iterator InsertBefore;
372 const DebugLoc &DbgLoc;
373};
Diana Picus5b916532017-07-07 08:39:04 +0000374
Diana Picus995746d2017-07-12 10:31:16 +0000375void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
376 unsigned Constant) const {
377 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVi))
378 .addDef(DestReg)
379 .addImm(Constant)
380 .add(predOps(ARMCC::AL))
381 .add(condCodeOp());
382}
Diana Picus21014df2017-07-12 09:01:54 +0000383
Diana Picus995746d2017-07-12 10:31:16 +0000384bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
385 unsigned LHSReg, unsigned RHSReg,
386 unsigned ExpectedSize,
387 unsigned ExpectedRegBankID) const {
388 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
389 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
390 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
391}
Diana Picus5b916532017-07-07 08:39:04 +0000392
Diana Picus995746d2017-07-12 10:31:16 +0000393bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
394 unsigned ExpectedSize,
395 unsigned ExpectedRegBankID) const {
396 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
397 DEBUG(dbgs() << "Unexpected size for register");
398 return false;
399 }
400
401 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
402 DEBUG(dbgs() << "Unexpected register bank for register");
403 return false;
404 }
405
406 return true;
407}
408
409bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
410 MachineInstrBuilder &MIB,
411 MachineRegisterInfo &MRI) const {
412 const InsertInfo I(MIB);
Diana Picus5b916532017-07-07 08:39:04 +0000413
Diana Picus621894a2017-06-19 09:40:51 +0000414 auto ResReg = MIB->getOperand(0).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000415 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
Diana Picus5b916532017-07-07 08:39:04 +0000416 return false;
417
Diana Picus621894a2017-06-19 09:40:51 +0000418 auto Cond =
419 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
Diana Picus5b916532017-07-07 08:39:04 +0000420 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
Diana Picus995746d2017-07-12 10:31:16 +0000421 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
Diana Picus5b916532017-07-07 08:39:04 +0000422 MIB->eraseFromParent();
423 return true;
424 }
425
426 auto LHSReg = MIB->getOperand(2).getReg();
427 auto RHSReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000428 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
429 Helper.OperandRegBankID))
Diana Picus621894a2017-06-19 09:40:51 +0000430 return false;
431
Diana Picus5b916532017-07-07 08:39:04 +0000432 auto ARMConds = getComparePreds(Cond);
Diana Picus995746d2017-07-12 10:31:16 +0000433 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
434 putConstant(I, ZeroReg, 0);
Diana Picus5b916532017-07-07 08:39:04 +0000435
436 if (ARMConds.second == ARMCC::AL) {
437 // Simple case, we only need one comparison and we're done.
Diana Picus995746d2017-07-12 10:31:16 +0000438 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
439 ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000440 return false;
441 } else {
442 // Not so simple, we need two successive comparisons.
443 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picus995746d2017-07-12 10:31:16 +0000444 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
445 RHSReg, ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000446 return false;
Diana Picus995746d2017-07-12 10:31:16 +0000447 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
448 IntermediateRes))
Diana Picus5b916532017-07-07 08:39:04 +0000449 return false;
450 }
Diana Picus621894a2017-06-19 09:40:51 +0000451
452 MIB->eraseFromParent();
453 return true;
454}
455
Diana Picus995746d2017-07-12 10:31:16 +0000456bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
457 unsigned ResReg,
458 ARMCC::CondCodes Cond,
459 unsigned LHSReg, unsigned RHSReg,
460 unsigned PrevRes) const {
461 // Perform the comparison.
462 auto CmpI =
463 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
464 .addUse(LHSReg)
465 .addUse(RHSReg)
466 .add(predOps(ARMCC::AL));
467 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
468 return false;
469
470 // Read the comparison flags (if necessary).
471 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
472 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
473 TII.get(Helper.ReadFlagsOpcode))
474 .add(predOps(ARMCC::AL));
475 if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
476 return false;
477 }
478
479 // Select either 1 or the previous result based on the value of the flags.
480 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVCCi))
481 .addDef(ResReg)
482 .addUse(PrevRes)
483 .addImm(1)
484 .add(predOps(Cond, ARM::CPSR));
485 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
486 return false;
487
488 return true;
489}
490
Diana Picus7145d222017-06-27 09:19:51 +0000491bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
Diana Picus995746d2017-07-12 10:31:16 +0000492 MachineRegisterInfo &MRI) const {
Diana Picus7145d222017-06-27 09:19:51 +0000493 auto &MBB = *MIB->getParent();
494 auto InsertBefore = std::next(MIB->getIterator());
Diana Picus77367372017-07-07 08:53:27 +0000495 auto &DbgLoc = MIB->getDebugLoc();
Diana Picus7145d222017-06-27 09:19:51 +0000496
497 // Compare the condition to 0.
498 auto CondReg = MIB->getOperand(1).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000499 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000500 "Unsupported types for select operation");
Diana Picus77367372017-07-07 08:53:27 +0000501 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri))
Diana Picus7145d222017-06-27 09:19:51 +0000502 .addUse(CondReg)
503 .addImm(0)
504 .add(predOps(ARMCC::AL));
505 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
506 return false;
507
508 // Move a value into the result register based on the result of the
509 // comparison.
510 auto ResReg = MIB->getOperand(0).getReg();
511 auto TrueReg = MIB->getOperand(2).getReg();
512 auto FalseReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000513 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
514 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000515 "Unsupported types for select operation");
Diana Picus77367372017-07-07 08:53:27 +0000516 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr))
Diana Picus7145d222017-06-27 09:19:51 +0000517 .addDef(ResReg)
518 .addUse(TrueReg)
519 .addUse(FalseReg)
520 .add(predOps(ARMCC::EQ, ARM::CPSR));
521 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
522 return false;
523
524 MIB->eraseFromParent();
525 return true;
526}
527
Diana Picus812caee2016-12-16 12:54:46 +0000528bool ARMInstructionSelector::select(MachineInstr &I) const {
529 assert(I.getParent() && "Instruction should be in a basic block!");
530 assert(I.getParent()->getParent() && "Instruction should be in a function!");
531
532 auto &MBB = *I.getParent();
533 auto &MF = *MBB.getParent();
534 auto &MRI = MF.getRegInfo();
535
536 if (!isPreISelGenericOpcode(I.getOpcode())) {
537 if (I.isCopy())
538 return selectCopy(I, TII, MRI, TRI, RBI);
539
540 return true;
541 }
542
Diana Picus8abcbbb2017-05-02 09:40:49 +0000543 if (selectImpl(I))
544 return true;
545
Diana Picus519807f2016-12-19 11:26:31 +0000546 MachineInstrBuilder MIB{MF, I};
Diana Picusd83df5d2017-01-25 08:47:40 +0000547 bool isSExt = false;
Diana Picus519807f2016-12-19 11:26:31 +0000548
549 using namespace TargetOpcode;
550 switch (I.getOpcode()) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000551 case G_SEXT:
Diana Picusd83df5d2017-01-25 08:47:40 +0000552 isSExt = true;
553 LLVM_FALLTHROUGH;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000554 case G_ZEXT: {
555 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
556 // FIXME: Smaller destination sizes coming soon!
557 if (DstTy.getSizeInBits() != 32) {
558 DEBUG(dbgs() << "Unsupported destination size for extension");
559 return false;
560 }
561
562 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
563 unsigned SrcSize = SrcTy.getSizeInBits();
564 switch (SrcSize) {
Diana Picusd83df5d2017-01-25 08:47:40 +0000565 case 1: {
566 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
567 I.setDesc(TII.get(ARM::ANDri));
568 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
569
570 if (isSExt) {
571 unsigned SExtResult = I.getOperand(0).getReg();
572
573 // Use a new virtual register for the result of the AND
574 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
575 I.getOperand(0).setReg(AndResult);
576
577 auto InsertBefore = std::next(I.getIterator());
Martin Bohme8396e142017-01-25 14:28:19 +0000578 auto SubI =
Diana Picusd83df5d2017-01-25 08:47:40 +0000579 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri))
580 .addDef(SExtResult)
581 .addUse(AndResult)
582 .addImm(0)
583 .add(predOps(ARMCC::AL))
584 .add(condCodeOp());
585 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
586 return false;
587 }
588 break;
589 }
Diana Picus8b6c6be2017-01-25 08:10:40 +0000590 case 8:
591 case 16: {
592 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
Diana Picuse8368782017-02-17 13:44:19 +0000593 if (NewOpc == I.getOpcode())
594 return false;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000595 I.setDesc(TII.get(NewOpc));
596 MIB.addImm(0).add(predOps(ARMCC::AL));
597 break;
598 }
599 default:
600 DEBUG(dbgs() << "Unsupported source size for extension");
601 return false;
602 }
603 break;
604 }
Diana Picus657bfd32017-05-11 08:28:31 +0000605 case G_ANYEXT:
Diana Picus64a33432017-04-21 13:16:50 +0000606 case G_TRUNC: {
607 // The high bits are undefined, so there's nothing special to do, just
608 // treat it as a copy.
609 auto SrcReg = I.getOperand(1).getReg();
610 auto DstReg = I.getOperand(0).getReg();
611
612 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
613 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
614
615 if (SrcRegBank.getID() != DstRegBank.getID()) {
Diana Picus657bfd32017-05-11 08:28:31 +0000616 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
Diana Picus64a33432017-04-21 13:16:50 +0000617 return false;
618 }
619
620 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Diana Picus657bfd32017-05-11 08:28:31 +0000621 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
Diana Picus64a33432017-04-21 13:16:50 +0000622 return false;
623 }
624
625 I.setDesc(TII.get(COPY));
626 return selectCopy(I, TII, MRI, TRI, RBI);
627 }
Diana Picus7145d222017-06-27 09:19:51 +0000628 case G_SELECT:
Diana Picus995746d2017-07-12 10:31:16 +0000629 return selectSelect(MIB, MRI);
630 case G_ICMP: {
631 CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END,
632 ARM::GPRRegBankID, 32);
633 return selectCmp(Helper, MIB, MRI);
634 }
Diana Picus21014df2017-07-12 09:01:54 +0000635 case G_FCMP: {
Diana Picus5b916532017-07-07 08:39:04 +0000636 assert(TII.getSubtarget().hasVFP2() && "Can't select fcmp without VFP");
Diana Picus21014df2017-07-12 09:01:54 +0000637
638 unsigned OpReg = I.getOperand(2).getReg();
639 unsigned Size = MRI.getType(OpReg).getSizeInBits();
Diana Picus995746d2017-07-12 10:31:16 +0000640
641 if (Size == 64 && TII.getSubtarget().isFPOnlySP()) {
642 DEBUG(dbgs() << "Subtarget only supports single precision");
643 return false;
644 }
645 if (Size != 32 && Size != 64) {
646 DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
647 return false;
Diana Picus21014df2017-07-12 09:01:54 +0000648 }
649
Diana Picus995746d2017-07-12 10:31:16 +0000650 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
651 ARM::FPRRegBankID, Size);
652 return selectCmp(Helper, MIB, MRI);
Diana Picus21014df2017-07-12 09:01:54 +0000653 }
Diana Picus9d070942017-02-28 10:14:38 +0000654 case G_GEP:
Diana Picus812caee2016-12-16 12:54:46 +0000655 I.setDesc(TII.get(ARM::ADDrr));
Diana Picus8a73f552017-01-13 10:18:01 +0000656 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000657 break;
658 case G_FRAME_INDEX:
659 // Add 0 to the given frame index and hope it will eventually be folded into
660 // the user(s).
661 I.setDesc(TII.get(ARM::ADDri));
Diana Picus8a73f552017-01-13 10:18:01 +0000662 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000663 break;
Diana Picus5a7203a2017-02-28 13:05:42 +0000664 case G_CONSTANT: {
665 unsigned Reg = I.getOperand(0).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000666
667 if (!validReg(MRI, Reg, 32, ARM::GPRRegBankID))
Diana Picus5a7203a2017-02-28 13:05:42 +0000668 return false;
669
Diana Picus5a7203a2017-02-28 13:05:42 +0000670 I.setDesc(TII.get(ARM::MOVi));
671 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus95a8aa92017-04-24 06:30:56 +0000672
673 auto &Val = I.getOperand(1);
674 if (Val.isCImm()) {
675 if (Val.getCImm()->getBitWidth() > 32)
676 return false;
677 Val.ChangeToImmediate(Val.getCImm()->getZExtValue());
678 }
679
680 if (!Val.isImm()) {
681 return false;
682 }
683
Diana Picus5a7203a2017-02-28 13:05:42 +0000684 break;
685 }
Diana Picus3b99c642017-02-24 14:01:27 +0000686 case G_STORE:
Diana Picus278c7222017-01-26 09:20:47 +0000687 case G_LOAD: {
Diana Picus1c33c9f2017-02-20 14:45:58 +0000688 const auto &MemOp = **I.memoperands_begin();
689 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
690 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
691 return false;
692 }
693
Diana Picus1540b062017-02-16 14:10:50 +0000694 unsigned Reg = I.getOperand(0).getReg();
695 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
696
697 LLT ValTy = MRI.getType(Reg);
Diana Picus278c7222017-01-26 09:20:47 +0000698 const auto ValSize = ValTy.getSizeInBits();
699
Diana Picus1540b062017-02-16 14:10:50 +0000700 assert((ValSize != 64 || TII.getSubtarget().hasVFP2()) &&
Diana Picus3b99c642017-02-24 14:01:27 +0000701 "Don't know how to load/store 64-bit value without VFP");
Diana Picus1540b062017-02-16 14:10:50 +0000702
Diana Picus3b99c642017-02-24 14:01:27 +0000703 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
704 if (NewOpc == G_LOAD || NewOpc == G_STORE)
Diana Picuse8368782017-02-17 13:44:19 +0000705 return false;
706
Diana Picus278c7222017-01-26 09:20:47 +0000707 I.setDesc(TII.get(NewOpc));
708
Diana Picus3b99c642017-02-24 14:01:27 +0000709 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
Diana Picus278c7222017-01-26 09:20:47 +0000710 // LDRH has a funny addressing mode (there's already a FIXME for it).
711 MIB.addReg(0);
Diana Picus4f8c3e12017-01-13 09:37:56 +0000712 MIB.addImm(0).add(predOps(ARMCC::AL));
Diana Picus519807f2016-12-19 11:26:31 +0000713 break;
Diana Picus278c7222017-01-26 09:20:47 +0000714 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000715 case G_MERGE_VALUES: {
716 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000717 return false;
718 break;
719 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000720 case G_UNMERGE_VALUES: {
721 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000722 return false;
723 break;
724 }
Diana Picus87a70672017-07-14 09:46:06 +0000725 case G_BRCOND: {
726 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
727 DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
728 return false;
729 }
730
731 // Set the flags.
732 auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri))
733 .addReg(I.getOperand(0).getReg())
734 .addImm(1)
735 .add(predOps(ARMCC::AL));
736 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
737 return false;
738
739 // Branch conditionally.
740 auto Branch = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::Bcc))
741 .add(I.getOperand(1))
742 .add(predOps(ARMCC::EQ, ARM::CPSR));
743 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
744 return false;
745 I.eraseFromParent();
746 return true;
747 }
Diana Picus519807f2016-12-19 11:26:31 +0000748 default:
749 return false;
Diana Picus812caee2016-12-16 12:54:46 +0000750 }
751
Diana Picus519807f2016-12-19 11:26:31 +0000752 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
Diana Picus22274932016-11-11 08:27:37 +0000753}