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 || !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 if (!DefMI)
938 return 0;
939 unsigned Opc = 0;
940 unsigned SrcReg = 0;
941 switch (DefMI->getOpcode()) {
942 case AArch64::SUBREG_TO_REG:
943 // Check for the following way to define an 64-bit immediate:
944 // %0:gpr32 = MOVi32imm 1
945 // %1:gpr64 = SUBREG_TO_REG %0:gpr32, %subreg.sub_32
946 if (!DefMI->getOperand(1).isReg())
947 return 0;
948 if (!DefMI->getOperand(2).isImm() ||
949 DefMI->getOperand(2).getImm() != AArch64::sub_32)
950 return 0;
951 DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg());
952 if (DefMI->getOpcode() != AArch64::MOVi32imm)
953 return 0;
954 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
955 return 0;
956 assert(Is64Bit);
957 SrcReg = AArch64::XZR;
958 Opc = AArch64::CSINCXr;
959 break;
960
961 case AArch64::MOVi32imm:
962 case AArch64::MOVi64imm:
963 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
964 return 0;
965 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
966 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
967 break;
968
969 case AArch64::ADDSXri:
970 case AArch64::ADDSWri:
971 // if NZCV is used, do not fold.
972 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
973 true) == -1)
974 return 0;
975 // fall-through to ADDXri and ADDWri.
976 [[fallthrough]];
977 case AArch64::ADDXri:
978 case AArch64::ADDWri:
979 // add x, 1 -> csinc.
980 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
981 DefMI->getOperand(3).getImm() != 0)
982 return 0;
983 SrcReg = DefMI->getOperand(1).getReg();
984 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
985 break;
986
987 case AArch64::ORNXrr:
988 case AArch64::ORNWrr: {
989 // not x -> csinv, represented as orn dst, xzr, src.
990 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
991 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
992 return 0;
993 SrcReg = DefMI->getOperand(2).getReg();
994 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
995 break;
996 }
997
998 case AArch64::SUBSXrr:
999 case AArch64::SUBSWrr:
1000 // if NZCV is used, do not fold.
1001 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1002 true) == -1)
1003 return 0;
1004 // fall-through to SUBXrr and SUBWrr.
1005 [[fallthrough]];
1006 case AArch64::SUBXrr:
1007 case AArch64::SUBWrr: {
1008 // neg x -> csneg, represented as sub dst, xzr, src.
1009 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1010 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1011 return 0;
1012 SrcReg = DefMI->getOperand(2).getReg();
1013 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1014 break;
1015 }
1016 default:
1017 return 0;
1018 }
1019 assert(Opc && SrcReg && "Missing parameters");
1020
1021 if (NewReg)
1022 *NewReg = SrcReg;
1023 return Opc;
1024}
1025
1028 Register DstReg, Register TrueReg,
1029 Register FalseReg, int &CondCycles,
1030 int &TrueCycles,
1031 int &FalseCycles) const {
1032 // Check register classes.
1033 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1034 const TargetRegisterClass *RC =
1035 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
1036 if (!RC)
1037 return false;
1038
1039 // Also need to check the dest regclass, in case we're trying to optimize
1040 // something like:
1041 // %1(gpr) = PHI %2(fpr), bb1, %(fpr), bb2
1042 if (!RI.getCommonSubClass(RC, MRI.getRegClass(DstReg)))
1043 return false;
1044
1045 // Expanding cbz/tbz requires an extra cycle of latency on the condition.
1046 unsigned ExtraCondLat = Cond.size() != 1;
1047
1048 // GPRs are handled by csel.
1049 // FIXME: Fold in x+1, -x, and ~x when applicable.
1050 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1051 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1052 // Single-cycle csel, csinc, csinv, and csneg.
1053 CondCycles = 1 + ExtraCondLat;
1054 TrueCycles = FalseCycles = 1;
1055 if (canFoldIntoCSel(MRI, TrueReg))
1056 TrueCycles = 0;
1057 else if (canFoldIntoCSel(MRI, FalseReg))
1058 FalseCycles = 0;
1059 return true;
1060 }
1061
1062 // Scalar floating point is handled by fcsel.
1063 // FIXME: Form fabs, fmin, and fmax when applicable.
1064 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1065 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1066 CondCycles = 5 + ExtraCondLat;
1067 TrueCycles = FalseCycles = 2;
1068 return true;
1069 }
1070
1071 // Can't do vectors.
1072 return false;
1073}
1074
1077 const DebugLoc &DL, Register DstReg,
1079 Register TrueReg, Register FalseReg) const {
1080 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1081
1082 // Parse the condition code, see parseCondBranch() above.
1084 switch (Cond.size()) {
1085 default:
1086 llvm_unreachable("Unknown condition opcode in Cond");
1087 case 1: // b.cc
1088 CC = AArch64CC::CondCode(Cond[0].getImm());
1089 break;
1090 case 3: { // cbz/cbnz
1091 // We must insert a compare against 0.
1092 bool Is64Bit;
1093 switch (Cond[1].getImm()) {
1094 default:
1095 llvm_unreachable("Unknown branch opcode in Cond");
1096 case AArch64::CBZW:
1097 Is64Bit = false;
1098 CC = AArch64CC::EQ;
1099 break;
1100 case AArch64::CBZX:
1101 Is64Bit = true;
1102 CC = AArch64CC::EQ;
1103 break;
1104 case AArch64::CBNZW:
1105 Is64Bit = false;
1106 CC = AArch64CC::NE;
1107 break;
1108 case AArch64::CBNZX:
1109 Is64Bit = true;
1110 CC = AArch64CC::NE;
1111 break;
1112 }
1113 Register SrcReg = Cond[2].getReg();
1114 if (Is64Bit) {
1115 // cmp reg, #0 is actually subs xzr, reg, #0.
1116 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
1117 BuildMI(MBB, I, DL, get(AArch64::SUBSXri), AArch64::XZR)
1118 .addReg(SrcReg)
1119 .addImm(0)
1120 .addImm(0);
1121 } else {
1122 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
1123 BuildMI(MBB, I, DL, get(AArch64::SUBSWri), AArch64::WZR)
1124 .addReg(SrcReg)
1125 .addImm(0)
1126 .addImm(0);
1127 }
1128 break;
1129 }
1130 case 4: { // tbz/tbnz
1131 // We must insert a tst instruction.
1132 switch (Cond[1].getImm()) {
1133 default:
1134 llvm_unreachable("Unknown branch opcode in Cond");
1135 case AArch64::TBZW:
1136 case AArch64::TBZX:
1137 CC = AArch64CC::EQ;
1138 break;
1139 case AArch64::TBNZW:
1140 case AArch64::TBNZX:
1141 CC = AArch64CC::NE;
1142 break;
1143 }
1144 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
1145 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
1146 BuildMI(MBB, I, DL, get(AArch64::ANDSWri), AArch64::WZR)
1147 .addReg(Cond[2].getReg())
1148 .addImm(
1150 else
1151 BuildMI(MBB, I, DL, get(AArch64::ANDSXri), AArch64::XZR)
1152 .addReg(Cond[2].getReg())
1153 .addImm(
1155 break;
1156 }
1157 case 5: { // cb
1158 // We must insert a cmp, that is a subs
1159 // 0 1 2 3 4
1160 // Cond is { -1, Opcode, CC, Op0, Op1 }
1161
1162 unsigned SubsOpc, SubsDestReg;
1163 bool IsImm = false;
1164 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1165 switch (Cond[1].getImm()) {
1166 default:
1167 llvm_unreachable("Unknown branch opcode in Cond");
1168 case AArch64::CBWPri:
1169 SubsOpc = AArch64::SUBSWri;
1170 SubsDestReg = AArch64::WZR;
1171 IsImm = true;
1172 break;
1173 case AArch64::CBXPri:
1174 SubsOpc = AArch64::SUBSXri;
1175 SubsDestReg = AArch64::XZR;
1176 IsImm = true;
1177 break;
1178 case AArch64::CBWPrr:
1179 SubsOpc = AArch64::SUBSWrr;
1180 SubsDestReg = AArch64::WZR;
1181 IsImm = false;
1182 break;
1183 case AArch64::CBXPrr:
1184 SubsOpc = AArch64::SUBSXrr;
1185 SubsDestReg = AArch64::XZR;
1186 IsImm = false;
1187 break;
1188 }
1189
1190 if (IsImm)
1191 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1192 .addReg(Cond[3].getReg())
1193 .addImm(Cond[4].getImm())
1194 .addImm(0);
1195 else
1196 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1197 .addReg(Cond[3].getReg())
1198 .addReg(Cond[4].getReg());
1199 } break;
1200 case 7: { // cb[b,h]
1201 // We must insert a cmp, that is a subs, but also zero- or sign-extensions
1202 // that have been folded. For the first operand we codegen an explicit
1203 // extension, for the second operand we fold the extension into cmp.
1204 // 0 1 2 3 4 5 6
1205 // Cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
1206
1207 // We need a new register for the now explicitly extended register
1208 Register Reg = Cond[4].getReg();
1210 unsigned ExtOpc;
1211 unsigned ExtBits;
1212 AArch64_AM::ShiftExtendType ExtendType =
1214 switch (ExtendType) {
1215 default:
1216 llvm_unreachable("Unknown shift-extend for CB instruction");
1217 case AArch64_AM::SXTB:
1218 assert(
1219 Cond[1].getImm() == AArch64::CBBAssertExt &&
1220 "Unexpected compare-and-branch instruction for SXTB shift-extend");
1221 ExtOpc = AArch64::SBFMWri;
1222 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1223 break;
1224 case AArch64_AM::SXTH:
1225 assert(
1226 Cond[1].getImm() == AArch64::CBHAssertExt &&
1227 "Unexpected compare-and-branch instruction for SXTH shift-extend");
1228 ExtOpc = AArch64::SBFMWri;
1229 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1230 break;
1231 case AArch64_AM::UXTB:
1232 assert(
1233 Cond[1].getImm() == AArch64::CBBAssertExt &&
1234 "Unexpected compare-and-branch instruction for UXTB shift-extend");
1235 ExtOpc = AArch64::ANDWri;
1236 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1237 break;
1238 case AArch64_AM::UXTH:
1239 assert(
1240 Cond[1].getImm() == AArch64::CBHAssertExt &&
1241 "Unexpected compare-and-branch instruction for UXTH shift-extend");
1242 ExtOpc = AArch64::ANDWri;
1243 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1244 break;
1245 }
1246
1247 // Build the explicit extension of the first operand
1248 Reg = MRI.createVirtualRegister(&AArch64::GPR32spRegClass);
1250 BuildMI(MBB, I, DL, get(ExtOpc), Reg).addReg(Cond[4].getReg());
1251 if (ExtOpc != AArch64::ANDWri)
1252 MBBI.addImm(0);
1253 MBBI.addImm(ExtBits);
1254 }
1255
1256 // Now, subs with an extended second operand
1258 AArch64_AM::ShiftExtendType ExtendType =
1260 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1261 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1262 BuildMI(MBB, I, DL, get(AArch64::SUBSWrx), AArch64::WZR)
1263 .addReg(Cond[3].getReg())
1264 .addReg(Reg)
1265 .addImm(AArch64_AM::getArithExtendImm(ExtendType, 0));
1266 } // If no extension is needed, just a regular subs
1267 else {
1268 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1269 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1270 BuildMI(MBB, I, DL, get(AArch64::SUBSWrr), AArch64::WZR)
1271 .addReg(Cond[3].getReg())
1272 .addReg(Reg);
1273 }
1274
1275 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1276 } break;
1277 }
1278
1279 unsigned Opc = 0;
1280 const TargetRegisterClass *RC = nullptr;
1281 bool TryFold = false;
1282 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
1283 RC = &AArch64::GPR64RegClass;
1284 Opc = AArch64::CSELXr;
1285 TryFold = true;
1286 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
1287 RC = &AArch64::GPR32RegClass;
1288 Opc = AArch64::CSELWr;
1289 TryFold = true;
1290 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
1291 RC = &AArch64::FPR64RegClass;
1292 Opc = AArch64::FCSELDrrr;
1293 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
1294 RC = &AArch64::FPR32RegClass;
1295 Opc = AArch64::FCSELSrrr;
1296 }
1297 assert(RC && "Unsupported regclass");
1298
1299 // Try folding simple instructions into the csel.
1300 if (TryFold) {
1301 unsigned NewReg = 0;
1302 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewReg);
1303 if (FoldedOpc) {
1304 // The folded opcodes csinc, csinc and csneg apply the operation to
1305 // FalseReg, so we need to invert the condition.
1307 TrueReg = FalseReg;
1308 } else
1309 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewReg);
1310
1311 // Fold the operation. Leave any dead instructions for DCE to clean up.
1312 if (FoldedOpc) {
1313 FalseReg = NewReg;
1314 Opc = FoldedOpc;
1315 // Extend the live range of NewReg.
1316 MRI.clearKillFlags(NewReg);
1317 }
1318 }
1319
1320 // Pull all virtual register into the appropriate class.
1321 MRI.constrainRegClass(TrueReg, RC);
1322 // FalseReg might be WZR or XZR if the folded operand is a literal 1.
1323 assert(
1324 (FalseReg.isVirtual() || FalseReg == AArch64::WZR ||
1325 FalseReg == AArch64::XZR) &&
1326 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1327 if (FalseReg.isVirtual())
1328 MRI.constrainRegClass(FalseReg, RC);
1329
1330 // Insert the csel.
1331 BuildMI(MBB, I, DL, get(Opc), DstReg)
1332 .addReg(TrueReg)
1333 .addReg(FalseReg)
1334 .addImm(CC);
1335}
1336
1337// Return true if Imm can be loaded into a register by a "cheap" sequence of
1338// instructions. For now, "cheap" means at most two instructions.
1339static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
1340 if (BitSize == 32)
1341 return true;
1342
1343 assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
1344 uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
1346 AArch64_IMM::expandMOVImm(Imm, BitSize, Is);
1347
1348 return Is.size() <= 2;
1349}
1350
1351// Check if a COPY instruction is cheap.
1352static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
1353 assert(MI.isCopy() && "Expected COPY instruction");
1354 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1355
1356 // Cross-bank copies (e.g., between GPR and FPR) are expensive on AArch64,
1357 // typically requiring an FMOV instruction with a 2-6 cycle latency.
1358 auto GetRegClass = [&](Register Reg) -> const TargetRegisterClass * {
1359 if (Reg.isVirtual())
1360 return MRI.getRegClass(Reg);
1361 if (Reg.isPhysical())
1362 return RI.getMinimalPhysRegClass(Reg);
1363 return nullptr;
1364 };
1365 const TargetRegisterClass *DstRC = GetRegClass(MI.getOperand(0).getReg());
1366 const TargetRegisterClass *SrcRC = GetRegClass(MI.getOperand(1).getReg());
1367 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1368 return false;
1369
1370 return MI.isAsCheapAsAMove();
1371}
1372
1373// FIXME: this implementation should be micro-architecture dependent, so a
1374// micro-architecture target hook should be introduced here in future.
1376 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1377 if (isExynosCheapAsMove(MI))
1378 return true;
1379 return MI.isAsCheapAsAMove();
1380 }
1381
1382 switch (MI.getOpcode()) {
1383 default:
1384 return MI.isAsCheapAsAMove();
1385
1386 case TargetOpcode::COPY:
1387 return isCheapCopy(MI, RI);
1388
1389 case AArch64::ADDWrs:
1390 case AArch64::ADDXrs:
1391 case AArch64::SUBWrs:
1392 case AArch64::SUBXrs:
1393 return Subtarget.hasALULSLFast() && MI.getOperand(3).getImm() <= 4;
1394
1395 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
1396 // ORRXri, it is as cheap as MOV.
1397 // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
1398 case AArch64::MOVi32imm:
1399 return isCheapImmediate(MI, 32);
1400 case AArch64::MOVi64imm:
1401 return isCheapImmediate(MI, 64);
1402 }
1403}
1404
1405bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) {
1406 switch (MI.getOpcode()) {
1407 default:
1408 return false;
1409
1410 case AArch64::ADDWrs:
1411 case AArch64::ADDXrs:
1412 case AArch64::ADDSWrs:
1413 case AArch64::ADDSXrs: {
1414 unsigned Imm = MI.getOperand(3).getImm();
1415 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1416 if (ShiftVal == 0)
1417 return true;
1418 return AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL && ShiftVal <= 5;
1419 }
1420
1421 case AArch64::ADDWrx:
1422 case AArch64::ADDXrx:
1423 case AArch64::ADDXrx64:
1424 case AArch64::ADDSWrx:
1425 case AArch64::ADDSXrx:
1426 case AArch64::ADDSXrx64: {
1427 unsigned Imm = MI.getOperand(3).getImm();
1429 default:
1430 return false;
1431 case AArch64_AM::UXTB:
1432 case AArch64_AM::UXTH:
1433 case AArch64_AM::UXTW:
1434 case AArch64_AM::UXTX:
1436 }
1437 }
1438
1439 case AArch64::SUBWrs:
1440 case AArch64::SUBSWrs: {
1441 unsigned Imm = MI.getOperand(3).getImm();
1442 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1443 return ShiftVal == 0 ||
1444 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 31);
1445 }
1446
1447 case AArch64::SUBXrs:
1448 case AArch64::SUBSXrs: {
1449 unsigned Imm = MI.getOperand(3).getImm();
1450 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1451 return ShiftVal == 0 ||
1452 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 63);
1453 }
1454
1455 case AArch64::SUBWrx:
1456 case AArch64::SUBXrx:
1457 case AArch64::SUBXrx64:
1458 case AArch64::SUBSWrx:
1459 case AArch64::SUBSXrx:
1460 case AArch64::SUBSXrx64: {
1461 unsigned Imm = MI.getOperand(3).getImm();
1463 default:
1464 return false;
1465 case AArch64_AM::UXTB:
1466 case AArch64_AM::UXTH:
1467 case AArch64_AM::UXTW:
1468 case AArch64_AM::UXTX:
1470 }
1471 }
1472
1473 case AArch64::LDRBBroW:
1474 case AArch64::LDRBBroX:
1475 case AArch64::LDRBroW:
1476 case AArch64::LDRBroX:
1477 case AArch64::LDRDroW:
1478 case AArch64::LDRDroX:
1479 case AArch64::LDRHHroW:
1480 case AArch64::LDRHHroX:
1481 case AArch64::LDRHroW:
1482 case AArch64::LDRHroX:
1483 case AArch64::LDRQroW:
1484 case AArch64::LDRQroX:
1485 case AArch64::LDRSBWroW:
1486 case AArch64::LDRSBWroX:
1487 case AArch64::LDRSBXroW:
1488 case AArch64::LDRSBXroX:
1489 case AArch64::LDRSHWroW:
1490 case AArch64::LDRSHWroX:
1491 case AArch64::LDRSHXroW:
1492 case AArch64::LDRSHXroX:
1493 case AArch64::LDRSWroW:
1494 case AArch64::LDRSWroX:
1495 case AArch64::LDRSroW:
1496 case AArch64::LDRSroX:
1497 case AArch64::LDRWroW:
1498 case AArch64::LDRWroX:
1499 case AArch64::LDRXroW:
1500 case AArch64::LDRXroX:
1501 case AArch64::PRFMroW:
1502 case AArch64::PRFMroX:
1503 case AArch64::STRBBroW:
1504 case AArch64::STRBBroX:
1505 case AArch64::STRBroW:
1506 case AArch64::STRBroX:
1507 case AArch64::STRDroW:
1508 case AArch64::STRDroX:
1509 case AArch64::STRHHroW:
1510 case AArch64::STRHHroX:
1511 case AArch64::STRHroW:
1512 case AArch64::STRHroX:
1513 case AArch64::STRQroW:
1514 case AArch64::STRQroX:
1515 case AArch64::STRSroW:
1516 case AArch64::STRSroX:
1517 case AArch64::STRWroW:
1518 case AArch64::STRWroX:
1519 case AArch64::STRXroW:
1520 case AArch64::STRXroX: {
1521 unsigned IsSigned = MI.getOperand(3).getImm();
1522 return !IsSigned;
1523 }
1524 }
1525}
1526
1527bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
1528 unsigned Opc = MI.getOpcode();
1529 switch (Opc) {
1530 default:
1531 return false;
1532 case AArch64::SEH_StackAlloc:
1533 case AArch64::SEH_SaveFPLR:
1534 case AArch64::SEH_SaveFPLR_X:
1535 case AArch64::SEH_SaveReg:
1536 case AArch64::SEH_SaveReg_X:
1537 case AArch64::SEH_SaveRegP:
1538 case AArch64::SEH_SaveRegP_X:
1539 case AArch64::SEH_SaveFReg:
1540 case AArch64::SEH_SaveFReg_X:
1541 case AArch64::SEH_SaveFRegP:
1542 case AArch64::SEH_SaveFRegP_X:
1543 case AArch64::SEH_SetFP:
1544 case AArch64::SEH_AddFP:
1545 case AArch64::SEH_Nop:
1546 case AArch64::SEH_PrologEnd:
1547 case AArch64::SEH_EpilogStart:
1548 case AArch64::SEH_EpilogEnd:
1549 case AArch64::SEH_PACSignLR:
1550 case AArch64::SEH_SaveAnyRegI:
1551 case AArch64::SEH_SaveAnyRegIP:
1552 case AArch64::SEH_SaveAnyRegQP:
1553 case AArch64::SEH_SaveAnyRegQPX:
1554 case AArch64::SEH_AllocZ:
1555 case AArch64::SEH_SaveZReg:
1556 case AArch64::SEH_SavePReg:
1557 return true;
1558 }
1559}
1560
1562 Register &SrcReg, Register &DstReg,
1563 unsigned &SubIdx) const {
1564 switch (MI.getOpcode()) {
1565 default:
1566 return false;
1567 case AArch64::SBFMXri: // aka sxtw
1568 case AArch64::UBFMXri: // aka uxtw
1569 // Check for the 32 -> 64 bit extension case, these instructions can do
1570 // much more.
1571 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
1572 return false;
1573 // This is a signed or unsigned 32 -> 64 bit extension.
1574 SrcReg = MI.getOperand(1).getReg();
1575 DstReg = MI.getOperand(0).getReg();
1576 SubIdx = AArch64::sub_32;
1577 return true;
1578 }
1579}
1580
1582 const MachineInstr &MIa, const MachineInstr &MIb) const {
1584 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
1585 int64_t OffsetA = 0, OffsetB = 0;
1586 TypeSize WidthA(0, false), WidthB(0, false);
1587 bool OffsetAIsScalable = false, OffsetBIsScalable = false;
1588
1589 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
1590 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
1591
1594 return false;
1595
1596 // Retrieve the base, offset from the base and width. Width
1597 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
1598 // base are identical, and the offset of a lower memory access +
1599 // the width doesn't overlap the offset of a higher memory access,
1600 // then the memory accesses are different.
1601 // If OffsetAIsScalable and OffsetBIsScalable are both true, they
1602 // are assumed to have the same scale (vscale).
1603 if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, OffsetAIsScalable,
1604 WidthA, TRI) &&
1605 getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, OffsetBIsScalable,
1606 WidthB, TRI)) {
1607 if (BaseOpA->isIdenticalTo(*BaseOpB) &&
1608 OffsetAIsScalable == OffsetBIsScalable) {
1609 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1610 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1611 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1612 if (LowWidth.isScalable() == OffsetAIsScalable &&
1613 LowOffset + (int)LowWidth.getKnownMinValue() <= HighOffset)
1614 return true;
1615 }
1616 }
1617 return false;
1618}
1619
1621 const MachineBasicBlock *MBB,
1622 const MachineFunction &MF) const {
1624 return true;
1625
1626 // Do not move an instruction that can be recognized as a branch target.
1627 if (hasBTISemantics(MI))
1628 return true;
1629
1630 switch (MI.getOpcode()) {
1631 case AArch64::HINT:
1632 // CSDB hints are scheduling barriers.
1633 if (MI.getOperand(0).getImm() == 0x14)
1634 return true;
1635 break;
1636 case AArch64::DSB:
1637 case AArch64::ISB:
1638 // DSB and ISB also are scheduling barriers.
1639 return true;
1640 case AArch64::MSRpstatesvcrImm1:
1641 // SMSTART and SMSTOP are also scheduling barriers.
1642 return true;
1643 default:;
1644 }
1645 if (isSEHInstruction(MI))
1646 return true;
1647 auto Next = std::next(MI.getIterator());
1648 return Next != MBB->end() && Next->isCFIInstruction();
1649}
1650
1651/// analyzeCompare - For a comparison instruction, return the source registers
1652/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
1653/// Return true if the comparison instruction can be analyzed.
1655 Register &SrcReg2, int64_t &CmpMask,
1656 int64_t &CmpValue) const {
1657 // The first operand can be a frame index where we'd normally expect a
1658 // register.
1659 // FIXME: Pass subregisters out of analyzeCompare
1660 assert(MI.getNumOperands() >= 2 && "All AArch64 cmps should have 2 operands");
1661 if (!MI.getOperand(1).isReg() || MI.getOperand(1).getSubReg())
1662 return false;
1663
1664 switch (MI.getOpcode()) {
1665 default:
1666 break;
1667 case AArch64::PTEST_PP:
1668 case AArch64::PTEST_PP_ANY:
1669 case AArch64::PTEST_PP_FIRST:
1670 SrcReg = MI.getOperand(0).getReg();
1671 SrcReg2 = MI.getOperand(1).getReg();
1672 if (MI.getOperand(2).getSubReg())
1673 return false;
1674
1675 // Not sure about the mask and value for now...
1676 CmpMask = ~0;
1677 CmpValue = 0;
1678 return true;
1679 case AArch64::SUBSWrr:
1680 case AArch64::SUBSWrs:
1681 case AArch64::SUBSWrx:
1682 case AArch64::SUBSXrr:
1683 case AArch64::SUBSXrs:
1684 case AArch64::SUBSXrx:
1685 case AArch64::ADDSWrr:
1686 case AArch64::ADDSWrs:
1687 case AArch64::ADDSWrx:
1688 case AArch64::ADDSXrr:
1689 case AArch64::ADDSXrs:
1690 case AArch64::ADDSXrx:
1691 // Replace SUBSWrr with SUBWrr if NZCV is not used.
1692 SrcReg = MI.getOperand(1).getReg();
1693 SrcReg2 = MI.getOperand(2).getReg();
1694
1695 // FIXME: Pass subregisters out of analyzeCompare
1696 if (MI.getOperand(2).getSubReg())
1697 return false;
1698
1699 CmpMask = ~0;
1700 CmpValue = 0;
1701 return true;
1702 case AArch64::SUBSWri:
1703 case AArch64::ADDSWri:
1704 case AArch64::SUBSXri:
1705 case AArch64::ADDSXri:
1706 SrcReg = MI.getOperand(1).getReg();
1707 SrcReg2 = 0;
1708 CmpMask = ~0;
1709 CmpValue = MI.getOperand(2).getImm();
1710 return true;
1711 case AArch64::ANDSWri:
1712 case AArch64::ANDSXri:
1713 // ANDS does not use the same encoding scheme as the others xxxS
1714 // instructions.
1715 SrcReg = MI.getOperand(1).getReg();
1716 SrcReg2 = 0;
1717 CmpMask = ~0;
1719 MI.getOperand(2).getImm(),
1720 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1721 return true;
1722 }
1723
1724 return false;
1725}
1726
1728 MachineBasicBlock *MBB = Instr.getParent();
1729 assert(MBB && "Can't get MachineBasicBlock here");
1730 MachineFunction *MF = MBB->getParent();
1731 assert(MF && "Can't get MachineFunction here");
1734 MachineRegisterInfo *MRI = &MF->getRegInfo();
1735
1736 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1737 ++OpIdx) {
1738 MachineOperand &MO = Instr.getOperand(OpIdx);
1739 const TargetRegisterClass *OpRegCstraints =
1740 Instr.getRegClassConstraint(OpIdx, TII, TRI);
1741
1742 // If there's no constraint, there's nothing to do.
1743 if (!OpRegCstraints)
1744 continue;
1745 // If the operand is a frame index, there's nothing to do here.
1746 // A frame index operand will resolve correctly during PEI.
1747 if (MO.isFI())
1748 continue;
1749
1750 assert(MO.isReg() &&
1751 "Operand has register constraints without being a register!");
1752
1753 Register Reg = MO.getReg();
1754 if (Reg.isPhysical()) {
1755 if (!OpRegCstraints->contains(Reg))
1756 return false;
1757 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
1758 !MRI->constrainRegClass(Reg, OpRegCstraints))
1759 return false;
1760 }
1761
1762 return true;
1763}
1764
1765/// Return the opcode that does not set flags when possible - otherwise
1766/// return the original opcode. The caller is responsible to do the actual
1767/// substitution and legality checking.
1769 // Don't convert all compare instructions, because for some the zero register
1770 // encoding becomes the sp register.
1771 bool MIDefinesZeroReg = false;
1772 if (MI.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
1773 MI.definesRegister(AArch64::XZR, /*TRI=*/nullptr))
1774 MIDefinesZeroReg = true;
1775
1776 switch (MI.getOpcode()) {
1777 default:
1778 return MI.getOpcode();
1779 case AArch64::ADDSWrr:
1780 return AArch64::ADDWrr;
1781 case AArch64::ADDSWri:
1782 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1783 case AArch64::ADDSWrs:
1784 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1785 case AArch64::ADDSWrx:
1786 return AArch64::ADDWrx;
1787 case AArch64::ADDSXrr:
1788 return AArch64::ADDXrr;
1789 case AArch64::ADDSXri:
1790 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1791 case AArch64::ADDSXrs:
1792 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1793 case AArch64::ADDSXrx:
1794 return AArch64::ADDXrx;
1795 case AArch64::SUBSWrr:
1796 return AArch64::SUBWrr;
1797 case AArch64::SUBSWri:
1798 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1799 case AArch64::SUBSWrs:
1800 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1801 case AArch64::SUBSWrx:
1802 return AArch64::SUBWrx;
1803 case AArch64::SUBSXrr:
1804 return AArch64::SUBXrr;
1805 case AArch64::SUBSXri:
1806 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1807 case AArch64::SUBSXrs:
1808 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1809 case AArch64::SUBSXrx:
1810 return AArch64::SUBXrx;
1811 }
1812}
1813
1814enum AccessKind { AK_Write = 0x01, AK_Read = 0x10, AK_All = 0x11 };
1815
1816/// True when condition flags are accessed (either by writing or reading)
1817/// on the instruction trace starting at From and ending at To.
1818///
1819/// Note: If From and To are from different blocks it's assumed CC are accessed
1820/// on the path.
1823 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
1824 // Early exit if To is at the beginning of the BB.
1825 if (To == To->getParent()->begin())
1826 return true;
1827
1828 // Check whether the instructions are in the same basic block
1829 // If not, assume the condition flags might get modified somewhere.
1830 if (To->getParent() != From->getParent())
1831 return true;
1832
1833 // From must be above To.
1834 assert(std::any_of(
1835 ++To.getReverse(), To->getParent()->rend(),
1836 [From](MachineInstr &MI) { return MI.getIterator() == From; }));
1837
1838 // We iterate backward starting at \p To until we hit \p From.
1839 for (const MachineInstr &Instr :
1841 if (((AccessToCheck & AK_Write) &&
1842 Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
1843 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
1844 return true;
1845 }
1846 return false;
1847}
1848
1849std::optional<unsigned>
1850AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1851 MachineInstr *Pred,
1852 const MachineRegisterInfo *MRI) const {
1853 unsigned MaskOpcode = Mask->getOpcode();
1854 unsigned PredOpcode = Pred->getOpcode();
1855 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1856 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1857
1858 if (PredIsWhileLike) {
1859 // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1860 // instruction and the condition is "any" since WHILcc does an implicit
1861 // PTEST(ALL, PG) check and PG is always a subset of ALL.
1862 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1863 return PredOpcode;
1864
1865 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1866 // redundant since WHILE performs an implicit PTEST with an all active
1867 // mask.
1868 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1869 getElementSizeForOpcode(MaskOpcode) ==
1870 getElementSizeForOpcode(PredOpcode))
1871 return PredOpcode;
1872
1873 // For PTEST_FIRST(PTRUE_ALL, WHILE), the PTEST_FIRST is redundant since
1874 // WHILEcc performs an implicit PTEST with an all active mask, setting
1875 // the N flag as the PTEST_FIRST would.
1876 if (PTest->getOpcode() == AArch64::PTEST_PP_FIRST &&
1877 isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31)
1878 return PredOpcode;
1879
1880 return {};
1881 }
1882
1883 if (PredIsPTestLike) {
1884 // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1885 // instruction that sets the flags as PTEST would and the condition is
1886 // "any" since PG is always a subset of the governing predicate of the
1887 // ptest-like instruction.
1888 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1889 return PredOpcode;
1890
1891 auto PTestLikeMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1892
1893 // If the PTEST like instruction's general predicate is not `Mask`, attempt
1894 // to look through a copy and try again. This is because some instructions
1895 // take a predicate whose register class is a subset of its result class.
1896 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1897 PTestLikeMask->getOperand(1).getReg().isVirtual())
1898 PTestLikeMask =
1899 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1900
1901 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1902 // the element size matches and either the PTEST_LIKE instruction uses
1903 // the same all active mask or the condition is "any".
1904 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1905 getElementSizeForOpcode(MaskOpcode) ==
1906 getElementSizeForOpcode(PredOpcode)) {
1907 if (Mask == PTestLikeMask || PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1908 return PredOpcode;
1909 }
1910
1911 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
1912 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
1913 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
1914 // compare that also support 16/32/64-bit predicates, the implicit PTEST
1915 // performed by the compare could consider fewer lanes for these element
1916 // sizes.
1917 //
1918 // For example, consider
1919 //
1920 // ptrue p0.b ; P0=1111-1111-1111-1111
1921 // index z0.s, #0, #1 ; Z0=<0,1,2,3>
1922 // index z1.s, #1, #1 ; Z1=<1,2,3,4>
1923 // cmphi p1.s, p0/z, z1.s, z0.s ; P1=0001-0001-0001-0001
1924 // ; ^ last active
1925 // ptest p0, p1.b ; P1=0001-0001-0001-0001
1926 // ; ^ last active
1927 //
1928 // where the compare generates a canonical all active 32-bit predicate
1929 // (equivalent to 'ptrue p1.s, all'). The implicit PTEST sets the last
1930 // active flag, whereas the PTEST instruction with the same mask doesn't.
1931 // For PTEST_ANY this doesn't apply as the flags in this case would be
1932 // identical regardless of element size.
1933 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1934 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1935 PTest->getOpcode() == AArch64::PTEST_PP_ANY))
1936 return PredOpcode;
1937
1938 return {};
1939 }
1940
1941 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1942 // opcode so the PTEST becomes redundant.
1943 switch (PredOpcode) {
1944 case AArch64::AND_PPzPP:
1945 case AArch64::BIC_PPzPP:
1946 case AArch64::EOR_PPzPP:
1947 case AArch64::NAND_PPzPP:
1948 case AArch64::NOR_PPzPP:
1949 case AArch64::ORN_PPzPP:
1950 case AArch64::ORR_PPzPP:
1951 case AArch64::BRKA_PPzP:
1952 case AArch64::BRKPA_PPzPP:
1953 case AArch64::BRKB_PPzP:
1954 case AArch64::BRKPB_PPzPP:
1955 case AArch64::RDFFR_PPz: {
1956 // Check to see if our mask is the same. If not the resulting flag bits
1957 // may be different and we can't remove the ptest.
1958 auto *PredMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1959 if (Mask != PredMask)
1960 return {};
1961 break;
1962 }
1963 case AArch64::BRKN_PPzP: {
1964 // BRKN uses an all active implicit mask to set flags unlike the other
1965 // flag-setting instructions.
1966 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1967 if ((MaskOpcode != AArch64::PTRUE_B) ||
1968 (Mask->getOperand(1).getImm() != 31))
1969 return {};
1970 break;
1971 }
1972 case AArch64::PTRUE_B:
1973 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1974 break;
1975 default:
1976 // Bail out if we don't recognize the input
1977 return {};
1978 }
1979
1980 return convertToFlagSettingOpc(PredOpcode);
1981}
1982
1983/// optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
1984/// operation which could set the flags in an identical manner
1985bool AArch64InstrInfo::optimizePTestInstr(
1986 MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
1987 const MachineRegisterInfo *MRI) const {
1988 auto *Mask = MRI->getUniqueVRegDef(MaskReg);
1989 auto *Pred = MRI->getUniqueVRegDef(PredReg);
1990
1991 if (Pred->isCopy() && PTest->getOpcode() == AArch64::PTEST_PP_FIRST) {
1992 // Instructions which return a multi-vector (e.g. WHILECC_x2) require copies
1993 // before the branch to extract each subregister.
1994 auto Op = Pred->getOperand(1);
1995 if (Op.isReg() && Op.getReg().isVirtual() &&
1996 Op.getSubReg() == AArch64::psub0)
1997 Pred = MRI->getUniqueVRegDef(Op.getReg());
1998 }
1999
2000 unsigned PredOpcode = Pred->getOpcode();
2001 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
2002 if (!NewOp)
2003 return false;
2004
2005 const TargetRegisterInfo *TRI = &getRegisterInfo();
2006
2007 // If another instruction between Pred and PTest accesses flags, don't remove
2008 // the ptest or update the earlier instruction to modify them.
2009 if (areCFlagsAccessedBetweenInstrs(Pred, PTest, TRI))
2010 return false;
2011
2012 // If we pass all the checks, it's safe to remove the PTEST and use the flags
2013 // as they are prior to PTEST. Sometimes this requires the tested PTEST
2014 // operand to be replaced with an equivalent instruction that also sets the
2015 // flags.
2016 PTest->eraseFromParent();
2017 if (*NewOp != PredOpcode) {
2018 Pred->setDesc(get(*NewOp));
2019 bool succeeded = UpdateOperandRegClass(*Pred);
2020 (void)succeeded;
2021 assert(succeeded && "Operands have incompatible register classes!");
2022 Pred->addRegisterDefined(AArch64::NZCV, TRI);
2023 }
2024
2025 // Ensure that the flags def is live.
2026 if (Pred->registerDefIsDead(AArch64::NZCV, TRI)) {
2027 unsigned i = 0, e = Pred->getNumOperands();
2028 for (; i != e; ++i) {
2029 MachineOperand &MO = Pred->getOperand(i);
2030 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::NZCV) {
2031 MO.setIsDead(false);
2032 break;
2033 }
2034 }
2035 }
2036 return true;
2037}
2038
2039/// Try to optimize a compare instruction. A compare instruction is an
2040/// instruction which produces AArch64::NZCV. It can be truly compare
2041/// instruction
2042/// when there are no uses of its destination register.
2043///
2044/// The following steps are tried in order:
2045/// 1. Convert CmpInstr into an unconditional version.
2046/// 2. Remove CmpInstr if above there is an instruction producing a needed
2047/// condition code or an instruction which can be converted into such an
2048/// instruction.
2049/// Only comparison with zero is supported.
2051 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
2052 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
2053 assert(CmpInstr.getParent());
2054 assert(MRI);
2055
2056 // Replace SUBSWrr with SUBWrr if NZCV is not used.
2057 int DeadNZCVIdx =
2058 CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
2059 if (DeadNZCVIdx != -1) {
2060 if (CmpInstr.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
2061 CmpInstr.definesRegister(AArch64::XZR, /*TRI=*/nullptr)) {
2062 CmpInstr.eraseFromParent();
2063 return true;
2064 }
2065 unsigned Opc = CmpInstr.getOpcode();
2066 unsigned NewOpc = convertToNonFlagSettingOpc(CmpInstr);
2067 if (NewOpc == Opc)
2068 return false;
2069 const MCInstrDesc &MCID = get(NewOpc);
2070 CmpInstr.setDesc(MCID);
2071 CmpInstr.removeOperand(DeadNZCVIdx);
2072 bool succeeded = UpdateOperandRegClass(CmpInstr);
2073 (void)succeeded;
2074 assert(succeeded && "Some operands reg class are incompatible!");
2075 return true;
2076 }
2077
2078 if (CmpInstr.getOpcode() == AArch64::PTEST_PP ||
2079 CmpInstr.getOpcode() == AArch64::PTEST_PP_ANY ||
2080 CmpInstr.getOpcode() == AArch64::PTEST_PP_FIRST)
2081 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2082
2083 if (SrcReg2 != 0)
2084 return false;
2085
2086 // CmpInstr is a Compare instruction if destination register is not used.
2087 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
2088 return false;
2089
2090 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2091 return true;
2092 return (CmpValue == 0 || CmpValue == 1) &&
2093 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2094}
2095
2096/// Get opcode of S version of Instr.
2097/// If Instr is S version its opcode is returned.
2098/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
2099/// or we are not interested in it.
2100static unsigned sForm(MachineInstr &Instr) {
2101 switch (Instr.getOpcode()) {
2102 default:
2103 return AArch64::INSTRUCTION_LIST_END;
2104
2105 case AArch64::ADDSWrr:
2106 case AArch64::ADDSWri:
2107 case AArch64::ADDSXrr:
2108 case AArch64::ADDSXri:
2109 case AArch64::ADDSWrx:
2110 case AArch64::ADDSXrx:
2111 case AArch64::ADDSWrs:
2112 case AArch64::ADDSXrs:
2113 case AArch64::SUBSWrr:
2114 case AArch64::SUBSWri:
2115 case AArch64::SUBSWrx:
2116 case AArch64::SUBSWrs:
2117 case AArch64::SUBSXrr:
2118 case AArch64::SUBSXri:
2119 case AArch64::SUBSXrx:
2120 case AArch64::SUBSXrs:
2121 case AArch64::ANDSWri:
2122 case AArch64::ANDSWrr:
2123 case AArch64::ANDSWrs:
2124 case AArch64::ANDSXri:
2125 case AArch64::ANDSXrr:
2126 case AArch64::ANDSXrs:
2127 case AArch64::BICSWrr:
2128 case AArch64::BICSXrr:
2129 case AArch64::BICSWrs:
2130 case AArch64::BICSXrs:
2131 case AArch64::ADCSWr:
2132 case AArch64::ADCSXr:
2133 case AArch64::SBCSWr:
2134 case AArch64::SBCSXr:
2135 return Instr.getOpcode();
2136
2137 case AArch64::ADDWrr:
2138 return AArch64::ADDSWrr;
2139 case AArch64::ADDWri:
2140 return AArch64::ADDSWri;
2141 case AArch64::ADDXrr:
2142 return AArch64::ADDSXrr;
2143 case AArch64::ADDXri:
2144 return AArch64::ADDSXri;
2145 case AArch64::ADDWrx:
2146 return AArch64::ADDSWrx;
2147 case AArch64::ADDXrx:
2148 return AArch64::ADDSXrx;
2149 case AArch64::ADDWrs:
2150 return AArch64::ADDSWrs;
2151 case AArch64::ADDXrs:
2152 return AArch64::ADDSXrs;
2153 case AArch64::ADCWr:
2154 return AArch64::ADCSWr;
2155 case AArch64::ADCXr:
2156 return AArch64::ADCSXr;
2157 case AArch64::SUBWrr:
2158 return AArch64::SUBSWrr;
2159 case AArch64::SUBWri:
2160 return AArch64::SUBSWri;
2161 case AArch64::SUBXrr:
2162 return AArch64::SUBSXrr;
2163 case AArch64::SUBXri:
2164 return AArch64::SUBSXri;
2165 case AArch64::SUBWrx:
2166 return AArch64::SUBSWrx;
2167 case AArch64::SUBXrx:
2168 return AArch64::SUBSXrx;
2169 case AArch64::SUBWrs:
2170 return AArch64::SUBSWrs;
2171 case AArch64::SUBXrs:
2172 return AArch64::SUBSXrs;
2173 case AArch64::SBCWr:
2174 return AArch64::SBCSWr;
2175 case AArch64::SBCXr:
2176 return AArch64::SBCSXr;
2177 case AArch64::ANDWri:
2178 return AArch64::ANDSWri;
2179 case AArch64::ANDXri:
2180 return AArch64::ANDSXri;
2181 case AArch64::ANDWrr:
2182 return AArch64::ANDSWrr;
2183 case AArch64::ANDWrs:
2184 return AArch64::ANDSWrs;
2185 case AArch64::ANDXrr:
2186 return AArch64::ANDSXrr;
2187 case AArch64::ANDXrs:
2188 return AArch64::ANDSXrs;
2189 case AArch64::BICWrr:
2190 return AArch64::BICSWrr;
2191 case AArch64::BICXrr:
2192 return AArch64::BICSXrr;
2193 case AArch64::BICWrs:
2194 return AArch64::BICSWrs;
2195 case AArch64::BICXrs:
2196 return AArch64::BICSXrs;
2197 }
2198}
2199
2200/// Check if AArch64::NZCV should be alive in successors of MBB.
2202 for (auto *BB : MBB->successors())
2203 if (BB->isLiveIn(AArch64::NZCV))
2204 return true;
2205 return false;
2206}
2207
2208/// \returns The condition code operand index for \p Instr if it is a branch
2209/// or select and -1 otherwise.
2210int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2211 const MachineInstr &Instr) {
2212 switch (Instr.getOpcode()) {
2213 default:
2214 return -1;
2215
2216 case AArch64::Bcc: {
2217 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2218 assert(Idx >= 2);
2219 return Idx - 2;
2220 }
2221
2222 case AArch64::CSINVWr:
2223 case AArch64::CSINVXr:
2224 case AArch64::CSINCWr:
2225 case AArch64::CSINCXr:
2226 case AArch64::CSELWr:
2227 case AArch64::CSELXr:
2228 case AArch64::CSNEGWr:
2229 case AArch64::CSNEGXr:
2230 case AArch64::FCSELSrrr:
2231 case AArch64::FCSELDrrr: {
2232 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2233 assert(Idx >= 1);
2234 return Idx - 1;
2235 }
2236 }
2237}
2238
2239/// Find a condition code used by the instruction.
2240/// Returns AArch64CC::Invalid if either the instruction does not use condition
2241/// codes or we don't optimize CmpInstr in the presence of such instructions.
2243 int CCIdx =
2244 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2245 return CCIdx >= 0 ? static_cast<AArch64CC::CondCode>(
2246 Instr.getOperand(CCIdx).getImm())
2248}
2249
2252 UsedNZCV UsedFlags;
2253 switch (CC) {
2254 default:
2255 break;
2256
2257 case AArch64CC::EQ: // Z set
2258 case AArch64CC::NE: // Z clear
2259 UsedFlags.Z = true;
2260 break;
2261
2262 case AArch64CC::HI: // Z clear and C set
2263 case AArch64CC::LS: // Z set or C clear
2264 UsedFlags.Z = true;
2265 [[fallthrough]];
2266 case AArch64CC::HS: // C set
2267 case AArch64CC::LO: // C clear
2268 UsedFlags.C = true;
2269 break;
2270
2271 case AArch64CC::MI: // N set
2272 case AArch64CC::PL: // N clear
2273 UsedFlags.N = true;
2274 break;
2275
2276 case AArch64CC::VS: // V set
2277 case AArch64CC::VC: // V clear
2278 UsedFlags.V = true;
2279 break;
2280
2281 case AArch64CC::GT: // Z clear, N and V the same
2282 case AArch64CC::LE: // Z set, N and V differ
2283 UsedFlags.Z = true;
2284 [[fallthrough]];
2285 case AArch64CC::GE: // N and V the same
2286 case AArch64CC::LT: // N and V differ
2287 UsedFlags.N = true;
2288 UsedFlags.V = true;
2289 break;
2290 }
2291 return UsedFlags;
2292}
2293
2294/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
2295/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
2296/// \returns std::nullopt otherwise.
2297///
2298/// Collect instructions using that flags in \p CCUseInstrs if provided.
2299std::optional<UsedNZCV>
2301 const TargetRegisterInfo &TRI,
2302 SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
2303 MachineBasicBlock *CmpParent = CmpInstr.getParent();
2304 if (MI.getParent() != CmpParent)
2305 return std::nullopt;
2306
2307 if (areCFlagsAliveInSuccessors(CmpParent))
2308 return std::nullopt;
2309
2310 UsedNZCV NZCVUsedAfterCmp;
2312 std::next(CmpInstr.getIterator()), CmpParent->instr_end())) {
2313 if (Instr.readsRegister(AArch64::NZCV, &TRI)) {
2315 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
2316 return std::nullopt;
2317 NZCVUsedAfterCmp |= getUsedNZCV(CC);
2318 if (CCUseInstrs)
2319 CCUseInstrs->push_back(&Instr);
2320 }
2321 if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
2322 break;
2323 }
2324 return NZCVUsedAfterCmp;
2325}
2326
2327static bool isADDSRegImm(unsigned Opcode) {
2328 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2329}
2330
2331static bool isSUBSRegImm(unsigned Opcode) {
2332 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2333}
2334
2336 unsigned Opc = sForm(MI);
2337 switch (Opc) {
2338 case AArch64::ANDSWri:
2339 case AArch64::ANDSWrr:
2340 case AArch64::ANDSWrs:
2341 case AArch64::ANDSXri:
2342 case AArch64::ANDSXrr:
2343 case AArch64::ANDSXrs:
2344 case AArch64::BICSWrr:
2345 case AArch64::BICSXrr:
2346 case AArch64::BICSWrs:
2347 case AArch64::BICSXrs:
2348 return true;
2349 default:
2350 return false;
2351 }
2352}
2353
2354/// Check if CmpInstr can be substituted by MI.
2355///
2356/// CmpInstr can be substituted:
2357/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2358/// - and, MI and CmpInstr are from the same MachineBB
2359/// - and, condition flags are not alive in successors of the CmpInstr parent
2360/// - and, if MI opcode is the S form there must be no defs of flags between
2361/// MI and CmpInstr
2362/// or if MI opcode is not the S form there must be neither defs of flags
2363/// nor uses of flags between MI and CmpInstr.
2364/// - and, C is not used after CmpInstr; CmpInstr's C is from adds/subs #0 on
2365/// SrcReg and can differ from MI (e.g. carry out of ADCS/SBCS).
2366/// - and, V is not used after CmpInstr unless MI is AND/BIC (V cleared) or MI
2367/// has NoSWrap (overflow is poison and the fold is still safe).
2369 const TargetRegisterInfo &TRI) {
2370 // MI is an opcode sForm maps (add/sub/adc/sbc/and/bic and their S forms).
2371 assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END);
2372
2373 const unsigned CmpOpcode = CmpInstr.getOpcode();
2374 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
2375 return false;
2376
2377 assert((CmpInstr.getOperand(2).isImm() &&
2378 CmpInstr.getOperand(2).getImm() == 0) &&
2379 "Caller guarantees that CmpInstr compares with constant 0");
2380
2381 std::optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
2382 if (!NZVCUsed || NZVCUsed->C)
2383 return false;
2384
2385 // CmpInstr is ADDS/SUBS with immediate 0 on SrcReg (compare SrcReg to zero).
2386 // After the fold, users see NZCV from MI (or its S form), not from CmpInstr.
2387 // N/Z match CmpInstr for the value in SrcReg; C/V need not match in general
2388 // (e.g. ADCS vs adds #0), so we require C unused after CmpInstr and gate V
2389 // as below. NoSWrap makes signed overflow poison; AND/BIC clear V.
2390 if (NZVCUsed->V && !MI.getFlag(MachineInstr::NoSWrap) && !isANDOpcode(MI))
2391 return false;
2392
2393 AccessKind AccessToCheck = AK_Write;
2394 if (sForm(MI) != MI.getOpcode())
2395 AccessToCheck = AK_All;
2396 return !areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AccessToCheck);
2397}
2398
2399/// Substitute an instruction comparing to zero with another instruction
2400/// which produces needed condition flags.
2401///
2402/// Return true on success.
2403bool AArch64InstrInfo::substituteCmpToZero(
2404 MachineInstr &CmpInstr, unsigned SrcReg,
2405 const MachineRegisterInfo &MRI) const {
2406 // Get the unique definition of SrcReg.
2407 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2408 if (!MI)
2409 return false;
2410
2411 const TargetRegisterInfo &TRI = getRegisterInfo();
2412
2413 unsigned NewOpc = sForm(*MI);
2414 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2415 return false;
2416
2417 if (!canInstrSubstituteCmpInstr(*MI, CmpInstr, TRI))
2418 return false;
2419
2420 // Update the instruction to set NZCV.
2421 MI->setDesc(get(NewOpc));
2422 CmpInstr.eraseFromParent();
2424 (void)succeeded;
2425 assert(succeeded && "Some operands reg class are incompatible!");
2426 MI->addRegisterDefined(AArch64::NZCV, &TRI);
2427 return true;
2428}
2429
2430/// \returns True if \p CmpInstr can be removed.
2431///
2432/// \p IsInvertCC is true if, after removing \p CmpInstr, condition
2433/// codes used in \p CCUseInstrs must be inverted.
2435 int CmpValue, const TargetRegisterInfo &TRI,
2437 bool &IsInvertCC) {
2438 assert((CmpValue == 0 || CmpValue == 1) &&
2439 "Only comparisons to 0 or 1 considered for removal!");
2440
2441 // MI is 'CSINCWr %vreg, wzr, wzr, <cc>' or 'CSINCXr %vreg, xzr, xzr, <cc>'
2442 unsigned MIOpc = MI.getOpcode();
2443 if (MIOpc == AArch64::CSINCWr) {
2444 if (MI.getOperand(1).getReg() != AArch64::WZR ||
2445 MI.getOperand(2).getReg() != AArch64::WZR)
2446 return false;
2447 } else if (MIOpc == AArch64::CSINCXr) {
2448 if (MI.getOperand(1).getReg() != AArch64::XZR ||
2449 MI.getOperand(2).getReg() != AArch64::XZR)
2450 return false;
2451 } else {
2452 return false;
2453 }
2455 if (MICC == AArch64CC::Invalid)
2456 return false;
2457
2458 // NZCV needs to be defined
2459 if (MI.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) != -1)
2460 return false;
2461
2462 // CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0' or 'SUBS %vreg, 1'
2463 const unsigned CmpOpcode = CmpInstr.getOpcode();
2464 bool IsSubsRegImm = isSUBSRegImm(CmpOpcode);
2465 if (CmpValue && !IsSubsRegImm)
2466 return false;
2467 if (!CmpValue && !IsSubsRegImm && !isADDSRegImm(CmpOpcode))
2468 return false;
2469
2470 // MI conditions allowed: eq, ne, mi, pl
2471 UsedNZCV MIUsedNZCV = getUsedNZCV(MICC);
2472 if (MIUsedNZCV.C || MIUsedNZCV.V)
2473 return false;
2474
2475 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2476 examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
2477 // Condition flags are not used in CmpInstr basic block successors and only
2478 // Z or N flags allowed to be used after CmpInstr within its basic block
2479 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2480 return false;
2481 // Z or N flag used after CmpInstr must correspond to the flag used in MI
2482 if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||
2483 (MIUsedNZCV.N && NZCVUsedAfterCmp->Z))
2484 return false;
2485 // If CmpInstr is comparison to zero MI conditions are limited to eq, ne
2486 if (MIUsedNZCV.N && !CmpValue)
2487 return false;
2488
2489 // There must be no defs of flags between MI and CmpInstr
2490 if (areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AK_Write))
2491 return false;
2492
2493 // Condition code is inverted in the following cases:
2494 // 1. MI condition is ne; CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2495 // 2. MI condition is eq, pl; CmpInstr is 'SUBS %vreg, 1'
2496 IsInvertCC = (CmpValue && (MICC == AArch64CC::EQ || MICC == AArch64CC::PL)) ||
2497 (!CmpValue && MICC == AArch64CC::NE);
2498 return true;
2499}
2500
2501/// Remove comparison in csinc-cmp sequence
2502///
2503/// Examples:
2504/// 1. \code
2505/// csinc w9, wzr, wzr, ne
2506/// cmp w9, #0
2507/// b.eq
2508/// \endcode
2509/// to
2510/// \code
2511/// csinc w9, wzr, wzr, ne
2512/// b.ne
2513/// \endcode
2514///
2515/// 2. \code
2516/// csinc x2, xzr, xzr, mi
2517/// cmp x2, #1
2518/// b.pl
2519/// \endcode
2520/// to
2521/// \code
2522/// csinc x2, xzr, xzr, mi
2523/// b.pl
2524/// \endcode
2525///
2526/// \param CmpInstr comparison instruction
2527/// \return True when comparison removed
2528bool AArch64InstrInfo::removeCmpToZeroOrOne(
2529 MachineInstr &CmpInstr, unsigned SrcReg, int CmpValue,
2530 const MachineRegisterInfo &MRI) const {
2531 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2532 if (!MI)
2533 return false;
2534 const TargetRegisterInfo &TRI = getRegisterInfo();
2535 SmallVector<MachineInstr *, 4> CCUseInstrs;
2536 bool IsInvertCC = false;
2537 if (!canCmpInstrBeRemoved(*MI, CmpInstr, CmpValue, TRI, CCUseInstrs,
2538 IsInvertCC))
2539 return false;
2540 // Make transformation
2541 CmpInstr.eraseFromParent();
2542 if (IsInvertCC) {
2543 // Invert condition codes in CmpInstr CC users
2544 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2545 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2546 assert(Idx >= 0 && "Unexpected instruction using CC.");
2547 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2549 static_cast<AArch64CC::CondCode>(CCOperand.getImm()));
2550 CCOperand.setImm(CCUse);
2551 }
2552 }
2553 return true;
2554}
2555
2556bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
2557 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2558 MI.getOpcode() != AArch64::CATCHRET &&
2559 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2560 return false;
2561
2562 MachineBasicBlock &MBB = *MI.getParent();
2563 auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
2564 auto TRI = Subtarget.getRegisterInfo();
2565 DebugLoc DL = MI.getDebugLoc();
2566
2567 if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2568 // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
2569 // This computes FP - stored_mixed_value to unmix the cookie
2570 Register DstReg = MI.getOperand(0).getReg();
2571 Register SrcReg = MI.getOperand(1).getReg();
2572
2573 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
2574 .addReg(AArch64::FP)
2575 .addReg(SrcReg);
2576
2577 MBB.erase(MI);
2578 return true;
2579 }
2580
2581 if (MI.getOpcode() == AArch64::CATCHRET) {
2582 // Skip to the first instruction before the epilog.
2583 const TargetInstrInfo *TII =
2585 MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
2587 MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
2588 while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
2589 FirstEpilogSEH != MBB.begin())
2590 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2591 if (FirstEpilogSEH != MBB.begin())
2592 FirstEpilogSEH = std::next(FirstEpilogSEH);
2593 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
2594 .addReg(AArch64::X0, RegState::Define)
2595 .addMBB(TargetMBB);
2596 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
2597 .addReg(AArch64::X0, RegState::Define)
2598 .addReg(AArch64::X0)
2599 .addMBB(TargetMBB)
2600 .addImm(0);
2601 TargetMBB->setMachineBlockAddressTaken();
2602 return true;
2603 }
2604
2605 Register Reg = MI.getOperand(0).getReg();
2607 if (M.getStackProtectorGuard() == "sysreg") {
2608 const AArch64SysReg::SysReg *SrcReg =
2609 AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg());
2610 if (!SrcReg)
2611 report_fatal_error("Unknown SysReg for Stack Protector Guard Register");
2612
2613 // mrs xN, sysreg
2614 BuildMI(MBB, MI, DL, get(AArch64::MRS))
2616 .addImm(SrcReg->Encoding);
2617 int Offset = M.getStackProtectorGuardOffset();
2618 if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) {
2619 // ldr xN, [xN, #offset]
2620 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2621 .addDef(Reg)
2623 .addImm(Offset / 8);
2624 } else if (Offset >= -256 && Offset <= 255) {
2625 // ldur xN, [xN, #offset]
2626 BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
2627 .addDef(Reg)
2629 .addImm(Offset);
2630 } else if (Offset >= -4095 && Offset <= 4095) {
2631 if (Offset > 0) {
2632 // add xN, xN, #offset
2633 BuildMI(MBB, MI, DL, get(AArch64::ADDXri))
2634 .addDef(Reg)
2636 .addImm(Offset)
2637 .addImm(0);
2638 } else {
2639 // sub xN, xN, #offset
2640 BuildMI(MBB, MI, DL, get(AArch64::SUBXri))
2641 .addDef(Reg)
2643 .addImm(-Offset)
2644 .addImm(0);
2645 }
2646 // ldr xN, [xN]
2647 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2648 .addDef(Reg)
2650 .addImm(0);
2651 } else {
2652 // Cases that are larger than +/- 4095 and not a multiple of 8, or larger
2653 // than 23760.
2654 // It might be nice to use AArch64::MOVi32imm here, which would get
2655 // expanded in PreSched2 after PostRA, but our lone scratch Reg already
2656 // contains the MRS result. findScratchNonCalleeSaveRegister() in
2657 // AArch64FrameLowering might help us find such a scratch register
2658 // though. If we failed to find a scratch register, we could emit a
2659 // stream of add instructions to build up the immediate. Or, we could try
2660 // to insert a AArch64::MOVi32imm before register allocation so that we
2661 // didn't need to scavenge for a scratch register.
2662 report_fatal_error("Unable to encode Stack Protector Guard Offset");
2663 }
2664 MBB.erase(MI);
2665 return true;
2666 }
2667
2668 const GlobalValue *GV =
2669 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
2670 const TargetMachine &TM = MBB.getParent()->getTarget();
2671 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2672 const unsigned char MO_NC = AArch64II::MO_NC;
2673
2674 unsigned GuardWidth = M.getStackProtectorGuardValueWidth().value_or(
2675 Subtarget.isTargetILP32() ? 4 : 8);
2676 if (GuardWidth != 4 && GuardWidth != 8)
2677 report_fatal_error("Unsupported stack protector value width");
2678 if ((OpFlags & AArch64II::MO_GOT) != 0) {
2679 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
2680 .addGlobalAddress(GV, 0, OpFlags);
2681 if (GuardWidth == 4) {
2682 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2683 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2684 .addDef(Reg32, RegState::Dead)
2686 .addImm(0)
2687 .addMemOperand(*MI.memoperands_begin())
2689 } else {
2690 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2692 .addImm(0)
2693 .addMemOperand(*MI.memoperands_begin());
2694 }
2695 } else if (TM.getCodeModel() == CodeModel::Large) {
2696 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
2697 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
2698 .addImm(0);
2699 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2701 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC)
2702 .addImm(16);
2703 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2705 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC)
2706 .addImm(32);
2707 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2710 .addImm(48);
2711 if (GuardWidth == 4) {
2712 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2713 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2714 .addDef(Reg32, RegState::Dead)
2716 .addImm(0)
2717 .addMemOperand(*MI.memoperands_begin())
2719 } else {
2720 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2722 .addImm(0)
2723 .addMemOperand(*MI.memoperands_begin());
2724 }
2725 } else {
2726 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
2727 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
2728 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
2729 if (GuardWidth == 4) {
2730 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2731 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2732 .addDef(Reg32, RegState::Dead)
2734 .addGlobalAddress(GV, 0, LoFlags)
2735 .addMemOperand(*MI.memoperands_begin())
2737 } else {
2738 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2740 .addGlobalAddress(GV, 0, LoFlags)
2741 .addMemOperand(*MI.memoperands_begin());
2742 }
2743 }
2744 // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
2745 // we use sub instruction to mix the cookie on aarch64.
2746 // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
2747 // the final frame pointer value.
2748 if (Subtarget.getTargetTriple().isOSMSVCRT())
2749 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
2750 .addReg(AArch64::FP)
2752
2753 MBB.erase(MI);
2754
2755 return true;
2756}
2757
2758// Return true if this instruction simply sets its single destination register
2759// to zero. This is equivalent to a register rename of the zero-register.
2761 switch (MI.getOpcode()) {
2762 default:
2763 break;
2764 case AArch64::MOVZWi:
2765 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
2766 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
2767 assert(MI.getDesc().getNumOperands() == 3 &&
2768 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
2769 return true;
2770 }
2771 break;
2772 case AArch64::ANDWri: // and Rd, Rzr, #imm
2773 return MI.getOperand(1).getReg() == AArch64::WZR;
2774 case AArch64::ANDXri:
2775 return MI.getOperand(1).getReg() == AArch64::XZR;
2776 case TargetOpcode::COPY:
2777 return MI.getOperand(1).getReg() == AArch64::WZR;
2778 }
2779 return false;
2780}
2781
2782// Return true if this instruction simply renames a general register without
2783// modifying bits.
2785 switch (MI.getOpcode()) {
2786 default:
2787 break;
2788 case TargetOpcode::COPY: {
2789 // GPR32 copies will by lowered to ORRXrs
2790 Register DstReg = MI.getOperand(0).getReg();
2791 return (AArch64::GPR32RegClass.contains(DstReg) ||
2792 AArch64::GPR64RegClass.contains(DstReg));
2793 }
2794 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
2795 if (MI.getOperand(1).getReg() == AArch64::XZR) {
2796 assert(MI.getDesc().getNumOperands() == 4 &&
2797 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
2798 return true;
2799 }
2800 break;
2801 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
2802 if (MI.getOperand(2).getImm() == 0) {
2803 assert(MI.getDesc().getNumOperands() == 4 &&
2804 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
2805 return true;
2806 }
2807 break;
2808 }
2809 return false;
2810}
2811
2812// Return true if this instruction simply renames a general register without
2813// modifying bits.
2815 switch (MI.getOpcode()) {
2816 default:
2817 break;
2818 case TargetOpcode::COPY: {
2819 Register DstReg = MI.getOperand(0).getReg();
2820 return AArch64::FPR128RegClass.contains(DstReg);
2821 }
2822 case AArch64::ORRv16i8:
2823 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
2824 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
2825 "invalid ORRv16i8 operands");
2826 return true;
2827 }
2828 break;
2829 }
2830 return false;
2831}
2832
2833static bool isFrameLoadOpcode(int Opcode) {
2834 switch (Opcode) {
2835 default:
2836 return false;
2837 case AArch64::LDRWui:
2838 case AArch64::LDRXui:
2839 case AArch64::LDRBui:
2840 case AArch64::LDRHui:
2841 case AArch64::LDRSui:
2842 case AArch64::LDRDui:
2843 case AArch64::LDRQui:
2844 case AArch64::LDR_PXI:
2845 return true;
2846 }
2847}
2848
2850 int &FrameIndex) const {
2851 if (!isFrameLoadOpcode(MI.getOpcode()))
2852 return Register();
2853
2854 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2855 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2856 FrameIndex = MI.getOperand(1).getIndex();
2857 return MI.getOperand(0).getReg();
2858 }
2859 return Register();
2860}
2861
2862static bool isFrameStoreOpcode(int Opcode) {
2863 switch (Opcode) {
2864 default:
2865 return false;
2866 case AArch64::STRWui:
2867 case AArch64::STRXui:
2868 case AArch64::STRBui:
2869 case AArch64::STRHui:
2870 case AArch64::STRSui:
2871 case AArch64::STRDui:
2872 case AArch64::STRQui:
2873 case AArch64::STR_PXI:
2874 return true;
2875 }
2876}
2877
2879 int &FrameIndex) const {
2880 if (!isFrameStoreOpcode(MI.getOpcode()))
2881 return Register();
2882
2883 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2884 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2885 FrameIndex = MI.getOperand(1).getIndex();
2886 return MI.getOperand(0).getReg();
2887 }
2888 return Register();
2889}
2890
2892 int &FrameIndex) const {
2893 if (!isFrameStoreOpcode(MI.getOpcode()))
2894 return Register();
2895
2896 if (Register Reg = isStoreToStackSlot(MI, FrameIndex))
2897 return Reg;
2898
2900 if (hasStoreToStackSlot(MI, Accesses)) {
2901 if (Accesses.size() > 1)
2902 return Register();
2903
2904 FrameIndex =
2905 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2906 ->getFrameIndex();
2907 return MI.getOperand(0).getReg();
2908 }
2909 return Register();
2910}
2911
2913 int &FrameIndex) const {
2914 if (!isFrameLoadOpcode(MI.getOpcode()))
2915 return Register();
2916
2917 if (Register Reg = isLoadFromStackSlot(MI, FrameIndex))
2918 return Reg;
2919
2921 if (hasLoadFromStackSlot(MI, Accesses)) {
2922 if (Accesses.size() > 1)
2923 return Register();
2924
2925 FrameIndex =
2926 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2927 ->getFrameIndex();
2928 return MI.getOperand(0).getReg();
2929 }
2930 return Register();
2931}
2932
2933/// Check all MachineMemOperands for a hint to suppress pairing.
2935 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2936 return MMO->getFlags() & MOSuppressPair;
2937 });
2938}
2939
2940/// Set a flag on the first MachineMemOperand to suppress pairing.
2942 if (MI.memoperands_empty())
2943 return;
2944 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
2945}
2946
2947/// Check all MachineMemOperands for a hint that the load/store is strided.
2949 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2950 return MMO->getFlags() & MOStridedAccess;
2951 });
2952}
2953
2955 switch (Opc) {
2956 default:
2957 return false;
2958 case AArch64::STURSi:
2959 case AArch64::STRSpre:
2960 case AArch64::STURDi:
2961 case AArch64::STRDpre:
2962 case AArch64::STURQi:
2963 case AArch64::STRQpre:
2964 case AArch64::STURBBi:
2965 case AArch64::STURHHi:
2966 case AArch64::STURWi:
2967 case AArch64::STRWpre:
2968 case AArch64::STURXi:
2969 case AArch64::STRXpre:
2970 case AArch64::LDURSi:
2971 case AArch64::LDRSpre:
2972 case AArch64::LDURDi:
2973 case AArch64::LDRDpre:
2974 case AArch64::LDURQi:
2975 case AArch64::LDRQpre:
2976 case AArch64::LDURWi:
2977 case AArch64::LDRWpre:
2978 case AArch64::LDURXi:
2979 case AArch64::LDRXpre:
2980 case AArch64::LDRSWpre:
2981 case AArch64::LDURSWi:
2982 case AArch64::LDURHHi:
2983 case AArch64::LDURBBi:
2984 case AArch64::LDURSBWi:
2985 case AArch64::LDURSHWi:
2986 return true;
2987 }
2988}
2989
2990std::optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) {
2991 switch (Opc) {
2992 default: return {};
2993 case AArch64::PRFMui: return AArch64::PRFUMi;
2994 case AArch64::LDRXui: return AArch64::LDURXi;
2995 case AArch64::LDRWui: return AArch64::LDURWi;
2996 case AArch64::LDRBui: return AArch64::LDURBi;
2997 case AArch64::LDRHui: return AArch64::LDURHi;
2998 case AArch64::LDRSui: return AArch64::LDURSi;
2999 case AArch64::LDRDui: return AArch64::LDURDi;
3000 case AArch64::LDRQui: return AArch64::LDURQi;
3001 case AArch64::LDRBBui: return AArch64::LDURBBi;
3002 case AArch64::LDRHHui: return AArch64::LDURHHi;
3003 case AArch64::LDRSBXui: return AArch64::LDURSBXi;
3004 case AArch64::LDRSBWui: return AArch64::LDURSBWi;
3005 case AArch64::LDRSHXui: return AArch64::LDURSHXi;
3006 case AArch64::LDRSHWui: return AArch64::LDURSHWi;
3007 case AArch64::LDRSWui: return AArch64::LDURSWi;
3008 case AArch64::STRXui: return AArch64::STURXi;
3009 case AArch64::STRWui: return AArch64::STURWi;
3010 case AArch64::STRBui: return AArch64::STURBi;
3011 case AArch64::STRHui: return AArch64::STURHi;
3012 case AArch64::STRSui: return AArch64::STURSi;
3013 case AArch64::STRDui: return AArch64::STURDi;
3014 case AArch64::STRQui: return AArch64::STURQi;
3015 case AArch64::STRBBui: return AArch64::STURBBi;
3016 case AArch64::STRHHui: return AArch64::STURHHi;
3017 }
3018}
3019
3021 switch (Opc) {
3022 default:
3023 llvm_unreachable("Unhandled Opcode in getLoadStoreImmIdx");
3024 case AArch64::ADDG:
3025 case AArch64::LDAPURBi:
3026 case AArch64::LDAPURHi:
3027 case AArch64::LDAPURi:
3028 case AArch64::LDAPURSBWi:
3029 case AArch64::LDAPURSBXi:
3030 case AArch64::LDAPURSHWi:
3031 case AArch64::LDAPURSHXi:
3032 case AArch64::LDAPURSWi:
3033 case AArch64::LDAPURXi:
3034 case AArch64::LDR_PPXI:
3035 case AArch64::LDR_PXI:
3036 case AArch64::LDR_ZXI:
3037 case AArch64::LDR_ZZXI:
3038 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3039 case AArch64::LDR_ZZZXI:
3040 case AArch64::LDR_ZZZZXI:
3041 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3042 case AArch64::LDRBBui:
3043 case AArch64::LDRBui:
3044 case AArch64::LDRDui:
3045 case AArch64::LDRHHui:
3046 case AArch64::LDRHui:
3047 case AArch64::LDRQui:
3048 case AArch64::LDRSBWui:
3049 case AArch64::LDRSBXui:
3050 case AArch64::LDRSHWui:
3051 case AArch64::LDRSHXui:
3052 case AArch64::LDRSui:
3053 case AArch64::LDRSWui:
3054 case AArch64::LDRWui:
3055 case AArch64::LDRXui:
3056 case AArch64::LDURBBi:
3057 case AArch64::LDURBi:
3058 case AArch64::LDURDi:
3059 case AArch64::LDURHHi:
3060 case AArch64::LDURHi:
3061 case AArch64::LDURQi:
3062 case AArch64::LDURSBWi:
3063 case AArch64::LDURSBXi:
3064 case AArch64::LDURSHWi:
3065 case AArch64::LDURSHXi:
3066 case AArch64::LDURSi:
3067 case AArch64::LDURSWi:
3068 case AArch64::LDURWi:
3069 case AArch64::LDURXi:
3070 case AArch64::PRFMui:
3071 case AArch64::PRFUMi:
3072 case AArch64::ST2Gi:
3073 case AArch64::STGi:
3074 case AArch64::STLURBi:
3075 case AArch64::STLURHi:
3076 case AArch64::STLURWi:
3077 case AArch64::STLURXi:
3078 case AArch64::StoreSwiftAsyncContext:
3079 case AArch64::STR_PPXI:
3080 case AArch64::STR_PXI:
3081 case AArch64::STR_ZXI:
3082 case AArch64::STR_ZZXI:
3083 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3084 case AArch64::STR_ZZZXI:
3085 case AArch64::STR_ZZZZXI:
3086 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3087 case AArch64::STRBBui:
3088 case AArch64::STRBui:
3089 case AArch64::STRDui:
3090 case AArch64::STRHHui:
3091 case AArch64::STRHui:
3092 case AArch64::STRQui:
3093 case AArch64::STRSui:
3094 case AArch64::STRWui:
3095 case AArch64::STRXui:
3096 case AArch64::STURBBi:
3097 case AArch64::STURBi:
3098 case AArch64::STURDi:
3099 case AArch64::STURHHi:
3100 case AArch64::STURHi:
3101 case AArch64::STURQi:
3102 case AArch64::STURSi:
3103 case AArch64::STURWi:
3104 case AArch64::STURXi:
3105 case AArch64::STZ2Gi:
3106 case AArch64::STZGi:
3107 case AArch64::TAGPstack:
3108 return 2;
3109 case AArch64::LD1B_D_IMM:
3110 case AArch64::LD1B_H_IMM:
3111 case AArch64::LD1B_IMM:
3112 case AArch64::LD1B_S_IMM:
3113 case AArch64::LD1D_IMM:
3114 case AArch64::LD1H_D_IMM:
3115 case AArch64::LD1H_IMM:
3116 case AArch64::LD1H_S_IMM:
3117 case AArch64::LD1RB_D_IMM:
3118 case AArch64::LD1RB_H_IMM:
3119 case AArch64::LD1RB_IMM:
3120 case AArch64::LD1RB_S_IMM:
3121 case AArch64::LD1RD_IMM:
3122 case AArch64::LD1RH_D_IMM:
3123 case AArch64::LD1RH_IMM:
3124 case AArch64::LD1RH_S_IMM:
3125 case AArch64::LD1RSB_D_IMM:
3126 case AArch64::LD1RSB_H_IMM:
3127 case AArch64::LD1RSB_S_IMM:
3128 case AArch64::LD1RSH_D_IMM:
3129 case AArch64::LD1RSH_S_IMM:
3130 case AArch64::LD1RSW_IMM:
3131 case AArch64::LD1RW_D_IMM:
3132 case AArch64::LD1RW_IMM:
3133 case AArch64::LD1SB_D_IMM:
3134 case AArch64::LD1SB_H_IMM:
3135 case AArch64::LD1SB_S_IMM:
3136 case AArch64::LD1SH_D_IMM:
3137 case AArch64::LD1SH_S_IMM:
3138 case AArch64::LD1SW_D_IMM:
3139 case AArch64::LD1W_D_IMM:
3140 case AArch64::LD1W_IMM:
3141 case AArch64::LD2B_IMM:
3142 case AArch64::LD2D_IMM:
3143 case AArch64::LD2H_IMM:
3144 case AArch64::LD2W_IMM:
3145 case AArch64::LD3B_IMM:
3146 case AArch64::LD3D_IMM:
3147 case AArch64::LD3H_IMM:
3148 case AArch64::LD3W_IMM:
3149 case AArch64::LD4B_IMM:
3150 case AArch64::LD4D_IMM:
3151 case AArch64::LD4H_IMM:
3152 case AArch64::LD4W_IMM:
3153 case AArch64::LDG:
3154 case AArch64::LDNF1B_D_IMM:
3155 case AArch64::LDNF1B_H_IMM:
3156 case AArch64::LDNF1B_IMM:
3157 case AArch64::LDNF1B_S_IMM:
3158 case AArch64::LDNF1D_IMM:
3159 case AArch64::LDNF1H_D_IMM:
3160 case AArch64::LDNF1H_IMM:
3161 case AArch64::LDNF1H_S_IMM:
3162 case AArch64::LDNF1SB_D_IMM:
3163 case AArch64::LDNF1SB_H_IMM:
3164 case AArch64::LDNF1SB_S_IMM:
3165 case AArch64::LDNF1SH_D_IMM:
3166 case AArch64::LDNF1SH_S_IMM:
3167 case AArch64::LDNF1SW_D_IMM:
3168 case AArch64::LDNF1W_D_IMM:
3169 case AArch64::LDNF1W_IMM:
3170 case AArch64::LDNPDi:
3171 case AArch64::LDNPQi:
3172 case AArch64::LDNPSi:
3173 case AArch64::LDNPWi:
3174 case AArch64::LDNPXi:
3175 case AArch64::LDNT1B_ZRI:
3176 case AArch64::LDNT1D_ZRI:
3177 case AArch64::LDNT1H_ZRI:
3178 case AArch64::LDNT1W_ZRI:
3179 case AArch64::LDPDi:
3180 case AArch64::LDPQi:
3181 case AArch64::LDPSi:
3182 case AArch64::LDPWi:
3183 case AArch64::LDPXi:
3184 case AArch64::LDRBBpost:
3185 case AArch64::LDRBBpre:
3186 case AArch64::LDRBpost:
3187 case AArch64::LDRBpre:
3188 case AArch64::LDRDpost:
3189 case AArch64::LDRDpre:
3190 case AArch64::LDRHHpost:
3191 case AArch64::LDRHHpre:
3192 case AArch64::LDRHpost:
3193 case AArch64::LDRHpre:
3194 case AArch64::LDRQpost:
3195 case AArch64::LDRQpre:
3196 case AArch64::LDRSpost:
3197 case AArch64::LDRSpre:
3198 case AArch64::LDRWpost:
3199 case AArch64::LDRWpre:
3200 case AArch64::LDRXpost:
3201 case AArch64::LDRXpre:
3202 case AArch64::ST1B_D_IMM:
3203 case AArch64::ST1B_H_IMM:
3204 case AArch64::ST1B_IMM:
3205 case AArch64::ST1B_S_IMM:
3206 case AArch64::ST1D_IMM:
3207 case AArch64::ST1H_D_IMM:
3208 case AArch64::ST1H_IMM:
3209 case AArch64::ST1H_S_IMM:
3210 case AArch64::ST1W_D_IMM:
3211 case AArch64::ST1W_IMM:
3212 case AArch64::ST2B_IMM:
3213 case AArch64::ST2D_IMM:
3214 case AArch64::ST2H_IMM:
3215 case AArch64::ST2W_IMM:
3216 case AArch64::ST3B_IMM:
3217 case AArch64::ST3D_IMM:
3218 case AArch64::ST3H_IMM:
3219 case AArch64::ST3W_IMM:
3220 case AArch64::ST4B_IMM:
3221 case AArch64::ST4D_IMM:
3222 case AArch64::ST4H_IMM:
3223 case AArch64::ST4W_IMM:
3224 case AArch64::STGPi:
3225 case AArch64::STGPreIndex:
3226 case AArch64::STZGPreIndex:
3227 case AArch64::ST2GPreIndex:
3228 case AArch64::STZ2GPreIndex:
3229 case AArch64::STGPostIndex:
3230 case AArch64::STZGPostIndex:
3231 case AArch64::ST2GPostIndex:
3232 case AArch64::STZ2GPostIndex:
3233 case AArch64::STNPDi:
3234 case AArch64::STNPQi:
3235 case AArch64::STNPSi:
3236 case AArch64::STNPWi:
3237 case AArch64::STNPXi:
3238 case AArch64::STNT1B_ZRI:
3239 case AArch64::STNT1D_ZRI:
3240 case AArch64::STNT1H_ZRI:
3241 case AArch64::STNT1W_ZRI:
3242 case AArch64::STPDi:
3243 case AArch64::STPQi:
3244 case AArch64::STPSi:
3245 case AArch64::STPWi:
3246 case AArch64::STPXi:
3247 case AArch64::STRBBpost:
3248 case AArch64::STRBBpre:
3249 case AArch64::STRBpost:
3250 case AArch64::STRBpre:
3251 case AArch64::STRDpost:
3252 case AArch64::STRDpre:
3253 case AArch64::STRHHpost:
3254 case AArch64::STRHHpre:
3255 case AArch64::STRHpost:
3256 case AArch64::STRHpre:
3257 case AArch64::STRQpost:
3258 case AArch64::STRQpre:
3259 case AArch64::STRSpost:
3260 case AArch64::STRSpre:
3261 case AArch64::STRWpost:
3262 case AArch64::STRWpre:
3263 case AArch64::STRXpost:
3264 case AArch64::STRXpre:
3265 case AArch64::LD1B_2Z_IMM:
3266 case AArch64::LD1B_2Z_STRIDED_IMM:
3267 case AArch64::LD1H_2Z_IMM:
3268 case AArch64::LD1H_2Z_STRIDED_IMM:
3269 case AArch64::LD1W_2Z_IMM:
3270 case AArch64::LD1W_2Z_STRIDED_IMM:
3271 case AArch64::LD1D_2Z_IMM:
3272 case AArch64::LD1D_2Z_STRIDED_IMM:
3273 case AArch64::LD1B_4Z_IMM:
3274 case AArch64::LD1B_4Z_STRIDED_IMM:
3275 case AArch64::LD1H_4Z_IMM:
3276 case AArch64::LD1H_4Z_STRIDED_IMM:
3277 case AArch64::LD1W_4Z_IMM:
3278 case AArch64::LD1W_4Z_STRIDED_IMM:
3279 case AArch64::LD1D_4Z_IMM:
3280 case AArch64::LD1D_4Z_STRIDED_IMM:
3281 case AArch64::LD1B_2Z_IMM_PSEUDO:
3282 case AArch64::LD1H_2Z_IMM_PSEUDO:
3283 case AArch64::LD1W_2Z_IMM_PSEUDO:
3284 case AArch64::LD1D_2Z_IMM_PSEUDO:
3285 case AArch64::LD1B_4Z_IMM_PSEUDO:
3286 case AArch64::LD1H_4Z_IMM_PSEUDO:
3287 case AArch64::LD1W_4Z_IMM_PSEUDO:
3288 case AArch64::LD1D_4Z_IMM_PSEUDO:
3289 case AArch64::ST1B_2Z_IMM:
3290 case AArch64::ST1B_2Z_STRIDED_IMM:
3291 case AArch64::ST1H_2Z_IMM:
3292 case AArch64::ST1H_2Z_STRIDED_IMM:
3293 case AArch64::ST1W_2Z_IMM:
3294 case AArch64::ST1W_2Z_STRIDED_IMM:
3295 case AArch64::ST1D_2Z_IMM:
3296 case AArch64::ST1D_2Z_STRIDED_IMM:
3297 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3298 case AArch64::LDNT1B_2Z_IMM:
3299 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3300 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3301 case AArch64::LDNT1H_2Z_IMM:
3302 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3303 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3304 case AArch64::LDNT1W_2Z_IMM:
3305 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3306 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3307 case AArch64::LDNT1D_2Z_IMM:
3308 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3309 case AArch64::STNT1B_2Z_IMM:
3310 case AArch64::STNT1B_2Z_STRIDED_IMM:
3311 case AArch64::STNT1H_2Z_IMM:
3312 case AArch64::STNT1H_2Z_STRIDED_IMM:
3313 case AArch64::STNT1W_2Z_IMM:
3314 case AArch64::STNT1W_2Z_STRIDED_IMM:
3315 case AArch64::STNT1D_2Z_IMM:
3316 case AArch64::STNT1D_2Z_STRIDED_IMM:
3317 case AArch64::ST1B_2Z_IMM_PSEUDO:
3318 case AArch64::ST1H_2Z_IMM_PSEUDO:
3319 case AArch64::ST1W_2Z_IMM_PSEUDO:
3320 case AArch64::ST1D_2Z_IMM_PSEUDO:
3321 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3322 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3323 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3324 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3325 case AArch64::ST1B_4Z_IMM:
3326 case AArch64::ST1B_4Z_STRIDED_IMM:
3327 case AArch64::ST1H_4Z_IMM:
3328 case AArch64::ST1H_4Z_STRIDED_IMM:
3329 case AArch64::ST1W_4Z_IMM:
3330 case AArch64::ST1W_4Z_STRIDED_IMM:
3331 case AArch64::ST1D_4Z_IMM:
3332 case AArch64::ST1D_4Z_STRIDED_IMM:
3333 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3334 case AArch64::LDNT1B_4Z_IMM:
3335 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3336 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3337 case AArch64::LDNT1H_4Z_IMM:
3338 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3339 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3340 case AArch64::LDNT1W_4Z_IMM:
3341 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3342 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3343 case AArch64::LDNT1D_4Z_IMM:
3344 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3345 case AArch64::STNT1B_4Z_IMM:
3346 case AArch64::STNT1B_4Z_STRIDED_IMM:
3347 case AArch64::STNT1H_4Z_IMM:
3348 case AArch64::STNT1H_4Z_STRIDED_IMM:
3349 case AArch64::STNT1W_4Z_IMM:
3350 case AArch64::STNT1W_4Z_STRIDED_IMM:
3351 case AArch64::STNT1D_4Z_IMM:
3352 case AArch64::STNT1D_4Z_STRIDED_IMM:
3353 case AArch64::ST1B_4Z_IMM_PSEUDO:
3354 case AArch64::ST1H_4Z_IMM_PSEUDO:
3355 case AArch64::ST1W_4Z_IMM_PSEUDO:
3356 case AArch64::ST1D_4Z_IMM_PSEUDO:
3357 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3358 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3359 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3360 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3361 return 3;
3362 case AArch64::LDPDpost:
3363 case AArch64::LDPDpre:
3364 case AArch64::LDPQpost:
3365 case AArch64::LDPQpre:
3366 case AArch64::LDPSpost:
3367 case AArch64::LDPSpre:
3368 case AArch64::LDPWpost:
3369 case AArch64::LDPWpre:
3370 case AArch64::LDPXpost:
3371 case AArch64::LDPXpre:
3372 case AArch64::STGPpre:
3373 case AArch64::STGPpost:
3374 case AArch64::STPDpost:
3375 case AArch64::STPDpre:
3376 case AArch64::STPQpost:
3377 case AArch64::STPQpre:
3378 case AArch64::STPSpost:
3379 case AArch64::STPSpre:
3380 case AArch64::STPWpost:
3381 case AArch64::STPWpre:
3382 case AArch64::STPXpost:
3383 case AArch64::STPXpre:
3384 return 4;
3385 }
3386}
3387
3389 switch (MI.getOpcode()) {
3390 default:
3391 return false;
3392 // Scaled instructions.
3393 case AArch64::STRSui:
3394 case AArch64::STRDui:
3395 case AArch64::STRQui:
3396 case AArch64::STRXui:
3397 case AArch64::STRWui:
3398 case AArch64::LDRSui:
3399 case AArch64::LDRDui:
3400 case AArch64::LDRQui:
3401 case AArch64::LDRXui:
3402 case AArch64::LDRWui:
3403 case AArch64::LDRSWui:
3404 // Unscaled instructions.
3405 case AArch64::STURSi:
3406 case AArch64::STRSpre:
3407 case AArch64::STURDi:
3408 case AArch64::STRDpre:
3409 case AArch64::STURQi:
3410 case AArch64::STRQpre:
3411 case AArch64::STURWi:
3412 case AArch64::STRWpre:
3413 case AArch64::STURXi:
3414 case AArch64::STRXpre:
3415 case AArch64::LDURSi:
3416 case AArch64::LDRSpre:
3417 case AArch64::LDURDi:
3418 case AArch64::LDRDpre:
3419 case AArch64::LDURQi:
3420 case AArch64::LDRQpre:
3421 case AArch64::LDURWi:
3422 case AArch64::LDRWpre:
3423 case AArch64::LDURXi:
3424 case AArch64::LDRXpre:
3425 case AArch64::LDURSWi:
3426 case AArch64::LDRSWpre:
3427 // SVE instructions.
3428 case AArch64::LDR_ZXI:
3429 case AArch64::STR_ZXI:
3430 return true;
3431 }
3432}
3433
3435 switch (MI.getOpcode()) {
3436 default:
3437 assert((!MI.isCall() || !MI.isReturn()) &&
3438 "Unexpected instruction - was a new tail call opcode introduced?");
3439 return false;
3440 case AArch64::TCRETURNdi:
3441 case AArch64::TCRETURNri:
3442 case AArch64::TCRETURNrix16x17:
3443 case AArch64::TCRETURNrix17:
3444 case AArch64::TCRETURNrinotx16:
3445 case AArch64::TCRETURNriALL:
3446 case AArch64::AUTH_TCRETURN:
3447 case AArch64::AUTH_TCRETURN_BTI:
3448 return true;
3449 }
3450}
3451
3453 switch (Opc) {
3454 default:
3455 llvm_unreachable("Opcode has no flag setting equivalent!");
3456 // 32-bit cases:
3457 case AArch64::ADDWri:
3458 return AArch64::ADDSWri;
3459 case AArch64::ADDWrr:
3460 return AArch64::ADDSWrr;
3461 case AArch64::ADDWrs:
3462 return AArch64::ADDSWrs;
3463 case AArch64::ADDWrx:
3464 return AArch64::ADDSWrx;
3465 case AArch64::ANDWri:
3466 return AArch64::ANDSWri;
3467 case AArch64::ANDWrr:
3468 return AArch64::ANDSWrr;
3469 case AArch64::ANDWrs:
3470 return AArch64::ANDSWrs;
3471 case AArch64::BICWrr:
3472 return AArch64::BICSWrr;
3473 case AArch64::BICWrs:
3474 return AArch64::BICSWrs;
3475 case AArch64::SUBWri:
3476 return AArch64::SUBSWri;
3477 case AArch64::SUBWrr:
3478 return AArch64::SUBSWrr;
3479 case AArch64::SUBWrs:
3480 return AArch64::SUBSWrs;
3481 case AArch64::SUBWrx:
3482 return AArch64::SUBSWrx;
3483 // 64-bit cases:
3484 case AArch64::ADDXri:
3485 return AArch64::ADDSXri;
3486 case AArch64::ADDXrr:
3487 return AArch64::ADDSXrr;
3488 case AArch64::ADDXrs:
3489 return AArch64::ADDSXrs;
3490 case AArch64::ADDXrx:
3491 return AArch64::ADDSXrx;
3492 case AArch64::ANDXri:
3493 return AArch64::ANDSXri;
3494 case AArch64::ANDXrr:
3495 return AArch64::ANDSXrr;
3496 case AArch64::ANDXrs:
3497 return AArch64::ANDSXrs;
3498 case AArch64::BICXrr:
3499 return AArch64::BICSXrr;
3500 case AArch64::BICXrs:
3501 return AArch64::BICSXrs;
3502 case AArch64::SUBXri:
3503 return AArch64::SUBSXri;
3504 case AArch64::SUBXrr:
3505 return AArch64::SUBSXrr;
3506 case AArch64::SUBXrs:
3507 return AArch64::SUBSXrs;
3508 case AArch64::SUBXrx:
3509 return AArch64::SUBSXrx;
3510 // SVE instructions:
3511 case AArch64::AND_PPzPP:
3512 return AArch64::ANDS_PPzPP;
3513 case AArch64::BIC_PPzPP:
3514 return AArch64::BICS_PPzPP;
3515 case AArch64::EOR_PPzPP:
3516 return AArch64::EORS_PPzPP;
3517 case AArch64::NAND_PPzPP:
3518 return AArch64::NANDS_PPzPP;
3519 case AArch64::NOR_PPzPP:
3520 return AArch64::NORS_PPzPP;
3521 case AArch64::ORN_PPzPP:
3522 return AArch64::ORNS_PPzPP;
3523 case AArch64::ORR_PPzPP:
3524 return AArch64::ORRS_PPzPP;
3525 case AArch64::BRKA_PPzP:
3526 return AArch64::BRKAS_PPzP;
3527 case AArch64::BRKPA_PPzPP:
3528 return AArch64::BRKPAS_PPzPP;
3529 case AArch64::BRKB_PPzP:
3530 return AArch64::BRKBS_PPzP;
3531 case AArch64::BRKPB_PPzPP:
3532 return AArch64::BRKPBS_PPzPP;
3533 case AArch64::BRKN_PPzP:
3534 return AArch64::BRKNS_PPzP;
3535 case AArch64::RDFFR_PPz:
3536 return AArch64::RDFFRS_PPz;
3537 case AArch64::PTRUE_B:
3538 return AArch64::PTRUES_B;
3539 }
3540}
3541
3542// Is this a candidate for ld/st merging or pairing? For example, we don't
3543// touch volatiles or load/stores that have a hint to avoid pair formation.
3545
3546 bool IsPreLdSt = isPreLdSt(MI);
3547
3548 // If this is a volatile load/store, don't mess with it.
3549 if (MI.hasOrderedMemoryRef())
3550 return false;
3551
3552 // Make sure this is a reg/fi+imm (as opposed to an address reloc).
3553 // For Pre-inc LD/ST, the operand is shifted by one.
3554 assert((MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3555 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3556 "Expected a reg or frame index operand.");
3557
3558 // For Pre-indexed addressing quadword instructions, the third operand is the
3559 // immediate value.
3560 bool IsImmPreLdSt = IsPreLdSt && MI.getOperand(3).isImm();
3561
3562 if (!MI.getOperand(2).isImm() && !IsImmPreLdSt)
3563 return false;
3564
3565 // Can't merge/pair if the instruction modifies the base register.
3566 // e.g., ldr x0, [x0]
3567 // This case will never occur with an FI base.
3568 // However, if the instruction is an LDR<S,D,Q,W,X,SW>pre or
3569 // STR<S,D,Q,W,X>pre, it can be merged.
3570 // For example:
3571 // ldr q0, [x11, #32]!
3572 // ldr q1, [x11, #16]
3573 // to
3574 // ldp q0, q1, [x11, #32]!
3575 if (MI.getOperand(1).isReg() && !IsPreLdSt) {
3576 Register BaseReg = MI.getOperand(1).getReg();
3578 if (MI.modifiesRegister(BaseReg, TRI))
3579 return false;
3580 }
3581
3582 // Pairing SVE fills/spills is only valid for little-endian targets that
3583 // implement VLS 128.
3584 switch (MI.getOpcode()) {
3585 default:
3586 break;
3587 case AArch64::LDR_ZXI:
3588 case AArch64::STR_ZXI:
3589 if (!Subtarget.isLittleEndian() ||
3590 Subtarget.getSVEVectorSizeInBits() != 128)
3591 return false;
3592 }
3593
3594 // Check if this load/store has a hint to avoid pair formation.
3595 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
3597 return false;
3598
3599 // Do not pair any callee-save store/reload instructions in the
3600 // prologue/epilogue if the CFI information encoded the operations as separate
3601 // instructions, as that will cause the size of the actual prologue to mismatch
3602 // with the prologue size recorded in the Windows CFI.
3603 const MCAsmInfo &MAI = MI.getMF()->getTarget().getMCAsmInfo();
3604 bool NeedsWinCFI =
3605 MAI.usesWindowsCFI() && MI.getMF()->getFunction().needsUnwindTableEntry();
3606 if (NeedsWinCFI && (MI.getFlag(MachineInstr::FrameSetup) ||
3608 return false;
3609
3610 // On some CPUs quad load/store pairs are slower than two single load/stores.
3611 if (Subtarget.isPaired128Slow()) {
3612 switch (MI.getOpcode()) {
3613 default:
3614 break;
3615 case AArch64::LDURQi:
3616 case AArch64::STURQi:
3617 case AArch64::LDRQui:
3618 case AArch64::STRQui:
3619 return false;
3620 }
3621 }
3622
3623 return true;
3624}
3625
3628 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
3629 const TargetRegisterInfo *TRI) const {
3630 if (!LdSt.mayLoadOrStore())
3631 return false;
3632
3633 const MachineOperand *BaseOp;
3634 TypeSize WidthN(0, false);
3635 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, OffsetIsScalable,
3636 WidthN, TRI))
3637 return false;
3638 // The maximum vscale is 16 under AArch64, return the maximal extent for the
3639 // vector.
3640 Width = LocationSize::precise(WidthN);
3641 BaseOps.push_back(BaseOp);
3642 return true;
3643}
3644
3645std::optional<ExtAddrMode>
3647 const TargetRegisterInfo *TRI) const {
3648 const MachineOperand *Base; // Filled with the base operand of MI.
3649 int64_t Offset; // Filled with the offset of MI.
3650 bool OffsetIsScalable;
3651 if (!getMemOperandWithOffset(MemI, Base, Offset, OffsetIsScalable, TRI))
3652 return std::nullopt;
3653
3654 if (!Base->isReg())
3655 return std::nullopt;
3656 ExtAddrMode AM;
3657 AM.BaseReg = Base->getReg();
3658 AM.Displacement = Offset;
3659 AM.ScaledReg = 0;
3660 AM.Scale = 0;
3661 return AM;
3662}
3663
3665 Register Reg,
3666 const MachineInstr &AddrI,
3667 ExtAddrMode &AM) const {
3668 // Filter out instructions into which we cannot fold.
3669 unsigned NumBytes;
3670 int64_t OffsetScale = 1;
3671 switch (MemI.getOpcode()) {
3672 default:
3673 return false;
3674
3675 case AArch64::LDURQi:
3676 case AArch64::STURQi:
3677 NumBytes = 16;
3678 break;
3679
3680 case AArch64::LDURDi:
3681 case AArch64::STURDi:
3682 case AArch64::LDURXi:
3683 case AArch64::STURXi:
3684 NumBytes = 8;
3685 break;
3686
3687 case AArch64::LDURWi:
3688 case AArch64::LDURSWi:
3689 case AArch64::STURWi:
3690 NumBytes = 4;
3691 break;
3692
3693 case AArch64::LDURHi:
3694 case AArch64::STURHi:
3695 case AArch64::LDURHHi:
3696 case AArch64::STURHHi:
3697 case AArch64::LDURSHXi:
3698 case AArch64::LDURSHWi:
3699 NumBytes = 2;
3700 break;
3701
3702 case AArch64::LDRBroX:
3703 case AArch64::LDRBBroX:
3704 case AArch64::LDRSBXroX:
3705 case AArch64::LDRSBWroX:
3706 case AArch64::STRBroX:
3707 case AArch64::STRBBroX:
3708 case AArch64::LDURBi:
3709 case AArch64::LDURBBi:
3710 case AArch64::LDURSBXi:
3711 case AArch64::LDURSBWi:
3712 case AArch64::STURBi:
3713 case AArch64::STURBBi:
3714 case AArch64::LDRBui:
3715 case AArch64::LDRBBui:
3716 case AArch64::LDRSBXui:
3717 case AArch64::LDRSBWui:
3718 case AArch64::STRBui:
3719 case AArch64::STRBBui:
3720 NumBytes = 1;
3721 break;
3722
3723 case AArch64::LDRQroX:
3724 case AArch64::STRQroX:
3725 case AArch64::LDRQui:
3726 case AArch64::STRQui:
3727 NumBytes = 16;
3728 OffsetScale = 16;
3729 break;
3730
3731 case AArch64::LDRDroX:
3732 case AArch64::STRDroX:
3733 case AArch64::LDRXroX:
3734 case AArch64::STRXroX:
3735 case AArch64::LDRDui:
3736 case AArch64::STRDui:
3737 case AArch64::LDRXui:
3738 case AArch64::STRXui:
3739 NumBytes = 8;
3740 OffsetScale = 8;
3741 break;
3742
3743 case AArch64::LDRWroX:
3744 case AArch64::LDRSWroX:
3745 case AArch64::STRWroX:
3746 case AArch64::LDRWui:
3747 case AArch64::LDRSWui:
3748 case AArch64::STRWui:
3749 NumBytes = 4;
3750 OffsetScale = 4;
3751 break;
3752
3753 case AArch64::LDRHroX:
3754 case AArch64::STRHroX:
3755 case AArch64::LDRHHroX:
3756 case AArch64::STRHHroX:
3757 case AArch64::LDRSHXroX:
3758 case AArch64::LDRSHWroX:
3759 case AArch64::LDRHui:
3760 case AArch64::STRHui:
3761 case AArch64::LDRHHui:
3762 case AArch64::STRHHui:
3763 case AArch64::LDRSHXui:
3764 case AArch64::LDRSHWui:
3765 NumBytes = 2;
3766 OffsetScale = 2;
3767 break;
3768 }
3769
3770 // Check the fold operand is not the loaded/stored value.
3771 const MachineOperand &BaseRegOp = MemI.getOperand(0);
3772 if (BaseRegOp.isReg() && BaseRegOp.getReg() == Reg)
3773 return false;
3774
3775 // Handle memory instructions with a [Reg, Reg] addressing mode.
3776 if (MemI.getOperand(2).isReg()) {
3777 // Bail if the addressing mode already includes extension of the offset
3778 // register.
3779 if (MemI.getOperand(3).getImm())
3780 return false;
3781
3782 // Check if we actually have a scaled offset.
3783 if (MemI.getOperand(4).getImm() == 0)
3784 OffsetScale = 1;
3785
3786 // If the address instructions is folded into the base register, then the
3787 // addressing mode must not have a scale. Then we can swap the base and the
3788 // scaled registers.
3789 if (MemI.getOperand(1).getReg() == Reg && OffsetScale != 1)
3790 return false;
3791
3792 switch (AddrI.getOpcode()) {
3793 default:
3794 return false;
3795
3796 case AArch64::SBFMXri:
3797 // sxtw Xa, Wm
3798 // ldr Xd, [Xn, Xa, lsl #N]
3799 // ->
3800 // ldr Xd, [Xn, Wm, sxtw #N]
3801 if (AddrI.getOperand(2).getImm() != 0 ||
3802 AddrI.getOperand(3).getImm() != 31)
3803 return false;
3804
3805 AM.BaseReg = MemI.getOperand(1).getReg();
3806 if (AM.BaseReg == Reg)
3807 AM.BaseReg = MemI.getOperand(2).getReg();
3808 AM.ScaledReg = AddrI.getOperand(1).getReg();
3809 AM.Scale = OffsetScale;
3810 AM.Displacement = 0;
3812 return true;
3813
3814 case TargetOpcode::SUBREG_TO_REG: {
3815 // mov Wa, Wm
3816 // ldr Xd, [Xn, Xa, lsl #N]
3817 // ->
3818 // ldr Xd, [Xn, Wm, uxtw #N]
3819
3820 // Zero-extension looks like an ORRWrs followed by a SUBREG_TO_REG.
3821 if (AddrI.getOperand(2).getImm() != AArch64::sub_32)
3822 return false;
3823
3824 const MachineRegisterInfo &MRI = AddrI.getMF()->getRegInfo();
3825 Register OffsetReg = AddrI.getOperand(1).getReg();
3826 if (!OffsetReg.isVirtual() || !MRI.hasOneNonDBGUse(OffsetReg))
3827 return false;
3828
3829 const MachineInstr &DefMI = *MRI.getVRegDef(OffsetReg);
3830 if (DefMI.getOpcode() != AArch64::ORRWrs ||
3831 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3832 DefMI.getOperand(3).getImm() != 0)
3833 return false;
3834
3835 AM.BaseReg = MemI.getOperand(1).getReg();
3836 if (AM.BaseReg == Reg)
3837 AM.BaseReg = MemI.getOperand(2).getReg();
3838 AM.ScaledReg = DefMI.getOperand(2).getReg();
3839 AM.Scale = OffsetScale;
3840 AM.Displacement = 0;
3842 return true;
3843 }
3844 }
3845 }
3846
3847 // Handle memory instructions with a [Reg, #Imm] addressing mode.
3848
3849 // Check we are not breaking a potential conversion to an LDP.
3850 auto validateOffsetForLDP = [](unsigned NumBytes, int64_t OldOffset,
3851 int64_t NewOffset) -> bool {
3852 int64_t MinOffset, MaxOffset;
3853 switch (NumBytes) {
3854 default:
3855 return true;
3856 case 4:
3857 MinOffset = -256;
3858 MaxOffset = 252;
3859 break;
3860 case 8:
3861 MinOffset = -512;
3862 MaxOffset = 504;
3863 break;
3864 case 16:
3865 MinOffset = -1024;
3866 MaxOffset = 1008;
3867 break;
3868 }
3869 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3870 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3871 };
3872 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) -> bool {
3873 int64_t OldOffset = MemI.getOperand(2).getImm() * OffsetScale;
3874 int64_t NewOffset = OldOffset + Disp;
3875 if (!isLegalAddressingMode(NumBytes, NewOffset, /* Scale */ 0))
3876 return false;
3877 // If the old offset would fit into an LDP, but the new offset wouldn't,
3878 // bail out.
3879 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3880 return false;
3881 AM.BaseReg = AddrI.getOperand(1).getReg();
3882 AM.ScaledReg = 0;
3883 AM.Scale = 0;
3884 AM.Displacement = NewOffset;
3886 return true;
3887 };
3888
3889 auto canFoldAddRegIntoAddrMode =
3890 [&](int64_t Scale,
3892 if (MemI.getOperand(2).getImm() != 0)
3893 return false;
3894 if ((unsigned)Scale != Scale)
3895 return false;
3896 if (!isLegalAddressingMode(NumBytes, /* Offset */ 0, Scale))
3897 return false;
3898 AM.BaseReg = AddrI.getOperand(1).getReg();
3899 AM.ScaledReg = AddrI.getOperand(2).getReg();
3900 AM.Scale = Scale;
3901 AM.Displacement = 0;
3902 AM.Form = Form;
3903 return true;
3904 };
3905
3906 auto avoidSlowSTRQ = [&](const MachineInstr &MemI) {
3907 unsigned Opcode = MemI.getOpcode();
3908 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3909 Subtarget.isSTRQroSlow();
3910 };
3911
3912 int64_t Disp = 0;
3913 const bool OptSize = MemI.getMF()->getFunction().hasOptSize();
3914 switch (AddrI.getOpcode()) {
3915 default:
3916 return false;
3917
3918 case AArch64::ADDXri:
3919 // add Xa, Xn, #N
3920 // ldr Xd, [Xa, #M]
3921 // ->
3922 // ldr Xd, [Xn, #N'+M]
3923 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3924 return canFoldAddSubImmIntoAddrMode(Disp);
3925
3926 case AArch64::SUBXri:
3927 // sub Xa, Xn, #N
3928 // ldr Xd, [Xa, #M]
3929 // ->
3930 // ldr Xd, [Xn, #N'+M]
3931 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3932 return canFoldAddSubImmIntoAddrMode(-Disp);
3933
3934 case AArch64::ADDXrs: {
3935 // add Xa, Xn, Xm, lsl #N
3936 // ldr Xd, [Xa]
3937 // ->
3938 // ldr Xd, [Xn, Xm, lsl #N]
3939
3940 // Don't fold the add if the result would be slower, unless optimising for
3941 // size.
3942 unsigned Shift = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3944 return false;
3945 Shift = AArch64_AM::getShiftValue(Shift);
3946 if (!OptSize) {
3947 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3948 return false;
3949 if (avoidSlowSTRQ(MemI))
3950 return false;
3951 }
3952 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3953 }
3954
3955 case AArch64::ADDXrr:
3956 // add Xa, Xn, Xm
3957 // ldr Xd, [Xa]
3958 // ->
3959 // ldr Xd, [Xn, Xm, lsl #0]
3960
3961 // Don't fold the add if the result would be slower, unless optimising for
3962 // size.
3963 if (!OptSize && avoidSlowSTRQ(MemI))
3964 return false;
3965 return canFoldAddRegIntoAddrMode(1);
3966
3967 case AArch64::ADDXrx:
3968 // add Xa, Xn, Wm, {s,u}xtw #N
3969 // ldr Xd, [Xa]
3970 // ->
3971 // ldr Xd, [Xn, Wm, {s,u}xtw #N]
3972
3973 // Don't fold the add if the result would be slower, unless optimising for
3974 // size.
3975 if (!OptSize && avoidSlowSTRQ(MemI))
3976 return false;
3977
3978 // Can fold only sign-/zero-extend of a word.
3979 unsigned Imm = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3981 if (Extend != AArch64_AM::UXTW && Extend != AArch64_AM::SXTW)
3982 return false;
3983
3984 return canFoldAddRegIntoAddrMode(
3988 }
3989}
3990
3991// Given an opcode for an instruction with a [Reg, #Imm] addressing mode,
3992// return the opcode of an instruction performing the same operation, but using
3993// the [Reg, Reg] addressing mode.
3994static unsigned regOffsetOpcode(unsigned Opcode) {
3995 switch (Opcode) {
3996 default:
3997 llvm_unreachable("Address folding not implemented for instruction");
3998
3999 case AArch64::LDURQi:
4000 case AArch64::LDRQui:
4001 return AArch64::LDRQroX;
4002 case AArch64::STURQi:
4003 case AArch64::STRQui:
4004 return AArch64::STRQroX;
4005 case AArch64::LDURDi:
4006 case AArch64::LDRDui:
4007 return AArch64::LDRDroX;
4008 case AArch64::STURDi:
4009 case AArch64::STRDui:
4010 return AArch64::STRDroX;
4011 case AArch64::LDURXi:
4012 case AArch64::LDRXui:
4013 return AArch64::LDRXroX;
4014 case AArch64::STURXi:
4015 case AArch64::STRXui:
4016 return AArch64::STRXroX;
4017 case AArch64::LDURWi:
4018 case AArch64::LDRWui:
4019 return AArch64::LDRWroX;
4020 case AArch64::LDURSWi:
4021 case AArch64::LDRSWui:
4022 return AArch64::LDRSWroX;
4023 case AArch64::STURWi:
4024 case AArch64::STRWui:
4025 return AArch64::STRWroX;
4026 case AArch64::LDURHi:
4027 case AArch64::LDRHui:
4028 return AArch64::LDRHroX;
4029 case AArch64::STURHi:
4030 case AArch64::STRHui:
4031 return AArch64::STRHroX;
4032 case AArch64::LDURHHi:
4033 case AArch64::LDRHHui:
4034 return AArch64::LDRHHroX;
4035 case AArch64::STURHHi:
4036 case AArch64::STRHHui:
4037 return AArch64::STRHHroX;
4038 case AArch64::LDURSHXi:
4039 case AArch64::LDRSHXui:
4040 return AArch64::LDRSHXroX;
4041 case AArch64::LDURSHWi:
4042 case AArch64::LDRSHWui:
4043 return AArch64::LDRSHWroX;
4044 case AArch64::LDURBi:
4045 case AArch64::LDRBui:
4046 return AArch64::LDRBroX;
4047 case AArch64::LDURBBi:
4048 case AArch64::LDRBBui:
4049 return AArch64::LDRBBroX;
4050 case AArch64::LDURSBXi:
4051 case AArch64::LDRSBXui:
4052 return AArch64::LDRSBXroX;
4053 case AArch64::LDURSBWi:
4054 case AArch64::LDRSBWui:
4055 return AArch64::LDRSBWroX;
4056 case AArch64::STURBi:
4057 case AArch64::STRBui:
4058 return AArch64::STRBroX;
4059 case AArch64::STURBBi:
4060 case AArch64::STRBBui:
4061 return AArch64::STRBBroX;
4062 }
4063}
4064
4065// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4066// the opcode of an instruction performing the same operation, but using the
4067// [Reg, #Imm] addressing mode with scaled offset.
4068unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale) {
4069 switch (Opcode) {
4070 default:
4071 llvm_unreachable("Address folding not implemented for instruction");
4072
4073 case AArch64::LDURQi:
4074 Scale = 16;
4075 return AArch64::LDRQui;
4076 case AArch64::STURQi:
4077 Scale = 16;
4078 return AArch64::STRQui;
4079 case AArch64::LDURDi:
4080 Scale = 8;
4081 return AArch64::LDRDui;
4082 case AArch64::STURDi:
4083 Scale = 8;
4084 return AArch64::STRDui;
4085 case AArch64::LDURXi:
4086 Scale = 8;
4087 return AArch64::LDRXui;
4088 case AArch64::STURXi:
4089 Scale = 8;
4090 return AArch64::STRXui;
4091 case AArch64::LDURWi:
4092 Scale = 4;
4093 return AArch64::LDRWui;
4094 case AArch64::LDURSWi:
4095 Scale = 4;
4096 return AArch64::LDRSWui;
4097 case AArch64::STURWi:
4098 Scale = 4;
4099 return AArch64::STRWui;
4100 case AArch64::LDURHi:
4101 Scale = 2;
4102 return AArch64::LDRHui;
4103 case AArch64::STURHi:
4104 Scale = 2;
4105 return AArch64::STRHui;
4106 case AArch64::LDURHHi:
4107 Scale = 2;
4108 return AArch64::LDRHHui;
4109 case AArch64::STURHHi:
4110 Scale = 2;
4111 return AArch64::STRHHui;
4112 case AArch64::LDURSHXi:
4113 Scale = 2;
4114 return AArch64::LDRSHXui;
4115 case AArch64::LDURSHWi:
4116 Scale = 2;
4117 return AArch64::LDRSHWui;
4118 case AArch64::LDURBi:
4119 Scale = 1;
4120 return AArch64::LDRBui;
4121 case AArch64::LDURBBi:
4122 Scale = 1;
4123 return AArch64::LDRBBui;
4124 case AArch64::LDURSBXi:
4125 Scale = 1;
4126 return AArch64::LDRSBXui;
4127 case AArch64::LDURSBWi:
4128 Scale = 1;
4129 return AArch64::LDRSBWui;
4130 case AArch64::STURBi:
4131 Scale = 1;
4132 return AArch64::STRBui;
4133 case AArch64::STURBBi:
4134 Scale = 1;
4135 return AArch64::STRBBui;
4136 case AArch64::LDRQui:
4137 case AArch64::STRQui:
4138 Scale = 16;
4139 return Opcode;
4140 case AArch64::LDRDui:
4141 case AArch64::STRDui:
4142 case AArch64::LDRXui:
4143 case AArch64::STRXui:
4144 Scale = 8;
4145 return Opcode;
4146 case AArch64::LDRWui:
4147 case AArch64::LDRSWui:
4148 case AArch64::STRWui:
4149 Scale = 4;
4150 return Opcode;
4151 case AArch64::LDRHui:
4152 case AArch64::STRHui:
4153 case AArch64::LDRHHui:
4154 case AArch64::STRHHui:
4155 case AArch64::LDRSHXui:
4156 case AArch64::LDRSHWui:
4157 Scale = 2;
4158 return Opcode;
4159 case AArch64::LDRBui:
4160 case AArch64::LDRBBui:
4161 case AArch64::LDRSBXui:
4162 case AArch64::LDRSBWui:
4163 case AArch64::STRBui:
4164 case AArch64::STRBBui:
4165 Scale = 1;
4166 return Opcode;
4167 }
4168}
4169
4170// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4171// the opcode of an instruction performing the same operation, but using the
4172// [Reg, #Imm] addressing mode with unscaled offset.
4173unsigned unscaledOffsetOpcode(unsigned Opcode) {
4174 switch (Opcode) {
4175 default:
4176 llvm_unreachable("Address folding not implemented for instruction");
4177
4178 case AArch64::LDURQi:
4179 case AArch64::STURQi:
4180 case AArch64::LDURDi:
4181 case AArch64::STURDi:
4182 case AArch64::LDURXi:
4183 case AArch64::STURXi:
4184 case AArch64::LDURWi:
4185 case AArch64::LDURSWi:
4186 case AArch64::STURWi:
4187 case AArch64::LDURHi:
4188 case AArch64::STURHi:
4189 case AArch64::LDURHHi:
4190 case AArch64::STURHHi:
4191 case AArch64::LDURSHXi:
4192 case AArch64::LDURSHWi:
4193 case AArch64::LDURBi:
4194 case AArch64::STURBi:
4195 case AArch64::LDURBBi:
4196 case AArch64::STURBBi:
4197 case AArch64::LDURSBWi:
4198 case AArch64::LDURSBXi:
4199 return Opcode;
4200 case AArch64::LDRQui:
4201 return AArch64::LDURQi;
4202 case AArch64::STRQui:
4203 return AArch64::STURQi;
4204 case AArch64::LDRDui:
4205 return AArch64::LDURDi;
4206 case AArch64::STRDui:
4207 return AArch64::STURDi;
4208 case AArch64::LDRXui:
4209 return AArch64::LDURXi;
4210 case AArch64::STRXui:
4211 return AArch64::STURXi;
4212 case AArch64::LDRWui:
4213 return AArch64::LDURWi;
4214 case AArch64::LDRSWui:
4215 return AArch64::LDURSWi;
4216 case AArch64::STRWui:
4217 return AArch64::STURWi;
4218 case AArch64::LDRHui:
4219 return AArch64::LDURHi;
4220 case AArch64::STRHui:
4221 return AArch64::STURHi;
4222 case AArch64::LDRHHui:
4223 return AArch64::LDURHHi;
4224 case AArch64::STRHHui:
4225 return AArch64::STURHHi;
4226 case AArch64::LDRSHXui:
4227 return AArch64::LDURSHXi;
4228 case AArch64::LDRSHWui:
4229 return AArch64::LDURSHWi;
4230 case AArch64::LDRBBui:
4231 return AArch64::LDURBBi;
4232 case AArch64::LDRBui:
4233 return AArch64::LDURBi;
4234 case AArch64::STRBBui:
4235 return AArch64::STURBBi;
4236 case AArch64::STRBui:
4237 return AArch64::STURBi;
4238 case AArch64::LDRSBWui:
4239 return AArch64::LDURSBWi;
4240 case AArch64::LDRSBXui:
4241 return AArch64::LDURSBXi;
4242 }
4243}
4244
4245// Given the opcode of a memory load/store instruction, return the opcode of an
4246// instruction performing the same operation, but using
4247// the [Reg, Reg, {s,u}xtw #N] addressing mode with sign-/zero-extend of the
4248// offset register.
4249static unsigned offsetExtendOpcode(unsigned Opcode) {
4250 switch (Opcode) {
4251 default:
4252 llvm_unreachable("Address folding not implemented for instruction");
4253
4254 case AArch64::LDRQroX:
4255 case AArch64::LDURQi:
4256 case AArch64::LDRQui:
4257 return AArch64::LDRQroW;
4258 case AArch64::STRQroX:
4259 case AArch64::STURQi:
4260 case AArch64::STRQui:
4261 return AArch64::STRQroW;
4262 case AArch64::LDRDroX:
4263 case AArch64::LDURDi:
4264 case AArch64::LDRDui:
4265 return AArch64::LDRDroW;
4266 case AArch64::STRDroX:
4267 case AArch64::STURDi:
4268 case AArch64::STRDui:
4269 return AArch64::STRDroW;
4270 case AArch64::LDRXroX:
4271 case AArch64::LDURXi:
4272 case AArch64::LDRXui:
4273 return AArch64::LDRXroW;
4274 case AArch64::STRXroX:
4275 case AArch64::STURXi:
4276 case AArch64::STRXui:
4277 return AArch64::STRXroW;
4278 case AArch64::LDRWroX:
4279 case AArch64::LDURWi:
4280 case AArch64::LDRWui:
4281 return AArch64::LDRWroW;
4282 case AArch64::LDRSWroX:
4283 case AArch64::LDURSWi:
4284 case AArch64::LDRSWui:
4285 return AArch64::LDRSWroW;
4286 case AArch64::STRWroX:
4287 case AArch64::STURWi:
4288 case AArch64::STRWui:
4289 return AArch64::STRWroW;
4290 case AArch64::LDRHroX:
4291 case AArch64::LDURHi:
4292 case AArch64::LDRHui:
4293 return AArch64::LDRHroW;
4294 case AArch64::STRHroX:
4295 case AArch64::STURHi:
4296 case AArch64::STRHui:
4297 return AArch64::STRHroW;
4298 case AArch64::LDRHHroX:
4299 case AArch64::LDURHHi:
4300 case AArch64::LDRHHui:
4301 return AArch64::LDRHHroW;
4302 case AArch64::STRHHroX:
4303 case AArch64::STURHHi:
4304 case AArch64::STRHHui:
4305 return AArch64::STRHHroW;
4306 case AArch64::LDRSHXroX:
4307 case AArch64::LDURSHXi:
4308 case AArch64::LDRSHXui:
4309 return AArch64::LDRSHXroW;
4310 case AArch64::LDRSHWroX:
4311 case AArch64::LDURSHWi:
4312 case AArch64::LDRSHWui:
4313 return AArch64::LDRSHWroW;
4314 case AArch64::LDRBroX:
4315 case AArch64::LDURBi:
4316 case AArch64::LDRBui:
4317 return AArch64::LDRBroW;
4318 case AArch64::LDRBBroX:
4319 case AArch64::LDURBBi:
4320 case AArch64::LDRBBui:
4321 return AArch64::LDRBBroW;
4322 case AArch64::LDRSBXroX:
4323 case AArch64::LDURSBXi:
4324 case AArch64::LDRSBXui:
4325 return AArch64::LDRSBXroW;
4326 case AArch64::LDRSBWroX:
4327 case AArch64::LDURSBWi:
4328 case AArch64::LDRSBWui:
4329 return AArch64::LDRSBWroW;
4330 case AArch64::STRBroX:
4331 case AArch64::STURBi:
4332 case AArch64::STRBui:
4333 return AArch64::STRBroW;
4334 case AArch64::STRBBroX:
4335 case AArch64::STURBBi:
4336 case AArch64::STRBBui:
4337 return AArch64::STRBBroW;
4338 }
4339}
4340
4342 const ExtAddrMode &AM) const {
4343
4344 const DebugLoc &DL = MemI.getDebugLoc();
4345 MachineBasicBlock &MBB = *MemI.getParent();
4346 MachineRegisterInfo &MRI = MemI.getMF()->getRegInfo();
4347
4349 if (AM.ScaledReg) {
4350 // The new instruction will be in the form `ldr Rt, [Xn, Xm, lsl #imm]`.
4351 unsigned Opcode = regOffsetOpcode(MemI.getOpcode());
4352 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4353 auto B = BuildMI(MBB, MemI, DL, get(Opcode))
4354 .addReg(MemI.getOperand(0).getReg(),
4355 getDefRegState(MemI.mayLoad()))
4356 .addReg(AM.BaseReg)
4357 .addReg(AM.ScaledReg)
4358 .addImm(0)
4359 .addImm(AM.Scale > 1)
4360 .setMemRefs(MemI.memoperands())
4361 .setMIFlags(MemI.getFlags());
4362 return B.getInstr();
4363 }
4364
4365 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
4366 "Addressing mode not supported for folding");
4367
4368 // The new instruction will be in the form `ld[u]r Rt, [Xn, #imm]`.
4369 unsigned Scale = 1;
4370 unsigned Opcode = MemI.getOpcode();
4371 if (isInt<9>(AM.Displacement))
4372 Opcode = unscaledOffsetOpcode(Opcode);
4373 else
4374 Opcode = scaledOffsetOpcode(Opcode, Scale);
4375
4376 auto B =
4377 BuildMI(MBB, MemI, DL, get(Opcode))
4378 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4379 .addReg(AM.BaseReg)
4380 .addImm(AM.Displacement / Scale)
4381 .setMemRefs(MemI.memoperands())
4382 .setMIFlags(MemI.getFlags());
4383 return B.getInstr();
4384 }
4385
4388 // The new instruction will be in the form `ldr Rt, [Xn, Wm, {s,u}xtw #N]`.
4389 assert(AM.ScaledReg && !AM.Displacement &&
4390 "Address offset can be a register or an immediate, but not both");
4391 unsigned Opcode = offsetExtendOpcode(MemI.getOpcode());
4392 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4393 // Make sure the offset register is in the correct register class.
4394 Register OffsetReg = AM.ScaledReg;
4395 const TargetRegisterClass *RC = MRI.getRegClass(OffsetReg);
4396 if (RC->hasSuperClassEq(&AArch64::GPR64RegClass)) {
4397 OffsetReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
4398 BuildMI(MBB, MemI, DL, get(TargetOpcode::COPY), OffsetReg)
4399 .addReg(AM.ScaledReg, {}, AArch64::sub_32);
4400 }
4401 auto B =
4402 BuildMI(MBB, MemI, DL, get(Opcode))
4403 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4404 .addReg(AM.BaseReg)
4405 .addReg(OffsetReg)
4407 .addImm(AM.Scale != 1)
4408 .setMemRefs(MemI.memoperands())
4409 .setMIFlags(MemI.getFlags());
4410
4411 return B.getInstr();
4412 }
4413
4415 "Function must not be called with an addressing mode it can't handle");
4416}
4417
4418/// Return true if the opcode is a post-index ld/st instruction, which really
4419/// loads from base+0.
4420static bool isPostIndexLdStOpcode(unsigned Opcode) {
4421 switch (Opcode) {
4422 default:
4423 return false;
4424 case AArch64::LD1Fourv16b_POST:
4425 case AArch64::LD1Fourv1d_POST:
4426 case AArch64::LD1Fourv2d_POST:
4427 case AArch64::LD1Fourv2s_POST:
4428 case AArch64::LD1Fourv4h_POST:
4429 case AArch64::LD1Fourv4s_POST:
4430 case AArch64::LD1Fourv8b_POST:
4431 case AArch64::LD1Fourv8h_POST:
4432 case AArch64::LD1Onev16b_POST:
4433 case AArch64::LD1Onev1d_POST:
4434 case AArch64::LD1Onev2d_POST:
4435 case AArch64::LD1Onev2s_POST:
4436 case AArch64::LD1Onev4h_POST:
4437 case AArch64::LD1Onev4s_POST:
4438 case AArch64::LD1Onev8b_POST:
4439 case AArch64::LD1Onev8h_POST:
4440 case AArch64::LD1Rv16b_POST:
4441 case AArch64::LD1Rv1d_POST:
4442 case AArch64::LD1Rv2d_POST:
4443 case AArch64::LD1Rv2s_POST:
4444 case AArch64::LD1Rv4h_POST:
4445 case AArch64::LD1Rv4s_POST:
4446 case AArch64::LD1Rv8b_POST:
4447 case AArch64::LD1Rv8h_POST:
4448 case AArch64::LD1Threev16b_POST:
4449 case AArch64::LD1Threev1d_POST:
4450 case AArch64::LD1Threev2d_POST:
4451 case AArch64::LD1Threev2s_POST:
4452 case AArch64::LD1Threev4h_POST:
4453 case AArch64::LD1Threev4s_POST:
4454 case AArch64::LD1Threev8b_POST:
4455 case AArch64::LD1Threev8h_POST:
4456 case AArch64::LD1Twov16b_POST:
4457 case AArch64::LD1Twov1d_POST:
4458 case AArch64::LD1Twov2d_POST:
4459 case AArch64::LD1Twov2s_POST:
4460 case AArch64::LD1Twov4h_POST:
4461 case AArch64::LD1Twov4s_POST:
4462 case AArch64::LD1Twov8b_POST:
4463 case AArch64::LD1Twov8h_POST:
4464 case AArch64::LD1i16_POST:
4465 case AArch64::LD1i32_POST:
4466 case AArch64::LD1i64_POST:
4467 case AArch64::LD1i8_POST:
4468 case AArch64::LD2Rv16b_POST:
4469 case AArch64::LD2Rv1d_POST:
4470 case AArch64::LD2Rv2d_POST:
4471 case AArch64::LD2Rv2s_POST:
4472 case AArch64::LD2Rv4h_POST:
4473 case AArch64::LD2Rv4s_POST:
4474 case AArch64::LD2Rv8b_POST:
4475 case AArch64::LD2Rv8h_POST:
4476 case AArch64::LD2Twov16b_POST:
4477 case AArch64::LD2Twov2d_POST:
4478 case AArch64::LD2Twov2s_POST:
4479 case AArch64::LD2Twov4h_POST:
4480 case AArch64::LD2Twov4s_POST:
4481 case AArch64::LD2Twov8b_POST:
4482 case AArch64::LD2Twov8h_POST:
4483 case AArch64::LD2i16_POST:
4484 case AArch64::LD2i32_POST:
4485 case AArch64::LD2i64_POST:
4486 case AArch64::LD2i8_POST:
4487 case AArch64::LD3Rv16b_POST:
4488 case AArch64::LD3Rv1d_POST:
4489 case AArch64::LD3Rv2d_POST:
4490 case AArch64::LD3Rv2s_POST:
4491 case AArch64::LD3Rv4h_POST:
4492 case AArch64::LD3Rv4s_POST:
4493 case AArch64::LD3Rv8b_POST:
4494 case AArch64::LD3Rv8h_POST:
4495 case AArch64::LD3Threev16b_POST:
4496 case AArch64::LD3Threev2d_POST:
4497 case AArch64::LD3Threev2s_POST:
4498 case AArch64::LD3Threev4h_POST:
4499 case AArch64::LD3Threev4s_POST:
4500 case AArch64::LD3Threev8b_POST:
4501 case AArch64::LD3Threev8h_POST:
4502 case AArch64::LD3i16_POST:
4503 case AArch64::LD3i32_POST:
4504 case AArch64::LD3i64_POST:
4505 case AArch64::LD3i8_POST:
4506 case AArch64::LD4Fourv16b_POST:
4507 case AArch64::LD4Fourv2d_POST:
4508 case AArch64::LD4Fourv2s_POST:
4509 case AArch64::LD4Fourv4h_POST:
4510 case AArch64::LD4Fourv4s_POST:
4511 case AArch64::LD4Fourv8b_POST:
4512 case AArch64::LD4Fourv8h_POST:
4513 case AArch64::LD4Rv16b_POST:
4514 case AArch64::LD4Rv1d_POST:
4515 case AArch64::LD4Rv2d_POST:
4516 case AArch64::LD4Rv2s_POST:
4517 case AArch64::LD4Rv4h_POST:
4518 case AArch64::LD4Rv4s_POST:
4519 case AArch64::LD4Rv8b_POST:
4520 case AArch64::LD4Rv8h_POST:
4521 case AArch64::LD4i16_POST:
4522 case AArch64::LD4i32_POST:
4523 case AArch64::LD4i64_POST:
4524 case AArch64::LD4i8_POST:
4525 case AArch64::LDAPRWpost:
4526 case AArch64::LDAPRXpost:
4527 case AArch64::LDIAPPWpost:
4528 case AArch64::LDIAPPXpost:
4529 case AArch64::LDPDpost:
4530 case AArch64::LDPQpost:
4531 case AArch64::LDPSWpost:
4532 case AArch64::LDPSpost:
4533 case AArch64::LDPWpost:
4534 case AArch64::LDPXpost:
4535 case AArch64::LDRBBpost:
4536 case AArch64::LDRBpost:
4537 case AArch64::LDRDpost:
4538 case AArch64::LDRHHpost:
4539 case AArch64::LDRHpost:
4540 case AArch64::LDRQpost:
4541 case AArch64::LDRSBWpost:
4542 case AArch64::LDRSBXpost:
4543 case AArch64::LDRSHWpost:
4544 case AArch64::LDRSHXpost:
4545 case AArch64::LDRSWpost:
4546 case AArch64::LDRSpost:
4547 case AArch64::LDRWpost:
4548 case AArch64::LDRXpost:
4549 case AArch64::ST1Fourv16b_POST:
4550 case AArch64::ST1Fourv1d_POST:
4551 case AArch64::ST1Fourv2d_POST:
4552 case AArch64::ST1Fourv2s_POST:
4553 case AArch64::ST1Fourv4h_POST:
4554 case AArch64::ST1Fourv4s_POST:
4555 case AArch64::ST1Fourv8b_POST:
4556 case AArch64::ST1Fourv8h_POST:
4557 case AArch64::ST1Onev16b_POST:
4558 case AArch64::ST1Onev1d_POST:
4559 case AArch64::ST1Onev2d_POST:
4560 case AArch64::ST1Onev2s_POST:
4561 case AArch64::ST1Onev4h_POST:
4562 case AArch64::ST1Onev4s_POST:
4563 case AArch64::ST1Onev8b_POST:
4564 case AArch64::ST1Onev8h_POST:
4565 case AArch64::ST1Threev16b_POST:
4566 case AArch64::ST1Threev1d_POST:
4567 case AArch64::ST1Threev2d_POST:
4568 case AArch64::ST1Threev2s_POST:
4569 case AArch64::ST1Threev4h_POST:
4570 case AArch64::ST1Threev4s_POST:
4571 case AArch64::ST1Threev8b_POST:
4572 case AArch64::ST1Threev8h_POST:
4573 case AArch64::ST1Twov16b_POST:
4574 case AArch64::ST1Twov1d_POST:
4575 case AArch64::ST1Twov2d_POST:
4576 case AArch64::ST1Twov2s_POST:
4577 case AArch64::ST1Twov4h_POST:
4578 case AArch64::ST1Twov4s_POST:
4579 case AArch64::ST1Twov8b_POST:
4580 case AArch64::ST1Twov8h_POST:
4581 case AArch64::ST1i16_POST:
4582 case AArch64::ST1i32_POST:
4583 case AArch64::ST1i64_POST:
4584 case AArch64::ST1i8_POST:
4585 case AArch64::ST2GPostIndex:
4586 case AArch64::ST2Twov16b_POST:
4587 case AArch64::ST2Twov2d_POST:
4588 case AArch64::ST2Twov2s_POST:
4589 case AArch64::ST2Twov4h_POST:
4590 case AArch64::ST2Twov4s_POST:
4591 case AArch64::ST2Twov8b_POST:
4592 case AArch64::ST2Twov8h_POST:
4593 case AArch64::ST2i16_POST:
4594 case AArch64::ST2i32_POST:
4595 case AArch64::ST2i64_POST:
4596 case AArch64::ST2i8_POST:
4597 case AArch64::ST3Threev16b_POST:
4598 case AArch64::ST3Threev2d_POST:
4599 case AArch64::ST3Threev2s_POST:
4600 case AArch64::ST3Threev4h_POST:
4601 case AArch64::ST3Threev4s_POST:
4602 case AArch64::ST3Threev8b_POST:
4603 case AArch64::ST3Threev8h_POST:
4604 case AArch64::ST3i16_POST:
4605 case AArch64::ST3i32_POST:
4606 case AArch64::ST3i64_POST:
4607 case AArch64::ST3i8_POST:
4608 case AArch64::ST4Fourv16b_POST:
4609 case AArch64::ST4Fourv2d_POST:
4610 case AArch64::ST4Fourv2s_POST:
4611 case AArch64::ST4Fourv4h_POST:
4612 case AArch64::ST4Fourv4s_POST:
4613 case AArch64::ST4Fourv8b_POST:
4614 case AArch64::ST4Fourv8h_POST:
4615 case AArch64::ST4i16_POST:
4616 case AArch64::ST4i32_POST:
4617 case AArch64::ST4i64_POST:
4618 case AArch64::ST4i8_POST:
4619 case AArch64::STGPostIndex:
4620 case AArch64::STGPpost:
4621 case AArch64::STPDpost:
4622 case AArch64::STPQpost:
4623 case AArch64::STPSpost:
4624 case AArch64::STPWpost:
4625 case AArch64::STPXpost:
4626 case AArch64::STRBBpost:
4627 case AArch64::STRBpost:
4628 case AArch64::STRDpost:
4629 case AArch64::STRHHpost:
4630 case AArch64::STRHpost:
4631 case AArch64::STRQpost:
4632 case AArch64::STRSpost:
4633 case AArch64::STRWpost:
4634 case AArch64::STRXpost:
4635 case AArch64::STZ2GPostIndex:
4636 case AArch64::STZGPostIndex:
4637 return true;
4638 }
4639}
4640
4642 const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset,
4643 bool &OffsetIsScalable, TypeSize &Width,
4644 const TargetRegisterInfo *TRI) const {
4645 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4646 // Handle only loads/stores with base register followed by immediate offset.
4647 if (LdSt.getNumExplicitOperands() == 3) {
4648 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
4649 if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
4650 !LdSt.getOperand(2).isImm())
4651 return false;
4652 } else if (LdSt.getNumExplicitOperands() == 4) {
4653 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
4654 if (!LdSt.getOperand(1).isReg() ||
4655 (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI()) ||
4656 !LdSt.getOperand(3).isImm())
4657 return false;
4658 } else
4659 return false;
4660
4661 // Get the scaling factor for the instruction and set the width for the
4662 // instruction.
4663 TypeSize Scale(0U, false);
4664 int64_t Dummy1, Dummy2;
4665
4666 // If this returns false, then it's an instruction we don't want to handle.
4667 if (!getMemOpInfo(LdSt.getOpcode(), Scale, Width, Dummy1, Dummy2))
4668 return false;
4669
4670 // Compute the offset. Offset is calculated as the immediate operand
4671 // multiplied by the scaling factor. Unscaled instructions have scaling factor
4672 // set to 1. Postindex are a special case which have an offset of 0.
4673 if (isPostIndexLdStOpcode(LdSt.getOpcode())) {
4674 BaseOp = &LdSt.getOperand(2);
4675 Offset = 0;
4676 } else if (LdSt.getNumExplicitOperands() == 3) {
4677 BaseOp = &LdSt.getOperand(1);
4678 Offset = LdSt.getOperand(2).getImm() * Scale.getKnownMinValue();
4679 } else {
4680 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
4681 BaseOp = &LdSt.getOperand(2);
4682 Offset = LdSt.getOperand(3).getImm() * Scale.getKnownMinValue();
4683 }
4684 OffsetIsScalable = Scale.isScalable();
4685
4686 return BaseOp->isReg() || BaseOp->isFI();
4687}
4688
4691 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4692 MachineOperand &OfsOp = LdSt.getOperand(LdSt.getNumExplicitOperands() - 1);
4693 assert(OfsOp.isImm() && "Offset operand wasn't immediate.");
4694 return OfsOp;
4695}
4696
4697bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale,
4698 TypeSize &Width, int64_t &MinOffset,
4699 int64_t &MaxOffset) {
4700 switch (Opcode) {
4701 // Not a memory operation or something we want to handle.
4702 default:
4703 Scale = Width = TypeSize::getFixed(0);
4704 MinOffset = MaxOffset = 0;
4705 return false;
4706 // LDR / STR
4707 case AArch64::LDRQui:
4708 case AArch64::STRQui:
4709 Scale = Width = TypeSize::getFixed(16);
4710 MinOffset = 0;
4711 MaxOffset = 4095;
4712 break;
4713 case AArch64::LDRXui:
4714 case AArch64::LDRDui:
4715 case AArch64::STRXui:
4716 case AArch64::STRDui:
4717 case AArch64::PRFMui:
4718 Scale = Width = TypeSize::getFixed(8);
4719 MinOffset = 0;
4720 MaxOffset = 4095;
4721 break;
4722 case AArch64::LDRWui:
4723 case AArch64::LDRSui:
4724 case AArch64::LDRSWui:
4725 case AArch64::STRWui:
4726 case AArch64::STRSui:
4727 Scale = Width = TypeSize::getFixed(4);
4728 MinOffset = 0;
4729 MaxOffset = 4095;
4730 break;
4731 case AArch64::LDRHui:
4732 case AArch64::LDRHHui:
4733 case AArch64::LDRSHWui:
4734 case AArch64::LDRSHXui:
4735 case AArch64::STRHui:
4736 case AArch64::STRHHui:
4737 Scale = Width = TypeSize::getFixed(2);
4738 MinOffset = 0;
4739 MaxOffset = 4095;
4740 break;
4741 case AArch64::LDRBui:
4742 case AArch64::LDRBBui:
4743 case AArch64::LDRSBWui:
4744 case AArch64::LDRSBXui:
4745 case AArch64::STRBui:
4746 case AArch64::STRBBui:
4747 Scale = Width = TypeSize::getFixed(1);
4748 MinOffset = 0;
4749 MaxOffset = 4095;
4750 break;
4751 // post/pre inc
4752 case AArch64::STRQpre:
4753 case AArch64::LDRQpost:
4754 Scale = TypeSize::getFixed(1);
4755 Width = TypeSize::getFixed(16);
4756 MinOffset = -256;
4757 MaxOffset = 255;
4758 break;
4759 case AArch64::LDRDpost:
4760 case AArch64::LDRDpre:
4761 case AArch64::LDRXpost:
4762 case AArch64::LDRXpre:
4763 case AArch64::STRDpost:
4764 case AArch64::STRDpre:
4765 case AArch64::STRXpost:
4766 case AArch64::STRXpre:
4767 Scale = TypeSize::getFixed(1);
4768 Width = TypeSize::getFixed(8);
4769 MinOffset = -256;
4770 MaxOffset = 255;
4771 break;
4772 case AArch64::STRWpost:
4773 case AArch64::STRWpre:
4774 case AArch64::LDRWpost:
4775 case AArch64::LDRWpre:
4776 case AArch64::STRSpost:
4777 case AArch64::STRSpre:
4778 case AArch64::LDRSpost:
4779 case AArch64::LDRSpre:
4780 Scale = TypeSize::getFixed(1);
4781 Width = TypeSize::getFixed(4);
4782 MinOffset = -256;
4783 MaxOffset = 255;
4784 break;
4785 case AArch64::LDRHpost:
4786 case AArch64::LDRHpre:
4787 case AArch64::STRHpost:
4788 case AArch64::STRHpre:
4789 case AArch64::LDRHHpost:
4790 case AArch64::LDRHHpre:
4791 case AArch64::STRHHpost:
4792 case AArch64::STRHHpre:
4793 Scale = TypeSize::getFixed(1);
4794 Width = TypeSize::getFixed(2);
4795 MinOffset = -256;
4796 MaxOffset = 255;
4797 break;
4798 case AArch64::LDRBpost:
4799 case AArch64::LDRBpre:
4800 case AArch64::STRBpost:
4801 case AArch64::STRBpre:
4802 case AArch64::LDRBBpost:
4803 case AArch64::LDRBBpre:
4804 case AArch64::STRBBpost:
4805 case AArch64::STRBBpre:
4806 Scale = Width = TypeSize::getFixed(1);
4807 MinOffset = -256;
4808 MaxOffset = 255;
4809 break;
4810 // Unscaled
4811 case AArch64::LDURQi:
4812 case AArch64::STURQi:
4813 Scale = TypeSize::getFixed(1);
4814 Width = TypeSize::getFixed(16);
4815 MinOffset = -256;
4816 MaxOffset = 255;
4817 break;
4818 case AArch64::LDURXi:
4819 case AArch64::LDURDi:
4820 case AArch64::LDAPURXi:
4821 case AArch64::STURXi:
4822 case AArch64::STURDi:
4823 case AArch64::STLURXi:
4824 case AArch64::PRFUMi:
4825 Scale = TypeSize::getFixed(1);
4826 Width = TypeSize::getFixed(8);
4827 MinOffset = -256;
4828 MaxOffset = 255;
4829 break;
4830 case AArch64::LDURWi:
4831 case AArch64::LDURSi:
4832 case AArch64::LDURSWi:
4833 case AArch64::LDAPURi:
4834 case AArch64::LDAPURSWi:
4835 case AArch64::STURWi:
4836 case AArch64::STURSi:
4837 case AArch64::STLURWi:
4838 Scale = TypeSize::getFixed(1);
4839 Width = TypeSize::getFixed(4);
4840 MinOffset = -256;
4841 MaxOffset = 255;
4842 break;
4843 case AArch64::LDURHi:
4844 case AArch64::LDURHHi:
4845 case AArch64::LDURSHXi:
4846 case AArch64::LDURSHWi:
4847 case AArch64::LDAPURHi:
4848 case AArch64::LDAPURSHWi:
4849 case AArch64::LDAPURSHXi:
4850 case AArch64::STURHi:
4851 case AArch64::STURHHi:
4852 case AArch64::STLURHi:
4853 Scale = TypeSize::getFixed(1);
4854 Width = TypeSize::getFixed(2);
4855 MinOffset = -256;
4856 MaxOffset = 255;
4857 break;
4858 case AArch64::LDURBi:
4859 case AArch64::LDURBBi:
4860 case AArch64::LDURSBXi:
4861 case AArch64::LDURSBWi:
4862 case AArch64::LDAPURBi:
4863 case AArch64::LDAPURSBWi:
4864 case AArch64::LDAPURSBXi:
4865 case AArch64::STURBi:
4866 case AArch64::STURBBi:
4867 case AArch64::STLURBi:
4868 Scale = Width = TypeSize::getFixed(1);
4869 MinOffset = -256;
4870 MaxOffset = 255;
4871 break;
4872 // LDP / STP (including pre/post inc)
4873 case AArch64::LDPQi:
4874 case AArch64::LDNPQi:
4875 case AArch64::STPQi:
4876 case AArch64::STNPQi:
4877 case AArch64::LDPQpost:
4878 case AArch64::LDPQpre:
4879 case AArch64::STPQpost:
4880 case AArch64::STPQpre:
4881 Scale = TypeSize::getFixed(16);
4882 Width = TypeSize::getFixed(16 * 2);
4883 MinOffset = -64;
4884 MaxOffset = 63;
4885 break;
4886 case AArch64::LDPXi:
4887 case AArch64::LDPDi:
4888 case AArch64::LDNPXi:
4889 case AArch64::LDNPDi:
4890 case AArch64::STPXi:
4891 case AArch64::STPDi:
4892 case AArch64::STNPXi:
4893 case AArch64::STNPDi:
4894 case AArch64::LDPDpost:
4895 case AArch64::LDPDpre:
4896 case AArch64::LDPXpost:
4897 case AArch64::LDPXpre:
4898 case AArch64::STPDpost:
4899 case AArch64::STPDpre:
4900 case AArch64::STPXpost:
4901 case AArch64::STPXpre:
4902 Scale = TypeSize::getFixed(8);
4903 Width = TypeSize::getFixed(8 * 2);
4904 MinOffset = -64;
4905 MaxOffset = 63;
4906 break;
4907 case AArch64::LDPWi:
4908 case AArch64::LDPSi:
4909 case AArch64::LDNPWi:
4910 case AArch64::LDNPSi:
4911 case AArch64::STPWi:
4912 case AArch64::STPSi:
4913 case AArch64::STNPWi:
4914 case AArch64::STNPSi:
4915 case AArch64::LDPSpost:
4916 case AArch64::LDPSpre:
4917 case AArch64::LDPWpost:
4918 case AArch64::LDPWpre:
4919 case AArch64::STPSpost:
4920 case AArch64::STPSpre:
4921 case AArch64::STPWpost:
4922 case AArch64::STPWpre:
4923 Scale = TypeSize::getFixed(4);
4924 Width = TypeSize::getFixed(4 * 2);
4925 MinOffset = -64;
4926 MaxOffset = 63;
4927 break;
4928 case AArch64::StoreSwiftAsyncContext:
4929 // Store is an STRXui, but there might be an ADDXri in the expansion too.
4930 Scale = TypeSize::getFixed(1);
4931 Width = TypeSize::getFixed(8);
4932 MinOffset = 0;
4933 MaxOffset = 4095;
4934 break;
4935 case AArch64::ADDG:
4936 Scale = TypeSize::getFixed(16);
4937 Width = TypeSize::getFixed(0);
4938 MinOffset = 0;
4939 MaxOffset = 63;
4940 break;
4941 case AArch64::TAGPstack:
4942 Scale = TypeSize::getFixed(16);
4943 Width = TypeSize::getFixed(0);
4944 // TAGP with a negative offset turns into SUBP, which has a maximum offset
4945 // of 63 (not 64!).
4946 MinOffset = -63;
4947 MaxOffset = 63;
4948 break;
4949 case AArch64::LDG:
4950 case AArch64::STGi:
4951 case AArch64::STGPreIndex:
4952 case AArch64::STGPostIndex:
4953 case AArch64::STZGi:
4954 case AArch64::STZGPreIndex:
4955 case AArch64::STZGPostIndex:
4956 Scale = Width = TypeSize::getFixed(16);
4957 MinOffset = -256;
4958 MaxOffset = 255;
4959 break;
4960 // SVE
4961 case AArch64::STR_ZZZZXI:
4962 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4963 case AArch64::LDR_ZZZZXI:
4964 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4965 Scale = TypeSize::getScalable(16);
4966 Width = TypeSize::getScalable(16 * 4);
4967 MinOffset = -256;
4968 MaxOffset = 252;
4969 break;
4970 case AArch64::STR_ZZZXI:
4971 case AArch64::LDR_ZZZXI:
4972 Scale = TypeSize::getScalable(16);
4973 Width = TypeSize::getScalable(16 * 3);
4974 MinOffset = -256;
4975 MaxOffset = 253;
4976 break;
4977 case AArch64::STR_ZZXI:
4978 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4979 case AArch64::LDR_ZZXI:
4980 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4981 Scale = TypeSize::getScalable(16);
4982 Width = TypeSize::getScalable(16 * 2);
4983 MinOffset = -256;
4984 MaxOffset = 254;
4985 break;
4986 case AArch64::LDR_PXI:
4987 case AArch64::STR_PXI:
4988 Scale = Width = TypeSize::getScalable(2);
4989 MinOffset = -256;
4990 MaxOffset = 255;
4991 break;
4992 case AArch64::LDR_PPXI:
4993 case AArch64::STR_PPXI:
4994 Scale = TypeSize::getScalable(2);
4995 Width = TypeSize::getScalable(2 * 2);
4996 MinOffset = -256;
4997 MaxOffset = 254;
4998 break;
4999 case AArch64::LDR_ZXI:
5000 case AArch64::STR_ZXI:
5001 Scale = Width = TypeSize::getScalable(16);
5002 MinOffset = -256;
5003 MaxOffset = 255;
5004 break;
5005 case AArch64::LD1B_IMM:
5006 case AArch64::LD1H_IMM:
5007 case AArch64::LD1W_IMM:
5008 case AArch64::LD1D_IMM:
5009 case AArch64::LDNT1B_ZRI:
5010 case AArch64::LDNT1H_ZRI:
5011 case AArch64::LDNT1W_ZRI:
5012 case AArch64::LDNT1D_ZRI:
5013 case AArch64::ST1B_IMM:
5014 case AArch64::ST1H_IMM:
5015 case AArch64::ST1W_IMM:
5016 case AArch64::ST1D_IMM:
5017 case AArch64::STNT1B_ZRI:
5018 case AArch64::STNT1H_ZRI:
5019 case AArch64::STNT1W_ZRI:
5020 case AArch64::STNT1D_ZRI:
5021 case AArch64::LDNF1B_IMM:
5022 case AArch64::LDNF1H_IMM:
5023 case AArch64::LDNF1W_IMM:
5024 case AArch64::LDNF1D_IMM:
5025 // A full vectors worth of data
5026 // Width = mbytes * elements
5027 Scale = Width = TypeSize::getScalable(16);
5028 MinOffset = -8;
5029 MaxOffset = 7;
5030 break;
5031 case AArch64::LD2B_IMM:
5032 case AArch64::LD2H_IMM:
5033 case AArch64::LD2W_IMM:
5034 case AArch64::LD2D_IMM:
5035 case AArch64::ST2B_IMM:
5036 case AArch64::ST2H_IMM:
5037 case AArch64::ST2W_IMM:
5038 case AArch64::ST2D_IMM:
5039 case AArch64::LD1B_2Z_IMM:
5040 case AArch64::LD1B_2Z_STRIDED_IMM:
5041 case AArch64::LD1H_2Z_IMM:
5042 case AArch64::LD1H_2Z_STRIDED_IMM:
5043 case AArch64::LD1W_2Z_IMM:
5044 case AArch64::LD1W_2Z_STRIDED_IMM:
5045 case AArch64::LD1D_2Z_IMM:
5046 case AArch64::LD1D_2Z_STRIDED_IMM:
5047 case AArch64::LD1B_2Z_IMM_PSEUDO:
5048 case AArch64::LD1H_2Z_IMM_PSEUDO:
5049 case AArch64::LD1W_2Z_IMM_PSEUDO:
5050 case AArch64::LD1D_2Z_IMM_PSEUDO:
5051 case AArch64::ST1B_2Z_IMM:
5052 case AArch64::ST1B_2Z_STRIDED_IMM:
5053 case AArch64::ST1H_2Z_IMM:
5054 case AArch64::ST1H_2Z_STRIDED_IMM:
5055 case AArch64::ST1W_2Z_IMM:
5056 case AArch64::ST1W_2Z_STRIDED_IMM:
5057 case AArch64::ST1D_2Z_IMM:
5058 case AArch64::ST1D_2Z_STRIDED_IMM:
5059 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5060 case AArch64::LDNT1B_2Z_IMM:
5061 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5062 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5063 case AArch64::LDNT1H_2Z_IMM:
5064 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5065 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5066 case AArch64::LDNT1W_2Z_IMM:
5067 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5068 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5069 case AArch64::LDNT1D_2Z_IMM:
5070 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5071 case AArch64::STNT1B_2Z_IMM:
5072 case AArch64::STNT1B_2Z_STRIDED_IMM:
5073 case AArch64::STNT1H_2Z_IMM:
5074 case AArch64::STNT1H_2Z_STRIDED_IMM:
5075 case AArch64::STNT1W_2Z_IMM:
5076 case AArch64::STNT1W_2Z_STRIDED_IMM:
5077 case AArch64::STNT1D_2Z_IMM:
5078 case AArch64::STNT1D_2Z_STRIDED_IMM:
5079 case AArch64::ST1B_2Z_IMM_PSEUDO:
5080 case AArch64::ST1H_2Z_IMM_PSEUDO:
5081 case AArch64::ST1W_2Z_IMM_PSEUDO:
5082 case AArch64::ST1D_2Z_IMM_PSEUDO:
5083 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5084 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5085 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5086 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5087 Scale = Width = TypeSize::getScalable(16 * 2);
5088 MinOffset = -8;
5089 MaxOffset = 7;
5090 break;
5091 case AArch64::LD3B_IMM:
5092 case AArch64::LD3H_IMM:
5093 case AArch64::LD3W_IMM:
5094 case AArch64::LD3D_IMM:
5095 case AArch64::ST3B_IMM:
5096 case AArch64::ST3H_IMM:
5097 case AArch64::ST3W_IMM:
5098 case AArch64::ST3D_IMM:
5099 Scale = Width = TypeSize::getScalable(16 * 3);
5100 MinOffset = -8;
5101 MaxOffset = 7;
5102 break;
5103 case AArch64::LD4B_IMM:
5104 case AArch64::LD4H_IMM:
5105 case AArch64::LD4W_IMM:
5106 case AArch64::LD4D_IMM:
5107 case AArch64::ST4B_IMM:
5108 case AArch64::ST4H_IMM:
5109 case AArch64::ST4W_IMM:
5110 case AArch64::ST4D_IMM:
5111 case AArch64::LD1B_4Z_IMM:
5112 case AArch64::LD1B_4Z_STRIDED_IMM:
5113 case AArch64::LD1H_4Z_IMM:
5114 case AArch64::LD1H_4Z_STRIDED_IMM:
5115 case AArch64::LD1W_4Z_IMM:
5116 case AArch64::LD1W_4Z_STRIDED_IMM:
5117 case AArch64::LD1D_4Z_IMM:
5118 case AArch64::LD1D_4Z_STRIDED_IMM:
5119 case AArch64::LD1B_4Z_IMM_PSEUDO:
5120 case AArch64::LD1H_4Z_IMM_PSEUDO:
5121 case AArch64::LD1W_4Z_IMM_PSEUDO:
5122 case AArch64::LD1D_4Z_IMM_PSEUDO:
5123 case AArch64::ST1B_4Z_IMM:
5124 case AArch64::ST1B_4Z_STRIDED_IMM:
5125 case AArch64::ST1H_4Z_IMM:
5126 case AArch64::ST1H_4Z_STRIDED_IMM:
5127 case AArch64::ST1W_4Z_IMM:
5128 case AArch64::ST1W_4Z_STRIDED_IMM:
5129 case AArch64::ST1D_4Z_IMM:
5130 case AArch64::ST1D_4Z_STRIDED_IMM:
5131 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5132 case AArch64::LDNT1B_4Z_IMM:
5133 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5134 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5135 case AArch64::LDNT1H_4Z_IMM:
5136 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5137 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5138 case AArch64::LDNT1W_4Z_IMM:
5139 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5140 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5141 case AArch64::LDNT1D_4Z_IMM:
5142 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5143 case AArch64::STNT1B_4Z_IMM:
5144 case AArch64::STNT1B_4Z_STRIDED_IMM:
5145 case AArch64::STNT1H_4Z_IMM:
5146 case AArch64::STNT1H_4Z_STRIDED_IMM:
5147 case AArch64::STNT1W_4Z_IMM:
5148 case AArch64::STNT1W_4Z_STRIDED_IMM:
5149 case AArch64::STNT1D_4Z_IMM:
5150 case AArch64::STNT1D_4Z_STRIDED_IMM:
5151 case AArch64::ST1B_4Z_IMM_PSEUDO:
5152 case AArch64::ST1H_4Z_IMM_PSEUDO:
5153 case AArch64::ST1W_4Z_IMM_PSEUDO:
5154 case AArch64::ST1D_4Z_IMM_PSEUDO:
5155 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5156 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5157 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5158 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5159 Scale = Width = TypeSize::getScalable(16 * 4);
5160 MinOffset = -8;
5161 MaxOffset = 7;
5162 break;
5163 case AArch64::LD1B_H_IMM:
5164 case AArch64::LD1SB_H_IMM:
5165 case AArch64::LD1H_S_IMM:
5166 case AArch64::LD1SH_S_IMM:
5167 case AArch64::LD1W_D_IMM:
5168 case AArch64::LD1SW_D_IMM:
5169 case AArch64::ST1B_H_IMM:
5170 case AArch64::ST1H_S_IMM:
5171 case AArch64::ST1W_D_IMM:
5172 case AArch64::LDNF1B_H_IMM:
5173 case AArch64::LDNF1SB_H_IMM:
5174 case AArch64::LDNF1H_S_IMM:
5175 case AArch64::LDNF1SH_S_IMM:
5176 case AArch64::LDNF1W_D_IMM:
5177 case AArch64::LDNF1SW_D_IMM:
5178 // A half vector worth of data
5179 // Width = mbytes * elements
5180 Scale = Width = TypeSize::getScalable(8);
5181 MinOffset = -8;
5182 MaxOffset = 7;
5183 break;
5184 case AArch64::LD1B_S_IMM:
5185 case AArch64::LD1SB_S_IMM:
5186 case AArch64::LD1H_D_IMM:
5187 case AArch64::LD1SH_D_IMM:
5188 case AArch64::ST1B_S_IMM:
5189 case AArch64::ST1H_D_IMM:
5190 case AArch64::LDNF1B_S_IMM:
5191 case AArch64::LDNF1SB_S_IMM:
5192 case AArch64::LDNF1H_D_IMM:
5193 case AArch64::LDNF1SH_D_IMM:
5194 // A quarter vector worth of data
5195 // Width = mbytes * elements
5196 Scale = Width = TypeSize::getScalable(4);
5197 MinOffset = -8;
5198 MaxOffset = 7;
5199 break;
5200 case AArch64::LD1B_D_IMM:
5201 case AArch64::LD1SB_D_IMM:
5202 case AArch64::ST1B_D_IMM:
5203 case AArch64::LDNF1B_D_IMM:
5204 case AArch64::LDNF1SB_D_IMM:
5205 // A eighth vector worth of data
5206 // Width = mbytes * elements
5207 Scale = Width = TypeSize::getScalable(2);
5208 MinOffset = -8;
5209 MaxOffset = 7;
5210 break;
5211 case AArch64::ST2Gi:
5212 case AArch64::ST2GPreIndex:
5213 case AArch64::ST2GPostIndex:
5214 case AArch64::STZ2Gi:
5215 case AArch64::STZ2GPreIndex:
5216 case AArch64::STZ2GPostIndex:
5217 Scale = TypeSize::getFixed(16);
5218 Width = TypeSize::getFixed(32);
5219 MinOffset = -256;
5220 MaxOffset = 255;
5221 break;
5222 case AArch64::STGPi:
5223 case AArch64::STGPpost:
5224 case AArch64::STGPpre:
5225 Scale = Width = TypeSize::getFixed(16);
5226 MinOffset = -64;
5227 MaxOffset = 63;
5228 break;
5229 case AArch64::LD1RB_IMM:
5230 case AArch64::LD1RB_H_IMM:
5231 case AArch64::LD1RB_S_IMM:
5232 case AArch64::LD1RB_D_IMM:
5233 case AArch64::LD1RSB_H_IMM:
5234 case AArch64::LD1RSB_S_IMM:
5235 case AArch64::LD1RSB_D_IMM:
5236 Scale = Width = TypeSize::getFixed(1);
5237 MinOffset = 0;
5238 MaxOffset = 63;
5239 break;
5240 case AArch64::LD1RH_IMM:
5241 case AArch64::LD1RH_S_IMM:
5242 case AArch64::LD1RH_D_IMM:
5243 case AArch64::LD1RSH_S_IMM:
5244 case AArch64::LD1RSH_D_IMM:
5245 Scale = Width = TypeSize::getFixed(2);
5246 MinOffset = 0;
5247 MaxOffset = 63;
5248 break;
5249 case AArch64::LD1RW_IMM:
5250 case AArch64::LD1RW_D_IMM:
5251 case AArch64::LD1RSW_IMM:
5252 Scale = Width = TypeSize::getFixed(4);
5253 MinOffset = 0;
5254 MaxOffset = 63;
5255 break;
5256 case AArch64::LD1RD_IMM:
5257 Scale = Width = TypeSize::getFixed(8);
5258 MinOffset = 0;
5259 MaxOffset = 63;
5260 break;
5261 }
5262
5263 return true;
5264}
5265
5266// Scaling factor for unscaled load or store.
5268 switch (Opc) {
5269 default:
5270 llvm_unreachable("Opcode has unknown scale!");
5271 case AArch64::LDRBui:
5272 case AArch64::LDRBBui:
5273 case AArch64::LDURBBi:
5274 case AArch64::LDRSBWui:
5275 case AArch64::LDURSBWi:
5276 case AArch64::STRBui:
5277 case AArch64::STRBBui:
5278 case AArch64::STURBBi:
5279 return 1;
5280 case AArch64::LDRHui:
5281 case AArch64::LDRHHui:
5282 case AArch64::LDURHHi:
5283 case AArch64::LDRSHWui:
5284 case AArch64::LDURSHWi:
5285 case AArch64::STRHui:
5286 case AArch64::STRHHui:
5287 case AArch64::STURHHi:
5288 return 2;
5289 case AArch64::LDRSui:
5290 case AArch64::LDURSi:
5291 case AArch64::LDRSpre:
5292 case AArch64::LDRSWui:
5293 case AArch64::LDURSWi:
5294 case AArch64::LDRSWpre:
5295 case AArch64::LDRWpre:
5296 case AArch64::LDRWui:
5297 case AArch64::LDURWi:
5298 case AArch64::STRSui:
5299 case AArch64::STURSi:
5300 case AArch64::STRSpre:
5301 case AArch64::STRWui:
5302 case AArch64::STURWi:
5303 case AArch64::STRWpre:
5304 case AArch64::LDPSi:
5305 case AArch64::LDPSWi:
5306 case AArch64::LDPWi:
5307 case AArch64::STPSi:
5308 case AArch64::STPWi:
5309 return 4;
5310 case AArch64::LDRDui:
5311 case AArch64::LDURDi:
5312 case AArch64::LDRDpre:
5313 case AArch64::LDRXui:
5314 case AArch64::LDURXi:
5315 case AArch64::LDRXpre:
5316 case AArch64::STRDui:
5317 case AArch64::STURDi:
5318 case AArch64::STRDpre:
5319 case AArch64::STRXui:
5320 case AArch64::STURXi:
5321 case AArch64::STRXpre:
5322 case AArch64::LDPDi:
5323 case AArch64::LDPXi:
5324 case AArch64::STPDi:
5325 case AArch64::STPXi:
5326 return 8;
5327 case AArch64::LDRQui:
5328 case AArch64::LDURQi:
5329 case AArch64::STRQui:
5330 case AArch64::STURQi:
5331 case AArch64::STRQpre:
5332 case AArch64::LDPQi:
5333 case AArch64::LDRQpre:
5334 case AArch64::STPQi:
5335 case AArch64::STGi:
5336 case AArch64::STZGi:
5337 case AArch64::ST2Gi:
5338 case AArch64::STZ2Gi:
5339 case AArch64::STGPi:
5340 return 16;
5341 }
5342}
5343
5345 switch (MI.getOpcode()) {
5346 default:
5347 return false;
5348 case AArch64::LDRWpre:
5349 case AArch64::LDRXpre:
5350 case AArch64::LDRSWpre:
5351 case AArch64::LDRSpre:
5352 case AArch64::LDRDpre:
5353 case AArch64::LDRQpre:
5354 return true;
5355 }
5356}
5357
5359 switch (MI.getOpcode()) {
5360 default:
5361 return false;
5362 case AArch64::STRWpre:
5363 case AArch64::STRXpre:
5364 case AArch64::STRSpre:
5365 case AArch64::STRDpre:
5366 case AArch64::STRQpre:
5367 return true;
5368 }
5369}
5370
5372 return isPreLd(MI) || isPreSt(MI);
5373}
5374
5376 switch (MI.getOpcode()) {
5377 default:
5378 return false;
5379 case AArch64::LDURBBi:
5380 case AArch64::LDURHHi:
5381 case AArch64::LDURWi:
5382 case AArch64::LDRBBui:
5383 case AArch64::LDRHHui:
5384 case AArch64::LDRWui:
5385 case AArch64::LDRBBroX:
5386 case AArch64::LDRHHroX:
5387 case AArch64::LDRWroX:
5388 case AArch64::LDRBBroW:
5389 case AArch64::LDRHHroW:
5390 case AArch64::LDRWroW:
5391 return true;
5392 }
5393}
5394
5396 switch (MI.getOpcode()) {
5397 default:
5398 return false;
5399 case AArch64::LDURSBWi:
5400 case AArch64::LDURSHWi:
5401 case AArch64::LDURSBXi:
5402 case AArch64::LDURSHXi:
5403 case AArch64::LDURSWi:
5404 case AArch64::LDRSBWui:
5405 case AArch64::LDRSHWui:
5406 case AArch64::LDRSBXui:
5407 case AArch64::LDRSHXui:
5408 case AArch64::LDRSWui:
5409 case AArch64::LDRSBWroX:
5410 case AArch64::LDRSHWroX:
5411 case AArch64::LDRSBXroX:
5412 case AArch64::LDRSHXroX:
5413 case AArch64::LDRSWroX:
5414 case AArch64::LDRSBWroW:
5415 case AArch64::LDRSHWroW:
5416 case AArch64::LDRSBXroW:
5417 case AArch64::LDRSHXroW:
5418 case AArch64::LDRSWroW:
5419 return true;
5420 }
5421}
5422
5424 switch (MI.getOpcode()) {
5425 default:
5426 return false;
5427 case AArch64::LDPSi:
5428 case AArch64::LDPSWi:
5429 case AArch64::LDPDi:
5430 case AArch64::LDPQi:
5431 case AArch64::LDPWi:
5432 case AArch64::LDPXi:
5433 case AArch64::STPSi:
5434 case AArch64::STPDi:
5435 case AArch64::STPQi:
5436 case AArch64::STPWi:
5437 case AArch64::STPXi:
5438 case AArch64::STGPi:
5439 return true;
5440 }
5441}
5442
5444 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5445 unsigned Idx =
5447 : 1;
5448 return MI.getOperand(Idx);
5449}
5450
5451const MachineOperand &
5453 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5454 unsigned Idx =
5456 : 2;
5457 return MI.getOperand(Idx);
5458}
5459
5460const MachineOperand &
5462 switch (MI.getOpcode()) {
5463 default:
5464 llvm_unreachable("Unexpected opcode");
5465 case AArch64::LDRBroX:
5466 case AArch64::LDRBBroX:
5467 case AArch64::LDRSBXroX:
5468 case AArch64::LDRSBWroX:
5469 case AArch64::LDRHroX:
5470 case AArch64::LDRHHroX:
5471 case AArch64::LDRSHXroX:
5472 case AArch64::LDRSHWroX:
5473 case AArch64::LDRWroX:
5474 case AArch64::LDRSroX:
5475 case AArch64::LDRSWroX:
5476 case AArch64::LDRDroX:
5477 case AArch64::LDRXroX:
5478 case AArch64::LDRQroX:
5479 return MI.getOperand(4);
5480 }
5481}
5482
5484 Register Reg) {
5485 if (MI.getParent() == nullptr)
5486 return nullptr;
5487 const MachineFunction *MF = MI.getParent()->getParent();
5488 return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr;
5489}
5490
5492 auto IsHFPR = [&](const MachineOperand &Op) {
5493 if (!Op.isReg())
5494 return false;
5495 auto Reg = Op.getReg();
5496 if (Reg.isPhysical())
5497 return AArch64::FPR16RegClass.contains(Reg);
5498 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5499 return TRC == &AArch64::FPR16RegClass ||
5500 TRC == &AArch64::FPR16_loRegClass;
5501 };
5502 return llvm::any_of(MI.operands(), IsHFPR);
5503}
5504
5506 auto IsQFPR = [&](const MachineOperand &Op) {
5507 if (!Op.isReg())
5508 return false;
5509 auto Reg = Op.getReg();
5510 if (Reg.isPhysical())
5511 return AArch64::FPR128RegClass.contains(Reg);
5512 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5513 return TRC == &AArch64::FPR128RegClass ||
5514 TRC == &AArch64::FPR128_loRegClass;
5515 };
5516 return llvm::any_of(MI.operands(), IsQFPR);
5517}
5518
5520 switch (MI.getOpcode()) {
5521 case AArch64::BRK:
5522 case AArch64::HLT:
5523 case AArch64::PACIASP:
5524 case AArch64::PACIBSP:
5525 // Implicit BTI behavior.
5526 return true;
5527 case AArch64::PAUTH_PROLOGUE:
5528 // PAUTH_PROLOGUE expands to PACI(A|B)SP.
5529 return true;
5530 case AArch64::HINT: {
5531 unsigned Imm = MI.getOperand(0).getImm();
5532 // Explicit BTI instruction.
5533 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5534 return true;
5535 // PACI(A|B)SP instructions.
5536 if (Imm == 25 || Imm == 27)
5537 return true;
5538 return false;
5539 }
5540 default:
5541 return false;
5542 }
5543}
5544
5546 if (Reg == 0)
5547 return false;
5548 assert(Reg.isPhysical() && "Expected physical register in isFpOrNEON");
5549 return AArch64::FPR128RegClass.contains(Reg) ||
5550 AArch64::FPR64RegClass.contains(Reg) ||
5551 AArch64::FPR32RegClass.contains(Reg) ||
5552 AArch64::FPR16RegClass.contains(Reg) ||
5553 AArch64::FPR8RegClass.contains(Reg);
5554}
5555
5557 auto IsFPR = [&](const MachineOperand &Op) {
5558 if (!Op.isReg())
5559 return false;
5560 auto Reg = Op.getReg();
5561 if (Reg.isPhysical())
5562 return isFpOrNEON(Reg);
5563
5564 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5565 return TRC == &AArch64::FPR128RegClass ||
5566 TRC == &AArch64::FPR128_loRegClass ||
5567 TRC == &AArch64::FPR64RegClass ||
5568 TRC == &AArch64::FPR64_loRegClass ||
5569 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5570 TRC == &AArch64::FPR8RegClass;
5571 };
5572 return llvm::any_of(MI.operands(), IsFPR);
5573}
5574
5575// Scale the unscaled offsets. Returns false if the unscaled offset can't be
5576// scaled.
5577static bool scaleOffset(unsigned Opc, int64_t &Offset) {
5579
5580 // If the byte-offset isn't a multiple of the stride, we can't scale this
5581 // offset.
5582 if (Offset % Scale != 0)
5583 return false;
5584
5585 // Convert the byte-offset used by unscaled into an "element" offset used
5586 // by the scaled pair load/store instructions.
5587 Offset /= Scale;
5588 return true;
5589}
5590
5591static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
5592 if (FirstOpc == SecondOpc)
5593 return true;
5594 // We can also pair sign-ext and zero-ext instructions.
5595 switch (FirstOpc) {
5596 default:
5597 return false;
5598 case AArch64::STRSui:
5599 case AArch64::STURSi:
5600 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5601 case AArch64::STRDui:
5602 case AArch64::STURDi:
5603 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5604 case AArch64::STRQui:
5605 case AArch64::STURQi:
5606 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5607 case AArch64::STRWui:
5608 case AArch64::STURWi:
5609 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5610 case AArch64::STRXui:
5611 case AArch64::STURXi:
5612 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5613 case AArch64::LDRSui:
5614 case AArch64::LDURSi:
5615 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5616 case AArch64::LDRDui:
5617 case AArch64::LDURDi:
5618 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5619 case AArch64::LDRQui:
5620 case AArch64::LDURQi:
5621 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5622 case AArch64::LDRWui:
5623 case AArch64::LDURWi:
5624 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5625 case AArch64::LDRSWui:
5626 case AArch64::LDURSWi:
5627 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5628 case AArch64::LDRXui:
5629 case AArch64::LDURXi:
5630 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5631 }
5632 // These instructions can't be paired based on their opcodes.
5633 return false;
5634}
5635
5636static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1,
5637 int64_t Offset1, unsigned Opcode1, int FI2,
5638 int64_t Offset2, unsigned Opcode2) {
5639 // Accesses through fixed stack object frame indices may access a different
5640 // fixed stack slot. Check that the object offsets + offsets match.
5641 if (MFI.isFixedObjectIndex(FI1) && MFI.isFixedObjectIndex(FI2)) {
5642 int64_t ObjectOffset1 = MFI.getObjectOffset(FI1);
5643 int64_t ObjectOffset2 = MFI.getObjectOffset(FI2);
5644 assert(ObjectOffset1 <= ObjectOffset2 && "Object offsets are not ordered.");
5645 // Convert to scaled object offsets.
5646 int Scale1 = AArch64InstrInfo::getMemScale(Opcode1);
5647 if (ObjectOffset1 % Scale1 != 0)
5648 return false;
5649 ObjectOffset1 /= Scale1;
5650 int Scale2 = AArch64InstrInfo::getMemScale(Opcode2);
5651 if (ObjectOffset2 % Scale2 != 0)
5652 return false;
5653 ObjectOffset2 /= Scale2;
5654 ObjectOffset1 += Offset1;
5655 ObjectOffset2 += Offset2;
5656 return ObjectOffset1 + 1 == ObjectOffset2;
5657 }
5658
5659 return FI1 == FI2;
5660}
5661
5662/// Detect opportunities for ldp/stp formation.
5663///
5664/// Only called for LdSt for which getMemOperandWithOffset returns true.
5666 ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
5667 bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
5668 int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
5669 unsigned NumBytes) const {
5670 assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
5671 const MachineOperand &BaseOp1 = *BaseOps1.front();
5672 const MachineOperand &BaseOp2 = *BaseOps2.front();
5673 const MachineInstr &FirstLdSt = *BaseOp1.getParent();
5674 const MachineInstr &SecondLdSt = *BaseOp2.getParent();
5675 if (BaseOp1.getType() != BaseOp2.getType())
5676 return false;
5677
5678 assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
5679 "Only base registers and frame indices are supported.");
5680
5681 // Check for both base regs and base FI.
5682 if (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg())
5683 return false;
5684
5685 // Only cluster up to a single pair.
5686 if (ClusterSize > 2)
5687 return false;
5688
5689 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
5690 return false;
5691
5692 // Can we pair these instructions based on their opcodes?
5693 unsigned FirstOpc = FirstLdSt.getOpcode();
5694 unsigned SecondOpc = SecondLdSt.getOpcode();
5695 if (!canPairLdStOpc(FirstOpc, SecondOpc))
5696 return false;
5697
5698 // Can't merge volatiles or load/stores that have a hint to avoid pair
5699 // formation, for example.
5700 if (!isCandidateToMergeOrPair(FirstLdSt) ||
5701 !isCandidateToMergeOrPair(SecondLdSt))
5702 return false;
5703
5704 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
5705 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
5706 if (hasUnscaledLdStOffset(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
5707 return false;
5708
5709 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
5710 if (hasUnscaledLdStOffset(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
5711 return false;
5712
5713 // Pairwise instructions have a 7-bit signed offset field.
5714 if (Offset1 > 63 || Offset1 < -64)
5715 return false;
5716
5717 // The caller should already have ordered First/SecondLdSt by offset.
5718 // Note: except for non-equal frame index bases
5719 if (BaseOp1.isFI()) {
5720 assert((!BaseOp1.isIdenticalTo(BaseOp2) || Offset1 <= Offset2) &&
5721 "Caller should have ordered offsets.");
5722
5723 const MachineFrameInfo &MFI =
5724 FirstLdSt.getParent()->getParent()->getFrameInfo();
5725 return shouldClusterFI(MFI, BaseOp1.getIndex(), Offset1, FirstOpc,
5726 BaseOp2.getIndex(), Offset2, SecondOpc);
5727 }
5728
5729 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
5730
5731 return Offset1 + 1 == Offset2;
5732}
5733
5735 MCRegister Reg, unsigned SubIdx,
5736 RegState State,
5737 const TargetRegisterInfo *TRI) {
5738 if (!SubIdx)
5739 return MIB.addReg(Reg, State);
5740
5741 if (Reg.isPhysical())
5742 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
5743 return MIB.addReg(Reg, State, SubIdx);
5744}
5745
5746static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg,
5747 unsigned NumRegs) {
5748 // We really want the positive remainder mod 32 here, that happens to be
5749 // easily obtainable with a mask.
5750 return ((DestReg - SrcReg) & 0x1f) < NumRegs;
5751}
5752
5755 const DebugLoc &DL, MCRegister DestReg,
5756 MCRegister SrcReg, bool KillSrc,
5757 unsigned Opcode,
5758 ArrayRef<unsigned> Indices) const {
5759 assert(Subtarget.hasNEON() && "Unexpected register copy without NEON");
5761 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5762 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5763 unsigned NumRegs = Indices.size();
5764
5765 int SubReg = 0, End = NumRegs, Incr = 1;
5766 if (forwardCopyWillClobberTuple(DestEncoding, SrcEncoding, NumRegs)) {
5767 SubReg = NumRegs - 1;
5768 End = -1;
5769 Incr = -1;
5770 }
5771
5772 for (; SubReg != End; SubReg += Incr) {
5773 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5774 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5775 AddSubReg(MIB, SrcReg, Indices[SubReg], {}, TRI);
5776 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5777 }
5778}
5779
5782 const DebugLoc &DL, MCRegister DestReg,
5783 MCRegister SrcReg, bool KillSrc,
5784 unsigned Opcode, unsigned ZeroReg,
5785 llvm::ArrayRef<unsigned> Indices) const {
5787 unsigned NumRegs = Indices.size();
5788
5789#ifndef NDEBUG
5790 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5791 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5792 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5793 "GPR reg sequences should not be able to overlap");
5794#endif
5795
5796 for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5797 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5798 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5799 MIB.addReg(ZeroReg);
5800 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5801 MIB.addImm(0);
5802 }
5803}
5804
5805/// Returns true if the instruction at I is in a streaming call site region,
5806/// within a single basic block.
5807/// A "call site streaming region" starts after smstart and ends at smstop
5808/// around a call to a streaming function. This walks backward from I.
5811 MachineFunction &MF = *MBB.getParent();
5813 if (!AFI->hasStreamingModeChanges())
5814 return false;
5815 // Walk backwards to find smstart/smstop
5816 for (MachineInstr &MI : reverse(make_range(MBB.begin(), I))) {
5817 unsigned Opc = MI.getOpcode();
5818 if (Opc == AArch64::MSRpstatesvcrImm1 || Opc == AArch64::MSRpstatePseudo) {
5819 // Check if this is SM change (not ZA)
5820 int64_t PState = MI.getOperand(0).getImm();
5821 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5822 // Operand 1 is 1 for start, 0 for stop
5823 return MI.getOperand(1).getImm() == 1;
5824 }
5825 }
5826 }
5827 return false;
5828}
5829
5830/// Returns true if in a streaming call site region without SME-FA64.
5831static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget,
5834 return !Subtarget.hasSMEFA64() && isInStreamingCallSiteRegion(MBB, I);
5835}
5836
5839 const DebugLoc &DL, Register DestReg,
5840 Register SrcReg, bool KillSrc,
5841 bool RenamableDest,
5842 bool RenamableSrc) const {
5843 ++NumCopyInstrs;
5844 if (AArch64::GPR32spRegClass.contains(DestReg) &&
5845 AArch64::GPR32spRegClass.contains(SrcReg)) {
5846 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5847 // If either operand is WSP, expand to ADD #0.
5848 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5849 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5850 // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
5851 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5852 &AArch64::GPR64spRegClass);
5853 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5854 &AArch64::GPR64spRegClass);
5855 // This instruction is reading and writing X registers. This may upset
5856 // the register scavenger and machine verifier, so we need to indicate
5857 // that we are reading an undefined value from SrcRegX, but a proper
5858 // value from SrcReg.
5859 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
5860 .addReg(SrcRegX, RegState::Undef)
5861 .addImm(0)
5863 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5864 ++NumZCRegMoveInstrsGPR;
5865 } else {
5866 BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
5867 .addReg(SrcReg, getKillRegState(KillSrc))
5868 .addImm(0)
5870 if (Subtarget.hasZeroCycleRegMoveGPR32())
5871 ++NumZCRegMoveInstrsGPR;
5872 }
5873 } else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5874 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5875 // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
5876 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5877 &AArch64::GPR64spRegClass);
5878 assert(DestRegX.isValid() && "Destination super-reg not valid");
5879 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5880 &AArch64::GPR64spRegClass);
5881 assert(SrcRegX.isValid() && "Source super-reg not valid");
5882 // This instruction is reading and writing X registers. This may upset
5883 // the register scavenger and machine verifier, so we need to indicate
5884 // that we are reading an undefined value from SrcRegX, but a proper
5885 // value from SrcReg.
5886 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
5887 .addReg(AArch64::XZR)
5888 .addReg(SrcRegX, RegState::Undef)
5889 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5890 ++NumZCRegMoveInstrsGPR;
5891 } else {
5892 // Otherwise, expand to ORR WZR.
5893 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5894 .addReg(AArch64::WZR)
5895 .addReg(SrcReg, getKillRegState(KillSrc));
5896 if (Subtarget.hasZeroCycleRegMoveGPR32())
5897 ++NumZCRegMoveInstrsGPR;
5898 }
5899 return;
5900 }
5901
5902 // GPR32 zeroing
5903 if (AArch64::GPR32spRegClass.contains(DestReg) && SrcReg == AArch64::WZR) {
5904 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5905 !Subtarget.hasZeroCycleZeroingGPR32()) {
5906 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5907 &AArch64::GPR64spRegClass);
5908 assert(DestRegX.isValid() && "Destination super-reg not valid");
5909 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestRegX)
5910 .addImm(0)
5912 ++NumZCZeroingInstrsGPR;
5913 } else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5914 BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg)
5915 .addImm(0)
5917 ++NumZCZeroingInstrsGPR;
5918 } else {
5919 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5920 .addReg(AArch64::WZR)
5921 .addReg(AArch64::WZR);
5922 }
5923 return;
5924 }
5925
5926 if (AArch64::GPR64spRegClass.contains(DestReg) &&
5927 AArch64::GPR64spRegClass.contains(SrcReg)) {
5928 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5929 // If either operand is SP, expand to ADD #0.
5930 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
5931 .addReg(SrcReg, getKillRegState(KillSrc))
5932 .addImm(0)
5934 if (Subtarget.hasZeroCycleRegMoveGPR64())
5935 ++NumZCRegMoveInstrsGPR;
5936 } else {
5937 // Otherwise, expand to ORR XZR.
5938 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5939 .addReg(AArch64::XZR)
5940 .addReg(SrcReg, getKillRegState(KillSrc));
5941 if (Subtarget.hasZeroCycleRegMoveGPR64())
5942 ++NumZCRegMoveInstrsGPR;
5943 }
5944 return;
5945 }
5946
5947 // GPR64 zeroing
5948 if (AArch64::GPR64spRegClass.contains(DestReg) && SrcReg == AArch64::XZR) {
5949 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5950 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg)
5951 .addImm(0)
5953 ++NumZCZeroingInstrsGPR;
5954 } else {
5955 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5956 .addReg(AArch64::XZR)
5957 .addReg(AArch64::XZR);
5958 }
5959 return;
5960 }
5961
5962 // Copy a Predicate register by ORRing with itself.
5963 if (AArch64::PPRRegClass.contains(DestReg) &&
5964 AArch64::PPRRegClass.contains(SrcReg)) {
5965 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5966 "Unexpected SVE register.");
5967 BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), DestReg)
5968 .addReg(SrcReg) // Pg
5969 .addReg(SrcReg)
5970 .addReg(SrcReg, getKillRegState(KillSrc));
5971 return;
5972 }
5973
5974 // Copy a predicate-as-counter register by ORRing with itself as if it
5975 // were a regular predicate (mask) register.
5976 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
5977 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
5978 if (DestIsPNR || SrcIsPNR) {
5979 auto ToPPR = [](MCRegister R) -> MCRegister {
5980 return (R - AArch64::PN0) + AArch64::P0;
5981 };
5982 MCRegister PPRSrcReg = SrcIsPNR ? ToPPR(SrcReg) : SrcReg.asMCReg();
5983 MCRegister PPRDestReg = DestIsPNR ? ToPPR(DestReg) : DestReg.asMCReg();
5984
5985 if (PPRSrcReg != PPRDestReg) {
5986 auto NewMI = BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), PPRDestReg)
5987 .addReg(PPRSrcReg) // Pg
5988 .addReg(PPRSrcReg)
5989 .addReg(PPRSrcReg, getKillRegState(KillSrc));
5990 if (DestIsPNR)
5991 NewMI.addDef(DestReg, RegState::Implicit);
5992 }
5993 return;
5994 }
5995
5996 // Copy a Z register by ORRing with itself.
5997 if (AArch64::ZPRRegClass.contains(DestReg) &&
5998 AArch64::ZPRRegClass.contains(SrcReg)) {
5999 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6000 "Unexpected SVE register.");
6001 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ), DestReg)
6002 .addReg(SrcReg)
6003 .addReg(SrcReg, getKillRegState(KillSrc));
6004 return;
6005 }
6006
6007 // Copy a Z register pair by copying the individual sub-registers.
6008 if ((AArch64::ZPR2RegClass.contains(DestReg) ||
6009 AArch64::ZPR2StridedOrContiguousRegClass.contains(DestReg)) &&
6010 (AArch64::ZPR2RegClass.contains(SrcReg) ||
6011 AArch64::ZPR2StridedOrContiguousRegClass.contains(SrcReg))) {
6012 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6013 "Unexpected SVE register.");
6014 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6015 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6016 Indices);
6017 return;
6018 }
6019
6020 // Copy a Z register triple by copying the individual sub-registers.
6021 if (AArch64::ZPR3RegClass.contains(DestReg) &&
6022 AArch64::ZPR3RegClass.contains(SrcReg)) {
6023 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6024 "Unexpected SVE register.");
6025 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6026 AArch64::zsub2};
6027 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6028 Indices);
6029 return;
6030 }
6031
6032 // Copy a Z register quad by copying the individual sub-registers.
6033 if ((AArch64::ZPR4RegClass.contains(DestReg) ||
6034 AArch64::ZPR4StridedOrContiguousRegClass.contains(DestReg)) &&
6035 (AArch64::ZPR4RegClass.contains(SrcReg) ||
6036 AArch64::ZPR4StridedOrContiguousRegClass.contains(SrcReg))) {
6037 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6038 "Unexpected SVE register.");
6039 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6040 AArch64::zsub2, AArch64::zsub3};
6041 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6042 Indices);
6043 return;
6044 }
6045
6046 // Copy a DDDD register quad by copying the individual sub-registers.
6047 if (AArch64::DDDDRegClass.contains(DestReg) &&
6048 AArch64::DDDDRegClass.contains(SrcReg)) {
6049 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6050 AArch64::dsub2, AArch64::dsub3};
6051 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6052 Indices);
6053 return;
6054 }
6055
6056 // Copy a DDD register triple by copying the individual sub-registers.
6057 if (AArch64::DDDRegClass.contains(DestReg) &&
6058 AArch64::DDDRegClass.contains(SrcReg)) {
6059 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6060 AArch64::dsub2};
6061 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6062 Indices);
6063 return;
6064 }
6065
6066 // Copy a DD register pair by copying the individual sub-registers.
6067 if (AArch64::DDRegClass.contains(DestReg) &&
6068 AArch64::DDRegClass.contains(SrcReg)) {
6069 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6070 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6071 Indices);
6072 return;
6073 }
6074
6075 // Copy a QQQQ register quad by copying the individual sub-registers.
6076 if (AArch64::QQQQRegClass.contains(DestReg) &&
6077 AArch64::QQQQRegClass.contains(SrcReg)) {
6078 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6079 AArch64::qsub2, AArch64::qsub3};
6080 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6081 Indices);
6082 return;
6083 }
6084
6085 // Copy a QQQ register triple by copying the individual sub-registers.
6086 if (AArch64::QQQRegClass.contains(DestReg) &&
6087 AArch64::QQQRegClass.contains(SrcReg)) {
6088 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6089 AArch64::qsub2};
6090 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6091 Indices);
6092 return;
6093 }
6094
6095 // Copy a QQ register pair by copying the individual sub-registers.
6096 if (AArch64::QQRegClass.contains(DestReg) &&
6097 AArch64::QQRegClass.contains(SrcReg)) {
6098 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6099 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6100 Indices);
6101 return;
6102 }
6103
6104 if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
6105 AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
6106 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6107 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
6108 AArch64::XZR, Indices);
6109 return;
6110 }
6111
6112 if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
6113 AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
6114 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6115 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
6116 AArch64::WZR, Indices);
6117 return;
6118 }
6119
6120 if (AArch64::FPR128RegClass.contains(DestReg) &&
6121 AArch64::FPR128RegClass.contains(SrcReg)) {
6122 // In streaming regions, NEON is illegal but streaming-SVE is available.
6123 // Use SVE for copies if we're in a streaming region and SME is available.
6124 // With +sme-fa64, NEON is legal in streaming mode so we can use it.
6125 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6126 !Subtarget.isNeonAvailable()) ||
6127 mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6128 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ))
6129 .addReg(AArch64::Z0 + (DestReg - AArch64::Q0), RegState::Define)
6130 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6131 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6132 } else if (Subtarget.isNeonAvailable()) {
6133 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
6134 .addReg(SrcReg)
6135 .addReg(SrcReg, getKillRegState(KillSrc));
6136 if (Subtarget.hasZeroCycleRegMoveFPR128())
6137 ++NumZCRegMoveInstrsFPR;
6138 } else {
6139 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
6140 .addReg(AArch64::SP, RegState::Define)
6141 .addReg(SrcReg, getKillRegState(KillSrc))
6142 .addReg(AArch64::SP)
6143 .addImm(-16);
6144 BuildMI(MBB, I, DL, get(AArch64::LDRQpost))
6145 .addReg(AArch64::SP, RegState::Define)
6146 .addReg(DestReg, RegState::Define)
6147 .addReg(AArch64::SP)
6148 .addImm(16);
6149 }
6150 return;
6151 }
6152
6153 if (AArch64::FPR64RegClass.contains(DestReg) &&
6154 AArch64::FPR64RegClass.contains(SrcReg)) {
6155 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6156 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6157 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6158 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6159 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6160 &AArch64::FPR128RegClass);
6161 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6162 &AArch64::FPR128RegClass);
6163 // This instruction is reading and writing Q registers. This may upset
6164 // the register scavenger and machine verifier, so we need to indicate
6165 // that we are reading an undefined value from SrcRegQ, but a proper
6166 // value from SrcReg.
6167 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6168 .addReg(SrcRegQ, RegState::Undef)
6169 .addReg(SrcRegQ, RegState::Undef)
6170 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6171 ++NumZCRegMoveInstrsFPR;
6172 } else {
6173 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
6174 .addReg(SrcReg, getKillRegState(KillSrc));
6175 if (Subtarget.hasZeroCycleRegMoveFPR64())
6176 ++NumZCRegMoveInstrsFPR;
6177 }
6178 return;
6179 }
6180
6181 if (AArch64::FPR32RegClass.contains(DestReg) &&
6182 AArch64::FPR32RegClass.contains(SrcReg)) {
6183 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6184 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6185 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6186 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6187 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6188 &AArch64::FPR128RegClass);
6189 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6190 &AArch64::FPR128RegClass);
6191 // This instruction is reading and writing Q registers. This may upset
6192 // the register scavenger and machine verifier, so we need to indicate
6193 // that we are reading an undefined value from SrcRegQ, but a proper
6194 // value from SrcReg.
6195 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6196 .addReg(SrcRegQ, RegState::Undef)
6197 .addReg(SrcRegQ, RegState::Undef)
6198 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6199 ++NumZCRegMoveInstrsFPR;
6200 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6201 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6202 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6203 &AArch64::FPR64RegClass);
6204 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6205 &AArch64::FPR64RegClass);
6206 // This instruction is reading and writing D registers. This may upset
6207 // the register scavenger and machine verifier, so we need to indicate
6208 // that we are reading an undefined value from SrcRegD, but a proper
6209 // value from SrcReg.
6210 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6211 .addReg(SrcRegD, RegState::Undef)
6212 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6213 ++NumZCRegMoveInstrsFPR;
6214 } else {
6215 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6216 .addReg(SrcReg, getKillRegState(KillSrc));
6217 if (Subtarget.hasZeroCycleRegMoveFPR32())
6218 ++NumZCRegMoveInstrsFPR;
6219 }
6220 return;
6221 }
6222
6223 if (AArch64::FPR16RegClass.contains(DestReg) &&
6224 AArch64::FPR16RegClass.contains(SrcReg)) {
6225 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6226 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6227 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6228 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6229 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6230 &AArch64::FPR128RegClass);
6231 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6232 &AArch64::FPR128RegClass);
6233 // This instruction is reading and writing Q registers. This may upset
6234 // the register scavenger and machine verifier, so we need to indicate
6235 // that we are reading an undefined value from SrcRegQ, but a proper
6236 // value from SrcReg.
6237 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6238 .addReg(SrcRegQ, RegState::Undef)
6239 .addReg(SrcRegQ, RegState::Undef)
6240 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6241 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6242 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6243 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6244 &AArch64::FPR64RegClass);
6245 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6246 &AArch64::FPR64RegClass);
6247 // This instruction is reading and writing D registers. This may upset
6248 // the register scavenger and machine verifier, so we need to indicate
6249 // that we are reading an undefined value from SrcRegD, but a proper
6250 // value from SrcReg.
6251 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6252 .addReg(SrcRegD, RegState::Undef)
6253 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6254 } else {
6255 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6256 &AArch64::FPR32RegClass);
6257 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6258 &AArch64::FPR32RegClass);
6259 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6260 .addReg(SrcReg, getKillRegState(KillSrc));
6261 }
6262 return;
6263 }
6264
6265 if (AArch64::FPR8RegClass.contains(DestReg) &&
6266 AArch64::FPR8RegClass.contains(SrcReg)) {
6267 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6268 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6269 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6270 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6271 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6272 &AArch64::FPR128RegClass);
6273 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6274 &AArch64::FPR128RegClass);
6275 // This instruction is reading and writing Q registers. This may upset
6276 // the register scavenger and machine verifier, so we need to indicate
6277 // that we are reading an undefined value from SrcRegQ, but a proper
6278 // value from SrcReg.
6279 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6280 .addReg(SrcRegQ, RegState::Undef)
6281 .addReg(SrcRegQ, RegState::Undef)
6282 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6283 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6284 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6285 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6286 &AArch64::FPR64RegClass);
6287 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6288 &AArch64::FPR64RegClass);
6289 // This instruction is reading and writing D registers. This may upset
6290 // the register scavenger and machine verifier, so we need to indicate
6291 // that we are reading an undefined value from SrcRegD, but a proper
6292 // value from SrcReg.
6293 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6294 .addReg(SrcRegD, RegState::Undef)
6295 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6296 } else {
6297 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6298 &AArch64::FPR32RegClass);
6299 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6300 &AArch64::FPR32RegClass);
6301 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6302 .addReg(SrcReg, getKillRegState(KillSrc));
6303 }
6304 return;
6305 }
6306
6307 // Copies between GPR64 and FPR64.
6308 if (AArch64::FPR64RegClass.contains(DestReg) &&
6309 AArch64::GPR64RegClass.contains(SrcReg)) {
6310 if (AArch64::XZR == SrcReg) {
6311 BuildMI(MBB, I, DL, get(AArch64::FMOVD0), DestReg);
6312 } else {
6313 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
6314 .addReg(SrcReg, getKillRegState(KillSrc));
6315 }
6316 return;
6317 }
6318 if (AArch64::GPR64RegClass.contains(DestReg) &&
6319 AArch64::FPR64RegClass.contains(SrcReg)) {
6320 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
6321 .addReg(SrcReg, getKillRegState(KillSrc));
6322 return;
6323 }
6324 // Copies between GPR32 and FPR32.
6325 if (AArch64::FPR32RegClass.contains(DestReg) &&
6326 AArch64::GPR32RegClass.contains(SrcReg)) {
6327 if (AArch64::WZR == SrcReg) {
6328 BuildMI(MBB, I, DL, get(AArch64::FMOVS0), DestReg);
6329 } else {
6330 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
6331 .addReg(SrcReg, getKillRegState(KillSrc));
6332 }
6333 return;
6334 }
6335 if (AArch64::GPR32RegClass.contains(DestReg) &&
6336 AArch64::FPR32RegClass.contains(SrcReg)) {
6337 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
6338 .addReg(SrcReg, getKillRegState(KillSrc));
6339 return;
6340 }
6341
6342 if (DestReg == AArch64::NZCV) {
6343 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
6344 BuildMI(MBB, I, DL, get(AArch64::MSR))
6345 .addImm(AArch64SysReg::NZCV)
6346 .addReg(SrcReg, getKillRegState(KillSrc))
6347 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
6348 return;
6349 }
6350
6351 if (SrcReg == AArch64::NZCV) {
6352 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
6353 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
6354 .addImm(AArch64SysReg::NZCV)
6355 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
6356 return;
6357 }
6358
6359#ifndef NDEBUG
6360 errs() << RI.getRegAsmName(DestReg) << " = COPY " << RI.getRegAsmName(SrcReg)
6361 << "\n";
6362#endif
6363 llvm_unreachable("unimplemented reg-to-reg copy");
6364}
6365
6368 MachineBasicBlock::iterator InsertBefore,
6369 const MCInstrDesc &MCID,
6370 Register SrcReg, bool IsKill,
6371 unsigned SubIdx0, unsigned SubIdx1, int FI,
6372 MachineMemOperand *MMO) {
6373 Register SrcReg0 = SrcReg;
6374 Register SrcReg1 = SrcReg;
6375 if (SrcReg.isPhysical()) {
6376 SrcReg0 = TRI.getSubReg(SrcReg, SubIdx0);
6377 SubIdx0 = 0;
6378 SrcReg1 = TRI.getSubReg(SrcReg, SubIdx1);
6379 SubIdx1 = 0;
6380 }
6381 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6382 .addReg(SrcReg0, getKillRegState(IsKill), SubIdx0)
6383 .addReg(SrcReg1, getKillRegState(IsKill), SubIdx1)
6384 .addFrameIndex(FI)
6385 .addImm(0)
6386 .addMemOperand(MMO);
6387}
6388
6391 Register SrcReg, bool isKill, int FI,
6392 const TargetRegisterClass *RC,
6393 Register VReg,
6394 MachineInstr::MIFlag Flags) const {
6395 MachineFunction &MF = *MBB.getParent();
6396 MachineFrameInfo &MFI = MF.getFrameInfo();
6397
6399 MachineMemOperand *MMO =
6401 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6402 unsigned Opc = 0;
6403 bool Offset = true;
6405 unsigned StackID = TargetStackID::Default;
6406 switch (RI.getSpillSize(*RC)) {
6407 case 1:
6408 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6409 Opc = AArch64::STRBui;
6410 break;
6411 case 2: {
6412 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6413 Opc = AArch64::STRHui;
6414 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6415 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6416 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6417 "Unexpected register store without SVE store instructions");
6418 Opc = AArch64::STR_PXI;
6420 }
6421 break;
6422 }
6423 case 4:
6424 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6425 Opc = AArch64::STRWui;
6426 if (SrcReg.isVirtual())
6427 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
6428 else
6429 assert(SrcReg != AArch64::WSP);
6430 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6431 Opc = AArch64::STRSui;
6432 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6433 Opc = AArch64::STR_PPXI;
6435 }
6436 break;
6437 case 8:
6438 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6439 Opc = AArch64::STRXui;
6440 if (SrcReg.isVirtual())
6441 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
6442 else
6443 assert(SrcReg != AArch64::SP);
6444 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6445 Opc = AArch64::STRDui;
6446 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6448 get(AArch64::STPWi), SrcReg, isKill,
6449 AArch64::sube32, AArch64::subo32, FI, MMO);
6450 return;
6451 }
6452 break;
6453 case 16:
6454 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6455 Opc = AArch64::STRQui;
6456 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6457 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6458 Opc = AArch64::ST1Twov1d;
6459 Offset = false;
6460 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6462 get(AArch64::STPXi), SrcReg, isKill,
6463 AArch64::sube64, AArch64::subo64, FI, MMO);
6464 return;
6465 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6466 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6467 "Unexpected register store without SVE store instructions");
6468 Opc = AArch64::STR_ZXI;
6470 }
6471 break;
6472 case 24:
6473 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6474 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6475 Opc = AArch64::ST1Threev1d;
6476 Offset = false;
6477 }
6478 break;
6479 case 32:
6480 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6481 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6482 Opc = AArch64::ST1Fourv1d;
6483 Offset = false;
6484 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6485 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6486 Opc = AArch64::ST1Twov2d;
6487 Offset = false;
6488 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6489 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6490 "Unexpected register store without SVE store instructions");
6491 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6493 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6494 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6495 "Unexpected register store without SVE store instructions");
6496 Opc = AArch64::STR_ZZXI;
6498 }
6499 break;
6500 case 48:
6501 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6502 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6503 Opc = AArch64::ST1Threev2d;
6504 Offset = false;
6505 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6506 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6507 "Unexpected register store without SVE store instructions");
6508 Opc = AArch64::STR_ZZZXI;
6510 }
6511 break;
6512 case 64:
6513 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6514 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6515 Opc = AArch64::ST1Fourv2d;
6516 Offset = false;
6517 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6518 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6519 "Unexpected register store without SVE store instructions");
6520 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6522 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6523 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6524 "Unexpected register store without SVE store instructions");
6525 Opc = AArch64::STR_ZZZZXI;
6527 }
6528 break;
6529 }
6530 assert(Opc && "Unknown register class");
6531 MFI.setStackID(FI, StackID);
6532
6534 .addReg(SrcReg, getKillRegState(isKill))
6535 .addFrameIndex(FI);
6536
6537 if (Offset)
6538 MI.addImm(0);
6539 if (PNRReg.isValid())
6540 MI.addDef(PNRReg, RegState::Implicit);
6541 MI.addMemOperand(MMO);
6542}
6543
6546 MachineBasicBlock::iterator InsertBefore,
6547 const MCInstrDesc &MCID,
6548 Register DestReg, unsigned SubIdx0,
6549 unsigned SubIdx1, int FI,
6550 MachineMemOperand *MMO) {
6551 Register DestReg0 = DestReg;
6552 Register DestReg1 = DestReg;
6553 bool IsUndef = true;
6554 if (DestReg.isPhysical()) {
6555 DestReg0 = TRI.getSubReg(DestReg, SubIdx0);
6556 SubIdx0 = 0;
6557 DestReg1 = TRI.getSubReg(DestReg, SubIdx1);
6558 SubIdx1 = 0;
6559 IsUndef = false;
6560 }
6561 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6562 .addReg(DestReg0, RegState::Define | getUndefRegState(IsUndef), SubIdx0)
6563 .addReg(DestReg1, RegState::Define | getUndefRegState(IsUndef), SubIdx1)
6564 .addFrameIndex(FI)
6565 .addImm(0)
6566 .addMemOperand(MMO);
6567}
6568
6571 Register DestReg, int FI,
6572 const TargetRegisterClass *RC,
6573 Register VReg, unsigned SubReg,
6574 MachineInstr::MIFlag Flags) const {
6575 MachineFunction &MF = *MBB.getParent();
6576 MachineFrameInfo &MFI = MF.getFrameInfo();
6578 MachineMemOperand *MMO =
6580 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6581
6582 unsigned Opc = 0;
6583 bool Offset = true;
6584 unsigned StackID = TargetStackID::Default;
6586 switch (TRI.getSpillSize(*RC)) {
6587 case 1:
6588 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6589 Opc = AArch64::LDRBui;
6590 break;
6591 case 2: {
6592 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6593 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6594 Opc = AArch64::LDRHui;
6595 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6596 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6597 "Unexpected register load without SVE load instructions");
6598 if (IsPNR)
6599 PNRReg = DestReg;
6600 Opc = AArch64::LDR_PXI;
6602 }
6603 break;
6604 }
6605 case 4:
6606 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6607 Opc = AArch64::LDRWui;
6608 if (DestReg.isVirtual())
6609 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
6610 else
6611 assert(DestReg != AArch64::WSP);
6612 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6613 Opc = AArch64::LDRSui;
6614 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6615 Opc = AArch64::LDR_PPXI;
6617 }
6618 break;
6619 case 8:
6620 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6621 Opc = AArch64::LDRXui;
6622 if (DestReg.isVirtual())
6623 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
6624 else
6625 assert(DestReg != AArch64::SP);
6626 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6627 Opc = AArch64::LDRDui;
6628 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6630 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6631 AArch64::subo32, FI, MMO);
6632 return;
6633 }
6634 break;
6635 case 16:
6636 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6637 Opc = AArch64::LDRQui;
6638 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6639 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6640 Opc = AArch64::LD1Twov1d;
6641 Offset = false;
6642 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6644 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6645 AArch64::subo64, FI, MMO);
6646 return;
6647 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6648 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6649 "Unexpected register load without SVE load instructions");
6650 Opc = AArch64::LDR_ZXI;
6652 }
6653 break;
6654 case 24:
6655 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6656 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6657 Opc = AArch64::LD1Threev1d;
6658 Offset = false;
6659 }
6660 break;
6661 case 32:
6662 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6663 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6664 Opc = AArch64::LD1Fourv1d;
6665 Offset = false;
6666 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6667 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6668 Opc = AArch64::LD1Twov2d;
6669 Offset = false;
6670 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6671 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6672 "Unexpected register load without SVE load instructions");
6673 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6675 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6676 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6677 "Unexpected register load without SVE load instructions");
6678 Opc = AArch64::LDR_ZZXI;
6680 }
6681 break;
6682 case 48:
6683 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6684 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6685 Opc = AArch64::LD1Threev2d;
6686 Offset = false;
6687 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6688 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6689 "Unexpected register load without SVE load instructions");
6690 Opc = AArch64::LDR_ZZZXI;
6692 }
6693 break;
6694 case 64:
6695 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6696 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6697 Opc = AArch64::LD1Fourv2d;
6698 Offset = false;
6699 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6700 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6701 "Unexpected register load without SVE load instructions");
6702 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6704 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6705 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6706 "Unexpected register load without SVE load instructions");
6707 Opc = AArch64::LDR_ZZZZXI;
6709 }
6710 break;
6711 }
6712
6713 assert(Opc && "Unknown register class");
6714 MFI.setStackID(FI, StackID);
6715
6717 .addReg(DestReg, getDefRegState(true))
6718 .addFrameIndex(FI);
6719 if (Offset)
6720 MI.addImm(0);
6721 if (PNRReg.isValid() && !PNRReg.isVirtual())
6722 MI.addDef(PNRReg, RegState::Implicit);
6723 MI.addMemOperand(MMO);
6724}
6725
6727 const MachineInstr &UseMI,
6728 const TargetRegisterInfo *TRI) {
6729 return any_of(instructionsWithoutDebug(std::next(DefMI.getIterator()),
6730 UseMI.getIterator()),
6731 [TRI](const MachineInstr &I) {
6732 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6733 I.readsRegister(AArch64::NZCV, TRI);
6734 });
6735}
6736
6737void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6738 const StackOffset &Offset, int64_t &ByteSized, int64_t &VGSized) {
6739 // The smallest scalable element supported by scaled SVE addressing
6740 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6741 // byte offset must always be a multiple of 2.
6742 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6743
6744 // VGSized offsets are divided by '2', because the VG register is the
6745 // the number of 64bit granules as opposed to 128bit vector chunks,
6746 // which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
6747 // So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
6748 // VG = n * 2 and the dwarf offset must be VG * 8 bytes.
6749 ByteSized = Offset.getFixed();
6750 VGSized = Offset.getScalable() / 2;
6751}
6752
6753/// Returns the offset in parts to which this frame offset can be
6754/// decomposed for the purpose of describing a frame offset.
6755/// For non-scalable offsets this is simply its byte size.
6756void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6757 const StackOffset &Offset, int64_t &NumBytes, int64_t &NumPredicateVectors,
6758 int64_t &NumDataVectors) {
6759 // The smallest scalable element supported by scaled SVE addressing
6760 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6761 // byte offset must always be a multiple of 2.
6762 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6763
6764 NumBytes = Offset.getFixed();
6765 NumDataVectors = 0;
6766 NumPredicateVectors = Offset.getScalable() / 2;
6767 // This method is used to get the offsets to adjust the frame offset.
6768 // If the function requires ADDPL to be used and needs more than two ADDPL
6769 // instructions, part of the offset is folded into NumDataVectors so that it
6770 // uses ADDVL for part of it, reducing the number of ADDPL instructions.
6771 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6772 NumPredicateVectors > 62) {
6773 NumDataVectors = NumPredicateVectors / 8;
6774 NumPredicateVectors -= NumDataVectors * 8;
6775 }
6776}
6777
6778// Convenience function to create a DWARF expression for: Constant `Operation`.
6779// This helper emits compact sequences for common cases. For example, for`-15
6780// DW_OP_plus`, this helper would create DW_OP_lit15 DW_OP_minus.
6783 if (Operation == dwarf::DW_OP_plus && Constant < 0 && -Constant <= 31) {
6784 // -Constant (1 to 31)
6785 Expr.push_back(dwarf::DW_OP_lit0 - Constant);
6786 Operation = dwarf::DW_OP_minus;
6787 } else if (Constant >= 0 && Constant <= 31) {
6788 // Literal value 0 to 31
6789 Expr.push_back(dwarf::DW_OP_lit0 + Constant);
6790 } else {
6791 // Signed constant
6792 Expr.push_back(dwarf::DW_OP_consts);
6794 }
6795 return Expr.push_back(Operation);
6796}
6797
6798// Convenience function to create a DWARF expression for a register.
6799static void appendReadRegExpr(SmallVectorImpl<char> &Expr, unsigned RegNum) {
6800 Expr.push_back((char)dwarf::DW_OP_bregx);
6802 Expr.push_back(0);
6803}
6804
6805// Convenience function to create a DWARF expression for loading a register from
6806// a CFA offset.
6808 int64_t OffsetFromDefCFA) {
6809 // This assumes the top of the DWARF stack contains the CFA.
6810 Expr.push_back(dwarf::DW_OP_dup);
6811 // Add the offset to the register.
6812 appendConstantExpr(Expr, OffsetFromDefCFA, dwarf::DW_OP_plus);
6813 // Dereference the address (loads a 64 bit value)..
6814 Expr.push_back(dwarf::DW_OP_deref);
6815}
6816
6817// Convenience function to create a comment for
6818// (+/-) NumBytes (* RegScale)?
6819static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment,
6820 StringRef RegScale = {}) {
6821 if (NumBytes) {
6822 Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
6823 if (!RegScale.empty())
6824 Comment << ' ' << RegScale;
6825 }
6826}
6827
6828// Creates an MCCFIInstruction:
6829// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
6831 unsigned Reg,
6832 const StackOffset &Offset) {
6833 int64_t NumBytes, NumVGScaledBytes;
6834 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(Offset, NumBytes,
6835 NumVGScaledBytes);
6836 std::string CommentBuffer;
6837 llvm::raw_string_ostream Comment(CommentBuffer);
6838
6839 if (Reg == AArch64::SP)
6840 Comment << "sp";
6841 else if (Reg == AArch64::FP)
6842 Comment << "fp";
6843 else
6844 Comment << printReg(Reg, &TRI);
6845
6846 // Build up the expression (Reg + NumBytes + VG * NumVGScaledBytes)
6847 SmallString<64> Expr;
6848 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6849 assert(DwarfReg <= 31 && "DwarfReg out of bounds (0..31)");
6850 // Reg + NumBytes
6851 Expr.push_back(dwarf::DW_OP_breg0 + DwarfReg);
6852 appendLEB128<LEB128Sign::Signed>(Expr, NumBytes);
6853 appendOffsetComment(NumBytes, Comment);
6854 if (NumVGScaledBytes) {
6855 // + VG * NumVGScaledBytes
6856 appendOffsetComment(NumVGScaledBytes, Comment, "* VG");
6857 appendReadRegExpr(Expr, TRI.getDwarfRegNum(AArch64::VG, true));
6858 appendConstantExpr(Expr, NumVGScaledBytes, dwarf::DW_OP_mul);
6859 Expr.push_back(dwarf::DW_OP_plus);
6860 }
6861
6862 // Wrap this into DW_CFA_def_cfa.
6863 SmallString<64> DefCfaExpr;
6864 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
6865 appendLEB128<LEB128Sign::Unsigned>(DefCfaExpr, Expr.size());
6866 DefCfaExpr.append(Expr.str());
6867 return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
6868 Comment.str());
6869}
6870
6872 unsigned FrameReg, unsigned Reg,
6873 const StackOffset &Offset,
6874 bool LastAdjustmentWasScalable) {
6875 if (Offset.getScalable())
6876 return createDefCFAExpression(TRI, Reg, Offset);
6877
6878 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6879 return MCCFIInstruction::cfiDefCfaOffset(nullptr, int(Offset.getFixed()));
6880
6881 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6882 return MCCFIInstruction::cfiDefCfa(nullptr, DwarfReg, (int)Offset.getFixed());
6883}
6884
6887 const StackOffset &OffsetFromDefCFA,
6888 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6889 int64_t NumBytes, NumVGScaledBytes;
6890 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6891 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6892
6893 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6894
6895 // Non-scalable offsets can use DW_CFA_offset directly.
6896 if (!NumVGScaledBytes)
6897 return MCCFIInstruction::createOffset(nullptr, DwarfReg, NumBytes);
6898
6899 std::string CommentBuffer;
6900 llvm::raw_string_ostream Comment(CommentBuffer);
6901 Comment << printReg(Reg, &TRI) << " @ cfa";
6902
6903 // Build up expression (CFA + VG * NumVGScaledBytes + NumBytes)
6904 assert(NumVGScaledBytes && "Expected scalable offset");
6905 SmallString<64> OffsetExpr;
6906 // + VG * NumVGScaledBytes
6907 StringRef VGRegScale;
6908 if (IncomingVGOffsetFromDefCFA) {
6909 appendLoadRegExpr(OffsetExpr, *IncomingVGOffsetFromDefCFA);
6910 VGRegScale = "* IncomingVG";
6911 } else {
6912 appendReadRegExpr(OffsetExpr, TRI.getDwarfRegNum(AArch64::VG, true));
6913 VGRegScale = "* VG";
6914 }
6915 appendConstantExpr(OffsetExpr, NumVGScaledBytes, dwarf::DW_OP_mul);
6916 appendOffsetComment(NumVGScaledBytes, Comment, VGRegScale);
6917 OffsetExpr.push_back(dwarf::DW_OP_plus);
6918 if (NumBytes) {
6919 // + NumBytes
6920 appendOffsetComment(NumBytes, Comment);
6921 appendConstantExpr(OffsetExpr, NumBytes, dwarf::DW_OP_plus);
6922 }
6923
6924 // Wrap this into DW_CFA_expression
6925 SmallString<64> CfaExpr;
6926 CfaExpr.push_back(dwarf::DW_CFA_expression);
6927 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, DwarfReg);
6928 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, OffsetExpr.size());
6929 CfaExpr.append(OffsetExpr.str());
6930
6931 return MCCFIInstruction::createEscape(nullptr, CfaExpr.str(), SMLoc(),
6932 Comment.str());
6933}
6934
6935// Helper function to emit a frame offset adjustment from a given
6936// pointer (SrcReg), stored into DestReg. This function is explicit
6937// in that it requires the opcode.
6940 const DebugLoc &DL, unsigned DestReg,
6941 unsigned SrcReg, int64_t Offset, unsigned Opc,
6942 const TargetInstrInfo *TII,
6943 MachineInstr::MIFlag Flag, bool NeedsWinCFI,
6944 bool *HasWinCFI, bool EmitCFAOffset,
6945 StackOffset CFAOffset, unsigned FrameReg) {
6946 int Sign = 1;
6947 unsigned MaxEncoding, ShiftSize;
6948 switch (Opc) {
6949 case AArch64::ADDXri:
6950 case AArch64::ADDSXri:
6951 case AArch64::SUBXri:
6952 case AArch64::SUBSXri:
6953 MaxEncoding = 0xfff;
6954 ShiftSize = 12;
6955 break;
6956 case AArch64::ADDVL_XXI:
6957 case AArch64::ADDPL_XXI:
6958 case AArch64::ADDSVL_XXI:
6959 case AArch64::ADDSPL_XXI:
6960 MaxEncoding = 31;
6961 ShiftSize = 0;
6962 if (Offset < 0) {
6963 MaxEncoding = 32;
6964 Sign = -1;
6965 Offset = -Offset;
6966 }
6967 break;
6968 default:
6969 llvm_unreachable("Unsupported opcode");
6970 }
6971
6972 // `Offset` can be in bytes or in "scalable bytes".
6973 int VScale = 1;
6974 if (Opc == AArch64::ADDVL_XXI || Opc == AArch64::ADDSVL_XXI)
6975 VScale = 16;
6976 else if (Opc == AArch64::ADDPL_XXI || Opc == AArch64::ADDSPL_XXI)
6977 VScale = 2;
6978
6979 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
6980 // scratch register. If DestReg is a virtual register, use it as the
6981 // scratch register; otherwise, create a new virtual register (to be
6982 // replaced by the scavenger at the end of PEI). That case can be optimized
6983 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
6984 // register can be loaded with offset%8 and the add/sub can use an extending
6985 // instruction with LSL#3.
6986 // Currently the function handles any offsets but generates a poor sequence
6987 // of code.
6988 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
6989
6990 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
6991 Register TmpReg = DestReg;
6992 if (TmpReg == AArch64::XZR)
6993 TmpReg = MBB.getParent()->getRegInfo().createVirtualRegister(
6994 &AArch64::GPR64RegClass);
6995 do {
6996 uint64_t ThisVal = std::min<uint64_t>(Offset, MaxEncodableValue);
6997 unsigned LocalShiftSize = 0;
6998 if (ThisVal > MaxEncoding) {
6999 ThisVal = ThisVal >> ShiftSize;
7000 LocalShiftSize = ShiftSize;
7001 }
7002 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
7003 "Encoding cannot handle value that big");
7004
7005 Offset -= ThisVal << LocalShiftSize;
7006 if (Offset == 0)
7007 TmpReg = DestReg;
7008 auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), TmpReg)
7009 .addReg(SrcReg)
7010 .addImm(Sign * (int)ThisVal);
7011 if (ShiftSize)
7012 MBI = MBI.addImm(
7014 MBI = MBI.setMIFlag(Flag);
7015
7016 auto Change =
7017 VScale == 1
7018 ? StackOffset::getFixed(ThisVal << LocalShiftSize)
7019 : StackOffset::getScalable(VScale * (ThisVal << LocalShiftSize));
7020 if (Sign == -1 || Opc == AArch64::SUBXri || Opc == AArch64::SUBSXri)
7021 CFAOffset += Change;
7022 else
7023 CFAOffset -= Change;
7024 if (EmitCFAOffset && DestReg == TmpReg) {
7025 MachineFunction &MF = *MBB.getParent();
7026 const TargetSubtargetInfo &STI = MF.getSubtarget();
7027 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
7028
7029 unsigned CFIIndex = MF.addFrameInst(
7030 createDefCFA(TRI, FrameReg, DestReg, CFAOffset, VScale != 1));
7031 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
7032 .addCFIIndex(CFIIndex)
7033 .setMIFlags(Flag);
7034 }
7035
7036 if (NeedsWinCFI) {
7037 int Imm = (int)(ThisVal << LocalShiftSize);
7038 if (VScale != 1 && DestReg == AArch64::SP) {
7039 if (HasWinCFI)
7040 *HasWinCFI = true;
7041 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ))
7042 .addImm(ThisVal)
7043 .setMIFlag(Flag);
7044 } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7045 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7046 assert(VScale == 1 && "Expected non-scalable operation");
7047 if (HasWinCFI)
7048 *HasWinCFI = true;
7049 if (Imm == 0)
7050 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
7051 else
7052 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
7053 .addImm(Imm)
7054 .setMIFlag(Flag);
7055 assert(Offset == 0 && "Expected remaining offset to be zero to "
7056 "emit a single SEH directive");
7057 } else if (DestReg == AArch64::SP) {
7058 assert(VScale == 1 && "Expected non-scalable operation");
7059 if (HasWinCFI)
7060 *HasWinCFI = true;
7061 assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
7062 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
7063 .addImm(Imm)
7064 .setMIFlag(Flag);
7065 }
7066 }
7067
7068 SrcReg = TmpReg;
7069 } while (Offset);
7070}
7071
7074 unsigned DestReg, unsigned SrcReg,
7076 MachineInstr::MIFlag Flag, bool SetNZCV,
7077 bool NeedsWinCFI, bool *HasWinCFI,
7078 bool EmitCFAOffset, StackOffset CFAOffset,
7079 unsigned FrameReg) {
7080 // If a function is marked as arm_locally_streaming, then the runtime value of
7081 // vscale in the prologue/epilogue is different the runtime value of vscale
7082 // in the function's body. To avoid having to consider multiple vscales,
7083 // we can use `addsvl` to allocate any scalable stack-slots, which under
7084 // most circumstances will be only locals, not callee-save slots.
7085 const Function &F = MBB.getParent()->getFunction();
7086 bool UseSVL = F.hasFnAttribute("aarch64_pstate_sm_body");
7087
7088 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7089 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7090 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7091
7092 // Insert ADDSXri for scalable offset at the end.
7093 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7094 if (NeedsFinalDefNZCV)
7095 SetNZCV = false;
7096
7097 // First emit non-scalable frame offsets, or a simple 'mov'.
7098 if (Bytes || (!Offset && SrcReg != DestReg)) {
7099 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7100 "SP increment/decrement not 8-byte aligned");
7101 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7102 if (Bytes < 0) {
7103 Bytes = -Bytes;
7104 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7105 }
7106 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
7107 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7108 FrameReg);
7109 CFAOffset += (Opc == AArch64::ADDXri || Opc == AArch64::ADDSXri)
7110 ? StackOffset::getFixed(-Bytes)
7111 : StackOffset::getFixed(Bytes);
7112 SrcReg = DestReg;
7113 FrameReg = DestReg;
7114 }
7115
7116 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7117 "WinCFI can't allocate fractions of an SVE data vector");
7118
7119 if (NumDataVectors) {
7120 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors,
7121 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII,
7122 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7123 FrameReg);
7124 CFAOffset += StackOffset::getScalable(-NumDataVectors * 16);
7125 SrcReg = DestReg;
7126 }
7127
7128 if (NumPredicateVectors) {
7129 assert(DestReg != AArch64::SP && "Unaligned access to SP");
7130 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors,
7131 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII,
7132 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7133 FrameReg);
7134 }
7135
7136 if (NeedsFinalDefNZCV)
7137 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDSXri), DestReg)
7138 .addReg(DestReg)
7139 .addImm(0)
7140 .addImm(0);
7141}
7142
7145 int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS,
7146 VirtRegMap *VRM) const {
7148 // This is a bit of a hack. Consider this instruction:
7149 //
7150 // %0 = COPY %sp; GPR64all:%0
7151 //
7152 // We explicitly chose GPR64all for the virtual register so such a copy might
7153 // be eliminated by RegisterCoalescer. However, that may not be possible, and
7154 // %0 may even spill. We can't spill %sp, and since it is in the GPR64all
7155 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
7156 //
7157 // To prevent that, we are going to constrain the %0 register class here.
7158 if (MI.isFullCopy()) {
7159 Register DstReg = MI.getOperand(0).getReg();
7160 Register SrcReg = MI.getOperand(1).getReg();
7161 if (SrcReg == AArch64::SP && DstReg.isVirtual()) {
7162 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
7163 return nullptr;
7164 }
7165 if (DstReg == AArch64::SP && SrcReg.isVirtual()) {
7166 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
7167 return nullptr;
7168 }
7169 // Nothing can folded with copy from/to NZCV.
7170 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7171 return nullptr;
7172 }
7173
7174 // Handle the case where a copy is being spilled or filled but the source
7175 // and destination register class don't match. For example:
7176 //
7177 // %0 = COPY %xzr; GPR64common:%0
7178 //
7179 // In this case we can still safely fold away the COPY and generate the
7180 // following spill code:
7181 //
7182 // STRXui %xzr, %stack.0
7183 //
7184 // This also eliminates spilled cross register class COPYs (e.g. between x and
7185 // d regs) of the same size. For example:
7186 //
7187 // %0 = COPY %1; GPR64:%0, FPR64:%1
7188 //
7189 // will be filled as
7190 //
7191 // LDRDui %0, fi<#0>
7192 //
7193 // instead of
7194 //
7195 // LDRXui %Temp, fi<#0>
7196 // %0 = FMOV %Temp
7197 //
7198 if (MI.isCopy() && Ops.size() == 1 &&
7199 // Make sure we're only folding the explicit COPY defs/uses.
7200 (Ops[0] == 0 || Ops[0] == 1)) {
7201 bool IsSpill = Ops[0] == 0;
7202 bool IsFill = !IsSpill;
7204 const MachineRegisterInfo &MRI = MF.getRegInfo();
7205 MachineBasicBlock &MBB = *MI.getParent();
7206 const MachineOperand &DstMO = MI.getOperand(0);
7207 const MachineOperand &SrcMO = MI.getOperand(1);
7208 Register DstReg = DstMO.getReg();
7209 Register SrcReg = SrcMO.getReg();
7210 // This is slightly expensive to compute for physical regs since
7211 // getMinimalPhysRegClass is slow.
7212 auto getRegClass = [&](unsigned Reg) {
7213 return Register::isVirtualRegister(Reg) ? MRI.getRegClass(Reg)
7214 : TRI.getMinimalPhysRegClass(Reg);
7215 };
7216
7217 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
7218 assert(TRI.getRegSizeInBits(*getRegClass(DstReg)) ==
7219 TRI.getRegSizeInBits(*getRegClass(SrcReg)) &&
7220 "Mismatched register size in non subreg COPY");
7221 if (IsSpill)
7222 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
7223 getRegClass(SrcReg), Register());
7224 else
7225 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
7226 getRegClass(DstReg), Register());
7227 return &*--InsertPt;
7228 }
7229
7230 // Handle cases like spilling def of:
7231 //
7232 // %0:sub_32<def,read-undef> = COPY %wzr; GPR64common:%0
7233 //
7234 // where the physical register source can be widened and stored to the full
7235 // virtual reg destination stack slot, in this case producing:
7236 //
7237 // STRXui %xzr, %stack.0
7238 //
7239 if (IsSpill && DstMO.isUndef() && SrcReg == AArch64::WZR &&
7240 TRI.getRegSizeInBits(*getRegClass(DstReg)) == 64) {
7241 assert(SrcMO.getSubReg() == 0 &&
7242 "Unexpected subreg on physical register");
7243 storeRegToStackSlot(MBB, InsertPt, AArch64::XZR, SrcMO.isKill(),
7244 FrameIndex, &AArch64::GPR64RegClass, Register());
7245 return &*--InsertPt;
7246 }
7247
7248 // Handle cases like filling use of:
7249 //
7250 // %0:sub_32<def,read-undef> = COPY %1; GPR64:%0, GPR32:%1
7251 //
7252 // where we can load the full virtual reg source stack slot, into the subreg
7253 // destination, in this case producing:
7254 //
7255 // LDRWui %0:sub_32<def,read-undef>, %stack.0
7256 //
7257 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
7258 const TargetRegisterClass *FillRC = nullptr;
7259 switch (DstMO.getSubReg()) {
7260 default:
7261 break;
7262 case AArch64::sub_32:
7263 if (AArch64::GPR64RegClass.hasSubClassEq(getRegClass(DstReg)))
7264 FillRC = &AArch64::GPR32RegClass;
7265 break;
7266 case AArch64::ssub:
7267 FillRC = &AArch64::FPR32RegClass;
7268 break;
7269 case AArch64::dsub:
7270 FillRC = &AArch64::FPR64RegClass;
7271 break;
7272 }
7273
7274 if (FillRC) {
7275 assert(TRI.getRegSizeInBits(*getRegClass(SrcReg)) ==
7276 TRI.getRegSizeInBits(*FillRC) &&
7277 "Mismatched regclass size on folded subreg COPY");
7278 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC,
7279 Register());
7280 MachineInstr &LoadMI = *--InsertPt;
7281 MachineOperand &LoadDst = LoadMI.getOperand(0);
7282 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
7283 LoadDst.setSubReg(DstMO.getSubReg());
7284 LoadDst.setIsUndef();
7285 return &LoadMI;
7286 }
7287 }
7288 }
7289
7290 // Cannot fold.
7291 return nullptr;
7292}
7293
7295 StackOffset &SOffset,
7296 bool *OutUseUnscaledOp,
7297 unsigned *OutUnscaledOp,
7298 int64_t *EmittableOffset) {
7299 // Set output values in case of early exit.
7300 if (EmittableOffset)
7301 *EmittableOffset = 0;
7302 if (OutUseUnscaledOp)
7303 *OutUseUnscaledOp = false;
7304 if (OutUnscaledOp)
7305 *OutUnscaledOp = 0;
7306
7307 // Exit early for structured vector spills/fills as they can't take an
7308 // immediate offset.
7309 switch (MI.getOpcode()) {
7310 default:
7311 break;
7312 case AArch64::LD1Rv1d:
7313 case AArch64::LD1Rv2s:
7314 case AArch64::LD1Rv2d:
7315 case AArch64::LD1Rv4h:
7316 case AArch64::LD1Rv4s:
7317 case AArch64::LD1Rv8b:
7318 case AArch64::LD1Rv8h:
7319 case AArch64::LD1Rv16b:
7320 case AArch64::LD1Twov2d:
7321 case AArch64::LD1Threev2d:
7322 case AArch64::LD1Fourv2d:
7323 case AArch64::LD1Twov1d:
7324 case AArch64::LD1Threev1d:
7325 case AArch64::LD1Fourv1d:
7326 case AArch64::ST1Twov2d:
7327 case AArch64::ST1Threev2d:
7328 case AArch64::ST1Fourv2d:
7329 case AArch64::ST1Twov1d:
7330 case AArch64::ST1Threev1d:
7331 case AArch64::ST1Fourv1d:
7332 case AArch64::ST1i8:
7333 case AArch64::ST1i16:
7334 case AArch64::ST1i32:
7335 case AArch64::ST1i64:
7336 case AArch64::IRG:
7337 case AArch64::IRGstack:
7338 case AArch64::STGloop:
7339 case AArch64::STZGloop:
7341 }
7342
7343 // Get the min/max offset and the scale.
7344 TypeSize ScaleValue(0U, false), Width(0U, false);
7345 int64_t MinOff, MaxOff;
7346 if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), ScaleValue, Width, MinOff,
7347 MaxOff))
7348 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7349
7350 // Construct the complete offset.
7351 bool IsMulVL = ScaleValue.isScalable();
7352 unsigned Scale = ScaleValue.getKnownMinValue();
7353 int64_t Offset = IsMulVL ? SOffset.getScalable() : SOffset.getFixed();
7354
7355 const MachineOperand &ImmOpnd =
7356 MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode()));
7357 Offset += ImmOpnd.getImm() * Scale;
7358
7359 // If the offset doesn't match the scale, we rewrite the instruction to
7360 // use the unscaled instruction instead. Likewise, if we have a negative
7361 // offset and there is an unscaled op to use.
7362 std::optional<unsigned> UnscaledOp =
7364 bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0);
7365 if (useUnscaledOp &&
7366 !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, ScaleValue, Width, MinOff,
7367 MaxOff))
7368 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7369
7370 Scale = ScaleValue.getKnownMinValue();
7371 assert(IsMulVL == ScaleValue.isScalable() &&
7372 "Unscaled opcode has different value for scalable");
7373
7374 int64_t Remainder = Offset % Scale;
7375 assert(!(Remainder && useUnscaledOp) &&
7376 "Cannot have remainder when using unscaled op");
7377
7378 assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
7379 int64_t NewOffset = Offset / Scale;
7380 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7381 Offset = Remainder;
7382 else {
7383 // Try to minimise the number of instructions required to materialise the
7384 // offset calculation. Specifically, for fixed offsets, if masking out the
7385 // low 12 bits leaves a legal add immediate, we can realise the offset
7386 // calculation with a single add instruction. Whenever this is possible,
7387 // prefer this split.
7388 int64_t HighPart = Offset & ~0xFFF;
7389 int64_t LowPart = Offset & 0xFFF;
7390 int64_t LowScaled = LowPart / Scale;
7391 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7392 MinOff <= LowScaled && LowScaled <= MaxOff &&
7394 NewOffset = LowScaled;
7395 Offset = HighPart;
7396 } else {
7397 // Default to a greedy split: take the memop immediate to be maximum /
7398 // minimum expressible offset and materialise the remainder.
7399 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7400 Offset = Offset - (NewOffset * Scale);
7401 }
7402 }
7403
7404 if (EmittableOffset)
7405 *EmittableOffset = NewOffset;
7406 if (OutUseUnscaledOp)
7407 *OutUseUnscaledOp = useUnscaledOp;
7408 if (OutUnscaledOp && UnscaledOp)
7409 *OutUnscaledOp = *UnscaledOp;
7410
7411 if (IsMulVL)
7412 SOffset = StackOffset::get(SOffset.getFixed(), Offset);
7413 else
7414 SOffset = StackOffset::get(Offset, SOffset.getScalable());
7416 (SOffset ? 0 : AArch64FrameOffsetIsLegal);
7417}
7418
7420 unsigned FrameReg, StackOffset &Offset,
7421 const AArch64InstrInfo *TII) {
7422 unsigned Opcode = MI.getOpcode();
7423 unsigned ImmIdx = FrameRegIdx + 1;
7424
7425 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7426 Offset += StackOffset::getFixed(MI.getOperand(ImmIdx).getImm());
7427 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
7428 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
7429 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
7430 MI.eraseFromParent();
7431 Offset = StackOffset();
7432 return true;
7433 }
7434
7435 int64_t NewOffset;
7436 unsigned UnscaledOp;
7437 bool UseUnscaledOp;
7438 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
7439 &UnscaledOp, &NewOffset);
7442 // Replace the FrameIndex with FrameReg.
7443 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
7444 if (UseUnscaledOp)
7445 MI.setDesc(TII->get(UnscaledOp));
7446
7447 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7448 return !Offset;
7449 }
7450
7451 return false;
7452}
7453
7459
7460MCInst AArch64InstrInfo::getNop() const { return MCInstBuilder(AArch64::NOP); }
7461
7462// AArch64 supports MachineCombiner.
7463bool AArch64InstrInfo::useMachineCombiner() const { return true; }
7464
7465// True when Opc sets flag
7466static bool isCombineInstrSettingFlag(unsigned Opc) {
7467 switch (Opc) {
7468 case AArch64::ADDSWrr:
7469 case AArch64::ADDSWri:
7470 case AArch64::ADDSXrr:
7471 case AArch64::ADDSXri:
7472 case AArch64::SUBSWrr:
7473 case AArch64::SUBSXrr:
7474 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7475 case AArch64::SUBSWri:
7476 case AArch64::SUBSXri:
7477 return true;
7478 default:
7479 break;
7480 }
7481 return false;
7482}
7483
7484// 32b Opcodes that can be combined with a MUL
7485static bool isCombineInstrCandidate32(unsigned Opc) {
7486 switch (Opc) {
7487 case AArch64::ADDWrr:
7488 case AArch64::ADDWri:
7489 case AArch64::SUBWrr:
7490 case AArch64::ADDSWrr:
7491 case AArch64::ADDSWri:
7492 case AArch64::SUBSWrr:
7493 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7494 case AArch64::SUBWri:
7495 case AArch64::SUBSWri:
7496 return true;
7497 default:
7498 break;
7499 }
7500 return false;
7501}
7502
7503// 64b Opcodes that can be combined with a MUL
7504static bool isCombineInstrCandidate64(unsigned Opc) {
7505 switch (Opc) {
7506 case AArch64::ADDXrr:
7507 case AArch64::ADDXri:
7508 case AArch64::SUBXrr:
7509 case AArch64::ADDSXrr:
7510 case AArch64::ADDSXri:
7511 case AArch64::SUBSXrr:
7512 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7513 case AArch64::SUBXri:
7514 case AArch64::SUBSXri:
7515 case AArch64::ADDv8i8:
7516 case AArch64::ADDv16i8:
7517 case AArch64::ADDv4i16:
7518 case AArch64::ADDv8i16:
7519 case AArch64::ADDv2i32:
7520 case AArch64::ADDv4i32:
7521 case AArch64::SUBv8i8:
7522 case AArch64::SUBv16i8:
7523 case AArch64::SUBv4i16:
7524 case AArch64::SUBv8i16:
7525 case AArch64::SUBv2i32:
7526 case AArch64::SUBv4i32:
7527 return true;
7528 default:
7529 break;
7530 }
7531 return false;
7532}
7533
7534// FP Opcodes that can be combined with a FMUL.
7535static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
7536 switch (Inst.getOpcode()) {
7537 default:
7538 break;
7539 case AArch64::FADDHrr:
7540 case AArch64::FADDSrr:
7541 case AArch64::FADDDrr:
7542 case AArch64::FADDv4f16:
7543 case AArch64::FADDv8f16:
7544 case AArch64::FADDv2f32:
7545 case AArch64::FADDv2f64:
7546 case AArch64::FADDv4f32:
7547 case AArch64::FSUBHrr:
7548 case AArch64::FSUBSrr:
7549 case AArch64::FSUBDrr:
7550 case AArch64::FSUBv4f16:
7551 case AArch64::FSUBv8f16:
7552 case AArch64::FSUBv2f32:
7553 case AArch64::FSUBv2f64:
7554 case AArch64::FSUBv4f32:
7556 // We can fuse FADD/FSUB with FMUL, if fusion is either allowed globally by
7557 // the target options or if FADD/FSUB has the contract fast-math flag.
7558 return Options.AllowFPOpFusion == FPOpFusion::Fast ||
7560 }
7561 return false;
7562}
7563
7564// Opcodes that can be combined with a MUL
7568
7569//
7570// Utility routine that checks if \param MO is defined by an
7571// \param CombineOpc instruction in the basic block \param MBB
7573 unsigned CombineOpc, unsigned ZeroReg = 0,
7574 bool CheckZeroReg = false) {
7575 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
7576 MachineInstr *MI = nullptr;
7577
7578 if (MO.isReg() && MO.getReg().isVirtual())
7579 MI = MRI.getUniqueVRegDef(MO.getReg());
7580 // And it needs to be in the trace (otherwise, it won't have a depth).
7581 if (!MI || MI->getParent() != &MBB || MI->getOpcode() != CombineOpc)
7582 return false;
7583 // Must only used by the user we combine with.
7584 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
7585 return false;
7586
7587 if (CheckZeroReg) {
7588 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
7589 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
7590 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
7591 // The third input reg must be zero.
7592 if (MI->getOperand(3).getReg() != ZeroReg)
7593 return false;
7594 }
7595
7596 if (isCombineInstrSettingFlag(CombineOpc) &&
7597 MI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) == -1)
7598 return false;
7599
7600 return true;
7601}
7602
7603//
7604// Is \param MO defined by an integer multiply and can be combined?
7606 unsigned MulOpc, unsigned ZeroReg) {
7607 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
7608}
7609
7610//
7611// Is \param MO defined by a floating-point multiply and can be combined?
7613 unsigned MulOpc) {
7614 return canCombine(MBB, MO, MulOpc);
7615}
7616
7617// TODO: There are many more machine instruction opcodes to match:
7618// 1. Other data types (integer, vectors)
7619// 2. Other math / logic operations (xor, or)
7620// 3. Other forms of the same operation (intrinsics and other variants)
7621bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
7622 bool Invert) const {
7623 if (Invert)
7624 return false;
7625 switch (Inst.getOpcode()) {
7626 // == Floating-point types ==
7627 // -- Floating-point instructions --
7628 case AArch64::FADDHrr:
7629 case AArch64::FADDSrr:
7630 case AArch64::FADDDrr:
7631 case AArch64::FMULHrr:
7632 case AArch64::FMULSrr:
7633 case AArch64::FMULDrr:
7634 case AArch64::FMULX16:
7635 case AArch64::FMULX32:
7636 case AArch64::FMULX64:
7637 // -- Advanced SIMD instructions --
7638 case AArch64::FADDv4f16:
7639 case AArch64::FADDv8f16:
7640 case AArch64::FADDv2f32:
7641 case AArch64::FADDv4f32:
7642 case AArch64::FADDv2f64:
7643 case AArch64::FMULv4f16:
7644 case AArch64::FMULv8f16:
7645 case AArch64::FMULv2f32:
7646 case AArch64::FMULv4f32:
7647 case AArch64::FMULv2f64:
7648 case AArch64::FMULXv4f16:
7649 case AArch64::FMULXv8f16:
7650 case AArch64::FMULXv2f32:
7651 case AArch64::FMULXv4f32:
7652 case AArch64::FMULXv2f64:
7653 // -- SVE instructions --
7654 // Opcodes FMULX_ZZZ_? don't exist because there is no unpredicated FMULX
7655 // in the SVE instruction set (though there are predicated ones).
7656 case AArch64::FADD_ZZZ_H:
7657 case AArch64::FADD_ZZZ_S:
7658 case AArch64::FADD_ZZZ_D:
7659 case AArch64::FMUL_ZZZ_H:
7660 case AArch64::FMUL_ZZZ_S:
7661 case AArch64::FMUL_ZZZ_D:
7664
7665 // == Integer types ==
7666 // -- Base instructions --
7667 // Opcodes MULWrr and MULXrr don't exist because
7668 // `MUL <Wd>, <Wn>, <Wm>` and `MUL <Xd>, <Xn>, <Xm>` are aliases of
7669 // `MADD <Wd>, <Wn>, <Wm>, WZR` and `MADD <Xd>, <Xn>, <Xm>, XZR` respectively.
7670 // The machine-combiner does not support three-source-operands machine
7671 // instruction. So we cannot reassociate MULs.
7672 case AArch64::ADDWrr:
7673 case AArch64::ADDXrr:
7674 case AArch64::ANDWrr:
7675 case AArch64::ANDXrr:
7676 case AArch64::ORRWrr:
7677 case AArch64::ORRXrr:
7678 case AArch64::EORWrr:
7679 case AArch64::EORXrr:
7680 case AArch64::EONWrr:
7681 case AArch64::EONXrr:
7682 // -- Advanced SIMD instructions --
7683 // Opcodes MULv1i64 and MULv2i64 don't exist because there is no 64-bit MUL
7684 // in the Advanced SIMD instruction set.
7685 case AArch64::ADDv8i8:
7686 case AArch64::ADDv16i8:
7687 case AArch64::ADDv4i16:
7688 case AArch64::ADDv8i16:
7689 case AArch64::ADDv2i32:
7690 case AArch64::ADDv4i32:
7691 case AArch64::ADDv1i64:
7692 case AArch64::ADDv2i64:
7693 case AArch64::MULv8i8:
7694 case AArch64::MULv16i8:
7695 case AArch64::MULv4i16:
7696 case AArch64::MULv8i16:
7697 case AArch64::MULv2i32:
7698 case AArch64::MULv4i32:
7699 case AArch64::ANDv8i8:
7700 case AArch64::ANDv16i8:
7701 case AArch64::ORRv8i8:
7702 case AArch64::ORRv16i8:
7703 case AArch64::EORv8i8:
7704 case AArch64::EORv16i8:
7705 // -- SVE instructions --
7706 case AArch64::ADD_ZZZ_B:
7707 case AArch64::ADD_ZZZ_H:
7708 case AArch64::ADD_ZZZ_S:
7709 case AArch64::ADD_ZZZ_D:
7710 case AArch64::MUL_ZZZ_B:
7711 case AArch64::MUL_ZZZ_H:
7712 case AArch64::MUL_ZZZ_S:
7713 case AArch64::MUL_ZZZ_D:
7714 case AArch64::AND_ZZZ:
7715 case AArch64::ORR_ZZZ:
7716 case AArch64::EOR_ZZZ:
7717 return true;
7718
7719 default:
7720 return false;
7721 }
7722}
7723
7724/// Find instructions that can be turned into madd.
7726 SmallVectorImpl<unsigned> &Patterns) {
7727 unsigned Opc = Root.getOpcode();
7728 MachineBasicBlock &MBB = *Root.getParent();
7729 bool Found = false;
7730
7732 return false;
7734 int Cmp_NZCV =
7735 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
7736 // When NZCV is live bail out.
7737 if (Cmp_NZCV == -1)
7738 return false;
7739 unsigned NewOpc = convertToNonFlagSettingOpc(Root);
7740 // When opcode can't change bail out.
7741 // CHECKME: do we miss any cases for opcode conversion?
7742 if (NewOpc == Opc)
7743 return false;
7744 Opc = NewOpc;
7745 }
7746
7747 auto setFound = [&](int Opcode, int Operand, unsigned ZeroReg,
7748 unsigned Pattern) {
7749 if (canCombineWithMUL(MBB, Root.getOperand(Operand), Opcode, ZeroReg)) {
7750 Patterns.push_back(Pattern);
7751 Found = true;
7752 }
7753 };
7754
7755 auto setVFound = [&](int Opcode, int Operand, unsigned Pattern) {
7756 if (canCombine(MBB, Root.getOperand(Operand), Opcode)) {
7757 Patterns.push_back(Pattern);
7758 Found = true;
7759 }
7760 };
7761
7763
7764 switch (Opc) {
7765 default:
7766 break;
7767 case AArch64::ADDWrr:
7768 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
7769 "ADDWrr does not have register operands");
7770 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7771 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7772 break;
7773 case AArch64::ADDXrr:
7774 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7775 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7776 break;
7777 case AArch64::SUBWrr:
7778 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7779 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7780 break;
7781 case AArch64::SUBXrr:
7782 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7783 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7784 break;
7785 case AArch64::ADDWri:
7786 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7787 break;
7788 case AArch64::ADDXri:
7789 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7790 break;
7791 case AArch64::SUBWri:
7792 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7793 break;
7794 case AArch64::SUBXri:
7795 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7796 break;
7797 case AArch64::ADDv8i8:
7798 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7799 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7800 break;
7801 case AArch64::ADDv16i8:
7802 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7803 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7804 break;
7805 case AArch64::ADDv4i16:
7806 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7807 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7808 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7809 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7810 break;
7811 case AArch64::ADDv8i16:
7812 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7813 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7814 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7815 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7816 break;
7817 case AArch64::ADDv2i32:
7818 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7819 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7820 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7821 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7822 break;
7823 case AArch64::ADDv4i32:
7824 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7825 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7826 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7827 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7828 break;
7829 case AArch64::SUBv8i8:
7830 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7831 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7832 break;
7833 case AArch64::SUBv16i8:
7834 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7835 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7836 break;
7837 case AArch64::SUBv4i16:
7838 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7839 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7840 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7841 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7842 break;
7843 case AArch64::SUBv8i16:
7844 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7845 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7846 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7847 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7848 break;
7849 case AArch64::SUBv2i32:
7850 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7851 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7852 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7853 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7854 break;
7855 case AArch64::SUBv4i32:
7856 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7857 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7858 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7859 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7860 break;
7861 }
7862 return Found;
7863}
7864
7865bool AArch64InstrInfo::isAccumulationOpcode(unsigned Opcode) const {
7866 switch (Opcode) {
7867 default:
7868 break;
7869 case AArch64::UABALB_ZZZ_D:
7870 case AArch64::UABALB_ZZZ_H:
7871 case AArch64::UABALB_ZZZ_S:
7872 case AArch64::UABALT_ZZZ_D:
7873 case AArch64::UABALT_ZZZ_H:
7874 case AArch64::UABALT_ZZZ_S:
7875 case AArch64::SABALB_ZZZ_D:
7876 case AArch64::SABALB_ZZZ_S:
7877 case AArch64::SABALB_ZZZ_H:
7878 case AArch64::SABALT_ZZZ_D:
7879 case AArch64::SABALT_ZZZ_S:
7880 case AArch64::SABALT_ZZZ_H:
7881 case AArch64::UABALv16i8_v8i16:
7882 case AArch64::UABALv2i32_v2i64:
7883 case AArch64::UABALv4i16_v4i32:
7884 case AArch64::UABALv4i32_v2i64:
7885 case AArch64::UABALv8i16_v4i32:
7886 case AArch64::UABALv8i8_v8i16:
7887 case AArch64::UABAv16i8:
7888 case AArch64::UABAv2i32:
7889 case AArch64::UABAv4i16:
7890 case AArch64::UABAv4i32:
7891 case AArch64::UABAv8i16:
7892 case AArch64::UABAv8i8:
7893 case AArch64::SABALv16i8_v8i16:
7894 case AArch64::SABALv2i32_v2i64:
7895 case AArch64::SABALv4i16_v4i32:
7896 case AArch64::SABALv4i32_v2i64:
7897 case AArch64::SABALv8i16_v4i32:
7898 case AArch64::SABALv8i8_v8i16:
7899 case AArch64::SABAv16i8:
7900 case AArch64::SABAv2i32:
7901 case AArch64::SABAv4i16:
7902 case AArch64::SABAv4i32:
7903 case AArch64::SABAv8i16:
7904 case AArch64::SABAv8i8:
7905 return true;
7906 }
7907
7908 return false;
7909}
7910
7911unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7912 unsigned AccumulationOpcode) const {
7913 switch (AccumulationOpcode) {
7914 default:
7915 llvm_unreachable("Unsupported accumulation Opcode!");
7916 case AArch64::UABALB_ZZZ_D:
7917 return AArch64::UABDLB_ZZZ_D;
7918 case AArch64::UABALB_ZZZ_H:
7919 return AArch64::UABDLB_ZZZ_H;
7920 case AArch64::UABALB_ZZZ_S:
7921 return AArch64::UABDLB_ZZZ_S;
7922 case AArch64::UABALT_ZZZ_D:
7923 return AArch64::UABDLT_ZZZ_D;
7924 case AArch64::UABALT_ZZZ_H:
7925 return AArch64::UABDLT_ZZZ_H;
7926 case AArch64::UABALT_ZZZ_S:
7927 return AArch64::UABDLT_ZZZ_S;
7928 case AArch64::UABALv16i8_v8i16:
7929 return AArch64::UABDLv16i8_v8i16;
7930 case AArch64::UABALv2i32_v2i64:
7931 return AArch64::UABDLv2i32_v2i64;
7932 case AArch64::UABALv4i16_v4i32:
7933 return AArch64::UABDLv4i16_v4i32;
7934 case AArch64::UABALv4i32_v2i64:
7935 return AArch64::UABDLv4i32_v2i64;
7936 case AArch64::UABALv8i16_v4i32:
7937 return AArch64::UABDLv8i16_v4i32;
7938 case AArch64::UABALv8i8_v8i16:
7939 return AArch64::UABDLv8i8_v8i16;
7940 case AArch64::UABAv16i8:
7941 return AArch64::UABDv16i8;
7942 case AArch64::UABAv2i32:
7943 return AArch64::UABDv2i32;
7944 case AArch64::UABAv4i16:
7945 return AArch64::UABDv4i16;
7946 case AArch64::UABAv4i32:
7947 return AArch64::UABDv4i32;
7948 case AArch64::UABAv8i16:
7949 return AArch64::UABDv8i16;
7950 case AArch64::UABAv8i8:
7951 return AArch64::UABDv8i8;
7952 case AArch64::SABALB_ZZZ_D:
7953 return AArch64::SABDLB_ZZZ_D;
7954 case AArch64::SABALB_ZZZ_S:
7955 return AArch64::SABDLB_ZZZ_S;
7956 case AArch64::SABALB_ZZZ_H:
7957 return AArch64::SABDLB_ZZZ_H;
7958 case AArch64::SABALT_ZZZ_D:
7959 return AArch64::SABDLT_ZZZ_D;
7960 case AArch64::SABALT_ZZZ_S:
7961 return AArch64::SABDLT_ZZZ_S;
7962 case AArch64::SABALT_ZZZ_H:
7963 return AArch64::SABDLT_ZZZ_H;
7964 case AArch64::SABALv16i8_v8i16:
7965 return AArch64::SABDLv16i8_v8i16;
7966 case AArch64::SABALv2i32_v2i64:
7967 return AArch64::SABDLv2i32_v2i64;
7968 case AArch64::SABALv4i16_v4i32:
7969 return AArch64::SABDLv4i16_v4i32;
7970 case AArch64::SABALv4i32_v2i64:
7971 return AArch64::SABDLv4i32_v2i64;
7972 case AArch64::SABALv8i16_v4i32:
7973 return AArch64::SABDLv8i16_v4i32;
7974 case AArch64::SABALv8i8_v8i16:
7975 return AArch64::SABDLv8i8_v8i16;
7976 case AArch64::SABAv16i8:
7977 return AArch64::SABDv16i8;
7978 case AArch64::SABAv2i32:
7979 return AArch64::SABAv2i32;
7980 case AArch64::SABAv4i16:
7981 return AArch64::SABDv4i16;
7982 case AArch64::SABAv4i32:
7983 return AArch64::SABDv4i32;
7984 case AArch64::SABAv8i16:
7985 return AArch64::SABDv8i16;
7986 case AArch64::SABAv8i8:
7987 return AArch64::SABDv8i8;
7988 }
7989}
7990
7991/// Floating-Point Support
7992
7993/// Find instructions that can be turned into madd.
7995 SmallVectorImpl<unsigned> &Patterns) {
7996
7997 if (!isCombineInstrCandidateFP(Root))
7998 return false;
7999
8000 MachineBasicBlock &MBB = *Root.getParent();
8001 bool Found = false;
8002
8003 auto Match = [&](int Opcode, int Operand, unsigned Pattern) -> bool {
8004 if (canCombineWithFMUL(MBB, Root.getOperand(Operand), Opcode)) {
8005 Patterns.push_back(Pattern);
8006 return true;
8007 }
8008 return false;
8009 };
8010
8012
8013 switch (Root.getOpcode()) {
8014 default:
8015 assert(false && "Unsupported FP instruction in combiner\n");
8016 break;
8017 case AArch64::FADDHrr:
8018 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8019 "FADDHrr does not have register operands");
8020
8021 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8022 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8023 break;
8024 case AArch64::FADDSrr:
8025 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8026 "FADDSrr does not have register operands");
8027
8028 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8029 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8030
8031 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8032 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8033 break;
8034 case AArch64::FADDDrr:
8035 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8036 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8037
8038 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8039 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8040 break;
8041 case AArch64::FADDv4f16:
8042 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8043 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8044
8045 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8046 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8047 break;
8048 case AArch64::FADDv8f16:
8049 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8050 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8051
8052 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8053 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8054 break;
8055 case AArch64::FADDv2f32:
8056 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8057 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8058
8059 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8060 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8061 break;
8062 case AArch64::FADDv2f64:
8063 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8064 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8065
8066 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8067 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8068 break;
8069 case AArch64::FADDv4f32:
8070 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8071 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8072
8073 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8074 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8075 break;
8076 case AArch64::FSUBHrr:
8077 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8078 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8079 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8080 break;
8081 case AArch64::FSUBSrr:
8082 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8083
8084 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8085 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8086
8087 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8088 break;
8089 case AArch64::FSUBDrr:
8090 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8091
8092 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8093 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8094
8095 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8096 break;
8097 case AArch64::FSUBv4f16:
8098 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8099 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8100
8101 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8102 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8103 break;
8104 case AArch64::FSUBv8f16:
8105 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8106 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8107
8108 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8109 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8110 break;
8111 case AArch64::FSUBv2f32:
8112 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8113 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8114
8115 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8116 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8117 break;
8118 case AArch64::FSUBv2f64:
8119 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8120 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8121
8122 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8123 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8124 break;
8125 case AArch64::FSUBv4f32:
8126 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8127 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8128
8129 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8130 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8131 break;
8132 }
8133 return Found;
8134}
8135
8137 SmallVectorImpl<unsigned> &Patterns) {
8138 MachineBasicBlock &MBB = *Root.getParent();
8139 bool Found = false;
8140
8141 auto Match = [&](unsigned Opcode, int Operand, unsigned Pattern) -> bool {
8142 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8143 MachineOperand &MO = Root.getOperand(Operand);
8144 MachineInstr *MI = nullptr;
8145 if (MO.isReg() && MO.getReg().isVirtual())
8146 MI = MRI.getUniqueVRegDef(MO.getReg());
8147 // Ignore No-op COPYs in FMUL(COPY(DUP(..)))
8148 if (MI && MI->getOpcode() == TargetOpcode::COPY &&
8149 MI->getOperand(1).getReg().isVirtual())
8150 MI = MRI.getUniqueVRegDef(MI->getOperand(1).getReg());
8151 if (MI && MI->getOpcode() == Opcode) {
8152 Patterns.push_back(Pattern);
8153 return true;
8154 }
8155 return false;
8156 };
8157
8159
8160 switch (Root.getOpcode()) {
8161 default:
8162 return false;
8163 case AArch64::FMULv2f32:
8164 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8165 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8166 break;
8167 case AArch64::FMULv2f64:
8168 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8169 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8170 break;
8171 case AArch64::FMULv4f16:
8172 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8173 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8174 break;
8175 case AArch64::FMULv4f32:
8176 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8177 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8178 break;
8179 case AArch64::FMULv8f16:
8180 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8181 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8182 break;
8183 }
8184
8185 return Found;
8186}
8187
8189 SmallVectorImpl<unsigned> &Patterns) {
8190 unsigned Opc = Root.getOpcode();
8191 MachineBasicBlock &MBB = *Root.getParent();
8192 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8193
8194 auto Match = [&](unsigned Opcode, unsigned Pattern) -> bool {
8195 MachineOperand &MO = Root.getOperand(1);
8197 if (MI != nullptr && (MI->getOpcode() == Opcode) &&
8198 MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()) &&
8202 MI->getFlag(MachineInstr::MIFlag::FmNsz)) {
8203 Patterns.push_back(Pattern);
8204 return true;
8205 }
8206 return false;
8207 };
8208
8209 switch (Opc) {
8210 default:
8211 break;
8212 case AArch64::FNEGDr:
8213 return Match(AArch64::FMADDDrrr, AArch64MachineCombinerPattern::FNMADD);
8214 case AArch64::FNEGSr:
8215 return Match(AArch64::FMADDSrrr, AArch64MachineCombinerPattern::FNMADD);
8216 }
8217
8218 return false;
8219}
8220
8221/// Return true when a code sequence can improve throughput. It
8222/// should be called only for instructions in loops.
8223/// \param Pattern - combiner pattern
8225 switch (Pattern) {
8226 default:
8227 break;
8333 return true;
8334 } // end switch (Pattern)
8335 return false;
8336}
8337
8338/// Find other MI combine patterns.
8340 SmallVectorImpl<unsigned> &Patterns) {
8341 // A - (B + C) ==> (A - B) - C or (A - C) - B
8342 unsigned Opc = Root.getOpcode();
8343 MachineBasicBlock &MBB = *Root.getParent();
8344
8345 switch (Opc) {
8346 case AArch64::SUBWrr:
8347 case AArch64::SUBSWrr:
8348 case AArch64::SUBXrr:
8349 case AArch64::SUBSXrr:
8350 // Found candidate root.
8351 break;
8352 default:
8353 return false;
8354 }
8355
8357 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) ==
8358 -1)
8359 return false;
8360
8361 if (canCombine(MBB, Root.getOperand(2), AArch64::ADDWrr) ||
8362 canCombine(MBB, Root.getOperand(2), AArch64::ADDSWrr) ||
8363 canCombine(MBB, Root.getOperand(2), AArch64::ADDXrr) ||
8364 canCombine(MBB, Root.getOperand(2), AArch64::ADDSXrr)) {
8367 return true;
8368 }
8369
8370 return false;
8371}
8372
8373/// Check if the given instruction forms a gather load pattern that can be
8374/// optimized for better Memory-Level Parallelism (MLP). This function
8375/// identifies chains of NEON lane load instructions that load data from
8376/// different memory addresses into individual lanes of a 128-bit vector
8377/// register, then attempts to split the pattern into parallel loads to break
8378/// the serial dependency between instructions.
8379///
8380/// Pattern Matched:
8381/// Initial scalar load -> SUBREG_TO_REG (lane 0) -> LD1i* (lane 1) ->
8382/// LD1i* (lane 2) -> ... -> LD1i* (lane N-1, Root)
8383///
8384/// Transformed Into:
8385/// Two parallel vector loads using fewer lanes each, followed by ZIP1v2i64
8386/// to combine the results, enabling better memory-level parallelism.
8387///
8388/// Supported Element Types:
8389/// - 32-bit elements (LD1i32, 4 lanes total)
8390/// - 16-bit elements (LD1i16, 8 lanes total)
8391/// - 8-bit elements (LD1i8, 16 lanes total)
8393 SmallVectorImpl<unsigned> &Patterns,
8394 unsigned LoadLaneOpCode, unsigned NumLanes) {
8395 const MachineFunction *MF = Root.getMF();
8396
8397 // Early exit if optimizing for size.
8398 if (MF->getFunction().hasMinSize())
8399 return false;
8400
8401 const MachineRegisterInfo &MRI = MF->getRegInfo();
8403
8404 // The root of the pattern must load into the last lane of the vector.
8405 if (Root.getOperand(2).getImm() != NumLanes - 1)
8406 return false;
8407
8408 // Check that we have load into all lanes except lane 0.
8409 // For each load we also want to check that:
8410 // 1. It has a single non-debug use (since we will be replacing the virtual
8411 // register)
8412 // 2. That the addressing mode only uses a single pointer operand
8413 auto *CurrInstr = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8414 auto Range = llvm::seq<unsigned>(1, NumLanes - 1);
8415 SmallSet<unsigned, 16> RemainingLanes(Range.begin(), Range.end());
8417 while (!RemainingLanes.empty() && CurrInstr &&
8418 CurrInstr->getOpcode() == LoadLaneOpCode &&
8419 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
8420 CurrInstr->getNumOperands() == 4) {
8421 RemainingLanes.erase(CurrInstr->getOperand(2).getImm());
8422 LoadInstrs.push_back(CurrInstr);
8423 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8424 }
8425
8426 // Check that we have found a match for lanes N-1.. 1.
8427 if (!RemainingLanes.empty())
8428 return false;
8429
8430 // Match the SUBREG_TO_REG sequence.
8431 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8432 return false;
8433
8434 // Verify that the subreg to reg loads an integer into the first lane.
8435 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8436 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8437 if (TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8438 return false;
8439
8440 // Verify that it also has a single non debug use.
8441 if (!MRI.hasOneNonDBGUse(Lane0LoadReg))
8442 return false;
8443
8444 LoadInstrs.push_back(MRI.getUniqueVRegDef(Lane0LoadReg));
8445
8446 // If there is any chance of aliasing, do not apply the pattern.
8447 // Walk backward through the MBB starting from Root.
8448 // Exit early if we've encountered all load instructions or hit the search
8449 // limit.
8450 auto MBBItr = Root.getIterator();
8451 unsigned RemainingSteps = GatherOptSearchLimit;
8452 SmallPtrSet<const MachineInstr *, 16> RemainingLoadInstrs;
8453 RemainingLoadInstrs.insert(LoadInstrs.begin(), LoadInstrs.end());
8454 const MachineBasicBlock *MBB = Root.getParent();
8455
8456 for (; MBBItr != MBB->begin() && RemainingSteps > 0 &&
8457 !RemainingLoadInstrs.empty();
8458 --MBBItr, --RemainingSteps) {
8459 const MachineInstr &CurrInstr = *MBBItr;
8460
8461 // Remove this instruction from remaining loads if it's one we're tracking.
8462 RemainingLoadInstrs.erase(&CurrInstr);
8463
8464 // Check for potential aliasing with any of the load instructions to
8465 // optimize.
8466 if (CurrInstr.isLoadFoldBarrier())
8467 return false;
8468 }
8469
8470 // If we hit the search limit without finding all load instructions,
8471 // don't match the pattern.
8472 if (RemainingSteps == 0 && !RemainingLoadInstrs.empty())
8473 return false;
8474
8475 switch (NumLanes) {
8476 case 4:
8478 break;
8479 case 8:
8481 break;
8482 case 16:
8484 break;
8485 default:
8486 llvm_unreachable("Got bad number of lanes for gather pattern.");
8487 }
8488
8489 return true;
8490}
8491
8492/// Search for patterns of LD instructions we can optimize.
8494 SmallVectorImpl<unsigned> &Patterns) {
8495
8496 // The pattern searches for loads into single lanes.
8497 switch (Root.getOpcode()) {
8498 case AArch64::LD1i32:
8499 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 4);
8500 case AArch64::LD1i16:
8501 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 8);
8502 case AArch64::LD1i8:
8503 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 16);
8504 default:
8505 return false;
8506 }
8507}
8508
8509/// Generate optimized instruction sequence for gather load patterns to improve
8510/// Memory-Level Parallelism (MLP). This function transforms a chain of
8511/// sequential NEON lane loads into parallel vector loads that can execute
8512/// concurrently.
8513static void
8517 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8518 unsigned Pattern, unsigned NumLanes) {
8519 MachineFunction &MF = *Root.getParent()->getParent();
8520 MachineRegisterInfo &MRI = MF.getRegInfo();
8522
8523 // Gather the initial load instructions to build the pattern.
8524 SmallVector<MachineInstr *, 16> LoadToLaneInstrs;
8525 MachineInstr *CurrInstr = &Root;
8526 for (unsigned i = 0; i < NumLanes - 1; ++i) {
8527 LoadToLaneInstrs.push_back(CurrInstr);
8528 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8529 }
8530
8531 // Sort the load instructions according to the lane.
8532 llvm::sort(LoadToLaneInstrs,
8533 [](const MachineInstr *A, const MachineInstr *B) {
8534 return A->getOperand(2).getImm() > B->getOperand(2).getImm();
8535 });
8536
8537 MachineInstr *SubregToReg = CurrInstr;
8538 LoadToLaneInstrs.push_back(
8539 MRI.getUniqueVRegDef(SubregToReg->getOperand(1).getReg()));
8540 auto LoadToLaneInstrsAscending = llvm::reverse(LoadToLaneInstrs);
8541
8542 const TargetRegisterClass *FPR128RegClass =
8543 MRI.getRegClass(Root.getOperand(0).getReg());
8544
8545 // Helper lambda to create a LD1 instruction.
8546 auto CreateLD1Instruction = [&](MachineInstr *OriginalInstr,
8547 Register SrcRegister, unsigned Lane,
8548 Register OffsetRegister,
8549 bool OffsetRegisterKillState) {
8550 auto NewRegister = MRI.createVirtualRegister(FPR128RegClass);
8551 MachineInstrBuilder LoadIndexIntoRegister =
8552 BuildMI(MF, MIMetadata(*OriginalInstr), TII->get(Root.getOpcode()),
8553 NewRegister)
8554 .addReg(SrcRegister)
8555 .addImm(Lane)
8556 .addReg(OffsetRegister, getKillRegState(OffsetRegisterKillState))
8557 .setMemRefs(OriginalInstr->memoperands());
8558 InstrIdxForVirtReg.insert(std::make_pair(NewRegister, InsInstrs.size()));
8559 InsInstrs.push_back(LoadIndexIntoRegister);
8560 return NewRegister;
8561 };
8562
8563 // Helper to create load instruction based on the NumLanes in the NEON
8564 // register we are rewriting.
8565 auto CreateLDRInstruction =
8566 [&](unsigned NumLanes, Register DestReg, Register OffsetReg,
8568 unsigned Opcode;
8569 switch (NumLanes) {
8570 case 4:
8571 Opcode = AArch64::LDRSui;
8572 break;
8573 case 8:
8574 Opcode = AArch64::LDRHui;
8575 break;
8576 case 16:
8577 Opcode = AArch64::LDRBui;
8578 break;
8579 default:
8581 "Got unsupported number of lanes in machine-combiner gather pattern");
8582 }
8583 // Immediate offset load
8584 return BuildMI(MF, MIMetadata(Root), TII->get(Opcode), DestReg)
8585 .addReg(OffsetReg)
8586 .addImm(0)
8587 .setMemRefs(MMOs);
8588 };
8589
8590 // Load the remaining lanes into register 0.
8591 auto LanesToLoadToReg0 =
8592 llvm::make_range(LoadToLaneInstrsAscending.begin() + 1,
8593 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8594 Register PrevReg = SubregToReg->getOperand(0).getReg();
8595 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg0)) {
8596 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8597 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8598 OffsetRegOperand.getReg(),
8599 OffsetRegOperand.isKill());
8600 DelInstrs.push_back(LoadInstr);
8601 }
8602 Register LastLoadReg0 = PrevReg;
8603
8604 // First load into register 1. Perform an integer load to zero out the upper
8605 // lanes in a single instruction.
8606 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8607 MachineInstr *OriginalSplitLoad =
8608 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8609 Register DestRegForMiddleIndex = MRI.createVirtualRegister(
8610 MRI.getRegClass(Lane0Load->getOperand(0).getReg()));
8611
8612 const MachineOperand &OriginalSplitToLoadOffsetOperand =
8613 OriginalSplitLoad->getOperand(3);
8614 MachineInstrBuilder MiddleIndexLoadInstr =
8615 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8616 OriginalSplitToLoadOffsetOperand.getReg(),
8617 OriginalSplitLoad->memoperands());
8618
8619 InstrIdxForVirtReg.insert(
8620 std::make_pair(DestRegForMiddleIndex, InsInstrs.size()));
8621 InsInstrs.push_back(MiddleIndexLoadInstr);
8622 DelInstrs.push_back(OriginalSplitLoad);
8623
8624 // Subreg To Reg instruction for register 1.
8625 Register DestRegForSubregToReg = MRI.createVirtualRegister(FPR128RegClass);
8626 unsigned SubregType;
8627 switch (NumLanes) {
8628 case 4:
8629 SubregType = AArch64::ssub;
8630 break;
8631 case 8:
8632 SubregType = AArch64::hsub;
8633 break;
8634 case 16:
8635 SubregType = AArch64::bsub;
8636 break;
8637 default:
8639 "Got invalid NumLanes for machine-combiner gather pattern");
8640 }
8641
8642 auto SubRegToRegInstr =
8643 BuildMI(MF, MIMetadata(Root), TII->get(SubregToReg->getOpcode()),
8644 DestRegForSubregToReg)
8645 .addReg(DestRegForMiddleIndex, getKillRegState(true))
8646 .addImm(SubregType);
8647 InstrIdxForVirtReg.insert(
8648 std::make_pair(DestRegForSubregToReg, InsInstrs.size()));
8649 InsInstrs.push_back(SubRegToRegInstr);
8650
8651 // Load remaining lanes into register 1.
8652 auto LanesToLoadToReg1 =
8653 llvm::make_range(LoadToLaneInstrsAscending.begin() + NumLanes / 2 + 1,
8654 LoadToLaneInstrsAscending.end());
8655 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8656 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg1)) {
8657 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8658 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8659 OffsetRegOperand.getReg(),
8660 OffsetRegOperand.isKill());
8661
8662 // Do not add the last reg to DelInstrs - it will be removed later.
8663 if (Index == NumLanes / 2 - 2) {
8664 break;
8665 }
8666 DelInstrs.push_back(LoadInstr);
8667 }
8668 Register LastLoadReg1 = PrevReg;
8669
8670 // Create the final zip instruction to combine the results.
8671 MachineInstrBuilder ZipInstr =
8672 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::ZIP1v2i64),
8673 Root.getOperand(0).getReg())
8674 .addReg(LastLoadReg0)
8675 .addReg(LastLoadReg1);
8676 InsInstrs.push_back(ZipInstr);
8677}
8678
8692
8693/// Return true when there is potentially a faster code sequence for an
8694/// instruction chain ending in \p Root. All potential patterns are listed in
8695/// the \p Pattern vector. Pattern should be sorted in priority order since the
8696/// pattern evaluator stops checking as soon as it finds a faster sequence.
8697
8698bool AArch64InstrInfo::getMachineCombinerPatterns(
8699 MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
8700 bool DoRegPressureReduce) const {
8701 // Integer patterns
8702 if (getMaddPatterns(Root, Patterns))
8703 return true;
8704 // Floating point patterns
8705 if (getFMULPatterns(Root, Patterns))
8706 return true;
8707 if (getFMAPatterns(Root, Patterns))
8708 return true;
8709 if (getFNEGPatterns(Root, Patterns))
8710 return true;
8711
8712 // Other patterns
8713 if (getMiscPatterns(Root, Patterns))
8714 return true;
8715
8716 // Load patterns
8717 if (getLoadPatterns(Root, Patterns))
8718 return true;
8719
8720 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
8721 DoRegPressureReduce);
8722}
8723
8725/// genFusedMultiply - Generate fused multiply instructions.
8726/// This function supports both integer and floating point instructions.
8727/// A typical example:
8728/// F|MUL I=A,B,0
8729/// F|ADD R,I,C
8730/// ==> F|MADD R,A,B,C
8731/// \param MF Containing MachineFunction
8732/// \param MRI Register information
8733/// \param TII Target information
8734/// \param Root is the F|ADD instruction
8735/// \param [out] InsInstrs is a vector of machine instructions and will
8736/// contain the generated madd instruction
8737/// \param IdxMulOpd is index of operand in Root that is the result of
8738/// the F|MUL. In the example above IdxMulOpd is 1.
8739/// \param MaddOpc the opcode fo the f|madd instruction
8740/// \param RC Register class of operands
8741/// \param kind of fma instruction (addressing mode) to be generated
8742/// \param ReplacedAddend is the result register from the instruction
8743/// replacing the non-combined operand, if any.
8744static MachineInstr *
8746 const TargetInstrInfo *TII, MachineInstr &Root,
8747 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
8748 unsigned MaddOpc, const TargetRegisterClass *RC,
8750 const Register *ReplacedAddend = nullptr) {
8751 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8752
8753 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8754 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8755 Register ResultReg = Root.getOperand(0).getReg();
8756 Register SrcReg0 = MUL->getOperand(1).getReg();
8757 bool Src0IsKill = MUL->getOperand(1).isKill();
8758 Register SrcReg1 = MUL->getOperand(2).getReg();
8759 bool Src1IsKill = MUL->getOperand(2).isKill();
8760
8761 Register SrcReg2;
8762 bool Src2IsKill;
8763 if (ReplacedAddend) {
8764 // If we just generated a new addend, we must be it's only use.
8765 SrcReg2 = *ReplacedAddend;
8766 Src2IsKill = true;
8767 } else {
8768 SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
8769 Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
8770 }
8771
8772 if (ResultReg.isVirtual())
8773 MRI.constrainRegClass(ResultReg, RC);
8774 if (SrcReg0.isVirtual())
8775 MRI.constrainRegClass(SrcReg0, RC);
8776 if (SrcReg1.isVirtual())
8777 MRI.constrainRegClass(SrcReg1, RC);
8778 if (SrcReg2.isVirtual())
8779 MRI.constrainRegClass(SrcReg2, RC);
8780
8782 if (kind == FMAInstKind::Default)
8783 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8784 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8785 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8786 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8787 else if (kind == FMAInstKind::Indexed)
8788 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8789 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8790 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8791 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8792 .addImm(MUL->getOperand(3).getImm());
8793 else if (kind == FMAInstKind::Accumulator)
8794 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8795 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8796 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8797 .addReg(SrcReg1, getKillRegState(Src1IsKill));
8798 else
8799 assert(false && "Invalid FMA instruction kind \n");
8800 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
8801 InsInstrs.push_back(MIB);
8802 return MUL;
8803}
8804
8805static MachineInstr *
8807 const TargetInstrInfo *TII, MachineInstr &Root,
8809 MachineInstr *MAD = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8810
8811 unsigned Opc = 0;
8812 const TargetRegisterClass *RC = MRI.getRegClass(MAD->getOperand(0).getReg());
8813 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8814 Opc = AArch64::FNMADDSrrr;
8815 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8816 Opc = AArch64::FNMADDDrrr;
8817 else
8818 return nullptr;
8819
8820 Register ResultReg = Root.getOperand(0).getReg();
8821 Register SrcReg0 = MAD->getOperand(1).getReg();
8822 Register SrcReg1 = MAD->getOperand(2).getReg();
8823 Register SrcReg2 = MAD->getOperand(3).getReg();
8824 bool Src0IsKill = MAD->getOperand(1).isKill();
8825 bool Src1IsKill = MAD->getOperand(2).isKill();
8826 bool Src2IsKill = MAD->getOperand(3).isKill();
8827 if (ResultReg.isVirtual())
8828 MRI.constrainRegClass(ResultReg, RC);
8829 if (SrcReg0.isVirtual())
8830 MRI.constrainRegClass(SrcReg0, RC);
8831 if (SrcReg1.isVirtual())
8832 MRI.constrainRegClass(SrcReg1, RC);
8833 if (SrcReg2.isVirtual())
8834 MRI.constrainRegClass(SrcReg2, RC);
8835
8837 BuildMI(MF, MIMetadata(Root), TII->get(Opc), ResultReg)
8838 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8839 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8840 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8841 InsInstrs.push_back(MIB);
8842
8843 return MAD;
8844}
8845
8846/// Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
8847static MachineInstr *
8850 unsigned IdxDupOp, unsigned MulOpc,
8851 const TargetRegisterClass *RC, MachineRegisterInfo &MRI) {
8852 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8853 "Invalid index of FMUL operand");
8854
8855 MachineFunction &MF = *Root.getMF();
8857
8858 MachineInstr *Dup =
8859 MF.getRegInfo().getUniqueVRegDef(Root.getOperand(IdxDupOp).getReg());
8860
8861 if (Dup->getOpcode() == TargetOpcode::COPY)
8862 Dup = MRI.getUniqueVRegDef(Dup->getOperand(1).getReg());
8863
8864 Register DupSrcReg = Dup->getOperand(1).getReg();
8865 MRI.clearKillFlags(DupSrcReg);
8866 MRI.constrainRegClass(DupSrcReg, RC);
8867
8868 unsigned DupSrcLane = Dup->getOperand(2).getImm();
8869
8870 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8871 MachineOperand &MulOp = Root.getOperand(IdxMulOp);
8872
8873 Register ResultReg = Root.getOperand(0).getReg();
8874
8876 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MulOpc), ResultReg)
8877 .add(MulOp)
8878 .addReg(DupSrcReg)
8879 .addImm(DupSrcLane);
8880
8881 InsInstrs.push_back(MIB);
8882 return &Root;
8883}
8884
8885/// genFusedMultiplyAcc - Helper to generate fused multiply accumulate
8886/// instructions.
8887///
8888/// \see genFusedMultiply
8892 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8893 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8895}
8896
8897/// genNeg - Helper to generate an intermediate negation of the second operand
8898/// of Root
8900 const TargetInstrInfo *TII, MachineInstr &Root,
8902 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8903 unsigned MnegOpc, const TargetRegisterClass *RC) {
8904 Register NewVR = MRI.createVirtualRegister(RC);
8906 BuildMI(MF, MIMetadata(Root), TII->get(MnegOpc), NewVR)
8907 .add(Root.getOperand(2));
8908 InsInstrs.push_back(MIB);
8909
8910 assert(InstrIdxForVirtReg.empty());
8911 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
8912
8913 return NewVR;
8914}
8915
8916/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8917/// instructions with an additional negation of the accumulator
8921 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8922 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8923 assert(IdxMulOpd == 1);
8924
8925 Register NewVR =
8926 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8927 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8928 FMAInstKind::Accumulator, &NewVR);
8929}
8930
8931/// genFusedMultiplyIdx - Helper to generate fused multiply accumulate
8932/// instructions.
8933///
8934/// \see genFusedMultiply
8938 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8939 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8941}
8942
8943/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8944/// instructions with an additional negation of the accumulator
8948 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8949 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8950 assert(IdxMulOpd == 1);
8951
8952 Register NewVR =
8953 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8954
8955 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8956 FMAInstKind::Indexed, &NewVR);
8957}
8958
8959/// genMaddR - Generate madd instruction and combine mul and add using
8960/// an extra virtual register
8961/// Example - an ADD intermediate needs to be stored in a register:
8962/// MUL I=A,B,0
8963/// ADD R,I,Imm
8964/// ==> ORR V, ZR, Imm
8965/// ==> MADD R,A,B,V
8966/// \param MF Containing MachineFunction
8967/// \param MRI Register information
8968/// \param TII Target information
8969/// \param Root is the ADD instruction
8970/// \param [out] InsInstrs is a vector of machine instructions and will
8971/// contain the generated madd instruction
8972/// \param IdxMulOpd is index of operand in Root that is the result of
8973/// the MUL. In the example above IdxMulOpd is 1.
8974/// \param MaddOpc the opcode fo the madd instruction
8975/// \param VR is a virtual register that holds the value of an ADD operand
8976/// (V in the example above).
8977/// \param RC Register class of operands
8979 const TargetInstrInfo *TII, MachineInstr &Root,
8981 unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR,
8982 const TargetRegisterClass *RC) {
8983 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8984
8985 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8986 Register ResultReg = Root.getOperand(0).getReg();
8987 Register SrcReg0 = MUL->getOperand(1).getReg();
8988 bool Src0IsKill = MUL->getOperand(1).isKill();
8989 Register SrcReg1 = MUL->getOperand(2).getReg();
8990 bool Src1IsKill = MUL->getOperand(2).isKill();
8991
8992 if (ResultReg.isVirtual())
8993 MRI.constrainRegClass(ResultReg, RC);
8994 if (SrcReg0.isVirtual())
8995 MRI.constrainRegClass(SrcReg0, RC);
8996 if (SrcReg1.isVirtual())
8997 MRI.constrainRegClass(SrcReg1, RC);
8999 MRI.constrainRegClass(VR, RC);
9000
9002 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
9003 .addReg(SrcReg0, getKillRegState(Src0IsKill))
9004 .addReg(SrcReg1, getKillRegState(Src1IsKill))
9005 .addReg(VR);
9006 // Insert the MADD
9007 InsInstrs.push_back(MIB);
9008 return MUL;
9009}
9010
9011/// Do the following transformation
9012/// A - (B + C) ==> (A - B) - C
9013/// A - (B + C) ==> (A - C) - B
9015 const TargetInstrInfo *TII, MachineInstr &Root,
9018 unsigned IdxOpd1,
9019 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
9020 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9021 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9022 MachineInstr *AddMI = MRI.getUniqueVRegDef(Root.getOperand(2).getReg());
9023
9024 Register ResultReg = Root.getOperand(0).getReg();
9025 Register RegA = Root.getOperand(1).getReg();
9026 bool RegAIsKill = Root.getOperand(1).isKill();
9027 Register RegB = AddMI->getOperand(IdxOpd1).getReg();
9028 bool RegBIsKill = AddMI->getOperand(IdxOpd1).isKill();
9029 Register RegC = AddMI->getOperand(IdxOtherOpd).getReg();
9030 bool RegCIsKill = AddMI->getOperand(IdxOtherOpd).isKill();
9031 Register NewVR =
9033
9034 unsigned Opcode = Root.getOpcode();
9035 if (Opcode == AArch64::SUBSWrr)
9036 Opcode = AArch64::SUBWrr;
9037 else if (Opcode == AArch64::SUBSXrr)
9038 Opcode = AArch64::SUBXrr;
9039 else
9040 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9041 "Unexpected instruction opcode.");
9042
9043 uint32_t Flags = Root.mergeFlagsWith(*AddMI);
9044 Flags &= ~MachineInstr::NoSWrap;
9045 Flags &= ~MachineInstr::NoUWrap;
9046
9047 MachineInstrBuilder MIB1 =
9048 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), NewVR)
9049 .addReg(RegA, getKillRegState(RegAIsKill))
9050 .addReg(RegB, getKillRegState(RegBIsKill))
9051 .setMIFlags(Flags);
9052 MachineInstrBuilder MIB2 =
9053 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), ResultReg)
9054 .addReg(NewVR, getKillRegState(true))
9055 .addReg(RegC, getKillRegState(RegCIsKill))
9056 .setMIFlags(Flags);
9057
9058 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9059 InsInstrs.push_back(MIB1);
9060 InsInstrs.push_back(MIB2);
9061 DelInstrs.push_back(AddMI);
9062 DelInstrs.push_back(&Root);
9063}
9064
9065unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9066 unsigned int AccumulatorOpCode) const {
9067 switch (AccumulatorOpCode) {
9068 case AArch64::UABALB_ZZZ_D:
9069 case AArch64::SABALB_ZZZ_D:
9070 case AArch64::UABALT_ZZZ_D:
9071 case AArch64::SABALT_ZZZ_D:
9072 return AArch64::ADD_ZZZ_D;
9073 case AArch64::UABALB_ZZZ_H:
9074 case AArch64::SABALB_ZZZ_H:
9075 case AArch64::UABALT_ZZZ_H:
9076 case AArch64::SABALT_ZZZ_H:
9077 return AArch64::ADD_ZZZ_H;
9078 case AArch64::UABALB_ZZZ_S:
9079 case AArch64::SABALB_ZZZ_S:
9080 case AArch64::UABALT_ZZZ_S:
9081 case AArch64::SABALT_ZZZ_S:
9082 return AArch64::ADD_ZZZ_S;
9083 case AArch64::UABALv16i8_v8i16:
9084 case AArch64::SABALv8i8_v8i16:
9085 case AArch64::SABAv8i16:
9086 case AArch64::UABAv8i16:
9087 return AArch64::ADDv8i16;
9088 case AArch64::SABALv2i32_v2i64:
9089 case AArch64::UABALv2i32_v2i64:
9090 case AArch64::SABALv4i32_v2i64:
9091 return AArch64::ADDv2i64;
9092 case AArch64::UABALv4i16_v4i32:
9093 case AArch64::SABALv4i16_v4i32:
9094 case AArch64::SABALv8i16_v4i32:
9095 case AArch64::SABAv4i32:
9096 case AArch64::UABAv4i32:
9097 return AArch64::ADDv4i32;
9098 case AArch64::UABALv4i32_v2i64:
9099 return AArch64::ADDv2i64;
9100 case AArch64::UABALv8i16_v4i32:
9101 return AArch64::ADDv4i32;
9102 case AArch64::UABALv8i8_v8i16:
9103 case AArch64::SABALv16i8_v8i16:
9104 return AArch64::ADDv8i16;
9105 case AArch64::UABAv16i8:
9106 case AArch64::SABAv16i8:
9107 return AArch64::ADDv16i8;
9108 case AArch64::UABAv4i16:
9109 case AArch64::SABAv4i16:
9110 return AArch64::ADDv4i16;
9111 case AArch64::UABAv2i32:
9112 case AArch64::SABAv2i32:
9113 return AArch64::ADDv2i32;
9114 case AArch64::UABAv8i8:
9115 case AArch64::SABAv8i8:
9116 return AArch64::ADDv8i8;
9117 default:
9118 llvm_unreachable("Unknown accumulator opcode");
9119 }
9120}
9121
9122/// When getMachineCombinerPatterns() finds potential patterns,
9123/// this function generates the instructions that could replace the
9124/// original code sequence
9125void AArch64InstrInfo::genAlternativeCodeSequence(
9126 MachineInstr &Root, unsigned Pattern,
9129 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const {
9130 MachineBasicBlock &MBB = *Root.getParent();
9131 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9132 MachineFunction &MF = *MBB.getParent();
9133 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
9134
9135 MachineInstr *MUL = nullptr;
9136 const TargetRegisterClass *RC;
9137 unsigned Opc;
9138 switch (Pattern) {
9139 default:
9140 // Reassociate instructions.
9141 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
9142 DelInstrs, InstrIdxForVirtReg);
9143 return;
9145 // A - (B + C)
9146 // ==> (A - B) - C
9147 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 1,
9148 InstrIdxForVirtReg);
9149 return;
9151 // A - (B + C)
9152 // ==> (A - C) - B
9153 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 2,
9154 InstrIdxForVirtReg);
9155 return;
9158 // MUL I=A,B,0
9159 // ADD R,I,C
9160 // ==> MADD R,A,B,C
9161 // --- Create(MADD);
9163 Opc = AArch64::MADDWrrr;
9164 RC = &AArch64::GPR32RegClass;
9165 } else {
9166 Opc = AArch64::MADDXrrr;
9167 RC = &AArch64::GPR64RegClass;
9168 }
9169 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9170 break;
9173 // MUL I=A,B,0
9174 // ADD R,C,I
9175 // ==> MADD R,A,B,C
9176 // --- Create(MADD);
9178 Opc = AArch64::MADDWrrr;
9179 RC = &AArch64::GPR32RegClass;
9180 } else {
9181 Opc = AArch64::MADDXrrr;
9182 RC = &AArch64::GPR64RegClass;
9183 }
9184 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9185 break;
9190 // MUL I=A,B,0
9191 // ADD/SUB R,I,Imm
9192 // ==> MOV V, Imm/-Imm
9193 // ==> MADD R,A,B,V
9194 // --- Create(MADD);
9195 const TargetRegisterClass *RC;
9196 unsigned BitSize, MovImm;
9199 MovImm = AArch64::MOVi32imm;
9200 RC = &AArch64::GPR32spRegClass;
9201 BitSize = 32;
9202 Opc = AArch64::MADDWrrr;
9203 RC = &AArch64::GPR32RegClass;
9204 } else {
9205 MovImm = AArch64::MOVi64imm;
9206 RC = &AArch64::GPR64spRegClass;
9207 BitSize = 64;
9208 Opc = AArch64::MADDXrrr;
9209 RC = &AArch64::GPR64RegClass;
9210 }
9211 Register NewVR = MRI.createVirtualRegister(RC);
9212 uint64_t Imm = Root.getOperand(2).getImm();
9213
9214 if (Root.getOperand(3).isImm()) {
9215 unsigned Val = Root.getOperand(3).getImm();
9216 Imm = Imm << Val;
9217 }
9218 bool IsSub = Pattern == AArch64MachineCombinerPattern::MULSUBWI_OP1 ||
9220 uint64_t UImm = SignExtend64(IsSub ? -Imm : Imm, BitSize);
9221 // Check that the immediate can be composed via a single instruction.
9223 AArch64_IMM::expandMOVImm(UImm, BitSize, Insn);
9224 if (Insn.size() != 1)
9225 return;
9226 MachineInstrBuilder MIB1 =
9227 BuildMI(MF, MIMetadata(Root), TII->get(MovImm), NewVR)
9228 .addImm(IsSub ? -Imm : Imm);
9229 InsInstrs.push_back(MIB1);
9230 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9231 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9232 break;
9233 }
9236 // MUL I=A,B,0
9237 // SUB R,I, C
9238 // ==> SUB V, 0, C
9239 // ==> MADD R,A,B,V // = -C + A*B
9240 // --- Create(MADD);
9241 const TargetRegisterClass *SubRC;
9242 unsigned SubOpc, ZeroReg;
9244 SubOpc = AArch64::SUBWrr;
9245 SubRC = &AArch64::GPR32spRegClass;
9246 ZeroReg = AArch64::WZR;
9247 Opc = AArch64::MADDWrrr;
9248 RC = &AArch64::GPR32RegClass;
9249 } else {
9250 SubOpc = AArch64::SUBXrr;
9251 SubRC = &AArch64::GPR64spRegClass;
9252 ZeroReg = AArch64::XZR;
9253 Opc = AArch64::MADDXrrr;
9254 RC = &AArch64::GPR64RegClass;
9255 }
9256 Register NewVR = MRI.createVirtualRegister(SubRC);
9257 // SUB NewVR, 0, C
9258 MachineInstrBuilder MIB1 =
9259 BuildMI(MF, MIMetadata(Root), TII->get(SubOpc), NewVR)
9260 .addReg(ZeroReg)
9261 .add(Root.getOperand(2));
9262 InsInstrs.push_back(MIB1);
9263 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9264 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9265 break;
9266 }
9269 // MUL I=A,B,0
9270 // SUB R,C,I
9271 // ==> MSUB R,A,B,C (computes C - A*B)
9272 // --- Create(MSUB);
9274 Opc = AArch64::MSUBWrrr;
9275 RC = &AArch64::GPR32RegClass;
9276 } else {
9277 Opc = AArch64::MSUBXrrr;
9278 RC = &AArch64::GPR64RegClass;
9279 }
9280 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9281 break;
9283 Opc = AArch64::MLAv8i8;
9284 RC = &AArch64::FPR64RegClass;
9285 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9286 break;
9288 Opc = AArch64::MLAv8i8;
9289 RC = &AArch64::FPR64RegClass;
9290 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9291 break;
9293 Opc = AArch64::MLAv16i8;
9294 RC = &AArch64::FPR128RegClass;
9295 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9296 break;
9298 Opc = AArch64::MLAv16i8;
9299 RC = &AArch64::FPR128RegClass;
9300 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9301 break;
9303 Opc = AArch64::MLAv4i16;
9304 RC = &AArch64::FPR64RegClass;
9305 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9306 break;
9308 Opc = AArch64::MLAv4i16;
9309 RC = &AArch64::FPR64RegClass;
9310 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9311 break;
9313 Opc = AArch64::MLAv8i16;
9314 RC = &AArch64::FPR128RegClass;
9315 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9316 break;
9318 Opc = AArch64::MLAv8i16;
9319 RC = &AArch64::FPR128RegClass;
9320 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9321 break;
9323 Opc = AArch64::MLAv2i32;
9324 RC = &AArch64::FPR64RegClass;
9325 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9326 break;
9328 Opc = AArch64::MLAv2i32;
9329 RC = &AArch64::FPR64RegClass;
9330 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9331 break;
9333 Opc = AArch64::MLAv4i32;
9334 RC = &AArch64::FPR128RegClass;
9335 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9336 break;
9338 Opc = AArch64::MLAv4i32;
9339 RC = &AArch64::FPR128RegClass;
9340 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9341 break;
9342
9344 Opc = AArch64::MLAv8i8;
9345 RC = &AArch64::FPR64RegClass;
9346 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9347 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i8,
9348 RC);
9349 break;
9351 Opc = AArch64::MLSv8i8;
9352 RC = &AArch64::FPR64RegClass;
9353 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9354 break;
9356 Opc = AArch64::MLAv16i8;
9357 RC = &AArch64::FPR128RegClass;
9358 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9359 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv16i8,
9360 RC);
9361 break;
9363 Opc = AArch64::MLSv16i8;
9364 RC = &AArch64::FPR128RegClass;
9365 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9366 break;
9368 Opc = AArch64::MLAv4i16;
9369 RC = &AArch64::FPR64RegClass;
9370 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9371 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9372 RC);
9373 break;
9375 Opc = AArch64::MLSv4i16;
9376 RC = &AArch64::FPR64RegClass;
9377 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9378 break;
9380 Opc = AArch64::MLAv8i16;
9381 RC = &AArch64::FPR128RegClass;
9382 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9383 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9384 RC);
9385 break;
9387 Opc = AArch64::MLSv8i16;
9388 RC = &AArch64::FPR128RegClass;
9389 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9390 break;
9392 Opc = AArch64::MLAv2i32;
9393 RC = &AArch64::FPR64RegClass;
9394 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9395 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9396 RC);
9397 break;
9399 Opc = AArch64::MLSv2i32;
9400 RC = &AArch64::FPR64RegClass;
9401 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9402 break;
9404 Opc = AArch64::MLAv4i32;
9405 RC = &AArch64::FPR128RegClass;
9406 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9407 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9408 RC);
9409 break;
9411 Opc = AArch64::MLSv4i32;
9412 RC = &AArch64::FPR128RegClass;
9413 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9414 break;
9415
9417 Opc = AArch64::MLAv4i16_indexed;
9418 RC = &AArch64::FPR64RegClass;
9419 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9420 break;
9422 Opc = AArch64::MLAv4i16_indexed;
9423 RC = &AArch64::FPR64RegClass;
9424 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9425 break;
9427 Opc = AArch64::MLAv8i16_indexed;
9428 RC = &AArch64::FPR128RegClass;
9429 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9430 break;
9432 Opc = AArch64::MLAv8i16_indexed;
9433 RC = &AArch64::FPR128RegClass;
9434 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9435 break;
9437 Opc = AArch64::MLAv2i32_indexed;
9438 RC = &AArch64::FPR64RegClass;
9439 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9440 break;
9442 Opc = AArch64::MLAv2i32_indexed;
9443 RC = &AArch64::FPR64RegClass;
9444 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9445 break;
9447 Opc = AArch64::MLAv4i32_indexed;
9448 RC = &AArch64::FPR128RegClass;
9449 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9450 break;
9452 Opc = AArch64::MLAv4i32_indexed;
9453 RC = &AArch64::FPR128RegClass;
9454 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9455 break;
9456
9458 Opc = AArch64::MLAv4i16_indexed;
9459 RC = &AArch64::FPR64RegClass;
9460 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9461 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9462 RC);
9463 break;
9465 Opc = AArch64::MLSv4i16_indexed;
9466 RC = &AArch64::FPR64RegClass;
9467 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9468 break;
9470 Opc = AArch64::MLAv8i16_indexed;
9471 RC = &AArch64::FPR128RegClass;
9472 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9473 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9474 RC);
9475 break;
9477 Opc = AArch64::MLSv8i16_indexed;
9478 RC = &AArch64::FPR128RegClass;
9479 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9480 break;
9482 Opc = AArch64::MLAv2i32_indexed;
9483 RC = &AArch64::FPR64RegClass;
9484 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9485 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9486 RC);
9487 break;
9489 Opc = AArch64::MLSv2i32_indexed;
9490 RC = &AArch64::FPR64RegClass;
9491 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9492 break;
9494 Opc = AArch64::MLAv4i32_indexed;
9495 RC = &AArch64::FPR128RegClass;
9496 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9497 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9498 RC);
9499 break;
9501 Opc = AArch64::MLSv4i32_indexed;
9502 RC = &AArch64::FPR128RegClass;
9503 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9504 break;
9505
9506 // Floating Point Support
9508 Opc = AArch64::FMADDHrrr;
9509 RC = &AArch64::FPR16RegClass;
9510 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9511 break;
9513 Opc = AArch64::FMADDSrrr;
9514 RC = &AArch64::FPR32RegClass;
9515 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9516 break;
9518 Opc = AArch64::FMADDDrrr;
9519 RC = &AArch64::FPR64RegClass;
9520 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9521 break;
9522
9524 Opc = AArch64::FMADDHrrr;
9525 RC = &AArch64::FPR16RegClass;
9526 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9527 break;
9529 Opc = AArch64::FMADDSrrr;
9530 RC = &AArch64::FPR32RegClass;
9531 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9532 break;
9534 Opc = AArch64::FMADDDrrr;
9535 RC = &AArch64::FPR64RegClass;
9536 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9537 break;
9538
9540 Opc = AArch64::FMLAv1i32_indexed;
9541 RC = &AArch64::FPR32RegClass;
9542 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9544 break;
9546 Opc = AArch64::FMLAv1i32_indexed;
9547 RC = &AArch64::FPR32RegClass;
9548 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9550 break;
9551
9553 Opc = AArch64::FMLAv1i64_indexed;
9554 RC = &AArch64::FPR64RegClass;
9555 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9557 break;
9559 Opc = AArch64::FMLAv1i64_indexed;
9560 RC = &AArch64::FPR64RegClass;
9561 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9563 break;
9564
9566 RC = &AArch64::FPR64RegClass;
9567 Opc = AArch64::FMLAv4i16_indexed;
9568 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9570 break;
9572 RC = &AArch64::FPR64RegClass;
9573 Opc = AArch64::FMLAv4f16;
9574 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9576 break;
9578 RC = &AArch64::FPR64RegClass;
9579 Opc = AArch64::FMLAv4i16_indexed;
9580 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9582 break;
9584 RC = &AArch64::FPR64RegClass;
9585 Opc = AArch64::FMLAv4f16;
9586 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9588 break;
9589
9592 RC = &AArch64::FPR64RegClass;
9594 Opc = AArch64::FMLAv2i32_indexed;
9595 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9597 } else {
9598 Opc = AArch64::FMLAv2f32;
9599 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9601 }
9602 break;
9605 RC = &AArch64::FPR64RegClass;
9607 Opc = AArch64::FMLAv2i32_indexed;
9608 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9610 } else {
9611 Opc = AArch64::FMLAv2f32;
9612 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9614 }
9615 break;
9616
9618 RC = &AArch64::FPR128RegClass;
9619 Opc = AArch64::FMLAv8i16_indexed;
9620 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9622 break;
9624 RC = &AArch64::FPR128RegClass;
9625 Opc = AArch64::FMLAv8f16;
9626 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9628 break;
9630 RC = &AArch64::FPR128RegClass;
9631 Opc = AArch64::FMLAv8i16_indexed;
9632 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9634 break;
9636 RC = &AArch64::FPR128RegClass;
9637 Opc = AArch64::FMLAv8f16;
9638 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9640 break;
9641
9644 RC = &AArch64::FPR128RegClass;
9646 Opc = AArch64::FMLAv2i64_indexed;
9647 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9649 } else {
9650 Opc = AArch64::FMLAv2f64;
9651 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9653 }
9654 break;
9657 RC = &AArch64::FPR128RegClass;
9659 Opc = AArch64::FMLAv2i64_indexed;
9660 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9662 } else {
9663 Opc = AArch64::FMLAv2f64;
9664 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9666 }
9667 break;
9668
9671 RC = &AArch64::FPR128RegClass;
9673 Opc = AArch64::FMLAv4i32_indexed;
9674 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9676 } else {
9677 Opc = AArch64::FMLAv4f32;
9678 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9680 }
9681 break;
9682
9685 RC = &AArch64::FPR128RegClass;
9687 Opc = AArch64::FMLAv4i32_indexed;
9688 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9690 } else {
9691 Opc = AArch64::FMLAv4f32;
9692 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9694 }
9695 break;
9696
9698 Opc = AArch64::FNMSUBHrrr;
9699 RC = &AArch64::FPR16RegClass;
9700 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9701 break;
9703 Opc = AArch64::FNMSUBSrrr;
9704 RC = &AArch64::FPR32RegClass;
9705 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9706 break;
9708 Opc = AArch64::FNMSUBDrrr;
9709 RC = &AArch64::FPR64RegClass;
9710 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9711 break;
9712
9714 Opc = AArch64::FNMADDHrrr;
9715 RC = &AArch64::FPR16RegClass;
9716 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9717 break;
9719 Opc = AArch64::FNMADDSrrr;
9720 RC = &AArch64::FPR32RegClass;
9721 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9722 break;
9724 Opc = AArch64::FNMADDDrrr;
9725 RC = &AArch64::FPR64RegClass;
9726 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9727 break;
9728
9730 Opc = AArch64::FMSUBHrrr;
9731 RC = &AArch64::FPR16RegClass;
9732 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9733 break;
9735 Opc = AArch64::FMSUBSrrr;
9736 RC = &AArch64::FPR32RegClass;
9737 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9738 break;
9740 Opc = AArch64::FMSUBDrrr;
9741 RC = &AArch64::FPR64RegClass;
9742 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9743 break;
9744
9746 Opc = AArch64::FMLSv1i32_indexed;
9747 RC = &AArch64::FPR32RegClass;
9748 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9750 break;
9751
9753 Opc = AArch64::FMLSv1i64_indexed;
9754 RC = &AArch64::FPR64RegClass;
9755 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9757 break;
9758
9761 RC = &AArch64::FPR64RegClass;
9762 Register NewVR = MRI.createVirtualRegister(RC);
9763 MachineInstrBuilder MIB1 =
9764 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f16), NewVR)
9765 .add(Root.getOperand(2));
9766 InsInstrs.push_back(MIB1);
9767 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9769 Opc = AArch64::FMLAv4f16;
9770 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9771 FMAInstKind::Accumulator, &NewVR);
9772 } else {
9773 Opc = AArch64::FMLAv4i16_indexed;
9774 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9775 FMAInstKind::Indexed, &NewVR);
9776 }
9777 break;
9778 }
9780 RC = &AArch64::FPR64RegClass;
9781 Opc = AArch64::FMLSv4f16;
9782 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9784 break;
9786 RC = &AArch64::FPR64RegClass;
9787 Opc = AArch64::FMLSv4i16_indexed;
9788 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9790 break;
9791
9794 RC = &AArch64::FPR64RegClass;
9796 Opc = AArch64::FMLSv2i32_indexed;
9797 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9799 } else {
9800 Opc = AArch64::FMLSv2f32;
9801 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9803 }
9804 break;
9805
9808 RC = &AArch64::FPR128RegClass;
9809 Register NewVR = MRI.createVirtualRegister(RC);
9810 MachineInstrBuilder MIB1 =
9811 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv8f16), NewVR)
9812 .add(Root.getOperand(2));
9813 InsInstrs.push_back(MIB1);
9814 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9816 Opc = AArch64::FMLAv8f16;
9817 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9818 FMAInstKind::Accumulator, &NewVR);
9819 } else {
9820 Opc = AArch64::FMLAv8i16_indexed;
9821 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9822 FMAInstKind::Indexed, &NewVR);
9823 }
9824 break;
9825 }
9827 RC = &AArch64::FPR128RegClass;
9828 Opc = AArch64::FMLSv8f16;
9829 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9831 break;
9833 RC = &AArch64::FPR128RegClass;
9834 Opc = AArch64::FMLSv8i16_indexed;
9835 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9837 break;
9838
9841 RC = &AArch64::FPR128RegClass;
9843 Opc = AArch64::FMLSv2i64_indexed;
9844 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9846 } else {
9847 Opc = AArch64::FMLSv2f64;
9848 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9850 }
9851 break;
9852
9855 RC = &AArch64::FPR128RegClass;
9857 Opc = AArch64::FMLSv4i32_indexed;
9858 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9860 } else {
9861 Opc = AArch64::FMLSv4f32;
9862 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9864 }
9865 break;
9868 RC = &AArch64::FPR64RegClass;
9869 Register NewVR = MRI.createVirtualRegister(RC);
9870 MachineInstrBuilder MIB1 =
9871 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f32), NewVR)
9872 .add(Root.getOperand(2));
9873 InsInstrs.push_back(MIB1);
9874 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9876 Opc = AArch64::FMLAv2i32_indexed;
9877 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9878 FMAInstKind::Indexed, &NewVR);
9879 } else {
9880 Opc = AArch64::FMLAv2f32;
9881 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9882 FMAInstKind::Accumulator, &NewVR);
9883 }
9884 break;
9885 }
9888 RC = &AArch64::FPR128RegClass;
9889 Register NewVR = MRI.createVirtualRegister(RC);
9890 MachineInstrBuilder MIB1 =
9891 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f32), NewVR)
9892 .add(Root.getOperand(2));
9893 InsInstrs.push_back(MIB1);
9894 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9896 Opc = AArch64::FMLAv4i32_indexed;
9897 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9898 FMAInstKind::Indexed, &NewVR);
9899 } else {
9900 Opc = AArch64::FMLAv4f32;
9901 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9902 FMAInstKind::Accumulator, &NewVR);
9903 }
9904 break;
9905 }
9908 RC = &AArch64::FPR128RegClass;
9909 Register NewVR = MRI.createVirtualRegister(RC);
9910 MachineInstrBuilder MIB1 =
9911 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f64), NewVR)
9912 .add(Root.getOperand(2));
9913 InsInstrs.push_back(MIB1);
9914 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9916 Opc = AArch64::FMLAv2i64_indexed;
9917 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9918 FMAInstKind::Indexed, &NewVR);
9919 } else {
9920 Opc = AArch64::FMLAv2f64;
9921 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9922 FMAInstKind::Accumulator, &NewVR);
9923 }
9924 break;
9925 }
9928 unsigned IdxDupOp =
9930 : 2;
9931 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i32_indexed,
9932 &AArch64::FPR128RegClass, MRI);
9933 break;
9934 }
9937 unsigned IdxDupOp =
9939 : 2;
9940 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i64_indexed,
9941 &AArch64::FPR128RegClass, MRI);
9942 break;
9943 }
9946 unsigned IdxDupOp =
9948 : 2;
9949 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i16_indexed,
9950 &AArch64::FPR128_loRegClass, MRI);
9951 break;
9952 }
9955 unsigned IdxDupOp =
9957 : 2;
9958 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i32_indexed,
9959 &AArch64::FPR128RegClass, MRI);
9960 break;
9961 }
9964 unsigned IdxDupOp =
9966 : 2;
9967 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv8i16_indexed,
9968 &AArch64::FPR128_loRegClass, MRI);
9969 break;
9970 }
9972 MUL = genFNegatedMAD(MF, MRI, TII, Root, InsInstrs);
9973 break;
9974 }
9976 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9977 Pattern, 4);
9978 break;
9979 }
9981 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9982 Pattern, 8);
9983 break;
9984 }
9986 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9987 Pattern, 16);
9988 break;
9989 }
9990
9991 } // end switch (Pattern)
9992 // Record MUL and ADD/SUB for deletion
9993 if (MUL)
9994 DelInstrs.push_back(MUL);
9995 DelInstrs.push_back(&Root);
9996
9997 // Set the flags on the inserted instructions to be the merged flags of the
9998 // instructions that we have combined.
9999 uint32_t Flags = Root.getFlags();
10000 if (MUL)
10001 Flags = Root.mergeFlagsWith(*MUL);
10002 for (auto *MI : InsInstrs)
10003 MI->setFlags(Flags);
10004}
10005
10006/// Replace csincr-branch sequence by simple conditional branch
10007///
10008/// Examples:
10009/// 1. \code
10010/// csinc w9, wzr, wzr, <condition code>
10011/// tbnz w9, #0, 0x44
10012/// \endcode
10013/// to
10014/// \code
10015/// b.<inverted condition code>
10016/// \endcode
10017///
10018/// 2. \code
10019/// csinc w9, wzr, wzr, <condition code>
10020/// tbz w9, #0, 0x44
10021/// \endcode
10022/// to
10023/// \code
10024/// b.<condition code>
10025/// \endcode
10026///
10027/// Replace compare and branch sequence by TBZ/TBNZ instruction when the
10028/// compare's constant operand is power of 2.
10029///
10030/// Examples:
10031/// \code
10032/// and w8, w8, #0x400
10033/// cbnz w8, L1
10034/// \endcode
10035/// to
10036/// \code
10037/// tbnz w8, #10, L1
10038/// \endcode
10039///
10040/// \param MI Conditional Branch
10041/// \return True when the simple conditional branch is generated
10042///
10044 bool IsNegativeBranch = false;
10045 bool IsTestAndBranch = false;
10046 unsigned TargetBBInMI = 0;
10047 switch (MI.getOpcode()) {
10048 default:
10049 llvm_unreachable("Unknown branch instruction?");
10050 case AArch64::Bcc:
10051 case AArch64::CBWPri:
10052 case AArch64::CBXPri:
10053 case AArch64::CBBAssertExt:
10054 case AArch64::CBHAssertExt:
10055 case AArch64::CBWPrr:
10056 case AArch64::CBXPrr:
10057 return false;
10058 case AArch64::CBZW:
10059 case AArch64::CBZX:
10060 TargetBBInMI = 1;
10061 break;
10062 case AArch64::CBNZW:
10063 case AArch64::CBNZX:
10064 TargetBBInMI = 1;
10065 IsNegativeBranch = true;
10066 break;
10067 case AArch64::TBZW:
10068 case AArch64::TBZX:
10069 TargetBBInMI = 2;
10070 IsTestAndBranch = true;
10071 break;
10072 case AArch64::TBNZW:
10073 case AArch64::TBNZX:
10074 TargetBBInMI = 2;
10075 IsNegativeBranch = true;
10076 IsTestAndBranch = true;
10077 break;
10078 }
10079 // So we increment a zero register and test for bits other
10080 // than bit 0? Conservatively bail out in case the verifier
10081 // missed this case.
10082 if (IsTestAndBranch && MI.getOperand(1).getImm())
10083 return false;
10084
10085 // Find Definition.
10086 assert(MI.getParent() && "Incomplete machine instruction\n");
10087 MachineBasicBlock *MBB = MI.getParent();
10088 MachineFunction *MF = MBB->getParent();
10089 MachineRegisterInfo *MRI = &MF->getRegInfo();
10090 Register VReg = MI.getOperand(0).getReg();
10091 if (!VReg.isVirtual())
10092 return false;
10093
10094 MachineInstr *DefMI = MRI->getVRegDef(VReg);
10095 if (!DefMI)
10096 return false;
10097
10098 // Look through COPY instructions to find definition.
10099 while (DefMI->isCopy()) {
10100 Register CopyVReg = DefMI->getOperand(1).getReg();
10101 if (!CopyVReg.isVirtual())
10102 return false;
10103 if (!MRI->hasOneNonDBGUse(CopyVReg))
10104 return false;
10105 if (!MRI->hasOneDef(CopyVReg))
10106 return false;
10107 DefMI = MRI->getVRegDef(CopyVReg);
10108 }
10109
10110 switch (DefMI->getOpcode()) {
10111 default:
10112 return false;
10113 // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
10114 case AArch64::ANDWri:
10115 case AArch64::ANDXri: {
10116 if (IsTestAndBranch)
10117 return false;
10118 if (DefMI->getParent() != MBB)
10119 return false;
10120 if (!MRI->hasOneNonDBGUse(VReg))
10121 return false;
10122
10123 bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
10124 uint64_t Mask = AArch64_AM::decodeLogicalImmediate(
10125 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
10126 if (!isPowerOf2_64(Mask))
10127 return false;
10128
10129 MachineOperand &MO = DefMI->getOperand(1);
10130 Register NewReg = MO.getReg();
10131 if (!NewReg.isVirtual())
10132 return false;
10133
10134 assert(!MRI->def_empty(NewReg) && "Register must be defined.");
10135
10136 MachineBasicBlock &RefToMBB = *MBB;
10137 MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
10138 DebugLoc DL = MI.getDebugLoc();
10139 unsigned Imm = Log2_64(Mask);
10140 unsigned Opc = (Imm < 32)
10141 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
10142 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
10143 MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
10144 .addReg(NewReg)
10145 .addImm(Imm)
10146 .addMBB(TBB);
10147 // Register lives on to the CBZ now.
10148 MO.setIsKill(false);
10149
10150 // For immediate smaller than 32, we need to use the 32-bit
10151 // variant (W) in all cases. Indeed the 64-bit variant does not
10152 // allow to encode them.
10153 // Therefore, if the input register is 64-bit, we need to take the
10154 // 32-bit sub-part.
10155 if (!Is32Bit && Imm < 32)
10156 NewMI->getOperand(0).setSubReg(AArch64::sub_32);
10157 MI.eraseFromParent();
10158 return true;
10159 }
10160 // Look for CSINC
10161 case AArch64::CSINCWr:
10162 case AArch64::CSINCXr: {
10163 if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
10164 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
10165 !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
10166 DefMI->getOperand(2).getReg() == AArch64::XZR))
10167 return false;
10168
10169 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
10170 true) != -1)
10171 return false;
10172
10173 AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
10174 // Convert only when the condition code is not modified between
10175 // the CSINC and the branch. The CC may be used by other
10176 // instructions in between.
10178 return false;
10179 MachineBasicBlock &RefToMBB = *MBB;
10180 MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
10181 DebugLoc DL = MI.getDebugLoc();
10182 if (IsNegativeBranch)
10184 BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
10185 MI.eraseFromParent();
10186 return true;
10187 }
10188 }
10189}
10190
10191std::pair<unsigned, unsigned>
10192AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
10193 const unsigned Mask = AArch64II::MO_FRAGMENT;
10194 return std::make_pair(TF & Mask, TF & ~Mask);
10195}
10196
10198AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
10199 using namespace AArch64II;
10200
10201 static const std::pair<unsigned, const char *> TargetFlags[] = {
10202 {MO_PAGE, "aarch64-page"}, {MO_PAGEOFF, "aarch64-pageoff"},
10203 {MO_G3, "aarch64-g3"}, {MO_G2, "aarch64-g2"},
10204 {MO_G1, "aarch64-g1"}, {MO_G0, "aarch64-g0"},
10205 {MO_HI12, "aarch64-hi12"}};
10206 return ArrayRef(TargetFlags);
10207}
10208
10210AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
10211 using namespace AArch64II;
10212
10213 static const std::pair<unsigned, const char *> TargetFlags[] = {
10214 {MO_COFFSTUB, "aarch64-coffstub"},
10215 {MO_GOT, "aarch64-got"},
10216 {MO_NC, "aarch64-nc"},
10217 {MO_S, "aarch64-s"},
10218 {MO_TLS, "aarch64-tls"},
10219 {MO_DLLIMPORT, "aarch64-dllimport"},
10220 {MO_PREL, "aarch64-prel"},
10221 {MO_TAGGED, "aarch64-tagged"},
10222 {MO_ARM64EC_CALLMANGLE, "aarch64-arm64ec-callmangle"},
10223 };
10224 return ArrayRef(TargetFlags);
10225}
10226
10228AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const {
10229 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10230 {{MOSuppressPair, "aarch64-suppress-pair"},
10231 {MOStridedAccess, "aarch64-strided-access"}};
10232 return ArrayRef(TargetFlags);
10233}
10234
10235/// Constants defining how certain sequences should be outlined.
10236/// This encompasses how an outlined function should be called, and what kind of
10237/// frame should be emitted for that outlined function.
10238///
10239/// \p MachineOutlinerDefault implies that the function should be called with
10240/// a save and restore of LR to the stack.
10241///
10242/// That is,
10243///
10244/// I1 Save LR OUTLINED_FUNCTION:
10245/// I2 --> BL OUTLINED_FUNCTION I1
10246/// I3 Restore LR I2
10247/// I3
10248/// RET
10249///
10250/// * Call construction overhead: 3 (save + BL + restore)
10251/// * Frame construction overhead: 1 (ret)
10252/// * Requires stack fixups? Yes
10253///
10254/// \p MachineOutlinerTailCall implies that the function is being created from
10255/// a sequence of instructions ending in a return.
10256///
10257/// That is,
10258///
10259/// I1 OUTLINED_FUNCTION:
10260/// I2 --> B OUTLINED_FUNCTION I1
10261/// RET I2
10262/// RET
10263///
10264/// * Call construction overhead: 1 (B)
10265/// * Frame construction overhead: 0 (Return included in sequence)
10266/// * Requires stack fixups? No
10267///
10268/// \p MachineOutlinerNoLRSave implies that the function should be called using
10269/// a BL instruction, but doesn't require LR to be saved and restored. This
10270/// happens when LR is known to be dead.
10271///
10272/// That is,
10273///
10274/// I1 OUTLINED_FUNCTION:
10275/// I2 --> BL OUTLINED_FUNCTION I1
10276/// I3 I2
10277/// I3
10278/// RET
10279///
10280/// * Call construction overhead: 1 (BL)
10281/// * Frame construction overhead: 1 (RET)
10282/// * Requires stack fixups? No
10283///
10284/// \p MachineOutlinerThunk implies that the function is being created from
10285/// a sequence of instructions ending in a call. The outlined function is
10286/// called with a BL instruction, and the outlined function tail-calls the
10287/// original call destination.
10288///
10289/// That is,
10290///
10291/// I1 OUTLINED_FUNCTION:
10292/// I2 --> BL OUTLINED_FUNCTION I1
10293/// BL f I2
10294/// B f
10295/// * Call construction overhead: 1 (BL)
10296/// * Frame construction overhead: 0
10297/// * Requires stack fixups? No
10298///
10299/// \p MachineOutlinerRegSave implies that the function should be called with a
10300/// save and restore of LR to an available register. This allows us to avoid
10301/// stack fixups. Note that this outlining variant is compatible with the
10302/// NoLRSave case.
10303///
10304/// That is,
10305///
10306/// I1 Save LR OUTLINED_FUNCTION:
10307/// I2 --> BL OUTLINED_FUNCTION I1
10308/// I3 Restore LR I2
10309/// I3
10310/// RET
10311///
10312/// * Call construction overhead: 3 (save + BL + restore)
10313/// * Frame construction overhead: 1 (ret)
10314/// * Requires stack fixups? No
10316 MachineOutlinerDefault, /// Emit a save, restore, call, and return.
10317 MachineOutlinerTailCall, /// Only emit a branch.
10318 MachineOutlinerNoLRSave, /// Emit a call and return.
10319 MachineOutlinerThunk, /// Emit a call and tail-call.
10320 MachineOutlinerRegSave /// Same as default, but save to a register.
10321};
10322
10328
10329/// Return true if the frame-record form of the outlined prologue is enabled for
10330/// the target of \p MF.
10331///
10332/// A non-leaf outlined function must save LR. On MachO, saving LR alone
10333/// (str x30) has no compact unwind encoding, so we get a large DWARF FDE
10334/// instead. Saving FP and LR as a frame record (stp x29, x30 ; mov x29, sp)
10335/// gets the small FRAME encoding, and costs one extra instruction.
10340
10341/// Return true if the outlined function in \p MBB should save FP and LR as a
10342/// frame record instead of saving LR alone.
10344 const MachineBasicBlock &MBB) {
10345 const MachineFunction &MF = *MBB.getParent();
10346
10347 // Only worth it if the function has unwind info to shrink.
10350 return false;
10351
10352 // Only safe if the outlined code never touches FP, since we overwrite it.
10354 for (const MachineInstr &MI : MBB.instrs())
10355 LRU.accumulate(MI);
10356 return LRU.available(AArch64::FP);
10357}
10358
10359/// Predict what the above will answer, for use while costing candidates. The
10360/// outlined function does not exist yet, so answer from \p RepeatedSequenceLocs
10361/// instead. This is only an estimate; buildOutlinedFrame() makes the call.
10363 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10364 const TargetRegisterInfo &TRI) {
10365 if (!isCompactUnwindFrameRecordEnabled(*RepeatedSequenceLocs.front().getMF()))
10366 return false;
10367
10368 // The outlined function is nounwind only if every candidate is, so it has
10369 // unwind info if any candidate does.
10370 if (llvm::none_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10371 const MachineFunction &MF = *C.getMF();
10372 return MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
10373 }))
10374 return false;
10375
10376 // FP is free in the outlined function only if it is free in every candidate.
10377 return llvm::all_of(RepeatedSequenceLocs, [&TRI](outliner::Candidate &C) {
10378 return C.isAvailableInsideSeq(AArch64::FP, TRI);
10379 });
10380}
10381
10383AArch64InstrInfo::findRegisterToSaveLRTo(outliner::Candidate &C) const {
10384 MachineFunction *MF = C.getMF();
10385 const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
10386 const AArch64RegisterInfo *ARI =
10387 static_cast<const AArch64RegisterInfo *>(&TRI);
10388 // Check if there is an available register across the sequence that we can
10389 // use.
10390 for (unsigned Reg : AArch64::GPR64RegClass) {
10391 if (!ARI->isReservedReg(*MF, Reg) &&
10392 Reg != AArch64::LR && // LR is not reserved, but don't use it.
10393 Reg != AArch64::X16 && // X16 is not guaranteed to be preserved.
10394 Reg != AArch64::X17 && // Ditto for X17.
10395 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&
10396 C.isAvailableInsideSeq(Reg, TRI))
10397 return Reg;
10398 }
10399 return Register();
10400}
10401
10402static bool
10404 const outliner::Candidate &b) {
10405 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10406 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10407
10408 return MFIa->getSignReturnAddressCondition() ==
10410}
10411
10412static bool
10414 const outliner::Candidate &b) {
10415 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10416 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10417
10418 return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey();
10419}
10420
10422 const outliner::Candidate &b) {
10423 const AArch64Subtarget &SubtargetA =
10425 const AArch64Subtarget &SubtargetB =
10426 b.getMF()->getSubtarget<AArch64Subtarget>();
10427 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10428}
10429
10430std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10431AArch64InstrInfo::getOutliningCandidateInfo(
10432 const MachineModuleInfo &MMI,
10433 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10434 unsigned MinRepeats) const {
10435 unsigned SequenceSize = 0;
10436 for (auto &MI : RepeatedSequenceLocs[0])
10437 SequenceSize += getInstSizeInBytes(MI);
10438
10439 unsigned NumBytesToCreateFrame = 0;
10440
10441 // Avoid splitting ADRP ADD/LDR pair into outlined functions.
10442 // These instructions are fused together by the scheduler.
10443 // Any candidate where ADRP is the last instruction should be rejected
10444 // as that will lead to splitting ADRP pair.
10445 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10446 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10447 if (LastMI.getOpcode() == AArch64::ADRP &&
10448 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0 &&
10449 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10450 return std::nullopt;
10451 }
10452
10453 // Similarly any candidate where the first instruction is ADD/LDR with a
10454 // page offset should be rejected to avoid ADRP splitting.
10455 if ((FirstMI.getOpcode() == AArch64::ADDXri ||
10456 FirstMI.getOpcode() == AArch64::LDRXui) &&
10457 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_PAGEOFF) != 0 &&
10458 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10459 return std::nullopt;
10460 }
10461
10462 // We only allow outlining for functions having exactly matching return
10463 // address signing attributes, i.e., all share the same value for the
10464 // attribute "sign-return-address" and all share the same type of key they
10465 // are signed with.
10466 // Additionally we require all functions to simultaneously either support
10467 // v8.3a features or not. Otherwise an outlined function could get signed
10468 // using dedicated v8.3 instructions and a call from a function that doesn't
10469 // support v8.3 instructions would therefore be invalid.
10470 if (std::adjacent_find(
10471 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10472 [](const outliner::Candidate &a, const outliner::Candidate &b) {
10473 // Return true if a and b are non-equal w.r.t. return address
10474 // signing or support of v8.3a features
10475 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10476 outliningCandidatesSigningKeyConsensus(a, b) &&
10477 outliningCandidatesV8_3OpsConsensus(a, b)) {
10478 return false;
10479 }
10480 return true;
10481 }) != RepeatedSequenceLocs.end()) {
10482 return std::nullopt;
10483 }
10484
10485 // Since at this point all candidates agree on their return address signing
10486 // picking just one is fine. If the candidate functions potentially sign their
10487 // return addresses, the outlined function should do the same. Note that in
10488 // the case of "sign-return-address"="non-leaf" this is an assumption: It is
10489 // not certainly true that the outlined function will have to sign its return
10490 // address but this decision is made later, when the decision to outline
10491 // has already been made.
10492 // The same holds for the number of additional instructions we need: On
10493 // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
10494 // necessary. However, at this point we don't know if the outlined function
10495 // will have a RET instruction so we assume the worst.
10496 const TargetRegisterInfo &TRI = getRegisterInfo();
10497 // Performing a tail call may require extra checks when PAuth is enabled.
10498 // If PAuth is disabled, set it to zero for uniformity.
10499 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10500 const auto RASignCondition = RepeatedSequenceLocs[0]
10501 .getMF()
10502 ->getInfo<AArch64FunctionInfo>()
10503 ->getSignReturnAddressCondition();
10504 if (RASignCondition != SignReturnAddress::None) {
10505 // One PAC and one AUT instructions
10506 NumBytesToCreateFrame += 8;
10507
10508 // PAuth is enabled - set extra tail call cost, if any.
10509 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10510 *RepeatedSequenceLocs[0].getMF());
10511 NumBytesToCheckLRInTCEpilogue =
10513 // Checking the authenticated LR value may significantly impact
10514 // SequenceSize, so account for it for more precise results.
10515 if (isTailCallReturnInst(RepeatedSequenceLocs[0].back()))
10516 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10517
10518 // We have to check if sp modifying instructions would get outlined.
10519 // If so we only allow outlining if sp is unchanged overall, so matching
10520 // sub and add instructions are okay to outline, all other sp modifications
10521 // are not
10522 auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) {
10523 int SPValue = 0;
10524 for (auto &MI : C) {
10525 if (MI.modifiesRegister(AArch64::SP, &TRI)) {
10526 switch (MI.getOpcode()) {
10527 case AArch64::ADDXri:
10528 case AArch64::ADDWri:
10529 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10530 assert(MI.getOperand(2).isImm() &&
10531 "Expected operand to be immediate");
10532 assert(MI.getOperand(1).isReg() &&
10533 "Expected operand to be a register");
10534 // Check if the add just increments sp. If so, we search for
10535 // matching sub instructions that decrement sp. If not, the
10536 // modification is illegal
10537 if (MI.getOperand(1).getReg() == AArch64::SP)
10538 SPValue += MI.getOperand(2).getImm();
10539 else
10540 return true;
10541 break;
10542 case AArch64::SUBXri:
10543 case AArch64::SUBWri:
10544 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10545 assert(MI.getOperand(2).isImm() &&
10546 "Expected operand to be immediate");
10547 assert(MI.getOperand(1).isReg() &&
10548 "Expected operand to be a register");
10549 // Check if the sub just decrements sp. If so, we search for
10550 // matching add instructions that increment sp. If not, the
10551 // modification is illegal
10552 if (MI.getOperand(1).getReg() == AArch64::SP)
10553 SPValue -= MI.getOperand(2).getImm();
10554 else
10555 return true;
10556 break;
10557 default:
10558 return true;
10559 }
10560 }
10561 }
10562 if (SPValue)
10563 return true;
10564 return false;
10565 };
10566 // Remove candidates with illegal stack modifying instructions
10567 llvm::erase_if(RepeatedSequenceLocs, hasIllegalSPModification);
10568
10569 // If the sequence doesn't have enough candidates left, then we're done.
10570 if (RepeatedSequenceLocs.size() < MinRepeats)
10571 return std::nullopt;
10572 }
10573
10574 // Properties about candidate MBBs that hold for all of them.
10575 unsigned FlagsSetInAll = 0xF;
10576
10577 // Compute liveness information for each candidate, and set FlagsSetInAll.
10578 for (outliner::Candidate &C : RepeatedSequenceLocs)
10579 FlagsSetInAll &= C.Flags;
10580
10581 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10582
10583 // Helper lambda which sets call information for every candidate.
10584 auto SetCandidateCallInfo =
10585 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {
10586 for (outliner::Candidate &C : RepeatedSequenceLocs)
10587 C.setCallInfo(CallID, NumBytesForCall);
10588 };
10589
10590 unsigned FrameID = MachineOutlinerDefault;
10591 NumBytesToCreateFrame += 4;
10592
10593 bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10594 return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement();
10595 });
10596
10597 // We check to see if CFI Instructions are present, and if they are
10598 // we find the number of CFI Instructions in the candidates.
10599 unsigned CFICount = 0;
10600 for (auto &I : RepeatedSequenceLocs[0]) {
10601 if (I.isCFIInstruction())
10602 CFICount++;
10603 }
10604
10605 // We compare the number of found CFI Instructions to the number of CFI
10606 // instructions in the parent function for each candidate. We must check this
10607 // since if we outline one of the CFI instructions in a function, we have to
10608 // outline them all for correctness. If we do not, the address offsets will be
10609 // incorrect between the two sections of the program.
10610 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10611 std::vector<MCCFIInstruction> CFIInstructions =
10612 C.getMF()->getFrameInstructions();
10613
10614 if (CFICount > 0 && CFICount != CFIInstructions.size())
10615 return std::nullopt;
10616 }
10617
10618 // Returns true if an instructions is safe to fix up, false otherwise.
10619 auto IsSafeToFixup = [this, &TRI](MachineInstr &MI) {
10620 if (MI.isCall())
10621 return true;
10622
10623 if (!MI.modifiesRegister(AArch64::SP, &TRI) &&
10624 !MI.readsRegister(AArch64::SP, &TRI))
10625 return true;
10626
10627 // Any modification of SP will break our code to save/restore LR.
10628 // FIXME: We could handle some instructions which add a constant
10629 // offset to SP, with a bit more work.
10630 if (MI.modifiesRegister(AArch64::SP, &TRI))
10631 return false;
10632
10633 // At this point, we have a stack instruction that we might need to
10634 // fix up. We'll handle it if it's a load or store.
10635 if (MI.mayLoadOrStore()) {
10636 const MachineOperand *Base; // Filled with the base operand of MI.
10637 int64_t Offset; // Filled with the offset of MI.
10638 bool OffsetIsScalable;
10639
10640 // Does it allow us to offset the base operand and is the base the
10641 // register SP?
10642 if (!getMemOperandWithOffset(MI, Base, Offset, OffsetIsScalable, &TRI) ||
10643 !Base->isReg() || Base->getReg() != AArch64::SP)
10644 return false;
10645
10646 // Fixe-up code below assumes bytes.
10647 if (OffsetIsScalable)
10648 return false;
10649
10650 // Find the minimum/maximum offset for this instruction and check
10651 // if fixing it up would be in range.
10652 int64_t MinOffset,
10653 MaxOffset; // Unscaled offsets for the instruction.
10654 // The scale to multiply the offsets by.
10655 TypeSize Scale(0U, false), DummyWidth(0U, false);
10656 getMemOpInfo(MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10657
10658 Offset += 16; // Update the offset to what it would be if we outlined.
10659 if (Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10660 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10661 return false;
10662
10663 // It's in range, so we can outline it.
10664 return true;
10665 }
10666
10667 // FIXME: Add handling for instructions like "add x0, sp, #8".
10668
10669 // We can't fix it up, so don't outline it.
10670 return false;
10671 };
10672
10673 // True if it's possible to fix up each stack instruction in this sequence.
10674 // Important for frames/call variants that modify the stack.
10675 bool AllStackInstrsSafe =
10676 llvm::all_of(RepeatedSequenceLocs[0], IsSafeToFixup);
10677
10678 // If the last instruction in any candidate is a terminator, then we should
10679 // tail call all of the candidates.
10680 if (RepeatedSequenceLocs[0].back().isTerminator()) {
10681 FrameID = MachineOutlinerTailCall;
10682 NumBytesToCreateFrame = 0;
10683 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10684 SetCandidateCallInfo(MachineOutlinerTailCall, NumBytesForCall);
10685 }
10686
10687 else if (LastInstrOpcode == AArch64::BL ||
10688 ((LastInstrOpcode == AArch64::BLR ||
10689 LastInstrOpcode == AArch64::BLRNoIP) &&
10690 !HasBTI)) {
10691 // FIXME: Do we need to check if the code after this uses the value of LR?
10692 FrameID = MachineOutlinerThunk;
10693 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10694 SetCandidateCallInfo(MachineOutlinerThunk, 4);
10695 }
10696
10697 else {
10698 // We need to decide how to emit calls + frames. We can always emit the same
10699 // frame if we don't need to save to the stack. If we have to save to the
10700 // stack, then we need a different frame.
10701 unsigned NumBytesNoStackCalls = 0;
10702 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10703
10704 // Check if we have to save LR.
10705 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10706 bool LRAvailable =
10708 ? C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI)
10709 : true;
10710 // If we have a noreturn caller, then we're going to be conservative and
10711 // say that we have to save LR. If we don't have a ret at the end of the
10712 // block, then we can't reason about liveness accurately.
10713 //
10714 // FIXME: We can probably do better than always disabling this in
10715 // noreturn functions by fixing up the liveness info.
10716 bool IsNoReturn =
10717 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10718
10719 // Is LR available? If so, we don't need a save.
10720 if (LRAvailable && !IsNoReturn) {
10721 NumBytesNoStackCalls += 4;
10722 C.setCallInfo(MachineOutlinerNoLRSave, 4);
10723 CandidatesWithoutStackFixups.push_back(C);
10724 }
10725
10726 // Is an unused register available? If so, we won't modify the stack, so
10727 // we can outline with the same frame type as those that don't save LR.
10728 else if (findRegisterToSaveLRTo(C)) {
10729 NumBytesNoStackCalls += 12;
10730 C.setCallInfo(MachineOutlinerRegSave, 12);
10731 CandidatesWithoutStackFixups.push_back(C);
10732 }
10733
10734 // Is SP used in the sequence at all? If not, we don't have to modify
10735 // the stack, so we are guaranteed to get the same frame.
10736 else if (C.isAvailableInsideSeq(AArch64::SP, TRI)) {
10737 NumBytesNoStackCalls += 12;
10738 C.setCallInfo(MachineOutlinerDefault, 12);
10739 CandidatesWithoutStackFixups.push_back(C);
10740 }
10741
10742 // If we outline this, we need to modify the stack. Pretend we don't
10743 // outline this by saving all of its bytes.
10744 else {
10745 NumBytesNoStackCalls += SequenceSize;
10746 }
10747 }
10748
10749 // If there are no places where we have to save LR, then note that we
10750 // don't have to update the stack. Otherwise, give every candidate the
10751 // default call type, as long as it's safe to do so.
10752 if (!AllStackInstrsSafe ||
10753 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10754 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10755 FrameID = MachineOutlinerNoLRSave;
10756 if (RepeatedSequenceLocs.size() < MinRepeats)
10757 return std::nullopt;
10758 } else {
10759 SetCandidateCallInfo(MachineOutlinerDefault, 12);
10760
10761 // Bugzilla ID: 46767
10762 // TODO: Check if fixing up the stack more than once is safe so we can
10763 // outline these.
10764 //
10765 // An outline resulting in a caller that requires stack fixups at the
10766 // callsite to a callee that also requires stack fixups can happen when
10767 // there are no available registers at the candidate callsite for a
10768 // candidate that itself also has calls.
10769 //
10770 // In other words if function_containing_sequence in the following pseudo
10771 // assembly requires that we save LR at the point of the call, but there
10772 // are no available registers: in this case we save using SP and as a
10773 // result the SP offsets requires stack fixups by multiples of 16.
10774 //
10775 // function_containing_sequence:
10776 // ...
10777 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10778 // call OUTLINED_FUNCTION_N
10779 // restore LR from SP
10780 // ...
10781 //
10782 // OUTLINED_FUNCTION_N:
10783 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10784 // ...
10785 // bl foo
10786 // restore LR from SP
10787 // ret
10788 //
10789 // Because the code to handle more than one stack fixup does not
10790 // currently have the proper checks for legality, these cases will assert
10791 // in the AArch64 MachineOutliner. This is because the code to do this
10792 // needs more hardening, testing, better checks that generated code is
10793 // legal, etc and because it is only verified to handle a single pass of
10794 // stack fixup.
10795 //
10796 // The assert happens in AArch64InstrInfo::buildOutlinedFrame to catch
10797 // these cases until they are known to be handled. Bugzilla 46767 is
10798 // referenced in comments at the assert site.
10799 //
10800 // To avoid asserting (or generating non-legal code on noassert builds)
10801 // we remove all candidates which would need more than one stack fixup by
10802 // pruning the cases where the candidate has calls while also having no
10803 // available LR and having no available general purpose registers to copy
10804 // LR to (ie one extra stack save/restore).
10805 //
10806 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10807 erase_if(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
10808 auto IsCall = [](const MachineInstr &MI) { return MI.isCall(); };
10809 return (llvm::any_of(C, IsCall)) &&
10810 (!C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI) ||
10811 !findRegisterToSaveLRTo(C));
10812 });
10813 }
10814 }
10815
10816 // If we dropped all of the candidates, bail out here.
10817 if (RepeatedSequenceLocs.size() < MinRepeats)
10818 return std::nullopt;
10819 }
10820
10821 // Does every candidate's MBB contain a call? If so, then we might have a call
10822 // in the range.
10823 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10824 // Check if the range contains a call. These require a save + restore of the
10825 // link register.
10826 outliner::Candidate &FirstCand = RepeatedSequenceLocs[0];
10827 bool ModStackToSaveLR = false;
10828 if (any_of(drop_end(FirstCand),
10829 [](const MachineInstr &MI) { return MI.isCall(); }))
10830 ModStackToSaveLR = true;
10831
10832 // Handle the last instruction separately. If this is a tail call, then the
10833 // last instruction is a call. We don't want to save + restore in this case.
10834 // However, it could be possible that the last instruction is a call without
10835 // it being valid to tail call this sequence. We should consider this as
10836 // well.
10837 else if (FrameID != MachineOutlinerThunk &&
10838 FrameID != MachineOutlinerTailCall && FirstCand.back().isCall())
10839 ModStackToSaveLR = true;
10840
10841 if (ModStackToSaveLR) {
10842 // We can't fix up the stack. Bail out.
10843 if (!AllStackInstrsSafe)
10844 return std::nullopt;
10845
10846 // Save + restore LR.
10847 NumBytesToCreateFrame += 8;
10848
10849 // Add the extra mov if we will save a frame record instead of just LR.
10851 RepeatedSequenceLocs, TRI))
10852 NumBytesToCreateFrame += 4;
10853 }
10854 }
10855
10856 // If we have CFI instructions, we can only outline if the outlined section
10857 // can be a tail call
10858 if (FrameID != MachineOutlinerTailCall && CFICount > 0)
10859 return std::nullopt;
10860
10861 return std::make_unique<outliner::OutlinedFunction>(
10862 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10863}
10864
10865void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10866 Function &F, std::vector<outliner::Candidate> &Candidates) const {
10867 // If a bunch of candidates reach this point they must agree on their return
10868 // address signing. It is therefore enough to just consider the signing
10869 // behaviour of one of them
10870 const auto &CFn = Candidates.front().getMF()->getFunction();
10871
10872 if (CFn.hasFnAttribute("ptrauth-returns"))
10873 F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
10874 if (CFn.hasFnAttribute("ptrauth-auth-traps"))
10875 F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
10876 // Since all candidates belong to the same module, just copy the
10877 // function-level attributes of an arbitrary function.
10878 if (CFn.hasFnAttribute("sign-return-address"))
10879 F.addFnAttr(CFn.getFnAttribute("sign-return-address"));
10880 if (CFn.hasFnAttribute("sign-return-address-key"))
10881 F.addFnAttr(CFn.getFnAttribute("sign-return-address-key"));
10882
10883 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);
10884}
10885
10886bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10887 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
10888 const Function &F = MF.getFunction();
10889
10890 // Can F be deduplicated by the linker? If it can, don't outline from it.
10891 if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
10892 return false;
10893
10894 // Don't outline from functions with section markings; the program could
10895 // expect that all the code is in the named section.
10896 // FIXME: Allow outlining from multiple functions with the same section
10897 // marking.
10898 if (F.hasSection())
10899 return false;
10900
10901 // Outlining from functions with redzones is unsafe since the outliner may
10902 // modify the stack. Check if hasRedZone is true or unknown; if yes, don't
10903 // outline from it.
10904 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
10905 if (!AFI || AFI->hasRedZone().value_or(true))
10906 return false;
10907
10908 // FIXME: Determine whether it is safe to outline from functions which contain
10909 // streaming-mode changes. We may need to ensure any smstart/smstop pairs are
10910 // outlined together and ensure it is safe to outline with async unwind info,
10911 // required for saving & restoring VG around calls.
10912 if (AFI->hasStreamingModeChanges())
10913 return false;
10914
10915 // FIXME: Teach the outliner to generate/handle Windows unwind info.
10917 return false;
10918
10919 // It's safe to outline from MF.
10920 return true;
10921}
10922
10924AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
10925 unsigned &Flags) const {
10927 "Must track liveness!");
10929 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10930 Ranges;
10931 // According to the AArch64 Procedure Call Standard, the following are
10932 // undefined on entry/exit from a function call:
10933 //
10934 // * Registers x16, x17, (and thus w16, w17)
10935 // * Condition codes (and thus the NZCV register)
10936 //
10937 // If any of these registers are used inside or live across an outlined
10938 // function, then they may be modified later, either by the compiler or
10939 // some other tool (like the linker).
10940 //
10941 // To avoid outlining in these situations, partition each block into ranges
10942 // where these registers are dead. We will only outline from those ranges.
10943 LiveRegUnits LRU(getRegisterInfo());
10944 auto AreAllUnsafeRegsDead = [&LRU]() {
10945 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10946 LRU.available(AArch64::NZCV);
10947 };
10948
10949 // We need to know if LR is live across an outlining boundary later on in
10950 // order to decide how we'll create the outlined call, frame, etc.
10951 //
10952 // It's pretty expensive to check this for *every candidate* within a block.
10953 // That's some potentially n^2 behaviour, since in the worst case, we'd need
10954 // to compute liveness from the end of the block for O(n) candidates within
10955 // the block.
10956 //
10957 // So, to improve the average case, let's keep track of liveness from the end
10958 // of the block to the beginning of *every outlinable range*. If we know that
10959 // LR is available in every range we could outline from, then we know that
10960 // we don't need to check liveness for any candidate within that range.
10961 bool LRAvailableEverywhere = true;
10962 // Compute liveness bottom-up.
10963 LRU.addLiveOuts(MBB);
10964 // Update flags that require info about the entire MBB.
10965 auto UpdateWholeMBBFlags = [&Flags](const MachineInstr &MI) {
10966 if (MI.isCall() && !MI.isTerminator())
10968 };
10969 // Range: [RangeBegin, RangeEnd)
10970 MachineBasicBlock::instr_iterator RangeBegin, RangeEnd;
10971 unsigned RangeLen;
10972 auto CreateNewRangeStartingAt =
10973 [&RangeBegin, &RangeEnd,
10974 &RangeLen](MachineBasicBlock::instr_iterator NewBegin) {
10975 RangeBegin = NewBegin;
10976 RangeEnd = std::next(RangeBegin);
10977 RangeLen = 0;
10978 };
10979 auto SaveRangeIfNonEmpty = [&RangeLen, &Ranges, &RangeBegin, &RangeEnd]() {
10980 // At least one unsafe register is not dead. We do not want to outline at
10981 // this point. If it is long enough to outline from and does not cross a
10982 // bundle boundary, save the range [RangeBegin, RangeEnd).
10983 if (RangeLen <= 1)
10984 return;
10985 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
10986 return;
10987 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
10988 return;
10989 Ranges.emplace_back(RangeBegin, RangeEnd);
10990 };
10991 // Find the first point where all unsafe registers are dead.
10992 // FIND: <safe instr> <-- end of first potential range
10993 // SKIP: <unsafe def>
10994 // SKIP: ... everything between ...
10995 // SKIP: <unsafe use>
10996 auto FirstPossibleEndPt = MBB.instr_rbegin();
10997 for (; FirstPossibleEndPt != MBB.instr_rend(); ++FirstPossibleEndPt) {
10998 if (!FirstPossibleEndPt->isDebugInstr())
10999 LRU.stepBackward(*FirstPossibleEndPt);
11000 // Update flags that impact how we outline across the entire block,
11001 // regardless of safety.
11002 UpdateWholeMBBFlags(*FirstPossibleEndPt);
11003 if (AreAllUnsafeRegsDead())
11004 break;
11005 }
11006 // If we exhausted the entire block, we have no safe ranges to outline.
11007 if (FirstPossibleEndPt == MBB.instr_rend())
11008 return Ranges;
11009 // Current range.
11010 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
11011 // StartPt points to the first place where all unsafe registers
11012 // are dead (if there is any such point). Begin partitioning the MBB into
11013 // ranges.
11014 for (auto &MI : make_range(FirstPossibleEndPt, MBB.instr_rend())) {
11015 if (!MI.isDebugInstr())
11016 LRU.stepBackward(MI);
11017 UpdateWholeMBBFlags(MI);
11018 if (!AreAllUnsafeRegsDead()) {
11019 SaveRangeIfNonEmpty();
11020 CreateNewRangeStartingAt(MI.getIterator());
11021 continue;
11022 }
11023 LRAvailableEverywhere &= LRU.available(AArch64::LR);
11024 RangeBegin = MI.getIterator();
11025 ++RangeLen;
11026 }
11027 // Above loop misses the last (or only) range. If we are still safe, then
11028 // let's save the range.
11029 if (AreAllUnsafeRegsDead())
11030 SaveRangeIfNonEmpty();
11031 if (Ranges.empty())
11032 return Ranges;
11033 // We found the ranges bottom-up. Mapping expects the top-down. Reverse
11034 // the order.
11035 std::reverse(Ranges.begin(), Ranges.end());
11036 // If there is at least one outlinable range where LR is unavailable
11037 // somewhere, remember that.
11038 if (!LRAvailableEverywhere)
11040 return Ranges;
11041}
11042
11044AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
11046 unsigned Flags) const {
11047 MachineInstr &MI = *MIT;
11048
11049 // Don't outline anything used for return address signing. The outlined
11050 // function will get signed later if needed
11051 switch (MI.getOpcode()) {
11052 case AArch64::PACM:
11053 case AArch64::PACIASP:
11054 case AArch64::PACIBSP:
11055 case AArch64::PACIASPPC:
11056 case AArch64::PACIBSPPC:
11057 case AArch64::AUTIASP:
11058 case AArch64::AUTIBSP:
11059 case AArch64::AUTIASPPCi:
11060 case AArch64::AUTIASPPCr:
11061 case AArch64::AUTIBSPPCi:
11062 case AArch64::AUTIBSPPCr:
11063 case AArch64::RETAA:
11064 case AArch64::RETAB:
11065 case AArch64::RETAASPPCi:
11066 case AArch64::RETAASPPCr:
11067 case AArch64::RETABSPPCi:
11068 case AArch64::RETABSPPCr:
11069 case AArch64::EMITBKEY:
11070 case AArch64::PAUTH_PROLOGUE:
11071 case AArch64::PAUTH_EPILOGUE:
11073 }
11074
11075 // We can only outline these if we will tail call the outlined function, or
11076 // fix up the CFI offsets. Currently, CFI instructions are outlined only if
11077 // in a tail call.
11078 //
11079 // FIXME: If the proper fixups for the offset are implemented, this should be
11080 // possible.
11081 if (MI.isCFIInstruction())
11083
11084 // Is this a terminator for a basic block?
11085 if (MI.isTerminator())
11086 // TargetInstrInfo::getOutliningType has already filtered out anything
11087 // that would break this, so we can allow it here.
11089
11090 // Make sure none of the operands are un-outlinable.
11091 for (const MachineOperand &MOP : MI.operands()) {
11092 // A check preventing CFI indices was here before, but only CFI
11093 // instructions should have those.
11094 assert(!MOP.isCFIIndex());
11095
11096 // If it uses LR or W30 explicitly, then don't touch it.
11097 if (MOP.isReg() && !MOP.isImplicit() &&
11098 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
11100 }
11101
11102 // Special cases for instructions that can always be outlined, but will fail
11103 // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
11104 // be outlined because they don't require a *specific* value to be in LR.
11105 if (MI.getOpcode() == AArch64::ADRP)
11107
11108 // If MI is a call we might be able to outline it. We don't want to outline
11109 // any calls that rely on the position of items on the stack. When we outline
11110 // something containing a call, we have to emit a save and restore of LR in
11111 // the outlined function. Currently, this always happens by saving LR to the
11112 // stack. Thus, if we outline, say, half the parameters for a function call
11113 // plus the call, then we'll break the callee's expectations for the layout
11114 // of the stack.
11115 //
11116 // FIXME: Allow calls to functions which construct a stack frame, as long
11117 // as they don't access arguments on the stack.
11118 // FIXME: Figure out some way to analyze functions defined in other modules.
11119 // We should be able to compute the memory usage based on the IR calling
11120 // convention, even if we can't see the definition.
11121 if (MI.isCall()) {
11122 // Get the function associated with the call. Look at each operand and find
11123 // the one that represents the callee and get its name.
11124 const Function *Callee = nullptr;
11125 for (const MachineOperand &MOP : MI.operands()) {
11126 if (MOP.isGlobal()) {
11127 Callee = dyn_cast<Function>(MOP.getGlobal());
11128 break;
11129 }
11130 }
11131
11132 // Never outline calls to mcount. There isn't any rule that would require
11133 // this, but the Linux kernel's "ftrace" feature depends on it.
11134 if (Callee && Callee->getName() == "\01_mcount")
11136
11137 // If we don't know anything about the callee, assume it depends on the
11138 // stack layout of the caller. In that case, it's only legal to outline
11139 // as a tail-call. Explicitly list the call instructions we know about so we
11140 // don't get unexpected results with call pseudo-instructions.
11141 auto UnknownCallOutlineType = outliner::InstrType::Illegal;
11142 if (MI.getOpcode() == AArch64::BLR ||
11143 MI.getOpcode() == AArch64::BLRNoIP || MI.getOpcode() == AArch64::BL)
11144 UnknownCallOutlineType = outliner::InstrType::LegalTerminator;
11145
11146 if (!Callee)
11147 return UnknownCallOutlineType;
11148
11149 // We have a function we have information about. Check it if it's something
11150 // can safely outline.
11151 MachineFunction *CalleeMF = MMI.getMachineFunction(*Callee);
11152
11153 // We don't know what's going on with the callee at all. Don't touch it.
11154 if (!CalleeMF)
11155 return UnknownCallOutlineType;
11156
11157 // Check if we know anything about the callee saves on the function. If we
11158 // don't, then don't touch it, since that implies that we haven't
11159 // computed anything about its stack frame yet.
11160 MachineFrameInfo &MFI = CalleeMF->getFrameInfo();
11161 if (!MFI.isCalleeSavedInfoValid() || MFI.getStackSize() > 0 ||
11162 MFI.getNumObjects() > 0)
11163 return UnknownCallOutlineType;
11164
11165 // At this point, we can say that CalleeMF ought to not pass anything on the
11166 // stack. Therefore, we can outline it.
11168 }
11169
11170 // Don't touch the link register or W30.
11171 if (MI.readsRegister(AArch64::W30, &getRegisterInfo()) ||
11172 MI.modifiesRegister(AArch64::W30, &getRegisterInfo()))
11174
11175 // Don't outline BTI instructions, because that will prevent the outlining
11176 // site from being indirectly callable.
11177 if (hasBTISemantics(MI))
11179
11181}
11182
11183void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
11184 for (MachineInstr &MI : MBB) {
11185 const MachineOperand *Base;
11186 TypeSize Width(0, false);
11187 int64_t Offset;
11188 bool OffsetIsScalable;
11189
11190 // Is this a load or store with an immediate offset with SP as the base?
11191 if (!MI.mayLoadOrStore() ||
11192 !getMemOperandWithOffsetWidth(MI, Base, Offset, OffsetIsScalable, Width,
11193 &RI) ||
11194 (Base->isReg() && Base->getReg() != AArch64::SP))
11195 continue;
11196
11197 // It is, so we have to fix it up.
11198 TypeSize Scale(0U, false);
11199 int64_t Dummy1, Dummy2;
11200
11201 MachineOperand &StackOffsetOperand = getMemOpBaseRegImmOfsOffsetOperand(MI);
11202 assert(StackOffsetOperand.isImm() && "Stack offset wasn't immediate!");
11203 getMemOpInfo(MI.getOpcode(), Scale, Width, Dummy1, Dummy2);
11204 assert(Scale != 0 && "Unexpected opcode!");
11205 assert(!OffsetIsScalable && "Expected offset to be a byte offset");
11206
11207 // We've pushed the return address to the stack, so add 16 to the offset.
11208 // This is safe, since we already checked if it would overflow when we
11209 // checked if this instruction was legal to outline.
11210 int64_t NewImm = (Offset + 16) / (int64_t)Scale.getFixedValue();
11211 StackOffsetOperand.setImm(NewImm);
11212 }
11213}
11214
11216 const AArch64InstrInfo *TII,
11217 bool ShouldSignReturnAddr) {
11218 if (!ShouldSignReturnAddr)
11219 return;
11220
11221 BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(AArch64::PAUTH_PROLOGUE))
11223 TII->createPauthEpilogueInstr(MBB, DebugLoc());
11224}
11225
11226void AArch64InstrInfo::buildOutlinedFrame(
11228 const outliner::OutlinedFunction &OF) const {
11229
11230 AArch64FunctionInfo *FI = MF.getInfo<AArch64FunctionInfo>();
11231
11232 if (OF.FrameConstructionID == MachineOutlinerTailCall)
11233 FI->setOutliningStyle("Tail Call");
11234 else if (OF.FrameConstructionID == MachineOutlinerThunk) {
11235 // For thunk outlining, rewrite the last instruction from a call to a
11236 // tail-call.
11237 MachineInstr *Call = &*--MBB.instr_end();
11238 unsigned TailOpcode;
11239 if (Call->getOpcode() == AArch64::BL) {
11240 TailOpcode = AArch64::TCRETURNdi;
11241 } else {
11242 assert(Call->getOpcode() == AArch64::BLR ||
11243 Call->getOpcode() == AArch64::BLRNoIP);
11244 TailOpcode = AArch64::TCRETURNriALL;
11245 }
11246 MachineInstr *TC = BuildMI(MF, DebugLoc(), get(TailOpcode))
11247 .add(Call->getOperand(0))
11248 .addImm(0);
11249 MBB.insert(MBB.end(), TC);
11251
11252 FI->setOutliningStyle("Thunk");
11253 }
11254
11255 bool IsLeafFunction = true;
11256
11257 // Is there a call in the outlined range?
11258 auto IsNonTailCall = [](const MachineInstr &MI) {
11259 return MI.isCall() && !MI.isReturn();
11260 };
11261
11262 if (llvm::any_of(MBB.instrs(), IsNonTailCall)) {
11263 // Fix up the instructions in the range, since we're going to modify the
11264 // stack.
11265
11266 // Bugzilla ID: 46767
11267 // TODO: Check if fixing up twice is safe so we can outline these.
11268 assert(OF.FrameConstructionID != MachineOutlinerDefault &&
11269 "Can only fix up stack references once");
11270 fixupPostOutline(MBB);
11271
11272 IsLeafFunction = false;
11273
11274 // LR has to be a live in so that we can save it.
11275 if (!MBB.isLiveIn(AArch64::LR))
11276 MBB.addLiveIn(AArch64::LR);
11277
11280
11281 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11282 OF.FrameConstructionID == MachineOutlinerThunk)
11283 Et = std::prev(MBB.end());
11284
11285 // There is a call in the range, so we must save LR. Save it as part of a
11286 // frame record when that gives us a smaller compact unwind encoding.
11288 // FP is saved here, so it must be live-in.
11289 if (!MBB.isLiveIn(AArch64::FP))
11290 MBB.addLiveIn(AArch64::FP);
11291
11292 // stp x29, x30, [sp, #-16]! (the pre-index imm is scaled by 8: -2 * 8)
11293 MachineInstr *STPXpre = BuildMI(MF, DebugLoc(), get(AArch64::STPXpre))
11294 .addReg(AArch64::SP, RegState::Define)
11295 .addReg(AArch64::FP)
11296 .addReg(AArch64::LR)
11297 .addReg(AArch64::SP)
11298 .addImm(-2);
11299 It = MBB.insert(It, STPXpre);
11300
11301 // mov x29, sp (add x29, sp, #0), so x29 points at the frame record.
11302 MachineInstr *SetFP = BuildMI(MF, DebugLoc(), get(AArch64::ADDXri))
11303 .addReg(AArch64::FP, RegState::Define)
11304 .addReg(AArch64::SP)
11305 .addImm(0)
11306 .addImm(0);
11307 MBB.insertAfter(It, SetFP);
11308
11309 // Describe the frame record with FP as the CFA. The encoder needs all
11310 // three to pick FRAME. No need to check for unwind info here: we only
11311 // get here if the function has it.
11312 CFIInstBuilder CFIBuilder(MBB, std::next(SetFP->getIterator()),
11314 CFIBuilder.buildDefCFA(AArch64::FP, 16);
11315 CFIBuilder.buildOffset(AArch64::LR, -8);
11316 CFIBuilder.buildOffset(AArch64::FP, -16);
11317
11318 // ldp x29, x30, [sp], #16
11319 MachineInstr *LDPXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDPXpost))
11320 .addReg(AArch64::SP, RegState::Define)
11321 .addReg(AArch64::FP, RegState::Define)
11322 .addReg(AArch64::LR, RegState::Define)
11323 .addReg(AArch64::SP)
11324 .addImm(2);
11325 Et = MBB.insert(Et, LDPXpost);
11326 } else {
11327 // Insert a save before the outlined region
11328 MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11329 .addReg(AArch64::SP, RegState::Define)
11330 .addReg(AArch64::LR)
11331 .addReg(AArch64::SP)
11332 .addImm(-16);
11333 It = MBB.insert(It, STRXpre);
11334
11335 if (MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11336 CFIInstBuilder CFIBuilder(MBB, It, MachineInstr::FrameSetup);
11337
11338 // Add a CFI saying the stack was moved 16 B down.
11339 CFIBuilder.buildDefCFAOffset(16);
11340
11341 // Add a CFI saying that the LR that we want to find is now 16 B higher
11342 // than before.
11343 CFIBuilder.buildOffset(AArch64::LR, -16);
11344 }
11345
11346 // Insert a restore before the terminator for the function.
11347 MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11348 .addReg(AArch64::SP, RegState::Define)
11349 .addReg(AArch64::LR, RegState::Define)
11350 .addReg(AArch64::SP)
11351 .addImm(16);
11352 Et = MBB.insert(Et, LDRXpost);
11353 }
11354 }
11355
11356 auto RASignCondition = FI->getSignReturnAddressCondition();
11357 bool ShouldSignReturnAddr = AArch64FunctionInfo::shouldSignReturnAddress(
11358 RASignCondition, !IsLeafFunction);
11359
11360 // If this is a tail call outlined function, then there's already a return.
11361 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11362 OF.FrameConstructionID == MachineOutlinerThunk) {
11363 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11364 return;
11365 }
11366
11367 // It's not a tail call, so we have to insert the return ourselves.
11368
11369 // LR has to be a live in so that we can return to it.
11370 if (!MBB.isLiveIn(AArch64::LR))
11371 MBB.addLiveIn(AArch64::LR);
11372
11373 MachineInstr *ret = BuildMI(MF, DebugLoc(), get(AArch64::RET))
11374 .addReg(AArch64::LR);
11375 MBB.insert(MBB.end(), ret);
11376
11377 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11378
11379 FI->setOutliningStyle("Function");
11380
11381 // Did we have to modify the stack by saving the link register?
11382 if (OF.FrameConstructionID != MachineOutlinerDefault)
11383 return;
11384
11385 // We modified the stack.
11386 // Walk over the basic block and fix up all the stack accesses.
11387 fixupPostOutline(MBB);
11388}
11389
11390MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall(
11393
11394 // Are we tail calling?
11395 if (C.CallConstructionID == MachineOutlinerTailCall) {
11396 // If yes, then we can just branch to the label.
11397 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::TCRETURNdi))
11398 .addGlobalAddress(M.getNamedValue(MF.getName()))
11399 .addImm(0));
11400 return It;
11401 }
11402
11403 // Are we saving the link register?
11404 if (C.CallConstructionID == MachineOutlinerNoLRSave ||
11405 C.CallConstructionID == MachineOutlinerThunk) {
11406 // No, so just insert the call.
11407 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11408 .addGlobalAddress(M.getNamedValue(MF.getName())));
11409 return It;
11410 }
11411
11412 // We want to return the spot where we inserted the call.
11414
11415 // Instructions for saving and restoring LR around the call instruction we're
11416 // going to insert.
11417 MachineInstr *Save;
11418 MachineInstr *Restore;
11419 // Can we save to a register?
11420 if (C.CallConstructionID == MachineOutlinerRegSave) {
11421 // FIXME: This logic should be sunk into a target-specific interface so that
11422 // we don't have to recompute the register.
11423 Register Reg = findRegisterToSaveLRTo(C);
11424 assert(Reg && "No callee-saved register available?");
11425
11426 // LR has to be a live in so that we can save it.
11427 if (!MBB.isLiveIn(AArch64::LR))
11428 MBB.addLiveIn(AArch64::LR);
11429
11430 // Save and restore LR from Reg.
11431 Save = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), Reg)
11432 .addReg(AArch64::XZR)
11433 .addReg(AArch64::LR)
11434 .addImm(0);
11435 Restore = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), AArch64::LR)
11436 .addReg(AArch64::XZR)
11437 .addReg(Reg)
11438 .addImm(0);
11439 } else {
11440 // We have the default case. Save and restore from SP.
11441 Save = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11442 .addReg(AArch64::SP, RegState::Define)
11443 .addReg(AArch64::LR)
11444 .addReg(AArch64::SP)
11445 .addImm(-16);
11446 Restore = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11447 .addReg(AArch64::SP, RegState::Define)
11448 .addReg(AArch64::LR, RegState::Define)
11449 .addReg(AArch64::SP)
11450 .addImm(16);
11451 }
11452
11453 It = MBB.insert(It, Save);
11454 It++;
11455
11456 // Insert the call.
11457 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11458 .addGlobalAddress(M.getNamedValue(MF.getName())));
11459 CallPt = It;
11460 It++;
11461
11462 It = MBB.insert(It, Restore);
11463 return CallPt;
11464}
11465
11466bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11467 MachineFunction &MF) const {
11468 return MF.getFunction().hasMinSize();
11469}
11470
11471void AArch64InstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
11473 DebugLoc &DL,
11474 bool AllowSideEffects) const {
11475 const MachineFunction &MF = *MBB.getParent();
11476 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
11477 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
11478
11479 if (TRI.isGeneralPurposeRegister(MF, Reg)) {
11480 BuildMI(MBB, Iter, DL, get(AArch64::MOVZXi), Reg).addImm(0).addImm(0);
11481 } else if (STI.isSVEorStreamingSVEAvailable()) {
11482 BuildMI(MBB, Iter, DL, get(AArch64::DUP_ZI_D), Reg)
11483 .addImm(0)
11484 .addImm(0);
11485 } else if (STI.isNeonAvailable()) {
11486 BuildMI(MBB, Iter, DL, get(AArch64::MOVIv2d_ns), Reg)
11487 .addImm(0);
11488 } else {
11489 // No Advanced SIMD (streaming-compatible without SVE, or +nosimd), so use
11490 // `fmov d...` instead of `movi v...`; writing `d` also clears the upper
11491 // 64 bits.
11492 assert(STI.hasFPARMv8() && "Expected FP to be available.");
11493 Register Reg64 = TRI.getSubReg(Reg, AArch64::dsub);
11494 BuildMI(MBB, Iter, DL, get(AArch64::FMOVD0), Reg64);
11495 }
11496}
11497
11498std::optional<DestSourcePair>
11500
11501 // AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg
11502 // and zero immediate operands used as an alias for mov instruction.
11503 if ((MI.getOpcode() == AArch64::ORRWrs &&
11504 MI.getOperand(1).getReg() == AArch64::WZR &&
11505 MI.getOperand(3).getImm() == 0x0) ||
11506 (MI.getOpcode() == AArch64::ORRWrr &&
11507 MI.getOperand(1).getReg() == AArch64::WZR)) {
11508 // Check that the w->w move is not a zero-extending w->x mov.
11509 if ((MI.getOperand(0).getReg().isPhysical() &&
11510 MI.findRegisterDefOperandIdx(
11511 getXRegFromWReg(MI.getOperand(0).getReg()),
11512 /*TRI=*/nullptr) == -1) ||
11513 (MI.getOperand(0).getReg().isVirtual() &&
11514 !MI.getOperand(0).getSubReg()))
11515 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11516 }
11517
11518 if (MI.getOpcode() == AArch64::ORRXrs &&
11519 MI.getOperand(1).getReg() == AArch64::XZR &&
11520 MI.getOperand(3).getImm() == 0x0)
11521 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11522
11523 return std::nullopt;
11524}
11525
11526std::optional<DestSourcePair>
11528 if ((MI.getOpcode() == AArch64::ORRWrs &&
11529 MI.getOperand(1).getReg() == AArch64::WZR &&
11530 MI.getOperand(3).getImm() == 0x0) ||
11531 (MI.getOpcode() == AArch64::ORRWrr &&
11532 MI.getOperand(1).getReg() == AArch64::WZR))
11533 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11534 return std::nullopt;
11535}
11536
11537std::optional<RegImmPair>
11538AArch64InstrInfo::isAddImmediate(const MachineInstr &MI, Register Reg) const {
11539 int Sign = 1;
11540 int64_t Offset = 0;
11541
11542 // TODO: Handle cases where Reg is a super- or sub-register of the
11543 // destination register.
11544 const MachineOperand &Op0 = MI.getOperand(0);
11545 if (!Op0.isReg() || Reg != Op0.getReg())
11546 return std::nullopt;
11547
11548 switch (MI.getOpcode()) {
11549 default:
11550 return std::nullopt;
11551 case AArch64::SUBWri:
11552 case AArch64::SUBXri:
11553 case AArch64::SUBSWri:
11554 case AArch64::SUBSXri:
11555 Sign *= -1;
11556 [[fallthrough]];
11557 case AArch64::ADDSWri:
11558 case AArch64::ADDSXri:
11559 case AArch64::ADDWri:
11560 case AArch64::ADDXri: {
11561 // TODO: Third operand can be global address (usually some string).
11562 if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
11563 !MI.getOperand(2).isImm())
11564 return std::nullopt;
11565 int Shift = MI.getOperand(3).getImm();
11566 assert((Shift == 0 || Shift == 12) && "Shift can be either 0 or 12");
11567 Offset = Sign * (MI.getOperand(2).getImm() << Shift);
11568 }
11569 }
11570 return RegImmPair{MI.getOperand(1).getReg(), Offset};
11571}
11572
11573/// If the given ORR instruction is a copy, and \p DescribedReg overlaps with
11574/// the destination register then, if possible, describe the value in terms of
11575/// the source register.
11576static std::optional<ParamLoadedValue>
11578 const TargetInstrInfo *TII,
11579 const TargetRegisterInfo *TRI) {
11580 auto DestSrc = TII->isCopyLikeInstr(MI);
11581 if (!DestSrc)
11582 return std::nullopt;
11583
11584 Register DestReg = DestSrc->Destination->getReg();
11585 Register SrcReg = DestSrc->Source->getReg();
11586
11587 if (!DestReg.isValid() || !SrcReg.isValid())
11588 return std::nullopt;
11589
11590 auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
11591
11592 // If the described register is the destination, just return the source.
11593 if (DestReg == DescribedReg)
11594 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11595
11596 // ORRWrs zero-extends to 64-bits, so we need to consider such cases.
11597 if (MI.getOpcode() == AArch64::ORRWrs &&
11598 TRI->isSuperRegister(DestReg, DescribedReg))
11599 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11600
11601 // We may need to describe the lower part of a ORRXrs move.
11602 if (MI.getOpcode() == AArch64::ORRXrs &&
11603 TRI->isSubRegister(DestReg, DescribedReg)) {
11604 Register SrcSubReg = TRI->getSubReg(SrcReg, AArch64::sub_32);
11605 return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
11606 }
11607
11608 assert(!TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11609 "Unhandled ORR[XW]rs copy case");
11610
11611 return std::nullopt;
11612}
11613
11614bool AArch64InstrInfo::isFunctionSafeToSplit(const MachineFunction &MF) const {
11615 // Functions cannot be split to different sections on AArch64 if they have
11616 // a red zone. This is because relaxing a cross-section branch may require
11617 // incrementing the stack pointer to spill a register, which would overwrite
11618 // the red zone.
11619 if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(true))
11620 return false;
11621
11623}
11624
11625bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11626 const MachineBasicBlock &MBB) const {
11627 // Asm Goto blocks can contain conditional branches to goto labels, which can
11628 // get moved out of range of the branch instruction.
11629 auto isAsmGoto = [](const MachineInstr &MI) {
11630 return MI.getOpcode() == AArch64::INLINEASM_BR;
11631 };
11632 if (llvm::any_of(MBB, isAsmGoto) || MBB.isInlineAsmBrIndirectTarget())
11633 return false;
11634
11635 // Because jump tables are label-relative instead of table-relative, they all
11636 // must be in the same section or relocation fixup handling will fail.
11637
11638 // Check if MBB is a jump table target
11639 const MachineJumpTableInfo *MJTI = MBB.getParent()->getJumpTableInfo();
11640 auto containsMBB = [&MBB](const MachineJumpTableEntry &JTE) {
11641 return llvm::is_contained(JTE.MBBs, &MBB);
11642 };
11643 if (MJTI != nullptr && llvm::any_of(MJTI->getJumpTables(), containsMBB))
11644 return false;
11645
11646 // Check if MBB contains a jump table lookup
11647 for (const MachineInstr &MI : MBB) {
11648 switch (MI.getOpcode()) {
11649 case TargetOpcode::G_BRJT:
11650 case AArch64::JumpTableDest32:
11651 case AArch64::JumpTableDest16:
11652 case AArch64::JumpTableDest8:
11653 return false;
11654 default:
11655 continue;
11656 }
11657 }
11658
11659 // MBB isn't a special case, so it's safe to be split to the cold section.
11660 return true;
11661}
11662
11663std::optional<ParamLoadedValue>
11664AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
11665 Register Reg) const {
11666 const MachineFunction *MF = MI.getMF();
11667 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
11668 switch (MI.getOpcode()) {
11669 case AArch64::MOVZWi:
11670 case AArch64::MOVZXi: {
11671 // MOVZWi may be used for producing zero-extended 32-bit immediates in
11672 // 64-bit parameters, so we need to consider super-registers.
11673 if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
11674 return std::nullopt;
11675
11676 if (!MI.getOperand(1).isImm())
11677 return std::nullopt;
11678 int64_t Immediate = MI.getOperand(1).getImm();
11679 int Shift = MI.getOperand(2).getImm();
11680 return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
11681 nullptr);
11682 }
11683 case AArch64::ORRWrs:
11684 case AArch64::ORRXrs:
11685 return describeORRLoadedValue(MI, Reg, this, TRI);
11686 }
11687
11689}
11690
11691bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11692 MachineInstr &ExtMI, MachineRegisterInfo &MRI) const {
11693 assert(ExtMI.getOpcode() == TargetOpcode::G_SEXT ||
11694 ExtMI.getOpcode() == TargetOpcode::G_ZEXT ||
11695 ExtMI.getOpcode() == TargetOpcode::G_ANYEXT);
11696
11697 // Anyexts are nops.
11698 if (ExtMI.getOpcode() == TargetOpcode::G_ANYEXT)
11699 return true;
11700
11701 Register DefReg = ExtMI.getOperand(0).getReg();
11702 if (!MRI.hasOneNonDBGUse(DefReg))
11703 return false;
11704
11705 // It's likely that a sext/zext as a G_PTR_ADD offset will be folded into an
11706 // addressing mode.
11707 auto *UserMI = &*MRI.use_instr_nodbg_begin(DefReg);
11708 return UserMI->getOpcode() == TargetOpcode::G_PTR_ADD;
11709}
11710
11711uint64_t AArch64InstrInfo::getElementSizeForOpcode(unsigned Opc) const {
11712 return get(Opc).TSFlags & AArch64::ElementSizeMask;
11713}
11714
11715bool AArch64InstrInfo::isPTestLikeOpcode(unsigned Opc) const {
11716 return get(Opc).TSFlags & AArch64::InstrFlagIsPTestLike;
11717}
11718
11719bool AArch64InstrInfo::isWhileOpcode(unsigned Opc) const {
11720 return get(Opc).TSFlags & AArch64::InstrFlagIsWhile;
11721}
11722
11723unsigned int
11724AArch64InstrInfo::getTailDuplicateSize(CodeGenOptLevel OptLevel) const {
11725 return OptLevel >= CodeGenOptLevel::Aggressive ? 6 : 2;
11726}
11727
11728bool AArch64InstrInfo::isLegalAddressingMode(unsigned NumBytes, int64_t Offset,
11729 unsigned Scale) const {
11730 if (Offset && Scale)
11731 return false;
11732
11733 // Check Reg + Imm
11734 if (!Scale) {
11735 // 9-bit signed offset
11736 if (isInt<9>(Offset))
11737 return true;
11738
11739 // 12-bit unsigned offset
11740 unsigned Shift = Log2_64(NumBytes);
11741 if (NumBytes && Offset > 0 && (Offset / NumBytes) <= (1LL << 12) - 1 &&
11742 // Must be a multiple of NumBytes (NumBytes is a power of 2)
11743 (Offset >> Shift) << Shift == Offset)
11744 return true;
11745 return false;
11746 }
11747
11748 // Check reg1 + SIZE_IN_BYTES * reg2 and reg1 + reg2
11749 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11750}
11751
11753 if (MF.getSubtarget<AArch64Subtarget>().hardenSlsBlr())
11754 return AArch64::BLRNoIP;
11755 else
11756 return AArch64::BLR;
11757}
11758
11760 DebugLoc DL) const {
11761 MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
11762 auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
11764
11765 MachineFunction &MF = *MBB.getParent();
11766 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
11767 auto &AFL = *static_cast<const AArch64FrameLowering *>(
11768 MF.getSubtarget().getFrameLowering());
11769 if (AFL.getArgumentStackToRestore(MF, MBB)) {
11770 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
11771 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11772 if (Subtarget.hasPAuthLR())
11773 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
11774 return;
11775 }
11776
11777 if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
11778 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11779}
11780
11782AArch64InstrInfo::probedStackAlloc(MachineBasicBlock::iterator MBBI,
11783 Register TargetReg, bool FrameSetup) const {
11784 assert(TargetReg != AArch64::SP && "New top of stack cannot already be in SP");
11785
11786 MachineBasicBlock &MBB = *MBBI->getParent();
11787 MachineFunction &MF = *MBB.getParent();
11788 const AArch64InstrInfo *TII =
11789 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
11790 int64_t ProbeSize = MF.getInfo<AArch64FunctionInfo>()->getStackProbeSize();
11791 DebugLoc DL = MBB.findDebugLoc(MBBI);
11792
11793 MachineFunction::iterator MBBInsertPoint = std::next(MBB.getIterator());
11794 MachineBasicBlock *LoopTestMBB =
11795 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11796 MF.insert(MBBInsertPoint, LoopTestMBB);
11797 MachineBasicBlock *LoopBodyMBB =
11798 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11799 MF.insert(MBBInsertPoint, LoopBodyMBB);
11800 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11801 MF.insert(MBBInsertPoint, ExitMBB);
11802 MachineInstr::MIFlag Flags =
11804
11805 // LoopTest:
11806 // SUB SP, SP, #ProbeSize
11807 emitFrameOffset(*LoopTestMBB, LoopTestMBB->end(), DL, AArch64::SP,
11808 AArch64::SP, StackOffset::getFixed(-ProbeSize), TII, Flags);
11809
11810 // CMP SP, TargetReg
11811 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::SUBSXrx64),
11812 AArch64::XZR)
11813 .addReg(AArch64::SP)
11814 .addReg(TargetReg)
11816 .setMIFlags(Flags);
11817
11818 // B.<Cond> LoopExit
11819 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::Bcc))
11821 .addMBB(ExitMBB)
11822 .setMIFlags(Flags);
11823
11824 // LDR XZR, [SP]
11825 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::LDRXui))
11826 .addDef(AArch64::XZR)
11827 .addReg(AArch64::SP)
11828 .addImm(0)
11832 Align(8)))
11833 .setMIFlags(Flags);
11834
11835 // B loop
11836 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::B))
11837 .addMBB(LoopTestMBB)
11838 .setMIFlags(Flags);
11839
11840 // LoopExit:
11841 // MOV SP, TargetReg
11842 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::ADDXri), AArch64::SP)
11843 .addReg(TargetReg)
11844 .addImm(0)
11846 .setMIFlags(Flags);
11847
11848 // LDR XZR, [SP]
11849 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::LDRXui))
11850 .addReg(AArch64::XZR, RegState::Define)
11851 .addReg(AArch64::SP)
11852 .addImm(0)
11853 .setMIFlags(Flags);
11854
11855 ExitMBB->splice(ExitMBB->end(), &MBB, std::next(MBBI), MBB.end());
11857
11858 LoopTestMBB->addSuccessor(ExitMBB);
11859 LoopTestMBB->addSuccessor(LoopBodyMBB);
11860 LoopBodyMBB->addSuccessor(LoopTestMBB);
11861 MBB.addSuccessor(LoopTestMBB);
11862
11863 // Update liveins.
11864 if (MF.getRegInfo().reservedRegsFrozen())
11865 fullyRecomputeLiveIns({ExitMBB, LoopBodyMBB, LoopTestMBB});
11866
11867 return ExitMBB->begin();
11868}
11869
11870namespace {
11871class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
11872 MachineFunction *MF;
11873 const TargetInstrInfo *TII;
11874 const TargetRegisterInfo *TRI;
11875 MachineRegisterInfo &MRI;
11876
11877 /// The block of the loop
11878 MachineBasicBlock *LoopBB;
11879 /// The conditional branch of the loop
11880 MachineInstr *CondBranch;
11881 /// The compare instruction for loop control
11882 MachineInstr *Comp;
11883 /// The number of the operand of the loop counter value in Comp
11884 unsigned CompCounterOprNum;
11885 /// The instruction that updates the loop counter value
11886 MachineInstr *Update;
11887 /// The number of the operand of the loop counter value in Update
11888 unsigned UpdateCounterOprNum;
11889 /// The initial value of the loop counter
11890 Register Init;
11891 /// True iff Update is a predecessor of Comp
11892 bool IsUpdatePriorComp;
11893
11894 /// The normalized condition used by createTripCountGreaterCondition()
11896
11897public:
11898 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11899 MachineInstr *Comp, unsigned CompCounterOprNum,
11900 MachineInstr *Update, unsigned UpdateCounterOprNum,
11901 Register Init, bool IsUpdatePriorComp,
11902 const SmallVectorImpl<MachineOperand> &Cond)
11903 : MF(Comp->getParent()->getParent()),
11904 TII(MF->getSubtarget().getInstrInfo()),
11905 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11906 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11907 CompCounterOprNum(CompCounterOprNum), Update(Update),
11908 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11909 IsUpdatePriorComp(IsUpdatePriorComp), Cond(Cond.begin(), Cond.end()) {}
11910
11911 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
11912 // Make the instructions for loop control be placed in stage 0.
11913 // The predecessors of Comp are considered by the caller.
11914 return MI == Comp;
11915 }
11916
11917 std::optional<bool> createTripCountGreaterCondition(
11918 int TC, MachineBasicBlock &MBB,
11919 SmallVectorImpl<MachineOperand> &CondParam) override {
11920 // A branch instruction will be inserted as "if (Cond) goto epilogue".
11921 // Cond is normalized for such use.
11922 // The predecessors of the branch are assumed to have already been inserted.
11923 CondParam = Cond;
11924 return {};
11925 }
11926
11927 void createRemainingIterationsGreaterCondition(
11928 int TC, MachineBasicBlock &MBB, SmallVectorImpl<MachineOperand> &Cond,
11929 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts) override;
11930
11931 void setPreheader(MachineBasicBlock *NewPreheader) override {}
11932
11933 void adjustTripCount(int TripCountAdjust) override {}
11934
11935 bool isMVEExpanderSupported() override { return true; }
11936};
11937} // namespace
11938
11939/// Clone an instruction from MI. The register of ReplaceOprNum-th operand
11940/// is replaced by ReplaceReg. The output register is newly created.
11941/// The other operands are unchanged from MI.
11942static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum,
11943 Register ReplaceReg, MachineBasicBlock &MBB,
11944 MachineBasicBlock::iterator InsertTo) {
11945 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
11946 const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
11947 MachineInstr *NewMI = MBB.getParent()->CloneMachineInstr(MI);
11948 Register Result = 0;
11949 for (unsigned I = 0; I < NewMI->getNumOperands(); ++I) {
11950 if (I == 0 && NewMI->getOperand(0).getReg().isVirtual()) {
11951 Result = MRI.createVirtualRegister(
11952 MRI.getRegClass(NewMI->getOperand(0).getReg()));
11953 NewMI->getOperand(I).setReg(Result);
11954 } else if (I == ReplaceOprNum) {
11955 MRI.constrainRegClass(ReplaceReg, TII->getRegClass(NewMI->getDesc(), I));
11956 NewMI->getOperand(I).setReg(ReplaceReg);
11957 }
11958 }
11959 MBB.insert(InsertTo, NewMI);
11960 return Result;
11961}
11962
11963void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
11966 // Create and accumulate conditions for next TC iterations.
11967 // Example:
11968 // SUBSXrr N, counter, implicit-def $nzcv # compare instruction for the last
11969 // # iteration of the kernel
11970 //
11971 // # insert the following instructions
11972 // cond = CSINCXr 0, 0, C, implicit $nzcv
11973 // counter = ADDXri counter, 1 # clone from this->Update
11974 // SUBSXrr n, counter, implicit-def $nzcv # clone from this->Comp
11975 // cond = CSINCXr cond, cond, C, implicit $nzcv
11976 // ... (repeat TC times)
11977 // SUBSXri cond, 0, implicit-def $nzcv
11978
11979 assert(CondBranch->getOpcode() == AArch64::Bcc);
11980 // CondCode to exit the loop
11982 (AArch64CC::CondCode)CondBranch->getOperand(0).getImm();
11983 if (CondBranch->getOperand(1).getMBB() == LoopBB)
11985
11986 // Accumulate conditions to exit the loop
11987 Register AccCond = AArch64::XZR;
11988
11989 // If CC holds, CurCond+1 is returned; otherwise CurCond is returned.
11990 auto AccumulateCond = [&](Register CurCond,
11992 Register NewCond = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
11993 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::CSINCXr))
11994 .addReg(NewCond, RegState::Define)
11995 .addReg(CurCond)
11996 .addReg(CurCond)
11998 return NewCond;
11999 };
12000
12001 if (!LastStage0Insts.empty() && LastStage0Insts[Comp]->getParent() == &MBB) {
12002 // Update and Comp for I==0 are already exists in MBB
12003 // (MBB is an unrolled kernel)
12004 Register Counter;
12005 for (int I = 0; I <= TC; ++I) {
12006 Register NextCounter;
12007 if (I != 0)
12008 NextCounter =
12009 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12010
12011 AccCond = AccumulateCond(AccCond, CC);
12012
12013 if (I != TC) {
12014 if (I == 0) {
12015 if (Update != Comp && IsUpdatePriorComp) {
12016 Counter =
12017 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12018 NextCounter = cloneInstr(Update, UpdateCounterOprNum, Counter, MBB,
12019 MBB.end());
12020 } else {
12021 // can use already calculated value
12022 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
12023 }
12024 } else if (Update != Comp) {
12025 NextCounter =
12026 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12027 }
12028 }
12029 Counter = NextCounter;
12030 }
12031 } else {
12032 Register Counter;
12033 if (LastStage0Insts.empty()) {
12034 // use initial counter value (testing if the trip count is sufficient to
12035 // be executed by pipelined code)
12036 Counter = Init;
12037 if (IsUpdatePriorComp)
12038 Counter =
12039 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12040 } else {
12041 // MBB is an epilogue block. LastStage0Insts[Comp] is in the kernel block.
12042 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12043 }
12044
12045 for (int I = 0; I <= TC; ++I) {
12046 Register NextCounter;
12047 NextCounter =
12048 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12049 AccCond = AccumulateCond(AccCond, CC);
12050 if (I != TC && Update != Comp)
12051 NextCounter =
12052 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12053 Counter = NextCounter;
12054 }
12055 }
12056
12057 // If AccCond == 0, the remainder is greater than TC.
12058 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::SUBSXri))
12059 .addReg(AArch64::XZR, RegState::Define | RegState::Dead)
12060 .addReg(AccCond)
12061 .addImm(0)
12062 .addImm(0);
12063 Cond.clear();
12065}
12066
12067static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB,
12068 Register &RegMBB, Register &RegOther) {
12069 assert(Phi.getNumOperands() == 5);
12070 if (Phi.getOperand(2).getMBB() == MBB) {
12071 RegMBB = Phi.getOperand(1).getReg();
12072 RegOther = Phi.getOperand(3).getReg();
12073 } else {
12074 assert(Phi.getOperand(4).getMBB() == MBB);
12075 RegMBB = Phi.getOperand(3).getReg();
12076 RegOther = Phi.getOperand(1).getReg();
12077 }
12078}
12079
12081 if (!Reg.isVirtual())
12082 return false;
12083 const MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
12084 return MRI.getDefBlock(Reg) != BB;
12085}
12086
12087/// If Reg is an induction variable, return true and set some parameters
12088static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB,
12089 MachineInstr *&UpdateInst,
12090 unsigned &UpdateCounterOprNum, Register &InitReg,
12091 bool &IsUpdatePriorComp) {
12092 // Example:
12093 //
12094 // Preheader:
12095 // InitReg = ...
12096 // LoopBB:
12097 // Reg0 = PHI (InitReg, Preheader), (Reg1, LoopBB)
12098 // Reg = COPY Reg0 ; COPY is ignored.
12099 // Reg1 = ADD Reg, #1; UpdateInst. Incremented by a loop invariant value.
12100 // ; Reg is the value calculated in the previous
12101 // ; iteration, so IsUpdatePriorComp == false.
12102
12103 if (LoopBB->pred_size() != 2)
12104 return false;
12105 if (!Reg.isVirtual())
12106 return false;
12107 const MachineRegisterInfo &MRI = LoopBB->getParent()->getRegInfo();
12108 UpdateInst = nullptr;
12109 UpdateCounterOprNum = 0;
12110 InitReg = 0;
12111 IsUpdatePriorComp = true;
12112 Register CurReg = Reg;
12113 while (true) {
12114 MachineInstr *Def = MRI.getVRegDef(CurReg);
12115 if (Def->getParent() != LoopBB)
12116 return false;
12117 if (Def->isCopy()) {
12118 // Ignore copy instructions unless they contain subregisters
12119 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
12120 return false;
12121 CurReg = Def->getOperand(1).getReg();
12122 } else if (Def->isPHI()) {
12123 if (InitReg != 0)
12124 return false;
12125 if (!UpdateInst)
12126 IsUpdatePriorComp = false;
12127 extractPhiReg(*Def, LoopBB, CurReg, InitReg);
12128 } else {
12129 if (UpdateInst)
12130 return false;
12131 switch (Def->getOpcode()) {
12132 case AArch64::ADDSXri:
12133 case AArch64::ADDSWri:
12134 case AArch64::SUBSXri:
12135 case AArch64::SUBSWri:
12136 case AArch64::ADDXri:
12137 case AArch64::ADDWri:
12138 case AArch64::SUBXri:
12139 case AArch64::SUBWri:
12140 UpdateInst = Def;
12141 UpdateCounterOprNum = 1;
12142 break;
12143 case AArch64::ADDSXrr:
12144 case AArch64::ADDSWrr:
12145 case AArch64::SUBSXrr:
12146 case AArch64::SUBSWrr:
12147 case AArch64::ADDXrr:
12148 case AArch64::ADDWrr:
12149 case AArch64::SUBXrr:
12150 case AArch64::SUBWrr:
12151 UpdateInst = Def;
12152 if (isDefinedOutside(Def->getOperand(2).getReg(), LoopBB))
12153 UpdateCounterOprNum = 1;
12154 else if (isDefinedOutside(Def->getOperand(1).getReg(), LoopBB))
12155 UpdateCounterOprNum = 2;
12156 else
12157 return false;
12158 break;
12159 default:
12160 return false;
12161 }
12162 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
12163 }
12164
12165 if (!CurReg.isVirtual())
12166 return false;
12167 if (Reg == CurReg)
12168 break;
12169 }
12170
12171 if (!UpdateInst)
12172 return false;
12173
12174 return true;
12175}
12176
12177std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
12179 // Accept loops that meet the following conditions
12180 // * The conditional branch is BCC
12181 // * The compare instruction is ADDS/SUBS/WHILEXX
12182 // * One operand of the compare is an induction variable and the other is a
12183 // loop invariant value
12184 // * The induction variable is incremented/decremented by a single instruction
12185 // * Does not contain CALL or instructions which have unmodeled side effects
12186
12187 for (MachineInstr &MI : *LoopBB)
12188 if (MI.isCall() || MI.hasUnmodeledSideEffects())
12189 // This instruction may use NZCV, which interferes with the instruction to
12190 // be inserted for loop control.
12191 return nullptr;
12192
12193 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
12195 if (analyzeBranch(*LoopBB, TBB, FBB, Cond))
12196 return nullptr;
12197
12198 // Infinite loops are not supported
12199 if (TBB == LoopBB && FBB == LoopBB)
12200 return nullptr;
12201
12202 // Must be conditional branch
12203 if (TBB != LoopBB && FBB == nullptr)
12204 return nullptr;
12205
12206 assert((TBB == LoopBB || FBB == LoopBB) &&
12207 "The Loop must be a single-basic-block loop");
12208
12209 MachineInstr *CondBranch = &*LoopBB->getFirstTerminator();
12211
12212 if (CondBranch->getOpcode() != AArch64::Bcc)
12213 return nullptr;
12214
12215 // Normalization for createTripCountGreaterCondition()
12216 if (TBB == LoopBB)
12218
12219 MachineInstr *Comp = nullptr;
12220 unsigned CompCounterOprNum = 0;
12221 for (MachineInstr &MI : reverse(*LoopBB)) {
12222 if (MI.modifiesRegister(AArch64::NZCV, &TRI)) {
12223 // Guarantee that the compare is SUBS/ADDS/WHILEXX and that one of the
12224 // operands is a loop invariant value
12225
12226 switch (MI.getOpcode()) {
12227 case AArch64::SUBSXri:
12228 case AArch64::SUBSWri:
12229 case AArch64::ADDSXri:
12230 case AArch64::ADDSWri:
12231 Comp = &MI;
12232 CompCounterOprNum = 1;
12233 break;
12234 case AArch64::ADDSWrr:
12235 case AArch64::ADDSXrr:
12236 case AArch64::SUBSWrr:
12237 case AArch64::SUBSXrr:
12238 Comp = &MI;
12239 break;
12240 default:
12241 if (isWhileOpcode(MI.getOpcode())) {
12242 Comp = &MI;
12243 break;
12244 }
12245 return nullptr;
12246 }
12247
12248 if (CompCounterOprNum == 0) {
12249 if (isDefinedOutside(Comp->getOperand(1).getReg(), LoopBB))
12250 CompCounterOprNum = 2;
12251 else if (isDefinedOutside(Comp->getOperand(2).getReg(), LoopBB))
12252 CompCounterOprNum = 1;
12253 else
12254 return nullptr;
12255 }
12256 break;
12257 }
12258 }
12259 if (!Comp)
12260 return nullptr;
12261
12262 MachineInstr *Update = nullptr;
12263 Register Init;
12264 bool IsUpdatePriorComp;
12265 unsigned UpdateCounterOprNum;
12266 if (!getIndVarInfo(Comp->getOperand(CompCounterOprNum).getReg(), LoopBB,
12267 Update, UpdateCounterOprNum, Init, IsUpdatePriorComp))
12268 return nullptr;
12269
12270 return std::make_unique<AArch64PipelinerLoopInfo>(
12271 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
12272 Init, IsUpdatePriorComp, Cond);
12273}
12274
12275/// verifyInstruction - Perform target specific instruction verification.
12276bool AArch64InstrInfo::verifyInstruction(const MachineInstr &MI,
12277 StringRef &ErrInfo) const {
12278 // Verify that immediate offsets on load/store instructions are within range.
12279 // Stack objects with an FI operand are excluded as they can be fixed up
12280 // during PEI.
12281 TypeSize Scale(0U, false), Width(0U, false);
12282 int64_t MinOffset, MaxOffset;
12283 if (getMemOpInfo(MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
12284 unsigned ImmIdx = getLoadStoreImmIdx(MI.getOpcode());
12285 if (MI.getOperand(ImmIdx).isImm() && !MI.getOperand(ImmIdx - 1).isFI()) {
12286 int64_t Imm = MI.getOperand(ImmIdx).getImm();
12287 if (Imm < MinOffset || Imm > MaxOffset) {
12288 ErrInfo = "Unexpected immediate on load/store instruction";
12289 return false;
12290 }
12291 }
12292 }
12293
12294 const MCInstrDesc &MCID = MI.getDesc();
12295 for (unsigned Op = 0; Op < MCID.getNumOperands(); Op++) {
12296 const MachineOperand &MO = MI.getOperand(Op);
12297 switch (MCID.operands()[Op].OperandType) {
12299 if (!MO.isImm() || MO.getImm() != 0) {
12300 ErrInfo = "OPERAND_IMPLICIT_IMM_0 should be 0";
12301 return false;
12302 }
12303 break;
12305 if (!MO.isImm() ||
12307 (AArch64_AM::getShiftValue(MO.getImm()) != 8 &&
12308 AArch64_AM::getShiftValue(MO.getImm()) != 16)) {
12309 ErrInfo = "OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
12310 return false;
12311 }
12312 break;
12314 if (!MO.isImm() || (MO.getImm() != 0 && MO.getImm() != 1)) {
12315 ErrInfo = "OPERAND_IMM_UINT1 should be 0 or 1";
12316 return false;
12317 }
12318 break;
12320 if (!MO.isImm() || MO.getImm() <= 0 || MO.getImm() > 16) {
12321 ErrInfo = "OPERAND_IMM_UINT4plus1 should be in the range 1 to 16";
12322 return false;
12323 }
12324 break;
12326 if (!MO.isImm() || !isUInt<5>(MO.getImm())) {
12327 ErrInfo = "OPERAND_IMM_UINT5 should be in the range 0 to 31";
12328 return false;
12329 }
12330 break;
12332 if (!MO.isImm() || !isUInt<8>(MO.getImm())) {
12333 ErrInfo = "OPERAND_IMM_UINT8 should be in the range 0 to 255";
12334 return false;
12335 }
12336 break;
12337 default:
12338 break;
12339 }
12340 }
12341 return true;
12342}
12343
12344#define GET_INSTRINFO_HELPERS
12345#define GET_INSTRMAP_INFO
12346#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!")
unsigned Imm
unsigned uint64_t
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.