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