blob: 6364ffbc753ac52f2a748212d30bd38fbf12523e [file] [log] [blame]
Diana Picus22274932016-11-11 08:27:37 +00001//===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// This file implements the targeting of the InstructionSelector class for ARM.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
Diana Picus22274932016-11-11 08:27:37 +000014#include "ARMRegisterBankInfo.h"
15#include "ARMSubtarget.h"
16#include "ARMTargetMachine.h"
Diana Picus674888d2017-04-28 09:10:38 +000017#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
Diana 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
Daniel Sanders6ab0daa2017-07-04 14:35:06 +000024#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
25
Diana Picus22274932016-11-11 08:27:37 +000026using namespace llvm;
27
28#ifndef LLVM_BUILD_GLOBAL_ISEL
29#error "You shouldn't build this"
30#endif
31
Diana Picus674888d2017-04-28 09:10:38 +000032namespace {
Diana Picus8abcbbb2017-05-02 09:40:49 +000033
34#define GET_GLOBALISEL_PREDICATE_BITSET
35#include "ARMGenGlobalISel.inc"
36#undef GET_GLOBALISEL_PREDICATE_BITSET
37
Diana Picus674888d2017-04-28 09:10:38 +000038class ARMInstructionSelector : public InstructionSelector {
39public:
Diana Picus8abcbbb2017-05-02 09:40:49 +000040 ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000041 const ARMRegisterBankInfo &RBI);
42
43 bool select(MachineInstr &I) const override;
44
45private:
Diana Picus8abcbbb2017-05-02 09:40:49 +000046 bool selectImpl(MachineInstr &I) const;
47
Diana Picus995746d2017-07-12 10:31:16 +000048 struct CmpConstants;
49 struct InsertInfo;
Diana Picus5b916532017-07-07 08:39:04 +000050
Diana Picus995746d2017-07-12 10:31:16 +000051 bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
52 MachineRegisterInfo &MRI) const;
Diana Picus621894a2017-06-19 09:40:51 +000053
Diana Picus995746d2017-07-12 10:31:16 +000054 // Helper for inserting a comparison sequence that sets \p ResReg to either 1
55 // if \p LHSReg and \p RHSReg are in the relationship defined by \p Cond, or
56 // \p PrevRes otherwise. In essence, it computes PrevRes OR (LHS Cond RHS).
57 bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
58 ARMCC::CondCodes Cond, unsigned LHSReg, unsigned RHSReg,
59 unsigned PrevRes) const;
60
61 // Set \p DestReg to \p Constant.
62 void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
63
Diana Picus930e6ec2017-08-03 09:14:59 +000064 bool selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
Diana Picus995746d2017-07-12 10:31:16 +000065 bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
66
67 // Check if the types match and both operands have the expected size and
68 // register bank.
69 bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
70 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
71
72 // Check if the register has the expected size and register bank.
73 bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
74 unsigned ExpectedRegBankID) const;
Diana Picus7145d222017-06-27 09:19:51 +000075
Diana Picus674888d2017-04-28 09:10:38 +000076 const ARMBaseInstrInfo &TII;
77 const ARMBaseRegisterInfo &TRI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000078 const ARMBaseTargetMachine &TM;
Diana Picus674888d2017-04-28 09:10:38 +000079 const ARMRegisterBankInfo &RBI;
Diana Picus8abcbbb2017-05-02 09:40:49 +000080 const ARMSubtarget &STI;
81
82#define GET_GLOBALISEL_PREDICATES_DECL
83#include "ARMGenGlobalISel.inc"
84#undef GET_GLOBALISEL_PREDICATES_DECL
85
86// We declare the temporaries used by selectImpl() in the class to minimize the
87// cost of constructing placeholder values.
88#define GET_GLOBALISEL_TEMPORARIES_DECL
89#include "ARMGenGlobalISel.inc"
90#undef GET_GLOBALISEL_TEMPORARIES_DECL
Diana Picus674888d2017-04-28 09:10:38 +000091};
92} // end anonymous namespace
93
94namespace llvm {
95InstructionSelector *
Diana Picus8abcbbb2017-05-02 09:40:49 +000096createARMInstructionSelector(const ARMBaseTargetMachine &TM,
97 const ARMSubtarget &STI,
Diana Picus674888d2017-04-28 09:10:38 +000098 const ARMRegisterBankInfo &RBI) {
Diana Picus8abcbbb2017-05-02 09:40:49 +000099 return new ARMInstructionSelector(TM, STI, RBI);
Diana Picus674888d2017-04-28 09:10:38 +0000100}
101}
102
Daniel Sanders8e82af22017-07-27 11:03:45 +0000103const unsigned zero_reg = 0;
Diana Picus8abcbbb2017-05-02 09:40:49 +0000104
105#define GET_GLOBALISEL_IMPL
106#include "ARMGenGlobalISel.inc"
107#undef GET_GLOBALISEL_IMPL
108
109ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
110 const ARMSubtarget &STI,
Diana Picus22274932016-11-11 08:27:37 +0000111 const ARMRegisterBankInfo &RBI)
Diana Picus895c6aa2016-11-15 16:42:10 +0000112 : InstructionSelector(), TII(*STI.getInstrInfo()),
Diana Picus8abcbbb2017-05-02 09:40:49 +0000113 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
114#define GET_GLOBALISEL_PREDICATES_INIT
115#include "ARMGenGlobalISel.inc"
116#undef GET_GLOBALISEL_PREDICATES_INIT
117#define GET_GLOBALISEL_TEMPORARIES_INIT
118#include "ARMGenGlobalISel.inc"
119#undef GET_GLOBALISEL_TEMPORARIES_INIT
120{
121}
Diana Picus22274932016-11-11 08:27:37 +0000122
Diana Picus812caee2016-12-16 12:54:46 +0000123static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
124 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
125 const RegisterBankInfo &RBI) {
126 unsigned DstReg = I.getOperand(0).getReg();
127 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
128 return true;
129
130 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
Benjamin Kramer24bf8682016-12-16 13:13:03 +0000131 (void)RegBank;
Diana Picus812caee2016-12-16 12:54:46 +0000132 assert(RegBank && "Can't get reg bank for virtual register");
133
Diana Picus36aa09f2016-12-19 14:07:50 +0000134 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Diana Picus4fa83c02017-02-08 13:23:04 +0000135 assert((RegBank->getID() == ARM::GPRRegBankID ||
136 RegBank->getID() == ARM::FPRRegBankID) &&
137 "Unsupported reg bank");
138
Diana Picus812caee2016-12-16 12:54:46 +0000139 const TargetRegisterClass *RC = &ARM::GPRRegClass;
140
Diana Picus4fa83c02017-02-08 13:23:04 +0000141 if (RegBank->getID() == ARM::FPRRegBankID) {
Diana Picus6beef3c2017-02-16 12:19:52 +0000142 if (DstSize == 32)
143 RC = &ARM::SPRRegClass;
144 else if (DstSize == 64)
145 RC = &ARM::DPRRegClass;
146 else
147 llvm_unreachable("Unsupported destination size");
Diana Picus4fa83c02017-02-08 13:23:04 +0000148 }
149
Diana Picus812caee2016-12-16 12:54:46 +0000150 // No need to constrain SrcReg. It will get constrained when
151 // we hit another of its uses or its defs.
152 // Copies do not have constraints.
153 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
154 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
155 << " operand\n");
156 return false;
157 }
158 return true;
159}
160
Diana Picus0b4190a2017-06-07 12:35:05 +0000161static bool selectMergeValues(MachineInstrBuilder &MIB,
162 const ARMBaseInstrInfo &TII,
163 MachineRegisterInfo &MRI,
164 const TargetRegisterInfo &TRI,
165 const RegisterBankInfo &RBI) {
166 assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000167
Diana Picus0b4190a2017-06-07 12:35:05 +0000168 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
Diana Picusb1701e02017-02-16 12:19:57 +0000169 // into one DPR.
170 unsigned VReg0 = MIB->getOperand(0).getReg();
171 (void)VReg0;
172 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
173 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000174 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000175 unsigned VReg1 = MIB->getOperand(1).getReg();
176 (void)VReg1;
177 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
178 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000179 "Unsupported operand for G_MERGE_VALUES");
180 unsigned VReg2 = MIB->getOperand(2).getReg();
Diana Picusb1701e02017-02-16 12:19:57 +0000181 (void)VReg2;
182 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
183 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000184 "Unsupported operand for G_MERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000185
186 MIB->setDesc(TII.get(ARM::VMOVDRR));
187 MIB.add(predOps(ARMCC::AL));
188
189 return true;
190}
191
Diana Picus0b4190a2017-06-07 12:35:05 +0000192static bool selectUnmergeValues(MachineInstrBuilder &MIB,
193 const ARMBaseInstrInfo &TII,
194 MachineRegisterInfo &MRI,
195 const TargetRegisterInfo &TRI,
196 const RegisterBankInfo &RBI) {
197 assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP");
Diana Picusb1701e02017-02-16 12:19:57 +0000198
Diana Picus0b4190a2017-06-07 12:35:05 +0000199 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
200 // GPRs.
Diana Picusb1701e02017-02-16 12:19:57 +0000201 unsigned VReg0 = MIB->getOperand(0).getReg();
202 (void)VReg0;
203 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
204 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
Diana Picus0b4190a2017-06-07 12:35:05 +0000205 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000206 unsigned VReg1 = MIB->getOperand(1).getReg();
207 (void)VReg1;
Diana Picus0b4190a2017-06-07 12:35:05 +0000208 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
209 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
210 "Unsupported operand for G_UNMERGE_VALUES");
211 unsigned VReg2 = MIB->getOperand(2).getReg();
212 (void)VReg2;
213 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
214 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
215 "Unsupported operand for G_UNMERGE_VALUES");
Diana Picusb1701e02017-02-16 12:19:57 +0000216
Diana Picus0b4190a2017-06-07 12:35:05 +0000217 MIB->setDesc(TII.get(ARM::VMOVRRD));
Diana Picusb1701e02017-02-16 12:19:57 +0000218 MIB.add(predOps(ARMCC::AL));
219
220 return true;
221}
222
Diana Picus8b6c6be2017-01-25 08:10:40 +0000223/// Select the opcode for simple extensions (that translate to a single SXT/UXT
224/// instruction). Extension operations more complicated than that should not
Diana Picuse8368782017-02-17 13:44:19 +0000225/// invoke this. Returns the original opcode if it doesn't know how to select a
226/// better one.
Diana Picus8b6c6be2017-01-25 08:10:40 +0000227static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) {
228 using namespace TargetOpcode;
229
Diana Picuse8368782017-02-17 13:44:19 +0000230 if (Size != 8 && Size != 16)
231 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000232
233 if (Opc == G_SEXT)
234 return Size == 8 ? ARM::SXTB : ARM::SXTH;
235
236 if (Opc == G_ZEXT)
237 return Size == 8 ? ARM::UXTB : ARM::UXTH;
238
Diana Picuse8368782017-02-17 13:44:19 +0000239 return Opc;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000240}
241
Diana Picus3b99c642017-02-24 14:01:27 +0000242/// Select the opcode for simple loads and stores. For types smaller than 32
243/// bits, the value will be zero extended. Returns the original opcode if it
244/// doesn't know how to select a better one.
245static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
246 unsigned Size) {
247 bool isStore = Opc == TargetOpcode::G_STORE;
248
Diana Picus1540b062017-02-16 14:10:50 +0000249 if (RegBank == ARM::GPRRegBankID) {
250 switch (Size) {
251 case 1:
252 case 8:
Diana Picus3b99c642017-02-24 14:01:27 +0000253 return isStore ? ARM::STRBi12 : ARM::LDRBi12;
Diana Picus1540b062017-02-16 14:10:50 +0000254 case 16:
Diana Picus3b99c642017-02-24 14:01:27 +0000255 return isStore ? ARM::STRH : ARM::LDRH;
Diana Picus1540b062017-02-16 14:10:50 +0000256 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000257 return isStore ? ARM::STRi12 : ARM::LDRi12;
Diana Picuse8368782017-02-17 13:44:19 +0000258 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000259 return Opc;
Diana Picus1540b062017-02-16 14:10:50 +0000260 }
Diana Picus1540b062017-02-16 14:10:50 +0000261 }
262
Diana Picuse8368782017-02-17 13:44:19 +0000263 if (RegBank == ARM::FPRRegBankID) {
264 switch (Size) {
265 case 32:
Diana Picus3b99c642017-02-24 14:01:27 +0000266 return isStore ? ARM::VSTRS : ARM::VLDRS;
Diana Picuse8368782017-02-17 13:44:19 +0000267 case 64:
Diana Picus3b99c642017-02-24 14:01:27 +0000268 return isStore ? ARM::VSTRD : ARM::VLDRD;
Diana Picuse8368782017-02-17 13:44:19 +0000269 default:
Diana Picus3b99c642017-02-24 14:01:27 +0000270 return Opc;
Diana Picuse8368782017-02-17 13:44:19 +0000271 }
Diana Picus278c7222017-01-26 09:20:47 +0000272 }
273
Diana Picus3b99c642017-02-24 14:01:27 +0000274 return Opc;
Diana Picus278c7222017-01-26 09:20:47 +0000275}
276
Diana Picus5b916532017-07-07 08:39:04 +0000277// When lowering comparisons, we sometimes need to perform two compares instead
278// of just one. Get the condition codes for both comparisons. If only one is
279// needed, the second member of the pair is ARMCC::AL.
280static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
281getComparePreds(CmpInst::Predicate Pred) {
282 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
Diana Picus621894a2017-06-19 09:40:51 +0000283 switch (Pred) {
Diana Picus621894a2017-06-19 09:40:51 +0000284 case CmpInst::FCMP_ONE:
Diana Picus5b916532017-07-07 08:39:04 +0000285 Preds = {ARMCC::GT, ARMCC::MI};
286 break;
Diana Picus621894a2017-06-19 09:40:51 +0000287 case CmpInst::FCMP_UEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000288 Preds = {ARMCC::EQ, ARMCC::VS};
289 break;
Diana Picus621894a2017-06-19 09:40:51 +0000290 case CmpInst::ICMP_EQ:
291 case CmpInst::FCMP_OEQ:
Diana Picus5b916532017-07-07 08:39:04 +0000292 Preds.first = ARMCC::EQ;
293 break;
Diana Picus621894a2017-06-19 09:40:51 +0000294 case CmpInst::ICMP_SGT:
295 case CmpInst::FCMP_OGT:
Diana Picus5b916532017-07-07 08:39:04 +0000296 Preds.first = ARMCC::GT;
297 break;
Diana Picus621894a2017-06-19 09:40:51 +0000298 case CmpInst::ICMP_SGE:
299 case CmpInst::FCMP_OGE:
Diana Picus5b916532017-07-07 08:39:04 +0000300 Preds.first = ARMCC::GE;
301 break;
Diana Picus621894a2017-06-19 09:40:51 +0000302 case CmpInst::ICMP_UGT:
303 case CmpInst::FCMP_UGT:
Diana Picus5b916532017-07-07 08:39:04 +0000304 Preds.first = ARMCC::HI;
305 break;
Diana Picus621894a2017-06-19 09:40:51 +0000306 case CmpInst::FCMP_OLT:
Diana Picus5b916532017-07-07 08:39:04 +0000307 Preds.first = ARMCC::MI;
308 break;
Diana Picus621894a2017-06-19 09:40:51 +0000309 case CmpInst::ICMP_ULE:
310 case CmpInst::FCMP_OLE:
Diana Picus5b916532017-07-07 08:39:04 +0000311 Preds.first = ARMCC::LS;
312 break;
Diana Picus621894a2017-06-19 09:40:51 +0000313 case CmpInst::FCMP_ORD:
Diana Picus5b916532017-07-07 08:39:04 +0000314 Preds.first = ARMCC::VC;
315 break;
Diana Picus621894a2017-06-19 09:40:51 +0000316 case CmpInst::FCMP_UNO:
Diana Picus5b916532017-07-07 08:39:04 +0000317 Preds.first = ARMCC::VS;
318 break;
Diana Picus621894a2017-06-19 09:40:51 +0000319 case CmpInst::FCMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000320 Preds.first = ARMCC::PL;
321 break;
Diana Picus621894a2017-06-19 09:40:51 +0000322 case CmpInst::ICMP_SLT:
323 case CmpInst::FCMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000324 Preds.first = ARMCC::LT;
325 break;
Diana Picus621894a2017-06-19 09:40:51 +0000326 case CmpInst::ICMP_SLE:
327 case CmpInst::FCMP_ULE:
Diana Picus5b916532017-07-07 08:39:04 +0000328 Preds.first = ARMCC::LE;
329 break;
Diana Picus621894a2017-06-19 09:40:51 +0000330 case CmpInst::FCMP_UNE:
331 case CmpInst::ICMP_NE:
Diana Picus5b916532017-07-07 08:39:04 +0000332 Preds.first = ARMCC::NE;
333 break;
Diana Picus621894a2017-06-19 09:40:51 +0000334 case CmpInst::ICMP_UGE:
Diana Picus5b916532017-07-07 08:39:04 +0000335 Preds.first = ARMCC::HS;
336 break;
Diana Picus621894a2017-06-19 09:40:51 +0000337 case CmpInst::ICMP_ULT:
Diana Picus5b916532017-07-07 08:39:04 +0000338 Preds.first = ARMCC::LO;
339 break;
340 default:
341 break;
Diana Picus621894a2017-06-19 09:40:51 +0000342 }
Diana Picus5b916532017-07-07 08:39:04 +0000343 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
344 return Preds;
Diana Picus621894a2017-06-19 09:40:51 +0000345}
346
Diana Picus995746d2017-07-12 10:31:16 +0000347struct ARMInstructionSelector::CmpConstants {
348 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned OpRegBank,
349 unsigned OpSize)
350 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
351 OperandRegBankID(OpRegBank), OperandSize(OpSize) {}
Diana Picus621894a2017-06-19 09:40:51 +0000352
Diana Picus5b916532017-07-07 08:39:04 +0000353 // The opcode used for performing the comparison.
Diana Picus995746d2017-07-12 10:31:16 +0000354 const unsigned ComparisonOpcode;
Diana Picus621894a2017-06-19 09:40:51 +0000355
Diana Picus5b916532017-07-07 08:39:04 +0000356 // The opcode used for reading the flags set by the comparison. May be
357 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
Diana Picus995746d2017-07-12 10:31:16 +0000358 const unsigned ReadFlagsOpcode;
Diana Picus5b916532017-07-07 08:39:04 +0000359
360 // The assumed register bank ID for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000361 const unsigned OperandRegBankID;
Diana Picus5b916532017-07-07 08:39:04 +0000362
Diana Picus21014df2017-07-12 09:01:54 +0000363 // The assumed size in bits for the operands.
Diana Picus995746d2017-07-12 10:31:16 +0000364 const unsigned OperandSize;
Diana Picus5b916532017-07-07 08:39:04 +0000365};
366
Diana Picus995746d2017-07-12 10:31:16 +0000367struct ARMInstructionSelector::InsertInfo {
368 InsertInfo(MachineInstrBuilder &MIB)
369 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
370 DbgLoc(MIB->getDebugLoc()) {}
Diana Picus5b916532017-07-07 08:39:04 +0000371
Diana Picus995746d2017-07-12 10:31:16 +0000372 MachineBasicBlock &MBB;
373 const MachineBasicBlock::instr_iterator InsertBefore;
374 const DebugLoc &DbgLoc;
375};
Diana Picus5b916532017-07-07 08:39:04 +0000376
Diana Picus995746d2017-07-12 10:31:16 +0000377void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
378 unsigned Constant) const {
379 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVi))
380 .addDef(DestReg)
381 .addImm(Constant)
382 .add(predOps(ARMCC::AL))
383 .add(condCodeOp());
384}
Diana Picus21014df2017-07-12 09:01:54 +0000385
Diana Picus995746d2017-07-12 10:31:16 +0000386bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
387 unsigned LHSReg, unsigned RHSReg,
388 unsigned ExpectedSize,
389 unsigned ExpectedRegBankID) const {
390 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
391 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
392 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
393}
Diana Picus5b916532017-07-07 08:39:04 +0000394
Diana Picus995746d2017-07-12 10:31:16 +0000395bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
396 unsigned ExpectedSize,
397 unsigned ExpectedRegBankID) const {
398 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
399 DEBUG(dbgs() << "Unexpected size for register");
400 return false;
401 }
402
403 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
404 DEBUG(dbgs() << "Unexpected register bank for register");
405 return false;
406 }
407
408 return true;
409}
410
411bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
412 MachineInstrBuilder &MIB,
413 MachineRegisterInfo &MRI) const {
414 const InsertInfo I(MIB);
Diana Picus5b916532017-07-07 08:39:04 +0000415
Diana Picus621894a2017-06-19 09:40:51 +0000416 auto ResReg = MIB->getOperand(0).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000417 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
Diana Picus5b916532017-07-07 08:39:04 +0000418 return false;
419
Diana Picus621894a2017-06-19 09:40:51 +0000420 auto Cond =
421 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
Diana Picus5b916532017-07-07 08:39:04 +0000422 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
Diana Picus995746d2017-07-12 10:31:16 +0000423 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
Diana Picus5b916532017-07-07 08:39:04 +0000424 MIB->eraseFromParent();
425 return true;
426 }
427
428 auto LHSReg = MIB->getOperand(2).getReg();
429 auto RHSReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000430 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
431 Helper.OperandRegBankID))
Diana Picus621894a2017-06-19 09:40:51 +0000432 return false;
433
Diana Picus5b916532017-07-07 08:39:04 +0000434 auto ARMConds = getComparePreds(Cond);
Diana Picus995746d2017-07-12 10:31:16 +0000435 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
436 putConstant(I, ZeroReg, 0);
Diana Picus5b916532017-07-07 08:39:04 +0000437
438 if (ARMConds.second == ARMCC::AL) {
439 // Simple case, we only need one comparison and we're done.
Diana Picus995746d2017-07-12 10:31:16 +0000440 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
441 ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000442 return false;
443 } else {
444 // Not so simple, we need two successive comparisons.
445 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
Diana Picus995746d2017-07-12 10:31:16 +0000446 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
447 RHSReg, ZeroReg))
Diana Picus5b916532017-07-07 08:39:04 +0000448 return false;
Diana Picus995746d2017-07-12 10:31:16 +0000449 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
450 IntermediateRes))
Diana Picus5b916532017-07-07 08:39:04 +0000451 return false;
452 }
Diana Picus621894a2017-06-19 09:40:51 +0000453
454 MIB->eraseFromParent();
455 return true;
456}
457
Diana Picus995746d2017-07-12 10:31:16 +0000458bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
459 unsigned ResReg,
460 ARMCC::CondCodes Cond,
461 unsigned LHSReg, unsigned RHSReg,
462 unsigned PrevRes) const {
463 // Perform the comparison.
464 auto CmpI =
465 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
466 .addUse(LHSReg)
467 .addUse(RHSReg)
468 .add(predOps(ARMCC::AL));
469 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
470 return false;
471
472 // Read the comparison flags (if necessary).
473 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
474 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
475 TII.get(Helper.ReadFlagsOpcode))
476 .add(predOps(ARMCC::AL));
477 if (!constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI))
478 return false;
479 }
480
481 // Select either 1 or the previous result based on the value of the flags.
482 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVCCi))
483 .addDef(ResReg)
484 .addUse(PrevRes)
485 .addImm(1)
486 .add(predOps(Cond, ARM::CPSR));
487 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
488 return false;
489
490 return true;
491}
492
Diana Picus930e6ec2017-08-03 09:14:59 +0000493bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
494 MachineRegisterInfo &MRI) const {
495 if (TII.getSubtarget().isROPI() || TII.getSubtarget().isRWPI()) {
496 DEBUG(dbgs() << "ROPI and RWPI not supported yet\n");
497 return false;
498 }
499 if (TM.isPositionIndependent()) {
500 DEBUG(dbgs() << "PIC not supported yet\n");
501 return false;
502 }
503
504 auto GV = MIB->getOperand(1).getGlobal();
505 if (GV->isThreadLocal()) {
506 DEBUG(dbgs() << "TLS variables not supported yet\n");
507 return false;
508 }
509
510 auto &MBB = *MIB->getParent();
511 auto &MF = *MBB.getParent();
512
513 auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat();
514 bool UseMovt = TII.getSubtarget().useMovt(MF);
515
516 if (ObjectFormat == Triple::ELF) {
517 if (UseMovt) {
518 MIB->setDesc(TII.get(ARM::MOVi32imm));
519 } else {
520 // Load the global's address from the constant pool.
521 MIB->setDesc(TII.get(ARM::LDRi12));
522 MIB->RemoveOperand(1);
523 unsigned Alignment = 4;
524 MIB.addConstantPoolIndex(
525 MF.getConstantPool()->getConstantPoolIndex(GV, Alignment),
526 /* Offset */ 0, /* TargetFlags */ 0)
527 .addMemOperand(MF.getMachineMemOperand(
528 MachinePointerInfo::getConstantPool(MF),
529 MachineMemOperand::MOLoad, TM.getPointerSize(), Alignment))
530 .addImm(0)
531 .add(predOps(ARMCC::AL));
532 }
533 } else if (ObjectFormat == Triple::MachO) {
534 if (UseMovt)
535 MIB->setDesc(TII.get(ARM::MOVi32imm));
536 else
537 MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs));
538 } else {
539 DEBUG(dbgs() << "Object format not supported yet\n");
540 return false;
541 }
542
543 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
544}
545
Diana Picus7145d222017-06-27 09:19:51 +0000546bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
Diana Picus995746d2017-07-12 10:31:16 +0000547 MachineRegisterInfo &MRI) const {
Diana Picus7145d222017-06-27 09:19:51 +0000548 auto &MBB = *MIB->getParent();
549 auto InsertBefore = std::next(MIB->getIterator());
Diana Picus77367372017-07-07 08:53:27 +0000550 auto &DbgLoc = MIB->getDebugLoc();
Diana Picus7145d222017-06-27 09:19:51 +0000551
552 // Compare the condition to 0.
553 auto CondReg = MIB->getOperand(1).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000554 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000555 "Unsupported types for select operation");
Diana Picus77367372017-07-07 08:53:27 +0000556 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri))
Diana Picus7145d222017-06-27 09:19:51 +0000557 .addUse(CondReg)
558 .addImm(0)
559 .add(predOps(ARMCC::AL));
560 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
561 return false;
562
563 // Move a value into the result register based on the result of the
564 // comparison.
565 auto ResReg = MIB->getOperand(0).getReg();
566 auto TrueReg = MIB->getOperand(2).getReg();
567 auto FalseReg = MIB->getOperand(3).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000568 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
569 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
Diana Picus7145d222017-06-27 09:19:51 +0000570 "Unsupported types for select operation");
Diana Picus77367372017-07-07 08:53:27 +0000571 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr))
Diana Picus7145d222017-06-27 09:19:51 +0000572 .addDef(ResReg)
573 .addUse(TrueReg)
574 .addUse(FalseReg)
575 .add(predOps(ARMCC::EQ, ARM::CPSR));
576 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
577 return false;
578
579 MIB->eraseFromParent();
580 return true;
581}
582
Diana Picus812caee2016-12-16 12:54:46 +0000583bool ARMInstructionSelector::select(MachineInstr &I) const {
584 assert(I.getParent() && "Instruction should be in a basic block!");
585 assert(I.getParent()->getParent() && "Instruction should be in a function!");
586
587 auto &MBB = *I.getParent();
588 auto &MF = *MBB.getParent();
589 auto &MRI = MF.getRegInfo();
590
591 if (!isPreISelGenericOpcode(I.getOpcode())) {
592 if (I.isCopy())
593 return selectCopy(I, TII, MRI, TRI, RBI);
594
595 return true;
596 }
597
Diana Picus8abcbbb2017-05-02 09:40:49 +0000598 if (selectImpl(I))
599 return true;
600
Diana Picus519807f2016-12-19 11:26:31 +0000601 MachineInstrBuilder MIB{MF, I};
Diana Picusd83df5d2017-01-25 08:47:40 +0000602 bool isSExt = false;
Diana Picus519807f2016-12-19 11:26:31 +0000603
604 using namespace TargetOpcode;
605 switch (I.getOpcode()) {
Diana Picus8b6c6be2017-01-25 08:10:40 +0000606 case G_SEXT:
Diana Picusd83df5d2017-01-25 08:47:40 +0000607 isSExt = true;
608 LLVM_FALLTHROUGH;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000609 case G_ZEXT: {
610 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
611 // FIXME: Smaller destination sizes coming soon!
612 if (DstTy.getSizeInBits() != 32) {
613 DEBUG(dbgs() << "Unsupported destination size for extension");
614 return false;
615 }
616
617 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
618 unsigned SrcSize = SrcTy.getSizeInBits();
619 switch (SrcSize) {
Diana Picusd83df5d2017-01-25 08:47:40 +0000620 case 1: {
621 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
622 I.setDesc(TII.get(ARM::ANDri));
623 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp());
624
625 if (isSExt) {
626 unsigned SExtResult = I.getOperand(0).getReg();
627
628 // Use a new virtual register for the result of the AND
629 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
630 I.getOperand(0).setReg(AndResult);
631
632 auto InsertBefore = std::next(I.getIterator());
Martin Bohme8396e142017-01-25 14:28:19 +0000633 auto SubI =
Diana Picusd83df5d2017-01-25 08:47:40 +0000634 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri))
635 .addDef(SExtResult)
636 .addUse(AndResult)
637 .addImm(0)
638 .add(predOps(ARMCC::AL))
639 .add(condCodeOp());
640 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
641 return false;
642 }
643 break;
644 }
Diana Picus8b6c6be2017-01-25 08:10:40 +0000645 case 8:
646 case 16: {
647 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
Diana Picuse8368782017-02-17 13:44:19 +0000648 if (NewOpc == I.getOpcode())
649 return false;
Diana Picus8b6c6be2017-01-25 08:10:40 +0000650 I.setDesc(TII.get(NewOpc));
651 MIB.addImm(0).add(predOps(ARMCC::AL));
652 break;
653 }
654 default:
655 DEBUG(dbgs() << "Unsupported source size for extension");
656 return false;
657 }
658 break;
659 }
Diana Picus657bfd32017-05-11 08:28:31 +0000660 case G_ANYEXT:
Diana Picus64a33432017-04-21 13:16:50 +0000661 case G_TRUNC: {
662 // The high bits are undefined, so there's nothing special to do, just
663 // treat it as a copy.
664 auto SrcReg = I.getOperand(1).getReg();
665 auto DstReg = I.getOperand(0).getReg();
666
667 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
668 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
669
670 if (SrcRegBank.getID() != DstRegBank.getID()) {
Diana Picus657bfd32017-05-11 08:28:31 +0000671 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
Diana Picus64a33432017-04-21 13:16:50 +0000672 return false;
673 }
674
675 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
Diana Picus657bfd32017-05-11 08:28:31 +0000676 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
Diana Picus64a33432017-04-21 13:16:50 +0000677 return false;
678 }
679
680 I.setDesc(TII.get(COPY));
681 return selectCopy(I, TII, MRI, TRI, RBI);
682 }
Diana Picus7145d222017-06-27 09:19:51 +0000683 case G_SELECT:
Diana Picus995746d2017-07-12 10:31:16 +0000684 return selectSelect(MIB, MRI);
685 case G_ICMP: {
686 CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END,
687 ARM::GPRRegBankID, 32);
688 return selectCmp(Helper, MIB, MRI);
689 }
Diana Picus21014df2017-07-12 09:01:54 +0000690 case G_FCMP: {
Diana Picus5b916532017-07-07 08:39:04 +0000691 assert(TII.getSubtarget().hasVFP2() && "Can't select fcmp without VFP");
Diana Picus21014df2017-07-12 09:01:54 +0000692
693 unsigned OpReg = I.getOperand(2).getReg();
694 unsigned Size = MRI.getType(OpReg).getSizeInBits();
Diana Picus995746d2017-07-12 10:31:16 +0000695
696 if (Size == 64 && TII.getSubtarget().isFPOnlySP()) {
697 DEBUG(dbgs() << "Subtarget only supports single precision");
698 return false;
699 }
700 if (Size != 32 && Size != 64) {
701 DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
702 return false;
Diana Picus21014df2017-07-12 09:01:54 +0000703 }
704
Diana Picus995746d2017-07-12 10:31:16 +0000705 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
706 ARM::FPRRegBankID, Size);
707 return selectCmp(Helper, MIB, MRI);
Diana Picus21014df2017-07-12 09:01:54 +0000708 }
Diana Picus9d070942017-02-28 10:14:38 +0000709 case G_GEP:
Diana Picus812caee2016-12-16 12:54:46 +0000710 I.setDesc(TII.get(ARM::ADDrr));
Diana Picus8a73f552017-01-13 10:18:01 +0000711 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000712 break;
713 case G_FRAME_INDEX:
714 // Add 0 to the given frame index and hope it will eventually be folded into
715 // the user(s).
716 I.setDesc(TII.get(ARM::ADDri));
Diana Picus8a73f552017-01-13 10:18:01 +0000717 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus519807f2016-12-19 11:26:31 +0000718 break;
Diana Picus5a7203a2017-02-28 13:05:42 +0000719 case G_CONSTANT: {
720 unsigned Reg = I.getOperand(0).getReg();
Diana Picus995746d2017-07-12 10:31:16 +0000721
722 if (!validReg(MRI, Reg, 32, ARM::GPRRegBankID))
Diana Picus5a7203a2017-02-28 13:05:42 +0000723 return false;
724
Diana Picus5a7203a2017-02-28 13:05:42 +0000725 I.setDesc(TII.get(ARM::MOVi));
726 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
Diana Picus95a8aa92017-04-24 06:30:56 +0000727
728 auto &Val = I.getOperand(1);
729 if (Val.isCImm()) {
730 if (Val.getCImm()->getBitWidth() > 32)
731 return false;
732 Val.ChangeToImmediate(Val.getCImm()->getZExtValue());
733 }
734
735 if (!Val.isImm()) {
736 return false;
737 }
738
Diana Picus5a7203a2017-02-28 13:05:42 +0000739 break;
740 }
Diana Picus930e6ec2017-08-03 09:14:59 +0000741 case G_GLOBAL_VALUE:
742 return selectGlobal(MIB, MRI);
Diana Picus3b99c642017-02-24 14:01:27 +0000743 case G_STORE:
Diana Picus278c7222017-01-26 09:20:47 +0000744 case G_LOAD: {
Diana Picus1c33c9f2017-02-20 14:45:58 +0000745 const auto &MemOp = **I.memoperands_begin();
746 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
747 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
748 return false;
749 }
750
Diana Picus1540b062017-02-16 14:10:50 +0000751 unsigned Reg = I.getOperand(0).getReg();
752 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
753
754 LLT ValTy = MRI.getType(Reg);
Diana Picus278c7222017-01-26 09:20:47 +0000755 const auto ValSize = ValTy.getSizeInBits();
756
Diana Picus1540b062017-02-16 14:10:50 +0000757 assert((ValSize != 64 || TII.getSubtarget().hasVFP2()) &&
Diana Picus3b99c642017-02-24 14:01:27 +0000758 "Don't know how to load/store 64-bit value without VFP");
Diana Picus1540b062017-02-16 14:10:50 +0000759
Diana Picus3b99c642017-02-24 14:01:27 +0000760 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
761 if (NewOpc == G_LOAD || NewOpc == G_STORE)
Diana Picuse8368782017-02-17 13:44:19 +0000762 return false;
763
Diana Picus278c7222017-01-26 09:20:47 +0000764 I.setDesc(TII.get(NewOpc));
765
Diana Picus3b99c642017-02-24 14:01:27 +0000766 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
Diana Picus278c7222017-01-26 09:20:47 +0000767 // LDRH has a funny addressing mode (there's already a FIXME for it).
768 MIB.addReg(0);
Diana Picus4f8c3e12017-01-13 09:37:56 +0000769 MIB.addImm(0).add(predOps(ARMCC::AL));
Diana Picus519807f2016-12-19 11:26:31 +0000770 break;
Diana Picus278c7222017-01-26 09:20:47 +0000771 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000772 case G_MERGE_VALUES: {
773 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000774 return false;
775 break;
776 }
Diana Picus0b4190a2017-06-07 12:35:05 +0000777 case G_UNMERGE_VALUES: {
778 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
Diana Picusb1701e02017-02-16 12:19:57 +0000779 return false;
780 break;
781 }
Diana Picus87a70672017-07-14 09:46:06 +0000782 case G_BRCOND: {
783 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
784 DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
785 return false;
786 }
787
788 // Set the flags.
789 auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri))
790 .addReg(I.getOperand(0).getReg())
791 .addImm(1)
792 .add(predOps(ARMCC::AL));
793 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
794 return false;
795
796 // Branch conditionally.
797 auto Branch = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::Bcc))
798 .add(I.getOperand(1))
799 .add(predOps(ARMCC::EQ, ARM::CPSR));
800 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
801 return false;
802 I.eraseFromParent();
803 return true;
804 }
Diana Picus519807f2016-12-19 11:26:31 +0000805 default:
806 return false;
Diana Picus812caee2016-12-16 12:54:46 +0000807 }
808
Diana Picus519807f2016-12-19 11:26:31 +0000809 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
Diana Picus22274932016-11-11 08:27:37 +0000810}