blob: 8d952d21af636354ea2b201ef1a2e02c2441ace6 [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 Picus621894a2017-06-19 09:40:51 +000047 bool selectICmp(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII,
48 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
49 const RegisterBankInfo &RBI) const;
50
Diana Picus7145d222017-06-27 09:19:51 +000051 bool selectSelect(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII,
52 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
53 const RegisterBankInfo &RBI) const;
54
Diana Picus674888d2017-04-28 09:10:38 +000055 const ARMBaseInstrInfo &TII;
56 const ARMBaseRegisterInfo &TRI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000057 const ARMBaseTargetMachine &TM;
Diana Picus674888d2017-04-28 09:10:38 +000058 const ARMRegisterBankInfo &RBI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000059 const ARMSubtarget &STI;
60
61#define GET_GLOBALISEL_PREDICATES_DECL
62#include "ARMGenGlobalISel.inc"
63#undef GET_GLOBALISEL_PREDICATES_DECL
64
65// We declare the temporaries used by selectImpl() in the class to minimize the
66// cost of constructing placeholder values.
67#define GET_GLOBALISEL_TEMPORARIES_DECL
68#include "ARMGenGlobalISel.inc"
69#undef GET_GLOBALISEL_TEMPORARIES_DECL
Diana Picus674888d2017-04-28 09:10:38 +000070};
71} // end anonymous namespace
72
73namespace llvm {
74InstructionSelector *
Diana Picus8abcbbb2017-05-02 09:40:49 +000075createARMInstructionSelector(const ARMBaseTargetMachine &TM,
76 const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000077 const ARMRegisterBankInfo &RBI) {
Diana Picus8abcbbb2017-05-02 09:40:49 +000078 return new ARMInstructionSelector(TM, STI, RBI);
Diana Picus674888d2017-04-28 09:10:38 +000079}
80}
81
Diana Picus8abcbbb2017-05-02 09:40:49 +000082unsigned zero_reg = 0;
83
84#define GET_GLOBALISEL_IMPL
85#include "ARMGenGlobalISel.inc"
86#undef GET_GLOBALISEL_IMPL
87
88ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
89 const ARMSubtarget &STI,
Diana Picus22274932016-11-11 08:27:37 +000090 const ARMRegisterBankInfo &RBI)
Diana Picus895c6aa2016-11-15 16:42:10 +000091 : InstructionSelector(), TII(*STI.getInstrInfo()),
Diana Picus8abcbbb2017-05-02 09:40:49 +000092 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
93#define GET_GLOBALISEL_PREDICATES_INIT
94#include "ARMGenGlobalISel.inc"
95#undef GET_GLOBALISEL_PREDICATES_INIT
96#define GET_GLOBALISEL_TEMPORARIES_INIT
97#include "ARMGenGlobalISel.inc"
98#undef GET_GLOBALISEL_TEMPORARIES_INIT
99{
100}
Diana Picus22274932016-11-11 08:27:37 +0000101
Diana Picus812caee2016-12-16 12:54:46 +0000102static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
103 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
104 const RegisterBankInfo &RBI) {
105 unsigned DstReg = I.getOperand(0).getReg();
106 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
107 return true;
108
109 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
Benjamin Kramer24bf8682016-12-16 13:13:03 +0000110 (void)RegBank;
Diana Picus812caee2016-12-16 12:54:46 +0000111 assert(RegBank && "Can't get reg bank for virtual register");
112
Diana Picus36aa09f2016-12-19 14:07:50 +0000113 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Diana Picus4fa83c02017-02-08 13:23:04 +0000114 assert((RegBank->getID() == ARM::GPRRegBankID ||
115 RegBank->getID() == ARM::FPRRegBankID) &&
116 "Unsupported reg bank");
117
Diana Picus812caee2016-12-16 12:54:46 +0000118 const TargetRegisterClass *RC = &ARM::GPRRegClass;
119
Diana Picus4fa83c02017-02-08 13:23:04 +0000120 if (RegBank->getID() == ARM::FPRRegBankID) {
Diana Picus6beef3c2017-02-16 12:19:52 +0000121 if (DstSize == 32)
122 RC = &ARM::SPRRegClass;
123 else if (DstSize == 64)
124 RC = &ARM::DPRRegClass;
125 else
126 llvm_unreachable("Unsupported destination size");
Diana Picus4fa83c02017-02-08 13:23:04 +0000127 }
128
Diana Picus812caee2016-12-16 12:54:46 +0000129 // No need to constrain SrcReg. It will get constrained when
130 // we hit another of its uses or its defs.
131 // Copies do not have constraints.
132 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
133 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
134 << " operand\n");
135 return false;
136 }
137 return true;
138}
139
Diana Picus0b4190a2017-06-07 12:35:05 +0000140static bool selectMergeValues(MachineInstrBuilder &MIB,
141 const ARMBaseInstrInfo &TII,
142 MachineRegisterInfo &MRI,
143 const TargetRegisterInfo &TRI,
144 const RegisterBankInfo &RBI) {
145 assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000146
Diana Picus0b4190a2017-06-07 12:35:05 +0000147 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
Diana Picusb1701e02017-02-16 12:19:57 +0000148 // into one DPR.
149 unsigned VReg0 = MIB->getOperand(0).getReg();
150 (void)VReg0;
151 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
152 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000153 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000154 unsigned VReg1 = MIB->getOperand(1).getReg();
155 (void)VReg1;
156 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
157 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000158 "Unsupported operand for G_MERGE_VALUES");
159 unsigned VReg2 = MIB->getOperand(2).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000160 (void)VReg2;
161 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
162 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000163 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000164
165 MIB->setDesc(TII.get(ARM::VMOVDRR));
166 MIB.add(predOps(ARMCC::AL));
167
168 return true;
169}
170
Diana Picus0b4190a2017-06-07 12:35:05 +0000171static bool selectUnmergeValues(MachineInstrBuilder &MIB,
172 const ARMBaseInstrInfo &TII,
173 MachineRegisterInfo &MRI,
174 const TargetRegisterInfo &TRI,
175 const RegisterBankInfo &RBI) {
176 assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000177
Diana Picus0b4190a2017-06-07 12:35:05 +0000178 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
179 // GPRs.
Diana Picusb1701e02017-02-16 12:19:57 +0000180 unsigned VReg0 = MIB->getOperand(0).getReg();
181 (void)VReg0;
182 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
183 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000184 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000185 unsigned VReg1 = MIB->getOperand(1).getReg();
186 (void)VReg1;
Diana Picus0b4190a2017-06-07 12:35:05 +0000187 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
188 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
189 "Unsupported operand for G_UNMERGE_VALUES");
190 unsigned VReg2 = MIB->getOperand(2).getReg();
191 (void)VReg2;
192 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
193 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
194 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000195
Diana Picus0b4190a2017-06-07 12:35:05 +0000196 MIB->setDesc(TII.get(ARM::VMOVRRD));
Diana Picusb1701e02017-02-16 12:19:57 +0000197 MIB.add(predOps(ARMCC::AL));
198
199 return true;
200}
201
Diana Picus8b6c6be2017-01-25 08:10:40 +0000202/// Select the opcode for simple extensions (that translate to a single SXT/UXT
203/// instruction). Extension operations more complicated than that should not
Diana Picuse8368782017-02-17 13:44:19 +0000204/// invoke this. Returns the original opcode if it doesn't know how to select a
205/// better one.
Diana Picus8b6c6be2017-01-25 08:10:40 +0000206static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) {
207 using namespace TargetOpcode;
208
Diana Picuse8368782017-02-17 13:44:19 +0000209 if (Size != 8 && Size != 16)
210 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000211
212 if (Opc == G_SEXT)
213 return Size == 8 ? ARM::SXTB : ARM::SXTH;
214
215 if (Opc == G_ZEXT)
216 return Size == 8 ? ARM::UXTB : ARM::UXTH;
217
Diana Picuse8368782017-02-17 13:44:19 +0000218 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000219}
220
Diana Picus3b99c642017-02-24 14:01:27 +0000221/// Select the opcode for simple loads and stores. For types smaller than 32
222/// bits, the value will be zero extended. Returns the original opcode if it
223/// doesn't know how to select a better one.
224static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
225 unsigned Size) {
226 bool isStore = Opc == TargetOpcode::G_STORE;
227
Diana Picus1540b062017-02-16 14:10:50 +0000228 if (RegBank == ARM::GPRRegBankID) {
229 switch (Size) {
230 case 1:
231 case 8:
Diana Picus3b99c642017-02-24 14:01:27 +0000232 return isStore ? ARM::STRBi12 : ARM::LDRBi12;
Diana Picus1540b062017-02-16 14:10:50 +0000233 case 16:
Diana Picus3b99c642017-02-24 14:01:27 +0000234 return isStore ? ARM::STRH : ARM::LDRH;
Diana Picus1540b062017-02-16 14:10:50 +0000235 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000236 return isStore ? ARM::STRi12 : ARM::LDRi12;
Diana Picuse8368782017-02-17 13:44:19 +0000237 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000238 return Opc;
Diana Picus1540b062017-02-16 14:10:50 +0000239 }
Diana Picus1540b062017-02-16 14:10:50 +0000240 }
241
Diana Picuse8368782017-02-17 13:44:19 +0000242 if (RegBank == ARM::FPRRegBankID) {
243 switch (Size) {
244 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000245 return isStore ? ARM::VSTRS : ARM::VLDRS;
Diana Picuse8368782017-02-17 13:44:19 +0000246 case 64:
Diana Picus3b99c642017-02-24 14:01:27 +0000247 return isStore ? ARM::VSTRD : ARM::VLDRD;
Diana Picuse8368782017-02-17 13:44:19 +0000248 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000249 return Opc;
Diana Picuse8368782017-02-17 13:44:19 +0000250 }
Diana Picus278c7222017-01-26 09:20:47 +0000251 }
252
Diana Picus3b99c642017-02-24 14:01:27 +0000253 return Opc;
Diana Picus278c7222017-01-26 09:20:47 +0000254}
255
Diana Picus621894a2017-06-19 09:40:51 +0000256static ARMCC::CondCodes getComparePred(CmpInst::Predicate Pred) {
257 switch (Pred) {
258 // Needs two compares...
259 case CmpInst::FCMP_ONE:
260 case CmpInst::FCMP_UEQ:
261 default:
262 // AL is our "false" for now. The other two need more compares.
263 return ARMCC::AL;
264 case CmpInst::ICMP_EQ:
265 case CmpInst::FCMP_OEQ:
266 return ARMCC::EQ;
267 case CmpInst::ICMP_SGT:
268 case CmpInst::FCMP_OGT:
269 return ARMCC::GT;
270 case CmpInst::ICMP_SGE:
271 case CmpInst::FCMP_OGE:
272 return ARMCC::GE;
273 case CmpInst::ICMP_UGT:
274 case CmpInst::FCMP_UGT:
275 return ARMCC::HI;
276 case CmpInst::FCMP_OLT:
277 return ARMCC::MI;
278 case CmpInst::ICMP_ULE:
279 case CmpInst::FCMP_OLE:
280 return ARMCC::LS;
281 case CmpInst::FCMP_ORD:
282 return ARMCC::VC;
283 case CmpInst::FCMP_UNO:
284 return ARMCC::VS;
285 case CmpInst::FCMP_UGE:
286 return ARMCC::PL;
287 case CmpInst::ICMP_SLT:
288 case CmpInst::FCMP_ULT:
289 return ARMCC::LT;
290 case CmpInst::ICMP_SLE:
291 case CmpInst::FCMP_ULE:
292 return ARMCC::LE;
293 case CmpInst::FCMP_UNE:
294 case CmpInst::ICMP_NE:
295 return ARMCC::NE;
296 case CmpInst::ICMP_UGE:
297 return ARMCC::HS;
298 case CmpInst::ICMP_ULT:
299 return ARMCC::LO;
300 }
301}
302
303bool ARMInstructionSelector::selectICmp(MachineInstrBuilder &MIB,
304 const ARMBaseInstrInfo &TII,
305 MachineRegisterInfo &MRI,
306 const TargetRegisterInfo &TRI,
307 const RegisterBankInfo &RBI) const {
308 auto &MBB = *MIB->getParent();
309 auto InsertBefore = std::next(MIB->getIterator());
310 auto &DebugLoc = MIB->getDebugLoc();
311
312 // Move 0 into the result register.
313 auto Mov0I = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::MOVi))
314 .addDef(MRI.createVirtualRegister(&ARM::GPRRegClass))
315 .addImm(0)
316 .add(predOps(ARMCC::AL))
317 .add(condCodeOp());
318 if (!constrainSelectedInstRegOperands(*Mov0I, TII, TRI, RBI))
319 return false;
320
321 // Perform the comparison.
322 auto LHSReg = MIB->getOperand(2).getReg();
323 auto RHSReg = MIB->getOperand(3).getReg();
324 assert(MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
325 MRI.getType(LHSReg).getSizeInBits() == 32 &&
326 MRI.getType(RHSReg).getSizeInBits() == 32 &&
327 "Unsupported types for comparison operation");
328 auto CmpI = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::CMPrr))
329 .addUse(LHSReg)
330 .addUse(RHSReg)
331 .add(predOps(ARMCC::AL));
332 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
333 return false;
334
335 // Move 1 into the result register if the flags say so.
336 auto ResReg = MIB->getOperand(0).getReg();
337 auto Cond =
338 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
339 auto ARMCond = getComparePred(Cond);
340 if (ARMCond == ARMCC::AL)
341 return false;
342
343 auto Mov1I = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::MOVCCi))
344 .addDef(ResReg)
345 .addUse(Mov0I->getOperand(0).getReg())
346 .addImm(1)
347 .add(predOps(ARMCond, ARM::CPSR));
348 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
349 return false;
350
351 MIB->eraseFromParent();
352 return true;
353}
354
Diana Picus7145d222017-06-27 09:19:51 +0000355bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
356 const ARMBaseInstrInfo &TII,
357 MachineRegisterInfo &MRI,
358 const TargetRegisterInfo &TRI,
359 const RegisterBankInfo &RBI) const {
360 auto &MBB = *MIB->getParent();
361 auto InsertBefore = std::next(MIB->getIterator());
362 auto &DebugLoc = MIB->getDebugLoc();
363
364 // Compare the condition to 0.
365 auto CondReg = MIB->getOperand(1).getReg();
366 assert(MRI.getType(CondReg).getSizeInBits() == 1 &&
367 RBI.getRegBank(CondReg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
368 "Unsupported types for select operation");
369 auto CmpI = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::CMPri))
370 .addUse(CondReg)
371 .addImm(0)
372 .add(predOps(ARMCC::AL));
373 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
374 return false;
375
376 // Move a value into the result register based on the result of the
377 // comparison.
378 auto ResReg = MIB->getOperand(0).getReg();
379 auto TrueReg = MIB->getOperand(2).getReg();
380 auto FalseReg = MIB->getOperand(3).getReg();
381 assert(MRI.getType(ResReg) == MRI.getType(TrueReg) &&
382 MRI.getType(TrueReg) == MRI.getType(FalseReg) &&
383 MRI.getType(FalseReg).getSizeInBits() == 32 &&
384 RBI.getRegBank(TrueReg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
385 RBI.getRegBank(FalseReg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
386 "Unsupported types for select operation");
387 auto Mov1I = BuildMI(MBB, InsertBefore, DebugLoc, TII.get(ARM::MOVCCr))
388 .addDef(ResReg)
389 .addUse(TrueReg)
390 .addUse(FalseReg)
391 .add(predOps(ARMCC::EQ, ARM::CPSR));
392 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
393 return false;
394
395 MIB->eraseFromParent();
396 return true;
397}
398
Diana Picus812caee2016-12-16 12:54:46 +0000399bool ARMInstructionSelector::select(MachineInstr &I) const {
400 assert(I.getParent() && "Instruction should be in a basic block!");
401 assert(I.getParent()->getParent() && "Instruction should be in a function!");
402
403 auto &MBB = *I.getParent();
404 auto &MF = *MBB.getParent();
405 auto &MRI = MF.getRegInfo();
406
407 if (!isPreISelGenericOpcode(I.getOpcode())) {
408 if (I.isCopy())
409 return selectCopy(I, TII, MRI, TRI, RBI);
410
411 return true;
412 }
413
Diana Picus8abcbbb2017-05-02 09:40:49 +0000414 if (selectImpl(I))
415 return true;
416
Diana Picus519807f2016-12-19 11:26:31 +0000417 MachineInstrBuilder MIB{MF, I};
Diana Picusd83df5d2017-01-25 08:47:40 +0000418 bool isSExt = false;
Diana Picus519807f2016-12-19 11:26:31 +0000419
420 using namespace TargetOpcode;
421 switch (I.getOpcode()) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000422 case G_SEXT:
Diana Picusd83df5d2017-01-25 08:47:40 +0000423 isSExt = true;
424 LLVM_FALLTHROUGH;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000425 case G_ZEXT: {
426 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
427 // FIXME: Smaller destination sizes coming soon!
428 if (DstTy.getSizeInBits() != 32) {
429 DEBUG(dbgs() << "Unsupported destination size for extension");
430 return false;
431 }
432
433 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
434 unsigned SrcSize = SrcTy.getSizeInBits();
435 switch (SrcSize) {
Diana Picusd83df5d2017-01-25 08:47:40 +0000436 case 1: {
437 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
438 I.setDesc(TII.get(ARM::ANDri));
439 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
440
441 if (isSExt) {
442 unsigned SExtResult = I.getOperand(0).getReg();
443
444 // Use a new virtual register for the result of the AND
445 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
446 I.getOperand(0).setReg(AndResult);
447
448 auto InsertBefore = std::next(I.getIterator());
Martin Bohme8396e142017-01-25 14:28:19 +0000449 auto SubI =
Diana Picusd83df5d2017-01-25 08:47:40 +0000450 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri))
451 .addDef(SExtResult)
452 .addUse(AndResult)
453 .addImm(0)
454 .add(predOps(ARMCC::AL))
455 .add(condCodeOp());
456 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
457 return false;
458 }
459 break;
460 }
Diana Picus8b6c6be2017-01-25 08:10:40 +0000461 case 8:
462 case 16: {
463 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
Diana Picuse8368782017-02-17 13:44:19 +0000464 if (NewOpc == I.getOpcode())
465 return false;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000466 I.setDesc(TII.get(NewOpc));
467 MIB.addImm(0).add(predOps(ARMCC::AL));
468 break;
469 }
470 default:
471 DEBUG(dbgs() << "Unsupported source size for extension");
472 return false;
473 }
474 break;
475 }
Diana Picus657bfd32017-05-11 08:28:31 +0000476 case G_ANYEXT:
Diana Picus64a33432017-04-21 13:16:50 +0000477 case G_TRUNC: {
478 // The high bits are undefined, so there's nothing special to do, just
479 // treat it as a copy.
480 auto SrcReg = I.getOperand(1).getReg();
481 auto DstReg = I.getOperand(0).getReg();
482
483 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
484 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
485
486 if (SrcRegBank.getID() != DstRegBank.getID()) {
Diana Picus657bfd32017-05-11 08:28:31 +0000487 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
Diana Picus64a33432017-04-21 13:16:50 +0000488 return false;
489 }
490
491 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Diana Picus657bfd32017-05-11 08:28:31 +0000492 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
Diana Picus64a33432017-04-21 13:16:50 +0000493 return false;
494 }
495
496 I.setDesc(TII.get(COPY));
497 return selectCopy(I, TII, MRI, TRI, RBI);
498 }
Diana Picus621894a2017-06-19 09:40:51 +0000499 case G_ICMP:
500 return selectICmp(MIB, TII, MRI, TRI, RBI);
Diana Picus7145d222017-06-27 09:19:51 +0000501 case G_SELECT:
502 return selectSelect(MIB, TII, MRI, TRI, RBI);
Diana Picus9d070942017-02-28 10:14:38 +0000503 case G_GEP:
Diana Picus812caee2016-12-16 12:54:46 +0000504 I.setDesc(TII.get(ARM::ADDrr));
Diana Picus8a73f552017-01-13 10:18:01 +0000505 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000506 break;
507 case G_FRAME_INDEX:
508 // Add 0 to the given frame index and hope it will eventually be folded into
509 // the user(s).
510 I.setDesc(TII.get(ARM::ADDri));
Diana Picus8a73f552017-01-13 10:18:01 +0000511 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000512 break;
Diana Picus5a7203a2017-02-28 13:05:42 +0000513 case G_CONSTANT: {
514 unsigned Reg = I.getOperand(0).getReg();
515 if (MRI.getType(Reg).getSizeInBits() != 32)
516 return false;
517
518 assert(RBI.getRegBank(Reg, MRI, TRI)->getID() == ARM::GPRRegBankID &&
519 "Expected constant to live in a GPR");
520 I.setDesc(TII.get(ARM::MOVi));
521 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus95a8aa92017-04-24 06:30:56 +0000522
523 auto &Val = I.getOperand(1);
524 if (Val.isCImm()) {
525 if (Val.getCImm()->getBitWidth() > 32)
526 return false;
527 Val.ChangeToImmediate(Val.getCImm()->getZExtValue());
528 }
529
530 if (!Val.isImm()) {
531 return false;
532 }
533
Diana Picus5a7203a2017-02-28 13:05:42 +0000534 break;
535 }
Diana Picus3b99c642017-02-24 14:01:27 +0000536 case G_STORE:
Diana Picus278c7222017-01-26 09:20:47 +0000537 case G_LOAD: {
Diana Picus1c33c9f2017-02-20 14:45:58 +0000538 const auto &MemOp = **I.memoperands_begin();
539 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
540 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
541 return false;
542 }
543
Diana Picus1540b062017-02-16 14:10:50 +0000544 unsigned Reg = I.getOperand(0).getReg();
545 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
546
547 LLT ValTy = MRI.getType(Reg);
Diana Picus278c7222017-01-26 09:20:47 +0000548 const auto ValSize = ValTy.getSizeInBits();
549
Diana Picus1540b062017-02-16 14:10:50 +0000550 assert((ValSize != 64 || TII.getSubtarget().hasVFP2()) &&
Diana Picus3b99c642017-02-24 14:01:27 +0000551 "Don't know how to load/store 64-bit value without VFP");
Diana Picus1540b062017-02-16 14:10:50 +0000552
Diana Picus3b99c642017-02-24 14:01:27 +0000553 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
554 if (NewOpc == G_LOAD || NewOpc == G_STORE)
Diana Picuse8368782017-02-17 13:44:19 +0000555 return false;
556
Diana Picus278c7222017-01-26 09:20:47 +0000557 I.setDesc(TII.get(NewOpc));
558
Diana Picus3b99c642017-02-24 14:01:27 +0000559 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
Diana Picus278c7222017-01-26 09:20:47 +0000560 // LDRH has a funny addressing mode (there's already a FIXME for it).
561 MIB.addReg(0);
Diana Picus4f8c3e12017-01-13 09:37:56 +0000562 MIB.addImm(0).add(predOps(ARMCC::AL));
Diana Picus519807f2016-12-19 11:26:31 +0000563 break;
Diana Picus278c7222017-01-26 09:20:47 +0000564 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000565 case G_MERGE_VALUES: {
566 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000567 return false;
568 break;
569 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000570 case G_UNMERGE_VALUES: {
571 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000572 return false;
573 break;
574 }
Diana Picus519807f2016-12-19 11:26:31 +0000575 default:
576 return false;
Diana Picus812caee2016-12-16 12:54:46 +0000577 }
578
Diana Picus519807f2016-12-19 11:26:31 +0000579 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
Diana Picus22274932016-11-11 08:27:37 +0000580}