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"
46#include "llvm/IR/DebugLoc.h"
47#include "llvm/IR/GlobalValue.h"
48#include "llvm/IR/Module.h"
49#include "llvm/MC/MCAsmInfo.h"
50#include "llvm/MC/MCInst.h"
52#include "llvm/MC/MCInstrDesc.h"
57#include "llvm/Support/LEB128.h"
61#include <cassert>
62#include <cstdint>
63#include <iterator>
64#include <utility>
65
66using namespace llvm;
67
68#define GET_INSTRINFO_CTOR_DTOR
69#include "AArch64GenInstrInfo.inc"
70
71#define DEBUG_TYPE "AArch64InstrInfo"
72
73STATISTIC(NumCopyInstrs, "Number of COPY instructions expanded");
74STATISTIC(NumZCRegMoveInstrsGPR, "Number of zero-cycle GPR register move "
75 "instructions expanded from canonical COPY");
76STATISTIC(NumZCRegMoveInstrsFPR, "Number of zero-cycle FPR register move "
77 "instructions expanded from canonical COPY");
78STATISTIC(NumZCZeroingInstrsGPR, "Number of zero-cycle GPR zeroing "
79 "instructions expanded from canonical COPY");
80// NumZCZeroingInstrsFPR is counted at AArch64AsmPrinter
81
83 CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9),
84 cl::desc("Restrict range of CB instructions (DEBUG)"));
85
87 "aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
88 cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
89
91 "aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
92 cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
93
95 BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
96 cl::desc("Restrict range of Bcc instructions (DEBUG)"));
97
99 BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26),
100 cl::desc("Restrict range of B instructions (DEBUG)"));
101
103 "aarch64-search-limit", cl::Hidden, cl::init(2048),
104 cl::desc("Restrict range of instructions to search for the "
105 "machine-combiner gather pattern optimization"));
106
108 "aarch64-outliner-compact-unwind-frame", cl::Hidden, cl::init(true),
109 cl::desc("Use a frame record for Mach-O non-leaf outlined functions"));
110
112 : AArch64GenInstrInfo(STI, RI, AArch64::ADJCALLSTACKDOWN,
113 AArch64::ADJCALLSTACKUP, AArch64::CATCHRET),
114 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
115
116/// Return the maximum number of bytes of code the specified instruction may be
117/// after LFI rewriting. If the instruction is not rewritten, std::nullopt is
118/// returned (use default sizing).
119///
120/// NOTE: the size estimates here must be kept in sync with the rewrites in
121/// AArch64MCLFIRewriter.cpp. Sizes may be overestimates of the rewritten
122/// instruction sequences.
123static std::optional<unsigned> getLFIInstSizeInBytes(const MachineInstr &MI) {
124 switch (MI.getOpcode()) {
125 case AArch64::SVC:
126 // SVC expands to 4 instructions.
127 return 16;
128 case AArch64::BR:
129 case AArch64::BLR:
130 // Indirect branches/calls expand to 2 instructions (guard + br/blr).
131 return 8;
132 case AArch64::RET:
133 // RET through LR is not rewritten, but RET through another register
134 // expands to 2 instructions (guard + ret).
135 if (MI.getOperand(0).getReg() != AArch64::LR)
136 return 8;
137 return 4;
138 case AArch64::RETAA:
139 case AArch64::RETAB:
140 // Authenticated returns expand to 3 instructions (authenticate + guard +
141 // ret).
142 return 12;
143 case AArch64::BRAA:
144 case AArch64::BRAAZ:
145 case AArch64::BRAB:
146 case AArch64::BRABZ:
147 case AArch64::BLRAA:
148 case AArch64::BLRAAZ:
149 case AArch64::BLRAB:
150 case AArch64::BLRABZ:
151 // Authenticated branches/calls expand to 3 instructions (authenticate +
152 // guard + branch).
153 return 12;
154 case AArch64::AUTIASP:
155 case AArch64::AUTIBSP:
156 case AArch64::AUTIAZ:
157 case AArch64::AUTIBZ:
158 case AArch64::XPACLRI:
159 // Authenticating LR expands to the instruction plus a deferred LR guard.
160 return 8;
161 case AArch64::SYSxt:
162 // VA-based DC/IC ops (op1=3, Cn=7, op2=1) expand to 2 instructions.
163 if (MI.getOperand(0).getImm() == 3 && MI.getOperand(1).getImm() == 7 &&
164 MI.getOperand(3).getImm() == 1)
165 return 8;
166 return std::nullopt;
167 default:
168 break;
169 }
170
171 // Detect instructions that explicitly define SP or LR.
172 bool ModifiesLR = false;
173 bool ModifiesSP = false;
174 for (const MachineOperand &MO : MI.defs()) {
175 if (!MO.isReg())
176 continue;
177 if (MO.getReg() == AArch64::LR)
178 ModifiesLR = true;
179 else if (MO.getReg() == AArch64::SP)
180 ModifiesSP = true;
181 }
182
183 // Memory accesses expand to a base-register guard plus the rewritten access
184 // (8 bytes), with an extra base-register update for pre/post-index forms (12
185 // bytes total). If the access also defines LR, an LR mask is appended (+4
186 // bytes). Depending on additional optimizations that the rewriter performs,
187 // this may be an overestimate.
188 if (MI.mayLoadOrStore()) {
189 unsigned Size = isLFIPrePostMemAccess(MI.getOpcode()) ? 12 : 8;
190 if (ModifiesLR)
191 Size += 4;
192 return Size;
193 }
194
195 // Non memory operations that modify LR or SP expand to 2 instructions.
196 if (ModifiesSP || ModifiesLR)
197 return 8;
198
199 // Default case: instructions that don't cause expansion.
200 // - TP accesses in LFI are a single load/store, so no expansion.
201 // - All remaining instructions are not rewritten.
202 return std::nullopt;
203}
204
205/// GetInstSize - Return the number of bytes of code the specified
206/// instruction may be. This returns the maximum number of bytes.
208 const MachineBasicBlock &MBB = *MI.getParent();
209 const MachineFunction *MF = MBB.getParent();
210 const Function &F = MF->getFunction();
211 const MCAsmInfo &MAI = MF->getTarget().getMCAsmInfo();
212
213 {
214 auto Op = MI.getOpcode();
215 if (Op == AArch64::INLINEASM || Op == AArch64::INLINEASM_BR)
216 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
217 }
218
219 // Meta-instructions emit no code.
220 if (MI.isMetaInstruction())
221 return 0;
222
223 // FIXME: We currently only handle pseudoinstructions that don't get expanded
224 // before the assembly printer.
225 unsigned NumBytes = 0;
226 const MCInstrDesc &Desc = MI.getDesc();
227
228 // LFI rewriter expansions that supersede normal sizing.
229 const auto &STI = MF->getSubtarget<AArch64Subtarget>();
230 if (STI.isLFI())
231 if (auto Size = getLFIInstSizeInBytes(MI))
232 return *Size;
233
234 if (!MI.isBundle() && isTailCallReturnInst(MI)) {
235 NumBytes = Desc.getSize() ? Desc.getSize() : 4;
236
237 const auto *MFI = MF->getInfo<AArch64FunctionInfo>();
238 if (!MFI->shouldSignReturnAddress(*MF))
239 return NumBytes;
240
241 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
242 NumBytes += AArch64PAuth::getCheckerSizeInBytes(Method);
243 return NumBytes;
244 }
245
246 // Size should be preferably set in
247 // llvm/lib/Target/AArch64/AArch64InstrInfo.td (default case).
248 // Specific cases handle instructions of variable sizes
249 switch (Desc.getOpcode()) {
250 default:
251 if (Desc.getSize())
252 return Desc.getSize();
253
254 // Anything not explicitly designated otherwise (i.e. pseudo-instructions
255 // with fixed constant size but not specified in .td file) is a normal
256 // 4-byte insn.
257 NumBytes = 4;
258 break;
259 case TargetOpcode::STACKMAP:
260 // The upper bound for a stackmap intrinsic is the full length of its shadow
261 NumBytes = StackMapOpers(&MI).getNumPatchBytes();
262 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
263 break;
264 case TargetOpcode::PATCHPOINT:
265 // The size of the patchpoint intrinsic is the number of bytes requested
266 NumBytes = PatchPointOpers(&MI).getNumPatchBytes();
267 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
268 break;
269 case TargetOpcode::STATEPOINT:
270 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
271 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
272 // No patch bytes means a normal call inst is emitted
273 if (NumBytes == 0)
274 NumBytes = 4;
275 break;
276 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
277 // If `patchable-function-entry` is set, PATCHABLE_FUNCTION_ENTER
278 // instructions are expanded to the specified number of NOPs. Otherwise,
279 // they are expanded to 36-byte XRay sleds.
280 NumBytes =
281 F.getFnAttributeAsParsedInteger("patchable-function-entry", 9) * 4;
282 break;
283 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
284 case TargetOpcode::PATCHABLE_TAIL_CALL:
285 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
286 // An XRay sled can be 4 bytes of alignment plus a 32-byte block.
287 NumBytes = 36;
288 break;
289 case TargetOpcode::PATCHABLE_EVENT_CALL:
290 // EVENT_CALL XRay sleds are exactly 6 instructions long (no alignment).
291 NumBytes = 24;
292 break;
293
294 case AArch64::SPACE:
295 NumBytes = MI.getOperand(1).getImm();
296 break;
297 case AArch64::MOVaddr:
298 case AArch64::MOVaddrJT:
299 case AArch64::MOVaddrCP:
300 case AArch64::MOVaddrBA:
301 case AArch64::MOVaddrTLS:
302 case AArch64::MOVaddrEXT: {
303 // Use the same logic as the pseudo expansion to count instructions.
306 MI.getOperand(1).getTargetFlags(),
307 Subtarget.isTargetMachO(), Insn);
308 NumBytes = Insn.size() * 4;
309 break;
310 }
311
312 case AArch64::MOVi32imm:
313 case AArch64::MOVi64imm: {
314 // Use the same logic as the pseudo expansion to count instructions.
315 unsigned BitSize = Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
317 AArch64_IMM::expandMOVImm(MI.getOperand(1).getImm(), BitSize, Insn);
318 NumBytes = Insn.size() * 4;
319 break;
320 }
321
322 case TargetOpcode::BUNDLE:
323 NumBytes = getInstBundleSize(MI);
324 break;
325 }
326
327 return NumBytes;
328}
329
332 // Block ends with fall-through condbranch.
333 switch (LastInst->getOpcode()) {
334 default:
335 llvm_unreachable("Unknown branch instruction?");
336 case AArch64::Bcc:
337 Target = LastInst->getOperand(1).getMBB();
338 Cond.push_back(LastInst->getOperand(0));
339 break;
340 case AArch64::CBZW:
341 case AArch64::CBZX:
342 case AArch64::CBNZW:
343 case AArch64::CBNZX:
344 Target = LastInst->getOperand(1).getMBB();
345 Cond.push_back(MachineOperand::CreateImm(-1));
346 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
347 Cond.push_back(LastInst->getOperand(0));
348 break;
349 case AArch64::TBZW:
350 case AArch64::TBZX:
351 case AArch64::TBNZW:
352 case AArch64::TBNZX:
353 Target = LastInst->getOperand(2).getMBB();
354 Cond.push_back(MachineOperand::CreateImm(-1));
355 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
356 Cond.push_back(LastInst->getOperand(0));
357 Cond.push_back(LastInst->getOperand(1));
358 break;
359 case AArch64::CBWPri:
360 case AArch64::CBXPri:
361 case AArch64::CBWPrr:
362 case AArch64::CBXPrr:
363 Target = LastInst->getOperand(3).getMBB();
364 Cond.push_back(MachineOperand::CreateImm(-1));
365 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
366 Cond.push_back(LastInst->getOperand(0));
367 Cond.push_back(LastInst->getOperand(1));
368 Cond.push_back(LastInst->getOperand(2));
369 break;
370 case AArch64::CBBAssertExt:
371 case AArch64::CBHAssertExt:
372 Target = LastInst->getOperand(3).getMBB();
373 Cond.push_back(MachineOperand::CreateImm(-1)); // -1
374 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); // Opc
375 Cond.push_back(LastInst->getOperand(0)); // Cond
376 Cond.push_back(LastInst->getOperand(1)); // Op0
377 Cond.push_back(LastInst->getOperand(2)); // Op1
378 Cond.push_back(LastInst->getOperand(4)); // Ext0
379 Cond.push_back(LastInst->getOperand(5)); // Ext1
380 break;
381 }
382}
383
384static unsigned getBranchDisplacementBits(unsigned Opc) {
385 switch (Opc) {
386 default:
387 llvm_unreachable("unexpected opcode!");
388 case AArch64::B:
389 return BDisplacementBits;
390 case AArch64::TBNZW:
391 case AArch64::TBZW:
392 case AArch64::TBNZX:
393 case AArch64::TBZX:
394 return TBZDisplacementBits;
395 case AArch64::CBNZW:
396 case AArch64::CBZW:
397 case AArch64::CBNZX:
398 case AArch64::CBZX:
399 return CBZDisplacementBits;
400 case AArch64::Bcc:
401 return BCCDisplacementBits;
402 case AArch64::CBWPri:
403 case AArch64::CBXPri:
404 case AArch64::CBBAssertExt:
405 case AArch64::CBHAssertExt:
406 case AArch64::CBWPrr:
407 case AArch64::CBXPrr:
408 return CBDisplacementBits;
409 }
410}
411
413 int64_t BrOffset) const {
414 unsigned Bits = getBranchDisplacementBits(BranchOp);
415 assert(Bits >= 3 && "max branch displacement must be enough to jump"
416 "over conditional branch expansion");
417 return isIntN(Bits, BrOffset / 4);
418}
419
422 switch (MI.getOpcode()) {
423 default:
424 llvm_unreachable("unexpected opcode!");
425 case AArch64::B:
426 return MI.getOperand(0).getMBB();
427 case AArch64::TBZW:
428 case AArch64::TBNZW:
429 case AArch64::TBZX:
430 case AArch64::TBNZX:
431 return MI.getOperand(2).getMBB();
432 case AArch64::CBZW:
433 case AArch64::CBNZW:
434 case AArch64::CBZX:
435 case AArch64::CBNZX:
436 case AArch64::Bcc:
437 return MI.getOperand(1).getMBB();
438 case AArch64::CBWPri:
439 case AArch64::CBXPri:
440 case AArch64::CBBAssertExt:
441 case AArch64::CBHAssertExt:
442 case AArch64::CBWPrr:
443 case AArch64::CBXPrr:
444 return MI.getOperand(3).getMBB();
445 }
446}
447
449 MachineBasicBlock &NewDestBB,
450 MachineBasicBlock &RestoreBB,
451 const DebugLoc &DL,
452 int64_t BrOffset,
453 RegScavenger *RS) const {
454 assert(RS && "RegScavenger required for long branching");
455 assert(MBB.empty() &&
456 "new block should be inserted for expanding unconditional branch");
457 assert(MBB.pred_size() == 1);
458 assert(RestoreBB.empty() &&
459 "restore block should be inserted for restoring clobbered registers");
460
461 auto buildIndirectBranch = [&](Register Reg, MachineBasicBlock &DestBB) {
462 // Offsets outside of the signed 33-bit range are not supported for ADRP +
463 // ADD.
464 if (!isInt<33>(BrOffset))
466 "Branch offsets outside of the signed 33-bit range not supported");
467
468 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADRP), Reg)
469 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGE);
470 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADDXri), Reg)
471 .addReg(Reg)
472 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGEOFF | AArch64II::MO_NC)
473 .addImm(0);
474 BuildMI(MBB, MBB.end(), DL, get(AArch64::BR)).addReg(Reg);
475 };
476
477 RS->enterBasicBlockEnd(MBB);
478 // If X16 is unused, we can rely on the linker to insert a range extension
479 // thunk if NewDestBB is out of range of a single B instruction.
480 constexpr Register Reg = AArch64::X16;
481 if (!RS->isRegUsed(Reg)) {
482 insertUnconditionalBranch(MBB, &NewDestBB, DL);
483 RS->setRegUsed(Reg);
484 return;
485 }
486
487 // In a cold block without BTI, insert the indirect branch if a register is
488 // free. Skip this if BTI is enabled to avoid inserting a BTI at the target,
489 // prioritizing a dynamic cost in cold code over a static cost in hot code.
490 AArch64FunctionInfo *AFI = MBB.getParent()->getInfo<AArch64FunctionInfo>();
491 bool HasBTI = AFI && AFI->branchTargetEnforcement();
492 if (MBB.getSectionID() == MBBSectionID::ColdSectionID && !HasBTI) {
493 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
494 if (Scavenged != AArch64::NoRegister) {
495 buildIndirectBranch(Scavenged, NewDestBB);
496 RS->setRegUsed(Scavenged);
497 return;
498 }
499 }
500
501 // Note: Spilling X16 briefly moves the stack pointer, making it incompatible
502 // with red zones.
503 if (!AFI || AFI->hasRedZone().value_or(true))
505 "Unable to insert indirect branch inside function that has red zone");
506
507 // Otherwise, spill X16 and defer range extension to the linker.
508 BuildMI(MBB, MBB.end(), DL, get(AArch64::STRXpre))
509 .addReg(AArch64::SP, RegState::Define)
510 .addReg(Reg)
511 .addReg(AArch64::SP)
512 .addImm(-16);
513
514 BuildMI(MBB, MBB.end(), DL, get(AArch64::B)).addMBB(&RestoreBB);
515
516 BuildMI(RestoreBB, RestoreBB.end(), DL, get(AArch64::LDRXpost))
517 .addReg(AArch64::SP, RegState::Define)
519 .addReg(AArch64::SP)
520 .addImm(16);
521}
522
523// Branch analysis.
526 MachineBasicBlock *&FBB,
528 bool AllowModify) const {
529 // If the block has no terminators, it just falls into the block after it.
530 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
531 if (I == MBB.end())
532 return false;
533
534 // Skip over SpeculationBarrierEndBB terminators
535 if (I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
536 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
537 --I;
538 }
539
540 if (!isUnpredicatedTerminator(*I))
541 return false;
542
543 // Get the last instruction in the block.
544 MachineInstr *LastInst = &*I;
545
546 // If there is only one terminator instruction, process it.
547 unsigned LastOpc = LastInst->getOpcode();
548 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
549 if (isUncondBranchOpcode(LastOpc)) {
550 TBB = LastInst->getOperand(0).getMBB();
551 return false;
552 }
553 if (isCondBranchOpcode(LastOpc)) {
554 // Block ends with fall-through condbranch.
555 parseCondBranch(LastInst, TBB, Cond);
556 return false;
557 }
558 return true; // Can't handle indirect branch.
559 }
560
561 // Get the instruction before it if it is a terminator.
562 MachineInstr *SecondLastInst = &*I;
563 unsigned SecondLastOpc = SecondLastInst->getOpcode();
564
565 // If AllowModify is true and the block ends with two or more unconditional
566 // branches, delete all but the first unconditional branch.
567 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
568 while (isUncondBranchOpcode(SecondLastOpc)) {
569 LastInst->eraseFromParent();
570 LastInst = SecondLastInst;
571 LastOpc = LastInst->getOpcode();
572 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
573 // Return now the only terminator is an unconditional branch.
574 TBB = LastInst->getOperand(0).getMBB();
575 return false;
576 }
577 SecondLastInst = &*I;
578 SecondLastOpc = SecondLastInst->getOpcode();
579 }
580 }
581
582 // If we're allowed to modify and the block ends in a unconditional branch
583 // which could simply fallthrough, remove the branch. (Note: This case only
584 // matters when we can't understand the whole sequence, otherwise it's also
585 // handled by BranchFolding.cpp.)
586 if (AllowModify && isUncondBranchOpcode(LastOpc) &&
587 MBB.isLayoutSuccessor(getBranchDestBlock(*LastInst))) {
588 LastInst->eraseFromParent();
589 LastInst = SecondLastInst;
590 LastOpc = LastInst->getOpcode();
591 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
592 assert(!isUncondBranchOpcode(LastOpc) &&
593 "unreachable unconditional branches removed above");
594
595 if (isCondBranchOpcode(LastOpc)) {
596 // Block ends with fall-through condbranch.
597 parseCondBranch(LastInst, TBB, Cond);
598 return false;
599 }
600 return true; // Can't handle indirect branch.
601 }
602 SecondLastInst = &*I;
603 SecondLastOpc = SecondLastInst->getOpcode();
604 }
605
606 // If there are three terminators, we don't know what sort of block this is.
607 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
608 return true;
609
610 // If the block ends with a B and a Bcc, handle it.
611 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
612 parseCondBranch(SecondLastInst, TBB, Cond);
613 FBB = LastInst->getOperand(0).getMBB();
614 return false;
615 }
616
617 // If the block ends with two unconditional branches, handle it. The second
618 // one is not executed, so remove it.
619 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
620 TBB = SecondLastInst->getOperand(0).getMBB();
621 I = LastInst;
622 if (AllowModify)
623 I->eraseFromParent();
624 return false;
625 }
626
627 // ...likewise if it ends with an indirect branch followed by an unconditional
628 // branch.
629 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
630 I = LastInst;
631 if (AllowModify)
632 I->eraseFromParent();
633 return true;
634 }
635
636 // Otherwise, can't handle this.
637 return true;
638}
639
641 MachineBranchPredicate &MBP,
642 bool AllowModify) const {
643 // Use analyzeBranch to validate the branch pattern.
644 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
646 if (analyzeBranch(MBB, TBB, FBB, Cond, AllowModify))
647 return true;
648
649 // analyzeBranch returns success with empty Cond for unconditional branches.
650 if (Cond.empty())
651 return true;
652
653 MBP.TrueDest = TBB;
654 assert(MBP.TrueDest && "expected!");
655 MBP.FalseDest = FBB ? FBB : MBB.getNextNode();
656
657 MBP.ConditionDef = nullptr;
658 MBP.SingleUseCondition = false;
659
660 // Find the conditional branch. After analyzeBranch succeeds with non-empty
661 // Cond, there's exactly one conditional branch - either last (fallthrough)
662 // or second-to-last (followed by unconditional B).
663 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
664 if (I == MBB.end())
665 return true;
666
667 if (isUncondBranchOpcode(I->getOpcode())) {
668 if (I == MBB.begin())
669 return true;
670 --I;
671 }
672
673 MachineInstr *CondBranch = &*I;
674 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
675
676 switch (CondBranch->getOpcode()) {
677 default:
678 return true;
679
680 case AArch64::Bcc:
681 // Bcc takes the NZCV flag as the operand to branch on, walk up the
682 // instruction stream to find the last instruction to define NZCV.
684 if (MI.modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
685 MBP.ConditionDef = &MI;
686 break;
687 }
688 }
689 return false;
690
691 case AArch64::CBZW:
692 case AArch64::CBZX:
693 case AArch64::CBNZW:
694 case AArch64::CBNZX: {
695 MBP.LHS = CondBranch->getOperand(0);
696 MBP.RHS = MachineOperand::CreateImm(0);
697 unsigned Opc = CondBranch->getOpcode();
698 MBP.Predicate = (Opc == AArch64::CBNZX || Opc == AArch64::CBNZW)
699 ? MachineBranchPredicate::PRED_NE
700 : MachineBranchPredicate::PRED_EQ;
701 Register CondReg = MBP.LHS.getReg();
702 if (CondReg.isVirtual())
703 MBP.ConditionDef = MRI.getVRegDef(CondReg);
704 return false;
705 }
706
707 case AArch64::TBZW:
708 case AArch64::TBZX:
709 case AArch64::TBNZW:
710 case AArch64::TBNZX: {
711 Register CondReg = CondBranch->getOperand(0).getReg();
712 if (CondReg.isVirtual())
713 MBP.ConditionDef = MRI.getVRegDef(CondReg);
714 return false;
715 }
716 }
717}
718
721 if (Cond[0].getImm() != -1) {
722 // Regular Bcc
723 AArch64CC::CondCode CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
725 } else {
726 // Folded compare-and-branch
727 switch (Cond[1].getImm()) {
728 default:
729 llvm_unreachable("Unknown conditional branch!");
730 case AArch64::CBZW:
731 Cond[1].setImm(AArch64::CBNZW);
732 break;
733 case AArch64::CBNZW:
734 Cond[1].setImm(AArch64::CBZW);
735 break;
736 case AArch64::CBZX:
737 Cond[1].setImm(AArch64::CBNZX);
738 break;
739 case AArch64::CBNZX:
740 Cond[1].setImm(AArch64::CBZX);
741 break;
742 case AArch64::TBZW:
743 Cond[1].setImm(AArch64::TBNZW);
744 break;
745 case AArch64::TBNZW:
746 Cond[1].setImm(AArch64::TBZW);
747 break;
748 case AArch64::TBZX:
749 Cond[1].setImm(AArch64::TBNZX);
750 break;
751 case AArch64::TBNZX:
752 Cond[1].setImm(AArch64::TBZX);
753 break;
754
755 // Cond is { -1, Opcode, CC, Op0, Op1, ... }
756 case AArch64::CBWPri:
757 case AArch64::CBXPri:
758 case AArch64::CBBAssertExt:
759 case AArch64::CBHAssertExt:
760 case AArch64::CBWPrr:
761 case AArch64::CBXPrr: {
762 // Pseudos using standard 4bit Arm condition codes
764 static_cast<AArch64CC::CondCode>(Cond[2].getImm());
766 }
767 }
768 }
769
770 return false;
771}
772
774 int *BytesRemoved) const {
775 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
776 if (I == MBB.end())
777 return 0;
778
779 if (!isUncondBranchOpcode(I->getOpcode()) &&
780 !isCondBranchOpcode(I->getOpcode()))
781 return 0;
782
783 // Remove the branch.
784 I->eraseFromParent();
785
786 I = MBB.end();
787
788 if (I == MBB.begin()) {
789 if (BytesRemoved)
790 *BytesRemoved = 4;
791 return 1;
792 }
793 --I;
794 if (!isCondBranchOpcode(I->getOpcode())) {
795 if (BytesRemoved)
796 *BytesRemoved = 4;
797 return 1;
798 }
799
800 // Remove the branch.
801 I->eraseFromParent();
802 if (BytesRemoved)
803 *BytesRemoved = 8;
804
805 return 2;
806}
807
808void AArch64InstrInfo::instantiateCondBranch(
811 if (Cond[0].getImm() != -1) {
812 // Regular Bcc
813 BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
814 } else {
815 // Folded compare-and-branch
816 // Note that we use addOperand instead of addReg to keep the flags.
817
818 // cbz, cbnz
819 const MachineInstrBuilder MIB =
820 BuildMI(&MBB, DL, get(Cond[1].getImm())).add(Cond[2]);
821
822 // tbz/tbnz
823 if (Cond.size() > 3)
824 MIB.add(Cond[3]);
825
826 // cb
827 if (Cond.size() > 4)
828 MIB.add(Cond[4]);
829
830 MIB.addMBB(TBB);
831
832 // cb[b,h]
833 if (Cond.size() > 5) {
834 MIB.addImm(Cond[5].getImm());
835 MIB.addImm(Cond[6].getImm());
836 }
837 }
838}
839
842 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
843 // Shouldn't be a fall through.
844 assert(TBB && "insertBranch must not be told to insert a fallthrough");
845
846 if (!FBB) {
847 if (Cond.empty()) // Unconditional branch?
848 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
849 else
850 instantiateCondBranch(MBB, DL, TBB, Cond);
851
852 if (BytesAdded)
853 *BytesAdded = 4;
854
855 return 1;
856 }
857
858 // Two-way conditional branch.
859 instantiateCondBranch(MBB, DL, TBB, Cond);
860 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
861
862 if (BytesAdded)
863 *BytesAdded = 8;
864
865 return 2;
866}
867
869 const TargetInstrInfo &TII) {
870 for (MachineInstr &MI : MBB->terminators()) {
871 unsigned Opc = MI.getOpcode();
872 switch (Opc) {
873 case AArch64::CBZW:
874 case AArch64::CBZX:
875 case AArch64::TBZW:
876 case AArch64::TBZX:
877 // CBZ/TBZ with WZR/XZR -> unconditional B
878 if (MI.getOperand(0).getReg() == AArch64::WZR ||
879 MI.getOperand(0).getReg() == AArch64::XZR) {
880 DEBUG_WITH_TYPE("optimizeTerminators",
881 dbgs() << "Removing always taken branch: " << MI);
882 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
883 SmallVector<MachineBasicBlock *> Succs(MBB->successors());
884 for (auto *S : Succs)
885 if (S != Target)
886 MBB->removeSuccessor(S);
887 DebugLoc DL = MI.getDebugLoc();
888 while (MBB->rbegin() != &MI)
889 MBB->rbegin()->eraseFromParent();
890 MI.eraseFromParent();
891 BuildMI(MBB, DL, TII.get(AArch64::B)).addMBB(Target);
892 return true;
893 }
894 break;
895 case AArch64::CBNZW:
896 case AArch64::CBNZX:
897 case AArch64::TBNZW:
898 case AArch64::TBNZX:
899 // CBNZ/TBNZ with WZR/XZR -> never taken, remove branch and successor
900 if (MI.getOperand(0).getReg() == AArch64::WZR ||
901 MI.getOperand(0).getReg() == AArch64::XZR) {
902 DEBUG_WITH_TYPE("optimizeTerminators",
903 dbgs() << "Removing never taken branch: " << MI);
904 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
905 MI.getParent()->removeSuccessor(Target);
906 MI.eraseFromParent();
907 return true;
908 }
909 break;
910 }
911 }
912 return false;
913}
914
915// Find the original register that VReg is copied from.
916static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
917 while (Register::isVirtualRegister(VReg)) {
918 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
919 if (!DefMI->isFullCopy())
920 return VReg;
921 VReg = DefMI->getOperand(1).getReg();
922 }
923 return VReg;
924}
925
926// Determine if VReg is defined by an instruction that can be folded into a
927// csel instruction. If so, return the folded opcode, and the replacement
928// register.
929static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
930 unsigned *NewReg = nullptr) {
931 VReg = removeCopies(MRI, VReg);
933 return 0;
934
935 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
936 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
937 unsigned Opc = 0;
938 unsigned SrcReg = 0;
939 switch (DefMI->getOpcode()) {
940 case AArch64::SUBREG_TO_REG:
941 // Check for the following way to define an 64-bit immediate:
942 // %0:gpr32 = MOVi32imm 1
943 // %1:gpr64 = SUBREG_TO_REG %0:gpr32, %subreg.sub_32
944 if (!DefMI->getOperand(1).isReg())
945 return 0;
946 if (!DefMI->getOperand(2).isImm() ||
947 DefMI->getOperand(2).getImm() != AArch64::sub_32)
948 return 0;
949 DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg());
950 if (DefMI->getOpcode() != AArch64::MOVi32imm)
951 return 0;
952 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
953 return 0;
954 assert(Is64Bit);
955 SrcReg = AArch64::XZR;
956 Opc = AArch64::CSINCXr;
957 break;
958
959 case AArch64::MOVi32imm:
960 case AArch64::MOVi64imm:
961 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
962 return 0;
963 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
964 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
965 break;
966
967 case AArch64::ADDSXri:
968 case AArch64::ADDSWri:
969 // if NZCV is used, do not fold.
970 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
971 true) == -1)
972 return 0;
973 // fall-through to ADDXri and ADDWri.
974 [[fallthrough]];
975 case AArch64::ADDXri:
976 case AArch64::ADDWri:
977 // add x, 1 -> csinc.
978 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
979 DefMI->getOperand(3).getImm() != 0)
980 return 0;
981 SrcReg = DefMI->getOperand(1).getReg();
982 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
983 break;
984
985 case AArch64::ORNXrr:
986 case AArch64::ORNWrr: {
987 // not x -> csinv, represented as orn dst, xzr, src.
988 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
989 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
990 return 0;
991 SrcReg = DefMI->getOperand(2).getReg();
992 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
993 break;
994 }
995
996 case AArch64::SUBSXrr:
997 case AArch64::SUBSWrr:
998 // if NZCV is used, do not fold.
999 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1000 true) == -1)
1001 return 0;
1002 // fall-through to SUBXrr and SUBWrr.
1003 [[fallthrough]];
1004 case AArch64::SUBXrr:
1005 case AArch64::SUBWrr: {
1006 // neg x -> csneg, represented as sub dst, xzr, src.
1007 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1008 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1009 return 0;
1010 SrcReg = DefMI->getOperand(2).getReg();
1011 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1012 break;
1013 }
1014 default:
1015 return 0;
1016 }
1017 assert(Opc && SrcReg && "Missing parameters");
1018
1019 if (NewReg)
1020 *NewReg = SrcReg;
1021 return Opc;
1022}
1023
1026 Register DstReg, Register TrueReg,
1027 Register FalseReg, int &CondCycles,
1028 int &TrueCycles,
1029 int &FalseCycles) const {
1030 // Check register classes.
1031 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1032 const TargetRegisterClass *RC =
1033 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
1034 if (!RC)
1035 return false;
1036
1037 // Also need to check the dest regclass, in case we're trying to optimize
1038 // something like:
1039 // %1(gpr) = PHI %2(fpr), bb1, %(fpr), bb2
1040 if (!RI.getCommonSubClass(RC, MRI.getRegClass(DstReg)))
1041 return false;
1042
1043 // Expanding cbz/tbz requires an extra cycle of latency on the condition.
1044 unsigned ExtraCondLat = Cond.size() != 1;
1045
1046 // GPRs are handled by csel.
1047 // FIXME: Fold in x+1, -x, and ~x when applicable.
1048 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1049 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1050 // Single-cycle csel, csinc, csinv, and csneg.
1051 CondCycles = 1 + ExtraCondLat;
1052 TrueCycles = FalseCycles = 1;
1053 if (canFoldIntoCSel(MRI, TrueReg))
1054 TrueCycles = 0;
1055 else if (canFoldIntoCSel(MRI, FalseReg))
1056 FalseCycles = 0;
1057 return true;
1058 }
1059
1060 // Scalar floating point is handled by fcsel.
1061 // FIXME: Form fabs, fmin, and fmax when applicable.
1062 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1063 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1064 CondCycles = 5 + ExtraCondLat;
1065 TrueCycles = FalseCycles = 2;
1066 return true;
1067 }
1068
1069 // Can't do vectors.
1070 return false;
1071}
1072
1075 const DebugLoc &DL, Register DstReg,
1077 Register TrueReg, Register FalseReg) const {
1078 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1079
1080 // Parse the condition code, see parseCondBranch() above.
1082 switch (Cond.size()) {
1083 default:
1084 llvm_unreachable("Unknown condition opcode in Cond");
1085 case 1: // b.cc
1086 CC = AArch64CC::CondCode(Cond[0].getImm());
1087 break;
1088 case 3: { // cbz/cbnz
1089 // We must insert a compare against 0.
1090 bool Is64Bit;
1091 switch (Cond[1].getImm()) {
1092 default:
1093 llvm_unreachable("Unknown branch opcode in Cond");
1094 case AArch64::CBZW:
1095 Is64Bit = false;
1096 CC = AArch64CC::EQ;
1097 break;
1098 case AArch64::CBZX:
1099 Is64Bit = true;
1100 CC = AArch64CC::EQ;
1101 break;
1102 case AArch64::CBNZW:
1103 Is64Bit = false;
1104 CC = AArch64CC::NE;
1105 break;
1106 case AArch64::CBNZX:
1107 Is64Bit = true;
1108 CC = AArch64CC::NE;
1109 break;
1110 }
1111 Register SrcReg = Cond[2].getReg();
1112 if (Is64Bit) {
1113 // cmp reg, #0 is actually subs xzr, reg, #0.
1114 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
1115 BuildMI(MBB, I, DL, get(AArch64::SUBSXri), AArch64::XZR)
1116 .addReg(SrcReg)
1117 .addImm(0)
1118 .addImm(0);
1119 } else {
1120 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
1121 BuildMI(MBB, I, DL, get(AArch64::SUBSWri), AArch64::WZR)
1122 .addReg(SrcReg)
1123 .addImm(0)
1124 .addImm(0);
1125 }
1126 break;
1127 }
1128 case 4: { // tbz/tbnz
1129 // We must insert a tst instruction.
1130 switch (Cond[1].getImm()) {
1131 default:
1132 llvm_unreachable("Unknown branch opcode in Cond");
1133 case AArch64::TBZW:
1134 case AArch64::TBZX:
1135 CC = AArch64CC::EQ;
1136 break;
1137 case AArch64::TBNZW:
1138 case AArch64::TBNZX:
1139 CC = AArch64CC::NE;
1140 break;
1141 }
1142 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
1143 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
1144 BuildMI(MBB, I, DL, get(AArch64::ANDSWri), AArch64::WZR)
1145 .addReg(Cond[2].getReg())
1146 .addImm(
1148 else
1149 BuildMI(MBB, I, DL, get(AArch64::ANDSXri), AArch64::XZR)
1150 .addReg(Cond[2].getReg())
1151 .addImm(
1153 break;
1154 }
1155 case 5: { // cb
1156 // We must insert a cmp, that is a subs
1157 // 0 1 2 3 4
1158 // Cond is { -1, Opcode, CC, Op0, Op1 }
1159
1160 unsigned SubsOpc, SubsDestReg;
1161 bool IsImm = false;
1162 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1163 switch (Cond[1].getImm()) {
1164 default:
1165 llvm_unreachable("Unknown branch opcode in Cond");
1166 case AArch64::CBWPri:
1167 SubsOpc = AArch64::SUBSWri;
1168 SubsDestReg = AArch64::WZR;
1169 IsImm = true;
1170 break;
1171 case AArch64::CBXPri:
1172 SubsOpc = AArch64::SUBSXri;
1173 SubsDestReg = AArch64::XZR;
1174 IsImm = true;
1175 break;
1176 case AArch64::CBWPrr:
1177 SubsOpc = AArch64::SUBSWrr;
1178 SubsDestReg = AArch64::WZR;
1179 IsImm = false;
1180 break;
1181 case AArch64::CBXPrr:
1182 SubsOpc = AArch64::SUBSXrr;
1183 SubsDestReg = AArch64::XZR;
1184 IsImm = false;
1185 break;
1186 }
1187
1188 if (IsImm)
1189 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1190 .addReg(Cond[3].getReg())
1191 .addImm(Cond[4].getImm())
1192 .addImm(0);
1193 else
1194 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1195 .addReg(Cond[3].getReg())
1196 .addReg(Cond[4].getReg());
1197 } break;
1198 case 7: { // cb[b,h]
1199 // We must insert a cmp, that is a subs, but also zero- or sign-extensions
1200 // that have been folded. For the first operand we codegen an explicit
1201 // extension, for the second operand we fold the extension into cmp.
1202 // 0 1 2 3 4 5 6
1203 // Cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
1204
1205 // We need a new register for the now explicitly extended register
1206 Register Reg = Cond[4].getReg();
1208 unsigned ExtOpc;
1209 unsigned ExtBits;
1210 AArch64_AM::ShiftExtendType ExtendType =
1212 switch (ExtendType) {
1213 default:
1214 llvm_unreachable("Unknown shift-extend for CB instruction");
1215 case AArch64_AM::SXTB:
1216 assert(
1217 Cond[1].getImm() == AArch64::CBBAssertExt &&
1218 "Unexpected compare-and-branch instruction for SXTB shift-extend");
1219 ExtOpc = AArch64::SBFMWri;
1220 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1221 break;
1222 case AArch64_AM::SXTH:
1223 assert(
1224 Cond[1].getImm() == AArch64::CBHAssertExt &&
1225 "Unexpected compare-and-branch instruction for SXTH shift-extend");
1226 ExtOpc = AArch64::SBFMWri;
1227 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1228 break;
1229 case AArch64_AM::UXTB:
1230 assert(
1231 Cond[1].getImm() == AArch64::CBBAssertExt &&
1232 "Unexpected compare-and-branch instruction for UXTB shift-extend");
1233 ExtOpc = AArch64::ANDWri;
1234 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1235 break;
1236 case AArch64_AM::UXTH:
1237 assert(
1238 Cond[1].getImm() == AArch64::CBHAssertExt &&
1239 "Unexpected compare-and-branch instruction for UXTH shift-extend");
1240 ExtOpc = AArch64::ANDWri;
1241 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1242 break;
1243 }
1244
1245 // Build the explicit extension of the first operand
1246 Reg = MRI.createVirtualRegister(&AArch64::GPR32spRegClass);
1248 BuildMI(MBB, I, DL, get(ExtOpc), Reg).addReg(Cond[4].getReg());
1249 if (ExtOpc != AArch64::ANDWri)
1250 MBBI.addImm(0);
1251 MBBI.addImm(ExtBits);
1252 }
1253
1254 // Now, subs with an extended second operand
1256 AArch64_AM::ShiftExtendType ExtendType =
1258 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1259 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1260 BuildMI(MBB, I, DL, get(AArch64::SUBSWrx), AArch64::WZR)
1261 .addReg(Cond[3].getReg())
1262 .addReg(Reg)
1263 .addImm(AArch64_AM::getArithExtendImm(ExtendType, 0));
1264 } // If no extension is needed, just a regular subs
1265 else {
1266 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1267 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1268 BuildMI(MBB, I, DL, get(AArch64::SUBSWrr), AArch64::WZR)
1269 .addReg(Cond[3].getReg())
1270 .addReg(Reg);
1271 }
1272
1273 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1274 } break;
1275 }
1276
1277 unsigned Opc = 0;
1278 const TargetRegisterClass *RC = nullptr;
1279 bool TryFold = false;
1280 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
1281 RC = &AArch64::GPR64RegClass;
1282 Opc = AArch64::CSELXr;
1283 TryFold = true;
1284 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
1285 RC = &AArch64::GPR32RegClass;
1286 Opc = AArch64::CSELWr;
1287 TryFold = true;
1288 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
1289 RC = &AArch64::FPR64RegClass;
1290 Opc = AArch64::FCSELDrrr;
1291 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
1292 RC = &AArch64::FPR32RegClass;
1293 Opc = AArch64::FCSELSrrr;
1294 }
1295 assert(RC && "Unsupported regclass");
1296
1297 // Try folding simple instructions into the csel.
1298 if (TryFold) {
1299 unsigned NewReg = 0;
1300 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewReg);
1301 if (FoldedOpc) {
1302 // The folded opcodes csinc, csinc and csneg apply the operation to
1303 // FalseReg, so we need to invert the condition.
1305 TrueReg = FalseReg;
1306 } else
1307 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewReg);
1308
1309 // Fold the operation. Leave any dead instructions for DCE to clean up.
1310 if (FoldedOpc) {
1311 FalseReg = NewReg;
1312 Opc = FoldedOpc;
1313 // Extend the live range of NewReg.
1314 MRI.clearKillFlags(NewReg);
1315 }
1316 }
1317
1318 // Pull all virtual register into the appropriate class.
1319 MRI.constrainRegClass(TrueReg, RC);
1320 // FalseReg might be WZR or XZR if the folded operand is a literal 1.
1321 assert(
1322 (FalseReg.isVirtual() || FalseReg == AArch64::WZR ||
1323 FalseReg == AArch64::XZR) &&
1324 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1325 if (FalseReg.isVirtual())
1326 MRI.constrainRegClass(FalseReg, RC);
1327
1328 // Insert the csel.
1329 BuildMI(MBB, I, DL, get(Opc), DstReg)
1330 .addReg(TrueReg)
1331 .addReg(FalseReg)
1332 .addImm(CC);
1333}
1334
1335// Return true if Imm can be loaded into a register by a "cheap" sequence of
1336// instructions. For now, "cheap" means at most two instructions.
1337static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
1338 if (BitSize == 32)
1339 return true;
1340
1341 assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
1342 uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
1344 AArch64_IMM::expandMOVImm(Imm, BitSize, Is);
1345
1346 return Is.size() <= 2;
1347}
1348
1349// Check if a COPY instruction is cheap.
1350static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
1351 assert(MI.isCopy() && "Expected COPY instruction");
1352 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1353
1354 // Cross-bank copies (e.g., between GPR and FPR) are expensive on AArch64,
1355 // typically requiring an FMOV instruction with a 2-6 cycle latency.
1356 auto GetRegClass = [&](Register Reg) -> const TargetRegisterClass * {
1357 if (Reg.isVirtual())
1358 return MRI.getRegClass(Reg);
1359 if (Reg.isPhysical())
1360 return RI.getMinimalPhysRegClass(Reg);
1361 return nullptr;
1362 };
1363 const TargetRegisterClass *DstRC = GetRegClass(MI.getOperand(0).getReg());
1364 const TargetRegisterClass *SrcRC = GetRegClass(MI.getOperand(1).getReg());
1365 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1366 return false;
1367
1368 return MI.isAsCheapAsAMove();
1369}
1370
1371// FIXME: this implementation should be micro-architecture dependent, so a
1372// micro-architecture target hook should be introduced here in future.
1374 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1375 if (isExynosCheapAsMove(MI))
1376 return true;
1377 return MI.isAsCheapAsAMove();
1378 }
1379
1380 switch (MI.getOpcode()) {
1381 default:
1382 return MI.isAsCheapAsAMove();
1383
1384 case TargetOpcode::COPY:
1385 return isCheapCopy(MI, RI);
1386
1387 case AArch64::ADDWrs:
1388 case AArch64::ADDXrs:
1389 case AArch64::SUBWrs:
1390 case AArch64::SUBXrs:
1391 return Subtarget.hasALULSLFast() && MI.getOperand(3).getImm() <= 4;
1392
1393 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
1394 // ORRXri, it is as cheap as MOV.
1395 // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
1396 case AArch64::MOVi32imm:
1397 return isCheapImmediate(MI, 32);
1398 case AArch64::MOVi64imm:
1399 return isCheapImmediate(MI, 64);
1400 }
1401}
1402
1403bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) {
1404 switch (MI.getOpcode()) {
1405 default:
1406 return false;
1407
1408 case AArch64::ADDWrs:
1409 case AArch64::ADDXrs:
1410 case AArch64::ADDSWrs:
1411 case AArch64::ADDSXrs: {
1412 unsigned Imm = MI.getOperand(3).getImm();
1413 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1414 if (ShiftVal == 0)
1415 return true;
1416 return AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL && ShiftVal <= 5;
1417 }
1418
1419 case AArch64::ADDWrx:
1420 case AArch64::ADDXrx:
1421 case AArch64::ADDXrx64:
1422 case AArch64::ADDSWrx:
1423 case AArch64::ADDSXrx:
1424 case AArch64::ADDSXrx64: {
1425 unsigned Imm = MI.getOperand(3).getImm();
1426 switch (AArch64_AM::getArithExtendType(Imm)) {
1427 default:
1428 return false;
1429 case AArch64_AM::UXTB:
1430 case AArch64_AM::UXTH:
1431 case AArch64_AM::UXTW:
1432 case AArch64_AM::UXTX:
1433 return AArch64_AM::getArithShiftValue(Imm) <= 4;
1434 }
1435 }
1436
1437 case AArch64::SUBWrs:
1438 case AArch64::SUBSWrs: {
1439 unsigned Imm = MI.getOperand(3).getImm();
1440 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1441 return ShiftVal == 0 ||
1442 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 31);
1443 }
1444
1445 case AArch64::SUBXrs:
1446 case AArch64::SUBSXrs: {
1447 unsigned Imm = MI.getOperand(3).getImm();
1448 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1449 return ShiftVal == 0 ||
1450 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 63);
1451 }
1452
1453 case AArch64::SUBWrx:
1454 case AArch64::SUBXrx:
1455 case AArch64::SUBXrx64:
1456 case AArch64::SUBSWrx:
1457 case AArch64::SUBSXrx:
1458 case AArch64::SUBSXrx64: {
1459 unsigned Imm = MI.getOperand(3).getImm();
1460 switch (AArch64_AM::getArithExtendType(Imm)) {
1461 default:
1462 return false;
1463 case AArch64_AM::UXTB:
1464 case AArch64_AM::UXTH:
1465 case AArch64_AM::UXTW:
1466 case AArch64_AM::UXTX:
1467 return AArch64_AM::getArithShiftValue(Imm) == 0;
1468 }
1469 }
1470
1471 case AArch64::LDRBBroW:
1472 case AArch64::LDRBBroX:
1473 case AArch64::LDRBroW:
1474 case AArch64::LDRBroX:
1475 case AArch64::LDRDroW:
1476 case AArch64::LDRDroX:
1477 case AArch64::LDRHHroW:
1478 case AArch64::LDRHHroX:
1479 case AArch64::LDRHroW:
1480 case AArch64::LDRHroX:
1481 case AArch64::LDRQroW:
1482 case AArch64::LDRQroX:
1483 case AArch64::LDRSBWroW:
1484 case AArch64::LDRSBWroX:
1485 case AArch64::LDRSBXroW:
1486 case AArch64::LDRSBXroX:
1487 case AArch64::LDRSHWroW:
1488 case AArch64::LDRSHWroX:
1489 case AArch64::LDRSHXroW:
1490 case AArch64::LDRSHXroX:
1491 case AArch64::LDRSWroW:
1492 case AArch64::LDRSWroX:
1493 case AArch64::LDRSroW:
1494 case AArch64::LDRSroX:
1495 case AArch64::LDRWroW:
1496 case AArch64::LDRWroX:
1497 case AArch64::LDRXroW:
1498 case AArch64::LDRXroX:
1499 case AArch64::PRFMroW:
1500 case AArch64::PRFMroX:
1501 case AArch64::STRBBroW:
1502 case AArch64::STRBBroX:
1503 case AArch64::STRBroW:
1504 case AArch64::STRBroX:
1505 case AArch64::STRDroW:
1506 case AArch64::STRDroX:
1507 case AArch64::STRHHroW:
1508 case AArch64::STRHHroX:
1509 case AArch64::STRHroW:
1510 case AArch64::STRHroX:
1511 case AArch64::STRQroW:
1512 case AArch64::STRQroX:
1513 case AArch64::STRSroW:
1514 case AArch64::STRSroX:
1515 case AArch64::STRWroW:
1516 case AArch64::STRWroX:
1517 case AArch64::STRXroW:
1518 case AArch64::STRXroX: {
1519 unsigned IsSigned = MI.getOperand(3).getImm();
1520 return !IsSigned;
1521 }
1522 }
1523}
1524
1525bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
1526 unsigned Opc = MI.getOpcode();
1527 switch (Opc) {
1528 default:
1529 return false;
1530 case AArch64::SEH_StackAlloc:
1531 case AArch64::SEH_SaveFPLR:
1532 case AArch64::SEH_SaveFPLR_X:
1533 case AArch64::SEH_SaveReg:
1534 case AArch64::SEH_SaveReg_X:
1535 case AArch64::SEH_SaveRegP:
1536 case AArch64::SEH_SaveRegP_X:
1537 case AArch64::SEH_SaveFReg:
1538 case AArch64::SEH_SaveFReg_X:
1539 case AArch64::SEH_SaveFRegP:
1540 case AArch64::SEH_SaveFRegP_X:
1541 case AArch64::SEH_SetFP:
1542 case AArch64::SEH_AddFP:
1543 case AArch64::SEH_Nop:
1544 case AArch64::SEH_PrologEnd:
1545 case AArch64::SEH_EpilogStart:
1546 case AArch64::SEH_EpilogEnd:
1547 case AArch64::SEH_PACSignLR:
1548 case AArch64::SEH_SaveAnyRegI:
1549 case AArch64::SEH_SaveAnyRegIP:
1550 case AArch64::SEH_SaveAnyRegQP:
1551 case AArch64::SEH_SaveAnyRegQPX:
1552 case AArch64::SEH_AllocZ:
1553 case AArch64::SEH_SaveZReg:
1554 case AArch64::SEH_SavePReg:
1555 return true;
1556 }
1557}
1558
1560 Register &SrcReg, Register &DstReg,
1561 unsigned &SubIdx) const {
1562 switch (MI.getOpcode()) {
1563 default:
1564 return false;
1565 case AArch64::SBFMXri: // aka sxtw
1566 case AArch64::UBFMXri: // aka uxtw
1567 // Check for the 32 -> 64 bit extension case, these instructions can do
1568 // much more.
1569 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
1570 return false;
1571 // This is a signed or unsigned 32 -> 64 bit extension.
1572 SrcReg = MI.getOperand(1).getReg();
1573 DstReg = MI.getOperand(0).getReg();
1574 SubIdx = AArch64::sub_32;
1575 return true;
1576 }
1577}
1578
1580 const MachineInstr &MIa, const MachineInstr &MIb) const {
1582 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
1583 int64_t OffsetA = 0, OffsetB = 0;
1584 TypeSize WidthA(0, false), WidthB(0, false);
1585 bool OffsetAIsScalable = false, OffsetBIsScalable = false;
1586
1587 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
1588 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
1589
1592 return false;
1593
1594 // Retrieve the base, offset from the base and width. Width
1595 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
1596 // base are identical, and the offset of a lower memory access +
1597 // the width doesn't overlap the offset of a higher memory access,
1598 // then the memory accesses are different.
1599 // If OffsetAIsScalable and OffsetBIsScalable are both true, they
1600 // are assumed to have the same scale (vscale).
1601 if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, OffsetAIsScalable,
1602 WidthA, TRI) &&
1603 getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, OffsetBIsScalable,
1604 WidthB, TRI)) {
1605 if (BaseOpA->isIdenticalTo(*BaseOpB) &&
1606 OffsetAIsScalable == OffsetBIsScalable) {
1607 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1608 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1609 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1610 if (LowWidth.isScalable() == OffsetAIsScalable &&
1611 LowOffset + (int)LowWidth.getKnownMinValue() <= HighOffset)
1612 return true;
1613 }
1614 }
1615 return false;
1616}
1617
1619 const MachineBasicBlock *MBB,
1620 const MachineFunction &MF) const {
1622 return true;
1623
1624 // Do not move an instruction that can be recognized as a branch target.
1625 if (hasBTISemantics(MI))
1626 return true;
1627
1628 switch (MI.getOpcode()) {
1629 case AArch64::HINT:
1630 // CSDB hints are scheduling barriers.
1631 if (MI.getOperand(0).getImm() == 0x14)
1632 return true;
1633 break;
1634 case AArch64::DSB:
1635 case AArch64::ISB:
1636 // DSB and ISB also are scheduling barriers.
1637 return true;
1638 case AArch64::MSRpstatesvcrImm1:
1639 // SMSTART and SMSTOP are also scheduling barriers.
1640 return true;
1641 default:;
1642 }
1643 if (isSEHInstruction(MI))
1644 return true;
1645 auto Next = std::next(MI.getIterator());
1646 return Next != MBB->end() && Next->isCFIInstruction();
1647}
1648
1649/// analyzeCompare - For a comparison instruction, return the source registers
1650/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
1651/// Return true if the comparison instruction can be analyzed.
1653 Register &SrcReg2, int64_t &CmpMask,
1654 int64_t &CmpValue) const {
1655 // The first operand can be a frame index where we'd normally expect a
1656 // register.
1657 // FIXME: Pass subregisters out of analyzeCompare
1658 assert(MI.getNumOperands() >= 2 && "All AArch64 cmps should have 2 operands");
1659 if (!MI.getOperand(1).isReg() || MI.getOperand(1).getSubReg())
1660 return false;
1661
1662 switch (MI.getOpcode()) {
1663 default:
1664 break;
1665 case AArch64::PTEST_PP:
1666 case AArch64::PTEST_PP_ANY:
1667 case AArch64::PTEST_PP_FIRST:
1668 SrcReg = MI.getOperand(0).getReg();
1669 SrcReg2 = MI.getOperand(1).getReg();
1670 if (MI.getOperand(2).getSubReg())
1671 return false;
1672
1673 // Not sure about the mask and value for now...
1674 CmpMask = ~0;
1675 CmpValue = 0;
1676 return true;
1677 case AArch64::SUBSWrr:
1678 case AArch64::SUBSWrs:
1679 case AArch64::SUBSWrx:
1680 case AArch64::SUBSXrr:
1681 case AArch64::SUBSXrs:
1682 case AArch64::SUBSXrx:
1683 case AArch64::ADDSWrr:
1684 case AArch64::ADDSWrs:
1685 case AArch64::ADDSWrx:
1686 case AArch64::ADDSXrr:
1687 case AArch64::ADDSXrs:
1688 case AArch64::ADDSXrx:
1689 // Replace SUBSWrr with SUBWrr if NZCV is not used.
1690 SrcReg = MI.getOperand(1).getReg();
1691 SrcReg2 = MI.getOperand(2).getReg();
1692
1693 // FIXME: Pass subregisters out of analyzeCompare
1694 if (MI.getOperand(2).getSubReg())
1695 return false;
1696
1697 CmpMask = ~0;
1698 CmpValue = 0;
1699 return true;
1700 case AArch64::SUBSWri:
1701 case AArch64::ADDSWri:
1702 case AArch64::SUBSXri:
1703 case AArch64::ADDSXri:
1704 SrcReg = MI.getOperand(1).getReg();
1705 SrcReg2 = 0;
1706 CmpMask = ~0;
1707 CmpValue = MI.getOperand(2).getImm();
1708 return true;
1709 case AArch64::ANDSWri:
1710 case AArch64::ANDSXri:
1711 // ANDS does not use the same encoding scheme as the others xxxS
1712 // instructions.
1713 SrcReg = MI.getOperand(1).getReg();
1714 SrcReg2 = 0;
1715 CmpMask = ~0;
1717 MI.getOperand(2).getImm(),
1718 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1719 return true;
1720 }
1721
1722 return false;
1723}
1724
1726 MachineBasicBlock *MBB = Instr.getParent();
1727 assert(MBB && "Can't get MachineBasicBlock here");
1728 MachineFunction *MF = MBB->getParent();
1729 assert(MF && "Can't get MachineFunction here");
1732 MachineRegisterInfo *MRI = &MF->getRegInfo();
1733
1734 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1735 ++OpIdx) {
1736 MachineOperand &MO = Instr.getOperand(OpIdx);
1737 const TargetRegisterClass *OpRegCstraints =
1738 Instr.getRegClassConstraint(OpIdx, TII, TRI);
1739
1740 // If there's no constraint, there's nothing to do.
1741 if (!OpRegCstraints)
1742 continue;
1743 // If the operand is a frame index, there's nothing to do here.
1744 // A frame index operand will resolve correctly during PEI.
1745 if (MO.isFI())
1746 continue;
1747
1748 assert(MO.isReg() &&
1749 "Operand has register constraints without being a register!");
1750
1751 Register Reg = MO.getReg();
1752 if (Reg.isPhysical()) {
1753 if (!OpRegCstraints->contains(Reg))
1754 return false;
1755 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
1756 !MRI->constrainRegClass(Reg, OpRegCstraints))
1757 return false;
1758 }
1759
1760 return true;
1761}
1762
1763/// Return the opcode that does not set flags when possible - otherwise
1764/// return the original opcode. The caller is responsible to do the actual
1765/// substitution and legality checking.
1767 // Don't convert all compare instructions, because for some the zero register
1768 // encoding becomes the sp register.
1769 bool MIDefinesZeroReg = false;
1770 if (MI.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
1771 MI.definesRegister(AArch64::XZR, /*TRI=*/nullptr))
1772 MIDefinesZeroReg = true;
1773
1774 switch (MI.getOpcode()) {
1775 default:
1776 return MI.getOpcode();
1777 case AArch64::ADDSWrr:
1778 return AArch64::ADDWrr;
1779 case AArch64::ADDSWri:
1780 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1781 case AArch64::ADDSWrs:
1782 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1783 case AArch64::ADDSWrx:
1784 return AArch64::ADDWrx;
1785 case AArch64::ADDSXrr:
1786 return AArch64::ADDXrr;
1787 case AArch64::ADDSXri:
1788 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1789 case AArch64::ADDSXrs:
1790 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1791 case AArch64::ADDSXrx:
1792 return AArch64::ADDXrx;
1793 case AArch64::SUBSWrr:
1794 return AArch64::SUBWrr;
1795 case AArch64::SUBSWri:
1796 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1797 case AArch64::SUBSWrs:
1798 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1799 case AArch64::SUBSWrx:
1800 return AArch64::SUBWrx;
1801 case AArch64::SUBSXrr:
1802 return AArch64::SUBXrr;
1803 case AArch64::SUBSXri:
1804 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1805 case AArch64::SUBSXrs:
1806 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1807 case AArch64::SUBSXrx:
1808 return AArch64::SUBXrx;
1809 }
1810}
1811
1812enum AccessKind { AK_Write = 0x01, AK_Read = 0x10, AK_All = 0x11 };
1813
1814/// True when condition flags are accessed (either by writing or reading)
1815/// on the instruction trace starting at From and ending at To.
1816///
1817/// Note: If From and To are from different blocks it's assumed CC are accessed
1818/// on the path.
1821 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
1822 // Early exit if To is at the beginning of the BB.
1823 if (To == To->getParent()->begin())
1824 return true;
1825
1826 // Check whether the instructions are in the same basic block
1827 // If not, assume the condition flags might get modified somewhere.
1828 if (To->getParent() != From->getParent())
1829 return true;
1830
1831 // From must be above To.
1832 assert(std::any_of(
1833 ++To.getReverse(), To->getParent()->rend(),
1834 [From](MachineInstr &MI) { return MI.getIterator() == From; }));
1835
1836 // We iterate backward starting at \p To until we hit \p From.
1837 for (const MachineInstr &Instr :
1839 if (((AccessToCheck & AK_Write) &&
1840 Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
1841 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
1842 return true;
1843 }
1844 return false;
1845}
1846
1847std::optional<unsigned>
1848AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1849 MachineInstr *Pred,
1850 const MachineRegisterInfo *MRI) const {
1851 unsigned MaskOpcode = Mask->getOpcode();
1852 unsigned PredOpcode = Pred->getOpcode();
1853 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1854 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1855
1856 if (PredIsWhileLike) {
1857 // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1858 // instruction and the condition is "any" since WHILcc does an implicit
1859 // PTEST(ALL, PG) check and PG is always a subset of ALL.
1860 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1861 return PredOpcode;
1862
1863 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1864 // redundant since WHILE performs an implicit PTEST with an all active
1865 // mask.
1866 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1867 getElementSizeForOpcode(MaskOpcode) ==
1868 getElementSizeForOpcode(PredOpcode))
1869 return PredOpcode;
1870
1871 // For PTEST_FIRST(PTRUE_ALL, WHILE), the PTEST_FIRST is redundant since
1872 // WHILEcc performs an implicit PTEST with an all active mask, setting
1873 // the N flag as the PTEST_FIRST would.
1874 if (PTest->getOpcode() == AArch64::PTEST_PP_FIRST &&
1875 isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31)
1876 return PredOpcode;
1877
1878 return {};
1879 }
1880
1881 if (PredIsPTestLike) {
1882 // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1883 // instruction that sets the flags as PTEST would and the condition is
1884 // "any" since PG is always a subset of the governing predicate of the
1885 // ptest-like instruction.
1886 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1887 return PredOpcode;
1888
1889 auto PTestLikeMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1890
1891 // If the PTEST like instruction's general predicate is not `Mask`, attempt
1892 // to look through a copy and try again. This is because some instructions
1893 // take a predicate whose register class is a subset of its result class.
1894 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1895 PTestLikeMask->getOperand(1).getReg().isVirtual())
1896 PTestLikeMask =
1897 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1898
1899 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1900 // the element size matches and either the PTEST_LIKE instruction uses
1901 // the same all active mask or the condition is "any".
1902 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1903 getElementSizeForOpcode(MaskOpcode) ==
1904 getElementSizeForOpcode(PredOpcode)) {
1905 if (Mask == PTestLikeMask || PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1906 return PredOpcode;
1907 }
1908
1909 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
1910 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
1911 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
1912 // compare that also support 16/32/64-bit predicates, the implicit PTEST
1913 // performed by the compare could consider fewer lanes for these element
1914 // sizes.
1915 //
1916 // For example, consider
1917 //
1918 // ptrue p0.b ; P0=1111-1111-1111-1111
1919 // index z0.s, #0, #1 ; Z0=<0,1,2,3>
1920 // index z1.s, #1, #1 ; Z1=<1,2,3,4>
1921 // cmphi p1.s, p0/z, z1.s, z0.s ; P1=0001-0001-0001-0001
1922 // ; ^ last active
1923 // ptest p0, p1.b ; P1=0001-0001-0001-0001
1924 // ; ^ last active
1925 //
1926 // where the compare generates a canonical all active 32-bit predicate
1927 // (equivalent to 'ptrue p1.s, all'). The implicit PTEST sets the last
1928 // active flag, whereas the PTEST instruction with the same mask doesn't.
1929 // For PTEST_ANY this doesn't apply as the flags in this case would be
1930 // identical regardless of element size.
1931 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1932 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1933 PTest->getOpcode() == AArch64::PTEST_PP_ANY))
1934 return PredOpcode;
1935
1936 return {};
1937 }
1938
1939 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1940 // opcode so the PTEST becomes redundant.
1941 switch (PredOpcode) {
1942 case AArch64::AND_PPzPP:
1943 case AArch64::BIC_PPzPP:
1944 case AArch64::EOR_PPzPP:
1945 case AArch64::NAND_PPzPP:
1946 case AArch64::NOR_PPzPP:
1947 case AArch64::ORN_PPzPP:
1948 case AArch64::ORR_PPzPP:
1949 case AArch64::BRKA_PPzP:
1950 case AArch64::BRKPA_PPzPP:
1951 case AArch64::BRKB_PPzP:
1952 case AArch64::BRKPB_PPzPP:
1953 case AArch64::RDFFR_PPz: {
1954 // Check to see if our mask is the same. If not the resulting flag bits
1955 // may be different and we can't remove the ptest.
1956 auto *PredMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1957 if (Mask != PredMask)
1958 return {};
1959 break;
1960 }
1961 case AArch64::BRKN_PPzP: {
1962 // BRKN uses an all active implicit mask to set flags unlike the other
1963 // flag-setting instructions.
1964 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1965 if ((MaskOpcode != AArch64::PTRUE_B) ||
1966 (Mask->getOperand(1).getImm() != 31))
1967 return {};
1968 break;
1969 }
1970 case AArch64::PTRUE_B:
1971 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1972 break;
1973 default:
1974 // Bail out if we don't recognize the input
1975 return {};
1976 }
1977
1978 return convertToFlagSettingOpc(PredOpcode);
1979}
1980
1981/// optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
1982/// operation which could set the flags in an identical manner
1983bool AArch64InstrInfo::optimizePTestInstr(
1984 MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
1985 const MachineRegisterInfo *MRI) const {
1986 auto *Mask = MRI->getUniqueVRegDef(MaskReg);
1987 auto *Pred = MRI->getUniqueVRegDef(PredReg);
1988
1989 if (Pred->isCopy() && PTest->getOpcode() == AArch64::PTEST_PP_FIRST) {
1990 // Instructions which return a multi-vector (e.g. WHILECC_x2) require copies
1991 // before the branch to extract each subregister.
1992 auto Op = Pred->getOperand(1);
1993 if (Op.isReg() && Op.getReg().isVirtual() &&
1994 Op.getSubReg() == AArch64::psub0)
1995 Pred = MRI->getUniqueVRegDef(Op.getReg());
1996 }
1997
1998 unsigned PredOpcode = Pred->getOpcode();
1999 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
2000 if (!NewOp)
2001 return false;
2002
2003 const TargetRegisterInfo *TRI = &getRegisterInfo();
2004
2005 // If another instruction between Pred and PTest accesses flags, don't remove
2006 // the ptest or update the earlier instruction to modify them.
2007 if (areCFlagsAccessedBetweenInstrs(Pred, PTest, TRI))
2008 return false;
2009
2010 // If we pass all the checks, it's safe to remove the PTEST and use the flags
2011 // as they are prior to PTEST. Sometimes this requires the tested PTEST
2012 // operand to be replaced with an equivalent instruction that also sets the
2013 // flags.
2014 PTest->eraseFromParent();
2015 if (*NewOp != PredOpcode) {
2016 Pred->setDesc(get(*NewOp));
2017 bool succeeded = UpdateOperandRegClass(*Pred);
2018 (void)succeeded;
2019 assert(succeeded && "Operands have incompatible register classes!");
2020 Pred->addRegisterDefined(AArch64::NZCV, TRI);
2021 }
2022
2023 // Ensure that the flags def is live.
2024 if (Pred->registerDefIsDead(AArch64::NZCV, TRI)) {
2025 unsigned i = 0, e = Pred->getNumOperands();
2026 for (; i != e; ++i) {
2027 MachineOperand &MO = Pred->getOperand(i);
2028 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::NZCV) {
2029 MO.setIsDead(false);
2030 break;
2031 }
2032 }
2033 }
2034 return true;
2035}
2036
2037/// Try to optimize a compare instruction. A compare instruction is an
2038/// instruction which produces AArch64::NZCV. It can be truly compare
2039/// instruction
2040/// when there are no uses of its destination register.
2041///
2042/// The following steps are tried in order:
2043/// 1. Convert CmpInstr into an unconditional version.
2044/// 2. Remove CmpInstr if above there is an instruction producing a needed
2045/// condition code or an instruction which can be converted into such an
2046/// instruction.
2047/// Only comparison with zero is supported.
2049 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
2050 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
2051 assert(CmpInstr.getParent());
2052 assert(MRI);
2053
2054 // Replace SUBSWrr with SUBWrr if NZCV is not used.
2055 int DeadNZCVIdx =
2056 CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
2057 if (DeadNZCVIdx != -1) {
2058 if (CmpInstr.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
2059 CmpInstr.definesRegister(AArch64::XZR, /*TRI=*/nullptr)) {
2060 CmpInstr.eraseFromParent();
2061 return true;
2062 }
2063 unsigned Opc = CmpInstr.getOpcode();
2064 unsigned NewOpc = convertToNonFlagSettingOpc(CmpInstr);
2065 if (NewOpc == Opc)
2066 return false;
2067 const MCInstrDesc &MCID = get(NewOpc);
2068 CmpInstr.setDesc(MCID);
2069 CmpInstr.removeOperand(DeadNZCVIdx);
2070 bool succeeded = UpdateOperandRegClass(CmpInstr);
2071 (void)succeeded;
2072 assert(succeeded && "Some operands reg class are incompatible!");
2073 return true;
2074 }
2075
2076 if (CmpInstr.getOpcode() == AArch64::PTEST_PP ||
2077 CmpInstr.getOpcode() == AArch64::PTEST_PP_ANY ||
2078 CmpInstr.getOpcode() == AArch64::PTEST_PP_FIRST)
2079 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2080
2081 if (SrcReg2 != 0)
2082 return false;
2083
2084 // CmpInstr is a Compare instruction if destination register is not used.
2085 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
2086 return false;
2087
2088 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2089 return true;
2090 return (CmpValue == 0 || CmpValue == 1) &&
2091 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2092}
2093
2094/// Get opcode of S version of Instr.
2095/// If Instr is S version its opcode is returned.
2096/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
2097/// or we are not interested in it.
2098static unsigned sForm(MachineInstr &Instr) {
2099 switch (Instr.getOpcode()) {
2100 default:
2101 return AArch64::INSTRUCTION_LIST_END;
2102
2103 case AArch64::ADDSWrr:
2104 case AArch64::ADDSWri:
2105 case AArch64::ADDSXrr:
2106 case AArch64::ADDSXri:
2107 case AArch64::ADDSWrx:
2108 case AArch64::ADDSXrx:
2109 case AArch64::ADDSWrs:
2110 case AArch64::ADDSXrs:
2111 case AArch64::SUBSWrr:
2112 case AArch64::SUBSWri:
2113 case AArch64::SUBSWrx:
2114 case AArch64::SUBSWrs:
2115 case AArch64::SUBSXrr:
2116 case AArch64::SUBSXri:
2117 case AArch64::SUBSXrx:
2118 case AArch64::SUBSXrs:
2119 case AArch64::ANDSWri:
2120 case AArch64::ANDSWrr:
2121 case AArch64::ANDSWrs:
2122 case AArch64::ANDSXri:
2123 case AArch64::ANDSXrr:
2124 case AArch64::ANDSXrs:
2125 case AArch64::BICSWrr:
2126 case AArch64::BICSXrr:
2127 case AArch64::BICSWrs:
2128 case AArch64::BICSXrs:
2129 case AArch64::ADCSWr:
2130 case AArch64::ADCSXr:
2131 case AArch64::SBCSWr:
2132 case AArch64::SBCSXr:
2133 return Instr.getOpcode();
2134
2135 case AArch64::ADDWrr:
2136 return AArch64::ADDSWrr;
2137 case AArch64::ADDWri:
2138 return AArch64::ADDSWri;
2139 case AArch64::ADDXrr:
2140 return AArch64::ADDSXrr;
2141 case AArch64::ADDXri:
2142 return AArch64::ADDSXri;
2143 case AArch64::ADDWrx:
2144 return AArch64::ADDSWrx;
2145 case AArch64::ADDXrx:
2146 return AArch64::ADDSXrx;
2147 case AArch64::ADDWrs:
2148 return AArch64::ADDSWrs;
2149 case AArch64::ADDXrs:
2150 return AArch64::ADDSXrs;
2151 case AArch64::ADCWr:
2152 return AArch64::ADCSWr;
2153 case AArch64::ADCXr:
2154 return AArch64::ADCSXr;
2155 case AArch64::SUBWrr:
2156 return AArch64::SUBSWrr;
2157 case AArch64::SUBWri:
2158 return AArch64::SUBSWri;
2159 case AArch64::SUBXrr:
2160 return AArch64::SUBSXrr;
2161 case AArch64::SUBXri:
2162 return AArch64::SUBSXri;
2163 case AArch64::SUBWrx:
2164 return AArch64::SUBSWrx;
2165 case AArch64::SUBXrx:
2166 return AArch64::SUBSXrx;
2167 case AArch64::SUBWrs:
2168 return AArch64::SUBSWrs;
2169 case AArch64::SUBXrs:
2170 return AArch64::SUBSXrs;
2171 case AArch64::SBCWr:
2172 return AArch64::SBCSWr;
2173 case AArch64::SBCXr:
2174 return AArch64::SBCSXr;
2175 case AArch64::ANDWri:
2176 return AArch64::ANDSWri;
2177 case AArch64::ANDXri:
2178 return AArch64::ANDSXri;
2179 case AArch64::ANDWrr:
2180 return AArch64::ANDSWrr;
2181 case AArch64::ANDWrs:
2182 return AArch64::ANDSWrs;
2183 case AArch64::ANDXrr:
2184 return AArch64::ANDSXrr;
2185 case AArch64::ANDXrs:
2186 return AArch64::ANDSXrs;
2187 case AArch64::BICWrr:
2188 return AArch64::BICSWrr;
2189 case AArch64::BICXrr:
2190 return AArch64::BICSXrr;
2191 case AArch64::BICWrs:
2192 return AArch64::BICSWrs;
2193 case AArch64::BICXrs:
2194 return AArch64::BICSXrs;
2195 }
2196}
2197
2198/// Check if AArch64::NZCV should be alive in successors of MBB.
2200 for (auto *BB : MBB->successors())
2201 if (BB->isLiveIn(AArch64::NZCV))
2202 return true;
2203 return false;
2204}
2205
2206/// \returns The condition code operand index for \p Instr if it is a branch
2207/// or select and -1 otherwise.
2208int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2209 const MachineInstr &Instr) {
2210 switch (Instr.getOpcode()) {
2211 default:
2212 return -1;
2213
2214 case AArch64::Bcc: {
2215 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2216 assert(Idx >= 2);
2217 return Idx - 2;
2218 }
2219
2220 case AArch64::CSINVWr:
2221 case AArch64::CSINVXr:
2222 case AArch64::CSINCWr:
2223 case AArch64::CSINCXr:
2224 case AArch64::CSELWr:
2225 case AArch64::CSELXr:
2226 case AArch64::CSNEGWr:
2227 case AArch64::CSNEGXr:
2228 case AArch64::FCSELSrrr:
2229 case AArch64::FCSELDrrr: {
2230 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2231 assert(Idx >= 1);
2232 return Idx - 1;
2233 }
2234 }
2235}
2236
2237/// Find a condition code used by the instruction.
2238/// Returns AArch64CC::Invalid if either the instruction does not use condition
2239/// codes or we don't optimize CmpInstr in the presence of such instructions.
2241 int CCIdx =
2242 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2243 return CCIdx >= 0 ? static_cast<AArch64CC::CondCode>(
2244 Instr.getOperand(CCIdx).getImm())
2246}
2247
2250 UsedNZCV UsedFlags;
2251 switch (CC) {
2252 default:
2253 break;
2254
2255 case AArch64CC::EQ: // Z set
2256 case AArch64CC::NE: // Z clear
2257 UsedFlags.Z = true;
2258 break;
2259
2260 case AArch64CC::HI: // Z clear and C set
2261 case AArch64CC::LS: // Z set or C clear
2262 UsedFlags.Z = true;
2263 [[fallthrough]];
2264 case AArch64CC::HS: // C set
2265 case AArch64CC::LO: // C clear
2266 UsedFlags.C = true;
2267 break;
2268
2269 case AArch64CC::MI: // N set
2270 case AArch64CC::PL: // N clear
2271 UsedFlags.N = true;
2272 break;
2273
2274 case AArch64CC::VS: // V set
2275 case AArch64CC::VC: // V clear
2276 UsedFlags.V = true;
2277 break;
2278
2279 case AArch64CC::GT: // Z clear, N and V the same
2280 case AArch64CC::LE: // Z set, N and V differ
2281 UsedFlags.Z = true;
2282 [[fallthrough]];
2283 case AArch64CC::GE: // N and V the same
2284 case AArch64CC::LT: // N and V differ
2285 UsedFlags.N = true;
2286 UsedFlags.V = true;
2287 break;
2288 }
2289 return UsedFlags;
2290}
2291
2292/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
2293/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
2294/// \returns std::nullopt otherwise.
2295///
2296/// Collect instructions using that flags in \p CCUseInstrs if provided.
2297std::optional<UsedNZCV>
2299 const TargetRegisterInfo &TRI,
2300 SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
2301 MachineBasicBlock *CmpParent = CmpInstr.getParent();
2302 if (MI.getParent() != CmpParent)
2303 return std::nullopt;
2304
2305 if (areCFlagsAliveInSuccessors(CmpParent))
2306 return std::nullopt;
2307
2308 UsedNZCV NZCVUsedAfterCmp;
2310 std::next(CmpInstr.getIterator()), CmpParent->instr_end())) {
2311 if (Instr.readsRegister(AArch64::NZCV, &TRI)) {
2313 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
2314 return std::nullopt;
2315 NZCVUsedAfterCmp |= getUsedNZCV(CC);
2316 if (CCUseInstrs)
2317 CCUseInstrs->push_back(&Instr);
2318 }
2319 if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
2320 break;
2321 }
2322 return NZCVUsedAfterCmp;
2323}
2324
2325static bool isADDSRegImm(unsigned Opcode) {
2326 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2327}
2328
2329static bool isSUBSRegImm(unsigned Opcode) {
2330 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2331}
2332
2334 unsigned Opc = sForm(MI);
2335 switch (Opc) {
2336 case AArch64::ANDSWri:
2337 case AArch64::ANDSWrr:
2338 case AArch64::ANDSWrs:
2339 case AArch64::ANDSXri:
2340 case AArch64::ANDSXrr:
2341 case AArch64::ANDSXrs:
2342 case AArch64::BICSWrr:
2343 case AArch64::BICSXrr:
2344 case AArch64::BICSWrs:
2345 case AArch64::BICSXrs:
2346 return true;
2347 default:
2348 return false;
2349 }
2350}
2351
2352/// Check if CmpInstr can be substituted by MI.
2353///
2354/// CmpInstr can be substituted:
2355/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2356/// - and, MI and CmpInstr are from the same MachineBB
2357/// - and, condition flags are not alive in successors of the CmpInstr parent
2358/// - and, if MI opcode is the S form there must be no defs of flags between
2359/// MI and CmpInstr
2360/// or if MI opcode is not the S form there must be neither defs of flags
2361/// nor uses of flags between MI and CmpInstr.
2362/// - and, C is not used after CmpInstr; CmpInstr's C is from adds/subs #0 on
2363/// SrcReg and can differ from MI (e.g. carry out of ADCS/SBCS).
2364/// - and, V is not used after CmpInstr unless MI is AND/BIC (V cleared) or MI
2365/// has NoSWrap (overflow is poison and the fold is still safe).
2367 const TargetRegisterInfo &TRI) {
2368 // MI is an opcode sForm maps (add/sub/adc/sbc/and/bic and their S forms).
2369 assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END);
2370
2371 const unsigned CmpOpcode = CmpInstr.getOpcode();
2372 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
2373 return false;
2374
2375 assert((CmpInstr.getOperand(2).isImm() &&
2376 CmpInstr.getOperand(2).getImm() == 0) &&
2377 "Caller guarantees that CmpInstr compares with constant 0");
2378
2379 std::optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
2380 if (!NZVCUsed || NZVCUsed->C)
2381 return false;
2382
2383 // CmpInstr is ADDS/SUBS with immediate 0 on SrcReg (compare SrcReg to zero).
2384 // After the fold, users see NZCV from MI (or its S form), not from CmpInstr.
2385 // N/Z match CmpInstr for the value in SrcReg; C/V need not match in general
2386 // (e.g. ADCS vs adds #0), so we require C unused after CmpInstr and gate V
2387 // as below. NoSWrap makes signed overflow poison; AND/BIC clear V.
2388 if (NZVCUsed->V && !MI.getFlag(MachineInstr::NoSWrap) && !isANDOpcode(MI))
2389 return false;
2390
2391 AccessKind AccessToCheck = AK_Write;
2392 if (sForm(MI) != MI.getOpcode())
2393 AccessToCheck = AK_All;
2394 return !areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AccessToCheck);
2395}
2396
2397/// Substitute an instruction comparing to zero with another instruction
2398/// which produces needed condition flags.
2399///
2400/// Return true on success.
2401bool AArch64InstrInfo::substituteCmpToZero(
2402 MachineInstr &CmpInstr, unsigned SrcReg,
2403 const MachineRegisterInfo &MRI) const {
2404 // Get the unique definition of SrcReg.
2405 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2406 if (!MI)
2407 return false;
2408
2409 const TargetRegisterInfo &TRI = getRegisterInfo();
2410
2411 unsigned NewOpc = sForm(*MI);
2412 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2413 return false;
2414
2415 if (!canInstrSubstituteCmpInstr(*MI, CmpInstr, TRI))
2416 return false;
2417
2418 // Update the instruction to set NZCV.
2419 MI->setDesc(get(NewOpc));
2420 CmpInstr.eraseFromParent();
2422 (void)succeeded;
2423 assert(succeeded && "Some operands reg class are incompatible!");
2424 MI->addRegisterDefined(AArch64::NZCV, &TRI);
2425 return true;
2426}
2427
2428/// \returns True if \p CmpInstr can be removed.
2429///
2430/// \p IsInvertCC is true if, after removing \p CmpInstr, condition
2431/// codes used in \p CCUseInstrs must be inverted.
2433 int CmpValue, const TargetRegisterInfo &TRI,
2435 bool &IsInvertCC) {
2436 assert((CmpValue == 0 || CmpValue == 1) &&
2437 "Only comparisons to 0 or 1 considered for removal!");
2438
2439 // MI is 'CSINCWr %vreg, wzr, wzr, <cc>' or 'CSINCXr %vreg, xzr, xzr, <cc>'
2440 unsigned MIOpc = MI.getOpcode();
2441 if (MIOpc == AArch64::CSINCWr) {
2442 if (MI.getOperand(1).getReg() != AArch64::WZR ||
2443 MI.getOperand(2).getReg() != AArch64::WZR)
2444 return false;
2445 } else if (MIOpc == AArch64::CSINCXr) {
2446 if (MI.getOperand(1).getReg() != AArch64::XZR ||
2447 MI.getOperand(2).getReg() != AArch64::XZR)
2448 return false;
2449 } else {
2450 return false;
2451 }
2453 if (MICC == AArch64CC::Invalid)
2454 return false;
2455
2456 // NZCV needs to be defined
2457 if (MI.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) != -1)
2458 return false;
2459
2460 // CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0' or 'SUBS %vreg, 1'
2461 const unsigned CmpOpcode = CmpInstr.getOpcode();
2462 bool IsSubsRegImm = isSUBSRegImm(CmpOpcode);
2463 if (CmpValue && !IsSubsRegImm)
2464 return false;
2465 if (!CmpValue && !IsSubsRegImm && !isADDSRegImm(CmpOpcode))
2466 return false;
2467
2468 // MI conditions allowed: eq, ne, mi, pl
2469 UsedNZCV MIUsedNZCV = getUsedNZCV(MICC);
2470 if (MIUsedNZCV.C || MIUsedNZCV.V)
2471 return false;
2472
2473 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2474 examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
2475 // Condition flags are not used in CmpInstr basic block successors and only
2476 // Z or N flags allowed to be used after CmpInstr within its basic block
2477 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2478 return false;
2479 // Z or N flag used after CmpInstr must correspond to the flag used in MI
2480 if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||
2481 (MIUsedNZCV.N && NZCVUsedAfterCmp->Z))
2482 return false;
2483 // If CmpInstr is comparison to zero MI conditions are limited to eq, ne
2484 if (MIUsedNZCV.N && !CmpValue)
2485 return false;
2486
2487 // There must be no defs of flags between MI and CmpInstr
2488 if (areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AK_Write))
2489 return false;
2490
2491 // Condition code is inverted in the following cases:
2492 // 1. MI condition is ne; CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2493 // 2. MI condition is eq, pl; CmpInstr is 'SUBS %vreg, 1'
2494 IsInvertCC = (CmpValue && (MICC == AArch64CC::EQ || MICC == AArch64CC::PL)) ||
2495 (!CmpValue && MICC == AArch64CC::NE);
2496 return true;
2497}
2498
2499/// Remove comparison in csinc-cmp sequence
2500///
2501/// Examples:
2502/// 1. \code
2503/// csinc w9, wzr, wzr, ne
2504/// cmp w9, #0
2505/// b.eq
2506/// \endcode
2507/// to
2508/// \code
2509/// csinc w9, wzr, wzr, ne
2510/// b.ne
2511/// \endcode
2512///
2513/// 2. \code
2514/// csinc x2, xzr, xzr, mi
2515/// cmp x2, #1
2516/// b.pl
2517/// \endcode
2518/// to
2519/// \code
2520/// csinc x2, xzr, xzr, mi
2521/// b.pl
2522/// \endcode
2523///
2524/// \param CmpInstr comparison instruction
2525/// \return True when comparison removed
2526bool AArch64InstrInfo::removeCmpToZeroOrOne(
2527 MachineInstr &CmpInstr, unsigned SrcReg, int CmpValue,
2528 const MachineRegisterInfo &MRI) const {
2529 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2530 if (!MI)
2531 return false;
2532 const TargetRegisterInfo &TRI = getRegisterInfo();
2533 SmallVector<MachineInstr *, 4> CCUseInstrs;
2534 bool IsInvertCC = false;
2535 if (!canCmpInstrBeRemoved(*MI, CmpInstr, CmpValue, TRI, CCUseInstrs,
2536 IsInvertCC))
2537 return false;
2538 // Make transformation
2539 CmpInstr.eraseFromParent();
2540 if (IsInvertCC) {
2541 // Invert condition codes in CmpInstr CC users
2542 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2543 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2544 assert(Idx >= 0 && "Unexpected instruction using CC.");
2545 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2547 static_cast<AArch64CC::CondCode>(CCOperand.getImm()));
2548 CCOperand.setImm(CCUse);
2549 }
2550 }
2551 return true;
2552}
2553
2554bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
2555 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2556 MI.getOpcode() != AArch64::CATCHRET &&
2557 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2558 return false;
2559
2560 MachineBasicBlock &MBB = *MI.getParent();
2561 auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
2562 auto TRI = Subtarget.getRegisterInfo();
2563 DebugLoc DL = MI.getDebugLoc();
2564
2565 if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2566 // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
2567 // This computes FP - stored_mixed_value to unmix the cookie
2568 Register DstReg = MI.getOperand(0).getReg();
2569 Register SrcReg = MI.getOperand(1).getReg();
2570
2571 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
2572 .addReg(AArch64::FP)
2573 .addReg(SrcReg);
2574
2575 MBB.erase(MI);
2576 return true;
2577 }
2578
2579 if (MI.getOpcode() == AArch64::CATCHRET) {
2580 // Skip to the first instruction before the epilog.
2581 const TargetInstrInfo *TII =
2583 MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
2585 MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
2586 while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
2587 FirstEpilogSEH != MBB.begin())
2588 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2589 if (FirstEpilogSEH != MBB.begin())
2590 FirstEpilogSEH = std::next(FirstEpilogSEH);
2591 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
2592 .addReg(AArch64::X0, RegState::Define)
2593 .addMBB(TargetMBB);
2594 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
2595 .addReg(AArch64::X0, RegState::Define)
2596 .addReg(AArch64::X0)
2597 .addMBB(TargetMBB)
2598 .addImm(0);
2599 TargetMBB->setMachineBlockAddressTaken();
2600 return true;
2601 }
2602
2603 Register Reg = MI.getOperand(0).getReg();
2605 if (M.getStackProtectorGuard() == "sysreg") {
2606 const AArch64SysReg::SysReg *SrcReg =
2607 AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg());
2608 if (!SrcReg)
2609 report_fatal_error("Unknown SysReg for Stack Protector Guard Register");
2610
2611 // mrs xN, sysreg
2612 BuildMI(MBB, MI, DL, get(AArch64::MRS))
2614 .addImm(SrcReg->Encoding);
2615 int Offset = M.getStackProtectorGuardOffset();
2616 if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) {
2617 // ldr xN, [xN, #offset]
2618 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2619 .addDef(Reg)
2621 .addImm(Offset / 8);
2622 } else if (Offset >= -256 && Offset <= 255) {
2623 // ldur xN, [xN, #offset]
2624 BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
2625 .addDef(Reg)
2627 .addImm(Offset);
2628 } else if (Offset >= -4095 && Offset <= 4095) {
2629 if (Offset > 0) {
2630 // add xN, xN, #offset
2631 BuildMI(MBB, MI, DL, get(AArch64::ADDXri))
2632 .addDef(Reg)
2634 .addImm(Offset)
2635 .addImm(0);
2636 } else {
2637 // sub xN, xN, #offset
2638 BuildMI(MBB, MI, DL, get(AArch64::SUBXri))
2639 .addDef(Reg)
2641 .addImm(-Offset)
2642 .addImm(0);
2643 }
2644 // ldr xN, [xN]
2645 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2646 .addDef(Reg)
2648 .addImm(0);
2649 } else {
2650 // Cases that are larger than +/- 4095 and not a multiple of 8, or larger
2651 // than 23760.
2652 // It might be nice to use AArch64::MOVi32imm here, which would get
2653 // expanded in PreSched2 after PostRA, but our lone scratch Reg already
2654 // contains the MRS result. findScratchNonCalleeSaveRegister() in
2655 // AArch64FrameLowering might help us find such a scratch register
2656 // though. If we failed to find a scratch register, we could emit a
2657 // stream of add instructions to build up the immediate. Or, we could try
2658 // to insert a AArch64::MOVi32imm before register allocation so that we
2659 // didn't need to scavenge for a scratch register.
2660 report_fatal_error("Unable to encode Stack Protector Guard Offset");
2661 }
2662 MBB.erase(MI);
2663 return true;
2664 }
2665
2666 const GlobalValue *GV =
2667 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
2668 const TargetMachine &TM = MBB.getParent()->getTarget();
2669 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2670 const unsigned char MO_NC = AArch64II::MO_NC;
2671
2672 unsigned GuardWidth = M.getStackProtectorGuardValueWidth().value_or(
2673 Subtarget.isTargetILP32() ? 4 : 8);
2674 if (GuardWidth != 4 && GuardWidth != 8)
2675 report_fatal_error("Unsupported stack protector value width");
2676 if ((OpFlags & AArch64II::MO_GOT) != 0) {
2677 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
2678 .addGlobalAddress(GV, 0, OpFlags);
2679 if (GuardWidth == 4) {
2680 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2681 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2682 .addDef(Reg32, RegState::Dead)
2684 .addImm(0)
2685 .addMemOperand(*MI.memoperands_begin())
2687 } else {
2688 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2690 .addImm(0)
2691 .addMemOperand(*MI.memoperands_begin());
2692 }
2693 } else if (TM.getCodeModel() == CodeModel::Large) {
2694 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
2695 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
2696 .addImm(0);
2697 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2699 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC)
2700 .addImm(16);
2701 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2703 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC)
2704 .addImm(32);
2705 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2708 .addImm(48);
2709 if (GuardWidth == 4) {
2710 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2711 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2712 .addDef(Reg32, RegState::Dead)
2714 .addImm(0)
2715 .addMemOperand(*MI.memoperands_begin())
2717 } else {
2718 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2720 .addImm(0)
2721 .addMemOperand(*MI.memoperands_begin());
2722 }
2723 } else {
2724 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
2725 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
2726 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
2727 if (GuardWidth == 4) {
2728 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2729 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2730 .addDef(Reg32, RegState::Dead)
2732 .addGlobalAddress(GV, 0, LoFlags)
2733 .addMemOperand(*MI.memoperands_begin())
2735 } else {
2736 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2738 .addGlobalAddress(GV, 0, LoFlags)
2739 .addMemOperand(*MI.memoperands_begin());
2740 }
2741 }
2742 // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
2743 // we use sub instruction to mix the cookie on aarch64.
2744 // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
2745 // the final frame pointer value.
2746 if (Subtarget.getTargetTriple().isOSMSVCRT())
2747 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
2748 .addReg(AArch64::FP)
2750
2751 MBB.erase(MI);
2752
2753 return true;
2754}
2755
2756// Return true if this instruction simply sets its single destination register
2757// to zero. This is equivalent to a register rename of the zero-register.
2759 switch (MI.getOpcode()) {
2760 default:
2761 break;
2762 case AArch64::MOVZWi:
2763 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
2764 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
2765 assert(MI.getDesc().getNumOperands() == 3 &&
2766 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
2767 return true;
2768 }
2769 break;
2770 case AArch64::ANDWri: // and Rd, Rzr, #imm
2771 return MI.getOperand(1).getReg() == AArch64::WZR;
2772 case AArch64::ANDXri:
2773 return MI.getOperand(1).getReg() == AArch64::XZR;
2774 case TargetOpcode::COPY:
2775 return MI.getOperand(1).getReg() == AArch64::WZR;
2776 }
2777 return false;
2778}
2779
2780// Return true if this instruction simply renames a general register without
2781// modifying bits.
2783 switch (MI.getOpcode()) {
2784 default:
2785 break;
2786 case TargetOpcode::COPY: {
2787 // GPR32 copies will by lowered to ORRXrs
2788 Register DstReg = MI.getOperand(0).getReg();
2789 return (AArch64::GPR32RegClass.contains(DstReg) ||
2790 AArch64::GPR64RegClass.contains(DstReg));
2791 }
2792 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
2793 if (MI.getOperand(1).getReg() == AArch64::XZR) {
2794 assert(MI.getDesc().getNumOperands() == 4 &&
2795 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
2796 return true;
2797 }
2798 break;
2799 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
2800 if (MI.getOperand(2).getImm() == 0) {
2801 assert(MI.getDesc().getNumOperands() == 4 &&
2802 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
2803 return true;
2804 }
2805 break;
2806 }
2807 return false;
2808}
2809
2810// Return true if this instruction simply renames a general register without
2811// modifying bits.
2813 switch (MI.getOpcode()) {
2814 default:
2815 break;
2816 case TargetOpcode::COPY: {
2817 Register DstReg = MI.getOperand(0).getReg();
2818 return AArch64::FPR128RegClass.contains(DstReg);
2819 }
2820 case AArch64::ORRv16i8:
2821 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
2822 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
2823 "invalid ORRv16i8 operands");
2824 return true;
2825 }
2826 break;
2827 }
2828 return false;
2829}
2830
2831static bool isFrameLoadOpcode(int Opcode) {
2832 switch (Opcode) {
2833 default:
2834 return false;
2835 case AArch64::LDRWui:
2836 case AArch64::LDRXui:
2837 case AArch64::LDRBui:
2838 case AArch64::LDRHui:
2839 case AArch64::LDRSui:
2840 case AArch64::LDRDui:
2841 case AArch64::LDRQui:
2842 case AArch64::LDR_PXI:
2843 return true;
2844 }
2845}
2846
2848 int &FrameIndex) const {
2849 if (!isFrameLoadOpcode(MI.getOpcode()))
2850 return Register();
2851
2852 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2853 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2854 FrameIndex = MI.getOperand(1).getIndex();
2855 return MI.getOperand(0).getReg();
2856 }
2857 return Register();
2858}
2859
2860static bool isFrameStoreOpcode(int Opcode) {
2861 switch (Opcode) {
2862 default:
2863 return false;
2864 case AArch64::STRWui:
2865 case AArch64::STRXui:
2866 case AArch64::STRBui:
2867 case AArch64::STRHui:
2868 case AArch64::STRSui:
2869 case AArch64::STRDui:
2870 case AArch64::STRQui:
2871 case AArch64::STR_PXI:
2872 return true;
2873 }
2874}
2875
2877 int &FrameIndex) const {
2878 if (!isFrameStoreOpcode(MI.getOpcode()))
2879 return Register();
2880
2881 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2882 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2883 FrameIndex = MI.getOperand(1).getIndex();
2884 return MI.getOperand(0).getReg();
2885 }
2886 return Register();
2887}
2888
2890 int &FrameIndex) const {
2891 if (!isFrameStoreOpcode(MI.getOpcode()))
2892 return Register();
2893
2894 if (Register Reg = isStoreToStackSlot(MI, FrameIndex))
2895 return Reg;
2896
2898 if (hasStoreToStackSlot(MI, Accesses)) {
2899 if (Accesses.size() > 1)
2900 return Register();
2901
2902 FrameIndex =
2903 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2904 ->getFrameIndex();
2905 return MI.getOperand(0).getReg();
2906 }
2907 return Register();
2908}
2909
2911 int &FrameIndex) const {
2912 if (!isFrameLoadOpcode(MI.getOpcode()))
2913 return Register();
2914
2915 if (Register Reg = isLoadFromStackSlot(MI, FrameIndex))
2916 return Reg;
2917
2919 if (hasLoadFromStackSlot(MI, Accesses)) {
2920 if (Accesses.size() > 1)
2921 return Register();
2922
2923 FrameIndex =
2924 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2925 ->getFrameIndex();
2926 return MI.getOperand(0).getReg();
2927 }
2928 return Register();
2929}
2930
2931/// Check all MachineMemOperands for a hint to suppress pairing.
2933 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2934 return MMO->getFlags() & MOSuppressPair;
2935 });
2936}
2937
2938/// Set a flag on the first MachineMemOperand to suppress pairing.
2940 if (MI.memoperands_empty())
2941 return;
2942 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
2943}
2944
2945/// Check all MachineMemOperands for a hint that the load/store is strided.
2947 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2948 return MMO->getFlags() & MOStridedAccess;
2949 });
2950}
2951
2953 switch (Opc) {
2954 default:
2955 return false;
2956 case AArch64::STURSi:
2957 case AArch64::STRSpre:
2958 case AArch64::STURDi:
2959 case AArch64::STRDpre:
2960 case AArch64::STURQi:
2961 case AArch64::STRQpre:
2962 case AArch64::STURBBi:
2963 case AArch64::STURHHi:
2964 case AArch64::STURWi:
2965 case AArch64::STRWpre:
2966 case AArch64::STURXi:
2967 case AArch64::STRXpre:
2968 case AArch64::LDURSi:
2969 case AArch64::LDRSpre:
2970 case AArch64::LDURDi:
2971 case AArch64::LDRDpre:
2972 case AArch64::LDURQi:
2973 case AArch64::LDRQpre:
2974 case AArch64::LDURWi:
2975 case AArch64::LDRWpre:
2976 case AArch64::LDURXi:
2977 case AArch64::LDRXpre:
2978 case AArch64::LDRSWpre:
2979 case AArch64::LDURSWi:
2980 case AArch64::LDURHHi:
2981 case AArch64::LDURBBi:
2982 case AArch64::LDURSBWi:
2983 case AArch64::LDURSHWi:
2984 return true;
2985 }
2986}
2987
2988std::optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) {
2989 switch (Opc) {
2990 default: return {};
2991 case AArch64::PRFMui: return AArch64::PRFUMi;
2992 case AArch64::LDRXui: return AArch64::LDURXi;
2993 case AArch64::LDRWui: return AArch64::LDURWi;
2994 case AArch64::LDRBui: return AArch64::LDURBi;
2995 case AArch64::LDRHui: return AArch64::LDURHi;
2996 case AArch64::LDRSui: return AArch64::LDURSi;
2997 case AArch64::LDRDui: return AArch64::LDURDi;
2998 case AArch64::LDRQui: return AArch64::LDURQi;
2999 case AArch64::LDRBBui: return AArch64::LDURBBi;
3000 case AArch64::LDRHHui: return AArch64::LDURHHi;
3001 case AArch64::LDRSBXui: return AArch64::LDURSBXi;
3002 case AArch64::LDRSBWui: return AArch64::LDURSBWi;
3003 case AArch64::LDRSHXui: return AArch64::LDURSHXi;
3004 case AArch64::LDRSHWui: return AArch64::LDURSHWi;
3005 case AArch64::LDRSWui: return AArch64::LDURSWi;
3006 case AArch64::STRXui: return AArch64::STURXi;
3007 case AArch64::STRWui: return AArch64::STURWi;
3008 case AArch64::STRBui: return AArch64::STURBi;
3009 case AArch64::STRHui: return AArch64::STURHi;
3010 case AArch64::STRSui: return AArch64::STURSi;
3011 case AArch64::STRDui: return AArch64::STURDi;
3012 case AArch64::STRQui: return AArch64::STURQi;
3013 case AArch64::STRBBui: return AArch64::STURBBi;
3014 case AArch64::STRHHui: return AArch64::STURHHi;
3015 }
3016}
3017
3019 switch (Opc) {
3020 default:
3021 llvm_unreachable("Unhandled Opcode in getLoadStoreImmIdx");
3022 case AArch64::ADDG:
3023 case AArch64::LDAPURBi:
3024 case AArch64::LDAPURHi:
3025 case AArch64::LDAPURi:
3026 case AArch64::LDAPURSBWi:
3027 case AArch64::LDAPURSBXi:
3028 case AArch64::LDAPURSHWi:
3029 case AArch64::LDAPURSHXi:
3030 case AArch64::LDAPURSWi:
3031 case AArch64::LDAPURXi:
3032 case AArch64::LDR_PPXI:
3033 case AArch64::LDR_PXI:
3034 case AArch64::LDR_ZXI:
3035 case AArch64::LDR_ZZXI:
3036 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3037 case AArch64::LDR_ZZZXI:
3038 case AArch64::LDR_ZZZZXI:
3039 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3040 case AArch64::LDRBBui:
3041 case AArch64::LDRBui:
3042 case AArch64::LDRDui:
3043 case AArch64::LDRHHui:
3044 case AArch64::LDRHui:
3045 case AArch64::LDRQui:
3046 case AArch64::LDRSBWui:
3047 case AArch64::LDRSBXui:
3048 case AArch64::LDRSHWui:
3049 case AArch64::LDRSHXui:
3050 case AArch64::LDRSui:
3051 case AArch64::LDRSWui:
3052 case AArch64::LDRWui:
3053 case AArch64::LDRXui:
3054 case AArch64::LDURBBi:
3055 case AArch64::LDURBi:
3056 case AArch64::LDURDi:
3057 case AArch64::LDURHHi:
3058 case AArch64::LDURHi:
3059 case AArch64::LDURQi:
3060 case AArch64::LDURSBWi:
3061 case AArch64::LDURSBXi:
3062 case AArch64::LDURSHWi:
3063 case AArch64::LDURSHXi:
3064 case AArch64::LDURSi:
3065 case AArch64::LDURSWi:
3066 case AArch64::LDURWi:
3067 case AArch64::LDURXi:
3068 case AArch64::PRFMui:
3069 case AArch64::PRFUMi:
3070 case AArch64::ST2Gi:
3071 case AArch64::STGi:
3072 case AArch64::STLURBi:
3073 case AArch64::STLURHi:
3074 case AArch64::STLURWi:
3075 case AArch64::STLURXi:
3076 case AArch64::StoreSwiftAsyncContext:
3077 case AArch64::STR_PPXI:
3078 case AArch64::STR_PXI:
3079 case AArch64::STR_ZXI:
3080 case AArch64::STR_ZZXI:
3081 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3082 case AArch64::STR_ZZZXI:
3083 case AArch64::STR_ZZZZXI:
3084 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3085 case AArch64::STRBBui:
3086 case AArch64::STRBui:
3087 case AArch64::STRDui:
3088 case AArch64::STRHHui:
3089 case AArch64::STRHui:
3090 case AArch64::STRQui:
3091 case AArch64::STRSui:
3092 case AArch64::STRWui:
3093 case AArch64::STRXui:
3094 case AArch64::STURBBi:
3095 case AArch64::STURBi:
3096 case AArch64::STURDi:
3097 case AArch64::STURHHi:
3098 case AArch64::STURHi:
3099 case AArch64::STURQi:
3100 case AArch64::STURSi:
3101 case AArch64::STURWi:
3102 case AArch64::STURXi:
3103 case AArch64::STZ2Gi:
3104 case AArch64::STZGi:
3105 case AArch64::TAGPstack:
3106 return 2;
3107 case AArch64::LD1B_D_IMM:
3108 case AArch64::LD1B_H_IMM:
3109 case AArch64::LD1B_IMM:
3110 case AArch64::LD1B_S_IMM:
3111 case AArch64::LD1D_IMM:
3112 case AArch64::LD1H_D_IMM:
3113 case AArch64::LD1H_IMM:
3114 case AArch64::LD1H_S_IMM:
3115 case AArch64::LD1RB_D_IMM:
3116 case AArch64::LD1RB_H_IMM:
3117 case AArch64::LD1RB_IMM:
3118 case AArch64::LD1RB_S_IMM:
3119 case AArch64::LD1RD_IMM:
3120 case AArch64::LD1RH_D_IMM:
3121 case AArch64::LD1RH_IMM:
3122 case AArch64::LD1RH_S_IMM:
3123 case AArch64::LD1RSB_D_IMM:
3124 case AArch64::LD1RSB_H_IMM:
3125 case AArch64::LD1RSB_S_IMM:
3126 case AArch64::LD1RSH_D_IMM:
3127 case AArch64::LD1RSH_S_IMM:
3128 case AArch64::LD1RSW_IMM:
3129 case AArch64::LD1RW_D_IMM:
3130 case AArch64::LD1RW_IMM:
3131 case AArch64::LD1SB_D_IMM:
3132 case AArch64::LD1SB_H_IMM:
3133 case AArch64::LD1SB_S_IMM:
3134 case AArch64::LD1SH_D_IMM:
3135 case AArch64::LD1SH_S_IMM:
3136 case AArch64::LD1SW_D_IMM:
3137 case AArch64::LD1W_D_IMM:
3138 case AArch64::LD1W_IMM:
3139 case AArch64::LD2B_IMM:
3140 case AArch64::LD2D_IMM:
3141 case AArch64::LD2H_IMM:
3142 case AArch64::LD2W_IMM:
3143 case AArch64::LD3B_IMM:
3144 case AArch64::LD3D_IMM:
3145 case AArch64::LD3H_IMM:
3146 case AArch64::LD3W_IMM:
3147 case AArch64::LD4B_IMM:
3148 case AArch64::LD4D_IMM:
3149 case AArch64::LD4H_IMM:
3150 case AArch64::LD4W_IMM:
3151 case AArch64::LDG:
3152 case AArch64::LDNF1B_D_IMM:
3153 case AArch64::LDNF1B_H_IMM:
3154 case AArch64::LDNF1B_IMM:
3155 case AArch64::LDNF1B_S_IMM:
3156 case AArch64::LDNF1D_IMM:
3157 case AArch64::LDNF1H_D_IMM:
3158 case AArch64::LDNF1H_IMM:
3159 case AArch64::LDNF1H_S_IMM:
3160 case AArch64::LDNF1SB_D_IMM:
3161 case AArch64::LDNF1SB_H_IMM:
3162 case AArch64::LDNF1SB_S_IMM:
3163 case AArch64::LDNF1SH_D_IMM:
3164 case AArch64::LDNF1SH_S_IMM:
3165 case AArch64::LDNF1SW_D_IMM:
3166 case AArch64::LDNF1W_D_IMM:
3167 case AArch64::LDNF1W_IMM:
3168 case AArch64::LDNPDi:
3169 case AArch64::LDNPQi:
3170 case AArch64::LDNPSi:
3171 case AArch64::LDNPWi:
3172 case AArch64::LDNPXi:
3173 case AArch64::LDNT1B_ZRI:
3174 case AArch64::LDNT1D_ZRI:
3175 case AArch64::LDNT1H_ZRI:
3176 case AArch64::LDNT1W_ZRI:
3177 case AArch64::LDPDi:
3178 case AArch64::LDPQi:
3179 case AArch64::LDPSi:
3180 case AArch64::LDPWi:
3181 case AArch64::LDPXi:
3182 case AArch64::LDRBBpost:
3183 case AArch64::LDRBBpre:
3184 case AArch64::LDRBpost:
3185 case AArch64::LDRBpre:
3186 case AArch64::LDRDpost:
3187 case AArch64::LDRDpre:
3188 case AArch64::LDRHHpost:
3189 case AArch64::LDRHHpre:
3190 case AArch64::LDRHpost:
3191 case AArch64::LDRHpre:
3192 case AArch64::LDRQpost:
3193 case AArch64::LDRQpre:
3194 case AArch64::LDRSpost:
3195 case AArch64::LDRSpre:
3196 case AArch64::LDRWpost:
3197 case AArch64::LDRWpre:
3198 case AArch64::LDRXpost:
3199 case AArch64::LDRXpre:
3200 case AArch64::ST1B_D_IMM:
3201 case AArch64::ST1B_H_IMM:
3202 case AArch64::ST1B_IMM:
3203 case AArch64::ST1B_S_IMM:
3204 case AArch64::ST1D_IMM:
3205 case AArch64::ST1H_D_IMM:
3206 case AArch64::ST1H_IMM:
3207 case AArch64::ST1H_S_IMM:
3208 case AArch64::ST1W_D_IMM:
3209 case AArch64::ST1W_IMM:
3210 case AArch64::ST2B_IMM:
3211 case AArch64::ST2D_IMM:
3212 case AArch64::ST2H_IMM:
3213 case AArch64::ST2W_IMM:
3214 case AArch64::ST3B_IMM:
3215 case AArch64::ST3D_IMM:
3216 case AArch64::ST3H_IMM:
3217 case AArch64::ST3W_IMM:
3218 case AArch64::ST4B_IMM:
3219 case AArch64::ST4D_IMM:
3220 case AArch64::ST4H_IMM:
3221 case AArch64::ST4W_IMM:
3222 case AArch64::STGPi:
3223 case AArch64::STGPreIndex:
3224 case AArch64::STZGPreIndex:
3225 case AArch64::ST2GPreIndex:
3226 case AArch64::STZ2GPreIndex:
3227 case AArch64::STGPostIndex:
3228 case AArch64::STZGPostIndex:
3229 case AArch64::ST2GPostIndex:
3230 case AArch64::STZ2GPostIndex:
3231 case AArch64::STNPDi:
3232 case AArch64::STNPQi:
3233 case AArch64::STNPSi:
3234 case AArch64::STNPWi:
3235 case AArch64::STNPXi:
3236 case AArch64::STNT1B_ZRI:
3237 case AArch64::STNT1D_ZRI:
3238 case AArch64::STNT1H_ZRI:
3239 case AArch64::STNT1W_ZRI:
3240 case AArch64::STPDi:
3241 case AArch64::STPQi:
3242 case AArch64::STPSi:
3243 case AArch64::STPWi:
3244 case AArch64::STPXi:
3245 case AArch64::STRBBpost:
3246 case AArch64::STRBBpre:
3247 case AArch64::STRBpost:
3248 case AArch64::STRBpre:
3249 case AArch64::STRDpost:
3250 case AArch64::STRDpre:
3251 case AArch64::STRHHpost:
3252 case AArch64::STRHHpre:
3253 case AArch64::STRHpost:
3254 case AArch64::STRHpre:
3255 case AArch64::STRQpost:
3256 case AArch64::STRQpre:
3257 case AArch64::STRSpost:
3258 case AArch64::STRSpre:
3259 case AArch64::STRWpost:
3260 case AArch64::STRWpre:
3261 case AArch64::STRXpost:
3262 case AArch64::STRXpre:
3263 case AArch64::LD1B_2Z_IMM:
3264 case AArch64::LD1B_2Z_STRIDED_IMM:
3265 case AArch64::LD1H_2Z_IMM:
3266 case AArch64::LD1H_2Z_STRIDED_IMM:
3267 case AArch64::LD1W_2Z_IMM:
3268 case AArch64::LD1W_2Z_STRIDED_IMM:
3269 case AArch64::LD1D_2Z_IMM:
3270 case AArch64::LD1D_2Z_STRIDED_IMM:
3271 case AArch64::LD1B_4Z_IMM:
3272 case AArch64::LD1B_4Z_STRIDED_IMM:
3273 case AArch64::LD1H_4Z_IMM:
3274 case AArch64::LD1H_4Z_STRIDED_IMM:
3275 case AArch64::LD1W_4Z_IMM:
3276 case AArch64::LD1W_4Z_STRIDED_IMM:
3277 case AArch64::LD1D_4Z_IMM:
3278 case AArch64::LD1D_4Z_STRIDED_IMM:
3279 case AArch64::LD1B_2Z_IMM_PSEUDO:
3280 case AArch64::LD1H_2Z_IMM_PSEUDO:
3281 case AArch64::LD1W_2Z_IMM_PSEUDO:
3282 case AArch64::LD1D_2Z_IMM_PSEUDO:
3283 case AArch64::LD1B_4Z_IMM_PSEUDO:
3284 case AArch64::LD1H_4Z_IMM_PSEUDO:
3285 case AArch64::LD1W_4Z_IMM_PSEUDO:
3286 case AArch64::LD1D_4Z_IMM_PSEUDO:
3287 case AArch64::ST1B_2Z_IMM:
3288 case AArch64::ST1B_2Z_STRIDED_IMM:
3289 case AArch64::ST1H_2Z_IMM:
3290 case AArch64::ST1H_2Z_STRIDED_IMM:
3291 case AArch64::ST1W_2Z_IMM:
3292 case AArch64::ST1W_2Z_STRIDED_IMM:
3293 case AArch64::ST1D_2Z_IMM:
3294 case AArch64::ST1D_2Z_STRIDED_IMM:
3295 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3296 case AArch64::LDNT1B_2Z_IMM:
3297 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3298 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3299 case AArch64::LDNT1H_2Z_IMM:
3300 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3301 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3302 case AArch64::LDNT1W_2Z_IMM:
3303 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3304 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3305 case AArch64::LDNT1D_2Z_IMM:
3306 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3307 case AArch64::STNT1B_2Z_IMM:
3308 case AArch64::STNT1B_2Z_STRIDED_IMM:
3309 case AArch64::STNT1H_2Z_IMM:
3310 case AArch64::STNT1H_2Z_STRIDED_IMM:
3311 case AArch64::STNT1W_2Z_IMM:
3312 case AArch64::STNT1W_2Z_STRIDED_IMM:
3313 case AArch64::STNT1D_2Z_IMM:
3314 case AArch64::STNT1D_2Z_STRIDED_IMM:
3315 case AArch64::ST1B_2Z_IMM_PSEUDO:
3316 case AArch64::ST1H_2Z_IMM_PSEUDO:
3317 case AArch64::ST1W_2Z_IMM_PSEUDO:
3318 case AArch64::ST1D_2Z_IMM_PSEUDO:
3319 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3320 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3321 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3322 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3323 case AArch64::ST1B_4Z_IMM:
3324 case AArch64::ST1B_4Z_STRIDED_IMM:
3325 case AArch64::ST1H_4Z_IMM:
3326 case AArch64::ST1H_4Z_STRIDED_IMM:
3327 case AArch64::ST1W_4Z_IMM:
3328 case AArch64::ST1W_4Z_STRIDED_IMM:
3329 case AArch64::ST1D_4Z_IMM:
3330 case AArch64::ST1D_4Z_STRIDED_IMM:
3331 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3332 case AArch64::LDNT1B_4Z_IMM:
3333 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3334 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3335 case AArch64::LDNT1H_4Z_IMM:
3336 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3337 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3338 case AArch64::LDNT1W_4Z_IMM:
3339 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3340 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3341 case AArch64::LDNT1D_4Z_IMM:
3342 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3343 case AArch64::STNT1B_4Z_IMM:
3344 case AArch64::STNT1B_4Z_STRIDED_IMM:
3345 case AArch64::STNT1H_4Z_IMM:
3346 case AArch64::STNT1H_4Z_STRIDED_IMM:
3347 case AArch64::STNT1W_4Z_IMM:
3348 case AArch64::STNT1W_4Z_STRIDED_IMM:
3349 case AArch64::STNT1D_4Z_IMM:
3350 case AArch64::STNT1D_4Z_STRIDED_IMM:
3351 case AArch64::ST1B_4Z_IMM_PSEUDO:
3352 case AArch64::ST1H_4Z_IMM_PSEUDO:
3353 case AArch64::ST1W_4Z_IMM_PSEUDO:
3354 case AArch64::ST1D_4Z_IMM_PSEUDO:
3355 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3356 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3357 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3358 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3359 return 3;
3360 case AArch64::LDPDpost:
3361 case AArch64::LDPDpre:
3362 case AArch64::LDPQpost:
3363 case AArch64::LDPQpre:
3364 case AArch64::LDPSpost:
3365 case AArch64::LDPSpre:
3366 case AArch64::LDPWpost:
3367 case AArch64::LDPWpre:
3368 case AArch64::LDPXpost:
3369 case AArch64::LDPXpre:
3370 case AArch64::STGPpre:
3371 case AArch64::STGPpost:
3372 case AArch64::STPDpost:
3373 case AArch64::STPDpre:
3374 case AArch64::STPQpost:
3375 case AArch64::STPQpre:
3376 case AArch64::STPSpost:
3377 case AArch64::STPSpre:
3378 case AArch64::STPWpost:
3379 case AArch64::STPWpre:
3380 case AArch64::STPXpost:
3381 case AArch64::STPXpre:
3382 return 4;
3383 }
3384}
3385
3387 switch (MI.getOpcode()) {
3388 default:
3389 return false;
3390 // Scaled instructions.
3391 case AArch64::STRSui:
3392 case AArch64::STRDui:
3393 case AArch64::STRQui:
3394 case AArch64::STRXui:
3395 case AArch64::STRWui:
3396 case AArch64::LDRSui:
3397 case AArch64::LDRDui:
3398 case AArch64::LDRQui:
3399 case AArch64::LDRXui:
3400 case AArch64::LDRWui:
3401 case AArch64::LDRSWui:
3402 // Unscaled instructions.
3403 case AArch64::STURSi:
3404 case AArch64::STRSpre:
3405 case AArch64::STURDi:
3406 case AArch64::STRDpre:
3407 case AArch64::STURQi:
3408 case AArch64::STRQpre:
3409 case AArch64::STURWi:
3410 case AArch64::STRWpre:
3411 case AArch64::STURXi:
3412 case AArch64::STRXpre:
3413 case AArch64::LDURSi:
3414 case AArch64::LDRSpre:
3415 case AArch64::LDURDi:
3416 case AArch64::LDRDpre:
3417 case AArch64::LDURQi:
3418 case AArch64::LDRQpre:
3419 case AArch64::LDURWi:
3420 case AArch64::LDRWpre:
3421 case AArch64::LDURXi:
3422 case AArch64::LDRXpre:
3423 case AArch64::LDURSWi:
3424 case AArch64::LDRSWpre:
3425 // SVE instructions.
3426 case AArch64::LDR_ZXI:
3427 case AArch64::STR_ZXI:
3428 return true;
3429 }
3430}
3431
3433 switch (MI.getOpcode()) {
3434 default:
3435 assert((!MI.isCall() || !MI.isReturn()) &&
3436 "Unexpected instruction - was a new tail call opcode introduced?");
3437 return false;
3438 case AArch64::TCRETURNdi:
3439 case AArch64::TCRETURNri:
3440 case AArch64::TCRETURNrix16x17:
3441 case AArch64::TCRETURNrix17:
3442 case AArch64::TCRETURNrinotx16:
3443 case AArch64::TCRETURNriALL:
3444 case AArch64::AUTH_TCRETURN:
3445 case AArch64::AUTH_TCRETURN_BTI:
3446 return true;
3447 }
3448}
3449
3451 switch (Opc) {
3452 default:
3453 llvm_unreachable("Opcode has no flag setting equivalent!");
3454 // 32-bit cases:
3455 case AArch64::ADDWri:
3456 return AArch64::ADDSWri;
3457 case AArch64::ADDWrr:
3458 return AArch64::ADDSWrr;
3459 case AArch64::ADDWrs:
3460 return AArch64::ADDSWrs;
3461 case AArch64::ADDWrx:
3462 return AArch64::ADDSWrx;
3463 case AArch64::ANDWri:
3464 return AArch64::ANDSWri;
3465 case AArch64::ANDWrr:
3466 return AArch64::ANDSWrr;
3467 case AArch64::ANDWrs:
3468 return AArch64::ANDSWrs;
3469 case AArch64::BICWrr:
3470 return AArch64::BICSWrr;
3471 case AArch64::BICWrs:
3472 return AArch64::BICSWrs;
3473 case AArch64::SUBWri:
3474 return AArch64::SUBSWri;
3475 case AArch64::SUBWrr:
3476 return AArch64::SUBSWrr;
3477 case AArch64::SUBWrs:
3478 return AArch64::SUBSWrs;
3479 case AArch64::SUBWrx:
3480 return AArch64::SUBSWrx;
3481 // 64-bit cases:
3482 case AArch64::ADDXri:
3483 return AArch64::ADDSXri;
3484 case AArch64::ADDXrr:
3485 return AArch64::ADDSXrr;
3486 case AArch64::ADDXrs:
3487 return AArch64::ADDSXrs;
3488 case AArch64::ADDXrx:
3489 return AArch64::ADDSXrx;
3490 case AArch64::ANDXri:
3491 return AArch64::ANDSXri;
3492 case AArch64::ANDXrr:
3493 return AArch64::ANDSXrr;
3494 case AArch64::ANDXrs:
3495 return AArch64::ANDSXrs;
3496 case AArch64::BICXrr:
3497 return AArch64::BICSXrr;
3498 case AArch64::BICXrs:
3499 return AArch64::BICSXrs;
3500 case AArch64::SUBXri:
3501 return AArch64::SUBSXri;
3502 case AArch64::SUBXrr:
3503 return AArch64::SUBSXrr;
3504 case AArch64::SUBXrs:
3505 return AArch64::SUBSXrs;
3506 case AArch64::SUBXrx:
3507 return AArch64::SUBSXrx;
3508 // SVE instructions:
3509 case AArch64::AND_PPzPP:
3510 return AArch64::ANDS_PPzPP;
3511 case AArch64::BIC_PPzPP:
3512 return AArch64::BICS_PPzPP;
3513 case AArch64::EOR_PPzPP:
3514 return AArch64::EORS_PPzPP;
3515 case AArch64::NAND_PPzPP:
3516 return AArch64::NANDS_PPzPP;
3517 case AArch64::NOR_PPzPP:
3518 return AArch64::NORS_PPzPP;
3519 case AArch64::ORN_PPzPP:
3520 return AArch64::ORNS_PPzPP;
3521 case AArch64::ORR_PPzPP:
3522 return AArch64::ORRS_PPzPP;
3523 case AArch64::BRKA_PPzP:
3524 return AArch64::BRKAS_PPzP;
3525 case AArch64::BRKPA_PPzPP:
3526 return AArch64::BRKPAS_PPzPP;
3527 case AArch64::BRKB_PPzP:
3528 return AArch64::BRKBS_PPzP;
3529 case AArch64::BRKPB_PPzPP:
3530 return AArch64::BRKPBS_PPzPP;
3531 case AArch64::BRKN_PPzP:
3532 return AArch64::BRKNS_PPzP;
3533 case AArch64::RDFFR_PPz:
3534 return AArch64::RDFFRS_PPz;
3535 case AArch64::PTRUE_B:
3536 return AArch64::PTRUES_B;
3537 }
3538}
3539
3540// Is this a candidate for ld/st merging or pairing? For example, we don't
3541// touch volatiles or load/stores that have a hint to avoid pair formation.
3543
3544 bool IsPreLdSt = isPreLdSt(MI);
3545
3546 // If this is a volatile load/store, don't mess with it.
3547 if (MI.hasOrderedMemoryRef())
3548 return false;
3549
3550 // Make sure this is a reg/fi+imm (as opposed to an address reloc).
3551 // For Pre-inc LD/ST, the operand is shifted by one.
3552 assert((MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3553 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3554 "Expected a reg or frame index operand.");
3555
3556 // For Pre-indexed addressing quadword instructions, the third operand is the
3557 // immediate value.
3558 bool IsImmPreLdSt = IsPreLdSt && MI.getOperand(3).isImm();
3559
3560 if (!MI.getOperand(2).isImm() && !IsImmPreLdSt)
3561 return false;
3562
3563 // Can't merge/pair if the instruction modifies the base register.
3564 // e.g., ldr x0, [x0]
3565 // This case will never occur with an FI base.
3566 // However, if the instruction is an LDR<S,D,Q,W,X,SW>pre or
3567 // STR<S,D,Q,W,X>pre, it can be merged.
3568 // For example:
3569 // ldr q0, [x11, #32]!
3570 // ldr q1, [x11, #16]
3571 // to
3572 // ldp q0, q1, [x11, #32]!
3573 if (MI.getOperand(1).isReg() && !IsPreLdSt) {
3574 Register BaseReg = MI.getOperand(1).getReg();
3576 if (MI.modifiesRegister(BaseReg, TRI))
3577 return false;
3578 }
3579
3580 // Pairing SVE fills/spills is only valid for little-endian targets that
3581 // implement VLS 128.
3582 switch (MI.getOpcode()) {
3583 default:
3584 break;
3585 case AArch64::LDR_ZXI:
3586 case AArch64::STR_ZXI:
3587 if (!Subtarget.isLittleEndian() ||
3588 Subtarget.getSVEVectorSizeInBits() != 128)
3589 return false;
3590 }
3591
3592 // Check if this load/store has a hint to avoid pair formation.
3593 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
3595 return false;
3596
3597 // Do not pair any callee-save store/reload instructions in the
3598 // prologue/epilogue if the CFI information encoded the operations as separate
3599 // instructions, as that will cause the size of the actual prologue to mismatch
3600 // with the prologue size recorded in the Windows CFI.
3601 const MCAsmInfo &MAI = MI.getMF()->getTarget().getMCAsmInfo();
3602 bool NeedsWinCFI =
3603 MAI.usesWindowsCFI() && MI.getMF()->getFunction().needsUnwindTableEntry();
3604 if (NeedsWinCFI && (MI.getFlag(MachineInstr::FrameSetup) ||
3606 return false;
3607
3608 // On some CPUs quad load/store pairs are slower than two single load/stores.
3609 if (Subtarget.isPaired128Slow()) {
3610 switch (MI.getOpcode()) {
3611 default:
3612 break;
3613 case AArch64::LDURQi:
3614 case AArch64::STURQi:
3615 case AArch64::LDRQui:
3616 case AArch64::STRQui:
3617 return false;
3618 }
3619 }
3620
3621 return true;
3622}
3623
3626 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
3627 const TargetRegisterInfo *TRI) const {
3628 if (!LdSt.mayLoadOrStore())
3629 return false;
3630
3631 const MachineOperand *BaseOp;
3632 TypeSize WidthN(0, false);
3633 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, OffsetIsScalable,
3634 WidthN, TRI))
3635 return false;
3636 // The maximum vscale is 16 under AArch64, return the maximal extent for the
3637 // vector.
3638 Width = LocationSize::precise(WidthN);
3639 BaseOps.push_back(BaseOp);
3640 return true;
3641}
3642
3643std::optional<ExtAddrMode>
3645 const TargetRegisterInfo *TRI) const {
3646 const MachineOperand *Base; // Filled with the base operand of MI.
3647 int64_t Offset; // Filled with the offset of MI.
3648 bool OffsetIsScalable;
3649 if (!getMemOperandWithOffset(MemI, Base, Offset, OffsetIsScalable, TRI))
3650 return std::nullopt;
3651
3652 if (!Base->isReg())
3653 return std::nullopt;
3654 ExtAddrMode AM;
3655 AM.BaseReg = Base->getReg();
3656 AM.Displacement = Offset;
3657 AM.ScaledReg = 0;
3658 AM.Scale = 0;
3659 return AM;
3660}
3661
3663 Register Reg,
3664 const MachineInstr &AddrI,
3665 ExtAddrMode &AM) const {
3666 // Filter out instructions into which we cannot fold.
3667 unsigned NumBytes;
3668 int64_t OffsetScale = 1;
3669 switch (MemI.getOpcode()) {
3670 default:
3671 return false;
3672
3673 case AArch64::LDURQi:
3674 case AArch64::STURQi:
3675 NumBytes = 16;
3676 break;
3677
3678 case AArch64::LDURDi:
3679 case AArch64::STURDi:
3680 case AArch64::LDURXi:
3681 case AArch64::STURXi:
3682 NumBytes = 8;
3683 break;
3684
3685 case AArch64::LDURWi:
3686 case AArch64::LDURSWi:
3687 case AArch64::STURWi:
3688 NumBytes = 4;
3689 break;
3690
3691 case AArch64::LDURHi:
3692 case AArch64::STURHi:
3693 case AArch64::LDURHHi:
3694 case AArch64::STURHHi:
3695 case AArch64::LDURSHXi:
3696 case AArch64::LDURSHWi:
3697 NumBytes = 2;
3698 break;
3699
3700 case AArch64::LDRBroX:
3701 case AArch64::LDRBBroX:
3702 case AArch64::LDRSBXroX:
3703 case AArch64::LDRSBWroX:
3704 case AArch64::STRBroX:
3705 case AArch64::STRBBroX:
3706 case AArch64::LDURBi:
3707 case AArch64::LDURBBi:
3708 case AArch64::LDURSBXi:
3709 case AArch64::LDURSBWi:
3710 case AArch64::STURBi:
3711 case AArch64::STURBBi:
3712 case AArch64::LDRBui:
3713 case AArch64::LDRBBui:
3714 case AArch64::LDRSBXui:
3715 case AArch64::LDRSBWui:
3716 case AArch64::STRBui:
3717 case AArch64::STRBBui:
3718 NumBytes = 1;
3719 break;
3720
3721 case AArch64::LDRQroX:
3722 case AArch64::STRQroX:
3723 case AArch64::LDRQui:
3724 case AArch64::STRQui:
3725 NumBytes = 16;
3726 OffsetScale = 16;
3727 break;
3728
3729 case AArch64::LDRDroX:
3730 case AArch64::STRDroX:
3731 case AArch64::LDRXroX:
3732 case AArch64::STRXroX:
3733 case AArch64::LDRDui:
3734 case AArch64::STRDui:
3735 case AArch64::LDRXui:
3736 case AArch64::STRXui:
3737 NumBytes = 8;
3738 OffsetScale = 8;
3739 break;
3740
3741 case AArch64::LDRWroX:
3742 case AArch64::LDRSWroX:
3743 case AArch64::STRWroX:
3744 case AArch64::LDRWui:
3745 case AArch64::LDRSWui:
3746 case AArch64::STRWui:
3747 NumBytes = 4;
3748 OffsetScale = 4;
3749 break;
3750
3751 case AArch64::LDRHroX:
3752 case AArch64::STRHroX:
3753 case AArch64::LDRHHroX:
3754 case AArch64::STRHHroX:
3755 case AArch64::LDRSHXroX:
3756 case AArch64::LDRSHWroX:
3757 case AArch64::LDRHui:
3758 case AArch64::STRHui:
3759 case AArch64::LDRHHui:
3760 case AArch64::STRHHui:
3761 case AArch64::LDRSHXui:
3762 case AArch64::LDRSHWui:
3763 NumBytes = 2;
3764 OffsetScale = 2;
3765 break;
3766 }
3767
3768 // Check the fold operand is not the loaded/stored value.
3769 const MachineOperand &BaseRegOp = MemI.getOperand(0);
3770 if (BaseRegOp.isReg() && BaseRegOp.getReg() == Reg)
3771 return false;
3772
3773 // Handle memory instructions with a [Reg, Reg] addressing mode.
3774 if (MemI.getOperand(2).isReg()) {
3775 // Bail if the addressing mode already includes extension of the offset
3776 // register.
3777 if (MemI.getOperand(3).getImm())
3778 return false;
3779
3780 // Check if we actually have a scaled offset.
3781 if (MemI.getOperand(4).getImm() == 0)
3782 OffsetScale = 1;
3783
3784 // If the address instructions is folded into the base register, then the
3785 // addressing mode must not have a scale. Then we can swap the base and the
3786 // scaled registers.
3787 if (MemI.getOperand(1).getReg() == Reg && OffsetScale != 1)
3788 return false;
3789
3790 switch (AddrI.getOpcode()) {
3791 default:
3792 return false;
3793
3794 case AArch64::SBFMXri:
3795 // sxtw Xa, Wm
3796 // ldr Xd, [Xn, Xa, lsl #N]
3797 // ->
3798 // ldr Xd, [Xn, Wm, sxtw #N]
3799 if (AddrI.getOperand(2).getImm() != 0 ||
3800 AddrI.getOperand(3).getImm() != 31)
3801 return false;
3802
3803 AM.BaseReg = MemI.getOperand(1).getReg();
3804 if (AM.BaseReg == Reg)
3805 AM.BaseReg = MemI.getOperand(2).getReg();
3806 AM.ScaledReg = AddrI.getOperand(1).getReg();
3807 AM.Scale = OffsetScale;
3808 AM.Displacement = 0;
3810 return true;
3811
3812 case TargetOpcode::SUBREG_TO_REG: {
3813 // mov Wa, Wm
3814 // ldr Xd, [Xn, Xa, lsl #N]
3815 // ->
3816 // ldr Xd, [Xn, Wm, uxtw #N]
3817
3818 // Zero-extension looks like an ORRWrs followed by a SUBREG_TO_REG.
3819 if (AddrI.getOperand(2).getImm() != AArch64::sub_32)
3820 return false;
3821
3822 const MachineRegisterInfo &MRI = AddrI.getMF()->getRegInfo();
3823 Register OffsetReg = AddrI.getOperand(1).getReg();
3824 if (!OffsetReg.isVirtual() || !MRI.hasOneNonDBGUse(OffsetReg))
3825 return false;
3826
3827 const MachineInstr &DefMI = *MRI.getVRegDef(OffsetReg);
3828 if (DefMI.getOpcode() != AArch64::ORRWrs ||
3829 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3830 DefMI.getOperand(3).getImm() != 0)
3831 return false;
3832
3833 AM.BaseReg = MemI.getOperand(1).getReg();
3834 if (AM.BaseReg == Reg)
3835 AM.BaseReg = MemI.getOperand(2).getReg();
3836 AM.ScaledReg = DefMI.getOperand(2).getReg();
3837 AM.Scale = OffsetScale;
3838 AM.Displacement = 0;
3840 return true;
3841 }
3842 }
3843 }
3844
3845 // Handle memory instructions with a [Reg, #Imm] addressing mode.
3846
3847 // Check we are not breaking a potential conversion to an LDP.
3848 auto validateOffsetForLDP = [](unsigned NumBytes, int64_t OldOffset,
3849 int64_t NewOffset) -> bool {
3850 int64_t MinOffset, MaxOffset;
3851 switch (NumBytes) {
3852 default:
3853 return true;
3854 case 4:
3855 MinOffset = -256;
3856 MaxOffset = 252;
3857 break;
3858 case 8:
3859 MinOffset = -512;
3860 MaxOffset = 504;
3861 break;
3862 case 16:
3863 MinOffset = -1024;
3864 MaxOffset = 1008;
3865 break;
3866 }
3867 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3868 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3869 };
3870 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) -> bool {
3871 int64_t OldOffset = MemI.getOperand(2).getImm() * OffsetScale;
3872 int64_t NewOffset = OldOffset + Disp;
3873 if (!isLegalAddressingMode(NumBytes, NewOffset, /* Scale */ 0))
3874 return false;
3875 // If the old offset would fit into an LDP, but the new offset wouldn't,
3876 // bail out.
3877 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3878 return false;
3879 AM.BaseReg = AddrI.getOperand(1).getReg();
3880 AM.ScaledReg = 0;
3881 AM.Scale = 0;
3882 AM.Displacement = NewOffset;
3884 return true;
3885 };
3886
3887 auto canFoldAddRegIntoAddrMode =
3888 [&](int64_t Scale,
3890 if (MemI.getOperand(2).getImm() != 0)
3891 return false;
3892 if ((unsigned)Scale != Scale)
3893 return false;
3894 if (!isLegalAddressingMode(NumBytes, /* Offset */ 0, Scale))
3895 return false;
3896 AM.BaseReg = AddrI.getOperand(1).getReg();
3897 AM.ScaledReg = AddrI.getOperand(2).getReg();
3898 AM.Scale = Scale;
3899 AM.Displacement = 0;
3900 AM.Form = Form;
3901 return true;
3902 };
3903
3904 auto avoidSlowSTRQ = [&](const MachineInstr &MemI) {
3905 unsigned Opcode = MemI.getOpcode();
3906 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3907 Subtarget.isSTRQroSlow();
3908 };
3909
3910 int64_t Disp = 0;
3911 const bool OptSize = MemI.getMF()->getFunction().hasOptSize();
3912 switch (AddrI.getOpcode()) {
3913 default:
3914 return false;
3915
3916 case AArch64::ADDXri:
3917 // add Xa, Xn, #N
3918 // ldr Xd, [Xa, #M]
3919 // ->
3920 // ldr Xd, [Xn, #N'+M]
3921 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3922 return canFoldAddSubImmIntoAddrMode(Disp);
3923
3924 case AArch64::SUBXri:
3925 // sub Xa, Xn, #N
3926 // ldr Xd, [Xa, #M]
3927 // ->
3928 // ldr Xd, [Xn, #N'+M]
3929 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3930 return canFoldAddSubImmIntoAddrMode(-Disp);
3931
3932 case AArch64::ADDXrs: {
3933 // add Xa, Xn, Xm, lsl #N
3934 // ldr Xd, [Xa]
3935 // ->
3936 // ldr Xd, [Xn, Xm, lsl #N]
3937
3938 // Don't fold the add if the result would be slower, unless optimising for
3939 // size.
3940 unsigned Shift = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3942 return false;
3943 Shift = AArch64_AM::getShiftValue(Shift);
3944 if (!OptSize) {
3945 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3946 return false;
3947 if (avoidSlowSTRQ(MemI))
3948 return false;
3949 }
3950 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3951 }
3952
3953 case AArch64::ADDXrr:
3954 // add Xa, Xn, Xm
3955 // ldr Xd, [Xa]
3956 // ->
3957 // ldr Xd, [Xn, Xm, lsl #0]
3958
3959 // Don't fold the add if the result would be slower, unless optimising for
3960 // size.
3961 if (!OptSize && avoidSlowSTRQ(MemI))
3962 return false;
3963 return canFoldAddRegIntoAddrMode(1);
3964
3965 case AArch64::ADDXrx:
3966 // add Xa, Xn, Wm, {s,u}xtw #N
3967 // ldr Xd, [Xa]
3968 // ->
3969 // ldr Xd, [Xn, Wm, {s,u}xtw #N]
3970
3971 // Don't fold the add if the result would be slower, unless optimising for
3972 // size.
3973 if (!OptSize && avoidSlowSTRQ(MemI))
3974 return false;
3975
3976 // Can fold only sign-/zero-extend of a word.
3977 unsigned Imm = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3979 if (Extend != AArch64_AM::UXTW && Extend != AArch64_AM::SXTW)
3980 return false;
3981
3982 return canFoldAddRegIntoAddrMode(
3983 1ULL << AArch64_AM::getArithShiftValue(Imm),
3986 }
3987}
3988
3989// Given an opcode for an instruction with a [Reg, #Imm] addressing mode,
3990// return the opcode of an instruction performing the same operation, but using
3991// the [Reg, Reg] addressing mode.
3992static unsigned regOffsetOpcode(unsigned Opcode) {
3993 switch (Opcode) {
3994 default:
3995 llvm_unreachable("Address folding not implemented for instruction");
3996
3997 case AArch64::LDURQi:
3998 case AArch64::LDRQui:
3999 return AArch64::LDRQroX;
4000 case AArch64::STURQi:
4001 case AArch64::STRQui:
4002 return AArch64::STRQroX;
4003 case AArch64::LDURDi:
4004 case AArch64::LDRDui:
4005 return AArch64::LDRDroX;
4006 case AArch64::STURDi:
4007 case AArch64::STRDui:
4008 return AArch64::STRDroX;
4009 case AArch64::LDURXi:
4010 case AArch64::LDRXui:
4011 return AArch64::LDRXroX;
4012 case AArch64::STURXi:
4013 case AArch64::STRXui:
4014 return AArch64::STRXroX;
4015 case AArch64::LDURWi:
4016 case AArch64::LDRWui:
4017 return AArch64::LDRWroX;
4018 case AArch64::LDURSWi:
4019 case AArch64::LDRSWui:
4020 return AArch64::LDRSWroX;
4021 case AArch64::STURWi:
4022 case AArch64::STRWui:
4023 return AArch64::STRWroX;
4024 case AArch64::LDURHi:
4025 case AArch64::LDRHui:
4026 return AArch64::LDRHroX;
4027 case AArch64::STURHi:
4028 case AArch64::STRHui:
4029 return AArch64::STRHroX;
4030 case AArch64::LDURHHi:
4031 case AArch64::LDRHHui:
4032 return AArch64::LDRHHroX;
4033 case AArch64::STURHHi:
4034 case AArch64::STRHHui:
4035 return AArch64::STRHHroX;
4036 case AArch64::LDURSHXi:
4037 case AArch64::LDRSHXui:
4038 return AArch64::LDRSHXroX;
4039 case AArch64::LDURSHWi:
4040 case AArch64::LDRSHWui:
4041 return AArch64::LDRSHWroX;
4042 case AArch64::LDURBi:
4043 case AArch64::LDRBui:
4044 return AArch64::LDRBroX;
4045 case AArch64::LDURBBi:
4046 case AArch64::LDRBBui:
4047 return AArch64::LDRBBroX;
4048 case AArch64::LDURSBXi:
4049 case AArch64::LDRSBXui:
4050 return AArch64::LDRSBXroX;
4051 case AArch64::LDURSBWi:
4052 case AArch64::LDRSBWui:
4053 return AArch64::LDRSBWroX;
4054 case AArch64::STURBi:
4055 case AArch64::STRBui:
4056 return AArch64::STRBroX;
4057 case AArch64::STURBBi:
4058 case AArch64::STRBBui:
4059 return AArch64::STRBBroX;
4060 }
4061}
4062
4063// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4064// the opcode of an instruction performing the same operation, but using the
4065// [Reg, #Imm] addressing mode with scaled offset.
4066unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale) {
4067 switch (Opcode) {
4068 default:
4069 llvm_unreachable("Address folding not implemented for instruction");
4070
4071 case AArch64::LDURQi:
4072 Scale = 16;
4073 return AArch64::LDRQui;
4074 case AArch64::STURQi:
4075 Scale = 16;
4076 return AArch64::STRQui;
4077 case AArch64::LDURDi:
4078 Scale = 8;
4079 return AArch64::LDRDui;
4080 case AArch64::STURDi:
4081 Scale = 8;
4082 return AArch64::STRDui;
4083 case AArch64::LDURXi:
4084 Scale = 8;
4085 return AArch64::LDRXui;
4086 case AArch64::STURXi:
4087 Scale = 8;
4088 return AArch64::STRXui;
4089 case AArch64::LDURWi:
4090 Scale = 4;
4091 return AArch64::LDRWui;
4092 case AArch64::LDURSWi:
4093 Scale = 4;
4094 return AArch64::LDRSWui;
4095 case AArch64::STURWi:
4096 Scale = 4;
4097 return AArch64::STRWui;
4098 case AArch64::LDURHi:
4099 Scale = 2;
4100 return AArch64::LDRHui;
4101 case AArch64::STURHi:
4102 Scale = 2;
4103 return AArch64::STRHui;
4104 case AArch64::LDURHHi:
4105 Scale = 2;
4106 return AArch64::LDRHHui;
4107 case AArch64::STURHHi:
4108 Scale = 2;
4109 return AArch64::STRHHui;
4110 case AArch64::LDURSHXi:
4111 Scale = 2;
4112 return AArch64::LDRSHXui;
4113 case AArch64::LDURSHWi:
4114 Scale = 2;
4115 return AArch64::LDRSHWui;
4116 case AArch64::LDURBi:
4117 Scale = 1;
4118 return AArch64::LDRBui;
4119 case AArch64::LDURBBi:
4120 Scale = 1;
4121 return AArch64::LDRBBui;
4122 case AArch64::LDURSBXi:
4123 Scale = 1;
4124 return AArch64::LDRSBXui;
4125 case AArch64::LDURSBWi:
4126 Scale = 1;
4127 return AArch64::LDRSBWui;
4128 case AArch64::STURBi:
4129 Scale = 1;
4130 return AArch64::STRBui;
4131 case AArch64::STURBBi:
4132 Scale = 1;
4133 return AArch64::STRBBui;
4134 case AArch64::LDRQui:
4135 case AArch64::STRQui:
4136 Scale = 16;
4137 return Opcode;
4138 case AArch64::LDRDui:
4139 case AArch64::STRDui:
4140 case AArch64::LDRXui:
4141 case AArch64::STRXui:
4142 Scale = 8;
4143 return Opcode;
4144 case AArch64::LDRWui:
4145 case AArch64::LDRSWui:
4146 case AArch64::STRWui:
4147 Scale = 4;
4148 return Opcode;
4149 case AArch64::LDRHui:
4150 case AArch64::STRHui:
4151 case AArch64::LDRHHui:
4152 case AArch64::STRHHui:
4153 case AArch64::LDRSHXui:
4154 case AArch64::LDRSHWui:
4155 Scale = 2;
4156 return Opcode;
4157 case AArch64::LDRBui:
4158 case AArch64::LDRBBui:
4159 case AArch64::LDRSBXui:
4160 case AArch64::LDRSBWui:
4161 case AArch64::STRBui:
4162 case AArch64::STRBBui:
4163 Scale = 1;
4164 return Opcode;
4165 }
4166}
4167
4168// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4169// the opcode of an instruction performing the same operation, but using the
4170// [Reg, #Imm] addressing mode with unscaled offset.
4171unsigned unscaledOffsetOpcode(unsigned Opcode) {
4172 switch (Opcode) {
4173 default:
4174 llvm_unreachable("Address folding not implemented for instruction");
4175
4176 case AArch64::LDURQi:
4177 case AArch64::STURQi:
4178 case AArch64::LDURDi:
4179 case AArch64::STURDi:
4180 case AArch64::LDURXi:
4181 case AArch64::STURXi:
4182 case AArch64::LDURWi:
4183 case AArch64::LDURSWi:
4184 case AArch64::STURWi:
4185 case AArch64::LDURHi:
4186 case AArch64::STURHi:
4187 case AArch64::LDURHHi:
4188 case AArch64::STURHHi:
4189 case AArch64::LDURSHXi:
4190 case AArch64::LDURSHWi:
4191 case AArch64::LDURBi:
4192 case AArch64::STURBi:
4193 case AArch64::LDURBBi:
4194 case AArch64::STURBBi:
4195 case AArch64::LDURSBWi:
4196 case AArch64::LDURSBXi:
4197 return Opcode;
4198 case AArch64::LDRQui:
4199 return AArch64::LDURQi;
4200 case AArch64::STRQui:
4201 return AArch64::STURQi;
4202 case AArch64::LDRDui:
4203 return AArch64::LDURDi;
4204 case AArch64::STRDui:
4205 return AArch64::STURDi;
4206 case AArch64::LDRXui:
4207 return AArch64::LDURXi;
4208 case AArch64::STRXui:
4209 return AArch64::STURXi;
4210 case AArch64::LDRWui:
4211 return AArch64::LDURWi;
4212 case AArch64::LDRSWui:
4213 return AArch64::LDURSWi;
4214 case AArch64::STRWui:
4215 return AArch64::STURWi;
4216 case AArch64::LDRHui:
4217 return AArch64::LDURHi;
4218 case AArch64::STRHui:
4219 return AArch64::STURHi;
4220 case AArch64::LDRHHui:
4221 return AArch64::LDURHHi;
4222 case AArch64::STRHHui:
4223 return AArch64::STURHHi;
4224 case AArch64::LDRSHXui:
4225 return AArch64::LDURSHXi;
4226 case AArch64::LDRSHWui:
4227 return AArch64::LDURSHWi;
4228 case AArch64::LDRBBui:
4229 return AArch64::LDURBBi;
4230 case AArch64::LDRBui:
4231 return AArch64::LDURBi;
4232 case AArch64::STRBBui:
4233 return AArch64::STURBBi;
4234 case AArch64::STRBui:
4235 return AArch64::STURBi;
4236 case AArch64::LDRSBWui:
4237 return AArch64::LDURSBWi;
4238 case AArch64::LDRSBXui:
4239 return AArch64::LDURSBXi;
4240 }
4241}
4242
4243// Given the opcode of a memory load/store instruction, return the opcode of an
4244// instruction performing the same operation, but using
4245// the [Reg, Reg, {s,u}xtw #N] addressing mode with sign-/zero-extend of the
4246// offset register.
4247static unsigned offsetExtendOpcode(unsigned Opcode) {
4248 switch (Opcode) {
4249 default:
4250 llvm_unreachable("Address folding not implemented for instruction");
4251
4252 case AArch64::LDRQroX:
4253 case AArch64::LDURQi:
4254 case AArch64::LDRQui:
4255 return AArch64::LDRQroW;
4256 case AArch64::STRQroX:
4257 case AArch64::STURQi:
4258 case AArch64::STRQui:
4259 return AArch64::STRQroW;
4260 case AArch64::LDRDroX:
4261 case AArch64::LDURDi:
4262 case AArch64::LDRDui:
4263 return AArch64::LDRDroW;
4264 case AArch64::STRDroX:
4265 case AArch64::STURDi:
4266 case AArch64::STRDui:
4267 return AArch64::STRDroW;
4268 case AArch64::LDRXroX:
4269 case AArch64::LDURXi:
4270 case AArch64::LDRXui:
4271 return AArch64::LDRXroW;
4272 case AArch64::STRXroX:
4273 case AArch64::STURXi:
4274 case AArch64::STRXui:
4275 return AArch64::STRXroW;
4276 case AArch64::LDRWroX:
4277 case AArch64::LDURWi:
4278 case AArch64::LDRWui:
4279 return AArch64::LDRWroW;
4280 case AArch64::LDRSWroX:
4281 case AArch64::LDURSWi:
4282 case AArch64::LDRSWui:
4283 return AArch64::LDRSWroW;
4284 case AArch64::STRWroX:
4285 case AArch64::STURWi:
4286 case AArch64::STRWui:
4287 return AArch64::STRWroW;
4288 case AArch64::LDRHroX:
4289 case AArch64::LDURHi:
4290 case AArch64::LDRHui:
4291 return AArch64::LDRHroW;
4292 case AArch64::STRHroX:
4293 case AArch64::STURHi:
4294 case AArch64::STRHui:
4295 return AArch64::STRHroW;
4296 case AArch64::LDRHHroX:
4297 case AArch64::LDURHHi:
4298 case AArch64::LDRHHui:
4299 return AArch64::LDRHHroW;
4300 case AArch64::STRHHroX:
4301 case AArch64::STURHHi:
4302 case AArch64::STRHHui:
4303 return AArch64::STRHHroW;
4304 case AArch64::LDRSHXroX:
4305 case AArch64::LDURSHXi:
4306 case AArch64::LDRSHXui:
4307 return AArch64::LDRSHXroW;
4308 case AArch64::LDRSHWroX:
4309 case AArch64::LDURSHWi:
4310 case AArch64::LDRSHWui:
4311 return AArch64::LDRSHWroW;
4312 case AArch64::LDRBroX:
4313 case AArch64::LDURBi:
4314 case AArch64::LDRBui:
4315 return AArch64::LDRBroW;
4316 case AArch64::LDRBBroX:
4317 case AArch64::LDURBBi:
4318 case AArch64::LDRBBui:
4319 return AArch64::LDRBBroW;
4320 case AArch64::LDRSBXroX:
4321 case AArch64::LDURSBXi:
4322 case AArch64::LDRSBXui:
4323 return AArch64::LDRSBXroW;
4324 case AArch64::LDRSBWroX:
4325 case AArch64::LDURSBWi:
4326 case AArch64::LDRSBWui:
4327 return AArch64::LDRSBWroW;
4328 case AArch64::STRBroX:
4329 case AArch64::STURBi:
4330 case AArch64::STRBui:
4331 return AArch64::STRBroW;
4332 case AArch64::STRBBroX:
4333 case AArch64::STURBBi:
4334 case AArch64::STRBBui:
4335 return AArch64::STRBBroW;
4336 }
4337}
4338
4340 const ExtAddrMode &AM) const {
4341
4342 const DebugLoc &DL = MemI.getDebugLoc();
4343 MachineBasicBlock &MBB = *MemI.getParent();
4344 MachineRegisterInfo &MRI = MemI.getMF()->getRegInfo();
4345
4347 if (AM.ScaledReg) {
4348 // The new instruction will be in the form `ldr Rt, [Xn, Xm, lsl #imm]`.
4349 unsigned Opcode = regOffsetOpcode(MemI.getOpcode());
4350 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4351 auto B = BuildMI(MBB, MemI, DL, get(Opcode))
4352 .addReg(MemI.getOperand(0).getReg(),
4353 getDefRegState(MemI.mayLoad()))
4354 .addReg(AM.BaseReg)
4355 .addReg(AM.ScaledReg)
4356 .addImm(0)
4357 .addImm(AM.Scale > 1)
4358 .setMemRefs(MemI.memoperands())
4359 .setMIFlags(MemI.getFlags());
4360 return B.getInstr();
4361 }
4362
4363 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
4364 "Addressing mode not supported for folding");
4365
4366 // The new instruction will be in the form `ld[u]r Rt, [Xn, #imm]`.
4367 unsigned Scale = 1;
4368 unsigned Opcode = MemI.getOpcode();
4369 if (isInt<9>(AM.Displacement))
4370 Opcode = unscaledOffsetOpcode(Opcode);
4371 else
4372 Opcode = scaledOffsetOpcode(Opcode, Scale);
4373
4374 auto B =
4375 BuildMI(MBB, MemI, DL, get(Opcode))
4376 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4377 .addReg(AM.BaseReg)
4378 .addImm(AM.Displacement / Scale)
4379 .setMemRefs(MemI.memoperands())
4380 .setMIFlags(MemI.getFlags());
4381 return B.getInstr();
4382 }
4383
4386 // The new instruction will be in the form `ldr Rt, [Xn, Wm, {s,u}xtw #N]`.
4387 assert(AM.ScaledReg && !AM.Displacement &&
4388 "Address offset can be a register or an immediate, but not both");
4389 unsigned Opcode = offsetExtendOpcode(MemI.getOpcode());
4390 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4391 // Make sure the offset register is in the correct register class.
4392 Register OffsetReg = AM.ScaledReg;
4393 const TargetRegisterClass *RC = MRI.getRegClass(OffsetReg);
4394 if (RC->hasSuperClassEq(&AArch64::GPR64RegClass)) {
4395 OffsetReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
4396 BuildMI(MBB, MemI, DL, get(TargetOpcode::COPY), OffsetReg)
4397 .addReg(AM.ScaledReg, {}, AArch64::sub_32);
4398 }
4399 auto B =
4400 BuildMI(MBB, MemI, DL, get(Opcode))
4401 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4402 .addReg(AM.BaseReg)
4403 .addReg(OffsetReg)
4405 .addImm(AM.Scale != 1)
4406 .setMemRefs(MemI.memoperands())
4407 .setMIFlags(MemI.getFlags());
4408
4409 return B.getInstr();
4410 }
4411
4413 "Function must not be called with an addressing mode it can't handle");
4414}
4415
4416/// Return true if the opcode is a post-index ld/st instruction, which really
4417/// loads from base+0.
4418static bool isPostIndexLdStOpcode(unsigned Opcode) {
4419 switch (Opcode) {
4420 default:
4421 return false;
4422 case AArch64::LD1Fourv16b_POST:
4423 case AArch64::LD1Fourv1d_POST:
4424 case AArch64::LD1Fourv2d_POST:
4425 case AArch64::LD1Fourv2s_POST:
4426 case AArch64::LD1Fourv4h_POST:
4427 case AArch64::LD1Fourv4s_POST:
4428 case AArch64::LD1Fourv8b_POST:
4429 case AArch64::LD1Fourv8h_POST:
4430 case AArch64::LD1Onev16b_POST:
4431 case AArch64::LD1Onev1d_POST:
4432 case AArch64::LD1Onev2d_POST:
4433 case AArch64::LD1Onev2s_POST:
4434 case AArch64::LD1Onev4h_POST:
4435 case AArch64::LD1Onev4s_POST:
4436 case AArch64::LD1Onev8b_POST:
4437 case AArch64::LD1Onev8h_POST:
4438 case AArch64::LD1Rv16b_POST:
4439 case AArch64::LD1Rv1d_POST:
4440 case AArch64::LD1Rv2d_POST:
4441 case AArch64::LD1Rv2s_POST:
4442 case AArch64::LD1Rv4h_POST:
4443 case AArch64::LD1Rv4s_POST:
4444 case AArch64::LD1Rv8b_POST:
4445 case AArch64::LD1Rv8h_POST:
4446 case AArch64::LD1Threev16b_POST:
4447 case AArch64::LD1Threev1d_POST:
4448 case AArch64::LD1Threev2d_POST:
4449 case AArch64::LD1Threev2s_POST:
4450 case AArch64::LD1Threev4h_POST:
4451 case AArch64::LD1Threev4s_POST:
4452 case AArch64::LD1Threev8b_POST:
4453 case AArch64::LD1Threev8h_POST:
4454 case AArch64::LD1Twov16b_POST:
4455 case AArch64::LD1Twov1d_POST:
4456 case AArch64::LD1Twov2d_POST:
4457 case AArch64::LD1Twov2s_POST:
4458 case AArch64::LD1Twov4h_POST:
4459 case AArch64::LD1Twov4s_POST:
4460 case AArch64::LD1Twov8b_POST:
4461 case AArch64::LD1Twov8h_POST:
4462 case AArch64::LD1i16_POST:
4463 case AArch64::LD1i32_POST:
4464 case AArch64::LD1i64_POST:
4465 case AArch64::LD1i8_POST:
4466 case AArch64::LD2Rv16b_POST:
4467 case AArch64::LD2Rv1d_POST:
4468 case AArch64::LD2Rv2d_POST:
4469 case AArch64::LD2Rv2s_POST:
4470 case AArch64::LD2Rv4h_POST:
4471 case AArch64::LD2Rv4s_POST:
4472 case AArch64::LD2Rv8b_POST:
4473 case AArch64::LD2Rv8h_POST:
4474 case AArch64::LD2Twov16b_POST:
4475 case AArch64::LD2Twov2d_POST:
4476 case AArch64::LD2Twov2s_POST:
4477 case AArch64::LD2Twov4h_POST:
4478 case AArch64::LD2Twov4s_POST:
4479 case AArch64::LD2Twov8b_POST:
4480 case AArch64::LD2Twov8h_POST:
4481 case AArch64::LD2i16_POST:
4482 case AArch64::LD2i32_POST:
4483 case AArch64::LD2i64_POST:
4484 case AArch64::LD2i8_POST:
4485 case AArch64::LD3Rv16b_POST:
4486 case AArch64::LD3Rv1d_POST:
4487 case AArch64::LD3Rv2d_POST:
4488 case AArch64::LD3Rv2s_POST:
4489 case AArch64::LD3Rv4h_POST:
4490 case AArch64::LD3Rv4s_POST:
4491 case AArch64::LD3Rv8b_POST:
4492 case AArch64::LD3Rv8h_POST:
4493 case AArch64::LD3Threev16b_POST:
4494 case AArch64::LD3Threev2d_POST:
4495 case AArch64::LD3Threev2s_POST:
4496 case AArch64::LD3Threev4h_POST:
4497 case AArch64::LD3Threev4s_POST:
4498 case AArch64::LD3Threev8b_POST:
4499 case AArch64::LD3Threev8h_POST:
4500 case AArch64::LD3i16_POST:
4501 case AArch64::LD3i32_POST:
4502 case AArch64::LD3i64_POST:
4503 case AArch64::LD3i8_POST:
4504 case AArch64::LD4Fourv16b_POST:
4505 case AArch64::LD4Fourv2d_POST:
4506 case AArch64::LD4Fourv2s_POST:
4507 case AArch64::LD4Fourv4h_POST:
4508 case AArch64::LD4Fourv4s_POST:
4509 case AArch64::LD4Fourv8b_POST:
4510 case AArch64::LD4Fourv8h_POST:
4511 case AArch64::LD4Rv16b_POST:
4512 case AArch64::LD4Rv1d_POST:
4513 case AArch64::LD4Rv2d_POST:
4514 case AArch64::LD4Rv2s_POST:
4515 case AArch64::LD4Rv4h_POST:
4516 case AArch64::LD4Rv4s_POST:
4517 case AArch64::LD4Rv8b_POST:
4518 case AArch64::LD4Rv8h_POST:
4519 case AArch64::LD4i16_POST:
4520 case AArch64::LD4i32_POST:
4521 case AArch64::LD4i64_POST:
4522 case AArch64::LD4i8_POST:
4523 case AArch64::LDAPRWpost:
4524 case AArch64::LDAPRXpost:
4525 case AArch64::LDIAPPWpost:
4526 case AArch64::LDIAPPXpost:
4527 case AArch64::LDPDpost:
4528 case AArch64::LDPQpost:
4529 case AArch64::LDPSWpost:
4530 case AArch64::LDPSpost:
4531 case AArch64::LDPWpost:
4532 case AArch64::LDPXpost:
4533 case AArch64::LDRBBpost:
4534 case AArch64::LDRBpost:
4535 case AArch64::LDRDpost:
4536 case AArch64::LDRHHpost:
4537 case AArch64::LDRHpost:
4538 case AArch64::LDRQpost:
4539 case AArch64::LDRSBWpost:
4540 case AArch64::LDRSBXpost:
4541 case AArch64::LDRSHWpost:
4542 case AArch64::LDRSHXpost:
4543 case AArch64::LDRSWpost:
4544 case AArch64::LDRSpost:
4545 case AArch64::LDRWpost:
4546 case AArch64::LDRXpost:
4547 case AArch64::ST1Fourv16b_POST:
4548 case AArch64::ST1Fourv1d_POST:
4549 case AArch64::ST1Fourv2d_POST:
4550 case AArch64::ST1Fourv2s_POST:
4551 case AArch64::ST1Fourv4h_POST:
4552 case AArch64::ST1Fourv4s_POST:
4553 case AArch64::ST1Fourv8b_POST:
4554 case AArch64::ST1Fourv8h_POST:
4555 case AArch64::ST1Onev16b_POST:
4556 case AArch64::ST1Onev1d_POST:
4557 case AArch64::ST1Onev2d_POST:
4558 case AArch64::ST1Onev2s_POST:
4559 case AArch64::ST1Onev4h_POST:
4560 case AArch64::ST1Onev4s_POST:
4561 case AArch64::ST1Onev8b_POST:
4562 case AArch64::ST1Onev8h_POST:
4563 case AArch64::ST1Threev16b_POST:
4564 case AArch64::ST1Threev1d_POST:
4565 case AArch64::ST1Threev2d_POST:
4566 case AArch64::ST1Threev2s_POST:
4567 case AArch64::ST1Threev4h_POST:
4568 case AArch64::ST1Threev4s_POST:
4569 case AArch64::ST1Threev8b_POST:
4570 case AArch64::ST1Threev8h_POST:
4571 case AArch64::ST1Twov16b_POST:
4572 case AArch64::ST1Twov1d_POST:
4573 case AArch64::ST1Twov2d_POST:
4574 case AArch64::ST1Twov2s_POST:
4575 case AArch64::ST1Twov4h_POST:
4576 case AArch64::ST1Twov4s_POST:
4577 case AArch64::ST1Twov8b_POST:
4578 case AArch64::ST1Twov8h_POST:
4579 case AArch64::ST1i16_POST:
4580 case AArch64::ST1i32_POST:
4581 case AArch64::ST1i64_POST:
4582 case AArch64::ST1i8_POST:
4583 case AArch64::ST2GPostIndex:
4584 case AArch64::ST2Twov16b_POST:
4585 case AArch64::ST2Twov2d_POST:
4586 case AArch64::ST2Twov2s_POST:
4587 case AArch64::ST2Twov4h_POST:
4588 case AArch64::ST2Twov4s_POST:
4589 case AArch64::ST2Twov8b_POST:
4590 case AArch64::ST2Twov8h_POST:
4591 case AArch64::ST2i16_POST:
4592 case AArch64::ST2i32_POST:
4593 case AArch64::ST2i64_POST:
4594 case AArch64::ST2i8_POST:
4595 case AArch64::ST3Threev16b_POST:
4596 case AArch64::ST3Threev2d_POST:
4597 case AArch64::ST3Threev2s_POST:
4598 case AArch64::ST3Threev4h_POST:
4599 case AArch64::ST3Threev4s_POST:
4600 case AArch64::ST3Threev8b_POST:
4601 case AArch64::ST3Threev8h_POST:
4602 case AArch64::ST3i16_POST:
4603 case AArch64::ST3i32_POST:
4604 case AArch64::ST3i64_POST:
4605 case AArch64::ST3i8_POST:
4606 case AArch64::ST4Fourv16b_POST:
4607 case AArch64::ST4Fourv2d_POST:
4608 case AArch64::ST4Fourv2s_POST:
4609 case AArch64::ST4Fourv4h_POST:
4610 case AArch64::ST4Fourv4s_POST:
4611 case AArch64::ST4Fourv8b_POST:
4612 case AArch64::ST4Fourv8h_POST:
4613 case AArch64::ST4i16_POST:
4614 case AArch64::ST4i32_POST:
4615 case AArch64::ST4i64_POST:
4616 case AArch64::ST4i8_POST:
4617 case AArch64::STGPostIndex:
4618 case AArch64::STGPpost:
4619 case AArch64::STPDpost:
4620 case AArch64::STPQpost:
4621 case AArch64::STPSpost:
4622 case AArch64::STPWpost:
4623 case AArch64::STPXpost:
4624 case AArch64::STRBBpost:
4625 case AArch64::STRBpost:
4626 case AArch64::STRDpost:
4627 case AArch64::STRHHpost:
4628 case AArch64::STRHpost:
4629 case AArch64::STRQpost:
4630 case AArch64::STRSpost:
4631 case AArch64::STRWpost:
4632 case AArch64::STRXpost:
4633 case AArch64::STZ2GPostIndex:
4634 case AArch64::STZGPostIndex:
4635 return true;
4636 }
4637}
4638
4640 const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset,
4641 bool &OffsetIsScalable, TypeSize &Width,
4642 const TargetRegisterInfo *TRI) const {
4643 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4644 // Handle only loads/stores with base register followed by immediate offset.
4645 if (LdSt.getNumExplicitOperands() == 3) {
4646 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
4647 if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
4648 !LdSt.getOperand(2).isImm())
4649 return false;
4650 } else if (LdSt.getNumExplicitOperands() == 4) {
4651 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
4652 if (!LdSt.getOperand(1).isReg() ||
4653 (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI()) ||
4654 !LdSt.getOperand(3).isImm())
4655 return false;
4656 } else
4657 return false;
4658
4659 // Get the scaling factor for the instruction and set the width for the
4660 // instruction.
4661 TypeSize Scale(0U, false);
4662 int64_t Dummy1, Dummy2;
4663
4664 // If this returns false, then it's an instruction we don't want to handle.
4665 if (!getMemOpInfo(LdSt.getOpcode(), Scale, Width, Dummy1, Dummy2))
4666 return false;
4667
4668 // Compute the offset. Offset is calculated as the immediate operand
4669 // multiplied by the scaling factor. Unscaled instructions have scaling factor
4670 // set to 1. Postindex are a special case which have an offset of 0.
4671 if (isPostIndexLdStOpcode(LdSt.getOpcode())) {
4672 BaseOp = &LdSt.getOperand(2);
4673 Offset = 0;
4674 } else if (LdSt.getNumExplicitOperands() == 3) {
4675 BaseOp = &LdSt.getOperand(1);
4676 Offset = LdSt.getOperand(2).getImm() * Scale.getKnownMinValue();
4677 } else {
4678 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
4679 BaseOp = &LdSt.getOperand(2);
4680 Offset = LdSt.getOperand(3).getImm() * Scale.getKnownMinValue();
4681 }
4682 OffsetIsScalable = Scale.isScalable();
4683
4684 return BaseOp->isReg() || BaseOp->isFI();
4685}
4686
4689 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4690 MachineOperand &OfsOp = LdSt.getOperand(LdSt.getNumExplicitOperands() - 1);
4691 assert(OfsOp.isImm() && "Offset operand wasn't immediate.");
4692 return OfsOp;
4693}
4694
4695bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale,
4696 TypeSize &Width, int64_t &MinOffset,
4697 int64_t &MaxOffset) {
4698 switch (Opcode) {
4699 // Not a memory operation or something we want to handle.
4700 default:
4701 Scale = Width = TypeSize::getFixed(0);
4702 MinOffset = MaxOffset = 0;
4703 return false;
4704 // LDR / STR
4705 case AArch64::LDRQui:
4706 case AArch64::STRQui:
4707 Scale = Width = TypeSize::getFixed(16);
4708 MinOffset = 0;
4709 MaxOffset = 4095;
4710 break;
4711 case AArch64::LDRXui:
4712 case AArch64::LDRDui:
4713 case AArch64::STRXui:
4714 case AArch64::STRDui:
4715 case AArch64::PRFMui:
4716 Scale = Width = TypeSize::getFixed(8);
4717 MinOffset = 0;
4718 MaxOffset = 4095;
4719 break;
4720 case AArch64::LDRWui:
4721 case AArch64::LDRSui:
4722 case AArch64::LDRSWui:
4723 case AArch64::STRWui:
4724 case AArch64::STRSui:
4725 Scale = Width = TypeSize::getFixed(4);
4726 MinOffset = 0;
4727 MaxOffset = 4095;
4728 break;
4729 case AArch64::LDRHui:
4730 case AArch64::LDRHHui:
4731 case AArch64::LDRSHWui:
4732 case AArch64::LDRSHXui:
4733 case AArch64::STRHui:
4734 case AArch64::STRHHui:
4735 Scale = Width = TypeSize::getFixed(2);
4736 MinOffset = 0;
4737 MaxOffset = 4095;
4738 break;
4739 case AArch64::LDRBui:
4740 case AArch64::LDRBBui:
4741 case AArch64::LDRSBWui:
4742 case AArch64::LDRSBXui:
4743 case AArch64::STRBui:
4744 case AArch64::STRBBui:
4745 Scale = Width = TypeSize::getFixed(1);
4746 MinOffset = 0;
4747 MaxOffset = 4095;
4748 break;
4749 // post/pre inc
4750 case AArch64::STRQpre:
4751 case AArch64::LDRQpost:
4752 Scale = TypeSize::getFixed(1);
4753 Width = TypeSize::getFixed(16);
4754 MinOffset = -256;
4755 MaxOffset = 255;
4756 break;
4757 case AArch64::LDRDpost:
4758 case AArch64::LDRDpre:
4759 case AArch64::LDRXpost:
4760 case AArch64::LDRXpre:
4761 case AArch64::STRDpost:
4762 case AArch64::STRDpre:
4763 case AArch64::STRXpost:
4764 case AArch64::STRXpre:
4765 Scale = TypeSize::getFixed(1);
4766 Width = TypeSize::getFixed(8);
4767 MinOffset = -256;
4768 MaxOffset = 255;
4769 break;
4770 case AArch64::STRWpost:
4771 case AArch64::STRWpre:
4772 case AArch64::LDRWpost:
4773 case AArch64::LDRWpre:
4774 case AArch64::STRSpost:
4775 case AArch64::STRSpre:
4776 case AArch64::LDRSpost:
4777 case AArch64::LDRSpre:
4778 Scale = TypeSize::getFixed(1);
4779 Width = TypeSize::getFixed(4);
4780 MinOffset = -256;
4781 MaxOffset = 255;
4782 break;
4783 case AArch64::LDRHpost:
4784 case AArch64::LDRHpre:
4785 case AArch64::STRHpost:
4786 case AArch64::STRHpre:
4787 case AArch64::LDRHHpost:
4788 case AArch64::LDRHHpre:
4789 case AArch64::STRHHpost:
4790 case AArch64::STRHHpre:
4791 Scale = TypeSize::getFixed(1);
4792 Width = TypeSize::getFixed(2);
4793 MinOffset = -256;
4794 MaxOffset = 255;
4795 break;
4796 case AArch64::LDRBpost:
4797 case AArch64::LDRBpre:
4798 case AArch64::STRBpost:
4799 case AArch64::STRBpre:
4800 case AArch64::LDRBBpost:
4801 case AArch64::LDRBBpre:
4802 case AArch64::STRBBpost:
4803 case AArch64::STRBBpre:
4804 Scale = Width = TypeSize::getFixed(1);
4805 MinOffset = -256;
4806 MaxOffset = 255;
4807 break;
4808 // Unscaled
4809 case AArch64::LDURQi:
4810 case AArch64::STURQi:
4811 Scale = TypeSize::getFixed(1);
4812 Width = TypeSize::getFixed(16);
4813 MinOffset = -256;
4814 MaxOffset = 255;
4815 break;
4816 case AArch64::LDURXi:
4817 case AArch64::LDURDi:
4818 case AArch64::LDAPURXi:
4819 case AArch64::STURXi:
4820 case AArch64::STURDi:
4821 case AArch64::STLURXi:
4822 case AArch64::PRFUMi:
4823 Scale = TypeSize::getFixed(1);
4824 Width = TypeSize::getFixed(8);
4825 MinOffset = -256;
4826 MaxOffset = 255;
4827 break;
4828 case AArch64::LDURWi:
4829 case AArch64::LDURSi:
4830 case AArch64::LDURSWi:
4831 case AArch64::LDAPURi:
4832 case AArch64::LDAPURSWi:
4833 case AArch64::STURWi:
4834 case AArch64::STURSi:
4835 case AArch64::STLURWi:
4836 Scale = TypeSize::getFixed(1);
4837 Width = TypeSize::getFixed(4);
4838 MinOffset = -256;
4839 MaxOffset = 255;
4840 break;
4841 case AArch64::LDURHi:
4842 case AArch64::LDURHHi:
4843 case AArch64::LDURSHXi:
4844 case AArch64::LDURSHWi:
4845 case AArch64::LDAPURHi:
4846 case AArch64::LDAPURSHWi:
4847 case AArch64::LDAPURSHXi:
4848 case AArch64::STURHi:
4849 case AArch64::STURHHi:
4850 case AArch64::STLURHi:
4851 Scale = TypeSize::getFixed(1);
4852 Width = TypeSize::getFixed(2);
4853 MinOffset = -256;
4854 MaxOffset = 255;
4855 break;
4856 case AArch64::LDURBi:
4857 case AArch64::LDURBBi:
4858 case AArch64::LDURSBXi:
4859 case AArch64::LDURSBWi:
4860 case AArch64::LDAPURBi:
4861 case AArch64::LDAPURSBWi:
4862 case AArch64::LDAPURSBXi:
4863 case AArch64::STURBi:
4864 case AArch64::STURBBi:
4865 case AArch64::STLURBi:
4866 Scale = Width = TypeSize::getFixed(1);
4867 MinOffset = -256;
4868 MaxOffset = 255;
4869 break;
4870 // LDP / STP (including pre/post inc)
4871 case AArch64::LDPQi:
4872 case AArch64::LDNPQi:
4873 case AArch64::STPQi:
4874 case AArch64::STNPQi:
4875 case AArch64::LDPQpost:
4876 case AArch64::LDPQpre:
4877 case AArch64::STPQpost:
4878 case AArch64::STPQpre:
4879 Scale = TypeSize::getFixed(16);
4880 Width = TypeSize::getFixed(16 * 2);
4881 MinOffset = -64;
4882 MaxOffset = 63;
4883 break;
4884 case AArch64::LDPXi:
4885 case AArch64::LDPDi:
4886 case AArch64::LDNPXi:
4887 case AArch64::LDNPDi:
4888 case AArch64::STPXi:
4889 case AArch64::STPDi:
4890 case AArch64::STNPXi:
4891 case AArch64::STNPDi:
4892 case AArch64::LDPDpost:
4893 case AArch64::LDPDpre:
4894 case AArch64::LDPXpost:
4895 case AArch64::LDPXpre:
4896 case AArch64::STPDpost:
4897 case AArch64::STPDpre:
4898 case AArch64::STPXpost:
4899 case AArch64::STPXpre:
4900 Scale = TypeSize::getFixed(8);
4901 Width = TypeSize::getFixed(8 * 2);
4902 MinOffset = -64;
4903 MaxOffset = 63;
4904 break;
4905 case AArch64::LDPWi:
4906 case AArch64::LDPSi:
4907 case AArch64::LDNPWi:
4908 case AArch64::LDNPSi:
4909 case AArch64::STPWi:
4910 case AArch64::STPSi:
4911 case AArch64::STNPWi:
4912 case AArch64::STNPSi:
4913 case AArch64::LDPSpost:
4914 case AArch64::LDPSpre:
4915 case AArch64::LDPWpost:
4916 case AArch64::LDPWpre:
4917 case AArch64::STPSpost:
4918 case AArch64::STPSpre:
4919 case AArch64::STPWpost:
4920 case AArch64::STPWpre:
4921 Scale = TypeSize::getFixed(4);
4922 Width = TypeSize::getFixed(4 * 2);
4923 MinOffset = -64;
4924 MaxOffset = 63;
4925 break;
4926 case AArch64::StoreSwiftAsyncContext:
4927 // Store is an STRXui, but there might be an ADDXri in the expansion too.
4928 Scale = TypeSize::getFixed(1);
4929 Width = TypeSize::getFixed(8);
4930 MinOffset = 0;
4931 MaxOffset = 4095;
4932 break;
4933 case AArch64::ADDG:
4934 Scale = TypeSize::getFixed(16);
4935 Width = TypeSize::getFixed(0);
4936 MinOffset = 0;
4937 MaxOffset = 63;
4938 break;
4939 case AArch64::TAGPstack:
4940 Scale = TypeSize::getFixed(16);
4941 Width = TypeSize::getFixed(0);
4942 // TAGP with a negative offset turns into SUBP, which has a maximum offset
4943 // of 63 (not 64!).
4944 MinOffset = -63;
4945 MaxOffset = 63;
4946 break;
4947 case AArch64::LDG:
4948 case AArch64::STGi:
4949 case AArch64::STGPreIndex:
4950 case AArch64::STGPostIndex:
4951 case AArch64::STZGi:
4952 case AArch64::STZGPreIndex:
4953 case AArch64::STZGPostIndex:
4954 Scale = Width = TypeSize::getFixed(16);
4955 MinOffset = -256;
4956 MaxOffset = 255;
4957 break;
4958 // SVE
4959 case AArch64::STR_ZZZZXI:
4960 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4961 case AArch64::LDR_ZZZZXI:
4962 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4963 Scale = TypeSize::getScalable(16);
4964 Width = TypeSize::getScalable(16 * 4);
4965 MinOffset = -256;
4966 MaxOffset = 252;
4967 break;
4968 case AArch64::STR_ZZZXI:
4969 case AArch64::LDR_ZZZXI:
4970 Scale = TypeSize::getScalable(16);
4971 Width = TypeSize::getScalable(16 * 3);
4972 MinOffset = -256;
4973 MaxOffset = 253;
4974 break;
4975 case AArch64::STR_ZZXI:
4976 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4977 case AArch64::LDR_ZZXI:
4978 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4979 Scale = TypeSize::getScalable(16);
4980 Width = TypeSize::getScalable(16 * 2);
4981 MinOffset = -256;
4982 MaxOffset = 254;
4983 break;
4984 case AArch64::LDR_PXI:
4985 case AArch64::STR_PXI:
4986 Scale = Width = TypeSize::getScalable(2);
4987 MinOffset = -256;
4988 MaxOffset = 255;
4989 break;
4990 case AArch64::LDR_PPXI:
4991 case AArch64::STR_PPXI:
4992 Scale = TypeSize::getScalable(2);
4993 Width = TypeSize::getScalable(2 * 2);
4994 MinOffset = -256;
4995 MaxOffset = 254;
4996 break;
4997 case AArch64::LDR_ZXI:
4998 case AArch64::STR_ZXI:
4999 Scale = Width = TypeSize::getScalable(16);
5000 MinOffset = -256;
5001 MaxOffset = 255;
5002 break;
5003 case AArch64::LD1B_IMM:
5004 case AArch64::LD1H_IMM:
5005 case AArch64::LD1W_IMM:
5006 case AArch64::LD1D_IMM:
5007 case AArch64::LDNT1B_ZRI:
5008 case AArch64::LDNT1H_ZRI:
5009 case AArch64::LDNT1W_ZRI:
5010 case AArch64::LDNT1D_ZRI:
5011 case AArch64::ST1B_IMM:
5012 case AArch64::ST1H_IMM:
5013 case AArch64::ST1W_IMM:
5014 case AArch64::ST1D_IMM:
5015 case AArch64::STNT1B_ZRI:
5016 case AArch64::STNT1H_ZRI:
5017 case AArch64::STNT1W_ZRI:
5018 case AArch64::STNT1D_ZRI:
5019 case AArch64::LDNF1B_IMM:
5020 case AArch64::LDNF1H_IMM:
5021 case AArch64::LDNF1W_IMM:
5022 case AArch64::LDNF1D_IMM:
5023 // A full vectors worth of data
5024 // Width = mbytes * elements
5025 Scale = Width = TypeSize::getScalable(16);
5026 MinOffset = -8;
5027 MaxOffset = 7;
5028 break;
5029 case AArch64::LD2B_IMM:
5030 case AArch64::LD2H_IMM:
5031 case AArch64::LD2W_IMM:
5032 case AArch64::LD2D_IMM:
5033 case AArch64::ST2B_IMM:
5034 case AArch64::ST2H_IMM:
5035 case AArch64::ST2W_IMM:
5036 case AArch64::ST2D_IMM:
5037 case AArch64::LD1B_2Z_IMM:
5038 case AArch64::LD1B_2Z_STRIDED_IMM:
5039 case AArch64::LD1H_2Z_IMM:
5040 case AArch64::LD1H_2Z_STRIDED_IMM:
5041 case AArch64::LD1W_2Z_IMM:
5042 case AArch64::LD1W_2Z_STRIDED_IMM:
5043 case AArch64::LD1D_2Z_IMM:
5044 case AArch64::LD1D_2Z_STRIDED_IMM:
5045 case AArch64::LD1B_2Z_IMM_PSEUDO:
5046 case AArch64::LD1H_2Z_IMM_PSEUDO:
5047 case AArch64::LD1W_2Z_IMM_PSEUDO:
5048 case AArch64::LD1D_2Z_IMM_PSEUDO:
5049 case AArch64::ST1B_2Z_IMM:
5050 case AArch64::ST1B_2Z_STRIDED_IMM:
5051 case AArch64::ST1H_2Z_IMM:
5052 case AArch64::ST1H_2Z_STRIDED_IMM:
5053 case AArch64::ST1W_2Z_IMM:
5054 case AArch64::ST1W_2Z_STRIDED_IMM:
5055 case AArch64::ST1D_2Z_IMM:
5056 case AArch64::ST1D_2Z_STRIDED_IMM:
5057 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5058 case AArch64::LDNT1B_2Z_IMM:
5059 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5060 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5061 case AArch64::LDNT1H_2Z_IMM:
5062 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5063 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5064 case AArch64::LDNT1W_2Z_IMM:
5065 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5066 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5067 case AArch64::LDNT1D_2Z_IMM:
5068 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5069 case AArch64::STNT1B_2Z_IMM:
5070 case AArch64::STNT1B_2Z_STRIDED_IMM:
5071 case AArch64::STNT1H_2Z_IMM:
5072 case AArch64::STNT1H_2Z_STRIDED_IMM:
5073 case AArch64::STNT1W_2Z_IMM:
5074 case AArch64::STNT1W_2Z_STRIDED_IMM:
5075 case AArch64::STNT1D_2Z_IMM:
5076 case AArch64::STNT1D_2Z_STRIDED_IMM:
5077 case AArch64::ST1B_2Z_IMM_PSEUDO:
5078 case AArch64::ST1H_2Z_IMM_PSEUDO:
5079 case AArch64::ST1W_2Z_IMM_PSEUDO:
5080 case AArch64::ST1D_2Z_IMM_PSEUDO:
5081 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5082 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5083 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5084 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5085 Scale = Width = TypeSize::getScalable(16 * 2);
5086 MinOffset = -8;
5087 MaxOffset = 7;
5088 break;
5089 case AArch64::LD3B_IMM:
5090 case AArch64::LD3H_IMM:
5091 case AArch64::LD3W_IMM:
5092 case AArch64::LD3D_IMM:
5093 case AArch64::ST3B_IMM:
5094 case AArch64::ST3H_IMM:
5095 case AArch64::ST3W_IMM:
5096 case AArch64::ST3D_IMM:
5097 Scale = Width = TypeSize::getScalable(16 * 3);
5098 MinOffset = -8;
5099 MaxOffset = 7;
5100 break;
5101 case AArch64::LD4B_IMM:
5102 case AArch64::LD4H_IMM:
5103 case AArch64::LD4W_IMM:
5104 case AArch64::LD4D_IMM:
5105 case AArch64::ST4B_IMM:
5106 case AArch64::ST4H_IMM:
5107 case AArch64::ST4W_IMM:
5108 case AArch64::ST4D_IMM:
5109 case AArch64::LD1B_4Z_IMM:
5110 case AArch64::LD1B_4Z_STRIDED_IMM:
5111 case AArch64::LD1H_4Z_IMM:
5112 case AArch64::LD1H_4Z_STRIDED_IMM:
5113 case AArch64::LD1W_4Z_IMM:
5114 case AArch64::LD1W_4Z_STRIDED_IMM:
5115 case AArch64::LD1D_4Z_IMM:
5116 case AArch64::LD1D_4Z_STRIDED_IMM:
5117 case AArch64::LD1B_4Z_IMM_PSEUDO:
5118 case AArch64::LD1H_4Z_IMM_PSEUDO:
5119 case AArch64::LD1W_4Z_IMM_PSEUDO:
5120 case AArch64::LD1D_4Z_IMM_PSEUDO:
5121 case AArch64::ST1B_4Z_IMM:
5122 case AArch64::ST1B_4Z_STRIDED_IMM:
5123 case AArch64::ST1H_4Z_IMM:
5124 case AArch64::ST1H_4Z_STRIDED_IMM:
5125 case AArch64::ST1W_4Z_IMM:
5126 case AArch64::ST1W_4Z_STRIDED_IMM:
5127 case AArch64::ST1D_4Z_IMM:
5128 case AArch64::ST1D_4Z_STRIDED_IMM:
5129 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5130 case AArch64::LDNT1B_4Z_IMM:
5131 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5132 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5133 case AArch64::LDNT1H_4Z_IMM:
5134 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5135 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5136 case AArch64::LDNT1W_4Z_IMM:
5137 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5138 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5139 case AArch64::LDNT1D_4Z_IMM:
5140 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5141 case AArch64::STNT1B_4Z_IMM:
5142 case AArch64::STNT1B_4Z_STRIDED_IMM:
5143 case AArch64::STNT1H_4Z_IMM:
5144 case AArch64::STNT1H_4Z_STRIDED_IMM:
5145 case AArch64::STNT1W_4Z_IMM:
5146 case AArch64::STNT1W_4Z_STRIDED_IMM:
5147 case AArch64::STNT1D_4Z_IMM:
5148 case AArch64::STNT1D_4Z_STRIDED_IMM:
5149 case AArch64::ST1B_4Z_IMM_PSEUDO:
5150 case AArch64::ST1H_4Z_IMM_PSEUDO:
5151 case AArch64::ST1W_4Z_IMM_PSEUDO:
5152 case AArch64::ST1D_4Z_IMM_PSEUDO:
5153 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5154 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5155 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5156 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5157 Scale = Width = TypeSize::getScalable(16 * 4);
5158 MinOffset = -8;
5159 MaxOffset = 7;
5160 break;
5161 case AArch64::LD1B_H_IMM:
5162 case AArch64::LD1SB_H_IMM:
5163 case AArch64::LD1H_S_IMM:
5164 case AArch64::LD1SH_S_IMM:
5165 case AArch64::LD1W_D_IMM:
5166 case AArch64::LD1SW_D_IMM:
5167 case AArch64::ST1B_H_IMM:
5168 case AArch64::ST1H_S_IMM:
5169 case AArch64::ST1W_D_IMM:
5170 case AArch64::LDNF1B_H_IMM:
5171 case AArch64::LDNF1SB_H_IMM:
5172 case AArch64::LDNF1H_S_IMM:
5173 case AArch64::LDNF1SH_S_IMM:
5174 case AArch64::LDNF1W_D_IMM:
5175 case AArch64::LDNF1SW_D_IMM:
5176 // A half vector worth of data
5177 // Width = mbytes * elements
5178 Scale = Width = TypeSize::getScalable(8);
5179 MinOffset = -8;
5180 MaxOffset = 7;
5181 break;
5182 case AArch64::LD1B_S_IMM:
5183 case AArch64::LD1SB_S_IMM:
5184 case AArch64::LD1H_D_IMM:
5185 case AArch64::LD1SH_D_IMM:
5186 case AArch64::ST1B_S_IMM:
5187 case AArch64::ST1H_D_IMM:
5188 case AArch64::LDNF1B_S_IMM:
5189 case AArch64::LDNF1SB_S_IMM:
5190 case AArch64::LDNF1H_D_IMM:
5191 case AArch64::LDNF1SH_D_IMM:
5192 // A quarter vector worth of data
5193 // Width = mbytes * elements
5194 Scale = Width = TypeSize::getScalable(4);
5195 MinOffset = -8;
5196 MaxOffset = 7;
5197 break;
5198 case AArch64::LD1B_D_IMM:
5199 case AArch64::LD1SB_D_IMM:
5200 case AArch64::ST1B_D_IMM:
5201 case AArch64::LDNF1B_D_IMM:
5202 case AArch64::LDNF1SB_D_IMM:
5203 // A eighth vector worth of data
5204 // Width = mbytes * elements
5205 Scale = Width = TypeSize::getScalable(2);
5206 MinOffset = -8;
5207 MaxOffset = 7;
5208 break;
5209 case AArch64::ST2Gi:
5210 case AArch64::ST2GPreIndex:
5211 case AArch64::ST2GPostIndex:
5212 case AArch64::STZ2Gi:
5213 case AArch64::STZ2GPreIndex:
5214 case AArch64::STZ2GPostIndex:
5215 Scale = TypeSize::getFixed(16);
5216 Width = TypeSize::getFixed(32);
5217 MinOffset = -256;
5218 MaxOffset = 255;
5219 break;
5220 case AArch64::STGPi:
5221 case AArch64::STGPpost:
5222 case AArch64::STGPpre:
5223 Scale = Width = TypeSize::getFixed(16);
5224 MinOffset = -64;
5225 MaxOffset = 63;
5226 break;
5227 case AArch64::LD1RB_IMM:
5228 case AArch64::LD1RB_H_IMM:
5229 case AArch64::LD1RB_S_IMM:
5230 case AArch64::LD1RB_D_IMM:
5231 case AArch64::LD1RSB_H_IMM:
5232 case AArch64::LD1RSB_S_IMM:
5233 case AArch64::LD1RSB_D_IMM:
5234 Scale = Width = TypeSize::getFixed(1);
5235 MinOffset = 0;
5236 MaxOffset = 63;
5237 break;
5238 case AArch64::LD1RH_IMM:
5239 case AArch64::LD1RH_S_IMM:
5240 case AArch64::LD1RH_D_IMM:
5241 case AArch64::LD1RSH_S_IMM:
5242 case AArch64::LD1RSH_D_IMM:
5243 Scale = Width = TypeSize::getFixed(2);
5244 MinOffset = 0;
5245 MaxOffset = 63;
5246 break;
5247 case AArch64::LD1RW_IMM:
5248 case AArch64::LD1RW_D_IMM:
5249 case AArch64::LD1RSW_IMM:
5250 Scale = Width = TypeSize::getFixed(4);
5251 MinOffset = 0;
5252 MaxOffset = 63;
5253 break;
5254 case AArch64::LD1RD_IMM:
5255 Scale = Width = TypeSize::getFixed(8);
5256 MinOffset = 0;
5257 MaxOffset = 63;
5258 break;
5259 }
5260
5261 return true;
5262}
5263
5264// Scaling factor for unscaled load or store.
5266 switch (Opc) {
5267 default:
5268 llvm_unreachable("Opcode has unknown scale!");
5269 case AArch64::LDRBui:
5270 case AArch64::LDRBBui:
5271 case AArch64::LDURBBi:
5272 case AArch64::LDRSBWui:
5273 case AArch64::LDURSBWi:
5274 case AArch64::STRBui:
5275 case AArch64::STRBBui:
5276 case AArch64::STURBBi:
5277 return 1;
5278 case AArch64::LDRHui:
5279 case AArch64::LDRHHui:
5280 case AArch64::LDURHHi:
5281 case AArch64::LDRSHWui:
5282 case AArch64::LDURSHWi:
5283 case AArch64::STRHui:
5284 case AArch64::STRHHui:
5285 case AArch64::STURHHi:
5286 return 2;
5287 case AArch64::LDRSui:
5288 case AArch64::LDURSi:
5289 case AArch64::LDRSpre:
5290 case AArch64::LDRSWui:
5291 case AArch64::LDURSWi:
5292 case AArch64::LDRSWpre:
5293 case AArch64::LDRWpre:
5294 case AArch64::LDRWui:
5295 case AArch64::LDURWi:
5296 case AArch64::STRSui:
5297 case AArch64::STURSi:
5298 case AArch64::STRSpre:
5299 case AArch64::STRWui:
5300 case AArch64::STURWi:
5301 case AArch64::STRWpre:
5302 case AArch64::LDPSi:
5303 case AArch64::LDPSWi:
5304 case AArch64::LDPWi:
5305 case AArch64::STPSi:
5306 case AArch64::STPWi:
5307 return 4;
5308 case AArch64::LDRDui:
5309 case AArch64::LDURDi:
5310 case AArch64::LDRDpre:
5311 case AArch64::LDRXui:
5312 case AArch64::LDURXi:
5313 case AArch64::LDRXpre:
5314 case AArch64::STRDui:
5315 case AArch64::STURDi:
5316 case AArch64::STRDpre:
5317 case AArch64::STRXui:
5318 case AArch64::STURXi:
5319 case AArch64::STRXpre:
5320 case AArch64::LDPDi:
5321 case AArch64::LDPXi:
5322 case AArch64::STPDi:
5323 case AArch64::STPXi:
5324 return 8;
5325 case AArch64::LDRQui:
5326 case AArch64::LDURQi:
5327 case AArch64::STRQui:
5328 case AArch64::STURQi:
5329 case AArch64::STRQpre:
5330 case AArch64::LDPQi:
5331 case AArch64::LDRQpre:
5332 case AArch64::STPQi:
5333 case AArch64::STGi:
5334 case AArch64::STZGi:
5335 case AArch64::ST2Gi:
5336 case AArch64::STZ2Gi:
5337 case AArch64::STGPi:
5338 return 16;
5339 }
5340}
5341
5343 switch (MI.getOpcode()) {
5344 default:
5345 return false;
5346 case AArch64::LDRWpre:
5347 case AArch64::LDRXpre:
5348 case AArch64::LDRSWpre:
5349 case AArch64::LDRSpre:
5350 case AArch64::LDRDpre:
5351 case AArch64::LDRQpre:
5352 return true;
5353 }
5354}
5355
5357 switch (MI.getOpcode()) {
5358 default:
5359 return false;
5360 case AArch64::STRWpre:
5361 case AArch64::STRXpre:
5362 case AArch64::STRSpre:
5363 case AArch64::STRDpre:
5364 case AArch64::STRQpre:
5365 return true;
5366 }
5367}
5368
5370 return isPreLd(MI) || isPreSt(MI);
5371}
5372
5374 switch (MI.getOpcode()) {
5375 default:
5376 return false;
5377 case AArch64::LDURBBi:
5378 case AArch64::LDURHHi:
5379 case AArch64::LDURWi:
5380 case AArch64::LDRBBui:
5381 case AArch64::LDRHHui:
5382 case AArch64::LDRWui:
5383 case AArch64::LDRBBroX:
5384 case AArch64::LDRHHroX:
5385 case AArch64::LDRWroX:
5386 case AArch64::LDRBBroW:
5387 case AArch64::LDRHHroW:
5388 case AArch64::LDRWroW:
5389 return true;
5390 }
5391}
5392
5394 switch (MI.getOpcode()) {
5395 default:
5396 return false;
5397 case AArch64::LDURSBWi:
5398 case AArch64::LDURSHWi:
5399 case AArch64::LDURSBXi:
5400 case AArch64::LDURSHXi:
5401 case AArch64::LDURSWi:
5402 case AArch64::LDRSBWui:
5403 case AArch64::LDRSHWui:
5404 case AArch64::LDRSBXui:
5405 case AArch64::LDRSHXui:
5406 case AArch64::LDRSWui:
5407 case AArch64::LDRSBWroX:
5408 case AArch64::LDRSHWroX:
5409 case AArch64::LDRSBXroX:
5410 case AArch64::LDRSHXroX:
5411 case AArch64::LDRSWroX:
5412 case AArch64::LDRSBWroW:
5413 case AArch64::LDRSHWroW:
5414 case AArch64::LDRSBXroW:
5415 case AArch64::LDRSHXroW:
5416 case AArch64::LDRSWroW:
5417 return true;
5418 }
5419}
5420
5422 switch (MI.getOpcode()) {
5423 default:
5424 return false;
5425 case AArch64::LDPSi:
5426 case AArch64::LDPSWi:
5427 case AArch64::LDPDi:
5428 case AArch64::LDPQi:
5429 case AArch64::LDPWi:
5430 case AArch64::LDPXi:
5431 case AArch64::STPSi:
5432 case AArch64::STPDi:
5433 case AArch64::STPQi:
5434 case AArch64::STPWi:
5435 case AArch64::STPXi:
5436 case AArch64::STGPi:
5437 return true;
5438 }
5439}
5440
5442 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5443 unsigned Idx =
5445 : 1;
5446 return MI.getOperand(Idx);
5447}
5448
5449const MachineOperand &
5451 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5452 unsigned Idx =
5454 : 2;
5455 return MI.getOperand(Idx);
5456}
5457
5458const MachineOperand &
5460 switch (MI.getOpcode()) {
5461 default:
5462 llvm_unreachable("Unexpected opcode");
5463 case AArch64::LDRBroX:
5464 case AArch64::LDRBBroX:
5465 case AArch64::LDRSBXroX:
5466 case AArch64::LDRSBWroX:
5467 case AArch64::LDRHroX:
5468 case AArch64::LDRHHroX:
5469 case AArch64::LDRSHXroX:
5470 case AArch64::LDRSHWroX:
5471 case AArch64::LDRWroX:
5472 case AArch64::LDRSroX:
5473 case AArch64::LDRSWroX:
5474 case AArch64::LDRDroX:
5475 case AArch64::LDRXroX:
5476 case AArch64::LDRQroX:
5477 return MI.getOperand(4);
5478 }
5479}
5480
5482 Register Reg) {
5483 if (MI.getParent() == nullptr)
5484 return nullptr;
5485 const MachineFunction *MF = MI.getParent()->getParent();
5486 return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr;
5487}
5488
5490 auto IsHFPR = [&](const MachineOperand &Op) {
5491 if (!Op.isReg())
5492 return false;
5493 auto Reg = Op.getReg();
5494 if (Reg.isPhysical())
5495 return AArch64::FPR16RegClass.contains(Reg);
5496 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5497 return TRC == &AArch64::FPR16RegClass ||
5498 TRC == &AArch64::FPR16_loRegClass;
5499 };
5500 return llvm::any_of(MI.operands(), IsHFPR);
5501}
5502
5504 auto IsQFPR = [&](const MachineOperand &Op) {
5505 if (!Op.isReg())
5506 return false;
5507 auto Reg = Op.getReg();
5508 if (Reg.isPhysical())
5509 return AArch64::FPR128RegClass.contains(Reg);
5510 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5511 return TRC == &AArch64::FPR128RegClass ||
5512 TRC == &AArch64::FPR128_loRegClass;
5513 };
5514 return llvm::any_of(MI.operands(), IsQFPR);
5515}
5516
5518 switch (MI.getOpcode()) {
5519 case AArch64::BRK:
5520 case AArch64::HLT:
5521 case AArch64::PACIASP:
5522 case AArch64::PACIBSP:
5523 // Implicit BTI behavior.
5524 return true;
5525 case AArch64::PAUTH_PROLOGUE:
5526 // PAUTH_PROLOGUE expands to PACI(A|B)SP.
5527 return true;
5528 case AArch64::HINT: {
5529 unsigned Imm = MI.getOperand(0).getImm();
5530 // Explicit BTI instruction.
5531 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5532 return true;
5533 // PACI(A|B)SP instructions.
5534 if (Imm == 25 || Imm == 27)
5535 return true;
5536 return false;
5537 }
5538 default:
5539 return false;
5540 }
5541}
5542
5544 if (Reg == 0)
5545 return false;
5546 assert(Reg.isPhysical() && "Expected physical register in isFpOrNEON");
5547 return AArch64::FPR128RegClass.contains(Reg) ||
5548 AArch64::FPR64RegClass.contains(Reg) ||
5549 AArch64::FPR32RegClass.contains(Reg) ||
5550 AArch64::FPR16RegClass.contains(Reg) ||
5551 AArch64::FPR8RegClass.contains(Reg);
5552}
5553
5555 auto IsFPR = [&](const MachineOperand &Op) {
5556 if (!Op.isReg())
5557 return false;
5558 auto Reg = Op.getReg();
5559 if (Reg.isPhysical())
5560 return isFpOrNEON(Reg);
5561
5562 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5563 return TRC == &AArch64::FPR128RegClass ||
5564 TRC == &AArch64::FPR128_loRegClass ||
5565 TRC == &AArch64::FPR64RegClass ||
5566 TRC == &AArch64::FPR64_loRegClass ||
5567 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5568 TRC == &AArch64::FPR8RegClass;
5569 };
5570 return llvm::any_of(MI.operands(), IsFPR);
5571}
5572
5573// Scale the unscaled offsets. Returns false if the unscaled offset can't be
5574// scaled.
5575static bool scaleOffset(unsigned Opc, int64_t &Offset) {
5577
5578 // If the byte-offset isn't a multiple of the stride, we can't scale this
5579 // offset.
5580 if (Offset % Scale != 0)
5581 return false;
5582
5583 // Convert the byte-offset used by unscaled into an "element" offset used
5584 // by the scaled pair load/store instructions.
5585 Offset /= Scale;
5586 return true;
5587}
5588
5589static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
5590 if (FirstOpc == SecondOpc)
5591 return true;
5592 // We can also pair sign-ext and zero-ext instructions.
5593 switch (FirstOpc) {
5594 default:
5595 return false;
5596 case AArch64::STRSui:
5597 case AArch64::STURSi:
5598 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5599 case AArch64::STRDui:
5600 case AArch64::STURDi:
5601 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5602 case AArch64::STRQui:
5603 case AArch64::STURQi:
5604 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5605 case AArch64::STRWui:
5606 case AArch64::STURWi:
5607 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5608 case AArch64::STRXui:
5609 case AArch64::STURXi:
5610 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5611 case AArch64::LDRSui:
5612 case AArch64::LDURSi:
5613 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5614 case AArch64::LDRDui:
5615 case AArch64::LDURDi:
5616 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5617 case AArch64::LDRQui:
5618 case AArch64::LDURQi:
5619 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5620 case AArch64::LDRWui:
5621 case AArch64::LDURWi:
5622 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5623 case AArch64::LDRSWui:
5624 case AArch64::LDURSWi:
5625 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5626 case AArch64::LDRXui:
5627 case AArch64::LDURXi:
5628 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5629 }
5630 // These instructions can't be paired based on their opcodes.
5631 return false;
5632}
5633
5634static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1,
5635 int64_t Offset1, unsigned Opcode1, int FI2,
5636 int64_t Offset2, unsigned Opcode2) {
5637 // Accesses through fixed stack object frame indices may access a different
5638 // fixed stack slot. Check that the object offsets + offsets match.
5639 if (MFI.isFixedObjectIndex(FI1) && MFI.isFixedObjectIndex(FI2)) {
5640 int64_t ObjectOffset1 = MFI.getObjectOffset(FI1);
5641 int64_t ObjectOffset2 = MFI.getObjectOffset(FI2);
5642 assert(ObjectOffset1 <= ObjectOffset2 && "Object offsets are not ordered.");
5643 // Convert to scaled object offsets.
5644 int Scale1 = AArch64InstrInfo::getMemScale(Opcode1);
5645 if (ObjectOffset1 % Scale1 != 0)
5646 return false;
5647 ObjectOffset1 /= Scale1;
5648 int Scale2 = AArch64InstrInfo::getMemScale(Opcode2);
5649 if (ObjectOffset2 % Scale2 != 0)
5650 return false;
5651 ObjectOffset2 /= Scale2;
5652 ObjectOffset1 += Offset1;
5653 ObjectOffset2 += Offset2;
5654 return ObjectOffset1 + 1 == ObjectOffset2;
5655 }
5656
5657 return FI1 == FI2;
5658}
5659
5660/// Detect opportunities for ldp/stp formation.
5661///
5662/// Only called for LdSt for which getMemOperandWithOffset returns true.
5664 ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
5665 bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
5666 int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
5667 unsigned NumBytes) const {
5668 assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
5669 const MachineOperand &BaseOp1 = *BaseOps1.front();
5670 const MachineOperand &BaseOp2 = *BaseOps2.front();
5671 const MachineInstr &FirstLdSt = *BaseOp1.getParent();
5672 const MachineInstr &SecondLdSt = *BaseOp2.getParent();
5673 if (BaseOp1.getType() != BaseOp2.getType())
5674 return false;
5675
5676 assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
5677 "Only base registers and frame indices are supported.");
5678
5679 // Check for both base regs and base FI.
5680 if (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg())
5681 return false;
5682
5683 // Only cluster up to a single pair.
5684 if (ClusterSize > 2)
5685 return false;
5686
5687 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
5688 return false;
5689
5690 // Can we pair these instructions based on their opcodes?
5691 unsigned FirstOpc = FirstLdSt.getOpcode();
5692 unsigned SecondOpc = SecondLdSt.getOpcode();
5693 if (!canPairLdStOpc(FirstOpc, SecondOpc))
5694 return false;
5695
5696 // Can't merge volatiles or load/stores that have a hint to avoid pair
5697 // formation, for example.
5698 if (!isCandidateToMergeOrPair(FirstLdSt) ||
5699 !isCandidateToMergeOrPair(SecondLdSt))
5700 return false;
5701
5702 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
5703 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
5704 if (hasUnscaledLdStOffset(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
5705 return false;
5706
5707 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
5708 if (hasUnscaledLdStOffset(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
5709 return false;
5710
5711 // Pairwise instructions have a 7-bit signed offset field.
5712 if (Offset1 > 63 || Offset1 < -64)
5713 return false;
5714
5715 // The caller should already have ordered First/SecondLdSt by offset.
5716 // Note: except for non-equal frame index bases
5717 if (BaseOp1.isFI()) {
5718 assert((!BaseOp1.isIdenticalTo(BaseOp2) || Offset1 <= Offset2) &&
5719 "Caller should have ordered offsets.");
5720
5721 const MachineFrameInfo &MFI =
5722 FirstLdSt.getParent()->getParent()->getFrameInfo();
5723 return shouldClusterFI(MFI, BaseOp1.getIndex(), Offset1, FirstOpc,
5724 BaseOp2.getIndex(), Offset2, SecondOpc);
5725 }
5726
5727 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
5728
5729 return Offset1 + 1 == Offset2;
5730}
5731
5733 MCRegister Reg, unsigned SubIdx,
5734 RegState State,
5735 const TargetRegisterInfo *TRI) {
5736 if (!SubIdx)
5737 return MIB.addReg(Reg, State);
5738
5739 if (Reg.isPhysical())
5740 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
5741 return MIB.addReg(Reg, State, SubIdx);
5742}
5743
5744static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg,
5745 unsigned NumRegs) {
5746 // We really want the positive remainder mod 32 here, that happens to be
5747 // easily obtainable with a mask.
5748 return ((DestReg - SrcReg) & 0x1f) < NumRegs;
5749}
5750
5753 const DebugLoc &DL, MCRegister DestReg,
5754 MCRegister SrcReg, bool KillSrc,
5755 unsigned Opcode,
5756 ArrayRef<unsigned> Indices) const {
5757 assert(Subtarget.hasNEON() && "Unexpected register copy without NEON");
5759 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5760 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5761 unsigned NumRegs = Indices.size();
5762
5763 int SubReg = 0, End = NumRegs, Incr = 1;
5764 if (forwardCopyWillClobberTuple(DestEncoding, SrcEncoding, NumRegs)) {
5765 SubReg = NumRegs - 1;
5766 End = -1;
5767 Incr = -1;
5768 }
5769
5770 for (; SubReg != End; SubReg += Incr) {
5771 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5772 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5773 AddSubReg(MIB, SrcReg, Indices[SubReg], {}, TRI);
5774 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5775 }
5776}
5777
5780 const DebugLoc &DL, MCRegister DestReg,
5781 MCRegister SrcReg, bool KillSrc,
5782 unsigned Opcode, unsigned ZeroReg,
5783 llvm::ArrayRef<unsigned> Indices) const {
5785 unsigned NumRegs = Indices.size();
5786
5787#ifndef NDEBUG
5788 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5789 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5790 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5791 "GPR reg sequences should not be able to overlap");
5792#endif
5793
5794 for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5795 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5796 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5797 MIB.addReg(ZeroReg);
5798 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5799 MIB.addImm(0);
5800 }
5801}
5802
5803/// Returns true if the instruction at I is in a streaming call site region,
5804/// within a single basic block.
5805/// A "call site streaming region" starts after smstart and ends at smstop
5806/// around a call to a streaming function. This walks backward from I.
5809 MachineFunction &MF = *MBB.getParent();
5811 if (!AFI->hasStreamingModeChanges())
5812 return false;
5813 // Walk backwards to find smstart/smstop
5814 for (MachineInstr &MI : reverse(make_range(MBB.begin(), I))) {
5815 unsigned Opc = MI.getOpcode();
5816 if (Opc == AArch64::MSRpstatesvcrImm1 || Opc == AArch64::MSRpstatePseudo) {
5817 // Check if this is SM change (not ZA)
5818 int64_t PState = MI.getOperand(0).getImm();
5819 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5820 // Operand 1 is 1 for start, 0 for stop
5821 return MI.getOperand(1).getImm() == 1;
5822 }
5823 }
5824 }
5825 return false;
5826}
5827
5828/// Returns true if in a streaming call site region without SME-FA64.
5829static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget,
5832 return !Subtarget.hasSMEFA64() && isInStreamingCallSiteRegion(MBB, I);
5833}
5834
5837 const DebugLoc &DL, Register DestReg,
5838 Register SrcReg, bool KillSrc,
5839 bool RenamableDest,
5840 bool RenamableSrc) const {
5841 ++NumCopyInstrs;
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 Z register by ORRing with itself.
5995 if (AArch64::ZPRRegClass.contains(DestReg) &&
5996 AArch64::ZPRRegClass.contains(SrcReg)) {
5997 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5998 "Unexpected SVE register.");
5999 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ), DestReg)
6000 .addReg(SrcReg)
6001 .addReg(SrcReg, getKillRegState(KillSrc));
6002 return;
6003 }
6004
6005 // Copy a Z register pair by copying the individual sub-registers.
6006 if ((AArch64::ZPR2RegClass.contains(DestReg) ||
6007 AArch64::ZPR2StridedOrContiguousRegClass.contains(DestReg)) &&
6008 (AArch64::ZPR2RegClass.contains(SrcReg) ||
6009 AArch64::ZPR2StridedOrContiguousRegClass.contains(SrcReg))) {
6010 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6011 "Unexpected SVE register.");
6012 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6013 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6014 Indices);
6015 return;
6016 }
6017
6018 // Copy a Z register triple by copying the individual sub-registers.
6019 if (AArch64::ZPR3RegClass.contains(DestReg) &&
6020 AArch64::ZPR3RegClass.contains(SrcReg)) {
6021 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6022 "Unexpected SVE register.");
6023 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6024 AArch64::zsub2};
6025 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6026 Indices);
6027 return;
6028 }
6029
6030 // Copy a Z register quad by copying the individual sub-registers.
6031 if ((AArch64::ZPR4RegClass.contains(DestReg) ||
6032 AArch64::ZPR4StridedOrContiguousRegClass.contains(DestReg)) &&
6033 (AArch64::ZPR4RegClass.contains(SrcReg) ||
6034 AArch64::ZPR4StridedOrContiguousRegClass.contains(SrcReg))) {
6035 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6036 "Unexpected SVE register.");
6037 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6038 AArch64::zsub2, AArch64::zsub3};
6039 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6040 Indices);
6041 return;
6042 }
6043
6044 // Copy a DDDD register quad by copying the individual sub-registers.
6045 if (AArch64::DDDDRegClass.contains(DestReg) &&
6046 AArch64::DDDDRegClass.contains(SrcReg)) {
6047 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6048 AArch64::dsub2, AArch64::dsub3};
6049 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6050 Indices);
6051 return;
6052 }
6053
6054 // Copy a DDD register triple by copying the individual sub-registers.
6055 if (AArch64::DDDRegClass.contains(DestReg) &&
6056 AArch64::DDDRegClass.contains(SrcReg)) {
6057 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6058 AArch64::dsub2};
6059 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6060 Indices);
6061 return;
6062 }
6063
6064 // Copy a DD register pair by copying the individual sub-registers.
6065 if (AArch64::DDRegClass.contains(DestReg) &&
6066 AArch64::DDRegClass.contains(SrcReg)) {
6067 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6068 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6069 Indices);
6070 return;
6071 }
6072
6073 // Copy a QQQQ register quad by copying the individual sub-registers.
6074 if (AArch64::QQQQRegClass.contains(DestReg) &&
6075 AArch64::QQQQRegClass.contains(SrcReg)) {
6076 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6077 AArch64::qsub2, AArch64::qsub3};
6078 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6079 Indices);
6080 return;
6081 }
6082
6083 // Copy a QQQ register triple by copying the individual sub-registers.
6084 if (AArch64::QQQRegClass.contains(DestReg) &&
6085 AArch64::QQQRegClass.contains(SrcReg)) {
6086 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6087 AArch64::qsub2};
6088 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6089 Indices);
6090 return;
6091 }
6092
6093 // Copy a QQ register pair by copying the individual sub-registers.
6094 if (AArch64::QQRegClass.contains(DestReg) &&
6095 AArch64::QQRegClass.contains(SrcReg)) {
6096 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6097 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6098 Indices);
6099 return;
6100 }
6101
6102 if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
6103 AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
6104 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6105 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
6106 AArch64::XZR, Indices);
6107 return;
6108 }
6109
6110 if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
6111 AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
6112 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6113 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
6114 AArch64::WZR, Indices);
6115 return;
6116 }
6117
6118 if (AArch64::FPR128RegClass.contains(DestReg) &&
6119 AArch64::FPR128RegClass.contains(SrcReg)) {
6120 // In streaming regions, NEON is illegal but streaming-SVE is available.
6121 // Use SVE for copies if we're in a streaming region and SME is available.
6122 // With +sme-fa64, NEON is legal in streaming mode so we can use it.
6123 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6124 !Subtarget.isNeonAvailable()) ||
6125 mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6126 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ))
6127 .addReg(AArch64::Z0 + (DestReg - AArch64::Q0), RegState::Define)
6128 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6129 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6130 } else if (Subtarget.isNeonAvailable()) {
6131 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
6132 .addReg(SrcReg)
6133 .addReg(SrcReg, getKillRegState(KillSrc));
6134 if (Subtarget.hasZeroCycleRegMoveFPR128())
6135 ++NumZCRegMoveInstrsFPR;
6136 } else {
6137 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
6138 .addReg(AArch64::SP, RegState::Define)
6139 .addReg(SrcReg, getKillRegState(KillSrc))
6140 .addReg(AArch64::SP)
6141 .addImm(-16);
6142 BuildMI(MBB, I, DL, get(AArch64::LDRQpost))
6143 .addReg(AArch64::SP, RegState::Define)
6144 .addReg(DestReg, RegState::Define)
6145 .addReg(AArch64::SP)
6146 .addImm(16);
6147 }
6148 return;
6149 }
6150
6151 if (AArch64::FPR64RegClass.contains(DestReg) &&
6152 AArch64::FPR64RegClass.contains(SrcReg)) {
6153 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6154 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6155 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6156 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6157 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6158 &AArch64::FPR128RegClass);
6159 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6160 &AArch64::FPR128RegClass);
6161 // This instruction is reading and writing Q registers. This may upset
6162 // the register scavenger and machine verifier, so we need to indicate
6163 // that we are reading an undefined value from SrcRegQ, but a proper
6164 // value from SrcReg.
6165 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6166 .addReg(SrcRegQ, RegState::Undef)
6167 .addReg(SrcRegQ, RegState::Undef)
6168 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6169 ++NumZCRegMoveInstrsFPR;
6170 } else {
6171 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
6172 .addReg(SrcReg, getKillRegState(KillSrc));
6173 if (Subtarget.hasZeroCycleRegMoveFPR64())
6174 ++NumZCRegMoveInstrsFPR;
6175 }
6176 return;
6177 }
6178
6179 if (AArch64::FPR32RegClass.contains(DestReg) &&
6180 AArch64::FPR32RegClass.contains(SrcReg)) {
6181 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6182 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6183 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6184 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6185 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6186 &AArch64::FPR128RegClass);
6187 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6188 &AArch64::FPR128RegClass);
6189 // This instruction is reading and writing Q registers. This may upset
6190 // the register scavenger and machine verifier, so we need to indicate
6191 // that we are reading an undefined value from SrcRegQ, but a proper
6192 // value from SrcReg.
6193 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6194 .addReg(SrcRegQ, RegState::Undef)
6195 .addReg(SrcRegQ, RegState::Undef)
6196 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6197 ++NumZCRegMoveInstrsFPR;
6198 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6199 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6200 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6201 &AArch64::FPR64RegClass);
6202 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6203 &AArch64::FPR64RegClass);
6204 // This instruction is reading and writing D registers. This may upset
6205 // the register scavenger and machine verifier, so we need to indicate
6206 // that we are reading an undefined value from SrcRegD, but a proper
6207 // value from SrcReg.
6208 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6209 .addReg(SrcRegD, RegState::Undef)
6210 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6211 ++NumZCRegMoveInstrsFPR;
6212 } else {
6213 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6214 .addReg(SrcReg, getKillRegState(KillSrc));
6215 if (Subtarget.hasZeroCycleRegMoveFPR32())
6216 ++NumZCRegMoveInstrsFPR;
6217 }
6218 return;
6219 }
6220
6221 if (AArch64::FPR16RegClass.contains(DestReg) &&
6222 AArch64::FPR16RegClass.contains(SrcReg)) {
6223 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6224 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6225 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6226 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6227 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6228 &AArch64::FPR128RegClass);
6229 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6230 &AArch64::FPR128RegClass);
6231 // This instruction is reading and writing Q registers. This may upset
6232 // the register scavenger and machine verifier, so we need to indicate
6233 // that we are reading an undefined value from SrcRegQ, but a proper
6234 // value from SrcReg.
6235 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6236 .addReg(SrcRegQ, RegState::Undef)
6237 .addReg(SrcRegQ, RegState::Undef)
6238 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6239 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6240 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6241 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6242 &AArch64::FPR64RegClass);
6243 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6244 &AArch64::FPR64RegClass);
6245 // This instruction is reading and writing D registers. This may upset
6246 // the register scavenger and machine verifier, so we need to indicate
6247 // that we are reading an undefined value from SrcRegD, but a proper
6248 // value from SrcReg.
6249 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6250 .addReg(SrcRegD, RegState::Undef)
6251 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6252 } else {
6253 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6254 &AArch64::FPR32RegClass);
6255 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6256 &AArch64::FPR32RegClass);
6257 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6258 .addReg(SrcReg, getKillRegState(KillSrc));
6259 }
6260 return;
6261 }
6262
6263 if (AArch64::FPR8RegClass.contains(DestReg) &&
6264 AArch64::FPR8RegClass.contains(SrcReg)) {
6265 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6266 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6267 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6268 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6269 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6270 &AArch64::FPR128RegClass);
6271 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6272 &AArch64::FPR128RegClass);
6273 // This instruction is reading and writing Q registers. This may upset
6274 // the register scavenger and machine verifier, so we need to indicate
6275 // that we are reading an undefined value from SrcRegQ, but a proper
6276 // value from SrcReg.
6277 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6278 .addReg(SrcRegQ, RegState::Undef)
6279 .addReg(SrcRegQ, RegState::Undef)
6280 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6281 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6282 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6283 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6284 &AArch64::FPR64RegClass);
6285 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6286 &AArch64::FPR64RegClass);
6287 // This instruction is reading and writing D registers. This may upset
6288 // the register scavenger and machine verifier, so we need to indicate
6289 // that we are reading an undefined value from SrcRegD, but a proper
6290 // value from SrcReg.
6291 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6292 .addReg(SrcRegD, RegState::Undef)
6293 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6294 } else {
6295 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6296 &AArch64::FPR32RegClass);
6297 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6298 &AArch64::FPR32RegClass);
6299 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6300 .addReg(SrcReg, getKillRegState(KillSrc));
6301 }
6302 return;
6303 }
6304
6305 // Copies between GPR64 and FPR64.
6306 if (AArch64::FPR64RegClass.contains(DestReg) &&
6307 AArch64::GPR64RegClass.contains(SrcReg)) {
6308 if (AArch64::XZR == SrcReg) {
6309 BuildMI(MBB, I, DL, get(AArch64::FMOVD0), DestReg);
6310 } else {
6311 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
6312 .addReg(SrcReg, getKillRegState(KillSrc));
6313 }
6314 return;
6315 }
6316 if (AArch64::GPR64RegClass.contains(DestReg) &&
6317 AArch64::FPR64RegClass.contains(SrcReg)) {
6318 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
6319 .addReg(SrcReg, getKillRegState(KillSrc));
6320 return;
6321 }
6322 // Copies between GPR32 and FPR32.
6323 if (AArch64::FPR32RegClass.contains(DestReg) &&
6324 AArch64::GPR32RegClass.contains(SrcReg)) {
6325 if (AArch64::WZR == SrcReg) {
6326 BuildMI(MBB, I, DL, get(AArch64::FMOVS0), DestReg);
6327 } else {
6328 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
6329 .addReg(SrcReg, getKillRegState(KillSrc));
6330 }
6331 return;
6332 }
6333 if (AArch64::GPR32RegClass.contains(DestReg) &&
6334 AArch64::FPR32RegClass.contains(SrcReg)) {
6335 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
6336 .addReg(SrcReg, getKillRegState(KillSrc));
6337 return;
6338 }
6339
6340 if (DestReg == AArch64::NZCV) {
6341 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
6342 BuildMI(MBB, I, DL, get(AArch64::MSR))
6343 .addImm(AArch64SysReg::NZCV)
6344 .addReg(SrcReg, getKillRegState(KillSrc))
6345 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
6346 return;
6347 }
6348
6349 if (SrcReg == AArch64::NZCV) {
6350 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
6351 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
6352 .addImm(AArch64SysReg::NZCV)
6353 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
6354 return;
6355 }
6356
6357#ifndef NDEBUG
6358 errs() << RI.getRegAsmName(DestReg) << " = COPY " << RI.getRegAsmName(SrcReg)
6359 << "\n";
6360#endif
6361 llvm_unreachable("unimplemented reg-to-reg copy");
6362}
6363
6366 MachineBasicBlock::iterator InsertBefore,
6367 const MCInstrDesc &MCID,
6368 Register SrcReg, bool IsKill,
6369 unsigned SubIdx0, unsigned SubIdx1, int FI,
6370 MachineMemOperand *MMO) {
6371 Register SrcReg0 = SrcReg;
6372 Register SrcReg1 = SrcReg;
6373 if (SrcReg.isPhysical()) {
6374 SrcReg0 = TRI.getSubReg(SrcReg, SubIdx0);
6375 SubIdx0 = 0;
6376 SrcReg1 = TRI.getSubReg(SrcReg, SubIdx1);
6377 SubIdx1 = 0;
6378 }
6379 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6380 .addReg(SrcReg0, getKillRegState(IsKill), SubIdx0)
6381 .addReg(SrcReg1, getKillRegState(IsKill), SubIdx1)
6382 .addFrameIndex(FI)
6383 .addImm(0)
6384 .addMemOperand(MMO);
6385}
6386
6389 Register SrcReg, bool isKill, int FI,
6390 const TargetRegisterClass *RC,
6391 Register VReg,
6392 MachineInstr::MIFlag Flags) const {
6393 MachineFunction &MF = *MBB.getParent();
6394 MachineFrameInfo &MFI = MF.getFrameInfo();
6395
6397 MachineMemOperand *MMO =
6399 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6400 unsigned Opc = 0;
6401 bool Offset = true;
6403 unsigned StackID = TargetStackID::Default;
6404 switch (RI.getSpillSize(*RC)) {
6405 case 1:
6406 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6407 Opc = AArch64::STRBui;
6408 break;
6409 case 2: {
6410 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6411 Opc = AArch64::STRHui;
6412 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6413 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6414 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6415 "Unexpected register store without SVE store instructions");
6416 Opc = AArch64::STR_PXI;
6418 }
6419 break;
6420 }
6421 case 4:
6422 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6423 Opc = AArch64::STRWui;
6424 if (SrcReg.isVirtual())
6425 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
6426 else
6427 assert(SrcReg != AArch64::WSP);
6428 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6429 Opc = AArch64::STRSui;
6430 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6431 Opc = AArch64::STR_PPXI;
6433 }
6434 break;
6435 case 8:
6436 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6437 Opc = AArch64::STRXui;
6438 if (SrcReg.isVirtual())
6439 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
6440 else
6441 assert(SrcReg != AArch64::SP);
6442 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6443 Opc = AArch64::STRDui;
6444 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6446 get(AArch64::STPWi), SrcReg, isKill,
6447 AArch64::sube32, AArch64::subo32, FI, MMO);
6448 return;
6449 }
6450 break;
6451 case 16:
6452 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6453 Opc = AArch64::STRQui;
6454 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6455 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6456 Opc = AArch64::ST1Twov1d;
6457 Offset = false;
6458 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6460 get(AArch64::STPXi), SrcReg, isKill,
6461 AArch64::sube64, AArch64::subo64, FI, MMO);
6462 return;
6463 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6464 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6465 "Unexpected register store without SVE store instructions");
6466 Opc = AArch64::STR_ZXI;
6468 }
6469 break;
6470 case 24:
6471 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6472 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6473 Opc = AArch64::ST1Threev1d;
6474 Offset = false;
6475 }
6476 break;
6477 case 32:
6478 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6479 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6480 Opc = AArch64::ST1Fourv1d;
6481 Offset = false;
6482 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6483 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6484 Opc = AArch64::ST1Twov2d;
6485 Offset = false;
6486 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6487 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6488 "Unexpected register store without SVE store instructions");
6489 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6491 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6492 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6493 "Unexpected register store without SVE store instructions");
6494 Opc = AArch64::STR_ZZXI;
6496 }
6497 break;
6498 case 48:
6499 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6500 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6501 Opc = AArch64::ST1Threev2d;
6502 Offset = false;
6503 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6504 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6505 "Unexpected register store without SVE store instructions");
6506 Opc = AArch64::STR_ZZZXI;
6508 }
6509 break;
6510 case 64:
6511 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6512 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6513 Opc = AArch64::ST1Fourv2d;
6514 Offset = false;
6515 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6516 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6517 "Unexpected register store without SVE store instructions");
6518 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6520 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6521 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6522 "Unexpected register store without SVE store instructions");
6523 Opc = AArch64::STR_ZZZZXI;
6525 }
6526 break;
6527 }
6528 assert(Opc && "Unknown register class");
6529 MFI.setStackID(FI, StackID);
6530
6532 .addReg(SrcReg, getKillRegState(isKill))
6533 .addFrameIndex(FI);
6534
6535 if (Offset)
6536 MI.addImm(0);
6537 if (PNRReg.isValid())
6538 MI.addDef(PNRReg, RegState::Implicit);
6539 MI.addMemOperand(MMO);
6540}
6541
6544 MachineBasicBlock::iterator InsertBefore,
6545 const MCInstrDesc &MCID,
6546 Register DestReg, unsigned SubIdx0,
6547 unsigned SubIdx1, int FI,
6548 MachineMemOperand *MMO) {
6549 Register DestReg0 = DestReg;
6550 Register DestReg1 = DestReg;
6551 bool IsUndef = true;
6552 if (DestReg.isPhysical()) {
6553 DestReg0 = TRI.getSubReg(DestReg, SubIdx0);
6554 SubIdx0 = 0;
6555 DestReg1 = TRI.getSubReg(DestReg, SubIdx1);
6556 SubIdx1 = 0;
6557 IsUndef = false;
6558 }
6559 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6560 .addReg(DestReg0, RegState::Define | getUndefRegState(IsUndef), SubIdx0)
6561 .addReg(DestReg1, RegState::Define | getUndefRegState(IsUndef), SubIdx1)
6562 .addFrameIndex(FI)
6563 .addImm(0)
6564 .addMemOperand(MMO);
6565}
6566
6569 Register DestReg, int FI,
6570 const TargetRegisterClass *RC,
6571 Register VReg, unsigned SubReg,
6572 MachineInstr::MIFlag Flags) const {
6573 MachineFunction &MF = *MBB.getParent();
6574 MachineFrameInfo &MFI = MF.getFrameInfo();
6576 MachineMemOperand *MMO =
6578 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6579
6580 unsigned Opc = 0;
6581 bool Offset = true;
6582 unsigned StackID = TargetStackID::Default;
6584 switch (TRI.getSpillSize(*RC)) {
6585 case 1:
6586 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6587 Opc = AArch64::LDRBui;
6588 break;
6589 case 2: {
6590 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6591 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6592 Opc = AArch64::LDRHui;
6593 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6594 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6595 "Unexpected register load without SVE load instructions");
6596 if (IsPNR)
6597 PNRReg = DestReg;
6598 Opc = AArch64::LDR_PXI;
6600 }
6601 break;
6602 }
6603 case 4:
6604 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6605 Opc = AArch64::LDRWui;
6606 if (DestReg.isVirtual())
6607 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
6608 else
6609 assert(DestReg != AArch64::WSP);
6610 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6611 Opc = AArch64::LDRSui;
6612 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6613 Opc = AArch64::LDR_PPXI;
6615 }
6616 break;
6617 case 8:
6618 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6619 Opc = AArch64::LDRXui;
6620 if (DestReg.isVirtual())
6621 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
6622 else
6623 assert(DestReg != AArch64::SP);
6624 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6625 Opc = AArch64::LDRDui;
6626 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6628 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6629 AArch64::subo32, FI, MMO);
6630 return;
6631 }
6632 break;
6633 case 16:
6634 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6635 Opc = AArch64::LDRQui;
6636 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6637 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6638 Opc = AArch64::LD1Twov1d;
6639 Offset = false;
6640 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6642 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6643 AArch64::subo64, FI, MMO);
6644 return;
6645 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6646 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6647 "Unexpected register load without SVE load instructions");
6648 Opc = AArch64::LDR_ZXI;
6650 }
6651 break;
6652 case 24:
6653 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6654 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6655 Opc = AArch64::LD1Threev1d;
6656 Offset = false;
6657 }
6658 break;
6659 case 32:
6660 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6661 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6662 Opc = AArch64::LD1Fourv1d;
6663 Offset = false;
6664 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6665 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6666 Opc = AArch64::LD1Twov2d;
6667 Offset = false;
6668 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6669 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6670 "Unexpected register load without SVE load instructions");
6671 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6673 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6674 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6675 "Unexpected register load without SVE load instructions");
6676 Opc = AArch64::LDR_ZZXI;
6678 }
6679 break;
6680 case 48:
6681 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6682 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6683 Opc = AArch64::LD1Threev2d;
6684 Offset = false;
6685 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6686 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6687 "Unexpected register load without SVE load instructions");
6688 Opc = AArch64::LDR_ZZZXI;
6690 }
6691 break;
6692 case 64:
6693 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6694 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6695 Opc = AArch64::LD1Fourv2d;
6696 Offset = false;
6697 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6698 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6699 "Unexpected register load without SVE load instructions");
6700 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6702 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6703 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6704 "Unexpected register load without SVE load instructions");
6705 Opc = AArch64::LDR_ZZZZXI;
6707 }
6708 break;
6709 }
6710
6711 assert(Opc && "Unknown register class");
6712 MFI.setStackID(FI, StackID);
6713
6715 .addReg(DestReg, getDefRegState(true))
6716 .addFrameIndex(FI);
6717 if (Offset)
6718 MI.addImm(0);
6719 if (PNRReg.isValid() && !PNRReg.isVirtual())
6720 MI.addDef(PNRReg, RegState::Implicit);
6721 MI.addMemOperand(MMO);
6722}
6723
6725 const MachineInstr &UseMI,
6726 const TargetRegisterInfo *TRI) {
6727 return any_of(instructionsWithoutDebug(std::next(DefMI.getIterator()),
6728 UseMI.getIterator()),
6729 [TRI](const MachineInstr &I) {
6730 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6731 I.readsRegister(AArch64::NZCV, TRI);
6732 });
6733}
6734
6735void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6736 const StackOffset &Offset, int64_t &ByteSized, int64_t &VGSized) {
6737 // The smallest scalable element supported by scaled SVE addressing
6738 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6739 // byte offset must always be a multiple of 2.
6740 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6741
6742 // VGSized offsets are divided by '2', because the VG register is the
6743 // the number of 64bit granules as opposed to 128bit vector chunks,
6744 // which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
6745 // So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
6746 // VG = n * 2 and the dwarf offset must be VG * 8 bytes.
6747 ByteSized = Offset.getFixed();
6748 VGSized = Offset.getScalable() / 2;
6749}
6750
6751/// Returns the offset in parts to which this frame offset can be
6752/// decomposed for the purpose of describing a frame offset.
6753/// For non-scalable offsets this is simply its byte size.
6754void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6755 const StackOffset &Offset, int64_t &NumBytes, int64_t &NumPredicateVectors,
6756 int64_t &NumDataVectors) {
6757 // The smallest scalable element supported by scaled SVE addressing
6758 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6759 // byte offset must always be a multiple of 2.
6760 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6761
6762 NumBytes = Offset.getFixed();
6763 NumDataVectors = 0;
6764 NumPredicateVectors = Offset.getScalable() / 2;
6765 // This method is used to get the offsets to adjust the frame offset.
6766 // If the function requires ADDPL to be used and needs more than two ADDPL
6767 // instructions, part of the offset is folded into NumDataVectors so that it
6768 // uses ADDVL for part of it, reducing the number of ADDPL instructions.
6769 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6770 NumPredicateVectors > 62) {
6771 NumDataVectors = NumPredicateVectors / 8;
6772 NumPredicateVectors -= NumDataVectors * 8;
6773 }
6774}
6775
6776// Convenience function to create a DWARF expression for: Constant `Operation`.
6777// This helper emits compact sequences for common cases. For example, for`-15
6778// DW_OP_plus`, this helper would create DW_OP_lit15 DW_OP_minus.
6781 if (Operation == dwarf::DW_OP_plus && Constant < 0 && -Constant <= 31) {
6782 // -Constant (1 to 31)
6783 Expr.push_back(dwarf::DW_OP_lit0 - Constant);
6784 Operation = dwarf::DW_OP_minus;
6785 } else if (Constant >= 0 && Constant <= 31) {
6786 // Literal value 0 to 31
6787 Expr.push_back(dwarf::DW_OP_lit0 + Constant);
6788 } else {
6789 // Signed constant
6790 Expr.push_back(dwarf::DW_OP_consts);
6792 }
6793 return Expr.push_back(Operation);
6794}
6795
6796// Convenience function to create a DWARF expression for a register.
6797static void appendReadRegExpr(SmallVectorImpl<char> &Expr, unsigned RegNum) {
6798 Expr.push_back((char)dwarf::DW_OP_bregx);
6800 Expr.push_back(0);
6801}
6802
6803// Convenience function to create a DWARF expression for loading a register from
6804// a CFA offset.
6806 int64_t OffsetFromDefCFA) {
6807 // This assumes the top of the DWARF stack contains the CFA.
6808 Expr.push_back(dwarf::DW_OP_dup);
6809 // Add the offset to the register.
6810 appendConstantExpr(Expr, OffsetFromDefCFA, dwarf::DW_OP_plus);
6811 // Dereference the address (loads a 64 bit value)..
6812 Expr.push_back(dwarf::DW_OP_deref);
6813}
6814
6815// Convenience function to create a comment for
6816// (+/-) NumBytes (* RegScale)?
6817static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment,
6818 StringRef RegScale = {}) {
6819 if (NumBytes) {
6820 Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
6821 if (!RegScale.empty())
6822 Comment << ' ' << RegScale;
6823 }
6824}
6825
6826// Creates an MCCFIInstruction:
6827// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
6829 unsigned Reg,
6830 const StackOffset &Offset) {
6831 int64_t NumBytes, NumVGScaledBytes;
6832 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(Offset, NumBytes,
6833 NumVGScaledBytes);
6834 std::string CommentBuffer;
6835 llvm::raw_string_ostream Comment(CommentBuffer);
6836
6837 if (Reg == AArch64::SP)
6838 Comment << "sp";
6839 else if (Reg == AArch64::FP)
6840 Comment << "fp";
6841 else
6842 Comment << printReg(Reg, &TRI);
6843
6844 // Build up the expression (Reg + NumBytes + VG * NumVGScaledBytes)
6845 SmallString<64> Expr;
6846 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6847 assert(DwarfReg <= 31 && "DwarfReg out of bounds (0..31)");
6848 // Reg + NumBytes
6849 Expr.push_back(dwarf::DW_OP_breg0 + DwarfReg);
6850 appendLEB128<LEB128Sign::Signed>(Expr, NumBytes);
6851 appendOffsetComment(NumBytes, Comment);
6852 if (NumVGScaledBytes) {
6853 // + VG * NumVGScaledBytes
6854 appendOffsetComment(NumVGScaledBytes, Comment, "* VG");
6855 appendReadRegExpr(Expr, TRI.getDwarfRegNum(AArch64::VG, true));
6856 appendConstantExpr(Expr, NumVGScaledBytes, dwarf::DW_OP_mul);
6857 Expr.push_back(dwarf::DW_OP_plus);
6858 }
6859
6860 // Wrap this into DW_CFA_def_cfa.
6861 SmallString<64> DefCfaExpr;
6862 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
6863 appendLEB128<LEB128Sign::Unsigned>(DefCfaExpr, Expr.size());
6864 DefCfaExpr.append(Expr.str());
6865 return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
6866 Comment.str());
6867}
6868
6870 unsigned FrameReg, unsigned Reg,
6871 const StackOffset &Offset,
6872 bool LastAdjustmentWasScalable) {
6873 if (Offset.getScalable())
6874 return createDefCFAExpression(TRI, Reg, Offset);
6875
6876 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6877 return MCCFIInstruction::cfiDefCfaOffset(nullptr, int(Offset.getFixed()));
6878
6879 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6880 return MCCFIInstruction::cfiDefCfa(nullptr, DwarfReg, (int)Offset.getFixed());
6881}
6882
6885 const StackOffset &OffsetFromDefCFA,
6886 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6887 int64_t NumBytes, NumVGScaledBytes;
6888 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6889 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6890
6891 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6892
6893 // Non-scalable offsets can use DW_CFA_offset directly.
6894 if (!NumVGScaledBytes)
6895 return MCCFIInstruction::createOffset(nullptr, DwarfReg, NumBytes);
6896
6897 std::string CommentBuffer;
6898 llvm::raw_string_ostream Comment(CommentBuffer);
6899 Comment << printReg(Reg, &TRI) << " @ cfa";
6900
6901 // Build up expression (CFA + VG * NumVGScaledBytes + NumBytes)
6902 assert(NumVGScaledBytes && "Expected scalable offset");
6903 SmallString<64> OffsetExpr;
6904 // + VG * NumVGScaledBytes
6905 StringRef VGRegScale;
6906 if (IncomingVGOffsetFromDefCFA) {
6907 appendLoadRegExpr(OffsetExpr, *IncomingVGOffsetFromDefCFA);
6908 VGRegScale = "* IncomingVG";
6909 } else {
6910 appendReadRegExpr(OffsetExpr, TRI.getDwarfRegNum(AArch64::VG, true));
6911 VGRegScale = "* VG";
6912 }
6913 appendConstantExpr(OffsetExpr, NumVGScaledBytes, dwarf::DW_OP_mul);
6914 appendOffsetComment(NumVGScaledBytes, Comment, VGRegScale);
6915 OffsetExpr.push_back(dwarf::DW_OP_plus);
6916 if (NumBytes) {
6917 // + NumBytes
6918 appendOffsetComment(NumBytes, Comment);
6919 appendConstantExpr(OffsetExpr, NumBytes, dwarf::DW_OP_plus);
6920 }
6921
6922 // Wrap this into DW_CFA_expression
6923 SmallString<64> CfaExpr;
6924 CfaExpr.push_back(dwarf::DW_CFA_expression);
6925 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, DwarfReg);
6926 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, OffsetExpr.size());
6927 CfaExpr.append(OffsetExpr.str());
6928
6929 return MCCFIInstruction::createEscape(nullptr, CfaExpr.str(), SMLoc(),
6930 Comment.str());
6931}
6932
6933// Helper function to emit a frame offset adjustment from a given
6934// pointer (SrcReg), stored into DestReg. This function is explicit
6935// in that it requires the opcode.
6938 const DebugLoc &DL, unsigned DestReg,
6939 unsigned SrcReg, int64_t Offset, unsigned Opc,
6940 const TargetInstrInfo *TII,
6941 MachineInstr::MIFlag Flag, bool NeedsWinCFI,
6942 bool *HasWinCFI, bool EmitCFAOffset,
6943 StackOffset CFAOffset, unsigned FrameReg) {
6944 int Sign = 1;
6945 unsigned MaxEncoding, ShiftSize;
6946 switch (Opc) {
6947 case AArch64::ADDXri:
6948 case AArch64::ADDSXri:
6949 case AArch64::SUBXri:
6950 case AArch64::SUBSXri:
6951 MaxEncoding = 0xfff;
6952 ShiftSize = 12;
6953 break;
6954 case AArch64::ADDVL_XXI:
6955 case AArch64::ADDPL_XXI:
6956 case AArch64::ADDSVL_XXI:
6957 case AArch64::ADDSPL_XXI:
6958 MaxEncoding = 31;
6959 ShiftSize = 0;
6960 if (Offset < 0) {
6961 MaxEncoding = 32;
6962 Sign = -1;
6963 Offset = -Offset;
6964 }
6965 break;
6966 default:
6967 llvm_unreachable("Unsupported opcode");
6968 }
6969
6970 // `Offset` can be in bytes or in "scalable bytes".
6971 int VScale = 1;
6972 if (Opc == AArch64::ADDVL_XXI || Opc == AArch64::ADDSVL_XXI)
6973 VScale = 16;
6974 else if (Opc == AArch64::ADDPL_XXI || Opc == AArch64::ADDSPL_XXI)
6975 VScale = 2;
6976
6977 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
6978 // scratch register. If DestReg is a virtual register, use it as the
6979 // scratch register; otherwise, create a new virtual register (to be
6980 // replaced by the scavenger at the end of PEI). That case can be optimized
6981 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
6982 // register can be loaded with offset%8 and the add/sub can use an extending
6983 // instruction with LSL#3.
6984 // Currently the function handles any offsets but generates a poor sequence
6985 // of code.
6986 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
6987
6988 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
6989 Register TmpReg = DestReg;
6990 if (TmpReg == AArch64::XZR)
6991 TmpReg = MBB.getParent()->getRegInfo().createVirtualRegister(
6992 &AArch64::GPR64RegClass);
6993 do {
6994 uint64_t ThisVal = std::min<uint64_t>(Offset, MaxEncodableValue);
6995 unsigned LocalShiftSize = 0;
6996 if (ThisVal > MaxEncoding) {
6997 ThisVal = ThisVal >> ShiftSize;
6998 LocalShiftSize = ShiftSize;
6999 }
7000 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
7001 "Encoding cannot handle value that big");
7002
7003 Offset -= ThisVal << LocalShiftSize;
7004 if (Offset == 0)
7005 TmpReg = DestReg;
7006 auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), TmpReg)
7007 .addReg(SrcReg)
7008 .addImm(Sign * (int)ThisVal);
7009 if (ShiftSize)
7010 MBI = MBI.addImm(
7012 MBI = MBI.setMIFlag(Flag);
7013
7014 auto Change =
7015 VScale == 1
7016 ? StackOffset::getFixed(ThisVal << LocalShiftSize)
7017 : StackOffset::getScalable(VScale * (ThisVal << LocalShiftSize));
7018 if (Sign == -1 || Opc == AArch64::SUBXri || Opc == AArch64::SUBSXri)
7019 CFAOffset += Change;
7020 else
7021 CFAOffset -= Change;
7022 if (EmitCFAOffset && DestReg == TmpReg) {
7023 MachineFunction &MF = *MBB.getParent();
7024 const TargetSubtargetInfo &STI = MF.getSubtarget();
7025 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
7026
7027 unsigned CFIIndex = MF.addFrameInst(
7028 createDefCFA(TRI, FrameReg, DestReg, CFAOffset, VScale != 1));
7029 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
7030 .addCFIIndex(CFIIndex)
7031 .setMIFlags(Flag);
7032 }
7033
7034 if (NeedsWinCFI) {
7035 int Imm = (int)(ThisVal << LocalShiftSize);
7036 if (VScale != 1 && DestReg == AArch64::SP) {
7037 if (HasWinCFI)
7038 *HasWinCFI = true;
7039 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ))
7040 .addImm(ThisVal)
7041 .setMIFlag(Flag);
7042 } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7043 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7044 assert(VScale == 1 && "Expected non-scalable operation");
7045 if (HasWinCFI)
7046 *HasWinCFI = true;
7047 if (Imm == 0)
7048 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
7049 else
7050 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
7051 .addImm(Imm)
7052 .setMIFlag(Flag);
7053 assert(Offset == 0 && "Expected remaining offset to be zero to "
7054 "emit a single SEH directive");
7055 } else if (DestReg == AArch64::SP) {
7056 assert(VScale == 1 && "Expected non-scalable operation");
7057 if (HasWinCFI)
7058 *HasWinCFI = true;
7059 assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
7060 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
7061 .addImm(Imm)
7062 .setMIFlag(Flag);
7063 }
7064 }
7065
7066 SrcReg = TmpReg;
7067 } while (Offset);
7068}
7069
7072 unsigned DestReg, unsigned SrcReg,
7074 MachineInstr::MIFlag Flag, bool SetNZCV,
7075 bool NeedsWinCFI, bool *HasWinCFI,
7076 bool EmitCFAOffset, StackOffset CFAOffset,
7077 unsigned FrameReg) {
7078 // If a function is marked as arm_locally_streaming, then the runtime value of
7079 // vscale in the prologue/epilogue is different the runtime value of vscale
7080 // in the function's body. To avoid having to consider multiple vscales,
7081 // we can use `addsvl` to allocate any scalable stack-slots, which under
7082 // most circumstances will be only locals, not callee-save slots.
7083 const Function &F = MBB.getParent()->getFunction();
7084 bool UseSVL = F.hasFnAttribute("aarch64_pstate_sm_body");
7085
7086 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7087 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7088 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7089
7090 // Insert ADDSXri for scalable offset at the end.
7091 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7092 if (NeedsFinalDefNZCV)
7093 SetNZCV = false;
7094
7095 // First emit non-scalable frame offsets, or a simple 'mov'.
7096 if (Bytes || (!Offset && SrcReg != DestReg)) {
7097 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7098 "SP increment/decrement not 8-byte aligned");
7099 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7100 if (Bytes < 0) {
7101 Bytes = -Bytes;
7102 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7103 }
7104 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
7105 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7106 FrameReg);
7107 CFAOffset += (Opc == AArch64::ADDXri || Opc == AArch64::ADDSXri)
7108 ? StackOffset::getFixed(-Bytes)
7109 : StackOffset::getFixed(Bytes);
7110 SrcReg = DestReg;
7111 FrameReg = DestReg;
7112 }
7113
7114 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7115 "WinCFI can't allocate fractions of an SVE data vector");
7116
7117 if (NumDataVectors) {
7118 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors,
7119 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII,
7120 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7121 FrameReg);
7122 CFAOffset += StackOffset::getScalable(-NumDataVectors * 16);
7123 SrcReg = DestReg;
7124 }
7125
7126 if (NumPredicateVectors) {
7127 assert(DestReg != AArch64::SP && "Unaligned access to SP");
7128 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors,
7129 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII,
7130 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7131 FrameReg);
7132 }
7133
7134 if (NeedsFinalDefNZCV)
7135 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDSXri), DestReg)
7136 .addReg(DestReg)
7137 .addImm(0)
7138 .addImm(0);
7139}
7140
7143 int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS,
7144 VirtRegMap *VRM) const {
7146 // This is a bit of a hack. Consider this instruction:
7147 //
7148 // %0 = COPY %sp; GPR64all:%0
7149 //
7150 // We explicitly chose GPR64all for the virtual register so such a copy might
7151 // be eliminated by RegisterCoalescer. However, that may not be possible, and
7152 // %0 may even spill. We can't spill %sp, and since it is in the GPR64all
7153 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
7154 //
7155 // To prevent that, we are going to constrain the %0 register class here.
7156 if (MI.isFullCopy()) {
7157 Register DstReg = MI.getOperand(0).getReg();
7158 Register SrcReg = MI.getOperand(1).getReg();
7159 if (SrcReg == AArch64::SP && DstReg.isVirtual()) {
7160 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
7161 return nullptr;
7162 }
7163 if (DstReg == AArch64::SP && SrcReg.isVirtual()) {
7164 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
7165 return nullptr;
7166 }
7167 // Nothing can folded with copy from/to NZCV.
7168 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7169 return nullptr;
7170 }
7171
7172 // Handle the case where a copy is being spilled or filled but the source
7173 // and destination register class don't match. For example:
7174 //
7175 // %0 = COPY %xzr; GPR64common:%0
7176 //
7177 // In this case we can still safely fold away the COPY and generate the
7178 // following spill code:
7179 //
7180 // STRXui %xzr, %stack.0
7181 //
7182 // This also eliminates spilled cross register class COPYs (e.g. between x and
7183 // d regs) of the same size. For example:
7184 //
7185 // %0 = COPY %1; GPR64:%0, FPR64:%1
7186 //
7187 // will be filled as
7188 //
7189 // LDRDui %0, fi<#0>
7190 //
7191 // instead of
7192 //
7193 // LDRXui %Temp, fi<#0>
7194 // %0 = FMOV %Temp
7195 //
7196 if (MI.isCopy() && Ops.size() == 1 &&
7197 // Make sure we're only folding the explicit COPY defs/uses.
7198 (Ops[0] == 0 || Ops[0] == 1)) {
7199 bool IsSpill = Ops[0] == 0;
7200 bool IsFill = !IsSpill;
7202 const MachineRegisterInfo &MRI = MF.getRegInfo();
7203 MachineBasicBlock &MBB = *MI.getParent();
7204 const MachineOperand &DstMO = MI.getOperand(0);
7205 const MachineOperand &SrcMO = MI.getOperand(1);
7206 Register DstReg = DstMO.getReg();
7207 Register SrcReg = SrcMO.getReg();
7208 // This is slightly expensive to compute for physical regs since
7209 // getMinimalPhysRegClass is slow.
7210 auto getRegClass = [&](unsigned Reg) {
7211 return Register::isVirtualRegister(Reg) ? MRI.getRegClass(Reg)
7212 : TRI.getMinimalPhysRegClass(Reg);
7213 };
7214
7215 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
7216 assert(TRI.getRegSizeInBits(*getRegClass(DstReg)) ==
7217 TRI.getRegSizeInBits(*getRegClass(SrcReg)) &&
7218 "Mismatched register size in non subreg COPY");
7219 if (IsSpill)
7220 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
7221 getRegClass(SrcReg), Register());
7222 else
7223 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
7224 getRegClass(DstReg), Register());
7225 return &*--InsertPt;
7226 }
7227
7228 // Handle cases like spilling def of:
7229 //
7230 // %0:sub_32<def,read-undef> = COPY %wzr; GPR64common:%0
7231 //
7232 // where the physical register source can be widened and stored to the full
7233 // virtual reg destination stack slot, in this case producing:
7234 //
7235 // STRXui %xzr, %stack.0
7236 //
7237 if (IsSpill && DstMO.isUndef() && SrcReg == AArch64::WZR &&
7238 TRI.getRegSizeInBits(*getRegClass(DstReg)) == 64) {
7239 assert(SrcMO.getSubReg() == 0 &&
7240 "Unexpected subreg on physical register");
7241 storeRegToStackSlot(MBB, InsertPt, AArch64::XZR, SrcMO.isKill(),
7242 FrameIndex, &AArch64::GPR64RegClass, Register());
7243 return &*--InsertPt;
7244 }
7245
7246 // Handle cases like filling use of:
7247 //
7248 // %0:sub_32<def,read-undef> = COPY %1; GPR64:%0, GPR32:%1
7249 //
7250 // where we can load the full virtual reg source stack slot, into the subreg
7251 // destination, in this case producing:
7252 //
7253 // LDRWui %0:sub_32<def,read-undef>, %stack.0
7254 //
7255 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
7256 const TargetRegisterClass *FillRC = nullptr;
7257 switch (DstMO.getSubReg()) {
7258 default:
7259 break;
7260 case AArch64::sub_32:
7261 if (AArch64::GPR64RegClass.hasSubClassEq(getRegClass(DstReg)))
7262 FillRC = &AArch64::GPR32RegClass;
7263 break;
7264 case AArch64::ssub:
7265 FillRC = &AArch64::FPR32RegClass;
7266 break;
7267 case AArch64::dsub:
7268 FillRC = &AArch64::FPR64RegClass;
7269 break;
7270 }
7271
7272 if (FillRC) {
7273 assert(TRI.getRegSizeInBits(*getRegClass(SrcReg)) ==
7274 TRI.getRegSizeInBits(*FillRC) &&
7275 "Mismatched regclass size on folded subreg COPY");
7276 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC,
7277 Register());
7278 MachineInstr &LoadMI = *--InsertPt;
7279 MachineOperand &LoadDst = LoadMI.getOperand(0);
7280 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
7281 LoadDst.setSubReg(DstMO.getSubReg());
7282 LoadDst.setIsUndef();
7283 return &LoadMI;
7284 }
7285 }
7286 }
7287
7288 // Cannot fold.
7289 return nullptr;
7290}
7291
7293 StackOffset &SOffset,
7294 bool *OutUseUnscaledOp,
7295 unsigned *OutUnscaledOp,
7296 int64_t *EmittableOffset) {
7297 // Set output values in case of early exit.
7298 if (EmittableOffset)
7299 *EmittableOffset = 0;
7300 if (OutUseUnscaledOp)
7301 *OutUseUnscaledOp = false;
7302 if (OutUnscaledOp)
7303 *OutUnscaledOp = 0;
7304
7305 // Exit early for structured vector spills/fills as they can't take an
7306 // immediate offset.
7307 switch (MI.getOpcode()) {
7308 default:
7309 break;
7310 case AArch64::LD1Rv1d:
7311 case AArch64::LD1Rv2s:
7312 case AArch64::LD1Rv2d:
7313 case AArch64::LD1Rv4h:
7314 case AArch64::LD1Rv4s:
7315 case AArch64::LD1Rv8b:
7316 case AArch64::LD1Rv8h:
7317 case AArch64::LD1Rv16b:
7318 case AArch64::LD1Twov2d:
7319 case AArch64::LD1Threev2d:
7320 case AArch64::LD1Fourv2d:
7321 case AArch64::LD1Twov1d:
7322 case AArch64::LD1Threev1d:
7323 case AArch64::LD1Fourv1d:
7324 case AArch64::ST1Twov2d:
7325 case AArch64::ST1Threev2d:
7326 case AArch64::ST1Fourv2d:
7327 case AArch64::ST1Twov1d:
7328 case AArch64::ST1Threev1d:
7329 case AArch64::ST1Fourv1d:
7330 case AArch64::ST1i8:
7331 case AArch64::ST1i16:
7332 case AArch64::ST1i32:
7333 case AArch64::ST1i64:
7334 case AArch64::IRG:
7335 case AArch64::IRGstack:
7336 case AArch64::STGloop:
7337 case AArch64::STZGloop:
7339 }
7340
7341 // Get the min/max offset and the scale.
7342 TypeSize ScaleValue(0U, false), Width(0U, false);
7343 int64_t MinOff, MaxOff;
7344 if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), ScaleValue, Width, MinOff,
7345 MaxOff))
7346 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7347
7348 // Construct the complete offset.
7349 bool IsMulVL = ScaleValue.isScalable();
7350 unsigned Scale = ScaleValue.getKnownMinValue();
7351 int64_t Offset = IsMulVL ? SOffset.getScalable() : SOffset.getFixed();
7352
7353 const MachineOperand &ImmOpnd =
7354 MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode()));
7355 Offset += ImmOpnd.getImm() * Scale;
7356
7357 // If the offset doesn't match the scale, we rewrite the instruction to
7358 // use the unscaled instruction instead. Likewise, if we have a negative
7359 // offset and there is an unscaled op to use.
7360 std::optional<unsigned> UnscaledOp =
7362 bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0);
7363 if (useUnscaledOp &&
7364 !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, ScaleValue, Width, MinOff,
7365 MaxOff))
7366 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7367
7368 Scale = ScaleValue.getKnownMinValue();
7369 assert(IsMulVL == ScaleValue.isScalable() &&
7370 "Unscaled opcode has different value for scalable");
7371
7372 int64_t Remainder = Offset % Scale;
7373 assert(!(Remainder && useUnscaledOp) &&
7374 "Cannot have remainder when using unscaled op");
7375
7376 assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
7377 int64_t NewOffset = Offset / Scale;
7378 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7379 Offset = Remainder;
7380 else {
7381 // Try to minimise the number of instructions required to materialise the
7382 // offset calculation. Specifically, for fixed offsets, if masking out the
7383 // low 12 bits leaves a legal add immediate, we can realise the offset
7384 // calculation with a single add instruction. Whenever this is possible,
7385 // prefer this split.
7386 int64_t HighPart = Offset & ~0xFFF;
7387 int64_t LowPart = Offset & 0xFFF;
7388 int64_t LowScaled = LowPart / Scale;
7389 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7390 MinOff <= LowScaled && LowScaled <= MaxOff &&
7392 NewOffset = LowScaled;
7393 Offset = HighPart;
7394 } else {
7395 // Default to a greedy split: take the memop immediate to be maximum /
7396 // minimum expressible offset and materialise the remainder.
7397 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7398 Offset = Offset - (NewOffset * Scale);
7399 }
7400 }
7401
7402 if (EmittableOffset)
7403 *EmittableOffset = NewOffset;
7404 if (OutUseUnscaledOp)
7405 *OutUseUnscaledOp = useUnscaledOp;
7406 if (OutUnscaledOp && UnscaledOp)
7407 *OutUnscaledOp = *UnscaledOp;
7408
7409 if (IsMulVL)
7410 SOffset = StackOffset::get(SOffset.getFixed(), Offset);
7411 else
7412 SOffset = StackOffset::get(Offset, SOffset.getScalable());
7414 (SOffset ? 0 : AArch64FrameOffsetIsLegal);
7415}
7416
7418 unsigned FrameReg, StackOffset &Offset,
7419 const AArch64InstrInfo *TII) {
7420 unsigned Opcode = MI.getOpcode();
7421 unsigned ImmIdx = FrameRegIdx + 1;
7422
7423 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7424 Offset += StackOffset::getFixed(MI.getOperand(ImmIdx).getImm());
7425 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
7426 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
7427 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
7428 MI.eraseFromParent();
7429 Offset = StackOffset();
7430 return true;
7431 }
7432
7433 int64_t NewOffset;
7434 unsigned UnscaledOp;
7435 bool UseUnscaledOp;
7436 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
7437 &UnscaledOp, &NewOffset);
7440 // Replace the FrameIndex with FrameReg.
7441 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
7442 if (UseUnscaledOp)
7443 MI.setDesc(TII->get(UnscaledOp));
7444
7445 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7446 return !Offset;
7447 }
7448
7449 return false;
7450}
7451
7457
7458MCInst AArch64InstrInfo::getNop() const { return MCInstBuilder(AArch64::NOP); }
7459
7460// AArch64 supports MachineCombiner.
7461bool AArch64InstrInfo::useMachineCombiner() const { return true; }
7462
7463// True when Opc sets flag
7464static bool isCombineInstrSettingFlag(unsigned Opc) {
7465 switch (Opc) {
7466 case AArch64::ADDSWrr:
7467 case AArch64::ADDSWri:
7468 case AArch64::ADDSXrr:
7469 case AArch64::ADDSXri:
7470 case AArch64::SUBSWrr:
7471 case AArch64::SUBSXrr:
7472 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7473 case AArch64::SUBSWri:
7474 case AArch64::SUBSXri:
7475 return true;
7476 default:
7477 break;
7478 }
7479 return false;
7480}
7481
7482// 32b Opcodes that can be combined with a MUL
7483static bool isCombineInstrCandidate32(unsigned Opc) {
7484 switch (Opc) {
7485 case AArch64::ADDWrr:
7486 case AArch64::ADDWri:
7487 case AArch64::SUBWrr:
7488 case AArch64::ADDSWrr:
7489 case AArch64::ADDSWri:
7490 case AArch64::SUBSWrr:
7491 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7492 case AArch64::SUBWri:
7493 case AArch64::SUBSWri:
7494 return true;
7495 default:
7496 break;
7497 }
7498 return false;
7499}
7500
7501// 64b Opcodes that can be combined with a MUL
7502static bool isCombineInstrCandidate64(unsigned Opc) {
7503 switch (Opc) {
7504 case AArch64::ADDXrr:
7505 case AArch64::ADDXri:
7506 case AArch64::SUBXrr:
7507 case AArch64::ADDSXrr:
7508 case AArch64::ADDSXri:
7509 case AArch64::SUBSXrr:
7510 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7511 case AArch64::SUBXri:
7512 case AArch64::SUBSXri:
7513 case AArch64::ADDv8i8:
7514 case AArch64::ADDv16i8:
7515 case AArch64::ADDv4i16:
7516 case AArch64::ADDv8i16:
7517 case AArch64::ADDv2i32:
7518 case AArch64::ADDv4i32:
7519 case AArch64::SUBv8i8:
7520 case AArch64::SUBv16i8:
7521 case AArch64::SUBv4i16:
7522 case AArch64::SUBv8i16:
7523 case AArch64::SUBv2i32:
7524 case AArch64::SUBv4i32:
7525 return true;
7526 default:
7527 break;
7528 }
7529 return false;
7530}
7531
7532// FP Opcodes that can be combined with a FMUL.
7533static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
7534 switch (Inst.getOpcode()) {
7535 default:
7536 break;
7537 case AArch64::FADDHrr:
7538 case AArch64::FADDSrr:
7539 case AArch64::FADDDrr:
7540 case AArch64::FADDv4f16:
7541 case AArch64::FADDv8f16:
7542 case AArch64::FADDv2f32:
7543 case AArch64::FADDv2f64:
7544 case AArch64::FADDv4f32:
7545 case AArch64::FSUBHrr:
7546 case AArch64::FSUBSrr:
7547 case AArch64::FSUBDrr:
7548 case AArch64::FSUBv4f16:
7549 case AArch64::FSUBv8f16:
7550 case AArch64::FSUBv2f32:
7551 case AArch64::FSUBv2f64:
7552 case AArch64::FSUBv4f32:
7554 // We can fuse FADD/FSUB with FMUL, if fusion is either allowed globally by
7555 // the target options or if FADD/FSUB has the contract fast-math flag.
7556 return Options.AllowFPOpFusion == FPOpFusion::Fast ||
7558 }
7559 return false;
7560}
7561
7562// Opcodes that can be combined with a MUL
7566
7567//
7568// Utility routine that checks if \param MO is defined by an
7569// \param CombineOpc instruction in the basic block \param MBB
7571 unsigned CombineOpc, unsigned ZeroReg = 0,
7572 bool CheckZeroReg = false) {
7573 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
7574 MachineInstr *MI = nullptr;
7575
7576 if (MO.isReg() && MO.getReg().isVirtual())
7577 MI = MRI.getUniqueVRegDef(MO.getReg());
7578 // And it needs to be in the trace (otherwise, it won't have a depth).
7579 if (!MI || MI->getParent() != &MBB || MI->getOpcode() != CombineOpc)
7580 return false;
7581 // Must only used by the user we combine with.
7582 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
7583 return false;
7584
7585 if (CheckZeroReg) {
7586 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
7587 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
7588 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
7589 // The third input reg must be zero.
7590 if (MI->getOperand(3).getReg() != ZeroReg)
7591 return false;
7592 }
7593
7594 if (isCombineInstrSettingFlag(CombineOpc) &&
7595 MI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) == -1)
7596 return false;
7597
7598 return true;
7599}
7600
7601//
7602// Is \param MO defined by an integer multiply and can be combined?
7604 unsigned MulOpc, unsigned ZeroReg) {
7605 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
7606}
7607
7608//
7609// Is \param MO defined by a floating-point multiply and can be combined?
7611 unsigned MulOpc) {
7612 return canCombine(MBB, MO, MulOpc);
7613}
7614
7615// TODO: There are many more machine instruction opcodes to match:
7616// 1. Other data types (integer, vectors)
7617// 2. Other math / logic operations (xor, or)
7618// 3. Other forms of the same operation (intrinsics and other variants)
7619bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
7620 bool Invert) const {
7621 if (Invert)
7622 return false;
7623 switch (Inst.getOpcode()) {
7624 // == Floating-point types ==
7625 // -- Floating-point instructions --
7626 case AArch64::FADDHrr:
7627 case AArch64::FADDSrr:
7628 case AArch64::FADDDrr:
7629 case AArch64::FMULHrr:
7630 case AArch64::FMULSrr:
7631 case AArch64::FMULDrr:
7632 case AArch64::FMULX16:
7633 case AArch64::FMULX32:
7634 case AArch64::FMULX64:
7635 // -- Advanced SIMD instructions --
7636 case AArch64::FADDv4f16:
7637 case AArch64::FADDv8f16:
7638 case AArch64::FADDv2f32:
7639 case AArch64::FADDv4f32:
7640 case AArch64::FADDv2f64:
7641 case AArch64::FMULv4f16:
7642 case AArch64::FMULv8f16:
7643 case AArch64::FMULv2f32:
7644 case AArch64::FMULv4f32:
7645 case AArch64::FMULv2f64:
7646 case AArch64::FMULXv4f16:
7647 case AArch64::FMULXv8f16:
7648 case AArch64::FMULXv2f32:
7649 case AArch64::FMULXv4f32:
7650 case AArch64::FMULXv2f64:
7651 // -- SVE instructions --
7652 // Opcodes FMULX_ZZZ_? don't exist because there is no unpredicated FMULX
7653 // in the SVE instruction set (though there are predicated ones).
7654 case AArch64::FADD_ZZZ_H:
7655 case AArch64::FADD_ZZZ_S:
7656 case AArch64::FADD_ZZZ_D:
7657 case AArch64::FMUL_ZZZ_H:
7658 case AArch64::FMUL_ZZZ_S:
7659 case AArch64::FMUL_ZZZ_D:
7662
7663 // == Integer types ==
7664 // -- Base instructions --
7665 // Opcodes MULWrr and MULXrr don't exist because
7666 // `MUL <Wd>, <Wn>, <Wm>` and `MUL <Xd>, <Xn>, <Xm>` are aliases of
7667 // `MADD <Wd>, <Wn>, <Wm>, WZR` and `MADD <Xd>, <Xn>, <Xm>, XZR` respectively.
7668 // The machine-combiner does not support three-source-operands machine
7669 // instruction. So we cannot reassociate MULs.
7670 case AArch64::ADDWrr:
7671 case AArch64::ADDXrr:
7672 case AArch64::ANDWrr:
7673 case AArch64::ANDXrr:
7674 case AArch64::ORRWrr:
7675 case AArch64::ORRXrr:
7676 case AArch64::EORWrr:
7677 case AArch64::EORXrr:
7678 case AArch64::EONWrr:
7679 case AArch64::EONXrr:
7680 // -- Advanced SIMD instructions --
7681 // Opcodes MULv1i64 and MULv2i64 don't exist because there is no 64-bit MUL
7682 // in the Advanced SIMD instruction set.
7683 case AArch64::ADDv8i8:
7684 case AArch64::ADDv16i8:
7685 case AArch64::ADDv4i16:
7686 case AArch64::ADDv8i16:
7687 case AArch64::ADDv2i32:
7688 case AArch64::ADDv4i32:
7689 case AArch64::ADDv1i64:
7690 case AArch64::ADDv2i64:
7691 case AArch64::MULv8i8:
7692 case AArch64::MULv16i8:
7693 case AArch64::MULv4i16:
7694 case AArch64::MULv8i16:
7695 case AArch64::MULv2i32:
7696 case AArch64::MULv4i32:
7697 case AArch64::ANDv8i8:
7698 case AArch64::ANDv16i8:
7699 case AArch64::ORRv8i8:
7700 case AArch64::ORRv16i8:
7701 case AArch64::EORv8i8:
7702 case AArch64::EORv16i8:
7703 // -- SVE instructions --
7704 case AArch64::ADD_ZZZ_B:
7705 case AArch64::ADD_ZZZ_H:
7706 case AArch64::ADD_ZZZ_S:
7707 case AArch64::ADD_ZZZ_D:
7708 case AArch64::MUL_ZZZ_B:
7709 case AArch64::MUL_ZZZ_H:
7710 case AArch64::MUL_ZZZ_S:
7711 case AArch64::MUL_ZZZ_D:
7712 case AArch64::AND_ZZZ:
7713 case AArch64::ORR_ZZZ:
7714 case AArch64::EOR_ZZZ:
7715 return true;
7716
7717 default:
7718 return false;
7719 }
7720}
7721
7722/// Find instructions that can be turned into madd.
7724 SmallVectorImpl<unsigned> &Patterns) {
7725 unsigned Opc = Root.getOpcode();
7726 MachineBasicBlock &MBB = *Root.getParent();
7727 bool Found = false;
7728
7730 return false;
7732 int Cmp_NZCV =
7733 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
7734 // When NZCV is live bail out.
7735 if (Cmp_NZCV == -1)
7736 return false;
7737 unsigned NewOpc = convertToNonFlagSettingOpc(Root);
7738 // When opcode can't change bail out.
7739 // CHECKME: do we miss any cases for opcode conversion?
7740 if (NewOpc == Opc)
7741 return false;
7742 Opc = NewOpc;
7743 }
7744
7745 auto setFound = [&](int Opcode, int Operand, unsigned ZeroReg,
7746 unsigned Pattern) {
7747 if (canCombineWithMUL(MBB, Root.getOperand(Operand), Opcode, ZeroReg)) {
7748 Patterns.push_back(Pattern);
7749 Found = true;
7750 }
7751 };
7752
7753 auto setVFound = [&](int Opcode, int Operand, unsigned Pattern) {
7754 if (canCombine(MBB, Root.getOperand(Operand), Opcode)) {
7755 Patterns.push_back(Pattern);
7756 Found = true;
7757 }
7758 };
7759
7761
7762 switch (Opc) {
7763 default:
7764 break;
7765 case AArch64::ADDWrr:
7766 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
7767 "ADDWrr does not have register operands");
7768 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7769 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7770 break;
7771 case AArch64::ADDXrr:
7772 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7773 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7774 break;
7775 case AArch64::SUBWrr:
7776 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7777 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7778 break;
7779 case AArch64::SUBXrr:
7780 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7781 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7782 break;
7783 case AArch64::ADDWri:
7784 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7785 break;
7786 case AArch64::ADDXri:
7787 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7788 break;
7789 case AArch64::SUBWri:
7790 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7791 break;
7792 case AArch64::SUBXri:
7793 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7794 break;
7795 case AArch64::ADDv8i8:
7796 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7797 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7798 break;
7799 case AArch64::ADDv16i8:
7800 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7801 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7802 break;
7803 case AArch64::ADDv4i16:
7804 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7805 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7806 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7807 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7808 break;
7809 case AArch64::ADDv8i16:
7810 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7811 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7812 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7813 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7814 break;
7815 case AArch64::ADDv2i32:
7816 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7817 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7818 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7819 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7820 break;
7821 case AArch64::ADDv4i32:
7822 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7823 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7824 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7825 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7826 break;
7827 case AArch64::SUBv8i8:
7828 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7829 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7830 break;
7831 case AArch64::SUBv16i8:
7832 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7833 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7834 break;
7835 case AArch64::SUBv4i16:
7836 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7837 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7838 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7839 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7840 break;
7841 case AArch64::SUBv8i16:
7842 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7843 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7844 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7845 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7846 break;
7847 case AArch64::SUBv2i32:
7848 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7849 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7850 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7851 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7852 break;
7853 case AArch64::SUBv4i32:
7854 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7855 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7856 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7857 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7858 break;
7859 }
7860 return Found;
7861}
7862
7863bool AArch64InstrInfo::isAccumulationOpcode(unsigned Opcode) const {
7864 switch (Opcode) {
7865 default:
7866 break;
7867 case AArch64::UABALB_ZZZ_D:
7868 case AArch64::UABALB_ZZZ_H:
7869 case AArch64::UABALB_ZZZ_S:
7870 case AArch64::UABALT_ZZZ_D:
7871 case AArch64::UABALT_ZZZ_H:
7872 case AArch64::UABALT_ZZZ_S:
7873 case AArch64::SABALB_ZZZ_D:
7874 case AArch64::SABALB_ZZZ_S:
7875 case AArch64::SABALB_ZZZ_H:
7876 case AArch64::SABALT_ZZZ_D:
7877 case AArch64::SABALT_ZZZ_S:
7878 case AArch64::SABALT_ZZZ_H:
7879 case AArch64::UABALv16i8_v8i16:
7880 case AArch64::UABALv2i32_v2i64:
7881 case AArch64::UABALv4i16_v4i32:
7882 case AArch64::UABALv4i32_v2i64:
7883 case AArch64::UABALv8i16_v4i32:
7884 case AArch64::UABALv8i8_v8i16:
7885 case AArch64::UABAv16i8:
7886 case AArch64::UABAv2i32:
7887 case AArch64::UABAv4i16:
7888 case AArch64::UABAv4i32:
7889 case AArch64::UABAv8i16:
7890 case AArch64::UABAv8i8:
7891 case AArch64::SABALv16i8_v8i16:
7892 case AArch64::SABALv2i32_v2i64:
7893 case AArch64::SABALv4i16_v4i32:
7894 case AArch64::SABALv4i32_v2i64:
7895 case AArch64::SABALv8i16_v4i32:
7896 case AArch64::SABALv8i8_v8i16:
7897 case AArch64::SABAv16i8:
7898 case AArch64::SABAv2i32:
7899 case AArch64::SABAv4i16:
7900 case AArch64::SABAv4i32:
7901 case AArch64::SABAv8i16:
7902 case AArch64::SABAv8i8:
7903 return true;
7904 }
7905
7906 return false;
7907}
7908
7909unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7910 unsigned AccumulationOpcode) const {
7911 switch (AccumulationOpcode) {
7912 default:
7913 llvm_unreachable("Unsupported accumulation Opcode!");
7914 case AArch64::UABALB_ZZZ_D:
7915 return AArch64::UABDLB_ZZZ_D;
7916 case AArch64::UABALB_ZZZ_H:
7917 return AArch64::UABDLB_ZZZ_H;
7918 case AArch64::UABALB_ZZZ_S:
7919 return AArch64::UABDLB_ZZZ_S;
7920 case AArch64::UABALT_ZZZ_D:
7921 return AArch64::UABDLT_ZZZ_D;
7922 case AArch64::UABALT_ZZZ_H:
7923 return AArch64::UABDLT_ZZZ_H;
7924 case AArch64::UABALT_ZZZ_S:
7925 return AArch64::UABDLT_ZZZ_S;
7926 case AArch64::UABALv16i8_v8i16:
7927 return AArch64::UABDLv16i8_v8i16;
7928 case AArch64::UABALv2i32_v2i64:
7929 return AArch64::UABDLv2i32_v2i64;
7930 case AArch64::UABALv4i16_v4i32:
7931 return AArch64::UABDLv4i16_v4i32;
7932 case AArch64::UABALv4i32_v2i64:
7933 return AArch64::UABDLv4i32_v2i64;
7934 case AArch64::UABALv8i16_v4i32:
7935 return AArch64::UABDLv8i16_v4i32;
7936 case AArch64::UABALv8i8_v8i16:
7937 return AArch64::UABDLv8i8_v8i16;
7938 case AArch64::UABAv16i8:
7939 return AArch64::UABDv16i8;
7940 case AArch64::UABAv2i32:
7941 return AArch64::UABDv2i32;
7942 case AArch64::UABAv4i16:
7943 return AArch64::UABDv4i16;
7944 case AArch64::UABAv4i32:
7945 return AArch64::UABDv4i32;
7946 case AArch64::UABAv8i16:
7947 return AArch64::UABDv8i16;
7948 case AArch64::UABAv8i8:
7949 return AArch64::UABDv8i8;
7950 case AArch64::SABALB_ZZZ_D:
7951 return AArch64::SABDLB_ZZZ_D;
7952 case AArch64::SABALB_ZZZ_S:
7953 return AArch64::SABDLB_ZZZ_S;
7954 case AArch64::SABALB_ZZZ_H:
7955 return AArch64::SABDLB_ZZZ_H;
7956 case AArch64::SABALT_ZZZ_D:
7957 return AArch64::SABDLT_ZZZ_D;
7958 case AArch64::SABALT_ZZZ_S:
7959 return AArch64::SABDLT_ZZZ_S;
7960 case AArch64::SABALT_ZZZ_H:
7961 return AArch64::SABDLT_ZZZ_H;
7962 case AArch64::SABALv16i8_v8i16:
7963 return AArch64::SABDLv16i8_v8i16;
7964 case AArch64::SABALv2i32_v2i64:
7965 return AArch64::SABDLv2i32_v2i64;
7966 case AArch64::SABALv4i16_v4i32:
7967 return AArch64::SABDLv4i16_v4i32;
7968 case AArch64::SABALv4i32_v2i64:
7969 return AArch64::SABDLv4i32_v2i64;
7970 case AArch64::SABALv8i16_v4i32:
7971 return AArch64::SABDLv8i16_v4i32;
7972 case AArch64::SABALv8i8_v8i16:
7973 return AArch64::SABDLv8i8_v8i16;
7974 case AArch64::SABAv16i8:
7975 return AArch64::SABDv16i8;
7976 case AArch64::SABAv2i32:
7977 return AArch64::SABAv2i32;
7978 case AArch64::SABAv4i16:
7979 return AArch64::SABDv4i16;
7980 case AArch64::SABAv4i32:
7981 return AArch64::SABDv4i32;
7982 case AArch64::SABAv8i16:
7983 return AArch64::SABDv8i16;
7984 case AArch64::SABAv8i8:
7985 return AArch64::SABDv8i8;
7986 }
7987}
7988
7989/// Floating-Point Support
7990
7991/// Find instructions that can be turned into madd.
7993 SmallVectorImpl<unsigned> &Patterns) {
7994
7995 if (!isCombineInstrCandidateFP(Root))
7996 return false;
7997
7998 MachineBasicBlock &MBB = *Root.getParent();
7999 bool Found = false;
8000
8001 auto Match = [&](int Opcode, int Operand, unsigned Pattern) -> bool {
8002 if (canCombineWithFMUL(MBB, Root.getOperand(Operand), Opcode)) {
8003 Patterns.push_back(Pattern);
8004 return true;
8005 }
8006 return false;
8007 };
8008
8010
8011 switch (Root.getOpcode()) {
8012 default:
8013 assert(false && "Unsupported FP instruction in combiner\n");
8014 break;
8015 case AArch64::FADDHrr:
8016 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8017 "FADDHrr does not have register operands");
8018
8019 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8020 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8021 break;
8022 case AArch64::FADDSrr:
8023 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8024 "FADDSrr does not have register operands");
8025
8026 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8027 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8028
8029 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8030 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8031 break;
8032 case AArch64::FADDDrr:
8033 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8034 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8035
8036 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8037 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8038 break;
8039 case AArch64::FADDv4f16:
8040 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8041 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8042
8043 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8044 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8045 break;
8046 case AArch64::FADDv8f16:
8047 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8048 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8049
8050 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8051 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8052 break;
8053 case AArch64::FADDv2f32:
8054 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8055 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8056
8057 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8058 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8059 break;
8060 case AArch64::FADDv2f64:
8061 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8062 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8063
8064 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8065 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8066 break;
8067 case AArch64::FADDv4f32:
8068 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8069 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8070
8071 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8072 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8073 break;
8074 case AArch64::FSUBHrr:
8075 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8076 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8077 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8078 break;
8079 case AArch64::FSUBSrr:
8080 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8081
8082 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8083 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8084
8085 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8086 break;
8087 case AArch64::FSUBDrr:
8088 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8089
8090 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8091 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8092
8093 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8094 break;
8095 case AArch64::FSUBv4f16:
8096 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8097 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8098
8099 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8100 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8101 break;
8102 case AArch64::FSUBv8f16:
8103 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8104 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8105
8106 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8107 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8108 break;
8109 case AArch64::FSUBv2f32:
8110 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8111 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8112
8113 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8114 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8115 break;
8116 case AArch64::FSUBv2f64:
8117 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8118 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8119
8120 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8121 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8122 break;
8123 case AArch64::FSUBv4f32:
8124 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8125 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8126
8127 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8128 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8129 break;
8130 }
8131 return Found;
8132}
8133
8135 SmallVectorImpl<unsigned> &Patterns) {
8136 MachineBasicBlock &MBB = *Root.getParent();
8137 bool Found = false;
8138
8139 auto Match = [&](unsigned Opcode, int Operand, unsigned Pattern) -> bool {
8140 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8141 MachineOperand &MO = Root.getOperand(Operand);
8142 MachineInstr *MI = nullptr;
8143 if (MO.isReg() && MO.getReg().isVirtual())
8144 MI = MRI.getUniqueVRegDef(MO.getReg());
8145 // Ignore No-op COPYs in FMUL(COPY(DUP(..)))
8146 if (MI && MI->getOpcode() == TargetOpcode::COPY &&
8147 MI->getOperand(1).getReg().isVirtual())
8148 MI = MRI.getUniqueVRegDef(MI->getOperand(1).getReg());
8149 if (MI && MI->getOpcode() == Opcode) {
8150 Patterns.push_back(Pattern);
8151 return true;
8152 }
8153 return false;
8154 };
8155
8157
8158 switch (Root.getOpcode()) {
8159 default:
8160 return false;
8161 case AArch64::FMULv2f32:
8162 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8163 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8164 break;
8165 case AArch64::FMULv2f64:
8166 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8167 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8168 break;
8169 case AArch64::FMULv4f16:
8170 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8171 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8172 break;
8173 case AArch64::FMULv4f32:
8174 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8175 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8176 break;
8177 case AArch64::FMULv8f16:
8178 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8179 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8180 break;
8181 }
8182
8183 return Found;
8184}
8185
8187 SmallVectorImpl<unsigned> &Patterns) {
8188 unsigned Opc = Root.getOpcode();
8189 MachineBasicBlock &MBB = *Root.getParent();
8190 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8191
8192 auto Match = [&](unsigned Opcode, unsigned Pattern) -> bool {
8193 MachineOperand &MO = Root.getOperand(1);
8195 if (MI != nullptr && (MI->getOpcode() == Opcode) &&
8196 MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()) &&
8200 MI->getFlag(MachineInstr::MIFlag::FmNsz)) {
8201 Patterns.push_back(Pattern);
8202 return true;
8203 }
8204 return false;
8205 };
8206
8207 switch (Opc) {
8208 default:
8209 break;
8210 case AArch64::FNEGDr:
8211 return Match(AArch64::FMADDDrrr, AArch64MachineCombinerPattern::FNMADD);
8212 case AArch64::FNEGSr:
8213 return Match(AArch64::FMADDSrrr, AArch64MachineCombinerPattern::FNMADD);
8214 }
8215
8216 return false;
8217}
8218
8219/// Return true when a code sequence can improve throughput. It
8220/// should be called only for instructions in loops.
8221/// \param Pattern - combiner pattern
8223 switch (Pattern) {
8224 default:
8225 break;
8331 return true;
8332 } // end switch (Pattern)
8333 return false;
8334}
8335
8336/// Find other MI combine patterns.
8338 SmallVectorImpl<unsigned> &Patterns) {
8339 // A - (B + C) ==> (A - B) - C or (A - C) - B
8340 unsigned Opc = Root.getOpcode();
8341 MachineBasicBlock &MBB = *Root.getParent();
8342
8343 switch (Opc) {
8344 case AArch64::SUBWrr:
8345 case AArch64::SUBSWrr:
8346 case AArch64::SUBXrr:
8347 case AArch64::SUBSXrr:
8348 // Found candidate root.
8349 break;
8350 default:
8351 return false;
8352 }
8353
8355 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) ==
8356 -1)
8357 return false;
8358
8359 if (canCombine(MBB, Root.getOperand(2), AArch64::ADDWrr) ||
8360 canCombine(MBB, Root.getOperand(2), AArch64::ADDSWrr) ||
8361 canCombine(MBB, Root.getOperand(2), AArch64::ADDXrr) ||
8362 canCombine(MBB, Root.getOperand(2), AArch64::ADDSXrr)) {
8365 return true;
8366 }
8367
8368 return false;
8369}
8370
8371/// Check if the given instruction forms a gather load pattern that can be
8372/// optimized for better Memory-Level Parallelism (MLP). This function
8373/// identifies chains of NEON lane load instructions that load data from
8374/// different memory addresses into individual lanes of a 128-bit vector
8375/// register, then attempts to split the pattern into parallel loads to break
8376/// the serial dependency between instructions.
8377///
8378/// Pattern Matched:
8379/// Initial scalar load -> SUBREG_TO_REG (lane 0) -> LD1i* (lane 1) ->
8380/// LD1i* (lane 2) -> ... -> LD1i* (lane N-1, Root)
8381///
8382/// Transformed Into:
8383/// Two parallel vector loads using fewer lanes each, followed by ZIP1v2i64
8384/// to combine the results, enabling better memory-level parallelism.
8385///
8386/// Supported Element Types:
8387/// - 32-bit elements (LD1i32, 4 lanes total)
8388/// - 16-bit elements (LD1i16, 8 lanes total)
8389/// - 8-bit elements (LD1i8, 16 lanes total)
8391 SmallVectorImpl<unsigned> &Patterns,
8392 unsigned LoadLaneOpCode, unsigned NumLanes) {
8393 const MachineFunction *MF = Root.getMF();
8394
8395 // Early exit if optimizing for size.
8396 if (MF->getFunction().hasMinSize())
8397 return false;
8398
8399 const MachineRegisterInfo &MRI = MF->getRegInfo();
8401
8402 // The root of the pattern must load into the last lane of the vector.
8403 if (Root.getOperand(2).getImm() != NumLanes - 1)
8404 return false;
8405
8406 // Check that we have load into all lanes except lane 0.
8407 // For each load we also want to check that:
8408 // 1. It has a single non-debug use (since we will be replacing the virtual
8409 // register)
8410 // 2. That the addressing mode only uses a single pointer operand
8411 auto *CurrInstr = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8412 auto Range = llvm::seq<unsigned>(1, NumLanes - 1);
8413 SmallSet<unsigned, 16> RemainingLanes(Range.begin(), Range.end());
8415 while (!RemainingLanes.empty() && CurrInstr &&
8416 CurrInstr->getOpcode() == LoadLaneOpCode &&
8417 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
8418 CurrInstr->getNumOperands() == 4) {
8419 RemainingLanes.erase(CurrInstr->getOperand(2).getImm());
8420 LoadInstrs.push_back(CurrInstr);
8421 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8422 }
8423
8424 // Check that we have found a match for lanes N-1.. 1.
8425 if (!RemainingLanes.empty())
8426 return false;
8427
8428 // Match the SUBREG_TO_REG sequence.
8429 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8430 return false;
8431
8432 // Verify that the subreg to reg loads an integer into the first lane.
8433 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8434 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8435 if (TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8436 return false;
8437
8438 // Verify that it also has a single non debug use.
8439 if (!MRI.hasOneNonDBGUse(Lane0LoadReg))
8440 return false;
8441
8442 LoadInstrs.push_back(MRI.getUniqueVRegDef(Lane0LoadReg));
8443
8444 // If there is any chance of aliasing, do not apply the pattern.
8445 // Walk backward through the MBB starting from Root.
8446 // Exit early if we've encountered all load instructions or hit the search
8447 // limit.
8448 auto MBBItr = Root.getIterator();
8449 unsigned RemainingSteps = GatherOptSearchLimit;
8450 SmallPtrSet<const MachineInstr *, 16> RemainingLoadInstrs;
8451 RemainingLoadInstrs.insert(LoadInstrs.begin(), LoadInstrs.end());
8452 const MachineBasicBlock *MBB = Root.getParent();
8453
8454 for (; MBBItr != MBB->begin() && RemainingSteps > 0 &&
8455 !RemainingLoadInstrs.empty();
8456 --MBBItr, --RemainingSteps) {
8457 const MachineInstr &CurrInstr = *MBBItr;
8458
8459 // Remove this instruction from remaining loads if it's one we're tracking.
8460 RemainingLoadInstrs.erase(&CurrInstr);
8461
8462 // Check for potential aliasing with any of the load instructions to
8463 // optimize.
8464 if (CurrInstr.isLoadFoldBarrier())
8465 return false;
8466 }
8467
8468 // If we hit the search limit without finding all load instructions,
8469 // don't match the pattern.
8470 if (RemainingSteps == 0 && !RemainingLoadInstrs.empty())
8471 return false;
8472
8473 switch (NumLanes) {
8474 case 4:
8476 break;
8477 case 8:
8479 break;
8480 case 16:
8482 break;
8483 default:
8484 llvm_unreachable("Got bad number of lanes for gather pattern.");
8485 }
8486
8487 return true;
8488}
8489
8490/// Search for patterns of LD instructions we can optimize.
8492 SmallVectorImpl<unsigned> &Patterns) {
8493
8494 // The pattern searches for loads into single lanes.
8495 switch (Root.getOpcode()) {
8496 case AArch64::LD1i32:
8497 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 4);
8498 case AArch64::LD1i16:
8499 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 8);
8500 case AArch64::LD1i8:
8501 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 16);
8502 default:
8503 return false;
8504 }
8505}
8506
8507/// Generate optimized instruction sequence for gather load patterns to improve
8508/// Memory-Level Parallelism (MLP). This function transforms a chain of
8509/// sequential NEON lane loads into parallel vector loads that can execute
8510/// concurrently.
8511static void
8515 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8516 unsigned Pattern, unsigned NumLanes) {
8517 MachineFunction &MF = *Root.getParent()->getParent();
8518 MachineRegisterInfo &MRI = MF.getRegInfo();
8520
8521 // Gather the initial load instructions to build the pattern.
8522 SmallVector<MachineInstr *, 16> LoadToLaneInstrs;
8523 MachineInstr *CurrInstr = &Root;
8524 for (unsigned i = 0; i < NumLanes - 1; ++i) {
8525 LoadToLaneInstrs.push_back(CurrInstr);
8526 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8527 }
8528
8529 // Sort the load instructions according to the lane.
8530 llvm::sort(LoadToLaneInstrs,
8531 [](const MachineInstr *A, const MachineInstr *B) {
8532 return A->getOperand(2).getImm() > B->getOperand(2).getImm();
8533 });
8534
8535 MachineInstr *SubregToReg = CurrInstr;
8536 LoadToLaneInstrs.push_back(
8537 MRI.getUniqueVRegDef(SubregToReg->getOperand(1).getReg()));
8538 auto LoadToLaneInstrsAscending = llvm::reverse(LoadToLaneInstrs);
8539
8540 const TargetRegisterClass *FPR128RegClass =
8541 MRI.getRegClass(Root.getOperand(0).getReg());
8542
8543 // Helper lambda to create a LD1 instruction.
8544 auto CreateLD1Instruction = [&](MachineInstr *OriginalInstr,
8545 Register SrcRegister, unsigned Lane,
8546 Register OffsetRegister,
8547 bool OffsetRegisterKillState) {
8548 auto NewRegister = MRI.createVirtualRegister(FPR128RegClass);
8549 MachineInstrBuilder LoadIndexIntoRegister =
8550 BuildMI(MF, MIMetadata(*OriginalInstr), TII->get(Root.getOpcode()),
8551 NewRegister)
8552 .addReg(SrcRegister)
8553 .addImm(Lane)
8554 .addReg(OffsetRegister, getKillRegState(OffsetRegisterKillState))
8555 .setMemRefs(OriginalInstr->memoperands());
8556 InstrIdxForVirtReg.insert(std::make_pair(NewRegister, InsInstrs.size()));
8557 InsInstrs.push_back(LoadIndexIntoRegister);
8558 return NewRegister;
8559 };
8560
8561 // Helper to create load instruction based on the NumLanes in the NEON
8562 // register we are rewriting.
8563 auto CreateLDRInstruction =
8564 [&](unsigned NumLanes, Register DestReg, Register OffsetReg,
8566 unsigned Opcode;
8567 switch (NumLanes) {
8568 case 4:
8569 Opcode = AArch64::LDRSui;
8570 break;
8571 case 8:
8572 Opcode = AArch64::LDRHui;
8573 break;
8574 case 16:
8575 Opcode = AArch64::LDRBui;
8576 break;
8577 default:
8579 "Got unsupported number of lanes in machine-combiner gather pattern");
8580 }
8581 // Immediate offset load
8582 return BuildMI(MF, MIMetadata(Root), TII->get(Opcode), DestReg)
8583 .addReg(OffsetReg)
8584 .addImm(0)
8585 .setMemRefs(MMOs);
8586 };
8587
8588 // Load the remaining lanes into register 0.
8589 auto LanesToLoadToReg0 =
8590 llvm::make_range(LoadToLaneInstrsAscending.begin() + 1,
8591 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8592 Register PrevReg = SubregToReg->getOperand(0).getReg();
8593 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg0)) {
8594 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8595 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8596 OffsetRegOperand.getReg(),
8597 OffsetRegOperand.isKill());
8598 DelInstrs.push_back(LoadInstr);
8599 }
8600 Register LastLoadReg0 = PrevReg;
8601
8602 // First load into register 1. Perform an integer load to zero out the upper
8603 // lanes in a single instruction.
8604 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8605 MachineInstr *OriginalSplitLoad =
8606 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8607 Register DestRegForMiddleIndex = MRI.createVirtualRegister(
8608 MRI.getRegClass(Lane0Load->getOperand(0).getReg()));
8609
8610 const MachineOperand &OriginalSplitToLoadOffsetOperand =
8611 OriginalSplitLoad->getOperand(3);
8612 MachineInstrBuilder MiddleIndexLoadInstr =
8613 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8614 OriginalSplitToLoadOffsetOperand.getReg(),
8615 OriginalSplitLoad->memoperands());
8616
8617 InstrIdxForVirtReg.insert(
8618 std::make_pair(DestRegForMiddleIndex, InsInstrs.size()));
8619 InsInstrs.push_back(MiddleIndexLoadInstr);
8620 DelInstrs.push_back(OriginalSplitLoad);
8621
8622 // Subreg To Reg instruction for register 1.
8623 Register DestRegForSubregToReg = MRI.createVirtualRegister(FPR128RegClass);
8624 unsigned SubregType;
8625 switch (NumLanes) {
8626 case 4:
8627 SubregType = AArch64::ssub;
8628 break;
8629 case 8:
8630 SubregType = AArch64::hsub;
8631 break;
8632 case 16:
8633 SubregType = AArch64::bsub;
8634 break;
8635 default:
8637 "Got invalid NumLanes for machine-combiner gather pattern");
8638 }
8639
8640 auto SubRegToRegInstr =
8641 BuildMI(MF, MIMetadata(Root), TII->get(SubregToReg->getOpcode()),
8642 DestRegForSubregToReg)
8643 .addReg(DestRegForMiddleIndex, getKillRegState(true))
8644 .addImm(SubregType);
8645 InstrIdxForVirtReg.insert(
8646 std::make_pair(DestRegForSubregToReg, InsInstrs.size()));
8647 InsInstrs.push_back(SubRegToRegInstr);
8648
8649 // Load remaining lanes into register 1.
8650 auto LanesToLoadToReg1 =
8651 llvm::make_range(LoadToLaneInstrsAscending.begin() + NumLanes / 2 + 1,
8652 LoadToLaneInstrsAscending.end());
8653 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8654 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg1)) {
8655 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8656 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8657 OffsetRegOperand.getReg(),
8658 OffsetRegOperand.isKill());
8659
8660 // Do not add the last reg to DelInstrs - it will be removed later.
8661 if (Index == NumLanes / 2 - 2) {
8662 break;
8663 }
8664 DelInstrs.push_back(LoadInstr);
8665 }
8666 Register LastLoadReg1 = PrevReg;
8667
8668 // Create the final zip instruction to combine the results.
8669 MachineInstrBuilder ZipInstr =
8670 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::ZIP1v2i64),
8671 Root.getOperand(0).getReg())
8672 .addReg(LastLoadReg0)
8673 .addReg(LastLoadReg1);
8674 InsInstrs.push_back(ZipInstr);
8675}
8676
8690
8691/// Return true when there is potentially a faster code sequence for an
8692/// instruction chain ending in \p Root. All potential patterns are listed in
8693/// the \p Pattern vector. Pattern should be sorted in priority order since the
8694/// pattern evaluator stops checking as soon as it finds a faster sequence.
8695
8696bool AArch64InstrInfo::getMachineCombinerPatterns(
8697 MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
8698 bool DoRegPressureReduce) const {
8699 // Integer patterns
8700 if (getMaddPatterns(Root, Patterns))
8701 return true;
8702 // Floating point patterns
8703 if (getFMULPatterns(Root, Patterns))
8704 return true;
8705 if (getFMAPatterns(Root, Patterns))
8706 return true;
8707 if (getFNEGPatterns(Root, Patterns))
8708 return true;
8709
8710 // Other patterns
8711 if (getMiscPatterns(Root, Patterns))
8712 return true;
8713
8714 // Load patterns
8715 if (getLoadPatterns(Root, Patterns))
8716 return true;
8717
8718 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
8719 DoRegPressureReduce);
8720}
8721
8723/// genFusedMultiply - Generate fused multiply instructions.
8724/// This function supports both integer and floating point instructions.
8725/// A typical example:
8726/// F|MUL I=A,B,0
8727/// F|ADD R,I,C
8728/// ==> F|MADD R,A,B,C
8729/// \param MF Containing MachineFunction
8730/// \param MRI Register information
8731/// \param TII Target information
8732/// \param Root is the F|ADD instruction
8733/// \param [out] InsInstrs is a vector of machine instructions and will
8734/// contain the generated madd instruction
8735/// \param IdxMulOpd is index of operand in Root that is the result of
8736/// the F|MUL. In the example above IdxMulOpd is 1.
8737/// \param MaddOpc the opcode fo the f|madd instruction
8738/// \param RC Register class of operands
8739/// \param kind of fma instruction (addressing mode) to be generated
8740/// \param ReplacedAddend is the result register from the instruction
8741/// replacing the non-combined operand, if any.
8742static MachineInstr *
8744 const TargetInstrInfo *TII, MachineInstr &Root,
8745 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
8746 unsigned MaddOpc, const TargetRegisterClass *RC,
8748 const Register *ReplacedAddend = nullptr) {
8749 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8750
8751 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8752 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8753 Register ResultReg = Root.getOperand(0).getReg();
8754 Register SrcReg0 = MUL->getOperand(1).getReg();
8755 bool Src0IsKill = MUL->getOperand(1).isKill();
8756 Register SrcReg1 = MUL->getOperand(2).getReg();
8757 bool Src1IsKill = MUL->getOperand(2).isKill();
8758
8759 Register SrcReg2;
8760 bool Src2IsKill;
8761 if (ReplacedAddend) {
8762 // If we just generated a new addend, we must be it's only use.
8763 SrcReg2 = *ReplacedAddend;
8764 Src2IsKill = true;
8765 } else {
8766 SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
8767 Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
8768 }
8769
8770 if (ResultReg.isVirtual())
8771 MRI.constrainRegClass(ResultReg, RC);
8772 if (SrcReg0.isVirtual())
8773 MRI.constrainRegClass(SrcReg0, RC);
8774 if (SrcReg1.isVirtual())
8775 MRI.constrainRegClass(SrcReg1, RC);
8776 if (SrcReg2.isVirtual())
8777 MRI.constrainRegClass(SrcReg2, RC);
8778
8780 if (kind == FMAInstKind::Default)
8781 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8782 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8783 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8784 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8785 else if (kind == FMAInstKind::Indexed)
8786 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8787 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8788 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8789 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8790 .addImm(MUL->getOperand(3).getImm());
8791 else if (kind == FMAInstKind::Accumulator)
8792 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8793 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8794 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8795 .addReg(SrcReg1, getKillRegState(Src1IsKill));
8796 else
8797 assert(false && "Invalid FMA instruction kind \n");
8798 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
8799 InsInstrs.push_back(MIB);
8800 return MUL;
8801}
8802
8803static MachineInstr *
8805 const TargetInstrInfo *TII, MachineInstr &Root,
8807 MachineInstr *MAD = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8808
8809 unsigned Opc = 0;
8810 const TargetRegisterClass *RC = MRI.getRegClass(MAD->getOperand(0).getReg());
8811 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8812 Opc = AArch64::FNMADDSrrr;
8813 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8814 Opc = AArch64::FNMADDDrrr;
8815 else
8816 return nullptr;
8817
8818 Register ResultReg = Root.getOperand(0).getReg();
8819 Register SrcReg0 = MAD->getOperand(1).getReg();
8820 Register SrcReg1 = MAD->getOperand(2).getReg();
8821 Register SrcReg2 = MAD->getOperand(3).getReg();
8822 bool Src0IsKill = MAD->getOperand(1).isKill();
8823 bool Src1IsKill = MAD->getOperand(2).isKill();
8824 bool Src2IsKill = MAD->getOperand(3).isKill();
8825 if (ResultReg.isVirtual())
8826 MRI.constrainRegClass(ResultReg, RC);
8827 if (SrcReg0.isVirtual())
8828 MRI.constrainRegClass(SrcReg0, RC);
8829 if (SrcReg1.isVirtual())
8830 MRI.constrainRegClass(SrcReg1, RC);
8831 if (SrcReg2.isVirtual())
8832 MRI.constrainRegClass(SrcReg2, RC);
8833
8835 BuildMI(MF, MIMetadata(Root), TII->get(Opc), ResultReg)
8836 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8837 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8838 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8839 InsInstrs.push_back(MIB);
8840
8841 return MAD;
8842}
8843
8844/// Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
8845static MachineInstr *
8848 unsigned IdxDupOp, unsigned MulOpc,
8849 const TargetRegisterClass *RC, MachineRegisterInfo &MRI) {
8850 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8851 "Invalid index of FMUL operand");
8852
8853 MachineFunction &MF = *Root.getMF();
8855
8856 MachineInstr *Dup =
8857 MF.getRegInfo().getUniqueVRegDef(Root.getOperand(IdxDupOp).getReg());
8858
8859 if (Dup->getOpcode() == TargetOpcode::COPY)
8860 Dup = MRI.getUniqueVRegDef(Dup->getOperand(1).getReg());
8861
8862 Register DupSrcReg = Dup->getOperand(1).getReg();
8863 MRI.clearKillFlags(DupSrcReg);
8864 MRI.constrainRegClass(DupSrcReg, RC);
8865
8866 unsigned DupSrcLane = Dup->getOperand(2).getImm();
8867
8868 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8869 MachineOperand &MulOp = Root.getOperand(IdxMulOp);
8870
8871 Register ResultReg = Root.getOperand(0).getReg();
8872
8874 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MulOpc), ResultReg)
8875 .add(MulOp)
8876 .addReg(DupSrcReg)
8877 .addImm(DupSrcLane);
8878
8879 InsInstrs.push_back(MIB);
8880 return &Root;
8881}
8882
8883/// genFusedMultiplyAcc - Helper to generate fused multiply accumulate
8884/// instructions.
8885///
8886/// \see genFusedMultiply
8890 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8891 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8893}
8894
8895/// genNeg - Helper to generate an intermediate negation of the second operand
8896/// of Root
8898 const TargetInstrInfo *TII, MachineInstr &Root,
8900 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8901 unsigned MnegOpc, const TargetRegisterClass *RC) {
8902 Register NewVR = MRI.createVirtualRegister(RC);
8904 BuildMI(MF, MIMetadata(Root), TII->get(MnegOpc), NewVR)
8905 .add(Root.getOperand(2));
8906 InsInstrs.push_back(MIB);
8907
8908 assert(InstrIdxForVirtReg.empty());
8909 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
8910
8911 return NewVR;
8912}
8913
8914/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8915/// instructions with an additional negation of the accumulator
8919 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8920 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8921 assert(IdxMulOpd == 1);
8922
8923 Register NewVR =
8924 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8925 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8926 FMAInstKind::Accumulator, &NewVR);
8927}
8928
8929/// genFusedMultiplyIdx - Helper to generate fused multiply accumulate
8930/// instructions.
8931///
8932/// \see genFusedMultiply
8936 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8937 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8939}
8940
8941/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8942/// instructions with an additional negation of the accumulator
8946 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8947 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8948 assert(IdxMulOpd == 1);
8949
8950 Register NewVR =
8951 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8952
8953 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8954 FMAInstKind::Indexed, &NewVR);
8955}
8956
8957/// genMaddR - Generate madd instruction and combine mul and add using
8958/// an extra virtual register
8959/// Example - an ADD intermediate needs to be stored in a register:
8960/// MUL I=A,B,0
8961/// ADD R,I,Imm
8962/// ==> ORR V, ZR, Imm
8963/// ==> MADD R,A,B,V
8964/// \param MF Containing MachineFunction
8965/// \param MRI Register information
8966/// \param TII Target information
8967/// \param Root is the ADD instruction
8968/// \param [out] InsInstrs is a vector of machine instructions and will
8969/// contain the generated madd instruction
8970/// \param IdxMulOpd is index of operand in Root that is the result of
8971/// the MUL. In the example above IdxMulOpd is 1.
8972/// \param MaddOpc the opcode fo the madd instruction
8973/// \param VR is a virtual register that holds the value of an ADD operand
8974/// (V in the example above).
8975/// \param RC Register class of operands
8977 const TargetInstrInfo *TII, MachineInstr &Root,
8979 unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR,
8980 const TargetRegisterClass *RC) {
8981 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8982
8983 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8984 Register ResultReg = Root.getOperand(0).getReg();
8985 Register SrcReg0 = MUL->getOperand(1).getReg();
8986 bool Src0IsKill = MUL->getOperand(1).isKill();
8987 Register SrcReg1 = MUL->getOperand(2).getReg();
8988 bool Src1IsKill = MUL->getOperand(2).isKill();
8989
8990 if (ResultReg.isVirtual())
8991 MRI.constrainRegClass(ResultReg, RC);
8992 if (SrcReg0.isVirtual())
8993 MRI.constrainRegClass(SrcReg0, RC);
8994 if (SrcReg1.isVirtual())
8995 MRI.constrainRegClass(SrcReg1, RC);
8997 MRI.constrainRegClass(VR, RC);
8998
9000 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
9001 .addReg(SrcReg0, getKillRegState(Src0IsKill))
9002 .addReg(SrcReg1, getKillRegState(Src1IsKill))
9003 .addReg(VR);
9004 // Insert the MADD
9005 InsInstrs.push_back(MIB);
9006 return MUL;
9007}
9008
9009/// Do the following transformation
9010/// A - (B + C) ==> (A - B) - C
9011/// A - (B + C) ==> (A - C) - B
9013 const TargetInstrInfo *TII, MachineInstr &Root,
9016 unsigned IdxOpd1,
9017 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
9018 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9019 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9020 MachineInstr *AddMI = MRI.getUniqueVRegDef(Root.getOperand(2).getReg());
9021
9022 Register ResultReg = Root.getOperand(0).getReg();
9023 Register RegA = Root.getOperand(1).getReg();
9024 bool RegAIsKill = Root.getOperand(1).isKill();
9025 Register RegB = AddMI->getOperand(IdxOpd1).getReg();
9026 bool RegBIsKill = AddMI->getOperand(IdxOpd1).isKill();
9027 Register RegC = AddMI->getOperand(IdxOtherOpd).getReg();
9028 bool RegCIsKill = AddMI->getOperand(IdxOtherOpd).isKill();
9029 Register NewVR =
9031
9032 unsigned Opcode = Root.getOpcode();
9033 if (Opcode == AArch64::SUBSWrr)
9034 Opcode = AArch64::SUBWrr;
9035 else if (Opcode == AArch64::SUBSXrr)
9036 Opcode = AArch64::SUBXrr;
9037 else
9038 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9039 "Unexpected instruction opcode.");
9040
9041 uint32_t Flags = Root.mergeFlagsWith(*AddMI);
9042 Flags &= ~MachineInstr::NoSWrap;
9043 Flags &= ~MachineInstr::NoUWrap;
9044
9045 MachineInstrBuilder MIB1 =
9046 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), NewVR)
9047 .addReg(RegA, getKillRegState(RegAIsKill))
9048 .addReg(RegB, getKillRegState(RegBIsKill))
9049 .setMIFlags(Flags);
9050 MachineInstrBuilder MIB2 =
9051 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), ResultReg)
9052 .addReg(NewVR, getKillRegState(true))
9053 .addReg(RegC, getKillRegState(RegCIsKill))
9054 .setMIFlags(Flags);
9055
9056 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9057 InsInstrs.push_back(MIB1);
9058 InsInstrs.push_back(MIB2);
9059 DelInstrs.push_back(AddMI);
9060 DelInstrs.push_back(&Root);
9061}
9062
9063unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9064 unsigned int AccumulatorOpCode) const {
9065 switch (AccumulatorOpCode) {
9066 case AArch64::UABALB_ZZZ_D:
9067 case AArch64::SABALB_ZZZ_D:
9068 case AArch64::UABALT_ZZZ_D:
9069 case AArch64::SABALT_ZZZ_D:
9070 return AArch64::ADD_ZZZ_D;
9071 case AArch64::UABALB_ZZZ_H:
9072 case AArch64::SABALB_ZZZ_H:
9073 case AArch64::UABALT_ZZZ_H:
9074 case AArch64::SABALT_ZZZ_H:
9075 return AArch64::ADD_ZZZ_H;
9076 case AArch64::UABALB_ZZZ_S:
9077 case AArch64::SABALB_ZZZ_S:
9078 case AArch64::UABALT_ZZZ_S:
9079 case AArch64::SABALT_ZZZ_S:
9080 return AArch64::ADD_ZZZ_S;
9081 case AArch64::UABALv16i8_v8i16:
9082 case AArch64::SABALv8i8_v8i16:
9083 case AArch64::SABAv8i16:
9084 case AArch64::UABAv8i16:
9085 return AArch64::ADDv8i16;
9086 case AArch64::SABALv2i32_v2i64:
9087 case AArch64::UABALv2i32_v2i64:
9088 case AArch64::SABALv4i32_v2i64:
9089 return AArch64::ADDv2i64;
9090 case AArch64::UABALv4i16_v4i32:
9091 case AArch64::SABALv4i16_v4i32:
9092 case AArch64::SABALv8i16_v4i32:
9093 case AArch64::SABAv4i32:
9094 case AArch64::UABAv4i32:
9095 return AArch64::ADDv4i32;
9096 case AArch64::UABALv4i32_v2i64:
9097 return AArch64::ADDv2i64;
9098 case AArch64::UABALv8i16_v4i32:
9099 return AArch64::ADDv4i32;
9100 case AArch64::UABALv8i8_v8i16:
9101 case AArch64::SABALv16i8_v8i16:
9102 return AArch64::ADDv8i16;
9103 case AArch64::UABAv16i8:
9104 case AArch64::SABAv16i8:
9105 return AArch64::ADDv16i8;
9106 case AArch64::UABAv4i16:
9107 case AArch64::SABAv4i16:
9108 return AArch64::ADDv4i16;
9109 case AArch64::UABAv2i32:
9110 case AArch64::SABAv2i32:
9111 return AArch64::ADDv2i32;
9112 case AArch64::UABAv8i8:
9113 case AArch64::SABAv8i8:
9114 return AArch64::ADDv8i8;
9115 default:
9116 llvm_unreachable("Unknown accumulator opcode");
9117 }
9118}
9119
9120/// When getMachineCombinerPatterns() finds potential patterns,
9121/// this function generates the instructions that could replace the
9122/// original code sequence
9123void AArch64InstrInfo::genAlternativeCodeSequence(
9124 MachineInstr &Root, unsigned Pattern,
9127 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const {
9128 MachineBasicBlock &MBB = *Root.getParent();
9129 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9130 MachineFunction &MF = *MBB.getParent();
9131 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
9132
9133 MachineInstr *MUL = nullptr;
9134 const TargetRegisterClass *RC;
9135 unsigned Opc;
9136 switch (Pattern) {
9137 default:
9138 // Reassociate instructions.
9139 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
9140 DelInstrs, InstrIdxForVirtReg);
9141 return;
9143 // A - (B + C)
9144 // ==> (A - B) - C
9145 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 1,
9146 InstrIdxForVirtReg);
9147 return;
9149 // A - (B + C)
9150 // ==> (A - C) - B
9151 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 2,
9152 InstrIdxForVirtReg);
9153 return;
9156 // MUL I=A,B,0
9157 // ADD R,I,C
9158 // ==> MADD R,A,B,C
9159 // --- Create(MADD);
9161 Opc = AArch64::MADDWrrr;
9162 RC = &AArch64::GPR32RegClass;
9163 } else {
9164 Opc = AArch64::MADDXrrr;
9165 RC = &AArch64::GPR64RegClass;
9166 }
9167 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9168 break;
9171 // MUL I=A,B,0
9172 // ADD R,C,I
9173 // ==> MADD R,A,B,C
9174 // --- Create(MADD);
9176 Opc = AArch64::MADDWrrr;
9177 RC = &AArch64::GPR32RegClass;
9178 } else {
9179 Opc = AArch64::MADDXrrr;
9180 RC = &AArch64::GPR64RegClass;
9181 }
9182 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9183 break;
9188 // MUL I=A,B,0
9189 // ADD/SUB R,I,Imm
9190 // ==> MOV V, Imm/-Imm
9191 // ==> MADD R,A,B,V
9192 // --- Create(MADD);
9193 const TargetRegisterClass *RC;
9194 unsigned BitSize, MovImm;
9197 MovImm = AArch64::MOVi32imm;
9198 RC = &AArch64::GPR32spRegClass;
9199 BitSize = 32;
9200 Opc = AArch64::MADDWrrr;
9201 RC = &AArch64::GPR32RegClass;
9202 } else {
9203 MovImm = AArch64::MOVi64imm;
9204 RC = &AArch64::GPR64spRegClass;
9205 BitSize = 64;
9206 Opc = AArch64::MADDXrrr;
9207 RC = &AArch64::GPR64RegClass;
9208 }
9209 Register NewVR = MRI.createVirtualRegister(RC);
9210 uint64_t Imm = Root.getOperand(2).getImm();
9211
9212 if (Root.getOperand(3).isImm()) {
9213 unsigned Val = Root.getOperand(3).getImm();
9214 Imm = Imm << Val;
9215 }
9216 bool IsSub = Pattern == AArch64MachineCombinerPattern::MULSUBWI_OP1 ||
9218 uint64_t UImm = SignExtend64(IsSub ? -Imm : Imm, BitSize);
9219 // Check that the immediate can be composed via a single instruction.
9221 AArch64_IMM::expandMOVImm(UImm, BitSize, Insn);
9222 if (Insn.size() != 1)
9223 return;
9224 MachineInstrBuilder MIB1 =
9225 BuildMI(MF, MIMetadata(Root), TII->get(MovImm), NewVR)
9226 .addImm(IsSub ? -Imm : Imm);
9227 InsInstrs.push_back(MIB1);
9228 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9229 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9230 break;
9231 }
9234 // MUL I=A,B,0
9235 // SUB R,I, C
9236 // ==> SUB V, 0, C
9237 // ==> MADD R,A,B,V // = -C + A*B
9238 // --- Create(MADD);
9239 const TargetRegisterClass *SubRC;
9240 unsigned SubOpc, ZeroReg;
9242 SubOpc = AArch64::SUBWrr;
9243 SubRC = &AArch64::GPR32spRegClass;
9244 ZeroReg = AArch64::WZR;
9245 Opc = AArch64::MADDWrrr;
9246 RC = &AArch64::GPR32RegClass;
9247 } else {
9248 SubOpc = AArch64::SUBXrr;
9249 SubRC = &AArch64::GPR64spRegClass;
9250 ZeroReg = AArch64::XZR;
9251 Opc = AArch64::MADDXrrr;
9252 RC = &AArch64::GPR64RegClass;
9253 }
9254 Register NewVR = MRI.createVirtualRegister(SubRC);
9255 // SUB NewVR, 0, C
9256 MachineInstrBuilder MIB1 =
9257 BuildMI(MF, MIMetadata(Root), TII->get(SubOpc), NewVR)
9258 .addReg(ZeroReg)
9259 .add(Root.getOperand(2));
9260 InsInstrs.push_back(MIB1);
9261 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9262 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9263 break;
9264 }
9267 // MUL I=A,B,0
9268 // SUB R,C,I
9269 // ==> MSUB R,A,B,C (computes C - A*B)
9270 // --- Create(MSUB);
9272 Opc = AArch64::MSUBWrrr;
9273 RC = &AArch64::GPR32RegClass;
9274 } else {
9275 Opc = AArch64::MSUBXrrr;
9276 RC = &AArch64::GPR64RegClass;
9277 }
9278 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9279 break;
9281 Opc = AArch64::MLAv8i8;
9282 RC = &AArch64::FPR64RegClass;
9283 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9284 break;
9286 Opc = AArch64::MLAv8i8;
9287 RC = &AArch64::FPR64RegClass;
9288 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9289 break;
9291 Opc = AArch64::MLAv16i8;
9292 RC = &AArch64::FPR128RegClass;
9293 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9294 break;
9296 Opc = AArch64::MLAv16i8;
9297 RC = &AArch64::FPR128RegClass;
9298 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9299 break;
9301 Opc = AArch64::MLAv4i16;
9302 RC = &AArch64::FPR64RegClass;
9303 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9304 break;
9306 Opc = AArch64::MLAv4i16;
9307 RC = &AArch64::FPR64RegClass;
9308 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9309 break;
9311 Opc = AArch64::MLAv8i16;
9312 RC = &AArch64::FPR128RegClass;
9313 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9314 break;
9316 Opc = AArch64::MLAv8i16;
9317 RC = &AArch64::FPR128RegClass;
9318 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9319 break;
9321 Opc = AArch64::MLAv2i32;
9322 RC = &AArch64::FPR64RegClass;
9323 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9324 break;
9326 Opc = AArch64::MLAv2i32;
9327 RC = &AArch64::FPR64RegClass;
9328 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9329 break;
9331 Opc = AArch64::MLAv4i32;
9332 RC = &AArch64::FPR128RegClass;
9333 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9334 break;
9336 Opc = AArch64::MLAv4i32;
9337 RC = &AArch64::FPR128RegClass;
9338 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9339 break;
9340
9342 Opc = AArch64::MLAv8i8;
9343 RC = &AArch64::FPR64RegClass;
9344 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9345 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i8,
9346 RC);
9347 break;
9349 Opc = AArch64::MLSv8i8;
9350 RC = &AArch64::FPR64RegClass;
9351 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9352 break;
9354 Opc = AArch64::MLAv16i8;
9355 RC = &AArch64::FPR128RegClass;
9356 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9357 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv16i8,
9358 RC);
9359 break;
9361 Opc = AArch64::MLSv16i8;
9362 RC = &AArch64::FPR128RegClass;
9363 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9364 break;
9366 Opc = AArch64::MLAv4i16;
9367 RC = &AArch64::FPR64RegClass;
9368 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9369 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9370 RC);
9371 break;
9373 Opc = AArch64::MLSv4i16;
9374 RC = &AArch64::FPR64RegClass;
9375 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9376 break;
9378 Opc = AArch64::MLAv8i16;
9379 RC = &AArch64::FPR128RegClass;
9380 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9381 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9382 RC);
9383 break;
9385 Opc = AArch64::MLSv8i16;
9386 RC = &AArch64::FPR128RegClass;
9387 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9388 break;
9390 Opc = AArch64::MLAv2i32;
9391 RC = &AArch64::FPR64RegClass;
9392 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9393 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9394 RC);
9395 break;
9397 Opc = AArch64::MLSv2i32;
9398 RC = &AArch64::FPR64RegClass;
9399 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9400 break;
9402 Opc = AArch64::MLAv4i32;
9403 RC = &AArch64::FPR128RegClass;
9404 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9405 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9406 RC);
9407 break;
9409 Opc = AArch64::MLSv4i32;
9410 RC = &AArch64::FPR128RegClass;
9411 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9412 break;
9413
9415 Opc = AArch64::MLAv4i16_indexed;
9416 RC = &AArch64::FPR64RegClass;
9417 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9418 break;
9420 Opc = AArch64::MLAv4i16_indexed;
9421 RC = &AArch64::FPR64RegClass;
9422 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9423 break;
9425 Opc = AArch64::MLAv8i16_indexed;
9426 RC = &AArch64::FPR128RegClass;
9427 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9428 break;
9430 Opc = AArch64::MLAv8i16_indexed;
9431 RC = &AArch64::FPR128RegClass;
9432 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9433 break;
9435 Opc = AArch64::MLAv2i32_indexed;
9436 RC = &AArch64::FPR64RegClass;
9437 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9438 break;
9440 Opc = AArch64::MLAv2i32_indexed;
9441 RC = &AArch64::FPR64RegClass;
9442 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9443 break;
9445 Opc = AArch64::MLAv4i32_indexed;
9446 RC = &AArch64::FPR128RegClass;
9447 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9448 break;
9450 Opc = AArch64::MLAv4i32_indexed;
9451 RC = &AArch64::FPR128RegClass;
9452 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9453 break;
9454
9456 Opc = AArch64::MLAv4i16_indexed;
9457 RC = &AArch64::FPR64RegClass;
9458 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9459 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9460 RC);
9461 break;
9463 Opc = AArch64::MLSv4i16_indexed;
9464 RC = &AArch64::FPR64RegClass;
9465 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9466 break;
9468 Opc = AArch64::MLAv8i16_indexed;
9469 RC = &AArch64::FPR128RegClass;
9470 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9471 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9472 RC);
9473 break;
9475 Opc = AArch64::MLSv8i16_indexed;
9476 RC = &AArch64::FPR128RegClass;
9477 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9478 break;
9480 Opc = AArch64::MLAv2i32_indexed;
9481 RC = &AArch64::FPR64RegClass;
9482 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9483 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9484 RC);
9485 break;
9487 Opc = AArch64::MLSv2i32_indexed;
9488 RC = &AArch64::FPR64RegClass;
9489 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9490 break;
9492 Opc = AArch64::MLAv4i32_indexed;
9493 RC = &AArch64::FPR128RegClass;
9494 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9495 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9496 RC);
9497 break;
9499 Opc = AArch64::MLSv4i32_indexed;
9500 RC = &AArch64::FPR128RegClass;
9501 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9502 break;
9503
9504 // Floating Point Support
9506 Opc = AArch64::FMADDHrrr;
9507 RC = &AArch64::FPR16RegClass;
9508 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9509 break;
9511 Opc = AArch64::FMADDSrrr;
9512 RC = &AArch64::FPR32RegClass;
9513 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9514 break;
9516 Opc = AArch64::FMADDDrrr;
9517 RC = &AArch64::FPR64RegClass;
9518 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9519 break;
9520
9522 Opc = AArch64::FMADDHrrr;
9523 RC = &AArch64::FPR16RegClass;
9524 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9525 break;
9527 Opc = AArch64::FMADDSrrr;
9528 RC = &AArch64::FPR32RegClass;
9529 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9530 break;
9532 Opc = AArch64::FMADDDrrr;
9533 RC = &AArch64::FPR64RegClass;
9534 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9535 break;
9536
9538 Opc = AArch64::FMLAv1i32_indexed;
9539 RC = &AArch64::FPR32RegClass;
9540 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9542 break;
9544 Opc = AArch64::FMLAv1i32_indexed;
9545 RC = &AArch64::FPR32RegClass;
9546 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9548 break;
9549
9551 Opc = AArch64::FMLAv1i64_indexed;
9552 RC = &AArch64::FPR64RegClass;
9553 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9555 break;
9557 Opc = AArch64::FMLAv1i64_indexed;
9558 RC = &AArch64::FPR64RegClass;
9559 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9561 break;
9562
9564 RC = &AArch64::FPR64RegClass;
9565 Opc = AArch64::FMLAv4i16_indexed;
9566 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9568 break;
9570 RC = &AArch64::FPR64RegClass;
9571 Opc = AArch64::FMLAv4f16;
9572 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9574 break;
9576 RC = &AArch64::FPR64RegClass;
9577 Opc = AArch64::FMLAv4i16_indexed;
9578 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9580 break;
9582 RC = &AArch64::FPR64RegClass;
9583 Opc = AArch64::FMLAv4f16;
9584 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9586 break;
9587
9590 RC = &AArch64::FPR64RegClass;
9592 Opc = AArch64::FMLAv2i32_indexed;
9593 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9595 } else {
9596 Opc = AArch64::FMLAv2f32;
9597 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9599 }
9600 break;
9603 RC = &AArch64::FPR64RegClass;
9605 Opc = AArch64::FMLAv2i32_indexed;
9606 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9608 } else {
9609 Opc = AArch64::FMLAv2f32;
9610 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9612 }
9613 break;
9614
9616 RC = &AArch64::FPR128RegClass;
9617 Opc = AArch64::FMLAv8i16_indexed;
9618 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9620 break;
9622 RC = &AArch64::FPR128RegClass;
9623 Opc = AArch64::FMLAv8f16;
9624 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9626 break;
9628 RC = &AArch64::FPR128RegClass;
9629 Opc = AArch64::FMLAv8i16_indexed;
9630 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9632 break;
9634 RC = &AArch64::FPR128RegClass;
9635 Opc = AArch64::FMLAv8f16;
9636 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9638 break;
9639
9642 RC = &AArch64::FPR128RegClass;
9644 Opc = AArch64::FMLAv2i64_indexed;
9645 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9647 } else {
9648 Opc = AArch64::FMLAv2f64;
9649 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9651 }
9652 break;
9655 RC = &AArch64::FPR128RegClass;
9657 Opc = AArch64::FMLAv2i64_indexed;
9658 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9660 } else {
9661 Opc = AArch64::FMLAv2f64;
9662 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9664 }
9665 break;
9666
9669 RC = &AArch64::FPR128RegClass;
9671 Opc = AArch64::FMLAv4i32_indexed;
9672 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9674 } else {
9675 Opc = AArch64::FMLAv4f32;
9676 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9678 }
9679 break;
9680
9683 RC = &AArch64::FPR128RegClass;
9685 Opc = AArch64::FMLAv4i32_indexed;
9686 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9688 } else {
9689 Opc = AArch64::FMLAv4f32;
9690 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9692 }
9693 break;
9694
9696 Opc = AArch64::FNMSUBHrrr;
9697 RC = &AArch64::FPR16RegClass;
9698 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9699 break;
9701 Opc = AArch64::FNMSUBSrrr;
9702 RC = &AArch64::FPR32RegClass;
9703 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9704 break;
9706 Opc = AArch64::FNMSUBDrrr;
9707 RC = &AArch64::FPR64RegClass;
9708 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9709 break;
9710
9712 Opc = AArch64::FNMADDHrrr;
9713 RC = &AArch64::FPR16RegClass;
9714 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9715 break;
9717 Opc = AArch64::FNMADDSrrr;
9718 RC = &AArch64::FPR32RegClass;
9719 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9720 break;
9722 Opc = AArch64::FNMADDDrrr;
9723 RC = &AArch64::FPR64RegClass;
9724 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9725 break;
9726
9728 Opc = AArch64::FMSUBHrrr;
9729 RC = &AArch64::FPR16RegClass;
9730 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9731 break;
9733 Opc = AArch64::FMSUBSrrr;
9734 RC = &AArch64::FPR32RegClass;
9735 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9736 break;
9738 Opc = AArch64::FMSUBDrrr;
9739 RC = &AArch64::FPR64RegClass;
9740 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9741 break;
9742
9744 Opc = AArch64::FMLSv1i32_indexed;
9745 RC = &AArch64::FPR32RegClass;
9746 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9748 break;
9749
9751 Opc = AArch64::FMLSv1i64_indexed;
9752 RC = &AArch64::FPR64RegClass;
9753 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9755 break;
9756
9759 RC = &AArch64::FPR64RegClass;
9760 Register NewVR = MRI.createVirtualRegister(RC);
9761 MachineInstrBuilder MIB1 =
9762 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f16), NewVR)
9763 .add(Root.getOperand(2));
9764 InsInstrs.push_back(MIB1);
9765 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9767 Opc = AArch64::FMLAv4f16;
9768 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9769 FMAInstKind::Accumulator, &NewVR);
9770 } else {
9771 Opc = AArch64::FMLAv4i16_indexed;
9772 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9773 FMAInstKind::Indexed, &NewVR);
9774 }
9775 break;
9776 }
9778 RC = &AArch64::FPR64RegClass;
9779 Opc = AArch64::FMLSv4f16;
9780 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9782 break;
9784 RC = &AArch64::FPR64RegClass;
9785 Opc = AArch64::FMLSv4i16_indexed;
9786 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9788 break;
9789
9792 RC = &AArch64::FPR64RegClass;
9794 Opc = AArch64::FMLSv2i32_indexed;
9795 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9797 } else {
9798 Opc = AArch64::FMLSv2f32;
9799 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9801 }
9802 break;
9803
9806 RC = &AArch64::FPR128RegClass;
9807 Register NewVR = MRI.createVirtualRegister(RC);
9808 MachineInstrBuilder MIB1 =
9809 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv8f16), NewVR)
9810 .add(Root.getOperand(2));
9811 InsInstrs.push_back(MIB1);
9812 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9814 Opc = AArch64::FMLAv8f16;
9815 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9816 FMAInstKind::Accumulator, &NewVR);
9817 } else {
9818 Opc = AArch64::FMLAv8i16_indexed;
9819 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9820 FMAInstKind::Indexed, &NewVR);
9821 }
9822 break;
9823 }
9825 RC = &AArch64::FPR128RegClass;
9826 Opc = AArch64::FMLSv8f16;
9827 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9829 break;
9831 RC = &AArch64::FPR128RegClass;
9832 Opc = AArch64::FMLSv8i16_indexed;
9833 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9835 break;
9836
9839 RC = &AArch64::FPR128RegClass;
9841 Opc = AArch64::FMLSv2i64_indexed;
9842 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9844 } else {
9845 Opc = AArch64::FMLSv2f64;
9846 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9848 }
9849 break;
9850
9853 RC = &AArch64::FPR128RegClass;
9855 Opc = AArch64::FMLSv4i32_indexed;
9856 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9858 } else {
9859 Opc = AArch64::FMLSv4f32;
9860 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9862 }
9863 break;
9866 RC = &AArch64::FPR64RegClass;
9867 Register NewVR = MRI.createVirtualRegister(RC);
9868 MachineInstrBuilder MIB1 =
9869 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f32), NewVR)
9870 .add(Root.getOperand(2));
9871 InsInstrs.push_back(MIB1);
9872 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9874 Opc = AArch64::FMLAv2i32_indexed;
9875 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9876 FMAInstKind::Indexed, &NewVR);
9877 } else {
9878 Opc = AArch64::FMLAv2f32;
9879 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9880 FMAInstKind::Accumulator, &NewVR);
9881 }
9882 break;
9883 }
9886 RC = &AArch64::FPR128RegClass;
9887 Register NewVR = MRI.createVirtualRegister(RC);
9888 MachineInstrBuilder MIB1 =
9889 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f32), NewVR)
9890 .add(Root.getOperand(2));
9891 InsInstrs.push_back(MIB1);
9892 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9894 Opc = AArch64::FMLAv4i32_indexed;
9895 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9896 FMAInstKind::Indexed, &NewVR);
9897 } else {
9898 Opc = AArch64::FMLAv4f32;
9899 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9900 FMAInstKind::Accumulator, &NewVR);
9901 }
9902 break;
9903 }
9906 RC = &AArch64::FPR128RegClass;
9907 Register NewVR = MRI.createVirtualRegister(RC);
9908 MachineInstrBuilder MIB1 =
9909 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f64), NewVR)
9910 .add(Root.getOperand(2));
9911 InsInstrs.push_back(MIB1);
9912 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9914 Opc = AArch64::FMLAv2i64_indexed;
9915 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9916 FMAInstKind::Indexed, &NewVR);
9917 } else {
9918 Opc = AArch64::FMLAv2f64;
9919 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9920 FMAInstKind::Accumulator, &NewVR);
9921 }
9922 break;
9923 }
9926 unsigned IdxDupOp =
9928 : 2;
9929 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i32_indexed,
9930 &AArch64::FPR128RegClass, MRI);
9931 break;
9932 }
9935 unsigned IdxDupOp =
9937 : 2;
9938 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i64_indexed,
9939 &AArch64::FPR128RegClass, MRI);
9940 break;
9941 }
9944 unsigned IdxDupOp =
9946 : 2;
9947 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i16_indexed,
9948 &AArch64::FPR128_loRegClass, MRI);
9949 break;
9950 }
9953 unsigned IdxDupOp =
9955 : 2;
9956 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i32_indexed,
9957 &AArch64::FPR128RegClass, MRI);
9958 break;
9959 }
9962 unsigned IdxDupOp =
9964 : 2;
9965 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv8i16_indexed,
9966 &AArch64::FPR128_loRegClass, MRI);
9967 break;
9968 }
9970 MUL = genFNegatedMAD(MF, MRI, TII, Root, InsInstrs);
9971 break;
9972 }
9974 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9975 Pattern, 4);
9976 break;
9977 }
9979 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9980 Pattern, 8);
9981 break;
9982 }
9984 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9985 Pattern, 16);
9986 break;
9987 }
9988
9989 } // end switch (Pattern)
9990 // Record MUL and ADD/SUB for deletion
9991 if (MUL)
9992 DelInstrs.push_back(MUL);
9993 DelInstrs.push_back(&Root);
9994
9995 // Set the flags on the inserted instructions to be the merged flags of the
9996 // instructions that we have combined.
9997 uint32_t Flags = Root.getFlags();
9998 if (MUL)
9999 Flags = Root.mergeFlagsWith(*MUL);
10000 for (auto *MI : InsInstrs)
10001 MI->setFlags(Flags);
10002}
10003
10004/// Replace csincr-branch sequence by simple conditional branch
10005///
10006/// Examples:
10007/// 1. \code
10008/// csinc w9, wzr, wzr, <condition code>
10009/// tbnz w9, #0, 0x44
10010/// \endcode
10011/// to
10012/// \code
10013/// b.<inverted condition code>
10014/// \endcode
10015///
10016/// 2. \code
10017/// csinc w9, wzr, wzr, <condition code>
10018/// tbz w9, #0, 0x44
10019/// \endcode
10020/// to
10021/// \code
10022/// b.<condition code>
10023/// \endcode
10024///
10025/// Replace compare and branch sequence by TBZ/TBNZ instruction when the
10026/// compare's constant operand is power of 2.
10027///
10028/// Examples:
10029/// \code
10030/// and w8, w8, #0x400
10031/// cbnz w8, L1
10032/// \endcode
10033/// to
10034/// \code
10035/// tbnz w8, #10, L1
10036/// \endcode
10037///
10038/// \param MI Conditional Branch
10039/// \return True when the simple conditional branch is generated
10040///
10042 bool IsNegativeBranch = false;
10043 bool IsTestAndBranch = false;
10044 unsigned TargetBBInMI = 0;
10045 switch (MI.getOpcode()) {
10046 default:
10047 llvm_unreachable("Unknown branch instruction?");
10048 case AArch64::Bcc:
10049 case AArch64::CBWPri:
10050 case AArch64::CBXPri:
10051 case AArch64::CBBAssertExt:
10052 case AArch64::CBHAssertExt:
10053 case AArch64::CBWPrr:
10054 case AArch64::CBXPrr:
10055 return false;
10056 case AArch64::CBZW:
10057 case AArch64::CBZX:
10058 TargetBBInMI = 1;
10059 break;
10060 case AArch64::CBNZW:
10061 case AArch64::CBNZX:
10062 TargetBBInMI = 1;
10063 IsNegativeBranch = true;
10064 break;
10065 case AArch64::TBZW:
10066 case AArch64::TBZX:
10067 TargetBBInMI = 2;
10068 IsTestAndBranch = true;
10069 break;
10070 case AArch64::TBNZW:
10071 case AArch64::TBNZX:
10072 TargetBBInMI = 2;
10073 IsNegativeBranch = true;
10074 IsTestAndBranch = true;
10075 break;
10076 }
10077 // So we increment a zero register and test for bits other
10078 // than bit 0? Conservatively bail out in case the verifier
10079 // missed this case.
10080 if (IsTestAndBranch && MI.getOperand(1).getImm())
10081 return false;
10082
10083 // Find Definition.
10084 assert(MI.getParent() && "Incomplete machine instruction\n");
10085 MachineBasicBlock *MBB = MI.getParent();
10086 MachineFunction *MF = MBB->getParent();
10087 MachineRegisterInfo *MRI = &MF->getRegInfo();
10088 Register VReg = MI.getOperand(0).getReg();
10089 if (!VReg.isVirtual())
10090 return false;
10091
10092 MachineInstr *DefMI = MRI->getVRegDef(VReg);
10093
10094 // Look through COPY instructions to find definition.
10095 while (DefMI->isCopy()) {
10096 Register CopyVReg = DefMI->getOperand(1).getReg();
10097 if (!MRI->hasOneNonDBGUse(CopyVReg))
10098 return false;
10099 if (!MRI->hasOneDef(CopyVReg))
10100 return false;
10101 DefMI = MRI->getVRegDef(CopyVReg);
10102 }
10103
10104 switch (DefMI->getOpcode()) {
10105 default:
10106 return false;
10107 // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
10108 case AArch64::ANDWri:
10109 case AArch64::ANDXri: {
10110 if (IsTestAndBranch)
10111 return false;
10112 if (DefMI->getParent() != MBB)
10113 return false;
10114 if (!MRI->hasOneNonDBGUse(VReg))
10115 return false;
10116
10117 bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
10119 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
10120 if (!isPowerOf2_64(Mask))
10121 return false;
10122
10123 MachineOperand &MO = DefMI->getOperand(1);
10124 Register NewReg = MO.getReg();
10125 if (!NewReg.isVirtual())
10126 return false;
10127
10128 assert(!MRI->def_empty(NewReg) && "Register must be defined.");
10129
10130 MachineBasicBlock &RefToMBB = *MBB;
10131 MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
10132 DebugLoc DL = MI.getDebugLoc();
10133 unsigned Imm = Log2_64(Mask);
10134 unsigned Opc = (Imm < 32)
10135 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
10136 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
10137 MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
10138 .addReg(NewReg)
10139 .addImm(Imm)
10140 .addMBB(TBB);
10141 // Register lives on to the CBZ now.
10142 MO.setIsKill(false);
10143
10144 // For immediate smaller than 32, we need to use the 32-bit
10145 // variant (W) in all cases. Indeed the 64-bit variant does not
10146 // allow to encode them.
10147 // Therefore, if the input register is 64-bit, we need to take the
10148 // 32-bit sub-part.
10149 if (!Is32Bit && Imm < 32)
10150 NewMI->getOperand(0).setSubReg(AArch64::sub_32);
10151 MI.eraseFromParent();
10152 return true;
10153 }
10154 // Look for CSINC
10155 case AArch64::CSINCWr:
10156 case AArch64::CSINCXr: {
10157 if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
10158 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
10159 !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
10160 DefMI->getOperand(2).getReg() == AArch64::XZR))
10161 return false;
10162
10163 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
10164 true) != -1)
10165 return false;
10166
10167 AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
10168 // Convert only when the condition code is not modified between
10169 // the CSINC and the branch. The CC may be used by other
10170 // instructions in between.
10172 return false;
10173 MachineBasicBlock &RefToMBB = *MBB;
10174 MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
10175 DebugLoc DL = MI.getDebugLoc();
10176 if (IsNegativeBranch)
10178 BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
10179 MI.eraseFromParent();
10180 return true;
10181 }
10182 }
10183}
10184
10185std::pair<unsigned, unsigned>
10186AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
10187 const unsigned Mask = AArch64II::MO_FRAGMENT;
10188 return std::make_pair(TF & Mask, TF & ~Mask);
10189}
10190
10192AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
10193 using namespace AArch64II;
10194
10195 static const std::pair<unsigned, const char *> TargetFlags[] = {
10196 {MO_PAGE, "aarch64-page"}, {MO_PAGEOFF, "aarch64-pageoff"},
10197 {MO_G3, "aarch64-g3"}, {MO_G2, "aarch64-g2"},
10198 {MO_G1, "aarch64-g1"}, {MO_G0, "aarch64-g0"},
10199 {MO_HI12, "aarch64-hi12"}};
10200 return ArrayRef(TargetFlags);
10201}
10202
10204AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
10205 using namespace AArch64II;
10206
10207 static const std::pair<unsigned, const char *> TargetFlags[] = {
10208 {MO_COFFSTUB, "aarch64-coffstub"},
10209 {MO_GOT, "aarch64-got"},
10210 {MO_NC, "aarch64-nc"},
10211 {MO_S, "aarch64-s"},
10212 {MO_TLS, "aarch64-tls"},
10213 {MO_DLLIMPORT, "aarch64-dllimport"},
10214 {MO_PREL, "aarch64-prel"},
10215 {MO_TAGGED, "aarch64-tagged"},
10216 {MO_ARM64EC_CALLMANGLE, "aarch64-arm64ec-callmangle"},
10217 };
10218 return ArrayRef(TargetFlags);
10219}
10220
10222AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const {
10223 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10224 {{MOSuppressPair, "aarch64-suppress-pair"},
10225 {MOStridedAccess, "aarch64-strided-access"}};
10226 return ArrayRef(TargetFlags);
10227}
10228
10229/// Constants defining how certain sequences should be outlined.
10230/// This encompasses how an outlined function should be called, and what kind of
10231/// frame should be emitted for that outlined function.
10232///
10233/// \p MachineOutlinerDefault implies that the function should be called with
10234/// a save and restore of LR to the stack.
10235///
10236/// That is,
10237///
10238/// I1 Save LR OUTLINED_FUNCTION:
10239/// I2 --> BL OUTLINED_FUNCTION I1
10240/// I3 Restore LR I2
10241/// I3
10242/// RET
10243///
10244/// * Call construction overhead: 3 (save + BL + restore)
10245/// * Frame construction overhead: 1 (ret)
10246/// * Requires stack fixups? Yes
10247///
10248/// \p MachineOutlinerTailCall implies that the function is being created from
10249/// a sequence of instructions ending in a return.
10250///
10251/// That is,
10252///
10253/// I1 OUTLINED_FUNCTION:
10254/// I2 --> B OUTLINED_FUNCTION I1
10255/// RET I2
10256/// RET
10257///
10258/// * Call construction overhead: 1 (B)
10259/// * Frame construction overhead: 0 (Return included in sequence)
10260/// * Requires stack fixups? No
10261///
10262/// \p MachineOutlinerNoLRSave implies that the function should be called using
10263/// a BL instruction, but doesn't require LR to be saved and restored. This
10264/// happens when LR is known to be dead.
10265///
10266/// That is,
10267///
10268/// I1 OUTLINED_FUNCTION:
10269/// I2 --> BL OUTLINED_FUNCTION I1
10270/// I3 I2
10271/// I3
10272/// RET
10273///
10274/// * Call construction overhead: 1 (BL)
10275/// * Frame construction overhead: 1 (RET)
10276/// * Requires stack fixups? No
10277///
10278/// \p MachineOutlinerThunk implies that the function is being created from
10279/// a sequence of instructions ending in a call. The outlined function is
10280/// called with a BL instruction, and the outlined function tail-calls the
10281/// original call destination.
10282///
10283/// That is,
10284///
10285/// I1 OUTLINED_FUNCTION:
10286/// I2 --> BL OUTLINED_FUNCTION I1
10287/// BL f I2
10288/// B f
10289/// * Call construction overhead: 1 (BL)
10290/// * Frame construction overhead: 0
10291/// * Requires stack fixups? No
10292///
10293/// \p MachineOutlinerRegSave implies that the function should be called with a
10294/// save and restore of LR to an available register. This allows us to avoid
10295/// stack fixups. Note that this outlining variant is compatible with the
10296/// NoLRSave case.
10297///
10298/// That is,
10299///
10300/// I1 Save LR OUTLINED_FUNCTION:
10301/// I2 --> BL OUTLINED_FUNCTION I1
10302/// I3 Restore LR I2
10303/// I3
10304/// RET
10305///
10306/// * Call construction overhead: 3 (save + BL + restore)
10307/// * Frame construction overhead: 1 (ret)
10308/// * Requires stack fixups? No
10310 MachineOutlinerDefault, /// Emit a save, restore, call, and return.
10311 MachineOutlinerTailCall, /// Only emit a branch.
10312 MachineOutlinerNoLRSave, /// Emit a call and return.
10313 MachineOutlinerThunk, /// Emit a call and tail-call.
10314 MachineOutlinerRegSave /// Same as default, but save to a register.
10315};
10316
10322
10323/// Return true if the frame-record form of the outlined prologue is enabled for
10324/// the target of \p MF.
10325///
10326/// A non-leaf outlined function must save LR. On MachO, saving LR alone
10327/// (str x30) has no compact unwind encoding, so we get a large DWARF FDE
10328/// instead. Saving FP and LR as a frame record (stp x29, x30 ; mov x29, sp)
10329/// gets the small FRAME encoding, and costs one extra instruction.
10334
10335/// Return true if the outlined function in \p MBB should save FP and LR as a
10336/// frame record instead of saving LR alone.
10338 const MachineBasicBlock &MBB) {
10339 const MachineFunction &MF = *MBB.getParent();
10340
10341 // Only worth it if the function has unwind info to shrink.
10344 return false;
10345
10346 // Only safe if the outlined code never touches FP, since we overwrite it.
10348 for (const MachineInstr &MI : MBB.instrs())
10349 LRU.accumulate(MI);
10350 return LRU.available(AArch64::FP);
10351}
10352
10353/// Predict what the above will answer, for use while costing candidates. The
10354/// outlined function does not exist yet, so answer from \p RepeatedSequenceLocs
10355/// instead. This is only an estimate; buildOutlinedFrame() makes the call.
10357 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10358 const TargetRegisterInfo &TRI) {
10359 if (!isCompactUnwindFrameRecordEnabled(*RepeatedSequenceLocs.front().getMF()))
10360 return false;
10361
10362 // The outlined function is nounwind only if every candidate is, so it has
10363 // unwind info if any candidate does.
10364 if (llvm::none_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10365 const MachineFunction &MF = *C.getMF();
10366 return MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
10367 }))
10368 return false;
10369
10370 // FP is free in the outlined function only if it is free in every candidate.
10371 return llvm::all_of(RepeatedSequenceLocs, [&TRI](outliner::Candidate &C) {
10372 return C.isAvailableInsideSeq(AArch64::FP, TRI);
10373 });
10374}
10375
10377AArch64InstrInfo::findRegisterToSaveLRTo(outliner::Candidate &C) const {
10378 MachineFunction *MF = C.getMF();
10379 const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
10380 const AArch64RegisterInfo *ARI =
10381 static_cast<const AArch64RegisterInfo *>(&TRI);
10382 // Check if there is an available register across the sequence that we can
10383 // use.
10384 for (unsigned Reg : AArch64::GPR64RegClass) {
10385 if (!ARI->isReservedReg(*MF, Reg) &&
10386 Reg != AArch64::LR && // LR is not reserved, but don't use it.
10387 Reg != AArch64::X16 && // X16 is not guaranteed to be preserved.
10388 Reg != AArch64::X17 && // Ditto for X17.
10389 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&
10390 C.isAvailableInsideSeq(Reg, TRI))
10391 return Reg;
10392 }
10393 return Register();
10394}
10395
10396static bool
10398 const outliner::Candidate &b) {
10399 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10400 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10401
10402 return MFIa->getSignReturnAddressCondition() ==
10404}
10405
10406static bool
10408 const outliner::Candidate &b) {
10409 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10410 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10411
10412 return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey();
10413}
10414
10416 const outliner::Candidate &b) {
10417 const AArch64Subtarget &SubtargetA =
10419 const AArch64Subtarget &SubtargetB =
10420 b.getMF()->getSubtarget<AArch64Subtarget>();
10421 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10422}
10423
10424std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10425AArch64InstrInfo::getOutliningCandidateInfo(
10426 const MachineModuleInfo &MMI,
10427 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10428 unsigned MinRepeats) const {
10429 unsigned SequenceSize = 0;
10430 for (auto &MI : RepeatedSequenceLocs[0])
10431 SequenceSize += getInstSizeInBytes(MI);
10432
10433 unsigned NumBytesToCreateFrame = 0;
10434
10435 // Avoid splitting ADRP ADD/LDR pair into outlined functions.
10436 // These instructions are fused together by the scheduler.
10437 // Any candidate where ADRP is the last instruction should be rejected
10438 // as that will lead to splitting ADRP pair.
10439 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10440 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10441 if (LastMI.getOpcode() == AArch64::ADRP &&
10442 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0 &&
10443 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10444 return std::nullopt;
10445 }
10446
10447 // Similarly any candidate where the first instruction is ADD/LDR with a
10448 // page offset should be rejected to avoid ADRP splitting.
10449 if ((FirstMI.getOpcode() == AArch64::ADDXri ||
10450 FirstMI.getOpcode() == AArch64::LDRXui) &&
10451 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_PAGEOFF) != 0 &&
10452 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10453 return std::nullopt;
10454 }
10455
10456 // We only allow outlining for functions having exactly matching return
10457 // address signing attributes, i.e., all share the same value for the
10458 // attribute "sign-return-address" and all share the same type of key they
10459 // are signed with.
10460 // Additionally we require all functions to simultaneously either support
10461 // v8.3a features or not. Otherwise an outlined function could get signed
10462 // using dedicated v8.3 instructions and a call from a function that doesn't
10463 // support v8.3 instructions would therefore be invalid.
10464 if (std::adjacent_find(
10465 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10466 [](const outliner::Candidate &a, const outliner::Candidate &b) {
10467 // Return true if a and b are non-equal w.r.t. return address
10468 // signing or support of v8.3a features
10469 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10470 outliningCandidatesSigningKeyConsensus(a, b) &&
10471 outliningCandidatesV8_3OpsConsensus(a, b)) {
10472 return false;
10473 }
10474 return true;
10475 }) != RepeatedSequenceLocs.end()) {
10476 return std::nullopt;
10477 }
10478
10479 // Since at this point all candidates agree on their return address signing
10480 // picking just one is fine. If the candidate functions potentially sign their
10481 // return addresses, the outlined function should do the same. Note that in
10482 // the case of "sign-return-address"="non-leaf" this is an assumption: It is
10483 // not certainly true that the outlined function will have to sign its return
10484 // address but this decision is made later, when the decision to outline
10485 // has already been made.
10486 // The same holds for the number of additional instructions we need: On
10487 // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
10488 // necessary. However, at this point we don't know if the outlined function
10489 // will have a RET instruction so we assume the worst.
10490 const TargetRegisterInfo &TRI = getRegisterInfo();
10491 // Performing a tail call may require extra checks when PAuth is enabled.
10492 // If PAuth is disabled, set it to zero for uniformity.
10493 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10494 const auto RASignCondition = RepeatedSequenceLocs[0]
10495 .getMF()
10496 ->getInfo<AArch64FunctionInfo>()
10497 ->getSignReturnAddressCondition();
10498 if (RASignCondition != SignReturnAddress::None) {
10499 // One PAC and one AUT instructions
10500 NumBytesToCreateFrame += 8;
10501
10502 // PAuth is enabled - set extra tail call cost, if any.
10503 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10504 *RepeatedSequenceLocs[0].getMF());
10505 NumBytesToCheckLRInTCEpilogue =
10507 // Checking the authenticated LR value may significantly impact
10508 // SequenceSize, so account for it for more precise results.
10509 if (isTailCallReturnInst(RepeatedSequenceLocs[0].back()))
10510 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10511
10512 // We have to check if sp modifying instructions would get outlined.
10513 // If so we only allow outlining if sp is unchanged overall, so matching
10514 // sub and add instructions are okay to outline, all other sp modifications
10515 // are not
10516 auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) {
10517 int SPValue = 0;
10518 for (auto &MI : C) {
10519 if (MI.modifiesRegister(AArch64::SP, &TRI)) {
10520 switch (MI.getOpcode()) {
10521 case AArch64::ADDXri:
10522 case AArch64::ADDWri:
10523 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10524 assert(MI.getOperand(2).isImm() &&
10525 "Expected operand to be immediate");
10526 assert(MI.getOperand(1).isReg() &&
10527 "Expected operand to be a register");
10528 // Check if the add just increments sp. If so, we search for
10529 // matching sub instructions that decrement sp. If not, the
10530 // modification is illegal
10531 if (MI.getOperand(1).getReg() == AArch64::SP)
10532 SPValue += MI.getOperand(2).getImm();
10533 else
10534 return true;
10535 break;
10536 case AArch64::SUBXri:
10537 case AArch64::SUBWri:
10538 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10539 assert(MI.getOperand(2).isImm() &&
10540 "Expected operand to be immediate");
10541 assert(MI.getOperand(1).isReg() &&
10542 "Expected operand to be a register");
10543 // Check if the sub just decrements sp. If so, we search for
10544 // matching add instructions that increment sp. If not, the
10545 // modification is illegal
10546 if (MI.getOperand(1).getReg() == AArch64::SP)
10547 SPValue -= MI.getOperand(2).getImm();
10548 else
10549 return true;
10550 break;
10551 default:
10552 return true;
10553 }
10554 }
10555 }
10556 if (SPValue)
10557 return true;
10558 return false;
10559 };
10560 // Remove candidates with illegal stack modifying instructions
10561 llvm::erase_if(RepeatedSequenceLocs, hasIllegalSPModification);
10562
10563 // If the sequence doesn't have enough candidates left, then we're done.
10564 if (RepeatedSequenceLocs.size() < MinRepeats)
10565 return std::nullopt;
10566 }
10567
10568 // Properties about candidate MBBs that hold for all of them.
10569 unsigned FlagsSetInAll = 0xF;
10570
10571 // Compute liveness information for each candidate, and set FlagsSetInAll.
10572 for (outliner::Candidate &C : RepeatedSequenceLocs)
10573 FlagsSetInAll &= C.Flags;
10574
10575 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10576
10577 // Helper lambda which sets call information for every candidate.
10578 auto SetCandidateCallInfo =
10579 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {
10580 for (outliner::Candidate &C : RepeatedSequenceLocs)
10581 C.setCallInfo(CallID, NumBytesForCall);
10582 };
10583
10584 unsigned FrameID = MachineOutlinerDefault;
10585 NumBytesToCreateFrame += 4;
10586
10587 bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10588 return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement();
10589 });
10590
10591 // We check to see if CFI Instructions are present, and if they are
10592 // we find the number of CFI Instructions in the candidates.
10593 unsigned CFICount = 0;
10594 for (auto &I : RepeatedSequenceLocs[0]) {
10595 if (I.isCFIInstruction())
10596 CFICount++;
10597 }
10598
10599 // We compare the number of found CFI Instructions to the number of CFI
10600 // instructions in the parent function for each candidate. We must check this
10601 // since if we outline one of the CFI instructions in a function, we have to
10602 // outline them all for correctness. If we do not, the address offsets will be
10603 // incorrect between the two sections of the program.
10604 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10605 std::vector<MCCFIInstruction> CFIInstructions =
10606 C.getMF()->getFrameInstructions();
10607
10608 if (CFICount > 0 && CFICount != CFIInstructions.size())
10609 return std::nullopt;
10610 }
10611
10612 // Returns true if an instructions is safe to fix up, false otherwise.
10613 auto IsSafeToFixup = [this, &TRI](MachineInstr &MI) {
10614 if (MI.isCall())
10615 return true;
10616
10617 if (!MI.modifiesRegister(AArch64::SP, &TRI) &&
10618 !MI.readsRegister(AArch64::SP, &TRI))
10619 return true;
10620
10621 // Any modification of SP will break our code to save/restore LR.
10622 // FIXME: We could handle some instructions which add a constant
10623 // offset to SP, with a bit more work.
10624 if (MI.modifiesRegister(AArch64::SP, &TRI))
10625 return false;
10626
10627 // At this point, we have a stack instruction that we might need to
10628 // fix up. We'll handle it if it's a load or store.
10629 if (MI.mayLoadOrStore()) {
10630 const MachineOperand *Base; // Filled with the base operand of MI.
10631 int64_t Offset; // Filled with the offset of MI.
10632 bool OffsetIsScalable;
10633
10634 // Does it allow us to offset the base operand and is the base the
10635 // register SP?
10636 if (!getMemOperandWithOffset(MI, Base, Offset, OffsetIsScalable, &TRI) ||
10637 !Base->isReg() || Base->getReg() != AArch64::SP)
10638 return false;
10639
10640 // Fixe-up code below assumes bytes.
10641 if (OffsetIsScalable)
10642 return false;
10643
10644 // Find the minimum/maximum offset for this instruction and check
10645 // if fixing it up would be in range.
10646 int64_t MinOffset,
10647 MaxOffset; // Unscaled offsets for the instruction.
10648 // The scale to multiply the offsets by.
10649 TypeSize Scale(0U, false), DummyWidth(0U, false);
10650 getMemOpInfo(MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10651
10652 Offset += 16; // Update the offset to what it would be if we outlined.
10653 if (Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10654 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10655 return false;
10656
10657 // It's in range, so we can outline it.
10658 return true;
10659 }
10660
10661 // FIXME: Add handling for instructions like "add x0, sp, #8".
10662
10663 // We can't fix it up, so don't outline it.
10664 return false;
10665 };
10666
10667 // True if it's possible to fix up each stack instruction in this sequence.
10668 // Important for frames/call variants that modify the stack.
10669 bool AllStackInstrsSafe =
10670 llvm::all_of(RepeatedSequenceLocs[0], IsSafeToFixup);
10671
10672 // If the last instruction in any candidate is a terminator, then we should
10673 // tail call all of the candidates.
10674 if (RepeatedSequenceLocs[0].back().isTerminator()) {
10675 FrameID = MachineOutlinerTailCall;
10676 NumBytesToCreateFrame = 0;
10677 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10678 SetCandidateCallInfo(MachineOutlinerTailCall, NumBytesForCall);
10679 }
10680
10681 else if (LastInstrOpcode == AArch64::BL ||
10682 ((LastInstrOpcode == AArch64::BLR ||
10683 LastInstrOpcode == AArch64::BLRNoIP) &&
10684 !HasBTI)) {
10685 // FIXME: Do we need to check if the code after this uses the value of LR?
10686 FrameID = MachineOutlinerThunk;
10687 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10688 SetCandidateCallInfo(MachineOutlinerThunk, 4);
10689 }
10690
10691 else {
10692 // We need to decide how to emit calls + frames. We can always emit the same
10693 // frame if we don't need to save to the stack. If we have to save to the
10694 // stack, then we need a different frame.
10695 unsigned NumBytesNoStackCalls = 0;
10696 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10697
10698 // Check if we have to save LR.
10699 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10700 bool LRAvailable =
10702 ? C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI)
10703 : true;
10704 // If we have a noreturn caller, then we're going to be conservative and
10705 // say that we have to save LR. If we don't have a ret at the end of the
10706 // block, then we can't reason about liveness accurately.
10707 //
10708 // FIXME: We can probably do better than always disabling this in
10709 // noreturn functions by fixing up the liveness info.
10710 bool IsNoReturn =
10711 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10712
10713 // Is LR available? If so, we don't need a save.
10714 if (LRAvailable && !IsNoReturn) {
10715 NumBytesNoStackCalls += 4;
10716 C.setCallInfo(MachineOutlinerNoLRSave, 4);
10717 CandidatesWithoutStackFixups.push_back(C);
10718 }
10719
10720 // Is an unused register available? If so, we won't modify the stack, so
10721 // we can outline with the same frame type as those that don't save LR.
10722 else if (findRegisterToSaveLRTo(C)) {
10723 NumBytesNoStackCalls += 12;
10724 C.setCallInfo(MachineOutlinerRegSave, 12);
10725 CandidatesWithoutStackFixups.push_back(C);
10726 }
10727
10728 // Is SP used in the sequence at all? If not, we don't have to modify
10729 // the stack, so we are guaranteed to get the same frame.
10730 else if (C.isAvailableInsideSeq(AArch64::SP, TRI)) {
10731 NumBytesNoStackCalls += 12;
10732 C.setCallInfo(MachineOutlinerDefault, 12);
10733 CandidatesWithoutStackFixups.push_back(C);
10734 }
10735
10736 // If we outline this, we need to modify the stack. Pretend we don't
10737 // outline this by saving all of its bytes.
10738 else {
10739 NumBytesNoStackCalls += SequenceSize;
10740 }
10741 }
10742
10743 // If there are no places where we have to save LR, then note that we
10744 // don't have to update the stack. Otherwise, give every candidate the
10745 // default call type, as long as it's safe to do so.
10746 if (!AllStackInstrsSafe ||
10747 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10748 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10749 FrameID = MachineOutlinerNoLRSave;
10750 if (RepeatedSequenceLocs.size() < MinRepeats)
10751 return std::nullopt;
10752 } else {
10753 SetCandidateCallInfo(MachineOutlinerDefault, 12);
10754
10755 // Bugzilla ID: 46767
10756 // TODO: Check if fixing up the stack more than once is safe so we can
10757 // outline these.
10758 //
10759 // An outline resulting in a caller that requires stack fixups at the
10760 // callsite to a callee that also requires stack fixups can happen when
10761 // there are no available registers at the candidate callsite for a
10762 // candidate that itself also has calls.
10763 //
10764 // In other words if function_containing_sequence in the following pseudo
10765 // assembly requires that we save LR at the point of the call, but there
10766 // are no available registers: in this case we save using SP and as a
10767 // result the SP offsets requires stack fixups by multiples of 16.
10768 //
10769 // function_containing_sequence:
10770 // ...
10771 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10772 // call OUTLINED_FUNCTION_N
10773 // restore LR from SP
10774 // ...
10775 //
10776 // OUTLINED_FUNCTION_N:
10777 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10778 // ...
10779 // bl foo
10780 // restore LR from SP
10781 // ret
10782 //
10783 // Because the code to handle more than one stack fixup does not
10784 // currently have the proper checks for legality, these cases will assert
10785 // in the AArch64 MachineOutliner. This is because the code to do this
10786 // needs more hardening, testing, better checks that generated code is
10787 // legal, etc and because it is only verified to handle a single pass of
10788 // stack fixup.
10789 //
10790 // The assert happens in AArch64InstrInfo::buildOutlinedFrame to catch
10791 // these cases until they are known to be handled. Bugzilla 46767 is
10792 // referenced in comments at the assert site.
10793 //
10794 // To avoid asserting (or generating non-legal code on noassert builds)
10795 // we remove all candidates which would need more than one stack fixup by
10796 // pruning the cases where the candidate has calls while also having no
10797 // available LR and having no available general purpose registers to copy
10798 // LR to (ie one extra stack save/restore).
10799 //
10800 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10801 erase_if(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
10802 auto IsCall = [](const MachineInstr &MI) { return MI.isCall(); };
10803 return (llvm::any_of(C, IsCall)) &&
10804 (!C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI) ||
10805 !findRegisterToSaveLRTo(C));
10806 });
10807 }
10808 }
10809
10810 // If we dropped all of the candidates, bail out here.
10811 if (RepeatedSequenceLocs.size() < MinRepeats)
10812 return std::nullopt;
10813 }
10814
10815 // Does every candidate's MBB contain a call? If so, then we might have a call
10816 // in the range.
10817 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10818 // Check if the range contains a call. These require a save + restore of the
10819 // link register.
10820 outliner::Candidate &FirstCand = RepeatedSequenceLocs[0];
10821 bool ModStackToSaveLR = false;
10822 if (any_of(drop_end(FirstCand),
10823 [](const MachineInstr &MI) { return MI.isCall(); }))
10824 ModStackToSaveLR = true;
10825
10826 // Handle the last instruction separately. If this is a tail call, then the
10827 // last instruction is a call. We don't want to save + restore in this case.
10828 // However, it could be possible that the last instruction is a call without
10829 // it being valid to tail call this sequence. We should consider this as
10830 // well.
10831 else if (FrameID != MachineOutlinerThunk &&
10832 FrameID != MachineOutlinerTailCall && FirstCand.back().isCall())
10833 ModStackToSaveLR = true;
10834
10835 if (ModStackToSaveLR) {
10836 // We can't fix up the stack. Bail out.
10837 if (!AllStackInstrsSafe)
10838 return std::nullopt;
10839
10840 // Save + restore LR.
10841 NumBytesToCreateFrame += 8;
10842
10843 // Add the extra mov if we will save a frame record instead of just LR.
10845 RepeatedSequenceLocs, TRI))
10846 NumBytesToCreateFrame += 4;
10847 }
10848 }
10849
10850 // If we have CFI instructions, we can only outline if the outlined section
10851 // can be a tail call
10852 if (FrameID != MachineOutlinerTailCall && CFICount > 0)
10853 return std::nullopt;
10854
10855 return std::make_unique<outliner::OutlinedFunction>(
10856 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10857}
10858
10859void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10860 Function &F, std::vector<outliner::Candidate> &Candidates) const {
10861 // If a bunch of candidates reach this point they must agree on their return
10862 // address signing. It is therefore enough to just consider the signing
10863 // behaviour of one of them
10864 const auto &CFn = Candidates.front().getMF()->getFunction();
10865
10866 if (CFn.hasFnAttribute("ptrauth-returns"))
10867 F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
10868 if (CFn.hasFnAttribute("ptrauth-auth-traps"))
10869 F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
10870 // Since all candidates belong to the same module, just copy the
10871 // function-level attributes of an arbitrary function.
10872 if (CFn.hasFnAttribute("sign-return-address"))
10873 F.addFnAttr(CFn.getFnAttribute("sign-return-address"));
10874 if (CFn.hasFnAttribute("sign-return-address-key"))
10875 F.addFnAttr(CFn.getFnAttribute("sign-return-address-key"));
10876
10877 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);
10878}
10879
10880bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10881 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
10882 const Function &F = MF.getFunction();
10883
10884 // Can F be deduplicated by the linker? If it can, don't outline from it.
10885 if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
10886 return false;
10887
10888 // Don't outline from functions with section markings; the program could
10889 // expect that all the code is in the named section.
10890 // FIXME: Allow outlining from multiple functions with the same section
10891 // marking.
10892 if (F.hasSection())
10893 return false;
10894
10895 // Outlining from functions with redzones is unsafe since the outliner may
10896 // modify the stack. Check if hasRedZone is true or unknown; if yes, don't
10897 // outline from it.
10898 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
10899 if (!AFI || AFI->hasRedZone().value_or(true))
10900 return false;
10901
10902 // FIXME: Determine whether it is safe to outline from functions which contain
10903 // streaming-mode changes. We may need to ensure any smstart/smstop pairs are
10904 // outlined together and ensure it is safe to outline with async unwind info,
10905 // required for saving & restoring VG around calls.
10906 if (AFI->hasStreamingModeChanges())
10907 return false;
10908
10909 // FIXME: Teach the outliner to generate/handle Windows unwind info.
10911 return false;
10912
10913 // It's safe to outline from MF.
10914 return true;
10915}
10916
10918AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
10919 unsigned &Flags) const {
10921 "Must track liveness!");
10923 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10924 Ranges;
10925 // According to the AArch64 Procedure Call Standard, the following are
10926 // undefined on entry/exit from a function call:
10927 //
10928 // * Registers x16, x17, (and thus w16, w17)
10929 // * Condition codes (and thus the NZCV register)
10930 //
10931 // If any of these registers are used inside or live across an outlined
10932 // function, then they may be modified later, either by the compiler or
10933 // some other tool (like the linker).
10934 //
10935 // To avoid outlining in these situations, partition each block into ranges
10936 // where these registers are dead. We will only outline from those ranges.
10937 LiveRegUnits LRU(getRegisterInfo());
10938 auto AreAllUnsafeRegsDead = [&LRU]() {
10939 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10940 LRU.available(AArch64::NZCV);
10941 };
10942
10943 // We need to know if LR is live across an outlining boundary later on in
10944 // order to decide how we'll create the outlined call, frame, etc.
10945 //
10946 // It's pretty expensive to check this for *every candidate* within a block.
10947 // That's some potentially n^2 behaviour, since in the worst case, we'd need
10948 // to compute liveness from the end of the block for O(n) candidates within
10949 // the block.
10950 //
10951 // So, to improve the average case, let's keep track of liveness from the end
10952 // of the block to the beginning of *every outlinable range*. If we know that
10953 // LR is available in every range we could outline from, then we know that
10954 // we don't need to check liveness for any candidate within that range.
10955 bool LRAvailableEverywhere = true;
10956 // Compute liveness bottom-up.
10957 LRU.addLiveOuts(MBB);
10958 // Update flags that require info about the entire MBB.
10959 auto UpdateWholeMBBFlags = [&Flags](const MachineInstr &MI) {
10960 if (MI.isCall() && !MI.isTerminator())
10962 };
10963 // Range: [RangeBegin, RangeEnd)
10964 MachineBasicBlock::instr_iterator RangeBegin, RangeEnd;
10965 unsigned RangeLen;
10966 auto CreateNewRangeStartingAt =
10967 [&RangeBegin, &RangeEnd,
10968 &RangeLen](MachineBasicBlock::instr_iterator NewBegin) {
10969 RangeBegin = NewBegin;
10970 RangeEnd = std::next(RangeBegin);
10971 RangeLen = 0;
10972 };
10973 auto SaveRangeIfNonEmpty = [&RangeLen, &Ranges, &RangeBegin, &RangeEnd]() {
10974 // At least one unsafe register is not dead. We do not want to outline at
10975 // this point. If it is long enough to outline from and does not cross a
10976 // bundle boundary, save the range [RangeBegin, RangeEnd).
10977 if (RangeLen <= 1)
10978 return;
10979 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
10980 return;
10981 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
10982 return;
10983 Ranges.emplace_back(RangeBegin, RangeEnd);
10984 };
10985 // Find the first point where all unsafe registers are dead.
10986 // FIND: <safe instr> <-- end of first potential range
10987 // SKIP: <unsafe def>
10988 // SKIP: ... everything between ...
10989 // SKIP: <unsafe use>
10990 auto FirstPossibleEndPt = MBB.instr_rbegin();
10991 for (; FirstPossibleEndPt != MBB.instr_rend(); ++FirstPossibleEndPt) {
10992 if (!FirstPossibleEndPt->isDebugInstr())
10993 LRU.stepBackward(*FirstPossibleEndPt);
10994 // Update flags that impact how we outline across the entire block,
10995 // regardless of safety.
10996 UpdateWholeMBBFlags(*FirstPossibleEndPt);
10997 if (AreAllUnsafeRegsDead())
10998 break;
10999 }
11000 // If we exhausted the entire block, we have no safe ranges to outline.
11001 if (FirstPossibleEndPt == MBB.instr_rend())
11002 return Ranges;
11003 // Current range.
11004 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
11005 // StartPt points to the first place where all unsafe registers
11006 // are dead (if there is any such point). Begin partitioning the MBB into
11007 // ranges.
11008 for (auto &MI : make_range(FirstPossibleEndPt, MBB.instr_rend())) {
11009 if (!MI.isDebugInstr())
11010 LRU.stepBackward(MI);
11011 UpdateWholeMBBFlags(MI);
11012 if (!AreAllUnsafeRegsDead()) {
11013 SaveRangeIfNonEmpty();
11014 CreateNewRangeStartingAt(MI.getIterator());
11015 continue;
11016 }
11017 LRAvailableEverywhere &= LRU.available(AArch64::LR);
11018 RangeBegin = MI.getIterator();
11019 ++RangeLen;
11020 }
11021 // Above loop misses the last (or only) range. If we are still safe, then
11022 // let's save the range.
11023 if (AreAllUnsafeRegsDead())
11024 SaveRangeIfNonEmpty();
11025 if (Ranges.empty())
11026 return Ranges;
11027 // We found the ranges bottom-up. Mapping expects the top-down. Reverse
11028 // the order.
11029 std::reverse(Ranges.begin(), Ranges.end());
11030 // If there is at least one outlinable range where LR is unavailable
11031 // somewhere, remember that.
11032 if (!LRAvailableEverywhere)
11034 return Ranges;
11035}
11036
11038AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
11040 unsigned Flags) const {
11041 MachineInstr &MI = *MIT;
11042
11043 // Don't outline anything used for return address signing. The outlined
11044 // function will get signed later if needed
11045 switch (MI.getOpcode()) {
11046 case AArch64::PACM:
11047 case AArch64::PACIASP:
11048 case AArch64::PACIBSP:
11049 case AArch64::PACIASPPC:
11050 case AArch64::PACIBSPPC:
11051 case AArch64::AUTIASP:
11052 case AArch64::AUTIBSP:
11053 case AArch64::AUTIASPPCi:
11054 case AArch64::AUTIASPPCr:
11055 case AArch64::AUTIBSPPCi:
11056 case AArch64::AUTIBSPPCr:
11057 case AArch64::RETAA:
11058 case AArch64::RETAB:
11059 case AArch64::RETAASPPCi:
11060 case AArch64::RETAASPPCr:
11061 case AArch64::RETABSPPCi:
11062 case AArch64::RETABSPPCr:
11063 case AArch64::EMITBKEY:
11064 case AArch64::PAUTH_PROLOGUE:
11065 case AArch64::PAUTH_EPILOGUE:
11067 }
11068
11069 // We can only outline these if we will tail call the outlined function, or
11070 // fix up the CFI offsets. Currently, CFI instructions are outlined only if
11071 // in a tail call.
11072 //
11073 // FIXME: If the proper fixups for the offset are implemented, this should be
11074 // possible.
11075 if (MI.isCFIInstruction())
11077
11078 // Is this a terminator for a basic block?
11079 if (MI.isTerminator())
11080 // TargetInstrInfo::getOutliningType has already filtered out anything
11081 // that would break this, so we can allow it here.
11083
11084 // Make sure none of the operands are un-outlinable.
11085 for (const MachineOperand &MOP : MI.operands()) {
11086 // A check preventing CFI indices was here before, but only CFI
11087 // instructions should have those.
11088 assert(!MOP.isCFIIndex());
11089
11090 // If it uses LR or W30 explicitly, then don't touch it.
11091 if (MOP.isReg() && !MOP.isImplicit() &&
11092 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
11094 }
11095
11096 // Special cases for instructions that can always be outlined, but will fail
11097 // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
11098 // be outlined because they don't require a *specific* value to be in LR.
11099 if (MI.getOpcode() == AArch64::ADRP)
11101
11102 // If MI is a call we might be able to outline it. We don't want to outline
11103 // any calls that rely on the position of items on the stack. When we outline
11104 // something containing a call, we have to emit a save and restore of LR in
11105 // the outlined function. Currently, this always happens by saving LR to the
11106 // stack. Thus, if we outline, say, half the parameters for a function call
11107 // plus the call, then we'll break the callee's expectations for the layout
11108 // of the stack.
11109 //
11110 // FIXME: Allow calls to functions which construct a stack frame, as long
11111 // as they don't access arguments on the stack.
11112 // FIXME: Figure out some way to analyze functions defined in other modules.
11113 // We should be able to compute the memory usage based on the IR calling
11114 // convention, even if we can't see the definition.
11115 if (MI.isCall()) {
11116 // Get the function associated with the call. Look at each operand and find
11117 // the one that represents the callee and get its name.
11118 const Function *Callee = nullptr;
11119 for (const MachineOperand &MOP : MI.operands()) {
11120 if (MOP.isGlobal()) {
11121 Callee = dyn_cast<Function>(MOP.getGlobal());
11122 break;
11123 }
11124 }
11125
11126 // Never outline calls to mcount. There isn't any rule that would require
11127 // this, but the Linux kernel's "ftrace" feature depends on it.
11128 if (Callee && Callee->getName() == "\01_mcount")
11130
11131 // If we don't know anything about the callee, assume it depends on the
11132 // stack layout of the caller. In that case, it's only legal to outline
11133 // as a tail-call. Explicitly list the call instructions we know about so we
11134 // don't get unexpected results with call pseudo-instructions.
11135 auto UnknownCallOutlineType = outliner::InstrType::Illegal;
11136 if (MI.getOpcode() == AArch64::BLR ||
11137 MI.getOpcode() == AArch64::BLRNoIP || MI.getOpcode() == AArch64::BL)
11138 UnknownCallOutlineType = outliner::InstrType::LegalTerminator;
11139
11140 if (!Callee)
11141 return UnknownCallOutlineType;
11142
11143 // We have a function we have information about. Check it if it's something
11144 // can safely outline.
11145 MachineFunction *CalleeMF = MMI.getMachineFunction(*Callee);
11146
11147 // We don't know what's going on with the callee at all. Don't touch it.
11148 if (!CalleeMF)
11149 return UnknownCallOutlineType;
11150
11151 // Check if we know anything about the callee saves on the function. If we
11152 // don't, then don't touch it, since that implies that we haven't
11153 // computed anything about its stack frame yet.
11154 MachineFrameInfo &MFI = CalleeMF->getFrameInfo();
11155 if (!MFI.isCalleeSavedInfoValid() || MFI.getStackSize() > 0 ||
11156 MFI.getNumObjects() > 0)
11157 return UnknownCallOutlineType;
11158
11159 // At this point, we can say that CalleeMF ought to not pass anything on the
11160 // stack. Therefore, we can outline it.
11162 }
11163
11164 // Don't touch the link register or W30.
11165 if (MI.readsRegister(AArch64::W30, &getRegisterInfo()) ||
11166 MI.modifiesRegister(AArch64::W30, &getRegisterInfo()))
11168
11169 // Don't outline BTI instructions, because that will prevent the outlining
11170 // site from being indirectly callable.
11171 if (hasBTISemantics(MI))
11173
11175}
11176
11177void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
11178 for (MachineInstr &MI : MBB) {
11179 const MachineOperand *Base;
11180 TypeSize Width(0, false);
11181 int64_t Offset;
11182 bool OffsetIsScalable;
11183
11184 // Is this a load or store with an immediate offset with SP as the base?
11185 if (!MI.mayLoadOrStore() ||
11186 !getMemOperandWithOffsetWidth(MI, Base, Offset, OffsetIsScalable, Width,
11187 &RI) ||
11188 (Base->isReg() && Base->getReg() != AArch64::SP))
11189 continue;
11190
11191 // It is, so we have to fix it up.
11192 TypeSize Scale(0U, false);
11193 int64_t Dummy1, Dummy2;
11194
11195 MachineOperand &StackOffsetOperand = getMemOpBaseRegImmOfsOffsetOperand(MI);
11196 assert(StackOffsetOperand.isImm() && "Stack offset wasn't immediate!");
11197 getMemOpInfo(MI.getOpcode(), Scale, Width, Dummy1, Dummy2);
11198 assert(Scale != 0 && "Unexpected opcode!");
11199 assert(!OffsetIsScalable && "Expected offset to be a byte offset");
11200
11201 // We've pushed the return address to the stack, so add 16 to the offset.
11202 // This is safe, since we already checked if it would overflow when we
11203 // checked if this instruction was legal to outline.
11204 int64_t NewImm = (Offset + 16) / (int64_t)Scale.getFixedValue();
11205 StackOffsetOperand.setImm(NewImm);
11206 }
11207}
11208
11210 const AArch64InstrInfo *TII,
11211 bool ShouldSignReturnAddr) {
11212 if (!ShouldSignReturnAddr)
11213 return;
11214
11215 BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(AArch64::PAUTH_PROLOGUE))
11217 TII->createPauthEpilogueInstr(MBB, DebugLoc());
11218}
11219
11220void AArch64InstrInfo::buildOutlinedFrame(
11222 const outliner::OutlinedFunction &OF) const {
11223
11224 AArch64FunctionInfo *FI = MF.getInfo<AArch64FunctionInfo>();
11225
11226 if (OF.FrameConstructionID == MachineOutlinerTailCall)
11227 FI->setOutliningStyle("Tail Call");
11228 else if (OF.FrameConstructionID == MachineOutlinerThunk) {
11229 // For thunk outlining, rewrite the last instruction from a call to a
11230 // tail-call.
11231 MachineInstr *Call = &*--MBB.instr_end();
11232 unsigned TailOpcode;
11233 if (Call->getOpcode() == AArch64::BL) {
11234 TailOpcode = AArch64::TCRETURNdi;
11235 } else {
11236 assert(Call->getOpcode() == AArch64::BLR ||
11237 Call->getOpcode() == AArch64::BLRNoIP);
11238 TailOpcode = AArch64::TCRETURNriALL;
11239 }
11240 MachineInstr *TC = BuildMI(MF, DebugLoc(), get(TailOpcode))
11241 .add(Call->getOperand(0))
11242 .addImm(0);
11243 MBB.insert(MBB.end(), TC);
11245
11246 FI->setOutliningStyle("Thunk");
11247 }
11248
11249 bool IsLeafFunction = true;
11250
11251 // Is there a call in the outlined range?
11252 auto IsNonTailCall = [](const MachineInstr &MI) {
11253 return MI.isCall() && !MI.isReturn();
11254 };
11255
11256 if (llvm::any_of(MBB.instrs(), IsNonTailCall)) {
11257 // Fix up the instructions in the range, since we're going to modify the
11258 // stack.
11259
11260 // Bugzilla ID: 46767
11261 // TODO: Check if fixing up twice is safe so we can outline these.
11262 assert(OF.FrameConstructionID != MachineOutlinerDefault &&
11263 "Can only fix up stack references once");
11264 fixupPostOutline(MBB);
11265
11266 IsLeafFunction = false;
11267
11268 // LR has to be a live in so that we can save it.
11269 if (!MBB.isLiveIn(AArch64::LR))
11270 MBB.addLiveIn(AArch64::LR);
11271
11274
11275 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11276 OF.FrameConstructionID == MachineOutlinerThunk)
11277 Et = std::prev(MBB.end());
11278
11279 // There is a call in the range, so we must save LR. Save it as part of a
11280 // frame record when that gives us a smaller compact unwind encoding.
11282 // FP is saved here, so it must be live-in.
11283 if (!MBB.isLiveIn(AArch64::FP))
11284 MBB.addLiveIn(AArch64::FP);
11285
11286 // stp x29, x30, [sp, #-16]! (the pre-index imm is scaled by 8: -2 * 8)
11287 MachineInstr *STPXpre = BuildMI(MF, DebugLoc(), get(AArch64::STPXpre))
11288 .addReg(AArch64::SP, RegState::Define)
11289 .addReg(AArch64::FP)
11290 .addReg(AArch64::LR)
11291 .addReg(AArch64::SP)
11292 .addImm(-2);
11293 It = MBB.insert(It, STPXpre);
11294
11295 // mov x29, sp (add x29, sp, #0), so x29 points at the frame record.
11296 MachineInstr *SetFP = BuildMI(MF, DebugLoc(), get(AArch64::ADDXri))
11297 .addReg(AArch64::FP, RegState::Define)
11298 .addReg(AArch64::SP)
11299 .addImm(0)
11300 .addImm(0);
11301 MBB.insertAfter(It, SetFP);
11302
11303 // Describe the frame record with FP as the CFA. The encoder needs all
11304 // three to pick FRAME. No need to check for unwind info here: we only
11305 // get here if the function has it.
11306 CFIInstBuilder CFIBuilder(MBB, std::next(SetFP->getIterator()),
11308 CFIBuilder.buildDefCFA(AArch64::FP, 16);
11309 CFIBuilder.buildOffset(AArch64::LR, -8);
11310 CFIBuilder.buildOffset(AArch64::FP, -16);
11311
11312 // ldp x29, x30, [sp], #16
11313 MachineInstr *LDPXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDPXpost))
11314 .addReg(AArch64::SP, RegState::Define)
11315 .addReg(AArch64::FP, RegState::Define)
11316 .addReg(AArch64::LR, RegState::Define)
11317 .addReg(AArch64::SP)
11318 .addImm(2);
11319 Et = MBB.insert(Et, LDPXpost);
11320 } else {
11321 // Insert a save before the outlined region
11322 MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11323 .addReg(AArch64::SP, RegState::Define)
11324 .addReg(AArch64::LR)
11325 .addReg(AArch64::SP)
11326 .addImm(-16);
11327 It = MBB.insert(It, STRXpre);
11328
11329 if (MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11330 CFIInstBuilder CFIBuilder(MBB, It, MachineInstr::FrameSetup);
11331
11332 // Add a CFI saying the stack was moved 16 B down.
11333 CFIBuilder.buildDefCFAOffset(16);
11334
11335 // Add a CFI saying that the LR that we want to find is now 16 B higher
11336 // than before.
11337 CFIBuilder.buildOffset(AArch64::LR, -16);
11338 }
11339
11340 // Insert a restore before the terminator for the function.
11341 MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11342 .addReg(AArch64::SP, RegState::Define)
11343 .addReg(AArch64::LR, RegState::Define)
11344 .addReg(AArch64::SP)
11345 .addImm(16);
11346 Et = MBB.insert(Et, LDRXpost);
11347 }
11348 }
11349
11350 auto RASignCondition = FI->getSignReturnAddressCondition();
11351 bool ShouldSignReturnAddr = AArch64FunctionInfo::shouldSignReturnAddress(
11352 RASignCondition, !IsLeafFunction);
11353
11354 // If this is a tail call outlined function, then there's already a return.
11355 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11356 OF.FrameConstructionID == MachineOutlinerThunk) {
11357 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11358 return;
11359 }
11360
11361 // It's not a tail call, so we have to insert the return ourselves.
11362
11363 // LR has to be a live in so that we can return to it.
11364 if (!MBB.isLiveIn(AArch64::LR))
11365 MBB.addLiveIn(AArch64::LR);
11366
11367 MachineInstr *ret = BuildMI(MF, DebugLoc(), get(AArch64::RET))
11368 .addReg(AArch64::LR);
11369 MBB.insert(MBB.end(), ret);
11370
11371 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11372
11373 FI->setOutliningStyle("Function");
11374
11375 // Did we have to modify the stack by saving the link register?
11376 if (OF.FrameConstructionID != MachineOutlinerDefault)
11377 return;
11378
11379 // We modified the stack.
11380 // Walk over the basic block and fix up all the stack accesses.
11381 fixupPostOutline(MBB);
11382}
11383
11384MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall(
11387
11388 // Are we tail calling?
11389 if (C.CallConstructionID == MachineOutlinerTailCall) {
11390 // If yes, then we can just branch to the label.
11391 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::TCRETURNdi))
11392 .addGlobalAddress(M.getNamedValue(MF.getName()))
11393 .addImm(0));
11394 return It;
11395 }
11396
11397 // Are we saving the link register?
11398 if (C.CallConstructionID == MachineOutlinerNoLRSave ||
11399 C.CallConstructionID == MachineOutlinerThunk) {
11400 // No, so just insert the call.
11401 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11402 .addGlobalAddress(M.getNamedValue(MF.getName())));
11403 return It;
11404 }
11405
11406 // We want to return the spot where we inserted the call.
11408
11409 // Instructions for saving and restoring LR around the call instruction we're
11410 // going to insert.
11411 MachineInstr *Save;
11412 MachineInstr *Restore;
11413 // Can we save to a register?
11414 if (C.CallConstructionID == MachineOutlinerRegSave) {
11415 // FIXME: This logic should be sunk into a target-specific interface so that
11416 // we don't have to recompute the register.
11417 Register Reg = findRegisterToSaveLRTo(C);
11418 assert(Reg && "No callee-saved register available?");
11419
11420 // LR has to be a live in so that we can save it.
11421 if (!MBB.isLiveIn(AArch64::LR))
11422 MBB.addLiveIn(AArch64::LR);
11423
11424 // Save and restore LR from Reg.
11425 Save = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), Reg)
11426 .addReg(AArch64::XZR)
11427 .addReg(AArch64::LR)
11428 .addImm(0);
11429 Restore = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), AArch64::LR)
11430 .addReg(AArch64::XZR)
11431 .addReg(Reg)
11432 .addImm(0);
11433 } else {
11434 // We have the default case. Save and restore from SP.
11435 Save = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11436 .addReg(AArch64::SP, RegState::Define)
11437 .addReg(AArch64::LR)
11438 .addReg(AArch64::SP)
11439 .addImm(-16);
11440 Restore = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11441 .addReg(AArch64::SP, RegState::Define)
11442 .addReg(AArch64::LR, RegState::Define)
11443 .addReg(AArch64::SP)
11444 .addImm(16);
11445 }
11446
11447 It = MBB.insert(It, Save);
11448 It++;
11449
11450 // Insert the call.
11451 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11452 .addGlobalAddress(M.getNamedValue(MF.getName())));
11453 CallPt = It;
11454 It++;
11455
11456 It = MBB.insert(It, Restore);
11457 return CallPt;
11458}
11459
11460bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11461 MachineFunction &MF) const {
11462 return MF.getFunction().hasMinSize();
11463}
11464
11465void AArch64InstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
11467 DebugLoc &DL,
11468 bool AllowSideEffects) const {
11469 const MachineFunction &MF = *MBB.getParent();
11470 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
11471 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
11472
11473 if (TRI.isGeneralPurposeRegister(MF, Reg)) {
11474 BuildMI(MBB, Iter, DL, get(AArch64::MOVZXi), Reg).addImm(0).addImm(0);
11475 } else if (STI.isSVEorStreamingSVEAvailable()) {
11476 BuildMI(MBB, Iter, DL, get(AArch64::DUP_ZI_D), Reg)
11477 .addImm(0)
11478 .addImm(0);
11479 } else if (STI.isNeonAvailable()) {
11480 BuildMI(MBB, Iter, DL, get(AArch64::MOVIv2d_ns), Reg)
11481 .addImm(0);
11482 } else {
11483 // No Advanced SIMD (streaming-compatible without SVE, or +nosimd), so use
11484 // `fmov d...` instead of `movi v...`; writing `d` also clears the upper
11485 // 64 bits.
11486 assert(STI.hasFPARMv8() && "Expected FP to be available.");
11487 Register Reg64 = TRI.getSubReg(Reg, AArch64::dsub);
11488 BuildMI(MBB, Iter, DL, get(AArch64::FMOVD0), Reg64);
11489 }
11490}
11491
11492std::optional<DestSourcePair>
11494
11495 // AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg
11496 // and zero immediate operands used as an alias for mov instruction.
11497 if ((MI.getOpcode() == AArch64::ORRWrs &&
11498 MI.getOperand(1).getReg() == AArch64::WZR &&
11499 MI.getOperand(3).getImm() == 0x0) ||
11500 (MI.getOpcode() == AArch64::ORRWrr &&
11501 MI.getOperand(1).getReg() == AArch64::WZR)) {
11502 // Check that the w->w move is not a zero-extending w->x mov.
11503 if ((MI.getOperand(0).getReg().isPhysical() &&
11504 MI.findRegisterDefOperandIdx(
11505 getXRegFromWReg(MI.getOperand(0).getReg()),
11506 /*TRI=*/nullptr) == -1) ||
11507 (MI.getOperand(0).getReg().isVirtual() &&
11508 !MI.getOperand(0).getSubReg()))
11509 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11510 }
11511
11512 if (MI.getOpcode() == AArch64::ORRXrs &&
11513 MI.getOperand(1).getReg() == AArch64::XZR &&
11514 MI.getOperand(3).getImm() == 0x0)
11515 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11516
11517 return std::nullopt;
11518}
11519
11520std::optional<DestSourcePair>
11522 if ((MI.getOpcode() == AArch64::ORRWrs &&
11523 MI.getOperand(1).getReg() == AArch64::WZR &&
11524 MI.getOperand(3).getImm() == 0x0) ||
11525 (MI.getOpcode() == AArch64::ORRWrr &&
11526 MI.getOperand(1).getReg() == AArch64::WZR))
11527 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11528 return std::nullopt;
11529}
11530
11531std::optional<RegImmPair>
11532AArch64InstrInfo::isAddImmediate(const MachineInstr &MI, Register Reg) const {
11533 int Sign = 1;
11534 int64_t Offset = 0;
11535
11536 // TODO: Handle cases where Reg is a super- or sub-register of the
11537 // destination register.
11538 const MachineOperand &Op0 = MI.getOperand(0);
11539 if (!Op0.isReg() || Reg != Op0.getReg())
11540 return std::nullopt;
11541
11542 switch (MI.getOpcode()) {
11543 default:
11544 return std::nullopt;
11545 case AArch64::SUBWri:
11546 case AArch64::SUBXri:
11547 case AArch64::SUBSWri:
11548 case AArch64::SUBSXri:
11549 Sign *= -1;
11550 [[fallthrough]];
11551 case AArch64::ADDSWri:
11552 case AArch64::ADDSXri:
11553 case AArch64::ADDWri:
11554 case AArch64::ADDXri: {
11555 // TODO: Third operand can be global address (usually some string).
11556 if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
11557 !MI.getOperand(2).isImm())
11558 return std::nullopt;
11559 int Shift = MI.getOperand(3).getImm();
11560 assert((Shift == 0 || Shift == 12) && "Shift can be either 0 or 12");
11561 Offset = Sign * (MI.getOperand(2).getImm() << Shift);
11562 }
11563 }
11564 return RegImmPair{MI.getOperand(1).getReg(), Offset};
11565}
11566
11567/// If the given ORR instruction is a copy, and \p DescribedReg overlaps with
11568/// the destination register then, if possible, describe the value in terms of
11569/// the source register.
11570static std::optional<ParamLoadedValue>
11572 const TargetInstrInfo *TII,
11573 const TargetRegisterInfo *TRI) {
11574 auto DestSrc = TII->isCopyLikeInstr(MI);
11575 if (!DestSrc)
11576 return std::nullopt;
11577
11578 Register DestReg = DestSrc->Destination->getReg();
11579 Register SrcReg = DestSrc->Source->getReg();
11580
11581 if (!DestReg.isValid() || !SrcReg.isValid())
11582 return std::nullopt;
11583
11584 auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
11585
11586 // If the described register is the destination, just return the source.
11587 if (DestReg == DescribedReg)
11588 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11589
11590 // ORRWrs zero-extends to 64-bits, so we need to consider such cases.
11591 if (MI.getOpcode() == AArch64::ORRWrs &&
11592 TRI->isSuperRegister(DestReg, DescribedReg))
11593 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11594
11595 // We may need to describe the lower part of a ORRXrs move.
11596 if (MI.getOpcode() == AArch64::ORRXrs &&
11597 TRI->isSubRegister(DestReg, DescribedReg)) {
11598 Register SrcSubReg = TRI->getSubReg(SrcReg, AArch64::sub_32);
11599 return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
11600 }
11601
11602 assert(!TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11603 "Unhandled ORR[XW]rs copy case");
11604
11605 return std::nullopt;
11606}
11607
11608bool AArch64InstrInfo::isFunctionSafeToSplit(const MachineFunction &MF) const {
11609 // Functions cannot be split to different sections on AArch64 if they have
11610 // a red zone. This is because relaxing a cross-section branch may require
11611 // incrementing the stack pointer to spill a register, which would overwrite
11612 // the red zone.
11613 if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(true))
11614 return false;
11615
11617}
11618
11619bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11620 const MachineBasicBlock &MBB) const {
11621 // Asm Goto blocks can contain conditional branches to goto labels, which can
11622 // get moved out of range of the branch instruction.
11623 auto isAsmGoto = [](const MachineInstr &MI) {
11624 return MI.getOpcode() == AArch64::INLINEASM_BR;
11625 };
11626 if (llvm::any_of(MBB, isAsmGoto) || MBB.isInlineAsmBrIndirectTarget())
11627 return false;
11628
11629 // Because jump tables are label-relative instead of table-relative, they all
11630 // must be in the same section or relocation fixup handling will fail.
11631
11632 // Check if MBB is a jump table target
11633 const MachineJumpTableInfo *MJTI = MBB.getParent()->getJumpTableInfo();
11634 auto containsMBB = [&MBB](const MachineJumpTableEntry &JTE) {
11635 return llvm::is_contained(JTE.MBBs, &MBB);
11636 };
11637 if (MJTI != nullptr && llvm::any_of(MJTI->getJumpTables(), containsMBB))
11638 return false;
11639
11640 // Check if MBB contains a jump table lookup
11641 for (const MachineInstr &MI : MBB) {
11642 switch (MI.getOpcode()) {
11643 case TargetOpcode::G_BRJT:
11644 case AArch64::JumpTableDest32:
11645 case AArch64::JumpTableDest16:
11646 case AArch64::JumpTableDest8:
11647 return false;
11648 default:
11649 continue;
11650 }
11651 }
11652
11653 // MBB isn't a special case, so it's safe to be split to the cold section.
11654 return true;
11655}
11656
11657std::optional<ParamLoadedValue>
11658AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
11659 Register Reg) const {
11660 const MachineFunction *MF = MI.getMF();
11661 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
11662 switch (MI.getOpcode()) {
11663 case AArch64::MOVZWi:
11664 case AArch64::MOVZXi: {
11665 // MOVZWi may be used for producing zero-extended 32-bit immediates in
11666 // 64-bit parameters, so we need to consider super-registers.
11667 if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
11668 return std::nullopt;
11669
11670 if (!MI.getOperand(1).isImm())
11671 return std::nullopt;
11672 int64_t Immediate = MI.getOperand(1).getImm();
11673 int Shift = MI.getOperand(2).getImm();
11674 return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
11675 nullptr);
11676 }
11677 case AArch64::ORRWrs:
11678 case AArch64::ORRXrs:
11679 return describeORRLoadedValue(MI, Reg, this, TRI);
11680 }
11681
11683}
11684
11685bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11686 MachineInstr &ExtMI, MachineRegisterInfo &MRI) const {
11687 assert(ExtMI.getOpcode() == TargetOpcode::G_SEXT ||
11688 ExtMI.getOpcode() == TargetOpcode::G_ZEXT ||
11689 ExtMI.getOpcode() == TargetOpcode::G_ANYEXT);
11690
11691 // Anyexts are nops.
11692 if (ExtMI.getOpcode() == TargetOpcode::G_ANYEXT)
11693 return true;
11694
11695 Register DefReg = ExtMI.getOperand(0).getReg();
11696 if (!MRI.hasOneNonDBGUse(DefReg))
11697 return false;
11698
11699 // It's likely that a sext/zext as a G_PTR_ADD offset will be folded into an
11700 // addressing mode.
11701 auto *UserMI = &*MRI.use_instr_nodbg_begin(DefReg);
11702 return UserMI->getOpcode() == TargetOpcode::G_PTR_ADD;
11703}
11704
11705uint64_t AArch64InstrInfo::getElementSizeForOpcode(unsigned Opc) const {
11706 return get(Opc).TSFlags & AArch64::ElementSizeMask;
11707}
11708
11709bool AArch64InstrInfo::isPTestLikeOpcode(unsigned Opc) const {
11710 return get(Opc).TSFlags & AArch64::InstrFlagIsPTestLike;
11711}
11712
11713bool AArch64InstrInfo::isWhileOpcode(unsigned Opc) const {
11714 return get(Opc).TSFlags & AArch64::InstrFlagIsWhile;
11715}
11716
11717unsigned int
11718AArch64InstrInfo::getTailDuplicateSize(CodeGenOptLevel OptLevel) const {
11719 return OptLevel >= CodeGenOptLevel::Aggressive ? 6 : 2;
11720}
11721
11722bool AArch64InstrInfo::isLegalAddressingMode(unsigned NumBytes, int64_t Offset,
11723 unsigned Scale) const {
11724 if (Offset && Scale)
11725 return false;
11726
11727 // Check Reg + Imm
11728 if (!Scale) {
11729 // 9-bit signed offset
11730 if (isInt<9>(Offset))
11731 return true;
11732
11733 // 12-bit unsigned offset
11734 unsigned Shift = Log2_64(NumBytes);
11735 if (NumBytes && Offset > 0 && (Offset / NumBytes) <= (1LL << 12) - 1 &&
11736 // Must be a multiple of NumBytes (NumBytes is a power of 2)
11737 (Offset >> Shift) << Shift == Offset)
11738 return true;
11739 return false;
11740 }
11741
11742 // Check reg1 + SIZE_IN_BYTES * reg2 and reg1 + reg2
11743 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11744}
11745
11747 if (MF.getSubtarget<AArch64Subtarget>().hardenSlsBlr())
11748 return AArch64::BLRNoIP;
11749 else
11750 return AArch64::BLR;
11751}
11752
11754 DebugLoc DL) const {
11755 MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
11756 auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
11758
11759 MachineFunction &MF = *MBB.getParent();
11760 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
11761 auto &AFL = *static_cast<const AArch64FrameLowering *>(
11762 MF.getSubtarget().getFrameLowering());
11763 if (AFL.getArgumentStackToRestore(MF, MBB)) {
11764 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
11765 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11766 if (Subtarget.hasPAuthLR())
11767 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
11768 return;
11769 }
11770
11771 if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
11772 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11773}
11774
11776AArch64InstrInfo::probedStackAlloc(MachineBasicBlock::iterator MBBI,
11777 Register TargetReg, bool FrameSetup) const {
11778 assert(TargetReg != AArch64::SP && "New top of stack cannot already be in SP");
11779
11780 MachineBasicBlock &MBB = *MBBI->getParent();
11781 MachineFunction &MF = *MBB.getParent();
11782 const AArch64InstrInfo *TII =
11783 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
11784 int64_t ProbeSize = MF.getInfo<AArch64FunctionInfo>()->getStackProbeSize();
11785 DebugLoc DL = MBB.findDebugLoc(MBBI);
11786
11787 MachineFunction::iterator MBBInsertPoint = std::next(MBB.getIterator());
11788 MachineBasicBlock *LoopTestMBB =
11789 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11790 MF.insert(MBBInsertPoint, LoopTestMBB);
11791 MachineBasicBlock *LoopBodyMBB =
11792 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11793 MF.insert(MBBInsertPoint, LoopBodyMBB);
11794 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11795 MF.insert(MBBInsertPoint, ExitMBB);
11796 MachineInstr::MIFlag Flags =
11798
11799 // LoopTest:
11800 // SUB SP, SP, #ProbeSize
11801 emitFrameOffset(*LoopTestMBB, LoopTestMBB->end(), DL, AArch64::SP,
11802 AArch64::SP, StackOffset::getFixed(-ProbeSize), TII, Flags);
11803
11804 // CMP SP, TargetReg
11805 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::SUBSXrx64),
11806 AArch64::XZR)
11807 .addReg(AArch64::SP)
11808 .addReg(TargetReg)
11810 .setMIFlags(Flags);
11811
11812 // B.<Cond> LoopExit
11813 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::Bcc))
11815 .addMBB(ExitMBB)
11816 .setMIFlags(Flags);
11817
11818 // LDR XZR, [SP]
11819 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::LDRXui))
11820 .addDef(AArch64::XZR)
11821 .addReg(AArch64::SP)
11822 .addImm(0)
11826 Align(8)))
11827 .setMIFlags(Flags);
11828
11829 // B loop
11830 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::B))
11831 .addMBB(LoopTestMBB)
11832 .setMIFlags(Flags);
11833
11834 // LoopExit:
11835 // MOV SP, TargetReg
11836 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::ADDXri), AArch64::SP)
11837 .addReg(TargetReg)
11838 .addImm(0)
11840 .setMIFlags(Flags);
11841
11842 // LDR XZR, [SP]
11843 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::LDRXui))
11844 .addReg(AArch64::XZR, RegState::Define)
11845 .addReg(AArch64::SP)
11846 .addImm(0)
11847 .setMIFlags(Flags);
11848
11849 ExitMBB->splice(ExitMBB->end(), &MBB, std::next(MBBI), MBB.end());
11851
11852 LoopTestMBB->addSuccessor(ExitMBB);
11853 LoopTestMBB->addSuccessor(LoopBodyMBB);
11854 LoopBodyMBB->addSuccessor(LoopTestMBB);
11855 MBB.addSuccessor(LoopTestMBB);
11856
11857 // Update liveins.
11858 if (MF.getRegInfo().reservedRegsFrozen())
11859 fullyRecomputeLiveIns({ExitMBB, LoopBodyMBB, LoopTestMBB});
11860
11861 return ExitMBB->begin();
11862}
11863
11864namespace {
11865class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
11866 MachineFunction *MF;
11867 const TargetInstrInfo *TII;
11868 const TargetRegisterInfo *TRI;
11869 MachineRegisterInfo &MRI;
11870
11871 /// The block of the loop
11872 MachineBasicBlock *LoopBB;
11873 /// The conditional branch of the loop
11874 MachineInstr *CondBranch;
11875 /// The compare instruction for loop control
11876 MachineInstr *Comp;
11877 /// The number of the operand of the loop counter value in Comp
11878 unsigned CompCounterOprNum;
11879 /// The instruction that updates the loop counter value
11880 MachineInstr *Update;
11881 /// The number of the operand of the loop counter value in Update
11882 unsigned UpdateCounterOprNum;
11883 /// The initial value of the loop counter
11884 Register Init;
11885 /// True iff Update is a predecessor of Comp
11886 bool IsUpdatePriorComp;
11887
11888 /// The normalized condition used by createTripCountGreaterCondition()
11890
11891public:
11892 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11893 MachineInstr *Comp, unsigned CompCounterOprNum,
11894 MachineInstr *Update, unsigned UpdateCounterOprNum,
11895 Register Init, bool IsUpdatePriorComp,
11896 const SmallVectorImpl<MachineOperand> &Cond)
11897 : MF(Comp->getParent()->getParent()),
11898 TII(MF->getSubtarget().getInstrInfo()),
11899 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11900 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11901 CompCounterOprNum(CompCounterOprNum), Update(Update),
11902 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11903 IsUpdatePriorComp(IsUpdatePriorComp), Cond(Cond.begin(), Cond.end()) {}
11904
11905 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
11906 // Make the instructions for loop control be placed in stage 0.
11907 // The predecessors of Comp are considered by the caller.
11908 return MI == Comp;
11909 }
11910
11911 std::optional<bool> createTripCountGreaterCondition(
11912 int TC, MachineBasicBlock &MBB,
11913 SmallVectorImpl<MachineOperand> &CondParam) override {
11914 // A branch instruction will be inserted as "if (Cond) goto epilogue".
11915 // Cond is normalized for such use.
11916 // The predecessors of the branch are assumed to have already been inserted.
11917 CondParam = Cond;
11918 return {};
11919 }
11920
11921 void createRemainingIterationsGreaterCondition(
11922 int TC, MachineBasicBlock &MBB, SmallVectorImpl<MachineOperand> &Cond,
11923 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts) override;
11924
11925 void setPreheader(MachineBasicBlock *NewPreheader) override {}
11926
11927 void adjustTripCount(int TripCountAdjust) override {}
11928
11929 bool isMVEExpanderSupported() override { return true; }
11930};
11931} // namespace
11932
11933/// Clone an instruction from MI. The register of ReplaceOprNum-th operand
11934/// is replaced by ReplaceReg. The output register is newly created.
11935/// The other operands are unchanged from MI.
11936static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum,
11937 Register ReplaceReg, MachineBasicBlock &MBB,
11938 MachineBasicBlock::iterator InsertTo) {
11939 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
11940 const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
11941 MachineInstr *NewMI = MBB.getParent()->CloneMachineInstr(MI);
11942 Register Result = 0;
11943 for (unsigned I = 0; I < NewMI->getNumOperands(); ++I) {
11944 if (I == 0 && NewMI->getOperand(0).getReg().isVirtual()) {
11945 Result = MRI.createVirtualRegister(
11946 MRI.getRegClass(NewMI->getOperand(0).getReg()));
11947 NewMI->getOperand(I).setReg(Result);
11948 } else if (I == ReplaceOprNum) {
11949 MRI.constrainRegClass(ReplaceReg, TII->getRegClass(NewMI->getDesc(), I));
11950 NewMI->getOperand(I).setReg(ReplaceReg);
11951 }
11952 }
11953 MBB.insert(InsertTo, NewMI);
11954 return Result;
11955}
11956
11957void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
11960 // Create and accumulate conditions for next TC iterations.
11961 // Example:
11962 // SUBSXrr N, counter, implicit-def $nzcv # compare instruction for the last
11963 // # iteration of the kernel
11964 //
11965 // # insert the following instructions
11966 // cond = CSINCXr 0, 0, C, implicit $nzcv
11967 // counter = ADDXri counter, 1 # clone from this->Update
11968 // SUBSXrr n, counter, implicit-def $nzcv # clone from this->Comp
11969 // cond = CSINCXr cond, cond, C, implicit $nzcv
11970 // ... (repeat TC times)
11971 // SUBSXri cond, 0, implicit-def $nzcv
11972
11973 assert(CondBranch->getOpcode() == AArch64::Bcc);
11974 // CondCode to exit the loop
11976 (AArch64CC::CondCode)CondBranch->getOperand(0).getImm();
11977 if (CondBranch->getOperand(1).getMBB() == LoopBB)
11979
11980 // Accumulate conditions to exit the loop
11981 Register AccCond = AArch64::XZR;
11982
11983 // If CC holds, CurCond+1 is returned; otherwise CurCond is returned.
11984 auto AccumulateCond = [&](Register CurCond,
11986 Register NewCond = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
11987 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::CSINCXr))
11988 .addReg(NewCond, RegState::Define)
11989 .addReg(CurCond)
11990 .addReg(CurCond)
11992 return NewCond;
11993 };
11994
11995 if (!LastStage0Insts.empty() && LastStage0Insts[Comp]->getParent() == &MBB) {
11996 // Update and Comp for I==0 are already exists in MBB
11997 // (MBB is an unrolled kernel)
11998 Register Counter;
11999 for (int I = 0; I <= TC; ++I) {
12000 Register NextCounter;
12001 if (I != 0)
12002 NextCounter =
12003 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12004
12005 AccCond = AccumulateCond(AccCond, CC);
12006
12007 if (I != TC) {
12008 if (I == 0) {
12009 if (Update != Comp && IsUpdatePriorComp) {
12010 Counter =
12011 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12012 NextCounter = cloneInstr(Update, UpdateCounterOprNum, Counter, MBB,
12013 MBB.end());
12014 } else {
12015 // can use already calculated value
12016 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
12017 }
12018 } else if (Update != Comp) {
12019 NextCounter =
12020 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12021 }
12022 }
12023 Counter = NextCounter;
12024 }
12025 } else {
12026 Register Counter;
12027 if (LastStage0Insts.empty()) {
12028 // use initial counter value (testing if the trip count is sufficient to
12029 // be executed by pipelined code)
12030 Counter = Init;
12031 if (IsUpdatePriorComp)
12032 Counter =
12033 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12034 } else {
12035 // MBB is an epilogue block. LastStage0Insts[Comp] is in the kernel block.
12036 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12037 }
12038
12039 for (int I = 0; I <= TC; ++I) {
12040 Register NextCounter;
12041 NextCounter =
12042 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12043 AccCond = AccumulateCond(AccCond, CC);
12044 if (I != TC && Update != Comp)
12045 NextCounter =
12046 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12047 Counter = NextCounter;
12048 }
12049 }
12050
12051 // If AccCond == 0, the remainder is greater than TC.
12052 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::SUBSXri))
12053 .addReg(AArch64::XZR, RegState::Define | RegState::Dead)
12054 .addReg(AccCond)
12055 .addImm(0)
12056 .addImm(0);
12057 Cond.clear();
12059}
12060
12061static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB,
12062 Register &RegMBB, Register &RegOther) {
12063 assert(Phi.getNumOperands() == 5);
12064 if (Phi.getOperand(2).getMBB() == MBB) {
12065 RegMBB = Phi.getOperand(1).getReg();
12066 RegOther = Phi.getOperand(3).getReg();
12067 } else {
12068 assert(Phi.getOperand(4).getMBB() == MBB);
12069 RegMBB = Phi.getOperand(3).getReg();
12070 RegOther = Phi.getOperand(1).getReg();
12071 }
12072}
12073
12075 if (!Reg.isVirtual())
12076 return false;
12077 const MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
12078 return MRI.getDefBlock(Reg) != BB;
12079}
12080
12081/// If Reg is an induction variable, return true and set some parameters
12082static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB,
12083 MachineInstr *&UpdateInst,
12084 unsigned &UpdateCounterOprNum, Register &InitReg,
12085 bool &IsUpdatePriorComp) {
12086 // Example:
12087 //
12088 // Preheader:
12089 // InitReg = ...
12090 // LoopBB:
12091 // Reg0 = PHI (InitReg, Preheader), (Reg1, LoopBB)
12092 // Reg = COPY Reg0 ; COPY is ignored.
12093 // Reg1 = ADD Reg, #1; UpdateInst. Incremented by a loop invariant value.
12094 // ; Reg is the value calculated in the previous
12095 // ; iteration, so IsUpdatePriorComp == false.
12096
12097 if (LoopBB->pred_size() != 2)
12098 return false;
12099 if (!Reg.isVirtual())
12100 return false;
12101 const MachineRegisterInfo &MRI = LoopBB->getParent()->getRegInfo();
12102 UpdateInst = nullptr;
12103 UpdateCounterOprNum = 0;
12104 InitReg = 0;
12105 IsUpdatePriorComp = true;
12106 Register CurReg = Reg;
12107 while (true) {
12108 MachineInstr *Def = MRI.getVRegDef(CurReg);
12109 if (Def->getParent() != LoopBB)
12110 return false;
12111 if (Def->isCopy()) {
12112 // Ignore copy instructions unless they contain subregisters
12113 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
12114 return false;
12115 CurReg = Def->getOperand(1).getReg();
12116 } else if (Def->isPHI()) {
12117 if (InitReg != 0)
12118 return false;
12119 if (!UpdateInst)
12120 IsUpdatePriorComp = false;
12121 extractPhiReg(*Def, LoopBB, CurReg, InitReg);
12122 } else {
12123 if (UpdateInst)
12124 return false;
12125 switch (Def->getOpcode()) {
12126 case AArch64::ADDSXri:
12127 case AArch64::ADDSWri:
12128 case AArch64::SUBSXri:
12129 case AArch64::SUBSWri:
12130 case AArch64::ADDXri:
12131 case AArch64::ADDWri:
12132 case AArch64::SUBXri:
12133 case AArch64::SUBWri:
12134 UpdateInst = Def;
12135 UpdateCounterOprNum = 1;
12136 break;
12137 case AArch64::ADDSXrr:
12138 case AArch64::ADDSWrr:
12139 case AArch64::SUBSXrr:
12140 case AArch64::SUBSWrr:
12141 case AArch64::ADDXrr:
12142 case AArch64::ADDWrr:
12143 case AArch64::SUBXrr:
12144 case AArch64::SUBWrr:
12145 UpdateInst = Def;
12146 if (isDefinedOutside(Def->getOperand(2).getReg(), LoopBB))
12147 UpdateCounterOprNum = 1;
12148 else if (isDefinedOutside(Def->getOperand(1).getReg(), LoopBB))
12149 UpdateCounterOprNum = 2;
12150 else
12151 return false;
12152 break;
12153 default:
12154 return false;
12155 }
12156 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
12157 }
12158
12159 if (!CurReg.isVirtual())
12160 return false;
12161 if (Reg == CurReg)
12162 break;
12163 }
12164
12165 if (!UpdateInst)
12166 return false;
12167
12168 return true;
12169}
12170
12171std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
12173 // Accept loops that meet the following conditions
12174 // * The conditional branch is BCC
12175 // * The compare instruction is ADDS/SUBS/WHILEXX
12176 // * One operand of the compare is an induction variable and the other is a
12177 // loop invariant value
12178 // * The induction variable is incremented/decremented by a single instruction
12179 // * Does not contain CALL or instructions which have unmodeled side effects
12180
12181 for (MachineInstr &MI : *LoopBB)
12182 if (MI.isCall() || MI.hasUnmodeledSideEffects())
12183 // This instruction may use NZCV, which interferes with the instruction to
12184 // be inserted for loop control.
12185 return nullptr;
12186
12187 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
12189 if (analyzeBranch(*LoopBB, TBB, FBB, Cond))
12190 return nullptr;
12191
12192 // Infinite loops are not supported
12193 if (TBB == LoopBB && FBB == LoopBB)
12194 return nullptr;
12195
12196 // Must be conditional branch
12197 if (TBB != LoopBB && FBB == nullptr)
12198 return nullptr;
12199
12200 assert((TBB == LoopBB || FBB == LoopBB) &&
12201 "The Loop must be a single-basic-block loop");
12202
12203 MachineInstr *CondBranch = &*LoopBB->getFirstTerminator();
12205
12206 if (CondBranch->getOpcode() != AArch64::Bcc)
12207 return nullptr;
12208
12209 // Normalization for createTripCountGreaterCondition()
12210 if (TBB == LoopBB)
12212
12213 MachineInstr *Comp = nullptr;
12214 unsigned CompCounterOprNum = 0;
12215 for (MachineInstr &MI : reverse(*LoopBB)) {
12216 if (MI.modifiesRegister(AArch64::NZCV, &TRI)) {
12217 // Guarantee that the compare is SUBS/ADDS/WHILEXX and that one of the
12218 // operands is a loop invariant value
12219
12220 switch (MI.getOpcode()) {
12221 case AArch64::SUBSXri:
12222 case AArch64::SUBSWri:
12223 case AArch64::ADDSXri:
12224 case AArch64::ADDSWri:
12225 Comp = &MI;
12226 CompCounterOprNum = 1;
12227 break;
12228 case AArch64::ADDSWrr:
12229 case AArch64::ADDSXrr:
12230 case AArch64::SUBSWrr:
12231 case AArch64::SUBSXrr:
12232 Comp = &MI;
12233 break;
12234 default:
12235 if (isWhileOpcode(MI.getOpcode())) {
12236 Comp = &MI;
12237 break;
12238 }
12239 return nullptr;
12240 }
12241
12242 if (CompCounterOprNum == 0) {
12243 if (isDefinedOutside(Comp->getOperand(1).getReg(), LoopBB))
12244 CompCounterOprNum = 2;
12245 else if (isDefinedOutside(Comp->getOperand(2).getReg(), LoopBB))
12246 CompCounterOprNum = 1;
12247 else
12248 return nullptr;
12249 }
12250 break;
12251 }
12252 }
12253 if (!Comp)
12254 return nullptr;
12255
12256 MachineInstr *Update = nullptr;
12257 Register Init;
12258 bool IsUpdatePriorComp;
12259 unsigned UpdateCounterOprNum;
12260 if (!getIndVarInfo(Comp->getOperand(CompCounterOprNum).getReg(), LoopBB,
12261 Update, UpdateCounterOprNum, Init, IsUpdatePriorComp))
12262 return nullptr;
12263
12264 return std::make_unique<AArch64PipelinerLoopInfo>(
12265 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
12266 Init, IsUpdatePriorComp, Cond);
12267}
12268
12269/// verifyInstruction - Perform target specific instruction verification.
12270bool AArch64InstrInfo::verifyInstruction(const MachineInstr &MI,
12271 StringRef &ErrInfo) const {
12272 // Verify that immediate offsets on load/store instructions are within range.
12273 // Stack objects with an FI operand are excluded as they can be fixed up
12274 // during PEI.
12275 TypeSize Scale(0U, false), Width(0U, false);
12276 int64_t MinOffset, MaxOffset;
12277 if (getMemOpInfo(MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
12278 unsigned ImmIdx = getLoadStoreImmIdx(MI.getOpcode());
12279 if (MI.getOperand(ImmIdx).isImm() && !MI.getOperand(ImmIdx - 1).isFI()) {
12280 int64_t Imm = MI.getOperand(ImmIdx).getImm();
12281 if (Imm < MinOffset || Imm > MaxOffset) {
12282 ErrInfo = "Unexpected immediate on load/store instruction";
12283 return false;
12284 }
12285 }
12286 }
12287
12288 const MCInstrDesc &MCID = MI.getDesc();
12289 for (unsigned Op = 0; Op < MCID.getNumOperands(); Op++) {
12290 const MachineOperand &MO = MI.getOperand(Op);
12291 switch (MCID.operands()[Op].OperandType) {
12293 if (!MO.isImm() || MO.getImm() != 0) {
12294 ErrInfo = "OPERAND_IMPLICIT_IMM_0 should be 0";
12295 return false;
12296 }
12297 break;
12299 if (!MO.isImm() ||
12301 (AArch64_AM::getShiftValue(MO.getImm()) != 8 &&
12302 AArch64_AM::getShiftValue(MO.getImm()) != 16)) {
12303 ErrInfo = "OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
12304 return false;
12305 }
12306 break;
12308 if (!MO.isImm() || (MO.getImm() != 0 && MO.getImm() != 1)) {
12309 ErrInfo = "OPERAND_IMM_UINT1 should be 0 or 1";
12310 return false;
12311 }
12312 break;
12314 if (!MO.isImm() || MO.getImm() <= 0 || MO.getImm() > 16) {
12315 ErrInfo = "OPERAND_IMM_UINT4plus1 should be in the range 1 to 16";
12316 return false;
12317 }
12318 break;
12320 if (!MO.isImm() || !isUInt<5>(MO.getImm())) {
12321 ErrInfo = "OPERAND_IMM_UINT5 should be in the range 0 to 31";
12322 return false;
12323 }
12324 break;
12326 if (!MO.isImm() || !isUInt<8>(MO.getImm())) {
12327 ErrInfo = "OPERAND_IMM_UINT8 should be in the range 0 to 255";
12328 return false;
12329 }
12330 break;
12331 default:
12332 break;
12333 }
12334 }
12335 return true;
12336}
12337
12338#define GET_INSTRINFO_HELPERS
12339#define GET_INSTRMAP_INFO
12340#include "AArch64GenInstrInfo.inc"
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
static cl::opt< unsigned > BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of Bcc instructions (DEBUG)"))
static Register genNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned MnegOpc, const TargetRegisterClass *RC)
genNeg - Helper to generate an intermediate negation of the second operand of Root
static bool isFrameStoreOpcode(int Opcode)
static cl::opt< unsigned > GatherOptSearchLimit("aarch64-search-limit", cl::Hidden, cl::init(2048), cl::desc("Restrict range of instructions to search for the " "machine-combiner gather pattern optimization"))
static bool getMaddPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find instructions that can be turned into madd.
static AArch64CC::CondCode findCondCodeUsedByInstr(const MachineInstr &Instr)
Find a condition code used by the instruction.
static MachineInstr * genFusedMultiplyAcc(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyAcc - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genFusedMultiplyAccNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate64(unsigned Opc)
static bool isFrameLoadOpcode(int Opcode)
static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg)
static bool areCFlagsAccessedBetweenInstrs(MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI, const AccessKind AccessToCheck=AK_All)
True when condition flags are accessed (either by writing or reading) on the instruction trace starti...
static bool getFMAPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Floating-Point Support.
static bool isADDSRegImm(unsigned Opcode)
static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI)
static bool isANDOpcode(MachineInstr &MI)
static bool predictCompactUnwindFrameRecordForOutlinedFunction(std::vector< outliner::Candidate > &RepeatedSequenceLocs, const TargetRegisterInfo &TRI)
Predict what the above will answer, for use while costing candidates.
static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment, StringRef RegScale={})
static unsigned sForm(MachineInstr &Instr)
Get opcode of S version of Instr.
static bool isCombineInstrSettingFlag(unsigned Opc)
static bool getFNEGPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB, MachineInstr *&UpdateInst, unsigned &UpdateCounterOprNum, Register &InitReg, bool &IsUpdatePriorComp)
If Reg is an induction variable, return true and set some parameters.
static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc)
static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if in a streaming call site region without SME-FA64.
static bool isPostIndexLdStOpcode(unsigned Opcode)
Return true if the opcode is a post-index ld/st instruction, which really loads from base+0.
static std::optional< unsigned > getLFIInstSizeInBytes(const MachineInstr &MI)
Return the maximum number of bytes of code the specified instruction may be after LFI rewriting.
static unsigned getBranchDisplacementBits(unsigned Opc)
static cl::opt< unsigned > CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9), cl::desc("Restrict range of CB instructions (DEBUG)"))
static std::optional< ParamLoadedValue > describeORRLoadedValue(const MachineInstr &MI, Register DescribedReg, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
If the given ORR instruction is a copy, and DescribedReg overlaps with the destination register then,...
static bool getFMULPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static void appendReadRegExpr(SmallVectorImpl< char > &Expr, unsigned RegNum)
static MachineInstr * genMaddR(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR, const TargetRegisterClass *RC)
genMaddR - Generate madd instruction and combine mul and add using an extra virtual register Example ...
static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum, Register ReplaceReg, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertTo)
Clone an instruction from MI.
static bool scaleOffset(unsigned Opc, int64_t &Offset)
static bool canCombineWithFMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc)
unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale)
static MachineInstr * genFusedMultiplyIdx(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyIdx - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genIndexedMultiply(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxDupOp, unsigned MulOpc, const TargetRegisterClass *RC, MachineRegisterInfo &MRI)
Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
static cl::opt< bool > UseCompactUnwindFrameRecordForOutlinedFunctions("aarch64-outliner-compact-unwind-frame", cl::Hidden, cl::init(true), cl::desc("Use a frame record for Mach-O non-leaf outlined functions"))
static bool shouldUseCompactUnwindFrameRecordForOutlinedFunction(const MachineBasicBlock &MBB)
Return true if the outlined function in MBB should save FP and LR as a frame record instead of saving...
static bool isSUBSRegImm(unsigned Opcode)
static bool UpdateOperandRegClass(MachineInstr &Instr)
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
static bool isInStreamingCallSiteRegion(MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if the instruction at I is in a streaming call site region, within a single basic block.
static bool canCmpInstrBeRemoved(MachineInstr &MI, MachineInstr &CmpInstr, int CmpValue, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > &CCUseInstrs, bool &IsInvertCC)
unsigned unscaledOffsetOpcode(unsigned Opcode)
static bool getLoadPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Search for patterns of LD instructions we can optimize.
static bool canInstrSubstituteCmpInstr(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI)
Check if CmpInstr can be substituted by MI.
static UsedNZCV getUsedNZCV(AArch64CC::CondCode CC)
static bool isCombineInstrCandidateFP(const MachineInstr &Inst)
static bool isCompactUnwindFrameRecordEnabled(const MachineFunction &MF)
Return true if the frame-record form of the outlined prologue is enabled for the target of MF.
static void appendLoadRegExpr(SmallVectorImpl< char > &Expr, int64_t OffsetFromDefCFA)
static void appendConstantExpr(SmallVectorImpl< char > &Expr, int64_t Constant, dwarf::LocationAtom Operation)
static unsigned convertToNonFlagSettingOpc(const MachineInstr &MI)
Return the opcode that does not set flags when possible - otherwise return the original opcode.
static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool isCombineInstrCandidate32(unsigned Opc)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
static unsigned offsetExtendOpcode(unsigned Opcode)
MachineOutlinerMBBFlags
@ LRUnavailableSomewhere
@ UnsafeRegsDead
static void loadRegPairFromStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register DestReg, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
static void generateGatherLanePattern(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned Pattern, unsigned NumLanes)
Generate optimized instruction sequence for gather load patterns to improve Memory-Level Parallelism ...
static bool getMiscPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find other MI combine patterns.
static bool outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, RegState State, const TargetRegisterInfo *TRI)
static bool outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1, int64_t Offset1, unsigned Opcode1, int FI2, int64_t Offset2, unsigned Opcode2)
static cl::opt< unsigned > TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14), cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"))
static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB, Register &RegMBB, Register &RegOther)
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
static bool isDefinedOutside(Register Reg, const MachineBasicBlock *BB)
static MachineInstr * genFusedMultiply(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC, FMAInstKind kind=FMAInstKind::Default, const Register *ReplacedAddend=nullptr)
genFusedMultiply - Generate fused multiply instructions.
static bool getGatherLanePattern(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, unsigned LoadLaneOpCode, unsigned NumLanes)
Check if the given instruction forms a gather load pattern that can be optimized for better Memory-Le...
static MachineInstr * genFusedMultiplyIdxNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate(unsigned Opc)
static unsigned regOffsetOpcode(unsigned Opcode)
MachineOutlinerClass
Constants defining how certain sequences should be outlined.
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
@ MachineOutlinerNoLRSave
Only emit a branch.
@ MachineOutlinerThunk
Emit a call and return.
@ MachineOutlinerDefault
static cl::opt< unsigned > BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26), cl::desc("Restrict range of B instructions (DEBUG)"))
static bool areCFlagsAliveInSuccessors(const MachineBasicBlock *MBB)
Check if AArch64::NZCV should be alive in successors of MBB.
static void emitFrameOffsetAdj(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, int64_t Offset, unsigned Opc, const TargetInstrInfo *TII, MachineInstr::MIFlag Flag, bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFAOffset, StackOffset CFAOffset, unsigned FrameReg)
static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize)
static cl::opt< unsigned > CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"))
static void genSubAdd2SubSub(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, unsigned IdxOpd1, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
Do the following transformation A - (B + C) ==> (A - B) - C A - (B + C) ==> (A - C) - B.
static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg, unsigned *NewReg=nullptr)
static void signOutlinedFunction(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64InstrInfo *TII, bool ShouldSignReturnAddr)
static MachineInstr * genFNegatedMAD(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs)
static bool canCombineWithMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc, unsigned ZeroReg)
static void storeRegPairToStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register SrcReg, bool IsKill, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
@ Default
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static LVOptions Options
Definition LVOptions.cpp:25
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
A set of register units.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc=0)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
SignReturnAddress getSignReturnAddressCondition() const
void setOutliningStyle(const std::string &Style)
bool needsDwarfUnwindInfo(const MachineFunction &MF) const
std::optional< bool > hasRedZone() const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
static bool isHForm(const MachineInstr &MI)
Returns whether the instruction is in H form (16 bit operands)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
static bool hasBTISemantics(const MachineInstr &MI)
Returns whether the instruction can be compatible with non-zero BTYPE.
static bool isQForm(const MachineInstr &MI)
Returns whether the instruction is in Q form (128 bit operands)
static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width, int64_t &MinOffset, int64_t &MaxOffset)
Returns true if opcode Opc is a memory operation.
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
static bool isFPRCopy(const MachineInstr &MI)
Does this instruction rename an FPR without modifying bits?
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is an instruction that moves/copies value from one register to an...
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
static bool isZExtLoad(const MachineInstr &MI)
Returns whether the instruction is a zero-extending load.
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
static bool isGPRCopy(const MachineInstr &MI)
Does this instruction rename a GPR without modifying bits?
static unsigned convertToFlagSettingOpc(unsigned Opc)
Return the opcode that set flags when possible.
void createPauthEpilogueInstr(MachineBasicBlock &MBB, DebugLoc DL) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
bool canInsertSelect(const MachineBasicBlock &, ArrayRef< MachineOperand > Cond, Register, Register, Register, int &, int &, int &) const override
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
static const MachineOperand & getLdStOffsetOp(const MachineInstr &MI)
Returns the immediate offset operator of a load/store.
bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg, Register &DstReg, unsigned &SubIdx) const override
static std::optional< unsigned > getUnscaledLdSt(unsigned Opc)
Returns the unscaled load/store for the scaled load/store opcode, if there is a corresponding unscale...
static bool hasUnscaledLdStOffset(unsigned Opc)
Return true if it has an unscaled load/store offset.
static const MachineOperand & getLdStAmountOp(const MachineInstr &MI)
Returns the shift amount operator of a load/store.
static bool isPreLdSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load/store.
std::optional< ExtAddrMode > getAddrModeFromMemoryOp(const MachineInstr &MemI, const TargetRegisterInfo *TRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
bool analyzeBranchPredicate(MachineBasicBlock &MBB, MachineBranchPredicate &MBP, bool AllowModify) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isPairableLdStInst(const MachineInstr &MI)
Return true if pairing the given load or store may be paired with another.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSExtLoad(const MachineInstr &MI)
Returns whether the instruction is a sign-extending load.
const AArch64RegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
static bool isPreSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed store.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
AArch64InstrInfo(const AArch64Subtarget &STI)
static bool isPairedLdSt(const MachineInstr &MI)
Returns whether the instruction is a paired load/store.
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &MI, const MachineOperand *&BaseOp, int64_t &Offset, bool &OffsetIsScalable, TypeSize &Width, const TargetRegisterInfo *TRI) const
If OffsetIsScalable is set to 'true', the offset is scaled by vscale.
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isStridedAccess(const MachineInstr &MI)
Return true if the given load or store is a strided memory access.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
Detect opportunities for ldp/stp formation.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool isThroughputPattern(unsigned Pattern) const override
Return true when a code sequence can improve throughput.
MachineOperand & getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const
Return the immediate offset of the base register in a load/store LdSt.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
static bool isLdStPairSuppressed(const MachineInstr &MI)
Return true if pairing the given load or store is hinted to be unprofitable.
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction supplying the argument to the comparison into one that...
static unsigned getLoadStoreImmIdx(unsigned Opc)
Returns the index for the immediate for a given instruction.
static bool isGPRZero(const MachineInstr &MI)
Does this instruction set its full destination register to zero?
void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, unsigned ZeroReg, llvm::ArrayRef< unsigned > Indices) const
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2,...
CombinerObjective getCombinerObjective(unsigned Pattern) const override
static bool isFpOrNEON(Register Reg)
Returns whether the physical register is FP or NEON.
bool isAsCheapAsAMove(const MachineInstr &MI) const override
std::optional< DestSourcePair > isCopyLikeInstrImpl(const MachineInstr &MI) const override
static void suppressLdStPair(MachineInstr &MI)
Hint that pairing the given load or store is unprofitable.
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isPreLd(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load.
void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, llvm::ArrayRef< unsigned > Indices) const
bool optimizeCondBranch(MachineInstr &MI) const override
Replace csincr-branch sequence by simple conditional branch.
static int getMemScale(unsigned Opc)
Scaling factor for (scaled or unscaled) load or store.
bool isCandidateToMergeOrPair(const MachineInstr &MI) const
Return true if this is a load/store that can be potentially paired/merged.
MCInst getNop() const override
static const MachineOperand & getLdStBaseOp(const MachineInstr &MI)
Returns the base register operator of a load/store.
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const
const AArch64RegisterInfo * getRegisterInfo() const override
bool isNeonAvailable() const
Returns true if the target has NEON and the function at runtime is known to have NEON enabled (e....
bool isSVEorStreamingSVEAvailable() const
Returns true if the target has access to either the full range of SVE instructions,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
This is an important base class in LLVM.
Definition Constant.h:43
A debug info location.
Definition DebugLoc.h:126
bool empty() const
Definition DenseMap.h:171
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Definition Function.h:698
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Definition Function.h:695
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
LLVM_ABI void accumulate(const MachineInstr &MI)
Adds all register units used, defined or clobbered in MI.
static LocationSize precise(uint64_t Value)
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:67
bool usesWindowsCFI() const
Definition MCAsmInfo.h:675
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
Definition MCDwarf.h:628
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Definition MCDwarf.h:670
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition MCDwarf.h:643
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
Definition MCDwarf.h:756
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
static constexpr unsigned NoRegister
Definition MCRegister.h:60
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
Set of metadata that should be preserved when using BuildMI().
bool isInlineAsmBrIndirectTarget() const
Returns true if this is the indirect dest of an INLINEASM_BR.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
reverse_instr_iterator instr_rbegin()
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
reverse_instr_iterator instr_rend()
Instructions::iterator instr_iterator
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator insertAfter(iterator I, MachineInstr *MI)
Insert MI into the instruction list after I.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
void setStackID(int ObjectIdx, uint8_t ID)
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getNumObjects() const
Return the number of objects.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
bool isCall(QueryType Type=AnyInBundle) const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
LLVM_ABI uint32_t mergeFlagsWith(const MachineInstr &Other) const
Return the MIFlags which represent both MachineInstrs.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
bool registerDefIsDead(Register Reg, const TargetRegisterInfo *TRI) const
Returns true if the register is dead in this machine instruction.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
LLVM_ABI bool isLoadFoldBarrier() const
Returns true if it is illegal to fold a load across this instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
MachineBasicBlock * getDefBlock(Register Reg) const
Return the machine basic block in which the specified virtual register is defined,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
MI-level patchpoint operands.
Definition StackMaps.h:77
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
Definition StackMaps.h:105
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:66
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents a location in source code.
Definition SMLoc.h:22
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
bool empty() const
Definition SmallSet.h:169
bool erase(const T &V)
Definition SmallSet.h:200
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:68
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
Definition StackMaps.h:36
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
Definition StackMaps.h:51
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
int64_t getFixed() const
Returns the fixed component of the stack.
Definition TypeSize.h:46
int64_t getScalable() const
Returns the scalable component of the stack.
Definition TypeSize.h:49
static StackOffset get(int64_t Fixed, int64_t Scalable)
Definition TypeSize.h:41
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:40
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:39
MI-level Statepoint operands.
Definition StackMaps.h:159
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Definition StackMaps.h:208
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const
Produce the expression describing the MI loading a value into the physical register Reg.
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual bool isFunctionSafeToSplit(const MachineFunction &MF) const
Return true if the function is a viable candidate for machine function splitting.
const Triple & getTargetTriple() const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetOptions Options
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition Triple.h:873
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:346
Value * getOperand(unsigned i) const
Definition User.h:207
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
self_iterator getIterator()
Definition ilist_node.h:123
A raw_ostream that writes to an std::string.
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCode getInvertedCondCode(CondCode Code)
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_ARM64EC_CALLMANGLE
MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version of a symbol,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_HI12
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address,...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
@ MO_G2
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address,...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
unsigned getCheckerSizeInBytes(AuthCheckMethod Method)
Returns the number of bytes added by checkAuthenticatedRegister.
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
constexpr bool isLegalArithImmed(const uint64_t C)
isLegalArithImmed -
static unsigned getArithShiftValue(unsigned Imm)
getArithShiftValue - get the arithmetic shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static AArch64_AM::ShiftExtendType getExtendType(unsigned Imm)
getExtendType - Extract the extend type for operands of arithmetic ops.
static AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void expandMOVAddr(unsigned Opcode, unsigned TargetFlags, bool IsTargetMachO, SmallVectorImpl< AddrInsnModel > &Insn)
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static const uint64_t InstrFlagIsWhile
static const uint64_t InstrFlagIsPTestLike
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
initializer< Ty > init(const Ty &Val)
constexpr double e
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< InstrNode * > Instr
Definition RDFGraph.h:389
iterator end() const
Definition BasicBlock.h:89
LLVM_ABI Instruction & back() const
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:578
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
static bool isCondBranchOpcode(int Opc)
MCCFIInstruction createDefCFA(const TargetRegisterInfo &TRI, unsigned FrameReg, unsigned Reg, const StackOffset &Offset, bool LastAdjustmentWasScalable=true)
static bool isPTrueOpcode(unsigned Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool succeeded(LogicalResult Result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset, bool *OutUseUnscaledOp=nullptr, unsigned *OutUnscaledOp=nullptr, int64_t *EmittableOffset=nullptr)
Check if the Offset is a valid frame offset for MI.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
@ Renamable
Register that may be renamed.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
static bool isIndirectBranchOpcode(int Opc)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
@ AArch64FrameOffsetIsLegal
Offset is legal.
@ AArch64FrameOffsetCanUpdate
Offset can apply, at least partly.
@ AArch64FrameOffsetCannotUpdate
Offset cannot apply.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:338
static bool isSEHInstruction(const MachineInstr &MI)
bool isLFIPrePostMemAccess(unsigned Opcode)
Returns true if Opcode is a pre- or post-indexed memory access that the LFI rewriter expands with a b...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
AArch64MachineCombinerPattern
@ MULSUBv8i16_OP2
@ FMULv4i16_indexed_OP1
@ FMLSv1i32_indexed_OP2
@ MULSUBv2i32_indexed_OP1
@ FMLAv2i32_indexed_OP2
@ MULADDv4i16_indexed_OP2
@ FMLAv1i64_indexed_OP1
@ MULSUBv16i8_OP1
@ FMLAv8i16_indexed_OP2
@ FMULv2i32_indexed_OP1
@ MULSUBv8i16_indexed_OP2
@ FMLAv1i64_indexed_OP2
@ MULSUBv4i16_indexed_OP2
@ FMLAv1i32_indexed_OP1
@ FMLAv2i64_indexed_OP2
@ FMLSv8i16_indexed_OP1
@ MULSUBv2i32_OP1
@ FMULv4i16_indexed_OP2
@ MULSUBv4i32_indexed_OP2
@ FMULv2i64_indexed_OP2
@ FMLAv4i32_indexed_OP1
@ MULADDv4i16_OP2
@ FMULv8i16_indexed_OP2
@ MULSUBv4i16_OP1
@ MULADDv4i32_OP2
@ MULADDv2i32_OP2
@ MULADDv16i8_OP2
@ FMLSv4i16_indexed_OP1
@ MULADDv16i8_OP1
@ FMLAv2i64_indexed_OP1
@ FMLAv1i32_indexed_OP2
@ FMLSv2i64_indexed_OP2
@ MULADDv2i32_OP1
@ MULADDv4i32_OP1
@ MULADDv2i32_indexed_OP1
@ MULSUBv16i8_OP2
@ MULADDv4i32_indexed_OP1
@ MULADDv2i32_indexed_OP2
@ FMLAv4i16_indexed_OP2
@ MULSUBv8i16_OP1
@ FMULv2i32_indexed_OP2
@ FMLSv2i32_indexed_OP2
@ FMLSv4i32_indexed_OP1
@ FMULv2i64_indexed_OP1
@ MULSUBv4i16_OP2
@ FMLSv4i16_indexed_OP2
@ FMLAv2i32_indexed_OP1
@ FMLSv2i32_indexed_OP1
@ FMLAv8i16_indexed_OP1
@ MULSUBv4i16_indexed_OP1
@ FMLSv4i32_indexed_OP2
@ MULADDv4i32_indexed_OP2
@ MULSUBv4i32_OP2
@ MULSUBv8i16_indexed_OP1
@ MULADDv8i16_OP2
@ MULSUBv2i32_indexed_OP2
@ FMULv4i32_indexed_OP2
@ FMLSv2i64_indexed_OP1
@ MULADDv4i16_OP1
@ FMLAv4i32_indexed_OP2
@ MULADDv8i16_indexed_OP1
@ FMULv4i32_indexed_OP1
@ FMLAv4i16_indexed_OP1
@ FMULv8i16_indexed_OP1
@ MULADDv8i16_OP1
@ MULSUBv4i32_indexed_OP1
@ MULSUBv4i32_OP1
@ FMLSv8i16_indexed_OP2
@ MULADDv8i16_indexed_OP2
@ MULSUBv2i32_OP2
@ FMLSv1i64_indexed_OP2
@ MULADDv4i16_indexed_OP1
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr RegState getDefRegState(bool B)
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
std::optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:149
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition STLExtras.h:322
static MCRegister getXRegFromWReg(MCRegister Reg)
MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg, const StackOffset &OffsetFromDefCFA, std::optional< int64_t > IncomingVGOffsetFromDefCFA)
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static bool isUncondBranchOpcode(int Opc)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2192
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, StackOffset &Offset, const AArch64InstrInfo *TII)
rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
static const MachineMemOperand::Flags MOSuppressPair
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
void appendLEB128(SmallVectorImpl< U > &Buffer, T Value)
Definition LEB128.h:246
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
bool optimizeTerminators(MachineBasicBlock *MBB, const TargetInstrInfo &TII)
std::pair< MachineOperand, DIExpression * > ParamLoadedValue
bool isNZCVTouchedInInstructionRange(const MachineInstr &DefMI, const MachineInstr &UseMI, const TargetRegisterInfo *TRI)
Return true if there is an instruction /after/ DefMI and before UseMI which either reads or clobbers ...
static const MachineMemOperand::Flags MOStridedAccess
constexpr RegState getUndefRegState(bool B)
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare.
LLVM_ABI static const MBBSectionID ColdSectionID
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
An individual sequence of instructions to be replaced with a call to an outlined function.
MachineFunction * getMF() const
The information necessary to create an outlined function for some class of candidate.