blob: c7bead914b6cf3f0cf5b26a0aa152ba18c317c95 [file] [log] [blame]
Diana Picus22274932016-11-11 08:27:37 +00001//===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Diana Picus22274932016-11-11 08:27:37 +00006//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements the targeting of the InstructionSelector class for ARM.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
Diana Picus22274932016-11-11 08:27:37 +000013#include "ARMRegisterBankInfo.h"
14#include "ARMSubtarget.h"
15#include "ARMTargetMachine.h"
Diana Picus674888d2017-04-28 09:10:38 +000016#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
David Blaikie62651302017-10-26 23:39:54 +000017#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
Diana Picus930e6ec2017-08-03 09:14:59 +000018#include "llvm/CodeGen/MachineConstantPool.h"
Diana Picus812caee2016-12-16 12:54:46 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
Diana Picus22274932016-11-11 08:27:37 +000020#include "llvm/Support/Debug.h"
21
22#define DEBUG_TYPE "arm-isel"
23
24using namespace llvm;
25
Diana Picus674888d2017-04-28 09:10:38 +000026namespace {
Diana Picus8abcbbb2017-05-02 09:40:49 +000027
28#define GET_GLOBALISEL_PREDICATE_BITSET
29#include "ARMGenGlobalISel.inc"
30#undef GET_GLOBALISEL_PREDICATE_BITSET
31
Diana Picus674888d2017-04-28 09:10:38 +000032class ARMInstructionSelector : public InstructionSelector {
33public:
Diana Picus8abcbbb2017-05-02 09:40:49 +000034 ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000035 const ARMRegisterBankInfo &RBI);
36
Daniel Sandersf76f3152017-11-16 00:46:35 +000037 bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
David Blaikie62651302017-10-26 23:39:54 +000038 static const char *getName() { return DEBUG_TYPE; }
Diana Picus674888d2017-04-28 09:10:38 +000039
40private:
Daniel Sandersf76f3152017-11-16 00:46:35 +000041 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
Diana Picus8abcbbb2017-05-02 09:40:49 +000042
Diana Picus995746d2017-07-12 10:31:16 +000043 struct CmpConstants;
44 struct InsertInfo;
Diana Picus5b916532017-07-07 08:39:04 +000045
Diana Picus995746d2017-07-12 10:31:16 +000046 bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
47 MachineRegisterInfo &MRI) const;
Diana Picus621894a2017-06-19 09:40:51 +000048
Diana Picus995746d2017-07-12 10:31:16 +000049 // Helper for inserting a comparison sequence that sets \p ResReg to either 1
50 // if \p LHSReg and \p RHSReg are in the relationship defined by \p Cond, or
51 // \p PrevRes otherwise. In essence, it computes PrevRes OR (LHS Cond RHS).
52 bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
53 ARMCC::CondCodes Cond, unsigned LHSReg, unsigned RHSReg,
54 unsigned PrevRes) const;
55
56 // Set \p DestReg to \p Constant.
57 void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
58
Diana Picus930e6ec2017-08-03 09:14:59 +000059 bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
Diana Picus995746d2017-07-12 10:31:16 +000060 bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
Diana Picuse393bc72017-10-06 15:39:16 +000061 bool selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const;
Diana Picus995746d2017-07-12 10:31:16 +000062
63 // Check if the types match and both operands have the expected size and
64 // register bank.
65 bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
66 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
67
68 // Check if the register has the expected size and register bank.
69 bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
70 unsigned ExpectedRegBankID) const;
Diana Picus7145d222017-06-27 09:19:51 +000071
Diana Picus674888d2017-04-28 09:10:38 +000072 const ARMBaseInstrInfo &TII;
73 const ARMBaseRegisterInfo &TRI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000074 const ARMBaseTargetMachine &TM;
Diana Picus674888d2017-04-28 09:10:38 +000075 const ARMRegisterBankInfo &RBI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000076 const ARMSubtarget &STI;
77
Diana Picuscf0ff632019-02-28 11:13:05 +000078 // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
79 // uses "STI." in the code generated by TableGen. If we want to reuse some of
80 // the custom C++ predicates written for DAGISel, we need to have both around.
81 const ARMSubtarget *Subtarget = &STI;
82
Diana Picus813af0d2018-12-14 12:37:24 +000083 // Store the opcodes that we might need, so we don't have to check what kind
84 // of subtarget (ARM vs Thumb) we have all the time.
85 struct OpcodeCache {
86 unsigned ZEXT16;
87 unsigned SEXT16;
88
89 unsigned ZEXT8;
90 unsigned SEXT8;
91
92 // Used for implementing ZEXT/SEXT from i1
93 unsigned AND;
94 unsigned RSB;
95
96 unsigned STORE32;
97 unsigned LOAD32;
98
99 unsigned STORE16;
100 unsigned LOAD16;
101
102 unsigned STORE8;
103 unsigned LOAD8;
104
Diana Picusc0f964eb2019-02-15 10:50:02 +0000105 unsigned ADDrr;
Diana Picusdcaa9392019-02-21 13:00:02 +0000106 unsigned ADDri;
Diana Picusc0f964eb2019-02-15 10:50:02 +0000107
Diana Picusaa4118a2019-02-13 11:25:32 +0000108 // Used for G_ICMP
Diana Picus75a04e22019-02-07 11:05:33 +0000109 unsigned CMPrr;
110 unsigned MOVi;
111 unsigned MOVCCi;
112
Diana Picusaa4118a2019-02-13 11:25:32 +0000113 // Used for G_SELECT
Diana Picusaa4118a2019-02-13 11:25:32 +0000114 unsigned MOVCCr;
115
Diana Picusa00425f2019-02-15 10:24:03 +0000116 unsigned TSTri;
117 unsigned Bcc;
118
Diana Picus3b7beaf2019-02-28 10:42:47 +0000119 // Used for G_GLOBAL_VALUE
120 unsigned MOVi32imm;
121 unsigned ConstPoolLoad;
122 unsigned MOV_ga_pcrel;
123 unsigned LDRLIT_ga_pcrel;
124 unsigned LDRLIT_ga_abs;
125
Diana Picus813af0d2018-12-14 12:37:24 +0000126 OpcodeCache(const ARMSubtarget &STI);
127 } const Opcodes;
128
129 // Select the opcode for simple extensions (that translate to a single SXT/UXT
130 // instruction). Extension operations more complicated than that should not
131 // invoke this. Returns the original opcode if it doesn't know how to select a
132 // better one.
133 unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) const;
134
135 // Select the opcode for simple loads and stores. Returns the original opcode
136 // if it doesn't know how to select a better one.
137 unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
138 unsigned Size) const;
139
Diana Picusb6e83b92019-04-10 09:14:32 +0000140 void renderVFPF32Imm(MachineInstrBuilder &New, const MachineInstr &Old) const;
141 void renderVFPF64Imm(MachineInstrBuilder &New, const MachineInstr &Old) const;
142
Diana Picus8abcbbb2017-05-02 09:40:49 +0000143#define GET_GLOBALISEL_PREDICATES_DECL
144#include "ARMGenGlobalISel.inc"
145#undef GET_GLOBALISEL_PREDICATES_DECL
146
147// We declare the temporaries used by selectImpl() in the class to minimize the
148// cost of constructing placeholder values.
149#define GET_GLOBALISEL_TEMPORARIES_DECL
150#include "ARMGenGlobalISel.inc"
151#undef GET_GLOBALISEL_TEMPORARIES_DECL
Diana Picus674888d2017-04-28 09:10:38 +0000152};
153} // end anonymous namespace
154
155namespace llvm {
156InstructionSelector *
Diana Picus8abcbbb2017-05-02 09:40:49 +0000157createARMInstructionSelector(const ARMBaseTargetMachine &TM,
158 const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +0000159 const ARMRegisterBankInfo &RBI) {
Diana Picus8abcbbb2017-05-02 09:40:49 +0000160 return new ARMInstructionSelector(TM, STI, RBI);
Diana Picus674888d2017-04-28 09:10:38 +0000161}
162}
163
Daniel Sanders8e82af22017-07-27 11:03:45 +0000164const unsigned zero_reg = 0;
Diana Picus8abcbbb2017-05-02 09:40:49 +0000165
166#define GET_GLOBALISEL_IMPL
167#include "ARMGenGlobalISel.inc"
168#undef GET_GLOBALISEL_IMPL
169
170ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
171 const ARMSubtarget &STI,
Diana Picus22274932016-11-11 08:27:37 +0000172 const ARMRegisterBankInfo &RBI)
Diana Picus895c6aa2016-11-15 16:42:10 +0000173 : InstructionSelector(), TII(*STI.getInstrInfo()),
Diana Picus813af0d2018-12-14 12:37:24 +0000174 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI), Opcodes(STI),
Diana Picus8abcbbb2017-05-02 09:40:49 +0000175#define GET_GLOBALISEL_PREDICATES_INIT
176#include "ARMGenGlobalISel.inc"
177#undef GET_GLOBALISEL_PREDICATES_INIT
178#define GET_GLOBALISEL_TEMPORARIES_INIT
179#include "ARMGenGlobalISel.inc"
180#undef GET_GLOBALISEL_TEMPORARIES_INIT
181{
182}
Diana Picus22274932016-11-11 08:27:37 +0000183
Diana Picus865f7fe2018-01-04 13:09:25 +0000184static const TargetRegisterClass *guessRegClass(unsigned Reg,
185 MachineRegisterInfo &MRI,
186 const TargetRegisterInfo &TRI,
187 const RegisterBankInfo &RBI) {
188 const RegisterBank *RegBank = RBI.getRegBank(Reg, MRI, TRI);
189 assert(RegBank && "Can't get reg bank for virtual register");
190
191 const unsigned Size = MRI.getType(Reg).getSizeInBits();
192 assert((RegBank->getID() == ARM::GPRRegBankID ||
193 RegBank->getID() == ARM::FPRRegBankID) &&
194 "Unsupported reg bank");
195
196 if (RegBank->getID() == ARM::FPRRegBankID) {
197 if (Size == 32)
198 return &ARM::SPRRegClass;
199 else if (Size == 64)
200 return &ARM::DPRRegClass;
Roman Tereshine79d6562018-05-23 02:59:31 +0000201 else if (Size == 128)
202 return &ARM::QPRRegClass;
Diana Picus865f7fe2018-01-04 13:09:25 +0000203 else
204 llvm_unreachable("Unsupported destination size");
205 }
206
207 return &ARM::GPRRegClass;
208}
209
Diana Picus812caee2016-12-16 12:54:46 +0000210static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
211 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
212 const RegisterBankInfo &RBI) {
213 unsigned DstReg = I.getOperand(0).getReg();
214 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
215 return true;
216
Diana Picus865f7fe2018-01-04 13:09:25 +0000217 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
Diana Picus4fa83c02017-02-08 13:23:04 +0000218
Diana Picus812caee2016-12-16 12:54:46 +0000219 // No need to constrain SrcReg. It will get constrained when
220 // we hit another of its uses or its defs.
221 // Copies do not have constraints.
222 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000223 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
224 << " operand\n");
Diana Picus812caee2016-12-16 12:54:46 +0000225 return false;
226 }
227 return true;
228}
229
Diana Picus0b4190a2017-06-07 12:35:05 +0000230static bool selectMergeValues(MachineInstrBuilder &MIB,
231 const ARMBaseInstrInfo &TII,
232 MachineRegisterInfo &MRI,
233 const TargetRegisterInfo &TRI,
234 const RegisterBankInfo &RBI) {
235 assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000236
Diana Picus0b4190a2017-06-07 12:35:05 +0000237 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
Diana Picusb1701e02017-02-16 12:19:57 +0000238 // into one DPR.
239 unsigned VReg0 = MIB->getOperand(0).getReg();
240 (void)VReg0;
241 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
242 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000243 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000244 unsigned VReg1 = MIB->getOperand(1).getReg();
245 (void)VReg1;
246 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
247 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000248 "Unsupported operand for G_MERGE_VALUES");
249 unsigned VReg2 = MIB->getOperand(2).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000250 (void)VReg2;
251 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
252 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000253 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000254
255 MIB->setDesc(TII.get(ARM::VMOVDRR));
256 MIB.add(predOps(ARMCC::AL));
257
258 return true;
259}
260
Diana Picus0b4190a2017-06-07 12:35:05 +0000261static bool selectUnmergeValues(MachineInstrBuilder &MIB,
262 const ARMBaseInstrInfo &TII,
263 MachineRegisterInfo &MRI,
264 const TargetRegisterInfo &TRI,
265 const RegisterBankInfo &RBI) {
266 assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000267
Diana Picus0b4190a2017-06-07 12:35:05 +0000268 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
269 // GPRs.
Diana Picusb1701e02017-02-16 12:19:57 +0000270 unsigned VReg0 = MIB->getOperand(0).getReg();
271 (void)VReg0;
272 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
273 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000274 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000275 unsigned VReg1 = MIB->getOperand(1).getReg();
276 (void)VReg1;
Diana Picus0b4190a2017-06-07 12:35:05 +0000277 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
278 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
279 "Unsupported operand for G_UNMERGE_VALUES");
280 unsigned VReg2 = MIB->getOperand(2).getReg();
281 (void)VReg2;
282 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
283 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
284 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000285
Diana Picus0b4190a2017-06-07 12:35:05 +0000286 MIB->setDesc(TII.get(ARM::VMOVRRD));
Diana Picusb1701e02017-02-16 12:19:57 +0000287 MIB.add(predOps(ARMCC::AL));
288
289 return true;
290}
291
Diana Picus813af0d2018-12-14 12:37:24 +0000292ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {
293 bool isThumb = STI.isThumb();
294
295 using namespace TargetOpcode;
296
297#define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC
298 STORE_OPCODE(SEXT16, SXTH);
299 STORE_OPCODE(ZEXT16, UXTH);
300
301 STORE_OPCODE(SEXT8, SXTB);
302 STORE_OPCODE(ZEXT8, UXTB);
303
304 STORE_OPCODE(AND, ANDri);
305 STORE_OPCODE(RSB, RSBri);
306
307 STORE_OPCODE(STORE32, STRi12);
308 STORE_OPCODE(LOAD32, LDRi12);
309
310 // LDRH/STRH are special...
311 STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
312 LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
313
314 STORE_OPCODE(STORE8, STRBi12);
315 STORE_OPCODE(LOAD8, LDRBi12);
Diana Picus75a04e22019-02-07 11:05:33 +0000316
Diana Picusc0f964eb2019-02-15 10:50:02 +0000317 STORE_OPCODE(ADDrr, ADDrr);
Diana Picusdcaa9392019-02-21 13:00:02 +0000318 STORE_OPCODE(ADDri, ADDri);
Diana Picusc0f964eb2019-02-15 10:50:02 +0000319
Diana Picus75a04e22019-02-07 11:05:33 +0000320 STORE_OPCODE(CMPrr, CMPrr);
321 STORE_OPCODE(MOVi, MOVi);
322 STORE_OPCODE(MOVCCi, MOVCCi);
Diana Picusaa4118a2019-02-13 11:25:32 +0000323
Diana Picusaa4118a2019-02-13 11:25:32 +0000324 STORE_OPCODE(MOVCCr, MOVCCr);
Diana Picusa00425f2019-02-15 10:24:03 +0000325
326 STORE_OPCODE(TSTri, TSTri);
327 STORE_OPCODE(Bcc, Bcc);
Diana Picus3b7beaf2019-02-28 10:42:47 +0000328
329 STORE_OPCODE(MOVi32imm, MOVi32imm);
330 ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;
331 STORE_OPCODE(MOV_ga_pcrel, MOV_ga_pcrel);
332 LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;
333 LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;
Diana Picus813af0d2018-12-14 12:37:24 +0000334#undef MAP_OPCODE
335}
336
337unsigned ARMInstructionSelector::selectSimpleExtOpc(unsigned Opc,
338 unsigned Size) const {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000339 using namespace TargetOpcode;
340
Diana Picuse8368782017-02-17 13:44:19 +0000341 if (Size != 8 && Size != 16)
342 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000343
344 if (Opc == G_SEXT)
Diana Picus813af0d2018-12-14 12:37:24 +0000345 return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000346
347 if (Opc == G_ZEXT)
Diana Picus813af0d2018-12-14 12:37:24 +0000348 return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000349
Diana Picuse8368782017-02-17 13:44:19 +0000350 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000351}
352
Diana Picus813af0d2018-12-14 12:37:24 +0000353unsigned ARMInstructionSelector::selectLoadStoreOpCode(unsigned Opc,
354 unsigned RegBank,
355 unsigned Size) const {
Diana Picus3b99c642017-02-24 14:01:27 +0000356 bool isStore = Opc == TargetOpcode::G_STORE;
357
Diana Picus1540b062017-02-16 14:10:50 +0000358 if (RegBank == ARM::GPRRegBankID) {
359 switch (Size) {
360 case 1:
361 case 8:
Diana Picus813af0d2018-12-14 12:37:24 +0000362 return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
Diana Picus1540b062017-02-16 14:10:50 +0000363 case 16:
Diana Picus813af0d2018-12-14 12:37:24 +0000364 return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
Diana Picus1540b062017-02-16 14:10:50 +0000365 case 32:
Diana Picus813af0d2018-12-14 12:37:24 +0000366 return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
Diana Picuse8368782017-02-17 13:44:19 +0000367 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000368 return Opc;
Diana Picus1540b062017-02-16 14:10:50 +0000369 }
Diana Picus1540b062017-02-16 14:10:50 +0000370 }
371
Diana Picuse8368782017-02-17 13:44:19 +0000372 if (RegBank == ARM::FPRRegBankID) {
373 switch (Size) {
374 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000375 return isStore ? ARM::VSTRS : ARM::VLDRS;
Diana Picuse8368782017-02-17 13:44:19 +0000376 case 64:
Diana Picus3b99c642017-02-24 14:01:27 +0000377 return isStore ? ARM::VSTRD : ARM::VLDRD;
Diana Picuse8368782017-02-17 13:44:19 +0000378 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000379 return Opc;
Diana Picuse8368782017-02-17 13:44:19 +0000380 }
Diana Picus278c7222017-01-26 09:20:47 +0000381 }
382
Diana Picus3b99c642017-02-24 14:01:27 +0000383 return Opc;
Diana Picus278c7222017-01-26 09:20:47 +0000384}
385
Diana Picus5b916532017-07-07 08:39:04 +0000386// When lowering comparisons, we sometimes need to perform two compares instead
387// of just one. Get the condition codes for both comparisons. If only one is
388// needed, the second member of the pair is ARMCC::AL.
389static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
390getComparePreds(CmpInst::Predicate Pred) {
391 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
Diana Picus621894a2017-06-19 09:40:51 +0000392 switch (Pred) {
Diana Picus621894a2017-06-19 09:40:51 +0000393 case CmpInst::FCMP_ONE:
Diana Picus5b916532017-07-07 08:39:04 +0000394 Preds = {ARMCC::GT, ARMCC::MI};
395 break;
Diana Picus621894a2017-06-19 09:40:51 +0000396 case CmpInst::FCMP_UEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000397 Preds = {ARMCC::EQ, ARMCC::VS};
398 break;
Diana Picus621894a2017-06-19 09:40:51 +0000399 case CmpInst::ICMP_EQ:
400 case CmpInst::FCMP_OEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000401 Preds.first = ARMCC::EQ;
402 break;
Diana Picus621894a2017-06-19 09:40:51 +0000403 case CmpInst::ICMP_SGT:
404 case CmpInst::FCMP_OGT:
Diana Picus5b916532017-07-07 08:39:04 +0000405 Preds.first = ARMCC::GT;
406 break;
Diana Picus621894a2017-06-19 09:40:51 +0000407 case CmpInst::ICMP_SGE:
408 case CmpInst::FCMP_OGE:
Diana Picus5b916532017-07-07 08:39:04 +0000409 Preds.first = ARMCC::GE;
410 break;
Diana Picus621894a2017-06-19 09:40:51 +0000411 case CmpInst::ICMP_UGT:
412 case CmpInst::FCMP_UGT:
Diana Picus5b916532017-07-07 08:39:04 +0000413 Preds.first = ARMCC::HI;
414 break;
Diana Picus621894a2017-06-19 09:40:51 +0000415 case CmpInst::FCMP_OLT:
Diana Picus5b916532017-07-07 08:39:04 +0000416 Preds.first = ARMCC::MI;
417 break;
Diana Picus621894a2017-06-19 09:40:51 +0000418 case CmpInst::ICMP_ULE:
419 case CmpInst::FCMP_OLE:
Diana Picus5b916532017-07-07 08:39:04 +0000420 Preds.first = ARMCC::LS;
421 break;
Diana Picus621894a2017-06-19 09:40:51 +0000422 case CmpInst::FCMP_ORD:
Diana Picus5b916532017-07-07 08:39:04 +0000423 Preds.first = ARMCC::VC;
424 break;
Diana Picus621894a2017-06-19 09:40:51 +0000425 case CmpInst::FCMP_UNO:
Diana Picus5b916532017-07-07 08:39:04 +0000426 Preds.first = ARMCC::VS;
427 break;
Diana Picus621894a2017-06-19 09:40:51 +0000428 case CmpInst::FCMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000429 Preds.first = ARMCC::PL;
430 break;
Diana Picus621894a2017-06-19 09:40:51 +0000431 case CmpInst::ICMP_SLT:
432 case CmpInst::FCMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000433 Preds.first = ARMCC::LT;
434 break;
Diana Picus621894a2017-06-19 09:40:51 +0000435 case CmpInst::ICMP_SLE:
436 case CmpInst::FCMP_ULE:
Diana Picus5b916532017-07-07 08:39:04 +0000437 Preds.first = ARMCC::LE;
438 break;
Diana Picus621894a2017-06-19 09:40:51 +0000439 case CmpInst::FCMP_UNE:
440 case CmpInst::ICMP_NE:
Diana Picus5b916532017-07-07 08:39:04 +0000441 Preds.first = ARMCC::NE;
442 break;
Diana Picus621894a2017-06-19 09:40:51 +0000443 case CmpInst::ICMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000444 Preds.first = ARMCC::HS;
445 break;
Diana Picus621894a2017-06-19 09:40:51 +0000446 case CmpInst::ICMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000447 Preds.first = ARMCC::LO;
448 break;
449 default:
450 break;
Diana Picus621894a2017-06-19 09:40:51 +0000451 }
Diana Picus5b916532017-07-07 08:39:04 +0000452 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
453 return Preds;
Diana Picus621894a2017-06-19 09:40:51 +0000454}
455
Diana Picus995746d2017-07-12 10:31:16 +0000456struct ARMInstructionSelector::CmpConstants {
Diana Picus75a04e22019-02-07 11:05:33 +0000457 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,
458 unsigned OpRegBank, unsigned OpSize)
Diana Picus995746d2017-07-12 10:31:16 +0000459 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
Diana Picus75a04e22019-02-07 11:05:33 +0000460 SelectResultOpcode(SelectOpcode), OperandRegBankID(OpRegBank),
461 OperandSize(OpSize) {}
Diana Picus621894a2017-06-19 09:40:51 +0000462
Diana Picus5b916532017-07-07 08:39:04 +0000463 // The opcode used for performing the comparison.
Diana Picus995746d2017-07-12 10:31:16 +0000464 const unsigned ComparisonOpcode;
Diana Picus621894a2017-06-19 09:40:51 +0000465
Diana Picus5b916532017-07-07 08:39:04 +0000466 // The opcode used for reading the flags set by the comparison. May be
467 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
Diana Picus995746d2017-07-12 10:31:16 +0000468 const unsigned ReadFlagsOpcode;
Diana Picus5b916532017-07-07 08:39:04 +0000469
Diana Picus75a04e22019-02-07 11:05:33 +0000470 // The opcode used for materializing the result of the comparison.
471 const unsigned SelectResultOpcode;
472
Diana Picus5b916532017-07-07 08:39:04 +0000473 // The assumed register bank ID for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000474 const unsigned OperandRegBankID;
Diana Picus5b916532017-07-07 08:39:04 +0000475
Diana Picus21014df2017-07-12 09:01:54 +0000476 // The assumed size in bits for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000477 const unsigned OperandSize;
Diana Picus5b916532017-07-07 08:39:04 +0000478};
479
Diana Picus995746d2017-07-12 10:31:16 +0000480struct ARMInstructionSelector::InsertInfo {
481 InsertInfo(MachineInstrBuilder &MIB)
482 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
483 DbgLoc(MIB->getDebugLoc()) {}
Diana Picus5b916532017-07-07 08:39:04 +0000484
Diana Picus995746d2017-07-12 10:31:16 +0000485 MachineBasicBlock &MBB;
486 const MachineBasicBlock::instr_iterator InsertBefore;
487 const DebugLoc &DbgLoc;
488};
Diana Picus5b916532017-07-07 08:39:04 +0000489
Diana Picus995746d2017-07-12 10:31:16 +0000490void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
491 unsigned Constant) const {
Diana Picus75a04e22019-02-07 11:05:33 +0000492 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
Diana Picus995746d2017-07-12 10:31:16 +0000493 .addDef(DestReg)
494 .addImm(Constant)
495 .add(predOps(ARMCC::AL))
496 .add(condCodeOp());
497}
Diana Picus21014df2017-07-12 09:01:54 +0000498
Diana Picus995746d2017-07-12 10:31:16 +0000499bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
500 unsigned LHSReg, unsigned RHSReg,
501 unsigned ExpectedSize,
502 unsigned ExpectedRegBankID) const {
503 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
504 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
505 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
506}
Diana Picus5b916532017-07-07 08:39:04 +0000507
Diana Picus995746d2017-07-12 10:31:16 +0000508bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
509 unsigned ExpectedSize,
510 unsigned ExpectedRegBankID) const {
511 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000512 LLVM_DEBUG(dbgs() << "Unexpected size for register");
Diana Picus995746d2017-07-12 10:31:16 +0000513 return false;
514 }
515
516 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000517 LLVM_DEBUG(dbgs() << "Unexpected register bank for register");
Diana Picus995746d2017-07-12 10:31:16 +0000518 return false;
519 }
520
521 return true;
522}
523
524bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
525 MachineInstrBuilder &MIB,
526 MachineRegisterInfo &MRI) const {
527 const InsertInfo I(MIB);
Diana Picus5b916532017-07-07 08:39:04 +0000528
Diana Picus621894a2017-06-19 09:40:51 +0000529 auto ResReg = MIB->getOperand(0).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000530 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
Diana Picus5b916532017-07-07 08:39:04 +0000531 return false;
532
Diana Picus621894a2017-06-19 09:40:51 +0000533 auto Cond =
534 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
Diana Picus5b916532017-07-07 08:39:04 +0000535 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
Diana Picus995746d2017-07-12 10:31:16 +0000536 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
Diana Picus5b916532017-07-07 08:39:04 +0000537 MIB->eraseFromParent();
538 return true;
539 }
540
541 auto LHSReg = MIB->getOperand(2).getReg();
542 auto RHSReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000543 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
544 Helper.OperandRegBankID))
Diana Picus621894a2017-06-19 09:40:51 +0000545 return false;
546
Diana Picus5b916532017-07-07 08:39:04 +0000547 auto ARMConds = getComparePreds(Cond);
Diana Picus995746d2017-07-12 10:31:16 +0000548 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
549 putConstant(I, ZeroReg, 0);
Diana Picus5b916532017-07-07 08:39:04 +0000550
551 if (ARMConds.second == ARMCC::AL) {
552 // Simple case, we only need one comparison and we're done.
Diana Picus995746d2017-07-12 10:31:16 +0000553 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
554 ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000555 return false;
556 } else {
557 // Not so simple, we need two successive comparisons.
558 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picus995746d2017-07-12 10:31:16 +0000559 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
560 RHSReg, ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000561 return false;
Diana Picus995746d2017-07-12 10:31:16 +0000562 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
563 IntermediateRes))
Diana Picus5b916532017-07-07 08:39:04 +0000564 return false;
565 }
Diana Picus621894a2017-06-19 09:40:51 +0000566
567 MIB->eraseFromParent();
568 return true;
569}
570
Diana Picus995746d2017-07-12 10:31:16 +0000571bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
572 unsigned ResReg,
573 ARMCC::CondCodes Cond,
574 unsigned LHSReg, unsigned RHSReg,
575 unsigned PrevRes) const {
576 // Perform the comparison.
577 auto CmpI =
578 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
579 .addUse(LHSReg)
580 .addUse(RHSReg)
581 .add(predOps(ARMCC::AL));
582 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
583 return false;
584
585 // Read the comparison flags (if necessary).
586 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
587 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
588 TII.get(Helper.ReadFlagsOpcode))
589 .add(predOps(ARMCC::AL));
590 if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
591 return false;
592 }
593
594 // Select either 1 or the previous result based on the value of the flags.
Diana Picus75a04e22019-02-07 11:05:33 +0000595 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
596 TII.get(Helper.SelectResultOpcode))
Diana Picus995746d2017-07-12 10:31:16 +0000597 .addDef(ResReg)
598 .addUse(PrevRes)
599 .addImm(1)
600 .add(predOps(Cond, ARM::CPSR));
601 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
602 return false;
603
604 return true;
605}
606
Diana Picus930e6ec2017-08-03 09:14:59 +0000607bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
608 MachineRegisterInfo &MRI) const {
Diana Picusabb08862017-09-05 07:57:41 +0000609 if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000610 LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
Diana Picus930e6ec2017-08-03 09:14:59 +0000611 return false;
612 }
Diana Picus930e6ec2017-08-03 09:14:59 +0000613
614 auto GV = MIB->getOperand(1).getGlobal();
615 if (GV->isThreadLocal()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000616 LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");
Diana Picus930e6ec2017-08-03 09:14:59 +0000617 return false;
618 }
619
620 auto &MBB = *MIB->getParent();
621 auto &MF = *MBB.getParent();
622
Sam Parker5b098342019-02-08 07:57:42 +0000623 bool UseMovt = STI.useMovt();
Diana Picus930e6ec2017-08-03 09:14:59 +0000624
Matt Arsenault41e5ac42018-03-14 00:36:23 +0000625 unsigned Size = TM.getPointerSize(0);
Diana Picusc9f29c62017-08-29 09:47:55 +0000626 unsigned Alignment = 4;
Diana Picusabb08862017-09-05 07:57:41 +0000627
628 auto addOpsForConstantPoolLoad = [&MF, Alignment,
629 Size](MachineInstrBuilder &MIB,
630 const GlobalValue *GV, bool IsSBREL) {
Diana Picus3b7beaf2019-02-28 10:42:47 +0000631 assert((MIB->getOpcode() == ARM::LDRi12 ||
632 MIB->getOpcode() == ARM::t2LDRpci) &&
633 "Unsupported instruction");
Diana Picusabb08862017-09-05 07:57:41 +0000634 auto ConstPool = MF.getConstantPool();
635 auto CPIndex =
636 // For SB relative entries we need a target-specific constant pool.
637 // Otherwise, just use a regular constant pool entry.
638 IsSBREL
639 ? ConstPool->getConstantPoolIndex(
640 ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
641 : ConstPool->getConstantPoolIndex(GV, Alignment);
642 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
Diana Picus3b7beaf2019-02-28 10:42:47 +0000643 .addMemOperand(MF.getMachineMemOperand(
644 MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
645 Size, Alignment));
646 if (MIB->getOpcode() == ARM::LDRi12)
647 MIB.addImm(0);
648 MIB.add(predOps(ARMCC::AL));
649 };
650
651 auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) {
652 MIB.addMemOperand(MF.getMachineMemOperand(
653 MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
654 TM.getProgramPointerSize(), Alignment));
Diana Picusabb08862017-09-05 07:57:41 +0000655 };
656
Diana Picusc9f29c62017-08-29 09:47:55 +0000657 if (TM.isPositionIndependent()) {
Diana Picusac154732017-09-05 08:22:47 +0000658 bool Indirect = STI.isGVIndirectSymbol(GV);
Diana Picus3b7beaf2019-02-28 10:42:47 +0000659
660 // For ARM mode, we have different pseudoinstructions for direct accesses
661 // and indirect accesses, and the ones for indirect accesses include the
662 // load from GOT. For Thumb mode, we use the same pseudoinstruction for both
663 // direct and indirect accesses, and we need to manually generate the load
664 // from GOT.
665 bool UseOpcodeThatLoads = Indirect && !STI.isThumb();
666
Diana Picusc9f29c62017-08-29 09:47:55 +0000667 // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
668 // support it yet. See PR28229.
Jonas Hahnfeld65a401f2019-03-04 08:51:32 +0000669 unsigned Opc =
670 UseMovt && !STI.isTargetELF()
671 ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
672 : Opcodes.MOV_ga_pcrel)
673 : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
674 : Opcodes.LDRLIT_ga_pcrel);
Diana Picusc9f29c62017-08-29 09:47:55 +0000675 MIB->setDesc(TII.get(Opc));
676
Evgeniy Stepanov76d5ac42017-11-13 20:45:38 +0000677 int TargetFlags = ARMII::MO_NO_FLAG;
Diana Picusac154732017-09-05 08:22:47 +0000678 if (STI.isTargetDarwin())
Evgeniy Stepanov76d5ac42017-11-13 20:45:38 +0000679 TargetFlags |= ARMII::MO_NONLAZY;
680 if (STI.isGVInGOT(GV))
681 TargetFlags |= ARMII::MO_GOT;
682 MIB->getOperand(1).setTargetFlags(TargetFlags);
Diana Picusc9f29c62017-08-29 09:47:55 +0000683
Diana Picus3b7beaf2019-02-28 10:42:47 +0000684 if (Indirect) {
685 if (!UseOpcodeThatLoads) {
686 auto ResultReg = MIB->getOperand(0).getReg();
687 auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
688
689 MIB->getOperand(0).setReg(AddressReg);
690
691 auto InsertBefore = std::next(MIB->getIterator());
692 auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),
693 TII.get(Opcodes.LOAD32))
694 .addDef(ResultReg)
695 .addReg(AddressReg)
696 .addImm(0)
697 .add(predOps(ARMCC::AL));
698 addGOTMemOperand(MIBLoad);
699
700 if (!constrainSelectedInstRegOperands(*MIBLoad, TII, TRI, RBI))
701 return false;
702 } else {
703 addGOTMemOperand(MIB);
704 }
705 }
Diana Picusc9f29c62017-08-29 09:47:55 +0000706
Diana Picusac154732017-09-05 08:22:47 +0000707 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
Diana Picusc9f29c62017-08-29 09:47:55 +0000708 }
709
Diana Picusf95979112017-09-01 11:13:39 +0000710 bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
711 if (STI.isROPI() && isReadOnly) {
Diana Picus3b7beaf2019-02-28 10:42:47 +0000712 unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
Diana Picusf95979112017-09-01 11:13:39 +0000713 MIB->setDesc(TII.get(Opc));
714 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
715 }
Diana Picusabb08862017-09-05 07:57:41 +0000716 if (STI.isRWPI() && !isReadOnly) {
717 auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
718 MachineInstrBuilder OffsetMIB;
719 if (UseMovt) {
720 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
Diana Picus3b7beaf2019-02-28 10:42:47 +0000721 TII.get(Opcodes.MOVi32imm), Offset);
Diana Picusabb08862017-09-05 07:57:41 +0000722 OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
723 } else {
724 // Load the offset from the constant pool.
Diana Picus3b7beaf2019-02-28 10:42:47 +0000725 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
726 TII.get(Opcodes.ConstPoolLoad), Offset);
Diana Picusabb08862017-09-05 07:57:41 +0000727 addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
728 }
729 if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
730 return false;
731
732 // Add the offset to the SB register.
Diana Picus3b7beaf2019-02-28 10:42:47 +0000733 MIB->setDesc(TII.get(Opcodes.ADDrr));
Diana Picusabb08862017-09-05 07:57:41 +0000734 MIB->RemoveOperand(1);
735 MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
736 .addReg(Offset)
737 .add(predOps(ARMCC::AL))
738 .add(condCodeOp());
739
740 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
741 }
Diana Picusf95979112017-09-01 11:13:39 +0000742
Diana Picusac154732017-09-05 08:22:47 +0000743 if (STI.isTargetELF()) {
Diana Picus930e6ec2017-08-03 09:14:59 +0000744 if (UseMovt) {
Diana Picus3b7beaf2019-02-28 10:42:47 +0000745 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
Diana Picus930e6ec2017-08-03 09:14:59 +0000746 } else {
747 // Load the global's address from the constant pool.
Diana Picus3b7beaf2019-02-28 10:42:47 +0000748 MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
Diana Picus930e6ec2017-08-03 09:14:59 +0000749 MIB->RemoveOperand(1);
Diana Picusabb08862017-09-05 07:57:41 +0000750 addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
Diana Picus930e6ec2017-08-03 09:14:59 +0000751 }
Diana Picusac154732017-09-05 08:22:47 +0000752 } else if (STI.isTargetMachO()) {
Diana Picus930e6ec2017-08-03 09:14:59 +0000753 if (UseMovt)
Diana Picus3b7beaf2019-02-28 10:42:47 +0000754 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
Diana Picus930e6ec2017-08-03 09:14:59 +0000755 else
Diana Picus3b7beaf2019-02-28 10:42:47 +0000756 MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));
Diana Picus930e6ec2017-08-03 09:14:59 +0000757 } else {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000758 LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
Diana Picus930e6ec2017-08-03 09:14:59 +0000759 return false;
760 }
761
762 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
763}
764
Diana Picus7145d222017-06-27 09:19:51 +0000765bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
Diana Picus995746d2017-07-12 10:31:16 +0000766 MachineRegisterInfo &MRI) const {
Diana Picus7145d222017-06-27 09:19:51 +0000767 auto &MBB = *MIB->getParent();
768 auto InsertBefore = std::next(MIB->getIterator());
Diana Picus77367372017-07-07 08:53:27 +0000769 auto &DbgLoc = MIB->getDebugLoc();
Diana Picus7145d222017-06-27 09:19:51 +0000770
Diana Picus4d512df2019-03-28 09:09:27 +0000771 // Compare the condition to 1.
Diana Picus7145d222017-06-27 09:19:51 +0000772 auto CondReg = MIB->getOperand(1).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000773 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000774 "Unsupported types for select operation");
Diana Picus4d512df2019-03-28 09:09:27 +0000775 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))
Diana Picus7145d222017-06-27 09:19:51 +0000776 .addUse(CondReg)
Diana Picus4d512df2019-03-28 09:09:27 +0000777 .addImm(1)
Diana Picus7145d222017-06-27 09:19:51 +0000778 .add(predOps(ARMCC::AL));
779 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
780 return false;
781
782 // Move a value into the result register based on the result of the
783 // comparison.
784 auto ResReg = MIB->getOperand(0).getReg();
785 auto TrueReg = MIB->getOperand(2).getReg();
786 auto FalseReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000787 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
788 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000789 "Unsupported types for select operation");
Diana Picusaa4118a2019-02-13 11:25:32 +0000790 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.MOVCCr))
Diana Picus7145d222017-06-27 09:19:51 +0000791 .addDef(ResReg)
792 .addUse(TrueReg)
793 .addUse(FalseReg)
794 .add(predOps(ARMCC::EQ, ARM::CPSR));
795 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
796 return false;
797
798 MIB->eraseFromParent();
799 return true;
800}
801
Diana Picuse393bc72017-10-06 15:39:16 +0000802bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
803 MachineInstrBuilder &MIB) const {
804 MIB->setDesc(TII.get(ARM::MOVsr));
805 MIB.addImm(ShiftOpc);
806 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
807 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
808}
809
Diana Picusb6e83b92019-04-10 09:14:32 +0000810void ARMInstructionSelector::renderVFPF32Imm(
811 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const {
812 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
813 "Expected G_FCONSTANT");
814
815 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
816 uint32_t FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue);
817 assert(FPImmEncoding != -1 && "Invalid immediate value");
818
819 NewInstBuilder.addImm(FPImmEncoding);
820}
821
822void ARMInstructionSelector::renderVFPF64Imm(
823 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const {
824 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
825 "Expected G_FCONSTANT");
826
827 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
828 uint64_t FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue);
829 assert(FPImmEncoding != -1 && "Invalid immediate value");
830
831 NewInstBuilder.addImm(FPImmEncoding);
832}
833
Daniel Sandersf76f3152017-11-16 00:46:35 +0000834bool ARMInstructionSelector::select(MachineInstr &I,
835 CodeGenCoverage &CoverageInfo) const {
Diana Picus812caee2016-12-16 12:54:46 +0000836 assert(I.getParent() && "Instruction should be in a basic block!");
837 assert(I.getParent()->getParent() && "Instruction should be in a function!");
838
839 auto &MBB = *I.getParent();
840 auto &MF = *MBB.getParent();
841 auto &MRI = MF.getRegInfo();
842
843 if (!isPreISelGenericOpcode(I.getOpcode())) {
844 if (I.isCopy())
845 return selectCopy(I, TII, MRI, TRI, RBI);
846
847 return true;
848 }
849
Diana Picus68773852017-12-22 11:09:18 +0000850 using namespace TargetOpcode;
Diana Picus68773852017-12-22 11:09:18 +0000851
Daniel Sandersf76f3152017-11-16 00:46:35 +0000852 if (selectImpl(I, CoverageInfo))
Diana Picus8abcbbb2017-05-02 09:40:49 +0000853 return true;
854
Diana Picus519807f2016-12-19 11:26:31 +0000855 MachineInstrBuilder MIB{MF, I};
Diana Picusd83df5d2017-01-25 08:47:40 +0000856 bool isSExt = false;
Diana Picus519807f2016-12-19 11:26:31 +0000857
Diana Picus519807f2016-12-19 11:26:31 +0000858 switch (I.getOpcode()) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000859 case G_SEXT:
Diana Picusd83df5d2017-01-25 08:47:40 +0000860 isSExt = true;
861 LLVM_FALLTHROUGH;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000862 case G_ZEXT: {
863 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
864 // FIXME: Smaller destination sizes coming soon!
865 if (DstTy.getSizeInBits() != 32) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000866 LLVM_DEBUG(dbgs() << "Unsupported destination size for extension");
Diana Picus8b6c6be2017-01-25 08:10:40 +0000867 return false;
868 }
869
870 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
871 unsigned SrcSize = SrcTy.getSizeInBits();
872 switch (SrcSize) {
Diana Picusd83df5d2017-01-25 08:47:40 +0000873 case 1: {
874 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
Diana Picus813af0d2018-12-14 12:37:24 +0000875 I.setDesc(TII.get(Opcodes.AND));
Diana Picusd83df5d2017-01-25 08:47:40 +0000876 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
877
878 if (isSExt) {
879 unsigned SExtResult = I.getOperand(0).getReg();
880
881 // Use a new virtual register for the result of the AND
882 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
883 I.getOperand(0).setReg(AndResult);
884
885 auto InsertBefore = std::next(I.getIterator());
Diana Picus813af0d2018-12-14 12:37:24 +0000886 auto SubI =
887 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))
888 .addDef(SExtResult)
889 .addUse(AndResult)
890 .addImm(0)
891 .add(predOps(ARMCC::AL))
892 .add(condCodeOp());
Diana Picusd83df5d2017-01-25 08:47:40 +0000893 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
894 return false;
895 }
896 break;
897 }
Diana Picus8b6c6be2017-01-25 08:10:40 +0000898 case 8:
899 case 16: {
Diana Picus813af0d2018-12-14 12:37:24 +0000900 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
Diana Picuse8368782017-02-17 13:44:19 +0000901 if (NewOpc == I.getOpcode())
902 return false;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000903 I.setDesc(TII.get(NewOpc));
904 MIB.addImm(0).add(predOps(ARMCC::AL));
905 break;
906 }
907 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000908 LLVM_DEBUG(dbgs() << "Unsupported source size for extension");
Diana Picus8b6c6be2017-01-25 08:10:40 +0000909 return false;
910 }
911 break;
912 }
Diana Picus657bfd32017-05-11 08:28:31 +0000913 case G_ANYEXT:
Diana Picus64a33432017-04-21 13:16:50 +0000914 case G_TRUNC: {
915 // The high bits are undefined, so there's nothing special to do, just
916 // treat it as a copy.
917 auto SrcReg = I.getOperand(1).getReg();
918 auto DstReg = I.getOperand(0).getReg();
919
920 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
921 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
922
Diana Picus75ce8522017-12-20 11:27:10 +0000923 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
924 // This should only happen in the obscure case where we have put a 64-bit
925 // integer into a D register. Get it out of there and keep only the
926 // interesting part.
927 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
928 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
929 "Unsupported combination of register banks");
930 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
931 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
932
933 unsigned IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
934 auto InsertBefore = std::next(I.getIterator());
935 auto MovI =
936 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
937 .addDef(DstReg)
938 .addDef(IgnoredBits)
939 .addUse(SrcReg)
940 .add(predOps(ARMCC::AL));
941 if (!constrainSelectedInstRegOperands(*MovI, TII, TRI, RBI))
942 return false;
943
944 MIB->eraseFromParent();
945 return true;
946 }
947
Diana Picus64a33432017-04-21 13:16:50 +0000948 if (SrcRegBank.getID() != DstRegBank.getID()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000949 LLVM_DEBUG(
950 dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
Diana Picus64a33432017-04-21 13:16:50 +0000951 return false;
952 }
953
954 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000955 LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
Diana Picus64a33432017-04-21 13:16:50 +0000956 return false;
957 }
958
959 I.setDesc(TII.get(COPY));
960 return selectCopy(I, TII, MRI, TRI, RBI);
961 }
Diana Picus37ae9f62018-01-04 10:54:57 +0000962 case G_CONSTANT: {
963 if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
964 // Non-pointer constants should be handled by TableGen.
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000965 LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
Diana Picus37ae9f62018-01-04 10:54:57 +0000966 return false;
967 }
968
969 auto &Val = I.getOperand(1);
970 if (Val.isCImm()) {
971 if (!Val.getCImm()->isZero()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000972 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
Diana Picus37ae9f62018-01-04 10:54:57 +0000973 return false;
974 }
975 Val.ChangeToImmediate(0);
976 } else {
977 assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
978 if (Val.getImm() != 0) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000979 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
Diana Picus37ae9f62018-01-04 10:54:57 +0000980 return false;
981 }
982 }
983
984 I.setDesc(TII.get(ARM::MOVi));
985 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
986 break;
987 }
Diana Picus3533ad682019-04-10 09:14:24 +0000988 case G_FCONSTANT: {
989 // Load from constant pool
990 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
991 unsigned Alignment = Size;
992
993 assert((Size == 4 || Size == 8) && "Unsupported FP constant type");
994 auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;
995
996 auto ConstPool = MF.getConstantPool();
997 auto CPIndex =
998 ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);
999 MIB->setDesc(TII.get(LoadOpcode));
1000 MIB->RemoveOperand(1);
1001 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
1002 .addMemOperand(
1003 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
1004 MachineMemOperand::MOLoad, Size, Alignment))
1005 .addImm(0)
1006 .add(predOps(ARMCC::AL));
1007 break;
1008 }
Diana Picus28a6d0e2017-12-22 13:05:51 +00001009 case G_INTTOPTR:
1010 case G_PTRTOINT: {
1011 auto SrcReg = I.getOperand(1).getReg();
1012 auto DstReg = I.getOperand(0).getReg();
1013
1014 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
1015 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1016
1017 if (SrcRegBank.getID() != DstRegBank.getID()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001018 LLVM_DEBUG(
1019 dbgs()
1020 << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
Diana Picus28a6d0e2017-12-22 13:05:51 +00001021 return false;
1022 }
1023
1024 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001025 LLVM_DEBUG(
1026 dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
Diana Picus28a6d0e2017-12-22 13:05:51 +00001027 return false;
1028 }
1029
1030 I.setDesc(TII.get(COPY));
1031 return selectCopy(I, TII, MRI, TRI, RBI);
1032 }
Diana Picus7145d222017-06-27 09:19:51 +00001033 case G_SELECT:
Diana Picus995746d2017-07-12 10:31:16 +00001034 return selectSelect(MIB, MRI);
1035 case G_ICMP: {
Diana Picus75a04e22019-02-07 11:05:33 +00001036 CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
1037 Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
Diana Picus995746d2017-07-12 10:31:16 +00001038 return selectCmp(Helper, MIB, MRI);
1039 }
Diana Picus21014df2017-07-12 09:01:54 +00001040 case G_FCMP: {
Diana Picusac154732017-09-05 08:22:47 +00001041 assert(STI.hasVFP2() && "Can't select fcmp without VFP");
Diana Picus21014df2017-07-12 09:01:54 +00001042
1043 unsigned OpReg = I.getOperand(2).getReg();
1044 unsigned Size = MRI.getType(OpReg).getSizeInBits();
Diana Picus995746d2017-07-12 10:31:16 +00001045
Diana Picusac154732017-09-05 08:22:47 +00001046 if (Size == 64 && STI.isFPOnlySP()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001047 LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");
Diana Picus995746d2017-07-12 10:31:16 +00001048 return false;
1049 }
1050 if (Size != 32 && Size != 64) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001051 LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
Diana Picus995746d2017-07-12 10:31:16 +00001052 return false;
Diana Picus21014df2017-07-12 09:01:54 +00001053 }
1054
Diana Picus995746d2017-07-12 10:31:16 +00001055 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
Diana Picus75a04e22019-02-07 11:05:33 +00001056 Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
Diana Picus995746d2017-07-12 10:31:16 +00001057 return selectCmp(Helper, MIB, MRI);
Diana Picus21014df2017-07-12 09:01:54 +00001058 }
Diana Picuse393bc72017-10-06 15:39:16 +00001059 case G_LSHR:
1060 return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
1061 case G_ASHR:
1062 return selectShift(ARM_AM::ShiftOpc::asr, MIB);
1063 case G_SHL: {
1064 return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
1065 }
Diana Picus9d070942017-02-28 10:14:38 +00001066 case G_GEP:
Diana Picusc0f964eb2019-02-15 10:50:02 +00001067 I.setDesc(TII.get(Opcodes.ADDrr));
Diana Picus8a73f552017-01-13 10:18:01 +00001068 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +00001069 break;
1070 case G_FRAME_INDEX:
1071 // Add 0 to the given frame index and hope it will eventually be folded into
1072 // the user(s).
Diana Picusdcaa9392019-02-21 13:00:02 +00001073 I.setDesc(TII.get(Opcodes.ADDri));
Diana Picus8a73f552017-01-13 10:18:01 +00001074 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +00001075 break;
Diana Picus930e6ec2017-08-03 09:14:59 +00001076 case G_GLOBAL_VALUE:
1077 return selectGlobal(MIB, MRI);
Diana Picus3b99c642017-02-24 14:01:27 +00001078 case G_STORE:
Diana Picus278c7222017-01-26 09:20:47 +00001079 case G_LOAD: {
Daniel Sanders3c1c4c02017-12-05 05:52:07 +00001080 const auto &MemOp = **I.memoperands_begin();
1081 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001082 LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
Daniel Sanders3c1c4c02017-12-05 05:52:07 +00001083 return false;
1084 }
1085
Diana Picus1540b062017-02-16 14:10:50 +00001086 unsigned Reg = I.getOperand(0).getReg();
1087 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
1088
1089 LLT ValTy = MRI.getType(Reg);
Diana Picus278c7222017-01-26 09:20:47 +00001090 const auto ValSize = ValTy.getSizeInBits();
1091
Diana Picusac154732017-09-05 08:22:47 +00001092 assert((ValSize != 64 || STI.hasVFP2()) &&
Diana Picus3b99c642017-02-24 14:01:27 +00001093 "Don't know how to load/store 64-bit value without VFP");
Diana Picus1540b062017-02-16 14:10:50 +00001094
Diana Picus813af0d2018-12-14 12:37:24 +00001095 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
Diana Picus3b99c642017-02-24 14:01:27 +00001096 if (NewOpc == G_LOAD || NewOpc == G_STORE)
Diana Picuse8368782017-02-17 13:44:19 +00001097 return false;
1098
Diana Picus52495c42019-03-28 09:09:36 +00001099 if (ValSize == 1 && NewOpc == Opcodes.STORE8) {
1100 // Before storing a 1-bit value, make sure to clear out any unneeded bits.
1101 unsigned OriginalValue = I.getOperand(0).getReg();
1102
1103 unsigned ValueToStore = MRI.createVirtualRegister(&ARM::GPRRegClass);
1104 I.getOperand(0).setReg(ValueToStore);
1105
1106 auto InsertBefore = I.getIterator();
1107 auto AndI = BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.AND))
1108 .addDef(ValueToStore)
1109 .addUse(OriginalValue)
1110 .addImm(1)
1111 .add(predOps(ARMCC::AL))
1112 .add(condCodeOp());
1113 if (!constrainSelectedInstRegOperands(*AndI, TII, TRI, RBI))
1114 return false;
1115 }
1116
Diana Picus278c7222017-01-26 09:20:47 +00001117 I.setDesc(TII.get(NewOpc));
1118
Diana Picus3b99c642017-02-24 14:01:27 +00001119 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
Diana Picus278c7222017-01-26 09:20:47 +00001120 // LDRH has a funny addressing mode (there's already a FIXME for it).
1121 MIB.addReg(0);
Diana Picus4f8c3e12017-01-13 09:37:56 +00001122 MIB.addImm(0).add(predOps(ARMCC::AL));
Diana Picus519807f2016-12-19 11:26:31 +00001123 break;
Diana Picus278c7222017-01-26 09:20:47 +00001124 }
Diana Picus0b4190a2017-06-07 12:35:05 +00001125 case G_MERGE_VALUES: {
1126 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +00001127 return false;
1128 break;
1129 }
Diana Picus0b4190a2017-06-07 12:35:05 +00001130 case G_UNMERGE_VALUES: {
1131 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +00001132 return false;
1133 break;
1134 }
Diana Picus87a70672017-07-14 09:46:06 +00001135 case G_BRCOND: {
1136 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001137 LLVM_DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
Diana Picus87a70672017-07-14 09:46:06 +00001138 return false;
1139 }
1140
1141 // Set the flags.
Diana Picusa00425f2019-02-15 10:24:03 +00001142 auto Test =
1143 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))
1144 .addReg(I.getOperand(0).getReg())
1145 .addImm(1)
1146 .add(predOps(ARMCC::AL));
Diana Picus87a70672017-07-14 09:46:06 +00001147 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
1148 return false;
1149
1150 // Branch conditionally.
Diana Picusa00425f2019-02-15 10:24:03 +00001151 auto Branch =
1152 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))
1153 .add(I.getOperand(1))
1154 .add(predOps(ARMCC::NE, ARM::CPSR));
Diana Picus87a70672017-07-14 09:46:06 +00001155 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
1156 return false;
1157 I.eraseFromParent();
1158 return true;
1159 }
Diana Picus865f7fe2018-01-04 13:09:25 +00001160 case G_PHI: {
1161 I.setDesc(TII.get(PHI));
1162
1163 unsigned DstReg = I.getOperand(0).getReg();
1164 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
1165 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1166 break;
1167 }
1168
1169 return true;
1170 }
Diana Picus519807f2016-12-19 11:26:31 +00001171 default:
1172 return false;
Diana Picus812caee2016-12-16 12:54:46 +00001173 }
1174
Diana Picus519807f2016-12-19 11:26:31 +00001175 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
Diana Picus22274932016-11-11 08:27:37 +00001176}