blob: 0db4523c7ee248a062ee31952bfb5481a41fcab5 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//===- AArch64InstrInfo.cpp - AArch64 Instruction Information -------------===//
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//
10// This file contains the AArch64 implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AArch64InstrInfo.h"
15#include "AArch64Subtarget.h"
16#include "MCTargetDesc/AArch64AddressingModes.h"
17#include "llvm/CodeGen/MachineFrameInfo.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineMemOperand.h"
20#include "llvm/CodeGen/MachineRegisterInfo.h"
21#include "llvm/CodeGen/PseudoSourceValue.h"
Diana Picus4b972882016-09-13 07:45:17 +000022#include "llvm/CodeGen/StackMaps.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000023#include "llvm/MC/MCInst.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/TargetRegistry.h"
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +000026#include <algorithm>
Tim Northover3b0846e2014-05-24 12:50:23 +000027
28using namespace llvm;
29
30#define GET_INSTRINFO_CTOR_DTOR
31#include "AArch64GenInstrInfo.inc"
32
George Burgess IV381fc0e2016-08-25 01:05:08 +000033static const MachineMemOperand::Flags MOSuppressPair =
Justin Lebar288b3372016-07-14 18:15:20 +000034 MachineMemOperand::MOTargetFlag1;
35
Matt Arsenaulte8da1452016-08-02 08:06:17 +000036static cl::opt<unsigned>
37TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
38 cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
39
40static cl::opt<unsigned>
41CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
42 cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
43
44static cl::opt<unsigned>
45BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
46 cl::desc("Restrict range of Bcc instructions (DEBUG)"));
47
Tim Northover3b0846e2014-05-24 12:50:23 +000048AArch64InstrInfo::AArch64InstrInfo(const AArch64Subtarget &STI)
49 : AArch64GenInstrInfo(AArch64::ADJCALLSTACKDOWN, AArch64::ADJCALLSTACKUP),
Eric Christophera0de2532015-03-18 20:37:30 +000050 RI(STI.getTargetTriple()), Subtarget(STI) {}
Tim Northover3b0846e2014-05-24 12:50:23 +000051
52/// GetInstSize - Return the number of bytes of code the specified
53/// instruction may be. This returns the maximum number of bytes.
Sjoerd Meijer89217f82016-07-28 16:32:22 +000054unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000055 const MachineBasicBlock &MBB = *MI.getParent();
Tim Northoverd5531f72014-06-17 11:31:42 +000056 const MachineFunction *MF = MBB.getParent();
57 const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
Tim Northover3b0846e2014-05-24 12:50:23 +000058
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000059 if (MI.getOpcode() == AArch64::INLINEASM)
60 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
Tim Northoverd5531f72014-06-17 11:31:42 +000061
Diana Picus4b972882016-09-13 07:45:17 +000062 // FIXME: We currently only handle pseudoinstructions that don't get expanded
63 // before the assembly printer.
64 unsigned NumBytes = 0;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +000065 const MCInstrDesc &Desc = MI.getDesc();
Tim Northover3b0846e2014-05-24 12:50:23 +000066 switch (Desc.getOpcode()) {
67 default:
Diana Picusc65d8bd2016-07-27 15:13:25 +000068 // Anything not explicitly designated otherwise is a normal 4-byte insn.
Diana Picus4b972882016-09-13 07:45:17 +000069 NumBytes = 4;
70 break;
Tim Northover3b0846e2014-05-24 12:50:23 +000071 case TargetOpcode::DBG_VALUE:
72 case TargetOpcode::EH_LABEL:
73 case TargetOpcode::IMPLICIT_DEF:
74 case TargetOpcode::KILL:
Diana Picus4b972882016-09-13 07:45:17 +000075 NumBytes = 0;
76 break;
77 case TargetOpcode::STACKMAP:
78 // The upper bound for a stackmap intrinsic is the full length of its shadow
79 NumBytes = StackMapOpers(&MI).getNumPatchBytes();
80 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
81 break;
82 case TargetOpcode::PATCHPOINT:
83 // The size of the patchpoint intrinsic is the number of bytes requested
84 NumBytes = PatchPointOpers(&MI).getNumPatchBytes();
85 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
86 break;
Diana Picusab5a4c72016-08-01 08:38:49 +000087 case AArch64::TLSDESC_CALLSEQ:
88 // This gets lowered to an instruction sequence which takes 16 bytes
Diana Picus4b972882016-09-13 07:45:17 +000089 NumBytes = 16;
90 break;
Tim Northover3b0846e2014-05-24 12:50:23 +000091 }
92
Diana Picus4b972882016-09-13 07:45:17 +000093 return NumBytes;
Tim Northover3b0846e2014-05-24 12:50:23 +000094}
95
96static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,
97 SmallVectorImpl<MachineOperand> &Cond) {
98 // Block ends with fall-through condbranch.
99 switch (LastInst->getOpcode()) {
100 default:
101 llvm_unreachable("Unknown branch instruction?");
102 case AArch64::Bcc:
103 Target = LastInst->getOperand(1).getMBB();
104 Cond.push_back(LastInst->getOperand(0));
105 break;
106 case AArch64::CBZW:
107 case AArch64::CBZX:
108 case AArch64::CBNZW:
109 case AArch64::CBNZX:
110 Target = LastInst->getOperand(1).getMBB();
111 Cond.push_back(MachineOperand::CreateImm(-1));
112 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
113 Cond.push_back(LastInst->getOperand(0));
114 break;
115 case AArch64::TBZW:
116 case AArch64::TBZX:
117 case AArch64::TBNZW:
118 case AArch64::TBNZX:
119 Target = LastInst->getOperand(2).getMBB();
120 Cond.push_back(MachineOperand::CreateImm(-1));
121 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
122 Cond.push_back(LastInst->getOperand(0));
123 Cond.push_back(LastInst->getOperand(1));
124 }
125}
126
Matt Arsenaulte8da1452016-08-02 08:06:17 +0000127static unsigned getBranchDisplacementBits(unsigned Opc) {
128 switch (Opc) {
129 default:
130 llvm_unreachable("unexpected opcode!");
Matt Arsenault0a3ea892016-10-06 15:38:09 +0000131 case AArch64::B:
132 return 64;
Matt Arsenaulte8da1452016-08-02 08:06:17 +0000133 case AArch64::TBNZW:
134 case AArch64::TBZW:
135 case AArch64::TBNZX:
136 case AArch64::TBZX:
137 return TBZDisplacementBits;
138 case AArch64::CBNZW:
139 case AArch64::CBZW:
140 case AArch64::CBNZX:
141 case AArch64::CBZX:
142 return CBZDisplacementBits;
143 case AArch64::Bcc:
144 return BCCDisplacementBits;
145 }
146}
147
Matt Arsenault0a3ea892016-10-06 15:38:09 +0000148bool AArch64InstrInfo::isBranchOffsetInRange(unsigned BranchOp,
149 int64_t BrOffset) const {
150 unsigned Bits = getBranchDisplacementBits(BranchOp);
151 assert(Bits >= 3 && "max branch displacement must be enough to jump"
152 "over conditional branch expansion");
153 return isIntN(Bits, BrOffset / 4);
Matt Arsenaulte8da1452016-08-02 08:06:17 +0000154}
155
Matt Arsenault0a3ea892016-10-06 15:38:09 +0000156MachineBasicBlock *AArch64InstrInfo::getBranchDestBlock(
157 const MachineInstr &MI) const {
158 switch (MI.getOpcode()) {
159 default:
160 llvm_unreachable("unexpected opcode!");
161 case AArch64::B:
162 return MI.getOperand(0).getMBB();
163 case AArch64::TBZW:
164 case AArch64::TBNZW:
165 case AArch64::TBZX:
166 case AArch64::TBNZX:
167 return MI.getOperand(2).getMBB();
168 case AArch64::CBZW:
169 case AArch64::CBNZW:
170 case AArch64::CBZX:
171 case AArch64::CBNZX:
172 case AArch64::Bcc:
173 return MI.getOperand(1).getMBB();
174 }
Matt Arsenaulte8da1452016-08-02 08:06:17 +0000175}
176
Tim Northover3b0846e2014-05-24 12:50:23 +0000177// Branch analysis.
Jacques Pienaar71c30a12016-07-15 14:41:04 +0000178bool AArch64InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
179 MachineBasicBlock *&TBB,
180 MachineBasicBlock *&FBB,
181 SmallVectorImpl<MachineOperand> &Cond,
182 bool AllowModify) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000183 // If the block has no terminators, it just falls into the block after it.
Benjamin Kramere61cbd12015-06-25 13:28:24 +0000184 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
185 if (I == MBB.end())
Tim Northover3b0846e2014-05-24 12:50:23 +0000186 return false;
Benjamin Kramere61cbd12015-06-25 13:28:24 +0000187
Duncan P. N. Exon Smith6307eb52016-02-23 02:46:52 +0000188 if (!isUnpredicatedTerminator(*I))
Tim Northover3b0846e2014-05-24 12:50:23 +0000189 return false;
190
191 // Get the last instruction in the block.
Duncan P. N. Exon Smithab53fd92016-07-08 20:29:42 +0000192 MachineInstr *LastInst = &*I;
Tim Northover3b0846e2014-05-24 12:50:23 +0000193
194 // If there is only one terminator instruction, process it.
195 unsigned LastOpc = LastInst->getOpcode();
Duncan P. N. Exon Smith6307eb52016-02-23 02:46:52 +0000196 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000197 if (isUncondBranchOpcode(LastOpc)) {
198 TBB = LastInst->getOperand(0).getMBB();
199 return false;
200 }
201 if (isCondBranchOpcode(LastOpc)) {
202 // Block ends with fall-through condbranch.
203 parseCondBranch(LastInst, TBB, Cond);
204 return false;
205 }
206 return true; // Can't handle indirect branch.
207 }
208
209 // Get the instruction before it if it is a terminator.
Duncan P. N. Exon Smithab53fd92016-07-08 20:29:42 +0000210 MachineInstr *SecondLastInst = &*I;
Tim Northover3b0846e2014-05-24 12:50:23 +0000211 unsigned SecondLastOpc = SecondLastInst->getOpcode();
212
213 // If AllowModify is true and the block ends with two or more unconditional
214 // branches, delete all but the first unconditional branch.
215 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
216 while (isUncondBranchOpcode(SecondLastOpc)) {
217 LastInst->eraseFromParent();
218 LastInst = SecondLastInst;
219 LastOpc = LastInst->getOpcode();
Duncan P. N. Exon Smith6307eb52016-02-23 02:46:52 +0000220 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000221 // Return now the only terminator is an unconditional branch.
222 TBB = LastInst->getOperand(0).getMBB();
223 return false;
224 } else {
Duncan P. N. Exon Smithab53fd92016-07-08 20:29:42 +0000225 SecondLastInst = &*I;
Tim Northover3b0846e2014-05-24 12:50:23 +0000226 SecondLastOpc = SecondLastInst->getOpcode();
227 }
228 }
229 }
230
231 // If there are three terminators, we don't know what sort of block this is.
Duncan P. N. Exon Smith6307eb52016-02-23 02:46:52 +0000232 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
Tim Northover3b0846e2014-05-24 12:50:23 +0000233 return true;
234
235 // If the block ends with a B and a Bcc, handle it.
236 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
237 parseCondBranch(SecondLastInst, TBB, Cond);
238 FBB = LastInst->getOperand(0).getMBB();
239 return false;
240 }
241
242 // If the block ends with two unconditional branches, handle it. The second
243 // one is not executed, so remove it.
244 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
245 TBB = SecondLastInst->getOperand(0).getMBB();
246 I = LastInst;
247 if (AllowModify)
248 I->eraseFromParent();
249 return false;
250 }
251
252 // ...likewise if it ends with an indirect branch followed by an unconditional
253 // branch.
254 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
255 I = LastInst;
256 if (AllowModify)
257 I->eraseFromParent();
258 return true;
259 }
260
261 // Otherwise, can't handle this.
262 return true;
263}
264
Matt Arsenault1b9fc8e2016-09-14 20:43:16 +0000265bool AArch64InstrInfo::reverseBranchCondition(
Tim Northover3b0846e2014-05-24 12:50:23 +0000266 SmallVectorImpl<MachineOperand> &Cond) const {
267 if (Cond[0].getImm() != -1) {
268 // Regular Bcc
269 AArch64CC::CondCode CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
270 Cond[0].setImm(AArch64CC::getInvertedCondCode(CC));
271 } else {
272 // Folded compare-and-branch
273 switch (Cond[1].getImm()) {
274 default:
275 llvm_unreachable("Unknown conditional branch!");
276 case AArch64::CBZW:
277 Cond[1].setImm(AArch64::CBNZW);
278 break;
279 case AArch64::CBNZW:
280 Cond[1].setImm(AArch64::CBZW);
281 break;
282 case AArch64::CBZX:
283 Cond[1].setImm(AArch64::CBNZX);
284 break;
285 case AArch64::CBNZX:
286 Cond[1].setImm(AArch64::CBZX);
287 break;
288 case AArch64::TBZW:
289 Cond[1].setImm(AArch64::TBNZW);
290 break;
291 case AArch64::TBNZW:
292 Cond[1].setImm(AArch64::TBZW);
293 break;
294 case AArch64::TBZX:
295 Cond[1].setImm(AArch64::TBNZX);
296 break;
297 case AArch64::TBNZX:
298 Cond[1].setImm(AArch64::TBZX);
299 break;
300 }
301 }
302
303 return false;
304}
305
Matt Arsenault1b9fc8e2016-09-14 20:43:16 +0000306unsigned AArch64InstrInfo::removeBranch(MachineBasicBlock &MBB,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000307 int *BytesRemoved) const {
Benjamin Kramere61cbd12015-06-25 13:28:24 +0000308 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
309 if (I == MBB.end())
Tim Northover3b0846e2014-05-24 12:50:23 +0000310 return 0;
Benjamin Kramere61cbd12015-06-25 13:28:24 +0000311
Tim Northover3b0846e2014-05-24 12:50:23 +0000312 if (!isUncondBranchOpcode(I->getOpcode()) &&
313 !isCondBranchOpcode(I->getOpcode()))
314 return 0;
315
316 // Remove the branch.
317 I->eraseFromParent();
318
319 I = MBB.end();
320
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000321 if (I == MBB.begin()) {
322 if (BytesRemoved)
323 *BytesRemoved = 4;
Tim Northover3b0846e2014-05-24 12:50:23 +0000324 return 1;
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000325 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000326 --I;
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000327 if (!isCondBranchOpcode(I->getOpcode())) {
328 if (BytesRemoved)
329 *BytesRemoved = 4;
Tim Northover3b0846e2014-05-24 12:50:23 +0000330 return 1;
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000331 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000332
333 // Remove the branch.
334 I->eraseFromParent();
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000335 if (BytesRemoved)
336 *BytesRemoved = 8;
337
Tim Northover3b0846e2014-05-24 12:50:23 +0000338 return 2;
339}
340
341void AArch64InstrInfo::instantiateCondBranch(
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000342 MachineBasicBlock &MBB, const DebugLoc &DL, MachineBasicBlock *TBB,
Ahmed Bougachac88bf542015-06-11 19:30:37 +0000343 ArrayRef<MachineOperand> Cond) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000344 if (Cond[0].getImm() != -1) {
345 // Regular Bcc
346 BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
347 } else {
348 // Folded compare-and-branch
Ahmed Bougacha72001cf2014-11-07 02:50:00 +0000349 // Note that we use addOperand instead of addReg to keep the flags.
Tim Northover3b0846e2014-05-24 12:50:23 +0000350 const MachineInstrBuilder MIB =
Ahmed Bougacha72001cf2014-11-07 02:50:00 +0000351 BuildMI(&MBB, DL, get(Cond[1].getImm())).addOperand(Cond[2]);
Tim Northover3b0846e2014-05-24 12:50:23 +0000352 if (Cond.size() > 3)
353 MIB.addImm(Cond[3].getImm());
354 MIB.addMBB(TBB);
355 }
356}
357
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000358unsigned AArch64InstrInfo::insertBranch(MachineBasicBlock &MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000359 MachineBasicBlock *TBB,
360 MachineBasicBlock *FBB,
361 ArrayRef<MachineOperand> Cond,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000362 const DebugLoc &DL,
363 int *BytesAdded) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000364 // Shouldn't be a fall through.
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000365 assert(TBB && "insertBranch must not be told to insert a fallthrough");
Tim Northover3b0846e2014-05-24 12:50:23 +0000366
367 if (!FBB) {
368 if (Cond.empty()) // Unconditional branch?
369 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
370 else
371 instantiateCondBranch(MBB, DL, TBB, Cond);
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000372
373 if (BytesAdded)
374 *BytesAdded = 4;
375
Tim Northover3b0846e2014-05-24 12:50:23 +0000376 return 1;
377 }
378
379 // Two-way conditional branch.
380 instantiateCondBranch(MBB, DL, TBB, Cond);
381 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000382
383 if (BytesAdded)
384 *BytesAdded = 8;
385
Tim Northover3b0846e2014-05-24 12:50:23 +0000386 return 2;
387}
388
389// Find the original register that VReg is copied from.
390static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
391 while (TargetRegisterInfo::isVirtualRegister(VReg)) {
392 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
393 if (!DefMI->isFullCopy())
394 return VReg;
395 VReg = DefMI->getOperand(1).getReg();
396 }
397 return VReg;
398}
399
400// Determine if VReg is defined by an instruction that can be folded into a
401// csel instruction. If so, return the folded opcode, and the replacement
402// register.
403static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
404 unsigned *NewVReg = nullptr) {
405 VReg = removeCopies(MRI, VReg);
406 if (!TargetRegisterInfo::isVirtualRegister(VReg))
407 return 0;
408
409 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
410 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
411 unsigned Opc = 0;
412 unsigned SrcOpNum = 0;
413 switch (DefMI->getOpcode()) {
414 case AArch64::ADDSXri:
415 case AArch64::ADDSWri:
416 // if NZCV is used, do not fold.
417 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, true) == -1)
418 return 0;
Justin Bognerb03fd122016-08-17 05:10:15 +0000419 // fall-through to ADDXri and ADDWri.
420 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +0000421 case AArch64::ADDXri:
422 case AArch64::ADDWri:
423 // add x, 1 -> csinc.
424 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
425 DefMI->getOperand(3).getImm() != 0)
426 return 0;
427 SrcOpNum = 1;
428 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
429 break;
430
431 case AArch64::ORNXrr:
432 case AArch64::ORNWrr: {
433 // not x -> csinv, represented as orn dst, xzr, src.
434 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
435 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
436 return 0;
437 SrcOpNum = 2;
438 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
439 break;
440 }
441
442 case AArch64::SUBSXrr:
443 case AArch64::SUBSWrr:
444 // if NZCV is used, do not fold.
445 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, true) == -1)
446 return 0;
Justin Bognerb03fd122016-08-17 05:10:15 +0000447 // fall-through to SUBXrr and SUBWrr.
448 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +0000449 case AArch64::SUBXrr:
450 case AArch64::SUBWrr: {
451 // neg x -> csneg, represented as sub dst, xzr, src.
452 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
453 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
454 return 0;
455 SrcOpNum = 2;
456 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
457 break;
458 }
459 default:
460 return 0;
461 }
462 assert(Opc && SrcOpNum && "Missing parameters");
463
464 if (NewVReg)
465 *NewVReg = DefMI->getOperand(SrcOpNum).getReg();
466 return Opc;
467}
468
469bool AArch64InstrInfo::canInsertSelect(
Ahmed Bougachac88bf542015-06-11 19:30:37 +0000470 const MachineBasicBlock &MBB, ArrayRef<MachineOperand> Cond,
Tim Northover3b0846e2014-05-24 12:50:23 +0000471 unsigned TrueReg, unsigned FalseReg, int &CondCycles, int &TrueCycles,
472 int &FalseCycles) const {
473 // Check register classes.
474 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
475 const TargetRegisterClass *RC =
Eric Christophera0de2532015-03-18 20:37:30 +0000476 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
Tim Northover3b0846e2014-05-24 12:50:23 +0000477 if (!RC)
478 return false;
479
480 // Expanding cbz/tbz requires an extra cycle of latency on the condition.
481 unsigned ExtraCondLat = Cond.size() != 1;
482
483 // GPRs are handled by csel.
484 // FIXME: Fold in x+1, -x, and ~x when applicable.
485 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
486 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
487 // Single-cycle csel, csinc, csinv, and csneg.
488 CondCycles = 1 + ExtraCondLat;
489 TrueCycles = FalseCycles = 1;
490 if (canFoldIntoCSel(MRI, TrueReg))
491 TrueCycles = 0;
492 else if (canFoldIntoCSel(MRI, FalseReg))
493 FalseCycles = 0;
494 return true;
495 }
496
497 // Scalar floating point is handled by fcsel.
498 // FIXME: Form fabs, fmin, and fmax when applicable.
499 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
500 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
501 CondCycles = 5 + ExtraCondLat;
502 TrueCycles = FalseCycles = 2;
503 return true;
504 }
505
506 // Can't do vectors.
507 return false;
508}
509
510void AArch64InstrInfo::insertSelect(MachineBasicBlock &MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000511 MachineBasicBlock::iterator I,
512 const DebugLoc &DL, unsigned DstReg,
Ahmed Bougachac88bf542015-06-11 19:30:37 +0000513 ArrayRef<MachineOperand> Cond,
Tim Northover3b0846e2014-05-24 12:50:23 +0000514 unsigned TrueReg, unsigned FalseReg) const {
515 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
516
517 // Parse the condition code, see parseCondBranch() above.
518 AArch64CC::CondCode CC;
519 switch (Cond.size()) {
520 default:
521 llvm_unreachable("Unknown condition opcode in Cond");
522 case 1: // b.cc
523 CC = AArch64CC::CondCode(Cond[0].getImm());
524 break;
525 case 3: { // cbz/cbnz
526 // We must insert a compare against 0.
527 bool Is64Bit;
528 switch (Cond[1].getImm()) {
529 default:
530 llvm_unreachable("Unknown branch opcode in Cond");
531 case AArch64::CBZW:
532 Is64Bit = 0;
533 CC = AArch64CC::EQ;
534 break;
535 case AArch64::CBZX:
536 Is64Bit = 1;
537 CC = AArch64CC::EQ;
538 break;
539 case AArch64::CBNZW:
540 Is64Bit = 0;
541 CC = AArch64CC::NE;
542 break;
543 case AArch64::CBNZX:
544 Is64Bit = 1;
545 CC = AArch64CC::NE;
546 break;
547 }
548 unsigned SrcReg = Cond[2].getReg();
549 if (Is64Bit) {
550 // cmp reg, #0 is actually subs xzr, reg, #0.
551 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
552 BuildMI(MBB, I, DL, get(AArch64::SUBSXri), AArch64::XZR)
553 .addReg(SrcReg)
554 .addImm(0)
555 .addImm(0);
556 } else {
557 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
558 BuildMI(MBB, I, DL, get(AArch64::SUBSWri), AArch64::WZR)
559 .addReg(SrcReg)
560 .addImm(0)
561 .addImm(0);
562 }
563 break;
564 }
565 case 4: { // tbz/tbnz
566 // We must insert a tst instruction.
567 switch (Cond[1].getImm()) {
568 default:
569 llvm_unreachable("Unknown branch opcode in Cond");
570 case AArch64::TBZW:
571 case AArch64::TBZX:
572 CC = AArch64CC::EQ;
573 break;
574 case AArch64::TBNZW:
575 case AArch64::TBNZX:
576 CC = AArch64CC::NE;
577 break;
578 }
579 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
580 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
581 BuildMI(MBB, I, DL, get(AArch64::ANDSWri), AArch64::WZR)
582 .addReg(Cond[2].getReg())
583 .addImm(
584 AArch64_AM::encodeLogicalImmediate(1ull << Cond[3].getImm(), 32));
585 else
586 BuildMI(MBB, I, DL, get(AArch64::ANDSXri), AArch64::XZR)
587 .addReg(Cond[2].getReg())
588 .addImm(
589 AArch64_AM::encodeLogicalImmediate(1ull << Cond[3].getImm(), 64));
590 break;
591 }
592 }
593
594 unsigned Opc = 0;
595 const TargetRegisterClass *RC = nullptr;
596 bool TryFold = false;
597 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
598 RC = &AArch64::GPR64RegClass;
599 Opc = AArch64::CSELXr;
600 TryFold = true;
601 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
602 RC = &AArch64::GPR32RegClass;
603 Opc = AArch64::CSELWr;
604 TryFold = true;
605 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
606 RC = &AArch64::FPR64RegClass;
607 Opc = AArch64::FCSELDrrr;
608 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
609 RC = &AArch64::FPR32RegClass;
610 Opc = AArch64::FCSELSrrr;
611 }
612 assert(RC && "Unsupported regclass");
613
614 // Try folding simple instructions into the csel.
615 if (TryFold) {
616 unsigned NewVReg = 0;
617 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewVReg);
618 if (FoldedOpc) {
619 // The folded opcodes csinc, csinc and csneg apply the operation to
620 // FalseReg, so we need to invert the condition.
621 CC = AArch64CC::getInvertedCondCode(CC);
622 TrueReg = FalseReg;
623 } else
624 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewVReg);
625
626 // Fold the operation. Leave any dead instructions for DCE to clean up.
627 if (FoldedOpc) {
628 FalseReg = NewVReg;
629 Opc = FoldedOpc;
630 // The extends the live range of NewVReg.
631 MRI.clearKillFlags(NewVReg);
632 }
633 }
634
635 // Pull all virtual register into the appropriate class.
636 MRI.constrainRegClass(TrueReg, RC);
637 MRI.constrainRegClass(FalseReg, RC);
638
639 // Insert the csel.
640 BuildMI(MBB, I, DL, get(Opc), DstReg).addReg(TrueReg).addReg(FalseReg).addImm(
641 CC);
642}
643
Lawrence Hu687097a2015-07-23 23:55:28 +0000644/// Returns true if a MOVi32imm or MOVi64imm can be expanded to an ORRxx.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000645static bool canBeExpandedToORR(const MachineInstr &MI, unsigned BitSize) {
646 uint64_t Imm = MI.getOperand(1).getImm();
Weiming Zhaob33a5552015-07-23 19:24:53 +0000647 uint64_t UImm = Imm << (64 - BitSize) >> (64 - BitSize);
648 uint64_t Encoding;
649 return AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding);
650}
651
Jiangning Liucd296372014-07-29 02:09:26 +0000652// FIXME: this implementation should be micro-architecture dependent, so a
653// micro-architecture target hook should be introduced here in future.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000654bool AArch64InstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
Matthias Braun651cff42016-06-02 18:03:53 +0000655 if (!Subtarget.hasCustomCheapAsMoveHandling())
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000656 return MI.isAsCheapAsAMove();
Jiangning Liucd296372014-07-29 02:09:26 +0000657
Evandro Menezesd23324a2016-05-04 20:47:25 +0000658 unsigned Imm;
659
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000660 switch (MI.getOpcode()) {
Jiangning Liucd296372014-07-29 02:09:26 +0000661 default:
662 return false;
663
664 // add/sub on register without shift
665 case AArch64::ADDWri:
666 case AArch64::ADDXri:
667 case AArch64::SUBWri:
668 case AArch64::SUBXri:
Matthias Braun651cff42016-06-02 18:03:53 +0000669 return (Subtarget.getProcFamily() == AArch64Subtarget::ExynosM1 ||
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000670 MI.getOperand(3).getImm() == 0);
Evandro Menezesd23324a2016-05-04 20:47:25 +0000671
672 // add/sub on register with shift
673 case AArch64::ADDWrs:
674 case AArch64::ADDXrs:
675 case AArch64::SUBWrs:
676 case AArch64::SUBXrs:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000677 Imm = MI.getOperand(3).getImm();
Matthias Braun651cff42016-06-02 18:03:53 +0000678 return (Subtarget.getProcFamily() == AArch64Subtarget::ExynosM1 &&
Evandro Menezesd23324a2016-05-04 20:47:25 +0000679 AArch64_AM::getArithShiftValue(Imm) < 4);
Jiangning Liucd296372014-07-29 02:09:26 +0000680
681 // logical ops on immediate
682 case AArch64::ANDWri:
683 case AArch64::ANDXri:
684 case AArch64::EORWri:
685 case AArch64::EORXri:
686 case AArch64::ORRWri:
687 case AArch64::ORRXri:
688 return true;
689
690 // logical ops on register without shift
691 case AArch64::ANDWrr:
692 case AArch64::ANDXrr:
693 case AArch64::BICWrr:
694 case AArch64::BICXrr:
695 case AArch64::EONWrr:
696 case AArch64::EONXrr:
697 case AArch64::EORWrr:
698 case AArch64::EORXrr:
699 case AArch64::ORNWrr:
700 case AArch64::ORNXrr:
701 case AArch64::ORRWrr:
702 case AArch64::ORRXrr:
703 return true;
Evandro Menezesd23324a2016-05-04 20:47:25 +0000704
705 // logical ops on register with shift
706 case AArch64::ANDWrs:
707 case AArch64::ANDXrs:
708 case AArch64::BICWrs:
709 case AArch64::BICXrs:
710 case AArch64::EONWrs:
711 case AArch64::EONXrs:
712 case AArch64::EORWrs:
713 case AArch64::EORXrs:
714 case AArch64::ORNWrs:
715 case AArch64::ORNXrs:
716 case AArch64::ORRWrs:
717 case AArch64::ORRXrs:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000718 Imm = MI.getOperand(3).getImm();
Matthias Braun651cff42016-06-02 18:03:53 +0000719 return (Subtarget.getProcFamily() == AArch64Subtarget::ExynosM1 &&
Evandro Menezesd23324a2016-05-04 20:47:25 +0000720 AArch64_AM::getShiftValue(Imm) < 4 &&
721 AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL);
722
Weiming Zhaob33a5552015-07-23 19:24:53 +0000723 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
724 // ORRXri, it is as cheap as MOV
725 case AArch64::MOVi32imm:
726 return canBeExpandedToORR(MI, 32);
727 case AArch64::MOVi64imm:
728 return canBeExpandedToORR(MI, 64);
Haicheng Wu711ca862016-07-12 15:31:41 +0000729
Haicheng Wuf0b01272016-07-15 00:27:01 +0000730 // It is cheap to zero out registers if the subtarget has ZeroCycleZeroing
731 // feature.
Haicheng Wu711ca862016-07-12 15:31:41 +0000732 case AArch64::FMOVS0:
733 case AArch64::FMOVD0:
734 return Subtarget.hasZeroCycleZeroing();
Haicheng Wuf0b01272016-07-15 00:27:01 +0000735 case TargetOpcode::COPY:
736 return (Subtarget.hasZeroCycleZeroing() &&
737 (MI.getOperand(1).getReg() == AArch64::WZR ||
738 MI.getOperand(1).getReg() == AArch64::XZR));
Jiangning Liucd296372014-07-29 02:09:26 +0000739 }
740
741 llvm_unreachable("Unknown opcode to check as cheap as a move!");
742}
743
Tim Northover3b0846e2014-05-24 12:50:23 +0000744bool AArch64InstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
745 unsigned &SrcReg, unsigned &DstReg,
746 unsigned &SubIdx) const {
747 switch (MI.getOpcode()) {
748 default:
749 return false;
750 case AArch64::SBFMXri: // aka sxtw
751 case AArch64::UBFMXri: // aka uxtw
752 // Check for the 32 -> 64 bit extension case, these instructions can do
753 // much more.
754 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
755 return false;
756 // This is a signed or unsigned 32 -> 64 bit extension.
757 SrcReg = MI.getOperand(1).getReg();
758 DstReg = MI.getOperand(0).getReg();
759 SubIdx = AArch64::sub_32;
760 return true;
761 }
762}
763
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000764bool AArch64InstrInfo::areMemAccessesTriviallyDisjoint(
765 MachineInstr &MIa, MachineInstr &MIb, AliasAnalysis *AA) const {
Eric Christophera0de2532015-03-18 20:37:30 +0000766 const TargetRegisterInfo *TRI = &getRegisterInfo();
Chad Rosier3528c1e2014-09-08 14:43:48 +0000767 unsigned BaseRegA = 0, BaseRegB = 0;
Chad Rosier0da267d2016-03-09 16:46:48 +0000768 int64_t OffsetA = 0, OffsetB = 0;
769 unsigned WidthA = 0, WidthB = 0;
Chad Rosier3528c1e2014-09-08 14:43:48 +0000770
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000771 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
772 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
Chad Rosier3528c1e2014-09-08 14:43:48 +0000773
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000774 if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() ||
775 MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
Chad Rosier3528c1e2014-09-08 14:43:48 +0000776 return false;
777
778 // Retrieve the base register, offset from the base register and width. Width
779 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
780 // base registers are identical, and the offset of a lower memory access +
781 // the width doesn't overlap the offset of a higher memory access,
782 // then the memory accesses are different.
Sanjoy Dasb666ea32015-06-15 18:44:14 +0000783 if (getMemOpBaseRegImmOfsWidth(MIa, BaseRegA, OffsetA, WidthA, TRI) &&
784 getMemOpBaseRegImmOfsWidth(MIb, BaseRegB, OffsetB, WidthB, TRI)) {
Chad Rosier3528c1e2014-09-08 14:43:48 +0000785 if (BaseRegA == BaseRegB) {
786 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
787 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
788 int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
789 if (LowOffset + LowWidth <= HighOffset)
790 return true;
791 }
792 }
793 return false;
794}
795
Tim Northover3b0846e2014-05-24 12:50:23 +0000796/// analyzeCompare - For a comparison instruction, return the source registers
797/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
798/// Return true if the comparison instruction can be analyzed.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000799bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
Tim Northover3b0846e2014-05-24 12:50:23 +0000800 unsigned &SrcReg2, int &CmpMask,
801 int &CmpValue) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000802 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000803 default:
804 break;
805 case AArch64::SUBSWrr:
806 case AArch64::SUBSWrs:
807 case AArch64::SUBSWrx:
808 case AArch64::SUBSXrr:
809 case AArch64::SUBSXrs:
810 case AArch64::SUBSXrx:
811 case AArch64::ADDSWrr:
812 case AArch64::ADDSWrs:
813 case AArch64::ADDSWrx:
814 case AArch64::ADDSXrr:
815 case AArch64::ADDSXrs:
816 case AArch64::ADDSXrx:
817 // Replace SUBSWrr with SUBWrr if NZCV is not used.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000818 SrcReg = MI.getOperand(1).getReg();
819 SrcReg2 = MI.getOperand(2).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +0000820 CmpMask = ~0;
821 CmpValue = 0;
822 return true;
823 case AArch64::SUBSWri:
824 case AArch64::ADDSWri:
825 case AArch64::SUBSXri:
826 case AArch64::ADDSXri:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000827 SrcReg = MI.getOperand(1).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +0000828 SrcReg2 = 0;
829 CmpMask = ~0;
Jiangning Liudcc651f2014-08-08 14:19:29 +0000830 // FIXME: In order to convert CmpValue to 0 or 1
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000831 CmpValue = MI.getOperand(2).getImm() != 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000832 return true;
833 case AArch64::ANDSWri:
834 case AArch64::ANDSXri:
835 // ANDS does not use the same encoding scheme as the others xxxS
836 // instructions.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000837 SrcReg = MI.getOperand(1).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +0000838 SrcReg2 = 0;
839 CmpMask = ~0;
Jiangning Liudcc651f2014-08-08 14:19:29 +0000840 // FIXME:The return val type of decodeLogicalImmediate is uint64_t,
841 // while the type of CmpValue is int. When converting uint64_t to int,
842 // the high 32 bits of uint64_t will be lost.
843 // In fact it causes a bug in spec2006-483.xalancbmk
844 // CmpValue is only used to compare with zero in OptimizeCompareInstr
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000845 CmpValue = AArch64_AM::decodeLogicalImmediate(
846 MI.getOperand(2).getImm(),
847 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64) != 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000848 return true;
849 }
850
851 return false;
852}
853
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000854static bool UpdateOperandRegClass(MachineInstr &Instr) {
855 MachineBasicBlock *MBB = Instr.getParent();
Tim Northover3b0846e2014-05-24 12:50:23 +0000856 assert(MBB && "Can't get MachineBasicBlock here");
857 MachineFunction *MF = MBB->getParent();
858 assert(MF && "Can't get MachineFunction here");
Eric Christopher6c901622015-01-28 03:51:33 +0000859 const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
860 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
Tim Northover3b0846e2014-05-24 12:50:23 +0000861 MachineRegisterInfo *MRI = &MF->getRegInfo();
862
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000863 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
Tim Northover3b0846e2014-05-24 12:50:23 +0000864 ++OpIdx) {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000865 MachineOperand &MO = Instr.getOperand(OpIdx);
Tim Northover3b0846e2014-05-24 12:50:23 +0000866 const TargetRegisterClass *OpRegCstraints =
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000867 Instr.getRegClassConstraint(OpIdx, TII, TRI);
Tim Northover3b0846e2014-05-24 12:50:23 +0000868
869 // If there's no constraint, there's nothing to do.
870 if (!OpRegCstraints)
871 continue;
872 // If the operand is a frame index, there's nothing to do here.
873 // A frame index operand will resolve correctly during PEI.
874 if (MO.isFI())
875 continue;
876
877 assert(MO.isReg() &&
878 "Operand has register constraints without being a register!");
879
880 unsigned Reg = MO.getReg();
881 if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
882 if (!OpRegCstraints->contains(Reg))
883 return false;
884 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
885 !MRI->constrainRegClass(Reg, OpRegCstraints))
886 return false;
887 }
888
889 return true;
890}
891
Juergen Ributzka7a7c4682014-11-18 21:02:40 +0000892/// \brief Return the opcode that does not set flags when possible - otherwise
893/// return the original opcode. The caller is responsible to do the actual
894/// substitution and legality checking.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000895static unsigned convertFlagSettingOpcode(const MachineInstr &MI) {
Juergen Ributzka7a7c4682014-11-18 21:02:40 +0000896 // Don't convert all compare instructions, because for some the zero register
897 // encoding becomes the sp register.
898 bool MIDefinesZeroReg = false;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000899 if (MI.definesRegister(AArch64::WZR) || MI.definesRegister(AArch64::XZR))
Juergen Ributzka7a7c4682014-11-18 21:02:40 +0000900 MIDefinesZeroReg = true;
901
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000902 switch (MI.getOpcode()) {
Juergen Ributzka7a7c4682014-11-18 21:02:40 +0000903 default:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000904 return MI.getOpcode();
Juergen Ributzka7a7c4682014-11-18 21:02:40 +0000905 case AArch64::ADDSWrr:
906 return AArch64::ADDWrr;
907 case AArch64::ADDSWri:
908 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
909 case AArch64::ADDSWrs:
910 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
911 case AArch64::ADDSWrx:
912 return AArch64::ADDWrx;
913 case AArch64::ADDSXrr:
914 return AArch64::ADDXrr;
915 case AArch64::ADDSXri:
916 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
917 case AArch64::ADDSXrs:
918 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
919 case AArch64::ADDSXrx:
920 return AArch64::ADDXrx;
921 case AArch64::SUBSWrr:
922 return AArch64::SUBWrr;
923 case AArch64::SUBSWri:
924 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
925 case AArch64::SUBSWrs:
926 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
927 case AArch64::SUBSWrx:
928 return AArch64::SUBWrx;
929 case AArch64::SUBSXrr:
930 return AArch64::SUBXrr;
931 case AArch64::SUBSXri:
932 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
933 case AArch64::SUBSXrs:
934 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
935 case AArch64::SUBSXrx:
936 return AArch64::SUBXrx;
937 }
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +0000938}
Tim Northover3b0846e2014-05-24 12:50:23 +0000939
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000940enum AccessKind {
941 AK_Write = 0x01,
942 AK_Read = 0x10,
943 AK_All = 0x11
944};
945
946/// True when condition flags are accessed (either by writing or reading)
947/// on the instruction trace starting at From and ending at To.
948///
949/// Note: If From and To are from different blocks it's assumed CC are accessed
950/// on the path.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000951static bool areCFlagsAccessedBetweenInstrs(
952 MachineBasicBlock::iterator From, MachineBasicBlock::iterator To,
953 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +0000954 // Early exit if To is at the beginning of the BB.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000955 if (To == To->getParent()->begin())
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +0000956 return true;
957
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000958 // Check whether the instructions are in the same basic block
959 // If not, assume the condition flags might get modified somewhere.
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +0000960 if (To->getParent() != From->getParent())
961 return true;
962
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000963 // From must be above To.
Duncan P. N. Exon Smith18720962016-09-11 18:51:28 +0000964 assert(std::find_if(++To.getReverse(), To->getParent()->rend(),
965 [From](MachineInstr &MI) {
966 return MI.getIterator() == From;
Duncan P. N. Exon Smithab53fd92016-07-08 20:29:42 +0000967 }) != To->getParent()->rend());
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000968
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000969 // We iterate backward starting \p To until we hit \p From.
970 for (--To; To != From; --To) {
971 const MachineInstr &Instr = *To;
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +0000972
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000973 if ( ((AccessToCheck & AK_Write) && Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
974 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +0000975 return true;
976 }
977 return false;
978}
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000979
980/// Try to optimize a compare instruction. A compare instruction is an
981/// instruction which produces AArch64::NZCV. It can be truly compare instruction
982/// when there are no uses of its destination register.
983///
984/// The following steps are tried in order:
985/// 1. Convert CmpInstr into an unconditional version.
986/// 2. Remove CmpInstr if above there is an instruction producing a needed
987/// condition code or an instruction which can be converted into such an instruction.
988/// Only comparison with zero is supported.
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +0000989bool AArch64InstrInfo::optimizeCompareInstr(
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000990 MachineInstr &CmpInstr, unsigned SrcReg, unsigned SrcReg2, int CmpMask,
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +0000991 int CmpValue, const MachineRegisterInfo *MRI) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000992 assert(CmpInstr.getParent());
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000993 assert(MRI);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +0000994
995 // Replace SUBSWrr with SUBWrr if NZCV is not used.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000996 int DeadNZCVIdx = CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, true);
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +0000997 if (DeadNZCVIdx != -1) {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000998 if (CmpInstr.definesRegister(AArch64::WZR) ||
999 CmpInstr.definesRegister(AArch64::XZR)) {
1000 CmpInstr.eraseFromParent();
Juergen Ributzka7a7c4682014-11-18 21:02:40 +00001001 return true;
1002 }
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001003 unsigned Opc = CmpInstr.getOpcode();
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00001004 unsigned NewOpc = convertFlagSettingOpcode(CmpInstr);
1005 if (NewOpc == Opc)
1006 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00001007 const MCInstrDesc &MCID = get(NewOpc);
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001008 CmpInstr.setDesc(MCID);
1009 CmpInstr.RemoveOperand(DeadNZCVIdx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001010 bool succeeded = UpdateOperandRegClass(CmpInstr);
1011 (void)succeeded;
1012 assert(succeeded && "Some operands reg class are incompatible!");
1013 return true;
1014 }
1015
1016 // Continue only if we have a "ri" where immediate is zero.
Jiangning Liudcc651f2014-08-08 14:19:29 +00001017 // FIXME:CmpValue has already been converted to 0 or 1 in analyzeCompare
1018 // function.
1019 assert((CmpValue == 0 || CmpValue == 1) && "CmpValue must be 0 or 1!");
Tim Northover3b0846e2014-05-24 12:50:23 +00001020 if (CmpValue != 0 || SrcReg2 != 0)
1021 return false;
1022
1023 // CmpInstr is a Compare instruction if destination register is not used.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001024 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00001025 return false;
1026
Evgeny Astigeevichfd89fe02016-04-21 08:54:08 +00001027 return substituteCmpToZero(CmpInstr, SrcReg, MRI);
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001028}
Tim Northover3b0846e2014-05-24 12:50:23 +00001029
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001030/// Get opcode of S version of Instr.
1031/// If Instr is S version its opcode is returned.
1032/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
1033/// or we are not interested in it.
1034static unsigned sForm(MachineInstr &Instr) {
1035 switch (Instr.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001036 default:
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001037 return AArch64::INSTRUCTION_LIST_END;
1038
Tim Northover3b0846e2014-05-24 12:50:23 +00001039 case AArch64::ADDSWrr:
1040 case AArch64::ADDSWri:
1041 case AArch64::ADDSXrr:
1042 case AArch64::ADDSXri:
1043 case AArch64::SUBSWrr:
1044 case AArch64::SUBSWri:
1045 case AArch64::SUBSXrr:
1046 case AArch64::SUBSXri:
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001047 return Instr.getOpcode();;
1048
1049 case AArch64::ADDWrr: return AArch64::ADDSWrr;
1050 case AArch64::ADDWri: return AArch64::ADDSWri;
1051 case AArch64::ADDXrr: return AArch64::ADDSXrr;
1052 case AArch64::ADDXri: return AArch64::ADDSXri;
1053 case AArch64::ADCWr: return AArch64::ADCSWr;
1054 case AArch64::ADCXr: return AArch64::ADCSXr;
1055 case AArch64::SUBWrr: return AArch64::SUBSWrr;
1056 case AArch64::SUBWri: return AArch64::SUBSWri;
1057 case AArch64::SUBXrr: return AArch64::SUBSXrr;
1058 case AArch64::SUBXri: return AArch64::SUBSXri;
1059 case AArch64::SBCWr: return AArch64::SBCSWr;
1060 case AArch64::SBCXr: return AArch64::SBCSXr;
1061 case AArch64::ANDWri: return AArch64::ANDSWri;
1062 case AArch64::ANDXri: return AArch64::ANDSXri;
Tim Northover3b0846e2014-05-24 12:50:23 +00001063 }
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001064}
1065
1066/// Check if AArch64::NZCV should be alive in successors of MBB.
1067static bool areCFlagsAliveInSuccessors(MachineBasicBlock *MBB) {
1068 for (auto *BB : MBB->successors())
1069 if (BB->isLiveIn(AArch64::NZCV))
1070 return true;
1071 return false;
1072}
1073
Benjamin Kramerb7d33112016-08-06 11:13:10 +00001074namespace {
Evgeny Astigeevichfd89fe02016-04-21 08:54:08 +00001075struct UsedNZCV {
1076 bool N;
1077 bool Z;
1078 bool C;
1079 bool V;
1080 UsedNZCV(): N(false), Z(false), C(false), V(false) {}
1081 UsedNZCV& operator |=(const UsedNZCV& UsedFlags) {
1082 this->N |= UsedFlags.N;
1083 this->Z |= UsedFlags.Z;
1084 this->C |= UsedFlags.C;
1085 this->V |= UsedFlags.V;
1086 return *this;
1087 }
1088};
Benjamin Kramerb7d33112016-08-06 11:13:10 +00001089} // end anonymous namespace
Evgeny Astigeevichfd89fe02016-04-21 08:54:08 +00001090
1091/// Find a condition code used by the instruction.
1092/// Returns AArch64CC::Invalid if either the instruction does not use condition
1093/// codes or we don't optimize CmpInstr in the presence of such instructions.
1094static AArch64CC::CondCode findCondCodeUsedByInstr(const MachineInstr &Instr) {
1095 switch (Instr.getOpcode()) {
1096 default:
1097 return AArch64CC::Invalid;
1098
1099 case AArch64::Bcc: {
1100 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV);
1101 assert(Idx >= 2);
1102 return static_cast<AArch64CC::CondCode>(Instr.getOperand(Idx - 2).getImm());
1103 }
1104
1105 case AArch64::CSINVWr:
1106 case AArch64::CSINVXr:
1107 case AArch64::CSINCWr:
1108 case AArch64::CSINCXr:
1109 case AArch64::CSELWr:
1110 case AArch64::CSELXr:
1111 case AArch64::CSNEGWr:
1112 case AArch64::CSNEGXr:
1113 case AArch64::FCSELSrrr:
1114 case AArch64::FCSELDrrr: {
1115 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV);
1116 assert(Idx >= 1);
1117 return static_cast<AArch64CC::CondCode>(Instr.getOperand(Idx - 1).getImm());
1118 }
1119 }
1120}
1121
1122static UsedNZCV getUsedNZCV(AArch64CC::CondCode CC) {
1123 assert(CC != AArch64CC::Invalid);
1124 UsedNZCV UsedFlags;
1125 switch (CC) {
1126 default:
1127 break;
1128
1129 case AArch64CC::EQ: // Z set
1130 case AArch64CC::NE: // Z clear
1131 UsedFlags.Z = true;
1132 break;
1133
1134 case AArch64CC::HI: // Z clear and C set
1135 case AArch64CC::LS: // Z set or C clear
1136 UsedFlags.Z = true;
1137 case AArch64CC::HS: // C set
1138 case AArch64CC::LO: // C clear
1139 UsedFlags.C = true;
1140 break;
1141
1142 case AArch64CC::MI: // N set
1143 case AArch64CC::PL: // N clear
1144 UsedFlags.N = true;
1145 break;
1146
1147 case AArch64CC::VS: // V set
1148 case AArch64CC::VC: // V clear
1149 UsedFlags.V = true;
1150 break;
1151
1152 case AArch64CC::GT: // Z clear, N and V the same
1153 case AArch64CC::LE: // Z set, N and V differ
1154 UsedFlags.Z = true;
1155 case AArch64CC::GE: // N and V the same
1156 case AArch64CC::LT: // N and V differ
1157 UsedFlags.N = true;
1158 UsedFlags.V = true;
1159 break;
1160 }
1161 return UsedFlags;
1162}
1163
1164static bool isADDSRegImm(unsigned Opcode) {
1165 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
1166}
1167
1168static bool isSUBSRegImm(unsigned Opcode) {
1169 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
1170}
1171
1172/// Check if CmpInstr can be substituted by MI.
1173///
1174/// CmpInstr can be substituted:
1175/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
1176/// - and, MI and CmpInstr are from the same MachineBB
1177/// - and, condition flags are not alive in successors of the CmpInstr parent
1178/// - and, if MI opcode is the S form there must be no defs of flags between
1179/// MI and CmpInstr
1180/// or if MI opcode is not the S form there must be neither defs of flags
1181/// nor uses of flags between MI and CmpInstr.
1182/// - and C/V flags are not used after CmpInstr
1183static bool canInstrSubstituteCmpInstr(MachineInstr *MI, MachineInstr *CmpInstr,
1184 const TargetRegisterInfo *TRI) {
1185 assert(MI);
1186 assert(sForm(*MI) != AArch64::INSTRUCTION_LIST_END);
1187 assert(CmpInstr);
1188
1189 const unsigned CmpOpcode = CmpInstr->getOpcode();
1190 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
1191 return false;
1192
1193 if (MI->getParent() != CmpInstr->getParent())
1194 return false;
1195
1196 if (areCFlagsAliveInSuccessors(CmpInstr->getParent()))
1197 return false;
1198
1199 AccessKind AccessToCheck = AK_Write;
1200 if (sForm(*MI) != MI->getOpcode())
1201 AccessToCheck = AK_All;
1202 if (areCFlagsAccessedBetweenInstrs(MI, CmpInstr, TRI, AccessToCheck))
1203 return false;
1204
1205 UsedNZCV NZCVUsedAfterCmp;
1206 for (auto I = std::next(CmpInstr->getIterator()), E = CmpInstr->getParent()->instr_end();
1207 I != E; ++I) {
1208 const MachineInstr &Instr = *I;
1209 if (Instr.readsRegister(AArch64::NZCV, TRI)) {
1210 AArch64CC::CondCode CC = findCondCodeUsedByInstr(Instr);
1211 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
1212 return false;
1213 NZCVUsedAfterCmp |= getUsedNZCV(CC);
1214 }
1215
1216 if (Instr.modifiesRegister(AArch64::NZCV, TRI))
1217 break;
1218 }
1219
1220 return !NZCVUsedAfterCmp.C && !NZCVUsedAfterCmp.V;
1221}
1222
1223/// Substitute an instruction comparing to zero with another instruction
1224/// which produces needed condition flags.
1225///
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001226/// Return true on success.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001227bool AArch64InstrInfo::substituteCmpToZero(
1228 MachineInstr &CmpInstr, unsigned SrcReg,
1229 const MachineRegisterInfo *MRI) const {
Evgeny Astigeevichfd89fe02016-04-21 08:54:08 +00001230 assert(MRI);
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001231 // Get the unique definition of SrcReg.
1232 MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
1233 if (!MI)
1234 return false;
1235
1236 const TargetRegisterInfo *TRI = &getRegisterInfo();
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001237
1238 unsigned NewOpc = sForm(*MI);
1239 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
1240 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00001241
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001242 if (!canInstrSubstituteCmpInstr(MI, &CmpInstr, TRI))
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00001243 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00001244
1245 // Update the instruction to set NZCV.
1246 MI->setDesc(get(NewOpc));
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001247 CmpInstr.eraseFromParent();
1248 bool succeeded = UpdateOperandRegClass(*MI);
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 (void)succeeded;
1250 assert(succeeded && "Some operands reg class are incompatible!");
1251 MI->addRegisterDefined(AArch64::NZCV, TRI);
1252 return true;
1253}
1254
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001255bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
1256 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD)
Akira Hatanakae5b6e0d2014-07-25 19:31:34 +00001257 return false;
1258
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001259 MachineBasicBlock &MBB = *MI.getParent();
1260 DebugLoc DL = MI.getDebugLoc();
1261 unsigned Reg = MI.getOperand(0).getReg();
Akira Hatanakae5b6e0d2014-07-25 19:31:34 +00001262 const GlobalValue *GV =
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001263 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
Akira Hatanakae5b6e0d2014-07-25 19:31:34 +00001264 const TargetMachine &TM = MBB.getParent()->getTarget();
1265 unsigned char OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
1266 const unsigned char MO_NC = AArch64II::MO_NC;
1267
1268 if ((OpFlags & AArch64II::MO_GOT) != 0) {
1269 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
1270 .addGlobalAddress(GV, 0, AArch64II::MO_GOT);
1271 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001272 .addReg(Reg, RegState::Kill)
1273 .addImm(0)
1274 .addMemOperand(*MI.memoperands_begin());
Akira Hatanakae5b6e0d2014-07-25 19:31:34 +00001275 } else if (TM.getCodeModel() == CodeModel::Large) {
1276 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
1277 .addGlobalAddress(GV, 0, AArch64II::MO_G3).addImm(48);
1278 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
1279 .addReg(Reg, RegState::Kill)
1280 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC).addImm(32);
1281 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
1282 .addReg(Reg, RegState::Kill)
1283 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC).addImm(16);
1284 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
1285 .addReg(Reg, RegState::Kill)
1286 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC).addImm(0);
1287 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001288 .addReg(Reg, RegState::Kill)
1289 .addImm(0)
1290 .addMemOperand(*MI.memoperands_begin());
Akira Hatanakae5b6e0d2014-07-25 19:31:34 +00001291 } else {
1292 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
1293 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
1294 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
1295 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
1296 .addReg(Reg, RegState::Kill)
1297 .addGlobalAddress(GV, 0, LoFlags)
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001298 .addMemOperand(*MI.memoperands_begin());
Akira Hatanakae5b6e0d2014-07-25 19:31:34 +00001299 }
1300
1301 MBB.erase(MI);
1302
1303 return true;
1304}
1305
Tim Northover3b0846e2014-05-24 12:50:23 +00001306/// Return true if this is this instruction has a non-zero immediate
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001307bool AArch64InstrInfo::hasShiftedReg(const MachineInstr &MI) const {
1308 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001309 default:
1310 break;
1311 case AArch64::ADDSWrs:
1312 case AArch64::ADDSXrs:
1313 case AArch64::ADDWrs:
1314 case AArch64::ADDXrs:
1315 case AArch64::ANDSWrs:
1316 case AArch64::ANDSXrs:
1317 case AArch64::ANDWrs:
1318 case AArch64::ANDXrs:
1319 case AArch64::BICSWrs:
1320 case AArch64::BICSXrs:
1321 case AArch64::BICWrs:
1322 case AArch64::BICXrs:
1323 case AArch64::CRC32Brr:
1324 case AArch64::CRC32CBrr:
1325 case AArch64::CRC32CHrr:
1326 case AArch64::CRC32CWrr:
1327 case AArch64::CRC32CXrr:
1328 case AArch64::CRC32Hrr:
1329 case AArch64::CRC32Wrr:
1330 case AArch64::CRC32Xrr:
1331 case AArch64::EONWrs:
1332 case AArch64::EONXrs:
1333 case AArch64::EORWrs:
1334 case AArch64::EORXrs:
1335 case AArch64::ORNWrs:
1336 case AArch64::ORNXrs:
1337 case AArch64::ORRWrs:
1338 case AArch64::ORRXrs:
1339 case AArch64::SUBSWrs:
1340 case AArch64::SUBSXrs:
1341 case AArch64::SUBWrs:
1342 case AArch64::SUBXrs:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001343 if (MI.getOperand(3).isImm()) {
1344 unsigned val = MI.getOperand(3).getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 return (val != 0);
1346 }
1347 break;
1348 }
1349 return false;
1350}
1351
1352/// Return true if this is this instruction has a non-zero immediate
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001353bool AArch64InstrInfo::hasExtendedReg(const MachineInstr &MI) const {
1354 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001355 default:
1356 break;
1357 case AArch64::ADDSWrx:
1358 case AArch64::ADDSXrx:
1359 case AArch64::ADDSXrx64:
1360 case AArch64::ADDWrx:
1361 case AArch64::ADDXrx:
1362 case AArch64::ADDXrx64:
1363 case AArch64::SUBSWrx:
1364 case AArch64::SUBSXrx:
1365 case AArch64::SUBSXrx64:
1366 case AArch64::SUBWrx:
1367 case AArch64::SUBXrx:
1368 case AArch64::SUBXrx64:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001369 if (MI.getOperand(3).isImm()) {
1370 unsigned val = MI.getOperand(3).getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001371 return (val != 0);
1372 }
1373 break;
1374 }
1375
1376 return false;
1377}
1378
1379// Return true if this instruction simply sets its single destination register
1380// to zero. This is equivalent to a register rename of the zero-register.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001381bool AArch64InstrInfo::isGPRZero(const MachineInstr &MI) const {
1382 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001383 default:
1384 break;
1385 case AArch64::MOVZWi:
1386 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001387 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
1388 assert(MI.getDesc().getNumOperands() == 3 &&
1389 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 return true;
1391 }
1392 break;
1393 case AArch64::ANDWri: // and Rd, Rzr, #imm
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001394 return MI.getOperand(1).getReg() == AArch64::WZR;
Tim Northover3b0846e2014-05-24 12:50:23 +00001395 case AArch64::ANDXri:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001396 return MI.getOperand(1).getReg() == AArch64::XZR;
Tim Northover3b0846e2014-05-24 12:50:23 +00001397 case TargetOpcode::COPY:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001398 return MI.getOperand(1).getReg() == AArch64::WZR;
Tim Northover3b0846e2014-05-24 12:50:23 +00001399 }
1400 return false;
1401}
1402
1403// Return true if this instruction simply renames a general register without
1404// modifying bits.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001405bool AArch64InstrInfo::isGPRCopy(const MachineInstr &MI) const {
1406 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001407 default:
1408 break;
1409 case TargetOpcode::COPY: {
1410 // GPR32 copies will by lowered to ORRXrs
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001411 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 return (AArch64::GPR32RegClass.contains(DstReg) ||
1413 AArch64::GPR64RegClass.contains(DstReg));
1414 }
1415 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001416 if (MI.getOperand(1).getReg() == AArch64::XZR) {
1417 assert(MI.getDesc().getNumOperands() == 4 &&
1418 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
Tim Northover3b0846e2014-05-24 12:50:23 +00001419 return true;
1420 }
Renato Golin541d7e72014-08-01 17:27:31 +00001421 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001422 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001423 if (MI.getOperand(2).getImm() == 0) {
1424 assert(MI.getDesc().getNumOperands() == 4 &&
1425 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
Tim Northover3b0846e2014-05-24 12:50:23 +00001426 return true;
1427 }
Renato Golin541d7e72014-08-01 17:27:31 +00001428 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430 return false;
1431}
1432
1433// Return true if this instruction simply renames a general register without
1434// modifying bits.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001435bool AArch64InstrInfo::isFPRCopy(const MachineInstr &MI) const {
1436 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 default:
1438 break;
1439 case TargetOpcode::COPY: {
1440 // FPR64 copies will by lowered to ORR.16b
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001441 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +00001442 return (AArch64::FPR64RegClass.contains(DstReg) ||
1443 AArch64::FPR128RegClass.contains(DstReg));
1444 }
1445 case AArch64::ORRv16i8:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001446 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
1447 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001448 "invalid ORRv16i8 operands");
1449 return true;
1450 }
Renato Golin541d7e72014-08-01 17:27:31 +00001451 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001452 }
1453 return false;
1454}
1455
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001456unsigned AArch64InstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 int &FrameIndex) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001458 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 default:
1460 break;
1461 case AArch64::LDRWui:
1462 case AArch64::LDRXui:
1463 case AArch64::LDRBui:
1464 case AArch64::LDRHui:
1465 case AArch64::LDRSui:
1466 case AArch64::LDRDui:
1467 case AArch64::LDRQui:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001468 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
1469 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
1470 FrameIndex = MI.getOperand(1).getIndex();
1471 return MI.getOperand(0).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +00001472 }
1473 break;
1474 }
1475
1476 return 0;
1477}
1478
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001479unsigned AArch64InstrInfo::isStoreToStackSlot(const MachineInstr &MI,
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 int &FrameIndex) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001481 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 default:
1483 break;
1484 case AArch64::STRWui:
1485 case AArch64::STRXui:
1486 case AArch64::STRBui:
1487 case AArch64::STRHui:
1488 case AArch64::STRSui:
1489 case AArch64::STRDui:
1490 case AArch64::STRQui:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001491 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
1492 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
1493 FrameIndex = MI.getOperand(1).getIndex();
1494 return MI.getOperand(0).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +00001495 }
1496 break;
1497 }
1498 return 0;
1499}
1500
1501/// Return true if this is load/store scales or extends its register offset.
1502/// This refers to scaling a dynamic index as opposed to scaled immediates.
1503/// MI should be a memory op that allows scaled addressing.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001504bool AArch64InstrInfo::isScaledAddr(const MachineInstr &MI) const {
1505 switch (MI.getOpcode()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001506 default:
1507 break;
1508 case AArch64::LDRBBroW:
1509 case AArch64::LDRBroW:
1510 case AArch64::LDRDroW:
1511 case AArch64::LDRHHroW:
1512 case AArch64::LDRHroW:
1513 case AArch64::LDRQroW:
1514 case AArch64::LDRSBWroW:
1515 case AArch64::LDRSBXroW:
1516 case AArch64::LDRSHWroW:
1517 case AArch64::LDRSHXroW:
1518 case AArch64::LDRSWroW:
1519 case AArch64::LDRSroW:
1520 case AArch64::LDRWroW:
1521 case AArch64::LDRXroW:
1522 case AArch64::STRBBroW:
1523 case AArch64::STRBroW:
1524 case AArch64::STRDroW:
1525 case AArch64::STRHHroW:
1526 case AArch64::STRHroW:
1527 case AArch64::STRQroW:
1528 case AArch64::STRSroW:
1529 case AArch64::STRWroW:
1530 case AArch64::STRXroW:
1531 case AArch64::LDRBBroX:
1532 case AArch64::LDRBroX:
1533 case AArch64::LDRDroX:
1534 case AArch64::LDRHHroX:
1535 case AArch64::LDRHroX:
1536 case AArch64::LDRQroX:
1537 case AArch64::LDRSBWroX:
1538 case AArch64::LDRSBXroX:
1539 case AArch64::LDRSHWroX:
1540 case AArch64::LDRSHXroX:
1541 case AArch64::LDRSWroX:
1542 case AArch64::LDRSroX:
1543 case AArch64::LDRWroX:
1544 case AArch64::LDRXroX:
1545 case AArch64::STRBBroX:
1546 case AArch64::STRBroX:
1547 case AArch64::STRDroX:
1548 case AArch64::STRHHroX:
1549 case AArch64::STRHroX:
1550 case AArch64::STRQroX:
1551 case AArch64::STRSroX:
1552 case AArch64::STRWroX:
1553 case AArch64::STRXroX:
1554
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001555 unsigned Val = MI.getOperand(3).getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001556 AArch64_AM::ShiftExtendType ExtType = AArch64_AM::getMemExtendType(Val);
1557 return (ExtType != AArch64_AM::UXTX) || AArch64_AM::getMemDoShift(Val);
1558 }
1559 return false;
1560}
1561
1562/// Check all MachineMemOperands for a hint to suppress pairing.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001563bool AArch64InstrInfo::isLdStPairSuppressed(const MachineInstr &MI) const {
Justin Lebar288b3372016-07-14 18:15:20 +00001564 return any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
1565 return MMO->getFlags() & MOSuppressPair;
1566 });
Tim Northover3b0846e2014-05-24 12:50:23 +00001567}
1568
1569/// Set a flag on the first MachineMemOperand to suppress pairing.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001570void AArch64InstrInfo::suppressLdStPair(MachineInstr &MI) const {
1571 if (MI.memoperands_empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 return;
Justin Lebar288b3372016-07-14 18:15:20 +00001573 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
Tim Northover3b0846e2014-05-24 12:50:23 +00001574}
1575
Chad Rosiere4e15ba2016-03-09 17:29:48 +00001576bool AArch64InstrInfo::isUnscaledLdSt(unsigned Opc) const {
1577 switch (Opc) {
1578 default:
1579 return false;
1580 case AArch64::STURSi:
1581 case AArch64::STURDi:
1582 case AArch64::STURQi:
1583 case AArch64::STURBBi:
1584 case AArch64::STURHHi:
1585 case AArch64::STURWi:
1586 case AArch64::STURXi:
1587 case AArch64::LDURSi:
1588 case AArch64::LDURDi:
1589 case AArch64::LDURQi:
1590 case AArch64::LDURWi:
1591 case AArch64::LDURXi:
1592 case AArch64::LDURSWi:
1593 case AArch64::LDURHHi:
1594 case AArch64::LDURBBi:
1595 case AArch64::LDURSBWi:
1596 case AArch64::LDURSHWi:
1597 return true;
1598 }
1599}
1600
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001601bool AArch64InstrInfo::isUnscaledLdSt(MachineInstr &MI) const {
1602 return isUnscaledLdSt(MI.getOpcode());
Chad Rosiere4e15ba2016-03-09 17:29:48 +00001603}
1604
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001605// Is this a candidate for ld/st merging or pairing? For example, we don't
1606// touch volatiles or load/stores that have a hint to avoid pair formation.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001607bool AArch64InstrInfo::isCandidateToMergeOrPair(MachineInstr &MI) const {
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001608 // If this is a volatile load/store, don't mess with it.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001609 if (MI.hasOrderedMemoryRef())
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001610 return false;
1611
1612 // Make sure this is a reg+imm (as opposed to an address reloc).
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001613 assert(MI.getOperand(1).isReg() && "Expected a reg operand.");
1614 if (!MI.getOperand(2).isImm())
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001615 return false;
1616
1617 // Can't merge/pair if the instruction modifies the base register.
1618 // e.g., ldr x0, [x0]
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001619 unsigned BaseReg = MI.getOperand(1).getReg();
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001620 const TargetRegisterInfo *TRI = &getRegisterInfo();
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001621 if (MI.modifiesRegister(BaseReg, TRI))
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001622 return false;
1623
1624 // Check if this load/store has a hint to avoid pair formation.
1625 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
1626 if (isLdStPairSuppressed(MI))
1627 return false;
1628
Matthias Braun651cff42016-06-02 18:03:53 +00001629 // On some CPUs quad load/store pairs are slower than two single load/stores.
1630 if (Subtarget.avoidQuadLdStPairs()) {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001631 switch (MI.getOpcode()) {
Matthias Braunbcfd2362016-05-28 01:06:51 +00001632 default:
1633 break;
Matthias Braunbcfd2362016-05-28 01:06:51 +00001634 case AArch64::LDURQi:
1635 case AArch64::STURQi:
1636 case AArch64::LDRQui:
1637 case AArch64::STRQui:
1638 return false;
Evandro Menezes8d53f882016-04-13 18:31:45 +00001639 }
Matthias Braunbcfd2362016-05-28 01:06:51 +00001640 }
Evandro Menezes8d53f882016-04-13 18:31:45 +00001641
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001642 return true;
1643}
1644
Chad Rosierc27a18f2016-03-09 16:00:35 +00001645bool AArch64InstrInfo::getMemOpBaseRegImmOfs(
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001646 MachineInstr &LdSt, unsigned &BaseReg, int64_t &Offset,
Chad Rosierc27a18f2016-03-09 16:00:35 +00001647 const TargetRegisterInfo *TRI) const {
Geoff Berry22dfbc52016-08-12 15:26:00 +00001648 unsigned Width;
1649 return getMemOpBaseRegImmOfsWidth(LdSt, BaseReg, Offset, Width, TRI);
Tim Northover3b0846e2014-05-24 12:50:23 +00001650}
1651
Sanjoy Dasb666ea32015-06-15 18:44:14 +00001652bool AArch64InstrInfo::getMemOpBaseRegImmOfsWidth(
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001653 MachineInstr &LdSt, unsigned &BaseReg, int64_t &Offset, unsigned &Width,
Chad Rosier3528c1e2014-09-08 14:43:48 +00001654 const TargetRegisterInfo *TRI) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001655 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
Chad Rosier3528c1e2014-09-08 14:43:48 +00001656 // Handle only loads/stores with base register followed by immediate offset.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001657 if (LdSt.getNumExplicitOperands() == 3) {
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001658 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001659 if (!LdSt.getOperand(1).isReg() || !LdSt.getOperand(2).isImm())
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001660 return false;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001661 } else if (LdSt.getNumExplicitOperands() == 4) {
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001662 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001663 if (!LdSt.getOperand(1).isReg() || !LdSt.getOperand(2).isReg() ||
1664 !LdSt.getOperand(3).isImm())
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001665 return false;
1666 } else
Chad Rosier3528c1e2014-09-08 14:43:48 +00001667 return false;
1668
1669 // Offset is calculated as the immediate operand multiplied by the scaling factor.
1670 // Unscaled instructions have scaling factor set to 1.
Chad Rosier0da267d2016-03-09 16:46:48 +00001671 unsigned Scale = 0;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001672 switch (LdSt.getOpcode()) {
Chad Rosier3528c1e2014-09-08 14:43:48 +00001673 default:
1674 return false;
1675 case AArch64::LDURQi:
1676 case AArch64::STURQi:
1677 Width = 16;
1678 Scale = 1;
1679 break;
1680 case AArch64::LDURXi:
1681 case AArch64::LDURDi:
1682 case AArch64::STURXi:
1683 case AArch64::STURDi:
1684 Width = 8;
1685 Scale = 1;
1686 break;
1687 case AArch64::LDURWi:
1688 case AArch64::LDURSi:
1689 case AArch64::LDURSWi:
1690 case AArch64::STURWi:
1691 case AArch64::STURSi:
1692 Width = 4;
1693 Scale = 1;
1694 break;
1695 case AArch64::LDURHi:
1696 case AArch64::LDURHHi:
1697 case AArch64::LDURSHXi:
1698 case AArch64::LDURSHWi:
1699 case AArch64::STURHi:
1700 case AArch64::STURHHi:
1701 Width = 2;
1702 Scale = 1;
1703 break;
1704 case AArch64::LDURBi:
1705 case AArch64::LDURBBi:
1706 case AArch64::LDURSBXi:
1707 case AArch64::LDURSBWi:
1708 case AArch64::STURBi:
1709 case AArch64::STURBBi:
1710 Width = 1;
1711 Scale = 1;
1712 break;
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001713 case AArch64::LDPQi:
1714 case AArch64::LDNPQi:
1715 case AArch64::STPQi:
1716 case AArch64::STNPQi:
1717 Scale = 16;
1718 Width = 32;
1719 break;
Chad Rosierd90e2eb2015-09-18 14:15:19 +00001720 case AArch64::LDRQui:
1721 case AArch64::STRQui:
1722 Scale = Width = 16;
1723 break;
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001724 case AArch64::LDPXi:
1725 case AArch64::LDPDi:
1726 case AArch64::LDNPXi:
1727 case AArch64::LDNPDi:
1728 case AArch64::STPXi:
1729 case AArch64::STPDi:
1730 case AArch64::STNPXi:
1731 case AArch64::STNPDi:
1732 Scale = 8;
1733 Width = 16;
1734 break;
Chad Rosier3528c1e2014-09-08 14:43:48 +00001735 case AArch64::LDRXui:
Chad Rosier84a0afd2015-09-18 14:13:18 +00001736 case AArch64::LDRDui:
Chad Rosier3528c1e2014-09-08 14:43:48 +00001737 case AArch64::STRXui:
Chad Rosier84a0afd2015-09-18 14:13:18 +00001738 case AArch64::STRDui:
Chad Rosier3528c1e2014-09-08 14:43:48 +00001739 Scale = Width = 8;
1740 break;
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001741 case AArch64::LDPWi:
1742 case AArch64::LDPSi:
1743 case AArch64::LDNPWi:
1744 case AArch64::LDNPSi:
1745 case AArch64::STPWi:
1746 case AArch64::STPSi:
1747 case AArch64::STNPWi:
1748 case AArch64::STNPSi:
1749 Scale = 4;
1750 Width = 8;
1751 break;
Chad Rosier3528c1e2014-09-08 14:43:48 +00001752 case AArch64::LDRWui:
Chad Rosier3528c1e2014-09-08 14:43:48 +00001753 case AArch64::LDRSui:
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001754 case AArch64::LDRSWui:
Chad Rosier84a0afd2015-09-18 14:13:18 +00001755 case AArch64::STRWui:
Chad Rosier3528c1e2014-09-08 14:43:48 +00001756 case AArch64::STRSui:
1757 Scale = Width = 4;
1758 break;
Chad Rosier84a0afd2015-09-18 14:13:18 +00001759 case AArch64::LDRHui:
1760 case AArch64::LDRHHui:
1761 case AArch64::STRHui:
1762 case AArch64::STRHHui:
1763 Scale = Width = 2;
Chad Rosier3528c1e2014-09-08 14:43:48 +00001764 break;
Chad Rosierd90e2eb2015-09-18 14:15:19 +00001765 case AArch64::LDRBui:
1766 case AArch64::LDRBBui:
1767 case AArch64::STRBui:
1768 case AArch64::STRBBui:
1769 Scale = Width = 1;
Chad Rosier3528c1e2014-09-08 14:43:48 +00001770 break;
Chad Rosier064261d2016-02-01 20:54:36 +00001771 }
Chad Rosier3528c1e2014-09-08 14:43:48 +00001772
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001773 if (LdSt.getNumExplicitOperands() == 3) {
1774 BaseReg = LdSt.getOperand(1).getReg();
1775 Offset = LdSt.getOperand(2).getImm() * Scale;
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001776 } else {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001777 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
1778 BaseReg = LdSt.getOperand(2).getReg();
1779 Offset = LdSt.getOperand(3).getImm() * Scale;
Chad Rosier1fbe9bc2016-04-15 18:09:10 +00001780 }
Chad Rosier3528c1e2014-09-08 14:43:48 +00001781 return true;
1782}
1783
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001784// Scale the unscaled offsets. Returns false if the unscaled offset can't be
1785// scaled.
1786static bool scaleOffset(unsigned Opc, int64_t &Offset) {
1787 unsigned OffsetStride = 1;
1788 switch (Opc) {
1789 default:
1790 return false;
1791 case AArch64::LDURQi:
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001792 case AArch64::STURQi:
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001793 OffsetStride = 16;
1794 break;
1795 case AArch64::LDURXi:
1796 case AArch64::LDURDi:
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001797 case AArch64::STURXi:
1798 case AArch64::STURDi:
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001799 OffsetStride = 8;
1800 break;
1801 case AArch64::LDURWi:
1802 case AArch64::LDURSi:
1803 case AArch64::LDURSWi:
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001804 case AArch64::STURWi:
1805 case AArch64::STURSi:
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001806 OffsetStride = 4;
1807 break;
1808 }
1809 // If the byte-offset isn't a multiple of the stride, we can't scale this
1810 // offset.
1811 if (Offset % OffsetStride != 0)
1812 return false;
1813
1814 // Convert the byte-offset used by unscaled into an "element" offset used
1815 // by the scaled pair load/store instructions.
1816 Offset /= OffsetStride;
1817 return true;
1818}
1819
1820static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
1821 if (FirstOpc == SecondOpc)
1822 return true;
1823 // We can also pair sign-ext and zero-ext instructions.
1824 switch (FirstOpc) {
1825 default:
1826 return false;
1827 case AArch64::LDRWui:
1828 case AArch64::LDURWi:
1829 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
1830 case AArch64::LDRSWui:
1831 case AArch64::LDURSWi:
1832 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
1833 }
1834 // These instructions can't be paired based on their opcodes.
1835 return false;
1836}
1837
Tim Northover3b0846e2014-05-24 12:50:23 +00001838/// Detect opportunities for ldp/stp formation.
1839///
Sanjoy Dasb666ea32015-06-15 18:44:14 +00001840/// Only called for LdSt for which getMemOpBaseRegImmOfs returns true.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001841bool AArch64InstrInfo::shouldClusterMemOps(MachineInstr &FirstLdSt,
1842 MachineInstr &SecondLdSt,
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001843 unsigned NumLoads) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001844 // Only cluster up to a single pair.
1845 if (NumLoads > 1)
1846 return false;
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001847
Geoff Berry22dfbc52016-08-12 15:26:00 +00001848 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
1849 return false;
1850
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001851 // Can we pair these instructions based on their opcodes?
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001852 unsigned FirstOpc = FirstLdSt.getOpcode();
1853 unsigned SecondOpc = SecondLdSt.getOpcode();
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001854 if (!canPairLdStOpc(FirstOpc, SecondOpc))
Tim Northover3b0846e2014-05-24 12:50:23 +00001855 return false;
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001856
1857 // Can't merge volatiles or load/stores that have a hint to avoid pair
1858 // formation, for example.
1859 if (!isCandidateToMergeOrPair(FirstLdSt) ||
1860 !isCandidateToMergeOrPair(SecondLdSt))
Tim Northover3b0846e2014-05-24 12:50:23 +00001861 return false;
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001862
1863 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001864 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001865 if (isUnscaledLdSt(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
1866 return false;
1867
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001868 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001869 if (isUnscaledLdSt(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
1870 return false;
1871
1872 // Pairwise instructions have a 7-bit signed offset field.
1873 if (Offset1 > 63 || Offset1 < -64)
1874 return false;
1875
Tim Northover3b0846e2014-05-24 12:50:23 +00001876 // The caller should already have ordered First/SecondLdSt by offset.
Chad Rosiercdfd7e72016-03-18 19:21:02 +00001877 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
1878 return Offset1 + 1 == Offset2;
Tim Northover3b0846e2014-05-24 12:50:23 +00001879}
1880
Matthias Braun115efcd2016-11-28 20:11:54 +00001881bool AArch64InstrInfo::shouldScheduleAdjacent(
1882 const MachineInstr &First, const MachineInstr &Second) const {
Matthias Braun46a52382016-10-04 19:28:21 +00001883 if (Subtarget.hasArithmeticBccFusion()) {
Matthias Braun651cff42016-06-02 18:03:53 +00001884 // Fuse CMN, CMP, TST followed by Bcc.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001885 unsigned SecondOpcode = Second.getOpcode();
Matthias Braunc8b67e62015-07-20 23:11:42 +00001886 if (SecondOpcode == AArch64::Bcc) {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001887 switch (First.getOpcode()) {
Matthias Braunc8b67e62015-07-20 23:11:42 +00001888 default:
1889 return false;
Matthias Braunc8b67e62015-07-20 23:11:42 +00001890 case AArch64::ADDSWri:
Matthias Braun46a52382016-10-04 19:28:21 +00001891 case AArch64::ADDSWrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001892 case AArch64::ADDSXri:
Matthias Braun46a52382016-10-04 19:28:21 +00001893 case AArch64::ADDSXrr:
1894 case AArch64::ANDSWri:
1895 case AArch64::ANDSWrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001896 case AArch64::ANDSXri:
Matthias Braun46a52382016-10-04 19:28:21 +00001897 case AArch64::ANDSXrr:
1898 case AArch64::SUBSWri:
1899 case AArch64::SUBSWrr:
1900 case AArch64::SUBSXri:
1901 case AArch64::SUBSXrr:
1902 case AArch64::BICSWrr:
1903 case AArch64::BICSXrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001904 return true;
Matthias Braun46a52382016-10-04 19:28:21 +00001905 case AArch64::ADDSWrs:
1906 case AArch64::ADDSXrs:
1907 case AArch64::ANDSWrs:
1908 case AArch64::ANDSXrs:
1909 case AArch64::SUBSWrs:
1910 case AArch64::SUBSXrs:
1911 case AArch64::BICSWrs:
1912 case AArch64::BICSXrs:
1913 // Shift value can be 0 making these behave like the "rr" variant...
1914 return !hasShiftedReg(Second);
Matthias Braunc8b67e62015-07-20 23:11:42 +00001915 }
Matthias Braune536f4f2015-07-20 22:34:47 +00001916 }
Matthias Braun46a52382016-10-04 19:28:21 +00001917 }
1918 if (Subtarget.hasArithmeticCbzFusion()) {
Matthias Braun651cff42016-06-02 18:03:53 +00001919 // Fuse ALU operations followed by CBZ/CBNZ.
Matthias Braun46a52382016-10-04 19:28:21 +00001920 unsigned SecondOpcode = Second.getOpcode();
Matthias Braunc8b67e62015-07-20 23:11:42 +00001921 if (SecondOpcode == AArch64::CBNZW || SecondOpcode == AArch64::CBNZX ||
1922 SecondOpcode == AArch64::CBZW || SecondOpcode == AArch64::CBZX) {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001923 switch (First.getOpcode()) {
Matthias Braunc8b67e62015-07-20 23:11:42 +00001924 default:
1925 return false;
1926 case AArch64::ADDWri:
Matthias Braun46a52382016-10-04 19:28:21 +00001927 case AArch64::ADDWrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001928 case AArch64::ADDXri:
Matthias Braun46a52382016-10-04 19:28:21 +00001929 case AArch64::ADDXrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001930 case AArch64::ANDWri:
Matthias Braun46a52382016-10-04 19:28:21 +00001931 case AArch64::ANDWrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001932 case AArch64::ANDXri:
Matthias Braun46a52382016-10-04 19:28:21 +00001933 case AArch64::ANDXrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001934 case AArch64::EORWri:
Matthias Braun46a52382016-10-04 19:28:21 +00001935 case AArch64::EORWrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001936 case AArch64::EORXri:
Matthias Braun46a52382016-10-04 19:28:21 +00001937 case AArch64::EORXrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001938 case AArch64::ORRWri:
Matthias Braun46a52382016-10-04 19:28:21 +00001939 case AArch64::ORRWrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001940 case AArch64::ORRXri:
Matthias Braun46a52382016-10-04 19:28:21 +00001941 case AArch64::ORRXrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001942 case AArch64::SUBWri:
Matthias Braun46a52382016-10-04 19:28:21 +00001943 case AArch64::SUBWrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001944 case AArch64::SUBXri:
Matthias Braun46a52382016-10-04 19:28:21 +00001945 case AArch64::SUBXrr:
Matthias Braunc8b67e62015-07-20 23:11:42 +00001946 return true;
Matthias Braun46a52382016-10-04 19:28:21 +00001947 case AArch64::ADDWrs:
1948 case AArch64::ADDXrs:
1949 case AArch64::ANDWrs:
1950 case AArch64::ANDXrs:
1951 case AArch64::SUBWrs:
1952 case AArch64::SUBXrs:
1953 case AArch64::BICWrs:
1954 case AArch64::BICXrs:
1955 // Shift value can be 0 making these behave like the "rr" variant...
1956 return !hasShiftedReg(Second);
Matthias Braunc8b67e62015-07-20 23:11:42 +00001957 }
Matthias Braune536f4f2015-07-20 22:34:47 +00001958 }
1959 }
1960 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00001961}
1962
Adrian Prantl87b7eb92014-10-01 18:55:02 +00001963MachineInstr *AArch64InstrInfo::emitFrameIndexDebugValue(
1964 MachineFunction &MF, int FrameIx, uint64_t Offset, const MDNode *Var,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001965 const MDNode *Expr, const DebugLoc &DL) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001966 MachineInstrBuilder MIB = BuildMI(MF, DL, get(AArch64::DBG_VALUE))
1967 .addFrameIndex(FrameIx)
1968 .addImm(0)
1969 .addImm(Offset)
Adrian Prantl87b7eb92014-10-01 18:55:02 +00001970 .addMetadata(Var)
1971 .addMetadata(Expr);
Tim Northover3b0846e2014-05-24 12:50:23 +00001972 return &*MIB;
1973}
1974
1975static const MachineInstrBuilder &AddSubReg(const MachineInstrBuilder &MIB,
1976 unsigned Reg, unsigned SubIdx,
1977 unsigned State,
1978 const TargetRegisterInfo *TRI) {
1979 if (!SubIdx)
1980 return MIB.addReg(Reg, State);
1981
1982 if (TargetRegisterInfo::isPhysicalRegister(Reg))
1983 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
1984 return MIB.addReg(Reg, State, SubIdx);
1985}
1986
1987static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg,
1988 unsigned NumRegs) {
1989 // We really want the positive remainder mod 32 here, that happens to be
1990 // easily obtainable with a mask.
1991 return ((DestReg - SrcReg) & 0x1f) < NumRegs;
1992}
1993
1994void AArch64InstrInfo::copyPhysRegTuple(
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001995 MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL,
Tim Northover3b0846e2014-05-24 12:50:23 +00001996 unsigned DestReg, unsigned SrcReg, bool KillSrc, unsigned Opcode,
1997 llvm::ArrayRef<unsigned> Indices) const {
Eric Christopher58f32662014-06-10 22:57:21 +00001998 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001999 "Unexpected register copy without NEON");
Eric Christophera0de2532015-03-18 20:37:30 +00002000 const TargetRegisterInfo *TRI = &getRegisterInfo();
Tim Northover3b0846e2014-05-24 12:50:23 +00002001 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
2002 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
2003 unsigned NumRegs = Indices.size();
2004
2005 int SubReg = 0, End = NumRegs, Incr = 1;
2006 if (forwardCopyWillClobberTuple(DestEncoding, SrcEncoding, NumRegs)) {
2007 SubReg = NumRegs - 1;
2008 End = -1;
2009 Incr = -1;
2010 }
2011
2012 for (; SubReg != End; SubReg += Incr) {
James Molloyf8aa57a2015-04-16 11:37:40 +00002013 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
Tim Northover3b0846e2014-05-24 12:50:23 +00002014 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
2015 AddSubReg(MIB, SrcReg, Indices[SubReg], 0, TRI);
2016 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
2017 }
2018}
2019
2020void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00002021 MachineBasicBlock::iterator I,
2022 const DebugLoc &DL, unsigned DestReg,
2023 unsigned SrcReg, bool KillSrc) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00002024 if (AArch64::GPR32spRegClass.contains(DestReg) &&
2025 (AArch64::GPR32spRegClass.contains(SrcReg) || SrcReg == AArch64::WZR)) {
Eric Christophera0de2532015-03-18 20:37:30 +00002026 const TargetRegisterInfo *TRI = &getRegisterInfo();
2027
Tim Northover3b0846e2014-05-24 12:50:23 +00002028 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
2029 // If either operand is WSP, expand to ADD #0.
2030 if (Subtarget.hasZeroCycleRegMove()) {
2031 // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
2032 unsigned DestRegX = TRI->getMatchingSuperReg(DestReg, AArch64::sub_32,
2033 &AArch64::GPR64spRegClass);
2034 unsigned SrcRegX = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_32,
2035 &AArch64::GPR64spRegClass);
2036 // This instruction is reading and writing X registers. This may upset
2037 // the register scavenger and machine verifier, so we need to indicate
2038 // that we are reading an undefined value from SrcRegX, but a proper
2039 // value from SrcReg.
2040 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
2041 .addReg(SrcRegX, RegState::Undef)
2042 .addImm(0)
2043 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0))
2044 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
2045 } else {
2046 BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
2047 .addReg(SrcReg, getKillRegState(KillSrc))
2048 .addImm(0)
2049 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
2050 }
2051 } else if (SrcReg == AArch64::WZR && Subtarget.hasZeroCycleZeroing()) {
2052 BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg).addImm(0).addImm(
2053 AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
2054 } else {
2055 if (Subtarget.hasZeroCycleRegMove()) {
2056 // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
2057 unsigned DestRegX = TRI->getMatchingSuperReg(DestReg, AArch64::sub_32,
2058 &AArch64::GPR64spRegClass);
2059 unsigned SrcRegX = TRI->getMatchingSuperReg(SrcReg, AArch64::sub_32,
2060 &AArch64::GPR64spRegClass);
2061 // This instruction is reading and writing X registers. This may upset
2062 // the register scavenger and machine verifier, so we need to indicate
2063 // that we are reading an undefined value from SrcRegX, but a proper
2064 // value from SrcReg.
2065 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
2066 .addReg(AArch64::XZR)
2067 .addReg(SrcRegX, RegState::Undef)
2068 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
2069 } else {
2070 // Otherwise, expand to ORR WZR.
2071 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
2072 .addReg(AArch64::WZR)
2073 .addReg(SrcReg, getKillRegState(KillSrc));
2074 }
2075 }
2076 return;
2077 }
2078
2079 if (AArch64::GPR64spRegClass.contains(DestReg) &&
2080 (AArch64::GPR64spRegClass.contains(SrcReg) || SrcReg == AArch64::XZR)) {
2081 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
2082 // If either operand is SP, expand to ADD #0.
2083 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
2084 .addReg(SrcReg, getKillRegState(KillSrc))
2085 .addImm(0)
2086 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
2087 } else if (SrcReg == AArch64::XZR && Subtarget.hasZeroCycleZeroing()) {
2088 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg).addImm(0).addImm(
2089 AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
2090 } else {
2091 // Otherwise, expand to ORR XZR.
2092 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
2093 .addReg(AArch64::XZR)
2094 .addReg(SrcReg, getKillRegState(KillSrc));
2095 }
2096 return;
2097 }
2098
2099 // Copy a DDDD register quad by copying the individual sub-registers.
2100 if (AArch64::DDDDRegClass.contains(DestReg) &&
2101 AArch64::DDDDRegClass.contains(SrcReg)) {
2102 static const unsigned Indices[] = { AArch64::dsub0, AArch64::dsub1,
2103 AArch64::dsub2, AArch64::dsub3 };
2104 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
2105 Indices);
2106 return;
2107 }
2108
2109 // Copy a DDD register triple by copying the individual sub-registers.
2110 if (AArch64::DDDRegClass.contains(DestReg) &&
2111 AArch64::DDDRegClass.contains(SrcReg)) {
2112 static const unsigned Indices[] = { AArch64::dsub0, AArch64::dsub1,
2113 AArch64::dsub2 };
2114 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
2115 Indices);
2116 return;
2117 }
2118
2119 // Copy a DD register pair by copying the individual sub-registers.
2120 if (AArch64::DDRegClass.contains(DestReg) &&
2121 AArch64::DDRegClass.contains(SrcReg)) {
2122 static const unsigned Indices[] = { AArch64::dsub0, AArch64::dsub1 };
2123 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
2124 Indices);
2125 return;
2126 }
2127
2128 // Copy a QQQQ register quad by copying the individual sub-registers.
2129 if (AArch64::QQQQRegClass.contains(DestReg) &&
2130 AArch64::QQQQRegClass.contains(SrcReg)) {
2131 static const unsigned Indices[] = { AArch64::qsub0, AArch64::qsub1,
2132 AArch64::qsub2, AArch64::qsub3 };
2133 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
2134 Indices);
2135 return;
2136 }
2137
2138 // Copy a QQQ register triple by copying the individual sub-registers.
2139 if (AArch64::QQQRegClass.contains(DestReg) &&
2140 AArch64::QQQRegClass.contains(SrcReg)) {
2141 static const unsigned Indices[] = { AArch64::qsub0, AArch64::qsub1,
2142 AArch64::qsub2 };
2143 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
2144 Indices);
2145 return;
2146 }
2147
2148 // Copy a QQ register pair by copying the individual sub-registers.
2149 if (AArch64::QQRegClass.contains(DestReg) &&
2150 AArch64::QQRegClass.contains(SrcReg)) {
2151 static const unsigned Indices[] = { AArch64::qsub0, AArch64::qsub1 };
2152 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
2153 Indices);
2154 return;
2155 }
2156
2157 if (AArch64::FPR128RegClass.contains(DestReg) &&
2158 AArch64::FPR128RegClass.contains(SrcReg)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002159 if(Subtarget.hasNEON()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002160 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2161 .addReg(SrcReg)
2162 .addReg(SrcReg, getKillRegState(KillSrc));
2163 } else {
2164 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
2165 .addReg(AArch64::SP, RegState::Define)
2166 .addReg(SrcReg, getKillRegState(KillSrc))
2167 .addReg(AArch64::SP)
2168 .addImm(-16);
2169 BuildMI(MBB, I, DL, get(AArch64::LDRQpre))
2170 .addReg(AArch64::SP, RegState::Define)
2171 .addReg(DestReg, RegState::Define)
2172 .addReg(AArch64::SP)
2173 .addImm(16);
2174 }
2175 return;
2176 }
2177
2178 if (AArch64::FPR64RegClass.contains(DestReg) &&
2179 AArch64::FPR64RegClass.contains(SrcReg)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002180 if(Subtarget.hasNEON()) {
Eric Christophera0de2532015-03-18 20:37:30 +00002181 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
2182 &AArch64::FPR128RegClass);
2183 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
2184 &AArch64::FPR128RegClass);
Tim Northover3b0846e2014-05-24 12:50:23 +00002185 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2186 .addReg(SrcReg)
2187 .addReg(SrcReg, getKillRegState(KillSrc));
2188 } else {
2189 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
2190 .addReg(SrcReg, getKillRegState(KillSrc));
2191 }
2192 return;
2193 }
2194
2195 if (AArch64::FPR32RegClass.contains(DestReg) &&
2196 AArch64::FPR32RegClass.contains(SrcReg)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002197 if(Subtarget.hasNEON()) {
Eric Christophera0de2532015-03-18 20:37:30 +00002198 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
2199 &AArch64::FPR128RegClass);
2200 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
2201 &AArch64::FPR128RegClass);
Tim Northover3b0846e2014-05-24 12:50:23 +00002202 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2203 .addReg(SrcReg)
2204 .addReg(SrcReg, getKillRegState(KillSrc));
2205 } else {
2206 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
2207 .addReg(SrcReg, getKillRegState(KillSrc));
2208 }
2209 return;
2210 }
2211
2212 if (AArch64::FPR16RegClass.contains(DestReg) &&
2213 AArch64::FPR16RegClass.contains(SrcReg)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002214 if(Subtarget.hasNEON()) {
Eric Christophera0de2532015-03-18 20:37:30 +00002215 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
2216 &AArch64::FPR128RegClass);
2217 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
2218 &AArch64::FPR128RegClass);
Tim Northover3b0846e2014-05-24 12:50:23 +00002219 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2220 .addReg(SrcReg)
2221 .addReg(SrcReg, getKillRegState(KillSrc));
2222 } else {
Eric Christophera0de2532015-03-18 20:37:30 +00002223 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
2224 &AArch64::FPR32RegClass);
2225 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
2226 &AArch64::FPR32RegClass);
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
2228 .addReg(SrcReg, getKillRegState(KillSrc));
2229 }
2230 return;
2231 }
2232
2233 if (AArch64::FPR8RegClass.contains(DestReg) &&
2234 AArch64::FPR8RegClass.contains(SrcReg)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002235 if(Subtarget.hasNEON()) {
Eric Christophera0de2532015-03-18 20:37:30 +00002236 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
Tim Northover3b0846e2014-05-24 12:50:23 +00002237 &AArch64::FPR128RegClass);
Eric Christophera0de2532015-03-18 20:37:30 +00002238 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
2239 &AArch64::FPR128RegClass);
Tim Northover3b0846e2014-05-24 12:50:23 +00002240 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
2241 .addReg(SrcReg)
2242 .addReg(SrcReg, getKillRegState(KillSrc));
2243 } else {
Eric Christophera0de2532015-03-18 20:37:30 +00002244 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
2245 &AArch64::FPR32RegClass);
2246 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
2247 &AArch64::FPR32RegClass);
Tim Northover3b0846e2014-05-24 12:50:23 +00002248 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
2249 .addReg(SrcReg, getKillRegState(KillSrc));
2250 }
2251 return;
2252 }
2253
2254 // Copies between GPR64 and FPR64.
2255 if (AArch64::FPR64RegClass.contains(DestReg) &&
2256 AArch64::GPR64RegClass.contains(SrcReg)) {
2257 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
2258 .addReg(SrcReg, getKillRegState(KillSrc));
2259 return;
2260 }
2261 if (AArch64::GPR64RegClass.contains(DestReg) &&
2262 AArch64::FPR64RegClass.contains(SrcReg)) {
2263 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
2264 .addReg(SrcReg, getKillRegState(KillSrc));
2265 return;
2266 }
2267 // Copies between GPR32 and FPR32.
2268 if (AArch64::FPR32RegClass.contains(DestReg) &&
2269 AArch64::GPR32RegClass.contains(SrcReg)) {
2270 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
2271 .addReg(SrcReg, getKillRegState(KillSrc));
2272 return;
2273 }
2274 if (AArch64::GPR32RegClass.contains(DestReg) &&
2275 AArch64::FPR32RegClass.contains(SrcReg)) {
2276 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
2277 .addReg(SrcReg, getKillRegState(KillSrc));
2278 return;
2279 }
2280
Tim Northover1bed9af2014-05-27 12:16:02 +00002281 if (DestReg == AArch64::NZCV) {
2282 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
2283 BuildMI(MBB, I, DL, get(AArch64::MSR))
2284 .addImm(AArch64SysReg::NZCV)
2285 .addReg(SrcReg, getKillRegState(KillSrc))
2286 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
2287 return;
2288 }
2289
2290 if (SrcReg == AArch64::NZCV) {
2291 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
Quentin Colombet658d9db2016-04-22 18:46:17 +00002292 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
Tim Northover1bed9af2014-05-27 12:16:02 +00002293 .addImm(AArch64SysReg::NZCV)
2294 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
2295 return;
2296 }
2297
2298 llvm_unreachable("unimplemented reg-to-reg copy");
Tim Northover3b0846e2014-05-24 12:50:23 +00002299}
2300
2301void AArch64InstrInfo::storeRegToStackSlot(
2302 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg,
2303 bool isKill, int FI, const TargetRegisterClass *RC,
2304 const TargetRegisterInfo *TRI) const {
2305 DebugLoc DL;
2306 if (MBBI != MBB.end())
2307 DL = MBBI->getDebugLoc();
2308 MachineFunction &MF = *MBB.getParent();
Matthias Braun941a7052016-07-28 18:40:00 +00002309 MachineFrameInfo &MFI = MF.getFrameInfo();
Tim Northover3b0846e2014-05-24 12:50:23 +00002310 unsigned Align = MFI.getObjectAlignment(FI);
2311
Alex Lorenze40c8a22015-08-11 23:09:45 +00002312 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
Tim Northover3b0846e2014-05-24 12:50:23 +00002313 MachineMemOperand *MMO = MF.getMachineMemOperand(
2314 PtrInfo, MachineMemOperand::MOStore, MFI.getObjectSize(FI), Align);
2315 unsigned Opc = 0;
2316 bool Offset = true;
2317 switch (RC->getSize()) {
2318 case 1:
2319 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
2320 Opc = AArch64::STRBui;
2321 break;
2322 case 2:
2323 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
2324 Opc = AArch64::STRHui;
2325 break;
2326 case 4:
2327 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
2328 Opc = AArch64::STRWui;
2329 if (TargetRegisterInfo::isVirtualRegister(SrcReg))
2330 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
2331 else
2332 assert(SrcReg != AArch64::WSP);
2333 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
2334 Opc = AArch64::STRSui;
2335 break;
2336 case 8:
2337 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
2338 Opc = AArch64::STRXui;
2339 if (TargetRegisterInfo::isVirtualRegister(SrcReg))
2340 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
2341 else
2342 assert(SrcReg != AArch64::SP);
2343 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
2344 Opc = AArch64::STRDui;
2345 break;
2346 case 16:
2347 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
2348 Opc = AArch64::STRQui;
2349 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002350 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002351 "Unexpected register store without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002352 Opc = AArch64::ST1Twov1d;
2353 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002354 }
2355 break;
2356 case 24:
2357 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002358 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002359 "Unexpected register store without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002360 Opc = AArch64::ST1Threev1d;
2361 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002362 }
2363 break;
2364 case 32:
2365 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002366 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002367 "Unexpected register store without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002368 Opc = AArch64::ST1Fourv1d;
2369 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002370 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002371 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002372 "Unexpected register store without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002373 Opc = AArch64::ST1Twov2d;
2374 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002375 }
2376 break;
2377 case 48:
2378 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002379 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002380 "Unexpected register store without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002381 Opc = AArch64::ST1Threev2d;
2382 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 }
2384 break;
2385 case 64:
2386 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002387 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002388 "Unexpected register store without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002389 Opc = AArch64::ST1Fourv2d;
2390 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002391 }
2392 break;
2393 }
2394 assert(Opc && "Unknown register class");
2395
James Molloyf8aa57a2015-04-16 11:37:40 +00002396 const MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, get(Opc))
Tim Northover3b0846e2014-05-24 12:50:23 +00002397 .addReg(SrcReg, getKillRegState(isKill))
2398 .addFrameIndex(FI);
2399
2400 if (Offset)
2401 MI.addImm(0);
2402 MI.addMemOperand(MMO);
2403}
2404
2405void AArch64InstrInfo::loadRegFromStackSlot(
2406 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg,
2407 int FI, const TargetRegisterClass *RC,
2408 const TargetRegisterInfo *TRI) const {
2409 DebugLoc DL;
2410 if (MBBI != MBB.end())
2411 DL = MBBI->getDebugLoc();
2412 MachineFunction &MF = *MBB.getParent();
Matthias Braun941a7052016-07-28 18:40:00 +00002413 MachineFrameInfo &MFI = MF.getFrameInfo();
Tim Northover3b0846e2014-05-24 12:50:23 +00002414 unsigned Align = MFI.getObjectAlignment(FI);
Alex Lorenze40c8a22015-08-11 23:09:45 +00002415 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
Tim Northover3b0846e2014-05-24 12:50:23 +00002416 MachineMemOperand *MMO = MF.getMachineMemOperand(
2417 PtrInfo, MachineMemOperand::MOLoad, MFI.getObjectSize(FI), Align);
2418
2419 unsigned Opc = 0;
2420 bool Offset = true;
2421 switch (RC->getSize()) {
2422 case 1:
2423 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
2424 Opc = AArch64::LDRBui;
2425 break;
2426 case 2:
2427 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
2428 Opc = AArch64::LDRHui;
2429 break;
2430 case 4:
2431 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
2432 Opc = AArch64::LDRWui;
2433 if (TargetRegisterInfo::isVirtualRegister(DestReg))
2434 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
2435 else
2436 assert(DestReg != AArch64::WSP);
2437 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
2438 Opc = AArch64::LDRSui;
2439 break;
2440 case 8:
2441 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
2442 Opc = AArch64::LDRXui;
2443 if (TargetRegisterInfo::isVirtualRegister(DestReg))
2444 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
2445 else
2446 assert(DestReg != AArch64::SP);
2447 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
2448 Opc = AArch64::LDRDui;
2449 break;
2450 case 16:
2451 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
2452 Opc = AArch64::LDRQui;
2453 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002454 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 "Unexpected register load without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002456 Opc = AArch64::LD1Twov1d;
2457 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002458 }
2459 break;
2460 case 24:
2461 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002462 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002463 "Unexpected register load without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002464 Opc = AArch64::LD1Threev1d;
2465 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002466 }
2467 break;
2468 case 32:
2469 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002470 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002471 "Unexpected register load without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002472 Opc = AArch64::LD1Fourv1d;
2473 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002474 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002475 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002476 "Unexpected register load without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002477 Opc = AArch64::LD1Twov2d;
2478 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002479 }
2480 break;
2481 case 48:
2482 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002483 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002484 "Unexpected register load without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002485 Opc = AArch64::LD1Threev2d;
2486 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002487 }
2488 break;
2489 case 64:
2490 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
Eric Christopher58f32662014-06-10 22:57:21 +00002491 assert(Subtarget.hasNEON() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 "Unexpected register load without NEON");
Richard Trieu7a083812016-02-18 22:09:30 +00002493 Opc = AArch64::LD1Fourv2d;
2494 Offset = false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002495 }
2496 break;
2497 }
2498 assert(Opc && "Unknown register class");
2499
James Molloyf8aa57a2015-04-16 11:37:40 +00002500 const MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, get(Opc))
Tim Northover3b0846e2014-05-24 12:50:23 +00002501 .addReg(DestReg, getDefRegState(true))
2502 .addFrameIndex(FI);
2503 if (Offset)
2504 MI.addImm(0);
2505 MI.addMemOperand(MMO);
2506}
2507
2508void llvm::emitFrameOffset(MachineBasicBlock &MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +00002509 MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 unsigned DestReg, unsigned SrcReg, int Offset,
Eric Christopherbc76b972014-06-10 17:33:39 +00002511 const TargetInstrInfo *TII,
Tim Northover3b0846e2014-05-24 12:50:23 +00002512 MachineInstr::MIFlag Flag, bool SetNZCV) {
2513 if (DestReg == SrcReg && Offset == 0)
2514 return;
2515
Geoff Berrya5335642016-05-06 16:34:59 +00002516 assert((DestReg != AArch64::SP || Offset % 16 == 0) &&
2517 "SP increment/decrement not 16-byte aligned");
2518
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 bool isSub = Offset < 0;
2520 if (isSub)
2521 Offset = -Offset;
2522
2523 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
2524 // scratch register. If DestReg is a virtual register, use it as the
2525 // scratch register; otherwise, create a new virtual register (to be
2526 // replaced by the scavenger at the end of PEI). That case can be optimized
2527 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
2528 // register can be loaded with offset%8 and the add/sub can use an extending
2529 // instruction with LSL#3.
2530 // Currently the function handles any offsets but generates a poor sequence
2531 // of code.
2532 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
2533
2534 unsigned Opc;
2535 if (SetNZCV)
2536 Opc = isSub ? AArch64::SUBSXri : AArch64::ADDSXri;
2537 else
2538 Opc = isSub ? AArch64::SUBXri : AArch64::ADDXri;
2539 const unsigned MaxEncoding = 0xfff;
2540 const unsigned ShiftSize = 12;
2541 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
2542 while (((unsigned)Offset) >= (1 << ShiftSize)) {
2543 unsigned ThisVal;
2544 if (((unsigned)Offset) > MaxEncodableValue) {
2545 ThisVal = MaxEncodableValue;
2546 } else {
2547 ThisVal = Offset & MaxEncodableValue;
2548 }
2549 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
2550 "Encoding cannot handle value that big");
2551 BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
2552 .addReg(SrcReg)
2553 .addImm(ThisVal >> ShiftSize)
2554 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftSize))
2555 .setMIFlag(Flag);
2556
2557 SrcReg = DestReg;
2558 Offset -= ThisVal;
2559 if (Offset == 0)
2560 return;
2561 }
2562 BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg)
2563 .addReg(SrcReg)
2564 .addImm(Offset)
2565 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0))
2566 .setMIFlag(Flag);
2567}
2568
Keno Fischere70b31f2015-06-08 20:09:58 +00002569MachineInstr *AArch64InstrInfo::foldMemoryOperandImpl(
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00002570 MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
Jonas Paulsson8e5b0c62016-05-10 08:09:37 +00002571 MachineBasicBlock::iterator InsertPt, int FrameIndex,
2572 LiveIntervals *LIS) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 // This is a bit of a hack. Consider this instruction:
2574 //
2575 // %vreg0<def> = COPY %SP; GPR64all:%vreg0
2576 //
2577 // We explicitly chose GPR64all for the virtual register so such a copy might
2578 // be eliminated by RegisterCoalescer. However, that may not be possible, and
2579 // %vreg0 may even spill. We can't spill %SP, and since it is in the GPR64all
2580 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
2581 //
2582 // To prevent that, we are going to constrain the %vreg0 register class here.
2583 //
2584 // <rdar://problem/11522048>
2585 //
Geoff Berryd46b6e82017-01-05 21:51:42 +00002586 if (MI.isFullCopy()) {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00002587 unsigned DstReg = MI.getOperand(0).getReg();
2588 unsigned SrcReg = MI.getOperand(1).getReg();
Tim Northover3b0846e2014-05-24 12:50:23 +00002589 if (SrcReg == AArch64::SP &&
2590 TargetRegisterInfo::isVirtualRegister(DstReg)) {
2591 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
2592 return nullptr;
2593 }
2594 if (DstReg == AArch64::SP &&
2595 TargetRegisterInfo::isVirtualRegister(SrcReg)) {
2596 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
2597 return nullptr;
2598 }
2599 }
2600
Geoff Berryd46b6e82017-01-05 21:51:42 +00002601 // Handle the case where a copy is being spilled or filled but the source
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002602 // and destination register class don't match. For example:
Geoff Berry7c078fc2016-11-29 18:28:32 +00002603 //
2604 // %vreg0<def> = COPY %XZR; GPR64common:%vreg0
2605 //
2606 // In this case we can still safely fold away the COPY and generate the
2607 // following spill code:
2608 //
2609 // STRXui %XZR, <fi#0>
2610 //
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002611 // This also eliminates spilled cross register class COPYs (e.g. between x and
2612 // d regs) of the same size. For example:
2613 //
2614 // %vreg0<def> = COPY %vreg1; GPR64:%vreg0, FPR64:%vreg1
2615 //
Geoff Berryd46b6e82017-01-05 21:51:42 +00002616 // will be filled as
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002617 //
2618 // LDRDui %vreg0, fi<#0>
2619 //
2620 // instead of
2621 //
2622 // LDRXui %vregTemp, fi<#0>
2623 // %vreg0 = FMOV %vregTemp
2624 //
Geoff Berryd46b6e82017-01-05 21:51:42 +00002625 if (MI.isCopy() && Ops.size() == 1 &&
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002626 // Make sure we're only folding the explicit COPY defs/uses.
2627 (Ops[0] == 0 || Ops[0] == 1)) {
Geoff Berryd46b6e82017-01-05 21:51:42 +00002628 bool IsSpill = Ops[0] == 0;
2629 bool IsFill = !IsSpill;
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002630 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
2631 const MachineRegisterInfo &MRI = MF.getRegInfo();
Geoff Berry7c078fc2016-11-29 18:28:32 +00002632 MachineBasicBlock &MBB = *MI.getParent();
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002633 const MachineOperand &DstMO = MI.getOperand(0);
Geoff Berry7c078fc2016-11-29 18:28:32 +00002634 const MachineOperand &SrcMO = MI.getOperand(1);
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002635 unsigned DstReg = DstMO.getReg();
Geoff Berry7c078fc2016-11-29 18:28:32 +00002636 unsigned SrcReg = SrcMO.getReg();
Geoff Berryd46b6e82017-01-05 21:51:42 +00002637 // This is slightly expensive to compute for physical regs since
2638 // getMinimalPhysRegClass is slow.
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002639 auto getRegClass = [&](unsigned Reg) {
2640 return TargetRegisterInfo::isVirtualRegister(Reg)
2641 ? MRI.getRegClass(Reg)
2642 : TRI.getMinimalPhysRegClass(Reg);
2643 };
Geoff Berryd46b6e82017-01-05 21:51:42 +00002644
2645 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
2646 assert(getRegClass(DstReg)->getSize() == getRegClass(SrcReg)->getSize() &&
2647 "Mismatched register size in non subreg COPY");
2648 if (IsSpill)
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002649 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
Geoff Berryd46b6e82017-01-05 21:51:42 +00002650 getRegClass(SrcReg), &TRI);
Geoff Berry7ffce7b2016-12-01 23:43:55 +00002651 else
Geoff Berryd46b6e82017-01-05 21:51:42 +00002652 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
2653 getRegClass(DstReg), &TRI);
Geoff Berry7c078fc2016-11-29 18:28:32 +00002654 return &*--InsertPt;
2655 }
Geoff Berryd46b6e82017-01-05 21:51:42 +00002656
2657 // Handle cases like spilling def of:
2658 //
2659 // %vreg0:sub_32<def,read-undef> = COPY %WZR; GPR64common:%vreg0
2660 //
2661 // where the physical register source can be widened and stored to the full
2662 // virtual reg destination stack slot, in this case producing:
2663 //
2664 // STRXui %XZR, <fi#0>
2665 //
2666 if (IsSpill && DstMO.isUndef() &&
2667 TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
2668 assert(SrcMO.getSubReg() == 0 &&
2669 "Unexpected subreg on physical register");
2670 const TargetRegisterClass *SpillRC;
2671 unsigned SpillSubreg;
2672 switch (DstMO.getSubReg()) {
2673 default:
2674 SpillRC = nullptr;
2675 break;
2676 case AArch64::sub_32:
2677 case AArch64::ssub:
2678 if (AArch64::GPR32RegClass.contains(SrcReg)) {
2679 SpillRC = &AArch64::GPR64RegClass;
2680 SpillSubreg = AArch64::sub_32;
2681 } else if (AArch64::FPR32RegClass.contains(SrcReg)) {
2682 SpillRC = &AArch64::FPR64RegClass;
2683 SpillSubreg = AArch64::ssub;
2684 } else
2685 SpillRC = nullptr;
2686 break;
2687 case AArch64::dsub:
2688 if (AArch64::FPR64RegClass.contains(SrcReg)) {
2689 SpillRC = &AArch64::FPR128RegClass;
2690 SpillSubreg = AArch64::dsub;
2691 } else
2692 SpillRC = nullptr;
2693 break;
2694 }
2695
2696 if (SpillRC)
2697 if (unsigned WidenedSrcReg =
2698 TRI.getMatchingSuperReg(SrcReg, SpillSubreg, SpillRC)) {
2699 storeRegToStackSlot(MBB, InsertPt, WidenedSrcReg, SrcMO.isKill(),
2700 FrameIndex, SpillRC, &TRI);
2701 return &*--InsertPt;
2702 }
2703 }
2704
2705 // Handle cases like filling use of:
2706 //
2707 // %vreg0:sub_32<def,read-undef> = COPY %vreg1; GPR64:%vreg0, GPR32:%vreg1
2708 //
2709 // where we can load the full virtual reg source stack slot, into the subreg
2710 // destination, in this case producing:
2711 //
2712 // LDRWui %vreg0:sub_32<def,read-undef>, <fi#0>
2713 //
2714 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
2715 const TargetRegisterClass *FillRC;
2716 switch (DstMO.getSubReg()) {
2717 default:
2718 FillRC = nullptr;
2719 break;
2720 case AArch64::sub_32:
2721 FillRC = &AArch64::GPR32RegClass;
2722 break;
2723 case AArch64::ssub:
2724 FillRC = &AArch64::FPR32RegClass;
2725 break;
2726 case AArch64::dsub:
2727 FillRC = &AArch64::FPR64RegClass;
2728 break;
2729 }
2730
2731 if (FillRC) {
2732 assert(getRegClass(SrcReg)->getSize() == FillRC->getSize() &&
2733 "Mismatched regclass size on folded subreg COPY");
2734 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC, &TRI);
2735 MachineInstr &LoadMI = *--InsertPt;
2736 MachineOperand &LoadDst = LoadMI.getOperand(0);
2737 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
2738 LoadDst.setSubReg(DstMO.getSubReg());
2739 LoadDst.setIsUndef();
2740 return &LoadMI;
2741 }
2742 }
Geoff Berry7c078fc2016-11-29 18:28:32 +00002743 }
2744
Tim Northover3b0846e2014-05-24 12:50:23 +00002745 // Cannot fold.
2746 return nullptr;
2747}
2748
2749int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset,
2750 bool *OutUseUnscaledOp,
2751 unsigned *OutUnscaledOp,
2752 int *EmittableOffset) {
2753 int Scale = 1;
2754 bool IsSigned = false;
2755 // The ImmIdx should be changed case by case if it is not 2.
2756 unsigned ImmIdx = 2;
2757 unsigned UnscaledOp = 0;
2758 // Set output values in case of early exit.
2759 if (EmittableOffset)
2760 *EmittableOffset = 0;
2761 if (OutUseUnscaledOp)
2762 *OutUseUnscaledOp = false;
2763 if (OutUnscaledOp)
2764 *OutUnscaledOp = 0;
2765 switch (MI.getOpcode()) {
2766 default:
Craig Topper2a30d782014-06-18 05:05:13 +00002767 llvm_unreachable("unhandled opcode in rewriteAArch64FrameIndex");
Tim Northover3b0846e2014-05-24 12:50:23 +00002768 // Vector spills/fills can't take an immediate offset.
2769 case AArch64::LD1Twov2d:
2770 case AArch64::LD1Threev2d:
2771 case AArch64::LD1Fourv2d:
2772 case AArch64::LD1Twov1d:
2773 case AArch64::LD1Threev1d:
2774 case AArch64::LD1Fourv1d:
2775 case AArch64::ST1Twov2d:
2776 case AArch64::ST1Threev2d:
2777 case AArch64::ST1Fourv2d:
2778 case AArch64::ST1Twov1d:
2779 case AArch64::ST1Threev1d:
2780 case AArch64::ST1Fourv1d:
2781 return AArch64FrameOffsetCannotUpdate;
2782 case AArch64::PRFMui:
2783 Scale = 8;
2784 UnscaledOp = AArch64::PRFUMi;
2785 break;
2786 case AArch64::LDRXui:
2787 Scale = 8;
2788 UnscaledOp = AArch64::LDURXi;
2789 break;
2790 case AArch64::LDRWui:
2791 Scale = 4;
2792 UnscaledOp = AArch64::LDURWi;
2793 break;
2794 case AArch64::LDRBui:
2795 Scale = 1;
2796 UnscaledOp = AArch64::LDURBi;
2797 break;
2798 case AArch64::LDRHui:
2799 Scale = 2;
2800 UnscaledOp = AArch64::LDURHi;
2801 break;
2802 case AArch64::LDRSui:
2803 Scale = 4;
2804 UnscaledOp = AArch64::LDURSi;
2805 break;
2806 case AArch64::LDRDui:
2807 Scale = 8;
2808 UnscaledOp = AArch64::LDURDi;
2809 break;
2810 case AArch64::LDRQui:
2811 Scale = 16;
2812 UnscaledOp = AArch64::LDURQi;
2813 break;
2814 case AArch64::LDRBBui:
2815 Scale = 1;
2816 UnscaledOp = AArch64::LDURBBi;
2817 break;
2818 case AArch64::LDRHHui:
2819 Scale = 2;
2820 UnscaledOp = AArch64::LDURHHi;
2821 break;
2822 case AArch64::LDRSBXui:
2823 Scale = 1;
2824 UnscaledOp = AArch64::LDURSBXi;
2825 break;
2826 case AArch64::LDRSBWui:
2827 Scale = 1;
2828 UnscaledOp = AArch64::LDURSBWi;
2829 break;
2830 case AArch64::LDRSHXui:
2831 Scale = 2;
2832 UnscaledOp = AArch64::LDURSHXi;
2833 break;
2834 case AArch64::LDRSHWui:
2835 Scale = 2;
2836 UnscaledOp = AArch64::LDURSHWi;
2837 break;
2838 case AArch64::LDRSWui:
2839 Scale = 4;
2840 UnscaledOp = AArch64::LDURSWi;
2841 break;
2842
2843 case AArch64::STRXui:
2844 Scale = 8;
2845 UnscaledOp = AArch64::STURXi;
2846 break;
2847 case AArch64::STRWui:
2848 Scale = 4;
2849 UnscaledOp = AArch64::STURWi;
2850 break;
2851 case AArch64::STRBui:
2852 Scale = 1;
2853 UnscaledOp = AArch64::STURBi;
2854 break;
2855 case AArch64::STRHui:
2856 Scale = 2;
2857 UnscaledOp = AArch64::STURHi;
2858 break;
2859 case AArch64::STRSui:
2860 Scale = 4;
2861 UnscaledOp = AArch64::STURSi;
2862 break;
2863 case AArch64::STRDui:
2864 Scale = 8;
2865 UnscaledOp = AArch64::STURDi;
2866 break;
2867 case AArch64::STRQui:
2868 Scale = 16;
2869 UnscaledOp = AArch64::STURQi;
2870 break;
2871 case AArch64::STRBBui:
2872 Scale = 1;
2873 UnscaledOp = AArch64::STURBBi;
2874 break;
2875 case AArch64::STRHHui:
2876 Scale = 2;
2877 UnscaledOp = AArch64::STURHHi;
2878 break;
2879
2880 case AArch64::LDPXi:
2881 case AArch64::LDPDi:
2882 case AArch64::STPXi:
2883 case AArch64::STPDi:
Ahmed Bougacha05541452015-09-10 01:54:43 +00002884 case AArch64::LDNPXi:
2885 case AArch64::LDNPDi:
2886 case AArch64::STNPXi:
2887 case AArch64::STNPDi:
2888 ImmIdx = 3;
Tim Northover3b0846e2014-05-24 12:50:23 +00002889 IsSigned = true;
2890 Scale = 8;
2891 break;
2892 case AArch64::LDPQi:
2893 case AArch64::STPQi:
Ahmed Bougacha05541452015-09-10 01:54:43 +00002894 case AArch64::LDNPQi:
2895 case AArch64::STNPQi:
2896 ImmIdx = 3;
Tim Northover3b0846e2014-05-24 12:50:23 +00002897 IsSigned = true;
2898 Scale = 16;
2899 break;
2900 case AArch64::LDPWi:
2901 case AArch64::LDPSi:
2902 case AArch64::STPWi:
2903 case AArch64::STPSi:
Ahmed Bougacha05541452015-09-10 01:54:43 +00002904 case AArch64::LDNPWi:
2905 case AArch64::LDNPSi:
2906 case AArch64::STNPWi:
2907 case AArch64::STNPSi:
2908 ImmIdx = 3;
Tim Northover3b0846e2014-05-24 12:50:23 +00002909 IsSigned = true;
2910 Scale = 4;
2911 break;
2912
2913 case AArch64::LDURXi:
2914 case AArch64::LDURWi:
2915 case AArch64::LDURBi:
2916 case AArch64::LDURHi:
2917 case AArch64::LDURSi:
2918 case AArch64::LDURDi:
2919 case AArch64::LDURQi:
2920 case AArch64::LDURHHi:
2921 case AArch64::LDURBBi:
2922 case AArch64::LDURSBXi:
2923 case AArch64::LDURSBWi:
2924 case AArch64::LDURSHXi:
2925 case AArch64::LDURSHWi:
2926 case AArch64::LDURSWi:
2927 case AArch64::STURXi:
2928 case AArch64::STURWi:
2929 case AArch64::STURBi:
2930 case AArch64::STURHi:
2931 case AArch64::STURSi:
2932 case AArch64::STURDi:
2933 case AArch64::STURQi:
2934 case AArch64::STURBBi:
2935 case AArch64::STURHHi:
2936 Scale = 1;
2937 break;
2938 }
2939
2940 Offset += MI.getOperand(ImmIdx).getImm() * Scale;
2941
2942 bool useUnscaledOp = false;
2943 // If the offset doesn't match the scale, we rewrite the instruction to
2944 // use the unscaled instruction instead. Likewise, if we have a negative
2945 // offset (and have an unscaled op to use).
2946 if ((Offset & (Scale - 1)) != 0 || (Offset < 0 && UnscaledOp != 0))
2947 useUnscaledOp = true;
2948
2949 // Use an unscaled addressing mode if the instruction has a negative offset
2950 // (or if the instruction is already using an unscaled addressing mode).
2951 unsigned MaskBits;
2952 if (IsSigned) {
2953 // ldp/stp instructions.
2954 MaskBits = 7;
2955 Offset /= Scale;
2956 } else if (UnscaledOp == 0 || useUnscaledOp) {
2957 MaskBits = 9;
2958 IsSigned = true;
2959 Scale = 1;
2960 } else {
2961 MaskBits = 12;
2962 IsSigned = false;
2963 Offset /= Scale;
2964 }
2965
2966 // Attempt to fold address computation.
2967 int MaxOff = (1 << (MaskBits - IsSigned)) - 1;
2968 int MinOff = (IsSigned ? (-MaxOff - 1) : 0);
2969 if (Offset >= MinOff && Offset <= MaxOff) {
2970 if (EmittableOffset)
2971 *EmittableOffset = Offset;
2972 Offset = 0;
2973 } else {
2974 int NewOff = Offset < 0 ? MinOff : MaxOff;
2975 if (EmittableOffset)
2976 *EmittableOffset = NewOff;
2977 Offset = (Offset - NewOff) * Scale;
2978 }
2979 if (OutUseUnscaledOp)
2980 *OutUseUnscaledOp = useUnscaledOp;
2981 if (OutUnscaledOp)
2982 *OutUnscaledOp = UnscaledOp;
2983 return AArch64FrameOffsetCanUpdate |
2984 (Offset == 0 ? AArch64FrameOffsetIsLegal : 0);
2985}
2986
2987bool llvm::rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
2988 unsigned FrameReg, int &Offset,
2989 const AArch64InstrInfo *TII) {
2990 unsigned Opcode = MI.getOpcode();
2991 unsigned ImmIdx = FrameRegIdx + 1;
2992
2993 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
2994 Offset += MI.getOperand(ImmIdx).getImm();
2995 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
2996 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
2997 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
2998 MI.eraseFromParent();
2999 Offset = 0;
3000 return true;
3001 }
3002
3003 int NewOffset;
3004 unsigned UnscaledOp;
3005 bool UseUnscaledOp;
3006 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
3007 &UnscaledOp, &NewOffset);
3008 if (Status & AArch64FrameOffsetCanUpdate) {
3009 if (Status & AArch64FrameOffsetIsLegal)
3010 // Replace the FrameIndex with FrameReg.
3011 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
3012 if (UseUnscaledOp)
3013 MI.setDesc(TII->get(UnscaledOp));
3014
3015 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
3016 return Offset == 0;
3017 }
3018
3019 return false;
3020}
3021
3022void AArch64InstrInfo::getNoopForMachoTarget(MCInst &NopInst) const {
3023 NopInst.setOpcode(AArch64::HINT);
Jim Grosbache9119e42015-05-13 18:37:00 +00003024 NopInst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00003025}
Chad Rosier9d1a5562016-05-02 14:56:21 +00003026
3027// AArch64 supports MachineCombiner.
Benjamin Kramer8c90fd72014-09-03 11:41:21 +00003028bool AArch64InstrInfo::useMachineCombiner() const {
Chad Rosier9d1a5562016-05-02 14:56:21 +00003029
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003030 return true;
3031}
3032//
3033// True when Opc sets flag
3034static bool isCombineInstrSettingFlag(unsigned Opc) {
3035 switch (Opc) {
3036 case AArch64::ADDSWrr:
3037 case AArch64::ADDSWri:
3038 case AArch64::ADDSXrr:
3039 case AArch64::ADDSXri:
3040 case AArch64::SUBSWrr:
3041 case AArch64::SUBSXrr:
3042 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
3043 case AArch64::SUBSWri:
3044 case AArch64::SUBSXri:
3045 return true;
3046 default:
3047 break;
3048 }
3049 return false;
3050}
3051//
3052// 32b Opcodes that can be combined with a MUL
3053static bool isCombineInstrCandidate32(unsigned Opc) {
3054 switch (Opc) {
3055 case AArch64::ADDWrr:
3056 case AArch64::ADDWri:
3057 case AArch64::SUBWrr:
3058 case AArch64::ADDSWrr:
3059 case AArch64::ADDSWri:
3060 case AArch64::SUBSWrr:
3061 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
3062 case AArch64::SUBWri:
3063 case AArch64::SUBSWri:
3064 return true;
3065 default:
3066 break;
3067 }
3068 return false;
3069}
3070//
3071// 64b Opcodes that can be combined with a MUL
3072static bool isCombineInstrCandidate64(unsigned Opc) {
3073 switch (Opc) {
3074 case AArch64::ADDXrr:
3075 case AArch64::ADDXri:
3076 case AArch64::SUBXrr:
3077 case AArch64::ADDSXrr:
3078 case AArch64::ADDSXri:
3079 case AArch64::SUBSXrr:
3080 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
3081 case AArch64::SUBXri:
3082 case AArch64::SUBSXri:
3083 return true;
3084 default:
3085 break;
3086 }
3087 return false;
3088}
3089//
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003090// FP Opcodes that can be combined with a FMUL
3091static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
3092 switch (Inst.getOpcode()) {
Evandro Menezes19b2aed2016-09-15 19:55:23 +00003093 default:
3094 break;
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003095 case AArch64::FADDSrr:
3096 case AArch64::FADDDrr:
3097 case AArch64::FADDv2f32:
3098 case AArch64::FADDv2f64:
3099 case AArch64::FADDv4f32:
3100 case AArch64::FSUBSrr:
3101 case AArch64::FSUBDrr:
3102 case AArch64::FSUBv2f32:
3103 case AArch64::FSUBv2f64:
3104 case AArch64::FSUBv4f32:
Evandro Menezes19b2aed2016-09-15 19:55:23 +00003105 TargetOptions Options = Inst.getParent()->getParent()->getTarget().Options;
3106 return (Options.UnsafeFPMath ||
3107 Options.AllowFPOpFusion == FPOpFusion::Fast);
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003108 }
3109 return false;
3110}
3111//
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003112// Opcodes that can be combined with a MUL
3113static bool isCombineInstrCandidate(unsigned Opc) {
3114 return (isCombineInstrCandidate32(Opc) || isCombineInstrCandidate64(Opc));
3115}
3116
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003117//
3118// Utility routine that checks if \param MO is defined by an
3119// \param CombineOpc instruction in the basic block \param MBB
3120static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO,
3121 unsigned CombineOpc, unsigned ZeroReg = 0,
3122 bool CheckZeroReg = false) {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003123 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3124 MachineInstr *MI = nullptr;
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003125
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003126 if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))
3127 MI = MRI.getUniqueVRegDef(MO.getReg());
3128 // And it needs to be in the trace (otherwise, it won't have a depth).
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003129 if (!MI || MI->getParent() != &MBB || (unsigned)MI->getOpcode() != CombineOpc)
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003130 return false;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003131 // Must only used by the user we combine with.
Gerolf Hoflehnerfe2c11f2014-08-13 22:07:36 +00003132 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003133 return false;
3134
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003135 if (CheckZeroReg) {
3136 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
3137 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
3138 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
3139 // The third input reg must be zero.
3140 if (MI->getOperand(3).getReg() != ZeroReg)
3141 return false;
3142 }
3143
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003144 return true;
3145}
3146
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003147//
3148// Is \param MO defined by an integer multiply and can be combined?
3149static bool canCombineWithMUL(MachineBasicBlock &MBB, MachineOperand &MO,
3150 unsigned MulOpc, unsigned ZeroReg) {
3151 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
3152}
3153
3154//
3155// Is \param MO defined by a floating-point multiply and can be combined?
3156static bool canCombineWithFMUL(MachineBasicBlock &MBB, MachineOperand &MO,
3157 unsigned MulOpc) {
3158 return canCombine(MBB, MO, MulOpc);
3159}
3160
Haicheng Wu08b94622016-01-07 04:01:02 +00003161// TODO: There are many more machine instruction opcodes to match:
3162// 1. Other data types (integer, vectors)
3163// 2. Other math / logic operations (xor, or)
3164// 3. Other forms of the same operation (intrinsics and other variants)
3165bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst) const {
3166 switch (Inst.getOpcode()) {
3167 case AArch64::FADDDrr:
3168 case AArch64::FADDSrr:
3169 case AArch64::FADDv2f32:
3170 case AArch64::FADDv2f64:
3171 case AArch64::FADDv4f32:
3172 case AArch64::FMULDrr:
3173 case AArch64::FMULSrr:
3174 case AArch64::FMULX32:
3175 case AArch64::FMULX64:
3176 case AArch64::FMULXv2f32:
3177 case AArch64::FMULXv2f64:
3178 case AArch64::FMULXv4f32:
3179 case AArch64::FMULv2f32:
3180 case AArch64::FMULv2f64:
3181 case AArch64::FMULv4f32:
3182 return Inst.getParent()->getParent()->getTarget().Options.UnsafeFPMath;
3183 default:
3184 return false;
3185 }
3186}
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003187
Haicheng Wu08b94622016-01-07 04:01:02 +00003188/// Find instructions that can be turned into madd.
3189static bool getMaddPatterns(MachineInstr &Root,
3190 SmallVectorImpl<MachineCombinerPattern> &Patterns) {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003191 unsigned Opc = Root.getOpcode();
3192 MachineBasicBlock &MBB = *Root.getParent();
3193 bool Found = false;
3194
3195 if (!isCombineInstrCandidate(Opc))
Chad Rosier85c85942016-03-23 20:07:28 +00003196 return false;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003197 if (isCombineInstrSettingFlag(Opc)) {
3198 int Cmp_NZCV = Root.findRegisterDefOperandIdx(AArch64::NZCV, true);
3199 // When NZCV is live bail out.
3200 if (Cmp_NZCV == -1)
Chad Rosier85c85942016-03-23 20:07:28 +00003201 return false;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00003202 unsigned NewOpc = convertFlagSettingOpcode(Root);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003203 // When opcode can't change bail out.
3204 // CHECKME: do we miss any cases for opcode conversion?
3205 if (NewOpc == Opc)
Chad Rosier85c85942016-03-23 20:07:28 +00003206 return false;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003207 Opc = NewOpc;
3208 }
3209
3210 switch (Opc) {
3211 default:
3212 break;
3213 case AArch64::ADDWrr:
3214 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
3215 "ADDWrr does not have register operands");
3216 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
3217 AArch64::WZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003218 Patterns.push_back(MachineCombinerPattern::MULADDW_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003219 Found = true;
3220 }
3221 if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDWrrr,
3222 AArch64::WZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003223 Patterns.push_back(MachineCombinerPattern::MULADDW_OP2);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003224 Found = true;
3225 }
3226 break;
3227 case AArch64::ADDXrr:
3228 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
3229 AArch64::XZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003230 Patterns.push_back(MachineCombinerPattern::MULADDX_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003231 Found = true;
3232 }
3233 if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDXrrr,
3234 AArch64::XZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003235 Patterns.push_back(MachineCombinerPattern::MULADDX_OP2);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003236 Found = true;
3237 }
3238 break;
3239 case AArch64::SUBWrr:
3240 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
3241 AArch64::WZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003242 Patterns.push_back(MachineCombinerPattern::MULSUBW_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003243 Found = true;
3244 }
3245 if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDWrrr,
3246 AArch64::WZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003247 Patterns.push_back(MachineCombinerPattern::MULSUBW_OP2);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003248 Found = true;
3249 }
3250 break;
3251 case AArch64::SUBXrr:
3252 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
3253 AArch64::XZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003254 Patterns.push_back(MachineCombinerPattern::MULSUBX_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003255 Found = true;
3256 }
3257 if (canCombineWithMUL(MBB, Root.getOperand(2), AArch64::MADDXrrr,
3258 AArch64::XZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003259 Patterns.push_back(MachineCombinerPattern::MULSUBX_OP2);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003260 Found = true;
3261 }
3262 break;
3263 case AArch64::ADDWri:
3264 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
3265 AArch64::WZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003266 Patterns.push_back(MachineCombinerPattern::MULADDWI_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003267 Found = true;
3268 }
3269 break;
3270 case AArch64::ADDXri:
3271 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
3272 AArch64::XZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003273 Patterns.push_back(MachineCombinerPattern::MULADDXI_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003274 Found = true;
3275 }
3276 break;
3277 case AArch64::SUBWri:
3278 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDWrrr,
3279 AArch64::WZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003280 Patterns.push_back(MachineCombinerPattern::MULSUBWI_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003281 Found = true;
3282 }
3283 break;
3284 case AArch64::SUBXri:
3285 if (canCombineWithMUL(MBB, Root.getOperand(1), AArch64::MADDXrrr,
3286 AArch64::XZR)) {
Sanjay Patel387e66e2015-11-05 19:34:57 +00003287 Patterns.push_back(MachineCombinerPattern::MULSUBXI_OP1);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003288 Found = true;
3289 }
3290 break;
3291 }
3292 return Found;
3293}
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003294/// Floating-Point Support
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003295
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003296/// Find instructions that can be turned into madd.
3297static bool getFMAPatterns(MachineInstr &Root,
3298 SmallVectorImpl<MachineCombinerPattern> &Patterns) {
3299
3300 if (!isCombineInstrCandidateFP(Root))
3301 return 0;
3302
3303 MachineBasicBlock &MBB = *Root.getParent();
3304 bool Found = false;
3305
3306 switch (Root.getOpcode()) {
3307 default:
3308 assert(false && "Unsupported FP instruction in combiner\n");
3309 break;
3310 case AArch64::FADDSrr:
3311 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
3312 "FADDWrr does not have register operands");
3313 if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULSrr)) {
3314 Patterns.push_back(MachineCombinerPattern::FMULADDS_OP1);
3315 Found = true;
3316 } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3317 AArch64::FMULv1i32_indexed)) {
3318 Patterns.push_back(MachineCombinerPattern::FMLAv1i32_indexed_OP1);
3319 Found = true;
3320 }
3321 if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULSrr)) {
3322 Patterns.push_back(MachineCombinerPattern::FMULADDS_OP2);
3323 Found = true;
3324 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3325 AArch64::FMULv1i32_indexed)) {
3326 Patterns.push_back(MachineCombinerPattern::FMLAv1i32_indexed_OP2);
3327 Found = true;
3328 }
3329 break;
3330 case AArch64::FADDDrr:
3331 if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULDrr)) {
3332 Patterns.push_back(MachineCombinerPattern::FMULADDD_OP1);
3333 Found = true;
3334 } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3335 AArch64::FMULv1i64_indexed)) {
3336 Patterns.push_back(MachineCombinerPattern::FMLAv1i64_indexed_OP1);
3337 Found = true;
3338 }
3339 if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULDrr)) {
3340 Patterns.push_back(MachineCombinerPattern::FMULADDD_OP2);
3341 Found = true;
3342 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3343 AArch64::FMULv1i64_indexed)) {
3344 Patterns.push_back(MachineCombinerPattern::FMLAv1i64_indexed_OP2);
3345 Found = true;
3346 }
3347 break;
3348 case AArch64::FADDv2f32:
3349 if (canCombineWithFMUL(MBB, Root.getOperand(1),
3350 AArch64::FMULv2i32_indexed)) {
3351 Patterns.push_back(MachineCombinerPattern::FMLAv2i32_indexed_OP1);
3352 Found = true;
3353 } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3354 AArch64::FMULv2f32)) {
3355 Patterns.push_back(MachineCombinerPattern::FMLAv2f32_OP1);
3356 Found = true;
3357 }
3358 if (canCombineWithFMUL(MBB, Root.getOperand(2),
3359 AArch64::FMULv2i32_indexed)) {
3360 Patterns.push_back(MachineCombinerPattern::FMLAv2i32_indexed_OP2);
3361 Found = true;
3362 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3363 AArch64::FMULv2f32)) {
3364 Patterns.push_back(MachineCombinerPattern::FMLAv2f32_OP2);
3365 Found = true;
3366 }
3367 break;
3368 case AArch64::FADDv2f64:
3369 if (canCombineWithFMUL(MBB, Root.getOperand(1),
3370 AArch64::FMULv2i64_indexed)) {
3371 Patterns.push_back(MachineCombinerPattern::FMLAv2i64_indexed_OP1);
3372 Found = true;
3373 } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3374 AArch64::FMULv2f64)) {
3375 Patterns.push_back(MachineCombinerPattern::FMLAv2f64_OP1);
3376 Found = true;
3377 }
3378 if (canCombineWithFMUL(MBB, Root.getOperand(2),
3379 AArch64::FMULv2i64_indexed)) {
3380 Patterns.push_back(MachineCombinerPattern::FMLAv2i64_indexed_OP2);
3381 Found = true;
3382 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3383 AArch64::FMULv2f64)) {
3384 Patterns.push_back(MachineCombinerPattern::FMLAv2f64_OP2);
3385 Found = true;
3386 }
3387 break;
3388 case AArch64::FADDv4f32:
3389 if (canCombineWithFMUL(MBB, Root.getOperand(1),
3390 AArch64::FMULv4i32_indexed)) {
3391 Patterns.push_back(MachineCombinerPattern::FMLAv4i32_indexed_OP1);
3392 Found = true;
3393 } else if (canCombineWithFMUL(MBB, Root.getOperand(1),
3394 AArch64::FMULv4f32)) {
3395 Patterns.push_back(MachineCombinerPattern::FMLAv4f32_OP1);
3396 Found = true;
3397 }
3398 if (canCombineWithFMUL(MBB, Root.getOperand(2),
3399 AArch64::FMULv4i32_indexed)) {
3400 Patterns.push_back(MachineCombinerPattern::FMLAv4i32_indexed_OP2);
3401 Found = true;
3402 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3403 AArch64::FMULv4f32)) {
3404 Patterns.push_back(MachineCombinerPattern::FMLAv4f32_OP2);
3405 Found = true;
3406 }
3407 break;
3408
3409 case AArch64::FSUBSrr:
3410 if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULSrr)) {
3411 Patterns.push_back(MachineCombinerPattern::FMULSUBS_OP1);
3412 Found = true;
3413 }
3414 if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULSrr)) {
3415 Patterns.push_back(MachineCombinerPattern::FMULSUBS_OP2);
3416 Found = true;
3417 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3418 AArch64::FMULv1i32_indexed)) {
3419 Patterns.push_back(MachineCombinerPattern::FMLSv1i32_indexed_OP2);
3420 Found = true;
3421 }
3422 break;
3423 case AArch64::FSUBDrr:
3424 if (canCombineWithFMUL(MBB, Root.getOperand(1), AArch64::FMULDrr)) {
3425 Patterns.push_back(MachineCombinerPattern::FMULSUBD_OP1);
3426 Found = true;
3427 }
3428 if (canCombineWithFMUL(MBB, Root.getOperand(2), AArch64::FMULDrr)) {
3429 Patterns.push_back(MachineCombinerPattern::FMULSUBD_OP2);
3430 Found = true;
3431 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3432 AArch64::FMULv1i64_indexed)) {
3433 Patterns.push_back(MachineCombinerPattern::FMLSv1i64_indexed_OP2);
3434 Found = true;
3435 }
3436 break;
3437 case AArch64::FSUBv2f32:
3438 if (canCombineWithFMUL(MBB, Root.getOperand(2),
3439 AArch64::FMULv2i32_indexed)) {
3440 Patterns.push_back(MachineCombinerPattern::FMLSv2i32_indexed_OP2);
3441 Found = true;
3442 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3443 AArch64::FMULv2f32)) {
3444 Patterns.push_back(MachineCombinerPattern::FMLSv2f32_OP2);
3445 Found = true;
3446 }
3447 break;
3448 case AArch64::FSUBv2f64:
3449 if (canCombineWithFMUL(MBB, Root.getOperand(2),
3450 AArch64::FMULv2i64_indexed)) {
3451 Patterns.push_back(MachineCombinerPattern::FMLSv2i64_indexed_OP2);
3452 Found = true;
3453 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3454 AArch64::FMULv2f64)) {
3455 Patterns.push_back(MachineCombinerPattern::FMLSv2f64_OP2);
3456 Found = true;
3457 }
3458 break;
3459 case AArch64::FSUBv4f32:
3460 if (canCombineWithFMUL(MBB, Root.getOperand(2),
3461 AArch64::FMULv4i32_indexed)) {
3462 Patterns.push_back(MachineCombinerPattern::FMLSv4i32_indexed_OP2);
3463 Found = true;
3464 } else if (canCombineWithFMUL(MBB, Root.getOperand(2),
3465 AArch64::FMULv4f32)) {
3466 Patterns.push_back(MachineCombinerPattern::FMLSv4f32_OP2);
3467 Found = true;
3468 }
3469 break;
3470 }
3471 return Found;
3472}
3473
3474/// Return true when a code sequence can improve throughput. It
3475/// should be called only for instructions in loops.
3476/// \param Pattern - combiner pattern
3477bool
3478AArch64InstrInfo::isThroughputPattern(MachineCombinerPattern Pattern) const {
3479 switch (Pattern) {
3480 default:
3481 break;
3482 case MachineCombinerPattern::FMULADDS_OP1:
3483 case MachineCombinerPattern::FMULADDS_OP2:
3484 case MachineCombinerPattern::FMULSUBS_OP1:
3485 case MachineCombinerPattern::FMULSUBS_OP2:
3486 case MachineCombinerPattern::FMULADDD_OP1:
3487 case MachineCombinerPattern::FMULADDD_OP2:
3488 case MachineCombinerPattern::FMULSUBD_OP1:
3489 case MachineCombinerPattern::FMULSUBD_OP2:
3490 case MachineCombinerPattern::FMLAv1i32_indexed_OP1:
3491 case MachineCombinerPattern::FMLAv1i32_indexed_OP2:
3492 case MachineCombinerPattern::FMLAv1i64_indexed_OP1:
3493 case MachineCombinerPattern::FMLAv1i64_indexed_OP2:
3494 case MachineCombinerPattern::FMLAv2f32_OP2:
3495 case MachineCombinerPattern::FMLAv2f32_OP1:
3496 case MachineCombinerPattern::FMLAv2f64_OP1:
3497 case MachineCombinerPattern::FMLAv2f64_OP2:
3498 case MachineCombinerPattern::FMLAv2i32_indexed_OP1:
3499 case MachineCombinerPattern::FMLAv2i32_indexed_OP2:
3500 case MachineCombinerPattern::FMLAv2i64_indexed_OP1:
3501 case MachineCombinerPattern::FMLAv2i64_indexed_OP2:
3502 case MachineCombinerPattern::FMLAv4f32_OP1:
3503 case MachineCombinerPattern::FMLAv4f32_OP2:
3504 case MachineCombinerPattern::FMLAv4i32_indexed_OP1:
3505 case MachineCombinerPattern::FMLAv4i32_indexed_OP2:
3506 case MachineCombinerPattern::FMLSv1i32_indexed_OP2:
3507 case MachineCombinerPattern::FMLSv1i64_indexed_OP2:
3508 case MachineCombinerPattern::FMLSv2i32_indexed_OP2:
3509 case MachineCombinerPattern::FMLSv2i64_indexed_OP2:
3510 case MachineCombinerPattern::FMLSv2f32_OP2:
3511 case MachineCombinerPattern::FMLSv2f64_OP2:
3512 case MachineCombinerPattern::FMLSv4i32_indexed_OP2:
3513 case MachineCombinerPattern::FMLSv4f32_OP2:
3514 return true;
3515 } // end switch (Pattern)
3516 return false;
3517}
Haicheng Wu08b94622016-01-07 04:01:02 +00003518/// Return true when there is potentially a faster code sequence for an
3519/// instruction chain ending in \p Root. All potential patterns are listed in
3520/// the \p Pattern vector. Pattern should be sorted in priority order since the
3521/// pattern evaluator stops checking as soon as it finds a faster sequence.
3522
3523bool AArch64InstrInfo::getMachineCombinerPatterns(
3524 MachineInstr &Root,
3525 SmallVectorImpl<MachineCombinerPattern> &Patterns) const {
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003526 // Integer patterns
Haicheng Wu08b94622016-01-07 04:01:02 +00003527 if (getMaddPatterns(Root, Patterns))
3528 return true;
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003529 // Floating point patterns
3530 if (getFMAPatterns(Root, Patterns))
3531 return true;
Haicheng Wu08b94622016-01-07 04:01:02 +00003532
3533 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns);
3534}
3535
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003536enum class FMAInstKind { Default, Indexed, Accumulator };
3537/// genFusedMultiply - Generate fused multiply instructions.
3538/// This function supports both integer and floating point instructions.
3539/// A typical example:
3540/// F|MUL I=A,B,0
3541/// F|ADD R,I,C
3542/// ==> F|MADD R,A,B,C
3543/// \param Root is the F|ADD instruction
NAKAMURA Takumi40da2672014-08-08 02:04:18 +00003544/// \param [out] InsInstrs is a vector of machine instructions and will
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003545/// contain the generated madd instruction
3546/// \param IdxMulOpd is index of operand in Root that is the result of
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003547/// the F|MUL. In the example above IdxMulOpd is 1.
3548/// \param MaddOpc the opcode fo the f|madd instruction
3549static MachineInstr *
3550genFusedMultiply(MachineFunction &MF, MachineRegisterInfo &MRI,
3551 const TargetInstrInfo *TII, MachineInstr &Root,
3552 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
3553 unsigned MaddOpc, const TargetRegisterClass *RC,
3554 FMAInstKind kind = FMAInstKind::Default) {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003555 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
3556
3557 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
3558 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003559 unsigned ResultReg = Root.getOperand(0).getReg();
3560 unsigned SrcReg0 = MUL->getOperand(1).getReg();
3561 bool Src0IsKill = MUL->getOperand(1).isKill();
3562 unsigned SrcReg1 = MUL->getOperand(2).getReg();
3563 bool Src1IsKill = MUL->getOperand(2).isKill();
3564 unsigned SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
3565 bool Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
3566
3567 if (TargetRegisterInfo::isVirtualRegister(ResultReg))
3568 MRI.constrainRegClass(ResultReg, RC);
3569 if (TargetRegisterInfo::isVirtualRegister(SrcReg0))
3570 MRI.constrainRegClass(SrcReg0, RC);
3571 if (TargetRegisterInfo::isVirtualRegister(SrcReg1))
3572 MRI.constrainRegClass(SrcReg1, RC);
3573 if (TargetRegisterInfo::isVirtualRegister(SrcReg2))
3574 MRI.constrainRegClass(SrcReg2, RC);
3575
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003576 MachineInstrBuilder MIB;
3577 if (kind == FMAInstKind::Default)
3578 MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc), ResultReg)
3579 .addReg(SrcReg0, getKillRegState(Src0IsKill))
3580 .addReg(SrcReg1, getKillRegState(Src1IsKill))
3581 .addReg(SrcReg2, getKillRegState(Src2IsKill));
3582 else if (kind == FMAInstKind::Indexed)
3583 MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc), ResultReg)
3584 .addReg(SrcReg2, getKillRegState(Src2IsKill))
3585 .addReg(SrcReg0, getKillRegState(Src0IsKill))
3586 .addReg(SrcReg1, getKillRegState(Src1IsKill))
3587 .addImm(MUL->getOperand(3).getImm());
3588 else if (kind == FMAInstKind::Accumulator)
3589 MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc), ResultReg)
3590 .addReg(SrcReg2, getKillRegState(Src2IsKill))
3591 .addReg(SrcReg0, getKillRegState(Src0IsKill))
3592 .addReg(SrcReg1, getKillRegState(Src1IsKill));
3593 else
3594 assert(false && "Invalid FMA instruction kind \n");
3595 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003596 InsInstrs.push_back(MIB);
3597 return MUL;
3598}
3599
3600/// genMaddR - Generate madd instruction and combine mul and add using
3601/// an extra virtual register
3602/// Example - an ADD intermediate needs to be stored in a register:
3603/// MUL I=A,B,0
3604/// ADD R,I,Imm
3605/// ==> ORR V, ZR, Imm
3606/// ==> MADD R,A,B,V
3607/// \param Root is the ADD instruction
NAKAMURA Takumi40da2672014-08-08 02:04:18 +00003608/// \param [out] InsInstrs is a vector of machine instructions and will
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003609/// contain the generated madd instruction
3610/// \param IdxMulOpd is index of operand in Root that is the result of
3611/// the MUL. In the example above IdxMulOpd is 1.
3612/// \param MaddOpc the opcode fo the madd instruction
3613/// \param VR is a virtual register that holds the value of an ADD operand
3614/// (V in the example above).
3615static MachineInstr *genMaddR(MachineFunction &MF, MachineRegisterInfo &MRI,
3616 const TargetInstrInfo *TII, MachineInstr &Root,
3617 SmallVectorImpl<MachineInstr *> &InsInstrs,
3618 unsigned IdxMulOpd, unsigned MaddOpc,
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003619 unsigned VR, const TargetRegisterClass *RC) {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003620 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
3621
3622 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003623 unsigned ResultReg = Root.getOperand(0).getReg();
3624 unsigned SrcReg0 = MUL->getOperand(1).getReg();
3625 bool Src0IsKill = MUL->getOperand(1).isKill();
3626 unsigned SrcReg1 = MUL->getOperand(2).getReg();
3627 bool Src1IsKill = MUL->getOperand(2).isKill();
3628
3629 if (TargetRegisterInfo::isVirtualRegister(ResultReg))
3630 MRI.constrainRegClass(ResultReg, RC);
3631 if (TargetRegisterInfo::isVirtualRegister(SrcReg0))
3632 MRI.constrainRegClass(SrcReg0, RC);
3633 if (TargetRegisterInfo::isVirtualRegister(SrcReg1))
3634 MRI.constrainRegClass(SrcReg1, RC);
3635 if (TargetRegisterInfo::isVirtualRegister(VR))
3636 MRI.constrainRegClass(VR, RC);
3637
3638 MachineInstrBuilder MIB = BuildMI(MF, Root.getDebugLoc(), TII->get(MaddOpc),
3639 ResultReg)
3640 .addReg(SrcReg0, getKillRegState(Src0IsKill))
3641 .addReg(SrcReg1, getKillRegState(Src1IsKill))
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003642 .addReg(VR);
3643 // Insert the MADD
3644 InsInstrs.push_back(MIB);
3645 return MUL;
3646}
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003647
Sanjay Patelcfe03932015-06-19 23:21:42 +00003648/// When getMachineCombinerPatterns() finds potential patterns,
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003649/// this function generates the instructions that could replace the
3650/// original code sequence
3651void AArch64InstrInfo::genAlternativeCodeSequence(
Sanjay Patel387e66e2015-11-05 19:34:57 +00003652 MachineInstr &Root, MachineCombinerPattern Pattern,
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003653 SmallVectorImpl<MachineInstr *> &InsInstrs,
3654 SmallVectorImpl<MachineInstr *> &DelInstrs,
3655 DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const {
3656 MachineBasicBlock &MBB = *Root.getParent();
3657 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3658 MachineFunction &MF = *MBB.getParent();
Eric Christophere0818912014-09-03 20:36:26 +00003659 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003660
3661 MachineInstr *MUL;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003662 const TargetRegisterClass *RC;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003663 unsigned Opc;
3664 switch (Pattern) {
3665 default:
Haicheng Wu08b94622016-01-07 04:01:02 +00003666 // Reassociate instructions.
3667 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
3668 DelInstrs, InstrIdxForVirtReg);
3669 return;
Sanjay Patel387e66e2015-11-05 19:34:57 +00003670 case MachineCombinerPattern::MULADDW_OP1:
3671 case MachineCombinerPattern::MULADDX_OP1:
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003672 // MUL I=A,B,0
3673 // ADD R,I,C
3674 // ==> MADD R,A,B,C
3675 // --- Create(MADD);
Sanjay Patel387e66e2015-11-05 19:34:57 +00003676 if (Pattern == MachineCombinerPattern::MULADDW_OP1) {
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003677 Opc = AArch64::MADDWrrr;
3678 RC = &AArch64::GPR32RegClass;
3679 } else {
3680 Opc = AArch64::MADDXrrr;
3681 RC = &AArch64::GPR64RegClass;
3682 }
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003683 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003684 break;
Sanjay Patel387e66e2015-11-05 19:34:57 +00003685 case MachineCombinerPattern::MULADDW_OP2:
3686 case MachineCombinerPattern::MULADDX_OP2:
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003687 // MUL I=A,B,0
3688 // ADD R,C,I
3689 // ==> MADD R,A,B,C
3690 // --- Create(MADD);
Sanjay Patel387e66e2015-11-05 19:34:57 +00003691 if (Pattern == MachineCombinerPattern::MULADDW_OP2) {
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003692 Opc = AArch64::MADDWrrr;
3693 RC = &AArch64::GPR32RegClass;
3694 } else {
3695 Opc = AArch64::MADDXrrr;
3696 RC = &AArch64::GPR64RegClass;
3697 }
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003698 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003699 break;
Sanjay Patel387e66e2015-11-05 19:34:57 +00003700 case MachineCombinerPattern::MULADDWI_OP1:
3701 case MachineCombinerPattern::MULADDXI_OP1: {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003702 // MUL I=A,B,0
3703 // ADD R,I,Imm
3704 // ==> ORR V, ZR, Imm
3705 // ==> MADD R,A,B,V
3706 // --- Create(MADD);
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003707 const TargetRegisterClass *OrrRC;
3708 unsigned BitSize, OrrOpc, ZeroReg;
Sanjay Patel387e66e2015-11-05 19:34:57 +00003709 if (Pattern == MachineCombinerPattern::MULADDWI_OP1) {
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003710 OrrOpc = AArch64::ORRWri;
3711 OrrRC = &AArch64::GPR32spRegClass;
3712 BitSize = 32;
3713 ZeroReg = AArch64::WZR;
3714 Opc = AArch64::MADDWrrr;
3715 RC = &AArch64::GPR32RegClass;
3716 } else {
3717 OrrOpc = AArch64::ORRXri;
3718 OrrRC = &AArch64::GPR64spRegClass;
3719 BitSize = 64;
3720 ZeroReg = AArch64::XZR;
3721 Opc = AArch64::MADDXrrr;
3722 RC = &AArch64::GPR64RegClass;
3723 }
3724 unsigned NewVR = MRI.createVirtualRegister(OrrRC);
3725 uint64_t Imm = Root.getOperand(2).getImm();
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003726
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003727 if (Root.getOperand(3).isImm()) {
3728 unsigned Val = Root.getOperand(3).getImm();
3729 Imm = Imm << Val;
3730 }
David Majnemer1182dd82016-07-21 23:46:56 +00003731 uint64_t UImm = SignExtend64(Imm, BitSize);
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003732 uint64_t Encoding;
3733 if (AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding)) {
3734 MachineInstrBuilder MIB1 =
3735 BuildMI(MF, Root.getDebugLoc(), TII->get(OrrOpc), NewVR)
3736 .addReg(ZeroReg)
3737 .addImm(Encoding);
3738 InsInstrs.push_back(MIB1);
3739 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
3740 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003741 }
3742 break;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003743 }
Sanjay Patel387e66e2015-11-05 19:34:57 +00003744 case MachineCombinerPattern::MULSUBW_OP1:
3745 case MachineCombinerPattern::MULSUBX_OP1: {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003746 // MUL I=A,B,0
3747 // SUB R,I, C
3748 // ==> SUB V, 0, C
3749 // ==> MADD R,A,B,V // = -C + A*B
3750 // --- Create(MADD);
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003751 const TargetRegisterClass *SubRC;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003752 unsigned SubOpc, ZeroReg;
Sanjay Patel387e66e2015-11-05 19:34:57 +00003753 if (Pattern == MachineCombinerPattern::MULSUBW_OP1) {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003754 SubOpc = AArch64::SUBWrr;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003755 SubRC = &AArch64::GPR32spRegClass;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003756 ZeroReg = AArch64::WZR;
3757 Opc = AArch64::MADDWrrr;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003758 RC = &AArch64::GPR32RegClass;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003759 } else {
3760 SubOpc = AArch64::SUBXrr;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003761 SubRC = &AArch64::GPR64spRegClass;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003762 ZeroReg = AArch64::XZR;
3763 Opc = AArch64::MADDXrrr;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003764 RC = &AArch64::GPR64RegClass;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003765 }
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003766 unsigned NewVR = MRI.createVirtualRegister(SubRC);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003767 // SUB NewVR, 0, C
3768 MachineInstrBuilder MIB1 =
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003769 BuildMI(MF, Root.getDebugLoc(), TII->get(SubOpc), NewVR)
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003770 .addReg(ZeroReg)
3771 .addOperand(Root.getOperand(2));
3772 InsInstrs.push_back(MIB1);
3773 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003774 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
3775 break;
3776 }
Sanjay Patel387e66e2015-11-05 19:34:57 +00003777 case MachineCombinerPattern::MULSUBW_OP2:
3778 case MachineCombinerPattern::MULSUBX_OP2:
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003779 // MUL I=A,B,0
3780 // SUB R,C,I
3781 // ==> MSUB R,A,B,C (computes C - A*B)
3782 // --- Create(MSUB);
Sanjay Patel387e66e2015-11-05 19:34:57 +00003783 if (Pattern == MachineCombinerPattern::MULSUBW_OP2) {
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003784 Opc = AArch64::MSUBWrrr;
3785 RC = &AArch64::GPR32RegClass;
3786 } else {
3787 Opc = AArch64::MSUBXrrr;
3788 RC = &AArch64::GPR64RegClass;
3789 }
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003790 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003791 break;
Sanjay Patel387e66e2015-11-05 19:34:57 +00003792 case MachineCombinerPattern::MULSUBWI_OP1:
3793 case MachineCombinerPattern::MULSUBXI_OP1: {
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003794 // MUL I=A,B,0
3795 // SUB R,I, Imm
3796 // ==> ORR V, ZR, -Imm
3797 // ==> MADD R,A,B,V // = -Imm + A*B
3798 // --- Create(MADD);
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003799 const TargetRegisterClass *OrrRC;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003800 unsigned BitSize, OrrOpc, ZeroReg;
Sanjay Patel387e66e2015-11-05 19:34:57 +00003801 if (Pattern == MachineCombinerPattern::MULSUBWI_OP1) {
Juergen Ributzka25816b02014-08-30 06:16:26 +00003802 OrrOpc = AArch64::ORRWri;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003803 OrrRC = &AArch64::GPR32spRegClass;
3804 BitSize = 32;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003805 ZeroReg = AArch64::WZR;
3806 Opc = AArch64::MADDWrrr;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003807 RC = &AArch64::GPR32RegClass;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003808 } else {
3809 OrrOpc = AArch64::ORRXri;
Juergen Ributzkaf9660f02014-11-04 22:20:07 +00003810 OrrRC = &AArch64::GPR64spRegClass;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003811 BitSize = 64;
3812 ZeroReg = AArch64::XZR;
3813 Opc = AArch64::MADDXrrr;
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003814 RC = &AArch64::GPR64RegClass;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003815 }
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003816 unsigned NewVR = MRI.createVirtualRegister(OrrRC);
David Majnemer1182dd82016-07-21 23:46:56 +00003817 uint64_t Imm = Root.getOperand(2).getImm();
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003818 if (Root.getOperand(3).isImm()) {
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003819 unsigned Val = Root.getOperand(3).getImm();
3820 Imm = Imm << Val;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003821 }
David Majnemer1182dd82016-07-21 23:46:56 +00003822 uint64_t UImm = SignExtend64(-Imm, BitSize);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003823 uint64_t Encoding;
3824 if (AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding)) {
3825 MachineInstrBuilder MIB1 =
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003826 BuildMI(MF, Root.getDebugLoc(), TII->get(OrrOpc), NewVR)
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003827 .addReg(ZeroReg)
3828 .addImm(Encoding);
3829 InsInstrs.push_back(MIB1);
3830 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003831 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003832 }
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00003833 break;
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00003834 }
Gerolf Hoflehner01b3a6182016-04-24 05:14:01 +00003835 // Floating Point Support
3836 case MachineCombinerPattern::FMULADDS_OP1:
3837 case MachineCombinerPattern::FMULADDD_OP1:
3838 // MUL I=A,B,0
3839 // ADD R,I,C
3840 // ==> MADD R,A,B,C
3841 // --- Create(MADD);
3842 if (Pattern == MachineCombinerPattern::FMULADDS_OP1) {
3843 Opc = AArch64::FMADDSrrr;
3844 RC = &AArch64::FPR32RegClass;
3845 } else {
3846 Opc = AArch64::FMADDDrrr;
3847 RC = &AArch64::FPR64RegClass;
3848 }
3849 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
3850 break;
3851 case MachineCombinerPattern::FMULADDS_OP2:
3852 case MachineCombinerPattern::FMULADDD_OP2:
3853 // FMUL I=A,B,0
3854 // FADD R,C,I
3855 // ==> FMADD R,A,B,C
3856 // --- Create(FMADD);
3857 if (Pattern == MachineCombinerPattern::FMULADDS_OP2) {
3858 Opc = AArch64::FMADDSrrr;
3859 RC = &AArch64::FPR32RegClass;
3860 } else {
3861 Opc = AArch64::FMADDDrrr;
3862 RC = &AArch64::FPR64RegClass;
3863 }
3864 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
3865 break;
3866
3867 case MachineCombinerPattern::FMLAv1i32_indexed_OP1:
3868 Opc = AArch64::FMLAv1i32_indexed;
3869 RC = &AArch64::FPR32RegClass;
3870 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3871 FMAInstKind::Indexed);
3872 break;
3873 case MachineCombinerPattern::FMLAv1i32_indexed_OP2:
3874 Opc = AArch64::FMLAv1i32_indexed;
3875 RC = &AArch64::FPR32RegClass;
3876 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3877 FMAInstKind::Indexed);
3878 break;
3879
3880 case MachineCombinerPattern::FMLAv1i64_indexed_OP1:
3881 Opc = AArch64::FMLAv1i64_indexed;
3882 RC = &AArch64::FPR64RegClass;
3883 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3884 FMAInstKind::Indexed);
3885 break;
3886 case MachineCombinerPattern::FMLAv1i64_indexed_OP2:
3887 Opc = AArch64::FMLAv1i64_indexed;
3888 RC = &AArch64::FPR64RegClass;
3889 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3890 FMAInstKind::Indexed);
3891 break;
3892
3893 case MachineCombinerPattern::FMLAv2i32_indexed_OP1:
3894 case MachineCombinerPattern::FMLAv2f32_OP1:
3895 RC = &AArch64::FPR64RegClass;
3896 if (Pattern == MachineCombinerPattern::FMLAv2i32_indexed_OP1) {
3897 Opc = AArch64::FMLAv2i32_indexed;
3898 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3899 FMAInstKind::Indexed);
3900 } else {
3901 Opc = AArch64::FMLAv2f32;
3902 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3903 FMAInstKind::Accumulator);
3904 }
3905 break;
3906 case MachineCombinerPattern::FMLAv2i32_indexed_OP2:
3907 case MachineCombinerPattern::FMLAv2f32_OP2:
3908 RC = &AArch64::FPR64RegClass;
3909 if (Pattern == MachineCombinerPattern::FMLAv2i32_indexed_OP2) {
3910 Opc = AArch64::FMLAv2i32_indexed;
3911 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3912 FMAInstKind::Indexed);
3913 } else {
3914 Opc = AArch64::FMLAv2f32;
3915 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3916 FMAInstKind::Accumulator);
3917 }
3918 break;
3919
3920 case MachineCombinerPattern::FMLAv2i64_indexed_OP1:
3921 case MachineCombinerPattern::FMLAv2f64_OP1:
3922 RC = &AArch64::FPR128RegClass;
3923 if (Pattern == MachineCombinerPattern::FMLAv2i64_indexed_OP1) {
3924 Opc = AArch64::FMLAv2i64_indexed;
3925 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3926 FMAInstKind::Indexed);
3927 } else {
3928 Opc = AArch64::FMLAv2f64;
3929 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3930 FMAInstKind::Accumulator);
3931 }
3932 break;
3933 case MachineCombinerPattern::FMLAv2i64_indexed_OP2:
3934 case MachineCombinerPattern::FMLAv2f64_OP2:
3935 RC = &AArch64::FPR128RegClass;
3936 if (Pattern == MachineCombinerPattern::FMLAv2i64_indexed_OP2) {
3937 Opc = AArch64::FMLAv2i64_indexed;
3938 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3939 FMAInstKind::Indexed);
3940 } else {
3941 Opc = AArch64::FMLAv2f64;
3942 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3943 FMAInstKind::Accumulator);
3944 }
3945 break;
3946
3947 case MachineCombinerPattern::FMLAv4i32_indexed_OP1:
3948 case MachineCombinerPattern::FMLAv4f32_OP1:
3949 RC = &AArch64::FPR128RegClass;
3950 if (Pattern == MachineCombinerPattern::FMLAv4i32_indexed_OP1) {
3951 Opc = AArch64::FMLAv4i32_indexed;
3952 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3953 FMAInstKind::Indexed);
3954 } else {
3955 Opc = AArch64::FMLAv4f32;
3956 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
3957 FMAInstKind::Accumulator);
3958 }
3959 break;
3960
3961 case MachineCombinerPattern::FMLAv4i32_indexed_OP2:
3962 case MachineCombinerPattern::FMLAv4f32_OP2:
3963 RC = &AArch64::FPR128RegClass;
3964 if (Pattern == MachineCombinerPattern::FMLAv4i32_indexed_OP2) {
3965 Opc = AArch64::FMLAv4i32_indexed;
3966 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3967 FMAInstKind::Indexed);
3968 } else {
3969 Opc = AArch64::FMLAv4f32;
3970 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
3971 FMAInstKind::Accumulator);
3972 }
3973 break;
3974
3975 case MachineCombinerPattern::FMULSUBS_OP1:
3976 case MachineCombinerPattern::FMULSUBD_OP1: {
3977 // FMUL I=A,B,0
3978 // FSUB R,I,C
3979 // ==> FNMSUB R,A,B,C // = -C + A*B
3980 // --- Create(FNMSUB);
3981 if (Pattern == MachineCombinerPattern::FMULSUBS_OP1) {
3982 Opc = AArch64::FNMSUBSrrr;
3983 RC = &AArch64::FPR32RegClass;
3984 } else {
3985 Opc = AArch64::FNMSUBDrrr;
3986 RC = &AArch64::FPR64RegClass;
3987 }
3988 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
3989 break;
3990 }
3991 case MachineCombinerPattern::FMULSUBS_OP2:
3992 case MachineCombinerPattern::FMULSUBD_OP2: {
3993 // FMUL I=A,B,0
3994 // FSUB R,C,I
3995 // ==> FMSUB R,A,B,C (computes C - A*B)
3996 // --- Create(FMSUB);
3997 if (Pattern == MachineCombinerPattern::FMULSUBS_OP2) {
3998 Opc = AArch64::FMSUBSrrr;
3999 RC = &AArch64::FPR32RegClass;
4000 } else {
4001 Opc = AArch64::FMSUBDrrr;
4002 RC = &AArch64::FPR64RegClass;
4003 }
4004 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
4005 break;
4006
4007 case MachineCombinerPattern::FMLSv1i32_indexed_OP2:
4008 Opc = AArch64::FMLSv1i32_indexed;
4009 RC = &AArch64::FPR32RegClass;
4010 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4011 FMAInstKind::Indexed);
4012 break;
4013
4014 case MachineCombinerPattern::FMLSv1i64_indexed_OP2:
4015 Opc = AArch64::FMLSv1i64_indexed;
4016 RC = &AArch64::FPR64RegClass;
4017 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4018 FMAInstKind::Indexed);
4019 break;
4020
4021 case MachineCombinerPattern::FMLSv2f32_OP2:
4022 case MachineCombinerPattern::FMLSv2i32_indexed_OP2:
4023 RC = &AArch64::FPR64RegClass;
4024 if (Pattern == MachineCombinerPattern::FMLSv2i32_indexed_OP2) {
4025 Opc = AArch64::FMLSv2i32_indexed;
4026 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4027 FMAInstKind::Indexed);
4028 } else {
4029 Opc = AArch64::FMLSv2f32;
4030 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4031 FMAInstKind::Accumulator);
4032 }
4033 break;
4034
4035 case MachineCombinerPattern::FMLSv2f64_OP2:
4036 case MachineCombinerPattern::FMLSv2i64_indexed_OP2:
4037 RC = &AArch64::FPR128RegClass;
4038 if (Pattern == MachineCombinerPattern::FMLSv2i64_indexed_OP2) {
4039 Opc = AArch64::FMLSv2i64_indexed;
4040 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4041 FMAInstKind::Indexed);
4042 } else {
4043 Opc = AArch64::FMLSv2f64;
4044 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4045 FMAInstKind::Accumulator);
4046 }
4047 break;
4048
4049 case MachineCombinerPattern::FMLSv4f32_OP2:
4050 case MachineCombinerPattern::FMLSv4i32_indexed_OP2:
4051 RC = &AArch64::FPR128RegClass;
4052 if (Pattern == MachineCombinerPattern::FMLSv4i32_indexed_OP2) {
4053 Opc = AArch64::FMLSv4i32_indexed;
4054 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4055 FMAInstKind::Indexed);
4056 } else {
4057 Opc = AArch64::FMLSv4f32;
4058 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
4059 FMAInstKind::Accumulator);
4060 }
4061 break;
4062 }
Juergen Ributzka31e5b7f2014-09-03 07:07:10 +00004063 } // end switch (Pattern)
Gerolf Hoflehner97c383b2014-08-07 21:40:58 +00004064 // Record MUL and ADD/SUB for deletion
4065 DelInstrs.push_back(MUL);
4066 DelInstrs.push_back(&Root);
4067
4068 return;
4069}
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004070
4071/// \brief Replace csincr-branch sequence by simple conditional branch
4072///
4073/// Examples:
4074/// 1.
4075/// csinc w9, wzr, wzr, <condition code>
4076/// tbnz w9, #0, 0x44
4077/// to
4078/// b.<inverted condition code>
4079///
4080/// 2.
4081/// csinc w9, wzr, wzr, <condition code>
4082/// tbz w9, #0, 0x44
4083/// to
4084/// b.<condition code>
4085///
Chad Rosier4aeab5f2016-03-21 13:43:58 +00004086/// Replace compare and branch sequence by TBZ/TBNZ instruction when the
4087/// compare's constant operand is power of 2.
Balaram Makame9b27252016-03-10 17:54:55 +00004088///
4089/// Examples:
4090/// and w8, w8, #0x400
4091/// cbnz w8, L1
4092/// to
4093/// tbnz w8, #10, L1
4094///
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004095/// \param MI Conditional Branch
4096/// \return True when the simple conditional branch is generated
4097///
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004098bool AArch64InstrInfo::optimizeCondBranch(MachineInstr &MI) const {
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004099 bool IsNegativeBranch = false;
4100 bool IsTestAndBranch = false;
4101 unsigned TargetBBInMI = 0;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004102 switch (MI.getOpcode()) {
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004103 default:
4104 llvm_unreachable("Unknown branch instruction?");
4105 case AArch64::Bcc:
4106 return false;
4107 case AArch64::CBZW:
4108 case AArch64::CBZX:
4109 TargetBBInMI = 1;
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004110 break;
4111 case AArch64::CBNZW:
4112 case AArch64::CBNZX:
4113 TargetBBInMI = 1;
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004114 IsNegativeBranch = true;
4115 break;
4116 case AArch64::TBZW:
4117 case AArch64::TBZX:
4118 TargetBBInMI = 2;
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004119 IsTestAndBranch = true;
4120 break;
4121 case AArch64::TBNZW:
4122 case AArch64::TBNZX:
4123 TargetBBInMI = 2;
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004124 IsNegativeBranch = true;
4125 IsTestAndBranch = true;
4126 break;
4127 }
4128 // So we increment a zero register and test for bits other
4129 // than bit 0? Conservatively bail out in case the verifier
4130 // missed this case.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004131 if (IsTestAndBranch && MI.getOperand(1).getImm())
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004132 return false;
4133
4134 // Find Definition.
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004135 assert(MI.getParent() && "Incomplete machine instruciton\n");
4136 MachineBasicBlock *MBB = MI.getParent();
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004137 MachineFunction *MF = MBB->getParent();
4138 MachineRegisterInfo *MRI = &MF->getRegInfo();
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004139 unsigned VReg = MI.getOperand(0).getReg();
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004140 if (!TargetRegisterInfo::isVirtualRegister(VReg))
4141 return false;
4142
4143 MachineInstr *DefMI = MRI->getVRegDef(VReg);
4144
Balaram Makame9b27252016-03-10 17:54:55 +00004145 // Look through COPY instructions to find definition.
4146 while (DefMI->isCopy()) {
4147 unsigned CopyVReg = DefMI->getOperand(1).getReg();
4148 if (!MRI->hasOneNonDBGUse(CopyVReg))
4149 return false;
4150 if (!MRI->hasOneDef(CopyVReg))
4151 return false;
4152 DefMI = MRI->getVRegDef(CopyVReg);
4153 }
4154
4155 switch (DefMI->getOpcode()) {
4156 default:
4157 return false;
4158 // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
4159 case AArch64::ANDWri:
4160 case AArch64::ANDXri: {
4161 if (IsTestAndBranch)
4162 return false;
4163 if (DefMI->getParent() != MBB)
4164 return false;
4165 if (!MRI->hasOneNonDBGUse(VReg))
4166 return false;
4167
Quentin Colombetabe2d012016-04-25 20:54:08 +00004168 bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
Balaram Makame9b27252016-03-10 17:54:55 +00004169 uint64_t Mask = AArch64_AM::decodeLogicalImmediate(
Quentin Colombetabe2d012016-04-25 20:54:08 +00004170 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
Balaram Makame9b27252016-03-10 17:54:55 +00004171 if (!isPowerOf2_64(Mask))
4172 return false;
4173
4174 MachineOperand &MO = DefMI->getOperand(1);
4175 unsigned NewReg = MO.getReg();
4176 if (!TargetRegisterInfo::isVirtualRegister(NewReg))
4177 return false;
4178
4179 assert(!MRI->def_empty(NewReg) && "Register must be defined.");
4180
4181 MachineBasicBlock &RefToMBB = *MBB;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004182 MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
4183 DebugLoc DL = MI.getDebugLoc();
Balaram Makame9b27252016-03-10 17:54:55 +00004184 unsigned Imm = Log2_64(Mask);
Renato Golin179d1f52016-04-23 19:30:52 +00004185 unsigned Opc = (Imm < 32)
4186 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
4187 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
Quentin Colombetabe2d012016-04-25 20:54:08 +00004188 MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
4189 .addReg(NewReg)
4190 .addImm(Imm)
4191 .addMBB(TBB);
Matthias Braune25bbd02016-05-03 04:54:16 +00004192 // Register lives on to the CBZ now.
4193 MO.setIsKill(false);
Quentin Colombetabe2d012016-04-25 20:54:08 +00004194
4195 // For immediate smaller than 32, we need to use the 32-bit
4196 // variant (W) in all cases. Indeed the 64-bit variant does not
4197 // allow to encode them.
4198 // Therefore, if the input register is 64-bit, we need to take the
4199 // 32-bit sub-part.
4200 if (!Is32Bit && Imm < 32)
4201 NewMI->getOperand(0).setSubReg(AArch64::sub_32);
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004202 MI.eraseFromParent();
Balaram Makame9b27252016-03-10 17:54:55 +00004203 return true;
4204 }
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004205 // Look for CSINC
Balaram Makame9b27252016-03-10 17:54:55 +00004206 case AArch64::CSINCWr:
4207 case AArch64::CSINCXr: {
4208 if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
4209 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
4210 !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
4211 DefMI->getOperand(2).getReg() == AArch64::XZR))
4212 return false;
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004213
Balaram Makame9b27252016-03-10 17:54:55 +00004214 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, true) != -1)
4215 return false;
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004216
Balaram Makame9b27252016-03-10 17:54:55 +00004217 AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
Balaram Makame9b27252016-03-10 17:54:55 +00004218 // Convert only when the condition code is not modified between
4219 // the CSINC and the branch. The CC may be used by other
4220 // instructions in between.
Evgeny Astigeevich9c24ebf2016-04-06 11:39:00 +00004221 if (areCFlagsAccessedBetweenInstrs(DefMI, MI, &getRegisterInfo(), AK_Write))
Balaram Makame9b27252016-03-10 17:54:55 +00004222 return false;
4223 MachineBasicBlock &RefToMBB = *MBB;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004224 MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
4225 DebugLoc DL = MI.getDebugLoc();
Balaram Makame9b27252016-03-10 17:54:55 +00004226 if (IsNegativeBranch)
4227 CC = AArch64CC::getInvertedCondCode(CC);
4228 BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00004229 MI.eraseFromParent();
Balaram Makame9b27252016-03-10 17:54:55 +00004230 return true;
4231 }
4232 }
Gerolf Hoflehnera4c96d02014-10-14 23:07:53 +00004233}
Alex Lorenzf3630112015-08-18 22:52:15 +00004234
4235std::pair<unsigned, unsigned>
4236AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
4237 const unsigned Mask = AArch64II::MO_FRAGMENT;
4238 return std::make_pair(TF & Mask, TF & ~Mask);
4239}
4240
4241ArrayRef<std::pair<unsigned, const char *>>
4242AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
4243 using namespace AArch64II;
Hal Finkel982e8d42015-08-30 08:07:29 +00004244 static const std::pair<unsigned, const char *> TargetFlags[] = {
Alex Lorenzf3630112015-08-18 22:52:15 +00004245 {MO_PAGE, "aarch64-page"},
4246 {MO_PAGEOFF, "aarch64-pageoff"},
4247 {MO_G3, "aarch64-g3"},
4248 {MO_G2, "aarch64-g2"},
4249 {MO_G1, "aarch64-g1"},
4250 {MO_G0, "aarch64-g0"},
4251 {MO_HI12, "aarch64-hi12"}};
4252 return makeArrayRef(TargetFlags);
4253}
4254
4255ArrayRef<std::pair<unsigned, const char *>>
4256AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
4257 using namespace AArch64II;
Hal Finkel982e8d42015-08-30 08:07:29 +00004258 static const std::pair<unsigned, const char *> TargetFlags[] = {
Alex Lorenzf3630112015-08-18 22:52:15 +00004259 {MO_GOT, "aarch64-got"},
4260 {MO_NC, "aarch64-nc"},
Rafael Espindola4d290992016-05-31 18:31:14 +00004261 {MO_TLS, "aarch64-tls"}};
Alex Lorenzf3630112015-08-18 22:52:15 +00004262 return makeArrayRef(TargetFlags);
4263}