blob: 8e5e474c0f59e19a969661c9b34243295536d32c [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
Amara Emersone14c91b2019-08-13 06:26:59 +000037 bool select(MachineInstr &I) 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) {
Daniel Sanders0c476112019-08-15 19:22:08 +0000213 Register DstReg = I.getOperand(0).getReg();
Daniel Sanders2bea69b2019-08-01 23:27:28 +0000214 if (Register::isPhysicalRegister(DstReg))
Diana Picus812caee2016-12-16 12:54:46 +0000215 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) {
Simon Tatham760df472019-05-28 16:13:20 +0000235 assert(TII.getSubtarget().hasVFP2Base() && "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.
Daniel Sanders0c476112019-08-15 19:22:08 +0000239 Register VReg0 = MIB->getOperand(0).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000240 (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");
Daniel Sanders0c476112019-08-15 19:22:08 +0000244 Register VReg1 = MIB->getOperand(1).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000245 (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");
Daniel Sanders0c476112019-08-15 19:22:08 +0000249 Register 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) {
Simon Tatham760df472019-05-28 16:13:20 +0000266 assert(TII.getSubtarget().hasVFP2Base() &&
267 "Can't select unmerge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000268
Diana Picus0b4190a2017-06-07 12:35:05 +0000269 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
270 // GPRs.
Daniel Sanders0c476112019-08-15 19:22:08 +0000271 Register VReg0 = MIB->getOperand(0).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000272 (void)VReg0;
273 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
274 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000275 "Unsupported operand for G_UNMERGE_VALUES");
Daniel Sanders0c476112019-08-15 19:22:08 +0000276 Register VReg1 = MIB->getOperand(1).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000277 (void)VReg1;
Diana Picus0b4190a2017-06-07 12:35:05 +0000278 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
279 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
280 "Unsupported operand for G_UNMERGE_VALUES");
Daniel Sanders0c476112019-08-15 19:22:08 +0000281 Register VReg2 = MIB->getOperand(2).getReg();
Diana Picus0b4190a2017-06-07 12:35:05 +0000282 (void)VReg2;
283 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
284 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
285 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000286
Diana Picus0b4190a2017-06-07 12:35:05 +0000287 MIB->setDesc(TII.get(ARM::VMOVRRD));
Diana Picusb1701e02017-02-16 12:19:57 +0000288 MIB.add(predOps(ARMCC::AL));
289
290 return true;
291}
292
Diana Picus813af0d2018-12-14 12:37:24 +0000293ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {
294 bool isThumb = STI.isThumb();
295
296 using namespace TargetOpcode;
297
298#define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC
299 STORE_OPCODE(SEXT16, SXTH);
300 STORE_OPCODE(ZEXT16, UXTH);
301
302 STORE_OPCODE(SEXT8, SXTB);
303 STORE_OPCODE(ZEXT8, UXTB);
304
305 STORE_OPCODE(AND, ANDri);
306 STORE_OPCODE(RSB, RSBri);
307
308 STORE_OPCODE(STORE32, STRi12);
309 STORE_OPCODE(LOAD32, LDRi12);
310
311 // LDRH/STRH are special...
312 STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
313 LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
314
315 STORE_OPCODE(STORE8, STRBi12);
316 STORE_OPCODE(LOAD8, LDRBi12);
Diana Picus75a04e22019-02-07 11:05:33 +0000317
Diana Picusc0f964eb2019-02-15 10:50:02 +0000318 STORE_OPCODE(ADDrr, ADDrr);
Diana Picusdcaa9392019-02-21 13:00:02 +0000319 STORE_OPCODE(ADDri, ADDri);
Diana Picusc0f964eb2019-02-15 10:50:02 +0000320
Diana Picus75a04e22019-02-07 11:05:33 +0000321 STORE_OPCODE(CMPrr, CMPrr);
322 STORE_OPCODE(MOVi, MOVi);
323 STORE_OPCODE(MOVCCi, MOVCCi);
Diana Picusaa4118a2019-02-13 11:25:32 +0000324
Diana Picusaa4118a2019-02-13 11:25:32 +0000325 STORE_OPCODE(MOVCCr, MOVCCr);
Diana Picusa00425f2019-02-15 10:24:03 +0000326
327 STORE_OPCODE(TSTri, TSTri);
328 STORE_OPCODE(Bcc, Bcc);
Diana Picus3b7beaf2019-02-28 10:42:47 +0000329
330 STORE_OPCODE(MOVi32imm, MOVi32imm);
331 ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;
332 STORE_OPCODE(MOV_ga_pcrel, MOV_ga_pcrel);
333 LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;
334 LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;
Diana Picus813af0d2018-12-14 12:37:24 +0000335#undef MAP_OPCODE
336}
337
338unsigned ARMInstructionSelector::selectSimpleExtOpc(unsigned Opc,
339 unsigned Size) const {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000340 using namespace TargetOpcode;
341
Diana Picuse8368782017-02-17 13:44:19 +0000342 if (Size != 8 && Size != 16)
343 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000344
345 if (Opc == G_SEXT)
Diana Picus813af0d2018-12-14 12:37:24 +0000346 return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000347
348 if (Opc == G_ZEXT)
Diana Picus813af0d2018-12-14 12:37:24 +0000349 return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000350
Diana Picuse8368782017-02-17 13:44:19 +0000351 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000352}
353
Diana Picus813af0d2018-12-14 12:37:24 +0000354unsigned ARMInstructionSelector::selectLoadStoreOpCode(unsigned Opc,
355 unsigned RegBank,
356 unsigned Size) const {
Diana Picus3b99c642017-02-24 14:01:27 +0000357 bool isStore = Opc == TargetOpcode::G_STORE;
358
Diana Picus1540b062017-02-16 14:10:50 +0000359 if (RegBank == ARM::GPRRegBankID) {
360 switch (Size) {
361 case 1:
362 case 8:
Diana Picus813af0d2018-12-14 12:37:24 +0000363 return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
Diana Picus1540b062017-02-16 14:10:50 +0000364 case 16:
Diana Picus813af0d2018-12-14 12:37:24 +0000365 return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
Diana Picus1540b062017-02-16 14:10:50 +0000366 case 32:
Diana Picus813af0d2018-12-14 12:37:24 +0000367 return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
Diana Picuse8368782017-02-17 13:44:19 +0000368 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000369 return Opc;
Diana Picus1540b062017-02-16 14:10:50 +0000370 }
Diana Picus1540b062017-02-16 14:10:50 +0000371 }
372
Diana Picuse8368782017-02-17 13:44:19 +0000373 if (RegBank == ARM::FPRRegBankID) {
374 switch (Size) {
375 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000376 return isStore ? ARM::VSTRS : ARM::VLDRS;
Diana Picuse8368782017-02-17 13:44:19 +0000377 case 64:
Diana Picus3b99c642017-02-24 14:01:27 +0000378 return isStore ? ARM::VSTRD : ARM::VLDRD;
Diana Picuse8368782017-02-17 13:44:19 +0000379 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000380 return Opc;
Diana Picuse8368782017-02-17 13:44:19 +0000381 }
Diana Picus278c7222017-01-26 09:20:47 +0000382 }
383
Diana Picus3b99c642017-02-24 14:01:27 +0000384 return Opc;
Diana Picus278c7222017-01-26 09:20:47 +0000385}
386
Diana Picus5b916532017-07-07 08:39:04 +0000387// When lowering comparisons, we sometimes need to perform two compares instead
388// of just one. Get the condition codes for both comparisons. If only one is
389// needed, the second member of the pair is ARMCC::AL.
390static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
391getComparePreds(CmpInst::Predicate Pred) {
392 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
Diana Picus621894a2017-06-19 09:40:51 +0000393 switch (Pred) {
Diana Picus621894a2017-06-19 09:40:51 +0000394 case CmpInst::FCMP_ONE:
Diana Picus5b916532017-07-07 08:39:04 +0000395 Preds = {ARMCC::GT, ARMCC::MI};
396 break;
Diana Picus621894a2017-06-19 09:40:51 +0000397 case CmpInst::FCMP_UEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000398 Preds = {ARMCC::EQ, ARMCC::VS};
399 break;
Diana Picus621894a2017-06-19 09:40:51 +0000400 case CmpInst::ICMP_EQ:
401 case CmpInst::FCMP_OEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000402 Preds.first = ARMCC::EQ;
403 break;
Diana Picus621894a2017-06-19 09:40:51 +0000404 case CmpInst::ICMP_SGT:
405 case CmpInst::FCMP_OGT:
Diana Picus5b916532017-07-07 08:39:04 +0000406 Preds.first = ARMCC::GT;
407 break;
Diana Picus621894a2017-06-19 09:40:51 +0000408 case CmpInst::ICMP_SGE:
409 case CmpInst::FCMP_OGE:
Diana Picus5b916532017-07-07 08:39:04 +0000410 Preds.first = ARMCC::GE;
411 break;
Diana Picus621894a2017-06-19 09:40:51 +0000412 case CmpInst::ICMP_UGT:
413 case CmpInst::FCMP_UGT:
Diana Picus5b916532017-07-07 08:39:04 +0000414 Preds.first = ARMCC::HI;
415 break;
Diana Picus621894a2017-06-19 09:40:51 +0000416 case CmpInst::FCMP_OLT:
Diana Picus5b916532017-07-07 08:39:04 +0000417 Preds.first = ARMCC::MI;
418 break;
Diana Picus621894a2017-06-19 09:40:51 +0000419 case CmpInst::ICMP_ULE:
420 case CmpInst::FCMP_OLE:
Diana Picus5b916532017-07-07 08:39:04 +0000421 Preds.first = ARMCC::LS;
422 break;
Diana Picus621894a2017-06-19 09:40:51 +0000423 case CmpInst::FCMP_ORD:
Diana Picus5b916532017-07-07 08:39:04 +0000424 Preds.first = ARMCC::VC;
425 break;
Diana Picus621894a2017-06-19 09:40:51 +0000426 case CmpInst::FCMP_UNO:
Diana Picus5b916532017-07-07 08:39:04 +0000427 Preds.first = ARMCC::VS;
428 break;
Diana Picus621894a2017-06-19 09:40:51 +0000429 case CmpInst::FCMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000430 Preds.first = ARMCC::PL;
431 break;
Diana Picus621894a2017-06-19 09:40:51 +0000432 case CmpInst::ICMP_SLT:
433 case CmpInst::FCMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000434 Preds.first = ARMCC::LT;
435 break;
Diana Picus621894a2017-06-19 09:40:51 +0000436 case CmpInst::ICMP_SLE:
437 case CmpInst::FCMP_ULE:
Diana Picus5b916532017-07-07 08:39:04 +0000438 Preds.first = ARMCC::LE;
439 break;
Diana Picus621894a2017-06-19 09:40:51 +0000440 case CmpInst::FCMP_UNE:
441 case CmpInst::ICMP_NE:
Diana Picus5b916532017-07-07 08:39:04 +0000442 Preds.first = ARMCC::NE;
443 break;
Diana Picus621894a2017-06-19 09:40:51 +0000444 case CmpInst::ICMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000445 Preds.first = ARMCC::HS;
446 break;
Diana Picus621894a2017-06-19 09:40:51 +0000447 case CmpInst::ICMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000448 Preds.first = ARMCC::LO;
449 break;
450 default:
451 break;
Diana Picus621894a2017-06-19 09:40:51 +0000452 }
Diana Picus5b916532017-07-07 08:39:04 +0000453 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
454 return Preds;
Diana Picus621894a2017-06-19 09:40:51 +0000455}
456
Diana Picus995746d2017-07-12 10:31:16 +0000457struct ARMInstructionSelector::CmpConstants {
Diana Picus75a04e22019-02-07 11:05:33 +0000458 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,
459 unsigned OpRegBank, unsigned OpSize)
Diana Picus995746d2017-07-12 10:31:16 +0000460 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
Diana Picus75a04e22019-02-07 11:05:33 +0000461 SelectResultOpcode(SelectOpcode), OperandRegBankID(OpRegBank),
462 OperandSize(OpSize) {}
Diana Picus621894a2017-06-19 09:40:51 +0000463
Diana Picus5b916532017-07-07 08:39:04 +0000464 // The opcode used for performing the comparison.
Diana Picus995746d2017-07-12 10:31:16 +0000465 const unsigned ComparisonOpcode;
Diana Picus621894a2017-06-19 09:40:51 +0000466
Diana Picus5b916532017-07-07 08:39:04 +0000467 // The opcode used for reading the flags set by the comparison. May be
468 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
Diana Picus995746d2017-07-12 10:31:16 +0000469 const unsigned ReadFlagsOpcode;
Diana Picus5b916532017-07-07 08:39:04 +0000470
Diana Picus75a04e22019-02-07 11:05:33 +0000471 // The opcode used for materializing the result of the comparison.
472 const unsigned SelectResultOpcode;
473
Diana Picus5b916532017-07-07 08:39:04 +0000474 // The assumed register bank ID for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000475 const unsigned OperandRegBankID;
Diana Picus5b916532017-07-07 08:39:04 +0000476
Diana Picus21014df2017-07-12 09:01:54 +0000477 // The assumed size in bits for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000478 const unsigned OperandSize;
Diana Picus5b916532017-07-07 08:39:04 +0000479};
480
Diana Picus995746d2017-07-12 10:31:16 +0000481struct ARMInstructionSelector::InsertInfo {
482 InsertInfo(MachineInstrBuilder &MIB)
483 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
484 DbgLoc(MIB->getDebugLoc()) {}
Diana Picus5b916532017-07-07 08:39:04 +0000485
Diana Picus995746d2017-07-12 10:31:16 +0000486 MachineBasicBlock &MBB;
487 const MachineBasicBlock::instr_iterator InsertBefore;
488 const DebugLoc &DbgLoc;
489};
Diana Picus5b916532017-07-07 08:39:04 +0000490
Diana Picus995746d2017-07-12 10:31:16 +0000491void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
492 unsigned Constant) const {
Diana Picus75a04e22019-02-07 11:05:33 +0000493 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
Diana Picus995746d2017-07-12 10:31:16 +0000494 .addDef(DestReg)
495 .addImm(Constant)
496 .add(predOps(ARMCC::AL))
497 .add(condCodeOp());
498}
Diana Picus21014df2017-07-12 09:01:54 +0000499
Diana Picus995746d2017-07-12 10:31:16 +0000500bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
501 unsigned LHSReg, unsigned RHSReg,
502 unsigned ExpectedSize,
503 unsigned ExpectedRegBankID) const {
504 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
505 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
506 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
507}
Diana Picus5b916532017-07-07 08:39:04 +0000508
Diana Picus995746d2017-07-12 10:31:16 +0000509bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
510 unsigned ExpectedSize,
511 unsigned ExpectedRegBankID) const {
512 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000513 LLVM_DEBUG(dbgs() << "Unexpected size for register");
Diana Picus995746d2017-07-12 10:31:16 +0000514 return false;
515 }
516
517 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000518 LLVM_DEBUG(dbgs() << "Unexpected register bank for register");
Diana Picus995746d2017-07-12 10:31:16 +0000519 return false;
520 }
521
522 return true;
523}
524
525bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
526 MachineInstrBuilder &MIB,
527 MachineRegisterInfo &MRI) const {
528 const InsertInfo I(MIB);
Diana Picus5b916532017-07-07 08:39:04 +0000529
Diana Picus621894a2017-06-19 09:40:51 +0000530 auto ResReg = MIB->getOperand(0).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000531 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
Diana Picus5b916532017-07-07 08:39:04 +0000532 return false;
533
Diana Picus621894a2017-06-19 09:40:51 +0000534 auto Cond =
535 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
Diana Picus5b916532017-07-07 08:39:04 +0000536 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
Diana Picus995746d2017-07-12 10:31:16 +0000537 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
Diana Picus5b916532017-07-07 08:39:04 +0000538 MIB->eraseFromParent();
539 return true;
540 }
541
542 auto LHSReg = MIB->getOperand(2).getReg();
543 auto RHSReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000544 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
545 Helper.OperandRegBankID))
Diana Picus621894a2017-06-19 09:40:51 +0000546 return false;
547
Diana Picus5b916532017-07-07 08:39:04 +0000548 auto ARMConds = getComparePreds(Cond);
Diana Picus995746d2017-07-12 10:31:16 +0000549 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
550 putConstant(I, ZeroReg, 0);
Diana Picus5b916532017-07-07 08:39:04 +0000551
552 if (ARMConds.second == ARMCC::AL) {
553 // Simple case, we only need one comparison and we're done.
Diana Picus995746d2017-07-12 10:31:16 +0000554 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
555 ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000556 return false;
557 } else {
558 // Not so simple, we need two successive comparisons.
559 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picus995746d2017-07-12 10:31:16 +0000560 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
561 RHSReg, ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000562 return false;
Diana Picus995746d2017-07-12 10:31:16 +0000563 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
564 IntermediateRes))
Diana Picus5b916532017-07-07 08:39:04 +0000565 return false;
566 }
Diana Picus621894a2017-06-19 09:40:51 +0000567
568 MIB->eraseFromParent();
569 return true;
570}
571
Diana Picus995746d2017-07-12 10:31:16 +0000572bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
573 unsigned ResReg,
574 ARMCC::CondCodes Cond,
575 unsigned LHSReg, unsigned RHSReg,
576 unsigned PrevRes) const {
577 // Perform the comparison.
578 auto CmpI =
579 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
580 .addUse(LHSReg)
581 .addUse(RHSReg)
582 .add(predOps(ARMCC::AL));
583 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
584 return false;
585
586 // Read the comparison flags (if necessary).
587 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
588 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
589 TII.get(Helper.ReadFlagsOpcode))
590 .add(predOps(ARMCC::AL));
591 if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
592 return false;
593 }
594
595 // Select either 1 or the previous result based on the value of the flags.
Diana Picus75a04e22019-02-07 11:05:33 +0000596 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
597 TII.get(Helper.SelectResultOpcode))
Diana Picus995746d2017-07-12 10:31:16 +0000598 .addDef(ResReg)
599 .addUse(PrevRes)
600 .addImm(1)
601 .add(predOps(Cond, ARM::CPSR));
602 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
603 return false;
604
605 return true;
606}
607
Diana Picus930e6ec2017-08-03 09:14:59 +0000608bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
609 MachineRegisterInfo &MRI) const {
Diana Picusabb08862017-09-05 07:57:41 +0000610 if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000611 LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
Diana Picus930e6ec2017-08-03 09:14:59 +0000612 return false;
613 }
Diana Picus930e6ec2017-08-03 09:14:59 +0000614
615 auto GV = MIB->getOperand(1).getGlobal();
616 if (GV->isThreadLocal()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000617 LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");
Diana Picus930e6ec2017-08-03 09:14:59 +0000618 return false;
619 }
620
621 auto &MBB = *MIB->getParent();
622 auto &MF = *MBB.getParent();
623
Sam Parker5b098342019-02-08 07:57:42 +0000624 bool UseMovt = STI.useMovt();
Diana Picus930e6ec2017-08-03 09:14:59 +0000625
Matt Arsenault41e5ac42018-03-14 00:36:23 +0000626 unsigned Size = TM.getPointerSize(0);
Diana Picusc9f29c62017-08-29 09:47:55 +0000627 unsigned Alignment = 4;
Diana Picusabb08862017-09-05 07:57:41 +0000628
629 auto addOpsForConstantPoolLoad = [&MF, Alignment,
630 Size](MachineInstrBuilder &MIB,
631 const GlobalValue *GV, bool IsSBREL) {
Diana Picus3b7beaf2019-02-28 10:42:47 +0000632 assert((MIB->getOpcode() == ARM::LDRi12 ||
633 MIB->getOpcode() == ARM::t2LDRpci) &&
634 "Unsupported instruction");
Diana Picusabb08862017-09-05 07:57:41 +0000635 auto ConstPool = MF.getConstantPool();
636 auto CPIndex =
637 // For SB relative entries we need a target-specific constant pool.
638 // Otherwise, just use a regular constant pool entry.
639 IsSBREL
640 ? ConstPool->getConstantPoolIndex(
641 ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
642 : ConstPool->getConstantPoolIndex(GV, Alignment);
643 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
Diana Picus3b7beaf2019-02-28 10:42:47 +0000644 .addMemOperand(MF.getMachineMemOperand(
645 MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
646 Size, Alignment));
647 if (MIB->getOpcode() == ARM::LDRi12)
648 MIB.addImm(0);
649 MIB.add(predOps(ARMCC::AL));
650 };
651
652 auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) {
653 MIB.addMemOperand(MF.getMachineMemOperand(
654 MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
655 TM.getProgramPointerSize(), Alignment));
Diana Picusabb08862017-09-05 07:57:41 +0000656 };
657
Diana Picusc9f29c62017-08-29 09:47:55 +0000658 if (TM.isPositionIndependent()) {
Diana Picusac154732017-09-05 08:22:47 +0000659 bool Indirect = STI.isGVIndirectSymbol(GV);
Diana Picus3b7beaf2019-02-28 10:42:47 +0000660
661 // For ARM mode, we have different pseudoinstructions for direct accesses
662 // and indirect accesses, and the ones for indirect accesses include the
663 // load from GOT. For Thumb mode, we use the same pseudoinstruction for both
664 // direct and indirect accesses, and we need to manually generate the load
665 // from GOT.
666 bool UseOpcodeThatLoads = Indirect && !STI.isThumb();
667
Diana Picusc9f29c62017-08-29 09:47:55 +0000668 // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
669 // support it yet. See PR28229.
Jonas Hahnfeld65a401f2019-03-04 08:51:32 +0000670 unsigned Opc =
671 UseMovt && !STI.isTargetELF()
672 ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
673 : Opcodes.MOV_ga_pcrel)
674 : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
675 : Opcodes.LDRLIT_ga_pcrel);
Diana Picusc9f29c62017-08-29 09:47:55 +0000676 MIB->setDesc(TII.get(Opc));
677
Evgeniy Stepanov76d5ac42017-11-13 20:45:38 +0000678 int TargetFlags = ARMII::MO_NO_FLAG;
Diana Picusac154732017-09-05 08:22:47 +0000679 if (STI.isTargetDarwin())
Evgeniy Stepanov76d5ac42017-11-13 20:45:38 +0000680 TargetFlags |= ARMII::MO_NONLAZY;
681 if (STI.isGVInGOT(GV))
682 TargetFlags |= ARMII::MO_GOT;
683 MIB->getOperand(1).setTargetFlags(TargetFlags);
Diana Picusc9f29c62017-08-29 09:47:55 +0000684
Diana Picus3b7beaf2019-02-28 10:42:47 +0000685 if (Indirect) {
686 if (!UseOpcodeThatLoads) {
687 auto ResultReg = MIB->getOperand(0).getReg();
688 auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
689
690 MIB->getOperand(0).setReg(AddressReg);
691
692 auto InsertBefore = std::next(MIB->getIterator());
693 auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),
694 TII.get(Opcodes.LOAD32))
695 .addDef(ResultReg)
696 .addReg(AddressReg)
697 .addImm(0)
698 .add(predOps(ARMCC::AL));
699 addGOTMemOperand(MIBLoad);
700
701 if (!constrainSelectedInstRegOperands(*MIBLoad, TII, TRI, RBI))
702 return false;
703 } else {
704 addGOTMemOperand(MIB);
705 }
706 }
Diana Picusc9f29c62017-08-29 09:47:55 +0000707
Diana Picusac154732017-09-05 08:22:47 +0000708 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
Diana Picusc9f29c62017-08-29 09:47:55 +0000709 }
710
Diana Picusf95979112017-09-01 11:13:39 +0000711 bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
712 if (STI.isROPI() && isReadOnly) {
Diana Picus3b7beaf2019-02-28 10:42:47 +0000713 unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
Diana Picusf95979112017-09-01 11:13:39 +0000714 MIB->setDesc(TII.get(Opc));
715 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
716 }
Diana Picusabb08862017-09-05 07:57:41 +0000717 if (STI.isRWPI() && !isReadOnly) {
718 auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
719 MachineInstrBuilder OffsetMIB;
720 if (UseMovt) {
721 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
Diana Picus3b7beaf2019-02-28 10:42:47 +0000722 TII.get(Opcodes.MOVi32imm), Offset);
Diana Picusabb08862017-09-05 07:57:41 +0000723 OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
724 } else {
725 // Load the offset from the constant pool.
Diana Picus3b7beaf2019-02-28 10:42:47 +0000726 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
727 TII.get(Opcodes.ConstPoolLoad), Offset);
Diana Picusabb08862017-09-05 07:57:41 +0000728 addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
729 }
730 if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
731 return false;
732
733 // Add the offset to the SB register.
Diana Picus3b7beaf2019-02-28 10:42:47 +0000734 MIB->setDesc(TII.get(Opcodes.ADDrr));
Diana Picusabb08862017-09-05 07:57:41 +0000735 MIB->RemoveOperand(1);
736 MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
737 .addReg(Offset)
738 .add(predOps(ARMCC::AL))
739 .add(condCodeOp());
740
741 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
742 }
Diana Picusf95979112017-09-01 11:13:39 +0000743
Diana Picusac154732017-09-05 08:22:47 +0000744 if (STI.isTargetELF()) {
Diana Picus930e6ec2017-08-03 09:14:59 +0000745 if (UseMovt) {
Diana Picus3b7beaf2019-02-28 10:42:47 +0000746 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
Diana Picus930e6ec2017-08-03 09:14:59 +0000747 } else {
748 // Load the global's address from the constant pool.
Diana Picus3b7beaf2019-02-28 10:42:47 +0000749 MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
Diana Picus930e6ec2017-08-03 09:14:59 +0000750 MIB->RemoveOperand(1);
Diana Picusabb08862017-09-05 07:57:41 +0000751 addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
Diana Picus930e6ec2017-08-03 09:14:59 +0000752 }
Diana Picusac154732017-09-05 08:22:47 +0000753 } else if (STI.isTargetMachO()) {
Diana Picus930e6ec2017-08-03 09:14:59 +0000754 if (UseMovt)
Diana Picus3b7beaf2019-02-28 10:42:47 +0000755 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
Diana Picus930e6ec2017-08-03 09:14:59 +0000756 else
Diana Picus3b7beaf2019-02-28 10:42:47 +0000757 MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));
Diana Picus930e6ec2017-08-03 09:14:59 +0000758 } else {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000759 LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
Diana Picus930e6ec2017-08-03 09:14:59 +0000760 return false;
761 }
762
763 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
764}
765
Diana Picus7145d222017-06-27 09:19:51 +0000766bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
Diana Picus995746d2017-07-12 10:31:16 +0000767 MachineRegisterInfo &MRI) const {
Diana Picus7145d222017-06-27 09:19:51 +0000768 auto &MBB = *MIB->getParent();
769 auto InsertBefore = std::next(MIB->getIterator());
Diana Picus77367372017-07-07 08:53:27 +0000770 auto &DbgLoc = MIB->getDebugLoc();
Diana Picus7145d222017-06-27 09:19:51 +0000771
Diana Picus4d512df2019-03-28 09:09:27 +0000772 // Compare the condition to 1.
Diana Picus7145d222017-06-27 09:19:51 +0000773 auto CondReg = MIB->getOperand(1).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000774 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000775 "Unsupported types for select operation");
Diana Picus4d512df2019-03-28 09:09:27 +0000776 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))
Diana Picus7145d222017-06-27 09:19:51 +0000777 .addUse(CondReg)
Diana Picus4d512df2019-03-28 09:09:27 +0000778 .addImm(1)
Diana Picus7145d222017-06-27 09:19:51 +0000779 .add(predOps(ARMCC::AL));
780 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
781 return false;
782
783 // Move a value into the result register based on the result of the
784 // comparison.
785 auto ResReg = MIB->getOperand(0).getReg();
786 auto TrueReg = MIB->getOperand(2).getReg();
787 auto FalseReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000788 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
789 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000790 "Unsupported types for select operation");
Diana Picusaa4118a2019-02-13 11:25:32 +0000791 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.MOVCCr))
Diana Picus7145d222017-06-27 09:19:51 +0000792 .addDef(ResReg)
793 .addUse(TrueReg)
794 .addUse(FalseReg)
795 .add(predOps(ARMCC::EQ, ARM::CPSR));
796 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
797 return false;
798
799 MIB->eraseFromParent();
800 return true;
801}
802
Diana Picuse393bc72017-10-06 15:39:16 +0000803bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
804 MachineInstrBuilder &MIB) const {
Diana Picus4a7f8d82019-04-10 09:14:37 +0000805 assert(!STI.isThumb() && "Unsupported subtarget");
Diana Picuse393bc72017-10-06 15:39:16 +0000806 MIB->setDesc(TII.get(ARM::MOVsr));
807 MIB.addImm(ShiftOpc);
808 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
809 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
810}
811
Diana Picusb6e83b92019-04-10 09:14:32 +0000812void ARMInstructionSelector::renderVFPF32Imm(
813 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const {
814 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
815 "Expected G_FCONSTANT");
816
817 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
Diana Picus6bdade82019-04-10 09:31:28 +0000818 int FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue);
Diana Picusb6e83b92019-04-10 09:14:32 +0000819 assert(FPImmEncoding != -1 && "Invalid immediate value");
820
821 NewInstBuilder.addImm(FPImmEncoding);
822}
823
824void ARMInstructionSelector::renderVFPF64Imm(
825 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst) const {
826 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
827 "Expected G_FCONSTANT");
828
829 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
Diana Picus6bdade82019-04-10 09:31:28 +0000830 int FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue);
Diana Picusb6e83b92019-04-10 09:14:32 +0000831 assert(FPImmEncoding != -1 && "Invalid immediate value");
832
833 NewInstBuilder.addImm(FPImmEncoding);
834}
835
Amara Emersone14c91b2019-08-13 06:26:59 +0000836bool ARMInstructionSelector::select(MachineInstr &I) {
Diana Picus812caee2016-12-16 12:54:46 +0000837 assert(I.getParent() && "Instruction should be in a basic block!");
838 assert(I.getParent()->getParent() && "Instruction should be in a function!");
839
840 auto &MBB = *I.getParent();
841 auto &MF = *MBB.getParent();
842 auto &MRI = MF.getRegInfo();
843
844 if (!isPreISelGenericOpcode(I.getOpcode())) {
845 if (I.isCopy())
846 return selectCopy(I, TII, MRI, TRI, RBI);
847
848 return true;
849 }
850
Diana Picus68773852017-12-22 11:09:18 +0000851 using namespace TargetOpcode;
Diana Picus68773852017-12-22 11:09:18 +0000852
Amara Emersone14c91b2019-08-13 06:26:59 +0000853 if (selectImpl(I, *CoverageInfo))
Diana Picus8abcbbb2017-05-02 09:40:49 +0000854 return true;
855
Diana Picus519807f2016-12-19 11:26:31 +0000856 MachineInstrBuilder MIB{MF, I};
Diana Picusd83df5d2017-01-25 08:47:40 +0000857 bool isSExt = false;
Diana Picus519807f2016-12-19 11:26:31 +0000858
Diana Picus519807f2016-12-19 11:26:31 +0000859 switch (I.getOpcode()) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000860 case G_SEXT:
Diana Picusd83df5d2017-01-25 08:47:40 +0000861 isSExt = true;
862 LLVM_FALLTHROUGH;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000863 case G_ZEXT: {
Diana Picus1136ea22019-05-02 10:08:29 +0000864 assert(MRI.getType(I.getOperand(0).getReg()).getSizeInBits() <= 32 &&
Diana Picus06a61cc2019-05-02 09:28:00 +0000865 "Unsupported destination size for extension");
Diana Picus8b6c6be2017-01-25 08:10:40 +0000866
867 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
868 unsigned SrcSize = SrcTy.getSizeInBits();
869 switch (SrcSize) {
Diana Picusd83df5d2017-01-25 08:47:40 +0000870 case 1: {
871 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
Diana Picus813af0d2018-12-14 12:37:24 +0000872 I.setDesc(TII.get(Opcodes.AND));
Diana Picusd83df5d2017-01-25 08:47:40 +0000873 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
874
875 if (isSExt) {
Daniel Sanders0c476112019-08-15 19:22:08 +0000876 Register SExtResult = I.getOperand(0).getReg();
Diana Picusd83df5d2017-01-25 08:47:40 +0000877
878 // Use a new virtual register for the result of the AND
Daniel Sanders0c476112019-08-15 19:22:08 +0000879 Register AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picusd83df5d2017-01-25 08:47:40 +0000880 I.getOperand(0).setReg(AndResult);
881
882 auto InsertBefore = std::next(I.getIterator());
Diana Picus813af0d2018-12-14 12:37:24 +0000883 auto SubI =
884 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))
885 .addDef(SExtResult)
886 .addUse(AndResult)
887 .addImm(0)
888 .add(predOps(ARMCC::AL))
889 .add(condCodeOp());
Diana Picusd83df5d2017-01-25 08:47:40 +0000890 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
891 return false;
892 }
893 break;
894 }
Diana Picus8b6c6be2017-01-25 08:10:40 +0000895 case 8:
896 case 16: {
Diana Picus813af0d2018-12-14 12:37:24 +0000897 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
Diana Picuse8368782017-02-17 13:44:19 +0000898 if (NewOpc == I.getOpcode())
899 return false;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000900 I.setDesc(TII.get(NewOpc));
901 MIB.addImm(0).add(predOps(ARMCC::AL));
902 break;
903 }
904 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000905 LLVM_DEBUG(dbgs() << "Unsupported source size for extension");
Diana Picus8b6c6be2017-01-25 08:10:40 +0000906 return false;
907 }
908 break;
909 }
Diana Picus657bfd32017-05-11 08:28:31 +0000910 case G_ANYEXT:
Diana Picus64a33432017-04-21 13:16:50 +0000911 case G_TRUNC: {
912 // The high bits are undefined, so there's nothing special to do, just
913 // treat it as a copy.
914 auto SrcReg = I.getOperand(1).getReg();
915 auto DstReg = I.getOperand(0).getReg();
916
917 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
918 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
919
Diana Picus75ce8522017-12-20 11:27:10 +0000920 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
921 // This should only happen in the obscure case where we have put a 64-bit
922 // integer into a D register. Get it out of there and keep only the
923 // interesting part.
924 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
925 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
926 "Unsupported combination of register banks");
927 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
928 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
929
Daniel Sanders0c476112019-08-15 19:22:08 +0000930 Register IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picus75ce8522017-12-20 11:27:10 +0000931 auto InsertBefore = std::next(I.getIterator());
932 auto MovI =
933 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
934 .addDef(DstReg)
935 .addDef(IgnoredBits)
936 .addUse(SrcReg)
937 .add(predOps(ARMCC::AL));
938 if (!constrainSelectedInstRegOperands(*MovI, TII, TRI, RBI))
939 return false;
940
941 MIB->eraseFromParent();
942 return true;
943 }
944
Diana Picus64a33432017-04-21 13:16:50 +0000945 if (SrcRegBank.getID() != DstRegBank.getID()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000946 LLVM_DEBUG(
947 dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
Diana Picus64a33432017-04-21 13:16:50 +0000948 return false;
949 }
950
951 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000952 LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
Diana Picus64a33432017-04-21 13:16:50 +0000953 return false;
954 }
955
956 I.setDesc(TII.get(COPY));
957 return selectCopy(I, TII, MRI, TRI, RBI);
958 }
Diana Picus37ae9f62018-01-04 10:54:57 +0000959 case G_CONSTANT: {
960 if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
961 // Non-pointer constants should be handled by TableGen.
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000962 LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
Diana Picus37ae9f62018-01-04 10:54:57 +0000963 return false;
964 }
965
966 auto &Val = I.getOperand(1);
967 if (Val.isCImm()) {
968 if (!Val.getCImm()->isZero()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000969 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
Diana Picus37ae9f62018-01-04 10:54:57 +0000970 return false;
971 }
972 Val.ChangeToImmediate(0);
973 } else {
974 assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
975 if (Val.getImm() != 0) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000976 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
Diana Picus37ae9f62018-01-04 10:54:57 +0000977 return false;
978 }
979 }
980
Diana Picus4a7f8d82019-04-10 09:14:37 +0000981 assert(!STI.isThumb() && "Unsupported subtarget");
Diana Picus37ae9f62018-01-04 10:54:57 +0000982 I.setDesc(TII.get(ARM::MOVi));
983 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
984 break;
985 }
Diana Picus3533ad682019-04-10 09:14:24 +0000986 case G_FCONSTANT: {
987 // Load from constant pool
988 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
989 unsigned Alignment = Size;
990
991 assert((Size == 4 || Size == 8) && "Unsupported FP constant type");
992 auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;
993
994 auto ConstPool = MF.getConstantPool();
995 auto CPIndex =
996 ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);
997 MIB->setDesc(TII.get(LoadOpcode));
998 MIB->RemoveOperand(1);
999 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
1000 .addMemOperand(
1001 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
1002 MachineMemOperand::MOLoad, Size, Alignment))
1003 .addImm(0)
1004 .add(predOps(ARMCC::AL));
1005 break;
1006 }
Diana Picus28a6d0e2017-12-22 13:05:51 +00001007 case G_INTTOPTR:
1008 case G_PTRTOINT: {
1009 auto SrcReg = I.getOperand(1).getReg();
1010 auto DstReg = I.getOperand(0).getReg();
1011
1012 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
1013 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1014
1015 if (SrcRegBank.getID() != DstRegBank.getID()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001016 LLVM_DEBUG(
1017 dbgs()
1018 << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
Diana Picus28a6d0e2017-12-22 13:05:51 +00001019 return false;
1020 }
1021
1022 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001023 LLVM_DEBUG(
1024 dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
Diana Picus28a6d0e2017-12-22 13:05:51 +00001025 return false;
1026 }
1027
1028 I.setDesc(TII.get(COPY));
1029 return selectCopy(I, TII, MRI, TRI, RBI);
1030 }
Diana Picus7145d222017-06-27 09:19:51 +00001031 case G_SELECT:
Diana Picus995746d2017-07-12 10:31:16 +00001032 return selectSelect(MIB, MRI);
1033 case G_ICMP: {
Diana Picus75a04e22019-02-07 11:05:33 +00001034 CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
1035 Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
Diana Picus995746d2017-07-12 10:31:16 +00001036 return selectCmp(Helper, MIB, MRI);
1037 }
Diana Picus21014df2017-07-12 09:01:54 +00001038 case G_FCMP: {
Simon Tatham760df472019-05-28 16:13:20 +00001039 assert(STI.hasVFP2Base() && "Can't select fcmp without VFP");
Diana Picus21014df2017-07-12 09:01:54 +00001040
Daniel Sanders0c476112019-08-15 19:22:08 +00001041 Register OpReg = I.getOperand(2).getReg();
Diana Picus21014df2017-07-12 09:01:54 +00001042 unsigned Size = MRI.getType(OpReg).getSizeInBits();
Diana Picus995746d2017-07-12 10:31:16 +00001043
Simon Tatham760df472019-05-28 16:13:20 +00001044 if (Size == 64 && !STI.hasFP64()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001045 LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");
Diana Picus995746d2017-07-12 10:31:16 +00001046 return false;
1047 }
1048 if (Size != 32 && Size != 64) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001049 LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
Diana Picus995746d2017-07-12 10:31:16 +00001050 return false;
Diana Picus21014df2017-07-12 09:01:54 +00001051 }
1052
Diana Picus995746d2017-07-12 10:31:16 +00001053 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
Diana Picus75a04e22019-02-07 11:05:33 +00001054 Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
Diana Picus995746d2017-07-12 10:31:16 +00001055 return selectCmp(Helper, MIB, MRI);
Diana Picus21014df2017-07-12 09:01:54 +00001056 }
Diana Picuse393bc72017-10-06 15:39:16 +00001057 case G_LSHR:
1058 return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
1059 case G_ASHR:
1060 return selectShift(ARM_AM::ShiftOpc::asr, MIB);
1061 case G_SHL: {
1062 return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
1063 }
Diana Picus9d070942017-02-28 10:14:38 +00001064 case G_GEP:
Diana Picusc0f964eb2019-02-15 10:50:02 +00001065 I.setDesc(TII.get(Opcodes.ADDrr));
Diana Picus8a73f552017-01-13 10:18:01 +00001066 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +00001067 break;
1068 case G_FRAME_INDEX:
1069 // Add 0 to the given frame index and hope it will eventually be folded into
1070 // the user(s).
Diana Picusdcaa9392019-02-21 13:00:02 +00001071 I.setDesc(TII.get(Opcodes.ADDri));
Diana Picus8a73f552017-01-13 10:18:01 +00001072 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +00001073 break;
Diana Picus930e6ec2017-08-03 09:14:59 +00001074 case G_GLOBAL_VALUE:
1075 return selectGlobal(MIB, MRI);
Diana Picus3b99c642017-02-24 14:01:27 +00001076 case G_STORE:
Diana Picus278c7222017-01-26 09:20:47 +00001077 case G_LOAD: {
Daniel Sanders3c1c4c02017-12-05 05:52:07 +00001078 const auto &MemOp = **I.memoperands_begin();
Philip Reames5c38ca32019-08-15 22:21:14 +00001079 if (MemOp.isAtomic()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001080 LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
Daniel Sanders3c1c4c02017-12-05 05:52:07 +00001081 return false;
1082 }
1083
Daniel Sanders0c476112019-08-15 19:22:08 +00001084 Register Reg = I.getOperand(0).getReg();
Diana Picus1540b062017-02-16 14:10:50 +00001085 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
1086
1087 LLT ValTy = MRI.getType(Reg);
Diana Picus278c7222017-01-26 09:20:47 +00001088 const auto ValSize = ValTy.getSizeInBits();
1089
Simon Tatham760df472019-05-28 16:13:20 +00001090 assert((ValSize != 64 || STI.hasVFP2Base()) &&
Diana Picus3b99c642017-02-24 14:01:27 +00001091 "Don't know how to load/store 64-bit value without VFP");
Diana Picus1540b062017-02-16 14:10:50 +00001092
Diana Picus813af0d2018-12-14 12:37:24 +00001093 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
Diana Picus3b99c642017-02-24 14:01:27 +00001094 if (NewOpc == G_LOAD || NewOpc == G_STORE)
Diana Picuse8368782017-02-17 13:44:19 +00001095 return false;
1096
Diana Picus52495c42019-03-28 09:09:36 +00001097 if (ValSize == 1 && NewOpc == Opcodes.STORE8) {
1098 // Before storing a 1-bit value, make sure to clear out any unneeded bits.
Daniel Sanders0c476112019-08-15 19:22:08 +00001099 Register OriginalValue = I.getOperand(0).getReg();
Diana Picus52495c42019-03-28 09:09:36 +00001100
Daniel Sanders0c476112019-08-15 19:22:08 +00001101 Register ValueToStore = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picus52495c42019-03-28 09:09:36 +00001102 I.getOperand(0).setReg(ValueToStore);
1103
1104 auto InsertBefore = I.getIterator();
1105 auto AndI = BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.AND))
1106 .addDef(ValueToStore)
1107 .addUse(OriginalValue)
1108 .addImm(1)
1109 .add(predOps(ARMCC::AL))
1110 .add(condCodeOp());
1111 if (!constrainSelectedInstRegOperands(*AndI, TII, TRI, RBI))
1112 return false;
1113 }
1114
Diana Picus278c7222017-01-26 09:20:47 +00001115 I.setDesc(TII.get(NewOpc));
1116
Diana Picus3b99c642017-02-24 14:01:27 +00001117 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
Diana Picus278c7222017-01-26 09:20:47 +00001118 // LDRH has a funny addressing mode (there's already a FIXME for it).
1119 MIB.addReg(0);
Diana Picus4f8c3e12017-01-13 09:37:56 +00001120 MIB.addImm(0).add(predOps(ARMCC::AL));
Diana Picus519807f2016-12-19 11:26:31 +00001121 break;
Diana Picus278c7222017-01-26 09:20:47 +00001122 }
Diana Picus0b4190a2017-06-07 12:35:05 +00001123 case G_MERGE_VALUES: {
1124 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +00001125 return false;
1126 break;
1127 }
Diana Picus0b4190a2017-06-07 12:35:05 +00001128 case G_UNMERGE_VALUES: {
1129 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +00001130 return false;
1131 break;
1132 }
Diana Picus87a70672017-07-14 09:46:06 +00001133 case G_BRCOND: {
1134 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001135 LLVM_DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
Diana Picus87a70672017-07-14 09:46:06 +00001136 return false;
1137 }
1138
1139 // Set the flags.
Diana Picusa00425f2019-02-15 10:24:03 +00001140 auto Test =
1141 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))
1142 .addReg(I.getOperand(0).getReg())
1143 .addImm(1)
1144 .add(predOps(ARMCC::AL));
Diana Picus87a70672017-07-14 09:46:06 +00001145 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
1146 return false;
1147
1148 // Branch conditionally.
Diana Picusa00425f2019-02-15 10:24:03 +00001149 auto Branch =
1150 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))
1151 .add(I.getOperand(1))
1152 .add(predOps(ARMCC::NE, ARM::CPSR));
Diana Picus87a70672017-07-14 09:46:06 +00001153 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
1154 return false;
1155 I.eraseFromParent();
1156 return true;
1157 }
Diana Picus865f7fe2018-01-04 13:09:25 +00001158 case G_PHI: {
1159 I.setDesc(TII.get(PHI));
1160
Daniel Sanders0c476112019-08-15 19:22:08 +00001161 Register DstReg = I.getOperand(0).getReg();
Diana Picus865f7fe2018-01-04 13:09:25 +00001162 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
1163 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1164 break;
1165 }
1166
1167 return true;
1168 }
Diana Picus519807f2016-12-19 11:26:31 +00001169 default:
1170 return false;
Diana Picus812caee2016-12-16 12:54:46 +00001171 }
1172
Diana Picus519807f2016-12-19 11:26:31 +00001173 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
Diana Picus22274932016-11-11 08:27:37 +00001174}