LLVM 24.0.0git
AArch64InstrInfo.cpp
Go to the documentation of this file.
1//===- AArch64InstrInfo.cpp - AArch64 Instruction Information -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the AArch64 implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AArch64InstrInfo.h"
14#include "AArch64ExpandImm.h"
16#include "AArch64PointerAuth.h"
17#include "AArch64Subtarget.h"
22#include "llvm/ADT/ArrayRef.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SmallSet.h"
26#include "llvm/ADT/Statistic.h"
45#include "llvm/IR/DebugLoc.h"
46#include "llvm/IR/GlobalValue.h"
47#include "llvm/IR/Module.h"
48#include "llvm/MC/MCAsmInfo.h"
49#include "llvm/MC/MCInst.h"
51#include "llvm/MC/MCInstrDesc.h"
56#include "llvm/Support/LEB128.h"
60#include <cassert>
61#include <cstdint>
62#include <iterator>
63#include <utility>
64
65using namespace llvm;
66
67#define GET_INSTRINFO_CTOR_DTOR
68#include "AArch64GenInstrInfo.inc"
69
70#define DEBUG_TYPE "AArch64InstrInfo"
71
72STATISTIC(NumCopyInstrs, "Number of COPY instructions expanded");
73STATISTIC(NumZCRegMoveInstrsGPR, "Number of zero-cycle GPR register move "
74 "instructions expanded from canonical COPY");
75STATISTIC(NumZCRegMoveInstrsFPR, "Number of zero-cycle FPR register move "
76 "instructions expanded from canonical COPY");
77STATISTIC(NumZCZeroingInstrsGPR, "Number of zero-cycle GPR zeroing "
78 "instructions expanded from canonical COPY");
79// NumZCZeroingInstrsFPR is counted at AArch64AsmPrinter
80
82 CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9),
83 cl::desc("Restrict range of CB instructions (DEBUG)"));
84
86 "aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
87 cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
88
90 "aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
91 cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
92
94 BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
95 cl::desc("Restrict range of Bcc instructions (DEBUG)"));
96
98 BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26),
99 cl::desc("Restrict range of B instructions (DEBUG)"));
100
102 "aarch64-search-limit", cl::Hidden, cl::init(2048),
103 cl::desc("Restrict range of instructions to search for the "
104 "machine-combiner gather pattern optimization"));
105
107 "aarch64-outliner-compact-unwind-frame", cl::Hidden, cl::init(true),
108 cl::desc("Use a frame record for Mach-O non-leaf outlined functions"));
109
111 : AArch64GenInstrInfo(STI, RI, AArch64::ADJCALLSTACKDOWN,
112 AArch64::ADJCALLSTACKUP, AArch64::CATCHRET),
113 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
114
115/// Return the maximum number of bytes of code the specified instruction may be
116/// after LFI rewriting. If the instruction is not rewritten, std::nullopt is
117/// returned (use default sizing).
118///
119/// NOTE: the size estimates here must be kept in sync with the rewrites in
120/// AArch64MCLFIRewriter.cpp. Sizes may be overestimates of the rewritten
121/// instruction sequences.
122static std::optional<unsigned> getLFIInstSizeInBytes(const MachineInstr &MI) {
123 switch (MI.getOpcode()) {
124 case AArch64::SVC:
125 // SVC expands to 4 instructions.
126 return 16;
127 case AArch64::BR:
128 case AArch64::BLR:
129 // Indirect branches/calls expand to 2 instructions (guard + br/blr).
130 return 8;
131 case AArch64::RET:
132 // RET through LR is not rewritten, but RET through another register
133 // expands to 2 instructions (guard + ret).
134 if (MI.getOperand(0).getReg() != AArch64::LR)
135 return 8;
136 return 4;
137 case AArch64::RETAA:
138 case AArch64::RETAB:
139 // Authenticated returns expand to 3 instructions (authenticate + guard +
140 // ret).
141 return 12;
142 case AArch64::BRAA:
143 case AArch64::BRAAZ:
144 case AArch64::BRAB:
145 case AArch64::BRABZ:
146 case AArch64::BLRAA:
147 case AArch64::BLRAAZ:
148 case AArch64::BLRAB:
149 case AArch64::BLRABZ:
150 // Authenticated branches/calls expand to 3 instructions (authenticate +
151 // guard + branch).
152 return 12;
153 case AArch64::AUTIASP:
154 case AArch64::AUTIBSP:
155 case AArch64::AUTIAZ:
156 case AArch64::AUTIBZ:
157 case AArch64::XPACLRI:
158 // Authenticating LR expands to the instruction plus a deferred LR guard.
159 return 8;
160 case AArch64::SYSxt:
161 // VA-based DC/IC ops (op1=3, Cn=7, op2=1) expand to 2 instructions.
162 if (MI.getOperand(0).getImm() == 3 && MI.getOperand(1).getImm() == 7 &&
163 MI.getOperand(3).getImm() == 1)
164 return 8;
165 return std::nullopt;
166 default:
167 break;
168 }
169
170 // Detect instructions that explicitly define SP or LR.
171 bool ModifiesLR = false;
172 bool ModifiesSP = false;
173 for (const MachineOperand &MO : MI.defs()) {
174 if (!MO.isReg())
175 continue;
176 if (MO.getReg() == AArch64::LR)
177 ModifiesLR = true;
178 else if (MO.getReg() == AArch64::SP)
179 ModifiesSP = true;
180 }
181
182 // Memory accesses expand to a base-register guard plus the rewritten access
183 // (8 bytes), with an extra base-register update for pre/post-index forms (12
184 // bytes total). If the access also defines LR, an LR mask is appended (+4
185 // bytes). Depending on additional optimizations that the rewriter performs,
186 // this may be an overestimate.
187 if (MI.mayLoadOrStore()) {
188 unsigned Size = isLFIPrePostMemAccess(MI.getOpcode()) ? 12 : 8;
189 if (ModifiesLR)
190 Size += 4;
191 return Size;
192 }
193
194 // Non memory operations that modify LR or SP expand to 2 instructions.
195 if (ModifiesSP || ModifiesLR)
196 return 8;
197
198 // Default case: instructions that don't cause expansion.
199 // - TP accesses in LFI are a single load/store, so no expansion.
200 // - All remaining instructions are not rewritten.
201 return std::nullopt;
202}
203
204/// GetInstSize - Return the number of bytes of code the specified
205/// instruction may be. This returns the maximum number of bytes.
207 const MCInstrDesc &Desc = MI.getDesc();
208 if (!Desc.isPseudo() && !Subtarget.isLFI()) {
209 assert(Desc.getSize() == 4 && "Unexpected instruction size");
210 return 4;
211 }
212
213 const MachineBasicBlock &MBB = *MI.getParent();
214 const MachineFunction *MF = MBB.getParent();
215 const Function &F = MF->getFunction();
216 const MCAsmInfo &MAI = MF->getTarget().getMCAsmInfo();
217
218 {
219 auto Op = MI.getOpcode();
220 if (Op == AArch64::INLINEASM || Op == AArch64::INLINEASM_BR)
221 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
222 }
223
224 // Meta-instructions emit no code.
225 if (MI.isMetaInstruction())
226 return 0;
227
228 // FIXME: We currently only handle pseudoinstructions that don't get expanded
229 // before the assembly printer.
230 unsigned NumBytes = 0;
231
232 // LFI rewriter expansions that supersede normal sizing.
233 const auto &STI = MF->getSubtarget<AArch64Subtarget>();
234 if (STI.isLFI())
235 if (auto Size = getLFIInstSizeInBytes(MI))
236 return *Size;
237
238 if (!MI.isBundle() && isTailCallReturnInst(MI)) {
239 NumBytes = Desc.getSize() ? Desc.getSize() : 4;
240
241 const auto *MFI = MF->getInfo<AArch64FunctionInfo>();
242 if (!MFI->shouldSignReturnAddress(*MF))
243 return NumBytes;
244
245 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
246 NumBytes += AArch64PAuth::getCheckerSizeInBytes(Method);
247 return NumBytes;
248 }
249
250 // Size should be preferably set in
251 // llvm/lib/Target/AArch64/AArch64InstrInfo.td (default case).
252 // Specific cases handle instructions of variable sizes
253 switch (Desc.getOpcode()) {
254 default:
255 if (Desc.getSize())
256 return Desc.getSize();
257
258 // Anything not explicitly designated otherwise (i.e. pseudo-instructions
259 // with fixed constant size but not specified in .td file) is a normal
260 // 4-byte insn.
261 NumBytes = 4;
262 break;
263 case TargetOpcode::STACKMAP:
264 // The upper bound for a stackmap intrinsic is the full length of its shadow
265 NumBytes = StackMapOpers(&MI).getNumPatchBytes();
266 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
267 break;
268 case TargetOpcode::PATCHPOINT:
269 // The size of the patchpoint intrinsic is the number of bytes requested
270 NumBytes = PatchPointOpers(&MI).getNumPatchBytes();
271 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
272 break;
273 case TargetOpcode::STATEPOINT:
274 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
275 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
276 // No patch bytes means a normal call inst is emitted
277 if (NumBytes == 0)
278 NumBytes = 4;
279 break;
280 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
281 // If `patchable-function-entry` is set, PATCHABLE_FUNCTION_ENTER
282 // instructions are expanded to the specified number of NOPs. Otherwise,
283 // they are expanded to 36-byte XRay sleds.
284 NumBytes =
285 F.getFnAttributeAsParsedInteger("patchable-function-entry", 9) * 4;
286 break;
287 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
288 case TargetOpcode::PATCHABLE_TAIL_CALL:
289 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
290 // An XRay sled can be 4 bytes of alignment plus a 32-byte block.
291 NumBytes = 36;
292 break;
293 case TargetOpcode::PATCHABLE_EVENT_CALL:
294 // EVENT_CALL XRay sleds are exactly 6 instructions long (no alignment).
295 NumBytes = 24;
296 break;
297
298 case AArch64::SPACE:
299 NumBytes = MI.getOperand(1).getImm();
300 break;
301 case AArch64::MOVaddr:
302 case AArch64::MOVaddrJT:
303 case AArch64::MOVaddrCP:
304 case AArch64::MOVaddrBA:
305 case AArch64::MOVaddrTLS:
306 case AArch64::MOVaddrEXT: {
307 // Use the same logic as the pseudo expansion to count instructions.
310 MI.getOperand(1).getTargetFlags(),
311 Subtarget.isTargetMachO(), Insn);
312 NumBytes = Insn.size() * 4;
313 break;
314 }
315
316 case AArch64::MOVi32imm:
317 case AArch64::MOVi64imm: {
318 // Use the same logic as the pseudo expansion to count instructions.
319 unsigned BitSize = Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
321 AArch64_IMM::expandMOVImm(MI.getOperand(1).getImm(), BitSize, Insn);
322 NumBytes = Insn.size() * 4;
323 break;
324 }
325
326 case TargetOpcode::BUNDLE:
327 NumBytes = getInstBundleSize(MI);
328 break;
329 }
330
331 return NumBytes;
332}
333
336 // Block ends with fall-through condbranch.
337 switch (LastInst->getOpcode()) {
338 default:
339 llvm_unreachable("Unknown branch instruction?");
340 case AArch64::Bcc:
341 Target = LastInst->getOperand(1).getMBB();
342 Cond.push_back(LastInst->getOperand(0));
343 break;
344 case AArch64::CBZW:
345 case AArch64::CBZX:
346 case AArch64::CBNZW:
347 case AArch64::CBNZX:
348 Target = LastInst->getOperand(1).getMBB();
349 Cond.push_back(MachineOperand::CreateImm(-1));
350 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
351 Cond.push_back(LastInst->getOperand(0));
352 break;
353 case AArch64::TBZW:
354 case AArch64::TBZX:
355 case AArch64::TBNZW:
356 case AArch64::TBNZX:
357 Target = LastInst->getOperand(2).getMBB();
358 Cond.push_back(MachineOperand::CreateImm(-1));
359 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
360 Cond.push_back(LastInst->getOperand(0));
361 Cond.push_back(LastInst->getOperand(1));
362 break;
363 case AArch64::CBWPri:
364 case AArch64::CBXPri:
365 case AArch64::CBWPrr:
366 case AArch64::CBXPrr:
367 Target = LastInst->getOperand(3).getMBB();
368 Cond.push_back(MachineOperand::CreateImm(-1));
369 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
370 Cond.push_back(LastInst->getOperand(0));
371 Cond.push_back(LastInst->getOperand(1));
372 Cond.push_back(LastInst->getOperand(2));
373 break;
374 case AArch64::CBBAssertExt:
375 case AArch64::CBHAssertExt:
376 Target = LastInst->getOperand(3).getMBB();
377 Cond.push_back(MachineOperand::CreateImm(-1)); // -1
378 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); // Opc
379 Cond.push_back(LastInst->getOperand(0)); // Cond
380 Cond.push_back(LastInst->getOperand(1)); // Op0
381 Cond.push_back(LastInst->getOperand(2)); // Op1
382 Cond.push_back(LastInst->getOperand(4)); // Ext0
383 Cond.push_back(LastInst->getOperand(5)); // Ext1
384 break;
385 }
386}
387
388static unsigned getBranchDisplacementBits(unsigned Opc) {
389 switch (Opc) {
390 default:
391 llvm_unreachable("unexpected opcode!");
392 case AArch64::B:
393 return BDisplacementBits;
394 case AArch64::TBNZW:
395 case AArch64::TBZW:
396 case AArch64::TBNZX:
397 case AArch64::TBZX:
398 return TBZDisplacementBits;
399 case AArch64::CBNZW:
400 case AArch64::CBZW:
401 case AArch64::CBNZX:
402 case AArch64::CBZX:
403 return CBZDisplacementBits;
404 case AArch64::Bcc:
405 return BCCDisplacementBits;
406 case AArch64::CBWPri:
407 case AArch64::CBXPri:
408 case AArch64::CBBAssertExt:
409 case AArch64::CBHAssertExt:
410 case AArch64::CBWPrr:
411 case AArch64::CBXPrr:
412 return CBDisplacementBits;
413 }
414}
415
417 int64_t BrOffset) const {
418 unsigned Bits = getBranchDisplacementBits(BranchOp);
419 assert(Bits >= 3 && "max branch displacement must be enough to jump"
420 "over conditional branch expansion");
421 return isIntN(Bits, BrOffset / 4);
422}
423
426 switch (MI.getOpcode()) {
427 default:
428 llvm_unreachable("unexpected opcode!");
429 case AArch64::B:
430 return MI.getOperand(0).getMBB();
431 case AArch64::TBZW:
432 case AArch64::TBNZW:
433 case AArch64::TBZX:
434 case AArch64::TBNZX:
435 return MI.getOperand(2).getMBB();
436 case AArch64::CBZW:
437 case AArch64::CBNZW:
438 case AArch64::CBZX:
439 case AArch64::CBNZX:
440 case AArch64::Bcc:
441 return MI.getOperand(1).getMBB();
442 case AArch64::CBWPri:
443 case AArch64::CBXPri:
444 case AArch64::CBBAssertExt:
445 case AArch64::CBHAssertExt:
446 case AArch64::CBWPrr:
447 case AArch64::CBXPrr:
448 return MI.getOperand(3).getMBB();
449 }
450}
451
453 MachineBasicBlock &NewDestBB,
454 MachineBasicBlock &RestoreBB,
455 const DebugLoc &DL,
456 int64_t BrOffset,
457 RegScavenger *RS) const {
458 assert(RS && "RegScavenger required for long branching");
459 assert(MBB.empty() &&
460 "new block should be inserted for expanding unconditional branch");
461 assert(MBB.pred_size() == 1);
462 assert(RestoreBB.empty() &&
463 "restore block should be inserted for restoring clobbered registers");
464
465 auto buildIndirectBranch = [&](Register Reg, MachineBasicBlock &DestBB) {
466 // Offsets outside of the signed 33-bit range are not supported for ADRP +
467 // ADD.
468 if (!isInt<33>(BrOffset))
470 "Branch offsets outside of the signed 33-bit range not supported");
471
472 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADRP), Reg)
473 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGE);
474 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADDXri), Reg)
475 .addReg(Reg)
476 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGEOFF | AArch64II::MO_NC)
477 .addImm(0);
478 BuildMI(MBB, MBB.end(), DL, get(AArch64::BR)).addReg(Reg);
479 };
480
481 RS->enterBasicBlockEnd(MBB);
482 // If X16 is unused, we can rely on the linker to insert a range extension
483 // thunk if NewDestBB is out of range of a single B instruction.
484 constexpr Register Reg = AArch64::X16;
485 if (!RS->isRegUsed(Reg)) {
486 insertUnconditionalBranch(MBB, &NewDestBB, DL);
487 RS->setRegUsed(Reg);
488 return;
489 }
490
491 // In a cold block without BTI, insert the indirect branch if a register is
492 // free. Skip this if BTI is enabled to avoid inserting a BTI at the target,
493 // prioritizing a dynamic cost in cold code over a static cost in hot code.
494 AArch64FunctionInfo *AFI = MBB.getParent()->getInfo<AArch64FunctionInfo>();
495 bool HasBTI = AFI && AFI->branchTargetEnforcement();
496 if (MBB.getSectionID() == MBBSectionID::ColdSectionID && !HasBTI) {
497 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
498 if (Scavenged != AArch64::NoRegister) {
499 buildIndirectBranch(Scavenged, NewDestBB);
500 RS->setRegUsed(Scavenged);
501 return;
502 }
503 }
504
505 // Note: Spilling X16 briefly moves the stack pointer, making it incompatible
506 // with red zones.
507 if (!AFI || AFI->hasRedZone().value_or(true))
509 "Unable to insert indirect branch inside function that has red zone");
510
511 // Otherwise, spill X16 and defer range extension to the linker.
512 BuildMI(MBB, MBB.end(), DL, get(AArch64::STRXpre))
513 .addReg(AArch64::SP, RegState::Define)
514 .addReg(Reg)
515 .addReg(AArch64::SP)
516 .addImm(-16);
517
518 BuildMI(MBB, MBB.end(), DL, get(AArch64::B)).addMBB(&RestoreBB);
519
520 BuildMI(RestoreBB, RestoreBB.end(), DL, get(AArch64::LDRXpost))
521 .addReg(AArch64::SP, RegState::Define)
523 .addReg(AArch64::SP)
524 .addImm(16);
525}
526
527// Branch analysis.
530 MachineBasicBlock *&FBB,
532 bool AllowModify) const {
533 // If the block has no terminators, it just falls into the block after it.
534 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
535 if (I == MBB.end())
536 return false;
537
538 // Skip over SpeculationBarrierEndBB terminators
539 if (I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
540 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
541 --I;
542 }
543
544 if (!isUnpredicatedTerminator(*I))
545 return false;
546
547 // Get the last instruction in the block.
548 MachineInstr *LastInst = &*I;
549
550 // If there is only one terminator instruction, process it.
551 unsigned LastOpc = LastInst->getOpcode();
552 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
553 if (isUncondBranchOpcode(LastOpc)) {
554 TBB = LastInst->getOperand(0).getMBB();
555 return false;
556 }
557 if (isCondBranchOpcode(LastOpc)) {
558 // Block ends with fall-through condbranch.
559 parseCondBranch(LastInst, TBB, Cond);
560 return false;
561 }
562 return true; // Can't handle indirect branch.
563 }
564
565 // Get the instruction before it if it is a terminator.
566 MachineInstr *SecondLastInst = &*I;
567 unsigned SecondLastOpc = SecondLastInst->getOpcode();
568
569 // If AllowModify is true and the block ends with two or more unconditional
570 // branches, delete all but the first unconditional branch.
571 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
572 while (isUncondBranchOpcode(SecondLastOpc)) {
573 LastInst->eraseFromParent();
574 LastInst = SecondLastInst;
575 LastOpc = LastInst->getOpcode();
576 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
577 // Return now the only terminator is an unconditional branch.
578 TBB = LastInst->getOperand(0).getMBB();
579 return false;
580 }
581 SecondLastInst = &*I;
582 SecondLastOpc = SecondLastInst->getOpcode();
583 }
584 }
585
586 // If we're allowed to modify and the block ends in a unconditional branch
587 // which could simply fallthrough, remove the branch. (Note: This case only
588 // matters when we can't understand the whole sequence, otherwise it's also
589 // handled by BranchFolding.cpp.)
590 if (AllowModify && isUncondBranchOpcode(LastOpc) &&
591 MBB.isLayoutSuccessor(getBranchDestBlock(*LastInst))) {
592 LastInst->eraseFromParent();
593 LastInst = SecondLastInst;
594 LastOpc = LastInst->getOpcode();
595 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
596 assert(!isUncondBranchOpcode(LastOpc) &&
597 "unreachable unconditional branches removed above");
598
599 if (isCondBranchOpcode(LastOpc)) {
600 // Block ends with fall-through condbranch.
601 parseCondBranch(LastInst, TBB, Cond);
602 return false;
603 }
604 return true; // Can't handle indirect branch.
605 }
606 SecondLastInst = &*I;
607 SecondLastOpc = SecondLastInst->getOpcode();
608 }
609
610 // If there are three terminators, we don't know what sort of block this is.
611 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
612 return true;
613
614 // If the block ends with a B and a Bcc, handle it.
615 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
616 parseCondBranch(SecondLastInst, TBB, Cond);
617 FBB = LastInst->getOperand(0).getMBB();
618 return false;
619 }
620
621 // If the block ends with two unconditional branches, handle it. The second
622 // one is not executed, so remove it.
623 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
624 TBB = SecondLastInst->getOperand(0).getMBB();
625 I = LastInst;
626 if (AllowModify)
627 I->eraseFromParent();
628 return false;
629 }
630
631 // ...likewise if it ends with an indirect branch followed by an unconditional
632 // branch.
633 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
634 I = LastInst;
635 if (AllowModify)
636 I->eraseFromParent();
637 return true;
638 }
639
640 // Otherwise, can't handle this.
641 return true;
642}
643
645 MachineBranchPredicate &MBP,
646 bool AllowModify) const {
647 // Use analyzeBranch to validate the branch pattern.
648 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
650 if (analyzeBranch(MBB, TBB, FBB, Cond, AllowModify))
651 return true;
652
653 // analyzeBranch returns success with empty Cond for unconditional branches.
654 if (Cond.empty())
655 return true;
656
657 MBP.TrueDest = TBB;
658 assert(MBP.TrueDest && "expected!");
659 MBP.FalseDest = FBB ? FBB : MBB.getNextNode();
660
661 MBP.ConditionDef = nullptr;
662 MBP.SingleUseCondition = false;
663
664 // Find the conditional branch. After analyzeBranch succeeds with non-empty
665 // Cond, there's exactly one conditional branch - either last (fallthrough)
666 // or second-to-last (followed by unconditional B).
667 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
668 if (I == MBB.end())
669 return true;
670
671 if (isUncondBranchOpcode(I->getOpcode())) {
672 if (I == MBB.begin())
673 return true;
674 --I;
675 }
676
677 MachineInstr *CondBranch = &*I;
678 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
679
680 switch (CondBranch->getOpcode()) {
681 default:
682 return true;
683
684 case AArch64::Bcc:
685 // Bcc takes the NZCV flag as the operand to branch on, walk up the
686 // instruction stream to find the last instruction to define NZCV.
688 if (MI.modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
689 MBP.ConditionDef = &MI;
690 break;
691 }
692 }
693 return false;
694
695 case AArch64::CBZW:
696 case AArch64::CBZX:
697 case AArch64::CBNZW:
698 case AArch64::CBNZX: {
699 MBP.LHS = CondBranch->getOperand(0);
700 MBP.RHS = MachineOperand::CreateImm(0);
701 unsigned Opc = CondBranch->getOpcode();
702 MBP.Predicate = (Opc == AArch64::CBNZX || Opc == AArch64::CBNZW)
703 ? MachineBranchPredicate::PRED_NE
704 : MachineBranchPredicate::PRED_EQ;
705 Register CondReg = MBP.LHS.getReg();
706 if (CondReg.isVirtual())
707 MBP.ConditionDef = MRI.getVRegDef(CondReg);
708 return false;
709 }
710
711 case AArch64::TBZW:
712 case AArch64::TBZX:
713 case AArch64::TBNZW:
714 case AArch64::TBNZX: {
715 Register CondReg = CondBranch->getOperand(0).getReg();
716 if (CondReg.isVirtual())
717 MBP.ConditionDef = MRI.getVRegDef(CondReg);
718 return false;
719 }
720 }
721}
722
725 if (Cond[0].getImm() != -1) {
726 // Regular Bcc
727 AArch64CC::CondCode CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
729 } else {
730 // Folded compare-and-branch
731 switch (Cond[1].getImm()) {
732 default:
733 llvm_unreachable("Unknown conditional branch!");
734 case AArch64::CBZW:
735 Cond[1].setImm(AArch64::CBNZW);
736 break;
737 case AArch64::CBNZW:
738 Cond[1].setImm(AArch64::CBZW);
739 break;
740 case AArch64::CBZX:
741 Cond[1].setImm(AArch64::CBNZX);
742 break;
743 case AArch64::CBNZX:
744 Cond[1].setImm(AArch64::CBZX);
745 break;
746 case AArch64::TBZW:
747 Cond[1].setImm(AArch64::TBNZW);
748 break;
749 case AArch64::TBNZW:
750 Cond[1].setImm(AArch64::TBZW);
751 break;
752 case AArch64::TBZX:
753 Cond[1].setImm(AArch64::TBNZX);
754 break;
755 case AArch64::TBNZX:
756 Cond[1].setImm(AArch64::TBZX);
757 break;
758
759 // Cond is { -1, Opcode, CC, Op0, Op1, ... }
760 case AArch64::CBWPri:
761 case AArch64::CBXPri:
762 case AArch64::CBBAssertExt:
763 case AArch64::CBHAssertExt:
764 case AArch64::CBWPrr:
765 case AArch64::CBXPrr: {
766 // Pseudos using standard 4bit Arm condition codes
768 static_cast<AArch64CC::CondCode>(Cond[2].getImm());
770 }
771 }
772 }
773
774 return false;
775}
776
778 int *BytesRemoved) const {
779 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
780 if (I == MBB.end())
781 return 0;
782
783 if (!isUncondBranchOpcode(I->getOpcode()) &&
784 !isCondBranchOpcode(I->getOpcode()))
785 return 0;
786
787 // Remove the branch.
788 I->eraseFromParent();
789
790 I = MBB.end();
791
792 if (I == MBB.begin()) {
793 if (BytesRemoved)
794 *BytesRemoved = 4;
795 return 1;
796 }
797 --I;
798 if (!isCondBranchOpcode(I->getOpcode())) {
799 if (BytesRemoved)
800 *BytesRemoved = 4;
801 return 1;
802 }
803
804 // Remove the branch.
805 I->eraseFromParent();
806 if (BytesRemoved)
807 *BytesRemoved = 8;
808
809 return 2;
810}
811
812void AArch64InstrInfo::instantiateCondBranch(
815 if (Cond[0].getImm() != -1) {
816 // Regular Bcc
817 BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
818 } else {
819 // Folded compare-and-branch
820 // Note that we use addOperand instead of addReg to keep the flags.
821
822 // cbz, cbnz
823 const MachineInstrBuilder MIB =
824 BuildMI(&MBB, DL, get(Cond[1].getImm())).add(Cond[2]);
825
826 // tbz/tbnz
827 if (Cond.size() > 3)
828 MIB.add(Cond[3]);
829
830 // cb
831 if (Cond.size() > 4)
832 MIB.add(Cond[4]);
833
834 MIB.addMBB(TBB);
835
836 // cb[b,h]
837 if (Cond.size() > 5) {
838 MIB.addImm(Cond[5].getImm());
839 MIB.addImm(Cond[6].getImm());
840 }
841 }
842}
843
846 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
847 // Shouldn't be a fall through.
848 assert(TBB && "insertBranch must not be told to insert a fallthrough");
849
850 if (!FBB) {
851 if (Cond.empty()) // Unconditional branch?
852 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
853 else
854 instantiateCondBranch(MBB, DL, TBB, Cond);
855
856 if (BytesAdded)
857 *BytesAdded = 4;
858
859 return 1;
860 }
861
862 // Two-way conditional branch.
863 instantiateCondBranch(MBB, DL, TBB, Cond);
864 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
865
866 if (BytesAdded)
867 *BytesAdded = 8;
868
869 return 2;
870}
871
872#ifndef NDEBUG
874 switch (Ext) {
875 default:
876 return false;
877 case AArch64_AM::UXTB:
878 case AArch64_AM::SXTB:
879 return Opc == AArch64::CBBAssertExt;
880 case AArch64_AM::UXTH:
881 case AArch64_AM::SXTH:
882 return Opc == AArch64::CBHAssertExt;
883 }
884}
885#endif
886
890 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
891
892 // Parse the condition code, see parseCondBranch() above.
894 switch (Cond.size()) {
895 default:
896 llvm_unreachable("Unknown condition opcode in Cond");
897 case 1: // b.cc
899 break;
900 case 3: { // cbz/cbnz
901 // We must insert a compare against 0.
902 bool Is64Bit;
903 switch (Cond[1].getImm()) {
904 default:
905 llvm_unreachable("Unknown branch opcode in Cond");
906 case AArch64::CBZW:
907 Is64Bit = false;
908 CC = AArch64CC::EQ;
909 break;
910 case AArch64::CBZX:
911 Is64Bit = true;
912 CC = AArch64CC::EQ;
913 break;
914 case AArch64::CBNZW:
915 Is64Bit = false;
916 CC = AArch64CC::NE;
917 break;
918 case AArch64::CBNZX:
919 Is64Bit = true;
920 CC = AArch64CC::NE;
921 break;
922 }
923 Register SrcReg = Cond[2].getReg();
924 if (Is64Bit) {
925 // cmp reg, #0 is actually subs xzr, reg, #0.
926 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
927 BuildMI(MBB, MI, DL, get(AArch64::SUBSXri), AArch64::XZR)
928 .addReg(SrcReg)
929 .addImm(0)
930 .addImm(0);
931 } else {
932 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
933 BuildMI(MBB, MI, DL, get(AArch64::SUBSWri), AArch64::WZR)
934 .addReg(SrcReg)
935 .addImm(0)
936 .addImm(0);
937 }
938 } break;
939 case 4: { // tbz/tbnz
940 // We must insert a tst instruction.
941 switch (Cond[1].getImm()) {
942 default:
943 llvm_unreachable("Unknown branch opcode in Cond");
944 case AArch64::TBZW:
945 case AArch64::TBZX:
946 CC = AArch64CC::EQ;
947 break;
948 case AArch64::TBNZW:
949 case AArch64::TBNZX:
950 CC = AArch64CC::NE;
951 break;
952 }
953 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
954 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
955 BuildMI(MBB, MI, DL, get(AArch64::ANDSWri), AArch64::WZR)
956 .addReg(Cond[2].getReg())
957 .addImm(
959 else
960 BuildMI(MBB, MI, DL, get(AArch64::ANDSXri), AArch64::XZR)
961 .addReg(Cond[2].getReg())
962 .addImm(
964 } break;
965 case 5: { // cb
966 // We must insert a cmp, that is a subs
967 // 0 1 2 3 4
968 // Cond is { -1, Opcode, CC, Op0, Op1 }
969 unsigned SubsOpc, SubsDestReg;
970 bool IsImm = false;
971 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
972 switch (Cond[1].getImm()) {
973 default:
974 llvm_unreachable("Unknown branch opcode in Cond");
975 case AArch64::CBWPri:
976 SubsOpc = AArch64::SUBSWri;
977 SubsDestReg = AArch64::WZR;
978 IsImm = true;
979 break;
980 case AArch64::CBXPri:
981 SubsOpc = AArch64::SUBSXri;
982 SubsDestReg = AArch64::XZR;
983 IsImm = true;
984 break;
985 case AArch64::CBWPrr:
986 SubsOpc = AArch64::SUBSWrr;
987 SubsDestReg = AArch64::WZR;
988 IsImm = false;
989 break;
990 case AArch64::CBXPrr:
991 SubsOpc = AArch64::SUBSXrr;
992 SubsDestReg = AArch64::XZR;
993 IsImm = false;
994 break;
995 }
996
997 if (IsImm) {
998 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
999 BuildMI(MBB, MI, DL, get(SubsOpc), SubsDestReg)
1000 .addReg(Cond[3].getReg())
1001 .addImm(Cond[4].getImm())
1002 .addImm(0);
1003 } else {
1004 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
1005 MRI.constrainRegClass(Cond[4].getReg(), getRegClass(get(SubsOpc), 2));
1006 BuildMI(MBB, MI, DL, get(SubsOpc), SubsDestReg)
1007 .addReg(Cond[3].getReg())
1008 .addReg(Cond[4].getReg());
1009 }
1010 } break;
1011 case 7: { // cb[b,h]
1012 // We must insert a cmp, that is a subs, but also zero- or sign-extensions
1013 // that have been folded. For the first operand we codegen an explicit
1014 // extension, for the second operand we fold the extension into cmp.
1015 // 0 1 2 3 4 5 6
1016 // Cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
1017
1018 // We need a new register for the now explicitly extended register
1019 Register Reg = Cond[3].getReg();
1021 unsigned ExtOpc;
1022 unsigned ExtBits;
1023 AArch64_AM::ShiftExtendType ExtendType =
1025 assert(isValidCBExtend(Cond[1].getImm(), ExtendType) &&
1026 "Unexpected compare-and-branch instruction for extend type");
1027 switch (ExtendType) {
1028 default:
1029 llvm_unreachable("Unknown shift-extend for CB instruction");
1030 case AArch64_AM::SXTB:
1031 ExtOpc = AArch64::SBFMWri;
1032 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1033 break;
1034 case AArch64_AM::SXTH:
1035 ExtOpc = AArch64::SBFMWri;
1036 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1037 break;
1038 case AArch64_AM::UXTB:
1039 ExtOpc = AArch64::ANDWri;
1040 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1041 break;
1042 case AArch64_AM::UXTH:
1043 ExtOpc = AArch64::ANDWri;
1044 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1045 break;
1046 }
1047
1048 // Build the explicit extension of the first operand
1049 Reg = MRI.createVirtualRegister(&AArch64::GPR32commonRegClass);
1051 BuildMI(MBB, MI, DL, get(ExtOpc), Reg).addReg(Cond[3].getReg());
1052 if (ExtOpc != AArch64::ANDWri)
1053 MBBI.addImm(0);
1054 MBBI.addImm(ExtBits);
1055 }
1056
1057 // Now, subs with an extended second operand
1059 MRI.constrainRegClass(Reg, &AArch64::GPR32commonRegClass);
1060 AArch64_AM::ShiftExtendType ExtendType =
1062 assert(isValidCBExtend(Cond[1].getImm(), ExtendType) &&
1063 "Unexpected compare-and-branch instruction for extend type");
1064 BuildMI(MBB, MI, DL, get(AArch64::SUBSWrx), AArch64::WZR)
1065 .addReg(Reg)
1066 .addReg(Cond[4].getReg())
1067 .addImm(AArch64_AM::getArithExtendImm(ExtendType, 0));
1068 } // If no extension is needed, just a regular subs
1069 else {
1070 BuildMI(MBB, MI, DL, get(AArch64::SUBSWrr), AArch64::WZR)
1071 .addReg(Reg)
1072 .addReg(Cond[4].getReg());
1073 }
1074
1075 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1076 } break;
1077 }
1078 return CC;
1079}
1080
1082 const TargetInstrInfo &TII) {
1083 for (MachineInstr &MI : MBB->terminators()) {
1084 unsigned Opc = MI.getOpcode();
1085 switch (Opc) {
1086 case AArch64::CBZW:
1087 case AArch64::CBZX:
1088 case AArch64::TBZW:
1089 case AArch64::TBZX:
1090 // CBZ/TBZ with WZR/XZR -> unconditional B
1091 if (MI.getOperand(0).getReg() == AArch64::WZR ||
1092 MI.getOperand(0).getReg() == AArch64::XZR) {
1093 DEBUG_WITH_TYPE("optimizeTerminators",
1094 dbgs() << "Removing always taken branch: " << MI);
1095 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
1096 SmallVector<MachineBasicBlock *> Succs(MBB->successors());
1097 for (auto *S : Succs)
1098 if (S != Target)
1099 MBB->removeSuccessor(S);
1100 DebugLoc DL = MI.getDebugLoc();
1101 while (MBB->rbegin() != &MI)
1102 MBB->rbegin()->eraseFromParent();
1103 MI.eraseFromParent();
1104 BuildMI(MBB, DL, TII.get(AArch64::B)).addMBB(Target);
1105 return true;
1106 }
1107 break;
1108 case AArch64::CBNZW:
1109 case AArch64::CBNZX:
1110 case AArch64::TBNZW:
1111 case AArch64::TBNZX:
1112 // CBNZ/TBNZ with WZR/XZR -> never taken, remove branch and successor
1113 if (MI.getOperand(0).getReg() == AArch64::WZR ||
1114 MI.getOperand(0).getReg() == AArch64::XZR) {
1115 DEBUG_WITH_TYPE("optimizeTerminators",
1116 dbgs() << "Removing never taken branch: " << MI);
1117 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
1118 MI.getParent()->removeSuccessor(Target);
1119 MI.eraseFromParent();
1120 return true;
1121 }
1122 break;
1123 }
1124 }
1125 return false;
1126}
1127
1128// Find the original register that VReg is copied from.
1129static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
1130 while (Register::isVirtualRegister(VReg)) {
1131 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
1132 if (!DefMI || !DefMI->isFullCopy())
1133 return VReg;
1134 VReg = DefMI->getOperand(1).getReg();
1135 }
1136 return VReg;
1137}
1138
1139// Determine if VReg is defined by an instruction that can be folded into a
1140// csel instruction. If so, return the folded opcode, and the replacement
1141// register.
1142static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
1143 unsigned *NewReg = nullptr) {
1144 VReg = removeCopies(MRI, VReg);
1145 if (!Register::isVirtualRegister(VReg))
1146 return 0;
1147
1148 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
1149 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
1150 if (!DefMI)
1151 return 0;
1152 unsigned Opc = 0;
1153 unsigned SrcReg = 0;
1154 switch (DefMI->getOpcode()) {
1155 case AArch64::SUBREG_TO_REG:
1156 // Check for the following way to define an 64-bit immediate:
1157 // %0:gpr32 = MOVi32imm 1
1158 // %1:gpr64 = SUBREG_TO_REG %0:gpr32, %subreg.sub_32
1159 if (!DefMI->getOperand(1).isReg())
1160 return 0;
1161 if (!DefMI->getOperand(2).isImm() ||
1162 DefMI->getOperand(2).getImm() != AArch64::sub_32)
1163 return 0;
1164 DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg());
1165 if (DefMI->getOpcode() != AArch64::MOVi32imm)
1166 return 0;
1167 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
1168 return 0;
1169 assert(Is64Bit);
1170 SrcReg = AArch64::XZR;
1171 Opc = AArch64::CSINCXr;
1172 break;
1173
1174 case AArch64::MOVi32imm:
1175 case AArch64::MOVi64imm:
1176 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
1177 return 0;
1178 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1179 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1180 break;
1181
1182 case AArch64::ADDSXri:
1183 case AArch64::ADDSWri:
1184 // if NZCV is used, do not fold.
1185 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1186 true) == -1)
1187 return 0;
1188 // fall-through to ADDXri and ADDWri.
1189 [[fallthrough]];
1190 case AArch64::ADDXri:
1191 case AArch64::ADDWri:
1192 // add x, 1 -> csinc.
1193 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
1194 DefMI->getOperand(3).getImm() != 0)
1195 return 0;
1196 SrcReg = DefMI->getOperand(1).getReg();
1197 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1198 break;
1199
1200 case AArch64::ORNXrr:
1201 case AArch64::ORNWrr: {
1202 // not x -> csinv, represented as orn dst, xzr, src.
1203 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1204 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1205 return 0;
1206 SrcReg = DefMI->getOperand(2).getReg();
1207 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
1208 break;
1209 }
1210
1211 case AArch64::SUBSXrr:
1212 case AArch64::SUBSWrr:
1213 // if NZCV is used, do not fold.
1214 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1215 true) == -1)
1216 return 0;
1217 // fall-through to SUBXrr and SUBWrr.
1218 [[fallthrough]];
1219 case AArch64::SUBXrr:
1220 case AArch64::SUBWrr: {
1221 // neg x -> csneg, represented as sub dst, xzr, src.
1222 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1223 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1224 return 0;
1225 SrcReg = DefMI->getOperand(2).getReg();
1226 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1227 break;
1228 }
1229 default:
1230 return 0;
1231 }
1232 assert(Opc && SrcReg && "Missing parameters");
1233
1234 if (NewReg)
1235 *NewReg = SrcReg;
1236 return Opc;
1237}
1238
1241 Register DstReg, Register TrueReg,
1242 Register FalseReg, int &CondCycles,
1243 int &TrueCycles,
1244 int &FalseCycles) const {
1245 // Check register classes.
1246 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1247 const TargetRegisterClass *RC =
1248 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
1249 if (!RC)
1250 return false;
1251
1252 // Also need to check the dest regclass, in case we're trying to optimize
1253 // something like:
1254 // %1(gpr) = PHI %2(fpr), bb1, %(fpr), bb2
1255 if (!RI.getCommonSubClass(RC, MRI.getRegClass(DstReg)))
1256 return false;
1257
1258 // Expanding cbz/tbz requires an extra cycle of latency on the condition.
1259 unsigned ExtraCondLat = Cond.size() != 1;
1260
1261 // GPRs are handled by csel.
1262 // FIXME: Fold in x+1, -x, and ~x when applicable.
1263 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1264 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1265 // Single-cycle csel, csinc, csinv, and csneg.
1266 CondCycles = 1 + ExtraCondLat;
1267 TrueCycles = FalseCycles = 1;
1268 if (canFoldIntoCSel(MRI, TrueReg))
1269 TrueCycles = 0;
1270 else if (canFoldIntoCSel(MRI, FalseReg))
1271 FalseCycles = 0;
1272 return true;
1273 }
1274
1275 // Scalar floating point is handled by fcsel.
1276 // FIXME: Form fabs, fmin, and fmax when applicable.
1277 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1278 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1279 CondCycles = 5 + ExtraCondLat;
1280 TrueCycles = FalseCycles = 2;
1281 return true;
1282 }
1283
1284 // Can't do vectors.
1285 return false;
1286}
1287
1290 const DebugLoc &DL, Register DstReg,
1292 Register TrueReg, Register FalseReg) const {
1293
1294 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1296
1297 unsigned Opc = 0;
1298 const TargetRegisterClass *RC = nullptr;
1299 bool TryFold = false;
1300 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
1301 RC = &AArch64::GPR64RegClass;
1302 Opc = AArch64::CSELXr;
1303 TryFold = true;
1304 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
1305 RC = &AArch64::GPR32RegClass;
1306 Opc = AArch64::CSELWr;
1307 TryFold = true;
1308 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
1309 RC = &AArch64::FPR64RegClass;
1310 Opc = AArch64::FCSELDrrr;
1311 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
1312 RC = &AArch64::FPR32RegClass;
1313 Opc = AArch64::FCSELSrrr;
1314 }
1315 assert(RC && "Unsupported regclass");
1316
1317 // Try folding simple instructions into the csel.
1318 if (TryFold) {
1319 unsigned NewReg = 0;
1320 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewReg);
1321 if (FoldedOpc) {
1322 // The folded opcodes csinc, csinc and csneg apply the operation to
1323 // FalseReg, so we need to invert the condition.
1325 TrueReg = FalseReg;
1326 } else
1327 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewReg);
1328
1329 // Fold the operation. Leave any dead instructions for DCE to clean up.
1330 if (FoldedOpc) {
1331 FalseReg = NewReg;
1332 Opc = FoldedOpc;
1333 // Extend the live range of NewReg.
1334 MRI.clearKillFlags(NewReg);
1335 }
1336 }
1337
1338 // Pull all virtual register into the appropriate class.
1339 MRI.constrainRegClass(TrueReg, RC);
1340 // FalseReg might be WZR or XZR if the folded operand is a literal 1.
1341 assert(
1342 (FalseReg.isVirtual() || FalseReg == AArch64::WZR ||
1343 FalseReg == AArch64::XZR) &&
1344 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1345 if (FalseReg.isVirtual())
1346 MRI.constrainRegClass(FalseReg, RC);
1347
1348 // Insert the csel.
1349 BuildMI(MBB, I, DL, get(Opc), DstReg)
1350 .addReg(TrueReg)
1351 .addReg(FalseReg)
1352 .addImm(CC);
1353}
1354
1355// Return true if Imm can be loaded into a register by a "cheap" sequence of
1356// instructions. For now, "cheap" means at most two instructions.
1357static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
1358 if (BitSize == 32)
1359 return true;
1360
1361 assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
1362 uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
1364 AArch64_IMM::expandMOVImm(Imm, BitSize, Is);
1365
1366 return Is.size() <= 2;
1367}
1368
1369// Check if a COPY instruction is cheap.
1370static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
1371 assert(MI.isCopy() && "Expected COPY instruction");
1372 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1373
1374 // Cross-bank copies (e.g., between GPR and FPR) are expensive on AArch64,
1375 // typically requiring an FMOV instruction with a 2-6 cycle latency.
1376 auto GetRegClass = [&](Register Reg) -> const TargetRegisterClass * {
1377 if (Reg.isVirtual())
1378 return MRI.getRegClass(Reg);
1379 if (Reg.isPhysical())
1380 return RI.getMinimalPhysRegClass(Reg);
1381 return nullptr;
1382 };
1383 const TargetRegisterClass *DstRC = GetRegClass(MI.getOperand(0).getReg());
1384 const TargetRegisterClass *SrcRC = GetRegClass(MI.getOperand(1).getReg());
1385 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1386 return false;
1387
1388 return MI.isAsCheapAsAMove();
1389}
1390
1391// FIXME: this implementation should be micro-architecture dependent, so a
1392// micro-architecture target hook should be introduced here in future.
1394 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1395 if (isExynosCheapAsMove(MI))
1396 return true;
1397 return MI.isAsCheapAsAMove();
1398 }
1399
1400 switch (MI.getOpcode()) {
1401 default:
1402 return MI.isAsCheapAsAMove();
1403
1404 case TargetOpcode::COPY:
1405 return isCheapCopy(MI, RI);
1406
1407 case AArch64::ADDWrs:
1408 case AArch64::ADDXrs:
1409 case AArch64::SUBWrs:
1410 case AArch64::SUBXrs:
1411 return Subtarget.hasALULSLFast() && MI.getOperand(3).getImm() <= 4;
1412
1413 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
1414 // ORRXri, it is as cheap as MOV.
1415 // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
1416 case AArch64::MOVi32imm:
1417 return isCheapImmediate(MI, 32);
1418 case AArch64::MOVi64imm:
1419 return isCheapImmediate(MI, 64);
1420 }
1421}
1422
1423bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) {
1424 switch (MI.getOpcode()) {
1425 default:
1426 return false;
1427
1428 case AArch64::ADDWrs:
1429 case AArch64::ADDXrs:
1430 case AArch64::ADDSWrs:
1431 case AArch64::ADDSXrs: {
1432 unsigned Imm = MI.getOperand(3).getImm();
1433 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1434 if (ShiftVal == 0)
1435 return true;
1436 return AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL && ShiftVal <= 5;
1437 }
1438
1439 case AArch64::ADDWrx:
1440 case AArch64::ADDXrx:
1441 case AArch64::ADDXrx64:
1442 case AArch64::ADDSWrx:
1443 case AArch64::ADDSXrx:
1444 case AArch64::ADDSXrx64: {
1445 unsigned Imm = MI.getOperand(3).getImm();
1447 default:
1448 return false;
1449 case AArch64_AM::UXTB:
1450 case AArch64_AM::UXTH:
1451 case AArch64_AM::UXTW:
1452 case AArch64_AM::UXTX:
1454 }
1455 }
1456
1457 case AArch64::SUBWrs:
1458 case AArch64::SUBSWrs: {
1459 unsigned Imm = MI.getOperand(3).getImm();
1460 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1461 return ShiftVal == 0 ||
1462 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 31);
1463 }
1464
1465 case AArch64::SUBXrs:
1466 case AArch64::SUBSXrs: {
1467 unsigned Imm = MI.getOperand(3).getImm();
1468 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1469 return ShiftVal == 0 ||
1470 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 63);
1471 }
1472
1473 case AArch64::SUBWrx:
1474 case AArch64::SUBXrx:
1475 case AArch64::SUBXrx64:
1476 case AArch64::SUBSWrx:
1477 case AArch64::SUBSXrx:
1478 case AArch64::SUBSXrx64: {
1479 unsigned Imm = MI.getOperand(3).getImm();
1481 default:
1482 return false;
1483 case AArch64_AM::UXTB:
1484 case AArch64_AM::UXTH:
1485 case AArch64_AM::UXTW:
1486 case AArch64_AM::UXTX:
1488 }
1489 }
1490
1491 case AArch64::LDRBBroW:
1492 case AArch64::LDRBBroX:
1493 case AArch64::LDRBroW:
1494 case AArch64::LDRBroX:
1495 case AArch64::LDRDroW:
1496 case AArch64::LDRDroX:
1497 case AArch64::LDRHHroW:
1498 case AArch64::LDRHHroX:
1499 case AArch64::LDRHroW:
1500 case AArch64::LDRHroX:
1501 case AArch64::LDRQroW:
1502 case AArch64::LDRQroX:
1503 case AArch64::LDRSBWroW:
1504 case AArch64::LDRSBWroX:
1505 case AArch64::LDRSBXroW:
1506 case AArch64::LDRSBXroX:
1507 case AArch64::LDRSHWroW:
1508 case AArch64::LDRSHWroX:
1509 case AArch64::LDRSHXroW:
1510 case AArch64::LDRSHXroX:
1511 case AArch64::LDRSWroW:
1512 case AArch64::LDRSWroX:
1513 case AArch64::LDRSroW:
1514 case AArch64::LDRSroX:
1515 case AArch64::LDRWroW:
1516 case AArch64::LDRWroX:
1517 case AArch64::LDRXroW:
1518 case AArch64::LDRXroX:
1519 case AArch64::PRFMroW:
1520 case AArch64::PRFMroX:
1521 case AArch64::STRBBroW:
1522 case AArch64::STRBBroX:
1523 case AArch64::STRBroW:
1524 case AArch64::STRBroX:
1525 case AArch64::STRDroW:
1526 case AArch64::STRDroX:
1527 case AArch64::STRHHroW:
1528 case AArch64::STRHHroX:
1529 case AArch64::STRHroW:
1530 case AArch64::STRHroX:
1531 case AArch64::STRQroW:
1532 case AArch64::STRQroX:
1533 case AArch64::STRSroW:
1534 case AArch64::STRSroX:
1535 case AArch64::STRWroW:
1536 case AArch64::STRWroX:
1537 case AArch64::STRXroW:
1538 case AArch64::STRXroX: {
1539 unsigned IsSigned = MI.getOperand(3).getImm();
1540 return !IsSigned;
1541 }
1542 }
1543}
1544
1545bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
1546 unsigned Opc = MI.getOpcode();
1547 switch (Opc) {
1548 default:
1549 return false;
1550 case AArch64::SEH_StackAlloc:
1551 case AArch64::SEH_SaveFPLR:
1552 case AArch64::SEH_SaveFPLR_X:
1553 case AArch64::SEH_SaveReg:
1554 case AArch64::SEH_SaveReg_X:
1555 case AArch64::SEH_SaveRegP:
1556 case AArch64::SEH_SaveRegP_X:
1557 case AArch64::SEH_SaveFReg:
1558 case AArch64::SEH_SaveFReg_X:
1559 case AArch64::SEH_SaveFRegP:
1560 case AArch64::SEH_SaveFRegP_X:
1561 case AArch64::SEH_SetFP:
1562 case AArch64::SEH_AddFP:
1563 case AArch64::SEH_Nop:
1564 case AArch64::SEH_PrologEnd:
1565 case AArch64::SEH_EpilogStart:
1566 case AArch64::SEH_EpilogEnd:
1567 case AArch64::SEH_PACSignLR:
1568 case AArch64::SEH_SaveAnyRegI:
1569 case AArch64::SEH_SaveAnyRegIP:
1570 case AArch64::SEH_SaveAnyRegQP:
1571 case AArch64::SEH_SaveAnyRegQPX:
1572 case AArch64::SEH_AllocZ:
1573 case AArch64::SEH_SaveZReg:
1574 case AArch64::SEH_SavePReg:
1575 return true;
1576 }
1577}
1578
1580 Register &SrcReg, Register &DstReg,
1581 unsigned &SubIdx) const {
1582 switch (MI.getOpcode()) {
1583 default:
1584 return false;
1585 case AArch64::SBFMXri: // aka sxtw
1586 case AArch64::UBFMXri: // aka uxtw
1587 // Check for the 32 -> 64 bit extension case, these instructions can do
1588 // much more.
1589 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
1590 return false;
1591 // This is a signed or unsigned 32 -> 64 bit extension.
1592 SrcReg = MI.getOperand(1).getReg();
1593 DstReg = MI.getOperand(0).getReg();
1594 SubIdx = AArch64::sub_32;
1595 return true;
1596 }
1597}
1598
1600 const MachineInstr &MIa, const MachineInstr &MIb) const {
1602 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
1603 int64_t OffsetA = 0, OffsetB = 0;
1604 TypeSize WidthA(0, false), WidthB(0, false);
1605 bool OffsetAIsScalable = false, OffsetBIsScalable = false;
1606
1607 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
1608 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
1609
1612 return false;
1613
1614 // Retrieve the base, offset from the base and width. Width
1615 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
1616 // base are identical, and the offset of a lower memory access +
1617 // the width doesn't overlap the offset of a higher memory access,
1618 // then the memory accesses are different.
1619 // If OffsetAIsScalable and OffsetBIsScalable are both true, they
1620 // are assumed to have the same scale (vscale).
1621 if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, OffsetAIsScalable,
1622 WidthA, TRI) &&
1623 getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, OffsetBIsScalable,
1624 WidthB, TRI)) {
1625 if (BaseOpA->isIdenticalTo(*BaseOpB) &&
1626 OffsetAIsScalable == OffsetBIsScalable) {
1627 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1628 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1629 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1630 if (LowWidth.isScalable() == OffsetAIsScalable &&
1631 LowOffset + (int)LowWidth.getKnownMinValue() <= HighOffset)
1632 return true;
1633 }
1634 }
1635 return false;
1636}
1637
1639 const MachineBasicBlock *MBB,
1640 const MachineFunction &MF) const {
1642 return true;
1643
1644 // Do not move an instruction that can be recognized as a branch target.
1645 if (hasBTISemantics(MI))
1646 return true;
1647
1648 switch (MI.getOpcode()) {
1649 case AArch64::HINT:
1650 // CSDB hints are scheduling barriers.
1651 if (MI.getOperand(0).getImm() == 0x14)
1652 return true;
1653 break;
1654 case AArch64::DSB:
1655 case AArch64::ISB:
1656 // DSB and ISB also are scheduling barriers.
1657 return true;
1658 case AArch64::MSRpstatesvcrImm1:
1659 // SMSTART and SMSTOP are also scheduling barriers.
1660 return true;
1661 default:;
1662 }
1663 if (isSEHInstruction(MI))
1664 return true;
1665 auto Next = std::next(MI.getIterator());
1666 return Next != MBB->end() && Next->isCFIInstruction();
1667}
1668
1669/// analyzeCompare - For a comparison instruction, return the source registers
1670/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
1671/// Return true if the comparison instruction can be analyzed.
1673 Register &SrcReg2, int64_t &CmpMask,
1674 int64_t &CmpValue) const {
1675 // The first operand can be a frame index where we'd normally expect a
1676 // register.
1677 // FIXME: Pass subregisters out of analyzeCompare
1678 assert(MI.getNumOperands() >= 2 && "All AArch64 cmps should have 2 operands");
1679 if (!MI.getOperand(1).isReg() || MI.getOperand(1).getSubReg())
1680 return false;
1681
1682 switch (MI.getOpcode()) {
1683 default:
1684 break;
1685 case AArch64::PTEST_PP:
1686 case AArch64::PTEST_PP_ANY:
1687 case AArch64::PTEST_PP_FIRST:
1688 SrcReg = MI.getOperand(0).getReg();
1689 SrcReg2 = MI.getOperand(1).getReg();
1690 if (MI.getOperand(2).getSubReg())
1691 return false;
1692
1693 // Not sure about the mask and value for now...
1694 CmpMask = ~0;
1695 CmpValue = 0;
1696 return true;
1697 case AArch64::SUBSWrr:
1698 case AArch64::SUBSWrs:
1699 case AArch64::SUBSWrx:
1700 case AArch64::SUBSXrr:
1701 case AArch64::SUBSXrs:
1702 case AArch64::SUBSXrx:
1703 case AArch64::ADDSWrr:
1704 case AArch64::ADDSWrs:
1705 case AArch64::ADDSWrx:
1706 case AArch64::ADDSXrr:
1707 case AArch64::ADDSXrs:
1708 case AArch64::ADDSXrx:
1709 // Replace SUBSWrr with SUBWrr if NZCV is not used.
1710 SrcReg = MI.getOperand(1).getReg();
1711 SrcReg2 = MI.getOperand(2).getReg();
1712
1713 // FIXME: Pass subregisters out of analyzeCompare
1714 if (MI.getOperand(2).getSubReg())
1715 return false;
1716
1717 CmpMask = ~0;
1718 CmpValue = 0;
1719 return true;
1720 case AArch64::SUBSWri:
1721 case AArch64::ADDSWri:
1722 case AArch64::SUBSXri:
1723 case AArch64::ADDSXri:
1724 SrcReg = MI.getOperand(1).getReg();
1725 SrcReg2 = 0;
1726 CmpMask = ~0;
1727 CmpValue = MI.getOperand(2).getImm();
1728 return true;
1729 case AArch64::ANDSWri:
1730 case AArch64::ANDSXri:
1731 // ANDS does not use the same encoding scheme as the others xxxS
1732 // instructions.
1733 SrcReg = MI.getOperand(1).getReg();
1734 SrcReg2 = 0;
1735 CmpMask = ~0;
1737 MI.getOperand(2).getImm(),
1738 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1739 return true;
1740 }
1741
1742 return false;
1743}
1744
1746 MachineBasicBlock *MBB = Instr.getParent();
1747 assert(MBB && "Can't get MachineBasicBlock here");
1748 MachineFunction *MF = MBB->getParent();
1749 assert(MF && "Can't get MachineFunction here");
1752 MachineRegisterInfo *MRI = &MF->getRegInfo();
1753
1754 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1755 ++OpIdx) {
1756 MachineOperand &MO = Instr.getOperand(OpIdx);
1757 const TargetRegisterClass *OpRegCstraints =
1758 Instr.getRegClassConstraint(OpIdx, TII, TRI);
1759
1760 // If there's no constraint, there's nothing to do.
1761 if (!OpRegCstraints)
1762 continue;
1763 // If the operand is a frame index, there's nothing to do here.
1764 // A frame index operand will resolve correctly during PEI.
1765 if (MO.isFI())
1766 continue;
1767
1768 assert(MO.isReg() &&
1769 "Operand has register constraints without being a register!");
1770
1771 Register Reg = MO.getReg();
1772 if (Reg.isPhysical()) {
1773 if (!OpRegCstraints->contains(Reg))
1774 return false;
1775 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
1776 !MRI->constrainRegClass(Reg, OpRegCstraints))
1777 return false;
1778 }
1779
1780 return true;
1781}
1782
1783/// Return the opcode that does not set flags when possible - otherwise
1784/// return the original opcode. The caller is responsible to do the actual
1785/// substitution and legality checking.
1787 // Don't convert all compare instructions, because for some the zero register
1788 // encoding becomes the sp register.
1789 bool MIDefinesZeroReg = false;
1790 if (MI.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
1791 MI.definesRegister(AArch64::XZR, /*TRI=*/nullptr))
1792 MIDefinesZeroReg = true;
1793
1794 switch (MI.getOpcode()) {
1795 default:
1796 return MI.getOpcode();
1797 case AArch64::ADDSWrr:
1798 return AArch64::ADDWrr;
1799 case AArch64::ADDSWri:
1800 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1801 case AArch64::ADDSWrs:
1802 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1803 case AArch64::ADDSWrx:
1804 return AArch64::ADDWrx;
1805 case AArch64::ADDSXrr:
1806 return AArch64::ADDXrr;
1807 case AArch64::ADDSXri:
1808 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1809 case AArch64::ADDSXrs:
1810 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1811 case AArch64::ADDSXrx:
1812 return AArch64::ADDXrx;
1813 case AArch64::SUBSWrr:
1814 return AArch64::SUBWrr;
1815 case AArch64::SUBSWri:
1816 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1817 case AArch64::SUBSWrs:
1818 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1819 case AArch64::SUBSWrx:
1820 return AArch64::SUBWrx;
1821 case AArch64::SUBSXrr:
1822 return AArch64::SUBXrr;
1823 case AArch64::SUBSXri:
1824 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1825 case AArch64::SUBSXrs:
1826 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1827 case AArch64::SUBSXrx:
1828 return AArch64::SUBXrx;
1829 }
1830}
1831
1832enum AccessKind { AK_Write = 0x01, AK_Read = 0x10, AK_All = 0x11 };
1833
1834/// True when condition flags are accessed (either by writing or reading)
1835/// on the instruction trace starting at From and ending at To.
1836///
1837/// Note: If From and To are from different blocks it's assumed CC are accessed
1838/// on the path.
1841 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
1842 // Early exit if To is at the beginning of the BB.
1843 if (To == To->getParent()->begin())
1844 return true;
1845
1846 // Check whether the instructions are in the same basic block
1847 // If not, assume the condition flags might get modified somewhere.
1848 if (To->getParent() != From->getParent())
1849 return true;
1850
1851 // From must be above To.
1852 assert(std::any_of(
1853 ++To.getReverse(), To->getParent()->rend(),
1854 [From](MachineInstr &MI) { return MI.getIterator() == From; }));
1855
1856 // We iterate backward starting at \p To until we hit \p From.
1857 for (const MachineInstr &Instr :
1859 if (((AccessToCheck & AK_Write) &&
1860 Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
1861 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
1862 return true;
1863 }
1864 return false;
1865}
1866
1867std::optional<unsigned>
1868AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1869 MachineInstr *Pred,
1870 const MachineRegisterInfo *MRI) const {
1871 unsigned MaskOpcode = Mask->getOpcode();
1872 unsigned PredOpcode = Pred->getOpcode();
1873 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1874 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1875
1876 if (PredIsWhileLike) {
1877 // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1878 // instruction and the condition is "any" since WHILcc does an implicit
1879 // PTEST(ALL, PG) check and PG is always a subset of ALL.
1880 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1881 return PredOpcode;
1882
1883 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1884 // redundant since WHILE performs an implicit PTEST with an all active
1885 // mask.
1886 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1887 getElementSizeForOpcode(MaskOpcode) ==
1888 getElementSizeForOpcode(PredOpcode))
1889 return PredOpcode;
1890
1891 // For PTEST_FIRST(PTRUE_ALL, WHILE), the PTEST_FIRST is redundant since
1892 // WHILEcc performs an implicit PTEST with an all active mask, setting
1893 // the N flag as the PTEST_FIRST would.
1894 if (PTest->getOpcode() == AArch64::PTEST_PP_FIRST &&
1895 isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31)
1896 return PredOpcode;
1897
1898 return {};
1899 }
1900
1901 if (PredIsPTestLike) {
1902 // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1903 // instruction that sets the flags as PTEST would and the condition is
1904 // "any" since PG is always a subset of the governing predicate of the
1905 // ptest-like instruction.
1906 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1907 return PredOpcode;
1908
1909 auto PTestLikeMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1910
1911 // If the PTEST like instruction's general predicate is not `Mask`, attempt
1912 // to look through a copy and try again. This is because some instructions
1913 // take a predicate whose register class is a subset of its result class.
1914 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1915 PTestLikeMask->getOperand(1).getReg().isVirtual())
1916 PTestLikeMask =
1917 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1918
1919 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1920 // the element size matches and either the PTEST_LIKE instruction uses
1921 // the same all active mask or the condition is "any".
1922 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1923 getElementSizeForOpcode(MaskOpcode) ==
1924 getElementSizeForOpcode(PredOpcode)) {
1925 if (Mask == PTestLikeMask || PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1926 return PredOpcode;
1927 }
1928
1929 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
1930 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
1931 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
1932 // compare that also support 16/32/64-bit predicates, the implicit PTEST
1933 // performed by the compare could consider fewer lanes for these element
1934 // sizes.
1935 //
1936 // For example, consider
1937 //
1938 // ptrue p0.b ; P0=1111-1111-1111-1111
1939 // index z0.s, #0, #1 ; Z0=<0,1,2,3>
1940 // index z1.s, #1, #1 ; Z1=<1,2,3,4>
1941 // cmphi p1.s, p0/z, z1.s, z0.s ; P1=0001-0001-0001-0001
1942 // ; ^ last active
1943 // ptest p0, p1.b ; P1=0001-0001-0001-0001
1944 // ; ^ last active
1945 //
1946 // where the compare generates a canonical all active 32-bit predicate
1947 // (equivalent to 'ptrue p1.s, all'). The implicit PTEST sets the last
1948 // active flag, whereas the PTEST instruction with the same mask doesn't.
1949 // For PTEST_ANY this doesn't apply as the flags in this case would be
1950 // identical regardless of element size.
1951 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1952 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1953 PTest->getOpcode() == AArch64::PTEST_PP_ANY))
1954 return PredOpcode;
1955
1956 return {};
1957 }
1958
1959 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1960 // opcode so the PTEST becomes redundant.
1961 switch (PredOpcode) {
1962 case AArch64::AND_PPzPP:
1963 case AArch64::BIC_PPzPP:
1964 case AArch64::EOR_PPzPP:
1965 case AArch64::NAND_PPzPP:
1966 case AArch64::NOR_PPzPP:
1967 case AArch64::ORN_PPzPP:
1968 case AArch64::ORR_PPzPP:
1969 case AArch64::BRKA_PPzP:
1970 case AArch64::BRKPA_PPzPP:
1971 case AArch64::BRKB_PPzP:
1972 case AArch64::BRKPB_PPzPP:
1973 case AArch64::RDFFR_PPz: {
1974 // Check to see if our mask is the same. If not the resulting flag bits
1975 // may be different and we can't remove the ptest.
1976 auto *PredMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1977 if (Mask != PredMask)
1978 return {};
1979 break;
1980 }
1981 case AArch64::BRKN_PPzP: {
1982 // BRKN uses an all active implicit mask to set flags unlike the other
1983 // flag-setting instructions.
1984 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1985 if ((MaskOpcode != AArch64::PTRUE_B) ||
1986 (Mask->getOperand(1).getImm() != 31))
1987 return {};
1988 break;
1989 }
1990 case AArch64::PTRUE_B:
1991 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1992 break;
1993 default:
1994 // Bail out if we don't recognize the input
1995 return {};
1996 }
1997
1998 return convertToFlagSettingOpc(PredOpcode);
1999}
2000
2001/// optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
2002/// operation which could set the flags in an identical manner
2003bool AArch64InstrInfo::optimizePTestInstr(
2004 MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
2005 const MachineRegisterInfo *MRI) const {
2006 auto *Mask = MRI->getUniqueVRegDef(MaskReg);
2007 auto *Pred = MRI->getUniqueVRegDef(PredReg);
2008
2009 if (Pred->isCopy() && PTest->getOpcode() == AArch64::PTEST_PP_FIRST) {
2010 // Instructions which return a multi-vector (e.g. WHILECC_x2) require copies
2011 // before the branch to extract each subregister.
2012 auto Op = Pred->getOperand(1);
2013 if (Op.isReg() && Op.getReg().isVirtual() &&
2014 Op.getSubReg() == AArch64::psub0)
2015 Pred = MRI->getUniqueVRegDef(Op.getReg());
2016 }
2017
2018 unsigned PredOpcode = Pred->getOpcode();
2019 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
2020 if (!NewOp)
2021 return false;
2022
2023 const TargetRegisterInfo *TRI = &getRegisterInfo();
2024
2025 // If another instruction between Pred and PTest accesses flags, don't remove
2026 // the ptest or update the earlier instruction to modify them.
2027 if (areCFlagsAccessedBetweenInstrs(Pred, PTest, TRI))
2028 return false;
2029
2030 // If we pass all the checks, it's safe to remove the PTEST and use the flags
2031 // as they are prior to PTEST. Sometimes this requires the tested PTEST
2032 // operand to be replaced with an equivalent instruction that also sets the
2033 // flags.
2034 PTest->eraseFromParent();
2035 if (*NewOp != PredOpcode) {
2036 Pred->setDesc(get(*NewOp));
2037 bool succeeded = UpdateOperandRegClass(*Pred);
2038 (void)succeeded;
2039 assert(succeeded && "Operands have incompatible register classes!");
2040 Pred->addRegisterDefined(AArch64::NZCV, TRI);
2041 }
2042
2043 // Ensure that the flags def is live.
2044 if (Pred->registerDefIsDead(AArch64::NZCV, TRI)) {
2045 unsigned i = 0, e = Pred->getNumOperands();
2046 for (; i != e; ++i) {
2047 MachineOperand &MO = Pred->getOperand(i);
2048 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::NZCV) {
2049 MO.setIsDead(false);
2050 break;
2051 }
2052 }
2053 }
2054 return true;
2055}
2056
2057/// Try to optimize a compare instruction. A compare instruction is an
2058/// instruction which produces AArch64::NZCV. It can be truly compare
2059/// instruction
2060/// when there are no uses of its destination register.
2061///
2062/// The following steps are tried in order:
2063/// 1. Convert CmpInstr into an unconditional version.
2064/// 2. Remove CmpInstr if above there is an instruction producing a needed
2065/// condition code or an instruction which can be converted into such an
2066/// instruction.
2067/// Only comparison with zero is supported.
2069 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
2070 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
2071 assert(CmpInstr.getParent());
2072 assert(MRI);
2073
2074 // Replace SUBSWrr with SUBWrr if NZCV is not used.
2075 int DeadNZCVIdx =
2076 CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
2077 if (DeadNZCVIdx != -1) {
2078 if (CmpInstr.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
2079 CmpInstr.definesRegister(AArch64::XZR, /*TRI=*/nullptr)) {
2080 CmpInstr.eraseFromParent();
2081 return true;
2082 }
2083 unsigned Opc = CmpInstr.getOpcode();
2084 unsigned NewOpc = convertToNonFlagSettingOpc(CmpInstr);
2085 if (NewOpc == Opc)
2086 return false;
2087 const MCInstrDesc &MCID = get(NewOpc);
2088 CmpInstr.setDesc(MCID);
2089 CmpInstr.removeOperand(DeadNZCVIdx);
2090 bool succeeded = UpdateOperandRegClass(CmpInstr);
2091 (void)succeeded;
2092 assert(succeeded && "Some operands reg class are incompatible!");
2093 return true;
2094 }
2095
2096 if (CmpInstr.getOpcode() == AArch64::PTEST_PP ||
2097 CmpInstr.getOpcode() == AArch64::PTEST_PP_ANY ||
2098 CmpInstr.getOpcode() == AArch64::PTEST_PP_FIRST)
2099 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2100
2101 if (SrcReg2 != 0)
2102 return false;
2103
2104 // CmpInstr is a Compare instruction if destination register is not used.
2105 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
2106 return false;
2107
2108 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2109 return true;
2110 return (CmpValue == 0 || CmpValue == 1) &&
2111 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2112}
2113
2114/// Get opcode of S version of Instr.
2115/// If Instr is S version its opcode is returned.
2116/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
2117/// or we are not interested in it.
2118static unsigned sForm(MachineInstr &Instr) {
2119 switch (Instr.getOpcode()) {
2120 default:
2121 return AArch64::INSTRUCTION_LIST_END;
2122
2123 case AArch64::ADDSWrr:
2124 case AArch64::ADDSWri:
2125 case AArch64::ADDSXrr:
2126 case AArch64::ADDSXri:
2127 case AArch64::ADDSWrx:
2128 case AArch64::ADDSXrx:
2129 case AArch64::ADDSWrs:
2130 case AArch64::ADDSXrs:
2131 case AArch64::SUBSWrr:
2132 case AArch64::SUBSWri:
2133 case AArch64::SUBSWrx:
2134 case AArch64::SUBSWrs:
2135 case AArch64::SUBSXrr:
2136 case AArch64::SUBSXri:
2137 case AArch64::SUBSXrx:
2138 case AArch64::SUBSXrs:
2139 case AArch64::ANDSWri:
2140 case AArch64::ANDSWrr:
2141 case AArch64::ANDSWrs:
2142 case AArch64::ANDSXri:
2143 case AArch64::ANDSXrr:
2144 case AArch64::ANDSXrs:
2145 case AArch64::BICSWrr:
2146 case AArch64::BICSXrr:
2147 case AArch64::BICSWrs:
2148 case AArch64::BICSXrs:
2149 case AArch64::ADCSWr:
2150 case AArch64::ADCSXr:
2151 case AArch64::SBCSWr:
2152 case AArch64::SBCSXr:
2153 return Instr.getOpcode();
2154
2155 case AArch64::ADDWrr:
2156 return AArch64::ADDSWrr;
2157 case AArch64::ADDWri:
2158 return AArch64::ADDSWri;
2159 case AArch64::ADDXrr:
2160 return AArch64::ADDSXrr;
2161 case AArch64::ADDXri:
2162 return AArch64::ADDSXri;
2163 case AArch64::ADDWrx:
2164 return AArch64::ADDSWrx;
2165 case AArch64::ADDXrx:
2166 return AArch64::ADDSXrx;
2167 case AArch64::ADDWrs:
2168 return AArch64::ADDSWrs;
2169 case AArch64::ADDXrs:
2170 return AArch64::ADDSXrs;
2171 case AArch64::ADCWr:
2172 return AArch64::ADCSWr;
2173 case AArch64::ADCXr:
2174 return AArch64::ADCSXr;
2175 case AArch64::SUBWrr:
2176 return AArch64::SUBSWrr;
2177 case AArch64::SUBWri:
2178 return AArch64::SUBSWri;
2179 case AArch64::SUBXrr:
2180 return AArch64::SUBSXrr;
2181 case AArch64::SUBXri:
2182 return AArch64::SUBSXri;
2183 case AArch64::SUBWrx:
2184 return AArch64::SUBSWrx;
2185 case AArch64::SUBXrx:
2186 return AArch64::SUBSXrx;
2187 case AArch64::SUBWrs:
2188 return AArch64::SUBSWrs;
2189 case AArch64::SUBXrs:
2190 return AArch64::SUBSXrs;
2191 case AArch64::SBCWr:
2192 return AArch64::SBCSWr;
2193 case AArch64::SBCXr:
2194 return AArch64::SBCSXr;
2195 case AArch64::ANDWri:
2196 return AArch64::ANDSWri;
2197 case AArch64::ANDXri:
2198 return AArch64::ANDSXri;
2199 case AArch64::ANDWrr:
2200 return AArch64::ANDSWrr;
2201 case AArch64::ANDWrs:
2202 return AArch64::ANDSWrs;
2203 case AArch64::ANDXrr:
2204 return AArch64::ANDSXrr;
2205 case AArch64::ANDXrs:
2206 return AArch64::ANDSXrs;
2207 case AArch64::BICWrr:
2208 return AArch64::BICSWrr;
2209 case AArch64::BICXrr:
2210 return AArch64::BICSXrr;
2211 case AArch64::BICWrs:
2212 return AArch64::BICSWrs;
2213 case AArch64::BICXrs:
2214 return AArch64::BICSXrs;
2215 }
2216}
2217
2218/// Check if AArch64::NZCV should be alive in successors of MBB.
2220 for (auto *BB : MBB->successors())
2221 if (BB->isLiveIn(AArch64::NZCV))
2222 return true;
2223 return false;
2224}
2225
2226/// \returns The condition code operand index for \p Instr if it is a branch
2227/// or select and -1 otherwise.
2228int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2229 const MachineInstr &Instr) {
2230 switch (Instr.getOpcode()) {
2231 default:
2232 return -1;
2233
2234 case AArch64::Bcc: {
2235 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2236 assert(Idx >= 2);
2237 return Idx - 2;
2238 }
2239
2240 case AArch64::CSINVWr:
2241 case AArch64::CSINVXr:
2242 case AArch64::CSINCWr:
2243 case AArch64::CSINCXr:
2244 case AArch64::CSELWr:
2245 case AArch64::CSELXr:
2246 case AArch64::CSNEGWr:
2247 case AArch64::CSNEGXr:
2248 case AArch64::FCSELSrrr:
2249 case AArch64::FCSELDrrr: {
2250 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2251 assert(Idx >= 1);
2252 return Idx - 1;
2253 }
2254 }
2255}
2256
2257/// Find a condition code used by the instruction.
2258/// Returns AArch64CC::Invalid if either the instruction does not use condition
2259/// codes or we don't optimize CmpInstr in the presence of such instructions.
2261 int CCIdx =
2262 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2263 return CCIdx >= 0 ? static_cast<AArch64CC::CondCode>(
2264 Instr.getOperand(CCIdx).getImm())
2266}
2267
2270 UsedNZCV UsedFlags;
2271 switch (CC) {
2272 default:
2273 break;
2274
2275 case AArch64CC::EQ: // Z set
2276 case AArch64CC::NE: // Z clear
2277 UsedFlags.Z = true;
2278 break;
2279
2280 case AArch64CC::HI: // Z clear and C set
2281 case AArch64CC::LS: // Z set or C clear
2282 UsedFlags.Z = true;
2283 [[fallthrough]];
2284 case AArch64CC::HS: // C set
2285 case AArch64CC::LO: // C clear
2286 UsedFlags.C = true;
2287 break;
2288
2289 case AArch64CC::MI: // N set
2290 case AArch64CC::PL: // N clear
2291 UsedFlags.N = true;
2292 break;
2293
2294 case AArch64CC::VS: // V set
2295 case AArch64CC::VC: // V clear
2296 UsedFlags.V = true;
2297 break;
2298
2299 case AArch64CC::GT: // Z clear, N and V the same
2300 case AArch64CC::LE: // Z set, N and V differ
2301 UsedFlags.Z = true;
2302 [[fallthrough]];
2303 case AArch64CC::GE: // N and V the same
2304 case AArch64CC::LT: // N and V differ
2305 UsedFlags.N = true;
2306 UsedFlags.V = true;
2307 break;
2308 }
2309 return UsedFlags;
2310}
2311
2312/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
2313/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
2314/// \returns std::nullopt otherwise.
2315///
2316/// Collect instructions using that flags in \p CCUseInstrs if provided.
2317std::optional<UsedNZCV>
2319 const TargetRegisterInfo &TRI,
2320 SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
2321 MachineBasicBlock *CmpParent = CmpInstr.getParent();
2322 if (MI.getParent() != CmpParent)
2323 return std::nullopt;
2324
2325 if (areCFlagsAliveInSuccessors(CmpParent))
2326 return std::nullopt;
2327
2328 UsedNZCV NZCVUsedAfterCmp;
2330 std::next(CmpInstr.getIterator()), CmpParent->instr_end())) {
2331 if (Instr.readsRegister(AArch64::NZCV, &TRI)) {
2333 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
2334 return std::nullopt;
2335 NZCVUsedAfterCmp |= getUsedNZCV(CC);
2336 if (CCUseInstrs)
2337 CCUseInstrs->push_back(&Instr);
2338 }
2339 if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
2340 break;
2341 }
2342 return NZCVUsedAfterCmp;
2343}
2344
2345static bool isADDSRegImm(unsigned Opcode) {
2346 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2347}
2348
2349static bool isSUBSRegImm(unsigned Opcode) {
2350 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2351}
2352
2354 unsigned Opc = sForm(MI);
2355 switch (Opc) {
2356 case AArch64::ANDSWri:
2357 case AArch64::ANDSWrr:
2358 case AArch64::ANDSWrs:
2359 case AArch64::ANDSXri:
2360 case AArch64::ANDSXrr:
2361 case AArch64::ANDSXrs:
2362 case AArch64::BICSWrr:
2363 case AArch64::BICSXrr:
2364 case AArch64::BICSWrs:
2365 case AArch64::BICSXrs:
2366 return true;
2367 default:
2368 return false;
2369 }
2370}
2371
2372/// Check if CmpInstr can be substituted by MI.
2373///
2374/// CmpInstr can be substituted:
2375/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2376/// - and, MI and CmpInstr are from the same MachineBB
2377/// - and, condition flags are not alive in successors of the CmpInstr parent
2378/// - and, if MI opcode is the S form there must be no defs of flags between
2379/// MI and CmpInstr
2380/// or if MI opcode is not the S form there must be neither defs of flags
2381/// nor uses of flags between MI and CmpInstr.
2382/// - and, C is not used after CmpInstr; CmpInstr's C is from adds/subs #0 on
2383/// SrcReg and can differ from MI (e.g. carry out of ADCS/SBCS).
2384/// - and, V is not used after CmpInstr unless MI is AND/BIC (V cleared) or MI
2385/// has NoSWrap (overflow is poison and the fold is still safe).
2387 const TargetRegisterInfo &TRI) {
2388 // MI is an opcode sForm maps (add/sub/adc/sbc/and/bic and their S forms).
2389 assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END);
2390
2391 const unsigned CmpOpcode = CmpInstr.getOpcode();
2392 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
2393 return false;
2394
2395 assert((CmpInstr.getOperand(2).isImm() &&
2396 CmpInstr.getOperand(2).getImm() == 0) &&
2397 "Caller guarantees that CmpInstr compares with constant 0");
2398
2399 std::optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
2400 if (!NZVCUsed || NZVCUsed->C)
2401 return false;
2402
2403 // CmpInstr is ADDS/SUBS with immediate 0 on SrcReg (compare SrcReg to zero).
2404 // After the fold, users see NZCV from MI (or its S form), not from CmpInstr.
2405 // N/Z match CmpInstr for the value in SrcReg; C/V need not match in general
2406 // (e.g. ADCS vs adds #0), so we require C unused after CmpInstr and gate V
2407 // as below. NoSWrap makes signed overflow poison; AND/BIC clear V.
2408 if (NZVCUsed->V && !MI.getFlag(MachineInstr::NoSWrap) && !isANDOpcode(MI))
2409 return false;
2410
2411 AccessKind AccessToCheck = AK_Write;
2412 if (sForm(MI) != MI.getOpcode())
2413 AccessToCheck = AK_All;
2414 return !areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AccessToCheck);
2415}
2416
2417/// Substitute an instruction comparing to zero with another instruction
2418/// which produces needed condition flags.
2419///
2420/// Return true on success.
2421bool AArch64InstrInfo::substituteCmpToZero(
2422 MachineInstr &CmpInstr, unsigned SrcReg,
2423 const MachineRegisterInfo &MRI) const {
2424 // Get the unique definition of SrcReg.
2425 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2426 if (!MI)
2427 return false;
2428
2429 const TargetRegisterInfo &TRI = getRegisterInfo();
2430
2431 unsigned NewOpc = sForm(*MI);
2432 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2433 return false;
2434
2435 if (!canInstrSubstituteCmpInstr(*MI, CmpInstr, TRI))
2436 return false;
2437
2438 // Update the instruction to set NZCV.
2439 MI->setDesc(get(NewOpc));
2440 CmpInstr.eraseFromParent();
2442 (void)succeeded;
2443 assert(succeeded && "Some operands reg class are incompatible!");
2444 MI->addRegisterDefined(AArch64::NZCV, &TRI);
2445 return true;
2446}
2447
2448/// \returns True if \p CmpInstr can be removed.
2449///
2450/// \p IsInvertCC is true if, after removing \p CmpInstr, condition
2451/// codes used in \p CCUseInstrs must be inverted.
2453 int CmpValue, const TargetRegisterInfo &TRI,
2455 bool &IsInvertCC) {
2456 assert((CmpValue == 0 || CmpValue == 1) &&
2457 "Only comparisons to 0 or 1 considered for removal!");
2458
2459 // MI is 'CSINCWr %vreg, wzr, wzr, <cc>' or 'CSINCXr %vreg, xzr, xzr, <cc>'
2460 unsigned MIOpc = MI.getOpcode();
2461 if (MIOpc == AArch64::CSINCWr) {
2462 if (MI.getOperand(1).getReg() != AArch64::WZR ||
2463 MI.getOperand(2).getReg() != AArch64::WZR)
2464 return false;
2465 } else if (MIOpc == AArch64::CSINCXr) {
2466 if (MI.getOperand(1).getReg() != AArch64::XZR ||
2467 MI.getOperand(2).getReg() != AArch64::XZR)
2468 return false;
2469 } else {
2470 return false;
2471 }
2473 if (MICC == AArch64CC::Invalid)
2474 return false;
2475
2476 // NZCV needs to be defined
2477 if (MI.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) != -1)
2478 return false;
2479
2480 // CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0' or 'SUBS %vreg, 1'
2481 const unsigned CmpOpcode = CmpInstr.getOpcode();
2482 bool IsSubsRegImm = isSUBSRegImm(CmpOpcode);
2483 if (CmpValue && !IsSubsRegImm)
2484 return false;
2485 if (!CmpValue && !IsSubsRegImm && !isADDSRegImm(CmpOpcode))
2486 return false;
2487
2488 // MI conditions allowed: eq, ne, mi, pl
2489 UsedNZCV MIUsedNZCV = getUsedNZCV(MICC);
2490 if (MIUsedNZCV.C || MIUsedNZCV.V)
2491 return false;
2492
2493 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2494 examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
2495 // Condition flags are not used in CmpInstr basic block successors and only
2496 // Z or N flags allowed to be used after CmpInstr within its basic block
2497 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2498 return false;
2499 // Z or N flag used after CmpInstr must correspond to the flag used in MI
2500 if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||
2501 (MIUsedNZCV.N && NZCVUsedAfterCmp->Z))
2502 return false;
2503 // If CmpInstr is comparison to zero MI conditions are limited to eq, ne
2504 if (MIUsedNZCV.N && !CmpValue)
2505 return false;
2506
2507 // There must be no defs of flags between MI and CmpInstr
2508 if (areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AK_Write))
2509 return false;
2510
2511 // Condition code is inverted in the following cases:
2512 // 1. MI condition is ne; CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2513 // 2. MI condition is eq, pl; CmpInstr is 'SUBS %vreg, 1'
2514 IsInvertCC = (CmpValue && (MICC == AArch64CC::EQ || MICC == AArch64CC::PL)) ||
2515 (!CmpValue && MICC == AArch64CC::NE);
2516 return true;
2517}
2518
2519/// Remove comparison in csinc-cmp sequence
2520///
2521/// Examples:
2522/// 1. \code
2523/// csinc w9, wzr, wzr, ne
2524/// cmp w9, #0
2525/// b.eq
2526/// \endcode
2527/// to
2528/// \code
2529/// csinc w9, wzr, wzr, ne
2530/// b.ne
2531/// \endcode
2532///
2533/// 2. \code
2534/// csinc x2, xzr, xzr, mi
2535/// cmp x2, #1
2536/// b.pl
2537/// \endcode
2538/// to
2539/// \code
2540/// csinc x2, xzr, xzr, mi
2541/// b.pl
2542/// \endcode
2543///
2544/// \param CmpInstr comparison instruction
2545/// \return True when comparison removed
2546bool AArch64InstrInfo::removeCmpToZeroOrOne(
2547 MachineInstr &CmpInstr, unsigned SrcReg, int CmpValue,
2548 const MachineRegisterInfo &MRI) const {
2549 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2550 if (!MI)
2551 return false;
2552 const TargetRegisterInfo &TRI = getRegisterInfo();
2553 SmallVector<MachineInstr *, 4> CCUseInstrs;
2554 bool IsInvertCC = false;
2555 if (!canCmpInstrBeRemoved(*MI, CmpInstr, CmpValue, TRI, CCUseInstrs,
2556 IsInvertCC))
2557 return false;
2558 // Make transformation
2559 CmpInstr.eraseFromParent();
2560 if (IsInvertCC) {
2561 // Invert condition codes in CmpInstr CC users
2562 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2563 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2564 assert(Idx >= 0 && "Unexpected instruction using CC.");
2565 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2567 static_cast<AArch64CC::CondCode>(CCOperand.getImm()));
2568 CCOperand.setImm(CCUse);
2569 }
2570 }
2571 return true;
2572}
2573
2574bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
2575 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2576 MI.getOpcode() != AArch64::CATCHRET &&
2577 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2578 return false;
2579
2580 MachineBasicBlock &MBB = *MI.getParent();
2581 auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
2582 auto TRI = Subtarget.getRegisterInfo();
2583 DebugLoc DL = MI.getDebugLoc();
2584
2585 if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2586 // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
2587 // This computes FP - stored_mixed_value to unmix the cookie
2588 Register DstReg = MI.getOperand(0).getReg();
2589 Register SrcReg = MI.getOperand(1).getReg();
2590
2591 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
2592 .addReg(AArch64::FP)
2593 .addReg(SrcReg);
2594
2595 MBB.erase(MI);
2596 return true;
2597 }
2598
2599 if (MI.getOpcode() == AArch64::CATCHRET) {
2600 // Skip to the first instruction before the epilog.
2601 const TargetInstrInfo *TII =
2603 MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
2605 MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
2606 while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
2607 FirstEpilogSEH != MBB.begin())
2608 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2609 if (FirstEpilogSEH != MBB.begin())
2610 FirstEpilogSEH = std::next(FirstEpilogSEH);
2611 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
2612 .addReg(AArch64::X0, RegState::Define)
2613 .addMBB(TargetMBB, AArch64II::MO_PAGE);
2614 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
2615 .addReg(AArch64::X0, RegState::Define)
2616 .addReg(AArch64::X0)
2618 .addImm(0);
2619 TargetMBB->setMachineBlockAddressTaken();
2620 return true;
2621 }
2622
2623 Register Reg = MI.getOperand(0).getReg();
2625 if (M.getStackProtectorGuard() == "sysreg") {
2626 const AArch64SysReg::SysReg *SrcReg =
2627 AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg());
2628 if (!SrcReg)
2629 report_fatal_error("Unknown SysReg for Stack Protector Guard Register");
2630
2631 // mrs xN, sysreg
2632 BuildMI(MBB, MI, DL, get(AArch64::MRS))
2634 .addImm(SrcReg->Encoding);
2635 int Offset = M.getStackProtectorGuardOffset();
2636 if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) {
2637 // ldr xN, [xN, #offset]
2638 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2639 .addDef(Reg)
2641 .addImm(Offset / 8);
2642 } else if (Offset >= -256 && Offset <= 255) {
2643 // ldur xN, [xN, #offset]
2644 BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
2645 .addDef(Reg)
2647 .addImm(Offset);
2648 } else if (Offset >= -4095 && Offset <= 4095) {
2649 if (Offset > 0) {
2650 // add xN, xN, #offset
2651 BuildMI(MBB, MI, DL, get(AArch64::ADDXri))
2652 .addDef(Reg)
2654 .addImm(Offset)
2655 .addImm(0);
2656 } else {
2657 // sub xN, xN, #offset
2658 BuildMI(MBB, MI, DL, get(AArch64::SUBXri))
2659 .addDef(Reg)
2661 .addImm(-Offset)
2662 .addImm(0);
2663 }
2664 // ldr xN, [xN]
2665 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2666 .addDef(Reg)
2668 .addImm(0);
2669 } else {
2670 // Cases that are larger than +/- 4095 and not a multiple of 8, or larger
2671 // than 23760.
2672 // It might be nice to use AArch64::MOVi32imm here, which would get
2673 // expanded in PreSched2 after PostRA, but our lone scratch Reg already
2674 // contains the MRS result. findScratchNonCalleeSaveRegister() in
2675 // AArch64FrameLowering might help us find such a scratch register
2676 // though. If we failed to find a scratch register, we could emit a
2677 // stream of add instructions to build up the immediate. Or, we could try
2678 // to insert a AArch64::MOVi32imm before register allocation so that we
2679 // didn't need to scavenge for a scratch register.
2680 report_fatal_error("Unable to encode Stack Protector Guard Offset");
2681 }
2682 MBB.erase(MI);
2683 return true;
2684 }
2685
2686 const GlobalValue *GV =
2687 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
2688 const TargetMachine &TM = MBB.getParent()->getTarget();
2689 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2690 const unsigned char MO_NC = AArch64II::MO_NC;
2691
2692 unsigned GuardWidth = M.getStackProtectorGuardValueWidth().value_or(
2693 Subtarget.isTargetILP32() ? 4 : 8);
2694 if (GuardWidth != 4 && GuardWidth != 8)
2695 report_fatal_error("Unsupported stack protector value width");
2696 if ((OpFlags & AArch64II::MO_GOT) != 0) {
2697 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
2698 .addGlobalAddress(GV, 0, OpFlags);
2699 if (GuardWidth == 4) {
2700 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2701 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2702 .addDef(Reg32, RegState::Dead)
2704 .addImm(0)
2705 .addMemOperand(*MI.memoperands_begin())
2707 } else {
2708 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2710 .addImm(0)
2711 .addMemOperand(*MI.memoperands_begin());
2712 }
2713 } else if (TM.getCodeModel() == CodeModel::Large) {
2714 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
2715 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
2716 .addImm(0);
2717 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2719 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC)
2720 .addImm(16);
2721 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2723 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC)
2724 .addImm(32);
2725 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2728 .addImm(48);
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 .addImm(0)
2735 .addMemOperand(*MI.memoperands_begin())
2737 } else {
2738 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2740 .addImm(0)
2741 .addMemOperand(*MI.memoperands_begin());
2742 }
2743 } else {
2744 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
2745 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
2746 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
2747 if (GuardWidth == 4) {
2748 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2749 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2750 .addDef(Reg32, RegState::Dead)
2752 .addGlobalAddress(GV, 0, LoFlags)
2753 .addMemOperand(*MI.memoperands_begin())
2755 } else {
2756 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2758 .addGlobalAddress(GV, 0, LoFlags)
2759 .addMemOperand(*MI.memoperands_begin());
2760 }
2761 }
2762 // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
2763 // we use sub instruction to mix the cookie on aarch64.
2764 // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
2765 // the final frame pointer value.
2766 if (Subtarget.getTargetTriple().isOSMSVCRT())
2767 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
2768 .addReg(AArch64::FP)
2770
2771 MBB.erase(MI);
2772
2773 return true;
2774}
2775
2776// Return true if this instruction simply sets its single destination register
2777// to zero. This is equivalent to a register rename of the zero-register.
2779 switch (MI.getOpcode()) {
2780 default:
2781 break;
2782 case AArch64::MOVZWi:
2783 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
2784 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
2785 assert(MI.getDesc().getNumOperands() == 3 &&
2786 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
2787 return true;
2788 }
2789 break;
2790 case AArch64::ANDWri: // and Rd, Rzr, #imm
2791 return MI.getOperand(1).getReg() == AArch64::WZR;
2792 case AArch64::ANDXri:
2793 return MI.getOperand(1).getReg() == AArch64::XZR;
2794 case TargetOpcode::COPY:
2795 return MI.getOperand(1).getReg() == AArch64::WZR;
2796 }
2797 return false;
2798}
2799
2800// Return true if this instruction simply renames a general register without
2801// modifying bits.
2803 switch (MI.getOpcode()) {
2804 default:
2805 break;
2806 case TargetOpcode::COPY: {
2807 // GPR32 copies will by lowered to ORRXrs
2808 Register DstReg = MI.getOperand(0).getReg();
2809 return (AArch64::GPR32RegClass.contains(DstReg) ||
2810 AArch64::GPR64RegClass.contains(DstReg));
2811 }
2812 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
2813 if (MI.getOperand(1).getReg() == AArch64::XZR) {
2814 assert(MI.getDesc().getNumOperands() == 4 &&
2815 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
2816 return true;
2817 }
2818 break;
2819 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
2820 if (MI.getOperand(2).getImm() == 0) {
2821 assert(MI.getDesc().getNumOperands() == 4 &&
2822 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
2823 return true;
2824 }
2825 break;
2826 }
2827 return false;
2828}
2829
2830// Return true if this instruction simply renames a general register without
2831// modifying bits.
2833 switch (MI.getOpcode()) {
2834 default:
2835 break;
2836 case TargetOpcode::COPY: {
2837 Register DstReg = MI.getOperand(0).getReg();
2838 return AArch64::FPR128RegClass.contains(DstReg);
2839 }
2840 case AArch64::ORRv16i8:
2841 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
2842 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
2843 "invalid ORRv16i8 operands");
2844 return true;
2845 }
2846 break;
2847 }
2848 return false;
2849}
2850
2851static bool isFrameLoadOpcode(int Opcode) {
2852 switch (Opcode) {
2853 default:
2854 return false;
2855 case AArch64::LDRWui:
2856 case AArch64::LDRXui:
2857 case AArch64::LDRBui:
2858 case AArch64::LDRHui:
2859 case AArch64::LDRSui:
2860 case AArch64::LDRDui:
2861 case AArch64::LDRQui:
2862 case AArch64::LDR_PXI:
2863 return true;
2864 }
2865}
2866
2868 int &FrameIndex) const {
2869 if (!isFrameLoadOpcode(MI.getOpcode()))
2870 return Register();
2871
2872 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2873 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2874 FrameIndex = MI.getOperand(1).getIndex();
2875 return MI.getOperand(0).getReg();
2876 }
2877 return Register();
2878}
2879
2880static bool isFrameStoreOpcode(int Opcode) {
2881 switch (Opcode) {
2882 default:
2883 return false;
2884 case AArch64::STRWui:
2885 case AArch64::STRXui:
2886 case AArch64::STRBui:
2887 case AArch64::STRHui:
2888 case AArch64::STRSui:
2889 case AArch64::STRDui:
2890 case AArch64::STRQui:
2891 case AArch64::STR_PXI:
2892 return true;
2893 }
2894}
2895
2897 int &FrameIndex) const {
2898 if (!isFrameStoreOpcode(MI.getOpcode()))
2899 return Register();
2900
2901 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2902 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2903 FrameIndex = MI.getOperand(1).getIndex();
2904 return MI.getOperand(0).getReg();
2905 }
2906 return Register();
2907}
2908
2910 int &FrameIndex) const {
2911 if (!isFrameStoreOpcode(MI.getOpcode()))
2912 return Register();
2913
2914 if (Register Reg = isStoreToStackSlot(MI, FrameIndex))
2915 return Reg;
2916
2918 if (hasStoreToStackSlot(MI, Accesses)) {
2919 if (Accesses.size() > 1)
2920 return Register();
2921
2922 FrameIndex =
2923 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2924 ->getFrameIndex();
2925 return MI.getOperand(0).getReg();
2926 }
2927 return Register();
2928}
2929
2931 int &FrameIndex) const {
2932 if (!isFrameLoadOpcode(MI.getOpcode()))
2933 return Register();
2934
2935 if (Register Reg = isLoadFromStackSlot(MI, FrameIndex))
2936 return Reg;
2937
2939 if (hasLoadFromStackSlot(MI, Accesses)) {
2940 if (Accesses.size() > 1)
2941 return Register();
2942
2943 FrameIndex =
2944 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2945 ->getFrameIndex();
2946 return MI.getOperand(0).getReg();
2947 }
2948 return Register();
2949}
2950
2951/// Check all MachineMemOperands for a hint to suppress pairing.
2953 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2954 return MMO->getFlags() & MOSuppressPair;
2955 });
2956}
2957
2958/// Set a flag on the first MachineMemOperand to suppress pairing.
2960 if (MI.memoperands_empty())
2961 return;
2962 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
2963}
2964
2965/// Check all MachineMemOperands for a hint that the load/store is strided.
2967 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2968 return MMO->getFlags() & MOStridedAccess;
2969 });
2970}
2971
2973 switch (Opc) {
2974 default:
2975 return false;
2976 case AArch64::STURSi:
2977 case AArch64::STRSpre:
2978 case AArch64::STURDi:
2979 case AArch64::STRDpre:
2980 case AArch64::STURQi:
2981 case AArch64::STRQpre:
2982 case AArch64::STURBBi:
2983 case AArch64::STURHHi:
2984 case AArch64::STURWi:
2985 case AArch64::STRWpre:
2986 case AArch64::STURXi:
2987 case AArch64::STRXpre:
2988 case AArch64::LDURSi:
2989 case AArch64::LDRSpre:
2990 case AArch64::LDURDi:
2991 case AArch64::LDRDpre:
2992 case AArch64::LDURQi:
2993 case AArch64::LDRQpre:
2994 case AArch64::LDURWi:
2995 case AArch64::LDRWpre:
2996 case AArch64::LDURXi:
2997 case AArch64::LDRXpre:
2998 case AArch64::LDRSWpre:
2999 case AArch64::LDURSWi:
3000 case AArch64::LDURHHi:
3001 case AArch64::LDURBBi:
3002 case AArch64::LDURSBWi:
3003 case AArch64::LDURSHWi:
3004 return true;
3005 }
3006}
3007
3008std::optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) {
3009 switch (Opc) {
3010 default: return {};
3011 case AArch64::PRFMui: return AArch64::PRFUMi;
3012 case AArch64::LDRXui: return AArch64::LDURXi;
3013 case AArch64::LDRWui: return AArch64::LDURWi;
3014 case AArch64::LDRBui: return AArch64::LDURBi;
3015 case AArch64::LDRHui: return AArch64::LDURHi;
3016 case AArch64::LDRSui: return AArch64::LDURSi;
3017 case AArch64::LDRDui: return AArch64::LDURDi;
3018 case AArch64::LDRQui: return AArch64::LDURQi;
3019 case AArch64::LDRBBui: return AArch64::LDURBBi;
3020 case AArch64::LDRHHui: return AArch64::LDURHHi;
3021 case AArch64::LDRSBXui: return AArch64::LDURSBXi;
3022 case AArch64::LDRSBWui: return AArch64::LDURSBWi;
3023 case AArch64::LDRSHXui: return AArch64::LDURSHXi;
3024 case AArch64::LDRSHWui: return AArch64::LDURSHWi;
3025 case AArch64::LDRSWui: return AArch64::LDURSWi;
3026 case AArch64::STRXui: return AArch64::STURXi;
3027 case AArch64::STRWui: return AArch64::STURWi;
3028 case AArch64::STRBui: return AArch64::STURBi;
3029 case AArch64::STRHui: return AArch64::STURHi;
3030 case AArch64::STRSui: return AArch64::STURSi;
3031 case AArch64::STRDui: return AArch64::STURDi;
3032 case AArch64::STRQui: return AArch64::STURQi;
3033 case AArch64::STRBBui: return AArch64::STURBBi;
3034 case AArch64::STRHHui: return AArch64::STURHHi;
3035 }
3036}
3037
3039 switch (Opc) {
3040 default:
3041 llvm_unreachable("Unhandled Opcode in getLoadStoreImmIdx");
3042 case AArch64::ADDG:
3043 case AArch64::LDAPURBi:
3044 case AArch64::LDAPURHi:
3045 case AArch64::LDAPURi:
3046 case AArch64::LDAPURSBWi:
3047 case AArch64::LDAPURSBXi:
3048 case AArch64::LDAPURSHWi:
3049 case AArch64::LDAPURSHXi:
3050 case AArch64::LDAPURSWi:
3051 case AArch64::LDAPURXi:
3052 case AArch64::LDR_PPXI:
3053 case AArch64::LDR_PXI:
3054 case AArch64::LDR_ZXI:
3055 case AArch64::LDR_ZZXI:
3056 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3057 case AArch64::LDR_ZZZXI:
3058 case AArch64::LDR_ZZZZXI:
3059 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3060 case AArch64::LDRBBui:
3061 case AArch64::LDRBui:
3062 case AArch64::LDRDui:
3063 case AArch64::LDRHHui:
3064 case AArch64::LDRHui:
3065 case AArch64::LDRQui:
3066 case AArch64::LDRSBWui:
3067 case AArch64::LDRSBXui:
3068 case AArch64::LDRSHWui:
3069 case AArch64::LDRSHXui:
3070 case AArch64::LDRSui:
3071 case AArch64::LDRSWui:
3072 case AArch64::LDRWui:
3073 case AArch64::LDRXui:
3074 case AArch64::LDURBBi:
3075 case AArch64::LDURBi:
3076 case AArch64::LDURDi:
3077 case AArch64::LDURHHi:
3078 case AArch64::LDURHi:
3079 case AArch64::LDURQi:
3080 case AArch64::LDURSBWi:
3081 case AArch64::LDURSBXi:
3082 case AArch64::LDURSHWi:
3083 case AArch64::LDURSHXi:
3084 case AArch64::LDURSi:
3085 case AArch64::LDURSWi:
3086 case AArch64::LDURWi:
3087 case AArch64::LDURXi:
3088 case AArch64::PRFMui:
3089 case AArch64::PRFUMi:
3090 case AArch64::ST2Gi:
3091 case AArch64::STGi:
3092 case AArch64::STLURBi:
3093 case AArch64::STLURHi:
3094 case AArch64::STLURWi:
3095 case AArch64::STLURXi:
3096 case AArch64::StoreSwiftAsyncContext:
3097 case AArch64::STR_PPXI:
3098 case AArch64::STR_PXI:
3099 case AArch64::STR_ZXI:
3100 case AArch64::STR_ZZXI:
3101 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3102 case AArch64::STR_ZZZXI:
3103 case AArch64::STR_ZZZZXI:
3104 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3105 case AArch64::STRBBui:
3106 case AArch64::STRBui:
3107 case AArch64::STRDui:
3108 case AArch64::STRHHui:
3109 case AArch64::STRHui:
3110 case AArch64::STRQui:
3111 case AArch64::STRSui:
3112 case AArch64::STRWui:
3113 case AArch64::STRXui:
3114 case AArch64::STURBBi:
3115 case AArch64::STURBi:
3116 case AArch64::STURDi:
3117 case AArch64::STURHHi:
3118 case AArch64::STURHi:
3119 case AArch64::STURQi:
3120 case AArch64::STURSi:
3121 case AArch64::STURWi:
3122 case AArch64::STURXi:
3123 case AArch64::STZ2Gi:
3124 case AArch64::STZGi:
3125 case AArch64::TAGPstack:
3126 return 2;
3127 case AArch64::LD1B_D_IMM:
3128 case AArch64::LD1B_H_IMM:
3129 case AArch64::LD1B_IMM:
3130 case AArch64::LD1B_S_IMM:
3131 case AArch64::LD1D_IMM:
3132 case AArch64::LD1H_D_IMM:
3133 case AArch64::LD1H_IMM:
3134 case AArch64::LD1H_S_IMM:
3135 case AArch64::LD1RB_D_IMM:
3136 case AArch64::LD1RB_H_IMM:
3137 case AArch64::LD1RB_IMM:
3138 case AArch64::LD1RB_S_IMM:
3139 case AArch64::LD1RD_IMM:
3140 case AArch64::LD1RH_D_IMM:
3141 case AArch64::LD1RH_IMM:
3142 case AArch64::LD1RH_S_IMM:
3143 case AArch64::LD1RSB_D_IMM:
3144 case AArch64::LD1RSB_H_IMM:
3145 case AArch64::LD1RSB_S_IMM:
3146 case AArch64::LD1RSH_D_IMM:
3147 case AArch64::LD1RSH_S_IMM:
3148 case AArch64::LD1RSW_IMM:
3149 case AArch64::LD1RW_D_IMM:
3150 case AArch64::LD1RW_IMM:
3151 case AArch64::LD1SB_D_IMM:
3152 case AArch64::LD1SB_H_IMM:
3153 case AArch64::LD1SB_S_IMM:
3154 case AArch64::LD1SH_D_IMM:
3155 case AArch64::LD1SH_S_IMM:
3156 case AArch64::LD1SW_D_IMM:
3157 case AArch64::LD1W_D_IMM:
3158 case AArch64::LD1W_IMM:
3159 case AArch64::LD2B_IMM:
3160 case AArch64::LD2D_IMM:
3161 case AArch64::LD2H_IMM:
3162 case AArch64::LD2W_IMM:
3163 case AArch64::LD3B_IMM:
3164 case AArch64::LD3D_IMM:
3165 case AArch64::LD3H_IMM:
3166 case AArch64::LD3W_IMM:
3167 case AArch64::LD4B_IMM:
3168 case AArch64::LD4D_IMM:
3169 case AArch64::LD4H_IMM:
3170 case AArch64::LD4W_IMM:
3171 case AArch64::LDG:
3172 case AArch64::LDNF1B_D_IMM:
3173 case AArch64::LDNF1B_H_IMM:
3174 case AArch64::LDNF1B_IMM:
3175 case AArch64::LDNF1B_S_IMM:
3176 case AArch64::LDNF1D_IMM:
3177 case AArch64::LDNF1H_D_IMM:
3178 case AArch64::LDNF1H_IMM:
3179 case AArch64::LDNF1H_S_IMM:
3180 case AArch64::LDNF1SB_D_IMM:
3181 case AArch64::LDNF1SB_H_IMM:
3182 case AArch64::LDNF1SB_S_IMM:
3183 case AArch64::LDNF1SH_D_IMM:
3184 case AArch64::LDNF1SH_S_IMM:
3185 case AArch64::LDNF1SW_D_IMM:
3186 case AArch64::LDNF1W_D_IMM:
3187 case AArch64::LDNF1W_IMM:
3188 case AArch64::LDNPDi:
3189 case AArch64::LDNPQi:
3190 case AArch64::LDNPSi:
3191 case AArch64::LDNPWi:
3192 case AArch64::LDNPXi:
3193 case AArch64::LDNT1B_ZRI:
3194 case AArch64::LDNT1D_ZRI:
3195 case AArch64::LDNT1H_ZRI:
3196 case AArch64::LDNT1W_ZRI:
3197 case AArch64::LDPDi:
3198 case AArch64::LDPQi:
3199 case AArch64::LDPSi:
3200 case AArch64::LDPWi:
3201 case AArch64::LDPXi:
3202 case AArch64::LDRBBpost:
3203 case AArch64::LDRBBpre:
3204 case AArch64::LDRBpost:
3205 case AArch64::LDRBpre:
3206 case AArch64::LDRDpost:
3207 case AArch64::LDRDpre:
3208 case AArch64::LDRHHpost:
3209 case AArch64::LDRHHpre:
3210 case AArch64::LDRHpost:
3211 case AArch64::LDRHpre:
3212 case AArch64::LDRQpost:
3213 case AArch64::LDRQpre:
3214 case AArch64::LDRSpost:
3215 case AArch64::LDRSpre:
3216 case AArch64::LDRWpost:
3217 case AArch64::LDRWpre:
3218 case AArch64::LDRXpost:
3219 case AArch64::LDRXpre:
3220 case AArch64::ST1B_D_IMM:
3221 case AArch64::ST1B_H_IMM:
3222 case AArch64::ST1B_IMM:
3223 case AArch64::ST1B_S_IMM:
3224 case AArch64::ST1D_IMM:
3225 case AArch64::ST1H_D_IMM:
3226 case AArch64::ST1H_IMM:
3227 case AArch64::ST1H_S_IMM:
3228 case AArch64::ST1W_D_IMM:
3229 case AArch64::ST1W_IMM:
3230 case AArch64::ST2B_IMM:
3231 case AArch64::ST2D_IMM:
3232 case AArch64::ST2H_IMM:
3233 case AArch64::ST2W_IMM:
3234 case AArch64::ST3B_IMM:
3235 case AArch64::ST3D_IMM:
3236 case AArch64::ST3H_IMM:
3237 case AArch64::ST3W_IMM:
3238 case AArch64::ST4B_IMM:
3239 case AArch64::ST4D_IMM:
3240 case AArch64::ST4H_IMM:
3241 case AArch64::ST4W_IMM:
3242 case AArch64::STGPi:
3243 case AArch64::STGPreIndex:
3244 case AArch64::STZGPreIndex:
3245 case AArch64::ST2GPreIndex:
3246 case AArch64::STZ2GPreIndex:
3247 case AArch64::STGPostIndex:
3248 case AArch64::STZGPostIndex:
3249 case AArch64::ST2GPostIndex:
3250 case AArch64::STZ2GPostIndex:
3251 case AArch64::STNPDi:
3252 case AArch64::STNPQi:
3253 case AArch64::STNPSi:
3254 case AArch64::STNPWi:
3255 case AArch64::STNPXi:
3256 case AArch64::STNT1B_ZRI:
3257 case AArch64::STNT1D_ZRI:
3258 case AArch64::STNT1H_ZRI:
3259 case AArch64::STNT1W_ZRI:
3260 case AArch64::STPDi:
3261 case AArch64::STPQi:
3262 case AArch64::STPSi:
3263 case AArch64::STPWi:
3264 case AArch64::STPXi:
3265 case AArch64::STRBBpost:
3266 case AArch64::STRBBpre:
3267 case AArch64::STRBpost:
3268 case AArch64::STRBpre:
3269 case AArch64::STRDpost:
3270 case AArch64::STRDpre:
3271 case AArch64::STRHHpost:
3272 case AArch64::STRHHpre:
3273 case AArch64::STRHpost:
3274 case AArch64::STRHpre:
3275 case AArch64::STRQpost:
3276 case AArch64::STRQpre:
3277 case AArch64::STRSpost:
3278 case AArch64::STRSpre:
3279 case AArch64::STRWpost:
3280 case AArch64::STRWpre:
3281 case AArch64::STRXpost:
3282 case AArch64::STRXpre:
3283 case AArch64::LD1B_2Z_IMM:
3284 case AArch64::LD1B_2Z_STRIDED_IMM:
3285 case AArch64::LD1H_2Z_IMM:
3286 case AArch64::LD1H_2Z_STRIDED_IMM:
3287 case AArch64::LD1W_2Z_IMM:
3288 case AArch64::LD1W_2Z_STRIDED_IMM:
3289 case AArch64::LD1D_2Z_IMM:
3290 case AArch64::LD1D_2Z_STRIDED_IMM:
3291 case AArch64::LD1B_4Z_IMM:
3292 case AArch64::LD1B_4Z_STRIDED_IMM:
3293 case AArch64::LD1H_4Z_IMM:
3294 case AArch64::LD1H_4Z_STRIDED_IMM:
3295 case AArch64::LD1W_4Z_IMM:
3296 case AArch64::LD1W_4Z_STRIDED_IMM:
3297 case AArch64::LD1D_4Z_IMM:
3298 case AArch64::LD1D_4Z_STRIDED_IMM:
3299 case AArch64::LD1B_2Z_IMM_PSEUDO:
3300 case AArch64::LD1H_2Z_IMM_PSEUDO:
3301 case AArch64::LD1W_2Z_IMM_PSEUDO:
3302 case AArch64::LD1D_2Z_IMM_PSEUDO:
3303 case AArch64::LD1B_4Z_IMM_PSEUDO:
3304 case AArch64::LD1H_4Z_IMM_PSEUDO:
3305 case AArch64::LD1W_4Z_IMM_PSEUDO:
3306 case AArch64::LD1D_4Z_IMM_PSEUDO:
3307 case AArch64::ST1B_2Z_IMM:
3308 case AArch64::ST1B_2Z_STRIDED_IMM:
3309 case AArch64::ST1H_2Z_IMM:
3310 case AArch64::ST1H_2Z_STRIDED_IMM:
3311 case AArch64::ST1W_2Z_IMM:
3312 case AArch64::ST1W_2Z_STRIDED_IMM:
3313 case AArch64::ST1D_2Z_IMM:
3314 case AArch64::ST1D_2Z_STRIDED_IMM:
3315 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3316 case AArch64::LDNT1B_2Z_IMM:
3317 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3318 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3319 case AArch64::LDNT1H_2Z_IMM:
3320 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3321 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3322 case AArch64::LDNT1W_2Z_IMM:
3323 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3324 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3325 case AArch64::LDNT1D_2Z_IMM:
3326 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3327 case AArch64::STNT1B_2Z_IMM:
3328 case AArch64::STNT1B_2Z_STRIDED_IMM:
3329 case AArch64::STNT1H_2Z_IMM:
3330 case AArch64::STNT1H_2Z_STRIDED_IMM:
3331 case AArch64::STNT1W_2Z_IMM:
3332 case AArch64::STNT1W_2Z_STRIDED_IMM:
3333 case AArch64::STNT1D_2Z_IMM:
3334 case AArch64::STNT1D_2Z_STRIDED_IMM:
3335 case AArch64::ST1B_2Z_IMM_PSEUDO:
3336 case AArch64::ST1H_2Z_IMM_PSEUDO:
3337 case AArch64::ST1W_2Z_IMM_PSEUDO:
3338 case AArch64::ST1D_2Z_IMM_PSEUDO:
3339 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3340 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3341 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3342 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3343 case AArch64::ST1B_4Z_IMM:
3344 case AArch64::ST1B_4Z_STRIDED_IMM:
3345 case AArch64::ST1H_4Z_IMM:
3346 case AArch64::ST1H_4Z_STRIDED_IMM:
3347 case AArch64::ST1W_4Z_IMM:
3348 case AArch64::ST1W_4Z_STRIDED_IMM:
3349 case AArch64::ST1D_4Z_IMM:
3350 case AArch64::ST1D_4Z_STRIDED_IMM:
3351 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3352 case AArch64::LDNT1B_4Z_IMM:
3353 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3354 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3355 case AArch64::LDNT1H_4Z_IMM:
3356 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3357 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3358 case AArch64::LDNT1W_4Z_IMM:
3359 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3360 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3361 case AArch64::LDNT1D_4Z_IMM:
3362 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3363 case AArch64::STNT1B_4Z_IMM:
3364 case AArch64::STNT1B_4Z_STRIDED_IMM:
3365 case AArch64::STNT1H_4Z_IMM:
3366 case AArch64::STNT1H_4Z_STRIDED_IMM:
3367 case AArch64::STNT1W_4Z_IMM:
3368 case AArch64::STNT1W_4Z_STRIDED_IMM:
3369 case AArch64::STNT1D_4Z_IMM:
3370 case AArch64::STNT1D_4Z_STRIDED_IMM:
3371 case AArch64::ST1B_4Z_IMM_PSEUDO:
3372 case AArch64::ST1H_4Z_IMM_PSEUDO:
3373 case AArch64::ST1W_4Z_IMM_PSEUDO:
3374 case AArch64::ST1D_4Z_IMM_PSEUDO:
3375 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3376 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3377 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3378 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3379 return 3;
3380 case AArch64::LDPDpost:
3381 case AArch64::LDPDpre:
3382 case AArch64::LDPQpost:
3383 case AArch64::LDPQpre:
3384 case AArch64::LDPSpost:
3385 case AArch64::LDPSpre:
3386 case AArch64::LDPWpost:
3387 case AArch64::LDPWpre:
3388 case AArch64::LDPXpost:
3389 case AArch64::LDPXpre:
3390 case AArch64::STGPpre:
3391 case AArch64::STGPpost:
3392 case AArch64::STPDpost:
3393 case AArch64::STPDpre:
3394 case AArch64::STPQpost:
3395 case AArch64::STPQpre:
3396 case AArch64::STPSpost:
3397 case AArch64::STPSpre:
3398 case AArch64::STPWpost:
3399 case AArch64::STPWpre:
3400 case AArch64::STPXpost:
3401 case AArch64::STPXpre:
3402 return 4;
3403 }
3404}
3405
3407 switch (MI.getOpcode()) {
3408 default:
3409 return false;
3410 // Scaled instructions.
3411 case AArch64::STRSui:
3412 case AArch64::STRDui:
3413 case AArch64::STRQui:
3414 case AArch64::STRXui:
3415 case AArch64::STRWui:
3416 case AArch64::LDRSui:
3417 case AArch64::LDRDui:
3418 case AArch64::LDRQui:
3419 case AArch64::LDRXui:
3420 case AArch64::LDRWui:
3421 case AArch64::LDRSWui:
3422 // Unscaled instructions.
3423 case AArch64::STURSi:
3424 case AArch64::STRSpre:
3425 case AArch64::STURDi:
3426 case AArch64::STRDpre:
3427 case AArch64::STURQi:
3428 case AArch64::STRQpre:
3429 case AArch64::STURWi:
3430 case AArch64::STRWpre:
3431 case AArch64::STURXi:
3432 case AArch64::STRXpre:
3433 case AArch64::LDURSi:
3434 case AArch64::LDRSpre:
3435 case AArch64::LDURDi:
3436 case AArch64::LDRDpre:
3437 case AArch64::LDURQi:
3438 case AArch64::LDRQpre:
3439 case AArch64::LDURWi:
3440 case AArch64::LDRWpre:
3441 case AArch64::LDURXi:
3442 case AArch64::LDRXpre:
3443 case AArch64::LDURSWi:
3444 case AArch64::LDRSWpre:
3445 // SVE instructions.
3446 case AArch64::LDR_ZXI:
3447 case AArch64::STR_ZXI:
3448 return true;
3449 }
3450}
3451
3453 switch (MI.getOpcode()) {
3454 default:
3455 assert((!MI.isCall() || !MI.isReturn()) &&
3456 "Unexpected instruction - was a new tail call opcode introduced?");
3457 return false;
3458 case AArch64::TCRETURNdi:
3459 case AArch64::TCRETURNri:
3460 case AArch64::TCRETURNrix16x17:
3461 case AArch64::TCRETURNrix17:
3462 case AArch64::TCRETURNrinotx16:
3463 case AArch64::TCRETURNriALL:
3464 case AArch64::AUTH_TCRETURN:
3465 case AArch64::AUTH_TCRETURN_BTI:
3466 return true;
3467 }
3468}
3469
3471 switch (Opc) {
3472 default:
3473 llvm_unreachable("Opcode has no flag setting equivalent!");
3474 // 32-bit cases:
3475 case AArch64::ADDWri:
3476 return AArch64::ADDSWri;
3477 case AArch64::ADDWrr:
3478 return AArch64::ADDSWrr;
3479 case AArch64::ADDWrs:
3480 return AArch64::ADDSWrs;
3481 case AArch64::ADDWrx:
3482 return AArch64::ADDSWrx;
3483 case AArch64::ANDWri:
3484 return AArch64::ANDSWri;
3485 case AArch64::ANDWrr:
3486 return AArch64::ANDSWrr;
3487 case AArch64::ANDWrs:
3488 return AArch64::ANDSWrs;
3489 case AArch64::BICWrr:
3490 return AArch64::BICSWrr;
3491 case AArch64::BICWrs:
3492 return AArch64::BICSWrs;
3493 case AArch64::SUBWri:
3494 return AArch64::SUBSWri;
3495 case AArch64::SUBWrr:
3496 return AArch64::SUBSWrr;
3497 case AArch64::SUBWrs:
3498 return AArch64::SUBSWrs;
3499 case AArch64::SUBWrx:
3500 return AArch64::SUBSWrx;
3501 // 64-bit cases:
3502 case AArch64::ADDXri:
3503 return AArch64::ADDSXri;
3504 case AArch64::ADDXrr:
3505 return AArch64::ADDSXrr;
3506 case AArch64::ADDXrs:
3507 return AArch64::ADDSXrs;
3508 case AArch64::ADDXrx:
3509 return AArch64::ADDSXrx;
3510 case AArch64::ANDXri:
3511 return AArch64::ANDSXri;
3512 case AArch64::ANDXrr:
3513 return AArch64::ANDSXrr;
3514 case AArch64::ANDXrs:
3515 return AArch64::ANDSXrs;
3516 case AArch64::BICXrr:
3517 return AArch64::BICSXrr;
3518 case AArch64::BICXrs:
3519 return AArch64::BICSXrs;
3520 case AArch64::SUBXri:
3521 return AArch64::SUBSXri;
3522 case AArch64::SUBXrr:
3523 return AArch64::SUBSXrr;
3524 case AArch64::SUBXrs:
3525 return AArch64::SUBSXrs;
3526 case AArch64::SUBXrx:
3527 return AArch64::SUBSXrx;
3528 // SVE instructions:
3529 case AArch64::AND_PPzPP:
3530 return AArch64::ANDS_PPzPP;
3531 case AArch64::BIC_PPzPP:
3532 return AArch64::BICS_PPzPP;
3533 case AArch64::EOR_PPzPP:
3534 return AArch64::EORS_PPzPP;
3535 case AArch64::NAND_PPzPP:
3536 return AArch64::NANDS_PPzPP;
3537 case AArch64::NOR_PPzPP:
3538 return AArch64::NORS_PPzPP;
3539 case AArch64::ORN_PPzPP:
3540 return AArch64::ORNS_PPzPP;
3541 case AArch64::ORR_PPzPP:
3542 return AArch64::ORRS_PPzPP;
3543 case AArch64::BRKA_PPzP:
3544 return AArch64::BRKAS_PPzP;
3545 case AArch64::BRKPA_PPzPP:
3546 return AArch64::BRKPAS_PPzPP;
3547 case AArch64::BRKB_PPzP:
3548 return AArch64::BRKBS_PPzP;
3549 case AArch64::BRKPB_PPzPP:
3550 return AArch64::BRKPBS_PPzPP;
3551 case AArch64::BRKN_PPzP:
3552 return AArch64::BRKNS_PPzP;
3553 case AArch64::RDFFR_PPz:
3554 return AArch64::RDFFRS_PPz;
3555 case AArch64::PTRUE_B:
3556 return AArch64::PTRUES_B;
3557 }
3558}
3559
3560// Is this a candidate for ld/st merging or pairing? For example, we don't
3561// touch volatiles or load/stores that have a hint to avoid pair formation.
3563
3564 bool IsPreLdSt = isPreLdSt(MI);
3565
3566 // If this is a volatile load/store, don't mess with it.
3567 if (MI.hasOrderedMemoryRef())
3568 return false;
3569
3570 // Make sure this is a reg/fi+imm (as opposed to an address reloc).
3571 // For Pre-inc LD/ST, the operand is shifted by one.
3572 assert((MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3573 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3574 "Expected a reg or frame index operand.");
3575
3576 // For Pre-indexed addressing quadword instructions, the third operand is the
3577 // immediate value.
3578 bool IsImmPreLdSt = IsPreLdSt && MI.getOperand(3).isImm();
3579
3580 if (!MI.getOperand(2).isImm() && !IsImmPreLdSt)
3581 return false;
3582
3583 // Can't merge/pair if the instruction modifies the base register.
3584 // e.g., ldr x0, [x0]
3585 // This case will never occur with an FI base.
3586 // However, if the instruction is an LDR<S,D,Q,W,X,SW>pre or
3587 // STR<S,D,Q,W,X>pre, it can be merged.
3588 // For example:
3589 // ldr q0, [x11, #32]!
3590 // ldr q1, [x11, #16]
3591 // to
3592 // ldp q0, q1, [x11, #32]!
3593 if (MI.getOperand(1).isReg() && !IsPreLdSt) {
3594 Register BaseReg = MI.getOperand(1).getReg();
3596 if (MI.modifiesRegister(BaseReg, TRI))
3597 return false;
3598 }
3599
3600 // Pairing SVE fills/spills is only valid for little-endian targets that
3601 // implement VLS 128.
3602 switch (MI.getOpcode()) {
3603 default:
3604 break;
3605 case AArch64::LDR_ZXI:
3606 case AArch64::STR_ZXI:
3607 if (!Subtarget.isLittleEndian() ||
3608 Subtarget.getSVEVectorSizeInBits() != 128)
3609 return false;
3610 }
3611
3612 // Check if this load/store has a hint to avoid pair formation.
3613 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
3615 return false;
3616
3617 // Do not pair any callee-save store/reload instructions in the
3618 // prologue/epilogue if the CFI information encoded the operations as separate
3619 // instructions, as that will cause the size of the actual prologue to mismatch
3620 // with the prologue size recorded in the Windows CFI.
3621 const MCAsmInfo &MAI = MI.getMF()->getTarget().getMCAsmInfo();
3622 bool NeedsWinCFI =
3623 MAI.usesWindowsCFI() && MI.getMF()->getFunction().needsUnwindTableEntry();
3624 if (NeedsWinCFI && (MI.getFlag(MachineInstr::FrameSetup) ||
3626 return false;
3627
3628 // On some CPUs quad load/store pairs are slower than two single load/stores.
3629 if (Subtarget.isPaired128Slow()) {
3630 switch (MI.getOpcode()) {
3631 default:
3632 break;
3633 case AArch64::LDURQi:
3634 case AArch64::STURQi:
3635 case AArch64::LDRQui:
3636 case AArch64::STRQui:
3637 return false;
3638 }
3639 }
3640
3641 return true;
3642}
3643
3646 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
3647 const TargetRegisterInfo *TRI) const {
3648 if (!LdSt.mayLoadOrStore())
3649 return false;
3650
3651 const MachineOperand *BaseOp;
3652 TypeSize WidthN(0, false);
3653 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, OffsetIsScalable,
3654 WidthN, TRI))
3655 return false;
3656 // The maximum vscale is 16 under AArch64, return the maximal extent for the
3657 // vector.
3658 Width = LocationSize::precise(WidthN);
3659 BaseOps.push_back(BaseOp);
3660 return true;
3661}
3662
3663std::optional<ExtAddrMode>
3665 const TargetRegisterInfo *TRI) const {
3666 const MachineOperand *Base; // Filled with the base operand of MI.
3667 int64_t Offset; // Filled with the offset of MI.
3668 bool OffsetIsScalable;
3669 if (!getMemOperandWithOffset(MemI, Base, Offset, OffsetIsScalable, TRI))
3670 return std::nullopt;
3671
3672 if (!Base->isReg())
3673 return std::nullopt;
3674 ExtAddrMode AM;
3675 AM.BaseReg = Base->getReg();
3676 AM.Displacement = Offset;
3677 AM.ScaledReg = 0;
3678 AM.Scale = 0;
3679 return AM;
3680}
3681
3683 Register Reg,
3684 const MachineInstr &AddrI,
3685 ExtAddrMode &AM) const {
3686 // Filter out instructions into which we cannot fold.
3687 unsigned NumBytes;
3688 int64_t OffsetScale = 1;
3689 switch (MemI.getOpcode()) {
3690 default:
3691 return false;
3692
3693 case AArch64::LDURQi:
3694 case AArch64::STURQi:
3695 NumBytes = 16;
3696 break;
3697
3698 case AArch64::LDURDi:
3699 case AArch64::STURDi:
3700 case AArch64::LDURXi:
3701 case AArch64::STURXi:
3702 NumBytes = 8;
3703 break;
3704
3705 case AArch64::LDURWi:
3706 case AArch64::LDURSWi:
3707 case AArch64::STURWi:
3708 NumBytes = 4;
3709 break;
3710
3711 case AArch64::LDURHi:
3712 case AArch64::STURHi:
3713 case AArch64::LDURHHi:
3714 case AArch64::STURHHi:
3715 case AArch64::LDURSHXi:
3716 case AArch64::LDURSHWi:
3717 NumBytes = 2;
3718 break;
3719
3720 case AArch64::LDRBroX:
3721 case AArch64::LDRBBroX:
3722 case AArch64::LDRSBXroX:
3723 case AArch64::LDRSBWroX:
3724 case AArch64::STRBroX:
3725 case AArch64::STRBBroX:
3726 case AArch64::LDURBi:
3727 case AArch64::LDURBBi:
3728 case AArch64::LDURSBXi:
3729 case AArch64::LDURSBWi:
3730 case AArch64::STURBi:
3731 case AArch64::STURBBi:
3732 case AArch64::LDRBui:
3733 case AArch64::LDRBBui:
3734 case AArch64::LDRSBXui:
3735 case AArch64::LDRSBWui:
3736 case AArch64::STRBui:
3737 case AArch64::STRBBui:
3738 NumBytes = 1;
3739 break;
3740
3741 case AArch64::LDRQroX:
3742 case AArch64::STRQroX:
3743 case AArch64::LDRQui:
3744 case AArch64::STRQui:
3745 NumBytes = 16;
3746 OffsetScale = 16;
3747 break;
3748
3749 case AArch64::LDRDroX:
3750 case AArch64::STRDroX:
3751 case AArch64::LDRXroX:
3752 case AArch64::STRXroX:
3753 case AArch64::LDRDui:
3754 case AArch64::STRDui:
3755 case AArch64::LDRXui:
3756 case AArch64::STRXui:
3757 NumBytes = 8;
3758 OffsetScale = 8;
3759 break;
3760
3761 case AArch64::LDRWroX:
3762 case AArch64::LDRSWroX:
3763 case AArch64::STRWroX:
3764 case AArch64::LDRWui:
3765 case AArch64::LDRSWui:
3766 case AArch64::STRWui:
3767 NumBytes = 4;
3768 OffsetScale = 4;
3769 break;
3770
3771 case AArch64::LDRHroX:
3772 case AArch64::STRHroX:
3773 case AArch64::LDRHHroX:
3774 case AArch64::STRHHroX:
3775 case AArch64::LDRSHXroX:
3776 case AArch64::LDRSHWroX:
3777 case AArch64::LDRHui:
3778 case AArch64::STRHui:
3779 case AArch64::LDRHHui:
3780 case AArch64::STRHHui:
3781 case AArch64::LDRSHXui:
3782 case AArch64::LDRSHWui:
3783 NumBytes = 2;
3784 OffsetScale = 2;
3785 break;
3786 }
3787
3788 // Check the fold operand is not the loaded/stored value.
3789 const MachineOperand &BaseRegOp = MemI.getOperand(0);
3790 if (BaseRegOp.isReg() && BaseRegOp.getReg() == Reg)
3791 return false;
3792
3793 // Handle memory instructions with a [Reg, Reg] addressing mode.
3794 if (MemI.getOperand(2).isReg()) {
3795 // Bail if the addressing mode already includes extension of the offset
3796 // register.
3797 if (MemI.getOperand(3).getImm())
3798 return false;
3799
3800 // Check if we actually have a scaled offset.
3801 if (MemI.getOperand(4).getImm() == 0)
3802 OffsetScale = 1;
3803
3804 // If the address instructions is folded into the base register, then the
3805 // addressing mode must not have a scale. Then we can swap the base and the
3806 // scaled registers.
3807 if (MemI.getOperand(1).getReg() == Reg && OffsetScale != 1)
3808 return false;
3809
3810 switch (AddrI.getOpcode()) {
3811 default:
3812 return false;
3813
3814 case AArch64::SBFMXri:
3815 // sxtw Xa, Wm
3816 // ldr Xd, [Xn, Xa, lsl #N]
3817 // ->
3818 // ldr Xd, [Xn, Wm, sxtw #N]
3819 if (AddrI.getOperand(2).getImm() != 0 ||
3820 AddrI.getOperand(3).getImm() != 31)
3821 return false;
3822
3823 AM.BaseReg = MemI.getOperand(1).getReg();
3824 if (AM.BaseReg == Reg)
3825 AM.BaseReg = MemI.getOperand(2).getReg();
3826 AM.ScaledReg = AddrI.getOperand(1).getReg();
3827 AM.Scale = OffsetScale;
3828 AM.Displacement = 0;
3830 return true;
3831
3832 case TargetOpcode::SUBREG_TO_REG: {
3833 // mov Wa, Wm
3834 // ldr Xd, [Xn, Xa, lsl #N]
3835 // ->
3836 // ldr Xd, [Xn, Wm, uxtw #N]
3837
3838 // Zero-extension looks like an ORRWrs followed by a SUBREG_TO_REG.
3839 if (AddrI.getOperand(2).getImm() != AArch64::sub_32)
3840 return false;
3841
3842 const MachineRegisterInfo &MRI = AddrI.getMF()->getRegInfo();
3843 Register OffsetReg = AddrI.getOperand(1).getReg();
3844 if (!OffsetReg.isVirtual() || !MRI.hasOneNonDBGUse(OffsetReg))
3845 return false;
3846
3847 const MachineInstr &DefMI = *MRI.getVRegDef(OffsetReg);
3848 if (DefMI.getOpcode() != AArch64::ORRWrs ||
3849 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3850 DefMI.getOperand(3).getImm() != 0)
3851 return false;
3852
3853 AM.BaseReg = MemI.getOperand(1).getReg();
3854 if (AM.BaseReg == Reg)
3855 AM.BaseReg = MemI.getOperand(2).getReg();
3856 AM.ScaledReg = DefMI.getOperand(2).getReg();
3857 AM.Scale = OffsetScale;
3858 AM.Displacement = 0;
3860 return true;
3861 }
3862 }
3863 }
3864
3865 // Handle memory instructions with a [Reg, #Imm] addressing mode.
3866
3867 // Check we are not breaking a potential conversion to an LDP.
3868 auto validateOffsetForLDP = [](unsigned NumBytes, int64_t OldOffset,
3869 int64_t NewOffset) -> bool {
3870 int64_t MinOffset, MaxOffset;
3871 switch (NumBytes) {
3872 default:
3873 return true;
3874 case 4:
3875 MinOffset = -256;
3876 MaxOffset = 252;
3877 break;
3878 case 8:
3879 MinOffset = -512;
3880 MaxOffset = 504;
3881 break;
3882 case 16:
3883 MinOffset = -1024;
3884 MaxOffset = 1008;
3885 break;
3886 }
3887 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3888 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3889 };
3890 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) -> bool {
3891 int64_t OldOffset = MemI.getOperand(2).getImm() * OffsetScale;
3892 int64_t NewOffset = OldOffset + Disp;
3893 if (!isLegalAddressingMode(NumBytes, NewOffset, /* Scale */ 0))
3894 return false;
3895 // If the old offset would fit into an LDP, but the new offset wouldn't,
3896 // bail out.
3897 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3898 return false;
3899 AM.BaseReg = AddrI.getOperand(1).getReg();
3900 AM.ScaledReg = 0;
3901 AM.Scale = 0;
3902 AM.Displacement = NewOffset;
3904 return true;
3905 };
3906
3907 auto canFoldAddRegIntoAddrMode =
3908 [&](int64_t Scale,
3910 if (MemI.getOperand(2).getImm() != 0)
3911 return false;
3912 if ((unsigned)Scale != Scale)
3913 return false;
3914 if (!isLegalAddressingMode(NumBytes, /* Offset */ 0, Scale))
3915 return false;
3916 AM.BaseReg = AddrI.getOperand(1).getReg();
3917 AM.ScaledReg = AddrI.getOperand(2).getReg();
3918 AM.Scale = Scale;
3919 AM.Displacement = 0;
3920 AM.Form = Form;
3921 return true;
3922 };
3923
3924 auto avoidSlowSTRQ = [&](const MachineInstr &MemI) {
3925 unsigned Opcode = MemI.getOpcode();
3926 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3927 Subtarget.isSTRQroSlow();
3928 };
3929
3930 int64_t Disp = 0;
3931 const bool OptSize = MemI.getMF()->getFunction().hasOptSize();
3932 switch (AddrI.getOpcode()) {
3933 default:
3934 return false;
3935
3936 case AArch64::ADDXri:
3937 // add Xa, Xn, #N
3938 // ldr Xd, [Xa, #M]
3939 // ->
3940 // ldr Xd, [Xn, #N'+M]
3941 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3942 return canFoldAddSubImmIntoAddrMode(Disp);
3943
3944 case AArch64::SUBXri:
3945 // sub Xa, Xn, #N
3946 // ldr Xd, [Xa, #M]
3947 // ->
3948 // ldr Xd, [Xn, #N'+M]
3949 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3950 return canFoldAddSubImmIntoAddrMode(-Disp);
3951
3952 case AArch64::ADDXrs: {
3953 // add Xa, Xn, Xm, lsl #N
3954 // ldr Xd, [Xa]
3955 // ->
3956 // ldr Xd, [Xn, Xm, lsl #N]
3957
3958 // Don't fold the add if the result would be slower, unless optimising for
3959 // size.
3960 unsigned Shift = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3962 return false;
3963 Shift = AArch64_AM::getShiftValue(Shift);
3964 if (!OptSize) {
3965 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3966 return false;
3967 if (avoidSlowSTRQ(MemI))
3968 return false;
3969 }
3970 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3971 }
3972
3973 case AArch64::ADDXrr:
3974 // add Xa, Xn, Xm
3975 // ldr Xd, [Xa]
3976 // ->
3977 // ldr Xd, [Xn, Xm, lsl #0]
3978
3979 // Don't fold the add if the result would be slower, unless optimising for
3980 // size.
3981 if (!OptSize && avoidSlowSTRQ(MemI))
3982 return false;
3983 return canFoldAddRegIntoAddrMode(1);
3984
3985 case AArch64::ADDXrx:
3986 // add Xa, Xn, Wm, {s,u}xtw #N
3987 // ldr Xd, [Xa]
3988 // ->
3989 // ldr Xd, [Xn, Wm, {s,u}xtw #N]
3990
3991 // Don't fold the add if the result would be slower, unless optimising for
3992 // size.
3993 if (!OptSize && avoidSlowSTRQ(MemI))
3994 return false;
3995
3996 // Can fold only sign-/zero-extend of a word.
3997 unsigned Imm = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3999 if (Extend != AArch64_AM::UXTW && Extend != AArch64_AM::SXTW)
4000 return false;
4001
4002 return canFoldAddRegIntoAddrMode(
4006 }
4007}
4008
4009// Given an opcode for an instruction with a [Reg, #Imm] addressing mode,
4010// return the opcode of an instruction performing the same operation, but using
4011// the [Reg, Reg] addressing mode.
4012static unsigned regOffsetOpcode(unsigned Opcode) {
4013 switch (Opcode) {
4014 default:
4015 llvm_unreachable("Address folding not implemented for instruction");
4016
4017 case AArch64::LDURQi:
4018 case AArch64::LDRQui:
4019 return AArch64::LDRQroX;
4020 case AArch64::STURQi:
4021 case AArch64::STRQui:
4022 return AArch64::STRQroX;
4023 case AArch64::LDURDi:
4024 case AArch64::LDRDui:
4025 return AArch64::LDRDroX;
4026 case AArch64::STURDi:
4027 case AArch64::STRDui:
4028 return AArch64::STRDroX;
4029 case AArch64::LDURXi:
4030 case AArch64::LDRXui:
4031 return AArch64::LDRXroX;
4032 case AArch64::STURXi:
4033 case AArch64::STRXui:
4034 return AArch64::STRXroX;
4035 case AArch64::LDURWi:
4036 case AArch64::LDRWui:
4037 return AArch64::LDRWroX;
4038 case AArch64::LDURSWi:
4039 case AArch64::LDRSWui:
4040 return AArch64::LDRSWroX;
4041 case AArch64::STURWi:
4042 case AArch64::STRWui:
4043 return AArch64::STRWroX;
4044 case AArch64::LDURHi:
4045 case AArch64::LDRHui:
4046 return AArch64::LDRHroX;
4047 case AArch64::STURHi:
4048 case AArch64::STRHui:
4049 return AArch64::STRHroX;
4050 case AArch64::LDURHHi:
4051 case AArch64::LDRHHui:
4052 return AArch64::LDRHHroX;
4053 case AArch64::STURHHi:
4054 case AArch64::STRHHui:
4055 return AArch64::STRHHroX;
4056 case AArch64::LDURSHXi:
4057 case AArch64::LDRSHXui:
4058 return AArch64::LDRSHXroX;
4059 case AArch64::LDURSHWi:
4060 case AArch64::LDRSHWui:
4061 return AArch64::LDRSHWroX;
4062 case AArch64::LDURBi:
4063 case AArch64::LDRBui:
4064 return AArch64::LDRBroX;
4065 case AArch64::LDURBBi:
4066 case AArch64::LDRBBui:
4067 return AArch64::LDRBBroX;
4068 case AArch64::LDURSBXi:
4069 case AArch64::LDRSBXui:
4070 return AArch64::LDRSBXroX;
4071 case AArch64::LDURSBWi:
4072 case AArch64::LDRSBWui:
4073 return AArch64::LDRSBWroX;
4074 case AArch64::STURBi:
4075 case AArch64::STRBui:
4076 return AArch64::STRBroX;
4077 case AArch64::STURBBi:
4078 case AArch64::STRBBui:
4079 return AArch64::STRBBroX;
4080 }
4081}
4082
4083// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4084// the opcode of an instruction performing the same operation, but using the
4085// [Reg, #Imm] addressing mode with scaled offset.
4086unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale) {
4087 switch (Opcode) {
4088 default:
4089 llvm_unreachable("Address folding not implemented for instruction");
4090
4091 case AArch64::LDURQi:
4092 Scale = 16;
4093 return AArch64::LDRQui;
4094 case AArch64::STURQi:
4095 Scale = 16;
4096 return AArch64::STRQui;
4097 case AArch64::LDURDi:
4098 Scale = 8;
4099 return AArch64::LDRDui;
4100 case AArch64::STURDi:
4101 Scale = 8;
4102 return AArch64::STRDui;
4103 case AArch64::LDURXi:
4104 Scale = 8;
4105 return AArch64::LDRXui;
4106 case AArch64::STURXi:
4107 Scale = 8;
4108 return AArch64::STRXui;
4109 case AArch64::LDURWi:
4110 Scale = 4;
4111 return AArch64::LDRWui;
4112 case AArch64::LDURSWi:
4113 Scale = 4;
4114 return AArch64::LDRSWui;
4115 case AArch64::STURWi:
4116 Scale = 4;
4117 return AArch64::STRWui;
4118 case AArch64::LDURHi:
4119 Scale = 2;
4120 return AArch64::LDRHui;
4121 case AArch64::STURHi:
4122 Scale = 2;
4123 return AArch64::STRHui;
4124 case AArch64::LDURHHi:
4125 Scale = 2;
4126 return AArch64::LDRHHui;
4127 case AArch64::STURHHi:
4128 Scale = 2;
4129 return AArch64::STRHHui;
4130 case AArch64::LDURSHXi:
4131 Scale = 2;
4132 return AArch64::LDRSHXui;
4133 case AArch64::LDURSHWi:
4134 Scale = 2;
4135 return AArch64::LDRSHWui;
4136 case AArch64::LDURBi:
4137 Scale = 1;
4138 return AArch64::LDRBui;
4139 case AArch64::LDURBBi:
4140 Scale = 1;
4141 return AArch64::LDRBBui;
4142 case AArch64::LDURSBXi:
4143 Scale = 1;
4144 return AArch64::LDRSBXui;
4145 case AArch64::LDURSBWi:
4146 Scale = 1;
4147 return AArch64::LDRSBWui;
4148 case AArch64::STURBi:
4149 Scale = 1;
4150 return AArch64::STRBui;
4151 case AArch64::STURBBi:
4152 Scale = 1;
4153 return AArch64::STRBBui;
4154 case AArch64::LDRQui:
4155 case AArch64::STRQui:
4156 Scale = 16;
4157 return Opcode;
4158 case AArch64::LDRDui:
4159 case AArch64::STRDui:
4160 case AArch64::LDRXui:
4161 case AArch64::STRXui:
4162 Scale = 8;
4163 return Opcode;
4164 case AArch64::LDRWui:
4165 case AArch64::LDRSWui:
4166 case AArch64::STRWui:
4167 Scale = 4;
4168 return Opcode;
4169 case AArch64::LDRHui:
4170 case AArch64::STRHui:
4171 case AArch64::LDRHHui:
4172 case AArch64::STRHHui:
4173 case AArch64::LDRSHXui:
4174 case AArch64::LDRSHWui:
4175 Scale = 2;
4176 return Opcode;
4177 case AArch64::LDRBui:
4178 case AArch64::LDRBBui:
4179 case AArch64::LDRSBXui:
4180 case AArch64::LDRSBWui:
4181 case AArch64::STRBui:
4182 case AArch64::STRBBui:
4183 Scale = 1;
4184 return Opcode;
4185 }
4186}
4187
4188// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4189// the opcode of an instruction performing the same operation, but using the
4190// [Reg, #Imm] addressing mode with unscaled offset.
4191unsigned unscaledOffsetOpcode(unsigned Opcode) {
4192 switch (Opcode) {
4193 default:
4194 llvm_unreachable("Address folding not implemented for instruction");
4195
4196 case AArch64::LDURQi:
4197 case AArch64::STURQi:
4198 case AArch64::LDURDi:
4199 case AArch64::STURDi:
4200 case AArch64::LDURXi:
4201 case AArch64::STURXi:
4202 case AArch64::LDURWi:
4203 case AArch64::LDURSWi:
4204 case AArch64::STURWi:
4205 case AArch64::LDURHi:
4206 case AArch64::STURHi:
4207 case AArch64::LDURHHi:
4208 case AArch64::STURHHi:
4209 case AArch64::LDURSHXi:
4210 case AArch64::LDURSHWi:
4211 case AArch64::LDURBi:
4212 case AArch64::STURBi:
4213 case AArch64::LDURBBi:
4214 case AArch64::STURBBi:
4215 case AArch64::LDURSBWi:
4216 case AArch64::LDURSBXi:
4217 return Opcode;
4218 case AArch64::LDRQui:
4219 return AArch64::LDURQi;
4220 case AArch64::STRQui:
4221 return AArch64::STURQi;
4222 case AArch64::LDRDui:
4223 return AArch64::LDURDi;
4224 case AArch64::STRDui:
4225 return AArch64::STURDi;
4226 case AArch64::LDRXui:
4227 return AArch64::LDURXi;
4228 case AArch64::STRXui:
4229 return AArch64::STURXi;
4230 case AArch64::LDRWui:
4231 return AArch64::LDURWi;
4232 case AArch64::LDRSWui:
4233 return AArch64::LDURSWi;
4234 case AArch64::STRWui:
4235 return AArch64::STURWi;
4236 case AArch64::LDRHui:
4237 return AArch64::LDURHi;
4238 case AArch64::STRHui:
4239 return AArch64::STURHi;
4240 case AArch64::LDRHHui:
4241 return AArch64::LDURHHi;
4242 case AArch64::STRHHui:
4243 return AArch64::STURHHi;
4244 case AArch64::LDRSHXui:
4245 return AArch64::LDURSHXi;
4246 case AArch64::LDRSHWui:
4247 return AArch64::LDURSHWi;
4248 case AArch64::LDRBBui:
4249 return AArch64::LDURBBi;
4250 case AArch64::LDRBui:
4251 return AArch64::LDURBi;
4252 case AArch64::STRBBui:
4253 return AArch64::STURBBi;
4254 case AArch64::STRBui:
4255 return AArch64::STURBi;
4256 case AArch64::LDRSBWui:
4257 return AArch64::LDURSBWi;
4258 case AArch64::LDRSBXui:
4259 return AArch64::LDURSBXi;
4260 }
4261}
4262
4263// Given the opcode of a memory load/store instruction, return the opcode of an
4264// instruction performing the same operation, but using
4265// the [Reg, Reg, {s,u}xtw #N] addressing mode with sign-/zero-extend of the
4266// offset register.
4267static unsigned offsetExtendOpcode(unsigned Opcode) {
4268 switch (Opcode) {
4269 default:
4270 llvm_unreachable("Address folding not implemented for instruction");
4271
4272 case AArch64::LDRQroX:
4273 case AArch64::LDURQi:
4274 case AArch64::LDRQui:
4275 return AArch64::LDRQroW;
4276 case AArch64::STRQroX:
4277 case AArch64::STURQi:
4278 case AArch64::STRQui:
4279 return AArch64::STRQroW;
4280 case AArch64::LDRDroX:
4281 case AArch64::LDURDi:
4282 case AArch64::LDRDui:
4283 return AArch64::LDRDroW;
4284 case AArch64::STRDroX:
4285 case AArch64::STURDi:
4286 case AArch64::STRDui:
4287 return AArch64::STRDroW;
4288 case AArch64::LDRXroX:
4289 case AArch64::LDURXi:
4290 case AArch64::LDRXui:
4291 return AArch64::LDRXroW;
4292 case AArch64::STRXroX:
4293 case AArch64::STURXi:
4294 case AArch64::STRXui:
4295 return AArch64::STRXroW;
4296 case AArch64::LDRWroX:
4297 case AArch64::LDURWi:
4298 case AArch64::LDRWui:
4299 return AArch64::LDRWroW;
4300 case AArch64::LDRSWroX:
4301 case AArch64::LDURSWi:
4302 case AArch64::LDRSWui:
4303 return AArch64::LDRSWroW;
4304 case AArch64::STRWroX:
4305 case AArch64::STURWi:
4306 case AArch64::STRWui:
4307 return AArch64::STRWroW;
4308 case AArch64::LDRHroX:
4309 case AArch64::LDURHi:
4310 case AArch64::LDRHui:
4311 return AArch64::LDRHroW;
4312 case AArch64::STRHroX:
4313 case AArch64::STURHi:
4314 case AArch64::STRHui:
4315 return AArch64::STRHroW;
4316 case AArch64::LDRHHroX:
4317 case AArch64::LDURHHi:
4318 case AArch64::LDRHHui:
4319 return AArch64::LDRHHroW;
4320 case AArch64::STRHHroX:
4321 case AArch64::STURHHi:
4322 case AArch64::STRHHui:
4323 return AArch64::STRHHroW;
4324 case AArch64::LDRSHXroX:
4325 case AArch64::LDURSHXi:
4326 case AArch64::LDRSHXui:
4327 return AArch64::LDRSHXroW;
4328 case AArch64::LDRSHWroX:
4329 case AArch64::LDURSHWi:
4330 case AArch64::LDRSHWui:
4331 return AArch64::LDRSHWroW;
4332 case AArch64::LDRBroX:
4333 case AArch64::LDURBi:
4334 case AArch64::LDRBui:
4335 return AArch64::LDRBroW;
4336 case AArch64::LDRBBroX:
4337 case AArch64::LDURBBi:
4338 case AArch64::LDRBBui:
4339 return AArch64::LDRBBroW;
4340 case AArch64::LDRSBXroX:
4341 case AArch64::LDURSBXi:
4342 case AArch64::LDRSBXui:
4343 return AArch64::LDRSBXroW;
4344 case AArch64::LDRSBWroX:
4345 case AArch64::LDURSBWi:
4346 case AArch64::LDRSBWui:
4347 return AArch64::LDRSBWroW;
4348 case AArch64::STRBroX:
4349 case AArch64::STURBi:
4350 case AArch64::STRBui:
4351 return AArch64::STRBroW;
4352 case AArch64::STRBBroX:
4353 case AArch64::STURBBi:
4354 case AArch64::STRBBui:
4355 return AArch64::STRBBroW;
4356 }
4357}
4358
4360 const ExtAddrMode &AM) const {
4361
4362 const DebugLoc &DL = MemI.getDebugLoc();
4363 MachineBasicBlock &MBB = *MemI.getParent();
4364 MachineRegisterInfo &MRI = MemI.getMF()->getRegInfo();
4365
4367 if (AM.ScaledReg) {
4368 // The new instruction will be in the form `ldr Rt, [Xn, Xm, lsl #imm]`.
4369 unsigned Opcode = regOffsetOpcode(MemI.getOpcode());
4370 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4371 auto B = BuildMI(MBB, MemI, DL, get(Opcode))
4372 .addReg(MemI.getOperand(0).getReg(),
4373 getDefRegState(MemI.mayLoad()))
4374 .addReg(AM.BaseReg)
4375 .addReg(AM.ScaledReg)
4376 .addImm(0)
4377 .addImm(AM.Scale > 1)
4378 .setMemRefs(MemI.memoperands())
4379 .setMIFlags(MemI.getFlags());
4380 return B.getInstr();
4381 }
4382
4383 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
4384 "Addressing mode not supported for folding");
4385
4386 // The new instruction will be in the form `ld[u]r Rt, [Xn, #imm]`.
4387 unsigned Scale = 1;
4388 unsigned Opcode = MemI.getOpcode();
4389 if (isInt<9>(AM.Displacement))
4390 Opcode = unscaledOffsetOpcode(Opcode);
4391 else
4392 Opcode = scaledOffsetOpcode(Opcode, Scale);
4393
4394 auto B =
4395 BuildMI(MBB, MemI, DL, get(Opcode))
4396 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4397 .addReg(AM.BaseReg)
4398 .addImm(AM.Displacement / Scale)
4399 .setMemRefs(MemI.memoperands())
4400 .setMIFlags(MemI.getFlags());
4401 return B.getInstr();
4402 }
4403
4406 // The new instruction will be in the form `ldr Rt, [Xn, Wm, {s,u}xtw #N]`.
4407 assert(AM.ScaledReg && !AM.Displacement &&
4408 "Address offset can be a register or an immediate, but not both");
4409 unsigned Opcode = offsetExtendOpcode(MemI.getOpcode());
4410 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4411 // Make sure the offset register is in the correct register class.
4412 Register OffsetReg = AM.ScaledReg;
4413 const TargetRegisterClass *RC = MRI.getRegClass(OffsetReg);
4414 if (RC->hasSuperClassEq(&AArch64::GPR64RegClass)) {
4415 OffsetReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
4416 BuildMI(MBB, MemI, DL, get(TargetOpcode::COPY), OffsetReg)
4417 .addReg(AM.ScaledReg, {}, AArch64::sub_32);
4418 }
4419 auto B =
4420 BuildMI(MBB, MemI, DL, get(Opcode))
4421 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4422 .addReg(AM.BaseReg)
4423 .addReg(OffsetReg)
4425 .addImm(AM.Scale != 1)
4426 .setMemRefs(MemI.memoperands())
4427 .setMIFlags(MemI.getFlags());
4428
4429 return B.getInstr();
4430 }
4431
4433 "Function must not be called with an addressing mode it can't handle");
4434}
4435
4436/// Return true if the opcode is a post-index ld/st instruction, which really
4437/// loads from base+0.
4438static bool isPostIndexLdStOpcode(unsigned Opcode) {
4439 switch (Opcode) {
4440 default:
4441 return false;
4442 case AArch64::LD1Fourv16b_POST:
4443 case AArch64::LD1Fourv1d_POST:
4444 case AArch64::LD1Fourv2d_POST:
4445 case AArch64::LD1Fourv2s_POST:
4446 case AArch64::LD1Fourv4h_POST:
4447 case AArch64::LD1Fourv4s_POST:
4448 case AArch64::LD1Fourv8b_POST:
4449 case AArch64::LD1Fourv8h_POST:
4450 case AArch64::LD1Onev16b_POST:
4451 case AArch64::LD1Onev1d_POST:
4452 case AArch64::LD1Onev2d_POST:
4453 case AArch64::LD1Onev2s_POST:
4454 case AArch64::LD1Onev4h_POST:
4455 case AArch64::LD1Onev4s_POST:
4456 case AArch64::LD1Onev8b_POST:
4457 case AArch64::LD1Onev8h_POST:
4458 case AArch64::LD1Rv16b_POST:
4459 case AArch64::LD1Rv1d_POST:
4460 case AArch64::LD1Rv2d_POST:
4461 case AArch64::LD1Rv2s_POST:
4462 case AArch64::LD1Rv4h_POST:
4463 case AArch64::LD1Rv4s_POST:
4464 case AArch64::LD1Rv8b_POST:
4465 case AArch64::LD1Rv8h_POST:
4466 case AArch64::LD1Threev16b_POST:
4467 case AArch64::LD1Threev1d_POST:
4468 case AArch64::LD1Threev2d_POST:
4469 case AArch64::LD1Threev2s_POST:
4470 case AArch64::LD1Threev4h_POST:
4471 case AArch64::LD1Threev4s_POST:
4472 case AArch64::LD1Threev8b_POST:
4473 case AArch64::LD1Threev8h_POST:
4474 case AArch64::LD1Twov16b_POST:
4475 case AArch64::LD1Twov1d_POST:
4476 case AArch64::LD1Twov2d_POST:
4477 case AArch64::LD1Twov2s_POST:
4478 case AArch64::LD1Twov4h_POST:
4479 case AArch64::LD1Twov4s_POST:
4480 case AArch64::LD1Twov8b_POST:
4481 case AArch64::LD1Twov8h_POST:
4482 case AArch64::LD1i16_POST:
4483 case AArch64::LD1i32_POST:
4484 case AArch64::LD1i64_POST:
4485 case AArch64::LD1i8_POST:
4486 case AArch64::LD2Rv16b_POST:
4487 case AArch64::LD2Rv1d_POST:
4488 case AArch64::LD2Rv2d_POST:
4489 case AArch64::LD2Rv2s_POST:
4490 case AArch64::LD2Rv4h_POST:
4491 case AArch64::LD2Rv4s_POST:
4492 case AArch64::LD2Rv8b_POST:
4493 case AArch64::LD2Rv8h_POST:
4494 case AArch64::LD2Twov16b_POST:
4495 case AArch64::LD2Twov2d_POST:
4496 case AArch64::LD2Twov2s_POST:
4497 case AArch64::LD2Twov4h_POST:
4498 case AArch64::LD2Twov4s_POST:
4499 case AArch64::LD2Twov8b_POST:
4500 case AArch64::LD2Twov8h_POST:
4501 case AArch64::LD2i16_POST:
4502 case AArch64::LD2i32_POST:
4503 case AArch64::LD2i64_POST:
4504 case AArch64::LD2i8_POST:
4505 case AArch64::LD3Rv16b_POST:
4506 case AArch64::LD3Rv1d_POST:
4507 case AArch64::LD3Rv2d_POST:
4508 case AArch64::LD3Rv2s_POST:
4509 case AArch64::LD3Rv4h_POST:
4510 case AArch64::LD3Rv4s_POST:
4511 case AArch64::LD3Rv8b_POST:
4512 case AArch64::LD3Rv8h_POST:
4513 case AArch64::LD3Threev16b_POST:
4514 case AArch64::LD3Threev2d_POST:
4515 case AArch64::LD3Threev2s_POST:
4516 case AArch64::LD3Threev4h_POST:
4517 case AArch64::LD3Threev4s_POST:
4518 case AArch64::LD3Threev8b_POST:
4519 case AArch64::LD3Threev8h_POST:
4520 case AArch64::LD3i16_POST:
4521 case AArch64::LD3i32_POST:
4522 case AArch64::LD3i64_POST:
4523 case AArch64::LD3i8_POST:
4524 case AArch64::LD4Fourv16b_POST:
4525 case AArch64::LD4Fourv2d_POST:
4526 case AArch64::LD4Fourv2s_POST:
4527 case AArch64::LD4Fourv4h_POST:
4528 case AArch64::LD4Fourv4s_POST:
4529 case AArch64::LD4Fourv8b_POST:
4530 case AArch64::LD4Fourv8h_POST:
4531 case AArch64::LD4Rv16b_POST:
4532 case AArch64::LD4Rv1d_POST:
4533 case AArch64::LD4Rv2d_POST:
4534 case AArch64::LD4Rv2s_POST:
4535 case AArch64::LD4Rv4h_POST:
4536 case AArch64::LD4Rv4s_POST:
4537 case AArch64::LD4Rv8b_POST:
4538 case AArch64::LD4Rv8h_POST:
4539 case AArch64::LD4i16_POST:
4540 case AArch64::LD4i32_POST:
4541 case AArch64::LD4i64_POST:
4542 case AArch64::LD4i8_POST:
4543 case AArch64::LDAPRWpost:
4544 case AArch64::LDAPRXpost:
4545 case AArch64::LDIAPPWpost:
4546 case AArch64::LDIAPPXpost:
4547 case AArch64::LDPDpost:
4548 case AArch64::LDPQpost:
4549 case AArch64::LDPSWpost:
4550 case AArch64::LDPSpost:
4551 case AArch64::LDPWpost:
4552 case AArch64::LDPXpost:
4553 case AArch64::LDRBBpost:
4554 case AArch64::LDRBpost:
4555 case AArch64::LDRDpost:
4556 case AArch64::LDRHHpost:
4557 case AArch64::LDRHpost:
4558 case AArch64::LDRQpost:
4559 case AArch64::LDRSBWpost:
4560 case AArch64::LDRSBXpost:
4561 case AArch64::LDRSHWpost:
4562 case AArch64::LDRSHXpost:
4563 case AArch64::LDRSWpost:
4564 case AArch64::LDRSpost:
4565 case AArch64::LDRWpost:
4566 case AArch64::LDRXpost:
4567 case AArch64::ST1Fourv16b_POST:
4568 case AArch64::ST1Fourv1d_POST:
4569 case AArch64::ST1Fourv2d_POST:
4570 case AArch64::ST1Fourv2s_POST:
4571 case AArch64::ST1Fourv4h_POST:
4572 case AArch64::ST1Fourv4s_POST:
4573 case AArch64::ST1Fourv8b_POST:
4574 case AArch64::ST1Fourv8h_POST:
4575 case AArch64::ST1Onev16b_POST:
4576 case AArch64::ST1Onev1d_POST:
4577 case AArch64::ST1Onev2d_POST:
4578 case AArch64::ST1Onev2s_POST:
4579 case AArch64::ST1Onev4h_POST:
4580 case AArch64::ST1Onev4s_POST:
4581 case AArch64::ST1Onev8b_POST:
4582 case AArch64::ST1Onev8h_POST:
4583 case AArch64::ST1Threev16b_POST:
4584 case AArch64::ST1Threev1d_POST:
4585 case AArch64::ST1Threev2d_POST:
4586 case AArch64::ST1Threev2s_POST:
4587 case AArch64::ST1Threev4h_POST:
4588 case AArch64::ST1Threev4s_POST:
4589 case AArch64::ST1Threev8b_POST:
4590 case AArch64::ST1Threev8h_POST:
4591 case AArch64::ST1Twov16b_POST:
4592 case AArch64::ST1Twov1d_POST:
4593 case AArch64::ST1Twov2d_POST:
4594 case AArch64::ST1Twov2s_POST:
4595 case AArch64::ST1Twov4h_POST:
4596 case AArch64::ST1Twov4s_POST:
4597 case AArch64::ST1Twov8b_POST:
4598 case AArch64::ST1Twov8h_POST:
4599 case AArch64::ST1i16_POST:
4600 case AArch64::ST1i32_POST:
4601 case AArch64::ST1i64_POST:
4602 case AArch64::ST1i8_POST:
4603 case AArch64::ST2GPostIndex:
4604 case AArch64::ST2Twov16b_POST:
4605 case AArch64::ST2Twov2d_POST:
4606 case AArch64::ST2Twov2s_POST:
4607 case AArch64::ST2Twov4h_POST:
4608 case AArch64::ST2Twov4s_POST:
4609 case AArch64::ST2Twov8b_POST:
4610 case AArch64::ST2Twov8h_POST:
4611 case AArch64::ST2i16_POST:
4612 case AArch64::ST2i32_POST:
4613 case AArch64::ST2i64_POST:
4614 case AArch64::ST2i8_POST:
4615 case AArch64::ST3Threev16b_POST:
4616 case AArch64::ST3Threev2d_POST:
4617 case AArch64::ST3Threev2s_POST:
4618 case AArch64::ST3Threev4h_POST:
4619 case AArch64::ST3Threev4s_POST:
4620 case AArch64::ST3Threev8b_POST:
4621 case AArch64::ST3Threev8h_POST:
4622 case AArch64::ST3i16_POST:
4623 case AArch64::ST3i32_POST:
4624 case AArch64::ST3i64_POST:
4625 case AArch64::ST3i8_POST:
4626 case AArch64::ST4Fourv16b_POST:
4627 case AArch64::ST4Fourv2d_POST:
4628 case AArch64::ST4Fourv2s_POST:
4629 case AArch64::ST4Fourv4h_POST:
4630 case AArch64::ST4Fourv4s_POST:
4631 case AArch64::ST4Fourv8b_POST:
4632 case AArch64::ST4Fourv8h_POST:
4633 case AArch64::ST4i16_POST:
4634 case AArch64::ST4i32_POST:
4635 case AArch64::ST4i64_POST:
4636 case AArch64::ST4i8_POST:
4637 case AArch64::STGPostIndex:
4638 case AArch64::STGPpost:
4639 case AArch64::STPDpost:
4640 case AArch64::STPQpost:
4641 case AArch64::STPSpost:
4642 case AArch64::STPWpost:
4643 case AArch64::STPXpost:
4644 case AArch64::STRBBpost:
4645 case AArch64::STRBpost:
4646 case AArch64::STRDpost:
4647 case AArch64::STRHHpost:
4648 case AArch64::STRHpost:
4649 case AArch64::STRQpost:
4650 case AArch64::STRSpost:
4651 case AArch64::STRWpost:
4652 case AArch64::STRXpost:
4653 case AArch64::STZ2GPostIndex:
4654 case AArch64::STZGPostIndex:
4655 return true;
4656 }
4657}
4658
4660 const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset,
4661 bool &OffsetIsScalable, TypeSize &Width,
4662 const TargetRegisterInfo *TRI) const {
4663 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4664 // Handle only loads/stores with base register followed by immediate offset.
4665 if (LdSt.getNumExplicitOperands() == 3) {
4666 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
4667 if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
4668 !LdSt.getOperand(2).isImm())
4669 return false;
4670 } else if (LdSt.getNumExplicitOperands() == 4) {
4671 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
4672 if (!LdSt.getOperand(1).isReg() ||
4673 (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI()) ||
4674 !LdSt.getOperand(3).isImm())
4675 return false;
4676 } else
4677 return false;
4678
4679 // Get the scaling factor for the instruction and set the width for the
4680 // instruction.
4681 TypeSize Scale(0U, false);
4682 int64_t Dummy1, Dummy2;
4683
4684 // If this returns false, then it's an instruction we don't want to handle.
4685 if (!getMemOpInfo(LdSt.getOpcode(), Scale, Width, Dummy1, Dummy2))
4686 return false;
4687
4688 // Compute the offset. Offset is calculated as the immediate operand
4689 // multiplied by the scaling factor. Unscaled instructions have scaling factor
4690 // set to 1. Postindex are a special case which have an offset of 0.
4691 if (isPostIndexLdStOpcode(LdSt.getOpcode())) {
4692 BaseOp = &LdSt.getOperand(2);
4693 Offset = 0;
4694 } else if (LdSt.getNumExplicitOperands() == 3) {
4695 BaseOp = &LdSt.getOperand(1);
4696 Offset = LdSt.getOperand(2).getImm() * Scale.getKnownMinValue();
4697 } else {
4698 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
4699 BaseOp = &LdSt.getOperand(2);
4700 Offset = LdSt.getOperand(3).getImm() * Scale.getKnownMinValue();
4701 }
4702 OffsetIsScalable = Scale.isScalable();
4703
4704 return BaseOp->isReg() || BaseOp->isFI();
4705}
4706
4709 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4710 MachineOperand &OfsOp = LdSt.getOperand(LdSt.getNumExplicitOperands() - 1);
4711 assert(OfsOp.isImm() && "Offset operand wasn't immediate.");
4712 return OfsOp;
4713}
4714
4715bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale,
4716 TypeSize &Width, int64_t &MinOffset,
4717 int64_t &MaxOffset) {
4718 switch (Opcode) {
4719 // Not a memory operation or something we want to handle.
4720 default:
4721 Scale = Width = TypeSize::getFixed(0);
4722 MinOffset = MaxOffset = 0;
4723 return false;
4724 // LDR / STR
4725 case AArch64::LDRQui:
4726 case AArch64::STRQui:
4727 Scale = Width = TypeSize::getFixed(16);
4728 MinOffset = 0;
4729 MaxOffset = 4095;
4730 break;
4731 case AArch64::LDRXui:
4732 case AArch64::LDRDui:
4733 case AArch64::STRXui:
4734 case AArch64::STRDui:
4735 case AArch64::PRFMui:
4736 Scale = Width = TypeSize::getFixed(8);
4737 MinOffset = 0;
4738 MaxOffset = 4095;
4739 break;
4740 case AArch64::LDRWui:
4741 case AArch64::LDRSui:
4742 case AArch64::LDRSWui:
4743 case AArch64::STRWui:
4744 case AArch64::STRSui:
4745 Scale = Width = TypeSize::getFixed(4);
4746 MinOffset = 0;
4747 MaxOffset = 4095;
4748 break;
4749 case AArch64::LDRHui:
4750 case AArch64::LDRHHui:
4751 case AArch64::LDRSHWui:
4752 case AArch64::LDRSHXui:
4753 case AArch64::STRHui:
4754 case AArch64::STRHHui:
4755 Scale = Width = TypeSize::getFixed(2);
4756 MinOffset = 0;
4757 MaxOffset = 4095;
4758 break;
4759 case AArch64::LDRBui:
4760 case AArch64::LDRBBui:
4761 case AArch64::LDRSBWui:
4762 case AArch64::LDRSBXui:
4763 case AArch64::STRBui:
4764 case AArch64::STRBBui:
4765 Scale = Width = TypeSize::getFixed(1);
4766 MinOffset = 0;
4767 MaxOffset = 4095;
4768 break;
4769 // post/pre inc
4770 case AArch64::STRQpre:
4771 case AArch64::LDRQpost:
4772 Scale = TypeSize::getFixed(1);
4773 Width = TypeSize::getFixed(16);
4774 MinOffset = -256;
4775 MaxOffset = 255;
4776 break;
4777 case AArch64::LDRDpost:
4778 case AArch64::LDRDpre:
4779 case AArch64::LDRXpost:
4780 case AArch64::LDRXpre:
4781 case AArch64::STRDpost:
4782 case AArch64::STRDpre:
4783 case AArch64::STRXpost:
4784 case AArch64::STRXpre:
4785 Scale = TypeSize::getFixed(1);
4786 Width = TypeSize::getFixed(8);
4787 MinOffset = -256;
4788 MaxOffset = 255;
4789 break;
4790 case AArch64::STRWpost:
4791 case AArch64::STRWpre:
4792 case AArch64::LDRWpost:
4793 case AArch64::LDRWpre:
4794 case AArch64::STRSpost:
4795 case AArch64::STRSpre:
4796 case AArch64::LDRSpost:
4797 case AArch64::LDRSpre:
4798 Scale = TypeSize::getFixed(1);
4799 Width = TypeSize::getFixed(4);
4800 MinOffset = -256;
4801 MaxOffset = 255;
4802 break;
4803 case AArch64::LDRHpost:
4804 case AArch64::LDRHpre:
4805 case AArch64::STRHpost:
4806 case AArch64::STRHpre:
4807 case AArch64::LDRHHpost:
4808 case AArch64::LDRHHpre:
4809 case AArch64::STRHHpost:
4810 case AArch64::STRHHpre:
4811 Scale = TypeSize::getFixed(1);
4812 Width = TypeSize::getFixed(2);
4813 MinOffset = -256;
4814 MaxOffset = 255;
4815 break;
4816 case AArch64::LDRBpost:
4817 case AArch64::LDRBpre:
4818 case AArch64::STRBpost:
4819 case AArch64::STRBpre:
4820 case AArch64::LDRBBpost:
4821 case AArch64::LDRBBpre:
4822 case AArch64::STRBBpost:
4823 case AArch64::STRBBpre:
4824 Scale = Width = TypeSize::getFixed(1);
4825 MinOffset = -256;
4826 MaxOffset = 255;
4827 break;
4828 // Unscaled
4829 case AArch64::LDURQi:
4830 case AArch64::STURQi:
4831 Scale = TypeSize::getFixed(1);
4832 Width = TypeSize::getFixed(16);
4833 MinOffset = -256;
4834 MaxOffset = 255;
4835 break;
4836 case AArch64::LDURXi:
4837 case AArch64::LDURDi:
4838 case AArch64::LDAPURXi:
4839 case AArch64::STURXi:
4840 case AArch64::STURDi:
4841 case AArch64::STLURXi:
4842 case AArch64::PRFUMi:
4843 Scale = TypeSize::getFixed(1);
4844 Width = TypeSize::getFixed(8);
4845 MinOffset = -256;
4846 MaxOffset = 255;
4847 break;
4848 case AArch64::LDURWi:
4849 case AArch64::LDURSi:
4850 case AArch64::LDURSWi:
4851 case AArch64::LDAPURi:
4852 case AArch64::LDAPURSWi:
4853 case AArch64::STURWi:
4854 case AArch64::STURSi:
4855 case AArch64::STLURWi:
4856 Scale = TypeSize::getFixed(1);
4857 Width = TypeSize::getFixed(4);
4858 MinOffset = -256;
4859 MaxOffset = 255;
4860 break;
4861 case AArch64::LDURHi:
4862 case AArch64::LDURHHi:
4863 case AArch64::LDURSHXi:
4864 case AArch64::LDURSHWi:
4865 case AArch64::LDAPURHi:
4866 case AArch64::LDAPURSHWi:
4867 case AArch64::LDAPURSHXi:
4868 case AArch64::STURHi:
4869 case AArch64::STURHHi:
4870 case AArch64::STLURHi:
4871 Scale = TypeSize::getFixed(1);
4872 Width = TypeSize::getFixed(2);
4873 MinOffset = -256;
4874 MaxOffset = 255;
4875 break;
4876 case AArch64::LDURBi:
4877 case AArch64::LDURBBi:
4878 case AArch64::LDURSBXi:
4879 case AArch64::LDURSBWi:
4880 case AArch64::LDAPURBi:
4881 case AArch64::LDAPURSBWi:
4882 case AArch64::LDAPURSBXi:
4883 case AArch64::STURBi:
4884 case AArch64::STURBBi:
4885 case AArch64::STLURBi:
4886 Scale = Width = TypeSize::getFixed(1);
4887 MinOffset = -256;
4888 MaxOffset = 255;
4889 break;
4890 // LDP / STP (including pre/post inc)
4891 case AArch64::LDPQi:
4892 case AArch64::LDNPQi:
4893 case AArch64::STPQi:
4894 case AArch64::STNPQi:
4895 case AArch64::LDPQpost:
4896 case AArch64::LDPQpre:
4897 case AArch64::STPQpost:
4898 case AArch64::STPQpre:
4899 Scale = TypeSize::getFixed(16);
4900 Width = TypeSize::getFixed(16 * 2);
4901 MinOffset = -64;
4902 MaxOffset = 63;
4903 break;
4904 case AArch64::LDPXi:
4905 case AArch64::LDPDi:
4906 case AArch64::LDNPXi:
4907 case AArch64::LDNPDi:
4908 case AArch64::STPXi:
4909 case AArch64::STPDi:
4910 case AArch64::STNPXi:
4911 case AArch64::STNPDi:
4912 case AArch64::LDPDpost:
4913 case AArch64::LDPDpre:
4914 case AArch64::LDPXpost:
4915 case AArch64::LDPXpre:
4916 case AArch64::STPDpost:
4917 case AArch64::STPDpre:
4918 case AArch64::STPXpost:
4919 case AArch64::STPXpre:
4920 Scale = TypeSize::getFixed(8);
4921 Width = TypeSize::getFixed(8 * 2);
4922 MinOffset = -64;
4923 MaxOffset = 63;
4924 break;
4925 case AArch64::LDPWi:
4926 case AArch64::LDPSi:
4927 case AArch64::LDNPWi:
4928 case AArch64::LDNPSi:
4929 case AArch64::STPWi:
4930 case AArch64::STPSi:
4931 case AArch64::STNPWi:
4932 case AArch64::STNPSi:
4933 case AArch64::LDPSpost:
4934 case AArch64::LDPSpre:
4935 case AArch64::LDPWpost:
4936 case AArch64::LDPWpre:
4937 case AArch64::STPSpost:
4938 case AArch64::STPSpre:
4939 case AArch64::STPWpost:
4940 case AArch64::STPWpre:
4941 Scale = TypeSize::getFixed(4);
4942 Width = TypeSize::getFixed(4 * 2);
4943 MinOffset = -64;
4944 MaxOffset = 63;
4945 break;
4946 case AArch64::StoreSwiftAsyncContext:
4947 // Store is an STRXui, but there might be an ADDXri in the expansion too.
4948 Scale = TypeSize::getFixed(1);
4949 Width = TypeSize::getFixed(8);
4950 MinOffset = 0;
4951 MaxOffset = 4095;
4952 break;
4953 case AArch64::ADDG:
4954 Scale = TypeSize::getFixed(16);
4955 Width = TypeSize::getFixed(0);
4956 MinOffset = 0;
4957 MaxOffset = 63;
4958 break;
4959 case AArch64::TAGPstack:
4960 Scale = TypeSize::getFixed(16);
4961 Width = TypeSize::getFixed(0);
4962 // TAGP with a negative offset turns into SUBP, which has a maximum offset
4963 // of 63 (not 64!).
4964 MinOffset = -63;
4965 MaxOffset = 63;
4966 break;
4967 case AArch64::LDG:
4968 case AArch64::STGi:
4969 case AArch64::STGPreIndex:
4970 case AArch64::STGPostIndex:
4971 case AArch64::STZGi:
4972 case AArch64::STZGPreIndex:
4973 case AArch64::STZGPostIndex:
4974 Scale = Width = TypeSize::getFixed(16);
4975 MinOffset = -256;
4976 MaxOffset = 255;
4977 break;
4978 // SVE
4979 case AArch64::STR_ZZZZXI:
4980 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4981 case AArch64::LDR_ZZZZXI:
4982 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4983 Scale = TypeSize::getScalable(16);
4984 Width = TypeSize::getScalable(16 * 4);
4985 MinOffset = -256;
4986 MaxOffset = 252;
4987 break;
4988 case AArch64::STR_ZZZXI:
4989 case AArch64::LDR_ZZZXI:
4990 Scale = TypeSize::getScalable(16);
4991 Width = TypeSize::getScalable(16 * 3);
4992 MinOffset = -256;
4993 MaxOffset = 253;
4994 break;
4995 case AArch64::STR_ZZXI:
4996 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4997 case AArch64::LDR_ZZXI:
4998 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4999 Scale = TypeSize::getScalable(16);
5000 Width = TypeSize::getScalable(16 * 2);
5001 MinOffset = -256;
5002 MaxOffset = 254;
5003 break;
5004 case AArch64::LDR_PXI:
5005 case AArch64::STR_PXI:
5006 Scale = Width = TypeSize::getScalable(2);
5007 MinOffset = -256;
5008 MaxOffset = 255;
5009 break;
5010 case AArch64::LDR_PPXI:
5011 case AArch64::STR_PPXI:
5012 Scale = TypeSize::getScalable(2);
5013 Width = TypeSize::getScalable(2 * 2);
5014 MinOffset = -256;
5015 MaxOffset = 254;
5016 break;
5017 case AArch64::LDR_ZXI:
5018 case AArch64::STR_ZXI:
5019 Scale = Width = TypeSize::getScalable(16);
5020 MinOffset = -256;
5021 MaxOffset = 255;
5022 break;
5023 case AArch64::LD1B_IMM:
5024 case AArch64::LD1H_IMM:
5025 case AArch64::LD1W_IMM:
5026 case AArch64::LD1D_IMM:
5027 case AArch64::LDNT1B_ZRI:
5028 case AArch64::LDNT1H_ZRI:
5029 case AArch64::LDNT1W_ZRI:
5030 case AArch64::LDNT1D_ZRI:
5031 case AArch64::ST1B_IMM:
5032 case AArch64::ST1H_IMM:
5033 case AArch64::ST1W_IMM:
5034 case AArch64::ST1D_IMM:
5035 case AArch64::STNT1B_ZRI:
5036 case AArch64::STNT1H_ZRI:
5037 case AArch64::STNT1W_ZRI:
5038 case AArch64::STNT1D_ZRI:
5039 case AArch64::LDNF1B_IMM:
5040 case AArch64::LDNF1H_IMM:
5041 case AArch64::LDNF1W_IMM:
5042 case AArch64::LDNF1D_IMM:
5043 // A full vectors worth of data
5044 // Width = mbytes * elements
5045 Scale = Width = TypeSize::getScalable(16);
5046 MinOffset = -8;
5047 MaxOffset = 7;
5048 break;
5049 case AArch64::LD2B_IMM:
5050 case AArch64::LD2H_IMM:
5051 case AArch64::LD2W_IMM:
5052 case AArch64::LD2D_IMM:
5053 case AArch64::ST2B_IMM:
5054 case AArch64::ST2H_IMM:
5055 case AArch64::ST2W_IMM:
5056 case AArch64::ST2D_IMM:
5057 case AArch64::LD1B_2Z_IMM:
5058 case AArch64::LD1B_2Z_STRIDED_IMM:
5059 case AArch64::LD1H_2Z_IMM:
5060 case AArch64::LD1H_2Z_STRIDED_IMM:
5061 case AArch64::LD1W_2Z_IMM:
5062 case AArch64::LD1W_2Z_STRIDED_IMM:
5063 case AArch64::LD1D_2Z_IMM:
5064 case AArch64::LD1D_2Z_STRIDED_IMM:
5065 case AArch64::LD1B_2Z_IMM_PSEUDO:
5066 case AArch64::LD1H_2Z_IMM_PSEUDO:
5067 case AArch64::LD1W_2Z_IMM_PSEUDO:
5068 case AArch64::LD1D_2Z_IMM_PSEUDO:
5069 case AArch64::ST1B_2Z_IMM:
5070 case AArch64::ST1B_2Z_STRIDED_IMM:
5071 case AArch64::ST1H_2Z_IMM:
5072 case AArch64::ST1H_2Z_STRIDED_IMM:
5073 case AArch64::ST1W_2Z_IMM:
5074 case AArch64::ST1W_2Z_STRIDED_IMM:
5075 case AArch64::ST1D_2Z_IMM:
5076 case AArch64::ST1D_2Z_STRIDED_IMM:
5077 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5078 case AArch64::LDNT1B_2Z_IMM:
5079 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5080 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5081 case AArch64::LDNT1H_2Z_IMM:
5082 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5083 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5084 case AArch64::LDNT1W_2Z_IMM:
5085 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5086 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5087 case AArch64::LDNT1D_2Z_IMM:
5088 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5089 case AArch64::STNT1B_2Z_IMM:
5090 case AArch64::STNT1B_2Z_STRIDED_IMM:
5091 case AArch64::STNT1H_2Z_IMM:
5092 case AArch64::STNT1H_2Z_STRIDED_IMM:
5093 case AArch64::STNT1W_2Z_IMM:
5094 case AArch64::STNT1W_2Z_STRIDED_IMM:
5095 case AArch64::STNT1D_2Z_IMM:
5096 case AArch64::STNT1D_2Z_STRIDED_IMM:
5097 case AArch64::ST1B_2Z_IMM_PSEUDO:
5098 case AArch64::ST1H_2Z_IMM_PSEUDO:
5099 case AArch64::ST1W_2Z_IMM_PSEUDO:
5100 case AArch64::ST1D_2Z_IMM_PSEUDO:
5101 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5102 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5103 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5104 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5105 Scale = Width = TypeSize::getScalable(16 * 2);
5106 MinOffset = -8;
5107 MaxOffset = 7;
5108 break;
5109 case AArch64::LD3B_IMM:
5110 case AArch64::LD3H_IMM:
5111 case AArch64::LD3W_IMM:
5112 case AArch64::LD3D_IMM:
5113 case AArch64::ST3B_IMM:
5114 case AArch64::ST3H_IMM:
5115 case AArch64::ST3W_IMM:
5116 case AArch64::ST3D_IMM:
5117 Scale = Width = TypeSize::getScalable(16 * 3);
5118 MinOffset = -8;
5119 MaxOffset = 7;
5120 break;
5121 case AArch64::LD4B_IMM:
5122 case AArch64::LD4H_IMM:
5123 case AArch64::LD4W_IMM:
5124 case AArch64::LD4D_IMM:
5125 case AArch64::ST4B_IMM:
5126 case AArch64::ST4H_IMM:
5127 case AArch64::ST4W_IMM:
5128 case AArch64::ST4D_IMM:
5129 case AArch64::LD1B_4Z_IMM:
5130 case AArch64::LD1B_4Z_STRIDED_IMM:
5131 case AArch64::LD1H_4Z_IMM:
5132 case AArch64::LD1H_4Z_STRIDED_IMM:
5133 case AArch64::LD1W_4Z_IMM:
5134 case AArch64::LD1W_4Z_STRIDED_IMM:
5135 case AArch64::LD1D_4Z_IMM:
5136 case AArch64::LD1D_4Z_STRIDED_IMM:
5137 case AArch64::LD1B_4Z_IMM_PSEUDO:
5138 case AArch64::LD1H_4Z_IMM_PSEUDO:
5139 case AArch64::LD1W_4Z_IMM_PSEUDO:
5140 case AArch64::LD1D_4Z_IMM_PSEUDO:
5141 case AArch64::ST1B_4Z_IMM:
5142 case AArch64::ST1B_4Z_STRIDED_IMM:
5143 case AArch64::ST1H_4Z_IMM:
5144 case AArch64::ST1H_4Z_STRIDED_IMM:
5145 case AArch64::ST1W_4Z_IMM:
5146 case AArch64::ST1W_4Z_STRIDED_IMM:
5147 case AArch64::ST1D_4Z_IMM:
5148 case AArch64::ST1D_4Z_STRIDED_IMM:
5149 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5150 case AArch64::LDNT1B_4Z_IMM:
5151 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5152 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5153 case AArch64::LDNT1H_4Z_IMM:
5154 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5155 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5156 case AArch64::LDNT1W_4Z_IMM:
5157 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5158 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5159 case AArch64::LDNT1D_4Z_IMM:
5160 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5161 case AArch64::STNT1B_4Z_IMM:
5162 case AArch64::STNT1B_4Z_STRIDED_IMM:
5163 case AArch64::STNT1H_4Z_IMM:
5164 case AArch64::STNT1H_4Z_STRIDED_IMM:
5165 case AArch64::STNT1W_4Z_IMM:
5166 case AArch64::STNT1W_4Z_STRIDED_IMM:
5167 case AArch64::STNT1D_4Z_IMM:
5168 case AArch64::STNT1D_4Z_STRIDED_IMM:
5169 case AArch64::ST1B_4Z_IMM_PSEUDO:
5170 case AArch64::ST1H_4Z_IMM_PSEUDO:
5171 case AArch64::ST1W_4Z_IMM_PSEUDO:
5172 case AArch64::ST1D_4Z_IMM_PSEUDO:
5173 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5174 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5175 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5176 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5177 Scale = Width = TypeSize::getScalable(16 * 4);
5178 MinOffset = -8;
5179 MaxOffset = 7;
5180 break;
5181 case AArch64::LD1B_H_IMM:
5182 case AArch64::LD1SB_H_IMM:
5183 case AArch64::LD1H_S_IMM:
5184 case AArch64::LD1SH_S_IMM:
5185 case AArch64::LD1W_D_IMM:
5186 case AArch64::LD1SW_D_IMM:
5187 case AArch64::ST1B_H_IMM:
5188 case AArch64::ST1H_S_IMM:
5189 case AArch64::ST1W_D_IMM:
5190 case AArch64::LDNF1B_H_IMM:
5191 case AArch64::LDNF1SB_H_IMM:
5192 case AArch64::LDNF1H_S_IMM:
5193 case AArch64::LDNF1SH_S_IMM:
5194 case AArch64::LDNF1W_D_IMM:
5195 case AArch64::LDNF1SW_D_IMM:
5196 // A half vector worth of data
5197 // Width = mbytes * elements
5198 Scale = Width = TypeSize::getScalable(8);
5199 MinOffset = -8;
5200 MaxOffset = 7;
5201 break;
5202 case AArch64::LD1B_S_IMM:
5203 case AArch64::LD1SB_S_IMM:
5204 case AArch64::LD1H_D_IMM:
5205 case AArch64::LD1SH_D_IMM:
5206 case AArch64::ST1B_S_IMM:
5207 case AArch64::ST1H_D_IMM:
5208 case AArch64::LDNF1B_S_IMM:
5209 case AArch64::LDNF1SB_S_IMM:
5210 case AArch64::LDNF1H_D_IMM:
5211 case AArch64::LDNF1SH_D_IMM:
5212 // A quarter vector worth of data
5213 // Width = mbytes * elements
5214 Scale = Width = TypeSize::getScalable(4);
5215 MinOffset = -8;
5216 MaxOffset = 7;
5217 break;
5218 case AArch64::LD1B_D_IMM:
5219 case AArch64::LD1SB_D_IMM:
5220 case AArch64::ST1B_D_IMM:
5221 case AArch64::LDNF1B_D_IMM:
5222 case AArch64::LDNF1SB_D_IMM:
5223 // A eighth vector worth of data
5224 // Width = mbytes * elements
5225 Scale = Width = TypeSize::getScalable(2);
5226 MinOffset = -8;
5227 MaxOffset = 7;
5228 break;
5229 case AArch64::ST2Gi:
5230 case AArch64::ST2GPreIndex:
5231 case AArch64::ST2GPostIndex:
5232 case AArch64::STZ2Gi:
5233 case AArch64::STZ2GPreIndex:
5234 case AArch64::STZ2GPostIndex:
5235 Scale = TypeSize::getFixed(16);
5236 Width = TypeSize::getFixed(32);
5237 MinOffset = -256;
5238 MaxOffset = 255;
5239 break;
5240 case AArch64::STGPi:
5241 case AArch64::STGPpost:
5242 case AArch64::STGPpre:
5243 Scale = Width = TypeSize::getFixed(16);
5244 MinOffset = -64;
5245 MaxOffset = 63;
5246 break;
5247 case AArch64::LD1RB_IMM:
5248 case AArch64::LD1RB_H_IMM:
5249 case AArch64::LD1RB_S_IMM:
5250 case AArch64::LD1RB_D_IMM:
5251 case AArch64::LD1RSB_H_IMM:
5252 case AArch64::LD1RSB_S_IMM:
5253 case AArch64::LD1RSB_D_IMM:
5254 Scale = Width = TypeSize::getFixed(1);
5255 MinOffset = 0;
5256 MaxOffset = 63;
5257 break;
5258 case AArch64::LD1RH_IMM:
5259 case AArch64::LD1RH_S_IMM:
5260 case AArch64::LD1RH_D_IMM:
5261 case AArch64::LD1RSH_S_IMM:
5262 case AArch64::LD1RSH_D_IMM:
5263 Scale = Width = TypeSize::getFixed(2);
5264 MinOffset = 0;
5265 MaxOffset = 63;
5266 break;
5267 case AArch64::LD1RW_IMM:
5268 case AArch64::LD1RW_D_IMM:
5269 case AArch64::LD1RSW_IMM:
5270 Scale = Width = TypeSize::getFixed(4);
5271 MinOffset = 0;
5272 MaxOffset = 63;
5273 break;
5274 case AArch64::LD1RD_IMM:
5275 Scale = Width = TypeSize::getFixed(8);
5276 MinOffset = 0;
5277 MaxOffset = 63;
5278 break;
5279 }
5280
5281 return true;
5282}
5283
5284// Scaling factor for unscaled load or store.
5286 switch (Opc) {
5287 default:
5288 llvm_unreachable("Opcode has unknown scale!");
5289 case AArch64::LDRBui:
5290 case AArch64::LDRBBui:
5291 case AArch64::LDURBBi:
5292 case AArch64::LDRSBWui:
5293 case AArch64::LDURSBWi:
5294 case AArch64::STRBui:
5295 case AArch64::STRBBui:
5296 case AArch64::STURBBi:
5297 return 1;
5298 case AArch64::LDRHui:
5299 case AArch64::LDRHHui:
5300 case AArch64::LDURHHi:
5301 case AArch64::LDRSHWui:
5302 case AArch64::LDURSHWi:
5303 case AArch64::STRHui:
5304 case AArch64::STRHHui:
5305 case AArch64::STURHHi:
5306 return 2;
5307 case AArch64::LDRSui:
5308 case AArch64::LDURSi:
5309 case AArch64::LDRSpre:
5310 case AArch64::LDRSWui:
5311 case AArch64::LDURSWi:
5312 case AArch64::LDRSWpre:
5313 case AArch64::LDRWpre:
5314 case AArch64::LDRWui:
5315 case AArch64::LDURWi:
5316 case AArch64::STRSui:
5317 case AArch64::STURSi:
5318 case AArch64::STRSpre:
5319 case AArch64::STRWui:
5320 case AArch64::STURWi:
5321 case AArch64::STRWpre:
5322 case AArch64::LDPSi:
5323 case AArch64::LDPSWi:
5324 case AArch64::LDPWi:
5325 case AArch64::STPSi:
5326 case AArch64::STPWi:
5327 return 4;
5328 case AArch64::LDRDui:
5329 case AArch64::LDURDi:
5330 case AArch64::LDRDpre:
5331 case AArch64::LDRXui:
5332 case AArch64::LDURXi:
5333 case AArch64::LDRXpre:
5334 case AArch64::STRDui:
5335 case AArch64::STURDi:
5336 case AArch64::STRDpre:
5337 case AArch64::STRXui:
5338 case AArch64::STURXi:
5339 case AArch64::STRXpre:
5340 case AArch64::LDPDi:
5341 case AArch64::LDPXi:
5342 case AArch64::STPDi:
5343 case AArch64::STPXi:
5344 return 8;
5345 case AArch64::LDRQui:
5346 case AArch64::LDURQi:
5347 case AArch64::STRQui:
5348 case AArch64::STURQi:
5349 case AArch64::STRQpre:
5350 case AArch64::LDPQi:
5351 case AArch64::LDRQpre:
5352 case AArch64::STPQi:
5353 case AArch64::STGi:
5354 case AArch64::STZGi:
5355 case AArch64::ST2Gi:
5356 case AArch64::STZ2Gi:
5357 case AArch64::STGPi:
5358 return 16;
5359 }
5360}
5361
5363 switch (MI.getOpcode()) {
5364 default:
5365 return false;
5366 case AArch64::LDRWpre:
5367 case AArch64::LDRXpre:
5368 case AArch64::LDRSWpre:
5369 case AArch64::LDRSpre:
5370 case AArch64::LDRDpre:
5371 case AArch64::LDRQpre:
5372 return true;
5373 }
5374}
5375
5377 switch (MI.getOpcode()) {
5378 default:
5379 return false;
5380 case AArch64::STRWpre:
5381 case AArch64::STRXpre:
5382 case AArch64::STRSpre:
5383 case AArch64::STRDpre:
5384 case AArch64::STRQpre:
5385 return true;
5386 }
5387}
5388
5390 return isPreLd(MI) || isPreSt(MI);
5391}
5392
5394 switch (MI.getOpcode()) {
5395 default:
5396 return false;
5397 case AArch64::LDURBBi:
5398 case AArch64::LDURHHi:
5399 case AArch64::LDURWi:
5400 case AArch64::LDRBBui:
5401 case AArch64::LDRHHui:
5402 case AArch64::LDRWui:
5403 case AArch64::LDRBBroX:
5404 case AArch64::LDRHHroX:
5405 case AArch64::LDRWroX:
5406 case AArch64::LDRBBroW:
5407 case AArch64::LDRHHroW:
5408 case AArch64::LDRWroW:
5409 return true;
5410 }
5411}
5412
5414 switch (MI.getOpcode()) {
5415 default:
5416 return false;
5417 case AArch64::LDURSBWi:
5418 case AArch64::LDURSHWi:
5419 case AArch64::LDURSBXi:
5420 case AArch64::LDURSHXi:
5421 case AArch64::LDURSWi:
5422 case AArch64::LDRSBWui:
5423 case AArch64::LDRSHWui:
5424 case AArch64::LDRSBXui:
5425 case AArch64::LDRSHXui:
5426 case AArch64::LDRSWui:
5427 case AArch64::LDRSBWroX:
5428 case AArch64::LDRSHWroX:
5429 case AArch64::LDRSBXroX:
5430 case AArch64::LDRSHXroX:
5431 case AArch64::LDRSWroX:
5432 case AArch64::LDRSBWroW:
5433 case AArch64::LDRSHWroW:
5434 case AArch64::LDRSBXroW:
5435 case AArch64::LDRSHXroW:
5436 case AArch64::LDRSWroW:
5437 return true;
5438 }
5439}
5440
5442 switch (MI.getOpcode()) {
5443 default:
5444 return false;
5445 case AArch64::LDPSi:
5446 case AArch64::LDPSWi:
5447 case AArch64::LDPDi:
5448 case AArch64::LDPQi:
5449 case AArch64::LDPWi:
5450 case AArch64::LDPXi:
5451 case AArch64::STPSi:
5452 case AArch64::STPDi:
5453 case AArch64::STPQi:
5454 case AArch64::STPWi:
5455 case AArch64::STPXi:
5456 case AArch64::STGPi:
5457 return true;
5458 }
5459}
5460
5462 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5463 unsigned Idx =
5465 : 1;
5466 return MI.getOperand(Idx);
5467}
5468
5469const MachineOperand &
5471 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5472 unsigned Idx =
5474 : 2;
5475 return MI.getOperand(Idx);
5476}
5477
5478const MachineOperand &
5480 switch (MI.getOpcode()) {
5481 default:
5482 llvm_unreachable("Unexpected opcode");
5483 case AArch64::LDRBroX:
5484 case AArch64::LDRBBroX:
5485 case AArch64::LDRSBXroX:
5486 case AArch64::LDRSBWroX:
5487 case AArch64::LDRHroX:
5488 case AArch64::LDRHHroX:
5489 case AArch64::LDRSHXroX:
5490 case AArch64::LDRSHWroX:
5491 case AArch64::LDRWroX:
5492 case AArch64::LDRSroX:
5493 case AArch64::LDRSWroX:
5494 case AArch64::LDRDroX:
5495 case AArch64::LDRXroX:
5496 case AArch64::LDRQroX:
5497 return MI.getOperand(4);
5498 }
5499}
5500
5502 Register Reg) {
5503 if (MI.getParent() == nullptr)
5504 return nullptr;
5505 const MachineFunction *MF = MI.getParent()->getParent();
5506 return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr;
5507}
5508
5510 auto IsHFPR = [&](const MachineOperand &Op) {
5511 if (!Op.isReg())
5512 return false;
5513 auto Reg = Op.getReg();
5514 if (Reg.isPhysical())
5515 return AArch64::FPR16RegClass.contains(Reg);
5516 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5517 return TRC == &AArch64::FPR16RegClass ||
5518 TRC == &AArch64::FPR16_loRegClass;
5519 };
5520 return llvm::any_of(MI.operands(), IsHFPR);
5521}
5522
5524 auto IsQFPR = [&](const MachineOperand &Op) {
5525 if (!Op.isReg())
5526 return false;
5527 auto Reg = Op.getReg();
5528 if (Reg.isPhysical())
5529 return AArch64::FPR128RegClass.contains(Reg);
5530 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5531 return TRC == &AArch64::FPR128RegClass ||
5532 TRC == &AArch64::FPR128_loRegClass;
5533 };
5534 return llvm::any_of(MI.operands(), IsQFPR);
5535}
5536
5538 switch (MI.getOpcode()) {
5539 case AArch64::BRK:
5540 case AArch64::HLT:
5541 case AArch64::PACIASP:
5542 case AArch64::PACIBSP:
5543 // Implicit BTI behavior.
5544 return true;
5545 case AArch64::PAUTH_PROLOGUE:
5546 // PAUTH_PROLOGUE expands to PACI(A|B)SP.
5547 return true;
5548 case AArch64::HINT: {
5549 unsigned Imm = MI.getOperand(0).getImm();
5550 // Explicit BTI instruction.
5551 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5552 return true;
5553 // PACI(A|B)SP instructions.
5554 if (Imm == 25 || Imm == 27)
5555 return true;
5556 return false;
5557 }
5558 default:
5559 return false;
5560 }
5561}
5562
5564 if (Reg == 0)
5565 return false;
5566 assert(Reg.isPhysical() && "Expected physical register in isFpOrNEON");
5567 return AArch64::FPR128RegClass.contains(Reg) ||
5568 AArch64::FPR64RegClass.contains(Reg) ||
5569 AArch64::FPR32RegClass.contains(Reg) ||
5570 AArch64::FPR16RegClass.contains(Reg) ||
5571 AArch64::FPR8RegClass.contains(Reg);
5572}
5573
5575 auto IsFPR = [&](const MachineOperand &Op) {
5576 if (!Op.isReg())
5577 return false;
5578 auto Reg = Op.getReg();
5579 if (Reg.isPhysical())
5580 return isFpOrNEON(Reg);
5581
5582 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5583 return TRC == &AArch64::FPR128RegClass ||
5584 TRC == &AArch64::FPR128_loRegClass ||
5585 TRC == &AArch64::FPR64RegClass ||
5586 TRC == &AArch64::FPR64_loRegClass ||
5587 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5588 TRC == &AArch64::FPR8RegClass;
5589 };
5590 return llvm::any_of(MI.operands(), IsFPR);
5591}
5592
5593// Scale the unscaled offsets. Returns false if the unscaled offset can't be
5594// scaled.
5595static bool scaleOffset(unsigned Opc, int64_t &Offset) {
5597
5598 // If the byte-offset isn't a multiple of the stride, we can't scale this
5599 // offset.
5600 if (Offset % Scale != 0)
5601 return false;
5602
5603 // Convert the byte-offset used by unscaled into an "element" offset used
5604 // by the scaled pair load/store instructions.
5605 Offset /= Scale;
5606 return true;
5607}
5608
5609static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
5610 if (FirstOpc == SecondOpc)
5611 return true;
5612 // We can also pair sign-ext and zero-ext instructions.
5613 switch (FirstOpc) {
5614 default:
5615 return false;
5616 case AArch64::STRSui:
5617 case AArch64::STURSi:
5618 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5619 case AArch64::STRDui:
5620 case AArch64::STURDi:
5621 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5622 case AArch64::STRQui:
5623 case AArch64::STURQi:
5624 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5625 case AArch64::STRWui:
5626 case AArch64::STURWi:
5627 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5628 case AArch64::STRXui:
5629 case AArch64::STURXi:
5630 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5631 case AArch64::LDRSui:
5632 case AArch64::LDURSi:
5633 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5634 case AArch64::LDRDui:
5635 case AArch64::LDURDi:
5636 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5637 case AArch64::LDRQui:
5638 case AArch64::LDURQi:
5639 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5640 case AArch64::LDRWui:
5641 case AArch64::LDURWi:
5642 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5643 case AArch64::LDRSWui:
5644 case AArch64::LDURSWi:
5645 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5646 case AArch64::LDRXui:
5647 case AArch64::LDURXi:
5648 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5649 }
5650 // These instructions can't be paired based on their opcodes.
5651 return false;
5652}
5653
5654static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1,
5655 int64_t Offset1, unsigned Opcode1, int FI2,
5656 int64_t Offset2, unsigned Opcode2) {
5657 // Accesses through fixed stack object frame indices may access a different
5658 // fixed stack slot. Check that the object offsets + offsets match.
5659 if (MFI.isFixedObjectIndex(FI1) && MFI.isFixedObjectIndex(FI2)) {
5660 int64_t ObjectOffset1 = MFI.getObjectOffset(FI1);
5661 int64_t ObjectOffset2 = MFI.getObjectOffset(FI2);
5662 assert(ObjectOffset1 <= ObjectOffset2 && "Object offsets are not ordered.");
5663 // Convert to scaled object offsets.
5664 int Scale1 = AArch64InstrInfo::getMemScale(Opcode1);
5665 if (ObjectOffset1 % Scale1 != 0)
5666 return false;
5667 ObjectOffset1 /= Scale1;
5668 int Scale2 = AArch64InstrInfo::getMemScale(Opcode2);
5669 if (ObjectOffset2 % Scale2 != 0)
5670 return false;
5671 ObjectOffset2 /= Scale2;
5672 ObjectOffset1 += Offset1;
5673 ObjectOffset2 += Offset2;
5674 return ObjectOffset1 + 1 == ObjectOffset2;
5675 }
5676
5677 return FI1 == FI2;
5678}
5679
5680/// Detect opportunities for ldp/stp formation.
5681///
5682/// Only called for LdSt for which getMemOperandWithOffset returns true.
5684 ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
5685 bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
5686 int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
5687 unsigned NumBytes) const {
5688 assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
5689 const MachineOperand &BaseOp1 = *BaseOps1.front();
5690 const MachineOperand &BaseOp2 = *BaseOps2.front();
5691 const MachineInstr &FirstLdSt = *BaseOp1.getParent();
5692 const MachineInstr &SecondLdSt = *BaseOp2.getParent();
5693 if (BaseOp1.getType() != BaseOp2.getType())
5694 return false;
5695
5696 assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
5697 "Only base registers and frame indices are supported.");
5698
5699 // Check for both base regs and base FI.
5700 if (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg())
5701 return false;
5702
5703 // Only cluster up to a single pair.
5704 if (ClusterSize > 2)
5705 return false;
5706
5707 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
5708 return false;
5709
5710 // Can we pair these instructions based on their opcodes?
5711 unsigned FirstOpc = FirstLdSt.getOpcode();
5712 unsigned SecondOpc = SecondLdSt.getOpcode();
5713 if (!canPairLdStOpc(FirstOpc, SecondOpc))
5714 return false;
5715
5716 // Can't merge volatiles or load/stores that have a hint to avoid pair
5717 // formation, for example.
5718 if (!isCandidateToMergeOrPair(FirstLdSt) ||
5719 !isCandidateToMergeOrPair(SecondLdSt))
5720 return false;
5721
5722 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
5723 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
5724 if (hasUnscaledLdStOffset(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
5725 return false;
5726
5727 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
5728 if (hasUnscaledLdStOffset(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
5729 return false;
5730
5731 // Pairwise instructions have a 7-bit signed offset field.
5732 if (Offset1 > 63 || Offset1 < -64)
5733 return false;
5734
5735 // The caller should already have ordered First/SecondLdSt by offset.
5736 // Note: except for non-equal frame index bases
5737 if (BaseOp1.isFI()) {
5738 assert((!BaseOp1.isIdenticalTo(BaseOp2) || Offset1 <= Offset2) &&
5739 "Caller should have ordered offsets.");
5740
5741 const MachineFrameInfo &MFI =
5742 FirstLdSt.getParent()->getParent()->getFrameInfo();
5743 return shouldClusterFI(MFI, BaseOp1.getIndex(), Offset1, FirstOpc,
5744 BaseOp2.getIndex(), Offset2, SecondOpc);
5745 }
5746
5747 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
5748
5749 return Offset1 + 1 == Offset2;
5750}
5751
5753 MCRegister Reg, unsigned SubIdx,
5754 RegState State,
5755 const TargetRegisterInfo *TRI) {
5756 if (!SubIdx)
5757 return MIB.addReg(Reg, State);
5758
5759 if (Reg.isPhysical())
5760 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
5761 return MIB.addReg(Reg, State, SubIdx);
5762}
5763
5766 const DebugLoc &DL, MCRegister DestReg,
5767 MCRegister SrcReg, bool KillSrc,
5768 ArrayRef<unsigned> Indices) const {
5769 assert(Subtarget.hasNEON() && "Unexpected register copy without NEON");
5771 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5772 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5773 unsigned NumRegs = Indices.size();
5774 MCRegister DestSubReg = TRI->getSubReg(DestReg, Indices[0]);
5775 assert(!AArch64::PNRRegClass.contains(DestSubReg) &&
5776 "Unexpected predicate tuple copy");
5777 unsigned MaxRegs = AArch64::PPRRegClass.contains(DestSubReg) ? 15 : 31;
5778
5779 int SubReg = 0, End = NumRegs, Incr = 1;
5780 // Copy in reverse if a forward copy will clobber the tuple
5781 if (((DestEncoding - SrcEncoding) & MaxRegs) < NumRegs) {
5782 SubReg = NumRegs - 1;
5783 End = -1;
5784 Incr = -1;
5785 }
5786
5787 for (; SubReg != End; SubReg += Incr) {
5788 DestSubReg = TRI->getSubReg(DestReg, Indices[SubReg]);
5789 MCRegister SrcSubReg = TRI->getSubReg(SrcReg, Indices[SubReg]);
5790 copyPhysRegImpl(MBB, I, DL, DestSubReg, SrcSubReg, KillSrc);
5791 }
5792}
5793
5796 const DebugLoc &DL, MCRegister DestReg,
5797 MCRegister SrcReg, bool KillSrc,
5798 unsigned Opcode, unsigned ZeroReg,
5799 llvm::ArrayRef<unsigned> Indices) const {
5801 unsigned NumRegs = Indices.size();
5802
5803#ifndef NDEBUG
5804 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5805 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5806 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5807 "GPR reg sequences should not be able to overlap");
5808#endif
5809
5810 for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5811 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5812 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5813 MIB.addReg(ZeroReg);
5814 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5815 MIB.addImm(0);
5816 }
5817}
5818
5819/// Returns true if the instruction at I is in a streaming call site region,
5820/// within a single basic block.
5821/// A "call site streaming region" starts after smstart and ends at smstop
5822/// around a call to a streaming function. This walks backward from I.
5825 MachineFunction &MF = *MBB.getParent();
5827 if (!AFI->hasStreamingModeChanges())
5828 return false;
5829 // Walk backwards to find smstart/smstop
5830 for (MachineInstr &MI : reverse(make_range(MBB.begin(), I))) {
5831 unsigned Opc = MI.getOpcode();
5832 if (Opc == AArch64::MSRpstatesvcrImm1 || Opc == AArch64::MSRpstatePseudo) {
5833 // Check if this is SM change (not ZA)
5834 int64_t PState = MI.getOperand(0).getImm();
5835 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5836 // Operand 1 is 1 for start, 0 for stop
5837 return MI.getOperand(1).getImm() == 1;
5838 }
5839 }
5840 }
5841 return false;
5842}
5843
5844/// Returns true if in a streaming call site region without SME-FA64.
5845static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget,
5848 return !Subtarget.hasSMEFA64() && isInStreamingCallSiteRegion(MBB, I);
5849}
5850
5853 const DebugLoc &DL, Register DestReg,
5854 Register SrcReg, bool KillSrc,
5855 bool RenamableDest,
5856 bool RenamableSrc) const {
5857 if (AArch64::GPR32spRegClass.contains(DestReg) &&
5858 AArch64::GPR32spRegClass.contains(SrcReg)) {
5859 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5860 // If either operand is WSP, expand to ADD #0.
5861 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5862 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5863 // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
5864 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5865 &AArch64::GPR64spRegClass);
5866 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5867 &AArch64::GPR64spRegClass);
5868 // This instruction is reading and writing X registers. This may upset
5869 // the register scavenger and machine verifier, so we need to indicate
5870 // that we are reading an undefined value from SrcRegX, but a proper
5871 // value from SrcReg.
5872 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
5873 .addReg(SrcRegX, RegState::Undef)
5874 .addImm(0)
5876 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5877 ++NumZCRegMoveInstrsGPR;
5878 } else {
5879 BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
5880 .addReg(SrcReg, getKillRegState(KillSrc))
5881 .addImm(0)
5883 if (Subtarget.hasZeroCycleRegMoveGPR32())
5884 ++NumZCRegMoveInstrsGPR;
5885 }
5886 } else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5887 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5888 // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
5889 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5890 &AArch64::GPR64spRegClass);
5891 assert(DestRegX.isValid() && "Destination super-reg not valid");
5892 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5893 &AArch64::GPR64spRegClass);
5894 assert(SrcRegX.isValid() && "Source super-reg not valid");
5895 // This instruction is reading and writing X registers. This may upset
5896 // the register scavenger and machine verifier, so we need to indicate
5897 // that we are reading an undefined value from SrcRegX, but a proper
5898 // value from SrcReg.
5899 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
5900 .addReg(AArch64::XZR)
5901 .addReg(SrcRegX, RegState::Undef)
5902 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5903 ++NumZCRegMoveInstrsGPR;
5904 } else {
5905 // Otherwise, expand to ORR WZR.
5906 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5907 .addReg(AArch64::WZR)
5908 .addReg(SrcReg, getKillRegState(KillSrc));
5909 if (Subtarget.hasZeroCycleRegMoveGPR32())
5910 ++NumZCRegMoveInstrsGPR;
5911 }
5912 return;
5913 }
5914
5915 // GPR32 zeroing
5916 if (AArch64::GPR32spRegClass.contains(DestReg) && SrcReg == AArch64::WZR) {
5917 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5918 !Subtarget.hasZeroCycleZeroingGPR32()) {
5919 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5920 &AArch64::GPR64spRegClass);
5921 assert(DestRegX.isValid() && "Destination super-reg not valid");
5922 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestRegX)
5923 .addImm(0)
5925 ++NumZCZeroingInstrsGPR;
5926 } else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5927 BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg)
5928 .addImm(0)
5930 ++NumZCZeroingInstrsGPR;
5931 } else {
5932 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5933 .addReg(AArch64::WZR)
5934 .addReg(AArch64::WZR);
5935 }
5936 return;
5937 }
5938
5939 if (AArch64::GPR64spRegClass.contains(DestReg) &&
5940 AArch64::GPR64spRegClass.contains(SrcReg)) {
5941 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5942 // If either operand is SP, expand to ADD #0.
5943 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
5944 .addReg(SrcReg, getKillRegState(KillSrc))
5945 .addImm(0)
5947 if (Subtarget.hasZeroCycleRegMoveGPR64())
5948 ++NumZCRegMoveInstrsGPR;
5949 } else {
5950 // Otherwise, expand to ORR XZR.
5951 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5952 .addReg(AArch64::XZR)
5953 .addReg(SrcReg, getKillRegState(KillSrc));
5954 if (Subtarget.hasZeroCycleRegMoveGPR64())
5955 ++NumZCRegMoveInstrsGPR;
5956 }
5957 return;
5958 }
5959
5960 // GPR64 zeroing
5961 if (AArch64::GPR64spRegClass.contains(DestReg) && SrcReg == AArch64::XZR) {
5962 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5963 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg)
5964 .addImm(0)
5966 ++NumZCZeroingInstrsGPR;
5967 } else {
5968 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5969 .addReg(AArch64::XZR)
5970 .addReg(AArch64::XZR);
5971 }
5972 return;
5973 }
5974
5975 // Copy a Predicate register by ORRing with itself.
5976 if (AArch64::PPRRegClass.contains(DestReg) &&
5977 AArch64::PPRRegClass.contains(SrcReg)) {
5978 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5979 "Unexpected SVE register.");
5980 BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), DestReg)
5981 .addReg(SrcReg) // Pg
5982 .addReg(SrcReg)
5983 .addReg(SrcReg, getKillRegState(KillSrc));
5984 return;
5985 }
5986
5987 // Copy a predicate-as-counter register by ORRing with itself as if it
5988 // were a regular predicate (mask) register.
5989 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
5990 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
5991 if (DestIsPNR || SrcIsPNR) {
5992 auto ToPPR = [](MCRegister R) -> MCRegister {
5993 return (R - AArch64::PN0) + AArch64::P0;
5994 };
5995 MCRegister PPRSrcReg = SrcIsPNR ? ToPPR(SrcReg) : SrcReg.asMCReg();
5996 MCRegister PPRDestReg = DestIsPNR ? ToPPR(DestReg) : DestReg.asMCReg();
5997
5998 if (PPRSrcReg != PPRDestReg) {
5999 auto NewMI = BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), PPRDestReg)
6000 .addReg(PPRSrcReg) // Pg
6001 .addReg(PPRSrcReg)
6002 .addReg(PPRSrcReg, getKillRegState(KillSrc));
6003 if (DestIsPNR)
6004 NewMI.addDef(DestReg, RegState::Implicit);
6005 }
6006 return;
6007 }
6008
6009 // Copy a predicate register pair by copying the individual sub-registers.
6010 if (AArch64::PPR2RegClass.contains(DestReg) &&
6011 AArch64::PPR2RegClass.contains(SrcReg)) {
6012 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6013 "Unexpected SVE predicate register.");
6014 static const unsigned Indices[] = {AArch64::psub0, AArch64::psub1};
6015 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6016 return;
6017 }
6018
6019 // Copy a Z register by ORRing with itself.
6020 if (AArch64::ZPRRegClass.contains(DestReg) &&
6021 AArch64::ZPRRegClass.contains(SrcReg)) {
6022 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6023 "Unexpected SVE register.");
6024 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ), DestReg)
6025 .addReg(SrcReg)
6026 .addReg(SrcReg, getKillRegState(KillSrc));
6027 return;
6028 }
6029
6030 // Copy a Z register pair by copying the individual sub-registers.
6031 if ((AArch64::ZPR2RegClass.contains(DestReg) ||
6032 AArch64::ZPR2StridedOrContiguousRegClass.contains(DestReg)) &&
6033 (AArch64::ZPR2RegClass.contains(SrcReg) ||
6034 AArch64::ZPR2StridedOrContiguousRegClass.contains(SrcReg))) {
6035 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6036 "Unexpected SVE register.");
6037 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6038 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6039 return;
6040 }
6041
6042 // Copy a Z register triple by copying the individual sub-registers.
6043 if (AArch64::ZPR3RegClass.contains(DestReg) &&
6044 AArch64::ZPR3RegClass.contains(SrcReg)) {
6045 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6046 "Unexpected SVE register.");
6047 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6048 AArch64::zsub2};
6049 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6050 return;
6051 }
6052
6053 // Copy a Z register quad by copying the individual sub-registers.
6054 if ((AArch64::ZPR4RegClass.contains(DestReg) ||
6055 AArch64::ZPR4StridedOrContiguousRegClass.contains(DestReg)) &&
6056 (AArch64::ZPR4RegClass.contains(SrcReg) ||
6057 AArch64::ZPR4StridedOrContiguousRegClass.contains(SrcReg))) {
6058 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6059 "Unexpected SVE register.");
6060 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6061 AArch64::zsub2, AArch64::zsub3};
6062 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6063 return;
6064 }
6065
6066 // Copy a DDDD register quad by copying the individual sub-registers.
6067 if (AArch64::DDDDRegClass.contains(DestReg) &&
6068 AArch64::DDDDRegClass.contains(SrcReg)) {
6069 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6070 AArch64::dsub2, AArch64::dsub3};
6071 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6072 return;
6073 }
6074
6075 // Copy a DDD register triple by copying the individual sub-registers.
6076 if (AArch64::DDDRegClass.contains(DestReg) &&
6077 AArch64::DDDRegClass.contains(SrcReg)) {
6078 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6079 AArch64::dsub2};
6080 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6081 return;
6082 }
6083
6084 // Copy a DD register pair by copying the individual sub-registers.
6085 if (AArch64::DDRegClass.contains(DestReg) &&
6086 AArch64::DDRegClass.contains(SrcReg)) {
6087 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6088 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6089 return;
6090 }
6091
6092 // Copy a QQQQ register quad by copying the individual sub-registers.
6093 if (AArch64::QQQQRegClass.contains(DestReg) &&
6094 AArch64::QQQQRegClass.contains(SrcReg)) {
6095 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6096 AArch64::qsub2, AArch64::qsub3};
6097 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6098 return;
6099 }
6100
6101 // Copy a QQQ register triple by copying the individual sub-registers.
6102 if (AArch64::QQQRegClass.contains(DestReg) &&
6103 AArch64::QQQRegClass.contains(SrcReg)) {
6104 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6105 AArch64::qsub2};
6106 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6107 return;
6108 }
6109
6110 // Copy a QQ register pair by copying the individual sub-registers.
6111 if (AArch64::QQRegClass.contains(DestReg) &&
6112 AArch64::QQRegClass.contains(SrcReg)) {
6113 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6114 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6115 return;
6116 }
6117
6118 if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
6119 AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
6120 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6121 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
6122 AArch64::XZR, Indices);
6123 return;
6124 }
6125
6126 if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
6127 AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
6128 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6129 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
6130 AArch64::WZR, Indices);
6131 return;
6132 }
6133
6134 if (AArch64::FPR128RegClass.contains(DestReg) &&
6135 AArch64::FPR128RegClass.contains(SrcReg)) {
6136 // In streaming regions, NEON is illegal but streaming-SVE is available.
6137 // Use SVE for copies if we're in a streaming region and SME is available.
6138 // With +sme-fa64, NEON is legal in streaming mode so we can use it.
6139 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6140 !Subtarget.isNeonAvailable()) ||
6141 mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6142 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ))
6143 .addReg(AArch64::Z0 + (DestReg - AArch64::Q0), RegState::Define)
6144 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6145 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6146 } else if (Subtarget.isNeonAvailable()) {
6147 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
6148 .addReg(SrcReg)
6149 .addReg(SrcReg, getKillRegState(KillSrc));
6150 if (Subtarget.hasZeroCycleRegMoveFPR128())
6151 ++NumZCRegMoveInstrsFPR;
6152 } else {
6153 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
6154 .addReg(AArch64::SP, RegState::Define)
6155 .addReg(SrcReg, getKillRegState(KillSrc))
6156 .addReg(AArch64::SP)
6157 .addImm(-16);
6158 BuildMI(MBB, I, DL, get(AArch64::LDRQpost))
6159 .addReg(AArch64::SP, RegState::Define)
6160 .addReg(DestReg, RegState::Define)
6161 .addReg(AArch64::SP)
6162 .addImm(16);
6163 }
6164 return;
6165 }
6166
6167 if (AArch64::FPR64RegClass.contains(DestReg) &&
6168 AArch64::FPR64RegClass.contains(SrcReg)) {
6169 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6170 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6171 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6172 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6173 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6174 &AArch64::FPR128RegClass);
6175 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6176 &AArch64::FPR128RegClass);
6177 // This instruction is reading and writing Q registers. This may upset
6178 // the register scavenger and machine verifier, so we need to indicate
6179 // that we are reading an undefined value from SrcRegQ, but a proper
6180 // value from SrcReg.
6181 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6182 .addReg(SrcRegQ, RegState::Undef)
6183 .addReg(SrcRegQ, RegState::Undef)
6184 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6185 ++NumZCRegMoveInstrsFPR;
6186 } else {
6187 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
6188 .addReg(SrcReg, getKillRegState(KillSrc));
6189 if (Subtarget.hasZeroCycleRegMoveFPR64())
6190 ++NumZCRegMoveInstrsFPR;
6191 }
6192 return;
6193 }
6194
6195 if (AArch64::FPR32RegClass.contains(DestReg) &&
6196 AArch64::FPR32RegClass.contains(SrcReg)) {
6197 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6198 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6199 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6200 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6201 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6202 &AArch64::FPR128RegClass);
6203 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6204 &AArch64::FPR128RegClass);
6205 // This instruction is reading and writing Q registers. This may upset
6206 // the register scavenger and machine verifier, so we need to indicate
6207 // that we are reading an undefined value from SrcRegQ, but a proper
6208 // value from SrcReg.
6209 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6210 .addReg(SrcRegQ, RegState::Undef)
6211 .addReg(SrcRegQ, RegState::Undef)
6212 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6213 ++NumZCRegMoveInstrsFPR;
6214 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6215 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6216 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6217 &AArch64::FPR64RegClass);
6218 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6219 &AArch64::FPR64RegClass);
6220 // This instruction is reading and writing D registers. This may upset
6221 // the register scavenger and machine verifier, so we need to indicate
6222 // that we are reading an undefined value from SrcRegD, but a proper
6223 // value from SrcReg.
6224 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6225 .addReg(SrcRegD, RegState::Undef)
6226 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6227 ++NumZCRegMoveInstrsFPR;
6228 } else {
6229 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6230 .addReg(SrcReg, getKillRegState(KillSrc));
6231 if (Subtarget.hasZeroCycleRegMoveFPR32())
6232 ++NumZCRegMoveInstrsFPR;
6233 }
6234 return;
6235 }
6236
6237 if (AArch64::FPR16RegClass.contains(DestReg) &&
6238 AArch64::FPR16RegClass.contains(SrcReg)) {
6239 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6240 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6241 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6242 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6243 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6244 &AArch64::FPR128RegClass);
6245 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6246 &AArch64::FPR128RegClass);
6247 // This instruction is reading and writing Q 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 SrcRegQ, but a proper
6250 // value from SrcReg.
6251 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6252 .addReg(SrcRegQ, RegState::Undef)
6253 .addReg(SrcRegQ, RegState::Undef)
6254 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6255 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6256 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6257 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6258 &AArch64::FPR64RegClass);
6259 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6260 &AArch64::FPR64RegClass);
6261 // This instruction is reading and writing D registers. This may upset
6262 // the register scavenger and machine verifier, so we need to indicate
6263 // that we are reading an undefined value from SrcRegD, but a proper
6264 // value from SrcReg.
6265 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6266 .addReg(SrcRegD, RegState::Undef)
6267 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6268 } else {
6269 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6270 &AArch64::FPR32RegClass);
6271 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6272 &AArch64::FPR32RegClass);
6273 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6274 .addReg(SrcReg, getKillRegState(KillSrc));
6275 }
6276 return;
6277 }
6278
6279 if (AArch64::FPR8RegClass.contains(DestReg) &&
6280 AArch64::FPR8RegClass.contains(SrcReg)) {
6281 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6282 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6283 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6284 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6285 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6286 &AArch64::FPR128RegClass);
6287 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6288 &AArch64::FPR128RegClass);
6289 // This instruction is reading and writing Q 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 SrcRegQ, but a proper
6292 // value from SrcReg.
6293 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6294 .addReg(SrcRegQ, RegState::Undef)
6295 .addReg(SrcRegQ, RegState::Undef)
6296 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6297 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6298 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6299 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6300 &AArch64::FPR64RegClass);
6301 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6302 &AArch64::FPR64RegClass);
6303 // This instruction is reading and writing D registers. This may upset
6304 // the register scavenger and machine verifier, so we need to indicate
6305 // that we are reading an undefined value from SrcRegD, but a proper
6306 // value from SrcReg.
6307 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6308 .addReg(SrcRegD, RegState::Undef)
6309 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6310 } else {
6311 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6312 &AArch64::FPR32RegClass);
6313 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6314 &AArch64::FPR32RegClass);
6315 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6316 .addReg(SrcReg, getKillRegState(KillSrc));
6317 }
6318 return;
6319 }
6320
6321 // Copies between GPR64 and FPR64.
6322 if (AArch64::FPR64RegClass.contains(DestReg) &&
6323 AArch64::GPR64RegClass.contains(SrcReg)) {
6324 if (AArch64::XZR == SrcReg) {
6325 BuildMI(MBB, I, DL, get(AArch64::FMOVD0), DestReg);
6326 } else {
6327 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
6328 .addReg(SrcReg, getKillRegState(KillSrc));
6329 }
6330 return;
6331 }
6332 if (AArch64::GPR64RegClass.contains(DestReg) &&
6333 AArch64::FPR64RegClass.contains(SrcReg)) {
6334 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
6335 .addReg(SrcReg, getKillRegState(KillSrc));
6336 return;
6337 }
6338 // Copies between GPR32 and FPR32.
6339 if (AArch64::FPR32RegClass.contains(DestReg) &&
6340 AArch64::GPR32RegClass.contains(SrcReg)) {
6341 if (AArch64::WZR == SrcReg) {
6342 BuildMI(MBB, I, DL, get(AArch64::FMOVS0), DestReg);
6343 } else {
6344 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
6345 .addReg(SrcReg, getKillRegState(KillSrc));
6346 }
6347 return;
6348 }
6349 if (AArch64::GPR32RegClass.contains(DestReg) &&
6350 AArch64::FPR32RegClass.contains(SrcReg)) {
6351 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
6352 .addReg(SrcReg, getKillRegState(KillSrc));
6353 return;
6354 }
6355
6356 if (DestReg == AArch64::NZCV) {
6357 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
6358 BuildMI(MBB, I, DL, get(AArch64::MSR))
6359 .addImm(AArch64SysReg::NZCV)
6360 .addReg(SrcReg, getKillRegState(KillSrc))
6361 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
6362 return;
6363 }
6364
6365 if (SrcReg == AArch64::NZCV) {
6366 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
6367 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
6368 .addImm(AArch64SysReg::NZCV)
6369 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
6370 return;
6371 }
6372
6373#ifndef NDEBUG
6374 errs() << RI.getRegAsmName(DestReg) << " = COPY " << RI.getRegAsmName(SrcReg)
6375 << "\n";
6376#endif
6377 llvm_unreachable("unimplemented reg-to-reg copy");
6378}
6379
6382 const DebugLoc &DL, Register DestReg,
6383 Register SrcReg, bool KillSrc,
6384 bool RenamableDest,
6385 bool RenamableSrc) const {
6386 ++NumCopyInstrs;
6387 copyPhysRegImpl(MBB, I, DL, DestReg, SrcReg, KillSrc, RenamableDest,
6388 RenamableSrc);
6389 return;
6390}
6391
6394 MachineBasicBlock::iterator InsertBefore,
6395 const MCInstrDesc &MCID,
6396 Register SrcReg, bool IsKill,
6397 unsigned SubIdx0, unsigned SubIdx1, int FI,
6398 MachineMemOperand *MMO) {
6399 Register SrcReg0 = SrcReg;
6400 Register SrcReg1 = SrcReg;
6401 if (SrcReg.isPhysical()) {
6402 SrcReg0 = TRI.getSubReg(SrcReg, SubIdx0);
6403 SubIdx0 = 0;
6404 SrcReg1 = TRI.getSubReg(SrcReg, SubIdx1);
6405 SubIdx1 = 0;
6406 }
6407 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6408 .addReg(SrcReg0, getKillRegState(IsKill), SubIdx0)
6409 .addReg(SrcReg1, getKillRegState(IsKill), SubIdx1)
6410 .addFrameIndex(FI)
6411 .addImm(0)
6412 .addMemOperand(MMO);
6413}
6414
6417 Register SrcReg, bool isKill, int FI,
6418 const TargetRegisterClass *RC,
6419 Register VReg,
6420 MachineInstr::MIFlag Flags) const {
6421 MachineFunction &MF = *MBB.getParent();
6422 MachineFrameInfo &MFI = MF.getFrameInfo();
6423
6425 MachineMemOperand *MMO =
6427 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6428 unsigned Opc = 0;
6429 bool Offset = true;
6431 unsigned StackID = TargetStackID::Default;
6432 switch (RI.getSpillSize(*RC)) {
6433 case 1:
6434 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6435 Opc = AArch64::STRBui;
6436 break;
6437 case 2: {
6438 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6439 Opc = AArch64::STRHui;
6440 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6441 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6442 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6443 "Unexpected register store without SVE store instructions");
6444 Opc = AArch64::STR_PXI;
6446 }
6447 break;
6448 }
6449 case 4:
6450 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6451 Opc = AArch64::STRWui;
6452 if (SrcReg.isVirtual())
6453 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
6454 else
6455 assert(SrcReg != AArch64::WSP);
6456 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6457 Opc = AArch64::STRSui;
6458 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6459 Opc = AArch64::STR_PPXI;
6461 }
6462 break;
6463 case 8:
6464 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6465 Opc = AArch64::STRXui;
6466 if (SrcReg.isVirtual())
6467 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
6468 else
6469 assert(SrcReg != AArch64::SP);
6470 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6471 Opc = AArch64::STRDui;
6472 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6474 get(AArch64::STPWi), SrcReg, isKill,
6475 AArch64::sube32, AArch64::subo32, FI, MMO);
6476 return;
6477 }
6478 break;
6479 case 16:
6480 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6481 Opc = AArch64::STRQui;
6482 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6483 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6484 Opc = AArch64::ST1Twov1d;
6485 Offset = false;
6486 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6488 get(AArch64::STPXi), SrcReg, isKill,
6489 AArch64::sube64, AArch64::subo64, FI, MMO);
6490 return;
6491 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6492 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6493 "Unexpected register store without SVE store instructions");
6494 Opc = AArch64::STR_ZXI;
6496 }
6497 break;
6498 case 24:
6499 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6500 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6501 Opc = AArch64::ST1Threev1d;
6502 Offset = false;
6503 }
6504 break;
6505 case 32:
6506 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6507 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6508 Opc = AArch64::ST1Fourv1d;
6509 Offset = false;
6510 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6511 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6512 Opc = AArch64::ST1Twov2d;
6513 Offset = false;
6514 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6515 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6516 "Unexpected register store without SVE store instructions");
6517 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6519 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6520 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6521 "Unexpected register store without SVE store instructions");
6522 Opc = AArch64::STR_ZZXI;
6524 }
6525 break;
6526 case 48:
6527 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6528 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6529 Opc = AArch64::ST1Threev2d;
6530 Offset = false;
6531 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6532 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6533 "Unexpected register store without SVE store instructions");
6534 Opc = AArch64::STR_ZZZXI;
6536 }
6537 break;
6538 case 64:
6539 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6540 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6541 Opc = AArch64::ST1Fourv2d;
6542 Offset = false;
6543 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6544 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6545 "Unexpected register store without SVE store instructions");
6546 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6548 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6549 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6550 "Unexpected register store without SVE store instructions");
6551 Opc = AArch64::STR_ZZZZXI;
6553 }
6554 break;
6555 }
6556 assert(Opc && "Unknown register class");
6557 MFI.setStackID(FI, StackID);
6558
6560 .addReg(SrcReg, getKillRegState(isKill))
6561 .addFrameIndex(FI);
6562
6563 if (Offset)
6564 MI.addImm(0);
6565 if (PNRReg.isValid())
6566 MI.addDef(PNRReg, RegState::Implicit);
6567 MI.addMemOperand(MMO);
6568}
6569
6572 MachineBasicBlock::iterator InsertBefore,
6573 const MCInstrDesc &MCID,
6574 Register DestReg, unsigned SubIdx0,
6575 unsigned SubIdx1, int FI,
6576 MachineMemOperand *MMO) {
6577 Register DestReg0 = DestReg;
6578 Register DestReg1 = DestReg;
6579 bool IsUndef = true;
6580 if (DestReg.isPhysical()) {
6581 DestReg0 = TRI.getSubReg(DestReg, SubIdx0);
6582 SubIdx0 = 0;
6583 DestReg1 = TRI.getSubReg(DestReg, SubIdx1);
6584 SubIdx1 = 0;
6585 IsUndef = false;
6586 }
6587 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6588 .addReg(DestReg0, RegState::Define | getUndefRegState(IsUndef), SubIdx0)
6589 .addReg(DestReg1, RegState::Define | getUndefRegState(IsUndef), SubIdx1)
6590 .addFrameIndex(FI)
6591 .addImm(0)
6592 .addMemOperand(MMO);
6593}
6594
6597 Register DestReg, int FI,
6598 const TargetRegisterClass *RC,
6599 Register VReg, unsigned SubReg,
6600 MachineInstr::MIFlag Flags) const {
6601 MachineFunction &MF = *MBB.getParent();
6602 MachineFrameInfo &MFI = MF.getFrameInfo();
6604 MachineMemOperand *MMO =
6606 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6607
6608 unsigned Opc = 0;
6609 bool Offset = true;
6610 unsigned StackID = TargetStackID::Default;
6612 switch (TRI.getSpillSize(*RC)) {
6613 case 1:
6614 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6615 Opc = AArch64::LDRBui;
6616 break;
6617 case 2: {
6618 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6619 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6620 Opc = AArch64::LDRHui;
6621 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6622 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6623 "Unexpected register load without SVE load instructions");
6624 if (IsPNR)
6625 PNRReg = DestReg;
6626 Opc = AArch64::LDR_PXI;
6628 }
6629 break;
6630 }
6631 case 4:
6632 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6633 Opc = AArch64::LDRWui;
6634 if (DestReg.isVirtual())
6635 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
6636 else
6637 assert(DestReg != AArch64::WSP);
6638 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6639 Opc = AArch64::LDRSui;
6640 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6641 Opc = AArch64::LDR_PPXI;
6643 }
6644 break;
6645 case 8:
6646 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6647 Opc = AArch64::LDRXui;
6648 if (DestReg.isVirtual())
6649 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
6650 else
6651 assert(DestReg != AArch64::SP);
6652 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6653 Opc = AArch64::LDRDui;
6654 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6656 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6657 AArch64::subo32, FI, MMO);
6658 return;
6659 }
6660 break;
6661 case 16:
6662 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6663 Opc = AArch64::LDRQui;
6664 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6665 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6666 Opc = AArch64::LD1Twov1d;
6667 Offset = false;
6668 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6670 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6671 AArch64::subo64, FI, MMO);
6672 return;
6673 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6674 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6675 "Unexpected register load without SVE load instructions");
6676 Opc = AArch64::LDR_ZXI;
6678 }
6679 break;
6680 case 24:
6681 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6682 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6683 Opc = AArch64::LD1Threev1d;
6684 Offset = false;
6685 }
6686 break;
6687 case 32:
6688 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6689 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6690 Opc = AArch64::LD1Fourv1d;
6691 Offset = false;
6692 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6693 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6694 Opc = AArch64::LD1Twov2d;
6695 Offset = false;
6696 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6697 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6698 "Unexpected register load without SVE load instructions");
6699 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6701 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6702 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6703 "Unexpected register load without SVE load instructions");
6704 Opc = AArch64::LDR_ZZXI;
6706 }
6707 break;
6708 case 48:
6709 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6710 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6711 Opc = AArch64::LD1Threev2d;
6712 Offset = false;
6713 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6714 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6715 "Unexpected register load without SVE load instructions");
6716 Opc = AArch64::LDR_ZZZXI;
6718 }
6719 break;
6720 case 64:
6721 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6722 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6723 Opc = AArch64::LD1Fourv2d;
6724 Offset = false;
6725 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6726 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6727 "Unexpected register load without SVE load instructions");
6728 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6730 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6731 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6732 "Unexpected register load without SVE load instructions");
6733 Opc = AArch64::LDR_ZZZZXI;
6735 }
6736 break;
6737 }
6738
6739 assert(Opc && "Unknown register class");
6740 MFI.setStackID(FI, StackID);
6741
6743 .addReg(DestReg, getDefRegState(true))
6744 .addFrameIndex(FI);
6745 if (Offset)
6746 MI.addImm(0);
6747 if (PNRReg.isValid() && !PNRReg.isVirtual())
6748 MI.addDef(PNRReg, RegState::Implicit);
6749 MI.addMemOperand(MMO);
6750}
6751
6753 const MachineInstr &UseMI,
6754 const TargetRegisterInfo *TRI) {
6755 return any_of(instructionsWithoutDebug(std::next(DefMI.getIterator()),
6756 UseMI.getIterator()),
6757 [TRI](const MachineInstr &I) {
6758 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6759 I.readsRegister(AArch64::NZCV, TRI);
6760 });
6761}
6762
6763void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6764 const StackOffset &Offset, int64_t &ByteSized, int64_t &VGSized) {
6765 // The smallest scalable element supported by scaled SVE addressing
6766 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6767 // byte offset must always be a multiple of 2.
6768 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6769
6770 // VGSized offsets are divided by '2', because the VG register is the
6771 // the number of 64bit granules as opposed to 128bit vector chunks,
6772 // which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
6773 // So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
6774 // VG = n * 2 and the dwarf offset must be VG * 8 bytes.
6775 ByteSized = Offset.getFixed();
6776 VGSized = Offset.getScalable() / 2;
6777}
6778
6779/// Returns the offset in parts to which this frame offset can be
6780/// decomposed for the purpose of describing a frame offset.
6781/// For non-scalable offsets this is simply its byte size.
6782void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6783 const StackOffset &Offset, int64_t &NumBytes, int64_t &NumPredicateVectors,
6784 int64_t &NumDataVectors) {
6785 // The smallest scalable element supported by scaled SVE addressing
6786 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6787 // byte offset must always be a multiple of 2.
6788 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6789
6790 NumBytes = Offset.getFixed();
6791 NumDataVectors = 0;
6792 NumPredicateVectors = Offset.getScalable() / 2;
6793 // This method is used to get the offsets to adjust the frame offset.
6794 // If the function requires ADDPL to be used and needs more than two ADDPL
6795 // instructions, part of the offset is folded into NumDataVectors so that it
6796 // uses ADDVL for part of it, reducing the number of ADDPL instructions.
6797 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6798 NumPredicateVectors > 62) {
6799 NumDataVectors = NumPredicateVectors / 8;
6800 NumPredicateVectors -= NumDataVectors * 8;
6801 }
6802}
6803
6804// Convenience function to create a DWARF expression for: Constant `Operation`.
6805// This helper emits compact sequences for common cases. For example, for`-15
6806// DW_OP_plus`, this helper would create DW_OP_lit15 DW_OP_minus.
6809 if (Operation == dwarf::DW_OP_plus && Constant < 0 && -Constant <= 31) {
6810 // -Constant (1 to 31)
6811 Expr.push_back(dwarf::DW_OP_lit0 - Constant);
6812 Operation = dwarf::DW_OP_minus;
6813 } else if (Constant >= 0 && Constant <= 31) {
6814 // Literal value 0 to 31
6815 Expr.push_back(dwarf::DW_OP_lit0 + Constant);
6816 } else {
6817 // Signed constant
6818 Expr.push_back(dwarf::DW_OP_consts);
6820 }
6821 return Expr.push_back(Operation);
6822}
6823
6824// Convenience function to create a DWARF expression for a register.
6825static void appendReadRegExpr(SmallVectorImpl<char> &Expr, unsigned RegNum) {
6826 Expr.push_back((char)dwarf::DW_OP_bregx);
6828 Expr.push_back(0);
6829}
6830
6831// Convenience function to create a DWARF expression for loading a register from
6832// a CFA offset.
6834 int64_t OffsetFromDefCFA) {
6835 // This assumes the top of the DWARF stack contains the CFA.
6836 Expr.push_back(dwarf::DW_OP_dup);
6837 // Add the offset to the register.
6838 appendConstantExpr(Expr, OffsetFromDefCFA, dwarf::DW_OP_plus);
6839 // Dereference the address (loads a 64 bit value)..
6840 Expr.push_back(dwarf::DW_OP_deref);
6841}
6842
6843// Convenience function to create a comment for
6844// (+/-) NumBytes (* RegScale)?
6845static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment,
6846 StringRef RegScale = {}) {
6847 if (NumBytes) {
6848 Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
6849 if (!RegScale.empty())
6850 Comment << ' ' << RegScale;
6851 }
6852}
6853
6854// Creates an MCCFIInstruction:
6855// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
6857 unsigned Reg,
6858 const StackOffset &Offset) {
6859 int64_t NumBytes, NumVGScaledBytes;
6860 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(Offset, NumBytes,
6861 NumVGScaledBytes);
6862 std::string CommentBuffer;
6863 llvm::raw_string_ostream Comment(CommentBuffer);
6864
6865 if (Reg == AArch64::SP)
6866 Comment << "sp";
6867 else if (Reg == AArch64::FP)
6868 Comment << "fp";
6869 else
6870 Comment << printReg(Reg, &TRI);
6871
6872 // Build up the expression (Reg + NumBytes + VG * NumVGScaledBytes)
6873 SmallString<64> Expr;
6874 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6875 assert(DwarfReg <= 31 && "DwarfReg out of bounds (0..31)");
6876 // Reg + NumBytes
6877 Expr.push_back(dwarf::DW_OP_breg0 + DwarfReg);
6878 appendLEB128<LEB128Sign::Signed>(Expr, NumBytes);
6879 appendOffsetComment(NumBytes, Comment);
6880 if (NumVGScaledBytes) {
6881 // + VG * NumVGScaledBytes
6882 appendOffsetComment(NumVGScaledBytes, Comment, "* VG");
6883 appendReadRegExpr(Expr, TRI.getDwarfRegNum(AArch64::VG, true));
6884 appendConstantExpr(Expr, NumVGScaledBytes, dwarf::DW_OP_mul);
6885 Expr.push_back(dwarf::DW_OP_plus);
6886 }
6887
6888 // Wrap this into DW_CFA_def_cfa.
6889 SmallString<64> DefCfaExpr;
6890 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
6891 appendLEB128<LEB128Sign::Unsigned>(DefCfaExpr, Expr.size());
6892 DefCfaExpr.append(Expr.str());
6893 return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
6894 Comment.str());
6895}
6896
6898 unsigned FrameReg, unsigned Reg,
6899 const StackOffset &Offset,
6900 bool LastAdjustmentWasScalable) {
6901 if (Offset.getScalable())
6902 return createDefCFAExpression(TRI, Reg, Offset);
6903
6904 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6905 return MCCFIInstruction::cfiDefCfaOffset(nullptr, int(Offset.getFixed()));
6906
6907 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6908 return MCCFIInstruction::cfiDefCfa(nullptr, DwarfReg, (int)Offset.getFixed());
6909}
6910
6913 const StackOffset &OffsetFromDefCFA,
6914 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6915 int64_t NumBytes, NumVGScaledBytes;
6916 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6917 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6918
6919 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6920
6921 // Non-scalable offsets can use DW_CFA_offset directly.
6922 if (!NumVGScaledBytes)
6923 return MCCFIInstruction::createOffset(nullptr, DwarfReg, NumBytes);
6924
6925 std::string CommentBuffer;
6926 llvm::raw_string_ostream Comment(CommentBuffer);
6927 Comment << printReg(Reg, &TRI) << " @ cfa";
6928
6929 // Build up expression (CFA + VG * NumVGScaledBytes + NumBytes)
6930 assert(NumVGScaledBytes && "Expected scalable offset");
6931 SmallString<64> OffsetExpr;
6932 // + VG * NumVGScaledBytes
6933 StringRef VGRegScale;
6934 if (IncomingVGOffsetFromDefCFA) {
6935 appendLoadRegExpr(OffsetExpr, *IncomingVGOffsetFromDefCFA);
6936 VGRegScale = "* IncomingVG";
6937 } else {
6938 appendReadRegExpr(OffsetExpr, TRI.getDwarfRegNum(AArch64::VG, true));
6939 VGRegScale = "* VG";
6940 }
6941 appendConstantExpr(OffsetExpr, NumVGScaledBytes, dwarf::DW_OP_mul);
6942 appendOffsetComment(NumVGScaledBytes, Comment, VGRegScale);
6943 OffsetExpr.push_back(dwarf::DW_OP_plus);
6944 if (NumBytes) {
6945 // + NumBytes
6946 appendOffsetComment(NumBytes, Comment);
6947 appendConstantExpr(OffsetExpr, NumBytes, dwarf::DW_OP_plus);
6948 }
6949
6950 // Wrap this into DW_CFA_expression
6951 SmallString<64> CfaExpr;
6952 CfaExpr.push_back(dwarf::DW_CFA_expression);
6953 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, DwarfReg);
6954 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, OffsetExpr.size());
6955 CfaExpr.append(OffsetExpr.str());
6956
6957 return MCCFIInstruction::createEscape(nullptr, CfaExpr.str(), SMLoc(),
6958 Comment.str());
6959}
6960
6961// Helper function to emit a frame offset adjustment from a given
6962// pointer (SrcReg), stored into DestReg. This function is explicit
6963// in that it requires the opcode.
6966 const DebugLoc &DL, unsigned DestReg,
6967 unsigned SrcReg, int64_t Offset, unsigned Opc,
6968 const TargetInstrInfo *TII,
6969 MachineInstr::MIFlag Flag, bool NeedsWinCFI,
6970 bool *HasWinCFI, bool EmitCFAOffset,
6971 StackOffset CFAOffset, unsigned FrameReg) {
6972 int Sign = 1;
6973 unsigned MaxEncoding, ShiftSize;
6974 switch (Opc) {
6975 case AArch64::ADDXri:
6976 case AArch64::ADDSXri:
6977 case AArch64::SUBXri:
6978 case AArch64::SUBSXri:
6979 MaxEncoding = 0xfff;
6980 ShiftSize = 12;
6981 break;
6982 case AArch64::ADDVL_XXI:
6983 case AArch64::ADDPL_XXI:
6984 case AArch64::ADDSVL_XXI:
6985 case AArch64::ADDSPL_XXI:
6986 MaxEncoding = 31;
6987 ShiftSize = 0;
6988 if (Offset < 0) {
6989 MaxEncoding = 32;
6990 Sign = -1;
6991 Offset = -Offset;
6992 }
6993 break;
6994 default:
6995 llvm_unreachable("Unsupported opcode");
6996 }
6997
6998 // `Offset` can be in bytes or in "scalable bytes".
6999 int VScale = 1;
7000 if (Opc == AArch64::ADDVL_XXI || Opc == AArch64::ADDSVL_XXI)
7001 VScale = 16;
7002 else if (Opc == AArch64::ADDPL_XXI || Opc == AArch64::ADDSPL_XXI)
7003 VScale = 2;
7004
7005 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
7006 // scratch register. If DestReg is a virtual register, use it as the
7007 // scratch register; otherwise, create a new virtual register (to be
7008 // replaced by the scavenger at the end of PEI). That case can be optimized
7009 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
7010 // register can be loaded with offset%8 and the add/sub can use an extending
7011 // instruction with LSL#3.
7012 // Currently the function handles any offsets but generates a poor sequence
7013 // of code.
7014 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
7015
7016 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
7017 Register TmpReg = DestReg;
7018 if (TmpReg == AArch64::XZR)
7019 TmpReg = MBB.getParent()->getRegInfo().createVirtualRegister(
7020 &AArch64::GPR64RegClass);
7021 do {
7022 uint64_t ThisVal = std::min<uint64_t>(Offset, MaxEncodableValue);
7023 unsigned LocalShiftSize = 0;
7024 if (ThisVal > MaxEncoding) {
7025 ThisVal = ThisVal >> ShiftSize;
7026 LocalShiftSize = ShiftSize;
7027 }
7028 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
7029 "Encoding cannot handle value that big");
7030
7031 Offset -= ThisVal << LocalShiftSize;
7032 if (Offset == 0)
7033 TmpReg = DestReg;
7034 auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), TmpReg)
7035 .addReg(SrcReg)
7036 .addImm(Sign * (int)ThisVal);
7037 if (ShiftSize)
7038 MBI = MBI.addImm(
7040 MBI = MBI.setMIFlag(Flag);
7041
7042 auto Change =
7043 VScale == 1
7044 ? StackOffset::getFixed(ThisVal << LocalShiftSize)
7045 : StackOffset::getScalable(VScale * (ThisVal << LocalShiftSize));
7046 if (Sign == -1 || Opc == AArch64::SUBXri || Opc == AArch64::SUBSXri)
7047 CFAOffset += Change;
7048 else
7049 CFAOffset -= Change;
7050 if (EmitCFAOffset && DestReg == TmpReg) {
7051 MachineFunction &MF = *MBB.getParent();
7052 const TargetSubtargetInfo &STI = MF.getSubtarget();
7053 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
7054
7055 unsigned CFIIndex = MF.addFrameInst(
7056 createDefCFA(TRI, FrameReg, DestReg, CFAOffset, VScale != 1));
7057 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
7058 .addCFIIndex(CFIIndex)
7059 .setMIFlags(Flag);
7060 }
7061
7062 if (NeedsWinCFI) {
7063 int Imm = (int)(ThisVal << LocalShiftSize);
7064 if (VScale != 1 && DestReg == AArch64::SP) {
7065 if (HasWinCFI)
7066 *HasWinCFI = true;
7067 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ))
7068 .addImm(ThisVal)
7069 .setMIFlag(Flag);
7070 } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7071 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7072 assert(VScale == 1 && "Expected non-scalable operation");
7073 if (HasWinCFI)
7074 *HasWinCFI = true;
7075 if (Imm == 0)
7076 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
7077 else
7078 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
7079 .addImm(Imm)
7080 .setMIFlag(Flag);
7081 assert(Offset == 0 && "Expected remaining offset to be zero to "
7082 "emit a single SEH directive");
7083 } else if (DestReg == AArch64::SP) {
7084 assert(VScale == 1 && "Expected non-scalable operation");
7085 if (HasWinCFI)
7086 *HasWinCFI = true;
7087 assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
7088 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
7089 .addImm(Imm)
7090 .setMIFlag(Flag);
7091 }
7092 }
7093
7094 SrcReg = TmpReg;
7095 } while (Offset);
7096}
7097
7100 unsigned DestReg, unsigned SrcReg,
7102 MachineInstr::MIFlag Flag, bool SetNZCV,
7103 bool NeedsWinCFI, bool *HasWinCFI,
7104 bool EmitCFAOffset, StackOffset CFAOffset,
7105 unsigned FrameReg) {
7106 // If a function is marked as arm_locally_streaming, then the runtime value of
7107 // vscale in the prologue/epilogue is different the runtime value of vscale
7108 // in the function's body. To avoid having to consider multiple vscales,
7109 // we can use `addsvl` to allocate any scalable stack-slots, which under
7110 // most circumstances will be only locals, not callee-save slots.
7111 const Function &F = MBB.getParent()->getFunction();
7112 bool UseSVL = F.hasFnAttribute("aarch64_pstate_sm_body");
7113
7114 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7115 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7116 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7117
7118 // Insert ADDSXri for scalable offset at the end.
7119 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7120 if (NeedsFinalDefNZCV)
7121 SetNZCV = false;
7122
7123 // First emit non-scalable frame offsets, or a simple 'mov'.
7124 if (Bytes || (!Offset && SrcReg != DestReg)) {
7125 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7126 "SP increment/decrement not 8-byte aligned");
7127 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7128 if (Bytes < 0) {
7129 Bytes = -Bytes;
7130 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7131 }
7132 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
7133 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7134 FrameReg);
7135 CFAOffset += (Opc == AArch64::ADDXri || Opc == AArch64::ADDSXri)
7136 ? StackOffset::getFixed(-Bytes)
7137 : StackOffset::getFixed(Bytes);
7138 SrcReg = DestReg;
7139 FrameReg = DestReg;
7140 }
7141
7142 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7143 "WinCFI can't allocate fractions of an SVE data vector");
7144
7145 if (NumDataVectors) {
7146 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors,
7147 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII,
7148 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7149 FrameReg);
7150 CFAOffset += StackOffset::getScalable(-NumDataVectors * 16);
7151 SrcReg = DestReg;
7152 }
7153
7154 if (NumPredicateVectors) {
7155 assert(DestReg != AArch64::SP && "Unaligned access to SP");
7156 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors,
7157 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII,
7158 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7159 FrameReg);
7160 }
7161
7162 if (NeedsFinalDefNZCV)
7163 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDSXri), DestReg)
7164 .addReg(DestReg)
7165 .addImm(0)
7166 .addImm(0);
7167}
7168
7171 int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS,
7172 VirtRegMap *VRM) const {
7174 // This is a bit of a hack. Consider this instruction:
7175 //
7176 // %0 = COPY %sp; GPR64all:%0
7177 //
7178 // We explicitly chose GPR64all for the virtual register so such a copy might
7179 // be eliminated by RegisterCoalescer. However, that may not be possible, and
7180 // %0 may even spill. We can't spill %sp, and since it is in the GPR64all
7181 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
7182 //
7183 // To prevent that, we are going to constrain the %0 register class here.
7184 if (MI.isFullCopy()) {
7185 Register DstReg = MI.getOperand(0).getReg();
7186 Register SrcReg = MI.getOperand(1).getReg();
7187 if (SrcReg == AArch64::SP && DstReg.isVirtual()) {
7188 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
7189 return nullptr;
7190 }
7191 if (DstReg == AArch64::SP && SrcReg.isVirtual()) {
7192 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
7193 return nullptr;
7194 }
7195 // Nothing can folded with copy from/to NZCV.
7196 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7197 return nullptr;
7198 }
7199
7200 // Handle the case where a copy is being spilled or filled but the source
7201 // and destination register class don't match. For example:
7202 //
7203 // %0 = COPY %xzr; GPR64common:%0
7204 //
7205 // In this case we can still safely fold away the COPY and generate the
7206 // following spill code:
7207 //
7208 // STRXui %xzr, %stack.0
7209 //
7210 // This also eliminates spilled cross register class COPYs (e.g. between x and
7211 // d regs) of the same size. For example:
7212 //
7213 // %0 = COPY %1; GPR64:%0, FPR64:%1
7214 //
7215 // will be filled as
7216 //
7217 // LDRDui %0, fi<#0>
7218 //
7219 // instead of
7220 //
7221 // LDRXui %Temp, fi<#0>
7222 // %0 = FMOV %Temp
7223 //
7224 if (MI.isCopy() && Ops.size() == 1 &&
7225 // Make sure we're only folding the explicit COPY defs/uses.
7226 (Ops[0] == 0 || Ops[0] == 1)) {
7227 bool IsSpill = Ops[0] == 0;
7228 bool IsFill = !IsSpill;
7230 const MachineRegisterInfo &MRI = MF.getRegInfo();
7231 MachineBasicBlock &MBB = *MI.getParent();
7232 const MachineOperand &DstMO = MI.getOperand(0);
7233 const MachineOperand &SrcMO = MI.getOperand(1);
7234 Register DstReg = DstMO.getReg();
7235 Register SrcReg = SrcMO.getReg();
7236 // This is slightly expensive to compute for physical regs since
7237 // getMinimalPhysRegClass is slow.
7238 auto getRegClass = [&](unsigned Reg) {
7239 return Register::isVirtualRegister(Reg) ? MRI.getRegClass(Reg)
7240 : TRI.getMinimalPhysRegClass(Reg);
7241 };
7242
7243 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
7244 assert(TRI.getRegSizeInBits(*getRegClass(DstReg)) ==
7245 TRI.getRegSizeInBits(*getRegClass(SrcReg)) &&
7246 "Mismatched register size in non subreg COPY");
7247 if (IsSpill)
7248 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
7249 getRegClass(SrcReg), Register());
7250 else
7251 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
7252 getRegClass(DstReg), Register());
7253 return &*--InsertPt;
7254 }
7255
7256 // Handle cases like spilling def of:
7257 //
7258 // %0:sub_32<def,read-undef> = COPY %wzr; GPR64common:%0
7259 //
7260 // where the physical register source can be widened and stored to the full
7261 // virtual reg destination stack slot, in this case producing:
7262 //
7263 // STRXui %xzr, %stack.0
7264 //
7265 if (IsSpill && DstMO.isUndef() && SrcReg == AArch64::WZR &&
7266 TRI.getRegSizeInBits(*getRegClass(DstReg)) == 64) {
7267 assert(SrcMO.getSubReg() == 0 &&
7268 "Unexpected subreg on physical register");
7269 storeRegToStackSlot(MBB, InsertPt, AArch64::XZR, SrcMO.isKill(),
7270 FrameIndex, &AArch64::GPR64RegClass, Register());
7271 return &*--InsertPt;
7272 }
7273
7274 // Handle cases like filling use of:
7275 //
7276 // %0:sub_32<def,read-undef> = COPY %1; GPR64:%0, GPR32:%1
7277 //
7278 // where we can load the full virtual reg source stack slot, into the subreg
7279 // destination, in this case producing:
7280 //
7281 // LDRWui %0:sub_32<def,read-undef>, %stack.0
7282 //
7283 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
7284 const TargetRegisterClass *FillRC = nullptr;
7285 switch (DstMO.getSubReg()) {
7286 default:
7287 break;
7288 case AArch64::sub_32:
7289 if (AArch64::GPR64RegClass.hasSubClassEq(getRegClass(DstReg)))
7290 FillRC = &AArch64::GPR32RegClass;
7291 break;
7292 case AArch64::ssub:
7293 FillRC = &AArch64::FPR32RegClass;
7294 break;
7295 case AArch64::dsub:
7296 FillRC = &AArch64::FPR64RegClass;
7297 break;
7298 }
7299
7300 if (FillRC) {
7301 assert(TRI.getRegSizeInBits(*getRegClass(SrcReg)) ==
7302 TRI.getRegSizeInBits(*FillRC) &&
7303 "Mismatched regclass size on folded subreg COPY");
7304 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC,
7305 Register());
7306 MachineInstr &LoadMI = *--InsertPt;
7307 MachineOperand &LoadDst = LoadMI.getOperand(0);
7308 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
7309 LoadDst.setSubReg(DstMO.getSubReg());
7310 LoadDst.setIsUndef();
7311 return &LoadMI;
7312 }
7313 }
7314 }
7315
7316 // Cannot fold.
7317 return nullptr;
7318}
7319
7321 StackOffset &SOffset,
7322 bool *OutUseUnscaledOp,
7323 unsigned *OutUnscaledOp,
7324 int64_t *EmittableOffset) {
7325 // Set output values in case of early exit.
7326 if (EmittableOffset)
7327 *EmittableOffset = 0;
7328 if (OutUseUnscaledOp)
7329 *OutUseUnscaledOp = false;
7330 if (OutUnscaledOp)
7331 *OutUnscaledOp = 0;
7332
7333 // Exit early for structured vector spills/fills as they can't take an
7334 // immediate offset.
7335 switch (MI.getOpcode()) {
7336 default:
7337 break;
7338 case AArch64::LD1Rv1d:
7339 case AArch64::LD1Rv2s:
7340 case AArch64::LD1Rv2d:
7341 case AArch64::LD1Rv4h:
7342 case AArch64::LD1Rv4s:
7343 case AArch64::LD1Rv8b:
7344 case AArch64::LD1Rv8h:
7345 case AArch64::LD1Rv16b:
7346 case AArch64::LD1Twov2d:
7347 case AArch64::LD1Threev2d:
7348 case AArch64::LD1Fourv2d:
7349 case AArch64::LD1Twov1d:
7350 case AArch64::LD1Threev1d:
7351 case AArch64::LD1Fourv1d:
7352 case AArch64::ST1Twov2d:
7353 case AArch64::ST1Threev2d:
7354 case AArch64::ST1Fourv2d:
7355 case AArch64::ST1Twov1d:
7356 case AArch64::ST1Threev1d:
7357 case AArch64::ST1Fourv1d:
7358 case AArch64::ST1i8:
7359 case AArch64::ST1i16:
7360 case AArch64::ST1i32:
7361 case AArch64::ST1i64:
7362 case AArch64::IRG:
7363 case AArch64::IRGstack:
7364 case AArch64::STGloop:
7365 case AArch64::STZGloop:
7367 }
7368
7369 // Get the min/max offset and the scale.
7370 TypeSize ScaleValue(0U, false), Width(0U, false);
7371 int64_t MinOff, MaxOff;
7372 if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), ScaleValue, Width, MinOff,
7373 MaxOff))
7374 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7375
7376 // Construct the complete offset.
7377 bool IsMulVL = ScaleValue.isScalable();
7378 unsigned Scale = ScaleValue.getKnownMinValue();
7379 int64_t Offset = IsMulVL ? SOffset.getScalable() : SOffset.getFixed();
7380
7381 const MachineOperand &ImmOpnd =
7382 MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode()));
7383 Offset += ImmOpnd.getImm() * Scale;
7384
7385 // If the offset doesn't match the scale, we rewrite the instruction to
7386 // use the unscaled instruction instead. Likewise, if we have a negative
7387 // offset and there is an unscaled op to use.
7388 std::optional<unsigned> UnscaledOp =
7390 bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0);
7391 if (useUnscaledOp &&
7392 !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, ScaleValue, Width, MinOff,
7393 MaxOff))
7394 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7395
7396 Scale = ScaleValue.getKnownMinValue();
7397 assert(IsMulVL == ScaleValue.isScalable() &&
7398 "Unscaled opcode has different value for scalable");
7399
7400 int64_t Remainder = Offset % Scale;
7401 assert(!(Remainder && useUnscaledOp) &&
7402 "Cannot have remainder when using unscaled op");
7403
7404 assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
7405 int64_t NewOffset = Offset / Scale;
7406 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7407 Offset = Remainder;
7408 else {
7409 // Try to minimise the number of instructions required to materialise the
7410 // offset calculation. Specifically, for fixed offsets, if masking out the
7411 // low 12 bits leaves a legal add immediate, we can realise the offset
7412 // calculation with a single add instruction. Whenever this is possible,
7413 // prefer this split.
7414 int64_t HighPart = Offset & ~0xFFF;
7415 int64_t LowPart = Offset & 0xFFF;
7416 int64_t LowScaled = LowPart / Scale;
7417 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7418 MinOff <= LowScaled && LowScaled <= MaxOff &&
7420 NewOffset = LowScaled;
7421 Offset = HighPart;
7422 } else {
7423 // Default to a greedy split: take the memop immediate to be maximum /
7424 // minimum expressible offset and materialise the remainder.
7425 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7426 Offset = Offset - (NewOffset * Scale);
7427 }
7428 }
7429
7430 if (EmittableOffset)
7431 *EmittableOffset = NewOffset;
7432 if (OutUseUnscaledOp)
7433 *OutUseUnscaledOp = useUnscaledOp;
7434 if (OutUnscaledOp && UnscaledOp)
7435 *OutUnscaledOp = *UnscaledOp;
7436
7437 if (IsMulVL)
7438 SOffset = StackOffset::get(SOffset.getFixed(), Offset);
7439 else
7440 SOffset = StackOffset::get(Offset, SOffset.getScalable());
7442 (SOffset ? 0 : AArch64FrameOffsetIsLegal);
7443}
7444
7446 unsigned FrameReg, StackOffset &Offset,
7447 const AArch64InstrInfo *TII) {
7448 unsigned Opcode = MI.getOpcode();
7449 unsigned ImmIdx = FrameRegIdx + 1;
7450
7451 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7452 Offset += StackOffset::getFixed(MI.getOperand(ImmIdx).getImm());
7453 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
7454 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
7455 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
7456 MI.eraseFromParent();
7457 Offset = StackOffset();
7458 return true;
7459 }
7460
7461 int64_t NewOffset;
7462 unsigned UnscaledOp;
7463 bool UseUnscaledOp;
7464 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
7465 &UnscaledOp, &NewOffset);
7468 // Replace the FrameIndex with FrameReg.
7469 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
7470 if (UseUnscaledOp)
7471 MI.setDesc(TII->get(UnscaledOp));
7472
7473 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7474 return !Offset;
7475 }
7476
7477 return false;
7478}
7479
7485
7486MCInst AArch64InstrInfo::getNop() const { return MCInstBuilder(AArch64::NOP); }
7487
7488// AArch64 supports MachineCombiner.
7489bool AArch64InstrInfo::useMachineCombiner() const { return true; }
7490
7491// True when Opc sets flag
7492static bool isCombineInstrSettingFlag(unsigned Opc) {
7493 switch (Opc) {
7494 case AArch64::ADDSWrr:
7495 case AArch64::ADDSWri:
7496 case AArch64::ADDSXrr:
7497 case AArch64::ADDSXri:
7498 case AArch64::SUBSWrr:
7499 case AArch64::SUBSXrr:
7500 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7501 case AArch64::SUBSWri:
7502 case AArch64::SUBSXri:
7503 return true;
7504 default:
7505 break;
7506 }
7507 return false;
7508}
7509
7510// 32b Opcodes that can be combined with a MUL
7511static bool isCombineInstrCandidate32(unsigned Opc) {
7512 switch (Opc) {
7513 case AArch64::ADDWrr:
7514 case AArch64::ADDWri:
7515 case AArch64::SUBWrr:
7516 case AArch64::ADDSWrr:
7517 case AArch64::ADDSWri:
7518 case AArch64::SUBSWrr:
7519 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7520 case AArch64::SUBWri:
7521 case AArch64::SUBSWri:
7522 return true;
7523 default:
7524 break;
7525 }
7526 return false;
7527}
7528
7529// 64b Opcodes that can be combined with a MUL
7530static bool isCombineInstrCandidate64(unsigned Opc) {
7531 switch (Opc) {
7532 case AArch64::ADDXrr:
7533 case AArch64::ADDXri:
7534 case AArch64::SUBXrr:
7535 case AArch64::ADDSXrr:
7536 case AArch64::ADDSXri:
7537 case AArch64::SUBSXrr:
7538 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7539 case AArch64::SUBXri:
7540 case AArch64::SUBSXri:
7541 case AArch64::ADDv8i8:
7542 case AArch64::ADDv16i8:
7543 case AArch64::ADDv4i16:
7544 case AArch64::ADDv8i16:
7545 case AArch64::ADDv2i32:
7546 case AArch64::ADDv4i32:
7547 case AArch64::SUBv8i8:
7548 case AArch64::SUBv16i8:
7549 case AArch64::SUBv4i16:
7550 case AArch64::SUBv8i16:
7551 case AArch64::SUBv2i32:
7552 case AArch64::SUBv4i32:
7553 return true;
7554 default:
7555 break;
7556 }
7557 return false;
7558}
7559
7560// FP Opcodes that can be combined with a FMUL.
7561static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
7562 switch (Inst.getOpcode()) {
7563 default:
7564 break;
7565 case AArch64::FADDHrr:
7566 case AArch64::FADDSrr:
7567 case AArch64::FADDDrr:
7568 case AArch64::FADDv4f16:
7569 case AArch64::FADDv8f16:
7570 case AArch64::FADDv2f32:
7571 case AArch64::FADDv2f64:
7572 case AArch64::FADDv4f32:
7573 case AArch64::FSUBHrr:
7574 case AArch64::FSUBSrr:
7575 case AArch64::FSUBDrr:
7576 case AArch64::FSUBv4f16:
7577 case AArch64::FSUBv8f16:
7578 case AArch64::FSUBv2f32:
7579 case AArch64::FSUBv2f64:
7580 case AArch64::FSUBv4f32:
7581 // We can fuse FADD/FSUB with FMUL, if FADD/FSUB has the contract fast-math
7582 // flag.
7583 return Inst.getFlag(MachineInstr::FmContract);
7584 }
7585 return false;
7586}
7587
7588// Opcodes that can be combined with a MUL
7592
7593//
7594// Utility routine that checks if \param MO is defined by an
7595// \param CombineOpc instruction in the basic block \param MBB
7597 unsigned CombineOpc, unsigned ZeroReg = 0,
7598 bool CheckZeroReg = false) {
7599 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
7600 MachineInstr *MI = nullptr;
7601
7602 if (MO.isReg() && MO.getReg().isVirtual())
7603 MI = MRI.getUniqueVRegDef(MO.getReg());
7604 // And it needs to be in the trace (otherwise, it won't have a depth).
7605 if (!MI || MI->getParent() != &MBB || MI->getOpcode() != CombineOpc)
7606 return false;
7607 // Must only used by the user we combine with.
7608 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
7609 return false;
7610
7611 if (CheckZeroReg) {
7612 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
7613 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
7614 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
7615 // The third input reg must be zero.
7616 if (MI->getOperand(3).getReg() != ZeroReg)
7617 return false;
7618 }
7619
7620 if (isCombineInstrSettingFlag(CombineOpc) &&
7621 MI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) == -1)
7622 return false;
7623
7624 return true;
7625}
7626
7627//
7628// Is \param MO defined by an integer multiply and can be combined?
7630 unsigned MulOpc, unsigned ZeroReg) {
7631 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
7632}
7633
7634//
7635// Is \param MO defined by a floating-point multiply and can be combined?
7637 unsigned MulOpc) {
7638 return canCombine(MBB, MO, MulOpc);
7639}
7640
7641// TODO: There are many more machine instruction opcodes to match:
7642// 1. Other data types (integer, vectors)
7643// 2. Other math / logic operations (xor, or)
7644// 3. Other forms of the same operation (intrinsics and other variants)
7645bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
7646 bool Invert) const {
7647 if (Invert)
7648 return false;
7649 switch (Inst.getOpcode()) {
7650 // == Floating-point types ==
7651 // -- Floating-point instructions --
7652 case AArch64::FADDHrr:
7653 case AArch64::FADDSrr:
7654 case AArch64::FADDDrr:
7655 case AArch64::FMULHrr:
7656 case AArch64::FMULSrr:
7657 case AArch64::FMULDrr:
7658 case AArch64::FMULX16:
7659 case AArch64::FMULX32:
7660 case AArch64::FMULX64:
7661 // -- Advanced SIMD instructions --
7662 case AArch64::FADDv4f16:
7663 case AArch64::FADDv8f16:
7664 case AArch64::FADDv2f32:
7665 case AArch64::FADDv4f32:
7666 case AArch64::FADDv2f64:
7667 case AArch64::FMULv4f16:
7668 case AArch64::FMULv8f16:
7669 case AArch64::FMULv2f32:
7670 case AArch64::FMULv4f32:
7671 case AArch64::FMULv2f64:
7672 case AArch64::FMULXv4f16:
7673 case AArch64::FMULXv8f16:
7674 case AArch64::FMULXv2f32:
7675 case AArch64::FMULXv4f32:
7676 case AArch64::FMULXv2f64:
7677 // -- SVE instructions --
7678 // Opcodes FMULX_ZZZ_? don't exist because there is no unpredicated FMULX
7679 // in the SVE instruction set (though there are predicated ones).
7680 case AArch64::FADD_ZZZ_H:
7681 case AArch64::FADD_ZZZ_S:
7682 case AArch64::FADD_ZZZ_D:
7683 case AArch64::FMUL_ZZZ_H:
7684 case AArch64::FMUL_ZZZ_S:
7685 case AArch64::FMUL_ZZZ_D:
7688
7689 // == Integer types ==
7690 // -- Base instructions --
7691 // Opcodes MULWrr and MULXrr don't exist because
7692 // `MUL <Wd>, <Wn>, <Wm>` and `MUL <Xd>, <Xn>, <Xm>` are aliases of
7693 // `MADD <Wd>, <Wn>, <Wm>, WZR` and `MADD <Xd>, <Xn>, <Xm>, XZR` respectively.
7694 // The machine-combiner does not support three-source-operands machine
7695 // instruction. So we cannot reassociate MULs.
7696 case AArch64::ADDWrr:
7697 case AArch64::ADDXrr:
7698 case AArch64::ANDWrr:
7699 case AArch64::ANDXrr:
7700 case AArch64::ORRWrr:
7701 case AArch64::ORRXrr:
7702 case AArch64::EORWrr:
7703 case AArch64::EORXrr:
7704 case AArch64::EONWrr:
7705 case AArch64::EONXrr:
7706 // -- Advanced SIMD instructions --
7707 // Opcodes MULv1i64 and MULv2i64 don't exist because there is no 64-bit MUL
7708 // in the Advanced SIMD instruction set.
7709 case AArch64::ADDv8i8:
7710 case AArch64::ADDv16i8:
7711 case AArch64::ADDv4i16:
7712 case AArch64::ADDv8i16:
7713 case AArch64::ADDv2i32:
7714 case AArch64::ADDv4i32:
7715 case AArch64::ADDv1i64:
7716 case AArch64::ADDv2i64:
7717 case AArch64::MULv8i8:
7718 case AArch64::MULv16i8:
7719 case AArch64::MULv4i16:
7720 case AArch64::MULv8i16:
7721 case AArch64::MULv2i32:
7722 case AArch64::MULv4i32:
7723 case AArch64::ANDv8i8:
7724 case AArch64::ANDv16i8:
7725 case AArch64::ORRv8i8:
7726 case AArch64::ORRv16i8:
7727 case AArch64::EORv8i8:
7728 case AArch64::EORv16i8:
7729 // -- SVE instructions --
7730 case AArch64::ADD_ZZZ_B:
7731 case AArch64::ADD_ZZZ_H:
7732 case AArch64::ADD_ZZZ_S:
7733 case AArch64::ADD_ZZZ_D:
7734 case AArch64::MUL_ZZZ_B:
7735 case AArch64::MUL_ZZZ_H:
7736 case AArch64::MUL_ZZZ_S:
7737 case AArch64::MUL_ZZZ_D:
7738 case AArch64::AND_ZZZ:
7739 case AArch64::ORR_ZZZ:
7740 case AArch64::EOR_ZZZ:
7741 return true;
7742
7743 default:
7744 return false;
7745 }
7746}
7747
7748/// Find instructions that can be turned into madd.
7750 SmallVectorImpl<unsigned> &Patterns) {
7751 unsigned Opc = Root.getOpcode();
7752 MachineBasicBlock &MBB = *Root.getParent();
7753 bool Found = false;
7754
7756 return false;
7758 int Cmp_NZCV =
7759 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
7760 // When NZCV is live bail out.
7761 if (Cmp_NZCV == -1)
7762 return false;
7763 unsigned NewOpc = convertToNonFlagSettingOpc(Root);
7764 // When opcode can't change bail out.
7765 // CHECKME: do we miss any cases for opcode conversion?
7766 if (NewOpc == Opc)
7767 return false;
7768 Opc = NewOpc;
7769 }
7770
7771 auto setFound = [&](int Opcode, int Operand, unsigned ZeroReg,
7772 unsigned Pattern) {
7773 if (canCombineWithMUL(MBB, Root.getOperand(Operand), Opcode, ZeroReg)) {
7774 Patterns.push_back(Pattern);
7775 Found = true;
7776 }
7777 };
7778
7779 auto setVFound = [&](int Opcode, int Operand, unsigned Pattern) {
7780 if (canCombine(MBB, Root.getOperand(Operand), Opcode)) {
7781 Patterns.push_back(Pattern);
7782 Found = true;
7783 }
7784 };
7785
7787
7788 switch (Opc) {
7789 default:
7790 break;
7791 case AArch64::ADDWrr:
7792 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
7793 "ADDWrr does not have register operands");
7794 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7795 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7796 break;
7797 case AArch64::ADDXrr:
7798 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7799 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7800 break;
7801 case AArch64::SUBWrr:
7802 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7803 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7804 break;
7805 case AArch64::SUBXrr:
7806 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7807 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7808 break;
7809 case AArch64::ADDWri:
7810 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7811 break;
7812 case AArch64::ADDXri:
7813 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7814 break;
7815 case AArch64::SUBWri:
7816 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7817 break;
7818 case AArch64::SUBXri:
7819 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7820 break;
7821 case AArch64::ADDv8i8:
7822 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7823 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7824 break;
7825 case AArch64::ADDv16i8:
7826 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7827 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7828 break;
7829 case AArch64::ADDv4i16:
7830 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7831 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7832 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7833 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7834 break;
7835 case AArch64::ADDv8i16:
7836 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7837 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7838 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7839 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7840 break;
7841 case AArch64::ADDv2i32:
7842 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7843 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7844 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7845 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7846 break;
7847 case AArch64::ADDv4i32:
7848 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7849 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7850 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7851 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7852 break;
7853 case AArch64::SUBv8i8:
7854 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7855 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7856 break;
7857 case AArch64::SUBv16i8:
7858 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7859 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7860 break;
7861 case AArch64::SUBv4i16:
7862 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7863 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7864 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7865 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7866 break;
7867 case AArch64::SUBv8i16:
7868 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7869 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7870 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7871 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7872 break;
7873 case AArch64::SUBv2i32:
7874 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7875 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7876 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7877 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7878 break;
7879 case AArch64::SUBv4i32:
7880 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7881 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7882 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7883 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7884 break;
7885 }
7886 return Found;
7887}
7888
7889bool AArch64InstrInfo::isAccumulationOpcode(unsigned Opcode) const {
7890 switch (Opcode) {
7891 default:
7892 break;
7893 case AArch64::UABALB_ZZZ_D:
7894 case AArch64::UABALB_ZZZ_H:
7895 case AArch64::UABALB_ZZZ_S:
7896 case AArch64::UABALT_ZZZ_D:
7897 case AArch64::UABALT_ZZZ_H:
7898 case AArch64::UABALT_ZZZ_S:
7899 case AArch64::SABALB_ZZZ_D:
7900 case AArch64::SABALB_ZZZ_S:
7901 case AArch64::SABALB_ZZZ_H:
7902 case AArch64::SABALT_ZZZ_D:
7903 case AArch64::SABALT_ZZZ_S:
7904 case AArch64::SABALT_ZZZ_H:
7905 case AArch64::UABALv16i8_v8i16:
7906 case AArch64::UABALv2i32_v2i64:
7907 case AArch64::UABALv4i16_v4i32:
7908 case AArch64::UABALv4i32_v2i64:
7909 case AArch64::UABALv8i16_v4i32:
7910 case AArch64::UABALv8i8_v8i16:
7911 case AArch64::UABAv16i8:
7912 case AArch64::UABAv2i32:
7913 case AArch64::UABAv4i16:
7914 case AArch64::UABAv4i32:
7915 case AArch64::UABAv8i16:
7916 case AArch64::UABAv8i8:
7917 case AArch64::SABALv16i8_v8i16:
7918 case AArch64::SABALv2i32_v2i64:
7919 case AArch64::SABALv4i16_v4i32:
7920 case AArch64::SABALv4i32_v2i64:
7921 case AArch64::SABALv8i16_v4i32:
7922 case AArch64::SABALv8i8_v8i16:
7923 case AArch64::SABAv16i8:
7924 case AArch64::SABAv2i32:
7925 case AArch64::SABAv4i16:
7926 case AArch64::SABAv4i32:
7927 case AArch64::SABAv8i16:
7928 case AArch64::SABAv8i8:
7929 return true;
7930 }
7931
7932 return false;
7933}
7934
7935unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7936 unsigned AccumulationOpcode) const {
7937 switch (AccumulationOpcode) {
7938 default:
7939 llvm_unreachable("Unsupported accumulation Opcode!");
7940 case AArch64::UABALB_ZZZ_D:
7941 return AArch64::UABDLB_ZZZ_D;
7942 case AArch64::UABALB_ZZZ_H:
7943 return AArch64::UABDLB_ZZZ_H;
7944 case AArch64::UABALB_ZZZ_S:
7945 return AArch64::UABDLB_ZZZ_S;
7946 case AArch64::UABALT_ZZZ_D:
7947 return AArch64::UABDLT_ZZZ_D;
7948 case AArch64::UABALT_ZZZ_H:
7949 return AArch64::UABDLT_ZZZ_H;
7950 case AArch64::UABALT_ZZZ_S:
7951 return AArch64::UABDLT_ZZZ_S;
7952 case AArch64::UABALv16i8_v8i16:
7953 return AArch64::UABDLv16i8_v8i16;
7954 case AArch64::UABALv2i32_v2i64:
7955 return AArch64::UABDLv2i32_v2i64;
7956 case AArch64::UABALv4i16_v4i32:
7957 return AArch64::UABDLv4i16_v4i32;
7958 case AArch64::UABALv4i32_v2i64:
7959 return AArch64::UABDLv4i32_v2i64;
7960 case AArch64::UABALv8i16_v4i32:
7961 return AArch64::UABDLv8i16_v4i32;
7962 case AArch64::UABALv8i8_v8i16:
7963 return AArch64::UABDLv8i8_v8i16;
7964 case AArch64::UABAv16i8:
7965 return AArch64::UABDv16i8;
7966 case AArch64::UABAv2i32:
7967 return AArch64::UABDv2i32;
7968 case AArch64::UABAv4i16:
7969 return AArch64::UABDv4i16;
7970 case AArch64::UABAv4i32:
7971 return AArch64::UABDv4i32;
7972 case AArch64::UABAv8i16:
7973 return AArch64::UABDv8i16;
7974 case AArch64::UABAv8i8:
7975 return AArch64::UABDv8i8;
7976 case AArch64::SABALB_ZZZ_D:
7977 return AArch64::SABDLB_ZZZ_D;
7978 case AArch64::SABALB_ZZZ_S:
7979 return AArch64::SABDLB_ZZZ_S;
7980 case AArch64::SABALB_ZZZ_H:
7981 return AArch64::SABDLB_ZZZ_H;
7982 case AArch64::SABALT_ZZZ_D:
7983 return AArch64::SABDLT_ZZZ_D;
7984 case AArch64::SABALT_ZZZ_S:
7985 return AArch64::SABDLT_ZZZ_S;
7986 case AArch64::SABALT_ZZZ_H:
7987 return AArch64::SABDLT_ZZZ_H;
7988 case AArch64::SABALv16i8_v8i16:
7989 return AArch64::SABDLv16i8_v8i16;
7990 case AArch64::SABALv2i32_v2i64:
7991 return AArch64::SABDLv2i32_v2i64;
7992 case AArch64::SABALv4i16_v4i32:
7993 return AArch64::SABDLv4i16_v4i32;
7994 case AArch64::SABALv4i32_v2i64:
7995 return AArch64::SABDLv4i32_v2i64;
7996 case AArch64::SABALv8i16_v4i32:
7997 return AArch64::SABDLv8i16_v4i32;
7998 case AArch64::SABALv8i8_v8i16:
7999 return AArch64::SABDLv8i8_v8i16;
8000 case AArch64::SABAv16i8:
8001 return AArch64::SABDv16i8;
8002 case AArch64::SABAv2i32:
8003 return AArch64::SABAv2i32;
8004 case AArch64::SABAv4i16:
8005 return AArch64::SABDv4i16;
8006 case AArch64::SABAv4i32:
8007 return AArch64::SABDv4i32;
8008 case AArch64::SABAv8i16:
8009 return AArch64::SABDv8i16;
8010 case AArch64::SABAv8i8:
8011 return AArch64::SABDv8i8;
8012 }
8013}
8014
8015/// Floating-Point Support
8016
8017/// Find instructions that can be turned into madd.
8019 SmallVectorImpl<unsigned> &Patterns) {
8020
8021 if (!isCombineInstrCandidateFP(Root))
8022 return false;
8023
8024 MachineBasicBlock &MBB = *Root.getParent();
8025 bool Found = false;
8026
8027 auto Match = [&](int Opcode, int Operand, unsigned Pattern) -> bool {
8028 if (canCombineWithFMUL(MBB, Root.getOperand(Operand), Opcode)) {
8029 Patterns.push_back(Pattern);
8030 return true;
8031 }
8032 return false;
8033 };
8034
8036
8037 switch (Root.getOpcode()) {
8038 default:
8039 assert(false && "Unsupported FP instruction in combiner\n");
8040 break;
8041 case AArch64::FADDHrr:
8042 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8043 "FADDHrr does not have register operands");
8044
8045 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8046 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8047 break;
8048 case AArch64::FADDSrr:
8049 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8050 "FADDSrr does not have register operands");
8051
8052 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8053 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8054
8055 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8056 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8057 break;
8058 case AArch64::FADDDrr:
8059 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8060 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8061
8062 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8063 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8064 break;
8065 case AArch64::FADDv4f16:
8066 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8067 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8068
8069 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8070 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8071 break;
8072 case AArch64::FADDv8f16:
8073 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8074 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8075
8076 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8077 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8078 break;
8079 case AArch64::FADDv2f32:
8080 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8081 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8082
8083 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8084 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8085 break;
8086 case AArch64::FADDv2f64:
8087 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8088 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8089
8090 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8091 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8092 break;
8093 case AArch64::FADDv4f32:
8094 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8095 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8096
8097 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8098 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8099 break;
8100 case AArch64::FSUBHrr:
8101 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8102 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8103 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8104 break;
8105 case AArch64::FSUBSrr:
8106 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8107
8108 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8109 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8110
8111 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8112 break;
8113 case AArch64::FSUBDrr:
8114 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8115
8116 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8117 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8118
8119 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8120 break;
8121 case AArch64::FSUBv4f16:
8122 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8123 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8124
8125 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8126 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8127 break;
8128 case AArch64::FSUBv8f16:
8129 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8130 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8131
8132 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8133 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8134 break;
8135 case AArch64::FSUBv2f32:
8136 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8137 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8138
8139 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8140 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8141 break;
8142 case AArch64::FSUBv2f64:
8143 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8144 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8145
8146 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8147 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8148 break;
8149 case AArch64::FSUBv4f32:
8150 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8151 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8152
8153 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8154 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8155 break;
8156 }
8157 return Found;
8158}
8159
8161 SmallVectorImpl<unsigned> &Patterns) {
8162 MachineBasicBlock &MBB = *Root.getParent();
8163 bool Found = false;
8164
8165 auto Match = [&](unsigned Opcode, int Operand, unsigned Pattern) -> bool {
8166 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8167 MachineOperand &MO = Root.getOperand(Operand);
8168 MachineInstr *MI = nullptr;
8169 if (MO.isReg() && MO.getReg().isVirtual())
8170 MI = MRI.getUniqueVRegDef(MO.getReg());
8171 // Ignore No-op COPYs in FMUL(COPY(DUP(..)))
8172 if (MI && MI->getOpcode() == TargetOpcode::COPY &&
8173 MI->getOperand(1).getReg().isVirtual())
8174 MI = MRI.getUniqueVRegDef(MI->getOperand(1).getReg());
8175 if (MI && MI->getOpcode() == Opcode) {
8176 Patterns.push_back(Pattern);
8177 return true;
8178 }
8179 return false;
8180 };
8181
8183
8184 switch (Root.getOpcode()) {
8185 default:
8186 return false;
8187 case AArch64::FMULv2f32:
8188 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8189 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8190 break;
8191 case AArch64::FMULv2f64:
8192 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8193 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8194 break;
8195 case AArch64::FMULv4f16:
8196 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8197 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8198 break;
8199 case AArch64::FMULv4f32:
8200 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8201 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8202 break;
8203 case AArch64::FMULv8f16:
8204 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8205 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8206 break;
8207 }
8208
8209 return Found;
8210}
8211
8213 SmallVectorImpl<unsigned> &Patterns) {
8214 unsigned Opc = Root.getOpcode();
8215 MachineBasicBlock &MBB = *Root.getParent();
8216 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8217
8218 auto Match = [&](unsigned Opcode, unsigned Pattern) -> bool {
8219 MachineOperand &MO = Root.getOperand(1);
8221 if (MI != nullptr && (MI->getOpcode() == Opcode) &&
8222 MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()) &&
8226 MI->getFlag(MachineInstr::MIFlag::FmNsz)) {
8227 Patterns.push_back(Pattern);
8228 return true;
8229 }
8230 return false;
8231 };
8232
8233 switch (Opc) {
8234 default:
8235 break;
8236 case AArch64::FNEGDr:
8237 return Match(AArch64::FMADDDrrr, AArch64MachineCombinerPattern::FNMADD);
8238 case AArch64::FNEGSr:
8239 return Match(AArch64::FMADDSrrr, AArch64MachineCombinerPattern::FNMADD);
8240 }
8241
8242 return false;
8243}
8244
8245/// Return true when a code sequence can improve throughput. It
8246/// should be called only for instructions in loops.
8247/// \param Pattern - combiner pattern
8249 switch (Pattern) {
8250 default:
8251 break;
8357 return true;
8358 } // end switch (Pattern)
8359 return false;
8360}
8361
8362/// Find other MI combine patterns.
8364 SmallVectorImpl<unsigned> &Patterns) {
8365 // A - (B + C) ==> (A - B) - C or (A - C) - B
8366 unsigned Opc = Root.getOpcode();
8367 MachineBasicBlock &MBB = *Root.getParent();
8368
8369 switch (Opc) {
8370 case AArch64::SUBWrr:
8371 case AArch64::SUBSWrr:
8372 case AArch64::SUBXrr:
8373 case AArch64::SUBSXrr:
8374 // Found candidate root.
8375 break;
8376 default:
8377 return false;
8378 }
8379
8381 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) ==
8382 -1)
8383 return false;
8384
8385 if (canCombine(MBB, Root.getOperand(2), AArch64::ADDWrr) ||
8386 canCombine(MBB, Root.getOperand(2), AArch64::ADDSWrr) ||
8387 canCombine(MBB, Root.getOperand(2), AArch64::ADDXrr) ||
8388 canCombine(MBB, Root.getOperand(2), AArch64::ADDSXrr)) {
8391 return true;
8392 }
8393
8394 return false;
8395}
8396
8397/// Check if the given instruction forms a gather load pattern that can be
8398/// optimized for better Memory-Level Parallelism (MLP). This function
8399/// identifies chains of NEON lane load instructions that load data from
8400/// different memory addresses into individual lanes of a 128-bit vector
8401/// register, then attempts to split the pattern into parallel loads to break
8402/// the serial dependency between instructions.
8403///
8404/// Pattern Matched:
8405/// Initial scalar load -> SUBREG_TO_REG (lane 0) -> LD1i* (lane 1) ->
8406/// LD1i* (lane 2) -> ... -> LD1i* (lane N-1, Root)
8407///
8408/// Transformed Into:
8409/// Two parallel vector loads using fewer lanes each, followed by ZIP1v2i64
8410/// to combine the results, enabling better memory-level parallelism.
8411///
8412/// Supported Element Types:
8413/// - 32-bit elements (LD1i32, 4 lanes total)
8414/// - 16-bit elements (LD1i16, 8 lanes total)
8415/// - 8-bit elements (LD1i8, 16 lanes total)
8417 SmallVectorImpl<unsigned> &Patterns,
8418 unsigned LoadLaneOpCode, unsigned NumLanes) {
8419 const MachineFunction *MF = Root.getMF();
8420
8421 // Early exit if optimizing for size.
8422 if (MF->getFunction().hasMinSize())
8423 return false;
8424
8425 const MachineRegisterInfo &MRI = MF->getRegInfo();
8427
8428 // The root of the pattern must load into the last lane of the vector.
8429 if (Root.getOperand(2).getImm() != NumLanes - 1)
8430 return false;
8431
8432 // Check that we have load into all lanes except lane 0.
8433 // For each load we also want to check that:
8434 // 1. It has a single non-debug use (since we will be replacing the virtual
8435 // register)
8436 // 2. That the addressing mode only uses a single pointer operand
8437 auto *CurrInstr = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8438 auto Range = llvm::seq<unsigned>(1, NumLanes - 1);
8439 SmallSet<unsigned, 16> RemainingLanes(Range.begin(), Range.end());
8441 while (!RemainingLanes.empty() && CurrInstr &&
8442 CurrInstr->getOpcode() == LoadLaneOpCode &&
8443 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
8444 CurrInstr->getNumOperands() == 4) {
8445 RemainingLanes.erase(CurrInstr->getOperand(2).getImm());
8446 LoadInstrs.push_back(CurrInstr);
8447 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8448 }
8449
8450 // Check that we have found a match for lanes N-1.. 1.
8451 if (!RemainingLanes.empty())
8452 return false;
8453
8454 // Match the SUBREG_TO_REG sequence.
8455 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8456 return false;
8457
8458 // Verify that the subreg to reg loads an integer into the first lane.
8459 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8460 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8461 if (TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8462 return false;
8463
8464 // Verify that it also has a single non debug use.
8465 if (!MRI.hasOneNonDBGUse(Lane0LoadReg))
8466 return false;
8467
8468 LoadInstrs.push_back(MRI.getUniqueVRegDef(Lane0LoadReg));
8469
8470 // If there is any chance of aliasing, do not apply the pattern.
8471 // Walk backward through the MBB starting from Root.
8472 // Exit early if we've encountered all load instructions or hit the search
8473 // limit.
8474 auto MBBItr = Root.getIterator();
8475 unsigned RemainingSteps = GatherOptSearchLimit;
8476 SmallPtrSet<const MachineInstr *, 16> RemainingLoadInstrs;
8477 RemainingLoadInstrs.insert(LoadInstrs.begin(), LoadInstrs.end());
8478 const MachineBasicBlock *MBB = Root.getParent();
8479
8480 for (; MBBItr != MBB->begin() && RemainingSteps > 0 &&
8481 !RemainingLoadInstrs.empty();
8482 --MBBItr, --RemainingSteps) {
8483 const MachineInstr &CurrInstr = *MBBItr;
8484
8485 // Remove this instruction from remaining loads if it's one we're tracking.
8486 RemainingLoadInstrs.erase(&CurrInstr);
8487
8488 // Check for potential aliasing with any of the load instructions to
8489 // optimize.
8490 if (CurrInstr.isLoadFoldBarrier())
8491 return false;
8492 }
8493
8494 // If we hit the search limit without finding all load instructions,
8495 // don't match the pattern.
8496 if (RemainingSteps == 0 && !RemainingLoadInstrs.empty())
8497 return false;
8498
8499 switch (NumLanes) {
8500 case 4:
8502 break;
8503 case 8:
8505 break;
8506 case 16:
8508 break;
8509 default:
8510 llvm_unreachable("Got bad number of lanes for gather pattern.");
8511 }
8512
8513 return true;
8514}
8515
8516/// Search for patterns of LD instructions we can optimize.
8518 SmallVectorImpl<unsigned> &Patterns) {
8519
8520 // The pattern searches for loads into single lanes.
8521 switch (Root.getOpcode()) {
8522 case AArch64::LD1i32:
8523 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 4);
8524 case AArch64::LD1i16:
8525 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 8);
8526 case AArch64::LD1i8:
8527 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 16);
8528 default:
8529 return false;
8530 }
8531}
8532
8533/// Generate optimized instruction sequence for gather load patterns to improve
8534/// Memory-Level Parallelism (MLP). This function transforms a chain of
8535/// sequential NEON lane loads into parallel vector loads that can execute
8536/// concurrently.
8537static void
8541 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8542 unsigned Pattern, unsigned NumLanes) {
8543 MachineFunction &MF = *Root.getParent()->getParent();
8544 MachineRegisterInfo &MRI = MF.getRegInfo();
8546
8547 // Gather the initial load instructions to build the pattern.
8548 SmallVector<MachineInstr *, 16> LoadToLaneInstrs;
8549 MachineInstr *CurrInstr = &Root;
8550 for (unsigned i = 0; i < NumLanes - 1; ++i) {
8551 LoadToLaneInstrs.push_back(CurrInstr);
8552 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8553 }
8554
8555 // Sort the load instructions according to the lane.
8556 llvm::sort(LoadToLaneInstrs,
8557 [](const MachineInstr *A, const MachineInstr *B) {
8558 return A->getOperand(2).getImm() > B->getOperand(2).getImm();
8559 });
8560
8561 MachineInstr *SubregToReg = CurrInstr;
8562 LoadToLaneInstrs.push_back(
8563 MRI.getUniqueVRegDef(SubregToReg->getOperand(1).getReg()));
8564 auto LoadToLaneInstrsAscending = llvm::reverse(LoadToLaneInstrs);
8565
8566 const TargetRegisterClass *FPR128RegClass =
8567 MRI.getRegClass(Root.getOperand(0).getReg());
8568
8569 // Helper lambda to create a LD1 instruction.
8570 auto CreateLD1Instruction = [&](MachineInstr *OriginalInstr,
8571 Register SrcRegister, unsigned Lane,
8572 Register OffsetRegister,
8573 bool OffsetRegisterKillState) {
8574 auto NewRegister = MRI.createVirtualRegister(FPR128RegClass);
8575 MachineInstrBuilder LoadIndexIntoRegister =
8576 BuildMI(MF, MIMetadata(*OriginalInstr), TII->get(Root.getOpcode()),
8577 NewRegister)
8578 .addReg(SrcRegister)
8579 .addImm(Lane)
8580 .addReg(OffsetRegister, getKillRegState(OffsetRegisterKillState))
8581 .setMemRefs(OriginalInstr->memoperands());
8582 InstrIdxForVirtReg.insert(std::make_pair(NewRegister, InsInstrs.size()));
8583 InsInstrs.push_back(LoadIndexIntoRegister);
8584 return NewRegister;
8585 };
8586
8587 // Helper to create load instruction based on the NumLanes in the NEON
8588 // register we are rewriting.
8589 auto CreateLDRInstruction =
8590 [&](unsigned NumLanes, Register DestReg, Register OffsetReg,
8592 unsigned Opcode;
8593 switch (NumLanes) {
8594 case 4:
8595 Opcode = AArch64::LDRSui;
8596 break;
8597 case 8:
8598 Opcode = AArch64::LDRHui;
8599 break;
8600 case 16:
8601 Opcode = AArch64::LDRBui;
8602 break;
8603 default:
8605 "Got unsupported number of lanes in machine-combiner gather pattern");
8606 }
8607 // Immediate offset load
8608 return BuildMI(MF, MIMetadata(Root), TII->get(Opcode), DestReg)
8609 .addReg(OffsetReg)
8610 .addImm(0)
8611 .setMemRefs(MMOs);
8612 };
8613
8614 // Load the remaining lanes into register 0.
8615 auto LanesToLoadToReg0 =
8616 llvm::make_range(LoadToLaneInstrsAscending.begin() + 1,
8617 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8618 Register PrevReg = SubregToReg->getOperand(0).getReg();
8619 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg0)) {
8620 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8621 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8622 OffsetRegOperand.getReg(),
8623 OffsetRegOperand.isKill());
8624 DelInstrs.push_back(LoadInstr);
8625 }
8626 Register LastLoadReg0 = PrevReg;
8627
8628 // First load into register 1. Perform an integer load to zero out the upper
8629 // lanes in a single instruction.
8630 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8631 MachineInstr *OriginalSplitLoad =
8632 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8633 Register DestRegForMiddleIndex = MRI.createVirtualRegister(
8634 MRI.getRegClass(Lane0Load->getOperand(0).getReg()));
8635
8636 const MachineOperand &OriginalSplitToLoadOffsetOperand =
8637 OriginalSplitLoad->getOperand(3);
8638 MachineInstrBuilder MiddleIndexLoadInstr =
8639 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8640 OriginalSplitToLoadOffsetOperand.getReg(),
8641 OriginalSplitLoad->memoperands());
8642
8643 InstrIdxForVirtReg.insert(
8644 std::make_pair(DestRegForMiddleIndex, InsInstrs.size()));
8645 InsInstrs.push_back(MiddleIndexLoadInstr);
8646 DelInstrs.push_back(OriginalSplitLoad);
8647
8648 // Subreg To Reg instruction for register 1.
8649 Register DestRegForSubregToReg = MRI.createVirtualRegister(FPR128RegClass);
8650 unsigned SubregType;
8651 switch (NumLanes) {
8652 case 4:
8653 SubregType = AArch64::ssub;
8654 break;
8655 case 8:
8656 SubregType = AArch64::hsub;
8657 break;
8658 case 16:
8659 SubregType = AArch64::bsub;
8660 break;
8661 default:
8663 "Got invalid NumLanes for machine-combiner gather pattern");
8664 }
8665
8666 auto SubRegToRegInstr =
8667 BuildMI(MF, MIMetadata(Root), TII->get(SubregToReg->getOpcode()),
8668 DestRegForSubregToReg)
8669 .addReg(DestRegForMiddleIndex, getKillRegState(true))
8670 .addImm(SubregType);
8671 InstrIdxForVirtReg.insert(
8672 std::make_pair(DestRegForSubregToReg, InsInstrs.size()));
8673 InsInstrs.push_back(SubRegToRegInstr);
8674
8675 // Load remaining lanes into register 1.
8676 auto LanesToLoadToReg1 =
8677 llvm::make_range(LoadToLaneInstrsAscending.begin() + NumLanes / 2 + 1,
8678 LoadToLaneInstrsAscending.end());
8679 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8680 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg1)) {
8681 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8682 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8683 OffsetRegOperand.getReg(),
8684 OffsetRegOperand.isKill());
8685
8686 // Do not add the last reg to DelInstrs - it will be removed later.
8687 if (Index == NumLanes / 2 - 2) {
8688 break;
8689 }
8690 DelInstrs.push_back(LoadInstr);
8691 }
8692 Register LastLoadReg1 = PrevReg;
8693
8694 // Create the final zip instruction to combine the results.
8695 MachineInstrBuilder ZipInstr =
8696 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::ZIP1v2i64),
8697 Root.getOperand(0).getReg())
8698 .addReg(LastLoadReg0)
8699 .addReg(LastLoadReg1);
8700 InsInstrs.push_back(ZipInstr);
8701}
8702
8716
8717/// Return true when there is potentially a faster code sequence for an
8718/// instruction chain ending in \p Root. All potential patterns are listed in
8719/// the \p Pattern vector. Pattern should be sorted in priority order since the
8720/// pattern evaluator stops checking as soon as it finds a faster sequence.
8721
8722bool AArch64InstrInfo::getMachineCombinerPatterns(
8723 MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
8724 bool DoRegPressureReduce) const {
8725 // Integer patterns
8726 if (getMaddPatterns(Root, Patterns))
8727 return true;
8728 // Floating point patterns
8729 if (getFMULPatterns(Root, Patterns))
8730 return true;
8731 if (getFMAPatterns(Root, Patterns))
8732 return true;
8733 if (getFNEGPatterns(Root, Patterns))
8734 return true;
8735
8736 // Other patterns
8737 if (getMiscPatterns(Root, Patterns))
8738 return true;
8739
8740 // Load patterns
8741 if (getLoadPatterns(Root, Patterns))
8742 return true;
8743
8744 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
8745 DoRegPressureReduce);
8746}
8747
8749/// genFusedMultiply - Generate fused multiply instructions.
8750/// This function supports both integer and floating point instructions.
8751/// A typical example:
8752/// F|MUL I=A,B,0
8753/// F|ADD R,I,C
8754/// ==> F|MADD R,A,B,C
8755/// \param MF Containing MachineFunction
8756/// \param MRI Register information
8757/// \param TII Target information
8758/// \param Root is the F|ADD instruction
8759/// \param [out] InsInstrs is a vector of machine instructions and will
8760/// contain the generated madd instruction
8761/// \param IdxMulOpd is index of operand in Root that is the result of
8762/// the F|MUL. In the example above IdxMulOpd is 1.
8763/// \param MaddOpc the opcode fo the f|madd instruction
8764/// \param RC Register class of operands
8765/// \param kind of fma instruction (addressing mode) to be generated
8766/// \param ReplacedAddend is the result register from the instruction
8767/// replacing the non-combined operand, if any.
8768static MachineInstr *
8770 const TargetInstrInfo *TII, MachineInstr &Root,
8771 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
8772 unsigned MaddOpc, const TargetRegisterClass *RC,
8774 const Register *ReplacedAddend = nullptr) {
8775 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8776
8777 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8778 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8779 Register ResultReg = Root.getOperand(0).getReg();
8780 Register SrcReg0 = MUL->getOperand(1).getReg();
8781 bool Src0IsKill = MUL->getOperand(1).isKill();
8782 Register SrcReg1 = MUL->getOperand(2).getReg();
8783 bool Src1IsKill = MUL->getOperand(2).isKill();
8784
8785 Register SrcReg2;
8786 bool Src2IsKill;
8787 if (ReplacedAddend) {
8788 // If we just generated a new addend, we must be it's only use.
8789 SrcReg2 = *ReplacedAddend;
8790 Src2IsKill = true;
8791 } else {
8792 SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
8793 Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
8794 }
8795
8796 if (ResultReg.isVirtual())
8797 MRI.constrainRegClass(ResultReg, RC);
8798 if (SrcReg0.isVirtual())
8799 MRI.constrainRegClass(SrcReg0, RC);
8800 if (SrcReg1.isVirtual())
8801 MRI.constrainRegClass(SrcReg1, RC);
8802 if (SrcReg2.isVirtual())
8803 MRI.constrainRegClass(SrcReg2, RC);
8804
8806 if (kind == FMAInstKind::Default)
8807 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8808 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8809 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8810 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8811 else if (kind == FMAInstKind::Indexed)
8812 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8813 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8814 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8815 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8816 .addImm(MUL->getOperand(3).getImm());
8817 else if (kind == FMAInstKind::Accumulator)
8818 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8819 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8820 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8821 .addReg(SrcReg1, getKillRegState(Src1IsKill));
8822 else
8823 assert(false && "Invalid FMA instruction kind \n");
8824 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
8825 InsInstrs.push_back(MIB);
8826 return MUL;
8827}
8828
8829static MachineInstr *
8831 const TargetInstrInfo *TII, MachineInstr &Root,
8833 MachineInstr *MAD = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8834
8835 unsigned Opc = 0;
8836 const TargetRegisterClass *RC = MRI.getRegClass(MAD->getOperand(0).getReg());
8837 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8838 Opc = AArch64::FNMADDSrrr;
8839 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8840 Opc = AArch64::FNMADDDrrr;
8841 else
8842 return nullptr;
8843
8844 Register ResultReg = Root.getOperand(0).getReg();
8845 Register SrcReg0 = MAD->getOperand(1).getReg();
8846 Register SrcReg1 = MAD->getOperand(2).getReg();
8847 Register SrcReg2 = MAD->getOperand(3).getReg();
8848 bool Src0IsKill = MAD->getOperand(1).isKill();
8849 bool Src1IsKill = MAD->getOperand(2).isKill();
8850 bool Src2IsKill = MAD->getOperand(3).isKill();
8851 if (ResultReg.isVirtual())
8852 MRI.constrainRegClass(ResultReg, RC);
8853 if (SrcReg0.isVirtual())
8854 MRI.constrainRegClass(SrcReg0, RC);
8855 if (SrcReg1.isVirtual())
8856 MRI.constrainRegClass(SrcReg1, RC);
8857 if (SrcReg2.isVirtual())
8858 MRI.constrainRegClass(SrcReg2, RC);
8859
8861 BuildMI(MF, MIMetadata(Root), TII->get(Opc), ResultReg)
8862 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8863 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8864 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8865 InsInstrs.push_back(MIB);
8866
8867 return MAD;
8868}
8869
8870/// Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
8871static MachineInstr *
8874 unsigned IdxDupOp, unsigned MulOpc,
8875 const TargetRegisterClass *RC, MachineRegisterInfo &MRI) {
8876 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8877 "Invalid index of FMUL operand");
8878
8879 MachineFunction &MF = *Root.getMF();
8881
8882 MachineInstr *Dup =
8883 MF.getRegInfo().getUniqueVRegDef(Root.getOperand(IdxDupOp).getReg());
8884
8885 if (Dup->getOpcode() == TargetOpcode::COPY)
8886 Dup = MRI.getUniqueVRegDef(Dup->getOperand(1).getReg());
8887
8888 Register DupSrcReg = Dup->getOperand(1).getReg();
8889 MRI.clearKillFlags(DupSrcReg);
8890 MRI.constrainRegClass(DupSrcReg, RC);
8891
8892 unsigned DupSrcLane = Dup->getOperand(2).getImm();
8893
8894 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8895 MachineOperand &MulOp = Root.getOperand(IdxMulOp);
8896
8897 Register ResultReg = Root.getOperand(0).getReg();
8898
8900 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MulOpc), ResultReg)
8901 .add(MulOp)
8902 .addReg(DupSrcReg)
8903 .addImm(DupSrcLane);
8904
8905 InsInstrs.push_back(MIB);
8906 return &Root;
8907}
8908
8909/// genFusedMultiplyAcc - Helper to generate fused multiply accumulate
8910/// instructions.
8911///
8912/// \see genFusedMultiply
8916 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8917 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8919}
8920
8921/// genNeg - Helper to generate an intermediate negation of the second operand
8922/// of Root
8924 const TargetInstrInfo *TII, MachineInstr &Root,
8926 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8927 unsigned MnegOpc, const TargetRegisterClass *RC) {
8928 Register NewVR = MRI.createVirtualRegister(RC);
8930 BuildMI(MF, MIMetadata(Root), TII->get(MnegOpc), NewVR)
8931 .add(Root.getOperand(2));
8932 InsInstrs.push_back(MIB);
8933
8934 assert(InstrIdxForVirtReg.empty());
8935 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
8936
8937 return NewVR;
8938}
8939
8940/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8941/// instructions with an additional negation of the accumulator
8945 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8946 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8947 assert(IdxMulOpd == 1);
8948
8949 Register NewVR =
8950 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8951 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8952 FMAInstKind::Accumulator, &NewVR);
8953}
8954
8955/// genFusedMultiplyIdx - Helper to generate fused multiply accumulate
8956/// instructions.
8957///
8958/// \see genFusedMultiply
8962 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8963 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8965}
8966
8967/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8968/// instructions with an additional negation of the accumulator
8972 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8973 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8974 assert(IdxMulOpd == 1);
8975
8976 Register NewVR =
8977 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8978
8979 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8980 FMAInstKind::Indexed, &NewVR);
8981}
8982
8983/// genMaddR - Generate madd instruction and combine mul and add using
8984/// an extra virtual register
8985/// Example - an ADD intermediate needs to be stored in a register:
8986/// MUL I=A,B,0
8987/// ADD R,I,Imm
8988/// ==> ORR V, ZR, Imm
8989/// ==> MADD R,A,B,V
8990/// \param MF Containing MachineFunction
8991/// \param MRI Register information
8992/// \param TII Target information
8993/// \param Root is the ADD instruction
8994/// \param [out] InsInstrs is a vector of machine instructions and will
8995/// contain the generated madd instruction
8996/// \param IdxMulOpd is index of operand in Root that is the result of
8997/// the MUL. In the example above IdxMulOpd is 1.
8998/// \param MaddOpc the opcode fo the madd instruction
8999/// \param VR is a virtual register that holds the value of an ADD operand
9000/// (V in the example above).
9001/// \param RC Register class of operands
9003 const TargetInstrInfo *TII, MachineInstr &Root,
9005 unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR,
9006 const TargetRegisterClass *RC) {
9007 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
9008
9009 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
9010 Register ResultReg = Root.getOperand(0).getReg();
9011 Register SrcReg0 = MUL->getOperand(1).getReg();
9012 bool Src0IsKill = MUL->getOperand(1).isKill();
9013 Register SrcReg1 = MUL->getOperand(2).getReg();
9014 bool Src1IsKill = MUL->getOperand(2).isKill();
9015
9016 if (ResultReg.isVirtual())
9017 MRI.constrainRegClass(ResultReg, RC);
9018 if (SrcReg0.isVirtual())
9019 MRI.constrainRegClass(SrcReg0, RC);
9020 if (SrcReg1.isVirtual())
9021 MRI.constrainRegClass(SrcReg1, RC);
9023 MRI.constrainRegClass(VR, RC);
9024
9026 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
9027 .addReg(SrcReg0, getKillRegState(Src0IsKill))
9028 .addReg(SrcReg1, getKillRegState(Src1IsKill))
9029 .addReg(VR);
9030 // Insert the MADD
9031 InsInstrs.push_back(MIB);
9032 return MUL;
9033}
9034
9035/// Do the following transformation
9036/// A - (B + C) ==> (A - B) - C
9037/// A - (B + C) ==> (A - C) - B
9039 const TargetInstrInfo *TII, MachineInstr &Root,
9042 unsigned IdxOpd1,
9043 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
9044 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9045 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9046 MachineInstr *AddMI = MRI.getUniqueVRegDef(Root.getOperand(2).getReg());
9047
9048 Register ResultReg = Root.getOperand(0).getReg();
9049 Register RegA = Root.getOperand(1).getReg();
9050 bool RegAIsKill = Root.getOperand(1).isKill();
9051 Register RegB = AddMI->getOperand(IdxOpd1).getReg();
9052 bool RegBIsKill = AddMI->getOperand(IdxOpd1).isKill();
9053 Register RegC = AddMI->getOperand(IdxOtherOpd).getReg();
9054 bool RegCIsKill = AddMI->getOperand(IdxOtherOpd).isKill();
9055 Register NewVR =
9057
9058 unsigned Opcode = Root.getOpcode();
9059 if (Opcode == AArch64::SUBSWrr)
9060 Opcode = AArch64::SUBWrr;
9061 else if (Opcode == AArch64::SUBSXrr)
9062 Opcode = AArch64::SUBXrr;
9063 else
9064 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9065 "Unexpected instruction opcode.");
9066
9067 uint32_t Flags = Root.mergeFlagsWith(*AddMI);
9068 Flags &= ~MachineInstr::NoSWrap;
9069 Flags &= ~MachineInstr::NoUWrap;
9070
9071 MachineInstrBuilder MIB1 =
9072 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), NewVR)
9073 .addReg(RegA, getKillRegState(RegAIsKill))
9074 .addReg(RegB, getKillRegState(RegBIsKill))
9075 .setMIFlags(Flags);
9076 MachineInstrBuilder MIB2 =
9077 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), ResultReg)
9078 .addReg(NewVR, getKillRegState(true))
9079 .addReg(RegC, getKillRegState(RegCIsKill))
9080 .setMIFlags(Flags);
9081
9082 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9083 InsInstrs.push_back(MIB1);
9084 InsInstrs.push_back(MIB2);
9085 DelInstrs.push_back(AddMI);
9086 DelInstrs.push_back(&Root);
9087}
9088
9089unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9090 unsigned int AccumulatorOpCode) const {
9091 switch (AccumulatorOpCode) {
9092 case AArch64::UABALB_ZZZ_D:
9093 case AArch64::SABALB_ZZZ_D:
9094 case AArch64::UABALT_ZZZ_D:
9095 case AArch64::SABALT_ZZZ_D:
9096 return AArch64::ADD_ZZZ_D;
9097 case AArch64::UABALB_ZZZ_H:
9098 case AArch64::SABALB_ZZZ_H:
9099 case AArch64::UABALT_ZZZ_H:
9100 case AArch64::SABALT_ZZZ_H:
9101 return AArch64::ADD_ZZZ_H;
9102 case AArch64::UABALB_ZZZ_S:
9103 case AArch64::SABALB_ZZZ_S:
9104 case AArch64::UABALT_ZZZ_S:
9105 case AArch64::SABALT_ZZZ_S:
9106 return AArch64::ADD_ZZZ_S;
9107 case AArch64::UABALv16i8_v8i16:
9108 case AArch64::SABALv8i8_v8i16:
9109 case AArch64::SABAv8i16:
9110 case AArch64::UABAv8i16:
9111 return AArch64::ADDv8i16;
9112 case AArch64::SABALv2i32_v2i64:
9113 case AArch64::UABALv2i32_v2i64:
9114 case AArch64::SABALv4i32_v2i64:
9115 return AArch64::ADDv2i64;
9116 case AArch64::UABALv4i16_v4i32:
9117 case AArch64::SABALv4i16_v4i32:
9118 case AArch64::SABALv8i16_v4i32:
9119 case AArch64::SABAv4i32:
9120 case AArch64::UABAv4i32:
9121 return AArch64::ADDv4i32;
9122 case AArch64::UABALv4i32_v2i64:
9123 return AArch64::ADDv2i64;
9124 case AArch64::UABALv8i16_v4i32:
9125 return AArch64::ADDv4i32;
9126 case AArch64::UABALv8i8_v8i16:
9127 case AArch64::SABALv16i8_v8i16:
9128 return AArch64::ADDv8i16;
9129 case AArch64::UABAv16i8:
9130 case AArch64::SABAv16i8:
9131 return AArch64::ADDv16i8;
9132 case AArch64::UABAv4i16:
9133 case AArch64::SABAv4i16:
9134 return AArch64::ADDv4i16;
9135 case AArch64::UABAv2i32:
9136 case AArch64::SABAv2i32:
9137 return AArch64::ADDv2i32;
9138 case AArch64::UABAv8i8:
9139 case AArch64::SABAv8i8:
9140 return AArch64::ADDv8i8;
9141 default:
9142 llvm_unreachable("Unknown accumulator opcode");
9143 }
9144}
9145
9146/// When getMachineCombinerPatterns() finds potential patterns,
9147/// this function generates the instructions that could replace the
9148/// original code sequence
9149void AArch64InstrInfo::genAlternativeCodeSequence(
9150 MachineInstr &Root, unsigned Pattern,
9153 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const {
9154 MachineBasicBlock &MBB = *Root.getParent();
9155 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9156 MachineFunction &MF = *MBB.getParent();
9157 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
9158
9159 MachineInstr *MUL = nullptr;
9160 const TargetRegisterClass *RC;
9161 unsigned Opc;
9162 switch (Pattern) {
9163 default:
9164 // Reassociate instructions.
9165 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
9166 DelInstrs, InstrIdxForVirtReg);
9167 return;
9169 // A - (B + C)
9170 // ==> (A - B) - C
9171 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 1,
9172 InstrIdxForVirtReg);
9173 return;
9175 // A - (B + C)
9176 // ==> (A - C) - B
9177 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 2,
9178 InstrIdxForVirtReg);
9179 return;
9182 // MUL I=A,B,0
9183 // ADD R,I,C
9184 // ==> MADD R,A,B,C
9185 // --- Create(MADD);
9187 Opc = AArch64::MADDWrrr;
9188 RC = &AArch64::GPR32RegClass;
9189 } else {
9190 Opc = AArch64::MADDXrrr;
9191 RC = &AArch64::GPR64RegClass;
9192 }
9193 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9194 break;
9197 // MUL I=A,B,0
9198 // ADD R,C,I
9199 // ==> MADD R,A,B,C
9200 // --- Create(MADD);
9202 Opc = AArch64::MADDWrrr;
9203 RC = &AArch64::GPR32RegClass;
9204 } else {
9205 Opc = AArch64::MADDXrrr;
9206 RC = &AArch64::GPR64RegClass;
9207 }
9208 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9209 break;
9214 // MUL I=A,B,0
9215 // ADD/SUB R,I,Imm
9216 // ==> MOV V, Imm/-Imm
9217 // ==> MADD R,A,B,V
9218 // --- Create(MADD);
9219 const TargetRegisterClass *RC;
9220 unsigned BitSize, MovImm;
9223 MovImm = AArch64::MOVi32imm;
9224 RC = &AArch64::GPR32spRegClass;
9225 BitSize = 32;
9226 Opc = AArch64::MADDWrrr;
9227 RC = &AArch64::GPR32RegClass;
9228 } else {
9229 MovImm = AArch64::MOVi64imm;
9230 RC = &AArch64::GPR64spRegClass;
9231 BitSize = 64;
9232 Opc = AArch64::MADDXrrr;
9233 RC = &AArch64::GPR64RegClass;
9234 }
9235 Register NewVR = MRI.createVirtualRegister(RC);
9236 uint64_t Imm = Root.getOperand(2).getImm();
9237
9238 if (Root.getOperand(3).isImm()) {
9239 unsigned Val = Root.getOperand(3).getImm();
9240 Imm = Imm << Val;
9241 }
9242 bool IsSub = Pattern == AArch64MachineCombinerPattern::MULSUBWI_OP1 ||
9244 uint64_t UImm = SignExtend64(IsSub ? -Imm : Imm, BitSize);
9245 // Check that the immediate can be composed via a single instruction.
9247 AArch64_IMM::expandMOVImm(UImm, BitSize, Insn);
9248 if (Insn.size() != 1)
9249 return;
9250 MachineInstrBuilder MIB1 =
9251 BuildMI(MF, MIMetadata(Root), TII->get(MovImm), NewVR)
9252 .addImm(IsSub ? -Imm : Imm);
9253 InsInstrs.push_back(MIB1);
9254 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9255 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9256 break;
9257 }
9260 // MUL I=A,B,0
9261 // SUB R,I, C
9262 // ==> SUB V, 0, C
9263 // ==> MADD R,A,B,V // = -C + A*B
9264 // --- Create(MADD);
9265 const TargetRegisterClass *SubRC;
9266 unsigned SubOpc, ZeroReg;
9268 SubOpc = AArch64::SUBWrr;
9269 SubRC = &AArch64::GPR32spRegClass;
9270 ZeroReg = AArch64::WZR;
9271 Opc = AArch64::MADDWrrr;
9272 RC = &AArch64::GPR32RegClass;
9273 } else {
9274 SubOpc = AArch64::SUBXrr;
9275 SubRC = &AArch64::GPR64spRegClass;
9276 ZeroReg = AArch64::XZR;
9277 Opc = AArch64::MADDXrrr;
9278 RC = &AArch64::GPR64RegClass;
9279 }
9280 Register NewVR = MRI.createVirtualRegister(SubRC);
9281 // SUB NewVR, 0, C
9282 MachineInstrBuilder MIB1 =
9283 BuildMI(MF, MIMetadata(Root), TII->get(SubOpc), NewVR)
9284 .addReg(ZeroReg)
9285 .add(Root.getOperand(2));
9286 InsInstrs.push_back(MIB1);
9287 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9288 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9289 break;
9290 }
9293 // MUL I=A,B,0
9294 // SUB R,C,I
9295 // ==> MSUB R,A,B,C (computes C - A*B)
9296 // --- Create(MSUB);
9298 Opc = AArch64::MSUBWrrr;
9299 RC = &AArch64::GPR32RegClass;
9300 } else {
9301 Opc = AArch64::MSUBXrrr;
9302 RC = &AArch64::GPR64RegClass;
9303 }
9304 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9305 break;
9307 Opc = AArch64::MLAv8i8;
9308 RC = &AArch64::FPR64RegClass;
9309 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9310 break;
9312 Opc = AArch64::MLAv8i8;
9313 RC = &AArch64::FPR64RegClass;
9314 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9315 break;
9317 Opc = AArch64::MLAv16i8;
9318 RC = &AArch64::FPR128RegClass;
9319 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9320 break;
9322 Opc = AArch64::MLAv16i8;
9323 RC = &AArch64::FPR128RegClass;
9324 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9325 break;
9327 Opc = AArch64::MLAv4i16;
9328 RC = &AArch64::FPR64RegClass;
9329 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9330 break;
9332 Opc = AArch64::MLAv4i16;
9333 RC = &AArch64::FPR64RegClass;
9334 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9335 break;
9337 Opc = AArch64::MLAv8i16;
9338 RC = &AArch64::FPR128RegClass;
9339 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9340 break;
9342 Opc = AArch64::MLAv8i16;
9343 RC = &AArch64::FPR128RegClass;
9344 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9345 break;
9347 Opc = AArch64::MLAv2i32;
9348 RC = &AArch64::FPR64RegClass;
9349 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9350 break;
9352 Opc = AArch64::MLAv2i32;
9353 RC = &AArch64::FPR64RegClass;
9354 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9355 break;
9357 Opc = AArch64::MLAv4i32;
9358 RC = &AArch64::FPR128RegClass;
9359 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9360 break;
9362 Opc = AArch64::MLAv4i32;
9363 RC = &AArch64::FPR128RegClass;
9364 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9365 break;
9366
9368 Opc = AArch64::MLAv8i8;
9369 RC = &AArch64::FPR64RegClass;
9370 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9371 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i8,
9372 RC);
9373 break;
9375 Opc = AArch64::MLSv8i8;
9376 RC = &AArch64::FPR64RegClass;
9377 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9378 break;
9380 Opc = AArch64::MLAv16i8;
9381 RC = &AArch64::FPR128RegClass;
9382 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9383 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv16i8,
9384 RC);
9385 break;
9387 Opc = AArch64::MLSv16i8;
9388 RC = &AArch64::FPR128RegClass;
9389 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9390 break;
9392 Opc = AArch64::MLAv4i16;
9393 RC = &AArch64::FPR64RegClass;
9394 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9395 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9396 RC);
9397 break;
9399 Opc = AArch64::MLSv4i16;
9400 RC = &AArch64::FPR64RegClass;
9401 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9402 break;
9404 Opc = AArch64::MLAv8i16;
9405 RC = &AArch64::FPR128RegClass;
9406 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9407 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9408 RC);
9409 break;
9411 Opc = AArch64::MLSv8i16;
9412 RC = &AArch64::FPR128RegClass;
9413 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9414 break;
9416 Opc = AArch64::MLAv2i32;
9417 RC = &AArch64::FPR64RegClass;
9418 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9419 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9420 RC);
9421 break;
9423 Opc = AArch64::MLSv2i32;
9424 RC = &AArch64::FPR64RegClass;
9425 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9426 break;
9428 Opc = AArch64::MLAv4i32;
9429 RC = &AArch64::FPR128RegClass;
9430 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9431 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9432 RC);
9433 break;
9435 Opc = AArch64::MLSv4i32;
9436 RC = &AArch64::FPR128RegClass;
9437 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9438 break;
9439
9441 Opc = AArch64::MLAv4i16_indexed;
9442 RC = &AArch64::FPR64RegClass;
9443 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9444 break;
9446 Opc = AArch64::MLAv4i16_indexed;
9447 RC = &AArch64::FPR64RegClass;
9448 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9449 break;
9451 Opc = AArch64::MLAv8i16_indexed;
9452 RC = &AArch64::FPR128RegClass;
9453 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9454 break;
9456 Opc = AArch64::MLAv8i16_indexed;
9457 RC = &AArch64::FPR128RegClass;
9458 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9459 break;
9461 Opc = AArch64::MLAv2i32_indexed;
9462 RC = &AArch64::FPR64RegClass;
9463 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9464 break;
9466 Opc = AArch64::MLAv2i32_indexed;
9467 RC = &AArch64::FPR64RegClass;
9468 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9469 break;
9471 Opc = AArch64::MLAv4i32_indexed;
9472 RC = &AArch64::FPR128RegClass;
9473 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9474 break;
9476 Opc = AArch64::MLAv4i32_indexed;
9477 RC = &AArch64::FPR128RegClass;
9478 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9479 break;
9480
9482 Opc = AArch64::MLAv4i16_indexed;
9483 RC = &AArch64::FPR64RegClass;
9484 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9485 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9486 RC);
9487 break;
9489 Opc = AArch64::MLSv4i16_indexed;
9490 RC = &AArch64::FPR64RegClass;
9491 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9492 break;
9494 Opc = AArch64::MLAv8i16_indexed;
9495 RC = &AArch64::FPR128RegClass;
9496 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9497 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9498 RC);
9499 break;
9501 Opc = AArch64::MLSv8i16_indexed;
9502 RC = &AArch64::FPR128RegClass;
9503 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9504 break;
9506 Opc = AArch64::MLAv2i32_indexed;
9507 RC = &AArch64::FPR64RegClass;
9508 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9509 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9510 RC);
9511 break;
9513 Opc = AArch64::MLSv2i32_indexed;
9514 RC = &AArch64::FPR64RegClass;
9515 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9516 break;
9518 Opc = AArch64::MLAv4i32_indexed;
9519 RC = &AArch64::FPR128RegClass;
9520 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9521 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9522 RC);
9523 break;
9525 Opc = AArch64::MLSv4i32_indexed;
9526 RC = &AArch64::FPR128RegClass;
9527 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9528 break;
9529
9530 // Floating Point Support
9532 Opc = AArch64::FMADDHrrr;
9533 RC = &AArch64::FPR16RegClass;
9534 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9535 break;
9537 Opc = AArch64::FMADDSrrr;
9538 RC = &AArch64::FPR32RegClass;
9539 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9540 break;
9542 Opc = AArch64::FMADDDrrr;
9543 RC = &AArch64::FPR64RegClass;
9544 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9545 break;
9546
9548 Opc = AArch64::FMADDHrrr;
9549 RC = &AArch64::FPR16RegClass;
9550 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9551 break;
9553 Opc = AArch64::FMADDSrrr;
9554 RC = &AArch64::FPR32RegClass;
9555 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9556 break;
9558 Opc = AArch64::FMADDDrrr;
9559 RC = &AArch64::FPR64RegClass;
9560 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9561 break;
9562
9564 Opc = AArch64::FMLAv1i32_indexed;
9565 RC = &AArch64::FPR32RegClass;
9566 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9568 break;
9570 Opc = AArch64::FMLAv1i32_indexed;
9571 RC = &AArch64::FPR32RegClass;
9572 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9574 break;
9575
9577 Opc = AArch64::FMLAv1i64_indexed;
9578 RC = &AArch64::FPR64RegClass;
9579 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9581 break;
9583 Opc = AArch64::FMLAv1i64_indexed;
9584 RC = &AArch64::FPR64RegClass;
9585 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9587 break;
9588
9590 RC = &AArch64::FPR64RegClass;
9591 Opc = AArch64::FMLAv4i16_indexed;
9592 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9594 break;
9596 RC = &AArch64::FPR64RegClass;
9597 Opc = AArch64::FMLAv4f16;
9598 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9600 break;
9602 RC = &AArch64::FPR64RegClass;
9603 Opc = AArch64::FMLAv4i16_indexed;
9604 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9606 break;
9608 RC = &AArch64::FPR64RegClass;
9609 Opc = AArch64::FMLAv4f16;
9610 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9612 break;
9613
9616 RC = &AArch64::FPR64RegClass;
9618 Opc = AArch64::FMLAv2i32_indexed;
9619 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9621 } else {
9622 Opc = AArch64::FMLAv2f32;
9623 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9625 }
9626 break;
9629 RC = &AArch64::FPR64RegClass;
9631 Opc = AArch64::FMLAv2i32_indexed;
9632 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9634 } else {
9635 Opc = AArch64::FMLAv2f32;
9636 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9638 }
9639 break;
9640
9642 RC = &AArch64::FPR128RegClass;
9643 Opc = AArch64::FMLAv8i16_indexed;
9644 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9646 break;
9648 RC = &AArch64::FPR128RegClass;
9649 Opc = AArch64::FMLAv8f16;
9650 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9652 break;
9654 RC = &AArch64::FPR128RegClass;
9655 Opc = AArch64::FMLAv8i16_indexed;
9656 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9658 break;
9660 RC = &AArch64::FPR128RegClass;
9661 Opc = AArch64::FMLAv8f16;
9662 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9664 break;
9665
9668 RC = &AArch64::FPR128RegClass;
9670 Opc = AArch64::FMLAv2i64_indexed;
9671 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9673 } else {
9674 Opc = AArch64::FMLAv2f64;
9675 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9677 }
9678 break;
9681 RC = &AArch64::FPR128RegClass;
9683 Opc = AArch64::FMLAv2i64_indexed;
9684 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9686 } else {
9687 Opc = AArch64::FMLAv2f64;
9688 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9690 }
9691 break;
9692
9695 RC = &AArch64::FPR128RegClass;
9697 Opc = AArch64::FMLAv4i32_indexed;
9698 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9700 } else {
9701 Opc = AArch64::FMLAv4f32;
9702 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9704 }
9705 break;
9706
9709 RC = &AArch64::FPR128RegClass;
9711 Opc = AArch64::FMLAv4i32_indexed;
9712 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9714 } else {
9715 Opc = AArch64::FMLAv4f32;
9716 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9718 }
9719 break;
9720
9722 Opc = AArch64::FNMSUBHrrr;
9723 RC = &AArch64::FPR16RegClass;
9724 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9725 break;
9727 Opc = AArch64::FNMSUBSrrr;
9728 RC = &AArch64::FPR32RegClass;
9729 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9730 break;
9732 Opc = AArch64::FNMSUBDrrr;
9733 RC = &AArch64::FPR64RegClass;
9734 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9735 break;
9736
9738 Opc = AArch64::FNMADDHrrr;
9739 RC = &AArch64::FPR16RegClass;
9740 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9741 break;
9743 Opc = AArch64::FNMADDSrrr;
9744 RC = &AArch64::FPR32RegClass;
9745 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9746 break;
9748 Opc = AArch64::FNMADDDrrr;
9749 RC = &AArch64::FPR64RegClass;
9750 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9751 break;
9752
9754 Opc = AArch64::FMSUBHrrr;
9755 RC = &AArch64::FPR16RegClass;
9756 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9757 break;
9759 Opc = AArch64::FMSUBSrrr;
9760 RC = &AArch64::FPR32RegClass;
9761 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9762 break;
9764 Opc = AArch64::FMSUBDrrr;
9765 RC = &AArch64::FPR64RegClass;
9766 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9767 break;
9768
9770 Opc = AArch64::FMLSv1i32_indexed;
9771 RC = &AArch64::FPR32RegClass;
9772 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9774 break;
9775
9777 Opc = AArch64::FMLSv1i64_indexed;
9778 RC = &AArch64::FPR64RegClass;
9779 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9781 break;
9782
9785 RC = &AArch64::FPR64RegClass;
9786 Register NewVR = MRI.createVirtualRegister(RC);
9787 MachineInstrBuilder MIB1 =
9788 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f16), NewVR)
9789 .add(Root.getOperand(2));
9790 InsInstrs.push_back(MIB1);
9791 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9793 Opc = AArch64::FMLAv4f16;
9794 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9795 FMAInstKind::Accumulator, &NewVR);
9796 } else {
9797 Opc = AArch64::FMLAv4i16_indexed;
9798 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9799 FMAInstKind::Indexed, &NewVR);
9800 }
9801 break;
9802 }
9804 RC = &AArch64::FPR64RegClass;
9805 Opc = AArch64::FMLSv4f16;
9806 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9808 break;
9810 RC = &AArch64::FPR64RegClass;
9811 Opc = AArch64::FMLSv4i16_indexed;
9812 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9814 break;
9815
9818 RC = &AArch64::FPR64RegClass;
9820 Opc = AArch64::FMLSv2i32_indexed;
9821 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9823 } else {
9824 Opc = AArch64::FMLSv2f32;
9825 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9827 }
9828 break;
9829
9832 RC = &AArch64::FPR128RegClass;
9833 Register NewVR = MRI.createVirtualRegister(RC);
9834 MachineInstrBuilder MIB1 =
9835 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv8f16), NewVR)
9836 .add(Root.getOperand(2));
9837 InsInstrs.push_back(MIB1);
9838 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9840 Opc = AArch64::FMLAv8f16;
9841 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9842 FMAInstKind::Accumulator, &NewVR);
9843 } else {
9844 Opc = AArch64::FMLAv8i16_indexed;
9845 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9846 FMAInstKind::Indexed, &NewVR);
9847 }
9848 break;
9849 }
9851 RC = &AArch64::FPR128RegClass;
9852 Opc = AArch64::FMLSv8f16;
9853 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9855 break;
9857 RC = &AArch64::FPR128RegClass;
9858 Opc = AArch64::FMLSv8i16_indexed;
9859 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9861 break;
9862
9865 RC = &AArch64::FPR128RegClass;
9867 Opc = AArch64::FMLSv2i64_indexed;
9868 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9870 } else {
9871 Opc = AArch64::FMLSv2f64;
9872 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9874 }
9875 break;
9876
9879 RC = &AArch64::FPR128RegClass;
9881 Opc = AArch64::FMLSv4i32_indexed;
9882 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9884 } else {
9885 Opc = AArch64::FMLSv4f32;
9886 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9888 }
9889 break;
9892 RC = &AArch64::FPR64RegClass;
9893 Register NewVR = MRI.createVirtualRegister(RC);
9894 MachineInstrBuilder MIB1 =
9895 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f32), NewVR)
9896 .add(Root.getOperand(2));
9897 InsInstrs.push_back(MIB1);
9898 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9900 Opc = AArch64::FMLAv2i32_indexed;
9901 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9902 FMAInstKind::Indexed, &NewVR);
9903 } else {
9904 Opc = AArch64::FMLAv2f32;
9905 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9906 FMAInstKind::Accumulator, &NewVR);
9907 }
9908 break;
9909 }
9912 RC = &AArch64::FPR128RegClass;
9913 Register NewVR = MRI.createVirtualRegister(RC);
9914 MachineInstrBuilder MIB1 =
9915 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f32), NewVR)
9916 .add(Root.getOperand(2));
9917 InsInstrs.push_back(MIB1);
9918 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9920 Opc = AArch64::FMLAv4i32_indexed;
9921 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9922 FMAInstKind::Indexed, &NewVR);
9923 } else {
9924 Opc = AArch64::FMLAv4f32;
9925 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9926 FMAInstKind::Accumulator, &NewVR);
9927 }
9928 break;
9929 }
9932 RC = &AArch64::FPR128RegClass;
9933 Register NewVR = MRI.createVirtualRegister(RC);
9934 MachineInstrBuilder MIB1 =
9935 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f64), NewVR)
9936 .add(Root.getOperand(2));
9937 InsInstrs.push_back(MIB1);
9938 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9940 Opc = AArch64::FMLAv2i64_indexed;
9941 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9942 FMAInstKind::Indexed, &NewVR);
9943 } else {
9944 Opc = AArch64::FMLAv2f64;
9945 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9946 FMAInstKind::Accumulator, &NewVR);
9947 }
9948 break;
9949 }
9952 unsigned IdxDupOp =
9954 : 2;
9955 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i32_indexed,
9956 &AArch64::FPR128RegClass, MRI);
9957 break;
9958 }
9961 unsigned IdxDupOp =
9963 : 2;
9964 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i64_indexed,
9965 &AArch64::FPR128RegClass, MRI);
9966 break;
9967 }
9970 unsigned IdxDupOp =
9972 : 2;
9973 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i16_indexed,
9974 &AArch64::FPR128_loRegClass, MRI);
9975 break;
9976 }
9979 unsigned IdxDupOp =
9981 : 2;
9982 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i32_indexed,
9983 &AArch64::FPR128RegClass, MRI);
9984 break;
9985 }
9988 unsigned IdxDupOp =
9990 : 2;
9991 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv8i16_indexed,
9992 &AArch64::FPR128_loRegClass, MRI);
9993 break;
9994 }
9996 MUL = genFNegatedMAD(MF, MRI, TII, Root, InsInstrs);
9997 break;
9998 }
10000 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10001 Pattern, 4);
10002 break;
10003 }
10005 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10006 Pattern, 8);
10007 break;
10008 }
10010 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10011 Pattern, 16);
10012 break;
10013 }
10014
10015 } // end switch (Pattern)
10016 // Record MUL and ADD/SUB for deletion
10017 if (MUL)
10018 DelInstrs.push_back(MUL);
10019 DelInstrs.push_back(&Root);
10020
10021 // Set the flags on the inserted instructions to be the merged flags of the
10022 // instructions that we have combined.
10023 uint32_t Flags = Root.getFlags();
10024 if (MUL)
10025 Flags = Root.mergeFlagsWith(*MUL);
10026 for (auto *MI : InsInstrs)
10027 MI->setFlags(Flags);
10028}
10029
10030/// Replace csincr-branch sequence by simple conditional branch
10031///
10032/// Examples:
10033/// 1. \code
10034/// csinc w9, wzr, wzr, <condition code>
10035/// tbnz w9, #0, 0x44
10036/// \endcode
10037/// to
10038/// \code
10039/// b.<inverted condition code>
10040/// \endcode
10041///
10042/// 2. \code
10043/// csinc w9, wzr, wzr, <condition code>
10044/// tbz w9, #0, 0x44
10045/// \endcode
10046/// to
10047/// \code
10048/// b.<condition code>
10049/// \endcode
10050///
10051/// Replace compare and branch sequence by TBZ/TBNZ instruction when the
10052/// compare's constant operand is power of 2.
10053///
10054/// Examples:
10055/// \code
10056/// and w8, w8, #0x400
10057/// cbnz w8, L1
10058/// \endcode
10059/// to
10060/// \code
10061/// tbnz w8, #10, L1
10062/// \endcode
10063///
10064/// \param MI Conditional Branch
10065/// \return True when the simple conditional branch is generated
10066///
10068 bool IsNegativeBranch = false;
10069 bool IsTestAndBranch = false;
10070 unsigned TargetBBInMI = 0;
10071 switch (MI.getOpcode()) {
10072 default:
10073 llvm_unreachable("Unknown branch instruction?");
10074 case AArch64::Bcc:
10075 case AArch64::CBWPri:
10076 case AArch64::CBXPri:
10077 case AArch64::CBBAssertExt:
10078 case AArch64::CBHAssertExt:
10079 case AArch64::CBWPrr:
10080 case AArch64::CBXPrr:
10081 return false;
10082 case AArch64::CBZW:
10083 case AArch64::CBZX:
10084 TargetBBInMI = 1;
10085 break;
10086 case AArch64::CBNZW:
10087 case AArch64::CBNZX:
10088 TargetBBInMI = 1;
10089 IsNegativeBranch = true;
10090 break;
10091 case AArch64::TBZW:
10092 case AArch64::TBZX:
10093 TargetBBInMI = 2;
10094 IsTestAndBranch = true;
10095 break;
10096 case AArch64::TBNZW:
10097 case AArch64::TBNZX:
10098 TargetBBInMI = 2;
10099 IsNegativeBranch = true;
10100 IsTestAndBranch = true;
10101 break;
10102 }
10103 // So we increment a zero register and test for bits other
10104 // than bit 0? Conservatively bail out in case the verifier
10105 // missed this case.
10106 if (IsTestAndBranch && MI.getOperand(1).getImm())
10107 return false;
10108
10109 // Find Definition.
10110 assert(MI.getParent() && "Incomplete machine instruction\n");
10111 MachineBasicBlock *MBB = MI.getParent();
10112 MachineFunction *MF = MBB->getParent();
10113 MachineRegisterInfo *MRI = &MF->getRegInfo();
10114 Register VReg = MI.getOperand(0).getReg();
10115 if (!VReg.isVirtual())
10116 return false;
10117
10118 MachineInstr *DefMI = MRI->getVRegDef(VReg);
10119 if (!DefMI)
10120 return false;
10121
10122 // Look through COPY instructions to find definition.
10123 while (DefMI->isCopy()) {
10124 Register CopyVReg = DefMI->getOperand(1).getReg();
10125 if (!CopyVReg.isVirtual())
10126 return false;
10127 if (!MRI->hasOneNonDBGUse(CopyVReg))
10128 return false;
10129 DefMI = MRI->getVRegDef(CopyVReg);
10130 if (!DefMI)
10131 return false;
10132 }
10133
10134 switch (DefMI->getOpcode()) {
10135 default:
10136 return false;
10137 // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
10138 case AArch64::ANDWri:
10139 case AArch64::ANDXri: {
10140 if (IsTestAndBranch)
10141 return false;
10142 if (DefMI->getParent() != MBB)
10143 return false;
10144 if (!MRI->hasOneNonDBGUse(VReg))
10145 return false;
10146
10147 bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
10148 uint64_t Mask = AArch64_AM::decodeLogicalImmediate(
10149 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
10150 if (!isPowerOf2_64(Mask))
10151 return false;
10152
10153 MachineOperand &MO = DefMI->getOperand(1);
10154 Register NewReg = MO.getReg();
10155 if (!NewReg.isVirtual())
10156 return false;
10157
10158 if (!MRI->getVRegDef(NewReg))
10159 return false;
10160
10161 MachineBasicBlock &RefToMBB = *MBB;
10162 MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
10163 DebugLoc DL = MI.getDebugLoc();
10164 unsigned Imm = Log2_64(Mask);
10165 unsigned Opc = (Imm < 32)
10166 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
10167 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
10168 MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
10169 .addReg(NewReg)
10170 .addImm(Imm)
10171 .addMBB(TBB);
10172 // Register lives on to the CBZ now.
10173 MO.setIsKill(false);
10174
10175 // For immediate smaller than 32, we need to use the 32-bit
10176 // variant (W) in all cases. Indeed the 64-bit variant does not
10177 // allow to encode them.
10178 // Therefore, if the input register is 64-bit, we need to take the
10179 // 32-bit sub-part.
10180 if (!Is32Bit && Imm < 32)
10181 NewMI->getOperand(0).setSubReg(AArch64::sub_32);
10182 MI.eraseFromParent();
10183 return true;
10184 }
10185 // Look for CSINC
10186 case AArch64::CSINCWr:
10187 case AArch64::CSINCXr: {
10188 if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
10189 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
10190 !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
10191 DefMI->getOperand(2).getReg() == AArch64::XZR))
10192 return false;
10193
10194 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
10195 true) != -1)
10196 return false;
10197
10198 AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
10199 // Convert only when the condition code is not modified between
10200 // the CSINC and the branch. The CC may be used by other
10201 // instructions in between.
10203 return false;
10204 MachineBasicBlock &RefToMBB = *MBB;
10205 MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
10206 DebugLoc DL = MI.getDebugLoc();
10207 if (IsNegativeBranch)
10209 BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
10210 MI.eraseFromParent();
10211 return true;
10212 }
10213 }
10214}
10215
10216std::pair<unsigned, unsigned>
10217AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
10218 const unsigned Mask = AArch64II::MO_FRAGMENT;
10219 return std::make_pair(TF & Mask, TF & ~Mask);
10220}
10221
10223AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
10224 using namespace AArch64II;
10225
10226 static const std::pair<unsigned, const char *> TargetFlags[] = {
10227 {MO_PAGE, "aarch64-page"}, {MO_PAGEOFF, "aarch64-pageoff"},
10228 {MO_G3, "aarch64-g3"}, {MO_G2, "aarch64-g2"},
10229 {MO_G1, "aarch64-g1"}, {MO_G0, "aarch64-g0"},
10230 {MO_HI12, "aarch64-hi12"}};
10231 return ArrayRef(TargetFlags);
10232}
10233
10235AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
10236 using namespace AArch64II;
10237
10238 static const std::pair<unsigned, const char *> TargetFlags[] = {
10239 {MO_COFFSTUB, "aarch64-coffstub"},
10240 {MO_GOT, "aarch64-got"},
10241 {MO_NC, "aarch64-nc"},
10242 {MO_S, "aarch64-s"},
10243 {MO_TLS, "aarch64-tls"},
10244 {MO_DLLIMPORT, "aarch64-dllimport"},
10245 {MO_PREL, "aarch64-prel"},
10246 {MO_TAGGED, "aarch64-tagged"},
10247 {MO_ARM64EC_CALLMANGLE, "aarch64-arm64ec-callmangle"},
10248 };
10249 return ArrayRef(TargetFlags);
10250}
10251
10253AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const {
10254 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10255 {{MOSuppressPair, "aarch64-suppress-pair"},
10256 {MOStridedAccess, "aarch64-strided-access"}};
10257 return ArrayRef(TargetFlags);
10258}
10259
10260/// Constants defining how certain sequences should be outlined.
10261/// This encompasses how an outlined function should be called, and what kind of
10262/// frame should be emitted for that outlined function.
10263///
10264/// \p MachineOutlinerDefault implies that the function should be called with
10265/// a save and restore of LR to the stack.
10266///
10267/// That is,
10268///
10269/// I1 Save LR OUTLINED_FUNCTION:
10270/// I2 --> BL OUTLINED_FUNCTION I1
10271/// I3 Restore LR I2
10272/// I3
10273/// RET
10274///
10275/// * Call construction overhead: 3 (save + BL + restore)
10276/// * Frame construction overhead: 1 (ret)
10277/// * Requires stack fixups? Yes
10278///
10279/// \p MachineOutlinerTailCall implies that the function is being created from
10280/// a sequence of instructions ending in a return.
10281///
10282/// That is,
10283///
10284/// I1 OUTLINED_FUNCTION:
10285/// I2 --> B OUTLINED_FUNCTION I1
10286/// RET I2
10287/// RET
10288///
10289/// * Call construction overhead: 1 (B)
10290/// * Frame construction overhead: 0 (Return included in sequence)
10291/// * Requires stack fixups? No
10292///
10293/// \p MachineOutlinerNoLRSave implies that the function should be called using
10294/// a BL instruction, but doesn't require LR to be saved and restored. This
10295/// happens when LR is known to be dead.
10296///
10297/// That is,
10298///
10299/// I1 OUTLINED_FUNCTION:
10300/// I2 --> BL OUTLINED_FUNCTION I1
10301/// I3 I2
10302/// I3
10303/// RET
10304///
10305/// * Call construction overhead: 1 (BL)
10306/// * Frame construction overhead: 1 (RET)
10307/// * Requires stack fixups? No
10308///
10309/// \p MachineOutlinerThunk implies that the function is being created from
10310/// a sequence of instructions ending in a call. The outlined function is
10311/// called with a BL instruction, and the outlined function tail-calls the
10312/// original call destination.
10313///
10314/// That is,
10315///
10316/// I1 OUTLINED_FUNCTION:
10317/// I2 --> BL OUTLINED_FUNCTION I1
10318/// BL f I2
10319/// B f
10320/// * Call construction overhead: 1 (BL)
10321/// * Frame construction overhead: 0
10322/// * Requires stack fixups? No
10323///
10324/// \p MachineOutlinerRegSave implies that the function should be called with a
10325/// save and restore of LR to an available register. This allows us to avoid
10326/// stack fixups. Note that this outlining variant is compatible with the
10327/// NoLRSave case.
10328///
10329/// That is,
10330///
10331/// I1 Save LR OUTLINED_FUNCTION:
10332/// I2 --> BL OUTLINED_FUNCTION I1
10333/// I3 Restore LR I2
10334/// I3
10335/// RET
10336///
10337/// * Call construction overhead: 3 (save + BL + restore)
10338/// * Frame construction overhead: 1 (ret)
10339/// * Requires stack fixups? No
10341 MachineOutlinerDefault, /// Emit a save, restore, call, and return.
10342 MachineOutlinerTailCall, /// Only emit a branch.
10343 MachineOutlinerNoLRSave, /// Emit a call and return.
10344 MachineOutlinerThunk, /// Emit a call and tail-call.
10345 MachineOutlinerRegSave /// Same as default, but save to a register.
10346};
10347
10353
10354/// Return true if the frame-record form of the outlined prologue is enabled for
10355/// the target of \p MF.
10356///
10357/// A non-leaf outlined function must save LR. On MachO, saving LR alone
10358/// (str x30) has no compact unwind encoding, so we get a large DWARF FDE
10359/// instead. Saving FP and LR as a frame record (stp x29, x30 ; mov x29, sp)
10360/// gets the small FRAME encoding, and costs one extra instruction.
10365
10366/// Return true if the outlined function in \p MBB should save FP and LR as a
10367/// frame record instead of saving LR alone.
10369 const MachineBasicBlock &MBB) {
10370 const MachineFunction &MF = *MBB.getParent();
10371
10372 // Only worth it if the function has unwind info to shrink.
10375 return false;
10376
10377 // Only safe if the outlined code never touches FP, since we overwrite it.
10379 for (const MachineInstr &MI : MBB.instrs())
10380 LRU.accumulate(MI);
10381 return LRU.available(AArch64::FP);
10382}
10383
10384/// Predict what the above will answer, for use while costing candidates. The
10385/// outlined function does not exist yet, so answer from \p RepeatedSequenceLocs
10386/// instead. This is only an estimate; buildOutlinedFrame() makes the call.
10388 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10389 const TargetRegisterInfo &TRI) {
10390 if (!isCompactUnwindFrameRecordEnabled(*RepeatedSequenceLocs.front().getMF()))
10391 return false;
10392
10393 // The outlined function is nounwind only if every candidate is, so it has
10394 // unwind info if any candidate does.
10395 if (llvm::none_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10396 const MachineFunction &MF = *C.getMF();
10397 return MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
10398 }))
10399 return false;
10400
10401 // FP is free in the outlined function only if it is free in every candidate.
10402 return llvm::all_of(RepeatedSequenceLocs, [&TRI](outliner::Candidate &C) {
10403 return C.isAvailableInsideSeq(AArch64::FP, TRI);
10404 });
10405}
10406
10408AArch64InstrInfo::findRegisterToSaveLRTo(outliner::Candidate &C) const {
10409 MachineFunction *MF = C.getMF();
10410 const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
10411 const AArch64RegisterInfo *ARI =
10412 static_cast<const AArch64RegisterInfo *>(&TRI);
10413 // Check if there is an available register across the sequence that we can
10414 // use.
10415 for (unsigned Reg : AArch64::GPR64RegClass) {
10416 if (!ARI->isReservedReg(*MF, Reg) &&
10417 Reg != AArch64::LR && // LR is not reserved, but don't use it.
10418 Reg != AArch64::X16 && // X16 is not guaranteed to be preserved.
10419 Reg != AArch64::X17 && // Ditto for X17.
10420 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&
10421 C.isAvailableInsideSeq(Reg, TRI))
10422 return Reg;
10423 }
10424 return Register();
10425}
10426
10427static bool
10429 const outliner::Candidate &b) {
10430 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10431 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10432
10433 return MFIa->getSignReturnAddressCondition() ==
10435}
10436
10437static bool
10439 const outliner::Candidate &b) {
10440 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10441 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10442
10443 return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey();
10444}
10445
10447 const outliner::Candidate &b) {
10448 const AArch64Subtarget &SubtargetA =
10450 const AArch64Subtarget &SubtargetB =
10451 b.getMF()->getSubtarget<AArch64Subtarget>();
10452 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10453}
10454
10455std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10456AArch64InstrInfo::getOutliningCandidateInfo(
10457 const MachineModuleInfo &MMI,
10458 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10459 unsigned MinRepeats) const {
10460 unsigned SequenceSize = 0;
10461 for (auto &MI : RepeatedSequenceLocs[0])
10462 SequenceSize += getInstSizeInBytes(MI);
10463
10464 unsigned NumBytesToCreateFrame = 0;
10465
10466 // Avoid splitting ADRP ADD/LDR pair into outlined functions.
10467 // These instructions are fused together by the scheduler.
10468 // Any candidate where ADRP is the last instruction should be rejected
10469 // as that will lead to splitting ADRP pair.
10470 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10471 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10472 if (LastMI.getOpcode() == AArch64::ADRP &&
10473 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0 &&
10474 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10475 return std::nullopt;
10476 }
10477
10478 // Similarly any candidate where the first instruction is ADD/LDR with a
10479 // page offset should be rejected to avoid ADRP splitting.
10480 if ((FirstMI.getOpcode() == AArch64::ADDXri ||
10481 FirstMI.getOpcode() == AArch64::LDRXui) &&
10482 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_PAGEOFF) != 0 &&
10483 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10484 return std::nullopt;
10485 }
10486
10487 // We only allow outlining for functions having exactly matching return
10488 // address signing attributes, i.e., all share the same value for the
10489 // attribute "sign-return-address" and all share the same type of key they
10490 // are signed with.
10491 // Additionally we require all functions to simultaneously either support
10492 // v8.3a features or not. Otherwise an outlined function could get signed
10493 // using dedicated v8.3 instructions and a call from a function that doesn't
10494 // support v8.3 instructions would therefore be invalid.
10495 if (std::adjacent_find(
10496 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10497 [](const outliner::Candidate &a, const outliner::Candidate &b) {
10498 // Return true if a and b are non-equal w.r.t. return address
10499 // signing or support of v8.3a features
10500 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10501 outliningCandidatesSigningKeyConsensus(a, b) &&
10502 outliningCandidatesV8_3OpsConsensus(a, b)) {
10503 return false;
10504 }
10505 return true;
10506 }) != RepeatedSequenceLocs.end()) {
10507 return std::nullopt;
10508 }
10509
10510 // Since at this point all candidates agree on their return address signing
10511 // picking just one is fine. If the candidate functions potentially sign their
10512 // return addresses, the outlined function should do the same. Note that in
10513 // the case of "sign-return-address"="non-leaf" this is an assumption: It is
10514 // not certainly true that the outlined function will have to sign its return
10515 // address but this decision is made later, when the decision to outline
10516 // has already been made.
10517 // The same holds for the number of additional instructions we need: On
10518 // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
10519 // necessary. However, at this point we don't know if the outlined function
10520 // will have a RET instruction so we assume the worst.
10521 const TargetRegisterInfo &TRI = getRegisterInfo();
10522 // Performing a tail call may require extra checks when PAuth is enabled.
10523 // If PAuth is disabled, set it to zero for uniformity.
10524 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10525 const auto RASignCondition = RepeatedSequenceLocs[0]
10526 .getMF()
10527 ->getInfo<AArch64FunctionInfo>()
10528 ->getSignReturnAddressCondition();
10529 if (RASignCondition != SignReturnAddress::None) {
10530 // One PAC and one AUT instructions
10531 NumBytesToCreateFrame += 8;
10532
10533 // PAuth is enabled - set extra tail call cost, if any.
10534 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10535 *RepeatedSequenceLocs[0].getMF());
10536 NumBytesToCheckLRInTCEpilogue =
10538 // Checking the authenticated LR value may significantly impact
10539 // SequenceSize, so account for it for more precise results.
10540 if (isTailCallReturnInst(RepeatedSequenceLocs[0].back()))
10541 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10542
10543 // We have to check if sp modifying instructions would get outlined.
10544 // If so we only allow outlining if sp is unchanged overall, so matching
10545 // sub and add instructions are okay to outline, all other sp modifications
10546 // are not
10547 auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) {
10548 int SPValue = 0;
10549 for (auto &MI : C) {
10550 if (MI.modifiesRegister(AArch64::SP, &TRI)) {
10551 switch (MI.getOpcode()) {
10552 case AArch64::ADDXri:
10553 case AArch64::ADDWri:
10554 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10555 assert(MI.getOperand(2).isImm() &&
10556 "Expected operand to be immediate");
10557 assert(MI.getOperand(1).isReg() &&
10558 "Expected operand to be a register");
10559 // Check if the add just increments sp. If so, we search for
10560 // matching sub instructions that decrement sp. If not, the
10561 // modification is illegal
10562 if (MI.getOperand(1).getReg() == AArch64::SP)
10563 SPValue += MI.getOperand(2).getImm();
10564 else
10565 return true;
10566 break;
10567 case AArch64::SUBXri:
10568 case AArch64::SUBWri:
10569 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10570 assert(MI.getOperand(2).isImm() &&
10571 "Expected operand to be immediate");
10572 assert(MI.getOperand(1).isReg() &&
10573 "Expected operand to be a register");
10574 // Check if the sub just decrements sp. If so, we search for
10575 // matching add instructions that increment sp. If not, the
10576 // modification is illegal
10577 if (MI.getOperand(1).getReg() == AArch64::SP)
10578 SPValue -= MI.getOperand(2).getImm();
10579 else
10580 return true;
10581 break;
10582 default:
10583 return true;
10584 }
10585 }
10586 }
10587 if (SPValue)
10588 return true;
10589 return false;
10590 };
10591 // Remove candidates with illegal stack modifying instructions
10592 llvm::erase_if(RepeatedSequenceLocs, hasIllegalSPModification);
10593
10594 // If the sequence doesn't have enough candidates left, then we're done.
10595 if (RepeatedSequenceLocs.size() < MinRepeats)
10596 return std::nullopt;
10597 }
10598
10599 // Properties about candidate MBBs that hold for all of them.
10600 unsigned FlagsSetInAll = 0xF;
10601
10602 // Compute liveness information for each candidate, and set FlagsSetInAll.
10603 for (outliner::Candidate &C : RepeatedSequenceLocs)
10604 FlagsSetInAll &= C.Flags;
10605
10606 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10607
10608 // Helper lambda which sets call information for every candidate.
10609 auto SetCandidateCallInfo =
10610 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {
10611 for (outliner::Candidate &C : RepeatedSequenceLocs)
10612 C.setCallInfo(CallID, NumBytesForCall);
10613 };
10614
10615 unsigned FrameID = MachineOutlinerDefault;
10616 NumBytesToCreateFrame += 4;
10617
10618 bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10619 return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement();
10620 });
10621
10622 // We check to see if CFI Instructions are present, and if they are
10623 // we find the number of CFI Instructions in the candidates.
10624 unsigned CFICount = 0;
10625 for (auto &I : RepeatedSequenceLocs[0]) {
10626 if (I.isCFIInstruction())
10627 CFICount++;
10628 }
10629
10630 // We compare the number of found CFI Instructions to the number of CFI
10631 // instructions in the parent function for each candidate. We must check this
10632 // since if we outline one of the CFI instructions in a function, we have to
10633 // outline them all for correctness. If we do not, the address offsets will be
10634 // incorrect between the two sections of the program.
10635 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10636 std::vector<MCCFIInstruction> CFIInstructions =
10637 C.getMF()->getFrameInstructions();
10638
10639 if (CFICount > 0 && CFICount != CFIInstructions.size())
10640 return std::nullopt;
10641 }
10642
10643 // Returns true if an instructions is safe to fix up, false otherwise.
10644 auto IsSafeToFixup = [this, &TRI](MachineInstr &MI) {
10645 if (MI.isCall())
10646 return true;
10647
10648 if (!MI.modifiesRegister(AArch64::SP, &TRI) &&
10649 !MI.readsRegister(AArch64::SP, &TRI))
10650 return true;
10651
10652 // Any modification of SP will break our code to save/restore LR.
10653 // FIXME: We could handle some instructions which add a constant
10654 // offset to SP, with a bit more work.
10655 if (MI.modifiesRegister(AArch64::SP, &TRI))
10656 return false;
10657
10658 // At this point, we have a stack instruction that we might need to
10659 // fix up. We'll handle it if it's a load or store.
10660 if (MI.mayLoadOrStore()) {
10661 const MachineOperand *Base; // Filled with the base operand of MI.
10662 int64_t Offset; // Filled with the offset of MI.
10663 bool OffsetIsScalable;
10664
10665 // Does it allow us to offset the base operand and is the base the
10666 // register SP?
10667 if (!getMemOperandWithOffset(MI, Base, Offset, OffsetIsScalable, &TRI) ||
10668 !Base->isReg() || Base->getReg() != AArch64::SP)
10669 return false;
10670
10671 // Fixe-up code below assumes bytes.
10672 if (OffsetIsScalable)
10673 return false;
10674
10675 // Find the minimum/maximum offset for this instruction and check
10676 // if fixing it up would be in range.
10677 int64_t MinOffset,
10678 MaxOffset; // Unscaled offsets for the instruction.
10679 // The scale to multiply the offsets by.
10680 TypeSize Scale(0U, false), DummyWidth(0U, false);
10681 getMemOpInfo(MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10682
10683 Offset += 16; // Update the offset to what it would be if we outlined.
10684 if (Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10685 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10686 return false;
10687
10688 // It's in range, so we can outline it.
10689 return true;
10690 }
10691
10692 // FIXME: Add handling for instructions like "add x0, sp, #8".
10693
10694 // We can't fix it up, so don't outline it.
10695 return false;
10696 };
10697
10698 // True if it's possible to fix up each stack instruction in this sequence.
10699 // Important for frames/call variants that modify the stack.
10700 bool AllStackInstrsSafe =
10701 llvm::all_of(RepeatedSequenceLocs[0], IsSafeToFixup);
10702
10703 // If the last instruction in any candidate is a terminator, then we should
10704 // tail call all of the candidates.
10705 if (RepeatedSequenceLocs[0].back().isTerminator()) {
10706 FrameID = MachineOutlinerTailCall;
10707 NumBytesToCreateFrame = 0;
10708 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10709 SetCandidateCallInfo(MachineOutlinerTailCall, NumBytesForCall);
10710 }
10711
10712 else if (LastInstrOpcode == AArch64::BL ||
10713 ((LastInstrOpcode == AArch64::BLR ||
10714 LastInstrOpcode == AArch64::BLRNoIP) &&
10715 !HasBTI)) {
10716 // FIXME: Do we need to check if the code after this uses the value of LR?
10717 FrameID = MachineOutlinerThunk;
10718 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10719 SetCandidateCallInfo(MachineOutlinerThunk, 4);
10720 }
10721
10722 else {
10723 // We need to decide how to emit calls + frames. We can always emit the same
10724 // frame if we don't need to save to the stack. If we have to save to the
10725 // stack, then we need a different frame.
10726 unsigned NumBytesNoStackCalls = 0;
10727 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10728
10729 // Check if we have to save LR.
10730 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10731 bool LRAvailable =
10733 ? C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI)
10734 : true;
10735 // If we have a noreturn caller, then we're going to be conservative and
10736 // say that we have to save LR. If we don't have a ret at the end of the
10737 // block, then we can't reason about liveness accurately.
10738 //
10739 // FIXME: We can probably do better than always disabling this in
10740 // noreturn functions by fixing up the liveness info.
10741 bool IsNoReturn =
10742 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10743
10744 // Is LR available? If so, we don't need a save.
10745 if (LRAvailable && !IsNoReturn) {
10746 NumBytesNoStackCalls += 4;
10747 C.setCallInfo(MachineOutlinerNoLRSave, 4);
10748 CandidatesWithoutStackFixups.push_back(C);
10749 }
10750
10751 // Is an unused register available? If so, we won't modify the stack, so
10752 // we can outline with the same frame type as those that don't save LR.
10753 else if (findRegisterToSaveLRTo(C)) {
10754 NumBytesNoStackCalls += 12;
10755 C.setCallInfo(MachineOutlinerRegSave, 12);
10756 CandidatesWithoutStackFixups.push_back(C);
10757 }
10758
10759 // Is SP used in the sequence at all? If not, we don't have to modify
10760 // the stack, so we are guaranteed to get the same frame.
10761 else if (C.isAvailableInsideSeq(AArch64::SP, TRI)) {
10762 NumBytesNoStackCalls += 12;
10763 C.setCallInfo(MachineOutlinerDefault, 12);
10764 CandidatesWithoutStackFixups.push_back(C);
10765 }
10766
10767 // If we outline this, we need to modify the stack. Pretend we don't
10768 // outline this by saving all of its bytes.
10769 else {
10770 NumBytesNoStackCalls += SequenceSize;
10771 }
10772 }
10773
10774 // If there are no places where we have to save LR, then note that we
10775 // don't have to update the stack. Otherwise, give every candidate the
10776 // default call type, as long as it's safe to do so.
10777 if (!AllStackInstrsSafe ||
10778 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10779 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10780 FrameID = MachineOutlinerNoLRSave;
10781 if (RepeatedSequenceLocs.size() < MinRepeats)
10782 return std::nullopt;
10783 } else {
10784 SetCandidateCallInfo(MachineOutlinerDefault, 12);
10785
10786 // Bugzilla ID: 46767
10787 // TODO: Check if fixing up the stack more than once is safe so we can
10788 // outline these.
10789 //
10790 // An outline resulting in a caller that requires stack fixups at the
10791 // callsite to a callee that also requires stack fixups can happen when
10792 // there are no available registers at the candidate callsite for a
10793 // candidate that itself also has calls.
10794 //
10795 // In other words if function_containing_sequence in the following pseudo
10796 // assembly requires that we save LR at the point of the call, but there
10797 // are no available registers: in this case we save using SP and as a
10798 // result the SP offsets requires stack fixups by multiples of 16.
10799 //
10800 // function_containing_sequence:
10801 // ...
10802 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10803 // call OUTLINED_FUNCTION_N
10804 // restore LR from SP
10805 // ...
10806 //
10807 // OUTLINED_FUNCTION_N:
10808 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10809 // ...
10810 // bl foo
10811 // restore LR from SP
10812 // ret
10813 //
10814 // Because the code to handle more than one stack fixup does not
10815 // currently have the proper checks for legality, these cases will assert
10816 // in the AArch64 MachineOutliner. This is because the code to do this
10817 // needs more hardening, testing, better checks that generated code is
10818 // legal, etc and because it is only verified to handle a single pass of
10819 // stack fixup.
10820 //
10821 // The assert happens in AArch64InstrInfo::buildOutlinedFrame to catch
10822 // these cases until they are known to be handled. Bugzilla 46767 is
10823 // referenced in comments at the assert site.
10824 //
10825 // To avoid asserting (or generating non-legal code on noassert builds)
10826 // we remove all candidates which would need more than one stack fixup by
10827 // pruning the cases where the candidate has calls while also having no
10828 // available LR and having no available general purpose registers to copy
10829 // LR to (ie one extra stack save/restore).
10830 //
10831 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10832 erase_if(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
10833 auto IsCall = [](const MachineInstr &MI) { return MI.isCall(); };
10834 return (llvm::any_of(C, IsCall)) &&
10835 (!C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI) ||
10836 !findRegisterToSaveLRTo(C));
10837 });
10838 }
10839 }
10840
10841 // If we dropped all of the candidates, bail out here.
10842 if (RepeatedSequenceLocs.size() < MinRepeats)
10843 return std::nullopt;
10844 }
10845
10846 // Does every candidate's MBB contain a call? If so, then we might have a call
10847 // in the range.
10848 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10849 // Check if the range contains a call. These require a save + restore of the
10850 // link register.
10851 outliner::Candidate &FirstCand = RepeatedSequenceLocs[0];
10852 bool ModStackToSaveLR = false;
10853 if (any_of(drop_end(FirstCand),
10854 [](const MachineInstr &MI) { return MI.isCall(); }))
10855 ModStackToSaveLR = true;
10856
10857 // Handle the last instruction separately. If this is a tail call, then the
10858 // last instruction is a call. We don't want to save + restore in this case.
10859 // However, it could be possible that the last instruction is a call without
10860 // it being valid to tail call this sequence. We should consider this as
10861 // well.
10862 else if (FrameID != MachineOutlinerThunk &&
10863 FrameID != MachineOutlinerTailCall && FirstCand.back().isCall())
10864 ModStackToSaveLR = true;
10865
10866 if (ModStackToSaveLR) {
10867 // We can't fix up the stack. Bail out.
10868 if (!AllStackInstrsSafe)
10869 return std::nullopt;
10870
10871 // Save + restore LR.
10872 NumBytesToCreateFrame += 8;
10873
10874 // Add the extra mov if we will save a frame record instead of just LR.
10876 RepeatedSequenceLocs, TRI))
10877 NumBytesToCreateFrame += 4;
10878 }
10879 }
10880
10881 // If we have CFI instructions, we can only outline if the outlined section
10882 // can be a tail call
10883 if (FrameID != MachineOutlinerTailCall && CFICount > 0)
10884 return std::nullopt;
10885
10886 return std::make_unique<outliner::OutlinedFunction>(
10887 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10888}
10889
10890void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10891 Function &F, std::vector<outliner::Candidate> &Candidates) const {
10892 // If a bunch of candidates reach this point they must agree on their return
10893 // address signing. It is therefore enough to just consider the signing
10894 // behaviour of one of them
10895 const auto &CFn = Candidates.front().getMF()->getFunction();
10896
10897 if (CFn.hasFnAttribute("ptrauth-returns"))
10898 F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
10899 if (CFn.hasFnAttribute("ptrauth-auth-traps"))
10900 F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
10901 // Since all candidates belong to the same module, just copy the
10902 // function-level attributes of an arbitrary function.
10903 if (CFn.hasFnAttribute("sign-return-address"))
10904 F.addFnAttr(CFn.getFnAttribute("sign-return-address"));
10905 if (CFn.hasFnAttribute("sign-return-address-key"))
10906 F.addFnAttr(CFn.getFnAttribute("sign-return-address-key"));
10907
10908 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);
10909}
10910
10911bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10912 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
10913 const Function &F = MF.getFunction();
10914
10915 // Can F be deduplicated by the linker? If it can, don't outline from it.
10916 if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
10917 return false;
10918
10919 // Don't outline from functions with section markings; the program could
10920 // expect that all the code is in the named section.
10921 // FIXME: Allow outlining from multiple functions with the same section
10922 // marking.
10923 if (F.hasSection())
10924 return false;
10925
10926 // Outlining from functions with redzones is unsafe since the outliner may
10927 // modify the stack. Check if hasRedZone is true or unknown; if yes, don't
10928 // outline from it.
10929 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
10930 if (!AFI || AFI->hasRedZone().value_or(true))
10931 return false;
10932
10933 // FIXME: Determine whether it is safe to outline from functions which contain
10934 // streaming-mode changes. We may need to ensure any smstart/smstop pairs are
10935 // outlined together and ensure it is safe to outline with async unwind info,
10936 // required for saving & restoring VG around calls.
10937 if (AFI->hasStreamingModeChanges())
10938 return false;
10939
10940 // FIXME: Teach the outliner to generate/handle Windows unwind info.
10942 return false;
10943
10944 // It's safe to outline from MF.
10945 return true;
10946}
10947
10949AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
10950 unsigned &Flags) const {
10952 "Must track liveness!");
10954 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10955 Ranges;
10956 // According to the AArch64 Procedure Call Standard, the following are
10957 // undefined on entry/exit from a function call:
10958 //
10959 // * Registers x16, x17, (and thus w16, w17)
10960 // * Condition codes (and thus the NZCV register)
10961 //
10962 // If any of these registers are used inside or live across an outlined
10963 // function, then they may be modified later, either by the compiler or
10964 // some other tool (like the linker).
10965 //
10966 // To avoid outlining in these situations, partition each block into ranges
10967 // where these registers are dead. We will only outline from those ranges.
10968 LiveRegUnits LRU(getRegisterInfo());
10969 auto AreAllUnsafeRegsDead = [&LRU]() {
10970 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10971 LRU.available(AArch64::NZCV);
10972 };
10973
10974 // We need to know if LR is live across an outlining boundary later on in
10975 // order to decide how we'll create the outlined call, frame, etc.
10976 //
10977 // It's pretty expensive to check this for *every candidate* within a block.
10978 // That's some potentially n^2 behaviour, since in the worst case, we'd need
10979 // to compute liveness from the end of the block for O(n) candidates within
10980 // the block.
10981 //
10982 // So, to improve the average case, let's keep track of liveness from the end
10983 // of the block to the beginning of *every outlinable range*. If we know that
10984 // LR is available in every range we could outline from, then we know that
10985 // we don't need to check liveness for any candidate within that range.
10986 bool LRAvailableEverywhere = true;
10987 // Compute liveness bottom-up.
10988 LRU.addLiveOuts(MBB);
10989 // Update flags that require info about the entire MBB.
10990 auto UpdateWholeMBBFlags = [&Flags](const MachineInstr &MI) {
10991 if (MI.isCall() && !MI.isTerminator())
10993 };
10994 // Range: [RangeBegin, RangeEnd)
10995 MachineBasicBlock::instr_iterator RangeBegin, RangeEnd;
10996 unsigned RangeLen;
10997 auto CreateNewRangeStartingAt =
10998 [&RangeBegin, &RangeEnd,
10999 &RangeLen](MachineBasicBlock::instr_iterator NewBegin) {
11000 RangeBegin = NewBegin;
11001 RangeEnd = std::next(RangeBegin);
11002 RangeLen = 0;
11003 };
11004 auto SaveRangeIfNonEmpty = [&RangeLen, &Ranges, &RangeBegin, &RangeEnd]() {
11005 // At least one unsafe register is not dead. We do not want to outline at
11006 // this point. If it is long enough to outline from and does not cross a
11007 // bundle boundary, save the range [RangeBegin, RangeEnd).
11008 if (RangeLen <= 1)
11009 return;
11010 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
11011 return;
11012 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
11013 return;
11014 Ranges.emplace_back(RangeBegin, RangeEnd);
11015 };
11016 // Find the first point where all unsafe registers are dead.
11017 // FIND: <safe instr> <-- end of first potential range
11018 // SKIP: <unsafe def>
11019 // SKIP: ... everything between ...
11020 // SKIP: <unsafe use>
11021 auto FirstPossibleEndPt = MBB.instr_rbegin();
11022 for (; FirstPossibleEndPt != MBB.instr_rend(); ++FirstPossibleEndPt) {
11023 if (!FirstPossibleEndPt->isDebugInstr())
11024 LRU.stepBackward(*FirstPossibleEndPt);
11025 // Update flags that impact how we outline across the entire block,
11026 // regardless of safety.
11027 UpdateWholeMBBFlags(*FirstPossibleEndPt);
11028 if (AreAllUnsafeRegsDead())
11029 break;
11030 }
11031 // If we exhausted the entire block, we have no safe ranges to outline.
11032 if (FirstPossibleEndPt == MBB.instr_rend())
11033 return Ranges;
11034 // Current range.
11035 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
11036 // StartPt points to the first place where all unsafe registers
11037 // are dead (if there is any such point). Begin partitioning the MBB into
11038 // ranges.
11039 for (auto &MI : make_range(FirstPossibleEndPt, MBB.instr_rend())) {
11040 if (!MI.isDebugInstr())
11041 LRU.stepBackward(MI);
11042 UpdateWholeMBBFlags(MI);
11043 if (!AreAllUnsafeRegsDead()) {
11044 SaveRangeIfNonEmpty();
11045 CreateNewRangeStartingAt(MI.getIterator());
11046 continue;
11047 }
11048 LRAvailableEverywhere &= LRU.available(AArch64::LR);
11049 // RangeBegin may point at a debug instruction because the mapper ignores
11050 // debug instructions wherever they appear. Only count non-debug
11051 // instructions so debug info cannot make a short range outlinable.
11052 RangeBegin = MI.getIterator();
11053 if (!MI.isDebugInstr())
11054 ++RangeLen;
11055 }
11056 // Above loop misses the last (or only) range. If we are still safe, then
11057 // let's save the range.
11058 if (AreAllUnsafeRegsDead())
11059 SaveRangeIfNonEmpty();
11060 if (Ranges.empty())
11061 return Ranges;
11062 // We found the ranges bottom-up. Mapping expects the top-down. Reverse
11063 // the order.
11064 std::reverse(Ranges.begin(), Ranges.end());
11065 // If there is at least one outlinable range where LR is unavailable
11066 // somewhere, remember that.
11067 if (!LRAvailableEverywhere)
11069 return Ranges;
11070}
11071
11073AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
11075 unsigned Flags) const {
11076 MachineInstr &MI = *MIT;
11077
11078 // Don't outline anything used for return address signing. The outlined
11079 // function will get signed later if needed
11080 switch (MI.getOpcode()) {
11081 case AArch64::PACM:
11082 case AArch64::PACIASP:
11083 case AArch64::PACIBSP:
11084 case AArch64::PACIASPPC:
11085 case AArch64::PACIBSPPC:
11086 case AArch64::AUTIASP:
11087 case AArch64::AUTIBSP:
11088 case AArch64::AUTIASPPCi:
11089 case AArch64::AUTIASPPCr:
11090 case AArch64::AUTIBSPPCi:
11091 case AArch64::AUTIBSPPCr:
11092 case AArch64::RETAA:
11093 case AArch64::RETAB:
11094 case AArch64::RETAASPPCi:
11095 case AArch64::RETAASPPCr:
11096 case AArch64::RETABSPPCi:
11097 case AArch64::RETABSPPCr:
11098 case AArch64::EMITBKEY:
11099 case AArch64::PAUTH_PROLOGUE:
11100 case AArch64::PAUTH_EPILOGUE:
11102 }
11103
11104 // We can only outline these if we will tail call the outlined function, or
11105 // fix up the CFI offsets. Currently, CFI instructions are outlined only if
11106 // in a tail call.
11107 //
11108 // FIXME: If the proper fixups for the offset are implemented, this should be
11109 // possible.
11110 if (MI.isCFIInstruction())
11112
11113 // Is this a terminator for a basic block?
11114 if (MI.isTerminator())
11115 // TargetInstrInfo::getOutliningType has already filtered out anything
11116 // that would break this, so we can allow it here.
11118
11119 // Make sure none of the operands are un-outlinable.
11120 for (const MachineOperand &MOP : MI.operands()) {
11121 // A check preventing CFI indices was here before, but only CFI
11122 // instructions should have those.
11123 assert(!MOP.isCFIIndex());
11124
11125 // If it uses LR or W30 explicitly, then don't touch it.
11126 if (MOP.isReg() && !MOP.isImplicit() &&
11127 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
11129 }
11130
11131 // Special cases for instructions that can always be outlined, but will fail
11132 // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
11133 // be outlined because they don't require a *specific* value to be in LR.
11134 if (MI.getOpcode() == AArch64::ADRP)
11136
11137 // If MI is a call we might be able to outline it. We don't want to outline
11138 // any calls that rely on the position of items on the stack. When we outline
11139 // something containing a call, we have to emit a save and restore of LR in
11140 // the outlined function. Currently, this always happens by saving LR to the
11141 // stack. Thus, if we outline, say, half the parameters for a function call
11142 // plus the call, then we'll break the callee's expectations for the layout
11143 // of the stack.
11144 //
11145 // FIXME: Allow calls to functions which construct a stack frame, as long
11146 // as they don't access arguments on the stack.
11147 // FIXME: Figure out some way to analyze functions defined in other modules.
11148 // We should be able to compute the memory usage based on the IR calling
11149 // convention, even if we can't see the definition.
11150 if (MI.isCall()) {
11151 // Get the function associated with the call. Look at each operand and find
11152 // the one that represents the callee and get its name.
11153 const Function *Callee = nullptr;
11154 for (const MachineOperand &MOP : MI.operands()) {
11155 if (MOP.isGlobal()) {
11156 Callee = dyn_cast<Function>(MOP.getGlobal());
11157 break;
11158 }
11159 }
11160
11161 // Never outline calls to mcount. There isn't any rule that would require
11162 // this, but the Linux kernel's "ftrace" feature depends on it.
11163 if (Callee && Callee->getName() == "\01_mcount")
11165
11166 // If we don't know anything about the callee, assume it depends on the
11167 // stack layout of the caller. In that case, it's only legal to outline
11168 // as a tail-call. Explicitly list the call instructions we know about so we
11169 // don't get unexpected results with call pseudo-instructions.
11170 auto UnknownCallOutlineType = outliner::InstrType::Illegal;
11171 if (MI.getOpcode() == AArch64::BLR ||
11172 MI.getOpcode() == AArch64::BLRNoIP || MI.getOpcode() == AArch64::BL)
11173 UnknownCallOutlineType = outliner::InstrType::LegalTerminator;
11174
11175 if (!Callee)
11176 return UnknownCallOutlineType;
11177
11178 // We have a function we have information about. Check it if it's something
11179 // can safely outline.
11180 MachineFunction *CalleeMF = MMI.getMachineFunction(*Callee);
11181
11182 // We don't know what's going on with the callee at all. Don't touch it.
11183 if (!CalleeMF)
11184 return UnknownCallOutlineType;
11185
11186 // Check if we know anything about the callee saves on the function. If we
11187 // don't, then don't touch it, since that implies that we haven't
11188 // computed anything about its stack frame yet.
11189 MachineFrameInfo &MFI = CalleeMF->getFrameInfo();
11190 if (!MFI.isCalleeSavedInfoValid() || MFI.getStackSize() > 0 ||
11191 MFI.getNumObjects() > 0)
11192 return UnknownCallOutlineType;
11193
11194 // At this point, we can say that CalleeMF ought to not pass anything on the
11195 // stack. Therefore, we can outline it.
11197 }
11198
11199 // Don't touch the link register or W30.
11200 if (MI.readsRegister(AArch64::W30, &getRegisterInfo()) ||
11201 MI.modifiesRegister(AArch64::W30, &getRegisterInfo()))
11203
11204 // Don't outline BTI instructions, because that will prevent the outlining
11205 // site from being indirectly callable.
11206 if (hasBTISemantics(MI))
11208
11210}
11211
11212void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
11213 for (MachineInstr &MI : MBB) {
11214 const MachineOperand *Base;
11215 TypeSize Width(0, false);
11216 int64_t Offset;
11217 bool OffsetIsScalable;
11218
11219 // Is this a load or store with an immediate offset with SP as the base?
11220 if (!MI.mayLoadOrStore() ||
11221 !getMemOperandWithOffsetWidth(MI, Base, Offset, OffsetIsScalable, Width,
11222 &RI) ||
11223 (Base->isReg() && Base->getReg() != AArch64::SP))
11224 continue;
11225
11226 // It is, so we have to fix it up.
11227 TypeSize Scale(0U, false);
11228 int64_t Dummy1, Dummy2;
11229
11230 MachineOperand &StackOffsetOperand = getMemOpBaseRegImmOfsOffsetOperand(MI);
11231 assert(StackOffsetOperand.isImm() && "Stack offset wasn't immediate!");
11232 getMemOpInfo(MI.getOpcode(), Scale, Width, Dummy1, Dummy2);
11233 assert(Scale != 0 && "Unexpected opcode!");
11234 assert(!OffsetIsScalable && "Expected offset to be a byte offset");
11235
11236 // We've pushed the return address to the stack, so add 16 to the offset.
11237 // This is safe, since we already checked if it would overflow when we
11238 // checked if this instruction was legal to outline.
11239 int64_t NewImm = (Offset + 16) / (int64_t)Scale.getFixedValue();
11240 StackOffsetOperand.setImm(NewImm);
11241 }
11242}
11243
11245 const AArch64InstrInfo *TII,
11246 bool ShouldSignReturnAddr) {
11247 if (!ShouldSignReturnAddr)
11248 return;
11249
11250 BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(AArch64::PAUTH_PROLOGUE))
11252 TII->createPauthEpilogueInstr(MBB, DebugLoc());
11253}
11254
11255void AArch64InstrInfo::buildOutlinedFrame(
11257 const outliner::OutlinedFunction &OF) const {
11258
11259 AArch64FunctionInfo *FI = MF.getInfo<AArch64FunctionInfo>();
11260
11261 if (OF.FrameConstructionID == MachineOutlinerTailCall)
11262 FI->setOutliningStyle("Tail Call");
11263 else if (OF.FrameConstructionID == MachineOutlinerThunk) {
11264 // For thunk outlining, rewrite the last instruction from a call to a
11265 // tail-call.
11266 MachineInstr *Call = &*--MBB.instr_end();
11267 unsigned TailOpcode;
11268 if (Call->getOpcode() == AArch64::BL) {
11269 TailOpcode = AArch64::TCRETURNdi;
11270 } else {
11271 assert(Call->getOpcode() == AArch64::BLR ||
11272 Call->getOpcode() == AArch64::BLRNoIP);
11273 TailOpcode = AArch64::TCRETURNriALL;
11274 }
11275 MachineInstr *TC = BuildMI(MF, DebugLoc(), get(TailOpcode))
11276 .add(Call->getOperand(0))
11277 .addImm(0);
11278 MBB.insert(MBB.end(), TC);
11280
11281 FI->setOutliningStyle("Thunk");
11282 }
11283
11284 bool IsLeafFunction = true;
11285
11286 // Is there a call in the outlined range?
11287 auto IsNonTailCall = [](const MachineInstr &MI) {
11288 return MI.isCall() && !MI.isReturn();
11289 };
11290
11291 if (llvm::any_of(MBB.instrs(), IsNonTailCall)) {
11292 // Fix up the instructions in the range, since we're going to modify the
11293 // stack.
11294
11295 // Bugzilla ID: 46767
11296 // TODO: Check if fixing up twice is safe so we can outline these.
11297 assert(OF.FrameConstructionID != MachineOutlinerDefault &&
11298 "Can only fix up stack references once");
11299 fixupPostOutline(MBB);
11300
11301 IsLeafFunction = false;
11302
11303 // LR has to be a live in so that we can save it.
11304 if (!MBB.isLiveIn(AArch64::LR))
11305 MBB.addLiveIn(AArch64::LR);
11306
11309
11310 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11311 OF.FrameConstructionID == MachineOutlinerThunk)
11312 Et = std::prev(MBB.end());
11313
11314 // There is a call in the range, so we must save LR. Save it as part of a
11315 // frame record when that gives us a smaller compact unwind encoding.
11317 // FP is saved here, so it must be live-in.
11318 if (!MBB.isLiveIn(AArch64::FP))
11319 MBB.addLiveIn(AArch64::FP);
11320
11321 // stp x29, x30, [sp, #-16]! (the pre-index imm is scaled by 8: -2 * 8)
11322 MachineInstr *STPXpre = BuildMI(MF, DebugLoc(), get(AArch64::STPXpre))
11323 .addReg(AArch64::SP, RegState::Define)
11324 .addReg(AArch64::FP)
11325 .addReg(AArch64::LR)
11326 .addReg(AArch64::SP)
11327 .addImm(-2);
11328 It = MBB.insert(It, STPXpre);
11329
11330 // mov x29, sp (add x29, sp, #0), so x29 points at the frame record.
11331 MachineInstr *SetFP = BuildMI(MF, DebugLoc(), get(AArch64::ADDXri))
11332 .addReg(AArch64::FP, RegState::Define)
11333 .addReg(AArch64::SP)
11334 .addImm(0)
11335 .addImm(0);
11336 MBB.insertAfter(It, SetFP);
11337
11338 // Describe the frame record with FP as the CFA. The encoder needs all
11339 // three to pick FRAME. No need to check for unwind info here: we only
11340 // get here if the function has it.
11341 CFIInstBuilder CFIBuilder(MBB, std::next(SetFP->getIterator()),
11343 CFIBuilder.buildDefCFA(AArch64::FP, 16);
11344 CFIBuilder.buildOffset(AArch64::LR, -8);
11345 CFIBuilder.buildOffset(AArch64::FP, -16);
11346
11347 // ldp x29, x30, [sp], #16
11348 MachineInstr *LDPXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDPXpost))
11349 .addReg(AArch64::SP, RegState::Define)
11350 .addReg(AArch64::FP, RegState::Define)
11351 .addReg(AArch64::LR, RegState::Define)
11352 .addReg(AArch64::SP)
11353 .addImm(2);
11354 Et = MBB.insert(Et, LDPXpost);
11355 } else {
11356 // Insert a save before the outlined region
11357 MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11358 .addReg(AArch64::SP, RegState::Define)
11359 .addReg(AArch64::LR)
11360 .addReg(AArch64::SP)
11361 .addImm(-16);
11362 It = MBB.insert(It, STRXpre);
11363
11364 if (MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11365 CFIInstBuilder CFIBuilder(MBB, It, MachineInstr::FrameSetup);
11366
11367 // Add a CFI saying the stack was moved 16 B down.
11368 CFIBuilder.buildDefCFAOffset(16);
11369
11370 // Add a CFI saying that the LR that we want to find is now 16 B higher
11371 // than before.
11372 CFIBuilder.buildOffset(AArch64::LR, -16);
11373 }
11374
11375 // Insert a restore before the terminator for the function.
11376 MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11377 .addReg(AArch64::SP, RegState::Define)
11378 .addReg(AArch64::LR, RegState::Define)
11379 .addReg(AArch64::SP)
11380 .addImm(16);
11381 Et = MBB.insert(Et, LDRXpost);
11382 }
11383 }
11384
11385 auto RASignCondition = FI->getSignReturnAddressCondition();
11386 bool ShouldSignReturnAddr = AArch64FunctionInfo::shouldSignReturnAddress(
11387 RASignCondition, !IsLeafFunction);
11388
11389 // If this is a tail call outlined function, then there's already a return.
11390 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11391 OF.FrameConstructionID == MachineOutlinerThunk) {
11392 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11393 return;
11394 }
11395
11396 // It's not a tail call, so we have to insert the return ourselves.
11397
11398 // LR has to be a live in so that we can return to it.
11399 if (!MBB.isLiveIn(AArch64::LR))
11400 MBB.addLiveIn(AArch64::LR);
11401
11402 MachineInstr *ret = BuildMI(MF, DebugLoc(), get(AArch64::RET))
11403 .addReg(AArch64::LR);
11404 MBB.insert(MBB.end(), ret);
11405
11406 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11407
11408 FI->setOutliningStyle("Function");
11409
11410 // Did we have to modify the stack by saving the link register?
11411 if (OF.FrameConstructionID != MachineOutlinerDefault)
11412 return;
11413
11414 // We modified the stack.
11415 // Walk over the basic block and fix up all the stack accesses.
11416 fixupPostOutline(MBB);
11417}
11418
11419MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall(
11422
11423 // Are we tail calling?
11424 if (C.CallConstructionID == MachineOutlinerTailCall) {
11425 // If yes, then we can just branch to the label.
11426 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::TCRETURNdi))
11427 .addGlobalAddress(M.getNamedValue(MF.getName()))
11428 .addImm(0));
11429 return It;
11430 }
11431
11432 // Are we saving the link register?
11433 if (C.CallConstructionID == MachineOutlinerNoLRSave ||
11434 C.CallConstructionID == MachineOutlinerThunk) {
11435 // No, so just insert the call.
11436 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11437 .addGlobalAddress(M.getNamedValue(MF.getName())));
11438 return It;
11439 }
11440
11441 // We want to return the spot where we inserted the call.
11443
11444 // Instructions for saving and restoring LR around the call instruction we're
11445 // going to insert.
11446 MachineInstr *Save;
11447 MachineInstr *Restore;
11448 // Can we save to a register?
11449 if (C.CallConstructionID == MachineOutlinerRegSave) {
11450 // FIXME: This logic should be sunk into a target-specific interface so that
11451 // we don't have to recompute the register.
11452 Register Reg = findRegisterToSaveLRTo(C);
11453 assert(Reg && "No callee-saved register available?");
11454
11455 // LR has to be a live in so that we can save it.
11456 if (!MBB.isLiveIn(AArch64::LR))
11457 MBB.addLiveIn(AArch64::LR);
11458
11459 // Save and restore LR from Reg.
11460 Save = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), Reg)
11461 .addReg(AArch64::XZR)
11462 .addReg(AArch64::LR)
11463 .addImm(0);
11464 Restore = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), AArch64::LR)
11465 .addReg(AArch64::XZR)
11466 .addReg(Reg)
11467 .addImm(0);
11468 } else {
11469 // We have the default case. Save and restore from SP.
11470 Save = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11471 .addReg(AArch64::SP, RegState::Define)
11472 .addReg(AArch64::LR)
11473 .addReg(AArch64::SP)
11474 .addImm(-16);
11475 Restore = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11476 .addReg(AArch64::SP, RegState::Define)
11477 .addReg(AArch64::LR, RegState::Define)
11478 .addReg(AArch64::SP)
11479 .addImm(16);
11480 }
11481
11482 It = MBB.insert(It, Save);
11483 It++;
11484
11485 // Insert the call.
11486 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11487 .addGlobalAddress(M.getNamedValue(MF.getName())));
11488 CallPt = It;
11489 It++;
11490
11491 It = MBB.insert(It, Restore);
11492 return CallPt;
11493}
11494
11495bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11496 MachineFunction &MF) const {
11497 return MF.getFunction().hasMinSize();
11498}
11499
11500void AArch64InstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
11502 DebugLoc &DL,
11503 bool AllowSideEffects) const {
11504 const MachineFunction &MF = *MBB.getParent();
11505 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
11506 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
11507
11508 if (TRI.isGeneralPurposeRegister(MF, Reg)) {
11509 BuildMI(MBB, Iter, DL, get(AArch64::MOVZXi), Reg).addImm(0).addImm(0);
11510 } else if (STI.isSVEorStreamingSVEAvailable()) {
11511 BuildMI(MBB, Iter, DL, get(AArch64::DUP_ZI_D), Reg)
11512 .addImm(0)
11513 .addImm(0);
11514 } else if (STI.isNeonAvailable()) {
11515 BuildMI(MBB, Iter, DL, get(AArch64::MOVIv2d_ns), Reg)
11516 .addImm(0);
11517 } else {
11518 // No Advanced SIMD (streaming-compatible without SVE, or +nosimd), so use
11519 // `fmov d...` instead of `movi v...`; writing `d` also clears the upper
11520 // 64 bits.
11521 assert(STI.hasFPARMv8() && "Expected FP to be available.");
11522 Register Reg64 = TRI.getSubReg(Reg, AArch64::dsub);
11523 BuildMI(MBB, Iter, DL, get(AArch64::FMOVD0), Reg64);
11524 }
11525}
11526
11527std::optional<DestSourcePair>
11529
11530 // AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg
11531 // and zero immediate operands used as an alias for mov instruction.
11532 if ((MI.getOpcode() == AArch64::ORRWrs &&
11533 MI.getOperand(1).getReg() == AArch64::WZR &&
11534 MI.getOperand(3).getImm() == 0x0) ||
11535 (MI.getOpcode() == AArch64::ORRWrr &&
11536 MI.getOperand(1).getReg() == AArch64::WZR)) {
11537 // Check that the w->w move is not a zero-extending w->x mov.
11538 if ((MI.getOperand(0).getReg().isPhysical() &&
11539 MI.findRegisterDefOperandIdx(
11540 getXRegFromWReg(MI.getOperand(0).getReg()),
11541 /*TRI=*/nullptr) == -1) ||
11542 (MI.getOperand(0).getReg().isVirtual() &&
11543 !MI.getOperand(0).getSubReg()))
11544 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11545 }
11546
11547 if (MI.getOpcode() == AArch64::ORRXrs &&
11548 MI.getOperand(1).getReg() == AArch64::XZR &&
11549 MI.getOperand(3).getImm() == 0x0)
11550 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11551
11552 return std::nullopt;
11553}
11554
11555std::optional<DestSourcePair>
11557 if ((MI.getOpcode() == AArch64::ORRWrs &&
11558 MI.getOperand(1).getReg() == AArch64::WZR &&
11559 MI.getOperand(3).getImm() == 0x0) ||
11560 (MI.getOpcode() == AArch64::ORRWrr &&
11561 MI.getOperand(1).getReg() == AArch64::WZR))
11562 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11563 return std::nullopt;
11564}
11565
11566std::optional<RegImmPair>
11567AArch64InstrInfo::isAddImmediate(const MachineInstr &MI, Register Reg) const {
11568 int Sign = 1;
11569 int64_t Offset = 0;
11570
11571 // TODO: Handle cases where Reg is a super- or sub-register of the
11572 // destination register.
11573 const MachineOperand &Op0 = MI.getOperand(0);
11574 if (!Op0.isReg() || Reg != Op0.getReg())
11575 return std::nullopt;
11576
11577 switch (MI.getOpcode()) {
11578 default:
11579 return std::nullopt;
11580 case AArch64::SUBWri:
11581 case AArch64::SUBXri:
11582 case AArch64::SUBSWri:
11583 case AArch64::SUBSXri:
11584 Sign *= -1;
11585 [[fallthrough]];
11586 case AArch64::ADDSWri:
11587 case AArch64::ADDSXri:
11588 case AArch64::ADDWri:
11589 case AArch64::ADDXri: {
11590 // TODO: Third operand can be global address (usually some string).
11591 if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
11592 !MI.getOperand(2).isImm())
11593 return std::nullopt;
11594 int Shift = MI.getOperand(3).getImm();
11595 assert((Shift == 0 || Shift == 12) && "Shift can be either 0 or 12");
11596 Offset = Sign * (MI.getOperand(2).getImm() << Shift);
11597 }
11598 }
11599 return RegImmPair{MI.getOperand(1).getReg(), Offset};
11600}
11601
11602/// If the given ORR instruction is a copy, and \p DescribedReg overlaps with
11603/// the destination register then, if possible, describe the value in terms of
11604/// the source register.
11605static std::optional<ParamLoadedValue>
11607 const TargetInstrInfo *TII,
11608 const TargetRegisterInfo *TRI) {
11609 auto DestSrc = TII->isCopyLikeInstr(MI);
11610 if (!DestSrc)
11611 return std::nullopt;
11612
11613 Register DestReg = DestSrc->Destination->getReg();
11614 Register SrcReg = DestSrc->Source->getReg();
11615
11616 if (!DestReg.isValid() || !SrcReg.isValid())
11617 return std::nullopt;
11618
11619 auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
11620
11621 // If the described register is the destination, just return the source.
11622 if (DestReg == DescribedReg)
11623 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11624
11625 // ORRWrs zero-extends to 64-bits, so we need to consider such cases.
11626 if (MI.getOpcode() == AArch64::ORRWrs &&
11627 TRI->isSuperRegister(DestReg, DescribedReg))
11628 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11629
11630 // We may need to describe the lower part of a ORRXrs move.
11631 if (MI.getOpcode() == AArch64::ORRXrs &&
11632 TRI->isSubRegister(DestReg, DescribedReg)) {
11633 Register SrcSubReg = TRI->getSubReg(SrcReg, AArch64::sub_32);
11634 return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
11635 }
11636
11637 assert(!TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11638 "Unhandled ORR[XW]rs copy case");
11639
11640 return std::nullopt;
11641}
11642
11643bool AArch64InstrInfo::isFunctionSafeToSplit(const MachineFunction &MF) const {
11644 // Functions cannot be split to different sections on AArch64 if they have
11645 // a red zone. This is because relaxing a cross-section branch may require
11646 // incrementing the stack pointer to spill a register, which would overwrite
11647 // the red zone.
11648 if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(true))
11649 return false;
11650
11652}
11653
11654bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11655 const MachineBasicBlock &MBB) const {
11656 // Asm Goto blocks can contain conditional branches to goto labels, which can
11657 // get moved out of range of the branch instruction.
11658 auto isAsmGoto = [](const MachineInstr &MI) {
11659 return MI.getOpcode() == AArch64::INLINEASM_BR;
11660 };
11661 if (llvm::any_of(MBB, isAsmGoto) || MBB.isInlineAsmBrIndirectTarget())
11662 return false;
11663
11664 // Because jump tables are label-relative instead of table-relative, they all
11665 // must be in the same section or relocation fixup handling will fail.
11666
11667 // Check if MBB is a jump table target
11668 const MachineJumpTableInfo *MJTI = MBB.getParent()->getJumpTableInfo();
11669 auto containsMBB = [&MBB](const MachineJumpTableEntry &JTE) {
11670 return llvm::is_contained(JTE.MBBs, &MBB);
11671 };
11672 if (MJTI != nullptr && llvm::any_of(MJTI->getJumpTables(), containsMBB))
11673 return false;
11674
11675 // Check if MBB contains a jump table lookup
11676 for (const MachineInstr &MI : MBB) {
11677 switch (MI.getOpcode()) {
11678 case TargetOpcode::G_BRJT:
11679 case AArch64::JumpTableDest32:
11680 case AArch64::JumpTableDest16:
11681 case AArch64::JumpTableDest8:
11682 return false;
11683 default:
11684 continue;
11685 }
11686 }
11687
11688 // MBB isn't a special case, so it's safe to be split to the cold section.
11689 return true;
11690}
11691
11692std::optional<ParamLoadedValue>
11693AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
11694 Register Reg) const {
11695 const MachineFunction *MF = MI.getMF();
11696 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
11697 switch (MI.getOpcode()) {
11698 case AArch64::MOVZWi:
11699 case AArch64::MOVZXi: {
11700 // MOVZWi may be used for producing zero-extended 32-bit immediates in
11701 // 64-bit parameters, so we need to consider super-registers.
11702 if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
11703 return std::nullopt;
11704
11705 if (!MI.getOperand(1).isImm())
11706 return std::nullopt;
11707 int64_t Immediate = MI.getOperand(1).getImm();
11708 int Shift = MI.getOperand(2).getImm();
11709 return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
11710 nullptr);
11711 }
11712 case AArch64::ORRWrs:
11713 case AArch64::ORRXrs:
11714 return describeORRLoadedValue(MI, Reg, this, TRI);
11715 }
11716
11718}
11719
11720bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11721 MachineInstr &ExtMI, MachineRegisterInfo &MRI) const {
11722 assert(ExtMI.getOpcode() == TargetOpcode::G_SEXT ||
11723 ExtMI.getOpcode() == TargetOpcode::G_ZEXT ||
11724 ExtMI.getOpcode() == TargetOpcode::G_ANYEXT);
11725
11726 // Anyexts are nops.
11727 if (ExtMI.getOpcode() == TargetOpcode::G_ANYEXT)
11728 return true;
11729
11730 Register DefReg = ExtMI.getOperand(0).getReg();
11731 if (!MRI.hasOneNonDBGUse(DefReg))
11732 return false;
11733
11734 // It's likely that a sext/zext as a G_PTR_ADD offset will be folded into an
11735 // addressing mode.
11736 auto *UserMI = &*MRI.use_instr_nodbg_begin(DefReg);
11737 return UserMI->getOpcode() == TargetOpcode::G_PTR_ADD;
11738}
11739
11740uint64_t AArch64InstrInfo::getElementSizeForOpcode(unsigned Opc) const {
11741 return get(Opc).TSFlags & AArch64::ElementSizeMask;
11742}
11743
11744bool AArch64InstrInfo::isPTestLikeOpcode(unsigned Opc) const {
11745 return get(Opc).TSFlags & AArch64::InstrFlagIsPTestLike;
11746}
11747
11748bool AArch64InstrInfo::isWhileOpcode(unsigned Opc) const {
11749 return get(Opc).TSFlags & AArch64::InstrFlagIsWhile;
11750}
11751
11752unsigned int
11753AArch64InstrInfo::getTailDuplicateSize(CodeGenOptLevel OptLevel) const {
11754 return OptLevel >= CodeGenOptLevel::Aggressive ? 6 : 2;
11755}
11756
11757bool AArch64InstrInfo::isLegalAddressingMode(unsigned NumBytes, int64_t Offset,
11758 unsigned Scale) const {
11759 if (Offset && Scale)
11760 return false;
11761
11762 // Check Reg + Imm
11763 if (!Scale) {
11764 // 9-bit signed offset
11765 if (isInt<9>(Offset))
11766 return true;
11767
11768 // 12-bit unsigned offset
11769 unsigned Shift = Log2_64(NumBytes);
11770 if (NumBytes && Offset > 0 && (Offset / NumBytes) <= (1LL << 12) - 1 &&
11771 // Must be a multiple of NumBytes (NumBytes is a power of 2)
11772 (Offset >> Shift) << Shift == Offset)
11773 return true;
11774 return false;
11775 }
11776
11777 // Check reg1 + SIZE_IN_BYTES * reg2 and reg1 + reg2
11778 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11779}
11780
11782 if (MF.getSubtarget<AArch64Subtarget>().hardenSlsBlr())
11783 return AArch64::BLRNoIP;
11784 else
11785 return AArch64::BLR;
11786}
11787
11789 DebugLoc DL) const {
11790 MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
11791 auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
11793
11794 MachineFunction &MF = *MBB.getParent();
11795 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
11796 auto &AFL = *static_cast<const AArch64FrameLowering *>(
11797 MF.getSubtarget().getFrameLowering());
11798 if (AFL.getArgumentStackToRestore(MF, MBB)) {
11799 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
11800 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11801 if (AFI->branchProtectionPAuthLR())
11802 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
11803 return;
11804 }
11805
11806 if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
11807 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11808}
11809
11811AArch64InstrInfo::probedStackAlloc(MachineBasicBlock::iterator MBBI,
11812 Register TargetReg, bool FrameSetup) const {
11813 assert(TargetReg != AArch64::SP && "New top of stack cannot already be in SP");
11814
11815 MachineBasicBlock &MBB = *MBBI->getParent();
11816 MachineFunction &MF = *MBB.getParent();
11817 const AArch64InstrInfo *TII =
11818 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
11819 int64_t ProbeSize = MF.getInfo<AArch64FunctionInfo>()->getStackProbeSize();
11820 DebugLoc DL = MBB.findDebugLoc(MBBI);
11821
11822 MachineFunction::iterator MBBInsertPoint = std::next(MBB.getIterator());
11823 MachineBasicBlock *LoopTestMBB =
11824 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11825 MF.insert(MBBInsertPoint, LoopTestMBB);
11826 MachineBasicBlock *LoopBodyMBB =
11827 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11828 MF.insert(MBBInsertPoint, LoopBodyMBB);
11829 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11830 MF.insert(MBBInsertPoint, ExitMBB);
11831 MachineInstr::MIFlag Flags =
11833
11834 // LoopTest:
11835 // SUB SP, SP, #ProbeSize
11836 emitFrameOffset(*LoopTestMBB, LoopTestMBB->end(), DL, AArch64::SP,
11837 AArch64::SP, StackOffset::getFixed(-ProbeSize), TII, Flags);
11838
11839 // CMP SP, TargetReg
11840 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::SUBSXrx64),
11841 AArch64::XZR)
11842 .addReg(AArch64::SP)
11843 .addReg(TargetReg)
11845 .setMIFlags(Flags);
11846
11847 // B.<Cond> LoopExit
11848 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::Bcc))
11850 .addMBB(ExitMBB)
11851 .setMIFlags(Flags);
11852
11853 // LDR XZR, [SP]
11854 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::LDRXui))
11855 .addDef(AArch64::XZR)
11856 .addReg(AArch64::SP)
11857 .addImm(0)
11861 Align(8)))
11862 .setMIFlags(Flags);
11863
11864 // B loop
11865 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::B))
11866 .addMBB(LoopTestMBB)
11867 .setMIFlags(Flags);
11868
11869 // LoopExit:
11870 // MOV SP, TargetReg
11871 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::ADDXri), AArch64::SP)
11872 .addReg(TargetReg)
11873 .addImm(0)
11875 .setMIFlags(Flags);
11876
11877 // LDR XZR, [SP]
11878 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::LDRXui))
11879 .addReg(AArch64::XZR, RegState::Define)
11880 .addReg(AArch64::SP)
11881 .addImm(0)
11882 .setMIFlags(Flags);
11883
11884 ExitMBB->splice(ExitMBB->end(), &MBB, std::next(MBBI), MBB.end());
11886
11887 LoopTestMBB->addSuccessor(ExitMBB);
11888 LoopTestMBB->addSuccessor(LoopBodyMBB);
11889 LoopBodyMBB->addSuccessor(LoopTestMBB);
11890 MBB.addSuccessor(LoopTestMBB);
11891
11892 // Update liveins.
11893 if (MF.getRegInfo().reservedRegsFrozen())
11894 fullyRecomputeLiveIns({ExitMBB, LoopBodyMBB, LoopTestMBB});
11895
11896 return ExitMBB->begin();
11897}
11898
11899namespace {
11900class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
11901 MachineFunction *MF;
11902 const TargetInstrInfo *TII;
11903 const TargetRegisterInfo *TRI;
11904 MachineRegisterInfo &MRI;
11905
11906 /// The block of the loop
11907 MachineBasicBlock *LoopBB;
11908 /// The conditional branch of the loop
11909 MachineInstr *CondBranch;
11910 /// The compare instruction for loop control
11911 MachineInstr *Comp;
11912 /// The number of the operand of the loop counter value in Comp
11913 unsigned CompCounterOprNum;
11914 /// The instruction that updates the loop counter value
11915 MachineInstr *Update;
11916 /// The number of the operand of the loop counter value in Update
11917 unsigned UpdateCounterOprNum;
11918 /// The initial value of the loop counter
11919 Register Init;
11920 /// True iff Update is a predecessor of Comp
11921 bool IsUpdatePriorComp;
11922
11923 /// The normalized condition used by createTripCountGreaterCondition()
11924 SmallVector<MachineOperand, 4> Cond;
11925
11926public:
11927 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11928 MachineInstr *Comp, unsigned CompCounterOprNum,
11929 MachineInstr *Update, unsigned UpdateCounterOprNum,
11930 Register Init, bool IsUpdatePriorComp,
11931 const SmallVectorImpl<MachineOperand> &Cond)
11932 : MF(Comp->getParent()->getParent()),
11933 TII(MF->getSubtarget().getInstrInfo()),
11934 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11935 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11936 CompCounterOprNum(CompCounterOprNum), Update(Update),
11937 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11938 IsUpdatePriorComp(IsUpdatePriorComp), Cond(Cond.begin(), Cond.end()) {}
11939
11940 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
11941 // Make the instructions for loop control be placed in stage 0.
11942 // The predecessors of Comp are considered by the caller.
11943 return MI == Comp;
11944 }
11945
11946 std::optional<bool> createTripCountGreaterCondition(
11947 int TC, MachineBasicBlock &MBB,
11948 SmallVectorImpl<MachineOperand> &CondParam) override {
11949 // A branch instruction will be inserted as "if (Cond) goto epilogue".
11950 // Cond is normalized for such use.
11951 // The predecessors of the branch are assumed to have already been inserted.
11952 CondParam = Cond;
11953 return {};
11954 }
11955
11956 void createRemainingIterationsGreaterCondition(
11957 int TC, MachineBasicBlock &MBB, SmallVectorImpl<MachineOperand> &Cond,
11958 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts) override;
11959
11960 void setPreheader(MachineBasicBlock *NewPreheader) override {}
11961
11962 void adjustTripCount(int TripCountAdjust) override {}
11963
11964 bool isMVEExpanderSupported() override { return true; }
11965};
11966} // namespace
11967
11968/// Clone an instruction from MI. The register of ReplaceOprNum-th operand
11969/// is replaced by ReplaceReg. The output register is newly created.
11970/// The other operands are unchanged from MI.
11971static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum,
11972 Register ReplaceReg, MachineBasicBlock &MBB,
11973 MachineBasicBlock::iterator InsertTo) {
11974 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
11975 const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
11976 MachineInstr *NewMI = MBB.getParent()->CloneMachineInstr(MI);
11977 Register Result = 0;
11978 for (unsigned I = 0; I < NewMI->getNumOperands(); ++I) {
11979 if (I == 0 && NewMI->getOperand(0).getReg().isVirtual()) {
11980 Result = MRI.createVirtualRegister(
11981 MRI.getRegClass(NewMI->getOperand(0).getReg()));
11982 NewMI->getOperand(I).setReg(Result);
11983 } else if (I == ReplaceOprNum) {
11984 MRI.constrainRegClass(ReplaceReg, TII->getRegClass(NewMI->getDesc(), I));
11985 NewMI->getOperand(I).setReg(ReplaceReg);
11986 }
11987 }
11988 MBB.insert(InsertTo, NewMI);
11989 return Result;
11990}
11991
11992void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
11995 // Create and accumulate conditions for next TC iterations.
11996 // Example:
11997 // SUBSXrr N, counter, implicit-def $nzcv # compare instruction for the last
11998 // # iteration of the kernel
11999 //
12000 // # insert the following instructions
12001 // cond = CSINCXr 0, 0, C, implicit $nzcv
12002 // counter = ADDXri counter, 1 # clone from this->Update
12003 // SUBSXrr n, counter, implicit-def $nzcv # clone from this->Comp
12004 // cond = CSINCXr cond, cond, C, implicit $nzcv
12005 // ... (repeat TC times)
12006 // SUBSXri cond, 0, implicit-def $nzcv
12007
12008 assert(CondBranch->getOpcode() == AArch64::Bcc);
12009 // CondCode to exit the loop
12011 (AArch64CC::CondCode)CondBranch->getOperand(0).getImm();
12012 if (CondBranch->getOperand(1).getMBB() == LoopBB)
12014
12015 // Accumulate conditions to exit the loop
12016 Register AccCond = AArch64::XZR;
12017
12018 // If CC holds, CurCond+1 is returned; otherwise CurCond is returned.
12019 auto AccumulateCond = [&](Register CurCond,
12021 Register NewCond = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
12022 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::CSINCXr))
12023 .addReg(NewCond, RegState::Define)
12024 .addReg(CurCond)
12025 .addReg(CurCond)
12027 return NewCond;
12028 };
12029
12030 if (!LastStage0Insts.empty() && LastStage0Insts[Comp]->getParent() == &MBB) {
12031 // Update and Comp for I==0 are already exists in MBB
12032 // (MBB is an unrolled kernel)
12033 Register Counter;
12034 for (int I = 0; I <= TC; ++I) {
12035 Register NextCounter;
12036 if (I != 0)
12037 NextCounter =
12038 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12039
12040 AccCond = AccumulateCond(AccCond, CC);
12041
12042 if (I != TC) {
12043 if (I == 0) {
12044 if (Update != Comp && IsUpdatePriorComp) {
12045 Counter =
12046 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12047 NextCounter = cloneInstr(Update, UpdateCounterOprNum, Counter, MBB,
12048 MBB.end());
12049 } else {
12050 // can use already calculated value
12051 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
12052 }
12053 } else if (Update != Comp) {
12054 NextCounter =
12055 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12056 }
12057 }
12058 Counter = NextCounter;
12059 }
12060 } else {
12061 Register Counter;
12062 if (LastStage0Insts.empty()) {
12063 // use initial counter value (testing if the trip count is sufficient to
12064 // be executed by pipelined code)
12065 Counter = Init;
12066 if (IsUpdatePriorComp)
12067 Counter =
12068 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12069 } else {
12070 // MBB is an epilogue block. LastStage0Insts[Comp] is in the kernel block.
12071 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12072 }
12073
12074 for (int I = 0; I <= TC; ++I) {
12075 Register NextCounter;
12076 NextCounter =
12077 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12078 AccCond = AccumulateCond(AccCond, CC);
12079 if (I != TC && Update != Comp)
12080 NextCounter =
12081 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12082 Counter = NextCounter;
12083 }
12084 }
12085
12086 // If AccCond == 0, the remainder is greater than TC.
12087 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::SUBSXri))
12088 .addReg(AArch64::XZR, RegState::Define | RegState::Dead)
12089 .addReg(AccCond)
12090 .addImm(0)
12091 .addImm(0);
12092 Cond.clear();
12094}
12095
12096static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB,
12097 Register &RegMBB, Register &RegOther) {
12098 assert(Phi.getNumOperands() == 5);
12099 if (Phi.getOperand(2).getMBB() == MBB) {
12100 RegMBB = Phi.getOperand(1).getReg();
12101 RegOther = Phi.getOperand(3).getReg();
12102 } else {
12103 assert(Phi.getOperand(4).getMBB() == MBB);
12104 RegMBB = Phi.getOperand(3).getReg();
12105 RegOther = Phi.getOperand(1).getReg();
12106 }
12107}
12108
12110 if (!Reg.isVirtual())
12111 return false;
12112 const MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
12113 return MRI.getDefBlock(Reg) != BB;
12114}
12115
12116/// If Reg is an induction variable, return true and set some parameters
12117static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB,
12118 MachineInstr *&UpdateInst,
12119 unsigned &UpdateCounterOprNum, Register &InitReg,
12120 bool &IsUpdatePriorComp) {
12121 // Example:
12122 //
12123 // Preheader:
12124 // InitReg = ...
12125 // LoopBB:
12126 // Reg0 = PHI (InitReg, Preheader), (Reg1, LoopBB)
12127 // Reg = COPY Reg0 ; COPY is ignored.
12128 // Reg1 = ADD Reg, #1; UpdateInst. Incremented by a loop invariant value.
12129 // ; Reg is the value calculated in the previous
12130 // ; iteration, so IsUpdatePriorComp == false.
12131
12132 if (LoopBB->pred_size() != 2)
12133 return false;
12134 if (!Reg.isVirtual())
12135 return false;
12136 const MachineRegisterInfo &MRI = LoopBB->getParent()->getRegInfo();
12137 UpdateInst = nullptr;
12138 UpdateCounterOprNum = 0;
12139 InitReg = 0;
12140 IsUpdatePriorComp = true;
12141 Register CurReg = Reg;
12142 while (true) {
12143 MachineInstr *Def = MRI.getVRegDef(CurReg);
12144 if (Def->getParent() != LoopBB)
12145 return false;
12146 if (Def->isCopy()) {
12147 // Ignore copy instructions unless they contain subregisters
12148 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
12149 return false;
12150 CurReg = Def->getOperand(1).getReg();
12151 } else if (Def->isPHI()) {
12152 if (InitReg != 0)
12153 return false;
12154 if (!UpdateInst)
12155 IsUpdatePriorComp = false;
12156 extractPhiReg(*Def, LoopBB, CurReg, InitReg);
12157 } else {
12158 if (UpdateInst)
12159 return false;
12160 switch (Def->getOpcode()) {
12161 case AArch64::ADDSXri:
12162 case AArch64::ADDSWri:
12163 case AArch64::SUBSXri:
12164 case AArch64::SUBSWri:
12165 case AArch64::ADDXri:
12166 case AArch64::ADDWri:
12167 case AArch64::SUBXri:
12168 case AArch64::SUBWri:
12169 UpdateInst = Def;
12170 UpdateCounterOprNum = 1;
12171 break;
12172 case AArch64::ADDSXrr:
12173 case AArch64::ADDSWrr:
12174 case AArch64::SUBSXrr:
12175 case AArch64::SUBSWrr:
12176 case AArch64::ADDXrr:
12177 case AArch64::ADDWrr:
12178 case AArch64::SUBXrr:
12179 case AArch64::SUBWrr:
12180 UpdateInst = Def;
12181 if (isDefinedOutside(Def->getOperand(2).getReg(), LoopBB))
12182 UpdateCounterOprNum = 1;
12183 else if (isDefinedOutside(Def->getOperand(1).getReg(), LoopBB))
12184 UpdateCounterOprNum = 2;
12185 else
12186 return false;
12187 break;
12188 default:
12189 return false;
12190 }
12191 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
12192 }
12193
12194 if (!CurReg.isVirtual())
12195 return false;
12196 if (Reg == CurReg)
12197 break;
12198 }
12199
12200 if (!UpdateInst)
12201 return false;
12202
12203 return true;
12204}
12205
12206std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
12208 // Accept loops that meet the following conditions
12209 // * The conditional branch is BCC
12210 // * The compare instruction is ADDS/SUBS/WHILEXX
12211 // * One operand of the compare is an induction variable and the other is a
12212 // loop invariant value
12213 // * The induction variable is incremented/decremented by a single instruction
12214 // * Does not contain CALL or instructions which have unmodeled side effects
12215
12216 for (MachineInstr &MI : *LoopBB)
12217 if (MI.isCall() || MI.hasUnmodeledSideEffects())
12218 // This instruction may use NZCV, which interferes with the instruction to
12219 // be inserted for loop control.
12220 return nullptr;
12221
12222 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
12224 if (analyzeBranch(*LoopBB, TBB, FBB, Cond))
12225 return nullptr;
12226
12227 // Infinite loops are not supported
12228 if (TBB == LoopBB && FBB == LoopBB)
12229 return nullptr;
12230
12231 // Must be conditional branch
12232 if (TBB != LoopBB && FBB == nullptr)
12233 return nullptr;
12234
12235 assert((TBB == LoopBB || FBB == LoopBB) &&
12236 "The Loop must be a single-basic-block loop");
12237
12238 MachineInstr *CondBranch = &*LoopBB->getFirstTerminator();
12240
12241 if (CondBranch->getOpcode() != AArch64::Bcc)
12242 return nullptr;
12243
12244 // Normalization for createTripCountGreaterCondition()
12245 if (TBB == LoopBB)
12247
12248 MachineInstr *Comp = nullptr;
12249 unsigned CompCounterOprNum = 0;
12250 for (MachineInstr &MI : reverse(*LoopBB)) {
12251 if (MI.modifiesRegister(AArch64::NZCV, &TRI)) {
12252 // Guarantee that the compare is SUBS/ADDS/WHILEXX and that one of the
12253 // operands is a loop invariant value
12254
12255 switch (MI.getOpcode()) {
12256 case AArch64::SUBSXri:
12257 case AArch64::SUBSWri:
12258 case AArch64::ADDSXri:
12259 case AArch64::ADDSWri:
12260 Comp = &MI;
12261 CompCounterOprNum = 1;
12262 break;
12263 case AArch64::ADDSWrr:
12264 case AArch64::ADDSXrr:
12265 case AArch64::SUBSWrr:
12266 case AArch64::SUBSXrr:
12267 Comp = &MI;
12268 break;
12269 default:
12270 if (isWhileOpcode(MI.getOpcode())) {
12271 Comp = &MI;
12272 break;
12273 }
12274 return nullptr;
12275 }
12276
12277 if (CompCounterOprNum == 0) {
12278 if (isDefinedOutside(Comp->getOperand(1).getReg(), LoopBB))
12279 CompCounterOprNum = 2;
12280 else if (isDefinedOutside(Comp->getOperand(2).getReg(), LoopBB))
12281 CompCounterOprNum = 1;
12282 else
12283 return nullptr;
12284 }
12285 break;
12286 }
12287 }
12288 if (!Comp)
12289 return nullptr;
12290
12291 MachineInstr *Update = nullptr;
12292 Register Init;
12293 bool IsUpdatePriorComp;
12294 unsigned UpdateCounterOprNum;
12295 if (!getIndVarInfo(Comp->getOperand(CompCounterOprNum).getReg(), LoopBB,
12296 Update, UpdateCounterOprNum, Init, IsUpdatePriorComp))
12297 return nullptr;
12298
12299 return std::make_unique<AArch64PipelinerLoopInfo>(
12300 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
12301 Init, IsUpdatePriorComp, Cond);
12302}
12303
12304/// verifyInstruction - Perform target specific instruction verification.
12305bool AArch64InstrInfo::verifyInstruction(const MachineInstr &MI,
12306 StringRef &ErrInfo) const {
12307 // Verify that immediate offsets on load/store instructions are within range.
12308 // Stack objects with an FI operand are excluded as they can be fixed up
12309 // during PEI.
12310 TypeSize Scale(0U, false), Width(0U, false);
12311 int64_t MinOffset, MaxOffset;
12312 if (getMemOpInfo(MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
12313 unsigned ImmIdx = getLoadStoreImmIdx(MI.getOpcode());
12314 if (MI.getOperand(ImmIdx).isImm() && !MI.getOperand(ImmIdx - 1).isFI()) {
12315 int64_t Imm = MI.getOperand(ImmIdx).getImm();
12316 if (Imm < MinOffset || Imm > MaxOffset) {
12317 ErrInfo = "Unexpected immediate on load/store instruction";
12318 return false;
12319 }
12320 }
12321 }
12322
12323 const MCInstrDesc &MCID = MI.getDesc();
12324 for (unsigned Op = 0; Op < MCID.getNumOperands(); Op++) {
12325 const MachineOperand &MO = MI.getOperand(Op);
12326 switch (MCID.operands()[Op].OperandType) {
12328 if (!MO.isImm() || MO.getImm() != 0) {
12329 ErrInfo = "OPERAND_IMPLICIT_IMM_0 should be 0";
12330 return false;
12331 }
12332 break;
12334 if (!MO.isImm() ||
12336 (AArch64_AM::getShiftValue(MO.getImm()) != 8 &&
12337 AArch64_AM::getShiftValue(MO.getImm()) != 16)) {
12338 ErrInfo = "OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
12339 return false;
12340 }
12341 break;
12343 if (!MO.isImm() || (MO.getImm() != 0 && MO.getImm() != 1)) {
12344 ErrInfo = "OPERAND_IMM_UINT1 should be 0 or 1";
12345 return false;
12346 }
12347 break;
12349 if (!MO.isImm() || MO.getImm() <= 0 || MO.getImm() > 16) {
12350 ErrInfo = "OPERAND_IMM_UINT4plus1 should be in the range 1 to 16";
12351 return false;
12352 }
12353 break;
12355 if (!MO.isImm() || !isUInt<5>(MO.getImm())) {
12356 ErrInfo = "OPERAND_IMM_UINT5 should be in the range 0 to 31";
12357 return false;
12358 }
12359 break;
12361 if (!MO.isImm() || !isUInt<8>(MO.getImm())) {
12362 ErrInfo = "OPERAND_IMM_UINT8 should be in the range 0 to 255";
12363 return false;
12364 }
12365 break;
12366 default:
12367 break;
12368 }
12369 }
12370 return true;
12371}
12372
12373#define GET_INSTRINFO_HELPERS
12374#define GET_INSTRMAP_INFO
12375#include "AArch64GenInstrInfo.inc"
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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 bool isValidCBExtend(int64_t Opc, AArch64_AM::ShiftExtendType Ext)
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[]
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 copyPhysRegImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const
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
void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, llvm::ArrayRef< unsigned > Indices) const
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
AArch64CC::CondCode insertCmpForCondBr(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, ArrayRef< MachineOperand > Cond) const
Inserts the compare instruction needed to un-fuse a fused conditional branch instruction and returns ...
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.
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:199
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:312
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Definition Function.h:699
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Definition Function.h:696
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...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
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:68
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.
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:875
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:342
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:577
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:332
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:177
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:567
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.