LLVM 24.0.0git
AArch64InstrInfo.cpp
Go to the documentation of this file.
1//===- AArch64InstrInfo.cpp - AArch64 Instruction Information -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the AArch64 implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AArch64InstrInfo.h"
14#include "AArch64ExpandImm.h"
16#include "AArch64PointerAuth.h"
17#include "AArch64Subtarget.h"
22#include "llvm/ADT/ArrayRef.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SmallSet.h"
26#include "llvm/ADT/Statistic.h"
45#include "llvm/IR/DebugLoc.h"
46#include "llvm/IR/GlobalValue.h"
47#include "llvm/IR/Module.h"
48#include "llvm/MC/MCAsmInfo.h"
49#include "llvm/MC/MCInst.h"
51#include "llvm/MC/MCInstrDesc.h"
56#include "llvm/Support/LEB128.h"
60#include <cassert>
61#include <cstdint>
62#include <iterator>
63#include <utility>
64
65using namespace llvm;
66
67#define GET_INSTRINFO_CTOR_DTOR
68#include "AArch64GenInstrInfo.inc"
69
70#define DEBUG_TYPE "AArch64InstrInfo"
71
72STATISTIC(NumCopyInstrs, "Number of COPY instructions expanded");
73STATISTIC(NumZCRegMoveInstrsGPR, "Number of zero-cycle GPR register move "
74 "instructions expanded from canonical COPY");
75STATISTIC(NumZCRegMoveInstrsFPR, "Number of zero-cycle FPR register move "
76 "instructions expanded from canonical COPY");
77STATISTIC(NumZCZeroingInstrsGPR, "Number of zero-cycle GPR zeroing "
78 "instructions expanded from canonical COPY");
79// NumZCZeroingInstrsFPR is counted at AArch64AsmPrinter
80
82 CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9),
83 cl::desc("Restrict range of CB instructions (DEBUG)"));
84
86 "aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
87 cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
88
90 "aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
91 cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
92
94 BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
95 cl::desc("Restrict range of Bcc instructions (DEBUG)"));
96
98 BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26),
99 cl::desc("Restrict range of B instructions (DEBUG)"));
100
102 "aarch64-search-limit", cl::Hidden, cl::init(2048),
103 cl::desc("Restrict range of instructions to search for the "
104 "machine-combiner gather pattern optimization"));
105
107 "aarch64-outliner-compact-unwind-frame", cl::Hidden, cl::init(true),
108 cl::desc("Use a frame record for Mach-O non-leaf outlined functions"));
109
111 : AArch64GenInstrInfo(STI, RI, AArch64::ADJCALLSTACKDOWN,
112 AArch64::ADJCALLSTACKUP, AArch64::CATCHRET),
113 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
114
115/// Return the maximum number of bytes of code the specified instruction may be
116/// after LFI rewriting. If the instruction is not rewritten, std::nullopt is
117/// returned (use default sizing).
118///
119/// NOTE: the size estimates here must be kept in sync with the rewrites in
120/// AArch64MCLFIRewriter.cpp. Sizes may be overestimates of the rewritten
121/// instruction sequences.
122static std::optional<unsigned> getLFIInstSizeInBytes(const MachineInstr &MI) {
123 switch (MI.getOpcode()) {
124 case AArch64::SVC:
125 // SVC expands to 4 instructions.
126 return 16;
127 case AArch64::BR:
128 case AArch64::BLR:
129 // Indirect branches/calls expand to 2 instructions (guard + br/blr).
130 return 8;
131 case AArch64::RET:
132 // RET through LR is not rewritten, but RET through another register
133 // expands to 2 instructions (guard + ret).
134 if (MI.getOperand(0).getReg() != AArch64::LR)
135 return 8;
136 return 4;
137 case AArch64::RETAA:
138 case AArch64::RETAB:
139 // Authenticated returns expand to 3 instructions (authenticate + guard +
140 // ret).
141 return 12;
142 case AArch64::BRAA:
143 case AArch64::BRAAZ:
144 case AArch64::BRAB:
145 case AArch64::BRABZ:
146 case AArch64::BLRAA:
147 case AArch64::BLRAAZ:
148 case AArch64::BLRAB:
149 case AArch64::BLRABZ:
150 // Authenticated branches/calls expand to 3 instructions (authenticate +
151 // guard + branch).
152 return 12;
153 case AArch64::AUTIASP:
154 case AArch64::AUTIBSP:
155 case AArch64::AUTIAZ:
156 case AArch64::AUTIBZ:
157 case AArch64::XPACLRI:
158 // Authenticating LR expands to the instruction plus a deferred LR guard.
159 return 8;
160 case AArch64::SYSxt:
161 // VA-based DC/IC ops (op1=3, Cn=7, op2=1) expand to 2 instructions.
162 if (MI.getOperand(0).getImm() == 3 && MI.getOperand(1).getImm() == 7 &&
163 MI.getOperand(3).getImm() == 1)
164 return 8;
165 return std::nullopt;
166 default:
167 break;
168 }
169
170 // Detect instructions that explicitly define SP or LR.
171 bool ModifiesLR = false;
172 bool ModifiesSP = false;
173 for (const MachineOperand &MO : MI.defs()) {
174 if (!MO.isReg())
175 continue;
176 if (MO.getReg() == AArch64::LR)
177 ModifiesLR = true;
178 else if (MO.getReg() == AArch64::SP)
179 ModifiesSP = true;
180 }
181
182 // Memory accesses expand to a base-register guard plus the rewritten access
183 // (8 bytes), with an extra base-register update for pre/post-index forms (12
184 // bytes total). If the access also defines LR, an LR mask is appended (+4
185 // bytes). Depending on additional optimizations that the rewriter performs,
186 // this may be an overestimate.
187 if (MI.mayLoadOrStore()) {
188 unsigned Size = isLFIPrePostMemAccess(MI.getOpcode()) ? 12 : 8;
189 if (ModifiesLR)
190 Size += 4;
191 return Size;
192 }
193
194 // Non memory operations that modify LR or SP expand to 2 instructions.
195 if (ModifiesSP || ModifiesLR)
196 return 8;
197
198 // Default case: instructions that don't cause expansion.
199 // - TP accesses in LFI are a single load/store, so no expansion.
200 // - All remaining instructions are not rewritten.
201 return std::nullopt;
202}
203
204/// GetInstSize - Return the number of bytes of code the specified
205/// instruction may be. This returns the maximum number of bytes.
207 const MachineBasicBlock &MBB = *MI.getParent();
208 const MachineFunction *MF = MBB.getParent();
209 const Function &F = MF->getFunction();
210 const MCAsmInfo &MAI = MF->getTarget().getMCAsmInfo();
211
212 {
213 auto Op = MI.getOpcode();
214 if (Op == AArch64::INLINEASM || Op == AArch64::INLINEASM_BR)
215 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
216 }
217
218 // Meta-instructions emit no code.
219 if (MI.isMetaInstruction())
220 return 0;
221
222 // FIXME: We currently only handle pseudoinstructions that don't get expanded
223 // before the assembly printer.
224 unsigned NumBytes = 0;
225 const MCInstrDesc &Desc = MI.getDesc();
226
227 // LFI rewriter expansions that supersede normal sizing.
228 const auto &STI = MF->getSubtarget<AArch64Subtarget>();
229 if (STI.isLFI())
230 if (auto Size = getLFIInstSizeInBytes(MI))
231 return *Size;
232
233 if (!MI.isBundle() && isTailCallReturnInst(MI)) {
234 NumBytes = Desc.getSize() ? Desc.getSize() : 4;
235
236 const auto *MFI = MF->getInfo<AArch64FunctionInfo>();
237 if (!MFI->shouldSignReturnAddress(*MF))
238 return NumBytes;
239
240 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
241 NumBytes += AArch64PAuth::getCheckerSizeInBytes(Method);
242 return NumBytes;
243 }
244
245 // Size should be preferably set in
246 // llvm/lib/Target/AArch64/AArch64InstrInfo.td (default case).
247 // Specific cases handle instructions of variable sizes
248 switch (Desc.getOpcode()) {
249 default:
250 if (Desc.getSize())
251 return Desc.getSize();
252
253 // Anything not explicitly designated otherwise (i.e. pseudo-instructions
254 // with fixed constant size but not specified in .td file) is a normal
255 // 4-byte insn.
256 NumBytes = 4;
257 break;
258 case TargetOpcode::STACKMAP:
259 // The upper bound for a stackmap intrinsic is the full length of its shadow
260 NumBytes = StackMapOpers(&MI).getNumPatchBytes();
261 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
262 break;
263 case TargetOpcode::PATCHPOINT:
264 // The size of the patchpoint intrinsic is the number of bytes requested
265 NumBytes = PatchPointOpers(&MI).getNumPatchBytes();
266 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
267 break;
268 case TargetOpcode::STATEPOINT:
269 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
270 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
271 // No patch bytes means a normal call inst is emitted
272 if (NumBytes == 0)
273 NumBytes = 4;
274 break;
275 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
276 // If `patchable-function-entry` is set, PATCHABLE_FUNCTION_ENTER
277 // instructions are expanded to the specified number of NOPs. Otherwise,
278 // they are expanded to 36-byte XRay sleds.
279 NumBytes =
280 F.getFnAttributeAsParsedInteger("patchable-function-entry", 9) * 4;
281 break;
282 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
283 case TargetOpcode::PATCHABLE_TAIL_CALL:
284 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
285 // An XRay sled can be 4 bytes of alignment plus a 32-byte block.
286 NumBytes = 36;
287 break;
288 case TargetOpcode::PATCHABLE_EVENT_CALL:
289 // EVENT_CALL XRay sleds are exactly 6 instructions long (no alignment).
290 NumBytes = 24;
291 break;
292
293 case AArch64::SPACE:
294 NumBytes = MI.getOperand(1).getImm();
295 break;
296 case AArch64::MOVaddr:
297 case AArch64::MOVaddrJT:
298 case AArch64::MOVaddrCP:
299 case AArch64::MOVaddrBA:
300 case AArch64::MOVaddrTLS:
301 case AArch64::MOVaddrEXT: {
302 // Use the same logic as the pseudo expansion to count instructions.
305 MI.getOperand(1).getTargetFlags(),
306 Subtarget.isTargetMachO(), Insn);
307 NumBytes = Insn.size() * 4;
308 break;
309 }
310
311 case AArch64::MOVi32imm:
312 case AArch64::MOVi64imm: {
313 // Use the same logic as the pseudo expansion to count instructions.
314 unsigned BitSize = Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
316 AArch64_IMM::expandMOVImm(MI.getOperand(1).getImm(), BitSize, Insn);
317 NumBytes = Insn.size() * 4;
318 break;
319 }
320
321 case TargetOpcode::BUNDLE:
322 NumBytes = getInstBundleSize(MI);
323 break;
324 }
325
326 return NumBytes;
327}
328
331 // Block ends with fall-through condbranch.
332 switch (LastInst->getOpcode()) {
333 default:
334 llvm_unreachable("Unknown branch instruction?");
335 case AArch64::Bcc:
336 Target = LastInst->getOperand(1).getMBB();
337 Cond.push_back(LastInst->getOperand(0));
338 break;
339 case AArch64::CBZW:
340 case AArch64::CBZX:
341 case AArch64::CBNZW:
342 case AArch64::CBNZX:
343 Target = LastInst->getOperand(1).getMBB();
344 Cond.push_back(MachineOperand::CreateImm(-1));
345 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
346 Cond.push_back(LastInst->getOperand(0));
347 break;
348 case AArch64::TBZW:
349 case AArch64::TBZX:
350 case AArch64::TBNZW:
351 case AArch64::TBNZX:
352 Target = LastInst->getOperand(2).getMBB();
353 Cond.push_back(MachineOperand::CreateImm(-1));
354 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
355 Cond.push_back(LastInst->getOperand(0));
356 Cond.push_back(LastInst->getOperand(1));
357 break;
358 case AArch64::CBWPri:
359 case AArch64::CBXPri:
360 case AArch64::CBWPrr:
361 case AArch64::CBXPrr:
362 Target = LastInst->getOperand(3).getMBB();
363 Cond.push_back(MachineOperand::CreateImm(-1));
364 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
365 Cond.push_back(LastInst->getOperand(0));
366 Cond.push_back(LastInst->getOperand(1));
367 Cond.push_back(LastInst->getOperand(2));
368 break;
369 case AArch64::CBBAssertExt:
370 case AArch64::CBHAssertExt:
371 Target = LastInst->getOperand(3).getMBB();
372 Cond.push_back(MachineOperand::CreateImm(-1)); // -1
373 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); // Opc
374 Cond.push_back(LastInst->getOperand(0)); // Cond
375 Cond.push_back(LastInst->getOperand(1)); // Op0
376 Cond.push_back(LastInst->getOperand(2)); // Op1
377 Cond.push_back(LastInst->getOperand(4)); // Ext0
378 Cond.push_back(LastInst->getOperand(5)); // Ext1
379 break;
380 }
381}
382
383static unsigned getBranchDisplacementBits(unsigned Opc) {
384 switch (Opc) {
385 default:
386 llvm_unreachable("unexpected opcode!");
387 case AArch64::B:
388 return BDisplacementBits;
389 case AArch64::TBNZW:
390 case AArch64::TBZW:
391 case AArch64::TBNZX:
392 case AArch64::TBZX:
393 return TBZDisplacementBits;
394 case AArch64::CBNZW:
395 case AArch64::CBZW:
396 case AArch64::CBNZX:
397 case AArch64::CBZX:
398 return CBZDisplacementBits;
399 case AArch64::Bcc:
400 return BCCDisplacementBits;
401 case AArch64::CBWPri:
402 case AArch64::CBXPri:
403 case AArch64::CBBAssertExt:
404 case AArch64::CBHAssertExt:
405 case AArch64::CBWPrr:
406 case AArch64::CBXPrr:
407 return CBDisplacementBits;
408 }
409}
410
412 int64_t BrOffset) const {
413 unsigned Bits = getBranchDisplacementBits(BranchOp);
414 assert(Bits >= 3 && "max branch displacement must be enough to jump"
415 "over conditional branch expansion");
416 return isIntN(Bits, BrOffset / 4);
417}
418
421 switch (MI.getOpcode()) {
422 default:
423 llvm_unreachable("unexpected opcode!");
424 case AArch64::B:
425 return MI.getOperand(0).getMBB();
426 case AArch64::TBZW:
427 case AArch64::TBNZW:
428 case AArch64::TBZX:
429 case AArch64::TBNZX:
430 return MI.getOperand(2).getMBB();
431 case AArch64::CBZW:
432 case AArch64::CBNZW:
433 case AArch64::CBZX:
434 case AArch64::CBNZX:
435 case AArch64::Bcc:
436 return MI.getOperand(1).getMBB();
437 case AArch64::CBWPri:
438 case AArch64::CBXPri:
439 case AArch64::CBBAssertExt:
440 case AArch64::CBHAssertExt:
441 case AArch64::CBWPrr:
442 case AArch64::CBXPrr:
443 return MI.getOperand(3).getMBB();
444 }
445}
446
448 MachineBasicBlock &NewDestBB,
449 MachineBasicBlock &RestoreBB,
450 const DebugLoc &DL,
451 int64_t BrOffset,
452 RegScavenger *RS) const {
453 assert(RS && "RegScavenger required for long branching");
454 assert(MBB.empty() &&
455 "new block should be inserted for expanding unconditional branch");
456 assert(MBB.pred_size() == 1);
457 assert(RestoreBB.empty() &&
458 "restore block should be inserted for restoring clobbered registers");
459
460 auto buildIndirectBranch = [&](Register Reg, MachineBasicBlock &DestBB) {
461 // Offsets outside of the signed 33-bit range are not supported for ADRP +
462 // ADD.
463 if (!isInt<33>(BrOffset))
465 "Branch offsets outside of the signed 33-bit range not supported");
466
467 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADRP), Reg)
468 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGE);
469 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADDXri), Reg)
470 .addReg(Reg)
471 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGEOFF | AArch64II::MO_NC)
472 .addImm(0);
473 BuildMI(MBB, MBB.end(), DL, get(AArch64::BR)).addReg(Reg);
474 };
475
476 RS->enterBasicBlockEnd(MBB);
477 // If X16 is unused, we can rely on the linker to insert a range extension
478 // thunk if NewDestBB is out of range of a single B instruction.
479 constexpr Register Reg = AArch64::X16;
480 if (!RS->isRegUsed(Reg)) {
481 insertUnconditionalBranch(MBB, &NewDestBB, DL);
482 RS->setRegUsed(Reg);
483 return;
484 }
485
486 // In a cold block without BTI, insert the indirect branch if a register is
487 // free. Skip this if BTI is enabled to avoid inserting a BTI at the target,
488 // prioritizing a dynamic cost in cold code over a static cost in hot code.
489 AArch64FunctionInfo *AFI = MBB.getParent()->getInfo<AArch64FunctionInfo>();
490 bool HasBTI = AFI && AFI->branchTargetEnforcement();
491 if (MBB.getSectionID() == MBBSectionID::ColdSectionID && !HasBTI) {
492 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
493 if (Scavenged != AArch64::NoRegister) {
494 buildIndirectBranch(Scavenged, NewDestBB);
495 RS->setRegUsed(Scavenged);
496 return;
497 }
498 }
499
500 // Note: Spilling X16 briefly moves the stack pointer, making it incompatible
501 // with red zones.
502 if (!AFI || AFI->hasRedZone().value_or(true))
504 "Unable to insert indirect branch inside function that has red zone");
505
506 // Otherwise, spill X16 and defer range extension to the linker.
507 BuildMI(MBB, MBB.end(), DL, get(AArch64::STRXpre))
508 .addReg(AArch64::SP, RegState::Define)
509 .addReg(Reg)
510 .addReg(AArch64::SP)
511 .addImm(-16);
512
513 BuildMI(MBB, MBB.end(), DL, get(AArch64::B)).addMBB(&RestoreBB);
514
515 BuildMI(RestoreBB, RestoreBB.end(), DL, get(AArch64::LDRXpost))
516 .addReg(AArch64::SP, RegState::Define)
518 .addReg(AArch64::SP)
519 .addImm(16);
520}
521
522// Branch analysis.
525 MachineBasicBlock *&FBB,
527 bool AllowModify) const {
528 // If the block has no terminators, it just falls into the block after it.
529 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
530 if (I == MBB.end())
531 return false;
532
533 // Skip over SpeculationBarrierEndBB terminators
534 if (I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
535 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
536 --I;
537 }
538
539 if (!isUnpredicatedTerminator(*I))
540 return false;
541
542 // Get the last instruction in the block.
543 MachineInstr *LastInst = &*I;
544
545 // If there is only one terminator instruction, process it.
546 unsigned LastOpc = LastInst->getOpcode();
547 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
548 if (isUncondBranchOpcode(LastOpc)) {
549 TBB = LastInst->getOperand(0).getMBB();
550 return false;
551 }
552 if (isCondBranchOpcode(LastOpc)) {
553 // Block ends with fall-through condbranch.
554 parseCondBranch(LastInst, TBB, Cond);
555 return false;
556 }
557 return true; // Can't handle indirect branch.
558 }
559
560 // Get the instruction before it if it is a terminator.
561 MachineInstr *SecondLastInst = &*I;
562 unsigned SecondLastOpc = SecondLastInst->getOpcode();
563
564 // If AllowModify is true and the block ends with two or more unconditional
565 // branches, delete all but the first unconditional branch.
566 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
567 while (isUncondBranchOpcode(SecondLastOpc)) {
568 LastInst->eraseFromParent();
569 LastInst = SecondLastInst;
570 LastOpc = LastInst->getOpcode();
571 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
572 // Return now the only terminator is an unconditional branch.
573 TBB = LastInst->getOperand(0).getMBB();
574 return false;
575 }
576 SecondLastInst = &*I;
577 SecondLastOpc = SecondLastInst->getOpcode();
578 }
579 }
580
581 // If we're allowed to modify and the block ends in a unconditional branch
582 // which could simply fallthrough, remove the branch. (Note: This case only
583 // matters when we can't understand the whole sequence, otherwise it's also
584 // handled by BranchFolding.cpp.)
585 if (AllowModify && isUncondBranchOpcode(LastOpc) &&
586 MBB.isLayoutSuccessor(getBranchDestBlock(*LastInst))) {
587 LastInst->eraseFromParent();
588 LastInst = SecondLastInst;
589 LastOpc = LastInst->getOpcode();
590 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
591 assert(!isUncondBranchOpcode(LastOpc) &&
592 "unreachable unconditional branches removed above");
593
594 if (isCondBranchOpcode(LastOpc)) {
595 // Block ends with fall-through condbranch.
596 parseCondBranch(LastInst, TBB, Cond);
597 return false;
598 }
599 return true; // Can't handle indirect branch.
600 }
601 SecondLastInst = &*I;
602 SecondLastOpc = SecondLastInst->getOpcode();
603 }
604
605 // If there are three terminators, we don't know what sort of block this is.
606 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
607 return true;
608
609 // If the block ends with a B and a Bcc, handle it.
610 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
611 parseCondBranch(SecondLastInst, TBB, Cond);
612 FBB = LastInst->getOperand(0).getMBB();
613 return false;
614 }
615
616 // If the block ends with two unconditional branches, handle it. The second
617 // one is not executed, so remove it.
618 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
619 TBB = SecondLastInst->getOperand(0).getMBB();
620 I = LastInst;
621 if (AllowModify)
622 I->eraseFromParent();
623 return false;
624 }
625
626 // ...likewise if it ends with an indirect branch followed by an unconditional
627 // branch.
628 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
629 I = LastInst;
630 if (AllowModify)
631 I->eraseFromParent();
632 return true;
633 }
634
635 // Otherwise, can't handle this.
636 return true;
637}
638
640 MachineBranchPredicate &MBP,
641 bool AllowModify) const {
642 // Use analyzeBranch to validate the branch pattern.
643 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
645 if (analyzeBranch(MBB, TBB, FBB, Cond, AllowModify))
646 return true;
647
648 // analyzeBranch returns success with empty Cond for unconditional branches.
649 if (Cond.empty())
650 return true;
651
652 MBP.TrueDest = TBB;
653 assert(MBP.TrueDest && "expected!");
654 MBP.FalseDest = FBB ? FBB : MBB.getNextNode();
655
656 MBP.ConditionDef = nullptr;
657 MBP.SingleUseCondition = false;
658
659 // Find the conditional branch. After analyzeBranch succeeds with non-empty
660 // Cond, there's exactly one conditional branch - either last (fallthrough)
661 // or second-to-last (followed by unconditional B).
662 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
663 if (I == MBB.end())
664 return true;
665
666 if (isUncondBranchOpcode(I->getOpcode())) {
667 if (I == MBB.begin())
668 return true;
669 --I;
670 }
671
672 MachineInstr *CondBranch = &*I;
673 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
674
675 switch (CondBranch->getOpcode()) {
676 default:
677 return true;
678
679 case AArch64::Bcc:
680 // Bcc takes the NZCV flag as the operand to branch on, walk up the
681 // instruction stream to find the last instruction to define NZCV.
683 if (MI.modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
684 MBP.ConditionDef = &MI;
685 break;
686 }
687 }
688 return false;
689
690 case AArch64::CBZW:
691 case AArch64::CBZX:
692 case AArch64::CBNZW:
693 case AArch64::CBNZX: {
694 MBP.LHS = CondBranch->getOperand(0);
695 MBP.RHS = MachineOperand::CreateImm(0);
696 unsigned Opc = CondBranch->getOpcode();
697 MBP.Predicate = (Opc == AArch64::CBNZX || Opc == AArch64::CBNZW)
698 ? MachineBranchPredicate::PRED_NE
699 : MachineBranchPredicate::PRED_EQ;
700 Register CondReg = MBP.LHS.getReg();
701 if (CondReg.isVirtual())
702 MBP.ConditionDef = MRI.getVRegDef(CondReg);
703 return false;
704 }
705
706 case AArch64::TBZW:
707 case AArch64::TBZX:
708 case AArch64::TBNZW:
709 case AArch64::TBNZX: {
710 Register CondReg = CondBranch->getOperand(0).getReg();
711 if (CondReg.isVirtual())
712 MBP.ConditionDef = MRI.getVRegDef(CondReg);
713 return false;
714 }
715 }
716}
717
720 if (Cond[0].getImm() != -1) {
721 // Regular Bcc
722 AArch64CC::CondCode CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
724 } else {
725 // Folded compare-and-branch
726 switch (Cond[1].getImm()) {
727 default:
728 llvm_unreachable("Unknown conditional branch!");
729 case AArch64::CBZW:
730 Cond[1].setImm(AArch64::CBNZW);
731 break;
732 case AArch64::CBNZW:
733 Cond[1].setImm(AArch64::CBZW);
734 break;
735 case AArch64::CBZX:
736 Cond[1].setImm(AArch64::CBNZX);
737 break;
738 case AArch64::CBNZX:
739 Cond[1].setImm(AArch64::CBZX);
740 break;
741 case AArch64::TBZW:
742 Cond[1].setImm(AArch64::TBNZW);
743 break;
744 case AArch64::TBNZW:
745 Cond[1].setImm(AArch64::TBZW);
746 break;
747 case AArch64::TBZX:
748 Cond[1].setImm(AArch64::TBNZX);
749 break;
750 case AArch64::TBNZX:
751 Cond[1].setImm(AArch64::TBZX);
752 break;
753
754 // Cond is { -1, Opcode, CC, Op0, Op1, ... }
755 case AArch64::CBWPri:
756 case AArch64::CBXPri:
757 case AArch64::CBBAssertExt:
758 case AArch64::CBHAssertExt:
759 case AArch64::CBWPrr:
760 case AArch64::CBXPrr: {
761 // Pseudos using standard 4bit Arm condition codes
763 static_cast<AArch64CC::CondCode>(Cond[2].getImm());
765 }
766 }
767 }
768
769 return false;
770}
771
773 int *BytesRemoved) const {
774 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
775 if (I == MBB.end())
776 return 0;
777
778 if (!isUncondBranchOpcode(I->getOpcode()) &&
779 !isCondBranchOpcode(I->getOpcode()))
780 return 0;
781
782 // Remove the branch.
783 I->eraseFromParent();
784
785 I = MBB.end();
786
787 if (I == MBB.begin()) {
788 if (BytesRemoved)
789 *BytesRemoved = 4;
790 return 1;
791 }
792 --I;
793 if (!isCondBranchOpcode(I->getOpcode())) {
794 if (BytesRemoved)
795 *BytesRemoved = 4;
796 return 1;
797 }
798
799 // Remove the branch.
800 I->eraseFromParent();
801 if (BytesRemoved)
802 *BytesRemoved = 8;
803
804 return 2;
805}
806
807void AArch64InstrInfo::instantiateCondBranch(
810 if (Cond[0].getImm() != -1) {
811 // Regular Bcc
812 BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
813 } else {
814 // Folded compare-and-branch
815 // Note that we use addOperand instead of addReg to keep the flags.
816
817 // cbz, cbnz
818 const MachineInstrBuilder MIB =
819 BuildMI(&MBB, DL, get(Cond[1].getImm())).add(Cond[2]);
820
821 // tbz/tbnz
822 if (Cond.size() > 3)
823 MIB.add(Cond[3]);
824
825 // cb
826 if (Cond.size() > 4)
827 MIB.add(Cond[4]);
828
829 MIB.addMBB(TBB);
830
831 // cb[b,h]
832 if (Cond.size() > 5) {
833 MIB.addImm(Cond[5].getImm());
834 MIB.addImm(Cond[6].getImm());
835 }
836 }
837}
838
841 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
842 // Shouldn't be a fall through.
843 assert(TBB && "insertBranch must not be told to insert a fallthrough");
844
845 if (!FBB) {
846 if (Cond.empty()) // Unconditional branch?
847 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
848 else
849 instantiateCondBranch(MBB, DL, TBB, Cond);
850
851 if (BytesAdded)
852 *BytesAdded = 4;
853
854 return 1;
855 }
856
857 // Two-way conditional branch.
858 instantiateCondBranch(MBB, DL, TBB, Cond);
859 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
860
861 if (BytesAdded)
862 *BytesAdded = 8;
863
864 return 2;
865}
866
868 const TargetInstrInfo &TII) {
869 for (MachineInstr &MI : MBB->terminators()) {
870 unsigned Opc = MI.getOpcode();
871 switch (Opc) {
872 case AArch64::CBZW:
873 case AArch64::CBZX:
874 case AArch64::TBZW:
875 case AArch64::TBZX:
876 // CBZ/TBZ with WZR/XZR -> unconditional B
877 if (MI.getOperand(0).getReg() == AArch64::WZR ||
878 MI.getOperand(0).getReg() == AArch64::XZR) {
879 DEBUG_WITH_TYPE("optimizeTerminators",
880 dbgs() << "Removing always taken branch: " << MI);
881 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
882 SmallVector<MachineBasicBlock *> Succs(MBB->successors());
883 for (auto *S : Succs)
884 if (S != Target)
885 MBB->removeSuccessor(S);
886 DebugLoc DL = MI.getDebugLoc();
887 while (MBB->rbegin() != &MI)
888 MBB->rbegin()->eraseFromParent();
889 MI.eraseFromParent();
890 BuildMI(MBB, DL, TII.get(AArch64::B)).addMBB(Target);
891 return true;
892 }
893 break;
894 case AArch64::CBNZW:
895 case AArch64::CBNZX:
896 case AArch64::TBNZW:
897 case AArch64::TBNZX:
898 // CBNZ/TBNZ with WZR/XZR -> never taken, remove branch and successor
899 if (MI.getOperand(0).getReg() == AArch64::WZR ||
900 MI.getOperand(0).getReg() == AArch64::XZR) {
901 DEBUG_WITH_TYPE("optimizeTerminators",
902 dbgs() << "Removing never taken branch: " << MI);
903 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
904 MI.getParent()->removeSuccessor(Target);
905 MI.eraseFromParent();
906 return true;
907 }
908 break;
909 }
910 }
911 return false;
912}
913
914// Find the original register that VReg is copied from.
915static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
916 while (Register::isVirtualRegister(VReg)) {
917 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
918 if (!DefMI || !DefMI->isFullCopy())
919 return VReg;
920 VReg = DefMI->getOperand(1).getReg();
921 }
922 return VReg;
923}
924
925// Determine if VReg is defined by an instruction that can be folded into a
926// csel instruction. If so, return the folded opcode, and the replacement
927// register.
928static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
929 unsigned *NewReg = nullptr) {
930 VReg = removeCopies(MRI, VReg);
932 return 0;
933
934 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
935 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
936 if (!DefMI)
937 return 0;
938 unsigned Opc = 0;
939 unsigned SrcReg = 0;
940 switch (DefMI->getOpcode()) {
941 case AArch64::SUBREG_TO_REG:
942 // Check for the following way to define an 64-bit immediate:
943 // %0:gpr32 = MOVi32imm 1
944 // %1:gpr64 = SUBREG_TO_REG %0:gpr32, %subreg.sub_32
945 if (!DefMI->getOperand(1).isReg())
946 return 0;
947 if (!DefMI->getOperand(2).isImm() ||
948 DefMI->getOperand(2).getImm() != AArch64::sub_32)
949 return 0;
950 DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg());
951 if (DefMI->getOpcode() != AArch64::MOVi32imm)
952 return 0;
953 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
954 return 0;
955 assert(Is64Bit);
956 SrcReg = AArch64::XZR;
957 Opc = AArch64::CSINCXr;
958 break;
959
960 case AArch64::MOVi32imm:
961 case AArch64::MOVi64imm:
962 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
963 return 0;
964 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
965 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
966 break;
967
968 case AArch64::ADDSXri:
969 case AArch64::ADDSWri:
970 // if NZCV is used, do not fold.
971 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
972 true) == -1)
973 return 0;
974 // fall-through to ADDXri and ADDWri.
975 [[fallthrough]];
976 case AArch64::ADDXri:
977 case AArch64::ADDWri:
978 // add x, 1 -> csinc.
979 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
980 DefMI->getOperand(3).getImm() != 0)
981 return 0;
982 SrcReg = DefMI->getOperand(1).getReg();
983 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
984 break;
985
986 case AArch64::ORNXrr:
987 case AArch64::ORNWrr: {
988 // not x -> csinv, represented as orn dst, xzr, src.
989 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
990 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
991 return 0;
992 SrcReg = DefMI->getOperand(2).getReg();
993 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
994 break;
995 }
996
997 case AArch64::SUBSXrr:
998 case AArch64::SUBSWrr:
999 // if NZCV is used, do not fold.
1000 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1001 true) == -1)
1002 return 0;
1003 // fall-through to SUBXrr and SUBWrr.
1004 [[fallthrough]];
1005 case AArch64::SUBXrr:
1006 case AArch64::SUBWrr: {
1007 // neg x -> csneg, represented as sub dst, xzr, src.
1008 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1009 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1010 return 0;
1011 SrcReg = DefMI->getOperand(2).getReg();
1012 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1013 break;
1014 }
1015 default:
1016 return 0;
1017 }
1018 assert(Opc && SrcReg && "Missing parameters");
1019
1020 if (NewReg)
1021 *NewReg = SrcReg;
1022 return Opc;
1023}
1024
1027 Register DstReg, Register TrueReg,
1028 Register FalseReg, int &CondCycles,
1029 int &TrueCycles,
1030 int &FalseCycles) const {
1031 // Check register classes.
1032 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1033 const TargetRegisterClass *RC =
1034 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
1035 if (!RC)
1036 return false;
1037
1038 // Also need to check the dest regclass, in case we're trying to optimize
1039 // something like:
1040 // %1(gpr) = PHI %2(fpr), bb1, %(fpr), bb2
1041 if (!RI.getCommonSubClass(RC, MRI.getRegClass(DstReg)))
1042 return false;
1043
1044 // Expanding cbz/tbz requires an extra cycle of latency on the condition.
1045 unsigned ExtraCondLat = Cond.size() != 1;
1046
1047 // GPRs are handled by csel.
1048 // FIXME: Fold in x+1, -x, and ~x when applicable.
1049 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1050 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1051 // Single-cycle csel, csinc, csinv, and csneg.
1052 CondCycles = 1 + ExtraCondLat;
1053 TrueCycles = FalseCycles = 1;
1054 if (canFoldIntoCSel(MRI, TrueReg))
1055 TrueCycles = 0;
1056 else if (canFoldIntoCSel(MRI, FalseReg))
1057 FalseCycles = 0;
1058 return true;
1059 }
1060
1061 // Scalar floating point is handled by fcsel.
1062 // FIXME: Form fabs, fmin, and fmax when applicable.
1063 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1064 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1065 CondCycles = 5 + ExtraCondLat;
1066 TrueCycles = FalseCycles = 2;
1067 return true;
1068 }
1069
1070 // Can't do vectors.
1071 return false;
1072}
1073
1076 const DebugLoc &DL, Register DstReg,
1078 Register TrueReg, Register FalseReg) const {
1079 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1080
1081 // Parse the condition code, see parseCondBranch() above.
1083 switch (Cond.size()) {
1084 default:
1085 llvm_unreachable("Unknown condition opcode in Cond");
1086 case 1: // b.cc
1087 CC = AArch64CC::CondCode(Cond[0].getImm());
1088 break;
1089 case 3: { // cbz/cbnz
1090 // We must insert a compare against 0.
1091 bool Is64Bit;
1092 switch (Cond[1].getImm()) {
1093 default:
1094 llvm_unreachable("Unknown branch opcode in Cond");
1095 case AArch64::CBZW:
1096 Is64Bit = false;
1097 CC = AArch64CC::EQ;
1098 break;
1099 case AArch64::CBZX:
1100 Is64Bit = true;
1101 CC = AArch64CC::EQ;
1102 break;
1103 case AArch64::CBNZW:
1104 Is64Bit = false;
1105 CC = AArch64CC::NE;
1106 break;
1107 case AArch64::CBNZX:
1108 Is64Bit = true;
1109 CC = AArch64CC::NE;
1110 break;
1111 }
1112 Register SrcReg = Cond[2].getReg();
1113 if (Is64Bit) {
1114 // cmp reg, #0 is actually subs xzr, reg, #0.
1115 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
1116 BuildMI(MBB, I, DL, get(AArch64::SUBSXri), AArch64::XZR)
1117 .addReg(SrcReg)
1118 .addImm(0)
1119 .addImm(0);
1120 } else {
1121 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
1122 BuildMI(MBB, I, DL, get(AArch64::SUBSWri), AArch64::WZR)
1123 .addReg(SrcReg)
1124 .addImm(0)
1125 .addImm(0);
1126 }
1127 break;
1128 }
1129 case 4: { // tbz/tbnz
1130 // We must insert a tst instruction.
1131 switch (Cond[1].getImm()) {
1132 default:
1133 llvm_unreachable("Unknown branch opcode in Cond");
1134 case AArch64::TBZW:
1135 case AArch64::TBZX:
1136 CC = AArch64CC::EQ;
1137 break;
1138 case AArch64::TBNZW:
1139 case AArch64::TBNZX:
1140 CC = AArch64CC::NE;
1141 break;
1142 }
1143 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
1144 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
1145 BuildMI(MBB, I, DL, get(AArch64::ANDSWri), AArch64::WZR)
1146 .addReg(Cond[2].getReg())
1147 .addImm(
1149 else
1150 BuildMI(MBB, I, DL, get(AArch64::ANDSXri), AArch64::XZR)
1151 .addReg(Cond[2].getReg())
1152 .addImm(
1154 break;
1155 }
1156 case 5: { // cb
1157 // We must insert a cmp, that is a subs
1158 // 0 1 2 3 4
1159 // Cond is { -1, Opcode, CC, Op0, Op1 }
1160
1161 unsigned SubsOpc, SubsDestReg;
1162 bool IsImm = false;
1163 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1164 switch (Cond[1].getImm()) {
1165 default:
1166 llvm_unreachable("Unknown branch opcode in Cond");
1167 case AArch64::CBWPri:
1168 SubsOpc = AArch64::SUBSWri;
1169 SubsDestReg = AArch64::WZR;
1170 IsImm = true;
1171 break;
1172 case AArch64::CBXPri:
1173 SubsOpc = AArch64::SUBSXri;
1174 SubsDestReg = AArch64::XZR;
1175 IsImm = true;
1176 break;
1177 case AArch64::CBWPrr:
1178 SubsOpc = AArch64::SUBSWrr;
1179 SubsDestReg = AArch64::WZR;
1180 IsImm = false;
1181 break;
1182 case AArch64::CBXPrr:
1183 SubsOpc = AArch64::SUBSXrr;
1184 SubsDestReg = AArch64::XZR;
1185 IsImm = false;
1186 break;
1187 }
1188
1189 if (IsImm) {
1190 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
1191 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1192 .addReg(Cond[3].getReg())
1193 .addImm(Cond[4].getImm())
1194 .addImm(0);
1195 } else {
1196 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
1197 MRI.constrainRegClass(Cond[4].getReg(), getRegClass(get(SubsOpc), 2));
1198 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1199 .addReg(Cond[3].getReg())
1200 .addReg(Cond[4].getReg());
1201 }
1202 } break;
1203 case 7: { // cb[b,h]
1204 // We must insert a cmp, that is a subs, but also zero- or sign-extensions
1205 // that have been folded. For the first operand we codegen an explicit
1206 // extension, for the second operand we fold the extension into cmp.
1207 // 0 1 2 3 4 5 6
1208 // Cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
1209
1210 // We need a new register for the now explicitly extended register
1211 Register Reg = Cond[4].getReg();
1213 unsigned ExtOpc;
1214 unsigned ExtBits;
1215 AArch64_AM::ShiftExtendType ExtendType =
1217 switch (ExtendType) {
1218 default:
1219 llvm_unreachable("Unknown shift-extend for CB instruction");
1220 case AArch64_AM::SXTB:
1221 assert(
1222 Cond[1].getImm() == AArch64::CBBAssertExt &&
1223 "Unexpected compare-and-branch instruction for SXTB shift-extend");
1224 ExtOpc = AArch64::SBFMWri;
1225 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1226 break;
1227 case AArch64_AM::SXTH:
1228 assert(
1229 Cond[1].getImm() == AArch64::CBHAssertExt &&
1230 "Unexpected compare-and-branch instruction for SXTH shift-extend");
1231 ExtOpc = AArch64::SBFMWri;
1232 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1233 break;
1234 case AArch64_AM::UXTB:
1235 assert(
1236 Cond[1].getImm() == AArch64::CBBAssertExt &&
1237 "Unexpected compare-and-branch instruction for UXTB shift-extend");
1238 ExtOpc = AArch64::ANDWri;
1239 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1240 break;
1241 case AArch64_AM::UXTH:
1242 assert(
1243 Cond[1].getImm() == AArch64::CBHAssertExt &&
1244 "Unexpected compare-and-branch instruction for UXTH shift-extend");
1245 ExtOpc = AArch64::ANDWri;
1246 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1247 break;
1248 }
1249
1250 // Build the explicit extension of the first operand
1251 Reg = MRI.createVirtualRegister(&AArch64::GPR32spRegClass);
1253 BuildMI(MBB, I, DL, get(ExtOpc), Reg).addReg(Cond[4].getReg());
1254 if (ExtOpc != AArch64::ANDWri)
1255 MBBI.addImm(0);
1256 MBBI.addImm(ExtBits);
1257 }
1258
1259 // Now, subs with an extended second operand
1261 AArch64_AM::ShiftExtendType ExtendType =
1263 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1264 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1265 BuildMI(MBB, I, DL, get(AArch64::SUBSWrx), AArch64::WZR)
1266 .addReg(Cond[3].getReg())
1267 .addReg(Reg)
1268 .addImm(AArch64_AM::getArithExtendImm(ExtendType, 0));
1269 } // If no extension is needed, just a regular subs
1270 else {
1271 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1272 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1273 BuildMI(MBB, I, DL, get(AArch64::SUBSWrr), AArch64::WZR)
1274 .addReg(Cond[3].getReg())
1275 .addReg(Reg);
1276 }
1277
1278 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1279 } break;
1280 }
1281
1282 unsigned Opc = 0;
1283 const TargetRegisterClass *RC = nullptr;
1284 bool TryFold = false;
1285 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
1286 RC = &AArch64::GPR64RegClass;
1287 Opc = AArch64::CSELXr;
1288 TryFold = true;
1289 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
1290 RC = &AArch64::GPR32RegClass;
1291 Opc = AArch64::CSELWr;
1292 TryFold = true;
1293 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
1294 RC = &AArch64::FPR64RegClass;
1295 Opc = AArch64::FCSELDrrr;
1296 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
1297 RC = &AArch64::FPR32RegClass;
1298 Opc = AArch64::FCSELSrrr;
1299 }
1300 assert(RC && "Unsupported regclass");
1301
1302 // Try folding simple instructions into the csel.
1303 if (TryFold) {
1304 unsigned NewReg = 0;
1305 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewReg);
1306 if (FoldedOpc) {
1307 // The folded opcodes csinc, csinc and csneg apply the operation to
1308 // FalseReg, so we need to invert the condition.
1310 TrueReg = FalseReg;
1311 } else
1312 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewReg);
1313
1314 // Fold the operation. Leave any dead instructions for DCE to clean up.
1315 if (FoldedOpc) {
1316 FalseReg = NewReg;
1317 Opc = FoldedOpc;
1318 // Extend the live range of NewReg.
1319 MRI.clearKillFlags(NewReg);
1320 }
1321 }
1322
1323 // Pull all virtual register into the appropriate class.
1324 MRI.constrainRegClass(TrueReg, RC);
1325 // FalseReg might be WZR or XZR if the folded operand is a literal 1.
1326 assert(
1327 (FalseReg.isVirtual() || FalseReg == AArch64::WZR ||
1328 FalseReg == AArch64::XZR) &&
1329 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1330 if (FalseReg.isVirtual())
1331 MRI.constrainRegClass(FalseReg, RC);
1332
1333 // Insert the csel.
1334 BuildMI(MBB, I, DL, get(Opc), DstReg)
1335 .addReg(TrueReg)
1336 .addReg(FalseReg)
1337 .addImm(CC);
1338}
1339
1340// Return true if Imm can be loaded into a register by a "cheap" sequence of
1341// instructions. For now, "cheap" means at most two instructions.
1342static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
1343 if (BitSize == 32)
1344 return true;
1345
1346 assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
1347 uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
1349 AArch64_IMM::expandMOVImm(Imm, BitSize, Is);
1350
1351 return Is.size() <= 2;
1352}
1353
1354// Check if a COPY instruction is cheap.
1355static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
1356 assert(MI.isCopy() && "Expected COPY instruction");
1357 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1358
1359 // Cross-bank copies (e.g., between GPR and FPR) are expensive on AArch64,
1360 // typically requiring an FMOV instruction with a 2-6 cycle latency.
1361 auto GetRegClass = [&](Register Reg) -> const TargetRegisterClass * {
1362 if (Reg.isVirtual())
1363 return MRI.getRegClass(Reg);
1364 if (Reg.isPhysical())
1365 return RI.getMinimalPhysRegClass(Reg);
1366 return nullptr;
1367 };
1368 const TargetRegisterClass *DstRC = GetRegClass(MI.getOperand(0).getReg());
1369 const TargetRegisterClass *SrcRC = GetRegClass(MI.getOperand(1).getReg());
1370 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1371 return false;
1372
1373 return MI.isAsCheapAsAMove();
1374}
1375
1376// FIXME: this implementation should be micro-architecture dependent, so a
1377// micro-architecture target hook should be introduced here in future.
1379 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1380 if (isExynosCheapAsMove(MI))
1381 return true;
1382 return MI.isAsCheapAsAMove();
1383 }
1384
1385 switch (MI.getOpcode()) {
1386 default:
1387 return MI.isAsCheapAsAMove();
1388
1389 case TargetOpcode::COPY:
1390 return isCheapCopy(MI, RI);
1391
1392 case AArch64::ADDWrs:
1393 case AArch64::ADDXrs:
1394 case AArch64::SUBWrs:
1395 case AArch64::SUBXrs:
1396 return Subtarget.hasALULSLFast() && MI.getOperand(3).getImm() <= 4;
1397
1398 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
1399 // ORRXri, it is as cheap as MOV.
1400 // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
1401 case AArch64::MOVi32imm:
1402 return isCheapImmediate(MI, 32);
1403 case AArch64::MOVi64imm:
1404 return isCheapImmediate(MI, 64);
1405 }
1406}
1407
1408bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) {
1409 switch (MI.getOpcode()) {
1410 default:
1411 return false;
1412
1413 case AArch64::ADDWrs:
1414 case AArch64::ADDXrs:
1415 case AArch64::ADDSWrs:
1416 case AArch64::ADDSXrs: {
1417 unsigned Imm = MI.getOperand(3).getImm();
1418 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1419 if (ShiftVal == 0)
1420 return true;
1421 return AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL && ShiftVal <= 5;
1422 }
1423
1424 case AArch64::ADDWrx:
1425 case AArch64::ADDXrx:
1426 case AArch64::ADDXrx64:
1427 case AArch64::ADDSWrx:
1428 case AArch64::ADDSXrx:
1429 case AArch64::ADDSXrx64: {
1430 unsigned Imm = MI.getOperand(3).getImm();
1432 default:
1433 return false;
1434 case AArch64_AM::UXTB:
1435 case AArch64_AM::UXTH:
1436 case AArch64_AM::UXTW:
1437 case AArch64_AM::UXTX:
1439 }
1440 }
1441
1442 case AArch64::SUBWrs:
1443 case AArch64::SUBSWrs: {
1444 unsigned Imm = MI.getOperand(3).getImm();
1445 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1446 return ShiftVal == 0 ||
1447 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 31);
1448 }
1449
1450 case AArch64::SUBXrs:
1451 case AArch64::SUBSXrs: {
1452 unsigned Imm = MI.getOperand(3).getImm();
1453 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1454 return ShiftVal == 0 ||
1455 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 63);
1456 }
1457
1458 case AArch64::SUBWrx:
1459 case AArch64::SUBXrx:
1460 case AArch64::SUBXrx64:
1461 case AArch64::SUBSWrx:
1462 case AArch64::SUBSXrx:
1463 case AArch64::SUBSXrx64: {
1464 unsigned Imm = MI.getOperand(3).getImm();
1466 default:
1467 return false;
1468 case AArch64_AM::UXTB:
1469 case AArch64_AM::UXTH:
1470 case AArch64_AM::UXTW:
1471 case AArch64_AM::UXTX:
1473 }
1474 }
1475
1476 case AArch64::LDRBBroW:
1477 case AArch64::LDRBBroX:
1478 case AArch64::LDRBroW:
1479 case AArch64::LDRBroX:
1480 case AArch64::LDRDroW:
1481 case AArch64::LDRDroX:
1482 case AArch64::LDRHHroW:
1483 case AArch64::LDRHHroX:
1484 case AArch64::LDRHroW:
1485 case AArch64::LDRHroX:
1486 case AArch64::LDRQroW:
1487 case AArch64::LDRQroX:
1488 case AArch64::LDRSBWroW:
1489 case AArch64::LDRSBWroX:
1490 case AArch64::LDRSBXroW:
1491 case AArch64::LDRSBXroX:
1492 case AArch64::LDRSHWroW:
1493 case AArch64::LDRSHWroX:
1494 case AArch64::LDRSHXroW:
1495 case AArch64::LDRSHXroX:
1496 case AArch64::LDRSWroW:
1497 case AArch64::LDRSWroX:
1498 case AArch64::LDRSroW:
1499 case AArch64::LDRSroX:
1500 case AArch64::LDRWroW:
1501 case AArch64::LDRWroX:
1502 case AArch64::LDRXroW:
1503 case AArch64::LDRXroX:
1504 case AArch64::PRFMroW:
1505 case AArch64::PRFMroX:
1506 case AArch64::STRBBroW:
1507 case AArch64::STRBBroX:
1508 case AArch64::STRBroW:
1509 case AArch64::STRBroX:
1510 case AArch64::STRDroW:
1511 case AArch64::STRDroX:
1512 case AArch64::STRHHroW:
1513 case AArch64::STRHHroX:
1514 case AArch64::STRHroW:
1515 case AArch64::STRHroX:
1516 case AArch64::STRQroW:
1517 case AArch64::STRQroX:
1518 case AArch64::STRSroW:
1519 case AArch64::STRSroX:
1520 case AArch64::STRWroW:
1521 case AArch64::STRWroX:
1522 case AArch64::STRXroW:
1523 case AArch64::STRXroX: {
1524 unsigned IsSigned = MI.getOperand(3).getImm();
1525 return !IsSigned;
1526 }
1527 }
1528}
1529
1530bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
1531 unsigned Opc = MI.getOpcode();
1532 switch (Opc) {
1533 default:
1534 return false;
1535 case AArch64::SEH_StackAlloc:
1536 case AArch64::SEH_SaveFPLR:
1537 case AArch64::SEH_SaveFPLR_X:
1538 case AArch64::SEH_SaveReg:
1539 case AArch64::SEH_SaveReg_X:
1540 case AArch64::SEH_SaveRegP:
1541 case AArch64::SEH_SaveRegP_X:
1542 case AArch64::SEH_SaveFReg:
1543 case AArch64::SEH_SaveFReg_X:
1544 case AArch64::SEH_SaveFRegP:
1545 case AArch64::SEH_SaveFRegP_X:
1546 case AArch64::SEH_SetFP:
1547 case AArch64::SEH_AddFP:
1548 case AArch64::SEH_Nop:
1549 case AArch64::SEH_PrologEnd:
1550 case AArch64::SEH_EpilogStart:
1551 case AArch64::SEH_EpilogEnd:
1552 case AArch64::SEH_PACSignLR:
1553 case AArch64::SEH_SaveAnyRegI:
1554 case AArch64::SEH_SaveAnyRegIP:
1555 case AArch64::SEH_SaveAnyRegQP:
1556 case AArch64::SEH_SaveAnyRegQPX:
1557 case AArch64::SEH_AllocZ:
1558 case AArch64::SEH_SaveZReg:
1559 case AArch64::SEH_SavePReg:
1560 return true;
1561 }
1562}
1563
1565 Register &SrcReg, Register &DstReg,
1566 unsigned &SubIdx) const {
1567 switch (MI.getOpcode()) {
1568 default:
1569 return false;
1570 case AArch64::SBFMXri: // aka sxtw
1571 case AArch64::UBFMXri: // aka uxtw
1572 // Check for the 32 -> 64 bit extension case, these instructions can do
1573 // much more.
1574 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
1575 return false;
1576 // This is a signed or unsigned 32 -> 64 bit extension.
1577 SrcReg = MI.getOperand(1).getReg();
1578 DstReg = MI.getOperand(0).getReg();
1579 SubIdx = AArch64::sub_32;
1580 return true;
1581 }
1582}
1583
1585 const MachineInstr &MIa, const MachineInstr &MIb) const {
1587 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
1588 int64_t OffsetA = 0, OffsetB = 0;
1589 TypeSize WidthA(0, false), WidthB(0, false);
1590 bool OffsetAIsScalable = false, OffsetBIsScalable = false;
1591
1592 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
1593 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
1594
1597 return false;
1598
1599 // Retrieve the base, offset from the base and width. Width
1600 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
1601 // base are identical, and the offset of a lower memory access +
1602 // the width doesn't overlap the offset of a higher memory access,
1603 // then the memory accesses are different.
1604 // If OffsetAIsScalable and OffsetBIsScalable are both true, they
1605 // are assumed to have the same scale (vscale).
1606 if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, OffsetAIsScalable,
1607 WidthA, TRI) &&
1608 getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, OffsetBIsScalable,
1609 WidthB, TRI)) {
1610 if (BaseOpA->isIdenticalTo(*BaseOpB) &&
1611 OffsetAIsScalable == OffsetBIsScalable) {
1612 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1613 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1614 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1615 if (LowWidth.isScalable() == OffsetAIsScalable &&
1616 LowOffset + (int)LowWidth.getKnownMinValue() <= HighOffset)
1617 return true;
1618 }
1619 }
1620 return false;
1621}
1622
1624 const MachineBasicBlock *MBB,
1625 const MachineFunction &MF) const {
1627 return true;
1628
1629 // Do not move an instruction that can be recognized as a branch target.
1630 if (hasBTISemantics(MI))
1631 return true;
1632
1633 switch (MI.getOpcode()) {
1634 case AArch64::HINT:
1635 // CSDB hints are scheduling barriers.
1636 if (MI.getOperand(0).getImm() == 0x14)
1637 return true;
1638 break;
1639 case AArch64::DSB:
1640 case AArch64::ISB:
1641 // DSB and ISB also are scheduling barriers.
1642 return true;
1643 case AArch64::MSRpstatesvcrImm1:
1644 // SMSTART and SMSTOP are also scheduling barriers.
1645 return true;
1646 default:;
1647 }
1648 if (isSEHInstruction(MI))
1649 return true;
1650 auto Next = std::next(MI.getIterator());
1651 return Next != MBB->end() && Next->isCFIInstruction();
1652}
1653
1654/// analyzeCompare - For a comparison instruction, return the source registers
1655/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
1656/// Return true if the comparison instruction can be analyzed.
1658 Register &SrcReg2, int64_t &CmpMask,
1659 int64_t &CmpValue) const {
1660 // The first operand can be a frame index where we'd normally expect a
1661 // register.
1662 // FIXME: Pass subregisters out of analyzeCompare
1663 assert(MI.getNumOperands() >= 2 && "All AArch64 cmps should have 2 operands");
1664 if (!MI.getOperand(1).isReg() || MI.getOperand(1).getSubReg())
1665 return false;
1666
1667 switch (MI.getOpcode()) {
1668 default:
1669 break;
1670 case AArch64::PTEST_PP:
1671 case AArch64::PTEST_PP_ANY:
1672 case AArch64::PTEST_PP_FIRST:
1673 SrcReg = MI.getOperand(0).getReg();
1674 SrcReg2 = MI.getOperand(1).getReg();
1675 if (MI.getOperand(2).getSubReg())
1676 return false;
1677
1678 // Not sure about the mask and value for now...
1679 CmpMask = ~0;
1680 CmpValue = 0;
1681 return true;
1682 case AArch64::SUBSWrr:
1683 case AArch64::SUBSWrs:
1684 case AArch64::SUBSWrx:
1685 case AArch64::SUBSXrr:
1686 case AArch64::SUBSXrs:
1687 case AArch64::SUBSXrx:
1688 case AArch64::ADDSWrr:
1689 case AArch64::ADDSWrs:
1690 case AArch64::ADDSWrx:
1691 case AArch64::ADDSXrr:
1692 case AArch64::ADDSXrs:
1693 case AArch64::ADDSXrx:
1694 // Replace SUBSWrr with SUBWrr if NZCV is not used.
1695 SrcReg = MI.getOperand(1).getReg();
1696 SrcReg2 = MI.getOperand(2).getReg();
1697
1698 // FIXME: Pass subregisters out of analyzeCompare
1699 if (MI.getOperand(2).getSubReg())
1700 return false;
1701
1702 CmpMask = ~0;
1703 CmpValue = 0;
1704 return true;
1705 case AArch64::SUBSWri:
1706 case AArch64::ADDSWri:
1707 case AArch64::SUBSXri:
1708 case AArch64::ADDSXri:
1709 SrcReg = MI.getOperand(1).getReg();
1710 SrcReg2 = 0;
1711 CmpMask = ~0;
1712 CmpValue = MI.getOperand(2).getImm();
1713 return true;
1714 case AArch64::ANDSWri:
1715 case AArch64::ANDSXri:
1716 // ANDS does not use the same encoding scheme as the others xxxS
1717 // instructions.
1718 SrcReg = MI.getOperand(1).getReg();
1719 SrcReg2 = 0;
1720 CmpMask = ~0;
1722 MI.getOperand(2).getImm(),
1723 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1724 return true;
1725 }
1726
1727 return false;
1728}
1729
1731 MachineBasicBlock *MBB = Instr.getParent();
1732 assert(MBB && "Can't get MachineBasicBlock here");
1733 MachineFunction *MF = MBB->getParent();
1734 assert(MF && "Can't get MachineFunction here");
1737 MachineRegisterInfo *MRI = &MF->getRegInfo();
1738
1739 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1740 ++OpIdx) {
1741 MachineOperand &MO = Instr.getOperand(OpIdx);
1742 const TargetRegisterClass *OpRegCstraints =
1743 Instr.getRegClassConstraint(OpIdx, TII, TRI);
1744
1745 // If there's no constraint, there's nothing to do.
1746 if (!OpRegCstraints)
1747 continue;
1748 // If the operand is a frame index, there's nothing to do here.
1749 // A frame index operand will resolve correctly during PEI.
1750 if (MO.isFI())
1751 continue;
1752
1753 assert(MO.isReg() &&
1754 "Operand has register constraints without being a register!");
1755
1756 Register Reg = MO.getReg();
1757 if (Reg.isPhysical()) {
1758 if (!OpRegCstraints->contains(Reg))
1759 return false;
1760 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
1761 !MRI->constrainRegClass(Reg, OpRegCstraints))
1762 return false;
1763 }
1764
1765 return true;
1766}
1767
1768/// Return the opcode that does not set flags when possible - otherwise
1769/// return the original opcode. The caller is responsible to do the actual
1770/// substitution and legality checking.
1772 // Don't convert all compare instructions, because for some the zero register
1773 // encoding becomes the sp register.
1774 bool MIDefinesZeroReg = false;
1775 if (MI.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
1776 MI.definesRegister(AArch64::XZR, /*TRI=*/nullptr))
1777 MIDefinesZeroReg = true;
1778
1779 switch (MI.getOpcode()) {
1780 default:
1781 return MI.getOpcode();
1782 case AArch64::ADDSWrr:
1783 return AArch64::ADDWrr;
1784 case AArch64::ADDSWri:
1785 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1786 case AArch64::ADDSWrs:
1787 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1788 case AArch64::ADDSWrx:
1789 return AArch64::ADDWrx;
1790 case AArch64::ADDSXrr:
1791 return AArch64::ADDXrr;
1792 case AArch64::ADDSXri:
1793 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1794 case AArch64::ADDSXrs:
1795 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1796 case AArch64::ADDSXrx:
1797 return AArch64::ADDXrx;
1798 case AArch64::SUBSWrr:
1799 return AArch64::SUBWrr;
1800 case AArch64::SUBSWri:
1801 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1802 case AArch64::SUBSWrs:
1803 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1804 case AArch64::SUBSWrx:
1805 return AArch64::SUBWrx;
1806 case AArch64::SUBSXrr:
1807 return AArch64::SUBXrr;
1808 case AArch64::SUBSXri:
1809 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1810 case AArch64::SUBSXrs:
1811 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1812 case AArch64::SUBSXrx:
1813 return AArch64::SUBXrx;
1814 }
1815}
1816
1817enum AccessKind { AK_Write = 0x01, AK_Read = 0x10, AK_All = 0x11 };
1818
1819/// True when condition flags are accessed (either by writing or reading)
1820/// on the instruction trace starting at From and ending at To.
1821///
1822/// Note: If From and To are from different blocks it's assumed CC are accessed
1823/// on the path.
1826 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
1827 // Early exit if To is at the beginning of the BB.
1828 if (To == To->getParent()->begin())
1829 return true;
1830
1831 // Check whether the instructions are in the same basic block
1832 // If not, assume the condition flags might get modified somewhere.
1833 if (To->getParent() != From->getParent())
1834 return true;
1835
1836 // From must be above To.
1837 assert(std::any_of(
1838 ++To.getReverse(), To->getParent()->rend(),
1839 [From](MachineInstr &MI) { return MI.getIterator() == From; }));
1840
1841 // We iterate backward starting at \p To until we hit \p From.
1842 for (const MachineInstr &Instr :
1844 if (((AccessToCheck & AK_Write) &&
1845 Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
1846 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
1847 return true;
1848 }
1849 return false;
1850}
1851
1852std::optional<unsigned>
1853AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1854 MachineInstr *Pred,
1855 const MachineRegisterInfo *MRI) const {
1856 unsigned MaskOpcode = Mask->getOpcode();
1857 unsigned PredOpcode = Pred->getOpcode();
1858 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1859 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1860
1861 if (PredIsWhileLike) {
1862 // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1863 // instruction and the condition is "any" since WHILcc does an implicit
1864 // PTEST(ALL, PG) check and PG is always a subset of ALL.
1865 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1866 return PredOpcode;
1867
1868 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1869 // redundant since WHILE performs an implicit PTEST with an all active
1870 // mask.
1871 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1872 getElementSizeForOpcode(MaskOpcode) ==
1873 getElementSizeForOpcode(PredOpcode))
1874 return PredOpcode;
1875
1876 // For PTEST_FIRST(PTRUE_ALL, WHILE), the PTEST_FIRST is redundant since
1877 // WHILEcc performs an implicit PTEST with an all active mask, setting
1878 // the N flag as the PTEST_FIRST would.
1879 if (PTest->getOpcode() == AArch64::PTEST_PP_FIRST &&
1880 isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31)
1881 return PredOpcode;
1882
1883 return {};
1884 }
1885
1886 if (PredIsPTestLike) {
1887 // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1888 // instruction that sets the flags as PTEST would and the condition is
1889 // "any" since PG is always a subset of the governing predicate of the
1890 // ptest-like instruction.
1891 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1892 return PredOpcode;
1893
1894 auto PTestLikeMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1895
1896 // If the PTEST like instruction's general predicate is not `Mask`, attempt
1897 // to look through a copy and try again. This is because some instructions
1898 // take a predicate whose register class is a subset of its result class.
1899 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1900 PTestLikeMask->getOperand(1).getReg().isVirtual())
1901 PTestLikeMask =
1902 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1903
1904 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1905 // the element size matches and either the PTEST_LIKE instruction uses
1906 // the same all active mask or the condition is "any".
1907 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1908 getElementSizeForOpcode(MaskOpcode) ==
1909 getElementSizeForOpcode(PredOpcode)) {
1910 if (Mask == PTestLikeMask || PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1911 return PredOpcode;
1912 }
1913
1914 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
1915 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
1916 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
1917 // compare that also support 16/32/64-bit predicates, the implicit PTEST
1918 // performed by the compare could consider fewer lanes for these element
1919 // sizes.
1920 //
1921 // For example, consider
1922 //
1923 // ptrue p0.b ; P0=1111-1111-1111-1111
1924 // index z0.s, #0, #1 ; Z0=<0,1,2,3>
1925 // index z1.s, #1, #1 ; Z1=<1,2,3,4>
1926 // cmphi p1.s, p0/z, z1.s, z0.s ; P1=0001-0001-0001-0001
1927 // ; ^ last active
1928 // ptest p0, p1.b ; P1=0001-0001-0001-0001
1929 // ; ^ last active
1930 //
1931 // where the compare generates a canonical all active 32-bit predicate
1932 // (equivalent to 'ptrue p1.s, all'). The implicit PTEST sets the last
1933 // active flag, whereas the PTEST instruction with the same mask doesn't.
1934 // For PTEST_ANY this doesn't apply as the flags in this case would be
1935 // identical regardless of element size.
1936 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1937 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1938 PTest->getOpcode() == AArch64::PTEST_PP_ANY))
1939 return PredOpcode;
1940
1941 return {};
1942 }
1943
1944 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1945 // opcode so the PTEST becomes redundant.
1946 switch (PredOpcode) {
1947 case AArch64::AND_PPzPP:
1948 case AArch64::BIC_PPzPP:
1949 case AArch64::EOR_PPzPP:
1950 case AArch64::NAND_PPzPP:
1951 case AArch64::NOR_PPzPP:
1952 case AArch64::ORN_PPzPP:
1953 case AArch64::ORR_PPzPP:
1954 case AArch64::BRKA_PPzP:
1955 case AArch64::BRKPA_PPzPP:
1956 case AArch64::BRKB_PPzP:
1957 case AArch64::BRKPB_PPzPP:
1958 case AArch64::RDFFR_PPz: {
1959 // Check to see if our mask is the same. If not the resulting flag bits
1960 // may be different and we can't remove the ptest.
1961 auto *PredMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1962 if (Mask != PredMask)
1963 return {};
1964 break;
1965 }
1966 case AArch64::BRKN_PPzP: {
1967 // BRKN uses an all active implicit mask to set flags unlike the other
1968 // flag-setting instructions.
1969 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1970 if ((MaskOpcode != AArch64::PTRUE_B) ||
1971 (Mask->getOperand(1).getImm() != 31))
1972 return {};
1973 break;
1974 }
1975 case AArch64::PTRUE_B:
1976 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1977 break;
1978 default:
1979 // Bail out if we don't recognize the input
1980 return {};
1981 }
1982
1983 return convertToFlagSettingOpc(PredOpcode);
1984}
1985
1986/// optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
1987/// operation which could set the flags in an identical manner
1988bool AArch64InstrInfo::optimizePTestInstr(
1989 MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
1990 const MachineRegisterInfo *MRI) const {
1991 auto *Mask = MRI->getUniqueVRegDef(MaskReg);
1992 auto *Pred = MRI->getUniqueVRegDef(PredReg);
1993
1994 if (Pred->isCopy() && PTest->getOpcode() == AArch64::PTEST_PP_FIRST) {
1995 // Instructions which return a multi-vector (e.g. WHILECC_x2) require copies
1996 // before the branch to extract each subregister.
1997 auto Op = Pred->getOperand(1);
1998 if (Op.isReg() && Op.getReg().isVirtual() &&
1999 Op.getSubReg() == AArch64::psub0)
2000 Pred = MRI->getUniqueVRegDef(Op.getReg());
2001 }
2002
2003 unsigned PredOpcode = Pred->getOpcode();
2004 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
2005 if (!NewOp)
2006 return false;
2007
2008 const TargetRegisterInfo *TRI = &getRegisterInfo();
2009
2010 // If another instruction between Pred and PTest accesses flags, don't remove
2011 // the ptest or update the earlier instruction to modify them.
2012 if (areCFlagsAccessedBetweenInstrs(Pred, PTest, TRI))
2013 return false;
2014
2015 // If we pass all the checks, it's safe to remove the PTEST and use the flags
2016 // as they are prior to PTEST. Sometimes this requires the tested PTEST
2017 // operand to be replaced with an equivalent instruction that also sets the
2018 // flags.
2019 PTest->eraseFromParent();
2020 if (*NewOp != PredOpcode) {
2021 Pred->setDesc(get(*NewOp));
2022 bool succeeded = UpdateOperandRegClass(*Pred);
2023 (void)succeeded;
2024 assert(succeeded && "Operands have incompatible register classes!");
2025 Pred->addRegisterDefined(AArch64::NZCV, TRI);
2026 }
2027
2028 // Ensure that the flags def is live.
2029 if (Pred->registerDefIsDead(AArch64::NZCV, TRI)) {
2030 unsigned i = 0, e = Pred->getNumOperands();
2031 for (; i != e; ++i) {
2032 MachineOperand &MO = Pred->getOperand(i);
2033 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::NZCV) {
2034 MO.setIsDead(false);
2035 break;
2036 }
2037 }
2038 }
2039 return true;
2040}
2041
2042/// Try to optimize a compare instruction. A compare instruction is an
2043/// instruction which produces AArch64::NZCV. It can be truly compare
2044/// instruction
2045/// when there are no uses of its destination register.
2046///
2047/// The following steps are tried in order:
2048/// 1. Convert CmpInstr into an unconditional version.
2049/// 2. Remove CmpInstr if above there is an instruction producing a needed
2050/// condition code or an instruction which can be converted into such an
2051/// instruction.
2052/// Only comparison with zero is supported.
2054 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
2055 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
2056 assert(CmpInstr.getParent());
2057 assert(MRI);
2058
2059 // Replace SUBSWrr with SUBWrr if NZCV is not used.
2060 int DeadNZCVIdx =
2061 CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
2062 if (DeadNZCVIdx != -1) {
2063 if (CmpInstr.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
2064 CmpInstr.definesRegister(AArch64::XZR, /*TRI=*/nullptr)) {
2065 CmpInstr.eraseFromParent();
2066 return true;
2067 }
2068 unsigned Opc = CmpInstr.getOpcode();
2069 unsigned NewOpc = convertToNonFlagSettingOpc(CmpInstr);
2070 if (NewOpc == Opc)
2071 return false;
2072 const MCInstrDesc &MCID = get(NewOpc);
2073 CmpInstr.setDesc(MCID);
2074 CmpInstr.removeOperand(DeadNZCVIdx);
2075 bool succeeded = UpdateOperandRegClass(CmpInstr);
2076 (void)succeeded;
2077 assert(succeeded && "Some operands reg class are incompatible!");
2078 return true;
2079 }
2080
2081 if (CmpInstr.getOpcode() == AArch64::PTEST_PP ||
2082 CmpInstr.getOpcode() == AArch64::PTEST_PP_ANY ||
2083 CmpInstr.getOpcode() == AArch64::PTEST_PP_FIRST)
2084 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2085
2086 if (SrcReg2 != 0)
2087 return false;
2088
2089 // CmpInstr is a Compare instruction if destination register is not used.
2090 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
2091 return false;
2092
2093 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2094 return true;
2095 return (CmpValue == 0 || CmpValue == 1) &&
2096 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2097}
2098
2099/// Get opcode of S version of Instr.
2100/// If Instr is S version its opcode is returned.
2101/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
2102/// or we are not interested in it.
2103static unsigned sForm(MachineInstr &Instr) {
2104 switch (Instr.getOpcode()) {
2105 default:
2106 return AArch64::INSTRUCTION_LIST_END;
2107
2108 case AArch64::ADDSWrr:
2109 case AArch64::ADDSWri:
2110 case AArch64::ADDSXrr:
2111 case AArch64::ADDSXri:
2112 case AArch64::ADDSWrx:
2113 case AArch64::ADDSXrx:
2114 case AArch64::ADDSWrs:
2115 case AArch64::ADDSXrs:
2116 case AArch64::SUBSWrr:
2117 case AArch64::SUBSWri:
2118 case AArch64::SUBSWrx:
2119 case AArch64::SUBSWrs:
2120 case AArch64::SUBSXrr:
2121 case AArch64::SUBSXri:
2122 case AArch64::SUBSXrx:
2123 case AArch64::SUBSXrs:
2124 case AArch64::ANDSWri:
2125 case AArch64::ANDSWrr:
2126 case AArch64::ANDSWrs:
2127 case AArch64::ANDSXri:
2128 case AArch64::ANDSXrr:
2129 case AArch64::ANDSXrs:
2130 case AArch64::BICSWrr:
2131 case AArch64::BICSXrr:
2132 case AArch64::BICSWrs:
2133 case AArch64::BICSXrs:
2134 case AArch64::ADCSWr:
2135 case AArch64::ADCSXr:
2136 case AArch64::SBCSWr:
2137 case AArch64::SBCSXr:
2138 return Instr.getOpcode();
2139
2140 case AArch64::ADDWrr:
2141 return AArch64::ADDSWrr;
2142 case AArch64::ADDWri:
2143 return AArch64::ADDSWri;
2144 case AArch64::ADDXrr:
2145 return AArch64::ADDSXrr;
2146 case AArch64::ADDXri:
2147 return AArch64::ADDSXri;
2148 case AArch64::ADDWrx:
2149 return AArch64::ADDSWrx;
2150 case AArch64::ADDXrx:
2151 return AArch64::ADDSXrx;
2152 case AArch64::ADDWrs:
2153 return AArch64::ADDSWrs;
2154 case AArch64::ADDXrs:
2155 return AArch64::ADDSXrs;
2156 case AArch64::ADCWr:
2157 return AArch64::ADCSWr;
2158 case AArch64::ADCXr:
2159 return AArch64::ADCSXr;
2160 case AArch64::SUBWrr:
2161 return AArch64::SUBSWrr;
2162 case AArch64::SUBWri:
2163 return AArch64::SUBSWri;
2164 case AArch64::SUBXrr:
2165 return AArch64::SUBSXrr;
2166 case AArch64::SUBXri:
2167 return AArch64::SUBSXri;
2168 case AArch64::SUBWrx:
2169 return AArch64::SUBSWrx;
2170 case AArch64::SUBXrx:
2171 return AArch64::SUBSXrx;
2172 case AArch64::SUBWrs:
2173 return AArch64::SUBSWrs;
2174 case AArch64::SUBXrs:
2175 return AArch64::SUBSXrs;
2176 case AArch64::SBCWr:
2177 return AArch64::SBCSWr;
2178 case AArch64::SBCXr:
2179 return AArch64::SBCSXr;
2180 case AArch64::ANDWri:
2181 return AArch64::ANDSWri;
2182 case AArch64::ANDXri:
2183 return AArch64::ANDSXri;
2184 case AArch64::ANDWrr:
2185 return AArch64::ANDSWrr;
2186 case AArch64::ANDWrs:
2187 return AArch64::ANDSWrs;
2188 case AArch64::ANDXrr:
2189 return AArch64::ANDSXrr;
2190 case AArch64::ANDXrs:
2191 return AArch64::ANDSXrs;
2192 case AArch64::BICWrr:
2193 return AArch64::BICSWrr;
2194 case AArch64::BICXrr:
2195 return AArch64::BICSXrr;
2196 case AArch64::BICWrs:
2197 return AArch64::BICSWrs;
2198 case AArch64::BICXrs:
2199 return AArch64::BICSXrs;
2200 }
2201}
2202
2203/// Check if AArch64::NZCV should be alive in successors of MBB.
2205 for (auto *BB : MBB->successors())
2206 if (BB->isLiveIn(AArch64::NZCV))
2207 return true;
2208 return false;
2209}
2210
2211/// \returns The condition code operand index for \p Instr if it is a branch
2212/// or select and -1 otherwise.
2213int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2214 const MachineInstr &Instr) {
2215 switch (Instr.getOpcode()) {
2216 default:
2217 return -1;
2218
2219 case AArch64::Bcc: {
2220 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2221 assert(Idx >= 2);
2222 return Idx - 2;
2223 }
2224
2225 case AArch64::CSINVWr:
2226 case AArch64::CSINVXr:
2227 case AArch64::CSINCWr:
2228 case AArch64::CSINCXr:
2229 case AArch64::CSELWr:
2230 case AArch64::CSELXr:
2231 case AArch64::CSNEGWr:
2232 case AArch64::CSNEGXr:
2233 case AArch64::FCSELSrrr:
2234 case AArch64::FCSELDrrr: {
2235 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2236 assert(Idx >= 1);
2237 return Idx - 1;
2238 }
2239 }
2240}
2241
2242/// Find a condition code used by the instruction.
2243/// Returns AArch64CC::Invalid if either the instruction does not use condition
2244/// codes or we don't optimize CmpInstr in the presence of such instructions.
2246 int CCIdx =
2247 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2248 return CCIdx >= 0 ? static_cast<AArch64CC::CondCode>(
2249 Instr.getOperand(CCIdx).getImm())
2251}
2252
2255 UsedNZCV UsedFlags;
2256 switch (CC) {
2257 default:
2258 break;
2259
2260 case AArch64CC::EQ: // Z set
2261 case AArch64CC::NE: // Z clear
2262 UsedFlags.Z = true;
2263 break;
2264
2265 case AArch64CC::HI: // Z clear and C set
2266 case AArch64CC::LS: // Z set or C clear
2267 UsedFlags.Z = true;
2268 [[fallthrough]];
2269 case AArch64CC::HS: // C set
2270 case AArch64CC::LO: // C clear
2271 UsedFlags.C = true;
2272 break;
2273
2274 case AArch64CC::MI: // N set
2275 case AArch64CC::PL: // N clear
2276 UsedFlags.N = true;
2277 break;
2278
2279 case AArch64CC::VS: // V set
2280 case AArch64CC::VC: // V clear
2281 UsedFlags.V = true;
2282 break;
2283
2284 case AArch64CC::GT: // Z clear, N and V the same
2285 case AArch64CC::LE: // Z set, N and V differ
2286 UsedFlags.Z = true;
2287 [[fallthrough]];
2288 case AArch64CC::GE: // N and V the same
2289 case AArch64CC::LT: // N and V differ
2290 UsedFlags.N = true;
2291 UsedFlags.V = true;
2292 break;
2293 }
2294 return UsedFlags;
2295}
2296
2297/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
2298/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
2299/// \returns std::nullopt otherwise.
2300///
2301/// Collect instructions using that flags in \p CCUseInstrs if provided.
2302std::optional<UsedNZCV>
2304 const TargetRegisterInfo &TRI,
2305 SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
2306 MachineBasicBlock *CmpParent = CmpInstr.getParent();
2307 if (MI.getParent() != CmpParent)
2308 return std::nullopt;
2309
2310 if (areCFlagsAliveInSuccessors(CmpParent))
2311 return std::nullopt;
2312
2313 UsedNZCV NZCVUsedAfterCmp;
2315 std::next(CmpInstr.getIterator()), CmpParent->instr_end())) {
2316 if (Instr.readsRegister(AArch64::NZCV, &TRI)) {
2318 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
2319 return std::nullopt;
2320 NZCVUsedAfterCmp |= getUsedNZCV(CC);
2321 if (CCUseInstrs)
2322 CCUseInstrs->push_back(&Instr);
2323 }
2324 if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
2325 break;
2326 }
2327 return NZCVUsedAfterCmp;
2328}
2329
2330static bool isADDSRegImm(unsigned Opcode) {
2331 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2332}
2333
2334static bool isSUBSRegImm(unsigned Opcode) {
2335 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2336}
2337
2339 unsigned Opc = sForm(MI);
2340 switch (Opc) {
2341 case AArch64::ANDSWri:
2342 case AArch64::ANDSWrr:
2343 case AArch64::ANDSWrs:
2344 case AArch64::ANDSXri:
2345 case AArch64::ANDSXrr:
2346 case AArch64::ANDSXrs:
2347 case AArch64::BICSWrr:
2348 case AArch64::BICSXrr:
2349 case AArch64::BICSWrs:
2350 case AArch64::BICSXrs:
2351 return true;
2352 default:
2353 return false;
2354 }
2355}
2356
2357/// Check if CmpInstr can be substituted by MI.
2358///
2359/// CmpInstr can be substituted:
2360/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2361/// - and, MI and CmpInstr are from the same MachineBB
2362/// - and, condition flags are not alive in successors of the CmpInstr parent
2363/// - and, if MI opcode is the S form there must be no defs of flags between
2364/// MI and CmpInstr
2365/// or if MI opcode is not the S form there must be neither defs of flags
2366/// nor uses of flags between MI and CmpInstr.
2367/// - and, C is not used after CmpInstr; CmpInstr's C is from adds/subs #0 on
2368/// SrcReg and can differ from MI (e.g. carry out of ADCS/SBCS).
2369/// - and, V is not used after CmpInstr unless MI is AND/BIC (V cleared) or MI
2370/// has NoSWrap (overflow is poison and the fold is still safe).
2372 const TargetRegisterInfo &TRI) {
2373 // MI is an opcode sForm maps (add/sub/adc/sbc/and/bic and their S forms).
2374 assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END);
2375
2376 const unsigned CmpOpcode = CmpInstr.getOpcode();
2377 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
2378 return false;
2379
2380 assert((CmpInstr.getOperand(2).isImm() &&
2381 CmpInstr.getOperand(2).getImm() == 0) &&
2382 "Caller guarantees that CmpInstr compares with constant 0");
2383
2384 std::optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
2385 if (!NZVCUsed || NZVCUsed->C)
2386 return false;
2387
2388 // CmpInstr is ADDS/SUBS with immediate 0 on SrcReg (compare SrcReg to zero).
2389 // After the fold, users see NZCV from MI (or its S form), not from CmpInstr.
2390 // N/Z match CmpInstr for the value in SrcReg; C/V need not match in general
2391 // (e.g. ADCS vs adds #0), so we require C unused after CmpInstr and gate V
2392 // as below. NoSWrap makes signed overflow poison; AND/BIC clear V.
2393 if (NZVCUsed->V && !MI.getFlag(MachineInstr::NoSWrap) && !isANDOpcode(MI))
2394 return false;
2395
2396 AccessKind AccessToCheck = AK_Write;
2397 if (sForm(MI) != MI.getOpcode())
2398 AccessToCheck = AK_All;
2399 return !areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AccessToCheck);
2400}
2401
2402/// Substitute an instruction comparing to zero with another instruction
2403/// which produces needed condition flags.
2404///
2405/// Return true on success.
2406bool AArch64InstrInfo::substituteCmpToZero(
2407 MachineInstr &CmpInstr, unsigned SrcReg,
2408 const MachineRegisterInfo &MRI) const {
2409 // Get the unique definition of SrcReg.
2410 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2411 if (!MI)
2412 return false;
2413
2414 const TargetRegisterInfo &TRI = getRegisterInfo();
2415
2416 unsigned NewOpc = sForm(*MI);
2417 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2418 return false;
2419
2420 if (!canInstrSubstituteCmpInstr(*MI, CmpInstr, TRI))
2421 return false;
2422
2423 // Update the instruction to set NZCV.
2424 MI->setDesc(get(NewOpc));
2425 CmpInstr.eraseFromParent();
2427 (void)succeeded;
2428 assert(succeeded && "Some operands reg class are incompatible!");
2429 MI->addRegisterDefined(AArch64::NZCV, &TRI);
2430 return true;
2431}
2432
2433/// \returns True if \p CmpInstr can be removed.
2434///
2435/// \p IsInvertCC is true if, after removing \p CmpInstr, condition
2436/// codes used in \p CCUseInstrs must be inverted.
2438 int CmpValue, const TargetRegisterInfo &TRI,
2440 bool &IsInvertCC) {
2441 assert((CmpValue == 0 || CmpValue == 1) &&
2442 "Only comparisons to 0 or 1 considered for removal!");
2443
2444 // MI is 'CSINCWr %vreg, wzr, wzr, <cc>' or 'CSINCXr %vreg, xzr, xzr, <cc>'
2445 unsigned MIOpc = MI.getOpcode();
2446 if (MIOpc == AArch64::CSINCWr) {
2447 if (MI.getOperand(1).getReg() != AArch64::WZR ||
2448 MI.getOperand(2).getReg() != AArch64::WZR)
2449 return false;
2450 } else if (MIOpc == AArch64::CSINCXr) {
2451 if (MI.getOperand(1).getReg() != AArch64::XZR ||
2452 MI.getOperand(2).getReg() != AArch64::XZR)
2453 return false;
2454 } else {
2455 return false;
2456 }
2458 if (MICC == AArch64CC::Invalid)
2459 return false;
2460
2461 // NZCV needs to be defined
2462 if (MI.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) != -1)
2463 return false;
2464
2465 // CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0' or 'SUBS %vreg, 1'
2466 const unsigned CmpOpcode = CmpInstr.getOpcode();
2467 bool IsSubsRegImm = isSUBSRegImm(CmpOpcode);
2468 if (CmpValue && !IsSubsRegImm)
2469 return false;
2470 if (!CmpValue && !IsSubsRegImm && !isADDSRegImm(CmpOpcode))
2471 return false;
2472
2473 // MI conditions allowed: eq, ne, mi, pl
2474 UsedNZCV MIUsedNZCV = getUsedNZCV(MICC);
2475 if (MIUsedNZCV.C || MIUsedNZCV.V)
2476 return false;
2477
2478 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2479 examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
2480 // Condition flags are not used in CmpInstr basic block successors and only
2481 // Z or N flags allowed to be used after CmpInstr within its basic block
2482 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2483 return false;
2484 // Z or N flag used after CmpInstr must correspond to the flag used in MI
2485 if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||
2486 (MIUsedNZCV.N && NZCVUsedAfterCmp->Z))
2487 return false;
2488 // If CmpInstr is comparison to zero MI conditions are limited to eq, ne
2489 if (MIUsedNZCV.N && !CmpValue)
2490 return false;
2491
2492 // There must be no defs of flags between MI and CmpInstr
2493 if (areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AK_Write))
2494 return false;
2495
2496 // Condition code is inverted in the following cases:
2497 // 1. MI condition is ne; CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2498 // 2. MI condition is eq, pl; CmpInstr is 'SUBS %vreg, 1'
2499 IsInvertCC = (CmpValue && (MICC == AArch64CC::EQ || MICC == AArch64CC::PL)) ||
2500 (!CmpValue && MICC == AArch64CC::NE);
2501 return true;
2502}
2503
2504/// Remove comparison in csinc-cmp sequence
2505///
2506/// Examples:
2507/// 1. \code
2508/// csinc w9, wzr, wzr, ne
2509/// cmp w9, #0
2510/// b.eq
2511/// \endcode
2512/// to
2513/// \code
2514/// csinc w9, wzr, wzr, ne
2515/// b.ne
2516/// \endcode
2517///
2518/// 2. \code
2519/// csinc x2, xzr, xzr, mi
2520/// cmp x2, #1
2521/// b.pl
2522/// \endcode
2523/// to
2524/// \code
2525/// csinc x2, xzr, xzr, mi
2526/// b.pl
2527/// \endcode
2528///
2529/// \param CmpInstr comparison instruction
2530/// \return True when comparison removed
2531bool AArch64InstrInfo::removeCmpToZeroOrOne(
2532 MachineInstr &CmpInstr, unsigned SrcReg, int CmpValue,
2533 const MachineRegisterInfo &MRI) const {
2534 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2535 if (!MI)
2536 return false;
2537 const TargetRegisterInfo &TRI = getRegisterInfo();
2538 SmallVector<MachineInstr *, 4> CCUseInstrs;
2539 bool IsInvertCC = false;
2540 if (!canCmpInstrBeRemoved(*MI, CmpInstr, CmpValue, TRI, CCUseInstrs,
2541 IsInvertCC))
2542 return false;
2543 // Make transformation
2544 CmpInstr.eraseFromParent();
2545 if (IsInvertCC) {
2546 // Invert condition codes in CmpInstr CC users
2547 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2548 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2549 assert(Idx >= 0 && "Unexpected instruction using CC.");
2550 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2552 static_cast<AArch64CC::CondCode>(CCOperand.getImm()));
2553 CCOperand.setImm(CCUse);
2554 }
2555 }
2556 return true;
2557}
2558
2559bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
2560 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2561 MI.getOpcode() != AArch64::CATCHRET &&
2562 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2563 return false;
2564
2565 MachineBasicBlock &MBB = *MI.getParent();
2566 auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
2567 auto TRI = Subtarget.getRegisterInfo();
2568 DebugLoc DL = MI.getDebugLoc();
2569
2570 if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2571 // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
2572 // This computes FP - stored_mixed_value to unmix the cookie
2573 Register DstReg = MI.getOperand(0).getReg();
2574 Register SrcReg = MI.getOperand(1).getReg();
2575
2576 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
2577 .addReg(AArch64::FP)
2578 .addReg(SrcReg);
2579
2580 MBB.erase(MI);
2581 return true;
2582 }
2583
2584 if (MI.getOpcode() == AArch64::CATCHRET) {
2585 // Skip to the first instruction before the epilog.
2586 const TargetInstrInfo *TII =
2588 MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
2590 MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
2591 while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
2592 FirstEpilogSEH != MBB.begin())
2593 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2594 if (FirstEpilogSEH != MBB.begin())
2595 FirstEpilogSEH = std::next(FirstEpilogSEH);
2596 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
2597 .addReg(AArch64::X0, RegState::Define)
2598 .addMBB(TargetMBB);
2599 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
2600 .addReg(AArch64::X0, RegState::Define)
2601 .addReg(AArch64::X0)
2602 .addMBB(TargetMBB)
2603 .addImm(0);
2604 TargetMBB->setMachineBlockAddressTaken();
2605 return true;
2606 }
2607
2608 Register Reg = MI.getOperand(0).getReg();
2610 if (M.getStackProtectorGuard() == "sysreg") {
2611 const AArch64SysReg::SysReg *SrcReg =
2612 AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg());
2613 if (!SrcReg)
2614 report_fatal_error("Unknown SysReg for Stack Protector Guard Register");
2615
2616 // mrs xN, sysreg
2617 BuildMI(MBB, MI, DL, get(AArch64::MRS))
2619 .addImm(SrcReg->Encoding);
2620 int Offset = M.getStackProtectorGuardOffset();
2621 if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) {
2622 // ldr xN, [xN, #offset]
2623 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2624 .addDef(Reg)
2626 .addImm(Offset / 8);
2627 } else if (Offset >= -256 && Offset <= 255) {
2628 // ldur xN, [xN, #offset]
2629 BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
2630 .addDef(Reg)
2632 .addImm(Offset);
2633 } else if (Offset >= -4095 && Offset <= 4095) {
2634 if (Offset > 0) {
2635 // add xN, xN, #offset
2636 BuildMI(MBB, MI, DL, get(AArch64::ADDXri))
2637 .addDef(Reg)
2639 .addImm(Offset)
2640 .addImm(0);
2641 } else {
2642 // sub xN, xN, #offset
2643 BuildMI(MBB, MI, DL, get(AArch64::SUBXri))
2644 .addDef(Reg)
2646 .addImm(-Offset)
2647 .addImm(0);
2648 }
2649 // ldr xN, [xN]
2650 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2651 .addDef(Reg)
2653 .addImm(0);
2654 } else {
2655 // Cases that are larger than +/- 4095 and not a multiple of 8, or larger
2656 // than 23760.
2657 // It might be nice to use AArch64::MOVi32imm here, which would get
2658 // expanded in PreSched2 after PostRA, but our lone scratch Reg already
2659 // contains the MRS result. findScratchNonCalleeSaveRegister() in
2660 // AArch64FrameLowering might help us find such a scratch register
2661 // though. If we failed to find a scratch register, we could emit a
2662 // stream of add instructions to build up the immediate. Or, we could try
2663 // to insert a AArch64::MOVi32imm before register allocation so that we
2664 // didn't need to scavenge for a scratch register.
2665 report_fatal_error("Unable to encode Stack Protector Guard Offset");
2666 }
2667 MBB.erase(MI);
2668 return true;
2669 }
2670
2671 const GlobalValue *GV =
2672 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
2673 const TargetMachine &TM = MBB.getParent()->getTarget();
2674 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2675 const unsigned char MO_NC = AArch64II::MO_NC;
2676
2677 unsigned GuardWidth = M.getStackProtectorGuardValueWidth().value_or(
2678 Subtarget.isTargetILP32() ? 4 : 8);
2679 if (GuardWidth != 4 && GuardWidth != 8)
2680 report_fatal_error("Unsupported stack protector value width");
2681 if ((OpFlags & AArch64II::MO_GOT) != 0) {
2682 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
2683 .addGlobalAddress(GV, 0, OpFlags);
2684 if (GuardWidth == 4) {
2685 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2686 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2687 .addDef(Reg32, RegState::Dead)
2689 .addImm(0)
2690 .addMemOperand(*MI.memoperands_begin())
2692 } else {
2693 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2695 .addImm(0)
2696 .addMemOperand(*MI.memoperands_begin());
2697 }
2698 } else if (TM.getCodeModel() == CodeModel::Large) {
2699 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
2700 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
2701 .addImm(0);
2702 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2704 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC)
2705 .addImm(16);
2706 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2708 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC)
2709 .addImm(32);
2710 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2713 .addImm(48);
2714 if (GuardWidth == 4) {
2715 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2716 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2717 .addDef(Reg32, RegState::Dead)
2719 .addImm(0)
2720 .addMemOperand(*MI.memoperands_begin())
2722 } else {
2723 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2725 .addImm(0)
2726 .addMemOperand(*MI.memoperands_begin());
2727 }
2728 } else {
2729 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
2730 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
2731 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
2732 if (GuardWidth == 4) {
2733 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2734 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2735 .addDef(Reg32, RegState::Dead)
2737 .addGlobalAddress(GV, 0, LoFlags)
2738 .addMemOperand(*MI.memoperands_begin())
2740 } else {
2741 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2743 .addGlobalAddress(GV, 0, LoFlags)
2744 .addMemOperand(*MI.memoperands_begin());
2745 }
2746 }
2747 // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
2748 // we use sub instruction to mix the cookie on aarch64.
2749 // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
2750 // the final frame pointer value.
2751 if (Subtarget.getTargetTriple().isOSMSVCRT())
2752 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
2753 .addReg(AArch64::FP)
2755
2756 MBB.erase(MI);
2757
2758 return true;
2759}
2760
2761// Return true if this instruction simply sets its single destination register
2762// to zero. This is equivalent to a register rename of the zero-register.
2764 switch (MI.getOpcode()) {
2765 default:
2766 break;
2767 case AArch64::MOVZWi:
2768 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
2769 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
2770 assert(MI.getDesc().getNumOperands() == 3 &&
2771 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
2772 return true;
2773 }
2774 break;
2775 case AArch64::ANDWri: // and Rd, Rzr, #imm
2776 return MI.getOperand(1).getReg() == AArch64::WZR;
2777 case AArch64::ANDXri:
2778 return MI.getOperand(1).getReg() == AArch64::XZR;
2779 case TargetOpcode::COPY:
2780 return MI.getOperand(1).getReg() == AArch64::WZR;
2781 }
2782 return false;
2783}
2784
2785// Return true if this instruction simply renames a general register without
2786// modifying bits.
2788 switch (MI.getOpcode()) {
2789 default:
2790 break;
2791 case TargetOpcode::COPY: {
2792 // GPR32 copies will by lowered to ORRXrs
2793 Register DstReg = MI.getOperand(0).getReg();
2794 return (AArch64::GPR32RegClass.contains(DstReg) ||
2795 AArch64::GPR64RegClass.contains(DstReg));
2796 }
2797 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
2798 if (MI.getOperand(1).getReg() == AArch64::XZR) {
2799 assert(MI.getDesc().getNumOperands() == 4 &&
2800 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
2801 return true;
2802 }
2803 break;
2804 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
2805 if (MI.getOperand(2).getImm() == 0) {
2806 assert(MI.getDesc().getNumOperands() == 4 &&
2807 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
2808 return true;
2809 }
2810 break;
2811 }
2812 return false;
2813}
2814
2815// Return true if this instruction simply renames a general register without
2816// modifying bits.
2818 switch (MI.getOpcode()) {
2819 default:
2820 break;
2821 case TargetOpcode::COPY: {
2822 Register DstReg = MI.getOperand(0).getReg();
2823 return AArch64::FPR128RegClass.contains(DstReg);
2824 }
2825 case AArch64::ORRv16i8:
2826 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
2827 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
2828 "invalid ORRv16i8 operands");
2829 return true;
2830 }
2831 break;
2832 }
2833 return false;
2834}
2835
2836static bool isFrameLoadOpcode(int Opcode) {
2837 switch (Opcode) {
2838 default:
2839 return false;
2840 case AArch64::LDRWui:
2841 case AArch64::LDRXui:
2842 case AArch64::LDRBui:
2843 case AArch64::LDRHui:
2844 case AArch64::LDRSui:
2845 case AArch64::LDRDui:
2846 case AArch64::LDRQui:
2847 case AArch64::LDR_PXI:
2848 return true;
2849 }
2850}
2851
2853 int &FrameIndex) const {
2854 if (!isFrameLoadOpcode(MI.getOpcode()))
2855 return Register();
2856
2857 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2858 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2859 FrameIndex = MI.getOperand(1).getIndex();
2860 return MI.getOperand(0).getReg();
2861 }
2862 return Register();
2863}
2864
2865static bool isFrameStoreOpcode(int Opcode) {
2866 switch (Opcode) {
2867 default:
2868 return false;
2869 case AArch64::STRWui:
2870 case AArch64::STRXui:
2871 case AArch64::STRBui:
2872 case AArch64::STRHui:
2873 case AArch64::STRSui:
2874 case AArch64::STRDui:
2875 case AArch64::STRQui:
2876 case AArch64::STR_PXI:
2877 return true;
2878 }
2879}
2880
2882 int &FrameIndex) const {
2883 if (!isFrameStoreOpcode(MI.getOpcode()))
2884 return Register();
2885
2886 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2887 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2888 FrameIndex = MI.getOperand(1).getIndex();
2889 return MI.getOperand(0).getReg();
2890 }
2891 return Register();
2892}
2893
2895 int &FrameIndex) const {
2896 if (!isFrameStoreOpcode(MI.getOpcode()))
2897 return Register();
2898
2899 if (Register Reg = isStoreToStackSlot(MI, FrameIndex))
2900 return Reg;
2901
2903 if (hasStoreToStackSlot(MI, Accesses)) {
2904 if (Accesses.size() > 1)
2905 return Register();
2906
2907 FrameIndex =
2908 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2909 ->getFrameIndex();
2910 return MI.getOperand(0).getReg();
2911 }
2912 return Register();
2913}
2914
2916 int &FrameIndex) const {
2917 if (!isFrameLoadOpcode(MI.getOpcode()))
2918 return Register();
2919
2920 if (Register Reg = isLoadFromStackSlot(MI, FrameIndex))
2921 return Reg;
2922
2924 if (hasLoadFromStackSlot(MI, Accesses)) {
2925 if (Accesses.size() > 1)
2926 return Register();
2927
2928 FrameIndex =
2929 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2930 ->getFrameIndex();
2931 return MI.getOperand(0).getReg();
2932 }
2933 return Register();
2934}
2935
2936/// Check all MachineMemOperands for a hint to suppress pairing.
2938 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2939 return MMO->getFlags() & MOSuppressPair;
2940 });
2941}
2942
2943/// Set a flag on the first MachineMemOperand to suppress pairing.
2945 if (MI.memoperands_empty())
2946 return;
2947 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
2948}
2949
2950/// Check all MachineMemOperands for a hint that the load/store is strided.
2952 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2953 return MMO->getFlags() & MOStridedAccess;
2954 });
2955}
2956
2958 switch (Opc) {
2959 default:
2960 return false;
2961 case AArch64::STURSi:
2962 case AArch64::STRSpre:
2963 case AArch64::STURDi:
2964 case AArch64::STRDpre:
2965 case AArch64::STURQi:
2966 case AArch64::STRQpre:
2967 case AArch64::STURBBi:
2968 case AArch64::STURHHi:
2969 case AArch64::STURWi:
2970 case AArch64::STRWpre:
2971 case AArch64::STURXi:
2972 case AArch64::STRXpre:
2973 case AArch64::LDURSi:
2974 case AArch64::LDRSpre:
2975 case AArch64::LDURDi:
2976 case AArch64::LDRDpre:
2977 case AArch64::LDURQi:
2978 case AArch64::LDRQpre:
2979 case AArch64::LDURWi:
2980 case AArch64::LDRWpre:
2981 case AArch64::LDURXi:
2982 case AArch64::LDRXpre:
2983 case AArch64::LDRSWpre:
2984 case AArch64::LDURSWi:
2985 case AArch64::LDURHHi:
2986 case AArch64::LDURBBi:
2987 case AArch64::LDURSBWi:
2988 case AArch64::LDURSHWi:
2989 return true;
2990 }
2991}
2992
2993std::optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) {
2994 switch (Opc) {
2995 default: return {};
2996 case AArch64::PRFMui: return AArch64::PRFUMi;
2997 case AArch64::LDRXui: return AArch64::LDURXi;
2998 case AArch64::LDRWui: return AArch64::LDURWi;
2999 case AArch64::LDRBui: return AArch64::LDURBi;
3000 case AArch64::LDRHui: return AArch64::LDURHi;
3001 case AArch64::LDRSui: return AArch64::LDURSi;
3002 case AArch64::LDRDui: return AArch64::LDURDi;
3003 case AArch64::LDRQui: return AArch64::LDURQi;
3004 case AArch64::LDRBBui: return AArch64::LDURBBi;
3005 case AArch64::LDRHHui: return AArch64::LDURHHi;
3006 case AArch64::LDRSBXui: return AArch64::LDURSBXi;
3007 case AArch64::LDRSBWui: return AArch64::LDURSBWi;
3008 case AArch64::LDRSHXui: return AArch64::LDURSHXi;
3009 case AArch64::LDRSHWui: return AArch64::LDURSHWi;
3010 case AArch64::LDRSWui: return AArch64::LDURSWi;
3011 case AArch64::STRXui: return AArch64::STURXi;
3012 case AArch64::STRWui: return AArch64::STURWi;
3013 case AArch64::STRBui: return AArch64::STURBi;
3014 case AArch64::STRHui: return AArch64::STURHi;
3015 case AArch64::STRSui: return AArch64::STURSi;
3016 case AArch64::STRDui: return AArch64::STURDi;
3017 case AArch64::STRQui: return AArch64::STURQi;
3018 case AArch64::STRBBui: return AArch64::STURBBi;
3019 case AArch64::STRHHui: return AArch64::STURHHi;
3020 }
3021}
3022
3024 switch (Opc) {
3025 default:
3026 llvm_unreachable("Unhandled Opcode in getLoadStoreImmIdx");
3027 case AArch64::ADDG:
3028 case AArch64::LDAPURBi:
3029 case AArch64::LDAPURHi:
3030 case AArch64::LDAPURi:
3031 case AArch64::LDAPURSBWi:
3032 case AArch64::LDAPURSBXi:
3033 case AArch64::LDAPURSHWi:
3034 case AArch64::LDAPURSHXi:
3035 case AArch64::LDAPURSWi:
3036 case AArch64::LDAPURXi:
3037 case AArch64::LDR_PPXI:
3038 case AArch64::LDR_PXI:
3039 case AArch64::LDR_ZXI:
3040 case AArch64::LDR_ZZXI:
3041 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3042 case AArch64::LDR_ZZZXI:
3043 case AArch64::LDR_ZZZZXI:
3044 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3045 case AArch64::LDRBBui:
3046 case AArch64::LDRBui:
3047 case AArch64::LDRDui:
3048 case AArch64::LDRHHui:
3049 case AArch64::LDRHui:
3050 case AArch64::LDRQui:
3051 case AArch64::LDRSBWui:
3052 case AArch64::LDRSBXui:
3053 case AArch64::LDRSHWui:
3054 case AArch64::LDRSHXui:
3055 case AArch64::LDRSui:
3056 case AArch64::LDRSWui:
3057 case AArch64::LDRWui:
3058 case AArch64::LDRXui:
3059 case AArch64::LDURBBi:
3060 case AArch64::LDURBi:
3061 case AArch64::LDURDi:
3062 case AArch64::LDURHHi:
3063 case AArch64::LDURHi:
3064 case AArch64::LDURQi:
3065 case AArch64::LDURSBWi:
3066 case AArch64::LDURSBXi:
3067 case AArch64::LDURSHWi:
3068 case AArch64::LDURSHXi:
3069 case AArch64::LDURSi:
3070 case AArch64::LDURSWi:
3071 case AArch64::LDURWi:
3072 case AArch64::LDURXi:
3073 case AArch64::PRFMui:
3074 case AArch64::PRFUMi:
3075 case AArch64::ST2Gi:
3076 case AArch64::STGi:
3077 case AArch64::STLURBi:
3078 case AArch64::STLURHi:
3079 case AArch64::STLURWi:
3080 case AArch64::STLURXi:
3081 case AArch64::StoreSwiftAsyncContext:
3082 case AArch64::STR_PPXI:
3083 case AArch64::STR_PXI:
3084 case AArch64::STR_ZXI:
3085 case AArch64::STR_ZZXI:
3086 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3087 case AArch64::STR_ZZZXI:
3088 case AArch64::STR_ZZZZXI:
3089 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3090 case AArch64::STRBBui:
3091 case AArch64::STRBui:
3092 case AArch64::STRDui:
3093 case AArch64::STRHHui:
3094 case AArch64::STRHui:
3095 case AArch64::STRQui:
3096 case AArch64::STRSui:
3097 case AArch64::STRWui:
3098 case AArch64::STRXui:
3099 case AArch64::STURBBi:
3100 case AArch64::STURBi:
3101 case AArch64::STURDi:
3102 case AArch64::STURHHi:
3103 case AArch64::STURHi:
3104 case AArch64::STURQi:
3105 case AArch64::STURSi:
3106 case AArch64::STURWi:
3107 case AArch64::STURXi:
3108 case AArch64::STZ2Gi:
3109 case AArch64::STZGi:
3110 case AArch64::TAGPstack:
3111 return 2;
3112 case AArch64::LD1B_D_IMM:
3113 case AArch64::LD1B_H_IMM:
3114 case AArch64::LD1B_IMM:
3115 case AArch64::LD1B_S_IMM:
3116 case AArch64::LD1D_IMM:
3117 case AArch64::LD1H_D_IMM:
3118 case AArch64::LD1H_IMM:
3119 case AArch64::LD1H_S_IMM:
3120 case AArch64::LD1RB_D_IMM:
3121 case AArch64::LD1RB_H_IMM:
3122 case AArch64::LD1RB_IMM:
3123 case AArch64::LD1RB_S_IMM:
3124 case AArch64::LD1RD_IMM:
3125 case AArch64::LD1RH_D_IMM:
3126 case AArch64::LD1RH_IMM:
3127 case AArch64::LD1RH_S_IMM:
3128 case AArch64::LD1RSB_D_IMM:
3129 case AArch64::LD1RSB_H_IMM:
3130 case AArch64::LD1RSB_S_IMM:
3131 case AArch64::LD1RSH_D_IMM:
3132 case AArch64::LD1RSH_S_IMM:
3133 case AArch64::LD1RSW_IMM:
3134 case AArch64::LD1RW_D_IMM:
3135 case AArch64::LD1RW_IMM:
3136 case AArch64::LD1SB_D_IMM:
3137 case AArch64::LD1SB_H_IMM:
3138 case AArch64::LD1SB_S_IMM:
3139 case AArch64::LD1SH_D_IMM:
3140 case AArch64::LD1SH_S_IMM:
3141 case AArch64::LD1SW_D_IMM:
3142 case AArch64::LD1W_D_IMM:
3143 case AArch64::LD1W_IMM:
3144 case AArch64::LD2B_IMM:
3145 case AArch64::LD2D_IMM:
3146 case AArch64::LD2H_IMM:
3147 case AArch64::LD2W_IMM:
3148 case AArch64::LD3B_IMM:
3149 case AArch64::LD3D_IMM:
3150 case AArch64::LD3H_IMM:
3151 case AArch64::LD3W_IMM:
3152 case AArch64::LD4B_IMM:
3153 case AArch64::LD4D_IMM:
3154 case AArch64::LD4H_IMM:
3155 case AArch64::LD4W_IMM:
3156 case AArch64::LDG:
3157 case AArch64::LDNF1B_D_IMM:
3158 case AArch64::LDNF1B_H_IMM:
3159 case AArch64::LDNF1B_IMM:
3160 case AArch64::LDNF1B_S_IMM:
3161 case AArch64::LDNF1D_IMM:
3162 case AArch64::LDNF1H_D_IMM:
3163 case AArch64::LDNF1H_IMM:
3164 case AArch64::LDNF1H_S_IMM:
3165 case AArch64::LDNF1SB_D_IMM:
3166 case AArch64::LDNF1SB_H_IMM:
3167 case AArch64::LDNF1SB_S_IMM:
3168 case AArch64::LDNF1SH_D_IMM:
3169 case AArch64::LDNF1SH_S_IMM:
3170 case AArch64::LDNF1SW_D_IMM:
3171 case AArch64::LDNF1W_D_IMM:
3172 case AArch64::LDNF1W_IMM:
3173 case AArch64::LDNPDi:
3174 case AArch64::LDNPQi:
3175 case AArch64::LDNPSi:
3176 case AArch64::LDNPWi:
3177 case AArch64::LDNPXi:
3178 case AArch64::LDNT1B_ZRI:
3179 case AArch64::LDNT1D_ZRI:
3180 case AArch64::LDNT1H_ZRI:
3181 case AArch64::LDNT1W_ZRI:
3182 case AArch64::LDPDi:
3183 case AArch64::LDPQi:
3184 case AArch64::LDPSi:
3185 case AArch64::LDPWi:
3186 case AArch64::LDPXi:
3187 case AArch64::LDRBBpost:
3188 case AArch64::LDRBBpre:
3189 case AArch64::LDRBpost:
3190 case AArch64::LDRBpre:
3191 case AArch64::LDRDpost:
3192 case AArch64::LDRDpre:
3193 case AArch64::LDRHHpost:
3194 case AArch64::LDRHHpre:
3195 case AArch64::LDRHpost:
3196 case AArch64::LDRHpre:
3197 case AArch64::LDRQpost:
3198 case AArch64::LDRQpre:
3199 case AArch64::LDRSpost:
3200 case AArch64::LDRSpre:
3201 case AArch64::LDRWpost:
3202 case AArch64::LDRWpre:
3203 case AArch64::LDRXpost:
3204 case AArch64::LDRXpre:
3205 case AArch64::ST1B_D_IMM:
3206 case AArch64::ST1B_H_IMM:
3207 case AArch64::ST1B_IMM:
3208 case AArch64::ST1B_S_IMM:
3209 case AArch64::ST1D_IMM:
3210 case AArch64::ST1H_D_IMM:
3211 case AArch64::ST1H_IMM:
3212 case AArch64::ST1H_S_IMM:
3213 case AArch64::ST1W_D_IMM:
3214 case AArch64::ST1W_IMM:
3215 case AArch64::ST2B_IMM:
3216 case AArch64::ST2D_IMM:
3217 case AArch64::ST2H_IMM:
3218 case AArch64::ST2W_IMM:
3219 case AArch64::ST3B_IMM:
3220 case AArch64::ST3D_IMM:
3221 case AArch64::ST3H_IMM:
3222 case AArch64::ST3W_IMM:
3223 case AArch64::ST4B_IMM:
3224 case AArch64::ST4D_IMM:
3225 case AArch64::ST4H_IMM:
3226 case AArch64::ST4W_IMM:
3227 case AArch64::STGPi:
3228 case AArch64::STGPreIndex:
3229 case AArch64::STZGPreIndex:
3230 case AArch64::ST2GPreIndex:
3231 case AArch64::STZ2GPreIndex:
3232 case AArch64::STGPostIndex:
3233 case AArch64::STZGPostIndex:
3234 case AArch64::ST2GPostIndex:
3235 case AArch64::STZ2GPostIndex:
3236 case AArch64::STNPDi:
3237 case AArch64::STNPQi:
3238 case AArch64::STNPSi:
3239 case AArch64::STNPWi:
3240 case AArch64::STNPXi:
3241 case AArch64::STNT1B_ZRI:
3242 case AArch64::STNT1D_ZRI:
3243 case AArch64::STNT1H_ZRI:
3244 case AArch64::STNT1W_ZRI:
3245 case AArch64::STPDi:
3246 case AArch64::STPQi:
3247 case AArch64::STPSi:
3248 case AArch64::STPWi:
3249 case AArch64::STPXi:
3250 case AArch64::STRBBpost:
3251 case AArch64::STRBBpre:
3252 case AArch64::STRBpost:
3253 case AArch64::STRBpre:
3254 case AArch64::STRDpost:
3255 case AArch64::STRDpre:
3256 case AArch64::STRHHpost:
3257 case AArch64::STRHHpre:
3258 case AArch64::STRHpost:
3259 case AArch64::STRHpre:
3260 case AArch64::STRQpost:
3261 case AArch64::STRQpre:
3262 case AArch64::STRSpost:
3263 case AArch64::STRSpre:
3264 case AArch64::STRWpost:
3265 case AArch64::STRWpre:
3266 case AArch64::STRXpost:
3267 case AArch64::STRXpre:
3268 case AArch64::LD1B_2Z_IMM:
3269 case AArch64::LD1B_2Z_STRIDED_IMM:
3270 case AArch64::LD1H_2Z_IMM:
3271 case AArch64::LD1H_2Z_STRIDED_IMM:
3272 case AArch64::LD1W_2Z_IMM:
3273 case AArch64::LD1W_2Z_STRIDED_IMM:
3274 case AArch64::LD1D_2Z_IMM:
3275 case AArch64::LD1D_2Z_STRIDED_IMM:
3276 case AArch64::LD1B_4Z_IMM:
3277 case AArch64::LD1B_4Z_STRIDED_IMM:
3278 case AArch64::LD1H_4Z_IMM:
3279 case AArch64::LD1H_4Z_STRIDED_IMM:
3280 case AArch64::LD1W_4Z_IMM:
3281 case AArch64::LD1W_4Z_STRIDED_IMM:
3282 case AArch64::LD1D_4Z_IMM:
3283 case AArch64::LD1D_4Z_STRIDED_IMM:
3284 case AArch64::LD1B_2Z_IMM_PSEUDO:
3285 case AArch64::LD1H_2Z_IMM_PSEUDO:
3286 case AArch64::LD1W_2Z_IMM_PSEUDO:
3287 case AArch64::LD1D_2Z_IMM_PSEUDO:
3288 case AArch64::LD1B_4Z_IMM_PSEUDO:
3289 case AArch64::LD1H_4Z_IMM_PSEUDO:
3290 case AArch64::LD1W_4Z_IMM_PSEUDO:
3291 case AArch64::LD1D_4Z_IMM_PSEUDO:
3292 case AArch64::ST1B_2Z_IMM:
3293 case AArch64::ST1B_2Z_STRIDED_IMM:
3294 case AArch64::ST1H_2Z_IMM:
3295 case AArch64::ST1H_2Z_STRIDED_IMM:
3296 case AArch64::ST1W_2Z_IMM:
3297 case AArch64::ST1W_2Z_STRIDED_IMM:
3298 case AArch64::ST1D_2Z_IMM:
3299 case AArch64::ST1D_2Z_STRIDED_IMM:
3300 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3301 case AArch64::LDNT1B_2Z_IMM:
3302 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3303 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3304 case AArch64::LDNT1H_2Z_IMM:
3305 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3306 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3307 case AArch64::LDNT1W_2Z_IMM:
3308 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3309 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3310 case AArch64::LDNT1D_2Z_IMM:
3311 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3312 case AArch64::STNT1B_2Z_IMM:
3313 case AArch64::STNT1B_2Z_STRIDED_IMM:
3314 case AArch64::STNT1H_2Z_IMM:
3315 case AArch64::STNT1H_2Z_STRIDED_IMM:
3316 case AArch64::STNT1W_2Z_IMM:
3317 case AArch64::STNT1W_2Z_STRIDED_IMM:
3318 case AArch64::STNT1D_2Z_IMM:
3319 case AArch64::STNT1D_2Z_STRIDED_IMM:
3320 case AArch64::ST1B_2Z_IMM_PSEUDO:
3321 case AArch64::ST1H_2Z_IMM_PSEUDO:
3322 case AArch64::ST1W_2Z_IMM_PSEUDO:
3323 case AArch64::ST1D_2Z_IMM_PSEUDO:
3324 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3325 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3326 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3327 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3328 case AArch64::ST1B_4Z_IMM:
3329 case AArch64::ST1B_4Z_STRIDED_IMM:
3330 case AArch64::ST1H_4Z_IMM:
3331 case AArch64::ST1H_4Z_STRIDED_IMM:
3332 case AArch64::ST1W_4Z_IMM:
3333 case AArch64::ST1W_4Z_STRIDED_IMM:
3334 case AArch64::ST1D_4Z_IMM:
3335 case AArch64::ST1D_4Z_STRIDED_IMM:
3336 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3337 case AArch64::LDNT1B_4Z_IMM:
3338 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3339 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3340 case AArch64::LDNT1H_4Z_IMM:
3341 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3342 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3343 case AArch64::LDNT1W_4Z_IMM:
3344 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3345 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3346 case AArch64::LDNT1D_4Z_IMM:
3347 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3348 case AArch64::STNT1B_4Z_IMM:
3349 case AArch64::STNT1B_4Z_STRIDED_IMM:
3350 case AArch64::STNT1H_4Z_IMM:
3351 case AArch64::STNT1H_4Z_STRIDED_IMM:
3352 case AArch64::STNT1W_4Z_IMM:
3353 case AArch64::STNT1W_4Z_STRIDED_IMM:
3354 case AArch64::STNT1D_4Z_IMM:
3355 case AArch64::STNT1D_4Z_STRIDED_IMM:
3356 case AArch64::ST1B_4Z_IMM_PSEUDO:
3357 case AArch64::ST1H_4Z_IMM_PSEUDO:
3358 case AArch64::ST1W_4Z_IMM_PSEUDO:
3359 case AArch64::ST1D_4Z_IMM_PSEUDO:
3360 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3361 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3362 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3363 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3364 return 3;
3365 case AArch64::LDPDpost:
3366 case AArch64::LDPDpre:
3367 case AArch64::LDPQpost:
3368 case AArch64::LDPQpre:
3369 case AArch64::LDPSpost:
3370 case AArch64::LDPSpre:
3371 case AArch64::LDPWpost:
3372 case AArch64::LDPWpre:
3373 case AArch64::LDPXpost:
3374 case AArch64::LDPXpre:
3375 case AArch64::STGPpre:
3376 case AArch64::STGPpost:
3377 case AArch64::STPDpost:
3378 case AArch64::STPDpre:
3379 case AArch64::STPQpost:
3380 case AArch64::STPQpre:
3381 case AArch64::STPSpost:
3382 case AArch64::STPSpre:
3383 case AArch64::STPWpost:
3384 case AArch64::STPWpre:
3385 case AArch64::STPXpost:
3386 case AArch64::STPXpre:
3387 return 4;
3388 }
3389}
3390
3392 switch (MI.getOpcode()) {
3393 default:
3394 return false;
3395 // Scaled instructions.
3396 case AArch64::STRSui:
3397 case AArch64::STRDui:
3398 case AArch64::STRQui:
3399 case AArch64::STRXui:
3400 case AArch64::STRWui:
3401 case AArch64::LDRSui:
3402 case AArch64::LDRDui:
3403 case AArch64::LDRQui:
3404 case AArch64::LDRXui:
3405 case AArch64::LDRWui:
3406 case AArch64::LDRSWui:
3407 // Unscaled instructions.
3408 case AArch64::STURSi:
3409 case AArch64::STRSpre:
3410 case AArch64::STURDi:
3411 case AArch64::STRDpre:
3412 case AArch64::STURQi:
3413 case AArch64::STRQpre:
3414 case AArch64::STURWi:
3415 case AArch64::STRWpre:
3416 case AArch64::STURXi:
3417 case AArch64::STRXpre:
3418 case AArch64::LDURSi:
3419 case AArch64::LDRSpre:
3420 case AArch64::LDURDi:
3421 case AArch64::LDRDpre:
3422 case AArch64::LDURQi:
3423 case AArch64::LDRQpre:
3424 case AArch64::LDURWi:
3425 case AArch64::LDRWpre:
3426 case AArch64::LDURXi:
3427 case AArch64::LDRXpre:
3428 case AArch64::LDURSWi:
3429 case AArch64::LDRSWpre:
3430 // SVE instructions.
3431 case AArch64::LDR_ZXI:
3432 case AArch64::STR_ZXI:
3433 return true;
3434 }
3435}
3436
3438 switch (MI.getOpcode()) {
3439 default:
3440 assert((!MI.isCall() || !MI.isReturn()) &&
3441 "Unexpected instruction - was a new tail call opcode introduced?");
3442 return false;
3443 case AArch64::TCRETURNdi:
3444 case AArch64::TCRETURNri:
3445 case AArch64::TCRETURNrix16x17:
3446 case AArch64::TCRETURNrix17:
3447 case AArch64::TCRETURNrinotx16:
3448 case AArch64::TCRETURNriALL:
3449 case AArch64::AUTH_TCRETURN:
3450 case AArch64::AUTH_TCRETURN_BTI:
3451 return true;
3452 }
3453}
3454
3456 switch (Opc) {
3457 default:
3458 llvm_unreachable("Opcode has no flag setting equivalent!");
3459 // 32-bit cases:
3460 case AArch64::ADDWri:
3461 return AArch64::ADDSWri;
3462 case AArch64::ADDWrr:
3463 return AArch64::ADDSWrr;
3464 case AArch64::ADDWrs:
3465 return AArch64::ADDSWrs;
3466 case AArch64::ADDWrx:
3467 return AArch64::ADDSWrx;
3468 case AArch64::ANDWri:
3469 return AArch64::ANDSWri;
3470 case AArch64::ANDWrr:
3471 return AArch64::ANDSWrr;
3472 case AArch64::ANDWrs:
3473 return AArch64::ANDSWrs;
3474 case AArch64::BICWrr:
3475 return AArch64::BICSWrr;
3476 case AArch64::BICWrs:
3477 return AArch64::BICSWrs;
3478 case AArch64::SUBWri:
3479 return AArch64::SUBSWri;
3480 case AArch64::SUBWrr:
3481 return AArch64::SUBSWrr;
3482 case AArch64::SUBWrs:
3483 return AArch64::SUBSWrs;
3484 case AArch64::SUBWrx:
3485 return AArch64::SUBSWrx;
3486 // 64-bit cases:
3487 case AArch64::ADDXri:
3488 return AArch64::ADDSXri;
3489 case AArch64::ADDXrr:
3490 return AArch64::ADDSXrr;
3491 case AArch64::ADDXrs:
3492 return AArch64::ADDSXrs;
3493 case AArch64::ADDXrx:
3494 return AArch64::ADDSXrx;
3495 case AArch64::ANDXri:
3496 return AArch64::ANDSXri;
3497 case AArch64::ANDXrr:
3498 return AArch64::ANDSXrr;
3499 case AArch64::ANDXrs:
3500 return AArch64::ANDSXrs;
3501 case AArch64::BICXrr:
3502 return AArch64::BICSXrr;
3503 case AArch64::BICXrs:
3504 return AArch64::BICSXrs;
3505 case AArch64::SUBXri:
3506 return AArch64::SUBSXri;
3507 case AArch64::SUBXrr:
3508 return AArch64::SUBSXrr;
3509 case AArch64::SUBXrs:
3510 return AArch64::SUBSXrs;
3511 case AArch64::SUBXrx:
3512 return AArch64::SUBSXrx;
3513 // SVE instructions:
3514 case AArch64::AND_PPzPP:
3515 return AArch64::ANDS_PPzPP;
3516 case AArch64::BIC_PPzPP:
3517 return AArch64::BICS_PPzPP;
3518 case AArch64::EOR_PPzPP:
3519 return AArch64::EORS_PPzPP;
3520 case AArch64::NAND_PPzPP:
3521 return AArch64::NANDS_PPzPP;
3522 case AArch64::NOR_PPzPP:
3523 return AArch64::NORS_PPzPP;
3524 case AArch64::ORN_PPzPP:
3525 return AArch64::ORNS_PPzPP;
3526 case AArch64::ORR_PPzPP:
3527 return AArch64::ORRS_PPzPP;
3528 case AArch64::BRKA_PPzP:
3529 return AArch64::BRKAS_PPzP;
3530 case AArch64::BRKPA_PPzPP:
3531 return AArch64::BRKPAS_PPzPP;
3532 case AArch64::BRKB_PPzP:
3533 return AArch64::BRKBS_PPzP;
3534 case AArch64::BRKPB_PPzPP:
3535 return AArch64::BRKPBS_PPzPP;
3536 case AArch64::BRKN_PPzP:
3537 return AArch64::BRKNS_PPzP;
3538 case AArch64::RDFFR_PPz:
3539 return AArch64::RDFFRS_PPz;
3540 case AArch64::PTRUE_B:
3541 return AArch64::PTRUES_B;
3542 }
3543}
3544
3545// Is this a candidate for ld/st merging or pairing? For example, we don't
3546// touch volatiles or load/stores that have a hint to avoid pair formation.
3548
3549 bool IsPreLdSt = isPreLdSt(MI);
3550
3551 // If this is a volatile load/store, don't mess with it.
3552 if (MI.hasOrderedMemoryRef())
3553 return false;
3554
3555 // Make sure this is a reg/fi+imm (as opposed to an address reloc).
3556 // For Pre-inc LD/ST, the operand is shifted by one.
3557 assert((MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3558 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3559 "Expected a reg or frame index operand.");
3560
3561 // For Pre-indexed addressing quadword instructions, the third operand is the
3562 // immediate value.
3563 bool IsImmPreLdSt = IsPreLdSt && MI.getOperand(3).isImm();
3564
3565 if (!MI.getOperand(2).isImm() && !IsImmPreLdSt)
3566 return false;
3567
3568 // Can't merge/pair if the instruction modifies the base register.
3569 // e.g., ldr x0, [x0]
3570 // This case will never occur with an FI base.
3571 // However, if the instruction is an LDR<S,D,Q,W,X,SW>pre or
3572 // STR<S,D,Q,W,X>pre, it can be merged.
3573 // For example:
3574 // ldr q0, [x11, #32]!
3575 // ldr q1, [x11, #16]
3576 // to
3577 // ldp q0, q1, [x11, #32]!
3578 if (MI.getOperand(1).isReg() && !IsPreLdSt) {
3579 Register BaseReg = MI.getOperand(1).getReg();
3581 if (MI.modifiesRegister(BaseReg, TRI))
3582 return false;
3583 }
3584
3585 // Pairing SVE fills/spills is only valid for little-endian targets that
3586 // implement VLS 128.
3587 switch (MI.getOpcode()) {
3588 default:
3589 break;
3590 case AArch64::LDR_ZXI:
3591 case AArch64::STR_ZXI:
3592 if (!Subtarget.isLittleEndian() ||
3593 Subtarget.getSVEVectorSizeInBits() != 128)
3594 return false;
3595 }
3596
3597 // Check if this load/store has a hint to avoid pair formation.
3598 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
3600 return false;
3601
3602 // Do not pair any callee-save store/reload instructions in the
3603 // prologue/epilogue if the CFI information encoded the operations as separate
3604 // instructions, as that will cause the size of the actual prologue to mismatch
3605 // with the prologue size recorded in the Windows CFI.
3606 const MCAsmInfo &MAI = MI.getMF()->getTarget().getMCAsmInfo();
3607 bool NeedsWinCFI =
3608 MAI.usesWindowsCFI() && MI.getMF()->getFunction().needsUnwindTableEntry();
3609 if (NeedsWinCFI && (MI.getFlag(MachineInstr::FrameSetup) ||
3611 return false;
3612
3613 // On some CPUs quad load/store pairs are slower than two single load/stores.
3614 if (Subtarget.isPaired128Slow()) {
3615 switch (MI.getOpcode()) {
3616 default:
3617 break;
3618 case AArch64::LDURQi:
3619 case AArch64::STURQi:
3620 case AArch64::LDRQui:
3621 case AArch64::STRQui:
3622 return false;
3623 }
3624 }
3625
3626 return true;
3627}
3628
3631 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
3632 const TargetRegisterInfo *TRI) const {
3633 if (!LdSt.mayLoadOrStore())
3634 return false;
3635
3636 const MachineOperand *BaseOp;
3637 TypeSize WidthN(0, false);
3638 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, OffsetIsScalable,
3639 WidthN, TRI))
3640 return false;
3641 // The maximum vscale is 16 under AArch64, return the maximal extent for the
3642 // vector.
3643 Width = LocationSize::precise(WidthN);
3644 BaseOps.push_back(BaseOp);
3645 return true;
3646}
3647
3648std::optional<ExtAddrMode>
3650 const TargetRegisterInfo *TRI) const {
3651 const MachineOperand *Base; // Filled with the base operand of MI.
3652 int64_t Offset; // Filled with the offset of MI.
3653 bool OffsetIsScalable;
3654 if (!getMemOperandWithOffset(MemI, Base, Offset, OffsetIsScalable, TRI))
3655 return std::nullopt;
3656
3657 if (!Base->isReg())
3658 return std::nullopt;
3659 ExtAddrMode AM;
3660 AM.BaseReg = Base->getReg();
3661 AM.Displacement = Offset;
3662 AM.ScaledReg = 0;
3663 AM.Scale = 0;
3664 return AM;
3665}
3666
3668 Register Reg,
3669 const MachineInstr &AddrI,
3670 ExtAddrMode &AM) const {
3671 // Filter out instructions into which we cannot fold.
3672 unsigned NumBytes;
3673 int64_t OffsetScale = 1;
3674 switch (MemI.getOpcode()) {
3675 default:
3676 return false;
3677
3678 case AArch64::LDURQi:
3679 case AArch64::STURQi:
3680 NumBytes = 16;
3681 break;
3682
3683 case AArch64::LDURDi:
3684 case AArch64::STURDi:
3685 case AArch64::LDURXi:
3686 case AArch64::STURXi:
3687 NumBytes = 8;
3688 break;
3689
3690 case AArch64::LDURWi:
3691 case AArch64::LDURSWi:
3692 case AArch64::STURWi:
3693 NumBytes = 4;
3694 break;
3695
3696 case AArch64::LDURHi:
3697 case AArch64::STURHi:
3698 case AArch64::LDURHHi:
3699 case AArch64::STURHHi:
3700 case AArch64::LDURSHXi:
3701 case AArch64::LDURSHWi:
3702 NumBytes = 2;
3703 break;
3704
3705 case AArch64::LDRBroX:
3706 case AArch64::LDRBBroX:
3707 case AArch64::LDRSBXroX:
3708 case AArch64::LDRSBWroX:
3709 case AArch64::STRBroX:
3710 case AArch64::STRBBroX:
3711 case AArch64::LDURBi:
3712 case AArch64::LDURBBi:
3713 case AArch64::LDURSBXi:
3714 case AArch64::LDURSBWi:
3715 case AArch64::STURBi:
3716 case AArch64::STURBBi:
3717 case AArch64::LDRBui:
3718 case AArch64::LDRBBui:
3719 case AArch64::LDRSBXui:
3720 case AArch64::LDRSBWui:
3721 case AArch64::STRBui:
3722 case AArch64::STRBBui:
3723 NumBytes = 1;
3724 break;
3725
3726 case AArch64::LDRQroX:
3727 case AArch64::STRQroX:
3728 case AArch64::LDRQui:
3729 case AArch64::STRQui:
3730 NumBytes = 16;
3731 OffsetScale = 16;
3732 break;
3733
3734 case AArch64::LDRDroX:
3735 case AArch64::STRDroX:
3736 case AArch64::LDRXroX:
3737 case AArch64::STRXroX:
3738 case AArch64::LDRDui:
3739 case AArch64::STRDui:
3740 case AArch64::LDRXui:
3741 case AArch64::STRXui:
3742 NumBytes = 8;
3743 OffsetScale = 8;
3744 break;
3745
3746 case AArch64::LDRWroX:
3747 case AArch64::LDRSWroX:
3748 case AArch64::STRWroX:
3749 case AArch64::LDRWui:
3750 case AArch64::LDRSWui:
3751 case AArch64::STRWui:
3752 NumBytes = 4;
3753 OffsetScale = 4;
3754 break;
3755
3756 case AArch64::LDRHroX:
3757 case AArch64::STRHroX:
3758 case AArch64::LDRHHroX:
3759 case AArch64::STRHHroX:
3760 case AArch64::LDRSHXroX:
3761 case AArch64::LDRSHWroX:
3762 case AArch64::LDRHui:
3763 case AArch64::STRHui:
3764 case AArch64::LDRHHui:
3765 case AArch64::STRHHui:
3766 case AArch64::LDRSHXui:
3767 case AArch64::LDRSHWui:
3768 NumBytes = 2;
3769 OffsetScale = 2;
3770 break;
3771 }
3772
3773 // Check the fold operand is not the loaded/stored value.
3774 const MachineOperand &BaseRegOp = MemI.getOperand(0);
3775 if (BaseRegOp.isReg() && BaseRegOp.getReg() == Reg)
3776 return false;
3777
3778 // Handle memory instructions with a [Reg, Reg] addressing mode.
3779 if (MemI.getOperand(2).isReg()) {
3780 // Bail if the addressing mode already includes extension of the offset
3781 // register.
3782 if (MemI.getOperand(3).getImm())
3783 return false;
3784
3785 // Check if we actually have a scaled offset.
3786 if (MemI.getOperand(4).getImm() == 0)
3787 OffsetScale = 1;
3788
3789 // If the address instructions is folded into the base register, then the
3790 // addressing mode must not have a scale. Then we can swap the base and the
3791 // scaled registers.
3792 if (MemI.getOperand(1).getReg() == Reg && OffsetScale != 1)
3793 return false;
3794
3795 switch (AddrI.getOpcode()) {
3796 default:
3797 return false;
3798
3799 case AArch64::SBFMXri:
3800 // sxtw Xa, Wm
3801 // ldr Xd, [Xn, Xa, lsl #N]
3802 // ->
3803 // ldr Xd, [Xn, Wm, sxtw #N]
3804 if (AddrI.getOperand(2).getImm() != 0 ||
3805 AddrI.getOperand(3).getImm() != 31)
3806 return false;
3807
3808 AM.BaseReg = MemI.getOperand(1).getReg();
3809 if (AM.BaseReg == Reg)
3810 AM.BaseReg = MemI.getOperand(2).getReg();
3811 AM.ScaledReg = AddrI.getOperand(1).getReg();
3812 AM.Scale = OffsetScale;
3813 AM.Displacement = 0;
3815 return true;
3816
3817 case TargetOpcode::SUBREG_TO_REG: {
3818 // mov Wa, Wm
3819 // ldr Xd, [Xn, Xa, lsl #N]
3820 // ->
3821 // ldr Xd, [Xn, Wm, uxtw #N]
3822
3823 // Zero-extension looks like an ORRWrs followed by a SUBREG_TO_REG.
3824 if (AddrI.getOperand(2).getImm() != AArch64::sub_32)
3825 return false;
3826
3827 const MachineRegisterInfo &MRI = AddrI.getMF()->getRegInfo();
3828 Register OffsetReg = AddrI.getOperand(1).getReg();
3829 if (!OffsetReg.isVirtual() || !MRI.hasOneNonDBGUse(OffsetReg))
3830 return false;
3831
3832 const MachineInstr &DefMI = *MRI.getVRegDef(OffsetReg);
3833 if (DefMI.getOpcode() != AArch64::ORRWrs ||
3834 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3835 DefMI.getOperand(3).getImm() != 0)
3836 return false;
3837
3838 AM.BaseReg = MemI.getOperand(1).getReg();
3839 if (AM.BaseReg == Reg)
3840 AM.BaseReg = MemI.getOperand(2).getReg();
3841 AM.ScaledReg = DefMI.getOperand(2).getReg();
3842 AM.Scale = OffsetScale;
3843 AM.Displacement = 0;
3845 return true;
3846 }
3847 }
3848 }
3849
3850 // Handle memory instructions with a [Reg, #Imm] addressing mode.
3851
3852 // Check we are not breaking a potential conversion to an LDP.
3853 auto validateOffsetForLDP = [](unsigned NumBytes, int64_t OldOffset,
3854 int64_t NewOffset) -> bool {
3855 int64_t MinOffset, MaxOffset;
3856 switch (NumBytes) {
3857 default:
3858 return true;
3859 case 4:
3860 MinOffset = -256;
3861 MaxOffset = 252;
3862 break;
3863 case 8:
3864 MinOffset = -512;
3865 MaxOffset = 504;
3866 break;
3867 case 16:
3868 MinOffset = -1024;
3869 MaxOffset = 1008;
3870 break;
3871 }
3872 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3873 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3874 };
3875 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) -> bool {
3876 int64_t OldOffset = MemI.getOperand(2).getImm() * OffsetScale;
3877 int64_t NewOffset = OldOffset + Disp;
3878 if (!isLegalAddressingMode(NumBytes, NewOffset, /* Scale */ 0))
3879 return false;
3880 // If the old offset would fit into an LDP, but the new offset wouldn't,
3881 // bail out.
3882 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3883 return false;
3884 AM.BaseReg = AddrI.getOperand(1).getReg();
3885 AM.ScaledReg = 0;
3886 AM.Scale = 0;
3887 AM.Displacement = NewOffset;
3889 return true;
3890 };
3891
3892 auto canFoldAddRegIntoAddrMode =
3893 [&](int64_t Scale,
3895 if (MemI.getOperand(2).getImm() != 0)
3896 return false;
3897 if ((unsigned)Scale != Scale)
3898 return false;
3899 if (!isLegalAddressingMode(NumBytes, /* Offset */ 0, Scale))
3900 return false;
3901 AM.BaseReg = AddrI.getOperand(1).getReg();
3902 AM.ScaledReg = AddrI.getOperand(2).getReg();
3903 AM.Scale = Scale;
3904 AM.Displacement = 0;
3905 AM.Form = Form;
3906 return true;
3907 };
3908
3909 auto avoidSlowSTRQ = [&](const MachineInstr &MemI) {
3910 unsigned Opcode = MemI.getOpcode();
3911 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3912 Subtarget.isSTRQroSlow();
3913 };
3914
3915 int64_t Disp = 0;
3916 const bool OptSize = MemI.getMF()->getFunction().hasOptSize();
3917 switch (AddrI.getOpcode()) {
3918 default:
3919 return false;
3920
3921 case AArch64::ADDXri:
3922 // add Xa, Xn, #N
3923 // ldr Xd, [Xa, #M]
3924 // ->
3925 // ldr Xd, [Xn, #N'+M]
3926 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3927 return canFoldAddSubImmIntoAddrMode(Disp);
3928
3929 case AArch64::SUBXri:
3930 // sub Xa, Xn, #N
3931 // ldr Xd, [Xa, #M]
3932 // ->
3933 // ldr Xd, [Xn, #N'+M]
3934 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3935 return canFoldAddSubImmIntoAddrMode(-Disp);
3936
3937 case AArch64::ADDXrs: {
3938 // add Xa, Xn, Xm, lsl #N
3939 // ldr Xd, [Xa]
3940 // ->
3941 // ldr Xd, [Xn, Xm, lsl #N]
3942
3943 // Don't fold the add if the result would be slower, unless optimising for
3944 // size.
3945 unsigned Shift = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3947 return false;
3948 Shift = AArch64_AM::getShiftValue(Shift);
3949 if (!OptSize) {
3950 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3951 return false;
3952 if (avoidSlowSTRQ(MemI))
3953 return false;
3954 }
3955 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3956 }
3957
3958 case AArch64::ADDXrr:
3959 // add Xa, Xn, Xm
3960 // ldr Xd, [Xa]
3961 // ->
3962 // ldr Xd, [Xn, Xm, lsl #0]
3963
3964 // Don't fold the add if the result would be slower, unless optimising for
3965 // size.
3966 if (!OptSize && avoidSlowSTRQ(MemI))
3967 return false;
3968 return canFoldAddRegIntoAddrMode(1);
3969
3970 case AArch64::ADDXrx:
3971 // add Xa, Xn, Wm, {s,u}xtw #N
3972 // ldr Xd, [Xa]
3973 // ->
3974 // ldr Xd, [Xn, Wm, {s,u}xtw #N]
3975
3976 // Don't fold the add if the result would be slower, unless optimising for
3977 // size.
3978 if (!OptSize && avoidSlowSTRQ(MemI))
3979 return false;
3980
3981 // Can fold only sign-/zero-extend of a word.
3982 unsigned Imm = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3984 if (Extend != AArch64_AM::UXTW && Extend != AArch64_AM::SXTW)
3985 return false;
3986
3987 return canFoldAddRegIntoAddrMode(
3991 }
3992}
3993
3994// Given an opcode for an instruction with a [Reg, #Imm] addressing mode,
3995// return the opcode of an instruction performing the same operation, but using
3996// the [Reg, Reg] addressing mode.
3997static unsigned regOffsetOpcode(unsigned Opcode) {
3998 switch (Opcode) {
3999 default:
4000 llvm_unreachable("Address folding not implemented for instruction");
4001
4002 case AArch64::LDURQi:
4003 case AArch64::LDRQui:
4004 return AArch64::LDRQroX;
4005 case AArch64::STURQi:
4006 case AArch64::STRQui:
4007 return AArch64::STRQroX;
4008 case AArch64::LDURDi:
4009 case AArch64::LDRDui:
4010 return AArch64::LDRDroX;
4011 case AArch64::STURDi:
4012 case AArch64::STRDui:
4013 return AArch64::STRDroX;
4014 case AArch64::LDURXi:
4015 case AArch64::LDRXui:
4016 return AArch64::LDRXroX;
4017 case AArch64::STURXi:
4018 case AArch64::STRXui:
4019 return AArch64::STRXroX;
4020 case AArch64::LDURWi:
4021 case AArch64::LDRWui:
4022 return AArch64::LDRWroX;
4023 case AArch64::LDURSWi:
4024 case AArch64::LDRSWui:
4025 return AArch64::LDRSWroX;
4026 case AArch64::STURWi:
4027 case AArch64::STRWui:
4028 return AArch64::STRWroX;
4029 case AArch64::LDURHi:
4030 case AArch64::LDRHui:
4031 return AArch64::LDRHroX;
4032 case AArch64::STURHi:
4033 case AArch64::STRHui:
4034 return AArch64::STRHroX;
4035 case AArch64::LDURHHi:
4036 case AArch64::LDRHHui:
4037 return AArch64::LDRHHroX;
4038 case AArch64::STURHHi:
4039 case AArch64::STRHHui:
4040 return AArch64::STRHHroX;
4041 case AArch64::LDURSHXi:
4042 case AArch64::LDRSHXui:
4043 return AArch64::LDRSHXroX;
4044 case AArch64::LDURSHWi:
4045 case AArch64::LDRSHWui:
4046 return AArch64::LDRSHWroX;
4047 case AArch64::LDURBi:
4048 case AArch64::LDRBui:
4049 return AArch64::LDRBroX;
4050 case AArch64::LDURBBi:
4051 case AArch64::LDRBBui:
4052 return AArch64::LDRBBroX;
4053 case AArch64::LDURSBXi:
4054 case AArch64::LDRSBXui:
4055 return AArch64::LDRSBXroX;
4056 case AArch64::LDURSBWi:
4057 case AArch64::LDRSBWui:
4058 return AArch64::LDRSBWroX;
4059 case AArch64::STURBi:
4060 case AArch64::STRBui:
4061 return AArch64::STRBroX;
4062 case AArch64::STURBBi:
4063 case AArch64::STRBBui:
4064 return AArch64::STRBBroX;
4065 }
4066}
4067
4068// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4069// the opcode of an instruction performing the same operation, but using the
4070// [Reg, #Imm] addressing mode with scaled offset.
4071unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale) {
4072 switch (Opcode) {
4073 default:
4074 llvm_unreachable("Address folding not implemented for instruction");
4075
4076 case AArch64::LDURQi:
4077 Scale = 16;
4078 return AArch64::LDRQui;
4079 case AArch64::STURQi:
4080 Scale = 16;
4081 return AArch64::STRQui;
4082 case AArch64::LDURDi:
4083 Scale = 8;
4084 return AArch64::LDRDui;
4085 case AArch64::STURDi:
4086 Scale = 8;
4087 return AArch64::STRDui;
4088 case AArch64::LDURXi:
4089 Scale = 8;
4090 return AArch64::LDRXui;
4091 case AArch64::STURXi:
4092 Scale = 8;
4093 return AArch64::STRXui;
4094 case AArch64::LDURWi:
4095 Scale = 4;
4096 return AArch64::LDRWui;
4097 case AArch64::LDURSWi:
4098 Scale = 4;
4099 return AArch64::LDRSWui;
4100 case AArch64::STURWi:
4101 Scale = 4;
4102 return AArch64::STRWui;
4103 case AArch64::LDURHi:
4104 Scale = 2;
4105 return AArch64::LDRHui;
4106 case AArch64::STURHi:
4107 Scale = 2;
4108 return AArch64::STRHui;
4109 case AArch64::LDURHHi:
4110 Scale = 2;
4111 return AArch64::LDRHHui;
4112 case AArch64::STURHHi:
4113 Scale = 2;
4114 return AArch64::STRHHui;
4115 case AArch64::LDURSHXi:
4116 Scale = 2;
4117 return AArch64::LDRSHXui;
4118 case AArch64::LDURSHWi:
4119 Scale = 2;
4120 return AArch64::LDRSHWui;
4121 case AArch64::LDURBi:
4122 Scale = 1;
4123 return AArch64::LDRBui;
4124 case AArch64::LDURBBi:
4125 Scale = 1;
4126 return AArch64::LDRBBui;
4127 case AArch64::LDURSBXi:
4128 Scale = 1;
4129 return AArch64::LDRSBXui;
4130 case AArch64::LDURSBWi:
4131 Scale = 1;
4132 return AArch64::LDRSBWui;
4133 case AArch64::STURBi:
4134 Scale = 1;
4135 return AArch64::STRBui;
4136 case AArch64::STURBBi:
4137 Scale = 1;
4138 return AArch64::STRBBui;
4139 case AArch64::LDRQui:
4140 case AArch64::STRQui:
4141 Scale = 16;
4142 return Opcode;
4143 case AArch64::LDRDui:
4144 case AArch64::STRDui:
4145 case AArch64::LDRXui:
4146 case AArch64::STRXui:
4147 Scale = 8;
4148 return Opcode;
4149 case AArch64::LDRWui:
4150 case AArch64::LDRSWui:
4151 case AArch64::STRWui:
4152 Scale = 4;
4153 return Opcode;
4154 case AArch64::LDRHui:
4155 case AArch64::STRHui:
4156 case AArch64::LDRHHui:
4157 case AArch64::STRHHui:
4158 case AArch64::LDRSHXui:
4159 case AArch64::LDRSHWui:
4160 Scale = 2;
4161 return Opcode;
4162 case AArch64::LDRBui:
4163 case AArch64::LDRBBui:
4164 case AArch64::LDRSBXui:
4165 case AArch64::LDRSBWui:
4166 case AArch64::STRBui:
4167 case AArch64::STRBBui:
4168 Scale = 1;
4169 return Opcode;
4170 }
4171}
4172
4173// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4174// the opcode of an instruction performing the same operation, but using the
4175// [Reg, #Imm] addressing mode with unscaled offset.
4176unsigned unscaledOffsetOpcode(unsigned Opcode) {
4177 switch (Opcode) {
4178 default:
4179 llvm_unreachable("Address folding not implemented for instruction");
4180
4181 case AArch64::LDURQi:
4182 case AArch64::STURQi:
4183 case AArch64::LDURDi:
4184 case AArch64::STURDi:
4185 case AArch64::LDURXi:
4186 case AArch64::STURXi:
4187 case AArch64::LDURWi:
4188 case AArch64::LDURSWi:
4189 case AArch64::STURWi:
4190 case AArch64::LDURHi:
4191 case AArch64::STURHi:
4192 case AArch64::LDURHHi:
4193 case AArch64::STURHHi:
4194 case AArch64::LDURSHXi:
4195 case AArch64::LDURSHWi:
4196 case AArch64::LDURBi:
4197 case AArch64::STURBi:
4198 case AArch64::LDURBBi:
4199 case AArch64::STURBBi:
4200 case AArch64::LDURSBWi:
4201 case AArch64::LDURSBXi:
4202 return Opcode;
4203 case AArch64::LDRQui:
4204 return AArch64::LDURQi;
4205 case AArch64::STRQui:
4206 return AArch64::STURQi;
4207 case AArch64::LDRDui:
4208 return AArch64::LDURDi;
4209 case AArch64::STRDui:
4210 return AArch64::STURDi;
4211 case AArch64::LDRXui:
4212 return AArch64::LDURXi;
4213 case AArch64::STRXui:
4214 return AArch64::STURXi;
4215 case AArch64::LDRWui:
4216 return AArch64::LDURWi;
4217 case AArch64::LDRSWui:
4218 return AArch64::LDURSWi;
4219 case AArch64::STRWui:
4220 return AArch64::STURWi;
4221 case AArch64::LDRHui:
4222 return AArch64::LDURHi;
4223 case AArch64::STRHui:
4224 return AArch64::STURHi;
4225 case AArch64::LDRHHui:
4226 return AArch64::LDURHHi;
4227 case AArch64::STRHHui:
4228 return AArch64::STURHHi;
4229 case AArch64::LDRSHXui:
4230 return AArch64::LDURSHXi;
4231 case AArch64::LDRSHWui:
4232 return AArch64::LDURSHWi;
4233 case AArch64::LDRBBui:
4234 return AArch64::LDURBBi;
4235 case AArch64::LDRBui:
4236 return AArch64::LDURBi;
4237 case AArch64::STRBBui:
4238 return AArch64::STURBBi;
4239 case AArch64::STRBui:
4240 return AArch64::STURBi;
4241 case AArch64::LDRSBWui:
4242 return AArch64::LDURSBWi;
4243 case AArch64::LDRSBXui:
4244 return AArch64::LDURSBXi;
4245 }
4246}
4247
4248// Given the opcode of a memory load/store instruction, return the opcode of an
4249// instruction performing the same operation, but using
4250// the [Reg, Reg, {s,u}xtw #N] addressing mode with sign-/zero-extend of the
4251// offset register.
4252static unsigned offsetExtendOpcode(unsigned Opcode) {
4253 switch (Opcode) {
4254 default:
4255 llvm_unreachable("Address folding not implemented for instruction");
4256
4257 case AArch64::LDRQroX:
4258 case AArch64::LDURQi:
4259 case AArch64::LDRQui:
4260 return AArch64::LDRQroW;
4261 case AArch64::STRQroX:
4262 case AArch64::STURQi:
4263 case AArch64::STRQui:
4264 return AArch64::STRQroW;
4265 case AArch64::LDRDroX:
4266 case AArch64::LDURDi:
4267 case AArch64::LDRDui:
4268 return AArch64::LDRDroW;
4269 case AArch64::STRDroX:
4270 case AArch64::STURDi:
4271 case AArch64::STRDui:
4272 return AArch64::STRDroW;
4273 case AArch64::LDRXroX:
4274 case AArch64::LDURXi:
4275 case AArch64::LDRXui:
4276 return AArch64::LDRXroW;
4277 case AArch64::STRXroX:
4278 case AArch64::STURXi:
4279 case AArch64::STRXui:
4280 return AArch64::STRXroW;
4281 case AArch64::LDRWroX:
4282 case AArch64::LDURWi:
4283 case AArch64::LDRWui:
4284 return AArch64::LDRWroW;
4285 case AArch64::LDRSWroX:
4286 case AArch64::LDURSWi:
4287 case AArch64::LDRSWui:
4288 return AArch64::LDRSWroW;
4289 case AArch64::STRWroX:
4290 case AArch64::STURWi:
4291 case AArch64::STRWui:
4292 return AArch64::STRWroW;
4293 case AArch64::LDRHroX:
4294 case AArch64::LDURHi:
4295 case AArch64::LDRHui:
4296 return AArch64::LDRHroW;
4297 case AArch64::STRHroX:
4298 case AArch64::STURHi:
4299 case AArch64::STRHui:
4300 return AArch64::STRHroW;
4301 case AArch64::LDRHHroX:
4302 case AArch64::LDURHHi:
4303 case AArch64::LDRHHui:
4304 return AArch64::LDRHHroW;
4305 case AArch64::STRHHroX:
4306 case AArch64::STURHHi:
4307 case AArch64::STRHHui:
4308 return AArch64::STRHHroW;
4309 case AArch64::LDRSHXroX:
4310 case AArch64::LDURSHXi:
4311 case AArch64::LDRSHXui:
4312 return AArch64::LDRSHXroW;
4313 case AArch64::LDRSHWroX:
4314 case AArch64::LDURSHWi:
4315 case AArch64::LDRSHWui:
4316 return AArch64::LDRSHWroW;
4317 case AArch64::LDRBroX:
4318 case AArch64::LDURBi:
4319 case AArch64::LDRBui:
4320 return AArch64::LDRBroW;
4321 case AArch64::LDRBBroX:
4322 case AArch64::LDURBBi:
4323 case AArch64::LDRBBui:
4324 return AArch64::LDRBBroW;
4325 case AArch64::LDRSBXroX:
4326 case AArch64::LDURSBXi:
4327 case AArch64::LDRSBXui:
4328 return AArch64::LDRSBXroW;
4329 case AArch64::LDRSBWroX:
4330 case AArch64::LDURSBWi:
4331 case AArch64::LDRSBWui:
4332 return AArch64::LDRSBWroW;
4333 case AArch64::STRBroX:
4334 case AArch64::STURBi:
4335 case AArch64::STRBui:
4336 return AArch64::STRBroW;
4337 case AArch64::STRBBroX:
4338 case AArch64::STURBBi:
4339 case AArch64::STRBBui:
4340 return AArch64::STRBBroW;
4341 }
4342}
4343
4345 const ExtAddrMode &AM) const {
4346
4347 const DebugLoc &DL = MemI.getDebugLoc();
4348 MachineBasicBlock &MBB = *MemI.getParent();
4349 MachineRegisterInfo &MRI = MemI.getMF()->getRegInfo();
4350
4352 if (AM.ScaledReg) {
4353 // The new instruction will be in the form `ldr Rt, [Xn, Xm, lsl #imm]`.
4354 unsigned Opcode = regOffsetOpcode(MemI.getOpcode());
4355 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4356 auto B = BuildMI(MBB, MemI, DL, get(Opcode))
4357 .addReg(MemI.getOperand(0).getReg(),
4358 getDefRegState(MemI.mayLoad()))
4359 .addReg(AM.BaseReg)
4360 .addReg(AM.ScaledReg)
4361 .addImm(0)
4362 .addImm(AM.Scale > 1)
4363 .setMemRefs(MemI.memoperands())
4364 .setMIFlags(MemI.getFlags());
4365 return B.getInstr();
4366 }
4367
4368 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
4369 "Addressing mode not supported for folding");
4370
4371 // The new instruction will be in the form `ld[u]r Rt, [Xn, #imm]`.
4372 unsigned Scale = 1;
4373 unsigned Opcode = MemI.getOpcode();
4374 if (isInt<9>(AM.Displacement))
4375 Opcode = unscaledOffsetOpcode(Opcode);
4376 else
4377 Opcode = scaledOffsetOpcode(Opcode, Scale);
4378
4379 auto B =
4380 BuildMI(MBB, MemI, DL, get(Opcode))
4381 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4382 .addReg(AM.BaseReg)
4383 .addImm(AM.Displacement / Scale)
4384 .setMemRefs(MemI.memoperands())
4385 .setMIFlags(MemI.getFlags());
4386 return B.getInstr();
4387 }
4388
4391 // The new instruction will be in the form `ldr Rt, [Xn, Wm, {s,u}xtw #N]`.
4392 assert(AM.ScaledReg && !AM.Displacement &&
4393 "Address offset can be a register or an immediate, but not both");
4394 unsigned Opcode = offsetExtendOpcode(MemI.getOpcode());
4395 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4396 // Make sure the offset register is in the correct register class.
4397 Register OffsetReg = AM.ScaledReg;
4398 const TargetRegisterClass *RC = MRI.getRegClass(OffsetReg);
4399 if (RC->hasSuperClassEq(&AArch64::GPR64RegClass)) {
4400 OffsetReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
4401 BuildMI(MBB, MemI, DL, get(TargetOpcode::COPY), OffsetReg)
4402 .addReg(AM.ScaledReg, {}, AArch64::sub_32);
4403 }
4404 auto B =
4405 BuildMI(MBB, MemI, DL, get(Opcode))
4406 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4407 .addReg(AM.BaseReg)
4408 .addReg(OffsetReg)
4410 .addImm(AM.Scale != 1)
4411 .setMemRefs(MemI.memoperands())
4412 .setMIFlags(MemI.getFlags());
4413
4414 return B.getInstr();
4415 }
4416
4418 "Function must not be called with an addressing mode it can't handle");
4419}
4420
4421/// Return true if the opcode is a post-index ld/st instruction, which really
4422/// loads from base+0.
4423static bool isPostIndexLdStOpcode(unsigned Opcode) {
4424 switch (Opcode) {
4425 default:
4426 return false;
4427 case AArch64::LD1Fourv16b_POST:
4428 case AArch64::LD1Fourv1d_POST:
4429 case AArch64::LD1Fourv2d_POST:
4430 case AArch64::LD1Fourv2s_POST:
4431 case AArch64::LD1Fourv4h_POST:
4432 case AArch64::LD1Fourv4s_POST:
4433 case AArch64::LD1Fourv8b_POST:
4434 case AArch64::LD1Fourv8h_POST:
4435 case AArch64::LD1Onev16b_POST:
4436 case AArch64::LD1Onev1d_POST:
4437 case AArch64::LD1Onev2d_POST:
4438 case AArch64::LD1Onev2s_POST:
4439 case AArch64::LD1Onev4h_POST:
4440 case AArch64::LD1Onev4s_POST:
4441 case AArch64::LD1Onev8b_POST:
4442 case AArch64::LD1Onev8h_POST:
4443 case AArch64::LD1Rv16b_POST:
4444 case AArch64::LD1Rv1d_POST:
4445 case AArch64::LD1Rv2d_POST:
4446 case AArch64::LD1Rv2s_POST:
4447 case AArch64::LD1Rv4h_POST:
4448 case AArch64::LD1Rv4s_POST:
4449 case AArch64::LD1Rv8b_POST:
4450 case AArch64::LD1Rv8h_POST:
4451 case AArch64::LD1Threev16b_POST:
4452 case AArch64::LD1Threev1d_POST:
4453 case AArch64::LD1Threev2d_POST:
4454 case AArch64::LD1Threev2s_POST:
4455 case AArch64::LD1Threev4h_POST:
4456 case AArch64::LD1Threev4s_POST:
4457 case AArch64::LD1Threev8b_POST:
4458 case AArch64::LD1Threev8h_POST:
4459 case AArch64::LD1Twov16b_POST:
4460 case AArch64::LD1Twov1d_POST:
4461 case AArch64::LD1Twov2d_POST:
4462 case AArch64::LD1Twov2s_POST:
4463 case AArch64::LD1Twov4h_POST:
4464 case AArch64::LD1Twov4s_POST:
4465 case AArch64::LD1Twov8b_POST:
4466 case AArch64::LD1Twov8h_POST:
4467 case AArch64::LD1i16_POST:
4468 case AArch64::LD1i32_POST:
4469 case AArch64::LD1i64_POST:
4470 case AArch64::LD1i8_POST:
4471 case AArch64::LD2Rv16b_POST:
4472 case AArch64::LD2Rv1d_POST:
4473 case AArch64::LD2Rv2d_POST:
4474 case AArch64::LD2Rv2s_POST:
4475 case AArch64::LD2Rv4h_POST:
4476 case AArch64::LD2Rv4s_POST:
4477 case AArch64::LD2Rv8b_POST:
4478 case AArch64::LD2Rv8h_POST:
4479 case AArch64::LD2Twov16b_POST:
4480 case AArch64::LD2Twov2d_POST:
4481 case AArch64::LD2Twov2s_POST:
4482 case AArch64::LD2Twov4h_POST:
4483 case AArch64::LD2Twov4s_POST:
4484 case AArch64::LD2Twov8b_POST:
4485 case AArch64::LD2Twov8h_POST:
4486 case AArch64::LD2i16_POST:
4487 case AArch64::LD2i32_POST:
4488 case AArch64::LD2i64_POST:
4489 case AArch64::LD2i8_POST:
4490 case AArch64::LD3Rv16b_POST:
4491 case AArch64::LD3Rv1d_POST:
4492 case AArch64::LD3Rv2d_POST:
4493 case AArch64::LD3Rv2s_POST:
4494 case AArch64::LD3Rv4h_POST:
4495 case AArch64::LD3Rv4s_POST:
4496 case AArch64::LD3Rv8b_POST:
4497 case AArch64::LD3Rv8h_POST:
4498 case AArch64::LD3Threev16b_POST:
4499 case AArch64::LD3Threev2d_POST:
4500 case AArch64::LD3Threev2s_POST:
4501 case AArch64::LD3Threev4h_POST:
4502 case AArch64::LD3Threev4s_POST:
4503 case AArch64::LD3Threev8b_POST:
4504 case AArch64::LD3Threev8h_POST:
4505 case AArch64::LD3i16_POST:
4506 case AArch64::LD3i32_POST:
4507 case AArch64::LD3i64_POST:
4508 case AArch64::LD3i8_POST:
4509 case AArch64::LD4Fourv16b_POST:
4510 case AArch64::LD4Fourv2d_POST:
4511 case AArch64::LD4Fourv2s_POST:
4512 case AArch64::LD4Fourv4h_POST:
4513 case AArch64::LD4Fourv4s_POST:
4514 case AArch64::LD4Fourv8b_POST:
4515 case AArch64::LD4Fourv8h_POST:
4516 case AArch64::LD4Rv16b_POST:
4517 case AArch64::LD4Rv1d_POST:
4518 case AArch64::LD4Rv2d_POST:
4519 case AArch64::LD4Rv2s_POST:
4520 case AArch64::LD4Rv4h_POST:
4521 case AArch64::LD4Rv4s_POST:
4522 case AArch64::LD4Rv8b_POST:
4523 case AArch64::LD4Rv8h_POST:
4524 case AArch64::LD4i16_POST:
4525 case AArch64::LD4i32_POST:
4526 case AArch64::LD4i64_POST:
4527 case AArch64::LD4i8_POST:
4528 case AArch64::LDAPRWpost:
4529 case AArch64::LDAPRXpost:
4530 case AArch64::LDIAPPWpost:
4531 case AArch64::LDIAPPXpost:
4532 case AArch64::LDPDpost:
4533 case AArch64::LDPQpost:
4534 case AArch64::LDPSWpost:
4535 case AArch64::LDPSpost:
4536 case AArch64::LDPWpost:
4537 case AArch64::LDPXpost:
4538 case AArch64::LDRBBpost:
4539 case AArch64::LDRBpost:
4540 case AArch64::LDRDpost:
4541 case AArch64::LDRHHpost:
4542 case AArch64::LDRHpost:
4543 case AArch64::LDRQpost:
4544 case AArch64::LDRSBWpost:
4545 case AArch64::LDRSBXpost:
4546 case AArch64::LDRSHWpost:
4547 case AArch64::LDRSHXpost:
4548 case AArch64::LDRSWpost:
4549 case AArch64::LDRSpost:
4550 case AArch64::LDRWpost:
4551 case AArch64::LDRXpost:
4552 case AArch64::ST1Fourv16b_POST:
4553 case AArch64::ST1Fourv1d_POST:
4554 case AArch64::ST1Fourv2d_POST:
4555 case AArch64::ST1Fourv2s_POST:
4556 case AArch64::ST1Fourv4h_POST:
4557 case AArch64::ST1Fourv4s_POST:
4558 case AArch64::ST1Fourv8b_POST:
4559 case AArch64::ST1Fourv8h_POST:
4560 case AArch64::ST1Onev16b_POST:
4561 case AArch64::ST1Onev1d_POST:
4562 case AArch64::ST1Onev2d_POST:
4563 case AArch64::ST1Onev2s_POST:
4564 case AArch64::ST1Onev4h_POST:
4565 case AArch64::ST1Onev4s_POST:
4566 case AArch64::ST1Onev8b_POST:
4567 case AArch64::ST1Onev8h_POST:
4568 case AArch64::ST1Threev16b_POST:
4569 case AArch64::ST1Threev1d_POST:
4570 case AArch64::ST1Threev2d_POST:
4571 case AArch64::ST1Threev2s_POST:
4572 case AArch64::ST1Threev4h_POST:
4573 case AArch64::ST1Threev4s_POST:
4574 case AArch64::ST1Threev8b_POST:
4575 case AArch64::ST1Threev8h_POST:
4576 case AArch64::ST1Twov16b_POST:
4577 case AArch64::ST1Twov1d_POST:
4578 case AArch64::ST1Twov2d_POST:
4579 case AArch64::ST1Twov2s_POST:
4580 case AArch64::ST1Twov4h_POST:
4581 case AArch64::ST1Twov4s_POST:
4582 case AArch64::ST1Twov8b_POST:
4583 case AArch64::ST1Twov8h_POST:
4584 case AArch64::ST1i16_POST:
4585 case AArch64::ST1i32_POST:
4586 case AArch64::ST1i64_POST:
4587 case AArch64::ST1i8_POST:
4588 case AArch64::ST2GPostIndex:
4589 case AArch64::ST2Twov16b_POST:
4590 case AArch64::ST2Twov2d_POST:
4591 case AArch64::ST2Twov2s_POST:
4592 case AArch64::ST2Twov4h_POST:
4593 case AArch64::ST2Twov4s_POST:
4594 case AArch64::ST2Twov8b_POST:
4595 case AArch64::ST2Twov8h_POST:
4596 case AArch64::ST2i16_POST:
4597 case AArch64::ST2i32_POST:
4598 case AArch64::ST2i64_POST:
4599 case AArch64::ST2i8_POST:
4600 case AArch64::ST3Threev16b_POST:
4601 case AArch64::ST3Threev2d_POST:
4602 case AArch64::ST3Threev2s_POST:
4603 case AArch64::ST3Threev4h_POST:
4604 case AArch64::ST3Threev4s_POST:
4605 case AArch64::ST3Threev8b_POST:
4606 case AArch64::ST3Threev8h_POST:
4607 case AArch64::ST3i16_POST:
4608 case AArch64::ST3i32_POST:
4609 case AArch64::ST3i64_POST:
4610 case AArch64::ST3i8_POST:
4611 case AArch64::ST4Fourv16b_POST:
4612 case AArch64::ST4Fourv2d_POST:
4613 case AArch64::ST4Fourv2s_POST:
4614 case AArch64::ST4Fourv4h_POST:
4615 case AArch64::ST4Fourv4s_POST:
4616 case AArch64::ST4Fourv8b_POST:
4617 case AArch64::ST4Fourv8h_POST:
4618 case AArch64::ST4i16_POST:
4619 case AArch64::ST4i32_POST:
4620 case AArch64::ST4i64_POST:
4621 case AArch64::ST4i8_POST:
4622 case AArch64::STGPostIndex:
4623 case AArch64::STGPpost:
4624 case AArch64::STPDpost:
4625 case AArch64::STPQpost:
4626 case AArch64::STPSpost:
4627 case AArch64::STPWpost:
4628 case AArch64::STPXpost:
4629 case AArch64::STRBBpost:
4630 case AArch64::STRBpost:
4631 case AArch64::STRDpost:
4632 case AArch64::STRHHpost:
4633 case AArch64::STRHpost:
4634 case AArch64::STRQpost:
4635 case AArch64::STRSpost:
4636 case AArch64::STRWpost:
4637 case AArch64::STRXpost:
4638 case AArch64::STZ2GPostIndex:
4639 case AArch64::STZGPostIndex:
4640 return true;
4641 }
4642}
4643
4645 const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset,
4646 bool &OffsetIsScalable, TypeSize &Width,
4647 const TargetRegisterInfo *TRI) const {
4648 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4649 // Handle only loads/stores with base register followed by immediate offset.
4650 if (LdSt.getNumExplicitOperands() == 3) {
4651 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
4652 if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
4653 !LdSt.getOperand(2).isImm())
4654 return false;
4655 } else if (LdSt.getNumExplicitOperands() == 4) {
4656 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
4657 if (!LdSt.getOperand(1).isReg() ||
4658 (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI()) ||
4659 !LdSt.getOperand(3).isImm())
4660 return false;
4661 } else
4662 return false;
4663
4664 // Get the scaling factor for the instruction and set the width for the
4665 // instruction.
4666 TypeSize Scale(0U, false);
4667 int64_t Dummy1, Dummy2;
4668
4669 // If this returns false, then it's an instruction we don't want to handle.
4670 if (!getMemOpInfo(LdSt.getOpcode(), Scale, Width, Dummy1, Dummy2))
4671 return false;
4672
4673 // Compute the offset. Offset is calculated as the immediate operand
4674 // multiplied by the scaling factor. Unscaled instructions have scaling factor
4675 // set to 1. Postindex are a special case which have an offset of 0.
4676 if (isPostIndexLdStOpcode(LdSt.getOpcode())) {
4677 BaseOp = &LdSt.getOperand(2);
4678 Offset = 0;
4679 } else if (LdSt.getNumExplicitOperands() == 3) {
4680 BaseOp = &LdSt.getOperand(1);
4681 Offset = LdSt.getOperand(2).getImm() * Scale.getKnownMinValue();
4682 } else {
4683 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
4684 BaseOp = &LdSt.getOperand(2);
4685 Offset = LdSt.getOperand(3).getImm() * Scale.getKnownMinValue();
4686 }
4687 OffsetIsScalable = Scale.isScalable();
4688
4689 return BaseOp->isReg() || BaseOp->isFI();
4690}
4691
4694 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4695 MachineOperand &OfsOp = LdSt.getOperand(LdSt.getNumExplicitOperands() - 1);
4696 assert(OfsOp.isImm() && "Offset operand wasn't immediate.");
4697 return OfsOp;
4698}
4699
4700bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale,
4701 TypeSize &Width, int64_t &MinOffset,
4702 int64_t &MaxOffset) {
4703 switch (Opcode) {
4704 // Not a memory operation or something we want to handle.
4705 default:
4706 Scale = Width = TypeSize::getFixed(0);
4707 MinOffset = MaxOffset = 0;
4708 return false;
4709 // LDR / STR
4710 case AArch64::LDRQui:
4711 case AArch64::STRQui:
4712 Scale = Width = TypeSize::getFixed(16);
4713 MinOffset = 0;
4714 MaxOffset = 4095;
4715 break;
4716 case AArch64::LDRXui:
4717 case AArch64::LDRDui:
4718 case AArch64::STRXui:
4719 case AArch64::STRDui:
4720 case AArch64::PRFMui:
4721 Scale = Width = TypeSize::getFixed(8);
4722 MinOffset = 0;
4723 MaxOffset = 4095;
4724 break;
4725 case AArch64::LDRWui:
4726 case AArch64::LDRSui:
4727 case AArch64::LDRSWui:
4728 case AArch64::STRWui:
4729 case AArch64::STRSui:
4730 Scale = Width = TypeSize::getFixed(4);
4731 MinOffset = 0;
4732 MaxOffset = 4095;
4733 break;
4734 case AArch64::LDRHui:
4735 case AArch64::LDRHHui:
4736 case AArch64::LDRSHWui:
4737 case AArch64::LDRSHXui:
4738 case AArch64::STRHui:
4739 case AArch64::STRHHui:
4740 Scale = Width = TypeSize::getFixed(2);
4741 MinOffset = 0;
4742 MaxOffset = 4095;
4743 break;
4744 case AArch64::LDRBui:
4745 case AArch64::LDRBBui:
4746 case AArch64::LDRSBWui:
4747 case AArch64::LDRSBXui:
4748 case AArch64::STRBui:
4749 case AArch64::STRBBui:
4750 Scale = Width = TypeSize::getFixed(1);
4751 MinOffset = 0;
4752 MaxOffset = 4095;
4753 break;
4754 // post/pre inc
4755 case AArch64::STRQpre:
4756 case AArch64::LDRQpost:
4757 Scale = TypeSize::getFixed(1);
4758 Width = TypeSize::getFixed(16);
4759 MinOffset = -256;
4760 MaxOffset = 255;
4761 break;
4762 case AArch64::LDRDpost:
4763 case AArch64::LDRDpre:
4764 case AArch64::LDRXpost:
4765 case AArch64::LDRXpre:
4766 case AArch64::STRDpost:
4767 case AArch64::STRDpre:
4768 case AArch64::STRXpost:
4769 case AArch64::STRXpre:
4770 Scale = TypeSize::getFixed(1);
4771 Width = TypeSize::getFixed(8);
4772 MinOffset = -256;
4773 MaxOffset = 255;
4774 break;
4775 case AArch64::STRWpost:
4776 case AArch64::STRWpre:
4777 case AArch64::LDRWpost:
4778 case AArch64::LDRWpre:
4779 case AArch64::STRSpost:
4780 case AArch64::STRSpre:
4781 case AArch64::LDRSpost:
4782 case AArch64::LDRSpre:
4783 Scale = TypeSize::getFixed(1);
4784 Width = TypeSize::getFixed(4);
4785 MinOffset = -256;
4786 MaxOffset = 255;
4787 break;
4788 case AArch64::LDRHpost:
4789 case AArch64::LDRHpre:
4790 case AArch64::STRHpost:
4791 case AArch64::STRHpre:
4792 case AArch64::LDRHHpost:
4793 case AArch64::LDRHHpre:
4794 case AArch64::STRHHpost:
4795 case AArch64::STRHHpre:
4796 Scale = TypeSize::getFixed(1);
4797 Width = TypeSize::getFixed(2);
4798 MinOffset = -256;
4799 MaxOffset = 255;
4800 break;
4801 case AArch64::LDRBpost:
4802 case AArch64::LDRBpre:
4803 case AArch64::STRBpost:
4804 case AArch64::STRBpre:
4805 case AArch64::LDRBBpost:
4806 case AArch64::LDRBBpre:
4807 case AArch64::STRBBpost:
4808 case AArch64::STRBBpre:
4809 Scale = Width = TypeSize::getFixed(1);
4810 MinOffset = -256;
4811 MaxOffset = 255;
4812 break;
4813 // Unscaled
4814 case AArch64::LDURQi:
4815 case AArch64::STURQi:
4816 Scale = TypeSize::getFixed(1);
4817 Width = TypeSize::getFixed(16);
4818 MinOffset = -256;
4819 MaxOffset = 255;
4820 break;
4821 case AArch64::LDURXi:
4822 case AArch64::LDURDi:
4823 case AArch64::LDAPURXi:
4824 case AArch64::STURXi:
4825 case AArch64::STURDi:
4826 case AArch64::STLURXi:
4827 case AArch64::PRFUMi:
4828 Scale = TypeSize::getFixed(1);
4829 Width = TypeSize::getFixed(8);
4830 MinOffset = -256;
4831 MaxOffset = 255;
4832 break;
4833 case AArch64::LDURWi:
4834 case AArch64::LDURSi:
4835 case AArch64::LDURSWi:
4836 case AArch64::LDAPURi:
4837 case AArch64::LDAPURSWi:
4838 case AArch64::STURWi:
4839 case AArch64::STURSi:
4840 case AArch64::STLURWi:
4841 Scale = TypeSize::getFixed(1);
4842 Width = TypeSize::getFixed(4);
4843 MinOffset = -256;
4844 MaxOffset = 255;
4845 break;
4846 case AArch64::LDURHi:
4847 case AArch64::LDURHHi:
4848 case AArch64::LDURSHXi:
4849 case AArch64::LDURSHWi:
4850 case AArch64::LDAPURHi:
4851 case AArch64::LDAPURSHWi:
4852 case AArch64::LDAPURSHXi:
4853 case AArch64::STURHi:
4854 case AArch64::STURHHi:
4855 case AArch64::STLURHi:
4856 Scale = TypeSize::getFixed(1);
4857 Width = TypeSize::getFixed(2);
4858 MinOffset = -256;
4859 MaxOffset = 255;
4860 break;
4861 case AArch64::LDURBi:
4862 case AArch64::LDURBBi:
4863 case AArch64::LDURSBXi:
4864 case AArch64::LDURSBWi:
4865 case AArch64::LDAPURBi:
4866 case AArch64::LDAPURSBWi:
4867 case AArch64::LDAPURSBXi:
4868 case AArch64::STURBi:
4869 case AArch64::STURBBi:
4870 case AArch64::STLURBi:
4871 Scale = Width = TypeSize::getFixed(1);
4872 MinOffset = -256;
4873 MaxOffset = 255;
4874 break;
4875 // LDP / STP (including pre/post inc)
4876 case AArch64::LDPQi:
4877 case AArch64::LDNPQi:
4878 case AArch64::STPQi:
4879 case AArch64::STNPQi:
4880 case AArch64::LDPQpost:
4881 case AArch64::LDPQpre:
4882 case AArch64::STPQpost:
4883 case AArch64::STPQpre:
4884 Scale = TypeSize::getFixed(16);
4885 Width = TypeSize::getFixed(16 * 2);
4886 MinOffset = -64;
4887 MaxOffset = 63;
4888 break;
4889 case AArch64::LDPXi:
4890 case AArch64::LDPDi:
4891 case AArch64::LDNPXi:
4892 case AArch64::LDNPDi:
4893 case AArch64::STPXi:
4894 case AArch64::STPDi:
4895 case AArch64::STNPXi:
4896 case AArch64::STNPDi:
4897 case AArch64::LDPDpost:
4898 case AArch64::LDPDpre:
4899 case AArch64::LDPXpost:
4900 case AArch64::LDPXpre:
4901 case AArch64::STPDpost:
4902 case AArch64::STPDpre:
4903 case AArch64::STPXpost:
4904 case AArch64::STPXpre:
4905 Scale = TypeSize::getFixed(8);
4906 Width = TypeSize::getFixed(8 * 2);
4907 MinOffset = -64;
4908 MaxOffset = 63;
4909 break;
4910 case AArch64::LDPWi:
4911 case AArch64::LDPSi:
4912 case AArch64::LDNPWi:
4913 case AArch64::LDNPSi:
4914 case AArch64::STPWi:
4915 case AArch64::STPSi:
4916 case AArch64::STNPWi:
4917 case AArch64::STNPSi:
4918 case AArch64::LDPSpost:
4919 case AArch64::LDPSpre:
4920 case AArch64::LDPWpost:
4921 case AArch64::LDPWpre:
4922 case AArch64::STPSpost:
4923 case AArch64::STPSpre:
4924 case AArch64::STPWpost:
4925 case AArch64::STPWpre:
4926 Scale = TypeSize::getFixed(4);
4927 Width = TypeSize::getFixed(4 * 2);
4928 MinOffset = -64;
4929 MaxOffset = 63;
4930 break;
4931 case AArch64::StoreSwiftAsyncContext:
4932 // Store is an STRXui, but there might be an ADDXri in the expansion too.
4933 Scale = TypeSize::getFixed(1);
4934 Width = TypeSize::getFixed(8);
4935 MinOffset = 0;
4936 MaxOffset = 4095;
4937 break;
4938 case AArch64::ADDG:
4939 Scale = TypeSize::getFixed(16);
4940 Width = TypeSize::getFixed(0);
4941 MinOffset = 0;
4942 MaxOffset = 63;
4943 break;
4944 case AArch64::TAGPstack:
4945 Scale = TypeSize::getFixed(16);
4946 Width = TypeSize::getFixed(0);
4947 // TAGP with a negative offset turns into SUBP, which has a maximum offset
4948 // of 63 (not 64!).
4949 MinOffset = -63;
4950 MaxOffset = 63;
4951 break;
4952 case AArch64::LDG:
4953 case AArch64::STGi:
4954 case AArch64::STGPreIndex:
4955 case AArch64::STGPostIndex:
4956 case AArch64::STZGi:
4957 case AArch64::STZGPreIndex:
4958 case AArch64::STZGPostIndex:
4959 Scale = Width = TypeSize::getFixed(16);
4960 MinOffset = -256;
4961 MaxOffset = 255;
4962 break;
4963 // SVE
4964 case AArch64::STR_ZZZZXI:
4965 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4966 case AArch64::LDR_ZZZZXI:
4967 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4968 Scale = TypeSize::getScalable(16);
4969 Width = TypeSize::getScalable(16 * 4);
4970 MinOffset = -256;
4971 MaxOffset = 252;
4972 break;
4973 case AArch64::STR_ZZZXI:
4974 case AArch64::LDR_ZZZXI:
4975 Scale = TypeSize::getScalable(16);
4976 Width = TypeSize::getScalable(16 * 3);
4977 MinOffset = -256;
4978 MaxOffset = 253;
4979 break;
4980 case AArch64::STR_ZZXI:
4981 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4982 case AArch64::LDR_ZZXI:
4983 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4984 Scale = TypeSize::getScalable(16);
4985 Width = TypeSize::getScalable(16 * 2);
4986 MinOffset = -256;
4987 MaxOffset = 254;
4988 break;
4989 case AArch64::LDR_PXI:
4990 case AArch64::STR_PXI:
4991 Scale = Width = TypeSize::getScalable(2);
4992 MinOffset = -256;
4993 MaxOffset = 255;
4994 break;
4995 case AArch64::LDR_PPXI:
4996 case AArch64::STR_PPXI:
4997 Scale = TypeSize::getScalable(2);
4998 Width = TypeSize::getScalable(2 * 2);
4999 MinOffset = -256;
5000 MaxOffset = 254;
5001 break;
5002 case AArch64::LDR_ZXI:
5003 case AArch64::STR_ZXI:
5004 Scale = Width = TypeSize::getScalable(16);
5005 MinOffset = -256;
5006 MaxOffset = 255;
5007 break;
5008 case AArch64::LD1B_IMM:
5009 case AArch64::LD1H_IMM:
5010 case AArch64::LD1W_IMM:
5011 case AArch64::LD1D_IMM:
5012 case AArch64::LDNT1B_ZRI:
5013 case AArch64::LDNT1H_ZRI:
5014 case AArch64::LDNT1W_ZRI:
5015 case AArch64::LDNT1D_ZRI:
5016 case AArch64::ST1B_IMM:
5017 case AArch64::ST1H_IMM:
5018 case AArch64::ST1W_IMM:
5019 case AArch64::ST1D_IMM:
5020 case AArch64::STNT1B_ZRI:
5021 case AArch64::STNT1H_ZRI:
5022 case AArch64::STNT1W_ZRI:
5023 case AArch64::STNT1D_ZRI:
5024 case AArch64::LDNF1B_IMM:
5025 case AArch64::LDNF1H_IMM:
5026 case AArch64::LDNF1W_IMM:
5027 case AArch64::LDNF1D_IMM:
5028 // A full vectors worth of data
5029 // Width = mbytes * elements
5030 Scale = Width = TypeSize::getScalable(16);
5031 MinOffset = -8;
5032 MaxOffset = 7;
5033 break;
5034 case AArch64::LD2B_IMM:
5035 case AArch64::LD2H_IMM:
5036 case AArch64::LD2W_IMM:
5037 case AArch64::LD2D_IMM:
5038 case AArch64::ST2B_IMM:
5039 case AArch64::ST2H_IMM:
5040 case AArch64::ST2W_IMM:
5041 case AArch64::ST2D_IMM:
5042 case AArch64::LD1B_2Z_IMM:
5043 case AArch64::LD1B_2Z_STRIDED_IMM:
5044 case AArch64::LD1H_2Z_IMM:
5045 case AArch64::LD1H_2Z_STRIDED_IMM:
5046 case AArch64::LD1W_2Z_IMM:
5047 case AArch64::LD1W_2Z_STRIDED_IMM:
5048 case AArch64::LD1D_2Z_IMM:
5049 case AArch64::LD1D_2Z_STRIDED_IMM:
5050 case AArch64::LD1B_2Z_IMM_PSEUDO:
5051 case AArch64::LD1H_2Z_IMM_PSEUDO:
5052 case AArch64::LD1W_2Z_IMM_PSEUDO:
5053 case AArch64::LD1D_2Z_IMM_PSEUDO:
5054 case AArch64::ST1B_2Z_IMM:
5055 case AArch64::ST1B_2Z_STRIDED_IMM:
5056 case AArch64::ST1H_2Z_IMM:
5057 case AArch64::ST1H_2Z_STRIDED_IMM:
5058 case AArch64::ST1W_2Z_IMM:
5059 case AArch64::ST1W_2Z_STRIDED_IMM:
5060 case AArch64::ST1D_2Z_IMM:
5061 case AArch64::ST1D_2Z_STRIDED_IMM:
5062 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5063 case AArch64::LDNT1B_2Z_IMM:
5064 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5065 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5066 case AArch64::LDNT1H_2Z_IMM:
5067 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5068 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5069 case AArch64::LDNT1W_2Z_IMM:
5070 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5071 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5072 case AArch64::LDNT1D_2Z_IMM:
5073 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5074 case AArch64::STNT1B_2Z_IMM:
5075 case AArch64::STNT1B_2Z_STRIDED_IMM:
5076 case AArch64::STNT1H_2Z_IMM:
5077 case AArch64::STNT1H_2Z_STRIDED_IMM:
5078 case AArch64::STNT1W_2Z_IMM:
5079 case AArch64::STNT1W_2Z_STRIDED_IMM:
5080 case AArch64::STNT1D_2Z_IMM:
5081 case AArch64::STNT1D_2Z_STRIDED_IMM:
5082 case AArch64::ST1B_2Z_IMM_PSEUDO:
5083 case AArch64::ST1H_2Z_IMM_PSEUDO:
5084 case AArch64::ST1W_2Z_IMM_PSEUDO:
5085 case AArch64::ST1D_2Z_IMM_PSEUDO:
5086 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5087 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5088 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5089 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5090 Scale = Width = TypeSize::getScalable(16 * 2);
5091 MinOffset = -8;
5092 MaxOffset = 7;
5093 break;
5094 case AArch64::LD3B_IMM:
5095 case AArch64::LD3H_IMM:
5096 case AArch64::LD3W_IMM:
5097 case AArch64::LD3D_IMM:
5098 case AArch64::ST3B_IMM:
5099 case AArch64::ST3H_IMM:
5100 case AArch64::ST3W_IMM:
5101 case AArch64::ST3D_IMM:
5102 Scale = Width = TypeSize::getScalable(16 * 3);
5103 MinOffset = -8;
5104 MaxOffset = 7;
5105 break;
5106 case AArch64::LD4B_IMM:
5107 case AArch64::LD4H_IMM:
5108 case AArch64::LD4W_IMM:
5109 case AArch64::LD4D_IMM:
5110 case AArch64::ST4B_IMM:
5111 case AArch64::ST4H_IMM:
5112 case AArch64::ST4W_IMM:
5113 case AArch64::ST4D_IMM:
5114 case AArch64::LD1B_4Z_IMM:
5115 case AArch64::LD1B_4Z_STRIDED_IMM:
5116 case AArch64::LD1H_4Z_IMM:
5117 case AArch64::LD1H_4Z_STRIDED_IMM:
5118 case AArch64::LD1W_4Z_IMM:
5119 case AArch64::LD1W_4Z_STRIDED_IMM:
5120 case AArch64::LD1D_4Z_IMM:
5121 case AArch64::LD1D_4Z_STRIDED_IMM:
5122 case AArch64::LD1B_4Z_IMM_PSEUDO:
5123 case AArch64::LD1H_4Z_IMM_PSEUDO:
5124 case AArch64::LD1W_4Z_IMM_PSEUDO:
5125 case AArch64::LD1D_4Z_IMM_PSEUDO:
5126 case AArch64::ST1B_4Z_IMM:
5127 case AArch64::ST1B_4Z_STRIDED_IMM:
5128 case AArch64::ST1H_4Z_IMM:
5129 case AArch64::ST1H_4Z_STRIDED_IMM:
5130 case AArch64::ST1W_4Z_IMM:
5131 case AArch64::ST1W_4Z_STRIDED_IMM:
5132 case AArch64::ST1D_4Z_IMM:
5133 case AArch64::ST1D_4Z_STRIDED_IMM:
5134 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5135 case AArch64::LDNT1B_4Z_IMM:
5136 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5137 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5138 case AArch64::LDNT1H_4Z_IMM:
5139 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5140 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5141 case AArch64::LDNT1W_4Z_IMM:
5142 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5143 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5144 case AArch64::LDNT1D_4Z_IMM:
5145 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5146 case AArch64::STNT1B_4Z_IMM:
5147 case AArch64::STNT1B_4Z_STRIDED_IMM:
5148 case AArch64::STNT1H_4Z_IMM:
5149 case AArch64::STNT1H_4Z_STRIDED_IMM:
5150 case AArch64::STNT1W_4Z_IMM:
5151 case AArch64::STNT1W_4Z_STRIDED_IMM:
5152 case AArch64::STNT1D_4Z_IMM:
5153 case AArch64::STNT1D_4Z_STRIDED_IMM:
5154 case AArch64::ST1B_4Z_IMM_PSEUDO:
5155 case AArch64::ST1H_4Z_IMM_PSEUDO:
5156 case AArch64::ST1W_4Z_IMM_PSEUDO:
5157 case AArch64::ST1D_4Z_IMM_PSEUDO:
5158 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5159 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5160 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5161 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5162 Scale = Width = TypeSize::getScalable(16 * 4);
5163 MinOffset = -8;
5164 MaxOffset = 7;
5165 break;
5166 case AArch64::LD1B_H_IMM:
5167 case AArch64::LD1SB_H_IMM:
5168 case AArch64::LD1H_S_IMM:
5169 case AArch64::LD1SH_S_IMM:
5170 case AArch64::LD1W_D_IMM:
5171 case AArch64::LD1SW_D_IMM:
5172 case AArch64::ST1B_H_IMM:
5173 case AArch64::ST1H_S_IMM:
5174 case AArch64::ST1W_D_IMM:
5175 case AArch64::LDNF1B_H_IMM:
5176 case AArch64::LDNF1SB_H_IMM:
5177 case AArch64::LDNF1H_S_IMM:
5178 case AArch64::LDNF1SH_S_IMM:
5179 case AArch64::LDNF1W_D_IMM:
5180 case AArch64::LDNF1SW_D_IMM:
5181 // A half vector worth of data
5182 // Width = mbytes * elements
5183 Scale = Width = TypeSize::getScalable(8);
5184 MinOffset = -8;
5185 MaxOffset = 7;
5186 break;
5187 case AArch64::LD1B_S_IMM:
5188 case AArch64::LD1SB_S_IMM:
5189 case AArch64::LD1H_D_IMM:
5190 case AArch64::LD1SH_D_IMM:
5191 case AArch64::ST1B_S_IMM:
5192 case AArch64::ST1H_D_IMM:
5193 case AArch64::LDNF1B_S_IMM:
5194 case AArch64::LDNF1SB_S_IMM:
5195 case AArch64::LDNF1H_D_IMM:
5196 case AArch64::LDNF1SH_D_IMM:
5197 // A quarter vector worth of data
5198 // Width = mbytes * elements
5199 Scale = Width = TypeSize::getScalable(4);
5200 MinOffset = -8;
5201 MaxOffset = 7;
5202 break;
5203 case AArch64::LD1B_D_IMM:
5204 case AArch64::LD1SB_D_IMM:
5205 case AArch64::ST1B_D_IMM:
5206 case AArch64::LDNF1B_D_IMM:
5207 case AArch64::LDNF1SB_D_IMM:
5208 // A eighth vector worth of data
5209 // Width = mbytes * elements
5210 Scale = Width = TypeSize::getScalable(2);
5211 MinOffset = -8;
5212 MaxOffset = 7;
5213 break;
5214 case AArch64::ST2Gi:
5215 case AArch64::ST2GPreIndex:
5216 case AArch64::ST2GPostIndex:
5217 case AArch64::STZ2Gi:
5218 case AArch64::STZ2GPreIndex:
5219 case AArch64::STZ2GPostIndex:
5220 Scale = TypeSize::getFixed(16);
5221 Width = TypeSize::getFixed(32);
5222 MinOffset = -256;
5223 MaxOffset = 255;
5224 break;
5225 case AArch64::STGPi:
5226 case AArch64::STGPpost:
5227 case AArch64::STGPpre:
5228 Scale = Width = TypeSize::getFixed(16);
5229 MinOffset = -64;
5230 MaxOffset = 63;
5231 break;
5232 case AArch64::LD1RB_IMM:
5233 case AArch64::LD1RB_H_IMM:
5234 case AArch64::LD1RB_S_IMM:
5235 case AArch64::LD1RB_D_IMM:
5236 case AArch64::LD1RSB_H_IMM:
5237 case AArch64::LD1RSB_S_IMM:
5238 case AArch64::LD1RSB_D_IMM:
5239 Scale = Width = TypeSize::getFixed(1);
5240 MinOffset = 0;
5241 MaxOffset = 63;
5242 break;
5243 case AArch64::LD1RH_IMM:
5244 case AArch64::LD1RH_S_IMM:
5245 case AArch64::LD1RH_D_IMM:
5246 case AArch64::LD1RSH_S_IMM:
5247 case AArch64::LD1RSH_D_IMM:
5248 Scale = Width = TypeSize::getFixed(2);
5249 MinOffset = 0;
5250 MaxOffset = 63;
5251 break;
5252 case AArch64::LD1RW_IMM:
5253 case AArch64::LD1RW_D_IMM:
5254 case AArch64::LD1RSW_IMM:
5255 Scale = Width = TypeSize::getFixed(4);
5256 MinOffset = 0;
5257 MaxOffset = 63;
5258 break;
5259 case AArch64::LD1RD_IMM:
5260 Scale = Width = TypeSize::getFixed(8);
5261 MinOffset = 0;
5262 MaxOffset = 63;
5263 break;
5264 }
5265
5266 return true;
5267}
5268
5269// Scaling factor for unscaled load or store.
5271 switch (Opc) {
5272 default:
5273 llvm_unreachable("Opcode has unknown scale!");
5274 case AArch64::LDRBui:
5275 case AArch64::LDRBBui:
5276 case AArch64::LDURBBi:
5277 case AArch64::LDRSBWui:
5278 case AArch64::LDURSBWi:
5279 case AArch64::STRBui:
5280 case AArch64::STRBBui:
5281 case AArch64::STURBBi:
5282 return 1;
5283 case AArch64::LDRHui:
5284 case AArch64::LDRHHui:
5285 case AArch64::LDURHHi:
5286 case AArch64::LDRSHWui:
5287 case AArch64::LDURSHWi:
5288 case AArch64::STRHui:
5289 case AArch64::STRHHui:
5290 case AArch64::STURHHi:
5291 return 2;
5292 case AArch64::LDRSui:
5293 case AArch64::LDURSi:
5294 case AArch64::LDRSpre:
5295 case AArch64::LDRSWui:
5296 case AArch64::LDURSWi:
5297 case AArch64::LDRSWpre:
5298 case AArch64::LDRWpre:
5299 case AArch64::LDRWui:
5300 case AArch64::LDURWi:
5301 case AArch64::STRSui:
5302 case AArch64::STURSi:
5303 case AArch64::STRSpre:
5304 case AArch64::STRWui:
5305 case AArch64::STURWi:
5306 case AArch64::STRWpre:
5307 case AArch64::LDPSi:
5308 case AArch64::LDPSWi:
5309 case AArch64::LDPWi:
5310 case AArch64::STPSi:
5311 case AArch64::STPWi:
5312 return 4;
5313 case AArch64::LDRDui:
5314 case AArch64::LDURDi:
5315 case AArch64::LDRDpre:
5316 case AArch64::LDRXui:
5317 case AArch64::LDURXi:
5318 case AArch64::LDRXpre:
5319 case AArch64::STRDui:
5320 case AArch64::STURDi:
5321 case AArch64::STRDpre:
5322 case AArch64::STRXui:
5323 case AArch64::STURXi:
5324 case AArch64::STRXpre:
5325 case AArch64::LDPDi:
5326 case AArch64::LDPXi:
5327 case AArch64::STPDi:
5328 case AArch64::STPXi:
5329 return 8;
5330 case AArch64::LDRQui:
5331 case AArch64::LDURQi:
5332 case AArch64::STRQui:
5333 case AArch64::STURQi:
5334 case AArch64::STRQpre:
5335 case AArch64::LDPQi:
5336 case AArch64::LDRQpre:
5337 case AArch64::STPQi:
5338 case AArch64::STGi:
5339 case AArch64::STZGi:
5340 case AArch64::ST2Gi:
5341 case AArch64::STZ2Gi:
5342 case AArch64::STGPi:
5343 return 16;
5344 }
5345}
5346
5348 switch (MI.getOpcode()) {
5349 default:
5350 return false;
5351 case AArch64::LDRWpre:
5352 case AArch64::LDRXpre:
5353 case AArch64::LDRSWpre:
5354 case AArch64::LDRSpre:
5355 case AArch64::LDRDpre:
5356 case AArch64::LDRQpre:
5357 return true;
5358 }
5359}
5360
5362 switch (MI.getOpcode()) {
5363 default:
5364 return false;
5365 case AArch64::STRWpre:
5366 case AArch64::STRXpre:
5367 case AArch64::STRSpre:
5368 case AArch64::STRDpre:
5369 case AArch64::STRQpre:
5370 return true;
5371 }
5372}
5373
5375 return isPreLd(MI) || isPreSt(MI);
5376}
5377
5379 switch (MI.getOpcode()) {
5380 default:
5381 return false;
5382 case AArch64::LDURBBi:
5383 case AArch64::LDURHHi:
5384 case AArch64::LDURWi:
5385 case AArch64::LDRBBui:
5386 case AArch64::LDRHHui:
5387 case AArch64::LDRWui:
5388 case AArch64::LDRBBroX:
5389 case AArch64::LDRHHroX:
5390 case AArch64::LDRWroX:
5391 case AArch64::LDRBBroW:
5392 case AArch64::LDRHHroW:
5393 case AArch64::LDRWroW:
5394 return true;
5395 }
5396}
5397
5399 switch (MI.getOpcode()) {
5400 default:
5401 return false;
5402 case AArch64::LDURSBWi:
5403 case AArch64::LDURSHWi:
5404 case AArch64::LDURSBXi:
5405 case AArch64::LDURSHXi:
5406 case AArch64::LDURSWi:
5407 case AArch64::LDRSBWui:
5408 case AArch64::LDRSHWui:
5409 case AArch64::LDRSBXui:
5410 case AArch64::LDRSHXui:
5411 case AArch64::LDRSWui:
5412 case AArch64::LDRSBWroX:
5413 case AArch64::LDRSHWroX:
5414 case AArch64::LDRSBXroX:
5415 case AArch64::LDRSHXroX:
5416 case AArch64::LDRSWroX:
5417 case AArch64::LDRSBWroW:
5418 case AArch64::LDRSHWroW:
5419 case AArch64::LDRSBXroW:
5420 case AArch64::LDRSHXroW:
5421 case AArch64::LDRSWroW:
5422 return true;
5423 }
5424}
5425
5427 switch (MI.getOpcode()) {
5428 default:
5429 return false;
5430 case AArch64::LDPSi:
5431 case AArch64::LDPSWi:
5432 case AArch64::LDPDi:
5433 case AArch64::LDPQi:
5434 case AArch64::LDPWi:
5435 case AArch64::LDPXi:
5436 case AArch64::STPSi:
5437 case AArch64::STPDi:
5438 case AArch64::STPQi:
5439 case AArch64::STPWi:
5440 case AArch64::STPXi:
5441 case AArch64::STGPi:
5442 return true;
5443 }
5444}
5445
5447 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5448 unsigned Idx =
5450 : 1;
5451 return MI.getOperand(Idx);
5452}
5453
5454const MachineOperand &
5456 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5457 unsigned Idx =
5459 : 2;
5460 return MI.getOperand(Idx);
5461}
5462
5463const MachineOperand &
5465 switch (MI.getOpcode()) {
5466 default:
5467 llvm_unreachable("Unexpected opcode");
5468 case AArch64::LDRBroX:
5469 case AArch64::LDRBBroX:
5470 case AArch64::LDRSBXroX:
5471 case AArch64::LDRSBWroX:
5472 case AArch64::LDRHroX:
5473 case AArch64::LDRHHroX:
5474 case AArch64::LDRSHXroX:
5475 case AArch64::LDRSHWroX:
5476 case AArch64::LDRWroX:
5477 case AArch64::LDRSroX:
5478 case AArch64::LDRSWroX:
5479 case AArch64::LDRDroX:
5480 case AArch64::LDRXroX:
5481 case AArch64::LDRQroX:
5482 return MI.getOperand(4);
5483 }
5484}
5485
5487 Register Reg) {
5488 if (MI.getParent() == nullptr)
5489 return nullptr;
5490 const MachineFunction *MF = MI.getParent()->getParent();
5491 return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr;
5492}
5493
5495 auto IsHFPR = [&](const MachineOperand &Op) {
5496 if (!Op.isReg())
5497 return false;
5498 auto Reg = Op.getReg();
5499 if (Reg.isPhysical())
5500 return AArch64::FPR16RegClass.contains(Reg);
5501 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5502 return TRC == &AArch64::FPR16RegClass ||
5503 TRC == &AArch64::FPR16_loRegClass;
5504 };
5505 return llvm::any_of(MI.operands(), IsHFPR);
5506}
5507
5509 auto IsQFPR = [&](const MachineOperand &Op) {
5510 if (!Op.isReg())
5511 return false;
5512 auto Reg = Op.getReg();
5513 if (Reg.isPhysical())
5514 return AArch64::FPR128RegClass.contains(Reg);
5515 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5516 return TRC == &AArch64::FPR128RegClass ||
5517 TRC == &AArch64::FPR128_loRegClass;
5518 };
5519 return llvm::any_of(MI.operands(), IsQFPR);
5520}
5521
5523 switch (MI.getOpcode()) {
5524 case AArch64::BRK:
5525 case AArch64::HLT:
5526 case AArch64::PACIASP:
5527 case AArch64::PACIBSP:
5528 // Implicit BTI behavior.
5529 return true;
5530 case AArch64::PAUTH_PROLOGUE:
5531 // PAUTH_PROLOGUE expands to PACI(A|B)SP.
5532 return true;
5533 case AArch64::HINT: {
5534 unsigned Imm = MI.getOperand(0).getImm();
5535 // Explicit BTI instruction.
5536 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5537 return true;
5538 // PACI(A|B)SP instructions.
5539 if (Imm == 25 || Imm == 27)
5540 return true;
5541 return false;
5542 }
5543 default:
5544 return false;
5545 }
5546}
5547
5549 if (Reg == 0)
5550 return false;
5551 assert(Reg.isPhysical() && "Expected physical register in isFpOrNEON");
5552 return AArch64::FPR128RegClass.contains(Reg) ||
5553 AArch64::FPR64RegClass.contains(Reg) ||
5554 AArch64::FPR32RegClass.contains(Reg) ||
5555 AArch64::FPR16RegClass.contains(Reg) ||
5556 AArch64::FPR8RegClass.contains(Reg);
5557}
5558
5560 auto IsFPR = [&](const MachineOperand &Op) {
5561 if (!Op.isReg())
5562 return false;
5563 auto Reg = Op.getReg();
5564 if (Reg.isPhysical())
5565 return isFpOrNEON(Reg);
5566
5567 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5568 return TRC == &AArch64::FPR128RegClass ||
5569 TRC == &AArch64::FPR128_loRegClass ||
5570 TRC == &AArch64::FPR64RegClass ||
5571 TRC == &AArch64::FPR64_loRegClass ||
5572 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5573 TRC == &AArch64::FPR8RegClass;
5574 };
5575 return llvm::any_of(MI.operands(), IsFPR);
5576}
5577
5578// Scale the unscaled offsets. Returns false if the unscaled offset can't be
5579// scaled.
5580static bool scaleOffset(unsigned Opc, int64_t &Offset) {
5582
5583 // If the byte-offset isn't a multiple of the stride, we can't scale this
5584 // offset.
5585 if (Offset % Scale != 0)
5586 return false;
5587
5588 // Convert the byte-offset used by unscaled into an "element" offset used
5589 // by the scaled pair load/store instructions.
5590 Offset /= Scale;
5591 return true;
5592}
5593
5594static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
5595 if (FirstOpc == SecondOpc)
5596 return true;
5597 // We can also pair sign-ext and zero-ext instructions.
5598 switch (FirstOpc) {
5599 default:
5600 return false;
5601 case AArch64::STRSui:
5602 case AArch64::STURSi:
5603 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5604 case AArch64::STRDui:
5605 case AArch64::STURDi:
5606 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5607 case AArch64::STRQui:
5608 case AArch64::STURQi:
5609 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5610 case AArch64::STRWui:
5611 case AArch64::STURWi:
5612 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5613 case AArch64::STRXui:
5614 case AArch64::STURXi:
5615 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5616 case AArch64::LDRSui:
5617 case AArch64::LDURSi:
5618 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5619 case AArch64::LDRDui:
5620 case AArch64::LDURDi:
5621 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5622 case AArch64::LDRQui:
5623 case AArch64::LDURQi:
5624 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5625 case AArch64::LDRWui:
5626 case AArch64::LDURWi:
5627 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5628 case AArch64::LDRSWui:
5629 case AArch64::LDURSWi:
5630 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5631 case AArch64::LDRXui:
5632 case AArch64::LDURXi:
5633 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5634 }
5635 // These instructions can't be paired based on their opcodes.
5636 return false;
5637}
5638
5639static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1,
5640 int64_t Offset1, unsigned Opcode1, int FI2,
5641 int64_t Offset2, unsigned Opcode2) {
5642 // Accesses through fixed stack object frame indices may access a different
5643 // fixed stack slot. Check that the object offsets + offsets match.
5644 if (MFI.isFixedObjectIndex(FI1) && MFI.isFixedObjectIndex(FI2)) {
5645 int64_t ObjectOffset1 = MFI.getObjectOffset(FI1);
5646 int64_t ObjectOffset2 = MFI.getObjectOffset(FI2);
5647 assert(ObjectOffset1 <= ObjectOffset2 && "Object offsets are not ordered.");
5648 // Convert to scaled object offsets.
5649 int Scale1 = AArch64InstrInfo::getMemScale(Opcode1);
5650 if (ObjectOffset1 % Scale1 != 0)
5651 return false;
5652 ObjectOffset1 /= Scale1;
5653 int Scale2 = AArch64InstrInfo::getMemScale(Opcode2);
5654 if (ObjectOffset2 % Scale2 != 0)
5655 return false;
5656 ObjectOffset2 /= Scale2;
5657 ObjectOffset1 += Offset1;
5658 ObjectOffset2 += Offset2;
5659 return ObjectOffset1 + 1 == ObjectOffset2;
5660 }
5661
5662 return FI1 == FI2;
5663}
5664
5665/// Detect opportunities for ldp/stp formation.
5666///
5667/// Only called for LdSt for which getMemOperandWithOffset returns true.
5669 ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
5670 bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
5671 int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
5672 unsigned NumBytes) const {
5673 assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
5674 const MachineOperand &BaseOp1 = *BaseOps1.front();
5675 const MachineOperand &BaseOp2 = *BaseOps2.front();
5676 const MachineInstr &FirstLdSt = *BaseOp1.getParent();
5677 const MachineInstr &SecondLdSt = *BaseOp2.getParent();
5678 if (BaseOp1.getType() != BaseOp2.getType())
5679 return false;
5680
5681 assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
5682 "Only base registers and frame indices are supported.");
5683
5684 // Check for both base regs and base FI.
5685 if (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg())
5686 return false;
5687
5688 // Only cluster up to a single pair.
5689 if (ClusterSize > 2)
5690 return false;
5691
5692 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
5693 return false;
5694
5695 // Can we pair these instructions based on their opcodes?
5696 unsigned FirstOpc = FirstLdSt.getOpcode();
5697 unsigned SecondOpc = SecondLdSt.getOpcode();
5698 if (!canPairLdStOpc(FirstOpc, SecondOpc))
5699 return false;
5700
5701 // Can't merge volatiles or load/stores that have a hint to avoid pair
5702 // formation, for example.
5703 if (!isCandidateToMergeOrPair(FirstLdSt) ||
5704 !isCandidateToMergeOrPair(SecondLdSt))
5705 return false;
5706
5707 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
5708 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
5709 if (hasUnscaledLdStOffset(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
5710 return false;
5711
5712 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
5713 if (hasUnscaledLdStOffset(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
5714 return false;
5715
5716 // Pairwise instructions have a 7-bit signed offset field.
5717 if (Offset1 > 63 || Offset1 < -64)
5718 return false;
5719
5720 // The caller should already have ordered First/SecondLdSt by offset.
5721 // Note: except for non-equal frame index bases
5722 if (BaseOp1.isFI()) {
5723 assert((!BaseOp1.isIdenticalTo(BaseOp2) || Offset1 <= Offset2) &&
5724 "Caller should have ordered offsets.");
5725
5726 const MachineFrameInfo &MFI =
5727 FirstLdSt.getParent()->getParent()->getFrameInfo();
5728 return shouldClusterFI(MFI, BaseOp1.getIndex(), Offset1, FirstOpc,
5729 BaseOp2.getIndex(), Offset2, SecondOpc);
5730 }
5731
5732 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
5733
5734 return Offset1 + 1 == Offset2;
5735}
5736
5738 MCRegister Reg, unsigned SubIdx,
5739 RegState State,
5740 const TargetRegisterInfo *TRI) {
5741 if (!SubIdx)
5742 return MIB.addReg(Reg, State);
5743
5744 if (Reg.isPhysical())
5745 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
5746 return MIB.addReg(Reg, State, SubIdx);
5747}
5748
5751 const DebugLoc &DL, MCRegister DestReg,
5752 MCRegister SrcReg, bool KillSrc,
5753 ArrayRef<unsigned> Indices) const {
5754 assert(Subtarget.hasNEON() && "Unexpected register copy without NEON");
5756 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5757 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5758 unsigned NumRegs = Indices.size();
5759 MCRegister DestSubReg = TRI->getSubReg(DestReg, Indices[0]);
5760 assert(!AArch64::PNRRegClass.contains(DestSubReg) &&
5761 "Unexpected predicate tuple copy");
5762 unsigned MaxRegs = AArch64::PPRRegClass.contains(DestSubReg) ? 15 : 31;
5763
5764 int SubReg = 0, End = NumRegs, Incr = 1;
5765 // Copy in reverse if a forward copy will clobber the tuple
5766 if (((DestEncoding - SrcEncoding) & MaxRegs) < NumRegs) {
5767 SubReg = NumRegs - 1;
5768 End = -1;
5769 Incr = -1;
5770 }
5771
5772 for (; SubReg != End; SubReg += Incr) {
5773 DestSubReg = TRI->getSubReg(DestReg, Indices[SubReg]);
5774 MCRegister SrcSubReg = TRI->getSubReg(SrcReg, Indices[SubReg]);
5775 copyPhysRegImpl(MBB, I, DL, DestSubReg, SrcSubReg, KillSrc);
5776 }
5777}
5778
5781 const DebugLoc &DL, MCRegister DestReg,
5782 MCRegister SrcReg, bool KillSrc,
5783 unsigned Opcode, unsigned ZeroReg,
5784 llvm::ArrayRef<unsigned> Indices) const {
5786 unsigned NumRegs = Indices.size();
5787
5788#ifndef NDEBUG
5789 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5790 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5791 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5792 "GPR reg sequences should not be able to overlap");
5793#endif
5794
5795 for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5796 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5797 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5798 MIB.addReg(ZeroReg);
5799 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5800 MIB.addImm(0);
5801 }
5802}
5803
5804/// Returns true if the instruction at I is in a streaming call site region,
5805/// within a single basic block.
5806/// A "call site streaming region" starts after smstart and ends at smstop
5807/// around a call to a streaming function. This walks backward from I.
5810 MachineFunction &MF = *MBB.getParent();
5812 if (!AFI->hasStreamingModeChanges())
5813 return false;
5814 // Walk backwards to find smstart/smstop
5815 for (MachineInstr &MI : reverse(make_range(MBB.begin(), I))) {
5816 unsigned Opc = MI.getOpcode();
5817 if (Opc == AArch64::MSRpstatesvcrImm1 || Opc == AArch64::MSRpstatePseudo) {
5818 // Check if this is SM change (not ZA)
5819 int64_t PState = MI.getOperand(0).getImm();
5820 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5821 // Operand 1 is 1 for start, 0 for stop
5822 return MI.getOperand(1).getImm() == 1;
5823 }
5824 }
5825 }
5826 return false;
5827}
5828
5829/// Returns true if in a streaming call site region without SME-FA64.
5830static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget,
5833 return !Subtarget.hasSMEFA64() && isInStreamingCallSiteRegion(MBB, I);
5834}
5835
5838 const DebugLoc &DL, Register DestReg,
5839 Register SrcReg, bool KillSrc,
5840 bool RenamableDest,
5841 bool RenamableSrc) const {
5842 if (AArch64::GPR32spRegClass.contains(DestReg) &&
5843 AArch64::GPR32spRegClass.contains(SrcReg)) {
5844 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5845 // If either operand is WSP, expand to ADD #0.
5846 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5847 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5848 // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
5849 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5850 &AArch64::GPR64spRegClass);
5851 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5852 &AArch64::GPR64spRegClass);
5853 // This instruction is reading and writing X registers. This may upset
5854 // the register scavenger and machine verifier, so we need to indicate
5855 // that we are reading an undefined value from SrcRegX, but a proper
5856 // value from SrcReg.
5857 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
5858 .addReg(SrcRegX, RegState::Undef)
5859 .addImm(0)
5861 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5862 ++NumZCRegMoveInstrsGPR;
5863 } else {
5864 BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
5865 .addReg(SrcReg, getKillRegState(KillSrc))
5866 .addImm(0)
5868 if (Subtarget.hasZeroCycleRegMoveGPR32())
5869 ++NumZCRegMoveInstrsGPR;
5870 }
5871 } else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5872 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5873 // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
5874 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5875 &AArch64::GPR64spRegClass);
5876 assert(DestRegX.isValid() && "Destination super-reg not valid");
5877 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5878 &AArch64::GPR64spRegClass);
5879 assert(SrcRegX.isValid() && "Source super-reg not valid");
5880 // This instruction is reading and writing X registers. This may upset
5881 // the register scavenger and machine verifier, so we need to indicate
5882 // that we are reading an undefined value from SrcRegX, but a proper
5883 // value from SrcReg.
5884 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
5885 .addReg(AArch64::XZR)
5886 .addReg(SrcRegX, RegState::Undef)
5887 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5888 ++NumZCRegMoveInstrsGPR;
5889 } else {
5890 // Otherwise, expand to ORR WZR.
5891 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5892 .addReg(AArch64::WZR)
5893 .addReg(SrcReg, getKillRegState(KillSrc));
5894 if (Subtarget.hasZeroCycleRegMoveGPR32())
5895 ++NumZCRegMoveInstrsGPR;
5896 }
5897 return;
5898 }
5899
5900 // GPR32 zeroing
5901 if (AArch64::GPR32spRegClass.contains(DestReg) && SrcReg == AArch64::WZR) {
5902 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5903 !Subtarget.hasZeroCycleZeroingGPR32()) {
5904 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5905 &AArch64::GPR64spRegClass);
5906 assert(DestRegX.isValid() && "Destination super-reg not valid");
5907 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestRegX)
5908 .addImm(0)
5910 ++NumZCZeroingInstrsGPR;
5911 } else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5912 BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg)
5913 .addImm(0)
5915 ++NumZCZeroingInstrsGPR;
5916 } else {
5917 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5918 .addReg(AArch64::WZR)
5919 .addReg(AArch64::WZR);
5920 }
5921 return;
5922 }
5923
5924 if (AArch64::GPR64spRegClass.contains(DestReg) &&
5925 AArch64::GPR64spRegClass.contains(SrcReg)) {
5926 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5927 // If either operand is SP, expand to ADD #0.
5928 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
5929 .addReg(SrcReg, getKillRegState(KillSrc))
5930 .addImm(0)
5932 if (Subtarget.hasZeroCycleRegMoveGPR64())
5933 ++NumZCRegMoveInstrsGPR;
5934 } else {
5935 // Otherwise, expand to ORR XZR.
5936 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5937 .addReg(AArch64::XZR)
5938 .addReg(SrcReg, getKillRegState(KillSrc));
5939 if (Subtarget.hasZeroCycleRegMoveGPR64())
5940 ++NumZCRegMoveInstrsGPR;
5941 }
5942 return;
5943 }
5944
5945 // GPR64 zeroing
5946 if (AArch64::GPR64spRegClass.contains(DestReg) && SrcReg == AArch64::XZR) {
5947 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5948 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg)
5949 .addImm(0)
5951 ++NumZCZeroingInstrsGPR;
5952 } else {
5953 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5954 .addReg(AArch64::XZR)
5955 .addReg(AArch64::XZR);
5956 }
5957 return;
5958 }
5959
5960 // Copy a Predicate register by ORRing with itself.
5961 if (AArch64::PPRRegClass.contains(DestReg) &&
5962 AArch64::PPRRegClass.contains(SrcReg)) {
5963 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5964 "Unexpected SVE register.");
5965 BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), DestReg)
5966 .addReg(SrcReg) // Pg
5967 .addReg(SrcReg)
5968 .addReg(SrcReg, getKillRegState(KillSrc));
5969 return;
5970 }
5971
5972 // Copy a predicate-as-counter register by ORRing with itself as if it
5973 // were a regular predicate (mask) register.
5974 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
5975 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
5976 if (DestIsPNR || SrcIsPNR) {
5977 auto ToPPR = [](MCRegister R) -> MCRegister {
5978 return (R - AArch64::PN0) + AArch64::P0;
5979 };
5980 MCRegister PPRSrcReg = SrcIsPNR ? ToPPR(SrcReg) : SrcReg.asMCReg();
5981 MCRegister PPRDestReg = DestIsPNR ? ToPPR(DestReg) : DestReg.asMCReg();
5982
5983 if (PPRSrcReg != PPRDestReg) {
5984 auto NewMI = BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), PPRDestReg)
5985 .addReg(PPRSrcReg) // Pg
5986 .addReg(PPRSrcReg)
5987 .addReg(PPRSrcReg, getKillRegState(KillSrc));
5988 if (DestIsPNR)
5989 NewMI.addDef(DestReg, RegState::Implicit);
5990 }
5991 return;
5992 }
5993
5994 // Copy a predicate register pair by copying the individual sub-registers.
5995 if (AArch64::PPR2RegClass.contains(DestReg) &&
5996 AArch64::PPR2RegClass.contains(SrcReg)) {
5997 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5998 "Unexpected SVE predicate register.");
5999 static const unsigned Indices[] = {AArch64::psub0, AArch64::psub1};
6000 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6001 return;
6002 }
6003
6004 // Copy a Z register by ORRing with itself.
6005 if (AArch64::ZPRRegClass.contains(DestReg) &&
6006 AArch64::ZPRRegClass.contains(SrcReg)) {
6007 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6008 "Unexpected SVE register.");
6009 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ), DestReg)
6010 .addReg(SrcReg)
6011 .addReg(SrcReg, getKillRegState(KillSrc));
6012 return;
6013 }
6014
6015 // Copy a Z register pair by copying the individual sub-registers.
6016 if ((AArch64::ZPR2RegClass.contains(DestReg) ||
6017 AArch64::ZPR2StridedOrContiguousRegClass.contains(DestReg)) &&
6018 (AArch64::ZPR2RegClass.contains(SrcReg) ||
6019 AArch64::ZPR2StridedOrContiguousRegClass.contains(SrcReg))) {
6020 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6021 "Unexpected SVE register.");
6022 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6023 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6024 return;
6025 }
6026
6027 // Copy a Z register triple by copying the individual sub-registers.
6028 if (AArch64::ZPR3RegClass.contains(DestReg) &&
6029 AArch64::ZPR3RegClass.contains(SrcReg)) {
6030 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6031 "Unexpected SVE register.");
6032 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6033 AArch64::zsub2};
6034 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6035 return;
6036 }
6037
6038 // Copy a Z register quad by copying the individual sub-registers.
6039 if ((AArch64::ZPR4RegClass.contains(DestReg) ||
6040 AArch64::ZPR4StridedOrContiguousRegClass.contains(DestReg)) &&
6041 (AArch64::ZPR4RegClass.contains(SrcReg) ||
6042 AArch64::ZPR4StridedOrContiguousRegClass.contains(SrcReg))) {
6043 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6044 "Unexpected SVE register.");
6045 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6046 AArch64::zsub2, AArch64::zsub3};
6047 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6048 return;
6049 }
6050
6051 // Copy a DDDD register quad by copying the individual sub-registers.
6052 if (AArch64::DDDDRegClass.contains(DestReg) &&
6053 AArch64::DDDDRegClass.contains(SrcReg)) {
6054 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6055 AArch64::dsub2, AArch64::dsub3};
6056 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6057 return;
6058 }
6059
6060 // Copy a DDD register triple by copying the individual sub-registers.
6061 if (AArch64::DDDRegClass.contains(DestReg) &&
6062 AArch64::DDDRegClass.contains(SrcReg)) {
6063 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6064 AArch64::dsub2};
6065 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6066 return;
6067 }
6068
6069 // Copy a DD register pair by copying the individual sub-registers.
6070 if (AArch64::DDRegClass.contains(DestReg) &&
6071 AArch64::DDRegClass.contains(SrcReg)) {
6072 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6073 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6074 return;
6075 }
6076
6077 // Copy a QQQQ register quad by copying the individual sub-registers.
6078 if (AArch64::QQQQRegClass.contains(DestReg) &&
6079 AArch64::QQQQRegClass.contains(SrcReg)) {
6080 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6081 AArch64::qsub2, AArch64::qsub3};
6082 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6083 return;
6084 }
6085
6086 // Copy a QQQ register triple by copying the individual sub-registers.
6087 if (AArch64::QQQRegClass.contains(DestReg) &&
6088 AArch64::QQQRegClass.contains(SrcReg)) {
6089 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6090 AArch64::qsub2};
6091 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6092 return;
6093 }
6094
6095 // Copy a QQ register pair by copying the individual sub-registers.
6096 if (AArch64::QQRegClass.contains(DestReg) &&
6097 AArch64::QQRegClass.contains(SrcReg)) {
6098 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6099 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6100 return;
6101 }
6102
6103 if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
6104 AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
6105 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6106 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
6107 AArch64::XZR, Indices);
6108 return;
6109 }
6110
6111 if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
6112 AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
6113 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6114 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
6115 AArch64::WZR, Indices);
6116 return;
6117 }
6118
6119 if (AArch64::FPR128RegClass.contains(DestReg) &&
6120 AArch64::FPR128RegClass.contains(SrcReg)) {
6121 // In streaming regions, NEON is illegal but streaming-SVE is available.
6122 // Use SVE for copies if we're in a streaming region and SME is available.
6123 // With +sme-fa64, NEON is legal in streaming mode so we can use it.
6124 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6125 !Subtarget.isNeonAvailable()) ||
6126 mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6127 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ))
6128 .addReg(AArch64::Z0 + (DestReg - AArch64::Q0), RegState::Define)
6129 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6130 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6131 } else if (Subtarget.isNeonAvailable()) {
6132 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
6133 .addReg(SrcReg)
6134 .addReg(SrcReg, getKillRegState(KillSrc));
6135 if (Subtarget.hasZeroCycleRegMoveFPR128())
6136 ++NumZCRegMoveInstrsFPR;
6137 } else {
6138 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
6139 .addReg(AArch64::SP, RegState::Define)
6140 .addReg(SrcReg, getKillRegState(KillSrc))
6141 .addReg(AArch64::SP)
6142 .addImm(-16);
6143 BuildMI(MBB, I, DL, get(AArch64::LDRQpost))
6144 .addReg(AArch64::SP, RegState::Define)
6145 .addReg(DestReg, RegState::Define)
6146 .addReg(AArch64::SP)
6147 .addImm(16);
6148 }
6149 return;
6150 }
6151
6152 if (AArch64::FPR64RegClass.contains(DestReg) &&
6153 AArch64::FPR64RegClass.contains(SrcReg)) {
6154 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6155 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6156 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6157 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6158 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6159 &AArch64::FPR128RegClass);
6160 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6161 &AArch64::FPR128RegClass);
6162 // This instruction is reading and writing Q registers. This may upset
6163 // the register scavenger and machine verifier, so we need to indicate
6164 // that we are reading an undefined value from SrcRegQ, but a proper
6165 // value from SrcReg.
6166 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6167 .addReg(SrcRegQ, RegState::Undef)
6168 .addReg(SrcRegQ, RegState::Undef)
6169 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6170 ++NumZCRegMoveInstrsFPR;
6171 } else {
6172 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
6173 .addReg(SrcReg, getKillRegState(KillSrc));
6174 if (Subtarget.hasZeroCycleRegMoveFPR64())
6175 ++NumZCRegMoveInstrsFPR;
6176 }
6177 return;
6178 }
6179
6180 if (AArch64::FPR32RegClass.contains(DestReg) &&
6181 AArch64::FPR32RegClass.contains(SrcReg)) {
6182 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6183 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6184 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6185 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6186 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6187 &AArch64::FPR128RegClass);
6188 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6189 &AArch64::FPR128RegClass);
6190 // This instruction is reading and writing Q registers. This may upset
6191 // the register scavenger and machine verifier, so we need to indicate
6192 // that we are reading an undefined value from SrcRegQ, but a proper
6193 // value from SrcReg.
6194 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6195 .addReg(SrcRegQ, RegState::Undef)
6196 .addReg(SrcRegQ, RegState::Undef)
6197 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6198 ++NumZCRegMoveInstrsFPR;
6199 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6200 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6201 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6202 &AArch64::FPR64RegClass);
6203 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6204 &AArch64::FPR64RegClass);
6205 // This instruction is reading and writing D registers. This may upset
6206 // the register scavenger and machine verifier, so we need to indicate
6207 // that we are reading an undefined value from SrcRegD, but a proper
6208 // value from SrcReg.
6209 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6210 .addReg(SrcRegD, RegState::Undef)
6211 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6212 ++NumZCRegMoveInstrsFPR;
6213 } else {
6214 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6215 .addReg(SrcReg, getKillRegState(KillSrc));
6216 if (Subtarget.hasZeroCycleRegMoveFPR32())
6217 ++NumZCRegMoveInstrsFPR;
6218 }
6219 return;
6220 }
6221
6222 if (AArch64::FPR16RegClass.contains(DestReg) &&
6223 AArch64::FPR16RegClass.contains(SrcReg)) {
6224 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6225 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6226 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6227 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6228 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6229 &AArch64::FPR128RegClass);
6230 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6231 &AArch64::FPR128RegClass);
6232 // This instruction is reading and writing Q registers. This may upset
6233 // the register scavenger and machine verifier, so we need to indicate
6234 // that we are reading an undefined value from SrcRegQ, but a proper
6235 // value from SrcReg.
6236 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6237 .addReg(SrcRegQ, RegState::Undef)
6238 .addReg(SrcRegQ, RegState::Undef)
6239 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6240 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6241 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6242 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6243 &AArch64::FPR64RegClass);
6244 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6245 &AArch64::FPR64RegClass);
6246 // This instruction is reading and writing D registers. This may upset
6247 // the register scavenger and machine verifier, so we need to indicate
6248 // that we are reading an undefined value from SrcRegD, but a proper
6249 // value from SrcReg.
6250 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6251 .addReg(SrcRegD, RegState::Undef)
6252 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6253 } else {
6254 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6255 &AArch64::FPR32RegClass);
6256 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6257 &AArch64::FPR32RegClass);
6258 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6259 .addReg(SrcReg, getKillRegState(KillSrc));
6260 }
6261 return;
6262 }
6263
6264 if (AArch64::FPR8RegClass.contains(DestReg) &&
6265 AArch64::FPR8RegClass.contains(SrcReg)) {
6266 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6267 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6268 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6269 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6270 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6271 &AArch64::FPR128RegClass);
6272 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6273 &AArch64::FPR128RegClass);
6274 // This instruction is reading and writing Q registers. This may upset
6275 // the register scavenger and machine verifier, so we need to indicate
6276 // that we are reading an undefined value from SrcRegQ, but a proper
6277 // value from SrcReg.
6278 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6279 .addReg(SrcRegQ, RegState::Undef)
6280 .addReg(SrcRegQ, RegState::Undef)
6281 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6282 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6283 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6284 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6285 &AArch64::FPR64RegClass);
6286 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6287 &AArch64::FPR64RegClass);
6288 // This instruction is reading and writing D registers. This may upset
6289 // the register scavenger and machine verifier, so we need to indicate
6290 // that we are reading an undefined value from SrcRegD, but a proper
6291 // value from SrcReg.
6292 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6293 .addReg(SrcRegD, RegState::Undef)
6294 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6295 } else {
6296 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6297 &AArch64::FPR32RegClass);
6298 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6299 &AArch64::FPR32RegClass);
6300 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6301 .addReg(SrcReg, getKillRegState(KillSrc));
6302 }
6303 return;
6304 }
6305
6306 // Copies between GPR64 and FPR64.
6307 if (AArch64::FPR64RegClass.contains(DestReg) &&
6308 AArch64::GPR64RegClass.contains(SrcReg)) {
6309 if (AArch64::XZR == SrcReg) {
6310 BuildMI(MBB, I, DL, get(AArch64::FMOVD0), DestReg);
6311 } else {
6312 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
6313 .addReg(SrcReg, getKillRegState(KillSrc));
6314 }
6315 return;
6316 }
6317 if (AArch64::GPR64RegClass.contains(DestReg) &&
6318 AArch64::FPR64RegClass.contains(SrcReg)) {
6319 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
6320 .addReg(SrcReg, getKillRegState(KillSrc));
6321 return;
6322 }
6323 // Copies between GPR32 and FPR32.
6324 if (AArch64::FPR32RegClass.contains(DestReg) &&
6325 AArch64::GPR32RegClass.contains(SrcReg)) {
6326 if (AArch64::WZR == SrcReg) {
6327 BuildMI(MBB, I, DL, get(AArch64::FMOVS0), DestReg);
6328 } else {
6329 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
6330 .addReg(SrcReg, getKillRegState(KillSrc));
6331 }
6332 return;
6333 }
6334 if (AArch64::GPR32RegClass.contains(DestReg) &&
6335 AArch64::FPR32RegClass.contains(SrcReg)) {
6336 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
6337 .addReg(SrcReg, getKillRegState(KillSrc));
6338 return;
6339 }
6340
6341 if (DestReg == AArch64::NZCV) {
6342 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
6343 BuildMI(MBB, I, DL, get(AArch64::MSR))
6344 .addImm(AArch64SysReg::NZCV)
6345 .addReg(SrcReg, getKillRegState(KillSrc))
6346 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
6347 return;
6348 }
6349
6350 if (SrcReg == AArch64::NZCV) {
6351 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
6352 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
6353 .addImm(AArch64SysReg::NZCV)
6354 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
6355 return;
6356 }
6357
6358#ifndef NDEBUG
6359 errs() << RI.getRegAsmName(DestReg) << " = COPY " << RI.getRegAsmName(SrcReg)
6360 << "\n";
6361#endif
6362 llvm_unreachable("unimplemented reg-to-reg copy");
6363}
6364
6367 const DebugLoc &DL, Register DestReg,
6368 Register SrcReg, bool KillSrc,
6369 bool RenamableDest,
6370 bool RenamableSrc) const {
6371 ++NumCopyInstrs;
6372 copyPhysRegImpl(MBB, I, DL, DestReg, SrcReg, KillSrc, RenamableDest,
6373 RenamableSrc);
6374 return;
6375}
6376
6379 MachineBasicBlock::iterator InsertBefore,
6380 const MCInstrDesc &MCID,
6381 Register SrcReg, bool IsKill,
6382 unsigned SubIdx0, unsigned SubIdx1, int FI,
6383 MachineMemOperand *MMO) {
6384 Register SrcReg0 = SrcReg;
6385 Register SrcReg1 = SrcReg;
6386 if (SrcReg.isPhysical()) {
6387 SrcReg0 = TRI.getSubReg(SrcReg, SubIdx0);
6388 SubIdx0 = 0;
6389 SrcReg1 = TRI.getSubReg(SrcReg, SubIdx1);
6390 SubIdx1 = 0;
6391 }
6392 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6393 .addReg(SrcReg0, getKillRegState(IsKill), SubIdx0)
6394 .addReg(SrcReg1, getKillRegState(IsKill), SubIdx1)
6395 .addFrameIndex(FI)
6396 .addImm(0)
6397 .addMemOperand(MMO);
6398}
6399
6402 Register SrcReg, bool isKill, int FI,
6403 const TargetRegisterClass *RC,
6404 Register VReg,
6405 MachineInstr::MIFlag Flags) const {
6406 MachineFunction &MF = *MBB.getParent();
6407 MachineFrameInfo &MFI = MF.getFrameInfo();
6408
6410 MachineMemOperand *MMO =
6412 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6413 unsigned Opc = 0;
6414 bool Offset = true;
6416 unsigned StackID = TargetStackID::Default;
6417 switch (RI.getSpillSize(*RC)) {
6418 case 1:
6419 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6420 Opc = AArch64::STRBui;
6421 break;
6422 case 2: {
6423 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6424 Opc = AArch64::STRHui;
6425 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6426 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6427 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6428 "Unexpected register store without SVE store instructions");
6429 Opc = AArch64::STR_PXI;
6431 }
6432 break;
6433 }
6434 case 4:
6435 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6436 Opc = AArch64::STRWui;
6437 if (SrcReg.isVirtual())
6438 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
6439 else
6440 assert(SrcReg != AArch64::WSP);
6441 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6442 Opc = AArch64::STRSui;
6443 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6444 Opc = AArch64::STR_PPXI;
6446 }
6447 break;
6448 case 8:
6449 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6450 Opc = AArch64::STRXui;
6451 if (SrcReg.isVirtual())
6452 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
6453 else
6454 assert(SrcReg != AArch64::SP);
6455 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6456 Opc = AArch64::STRDui;
6457 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6459 get(AArch64::STPWi), SrcReg, isKill,
6460 AArch64::sube32, AArch64::subo32, FI, MMO);
6461 return;
6462 }
6463 break;
6464 case 16:
6465 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6466 Opc = AArch64::STRQui;
6467 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6468 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6469 Opc = AArch64::ST1Twov1d;
6470 Offset = false;
6471 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6473 get(AArch64::STPXi), SrcReg, isKill,
6474 AArch64::sube64, AArch64::subo64, FI, MMO);
6475 return;
6476 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6477 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6478 "Unexpected register store without SVE store instructions");
6479 Opc = AArch64::STR_ZXI;
6481 }
6482 break;
6483 case 24:
6484 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6485 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6486 Opc = AArch64::ST1Threev1d;
6487 Offset = false;
6488 }
6489 break;
6490 case 32:
6491 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6492 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6493 Opc = AArch64::ST1Fourv1d;
6494 Offset = false;
6495 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6496 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6497 Opc = AArch64::ST1Twov2d;
6498 Offset = false;
6499 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6500 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6501 "Unexpected register store without SVE store instructions");
6502 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6504 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6505 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6506 "Unexpected register store without SVE store instructions");
6507 Opc = AArch64::STR_ZZXI;
6509 }
6510 break;
6511 case 48:
6512 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6513 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6514 Opc = AArch64::ST1Threev2d;
6515 Offset = false;
6516 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6517 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6518 "Unexpected register store without SVE store instructions");
6519 Opc = AArch64::STR_ZZZXI;
6521 }
6522 break;
6523 case 64:
6524 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6525 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6526 Opc = AArch64::ST1Fourv2d;
6527 Offset = false;
6528 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6529 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6530 "Unexpected register store without SVE store instructions");
6531 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6533 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6534 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6535 "Unexpected register store without SVE store instructions");
6536 Opc = AArch64::STR_ZZZZXI;
6538 }
6539 break;
6540 }
6541 assert(Opc && "Unknown register class");
6542 MFI.setStackID(FI, StackID);
6543
6545 .addReg(SrcReg, getKillRegState(isKill))
6546 .addFrameIndex(FI);
6547
6548 if (Offset)
6549 MI.addImm(0);
6550 if (PNRReg.isValid())
6551 MI.addDef(PNRReg, RegState::Implicit);
6552 MI.addMemOperand(MMO);
6553}
6554
6557 MachineBasicBlock::iterator InsertBefore,
6558 const MCInstrDesc &MCID,
6559 Register DestReg, unsigned SubIdx0,
6560 unsigned SubIdx1, int FI,
6561 MachineMemOperand *MMO) {
6562 Register DestReg0 = DestReg;
6563 Register DestReg1 = DestReg;
6564 bool IsUndef = true;
6565 if (DestReg.isPhysical()) {
6566 DestReg0 = TRI.getSubReg(DestReg, SubIdx0);
6567 SubIdx0 = 0;
6568 DestReg1 = TRI.getSubReg(DestReg, SubIdx1);
6569 SubIdx1 = 0;
6570 IsUndef = false;
6571 }
6572 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6573 .addReg(DestReg0, RegState::Define | getUndefRegState(IsUndef), SubIdx0)
6574 .addReg(DestReg1, RegState::Define | getUndefRegState(IsUndef), SubIdx1)
6575 .addFrameIndex(FI)
6576 .addImm(0)
6577 .addMemOperand(MMO);
6578}
6579
6582 Register DestReg, int FI,
6583 const TargetRegisterClass *RC,
6584 Register VReg, unsigned SubReg,
6585 MachineInstr::MIFlag Flags) const {
6586 MachineFunction &MF = *MBB.getParent();
6587 MachineFrameInfo &MFI = MF.getFrameInfo();
6589 MachineMemOperand *MMO =
6591 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6592
6593 unsigned Opc = 0;
6594 bool Offset = true;
6595 unsigned StackID = TargetStackID::Default;
6597 switch (TRI.getSpillSize(*RC)) {
6598 case 1:
6599 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6600 Opc = AArch64::LDRBui;
6601 break;
6602 case 2: {
6603 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6604 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6605 Opc = AArch64::LDRHui;
6606 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6607 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6608 "Unexpected register load without SVE load instructions");
6609 if (IsPNR)
6610 PNRReg = DestReg;
6611 Opc = AArch64::LDR_PXI;
6613 }
6614 break;
6615 }
6616 case 4:
6617 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6618 Opc = AArch64::LDRWui;
6619 if (DestReg.isVirtual())
6620 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
6621 else
6622 assert(DestReg != AArch64::WSP);
6623 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6624 Opc = AArch64::LDRSui;
6625 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6626 Opc = AArch64::LDR_PPXI;
6628 }
6629 break;
6630 case 8:
6631 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6632 Opc = AArch64::LDRXui;
6633 if (DestReg.isVirtual())
6634 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
6635 else
6636 assert(DestReg != AArch64::SP);
6637 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6638 Opc = AArch64::LDRDui;
6639 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6641 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6642 AArch64::subo32, FI, MMO);
6643 return;
6644 }
6645 break;
6646 case 16:
6647 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6648 Opc = AArch64::LDRQui;
6649 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6650 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6651 Opc = AArch64::LD1Twov1d;
6652 Offset = false;
6653 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6655 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6656 AArch64::subo64, FI, MMO);
6657 return;
6658 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6659 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6660 "Unexpected register load without SVE load instructions");
6661 Opc = AArch64::LDR_ZXI;
6663 }
6664 break;
6665 case 24:
6666 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6667 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6668 Opc = AArch64::LD1Threev1d;
6669 Offset = false;
6670 }
6671 break;
6672 case 32:
6673 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6674 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6675 Opc = AArch64::LD1Fourv1d;
6676 Offset = false;
6677 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6678 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6679 Opc = AArch64::LD1Twov2d;
6680 Offset = false;
6681 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6682 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6683 "Unexpected register load without SVE load instructions");
6684 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6686 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6687 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6688 "Unexpected register load without SVE load instructions");
6689 Opc = AArch64::LDR_ZZXI;
6691 }
6692 break;
6693 case 48:
6694 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6695 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6696 Opc = AArch64::LD1Threev2d;
6697 Offset = false;
6698 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6699 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6700 "Unexpected register load without SVE load instructions");
6701 Opc = AArch64::LDR_ZZZXI;
6703 }
6704 break;
6705 case 64:
6706 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6707 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6708 Opc = AArch64::LD1Fourv2d;
6709 Offset = false;
6710 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6711 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6712 "Unexpected register load without SVE load instructions");
6713 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6715 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6716 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6717 "Unexpected register load without SVE load instructions");
6718 Opc = AArch64::LDR_ZZZZXI;
6720 }
6721 break;
6722 }
6723
6724 assert(Opc && "Unknown register class");
6725 MFI.setStackID(FI, StackID);
6726
6728 .addReg(DestReg, getDefRegState(true))
6729 .addFrameIndex(FI);
6730 if (Offset)
6731 MI.addImm(0);
6732 if (PNRReg.isValid() && !PNRReg.isVirtual())
6733 MI.addDef(PNRReg, RegState::Implicit);
6734 MI.addMemOperand(MMO);
6735}
6736
6738 const MachineInstr &UseMI,
6739 const TargetRegisterInfo *TRI) {
6740 return any_of(instructionsWithoutDebug(std::next(DefMI.getIterator()),
6741 UseMI.getIterator()),
6742 [TRI](const MachineInstr &I) {
6743 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6744 I.readsRegister(AArch64::NZCV, TRI);
6745 });
6746}
6747
6748void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6749 const StackOffset &Offset, int64_t &ByteSized, int64_t &VGSized) {
6750 // The smallest scalable element supported by scaled SVE addressing
6751 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6752 // byte offset must always be a multiple of 2.
6753 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6754
6755 // VGSized offsets are divided by '2', because the VG register is the
6756 // the number of 64bit granules as opposed to 128bit vector chunks,
6757 // which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
6758 // So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
6759 // VG = n * 2 and the dwarf offset must be VG * 8 bytes.
6760 ByteSized = Offset.getFixed();
6761 VGSized = Offset.getScalable() / 2;
6762}
6763
6764/// Returns the offset in parts to which this frame offset can be
6765/// decomposed for the purpose of describing a frame offset.
6766/// For non-scalable offsets this is simply its byte size.
6767void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6768 const StackOffset &Offset, int64_t &NumBytes, int64_t &NumPredicateVectors,
6769 int64_t &NumDataVectors) {
6770 // The smallest scalable element supported by scaled SVE addressing
6771 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6772 // byte offset must always be a multiple of 2.
6773 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6774
6775 NumBytes = Offset.getFixed();
6776 NumDataVectors = 0;
6777 NumPredicateVectors = Offset.getScalable() / 2;
6778 // This method is used to get the offsets to adjust the frame offset.
6779 // If the function requires ADDPL to be used and needs more than two ADDPL
6780 // instructions, part of the offset is folded into NumDataVectors so that it
6781 // uses ADDVL for part of it, reducing the number of ADDPL instructions.
6782 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6783 NumPredicateVectors > 62) {
6784 NumDataVectors = NumPredicateVectors / 8;
6785 NumPredicateVectors -= NumDataVectors * 8;
6786 }
6787}
6788
6789// Convenience function to create a DWARF expression for: Constant `Operation`.
6790// This helper emits compact sequences for common cases. For example, for`-15
6791// DW_OP_plus`, this helper would create DW_OP_lit15 DW_OP_minus.
6794 if (Operation == dwarf::DW_OP_plus && Constant < 0 && -Constant <= 31) {
6795 // -Constant (1 to 31)
6796 Expr.push_back(dwarf::DW_OP_lit0 - Constant);
6797 Operation = dwarf::DW_OP_minus;
6798 } else if (Constant >= 0 && Constant <= 31) {
6799 // Literal value 0 to 31
6800 Expr.push_back(dwarf::DW_OP_lit0 + Constant);
6801 } else {
6802 // Signed constant
6803 Expr.push_back(dwarf::DW_OP_consts);
6805 }
6806 return Expr.push_back(Operation);
6807}
6808
6809// Convenience function to create a DWARF expression for a register.
6810static void appendReadRegExpr(SmallVectorImpl<char> &Expr, unsigned RegNum) {
6811 Expr.push_back((char)dwarf::DW_OP_bregx);
6813 Expr.push_back(0);
6814}
6815
6816// Convenience function to create a DWARF expression for loading a register from
6817// a CFA offset.
6819 int64_t OffsetFromDefCFA) {
6820 // This assumes the top of the DWARF stack contains the CFA.
6821 Expr.push_back(dwarf::DW_OP_dup);
6822 // Add the offset to the register.
6823 appendConstantExpr(Expr, OffsetFromDefCFA, dwarf::DW_OP_plus);
6824 // Dereference the address (loads a 64 bit value)..
6825 Expr.push_back(dwarf::DW_OP_deref);
6826}
6827
6828// Convenience function to create a comment for
6829// (+/-) NumBytes (* RegScale)?
6830static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment,
6831 StringRef RegScale = {}) {
6832 if (NumBytes) {
6833 Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
6834 if (!RegScale.empty())
6835 Comment << ' ' << RegScale;
6836 }
6837}
6838
6839// Creates an MCCFIInstruction:
6840// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
6842 unsigned Reg,
6843 const StackOffset &Offset) {
6844 int64_t NumBytes, NumVGScaledBytes;
6845 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(Offset, NumBytes,
6846 NumVGScaledBytes);
6847 std::string CommentBuffer;
6848 llvm::raw_string_ostream Comment(CommentBuffer);
6849
6850 if (Reg == AArch64::SP)
6851 Comment << "sp";
6852 else if (Reg == AArch64::FP)
6853 Comment << "fp";
6854 else
6855 Comment << printReg(Reg, &TRI);
6856
6857 // Build up the expression (Reg + NumBytes + VG * NumVGScaledBytes)
6858 SmallString<64> Expr;
6859 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6860 assert(DwarfReg <= 31 && "DwarfReg out of bounds (0..31)");
6861 // Reg + NumBytes
6862 Expr.push_back(dwarf::DW_OP_breg0 + DwarfReg);
6863 appendLEB128<LEB128Sign::Signed>(Expr, NumBytes);
6864 appendOffsetComment(NumBytes, Comment);
6865 if (NumVGScaledBytes) {
6866 // + VG * NumVGScaledBytes
6867 appendOffsetComment(NumVGScaledBytes, Comment, "* VG");
6868 appendReadRegExpr(Expr, TRI.getDwarfRegNum(AArch64::VG, true));
6869 appendConstantExpr(Expr, NumVGScaledBytes, dwarf::DW_OP_mul);
6870 Expr.push_back(dwarf::DW_OP_plus);
6871 }
6872
6873 // Wrap this into DW_CFA_def_cfa.
6874 SmallString<64> DefCfaExpr;
6875 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
6876 appendLEB128<LEB128Sign::Unsigned>(DefCfaExpr, Expr.size());
6877 DefCfaExpr.append(Expr.str());
6878 return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
6879 Comment.str());
6880}
6881
6883 unsigned FrameReg, unsigned Reg,
6884 const StackOffset &Offset,
6885 bool LastAdjustmentWasScalable) {
6886 if (Offset.getScalable())
6887 return createDefCFAExpression(TRI, Reg, Offset);
6888
6889 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6890 return MCCFIInstruction::cfiDefCfaOffset(nullptr, int(Offset.getFixed()));
6891
6892 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6893 return MCCFIInstruction::cfiDefCfa(nullptr, DwarfReg, (int)Offset.getFixed());
6894}
6895
6898 const StackOffset &OffsetFromDefCFA,
6899 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6900 int64_t NumBytes, NumVGScaledBytes;
6901 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6902 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6903
6904 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6905
6906 // Non-scalable offsets can use DW_CFA_offset directly.
6907 if (!NumVGScaledBytes)
6908 return MCCFIInstruction::createOffset(nullptr, DwarfReg, NumBytes);
6909
6910 std::string CommentBuffer;
6911 llvm::raw_string_ostream Comment(CommentBuffer);
6912 Comment << printReg(Reg, &TRI) << " @ cfa";
6913
6914 // Build up expression (CFA + VG * NumVGScaledBytes + NumBytes)
6915 assert(NumVGScaledBytes && "Expected scalable offset");
6916 SmallString<64> OffsetExpr;
6917 // + VG * NumVGScaledBytes
6918 StringRef VGRegScale;
6919 if (IncomingVGOffsetFromDefCFA) {
6920 appendLoadRegExpr(OffsetExpr, *IncomingVGOffsetFromDefCFA);
6921 VGRegScale = "* IncomingVG";
6922 } else {
6923 appendReadRegExpr(OffsetExpr, TRI.getDwarfRegNum(AArch64::VG, true));
6924 VGRegScale = "* VG";
6925 }
6926 appendConstantExpr(OffsetExpr, NumVGScaledBytes, dwarf::DW_OP_mul);
6927 appendOffsetComment(NumVGScaledBytes, Comment, VGRegScale);
6928 OffsetExpr.push_back(dwarf::DW_OP_plus);
6929 if (NumBytes) {
6930 // + NumBytes
6931 appendOffsetComment(NumBytes, Comment);
6932 appendConstantExpr(OffsetExpr, NumBytes, dwarf::DW_OP_plus);
6933 }
6934
6935 // Wrap this into DW_CFA_expression
6936 SmallString<64> CfaExpr;
6937 CfaExpr.push_back(dwarf::DW_CFA_expression);
6938 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, DwarfReg);
6939 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, OffsetExpr.size());
6940 CfaExpr.append(OffsetExpr.str());
6941
6942 return MCCFIInstruction::createEscape(nullptr, CfaExpr.str(), SMLoc(),
6943 Comment.str());
6944}
6945
6946// Helper function to emit a frame offset adjustment from a given
6947// pointer (SrcReg), stored into DestReg. This function is explicit
6948// in that it requires the opcode.
6951 const DebugLoc &DL, unsigned DestReg,
6952 unsigned SrcReg, int64_t Offset, unsigned Opc,
6953 const TargetInstrInfo *TII,
6954 MachineInstr::MIFlag Flag, bool NeedsWinCFI,
6955 bool *HasWinCFI, bool EmitCFAOffset,
6956 StackOffset CFAOffset, unsigned FrameReg) {
6957 int Sign = 1;
6958 unsigned MaxEncoding, ShiftSize;
6959 switch (Opc) {
6960 case AArch64::ADDXri:
6961 case AArch64::ADDSXri:
6962 case AArch64::SUBXri:
6963 case AArch64::SUBSXri:
6964 MaxEncoding = 0xfff;
6965 ShiftSize = 12;
6966 break;
6967 case AArch64::ADDVL_XXI:
6968 case AArch64::ADDPL_XXI:
6969 case AArch64::ADDSVL_XXI:
6970 case AArch64::ADDSPL_XXI:
6971 MaxEncoding = 31;
6972 ShiftSize = 0;
6973 if (Offset < 0) {
6974 MaxEncoding = 32;
6975 Sign = -1;
6976 Offset = -Offset;
6977 }
6978 break;
6979 default:
6980 llvm_unreachable("Unsupported opcode");
6981 }
6982
6983 // `Offset` can be in bytes or in "scalable bytes".
6984 int VScale = 1;
6985 if (Opc == AArch64::ADDVL_XXI || Opc == AArch64::ADDSVL_XXI)
6986 VScale = 16;
6987 else if (Opc == AArch64::ADDPL_XXI || Opc == AArch64::ADDSPL_XXI)
6988 VScale = 2;
6989
6990 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
6991 // scratch register. If DestReg is a virtual register, use it as the
6992 // scratch register; otherwise, create a new virtual register (to be
6993 // replaced by the scavenger at the end of PEI). That case can be optimized
6994 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
6995 // register can be loaded with offset%8 and the add/sub can use an extending
6996 // instruction with LSL#3.
6997 // Currently the function handles any offsets but generates a poor sequence
6998 // of code.
6999 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
7000
7001 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
7002 Register TmpReg = DestReg;
7003 if (TmpReg == AArch64::XZR)
7004 TmpReg = MBB.getParent()->getRegInfo().createVirtualRegister(
7005 &AArch64::GPR64RegClass);
7006 do {
7007 uint64_t ThisVal = std::min<uint64_t>(Offset, MaxEncodableValue);
7008 unsigned LocalShiftSize = 0;
7009 if (ThisVal > MaxEncoding) {
7010 ThisVal = ThisVal >> ShiftSize;
7011 LocalShiftSize = ShiftSize;
7012 }
7013 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
7014 "Encoding cannot handle value that big");
7015
7016 Offset -= ThisVal << LocalShiftSize;
7017 if (Offset == 0)
7018 TmpReg = DestReg;
7019 auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), TmpReg)
7020 .addReg(SrcReg)
7021 .addImm(Sign * (int)ThisVal);
7022 if (ShiftSize)
7023 MBI = MBI.addImm(
7025 MBI = MBI.setMIFlag(Flag);
7026
7027 auto Change =
7028 VScale == 1
7029 ? StackOffset::getFixed(ThisVal << LocalShiftSize)
7030 : StackOffset::getScalable(VScale * (ThisVal << LocalShiftSize));
7031 if (Sign == -1 || Opc == AArch64::SUBXri || Opc == AArch64::SUBSXri)
7032 CFAOffset += Change;
7033 else
7034 CFAOffset -= Change;
7035 if (EmitCFAOffset && DestReg == TmpReg) {
7036 MachineFunction &MF = *MBB.getParent();
7037 const TargetSubtargetInfo &STI = MF.getSubtarget();
7038 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
7039
7040 unsigned CFIIndex = MF.addFrameInst(
7041 createDefCFA(TRI, FrameReg, DestReg, CFAOffset, VScale != 1));
7042 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
7043 .addCFIIndex(CFIIndex)
7044 .setMIFlags(Flag);
7045 }
7046
7047 if (NeedsWinCFI) {
7048 int Imm = (int)(ThisVal << LocalShiftSize);
7049 if (VScale != 1 && DestReg == AArch64::SP) {
7050 if (HasWinCFI)
7051 *HasWinCFI = true;
7052 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ))
7053 .addImm(ThisVal)
7054 .setMIFlag(Flag);
7055 } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7056 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7057 assert(VScale == 1 && "Expected non-scalable operation");
7058 if (HasWinCFI)
7059 *HasWinCFI = true;
7060 if (Imm == 0)
7061 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
7062 else
7063 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
7064 .addImm(Imm)
7065 .setMIFlag(Flag);
7066 assert(Offset == 0 && "Expected remaining offset to be zero to "
7067 "emit a single SEH directive");
7068 } else if (DestReg == AArch64::SP) {
7069 assert(VScale == 1 && "Expected non-scalable operation");
7070 if (HasWinCFI)
7071 *HasWinCFI = true;
7072 assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
7073 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
7074 .addImm(Imm)
7075 .setMIFlag(Flag);
7076 }
7077 }
7078
7079 SrcReg = TmpReg;
7080 } while (Offset);
7081}
7082
7085 unsigned DestReg, unsigned SrcReg,
7087 MachineInstr::MIFlag Flag, bool SetNZCV,
7088 bool NeedsWinCFI, bool *HasWinCFI,
7089 bool EmitCFAOffset, StackOffset CFAOffset,
7090 unsigned FrameReg) {
7091 // If a function is marked as arm_locally_streaming, then the runtime value of
7092 // vscale in the prologue/epilogue is different the runtime value of vscale
7093 // in the function's body. To avoid having to consider multiple vscales,
7094 // we can use `addsvl` to allocate any scalable stack-slots, which under
7095 // most circumstances will be only locals, not callee-save slots.
7096 const Function &F = MBB.getParent()->getFunction();
7097 bool UseSVL = F.hasFnAttribute("aarch64_pstate_sm_body");
7098
7099 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7100 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7101 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7102
7103 // Insert ADDSXri for scalable offset at the end.
7104 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7105 if (NeedsFinalDefNZCV)
7106 SetNZCV = false;
7107
7108 // First emit non-scalable frame offsets, or a simple 'mov'.
7109 if (Bytes || (!Offset && SrcReg != DestReg)) {
7110 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7111 "SP increment/decrement not 8-byte aligned");
7112 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7113 if (Bytes < 0) {
7114 Bytes = -Bytes;
7115 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7116 }
7117 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
7118 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7119 FrameReg);
7120 CFAOffset += (Opc == AArch64::ADDXri || Opc == AArch64::ADDSXri)
7121 ? StackOffset::getFixed(-Bytes)
7122 : StackOffset::getFixed(Bytes);
7123 SrcReg = DestReg;
7124 FrameReg = DestReg;
7125 }
7126
7127 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7128 "WinCFI can't allocate fractions of an SVE data vector");
7129
7130 if (NumDataVectors) {
7131 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors,
7132 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII,
7133 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7134 FrameReg);
7135 CFAOffset += StackOffset::getScalable(-NumDataVectors * 16);
7136 SrcReg = DestReg;
7137 }
7138
7139 if (NumPredicateVectors) {
7140 assert(DestReg != AArch64::SP && "Unaligned access to SP");
7141 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors,
7142 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII,
7143 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7144 FrameReg);
7145 }
7146
7147 if (NeedsFinalDefNZCV)
7148 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDSXri), DestReg)
7149 .addReg(DestReg)
7150 .addImm(0)
7151 .addImm(0);
7152}
7153
7156 int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS,
7157 VirtRegMap *VRM) const {
7159 // This is a bit of a hack. Consider this instruction:
7160 //
7161 // %0 = COPY %sp; GPR64all:%0
7162 //
7163 // We explicitly chose GPR64all for the virtual register so such a copy might
7164 // be eliminated by RegisterCoalescer. However, that may not be possible, and
7165 // %0 may even spill. We can't spill %sp, and since it is in the GPR64all
7166 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
7167 //
7168 // To prevent that, we are going to constrain the %0 register class here.
7169 if (MI.isFullCopy()) {
7170 Register DstReg = MI.getOperand(0).getReg();
7171 Register SrcReg = MI.getOperand(1).getReg();
7172 if (SrcReg == AArch64::SP && DstReg.isVirtual()) {
7173 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
7174 return nullptr;
7175 }
7176 if (DstReg == AArch64::SP && SrcReg.isVirtual()) {
7177 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
7178 return nullptr;
7179 }
7180 // Nothing can folded with copy from/to NZCV.
7181 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7182 return nullptr;
7183 }
7184
7185 // Handle the case where a copy is being spilled or filled but the source
7186 // and destination register class don't match. For example:
7187 //
7188 // %0 = COPY %xzr; GPR64common:%0
7189 //
7190 // In this case we can still safely fold away the COPY and generate the
7191 // following spill code:
7192 //
7193 // STRXui %xzr, %stack.0
7194 //
7195 // This also eliminates spilled cross register class COPYs (e.g. between x and
7196 // d regs) of the same size. For example:
7197 //
7198 // %0 = COPY %1; GPR64:%0, FPR64:%1
7199 //
7200 // will be filled as
7201 //
7202 // LDRDui %0, fi<#0>
7203 //
7204 // instead of
7205 //
7206 // LDRXui %Temp, fi<#0>
7207 // %0 = FMOV %Temp
7208 //
7209 if (MI.isCopy() && Ops.size() == 1 &&
7210 // Make sure we're only folding the explicit COPY defs/uses.
7211 (Ops[0] == 0 || Ops[0] == 1)) {
7212 bool IsSpill = Ops[0] == 0;
7213 bool IsFill = !IsSpill;
7215 const MachineRegisterInfo &MRI = MF.getRegInfo();
7216 MachineBasicBlock &MBB = *MI.getParent();
7217 const MachineOperand &DstMO = MI.getOperand(0);
7218 const MachineOperand &SrcMO = MI.getOperand(1);
7219 Register DstReg = DstMO.getReg();
7220 Register SrcReg = SrcMO.getReg();
7221 // This is slightly expensive to compute for physical regs since
7222 // getMinimalPhysRegClass is slow.
7223 auto getRegClass = [&](unsigned Reg) {
7224 return Register::isVirtualRegister(Reg) ? MRI.getRegClass(Reg)
7225 : TRI.getMinimalPhysRegClass(Reg);
7226 };
7227
7228 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
7229 assert(TRI.getRegSizeInBits(*getRegClass(DstReg)) ==
7230 TRI.getRegSizeInBits(*getRegClass(SrcReg)) &&
7231 "Mismatched register size in non subreg COPY");
7232 if (IsSpill)
7233 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
7234 getRegClass(SrcReg), Register());
7235 else
7236 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
7237 getRegClass(DstReg), Register());
7238 return &*--InsertPt;
7239 }
7240
7241 // Handle cases like spilling def of:
7242 //
7243 // %0:sub_32<def,read-undef> = COPY %wzr; GPR64common:%0
7244 //
7245 // where the physical register source can be widened and stored to the full
7246 // virtual reg destination stack slot, in this case producing:
7247 //
7248 // STRXui %xzr, %stack.0
7249 //
7250 if (IsSpill && DstMO.isUndef() && SrcReg == AArch64::WZR &&
7251 TRI.getRegSizeInBits(*getRegClass(DstReg)) == 64) {
7252 assert(SrcMO.getSubReg() == 0 &&
7253 "Unexpected subreg on physical register");
7254 storeRegToStackSlot(MBB, InsertPt, AArch64::XZR, SrcMO.isKill(),
7255 FrameIndex, &AArch64::GPR64RegClass, Register());
7256 return &*--InsertPt;
7257 }
7258
7259 // Handle cases like filling use of:
7260 //
7261 // %0:sub_32<def,read-undef> = COPY %1; GPR64:%0, GPR32:%1
7262 //
7263 // where we can load the full virtual reg source stack slot, into the subreg
7264 // destination, in this case producing:
7265 //
7266 // LDRWui %0:sub_32<def,read-undef>, %stack.0
7267 //
7268 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
7269 const TargetRegisterClass *FillRC = nullptr;
7270 switch (DstMO.getSubReg()) {
7271 default:
7272 break;
7273 case AArch64::sub_32:
7274 if (AArch64::GPR64RegClass.hasSubClassEq(getRegClass(DstReg)))
7275 FillRC = &AArch64::GPR32RegClass;
7276 break;
7277 case AArch64::ssub:
7278 FillRC = &AArch64::FPR32RegClass;
7279 break;
7280 case AArch64::dsub:
7281 FillRC = &AArch64::FPR64RegClass;
7282 break;
7283 }
7284
7285 if (FillRC) {
7286 assert(TRI.getRegSizeInBits(*getRegClass(SrcReg)) ==
7287 TRI.getRegSizeInBits(*FillRC) &&
7288 "Mismatched regclass size on folded subreg COPY");
7289 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC,
7290 Register());
7291 MachineInstr &LoadMI = *--InsertPt;
7292 MachineOperand &LoadDst = LoadMI.getOperand(0);
7293 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
7294 LoadDst.setSubReg(DstMO.getSubReg());
7295 LoadDst.setIsUndef();
7296 return &LoadMI;
7297 }
7298 }
7299 }
7300
7301 // Cannot fold.
7302 return nullptr;
7303}
7304
7306 StackOffset &SOffset,
7307 bool *OutUseUnscaledOp,
7308 unsigned *OutUnscaledOp,
7309 int64_t *EmittableOffset) {
7310 // Set output values in case of early exit.
7311 if (EmittableOffset)
7312 *EmittableOffset = 0;
7313 if (OutUseUnscaledOp)
7314 *OutUseUnscaledOp = false;
7315 if (OutUnscaledOp)
7316 *OutUnscaledOp = 0;
7317
7318 // Exit early for structured vector spills/fills as they can't take an
7319 // immediate offset.
7320 switch (MI.getOpcode()) {
7321 default:
7322 break;
7323 case AArch64::LD1Rv1d:
7324 case AArch64::LD1Rv2s:
7325 case AArch64::LD1Rv2d:
7326 case AArch64::LD1Rv4h:
7327 case AArch64::LD1Rv4s:
7328 case AArch64::LD1Rv8b:
7329 case AArch64::LD1Rv8h:
7330 case AArch64::LD1Rv16b:
7331 case AArch64::LD1Twov2d:
7332 case AArch64::LD1Threev2d:
7333 case AArch64::LD1Fourv2d:
7334 case AArch64::LD1Twov1d:
7335 case AArch64::LD1Threev1d:
7336 case AArch64::LD1Fourv1d:
7337 case AArch64::ST1Twov2d:
7338 case AArch64::ST1Threev2d:
7339 case AArch64::ST1Fourv2d:
7340 case AArch64::ST1Twov1d:
7341 case AArch64::ST1Threev1d:
7342 case AArch64::ST1Fourv1d:
7343 case AArch64::ST1i8:
7344 case AArch64::ST1i16:
7345 case AArch64::ST1i32:
7346 case AArch64::ST1i64:
7347 case AArch64::IRG:
7348 case AArch64::IRGstack:
7349 case AArch64::STGloop:
7350 case AArch64::STZGloop:
7352 }
7353
7354 // Get the min/max offset and the scale.
7355 TypeSize ScaleValue(0U, false), Width(0U, false);
7356 int64_t MinOff, MaxOff;
7357 if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), ScaleValue, Width, MinOff,
7358 MaxOff))
7359 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7360
7361 // Construct the complete offset.
7362 bool IsMulVL = ScaleValue.isScalable();
7363 unsigned Scale = ScaleValue.getKnownMinValue();
7364 int64_t Offset = IsMulVL ? SOffset.getScalable() : SOffset.getFixed();
7365
7366 const MachineOperand &ImmOpnd =
7367 MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode()));
7368 Offset += ImmOpnd.getImm() * Scale;
7369
7370 // If the offset doesn't match the scale, we rewrite the instruction to
7371 // use the unscaled instruction instead. Likewise, if we have a negative
7372 // offset and there is an unscaled op to use.
7373 std::optional<unsigned> UnscaledOp =
7375 bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0);
7376 if (useUnscaledOp &&
7377 !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, ScaleValue, Width, MinOff,
7378 MaxOff))
7379 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7380
7381 Scale = ScaleValue.getKnownMinValue();
7382 assert(IsMulVL == ScaleValue.isScalable() &&
7383 "Unscaled opcode has different value for scalable");
7384
7385 int64_t Remainder = Offset % Scale;
7386 assert(!(Remainder && useUnscaledOp) &&
7387 "Cannot have remainder when using unscaled op");
7388
7389 assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
7390 int64_t NewOffset = Offset / Scale;
7391 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7392 Offset = Remainder;
7393 else {
7394 // Try to minimise the number of instructions required to materialise the
7395 // offset calculation. Specifically, for fixed offsets, if masking out the
7396 // low 12 bits leaves a legal add immediate, we can realise the offset
7397 // calculation with a single add instruction. Whenever this is possible,
7398 // prefer this split.
7399 int64_t HighPart = Offset & ~0xFFF;
7400 int64_t LowPart = Offset & 0xFFF;
7401 int64_t LowScaled = LowPart / Scale;
7402 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7403 MinOff <= LowScaled && LowScaled <= MaxOff &&
7405 NewOffset = LowScaled;
7406 Offset = HighPart;
7407 } else {
7408 // Default to a greedy split: take the memop immediate to be maximum /
7409 // minimum expressible offset and materialise the remainder.
7410 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7411 Offset = Offset - (NewOffset * Scale);
7412 }
7413 }
7414
7415 if (EmittableOffset)
7416 *EmittableOffset = NewOffset;
7417 if (OutUseUnscaledOp)
7418 *OutUseUnscaledOp = useUnscaledOp;
7419 if (OutUnscaledOp && UnscaledOp)
7420 *OutUnscaledOp = *UnscaledOp;
7421
7422 if (IsMulVL)
7423 SOffset = StackOffset::get(SOffset.getFixed(), Offset);
7424 else
7425 SOffset = StackOffset::get(Offset, SOffset.getScalable());
7427 (SOffset ? 0 : AArch64FrameOffsetIsLegal);
7428}
7429
7431 unsigned FrameReg, StackOffset &Offset,
7432 const AArch64InstrInfo *TII) {
7433 unsigned Opcode = MI.getOpcode();
7434 unsigned ImmIdx = FrameRegIdx + 1;
7435
7436 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7437 Offset += StackOffset::getFixed(MI.getOperand(ImmIdx).getImm());
7438 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
7439 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
7440 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
7441 MI.eraseFromParent();
7442 Offset = StackOffset();
7443 return true;
7444 }
7445
7446 int64_t NewOffset;
7447 unsigned UnscaledOp;
7448 bool UseUnscaledOp;
7449 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
7450 &UnscaledOp, &NewOffset);
7453 // Replace the FrameIndex with FrameReg.
7454 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
7455 if (UseUnscaledOp)
7456 MI.setDesc(TII->get(UnscaledOp));
7457
7458 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7459 return !Offset;
7460 }
7461
7462 return false;
7463}
7464
7470
7471MCInst AArch64InstrInfo::getNop() const { return MCInstBuilder(AArch64::NOP); }
7472
7473// AArch64 supports MachineCombiner.
7474bool AArch64InstrInfo::useMachineCombiner() const { return true; }
7475
7476// True when Opc sets flag
7477static bool isCombineInstrSettingFlag(unsigned Opc) {
7478 switch (Opc) {
7479 case AArch64::ADDSWrr:
7480 case AArch64::ADDSWri:
7481 case AArch64::ADDSXrr:
7482 case AArch64::ADDSXri:
7483 case AArch64::SUBSWrr:
7484 case AArch64::SUBSXrr:
7485 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7486 case AArch64::SUBSWri:
7487 case AArch64::SUBSXri:
7488 return true;
7489 default:
7490 break;
7491 }
7492 return false;
7493}
7494
7495// 32b Opcodes that can be combined with a MUL
7496static bool isCombineInstrCandidate32(unsigned Opc) {
7497 switch (Opc) {
7498 case AArch64::ADDWrr:
7499 case AArch64::ADDWri:
7500 case AArch64::SUBWrr:
7501 case AArch64::ADDSWrr:
7502 case AArch64::ADDSWri:
7503 case AArch64::SUBSWrr:
7504 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7505 case AArch64::SUBWri:
7506 case AArch64::SUBSWri:
7507 return true;
7508 default:
7509 break;
7510 }
7511 return false;
7512}
7513
7514// 64b Opcodes that can be combined with a MUL
7515static bool isCombineInstrCandidate64(unsigned Opc) {
7516 switch (Opc) {
7517 case AArch64::ADDXrr:
7518 case AArch64::ADDXri:
7519 case AArch64::SUBXrr:
7520 case AArch64::ADDSXrr:
7521 case AArch64::ADDSXri:
7522 case AArch64::SUBSXrr:
7523 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7524 case AArch64::SUBXri:
7525 case AArch64::SUBSXri:
7526 case AArch64::ADDv8i8:
7527 case AArch64::ADDv16i8:
7528 case AArch64::ADDv4i16:
7529 case AArch64::ADDv8i16:
7530 case AArch64::ADDv2i32:
7531 case AArch64::ADDv4i32:
7532 case AArch64::SUBv8i8:
7533 case AArch64::SUBv16i8:
7534 case AArch64::SUBv4i16:
7535 case AArch64::SUBv8i16:
7536 case AArch64::SUBv2i32:
7537 case AArch64::SUBv4i32:
7538 return true;
7539 default:
7540 break;
7541 }
7542 return false;
7543}
7544
7545// FP Opcodes that can be combined with a FMUL.
7546static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
7547 switch (Inst.getOpcode()) {
7548 default:
7549 break;
7550 case AArch64::FADDHrr:
7551 case AArch64::FADDSrr:
7552 case AArch64::FADDDrr:
7553 case AArch64::FADDv4f16:
7554 case AArch64::FADDv8f16:
7555 case AArch64::FADDv2f32:
7556 case AArch64::FADDv2f64:
7557 case AArch64::FADDv4f32:
7558 case AArch64::FSUBHrr:
7559 case AArch64::FSUBSrr:
7560 case AArch64::FSUBDrr:
7561 case AArch64::FSUBv4f16:
7562 case AArch64::FSUBv8f16:
7563 case AArch64::FSUBv2f32:
7564 case AArch64::FSUBv2f64:
7565 case AArch64::FSUBv4f32:
7567 // We can fuse FADD/FSUB with FMUL, if fusion is either allowed globally by
7568 // the target options or if FADD/FSUB has the contract fast-math flag.
7569 return Options.AllowFPOpFusion == FPOpFusion::Fast ||
7571 }
7572 return false;
7573}
7574
7575// Opcodes that can be combined with a MUL
7579
7580//
7581// Utility routine that checks if \param MO is defined by an
7582// \param CombineOpc instruction in the basic block \param MBB
7584 unsigned CombineOpc, unsigned ZeroReg = 0,
7585 bool CheckZeroReg = false) {
7586 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
7587 MachineInstr *MI = nullptr;
7588
7589 if (MO.isReg() && MO.getReg().isVirtual())
7590 MI = MRI.getUniqueVRegDef(MO.getReg());
7591 // And it needs to be in the trace (otherwise, it won't have a depth).
7592 if (!MI || MI->getParent() != &MBB || MI->getOpcode() != CombineOpc)
7593 return false;
7594 // Must only used by the user we combine with.
7595 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
7596 return false;
7597
7598 if (CheckZeroReg) {
7599 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
7600 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
7601 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
7602 // The third input reg must be zero.
7603 if (MI->getOperand(3).getReg() != ZeroReg)
7604 return false;
7605 }
7606
7607 if (isCombineInstrSettingFlag(CombineOpc) &&
7608 MI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) == -1)
7609 return false;
7610
7611 return true;
7612}
7613
7614//
7615// Is \param MO defined by an integer multiply and can be combined?
7617 unsigned MulOpc, unsigned ZeroReg) {
7618 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
7619}
7620
7621//
7622// Is \param MO defined by a floating-point multiply and can be combined?
7624 unsigned MulOpc) {
7625 return canCombine(MBB, MO, MulOpc);
7626}
7627
7628// TODO: There are many more machine instruction opcodes to match:
7629// 1. Other data types (integer, vectors)
7630// 2. Other math / logic operations (xor, or)
7631// 3. Other forms of the same operation (intrinsics and other variants)
7632bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
7633 bool Invert) const {
7634 if (Invert)
7635 return false;
7636 switch (Inst.getOpcode()) {
7637 // == Floating-point types ==
7638 // -- Floating-point instructions --
7639 case AArch64::FADDHrr:
7640 case AArch64::FADDSrr:
7641 case AArch64::FADDDrr:
7642 case AArch64::FMULHrr:
7643 case AArch64::FMULSrr:
7644 case AArch64::FMULDrr:
7645 case AArch64::FMULX16:
7646 case AArch64::FMULX32:
7647 case AArch64::FMULX64:
7648 // -- Advanced SIMD instructions --
7649 case AArch64::FADDv4f16:
7650 case AArch64::FADDv8f16:
7651 case AArch64::FADDv2f32:
7652 case AArch64::FADDv4f32:
7653 case AArch64::FADDv2f64:
7654 case AArch64::FMULv4f16:
7655 case AArch64::FMULv8f16:
7656 case AArch64::FMULv2f32:
7657 case AArch64::FMULv4f32:
7658 case AArch64::FMULv2f64:
7659 case AArch64::FMULXv4f16:
7660 case AArch64::FMULXv8f16:
7661 case AArch64::FMULXv2f32:
7662 case AArch64::FMULXv4f32:
7663 case AArch64::FMULXv2f64:
7664 // -- SVE instructions --
7665 // Opcodes FMULX_ZZZ_? don't exist because there is no unpredicated FMULX
7666 // in the SVE instruction set (though there are predicated ones).
7667 case AArch64::FADD_ZZZ_H:
7668 case AArch64::FADD_ZZZ_S:
7669 case AArch64::FADD_ZZZ_D:
7670 case AArch64::FMUL_ZZZ_H:
7671 case AArch64::FMUL_ZZZ_S:
7672 case AArch64::FMUL_ZZZ_D:
7675
7676 // == Integer types ==
7677 // -- Base instructions --
7678 // Opcodes MULWrr and MULXrr don't exist because
7679 // `MUL <Wd>, <Wn>, <Wm>` and `MUL <Xd>, <Xn>, <Xm>` are aliases of
7680 // `MADD <Wd>, <Wn>, <Wm>, WZR` and `MADD <Xd>, <Xn>, <Xm>, XZR` respectively.
7681 // The machine-combiner does not support three-source-operands machine
7682 // instruction. So we cannot reassociate MULs.
7683 case AArch64::ADDWrr:
7684 case AArch64::ADDXrr:
7685 case AArch64::ANDWrr:
7686 case AArch64::ANDXrr:
7687 case AArch64::ORRWrr:
7688 case AArch64::ORRXrr:
7689 case AArch64::EORWrr:
7690 case AArch64::EORXrr:
7691 case AArch64::EONWrr:
7692 case AArch64::EONXrr:
7693 // -- Advanced SIMD instructions --
7694 // Opcodes MULv1i64 and MULv2i64 don't exist because there is no 64-bit MUL
7695 // in the Advanced SIMD instruction set.
7696 case AArch64::ADDv8i8:
7697 case AArch64::ADDv16i8:
7698 case AArch64::ADDv4i16:
7699 case AArch64::ADDv8i16:
7700 case AArch64::ADDv2i32:
7701 case AArch64::ADDv4i32:
7702 case AArch64::ADDv1i64:
7703 case AArch64::ADDv2i64:
7704 case AArch64::MULv8i8:
7705 case AArch64::MULv16i8:
7706 case AArch64::MULv4i16:
7707 case AArch64::MULv8i16:
7708 case AArch64::MULv2i32:
7709 case AArch64::MULv4i32:
7710 case AArch64::ANDv8i8:
7711 case AArch64::ANDv16i8:
7712 case AArch64::ORRv8i8:
7713 case AArch64::ORRv16i8:
7714 case AArch64::EORv8i8:
7715 case AArch64::EORv16i8:
7716 // -- SVE instructions --
7717 case AArch64::ADD_ZZZ_B:
7718 case AArch64::ADD_ZZZ_H:
7719 case AArch64::ADD_ZZZ_S:
7720 case AArch64::ADD_ZZZ_D:
7721 case AArch64::MUL_ZZZ_B:
7722 case AArch64::MUL_ZZZ_H:
7723 case AArch64::MUL_ZZZ_S:
7724 case AArch64::MUL_ZZZ_D:
7725 case AArch64::AND_ZZZ:
7726 case AArch64::ORR_ZZZ:
7727 case AArch64::EOR_ZZZ:
7728 return true;
7729
7730 default:
7731 return false;
7732 }
7733}
7734
7735/// Find instructions that can be turned into madd.
7737 SmallVectorImpl<unsigned> &Patterns) {
7738 unsigned Opc = Root.getOpcode();
7739 MachineBasicBlock &MBB = *Root.getParent();
7740 bool Found = false;
7741
7743 return false;
7745 int Cmp_NZCV =
7746 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
7747 // When NZCV is live bail out.
7748 if (Cmp_NZCV == -1)
7749 return false;
7750 unsigned NewOpc = convertToNonFlagSettingOpc(Root);
7751 // When opcode can't change bail out.
7752 // CHECKME: do we miss any cases for opcode conversion?
7753 if (NewOpc == Opc)
7754 return false;
7755 Opc = NewOpc;
7756 }
7757
7758 auto setFound = [&](int Opcode, int Operand, unsigned ZeroReg,
7759 unsigned Pattern) {
7760 if (canCombineWithMUL(MBB, Root.getOperand(Operand), Opcode, ZeroReg)) {
7761 Patterns.push_back(Pattern);
7762 Found = true;
7763 }
7764 };
7765
7766 auto setVFound = [&](int Opcode, int Operand, unsigned Pattern) {
7767 if (canCombine(MBB, Root.getOperand(Operand), Opcode)) {
7768 Patterns.push_back(Pattern);
7769 Found = true;
7770 }
7771 };
7772
7774
7775 switch (Opc) {
7776 default:
7777 break;
7778 case AArch64::ADDWrr:
7779 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
7780 "ADDWrr does not have register operands");
7781 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7782 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7783 break;
7784 case AArch64::ADDXrr:
7785 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7786 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7787 break;
7788 case AArch64::SUBWrr:
7789 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7790 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7791 break;
7792 case AArch64::SUBXrr:
7793 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7794 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7795 break;
7796 case AArch64::ADDWri:
7797 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7798 break;
7799 case AArch64::ADDXri:
7800 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7801 break;
7802 case AArch64::SUBWri:
7803 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7804 break;
7805 case AArch64::SUBXri:
7806 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7807 break;
7808 case AArch64::ADDv8i8:
7809 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7810 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7811 break;
7812 case AArch64::ADDv16i8:
7813 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7814 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7815 break;
7816 case AArch64::ADDv4i16:
7817 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7818 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7819 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7820 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7821 break;
7822 case AArch64::ADDv8i16:
7823 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7824 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7825 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7826 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7827 break;
7828 case AArch64::ADDv2i32:
7829 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7830 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7831 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7832 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7833 break;
7834 case AArch64::ADDv4i32:
7835 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7836 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7837 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7838 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7839 break;
7840 case AArch64::SUBv8i8:
7841 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7842 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7843 break;
7844 case AArch64::SUBv16i8:
7845 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7846 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7847 break;
7848 case AArch64::SUBv4i16:
7849 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7850 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7851 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7852 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7853 break;
7854 case AArch64::SUBv8i16:
7855 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7856 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7857 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7858 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7859 break;
7860 case AArch64::SUBv2i32:
7861 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7862 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7863 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7864 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7865 break;
7866 case AArch64::SUBv4i32:
7867 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7868 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7869 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7870 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7871 break;
7872 }
7873 return Found;
7874}
7875
7876bool AArch64InstrInfo::isAccumulationOpcode(unsigned Opcode) const {
7877 switch (Opcode) {
7878 default:
7879 break;
7880 case AArch64::UABALB_ZZZ_D:
7881 case AArch64::UABALB_ZZZ_H:
7882 case AArch64::UABALB_ZZZ_S:
7883 case AArch64::UABALT_ZZZ_D:
7884 case AArch64::UABALT_ZZZ_H:
7885 case AArch64::UABALT_ZZZ_S:
7886 case AArch64::SABALB_ZZZ_D:
7887 case AArch64::SABALB_ZZZ_S:
7888 case AArch64::SABALB_ZZZ_H:
7889 case AArch64::SABALT_ZZZ_D:
7890 case AArch64::SABALT_ZZZ_S:
7891 case AArch64::SABALT_ZZZ_H:
7892 case AArch64::UABALv16i8_v8i16:
7893 case AArch64::UABALv2i32_v2i64:
7894 case AArch64::UABALv4i16_v4i32:
7895 case AArch64::UABALv4i32_v2i64:
7896 case AArch64::UABALv8i16_v4i32:
7897 case AArch64::UABALv8i8_v8i16:
7898 case AArch64::UABAv16i8:
7899 case AArch64::UABAv2i32:
7900 case AArch64::UABAv4i16:
7901 case AArch64::UABAv4i32:
7902 case AArch64::UABAv8i16:
7903 case AArch64::UABAv8i8:
7904 case AArch64::SABALv16i8_v8i16:
7905 case AArch64::SABALv2i32_v2i64:
7906 case AArch64::SABALv4i16_v4i32:
7907 case AArch64::SABALv4i32_v2i64:
7908 case AArch64::SABALv8i16_v4i32:
7909 case AArch64::SABALv8i8_v8i16:
7910 case AArch64::SABAv16i8:
7911 case AArch64::SABAv2i32:
7912 case AArch64::SABAv4i16:
7913 case AArch64::SABAv4i32:
7914 case AArch64::SABAv8i16:
7915 case AArch64::SABAv8i8:
7916 return true;
7917 }
7918
7919 return false;
7920}
7921
7922unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7923 unsigned AccumulationOpcode) const {
7924 switch (AccumulationOpcode) {
7925 default:
7926 llvm_unreachable("Unsupported accumulation Opcode!");
7927 case AArch64::UABALB_ZZZ_D:
7928 return AArch64::UABDLB_ZZZ_D;
7929 case AArch64::UABALB_ZZZ_H:
7930 return AArch64::UABDLB_ZZZ_H;
7931 case AArch64::UABALB_ZZZ_S:
7932 return AArch64::UABDLB_ZZZ_S;
7933 case AArch64::UABALT_ZZZ_D:
7934 return AArch64::UABDLT_ZZZ_D;
7935 case AArch64::UABALT_ZZZ_H:
7936 return AArch64::UABDLT_ZZZ_H;
7937 case AArch64::UABALT_ZZZ_S:
7938 return AArch64::UABDLT_ZZZ_S;
7939 case AArch64::UABALv16i8_v8i16:
7940 return AArch64::UABDLv16i8_v8i16;
7941 case AArch64::UABALv2i32_v2i64:
7942 return AArch64::UABDLv2i32_v2i64;
7943 case AArch64::UABALv4i16_v4i32:
7944 return AArch64::UABDLv4i16_v4i32;
7945 case AArch64::UABALv4i32_v2i64:
7946 return AArch64::UABDLv4i32_v2i64;
7947 case AArch64::UABALv8i16_v4i32:
7948 return AArch64::UABDLv8i16_v4i32;
7949 case AArch64::UABALv8i8_v8i16:
7950 return AArch64::UABDLv8i8_v8i16;
7951 case AArch64::UABAv16i8:
7952 return AArch64::UABDv16i8;
7953 case AArch64::UABAv2i32:
7954 return AArch64::UABDv2i32;
7955 case AArch64::UABAv4i16:
7956 return AArch64::UABDv4i16;
7957 case AArch64::UABAv4i32:
7958 return AArch64::UABDv4i32;
7959 case AArch64::UABAv8i16:
7960 return AArch64::UABDv8i16;
7961 case AArch64::UABAv8i8:
7962 return AArch64::UABDv8i8;
7963 case AArch64::SABALB_ZZZ_D:
7964 return AArch64::SABDLB_ZZZ_D;
7965 case AArch64::SABALB_ZZZ_S:
7966 return AArch64::SABDLB_ZZZ_S;
7967 case AArch64::SABALB_ZZZ_H:
7968 return AArch64::SABDLB_ZZZ_H;
7969 case AArch64::SABALT_ZZZ_D:
7970 return AArch64::SABDLT_ZZZ_D;
7971 case AArch64::SABALT_ZZZ_S:
7972 return AArch64::SABDLT_ZZZ_S;
7973 case AArch64::SABALT_ZZZ_H:
7974 return AArch64::SABDLT_ZZZ_H;
7975 case AArch64::SABALv16i8_v8i16:
7976 return AArch64::SABDLv16i8_v8i16;
7977 case AArch64::SABALv2i32_v2i64:
7978 return AArch64::SABDLv2i32_v2i64;
7979 case AArch64::SABALv4i16_v4i32:
7980 return AArch64::SABDLv4i16_v4i32;
7981 case AArch64::SABALv4i32_v2i64:
7982 return AArch64::SABDLv4i32_v2i64;
7983 case AArch64::SABALv8i16_v4i32:
7984 return AArch64::SABDLv8i16_v4i32;
7985 case AArch64::SABALv8i8_v8i16:
7986 return AArch64::SABDLv8i8_v8i16;
7987 case AArch64::SABAv16i8:
7988 return AArch64::SABDv16i8;
7989 case AArch64::SABAv2i32:
7990 return AArch64::SABAv2i32;
7991 case AArch64::SABAv4i16:
7992 return AArch64::SABDv4i16;
7993 case AArch64::SABAv4i32:
7994 return AArch64::SABDv4i32;
7995 case AArch64::SABAv8i16:
7996 return AArch64::SABDv8i16;
7997 case AArch64::SABAv8i8:
7998 return AArch64::SABDv8i8;
7999 }
8000}
8001
8002/// Floating-Point Support
8003
8004/// Find instructions that can be turned into madd.
8006 SmallVectorImpl<unsigned> &Patterns) {
8007
8008 if (!isCombineInstrCandidateFP(Root))
8009 return false;
8010
8011 MachineBasicBlock &MBB = *Root.getParent();
8012 bool Found = false;
8013
8014 auto Match = [&](int Opcode, int Operand, unsigned Pattern) -> bool {
8015 if (canCombineWithFMUL(MBB, Root.getOperand(Operand), Opcode)) {
8016 Patterns.push_back(Pattern);
8017 return true;
8018 }
8019 return false;
8020 };
8021
8023
8024 switch (Root.getOpcode()) {
8025 default:
8026 assert(false && "Unsupported FP instruction in combiner\n");
8027 break;
8028 case AArch64::FADDHrr:
8029 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8030 "FADDHrr does not have register operands");
8031
8032 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8033 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8034 break;
8035 case AArch64::FADDSrr:
8036 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8037 "FADDSrr does not have register operands");
8038
8039 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8040 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8041
8042 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8043 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8044 break;
8045 case AArch64::FADDDrr:
8046 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8047 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8048
8049 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8050 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8051 break;
8052 case AArch64::FADDv4f16:
8053 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8054 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8055
8056 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8057 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8058 break;
8059 case AArch64::FADDv8f16:
8060 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8061 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8062
8063 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8064 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8065 break;
8066 case AArch64::FADDv2f32:
8067 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8068 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8069
8070 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8071 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8072 break;
8073 case AArch64::FADDv2f64:
8074 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8075 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8076
8077 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8078 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8079 break;
8080 case AArch64::FADDv4f32:
8081 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8082 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8083
8084 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8085 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8086 break;
8087 case AArch64::FSUBHrr:
8088 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8089 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8090 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8091 break;
8092 case AArch64::FSUBSrr:
8093 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8094
8095 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8096 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8097
8098 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8099 break;
8100 case AArch64::FSUBDrr:
8101 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8102
8103 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8104 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8105
8106 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8107 break;
8108 case AArch64::FSUBv4f16:
8109 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8110 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8111
8112 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8113 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8114 break;
8115 case AArch64::FSUBv8f16:
8116 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8117 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8118
8119 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8120 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8121 break;
8122 case AArch64::FSUBv2f32:
8123 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8124 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8125
8126 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8127 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8128 break;
8129 case AArch64::FSUBv2f64:
8130 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8131 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8132
8133 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8134 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8135 break;
8136 case AArch64::FSUBv4f32:
8137 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8138 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8139
8140 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8141 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8142 break;
8143 }
8144 return Found;
8145}
8146
8148 SmallVectorImpl<unsigned> &Patterns) {
8149 MachineBasicBlock &MBB = *Root.getParent();
8150 bool Found = false;
8151
8152 auto Match = [&](unsigned Opcode, int Operand, unsigned Pattern) -> bool {
8153 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8154 MachineOperand &MO = Root.getOperand(Operand);
8155 MachineInstr *MI = nullptr;
8156 if (MO.isReg() && MO.getReg().isVirtual())
8157 MI = MRI.getUniqueVRegDef(MO.getReg());
8158 // Ignore No-op COPYs in FMUL(COPY(DUP(..)))
8159 if (MI && MI->getOpcode() == TargetOpcode::COPY &&
8160 MI->getOperand(1).getReg().isVirtual())
8161 MI = MRI.getUniqueVRegDef(MI->getOperand(1).getReg());
8162 if (MI && MI->getOpcode() == Opcode) {
8163 Patterns.push_back(Pattern);
8164 return true;
8165 }
8166 return false;
8167 };
8168
8170
8171 switch (Root.getOpcode()) {
8172 default:
8173 return false;
8174 case AArch64::FMULv2f32:
8175 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8176 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8177 break;
8178 case AArch64::FMULv2f64:
8179 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8180 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8181 break;
8182 case AArch64::FMULv4f16:
8183 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8184 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8185 break;
8186 case AArch64::FMULv4f32:
8187 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8188 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8189 break;
8190 case AArch64::FMULv8f16:
8191 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8192 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8193 break;
8194 }
8195
8196 return Found;
8197}
8198
8200 SmallVectorImpl<unsigned> &Patterns) {
8201 unsigned Opc = Root.getOpcode();
8202 MachineBasicBlock &MBB = *Root.getParent();
8203 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8204
8205 auto Match = [&](unsigned Opcode, unsigned Pattern) -> bool {
8206 MachineOperand &MO = Root.getOperand(1);
8208 if (MI != nullptr && (MI->getOpcode() == Opcode) &&
8209 MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()) &&
8213 MI->getFlag(MachineInstr::MIFlag::FmNsz)) {
8214 Patterns.push_back(Pattern);
8215 return true;
8216 }
8217 return false;
8218 };
8219
8220 switch (Opc) {
8221 default:
8222 break;
8223 case AArch64::FNEGDr:
8224 return Match(AArch64::FMADDDrrr, AArch64MachineCombinerPattern::FNMADD);
8225 case AArch64::FNEGSr:
8226 return Match(AArch64::FMADDSrrr, AArch64MachineCombinerPattern::FNMADD);
8227 }
8228
8229 return false;
8230}
8231
8232/// Return true when a code sequence can improve throughput. It
8233/// should be called only for instructions in loops.
8234/// \param Pattern - combiner pattern
8236 switch (Pattern) {
8237 default:
8238 break;
8344 return true;
8345 } // end switch (Pattern)
8346 return false;
8347}
8348
8349/// Find other MI combine patterns.
8351 SmallVectorImpl<unsigned> &Patterns) {
8352 // A - (B + C) ==> (A - B) - C or (A - C) - B
8353 unsigned Opc = Root.getOpcode();
8354 MachineBasicBlock &MBB = *Root.getParent();
8355
8356 switch (Opc) {
8357 case AArch64::SUBWrr:
8358 case AArch64::SUBSWrr:
8359 case AArch64::SUBXrr:
8360 case AArch64::SUBSXrr:
8361 // Found candidate root.
8362 break;
8363 default:
8364 return false;
8365 }
8366
8368 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) ==
8369 -1)
8370 return false;
8371
8372 if (canCombine(MBB, Root.getOperand(2), AArch64::ADDWrr) ||
8373 canCombine(MBB, Root.getOperand(2), AArch64::ADDSWrr) ||
8374 canCombine(MBB, Root.getOperand(2), AArch64::ADDXrr) ||
8375 canCombine(MBB, Root.getOperand(2), AArch64::ADDSXrr)) {
8378 return true;
8379 }
8380
8381 return false;
8382}
8383
8384/// Check if the given instruction forms a gather load pattern that can be
8385/// optimized for better Memory-Level Parallelism (MLP). This function
8386/// identifies chains of NEON lane load instructions that load data from
8387/// different memory addresses into individual lanes of a 128-bit vector
8388/// register, then attempts to split the pattern into parallel loads to break
8389/// the serial dependency between instructions.
8390///
8391/// Pattern Matched:
8392/// Initial scalar load -> SUBREG_TO_REG (lane 0) -> LD1i* (lane 1) ->
8393/// LD1i* (lane 2) -> ... -> LD1i* (lane N-1, Root)
8394///
8395/// Transformed Into:
8396/// Two parallel vector loads using fewer lanes each, followed by ZIP1v2i64
8397/// to combine the results, enabling better memory-level parallelism.
8398///
8399/// Supported Element Types:
8400/// - 32-bit elements (LD1i32, 4 lanes total)
8401/// - 16-bit elements (LD1i16, 8 lanes total)
8402/// - 8-bit elements (LD1i8, 16 lanes total)
8404 SmallVectorImpl<unsigned> &Patterns,
8405 unsigned LoadLaneOpCode, unsigned NumLanes) {
8406 const MachineFunction *MF = Root.getMF();
8407
8408 // Early exit if optimizing for size.
8409 if (MF->getFunction().hasMinSize())
8410 return false;
8411
8412 const MachineRegisterInfo &MRI = MF->getRegInfo();
8414
8415 // The root of the pattern must load into the last lane of the vector.
8416 if (Root.getOperand(2).getImm() != NumLanes - 1)
8417 return false;
8418
8419 // Check that we have load into all lanes except lane 0.
8420 // For each load we also want to check that:
8421 // 1. It has a single non-debug use (since we will be replacing the virtual
8422 // register)
8423 // 2. That the addressing mode only uses a single pointer operand
8424 auto *CurrInstr = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8425 auto Range = llvm::seq<unsigned>(1, NumLanes - 1);
8426 SmallSet<unsigned, 16> RemainingLanes(Range.begin(), Range.end());
8428 while (!RemainingLanes.empty() && CurrInstr &&
8429 CurrInstr->getOpcode() == LoadLaneOpCode &&
8430 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
8431 CurrInstr->getNumOperands() == 4) {
8432 RemainingLanes.erase(CurrInstr->getOperand(2).getImm());
8433 LoadInstrs.push_back(CurrInstr);
8434 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8435 }
8436
8437 // Check that we have found a match for lanes N-1.. 1.
8438 if (!RemainingLanes.empty())
8439 return false;
8440
8441 // Match the SUBREG_TO_REG sequence.
8442 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8443 return false;
8444
8445 // Verify that the subreg to reg loads an integer into the first lane.
8446 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8447 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8448 if (TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8449 return false;
8450
8451 // Verify that it also has a single non debug use.
8452 if (!MRI.hasOneNonDBGUse(Lane0LoadReg))
8453 return false;
8454
8455 LoadInstrs.push_back(MRI.getUniqueVRegDef(Lane0LoadReg));
8456
8457 // If there is any chance of aliasing, do not apply the pattern.
8458 // Walk backward through the MBB starting from Root.
8459 // Exit early if we've encountered all load instructions or hit the search
8460 // limit.
8461 auto MBBItr = Root.getIterator();
8462 unsigned RemainingSteps = GatherOptSearchLimit;
8463 SmallPtrSet<const MachineInstr *, 16> RemainingLoadInstrs;
8464 RemainingLoadInstrs.insert(LoadInstrs.begin(), LoadInstrs.end());
8465 const MachineBasicBlock *MBB = Root.getParent();
8466
8467 for (; MBBItr != MBB->begin() && RemainingSteps > 0 &&
8468 !RemainingLoadInstrs.empty();
8469 --MBBItr, --RemainingSteps) {
8470 const MachineInstr &CurrInstr = *MBBItr;
8471
8472 // Remove this instruction from remaining loads if it's one we're tracking.
8473 RemainingLoadInstrs.erase(&CurrInstr);
8474
8475 // Check for potential aliasing with any of the load instructions to
8476 // optimize.
8477 if (CurrInstr.isLoadFoldBarrier())
8478 return false;
8479 }
8480
8481 // If we hit the search limit without finding all load instructions,
8482 // don't match the pattern.
8483 if (RemainingSteps == 0 && !RemainingLoadInstrs.empty())
8484 return false;
8485
8486 switch (NumLanes) {
8487 case 4:
8489 break;
8490 case 8:
8492 break;
8493 case 16:
8495 break;
8496 default:
8497 llvm_unreachable("Got bad number of lanes for gather pattern.");
8498 }
8499
8500 return true;
8501}
8502
8503/// Search for patterns of LD instructions we can optimize.
8505 SmallVectorImpl<unsigned> &Patterns) {
8506
8507 // The pattern searches for loads into single lanes.
8508 switch (Root.getOpcode()) {
8509 case AArch64::LD1i32:
8510 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 4);
8511 case AArch64::LD1i16:
8512 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 8);
8513 case AArch64::LD1i8:
8514 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 16);
8515 default:
8516 return false;
8517 }
8518}
8519
8520/// Generate optimized instruction sequence for gather load patterns to improve
8521/// Memory-Level Parallelism (MLP). This function transforms a chain of
8522/// sequential NEON lane loads into parallel vector loads that can execute
8523/// concurrently.
8524static void
8528 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8529 unsigned Pattern, unsigned NumLanes) {
8530 MachineFunction &MF = *Root.getParent()->getParent();
8531 MachineRegisterInfo &MRI = MF.getRegInfo();
8533
8534 // Gather the initial load instructions to build the pattern.
8535 SmallVector<MachineInstr *, 16> LoadToLaneInstrs;
8536 MachineInstr *CurrInstr = &Root;
8537 for (unsigned i = 0; i < NumLanes - 1; ++i) {
8538 LoadToLaneInstrs.push_back(CurrInstr);
8539 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8540 }
8541
8542 // Sort the load instructions according to the lane.
8543 llvm::sort(LoadToLaneInstrs,
8544 [](const MachineInstr *A, const MachineInstr *B) {
8545 return A->getOperand(2).getImm() > B->getOperand(2).getImm();
8546 });
8547
8548 MachineInstr *SubregToReg = CurrInstr;
8549 LoadToLaneInstrs.push_back(
8550 MRI.getUniqueVRegDef(SubregToReg->getOperand(1).getReg()));
8551 auto LoadToLaneInstrsAscending = llvm::reverse(LoadToLaneInstrs);
8552
8553 const TargetRegisterClass *FPR128RegClass =
8554 MRI.getRegClass(Root.getOperand(0).getReg());
8555
8556 // Helper lambda to create a LD1 instruction.
8557 auto CreateLD1Instruction = [&](MachineInstr *OriginalInstr,
8558 Register SrcRegister, unsigned Lane,
8559 Register OffsetRegister,
8560 bool OffsetRegisterKillState) {
8561 auto NewRegister = MRI.createVirtualRegister(FPR128RegClass);
8562 MachineInstrBuilder LoadIndexIntoRegister =
8563 BuildMI(MF, MIMetadata(*OriginalInstr), TII->get(Root.getOpcode()),
8564 NewRegister)
8565 .addReg(SrcRegister)
8566 .addImm(Lane)
8567 .addReg(OffsetRegister, getKillRegState(OffsetRegisterKillState))
8568 .setMemRefs(OriginalInstr->memoperands());
8569 InstrIdxForVirtReg.insert(std::make_pair(NewRegister, InsInstrs.size()));
8570 InsInstrs.push_back(LoadIndexIntoRegister);
8571 return NewRegister;
8572 };
8573
8574 // Helper to create load instruction based on the NumLanes in the NEON
8575 // register we are rewriting.
8576 auto CreateLDRInstruction =
8577 [&](unsigned NumLanes, Register DestReg, Register OffsetReg,
8579 unsigned Opcode;
8580 switch (NumLanes) {
8581 case 4:
8582 Opcode = AArch64::LDRSui;
8583 break;
8584 case 8:
8585 Opcode = AArch64::LDRHui;
8586 break;
8587 case 16:
8588 Opcode = AArch64::LDRBui;
8589 break;
8590 default:
8592 "Got unsupported number of lanes in machine-combiner gather pattern");
8593 }
8594 // Immediate offset load
8595 return BuildMI(MF, MIMetadata(Root), TII->get(Opcode), DestReg)
8596 .addReg(OffsetReg)
8597 .addImm(0)
8598 .setMemRefs(MMOs);
8599 };
8600
8601 // Load the remaining lanes into register 0.
8602 auto LanesToLoadToReg0 =
8603 llvm::make_range(LoadToLaneInstrsAscending.begin() + 1,
8604 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8605 Register PrevReg = SubregToReg->getOperand(0).getReg();
8606 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg0)) {
8607 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8608 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8609 OffsetRegOperand.getReg(),
8610 OffsetRegOperand.isKill());
8611 DelInstrs.push_back(LoadInstr);
8612 }
8613 Register LastLoadReg0 = PrevReg;
8614
8615 // First load into register 1. Perform an integer load to zero out the upper
8616 // lanes in a single instruction.
8617 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8618 MachineInstr *OriginalSplitLoad =
8619 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8620 Register DestRegForMiddleIndex = MRI.createVirtualRegister(
8621 MRI.getRegClass(Lane0Load->getOperand(0).getReg()));
8622
8623 const MachineOperand &OriginalSplitToLoadOffsetOperand =
8624 OriginalSplitLoad->getOperand(3);
8625 MachineInstrBuilder MiddleIndexLoadInstr =
8626 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8627 OriginalSplitToLoadOffsetOperand.getReg(),
8628 OriginalSplitLoad->memoperands());
8629
8630 InstrIdxForVirtReg.insert(
8631 std::make_pair(DestRegForMiddleIndex, InsInstrs.size()));
8632 InsInstrs.push_back(MiddleIndexLoadInstr);
8633 DelInstrs.push_back(OriginalSplitLoad);
8634
8635 // Subreg To Reg instruction for register 1.
8636 Register DestRegForSubregToReg = MRI.createVirtualRegister(FPR128RegClass);
8637 unsigned SubregType;
8638 switch (NumLanes) {
8639 case 4:
8640 SubregType = AArch64::ssub;
8641 break;
8642 case 8:
8643 SubregType = AArch64::hsub;
8644 break;
8645 case 16:
8646 SubregType = AArch64::bsub;
8647 break;
8648 default:
8650 "Got invalid NumLanes for machine-combiner gather pattern");
8651 }
8652
8653 auto SubRegToRegInstr =
8654 BuildMI(MF, MIMetadata(Root), TII->get(SubregToReg->getOpcode()),
8655 DestRegForSubregToReg)
8656 .addReg(DestRegForMiddleIndex, getKillRegState(true))
8657 .addImm(SubregType);
8658 InstrIdxForVirtReg.insert(
8659 std::make_pair(DestRegForSubregToReg, InsInstrs.size()));
8660 InsInstrs.push_back(SubRegToRegInstr);
8661
8662 // Load remaining lanes into register 1.
8663 auto LanesToLoadToReg1 =
8664 llvm::make_range(LoadToLaneInstrsAscending.begin() + NumLanes / 2 + 1,
8665 LoadToLaneInstrsAscending.end());
8666 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8667 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg1)) {
8668 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8669 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8670 OffsetRegOperand.getReg(),
8671 OffsetRegOperand.isKill());
8672
8673 // Do not add the last reg to DelInstrs - it will be removed later.
8674 if (Index == NumLanes / 2 - 2) {
8675 break;
8676 }
8677 DelInstrs.push_back(LoadInstr);
8678 }
8679 Register LastLoadReg1 = PrevReg;
8680
8681 // Create the final zip instruction to combine the results.
8682 MachineInstrBuilder ZipInstr =
8683 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::ZIP1v2i64),
8684 Root.getOperand(0).getReg())
8685 .addReg(LastLoadReg0)
8686 .addReg(LastLoadReg1);
8687 InsInstrs.push_back(ZipInstr);
8688}
8689
8703
8704/// Return true when there is potentially a faster code sequence for an
8705/// instruction chain ending in \p Root. All potential patterns are listed in
8706/// the \p Pattern vector. Pattern should be sorted in priority order since the
8707/// pattern evaluator stops checking as soon as it finds a faster sequence.
8708
8709bool AArch64InstrInfo::getMachineCombinerPatterns(
8710 MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
8711 bool DoRegPressureReduce) const {
8712 // Integer patterns
8713 if (getMaddPatterns(Root, Patterns))
8714 return true;
8715 // Floating point patterns
8716 if (getFMULPatterns(Root, Patterns))
8717 return true;
8718 if (getFMAPatterns(Root, Patterns))
8719 return true;
8720 if (getFNEGPatterns(Root, Patterns))
8721 return true;
8722
8723 // Other patterns
8724 if (getMiscPatterns(Root, Patterns))
8725 return true;
8726
8727 // Load patterns
8728 if (getLoadPatterns(Root, Patterns))
8729 return true;
8730
8731 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
8732 DoRegPressureReduce);
8733}
8734
8736/// genFusedMultiply - Generate fused multiply instructions.
8737/// This function supports both integer and floating point instructions.
8738/// A typical example:
8739/// F|MUL I=A,B,0
8740/// F|ADD R,I,C
8741/// ==> F|MADD R,A,B,C
8742/// \param MF Containing MachineFunction
8743/// \param MRI Register information
8744/// \param TII Target information
8745/// \param Root is the F|ADD instruction
8746/// \param [out] InsInstrs is a vector of machine instructions and will
8747/// contain the generated madd instruction
8748/// \param IdxMulOpd is index of operand in Root that is the result of
8749/// the F|MUL. In the example above IdxMulOpd is 1.
8750/// \param MaddOpc the opcode fo the f|madd instruction
8751/// \param RC Register class of operands
8752/// \param kind of fma instruction (addressing mode) to be generated
8753/// \param ReplacedAddend is the result register from the instruction
8754/// replacing the non-combined operand, if any.
8755static MachineInstr *
8757 const TargetInstrInfo *TII, MachineInstr &Root,
8758 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
8759 unsigned MaddOpc, const TargetRegisterClass *RC,
8761 const Register *ReplacedAddend = nullptr) {
8762 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8763
8764 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8765 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8766 Register ResultReg = Root.getOperand(0).getReg();
8767 Register SrcReg0 = MUL->getOperand(1).getReg();
8768 bool Src0IsKill = MUL->getOperand(1).isKill();
8769 Register SrcReg1 = MUL->getOperand(2).getReg();
8770 bool Src1IsKill = MUL->getOperand(2).isKill();
8771
8772 Register SrcReg2;
8773 bool Src2IsKill;
8774 if (ReplacedAddend) {
8775 // If we just generated a new addend, we must be it's only use.
8776 SrcReg2 = *ReplacedAddend;
8777 Src2IsKill = true;
8778 } else {
8779 SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
8780 Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
8781 }
8782
8783 if (ResultReg.isVirtual())
8784 MRI.constrainRegClass(ResultReg, RC);
8785 if (SrcReg0.isVirtual())
8786 MRI.constrainRegClass(SrcReg0, RC);
8787 if (SrcReg1.isVirtual())
8788 MRI.constrainRegClass(SrcReg1, RC);
8789 if (SrcReg2.isVirtual())
8790 MRI.constrainRegClass(SrcReg2, RC);
8791
8793 if (kind == FMAInstKind::Default)
8794 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8795 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8796 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8797 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8798 else if (kind == FMAInstKind::Indexed)
8799 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8800 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8801 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8802 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8803 .addImm(MUL->getOperand(3).getImm());
8804 else if (kind == FMAInstKind::Accumulator)
8805 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8806 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8807 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8808 .addReg(SrcReg1, getKillRegState(Src1IsKill));
8809 else
8810 assert(false && "Invalid FMA instruction kind \n");
8811 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
8812 InsInstrs.push_back(MIB);
8813 return MUL;
8814}
8815
8816static MachineInstr *
8818 const TargetInstrInfo *TII, MachineInstr &Root,
8820 MachineInstr *MAD = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8821
8822 unsigned Opc = 0;
8823 const TargetRegisterClass *RC = MRI.getRegClass(MAD->getOperand(0).getReg());
8824 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8825 Opc = AArch64::FNMADDSrrr;
8826 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8827 Opc = AArch64::FNMADDDrrr;
8828 else
8829 return nullptr;
8830
8831 Register ResultReg = Root.getOperand(0).getReg();
8832 Register SrcReg0 = MAD->getOperand(1).getReg();
8833 Register SrcReg1 = MAD->getOperand(2).getReg();
8834 Register SrcReg2 = MAD->getOperand(3).getReg();
8835 bool Src0IsKill = MAD->getOperand(1).isKill();
8836 bool Src1IsKill = MAD->getOperand(2).isKill();
8837 bool Src2IsKill = MAD->getOperand(3).isKill();
8838 if (ResultReg.isVirtual())
8839 MRI.constrainRegClass(ResultReg, RC);
8840 if (SrcReg0.isVirtual())
8841 MRI.constrainRegClass(SrcReg0, RC);
8842 if (SrcReg1.isVirtual())
8843 MRI.constrainRegClass(SrcReg1, RC);
8844 if (SrcReg2.isVirtual())
8845 MRI.constrainRegClass(SrcReg2, RC);
8846
8848 BuildMI(MF, MIMetadata(Root), TII->get(Opc), ResultReg)
8849 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8850 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8851 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8852 InsInstrs.push_back(MIB);
8853
8854 return MAD;
8855}
8856
8857/// Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
8858static MachineInstr *
8861 unsigned IdxDupOp, unsigned MulOpc,
8862 const TargetRegisterClass *RC, MachineRegisterInfo &MRI) {
8863 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8864 "Invalid index of FMUL operand");
8865
8866 MachineFunction &MF = *Root.getMF();
8868
8869 MachineInstr *Dup =
8870 MF.getRegInfo().getUniqueVRegDef(Root.getOperand(IdxDupOp).getReg());
8871
8872 if (Dup->getOpcode() == TargetOpcode::COPY)
8873 Dup = MRI.getUniqueVRegDef(Dup->getOperand(1).getReg());
8874
8875 Register DupSrcReg = Dup->getOperand(1).getReg();
8876 MRI.clearKillFlags(DupSrcReg);
8877 MRI.constrainRegClass(DupSrcReg, RC);
8878
8879 unsigned DupSrcLane = Dup->getOperand(2).getImm();
8880
8881 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8882 MachineOperand &MulOp = Root.getOperand(IdxMulOp);
8883
8884 Register ResultReg = Root.getOperand(0).getReg();
8885
8887 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MulOpc), ResultReg)
8888 .add(MulOp)
8889 .addReg(DupSrcReg)
8890 .addImm(DupSrcLane);
8891
8892 InsInstrs.push_back(MIB);
8893 return &Root;
8894}
8895
8896/// genFusedMultiplyAcc - Helper to generate fused multiply accumulate
8897/// instructions.
8898///
8899/// \see genFusedMultiply
8903 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8904 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8906}
8907
8908/// genNeg - Helper to generate an intermediate negation of the second operand
8909/// of Root
8911 const TargetInstrInfo *TII, MachineInstr &Root,
8913 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8914 unsigned MnegOpc, const TargetRegisterClass *RC) {
8915 Register NewVR = MRI.createVirtualRegister(RC);
8917 BuildMI(MF, MIMetadata(Root), TII->get(MnegOpc), NewVR)
8918 .add(Root.getOperand(2));
8919 InsInstrs.push_back(MIB);
8920
8921 assert(InstrIdxForVirtReg.empty());
8922 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
8923
8924 return NewVR;
8925}
8926
8927/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8928/// instructions with an additional negation of the accumulator
8932 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8933 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8934 assert(IdxMulOpd == 1);
8935
8936 Register NewVR =
8937 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8938 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8939 FMAInstKind::Accumulator, &NewVR);
8940}
8941
8942/// genFusedMultiplyIdx - Helper to generate fused multiply accumulate
8943/// instructions.
8944///
8945/// \see genFusedMultiply
8949 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8950 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8952}
8953
8954/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8955/// instructions with an additional negation of the accumulator
8959 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8960 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8961 assert(IdxMulOpd == 1);
8962
8963 Register NewVR =
8964 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8965
8966 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8967 FMAInstKind::Indexed, &NewVR);
8968}
8969
8970/// genMaddR - Generate madd instruction and combine mul and add using
8971/// an extra virtual register
8972/// Example - an ADD intermediate needs to be stored in a register:
8973/// MUL I=A,B,0
8974/// ADD R,I,Imm
8975/// ==> ORR V, ZR, Imm
8976/// ==> MADD R,A,B,V
8977/// \param MF Containing MachineFunction
8978/// \param MRI Register information
8979/// \param TII Target information
8980/// \param Root is the ADD instruction
8981/// \param [out] InsInstrs is a vector of machine instructions and will
8982/// contain the generated madd instruction
8983/// \param IdxMulOpd is index of operand in Root that is the result of
8984/// the MUL. In the example above IdxMulOpd is 1.
8985/// \param MaddOpc the opcode fo the madd instruction
8986/// \param VR is a virtual register that holds the value of an ADD operand
8987/// (V in the example above).
8988/// \param RC Register class of operands
8990 const TargetInstrInfo *TII, MachineInstr &Root,
8992 unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR,
8993 const TargetRegisterClass *RC) {
8994 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8995
8996 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8997 Register ResultReg = Root.getOperand(0).getReg();
8998 Register SrcReg0 = MUL->getOperand(1).getReg();
8999 bool Src0IsKill = MUL->getOperand(1).isKill();
9000 Register SrcReg1 = MUL->getOperand(2).getReg();
9001 bool Src1IsKill = MUL->getOperand(2).isKill();
9002
9003 if (ResultReg.isVirtual())
9004 MRI.constrainRegClass(ResultReg, RC);
9005 if (SrcReg0.isVirtual())
9006 MRI.constrainRegClass(SrcReg0, RC);
9007 if (SrcReg1.isVirtual())
9008 MRI.constrainRegClass(SrcReg1, RC);
9010 MRI.constrainRegClass(VR, RC);
9011
9013 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
9014 .addReg(SrcReg0, getKillRegState(Src0IsKill))
9015 .addReg(SrcReg1, getKillRegState(Src1IsKill))
9016 .addReg(VR);
9017 // Insert the MADD
9018 InsInstrs.push_back(MIB);
9019 return MUL;
9020}
9021
9022/// Do the following transformation
9023/// A - (B + C) ==> (A - B) - C
9024/// A - (B + C) ==> (A - C) - B
9026 const TargetInstrInfo *TII, MachineInstr &Root,
9029 unsigned IdxOpd1,
9030 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
9031 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9032 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9033 MachineInstr *AddMI = MRI.getUniqueVRegDef(Root.getOperand(2).getReg());
9034
9035 Register ResultReg = Root.getOperand(0).getReg();
9036 Register RegA = Root.getOperand(1).getReg();
9037 bool RegAIsKill = Root.getOperand(1).isKill();
9038 Register RegB = AddMI->getOperand(IdxOpd1).getReg();
9039 bool RegBIsKill = AddMI->getOperand(IdxOpd1).isKill();
9040 Register RegC = AddMI->getOperand(IdxOtherOpd).getReg();
9041 bool RegCIsKill = AddMI->getOperand(IdxOtherOpd).isKill();
9042 Register NewVR =
9044
9045 unsigned Opcode = Root.getOpcode();
9046 if (Opcode == AArch64::SUBSWrr)
9047 Opcode = AArch64::SUBWrr;
9048 else if (Opcode == AArch64::SUBSXrr)
9049 Opcode = AArch64::SUBXrr;
9050 else
9051 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9052 "Unexpected instruction opcode.");
9053
9054 uint32_t Flags = Root.mergeFlagsWith(*AddMI);
9055 Flags &= ~MachineInstr::NoSWrap;
9056 Flags &= ~MachineInstr::NoUWrap;
9057
9058 MachineInstrBuilder MIB1 =
9059 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), NewVR)
9060 .addReg(RegA, getKillRegState(RegAIsKill))
9061 .addReg(RegB, getKillRegState(RegBIsKill))
9062 .setMIFlags(Flags);
9063 MachineInstrBuilder MIB2 =
9064 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), ResultReg)
9065 .addReg(NewVR, getKillRegState(true))
9066 .addReg(RegC, getKillRegState(RegCIsKill))
9067 .setMIFlags(Flags);
9068
9069 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9070 InsInstrs.push_back(MIB1);
9071 InsInstrs.push_back(MIB2);
9072 DelInstrs.push_back(AddMI);
9073 DelInstrs.push_back(&Root);
9074}
9075
9076unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9077 unsigned int AccumulatorOpCode) const {
9078 switch (AccumulatorOpCode) {
9079 case AArch64::UABALB_ZZZ_D:
9080 case AArch64::SABALB_ZZZ_D:
9081 case AArch64::UABALT_ZZZ_D:
9082 case AArch64::SABALT_ZZZ_D:
9083 return AArch64::ADD_ZZZ_D;
9084 case AArch64::UABALB_ZZZ_H:
9085 case AArch64::SABALB_ZZZ_H:
9086 case AArch64::UABALT_ZZZ_H:
9087 case AArch64::SABALT_ZZZ_H:
9088 return AArch64::ADD_ZZZ_H;
9089 case AArch64::UABALB_ZZZ_S:
9090 case AArch64::SABALB_ZZZ_S:
9091 case AArch64::UABALT_ZZZ_S:
9092 case AArch64::SABALT_ZZZ_S:
9093 return AArch64::ADD_ZZZ_S;
9094 case AArch64::UABALv16i8_v8i16:
9095 case AArch64::SABALv8i8_v8i16:
9096 case AArch64::SABAv8i16:
9097 case AArch64::UABAv8i16:
9098 return AArch64::ADDv8i16;
9099 case AArch64::SABALv2i32_v2i64:
9100 case AArch64::UABALv2i32_v2i64:
9101 case AArch64::SABALv4i32_v2i64:
9102 return AArch64::ADDv2i64;
9103 case AArch64::UABALv4i16_v4i32:
9104 case AArch64::SABALv4i16_v4i32:
9105 case AArch64::SABALv8i16_v4i32:
9106 case AArch64::SABAv4i32:
9107 case AArch64::UABAv4i32:
9108 return AArch64::ADDv4i32;
9109 case AArch64::UABALv4i32_v2i64:
9110 return AArch64::ADDv2i64;
9111 case AArch64::UABALv8i16_v4i32:
9112 return AArch64::ADDv4i32;
9113 case AArch64::UABALv8i8_v8i16:
9114 case AArch64::SABALv16i8_v8i16:
9115 return AArch64::ADDv8i16;
9116 case AArch64::UABAv16i8:
9117 case AArch64::SABAv16i8:
9118 return AArch64::ADDv16i8;
9119 case AArch64::UABAv4i16:
9120 case AArch64::SABAv4i16:
9121 return AArch64::ADDv4i16;
9122 case AArch64::UABAv2i32:
9123 case AArch64::SABAv2i32:
9124 return AArch64::ADDv2i32;
9125 case AArch64::UABAv8i8:
9126 case AArch64::SABAv8i8:
9127 return AArch64::ADDv8i8;
9128 default:
9129 llvm_unreachable("Unknown accumulator opcode");
9130 }
9131}
9132
9133/// When getMachineCombinerPatterns() finds potential patterns,
9134/// this function generates the instructions that could replace the
9135/// original code sequence
9136void AArch64InstrInfo::genAlternativeCodeSequence(
9137 MachineInstr &Root, unsigned Pattern,
9140 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const {
9141 MachineBasicBlock &MBB = *Root.getParent();
9142 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9143 MachineFunction &MF = *MBB.getParent();
9144 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
9145
9146 MachineInstr *MUL = nullptr;
9147 const TargetRegisterClass *RC;
9148 unsigned Opc;
9149 switch (Pattern) {
9150 default:
9151 // Reassociate instructions.
9152 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
9153 DelInstrs, InstrIdxForVirtReg);
9154 return;
9156 // A - (B + C)
9157 // ==> (A - B) - C
9158 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 1,
9159 InstrIdxForVirtReg);
9160 return;
9162 // A - (B + C)
9163 // ==> (A - C) - B
9164 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 2,
9165 InstrIdxForVirtReg);
9166 return;
9169 // MUL I=A,B,0
9170 // ADD R,I,C
9171 // ==> MADD R,A,B,C
9172 // --- Create(MADD);
9174 Opc = AArch64::MADDWrrr;
9175 RC = &AArch64::GPR32RegClass;
9176 } else {
9177 Opc = AArch64::MADDXrrr;
9178 RC = &AArch64::GPR64RegClass;
9179 }
9180 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9181 break;
9184 // MUL I=A,B,0
9185 // ADD R,C,I
9186 // ==> MADD R,A,B,C
9187 // --- Create(MADD);
9189 Opc = AArch64::MADDWrrr;
9190 RC = &AArch64::GPR32RegClass;
9191 } else {
9192 Opc = AArch64::MADDXrrr;
9193 RC = &AArch64::GPR64RegClass;
9194 }
9195 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9196 break;
9201 // MUL I=A,B,0
9202 // ADD/SUB R,I,Imm
9203 // ==> MOV V, Imm/-Imm
9204 // ==> MADD R,A,B,V
9205 // --- Create(MADD);
9206 const TargetRegisterClass *RC;
9207 unsigned BitSize, MovImm;
9210 MovImm = AArch64::MOVi32imm;
9211 RC = &AArch64::GPR32spRegClass;
9212 BitSize = 32;
9213 Opc = AArch64::MADDWrrr;
9214 RC = &AArch64::GPR32RegClass;
9215 } else {
9216 MovImm = AArch64::MOVi64imm;
9217 RC = &AArch64::GPR64spRegClass;
9218 BitSize = 64;
9219 Opc = AArch64::MADDXrrr;
9220 RC = &AArch64::GPR64RegClass;
9221 }
9222 Register NewVR = MRI.createVirtualRegister(RC);
9223 uint64_t Imm = Root.getOperand(2).getImm();
9224
9225 if (Root.getOperand(3).isImm()) {
9226 unsigned Val = Root.getOperand(3).getImm();
9227 Imm = Imm << Val;
9228 }
9229 bool IsSub = Pattern == AArch64MachineCombinerPattern::MULSUBWI_OP1 ||
9231 uint64_t UImm = SignExtend64(IsSub ? -Imm : Imm, BitSize);
9232 // Check that the immediate can be composed via a single instruction.
9234 AArch64_IMM::expandMOVImm(UImm, BitSize, Insn);
9235 if (Insn.size() != 1)
9236 return;
9237 MachineInstrBuilder MIB1 =
9238 BuildMI(MF, MIMetadata(Root), TII->get(MovImm), NewVR)
9239 .addImm(IsSub ? -Imm : Imm);
9240 InsInstrs.push_back(MIB1);
9241 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9242 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9243 break;
9244 }
9247 // MUL I=A,B,0
9248 // SUB R,I, C
9249 // ==> SUB V, 0, C
9250 // ==> MADD R,A,B,V // = -C + A*B
9251 // --- Create(MADD);
9252 const TargetRegisterClass *SubRC;
9253 unsigned SubOpc, ZeroReg;
9255 SubOpc = AArch64::SUBWrr;
9256 SubRC = &AArch64::GPR32spRegClass;
9257 ZeroReg = AArch64::WZR;
9258 Opc = AArch64::MADDWrrr;
9259 RC = &AArch64::GPR32RegClass;
9260 } else {
9261 SubOpc = AArch64::SUBXrr;
9262 SubRC = &AArch64::GPR64spRegClass;
9263 ZeroReg = AArch64::XZR;
9264 Opc = AArch64::MADDXrrr;
9265 RC = &AArch64::GPR64RegClass;
9266 }
9267 Register NewVR = MRI.createVirtualRegister(SubRC);
9268 // SUB NewVR, 0, C
9269 MachineInstrBuilder MIB1 =
9270 BuildMI(MF, MIMetadata(Root), TII->get(SubOpc), NewVR)
9271 .addReg(ZeroReg)
9272 .add(Root.getOperand(2));
9273 InsInstrs.push_back(MIB1);
9274 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9275 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9276 break;
9277 }
9280 // MUL I=A,B,0
9281 // SUB R,C,I
9282 // ==> MSUB R,A,B,C (computes C - A*B)
9283 // --- Create(MSUB);
9285 Opc = AArch64::MSUBWrrr;
9286 RC = &AArch64::GPR32RegClass;
9287 } else {
9288 Opc = AArch64::MSUBXrrr;
9289 RC = &AArch64::GPR64RegClass;
9290 }
9291 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9292 break;
9294 Opc = AArch64::MLAv8i8;
9295 RC = &AArch64::FPR64RegClass;
9296 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9297 break;
9299 Opc = AArch64::MLAv8i8;
9300 RC = &AArch64::FPR64RegClass;
9301 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9302 break;
9304 Opc = AArch64::MLAv16i8;
9305 RC = &AArch64::FPR128RegClass;
9306 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9307 break;
9309 Opc = AArch64::MLAv16i8;
9310 RC = &AArch64::FPR128RegClass;
9311 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9312 break;
9314 Opc = AArch64::MLAv4i16;
9315 RC = &AArch64::FPR64RegClass;
9316 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9317 break;
9319 Opc = AArch64::MLAv4i16;
9320 RC = &AArch64::FPR64RegClass;
9321 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9322 break;
9324 Opc = AArch64::MLAv8i16;
9325 RC = &AArch64::FPR128RegClass;
9326 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9327 break;
9329 Opc = AArch64::MLAv8i16;
9330 RC = &AArch64::FPR128RegClass;
9331 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9332 break;
9334 Opc = AArch64::MLAv2i32;
9335 RC = &AArch64::FPR64RegClass;
9336 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9337 break;
9339 Opc = AArch64::MLAv2i32;
9340 RC = &AArch64::FPR64RegClass;
9341 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9342 break;
9344 Opc = AArch64::MLAv4i32;
9345 RC = &AArch64::FPR128RegClass;
9346 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9347 break;
9349 Opc = AArch64::MLAv4i32;
9350 RC = &AArch64::FPR128RegClass;
9351 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9352 break;
9353
9355 Opc = AArch64::MLAv8i8;
9356 RC = &AArch64::FPR64RegClass;
9357 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9358 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i8,
9359 RC);
9360 break;
9362 Opc = AArch64::MLSv8i8;
9363 RC = &AArch64::FPR64RegClass;
9364 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9365 break;
9367 Opc = AArch64::MLAv16i8;
9368 RC = &AArch64::FPR128RegClass;
9369 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9370 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv16i8,
9371 RC);
9372 break;
9374 Opc = AArch64::MLSv16i8;
9375 RC = &AArch64::FPR128RegClass;
9376 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9377 break;
9379 Opc = AArch64::MLAv4i16;
9380 RC = &AArch64::FPR64RegClass;
9381 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9382 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9383 RC);
9384 break;
9386 Opc = AArch64::MLSv4i16;
9387 RC = &AArch64::FPR64RegClass;
9388 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9389 break;
9391 Opc = AArch64::MLAv8i16;
9392 RC = &AArch64::FPR128RegClass;
9393 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9394 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9395 RC);
9396 break;
9398 Opc = AArch64::MLSv8i16;
9399 RC = &AArch64::FPR128RegClass;
9400 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9401 break;
9403 Opc = AArch64::MLAv2i32;
9404 RC = &AArch64::FPR64RegClass;
9405 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9406 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9407 RC);
9408 break;
9410 Opc = AArch64::MLSv2i32;
9411 RC = &AArch64::FPR64RegClass;
9412 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9413 break;
9415 Opc = AArch64::MLAv4i32;
9416 RC = &AArch64::FPR128RegClass;
9417 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9418 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9419 RC);
9420 break;
9422 Opc = AArch64::MLSv4i32;
9423 RC = &AArch64::FPR128RegClass;
9424 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9425 break;
9426
9428 Opc = AArch64::MLAv4i16_indexed;
9429 RC = &AArch64::FPR64RegClass;
9430 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9431 break;
9433 Opc = AArch64::MLAv4i16_indexed;
9434 RC = &AArch64::FPR64RegClass;
9435 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9436 break;
9438 Opc = AArch64::MLAv8i16_indexed;
9439 RC = &AArch64::FPR128RegClass;
9440 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9441 break;
9443 Opc = AArch64::MLAv8i16_indexed;
9444 RC = &AArch64::FPR128RegClass;
9445 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9446 break;
9448 Opc = AArch64::MLAv2i32_indexed;
9449 RC = &AArch64::FPR64RegClass;
9450 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9451 break;
9453 Opc = AArch64::MLAv2i32_indexed;
9454 RC = &AArch64::FPR64RegClass;
9455 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9456 break;
9458 Opc = AArch64::MLAv4i32_indexed;
9459 RC = &AArch64::FPR128RegClass;
9460 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9461 break;
9463 Opc = AArch64::MLAv4i32_indexed;
9464 RC = &AArch64::FPR128RegClass;
9465 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9466 break;
9467
9469 Opc = AArch64::MLAv4i16_indexed;
9470 RC = &AArch64::FPR64RegClass;
9471 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9472 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9473 RC);
9474 break;
9476 Opc = AArch64::MLSv4i16_indexed;
9477 RC = &AArch64::FPR64RegClass;
9478 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9479 break;
9481 Opc = AArch64::MLAv8i16_indexed;
9482 RC = &AArch64::FPR128RegClass;
9483 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9484 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9485 RC);
9486 break;
9488 Opc = AArch64::MLSv8i16_indexed;
9489 RC = &AArch64::FPR128RegClass;
9490 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9491 break;
9493 Opc = AArch64::MLAv2i32_indexed;
9494 RC = &AArch64::FPR64RegClass;
9495 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9496 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9497 RC);
9498 break;
9500 Opc = AArch64::MLSv2i32_indexed;
9501 RC = &AArch64::FPR64RegClass;
9502 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9503 break;
9505 Opc = AArch64::MLAv4i32_indexed;
9506 RC = &AArch64::FPR128RegClass;
9507 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9508 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9509 RC);
9510 break;
9512 Opc = AArch64::MLSv4i32_indexed;
9513 RC = &AArch64::FPR128RegClass;
9514 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9515 break;
9516
9517 // Floating Point Support
9519 Opc = AArch64::FMADDHrrr;
9520 RC = &AArch64::FPR16RegClass;
9521 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9522 break;
9524 Opc = AArch64::FMADDSrrr;
9525 RC = &AArch64::FPR32RegClass;
9526 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9527 break;
9529 Opc = AArch64::FMADDDrrr;
9530 RC = &AArch64::FPR64RegClass;
9531 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9532 break;
9533
9535 Opc = AArch64::FMADDHrrr;
9536 RC = &AArch64::FPR16RegClass;
9537 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9538 break;
9540 Opc = AArch64::FMADDSrrr;
9541 RC = &AArch64::FPR32RegClass;
9542 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9543 break;
9545 Opc = AArch64::FMADDDrrr;
9546 RC = &AArch64::FPR64RegClass;
9547 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9548 break;
9549
9551 Opc = AArch64::FMLAv1i32_indexed;
9552 RC = &AArch64::FPR32RegClass;
9553 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9555 break;
9557 Opc = AArch64::FMLAv1i32_indexed;
9558 RC = &AArch64::FPR32RegClass;
9559 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9561 break;
9562
9564 Opc = AArch64::FMLAv1i64_indexed;
9565 RC = &AArch64::FPR64RegClass;
9566 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9568 break;
9570 Opc = AArch64::FMLAv1i64_indexed;
9571 RC = &AArch64::FPR64RegClass;
9572 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9574 break;
9575
9577 RC = &AArch64::FPR64RegClass;
9578 Opc = AArch64::FMLAv4i16_indexed;
9579 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9581 break;
9583 RC = &AArch64::FPR64RegClass;
9584 Opc = AArch64::FMLAv4f16;
9585 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9587 break;
9589 RC = &AArch64::FPR64RegClass;
9590 Opc = AArch64::FMLAv4i16_indexed;
9591 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9593 break;
9595 RC = &AArch64::FPR64RegClass;
9596 Opc = AArch64::FMLAv4f16;
9597 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9599 break;
9600
9603 RC = &AArch64::FPR64RegClass;
9605 Opc = AArch64::FMLAv2i32_indexed;
9606 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9608 } else {
9609 Opc = AArch64::FMLAv2f32;
9610 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9612 }
9613 break;
9616 RC = &AArch64::FPR64RegClass;
9618 Opc = AArch64::FMLAv2i32_indexed;
9619 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9621 } else {
9622 Opc = AArch64::FMLAv2f32;
9623 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9625 }
9626 break;
9627
9629 RC = &AArch64::FPR128RegClass;
9630 Opc = AArch64::FMLAv8i16_indexed;
9631 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9633 break;
9635 RC = &AArch64::FPR128RegClass;
9636 Opc = AArch64::FMLAv8f16;
9637 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9639 break;
9641 RC = &AArch64::FPR128RegClass;
9642 Opc = AArch64::FMLAv8i16_indexed;
9643 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9645 break;
9647 RC = &AArch64::FPR128RegClass;
9648 Opc = AArch64::FMLAv8f16;
9649 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9651 break;
9652
9655 RC = &AArch64::FPR128RegClass;
9657 Opc = AArch64::FMLAv2i64_indexed;
9658 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9660 } else {
9661 Opc = AArch64::FMLAv2f64;
9662 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9664 }
9665 break;
9668 RC = &AArch64::FPR128RegClass;
9670 Opc = AArch64::FMLAv2i64_indexed;
9671 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9673 } else {
9674 Opc = AArch64::FMLAv2f64;
9675 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9677 }
9678 break;
9679
9682 RC = &AArch64::FPR128RegClass;
9684 Opc = AArch64::FMLAv4i32_indexed;
9685 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9687 } else {
9688 Opc = AArch64::FMLAv4f32;
9689 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9691 }
9692 break;
9693
9696 RC = &AArch64::FPR128RegClass;
9698 Opc = AArch64::FMLAv4i32_indexed;
9699 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9701 } else {
9702 Opc = AArch64::FMLAv4f32;
9703 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9705 }
9706 break;
9707
9709 Opc = AArch64::FNMSUBHrrr;
9710 RC = &AArch64::FPR16RegClass;
9711 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9712 break;
9714 Opc = AArch64::FNMSUBSrrr;
9715 RC = &AArch64::FPR32RegClass;
9716 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9717 break;
9719 Opc = AArch64::FNMSUBDrrr;
9720 RC = &AArch64::FPR64RegClass;
9721 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9722 break;
9723
9725 Opc = AArch64::FNMADDHrrr;
9726 RC = &AArch64::FPR16RegClass;
9727 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9728 break;
9730 Opc = AArch64::FNMADDSrrr;
9731 RC = &AArch64::FPR32RegClass;
9732 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9733 break;
9735 Opc = AArch64::FNMADDDrrr;
9736 RC = &AArch64::FPR64RegClass;
9737 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9738 break;
9739
9741 Opc = AArch64::FMSUBHrrr;
9742 RC = &AArch64::FPR16RegClass;
9743 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9744 break;
9746 Opc = AArch64::FMSUBSrrr;
9747 RC = &AArch64::FPR32RegClass;
9748 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9749 break;
9751 Opc = AArch64::FMSUBDrrr;
9752 RC = &AArch64::FPR64RegClass;
9753 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9754 break;
9755
9757 Opc = AArch64::FMLSv1i32_indexed;
9758 RC = &AArch64::FPR32RegClass;
9759 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9761 break;
9762
9764 Opc = AArch64::FMLSv1i64_indexed;
9765 RC = &AArch64::FPR64RegClass;
9766 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9768 break;
9769
9772 RC = &AArch64::FPR64RegClass;
9773 Register NewVR = MRI.createVirtualRegister(RC);
9774 MachineInstrBuilder MIB1 =
9775 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f16), NewVR)
9776 .add(Root.getOperand(2));
9777 InsInstrs.push_back(MIB1);
9778 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9780 Opc = AArch64::FMLAv4f16;
9781 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9782 FMAInstKind::Accumulator, &NewVR);
9783 } else {
9784 Opc = AArch64::FMLAv4i16_indexed;
9785 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9786 FMAInstKind::Indexed, &NewVR);
9787 }
9788 break;
9789 }
9791 RC = &AArch64::FPR64RegClass;
9792 Opc = AArch64::FMLSv4f16;
9793 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9795 break;
9797 RC = &AArch64::FPR64RegClass;
9798 Opc = AArch64::FMLSv4i16_indexed;
9799 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9801 break;
9802
9805 RC = &AArch64::FPR64RegClass;
9807 Opc = AArch64::FMLSv2i32_indexed;
9808 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9810 } else {
9811 Opc = AArch64::FMLSv2f32;
9812 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9814 }
9815 break;
9816
9819 RC = &AArch64::FPR128RegClass;
9820 Register NewVR = MRI.createVirtualRegister(RC);
9821 MachineInstrBuilder MIB1 =
9822 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv8f16), NewVR)
9823 .add(Root.getOperand(2));
9824 InsInstrs.push_back(MIB1);
9825 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9827 Opc = AArch64::FMLAv8f16;
9828 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9829 FMAInstKind::Accumulator, &NewVR);
9830 } else {
9831 Opc = AArch64::FMLAv8i16_indexed;
9832 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9833 FMAInstKind::Indexed, &NewVR);
9834 }
9835 break;
9836 }
9838 RC = &AArch64::FPR128RegClass;
9839 Opc = AArch64::FMLSv8f16;
9840 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9842 break;
9844 RC = &AArch64::FPR128RegClass;
9845 Opc = AArch64::FMLSv8i16_indexed;
9846 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9848 break;
9849
9852 RC = &AArch64::FPR128RegClass;
9854 Opc = AArch64::FMLSv2i64_indexed;
9855 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9857 } else {
9858 Opc = AArch64::FMLSv2f64;
9859 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9861 }
9862 break;
9863
9866 RC = &AArch64::FPR128RegClass;
9868 Opc = AArch64::FMLSv4i32_indexed;
9869 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9871 } else {
9872 Opc = AArch64::FMLSv4f32;
9873 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9875 }
9876 break;
9879 RC = &AArch64::FPR64RegClass;
9880 Register NewVR = MRI.createVirtualRegister(RC);
9881 MachineInstrBuilder MIB1 =
9882 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f32), NewVR)
9883 .add(Root.getOperand(2));
9884 InsInstrs.push_back(MIB1);
9885 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9887 Opc = AArch64::FMLAv2i32_indexed;
9888 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9889 FMAInstKind::Indexed, &NewVR);
9890 } else {
9891 Opc = AArch64::FMLAv2f32;
9892 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9893 FMAInstKind::Accumulator, &NewVR);
9894 }
9895 break;
9896 }
9899 RC = &AArch64::FPR128RegClass;
9900 Register NewVR = MRI.createVirtualRegister(RC);
9901 MachineInstrBuilder MIB1 =
9902 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f32), NewVR)
9903 .add(Root.getOperand(2));
9904 InsInstrs.push_back(MIB1);
9905 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9907 Opc = AArch64::FMLAv4i32_indexed;
9908 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9909 FMAInstKind::Indexed, &NewVR);
9910 } else {
9911 Opc = AArch64::FMLAv4f32;
9912 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9913 FMAInstKind::Accumulator, &NewVR);
9914 }
9915 break;
9916 }
9919 RC = &AArch64::FPR128RegClass;
9920 Register NewVR = MRI.createVirtualRegister(RC);
9921 MachineInstrBuilder MIB1 =
9922 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f64), NewVR)
9923 .add(Root.getOperand(2));
9924 InsInstrs.push_back(MIB1);
9925 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9927 Opc = AArch64::FMLAv2i64_indexed;
9928 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9929 FMAInstKind::Indexed, &NewVR);
9930 } else {
9931 Opc = AArch64::FMLAv2f64;
9932 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9933 FMAInstKind::Accumulator, &NewVR);
9934 }
9935 break;
9936 }
9939 unsigned IdxDupOp =
9941 : 2;
9942 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i32_indexed,
9943 &AArch64::FPR128RegClass, MRI);
9944 break;
9945 }
9948 unsigned IdxDupOp =
9950 : 2;
9951 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i64_indexed,
9952 &AArch64::FPR128RegClass, MRI);
9953 break;
9954 }
9957 unsigned IdxDupOp =
9959 : 2;
9960 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i16_indexed,
9961 &AArch64::FPR128_loRegClass, MRI);
9962 break;
9963 }
9966 unsigned IdxDupOp =
9968 : 2;
9969 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i32_indexed,
9970 &AArch64::FPR128RegClass, MRI);
9971 break;
9972 }