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 : AArch64GenInstrInfo(STI, RI, AArch64::ADJCALLSTACKDOWN,
108 AArch64::ADJCALLSTACKUP, AArch64::CATCHRET),
109 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
110
111/// Return the maximum number of bytes of code the specified instruction may be
112/// after LFI rewriting. If the instruction is not rewritten, std::nullopt is
113/// returned (use default sizing).
114///
115/// NOTE: the size estimates here must be kept in sync with the rewrites in
116/// AArch64MCLFIRewriter.cpp. Sizes may be overestimates of the rewritten
117/// instruction sequences.
118static std::optional<unsigned> getLFIInstSizeInBytes(const MachineInstr &MI) {
119 switch (MI.getOpcode()) {
120 case AArch64::SVC:
121 // SVC expands to 4 instructions.
122 return 16;
123 case AArch64::BR:
124 case AArch64::BLR:
125 // Indirect branches/calls expand to 2 instructions (guard + br/blr).
126 return 8;
127 case AArch64::RET:
128 // RET through LR is not rewritten, but RET through another register
129 // expands to 2 instructions (guard + ret).
130 if (MI.getOperand(0).getReg() != AArch64::LR)
131 return 8;
132 return 4;
133 case AArch64::RETAA:
134 case AArch64::RETAB:
135 // Authenticated returns expand to 3 instructions (authenticate + guard +
136 // ret).
137 return 12;
138 case AArch64::BRAA:
139 case AArch64::BRAAZ:
140 case AArch64::BRAB:
141 case AArch64::BRABZ:
142 case AArch64::BLRAA:
143 case AArch64::BLRAAZ:
144 case AArch64::BLRAB:
145 case AArch64::BLRABZ:
146 // Authenticated branches/calls expand to 3 instructions (authenticate +
147 // guard + branch).
148 return 12;
149 case AArch64::AUTIASP:
150 case AArch64::AUTIBSP:
151 case AArch64::AUTIAZ:
152 case AArch64::AUTIBZ:
153 case AArch64::XPACLRI:
154 // Authenticating LR expands to the instruction plus a deferred LR guard.
155 return 8;
156 case AArch64::SYSxt:
157 // VA-based DC/IC ops (op1=3, Cn=7, op2=1) expand to 2 instructions.
158 if (MI.getOperand(0).getImm() == 3 && MI.getOperand(1).getImm() == 7 &&
159 MI.getOperand(3).getImm() == 1)
160 return 8;
161 return std::nullopt;
162 default:
163 break;
164 }
165
166 // Detect instructions that explicitly define SP or LR.
167 bool ModifiesLR = false;
168 bool ModifiesSP = false;
169 for (const MachineOperand &MO : MI.defs()) {
170 if (!MO.isReg())
171 continue;
172 if (MO.getReg() == AArch64::LR)
173 ModifiesLR = true;
174 else if (MO.getReg() == AArch64::SP)
175 ModifiesSP = true;
176 }
177
178 // Memory accesses expand to a base-register guard plus the rewritten access
179 // (8 bytes), with an extra base-register update for pre/post-index forms (12
180 // bytes total). If the access also defines LR, an LR mask is appended (+4
181 // bytes). Depending on additional optimizations that the rewriter performs,
182 // this may be an overestimate.
183 if (MI.mayLoadOrStore()) {
184 unsigned Size = isLFIPrePostMemAccess(MI.getOpcode()) ? 12 : 8;
185 if (ModifiesLR)
186 Size += 4;
187 return Size;
188 }
189
190 // Non memory operations that modify LR or SP expand to 2 instructions.
191 if (ModifiesSP || ModifiesLR)
192 return 8;
193
194 // Default case: instructions that don't cause expansion.
195 // - TP accesses in LFI are a single load/store, so no expansion.
196 // - All remaining instructions are not rewritten.
197 return std::nullopt;
198}
199
200/// GetInstSize - Return the number of bytes of code the specified
201/// instruction may be. This returns the maximum number of bytes.
203 const MachineBasicBlock &MBB = *MI.getParent();
204 const MachineFunction *MF = MBB.getParent();
205 const Function &F = MF->getFunction();
206 const MCAsmInfo &MAI = MF->getTarget().getMCAsmInfo();
207
208 {
209 auto Op = MI.getOpcode();
210 if (Op == AArch64::INLINEASM || Op == AArch64::INLINEASM_BR)
211 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
212 }
213
214 // Meta-instructions emit no code.
215 if (MI.isMetaInstruction())
216 return 0;
217
218 // FIXME: We currently only handle pseudoinstructions that don't get expanded
219 // before the assembly printer.
220 unsigned NumBytes = 0;
221 const MCInstrDesc &Desc = MI.getDesc();
222
223 // LFI rewriter expansions that supersede normal sizing.
224 const auto &STI = MF->getSubtarget<AArch64Subtarget>();
225 if (STI.isLFI())
226 if (auto Size = getLFIInstSizeInBytes(MI))
227 return *Size;
228
229 if (!MI.isBundle() && isTailCallReturnInst(MI)) {
230 NumBytes = Desc.getSize() ? Desc.getSize() : 4;
231
232 const auto *MFI = MF->getInfo<AArch64FunctionInfo>();
233 if (!MFI->shouldSignReturnAddress(*MF))
234 return NumBytes;
235
236 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
237 NumBytes += AArch64PAuth::getCheckerSizeInBytes(Method);
238 return NumBytes;
239 }
240
241 // Size should be preferably set in
242 // llvm/lib/Target/AArch64/AArch64InstrInfo.td (default case).
243 // Specific cases handle instructions of variable sizes
244 switch (Desc.getOpcode()) {
245 default:
246 if (Desc.getSize())
247 return Desc.getSize();
248
249 // Anything not explicitly designated otherwise (i.e. pseudo-instructions
250 // with fixed constant size but not specified in .td file) is a normal
251 // 4-byte insn.
252 NumBytes = 4;
253 break;
254 case TargetOpcode::STACKMAP:
255 // The upper bound for a stackmap intrinsic is the full length of its shadow
256 NumBytes = StackMapOpers(&MI).getNumPatchBytes();
257 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
258 break;
259 case TargetOpcode::PATCHPOINT:
260 // The size of the patchpoint intrinsic is the number of bytes requested
261 NumBytes = PatchPointOpers(&MI).getNumPatchBytes();
262 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
263 break;
264 case TargetOpcode::STATEPOINT:
265 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
266 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
267 // No patch bytes means a normal call inst is emitted
268 if (NumBytes == 0)
269 NumBytes = 4;
270 break;
271 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
272 // If `patchable-function-entry` is set, PATCHABLE_FUNCTION_ENTER
273 // instructions are expanded to the specified number of NOPs. Otherwise,
274 // they are expanded to 36-byte XRay sleds.
275 NumBytes =
276 F.getFnAttributeAsParsedInteger("patchable-function-entry", 9) * 4;
277 break;
278 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
279 case TargetOpcode::PATCHABLE_TAIL_CALL:
280 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
281 // An XRay sled can be 4 bytes of alignment plus a 32-byte block.
282 NumBytes = 36;
283 break;
284 case TargetOpcode::PATCHABLE_EVENT_CALL:
285 // EVENT_CALL XRay sleds are exactly 6 instructions long (no alignment).
286 NumBytes = 24;
287 break;
288
289 case AArch64::SPACE:
290 NumBytes = MI.getOperand(1).getImm();
291 break;
292 case AArch64::MOVaddr:
293 case AArch64::MOVaddrJT:
294 case AArch64::MOVaddrCP:
295 case AArch64::MOVaddrBA:
296 case AArch64::MOVaddrTLS:
297 case AArch64::MOVaddrEXT: {
298 // Use the same logic as the pseudo expansion to count instructions.
301 MI.getOperand(1).getTargetFlags(),
302 Subtarget.isTargetMachO(), Insn);
303 NumBytes = Insn.size() * 4;
304 break;
305 }
306
307 case AArch64::MOVi32imm:
308 case AArch64::MOVi64imm: {
309 // Use the same logic as the pseudo expansion to count instructions.
310 unsigned BitSize = Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
312 AArch64_IMM::expandMOVImm(MI.getOperand(1).getImm(), BitSize, Insn);
313 NumBytes = Insn.size() * 4;
314 break;
315 }
316
317 case TargetOpcode::BUNDLE:
318 NumBytes = getInstBundleSize(MI);
319 break;
320 }
321
322 return NumBytes;
323}
324
327 // Block ends with fall-through condbranch.
328 switch (LastInst->getOpcode()) {
329 default:
330 llvm_unreachable("Unknown branch instruction?");
331 case AArch64::Bcc:
332 Target = LastInst->getOperand(1).getMBB();
333 Cond.push_back(LastInst->getOperand(0));
334 break;
335 case AArch64::CBZW:
336 case AArch64::CBZX:
337 case AArch64::CBNZW:
338 case AArch64::CBNZX:
339 Target = LastInst->getOperand(1).getMBB();
340 Cond.push_back(MachineOperand::CreateImm(-1));
341 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
342 Cond.push_back(LastInst->getOperand(0));
343 break;
344 case AArch64::TBZW:
345 case AArch64::TBZX:
346 case AArch64::TBNZW:
347 case AArch64::TBNZX:
348 Target = LastInst->getOperand(2).getMBB();
349 Cond.push_back(MachineOperand::CreateImm(-1));
350 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
351 Cond.push_back(LastInst->getOperand(0));
352 Cond.push_back(LastInst->getOperand(1));
353 break;
354 case AArch64::CBWPri:
355 case AArch64::CBXPri:
356 case AArch64::CBWPrr:
357 case AArch64::CBXPrr:
358 Target = LastInst->getOperand(3).getMBB();
359 Cond.push_back(MachineOperand::CreateImm(-1));
360 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
361 Cond.push_back(LastInst->getOperand(0));
362 Cond.push_back(LastInst->getOperand(1));
363 Cond.push_back(LastInst->getOperand(2));
364 break;
365 case AArch64::CBBAssertExt:
366 case AArch64::CBHAssertExt:
367 Target = LastInst->getOperand(3).getMBB();
368 Cond.push_back(MachineOperand::CreateImm(-1)); // -1
369 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); // Opc
370 Cond.push_back(LastInst->getOperand(0)); // Cond
371 Cond.push_back(LastInst->getOperand(1)); // Op0
372 Cond.push_back(LastInst->getOperand(2)); // Op1
373 Cond.push_back(LastInst->getOperand(4)); // Ext0
374 Cond.push_back(LastInst->getOperand(5)); // Ext1
375 break;
376 }
377}
378
379static unsigned getBranchDisplacementBits(unsigned Opc) {
380 switch (Opc) {
381 default:
382 llvm_unreachable("unexpected opcode!");
383 case AArch64::B:
384 return BDisplacementBits;
385 case AArch64::TBNZW:
386 case AArch64::TBZW:
387 case AArch64::TBNZX:
388 case AArch64::TBZX:
389 return TBZDisplacementBits;
390 case AArch64::CBNZW:
391 case AArch64::CBZW:
392 case AArch64::CBNZX:
393 case AArch64::CBZX:
394 return CBZDisplacementBits;
395 case AArch64::Bcc:
396 return BCCDisplacementBits;
397 case AArch64::CBWPri:
398 case AArch64::CBXPri:
399 case AArch64::CBBAssertExt:
400 case AArch64::CBHAssertExt:
401 case AArch64::CBWPrr:
402 case AArch64::CBXPrr:
403 return CBDisplacementBits;
404 }
405}
406
408 int64_t BrOffset) const {
409 unsigned Bits = getBranchDisplacementBits(BranchOp);
410 assert(Bits >= 3 && "max branch displacement must be enough to jump"
411 "over conditional branch expansion");
412 return isIntN(Bits, BrOffset / 4);
413}
414
417 switch (MI.getOpcode()) {
418 default:
419 llvm_unreachable("unexpected opcode!");
420 case AArch64::B:
421 return MI.getOperand(0).getMBB();
422 case AArch64::TBZW:
423 case AArch64::TBNZW:
424 case AArch64::TBZX:
425 case AArch64::TBNZX:
426 return MI.getOperand(2).getMBB();
427 case AArch64::CBZW:
428 case AArch64::CBNZW:
429 case AArch64::CBZX:
430 case AArch64::CBNZX:
431 case AArch64::Bcc:
432 return MI.getOperand(1).getMBB();
433 case AArch64::CBWPri:
434 case AArch64::CBXPri:
435 case AArch64::CBBAssertExt:
436 case AArch64::CBHAssertExt:
437 case AArch64::CBWPrr:
438 case AArch64::CBXPrr:
439 return MI.getOperand(3).getMBB();
440 }
441}
442
444 MachineBasicBlock &NewDestBB,
445 MachineBasicBlock &RestoreBB,
446 const DebugLoc &DL,
447 int64_t BrOffset,
448 RegScavenger *RS) const {
449 assert(RS && "RegScavenger required for long branching");
450 assert(MBB.empty() &&
451 "new block should be inserted for expanding unconditional branch");
452 assert(MBB.pred_size() == 1);
453 assert(RestoreBB.empty() &&
454 "restore block should be inserted for restoring clobbered registers");
455
456 auto buildIndirectBranch = [&](Register Reg, MachineBasicBlock &DestBB) {
457 // Offsets outside of the signed 33-bit range are not supported for ADRP +
458 // ADD.
459 if (!isInt<33>(BrOffset))
461 "Branch offsets outside of the signed 33-bit range not supported");
462
463 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADRP), Reg)
464 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGE);
465 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADDXri), Reg)
466 .addReg(Reg)
467 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGEOFF | AArch64II::MO_NC)
468 .addImm(0);
469 BuildMI(MBB, MBB.end(), DL, get(AArch64::BR)).addReg(Reg);
470 };
471
472 RS->enterBasicBlockEnd(MBB);
473 // If X16 is unused, we can rely on the linker to insert a range extension
474 // thunk if NewDestBB is out of range of a single B instruction.
475 constexpr Register Reg = AArch64::X16;
476 if (!RS->isRegUsed(Reg)) {
477 insertUnconditionalBranch(MBB, &NewDestBB, DL);
478 RS->setRegUsed(Reg);
479 return;
480 }
481
482 // In a cold block without BTI, insert the indirect branch if a register is
483 // free. Skip this if BTI is enabled to avoid inserting a BTI at the target,
484 // prioritizing a dynamic cost in cold code over a static cost in hot code.
485 AArch64FunctionInfo *AFI = MBB.getParent()->getInfo<AArch64FunctionInfo>();
486 bool HasBTI = AFI && AFI->branchTargetEnforcement();
487 if (MBB.getSectionID() == MBBSectionID::ColdSectionID && !HasBTI) {
488 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
489 if (Scavenged != AArch64::NoRegister) {
490 buildIndirectBranch(Scavenged, NewDestBB);
491 RS->setRegUsed(Scavenged);
492 return;
493 }
494 }
495
496 // Note: Spilling X16 briefly moves the stack pointer, making it incompatible
497 // with red zones.
498 if (!AFI || AFI->hasRedZone().value_or(true))
500 "Unable to insert indirect branch inside function that has red zone");
501
502 // Otherwise, spill X16 and defer range extension to the linker.
503 BuildMI(MBB, MBB.end(), DL, get(AArch64::STRXpre))
504 .addReg(AArch64::SP, RegState::Define)
505 .addReg(Reg)
506 .addReg(AArch64::SP)
507 .addImm(-16);
508
509 BuildMI(MBB, MBB.end(), DL, get(AArch64::B)).addMBB(&RestoreBB);
510
511 BuildMI(RestoreBB, RestoreBB.end(), DL, get(AArch64::LDRXpost))
512 .addReg(AArch64::SP, RegState::Define)
514 .addReg(AArch64::SP)
515 .addImm(16);
516}
517
518// Branch analysis.
521 MachineBasicBlock *&FBB,
523 bool AllowModify) const {
524 // If the block has no terminators, it just falls into the block after it.
525 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
526 if (I == MBB.end())
527 return false;
528
529 // Skip over SpeculationBarrierEndBB terminators
530 if (I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
531 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
532 --I;
533 }
534
535 if (!isUnpredicatedTerminator(*I))
536 return false;
537
538 // Get the last instruction in the block.
539 MachineInstr *LastInst = &*I;
540
541 // If there is only one terminator instruction, process it.
542 unsigned LastOpc = LastInst->getOpcode();
543 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
544 if (isUncondBranchOpcode(LastOpc)) {
545 TBB = LastInst->getOperand(0).getMBB();
546 return false;
547 }
548 if (isCondBranchOpcode(LastOpc)) {
549 // Block ends with fall-through condbranch.
550 parseCondBranch(LastInst, TBB, Cond);
551 return false;
552 }
553 return true; // Can't handle indirect branch.
554 }
555
556 // Get the instruction before it if it is a terminator.
557 MachineInstr *SecondLastInst = &*I;
558 unsigned SecondLastOpc = SecondLastInst->getOpcode();
559
560 // If AllowModify is true and the block ends with two or more unconditional
561 // branches, delete all but the first unconditional branch.
562 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
563 while (isUncondBranchOpcode(SecondLastOpc)) {
564 LastInst->eraseFromParent();
565 LastInst = SecondLastInst;
566 LastOpc = LastInst->getOpcode();
567 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
568 // Return now the only terminator is an unconditional branch.
569 TBB = LastInst->getOperand(0).getMBB();
570 return false;
571 }
572 SecondLastInst = &*I;
573 SecondLastOpc = SecondLastInst->getOpcode();
574 }
575 }
576
577 // If we're allowed to modify and the block ends in a unconditional branch
578 // which could simply fallthrough, remove the branch. (Note: This case only
579 // matters when we can't understand the whole sequence, otherwise it's also
580 // handled by BranchFolding.cpp.)
581 if (AllowModify && isUncondBranchOpcode(LastOpc) &&
582 MBB.isLayoutSuccessor(getBranchDestBlock(*LastInst))) {
583 LastInst->eraseFromParent();
584 LastInst = SecondLastInst;
585 LastOpc = LastInst->getOpcode();
586 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
587 assert(!isUncondBranchOpcode(LastOpc) &&
588 "unreachable unconditional branches removed above");
589
590 if (isCondBranchOpcode(LastOpc)) {
591 // Block ends with fall-through condbranch.
592 parseCondBranch(LastInst, TBB, Cond);
593 return false;
594 }
595 return true; // Can't handle indirect branch.
596 }
597 SecondLastInst = &*I;
598 SecondLastOpc = SecondLastInst->getOpcode();
599 }
600
601 // If there are three terminators, we don't know what sort of block this is.
602 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
603 return true;
604
605 // If the block ends with a B and a Bcc, handle it.
606 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
607 parseCondBranch(SecondLastInst, TBB, Cond);
608 FBB = LastInst->getOperand(0).getMBB();
609 return false;
610 }
611
612 // If the block ends with two unconditional branches, handle it. The second
613 // one is not executed, so remove it.
614 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
615 TBB = SecondLastInst->getOperand(0).getMBB();
616 I = LastInst;
617 if (AllowModify)
618 I->eraseFromParent();
619 return false;
620 }
621
622 // ...likewise if it ends with an indirect branch followed by an unconditional
623 // branch.
624 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
625 I = LastInst;
626 if (AllowModify)
627 I->eraseFromParent();
628 return true;
629 }
630
631 // Otherwise, can't handle this.
632 return true;
633}
634
636 MachineBranchPredicate &MBP,
637 bool AllowModify) const {
638 // Use analyzeBranch to validate the branch pattern.
639 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
641 if (analyzeBranch(MBB, TBB, FBB, Cond, AllowModify))
642 return true;
643
644 // analyzeBranch returns success with empty Cond for unconditional branches.
645 if (Cond.empty())
646 return true;
647
648 MBP.TrueDest = TBB;
649 assert(MBP.TrueDest && "expected!");
650 MBP.FalseDest = FBB ? FBB : MBB.getNextNode();
651
652 MBP.ConditionDef = nullptr;
653 MBP.SingleUseCondition = false;
654
655 // Find the conditional branch. After analyzeBranch succeeds with non-empty
656 // Cond, there's exactly one conditional branch - either last (fallthrough)
657 // or second-to-last (followed by unconditional B).
658 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
659 if (I == MBB.end())
660 return true;
661
662 if (isUncondBranchOpcode(I->getOpcode())) {
663 if (I == MBB.begin())
664 return true;
665 --I;
666 }
667
668 MachineInstr *CondBranch = &*I;
669 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
670
671 switch (CondBranch->getOpcode()) {
672 default:
673 return true;
674
675 case AArch64::Bcc:
676 // Bcc takes the NZCV flag as the operand to branch on, walk up the
677 // instruction stream to find the last instruction to define NZCV.
679 if (MI.modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
680 MBP.ConditionDef = &MI;
681 break;
682 }
683 }
684 return false;
685
686 case AArch64::CBZW:
687 case AArch64::CBZX:
688 case AArch64::CBNZW:
689 case AArch64::CBNZX: {
690 MBP.LHS = CondBranch->getOperand(0);
691 MBP.RHS = MachineOperand::CreateImm(0);
692 unsigned Opc = CondBranch->getOpcode();
693 MBP.Predicate = (Opc == AArch64::CBNZX || Opc == AArch64::CBNZW)
694 ? MachineBranchPredicate::PRED_NE
695 : MachineBranchPredicate::PRED_EQ;
696 Register CondReg = MBP.LHS.getReg();
697 if (CondReg.isVirtual())
698 MBP.ConditionDef = MRI.getVRegDef(CondReg);
699 return false;
700 }
701
702 case AArch64::TBZW:
703 case AArch64::TBZX:
704 case AArch64::TBNZW:
705 case AArch64::TBNZX: {
706 Register CondReg = CondBranch->getOperand(0).getReg();
707 if (CondReg.isVirtual())
708 MBP.ConditionDef = MRI.getVRegDef(CondReg);
709 return false;
710 }
711 }
712}
713
716 if (Cond[0].getImm() != -1) {
717 // Regular Bcc
718 AArch64CC::CondCode CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
720 } else {
721 // Folded compare-and-branch
722 switch (Cond[1].getImm()) {
723 default:
724 llvm_unreachable("Unknown conditional branch!");
725 case AArch64::CBZW:
726 Cond[1].setImm(AArch64::CBNZW);
727 break;
728 case AArch64::CBNZW:
729 Cond[1].setImm(AArch64::CBZW);
730 break;
731 case AArch64::CBZX:
732 Cond[1].setImm(AArch64::CBNZX);
733 break;
734 case AArch64::CBNZX:
735 Cond[1].setImm(AArch64::CBZX);
736 break;
737 case AArch64::TBZW:
738 Cond[1].setImm(AArch64::TBNZW);
739 break;
740 case AArch64::TBNZW:
741 Cond[1].setImm(AArch64::TBZW);
742 break;
743 case AArch64::TBZX:
744 Cond[1].setImm(AArch64::TBNZX);
745 break;
746 case AArch64::TBNZX:
747 Cond[1].setImm(AArch64::TBZX);
748 break;
749
750 // Cond is { -1, Opcode, CC, Op0, Op1, ... }
751 case AArch64::CBWPri:
752 case AArch64::CBXPri:
753 case AArch64::CBBAssertExt:
754 case AArch64::CBHAssertExt:
755 case AArch64::CBWPrr:
756 case AArch64::CBXPrr: {
757 // Pseudos using standard 4bit Arm condition codes
759 static_cast<AArch64CC::CondCode>(Cond[2].getImm());
761 }
762 }
763 }
764
765 return false;
766}
767
769 int *BytesRemoved) const {
770 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
771 if (I == MBB.end())
772 return 0;
773
774 if (!isUncondBranchOpcode(I->getOpcode()) &&
775 !isCondBranchOpcode(I->getOpcode()))
776 return 0;
777
778 // Remove the branch.
779 I->eraseFromParent();
780
781 I = MBB.end();
782
783 if (I == MBB.begin()) {
784 if (BytesRemoved)
785 *BytesRemoved = 4;
786 return 1;
787 }
788 --I;
789 if (!isCondBranchOpcode(I->getOpcode())) {
790 if (BytesRemoved)
791 *BytesRemoved = 4;
792 return 1;
793 }
794
795 // Remove the branch.
796 I->eraseFromParent();
797 if (BytesRemoved)
798 *BytesRemoved = 8;
799
800 return 2;
801}
802
803void AArch64InstrInfo::instantiateCondBranch(
806 if (Cond[0].getImm() != -1) {
807 // Regular Bcc
808 BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
809 } else {
810 // Folded compare-and-branch
811 // Note that we use addOperand instead of addReg to keep the flags.
812
813 // cbz, cbnz
814 const MachineInstrBuilder MIB =
815 BuildMI(&MBB, DL, get(Cond[1].getImm())).add(Cond[2]);
816
817 // tbz/tbnz
818 if (Cond.size() > 3)
819 MIB.add(Cond[3]);
820
821 // cb
822 if (Cond.size() > 4)
823 MIB.add(Cond[4]);
824
825 MIB.addMBB(TBB);
826
827 // cb[b,h]
828 if (Cond.size() > 5) {
829 MIB.addImm(Cond[5].getImm());
830 MIB.addImm(Cond[6].getImm());
831 }
832 }
833}
834
837 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
838 // Shouldn't be a fall through.
839 assert(TBB && "insertBranch must not be told to insert a fallthrough");
840
841 if (!FBB) {
842 if (Cond.empty()) // Unconditional branch?
843 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
844 else
845 instantiateCondBranch(MBB, DL, TBB, Cond);
846
847 if (BytesAdded)
848 *BytesAdded = 4;
849
850 return 1;
851 }
852
853 // Two-way conditional branch.
854 instantiateCondBranch(MBB, DL, TBB, Cond);
855 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
856
857 if (BytesAdded)
858 *BytesAdded = 8;
859
860 return 2;
861}
862
864 const TargetInstrInfo &TII) {
865 for (MachineInstr &MI : MBB->terminators()) {
866 unsigned Opc = MI.getOpcode();
867 switch (Opc) {
868 case AArch64::CBZW:
869 case AArch64::CBZX:
870 case AArch64::TBZW:
871 case AArch64::TBZX:
872 // CBZ/TBZ with WZR/XZR -> unconditional B
873 if (MI.getOperand(0).getReg() == AArch64::WZR ||
874 MI.getOperand(0).getReg() == AArch64::XZR) {
875 DEBUG_WITH_TYPE("optimizeTerminators",
876 dbgs() << "Removing always taken branch: " << MI);
877 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
878 SmallVector<MachineBasicBlock *> Succs(MBB->successors());
879 for (auto *S : Succs)
880 if (S != Target)
881 MBB->removeSuccessor(S);
882 DebugLoc DL = MI.getDebugLoc();
883 while (MBB->rbegin() != &MI)
884 MBB->rbegin()->eraseFromParent();
885 MI.eraseFromParent();
886 BuildMI(MBB, DL, TII.get(AArch64::B)).addMBB(Target);
887 return true;
888 }
889 break;
890 case AArch64::CBNZW:
891 case AArch64::CBNZX:
892 case AArch64::TBNZW:
893 case AArch64::TBNZX:
894 // CBNZ/TBNZ with WZR/XZR -> never taken, remove branch and successor
895 if (MI.getOperand(0).getReg() == AArch64::WZR ||
896 MI.getOperand(0).getReg() == AArch64::XZR) {
897 DEBUG_WITH_TYPE("optimizeTerminators",
898 dbgs() << "Removing never taken branch: " << MI);
899 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
900 MI.getParent()->removeSuccessor(Target);
901 MI.eraseFromParent();
902 return true;
903 }
904 break;
905 }
906 }
907 return false;
908}
909
910// Find the original register that VReg is copied from.
911static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
912 while (Register::isVirtualRegister(VReg)) {
913 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
914 if (!DefMI->isFullCopy())
915 return VReg;
916 VReg = DefMI->getOperand(1).getReg();
917 }
918 return VReg;
919}
920
921// Determine if VReg is defined by an instruction that can be folded into a
922// csel instruction. If so, return the folded opcode, and the replacement
923// register.
924static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
925 unsigned *NewReg = nullptr) {
926 VReg = removeCopies(MRI, VReg);
928 return 0;
929
930 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
931 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
932 unsigned Opc = 0;
933 unsigned SrcReg = 0;
934 switch (DefMI->getOpcode()) {
935 case AArch64::SUBREG_TO_REG:
936 // Check for the following way to define an 64-bit immediate:
937 // %0:gpr32 = MOVi32imm 1
938 // %1:gpr64 = SUBREG_TO_REG %0:gpr32, %subreg.sub_32
939 if (!DefMI->getOperand(1).isReg())
940 return 0;
941 if (!DefMI->getOperand(2).isImm() ||
942 DefMI->getOperand(2).getImm() != AArch64::sub_32)
943 return 0;
944 DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg());
945 if (DefMI->getOpcode() != AArch64::MOVi32imm)
946 return 0;
947 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
948 return 0;
949 assert(Is64Bit);
950 SrcReg = AArch64::XZR;
951 Opc = AArch64::CSINCXr;
952 break;
953
954 case AArch64::MOVi32imm:
955 case AArch64::MOVi64imm:
956 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
957 return 0;
958 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
959 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
960 break;
961
962 case AArch64::ADDSXri:
963 case AArch64::ADDSWri:
964 // if NZCV is used, do not fold.
965 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
966 true) == -1)
967 return 0;
968 // fall-through to ADDXri and ADDWri.
969 [[fallthrough]];
970 case AArch64::ADDXri:
971 case AArch64::ADDWri:
972 // add x, 1 -> csinc.
973 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
974 DefMI->getOperand(3).getImm() != 0)
975 return 0;
976 SrcReg = DefMI->getOperand(1).getReg();
977 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
978 break;
979
980 case AArch64::ORNXrr:
981 case AArch64::ORNWrr: {
982 // not x -> csinv, represented as orn dst, xzr, src.
983 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
984 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
985 return 0;
986 SrcReg = DefMI->getOperand(2).getReg();
987 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
988 break;
989 }
990
991 case AArch64::SUBSXrr:
992 case AArch64::SUBSWrr:
993 // if NZCV is used, do not fold.
994 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
995 true) == -1)
996 return 0;
997 // fall-through to SUBXrr and SUBWrr.
998 [[fallthrough]];
999 case AArch64::SUBXrr:
1000 case AArch64::SUBWrr: {
1001 // neg x -> csneg, represented as sub dst, xzr, src.
1002 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1003 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1004 return 0;
1005 SrcReg = DefMI->getOperand(2).getReg();
1006 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1007 break;
1008 }
1009 default:
1010 return 0;
1011 }
1012 assert(Opc && SrcReg && "Missing parameters");
1013
1014 if (NewReg)
1015 *NewReg = SrcReg;
1016 return Opc;
1017}
1018
1021 Register DstReg, Register TrueReg,
1022 Register FalseReg, int &CondCycles,
1023 int &TrueCycles,
1024 int &FalseCycles) const {
1025 // Check register classes.
1026 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1027 const TargetRegisterClass *RC =
1028 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
1029 if (!RC)
1030 return false;
1031
1032 // Also need to check the dest regclass, in case we're trying to optimize
1033 // something like:
1034 // %1(gpr) = PHI %2(fpr), bb1, %(fpr), bb2
1035 if (!RI.getCommonSubClass(RC, MRI.getRegClass(DstReg)))
1036 return false;
1037
1038 // Expanding cbz/tbz requires an extra cycle of latency on the condition.
1039 unsigned ExtraCondLat = Cond.size() != 1;
1040
1041 // GPRs are handled by csel.
1042 // FIXME: Fold in x+1, -x, and ~x when applicable.
1043 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1044 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1045 // Single-cycle csel, csinc, csinv, and csneg.
1046 CondCycles = 1 + ExtraCondLat;
1047 TrueCycles = FalseCycles = 1;
1048 if (canFoldIntoCSel(MRI, TrueReg))
1049 TrueCycles = 0;
1050 else if (canFoldIntoCSel(MRI, FalseReg))
1051 FalseCycles = 0;
1052 return true;
1053 }
1054
1055 // Scalar floating point is handled by fcsel.
1056 // FIXME: Form fabs, fmin, and fmax when applicable.
1057 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1058 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1059 CondCycles = 5 + ExtraCondLat;
1060 TrueCycles = FalseCycles = 2;
1061 return true;
1062 }
1063
1064 // Can't do vectors.
1065 return false;
1066}
1067
1070 const DebugLoc &DL, Register DstReg,
1072 Register TrueReg, Register FalseReg) const {
1073 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1074
1075 // Parse the condition code, see parseCondBranch() above.
1077 switch (Cond.size()) {
1078 default:
1079 llvm_unreachable("Unknown condition opcode in Cond");
1080 case 1: // b.cc
1081 CC = AArch64CC::CondCode(Cond[0].getImm());
1082 break;
1083 case 3: { // cbz/cbnz
1084 // We must insert a compare against 0.
1085 bool Is64Bit;
1086 switch (Cond[1].getImm()) {
1087 default:
1088 llvm_unreachable("Unknown branch opcode in Cond");
1089 case AArch64::CBZW:
1090 Is64Bit = false;
1091 CC = AArch64CC::EQ;
1092 break;
1093 case AArch64::CBZX:
1094 Is64Bit = true;
1095 CC = AArch64CC::EQ;
1096 break;
1097 case AArch64::CBNZW:
1098 Is64Bit = false;
1099 CC = AArch64CC::NE;
1100 break;
1101 case AArch64::CBNZX:
1102 Is64Bit = true;
1103 CC = AArch64CC::NE;
1104 break;
1105 }
1106 Register SrcReg = Cond[2].getReg();
1107 if (Is64Bit) {
1108 // cmp reg, #0 is actually subs xzr, reg, #0.
1109 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
1110 BuildMI(MBB, I, DL, get(AArch64::SUBSXri), AArch64::XZR)
1111 .addReg(SrcReg)
1112 .addImm(0)
1113 .addImm(0);
1114 } else {
1115 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
1116 BuildMI(MBB, I, DL, get(AArch64::SUBSWri), AArch64::WZR)
1117 .addReg(SrcReg)
1118 .addImm(0)
1119 .addImm(0);
1120 }
1121 break;
1122 }
1123 case 4: { // tbz/tbnz
1124 // We must insert a tst instruction.
1125 switch (Cond[1].getImm()) {
1126 default:
1127 llvm_unreachable("Unknown branch opcode in Cond");
1128 case AArch64::TBZW:
1129 case AArch64::TBZX:
1130 CC = AArch64CC::EQ;
1131 break;
1132 case AArch64::TBNZW:
1133 case AArch64::TBNZX:
1134 CC = AArch64CC::NE;
1135 break;
1136 }
1137 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
1138 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
1139 BuildMI(MBB, I, DL, get(AArch64::ANDSWri), AArch64::WZR)
1140 .addReg(Cond[2].getReg())
1141 .addImm(
1143 else
1144 BuildMI(MBB, I, DL, get(AArch64::ANDSXri), AArch64::XZR)
1145 .addReg(Cond[2].getReg())
1146 .addImm(
1148 break;
1149 }
1150 case 5: { // cb
1151 // We must insert a cmp, that is a subs
1152 // 0 1 2 3 4
1153 // Cond is { -1, Opcode, CC, Op0, Op1 }
1154
1155 unsigned SubsOpc, SubsDestReg;
1156 bool IsImm = false;
1157 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1158 switch (Cond[1].getImm()) {
1159 default:
1160 llvm_unreachable("Unknown branch opcode in Cond");
1161 case AArch64::CBWPri:
1162 SubsOpc = AArch64::SUBSWri;
1163 SubsDestReg = AArch64::WZR;
1164 IsImm = true;
1165 break;
1166 case AArch64::CBXPri:
1167 SubsOpc = AArch64::SUBSXri;
1168 SubsDestReg = AArch64::XZR;
1169 IsImm = true;
1170 break;
1171 case AArch64::CBWPrr:
1172 SubsOpc = AArch64::SUBSWrr;
1173 SubsDestReg = AArch64::WZR;
1174 IsImm = false;
1175 break;
1176 case AArch64::CBXPrr:
1177 SubsOpc = AArch64::SUBSXrr;
1178 SubsDestReg = AArch64::XZR;
1179 IsImm = false;
1180 break;
1181 }
1182
1183 if (IsImm)
1184 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1185 .addReg(Cond[3].getReg())
1186 .addImm(Cond[4].getImm())
1187 .addImm(0);
1188 else
1189 BuildMI(MBB, I, DL, get(SubsOpc), SubsDestReg)
1190 .addReg(Cond[3].getReg())
1191 .addReg(Cond[4].getReg());
1192 } break;
1193 case 7: { // cb[b,h]
1194 // We must insert a cmp, that is a subs, but also zero- or sign-extensions
1195 // that have been folded. For the first operand we codegen an explicit
1196 // extension, for the second operand we fold the extension into cmp.
1197 // 0 1 2 3 4 5 6
1198 // Cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
1199
1200 // We need a new register for the now explicitly extended register
1201 Register Reg = Cond[4].getReg();
1203 unsigned ExtOpc;
1204 unsigned ExtBits;
1205 AArch64_AM::ShiftExtendType ExtendType =
1207 switch (ExtendType) {
1208 default:
1209 llvm_unreachable("Unknown shift-extend for CB instruction");
1210 case AArch64_AM::SXTB:
1211 assert(
1212 Cond[1].getImm() == AArch64::CBBAssertExt &&
1213 "Unexpected compare-and-branch instruction for SXTB shift-extend");
1214 ExtOpc = AArch64::SBFMWri;
1215 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1216 break;
1217 case AArch64_AM::SXTH:
1218 assert(
1219 Cond[1].getImm() == AArch64::CBHAssertExt &&
1220 "Unexpected compare-and-branch instruction for SXTH shift-extend");
1221 ExtOpc = AArch64::SBFMWri;
1222 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1223 break;
1224 case AArch64_AM::UXTB:
1225 assert(
1226 Cond[1].getImm() == AArch64::CBBAssertExt &&
1227 "Unexpected compare-and-branch instruction for UXTB shift-extend");
1228 ExtOpc = AArch64::ANDWri;
1229 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1230 break;
1231 case AArch64_AM::UXTH:
1232 assert(
1233 Cond[1].getImm() == AArch64::CBHAssertExt &&
1234 "Unexpected compare-and-branch instruction for UXTH shift-extend");
1235 ExtOpc = AArch64::ANDWri;
1236 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1237 break;
1238 }
1239
1240 // Build the explicit extension of the first operand
1241 Reg = MRI.createVirtualRegister(&AArch64::GPR32spRegClass);
1243 BuildMI(MBB, I, DL, get(ExtOpc), Reg).addReg(Cond[4].getReg());
1244 if (ExtOpc != AArch64::ANDWri)
1245 MBBI.addImm(0);
1246 MBBI.addImm(ExtBits);
1247 }
1248
1249 // Now, subs with an extended second operand
1251 AArch64_AM::ShiftExtendType ExtendType =
1253 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1254 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1255 BuildMI(MBB, I, DL, get(AArch64::SUBSWrx), AArch64::WZR)
1256 .addReg(Cond[3].getReg())
1257 .addReg(Reg)
1258 .addImm(AArch64_AM::getArithExtendImm(ExtendType, 0));
1259 } // If no extension is needed, just a regular subs
1260 else {
1261 MRI.constrainRegClass(Reg, MRI.getRegClass(Cond[3].getReg()));
1262 MRI.constrainRegClass(Cond[3].getReg(), &AArch64::GPR32spRegClass);
1263 BuildMI(MBB, I, DL, get(AArch64::SUBSWrr), AArch64::WZR)
1264 .addReg(Cond[3].getReg())
1265 .addReg(Reg);
1266 }
1267
1268 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1269 } break;
1270 }
1271
1272 unsigned Opc = 0;
1273 const TargetRegisterClass *RC = nullptr;
1274 bool TryFold = false;
1275 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
1276 RC = &AArch64::GPR64RegClass;
1277 Opc = AArch64::CSELXr;
1278 TryFold = true;
1279 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
1280 RC = &AArch64::GPR32RegClass;
1281 Opc = AArch64::CSELWr;
1282 TryFold = true;
1283 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
1284 RC = &AArch64::FPR64RegClass;
1285 Opc = AArch64::FCSELDrrr;
1286 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
1287 RC = &AArch64::FPR32RegClass;
1288 Opc = AArch64::FCSELSrrr;
1289 }
1290 assert(RC && "Unsupported regclass");
1291
1292 // Try folding simple instructions into the csel.
1293 if (TryFold) {
1294 unsigned NewReg = 0;
1295 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewReg);
1296 if (FoldedOpc) {
1297 // The folded opcodes csinc, csinc and csneg apply the operation to
1298 // FalseReg, so we need to invert the condition.
1300 TrueReg = FalseReg;
1301 } else
1302 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewReg);
1303
1304 // Fold the operation. Leave any dead instructions for DCE to clean up.
1305 if (FoldedOpc) {
1306 FalseReg = NewReg;
1307 Opc = FoldedOpc;
1308 // Extend the live range of NewReg.
1309 MRI.clearKillFlags(NewReg);
1310 }
1311 }
1312
1313 // Pull all virtual register into the appropriate class.
1314 MRI.constrainRegClass(TrueReg, RC);
1315 // FalseReg might be WZR or XZR if the folded operand is a literal 1.
1316 assert(
1317 (FalseReg.isVirtual() || FalseReg == AArch64::WZR ||
1318 FalseReg == AArch64::XZR) &&
1319 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1320 if (FalseReg.isVirtual())
1321 MRI.constrainRegClass(FalseReg, RC);
1322
1323 // Insert the csel.
1324 BuildMI(MBB, I, DL, get(Opc), DstReg)
1325 .addReg(TrueReg)
1326 .addReg(FalseReg)
1327 .addImm(CC);
1328}
1329
1330// Return true if Imm can be loaded into a register by a "cheap" sequence of
1331// instructions. For now, "cheap" means at most two instructions.
1332static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
1333 if (BitSize == 32)
1334 return true;
1335
1336 assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
1337 uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
1339 AArch64_IMM::expandMOVImm(Imm, BitSize, Is);
1340
1341 return Is.size() <= 2;
1342}
1343
1344// Check if a COPY instruction is cheap.
1345static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
1346 assert(MI.isCopy() && "Expected COPY instruction");
1347 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1348
1349 // Cross-bank copies (e.g., between GPR and FPR) are expensive on AArch64,
1350 // typically requiring an FMOV instruction with a 2-6 cycle latency.
1351 auto GetRegClass = [&](Register Reg) -> const TargetRegisterClass * {
1352 if (Reg.isVirtual())
1353 return MRI.getRegClass(Reg);
1354 if (Reg.isPhysical())
1355 return RI.getMinimalPhysRegClass(Reg);
1356 return nullptr;
1357 };
1358 const TargetRegisterClass *DstRC = GetRegClass(MI.getOperand(0).getReg());
1359 const TargetRegisterClass *SrcRC = GetRegClass(MI.getOperand(1).getReg());
1360 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1361 return false;
1362
1363 return MI.isAsCheapAsAMove();
1364}
1365
1366// FIXME: this implementation should be micro-architecture dependent, so a
1367// micro-architecture target hook should be introduced here in future.
1369 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1370 if (isExynosCheapAsMove(MI))
1371 return true;
1372 return MI.isAsCheapAsAMove();
1373 }
1374
1375 switch (MI.getOpcode()) {
1376 default:
1377 return MI.isAsCheapAsAMove();
1378
1379 case TargetOpcode::COPY:
1380 return isCheapCopy(MI, RI);
1381
1382 case AArch64::ADDWrs:
1383 case AArch64::ADDXrs:
1384 case AArch64::SUBWrs:
1385 case AArch64::SUBXrs:
1386 return Subtarget.hasALULSLFast() && MI.getOperand(3).getImm() <= 4;
1387
1388 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
1389 // ORRXri, it is as cheap as MOV.
1390 // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
1391 case AArch64::MOVi32imm:
1392 return isCheapImmediate(MI, 32);
1393 case AArch64::MOVi64imm:
1394 return isCheapImmediate(MI, 64);
1395 }
1396}
1397
1398bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) {
1399 switch (MI.getOpcode()) {
1400 default:
1401 return false;
1402
1403 case AArch64::ADDWrs:
1404 case AArch64::ADDXrs:
1405 case AArch64::ADDSWrs:
1406 case AArch64::ADDSXrs: {
1407 unsigned Imm = MI.getOperand(3).getImm();
1408 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1409 if (ShiftVal == 0)
1410 return true;
1411 return AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL && ShiftVal <= 5;
1412 }
1413
1414 case AArch64::ADDWrx:
1415 case AArch64::ADDXrx:
1416 case AArch64::ADDXrx64:
1417 case AArch64::ADDSWrx:
1418 case AArch64::ADDSXrx:
1419 case AArch64::ADDSXrx64: {
1420 unsigned Imm = MI.getOperand(3).getImm();
1421 switch (AArch64_AM::getArithExtendType(Imm)) {
1422 default:
1423 return false;
1424 case AArch64_AM::UXTB:
1425 case AArch64_AM::UXTH:
1426 case AArch64_AM::UXTW:
1427 case AArch64_AM::UXTX:
1428 return AArch64_AM::getArithShiftValue(Imm) <= 4;
1429 }
1430 }
1431
1432 case AArch64::SUBWrs:
1433 case AArch64::SUBSWrs: {
1434 unsigned Imm = MI.getOperand(3).getImm();
1435 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1436 return ShiftVal == 0 ||
1437 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 31);
1438 }
1439
1440 case AArch64::SUBXrs:
1441 case AArch64::SUBSXrs: {
1442 unsigned Imm = MI.getOperand(3).getImm();
1443 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1444 return ShiftVal == 0 ||
1445 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 63);
1446 }
1447
1448 case AArch64::SUBWrx:
1449 case AArch64::SUBXrx:
1450 case AArch64::SUBXrx64:
1451 case AArch64::SUBSWrx:
1452 case AArch64::SUBSXrx:
1453 case AArch64::SUBSXrx64: {
1454 unsigned Imm = MI.getOperand(3).getImm();
1455 switch (AArch64_AM::getArithExtendType(Imm)) {
1456 default:
1457 return false;
1458 case AArch64_AM::UXTB:
1459 case AArch64_AM::UXTH:
1460 case AArch64_AM::UXTW:
1461 case AArch64_AM::UXTX:
1462 return AArch64_AM::getArithShiftValue(Imm) == 0;
1463 }
1464 }
1465
1466 case AArch64::LDRBBroW:
1467 case AArch64::LDRBBroX:
1468 case AArch64::LDRBroW:
1469 case AArch64::LDRBroX:
1470 case AArch64::LDRDroW:
1471 case AArch64::LDRDroX:
1472 case AArch64::LDRHHroW:
1473 case AArch64::LDRHHroX:
1474 case AArch64::LDRHroW:
1475 case AArch64::LDRHroX:
1476 case AArch64::LDRQroW:
1477 case AArch64::LDRQroX:
1478 case AArch64::LDRSBWroW:
1479 case AArch64::LDRSBWroX:
1480 case AArch64::LDRSBXroW:
1481 case AArch64::LDRSBXroX:
1482 case AArch64::LDRSHWroW:
1483 case AArch64::LDRSHWroX:
1484 case AArch64::LDRSHXroW:
1485 case AArch64::LDRSHXroX:
1486 case AArch64::LDRSWroW:
1487 case AArch64::LDRSWroX:
1488 case AArch64::LDRSroW:
1489 case AArch64::LDRSroX:
1490 case AArch64::LDRWroW:
1491 case AArch64::LDRWroX:
1492 case AArch64::LDRXroW:
1493 case AArch64::LDRXroX:
1494 case AArch64::PRFMroW:
1495 case AArch64::PRFMroX:
1496 case AArch64::STRBBroW:
1497 case AArch64::STRBBroX:
1498 case AArch64::STRBroW:
1499 case AArch64::STRBroX:
1500 case AArch64::STRDroW:
1501 case AArch64::STRDroX:
1502 case AArch64::STRHHroW:
1503 case AArch64::STRHHroX:
1504 case AArch64::STRHroW:
1505 case AArch64::STRHroX:
1506 case AArch64::STRQroW:
1507 case AArch64::STRQroX:
1508 case AArch64::STRSroW:
1509 case AArch64::STRSroX:
1510 case AArch64::STRWroW:
1511 case AArch64::STRWroX:
1512 case AArch64::STRXroW:
1513 case AArch64::STRXroX: {
1514 unsigned IsSigned = MI.getOperand(3).getImm();
1515 return !IsSigned;
1516 }
1517 }
1518}
1519
1520bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
1521 unsigned Opc = MI.getOpcode();
1522 switch (Opc) {
1523 default:
1524 return false;
1525 case AArch64::SEH_StackAlloc:
1526 case AArch64::SEH_SaveFPLR:
1527 case AArch64::SEH_SaveFPLR_X:
1528 case AArch64::SEH_SaveReg:
1529 case AArch64::SEH_SaveReg_X:
1530 case AArch64::SEH_SaveRegP:
1531 case AArch64::SEH_SaveRegP_X:
1532 case AArch64::SEH_SaveFReg:
1533 case AArch64::SEH_SaveFReg_X:
1534 case AArch64::SEH_SaveFRegP:
1535 case AArch64::SEH_SaveFRegP_X:
1536 case AArch64::SEH_SetFP:
1537 case AArch64::SEH_AddFP:
1538 case AArch64::SEH_Nop:
1539 case AArch64::SEH_PrologEnd:
1540 case AArch64::SEH_EpilogStart:
1541 case AArch64::SEH_EpilogEnd:
1542 case AArch64::SEH_PACSignLR:
1543 case AArch64::SEH_SaveAnyRegI:
1544 case AArch64::SEH_SaveAnyRegIP:
1545 case AArch64::SEH_SaveAnyRegQP:
1546 case AArch64::SEH_SaveAnyRegQPX:
1547 case AArch64::SEH_AllocZ:
1548 case AArch64::SEH_SaveZReg:
1549 case AArch64::SEH_SavePReg:
1550 return true;
1551 }
1552}
1553
1555 Register &SrcReg, Register &DstReg,
1556 unsigned &SubIdx) const {
1557 switch (MI.getOpcode()) {
1558 default:
1559 return false;
1560 case AArch64::SBFMXri: // aka sxtw
1561 case AArch64::UBFMXri: // aka uxtw
1562 // Check for the 32 -> 64 bit extension case, these instructions can do
1563 // much more.
1564 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
1565 return false;
1566 // This is a signed or unsigned 32 -> 64 bit extension.
1567 SrcReg = MI.getOperand(1).getReg();
1568 DstReg = MI.getOperand(0).getReg();
1569 SubIdx = AArch64::sub_32;
1570 return true;
1571 }
1572}
1573
1575 const MachineInstr &MIa, const MachineInstr &MIb) const {
1577 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
1578 int64_t OffsetA = 0, OffsetB = 0;
1579 TypeSize WidthA(0, false), WidthB(0, false);
1580 bool OffsetAIsScalable = false, OffsetBIsScalable = false;
1581
1582 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
1583 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
1584
1587 return false;
1588
1589 // Retrieve the base, offset from the base and width. Width
1590 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
1591 // base are identical, and the offset of a lower memory access +
1592 // the width doesn't overlap the offset of a higher memory access,
1593 // then the memory accesses are different.
1594 // If OffsetAIsScalable and OffsetBIsScalable are both true, they
1595 // are assumed to have the same scale (vscale).
1596 if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, OffsetAIsScalable,
1597 WidthA, TRI) &&
1598 getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, OffsetBIsScalable,
1599 WidthB, TRI)) {
1600 if (BaseOpA->isIdenticalTo(*BaseOpB) &&
1601 OffsetAIsScalable == OffsetBIsScalable) {
1602 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1603 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1604 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1605 if (LowWidth.isScalable() == OffsetAIsScalable &&
1606 LowOffset + (int)LowWidth.getKnownMinValue() <= HighOffset)
1607 return true;
1608 }
1609 }
1610 return false;
1611}
1612
1614 const MachineBasicBlock *MBB,
1615 const MachineFunction &MF) const {
1617 return true;
1618
1619 // Do not move an instruction that can be recognized as a branch target.
1620 if (hasBTISemantics(MI))
1621 return true;
1622
1623 switch (MI.getOpcode()) {
1624 case AArch64::HINT:
1625 // CSDB hints are scheduling barriers.
1626 if (MI.getOperand(0).getImm() == 0x14)
1627 return true;
1628 break;
1629 case AArch64::DSB:
1630 case AArch64::ISB:
1631 // DSB and ISB also are scheduling barriers.
1632 return true;
1633 case AArch64::MSRpstatesvcrImm1:
1634 // SMSTART and SMSTOP are also scheduling barriers.
1635 return true;
1636 default:;
1637 }
1638 if (isSEHInstruction(MI))
1639 return true;
1640 auto Next = std::next(MI.getIterator());
1641 return Next != MBB->end() && Next->isCFIInstruction();
1642}
1643
1644/// analyzeCompare - For a comparison instruction, return the source registers
1645/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
1646/// Return true if the comparison instruction can be analyzed.
1648 Register &SrcReg2, int64_t &CmpMask,
1649 int64_t &CmpValue) const {
1650 // The first operand can be a frame index where we'd normally expect a
1651 // register.
1652 // FIXME: Pass subregisters out of analyzeCompare
1653 assert(MI.getNumOperands() >= 2 && "All AArch64 cmps should have 2 operands");
1654 if (!MI.getOperand(1).isReg() || MI.getOperand(1).getSubReg())
1655 return false;
1656
1657 switch (MI.getOpcode()) {
1658 default:
1659 break;
1660 case AArch64::PTEST_PP:
1661 case AArch64::PTEST_PP_ANY:
1662 case AArch64::PTEST_PP_FIRST:
1663 SrcReg = MI.getOperand(0).getReg();
1664 SrcReg2 = MI.getOperand(1).getReg();
1665 if (MI.getOperand(2).getSubReg())
1666 return false;
1667
1668 // Not sure about the mask and value for now...
1669 CmpMask = ~0;
1670 CmpValue = 0;
1671 return true;
1672 case AArch64::SUBSWrr:
1673 case AArch64::SUBSWrs:
1674 case AArch64::SUBSWrx:
1675 case AArch64::SUBSXrr:
1676 case AArch64::SUBSXrs:
1677 case AArch64::SUBSXrx:
1678 case AArch64::ADDSWrr:
1679 case AArch64::ADDSWrs:
1680 case AArch64::ADDSWrx:
1681 case AArch64::ADDSXrr:
1682 case AArch64::ADDSXrs:
1683 case AArch64::ADDSXrx:
1684 // Replace SUBSWrr with SUBWrr if NZCV is not used.
1685 SrcReg = MI.getOperand(1).getReg();
1686 SrcReg2 = MI.getOperand(2).getReg();
1687
1688 // FIXME: Pass subregisters out of analyzeCompare
1689 if (MI.getOperand(2).getSubReg())
1690 return false;
1691
1692 CmpMask = ~0;
1693 CmpValue = 0;
1694 return true;
1695 case AArch64::SUBSWri:
1696 case AArch64::ADDSWri:
1697 case AArch64::SUBSXri:
1698 case AArch64::ADDSXri:
1699 SrcReg = MI.getOperand(1).getReg();
1700 SrcReg2 = 0;
1701 CmpMask = ~0;
1702 CmpValue = MI.getOperand(2).getImm();
1703 return true;
1704 case AArch64::ANDSWri:
1705 case AArch64::ANDSXri:
1706 // ANDS does not use the same encoding scheme as the others xxxS
1707 // instructions.
1708 SrcReg = MI.getOperand(1).getReg();
1709 SrcReg2 = 0;
1710 CmpMask = ~0;
1712 MI.getOperand(2).getImm(),
1713 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1714 return true;
1715 }
1716
1717 return false;
1718}
1719
1721 MachineBasicBlock *MBB = Instr.getParent();
1722 assert(MBB && "Can't get MachineBasicBlock here");
1723 MachineFunction *MF = MBB->getParent();
1724 assert(MF && "Can't get MachineFunction here");
1727 MachineRegisterInfo *MRI = &MF->getRegInfo();
1728
1729 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1730 ++OpIdx) {
1731 MachineOperand &MO = Instr.getOperand(OpIdx);
1732 const TargetRegisterClass *OpRegCstraints =
1733 Instr.getRegClassConstraint(OpIdx, TII, TRI);
1734
1735 // If there's no constraint, there's nothing to do.
1736 if (!OpRegCstraints)
1737 continue;
1738 // If the operand is a frame index, there's nothing to do here.
1739 // A frame index operand will resolve correctly during PEI.
1740 if (MO.isFI())
1741 continue;
1742
1743 assert(MO.isReg() &&
1744 "Operand has register constraints without being a register!");
1745
1746 Register Reg = MO.getReg();
1747 if (Reg.isPhysical()) {
1748 if (!OpRegCstraints->contains(Reg))
1749 return false;
1750 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
1751 !MRI->constrainRegClass(Reg, OpRegCstraints))
1752 return false;
1753 }
1754
1755 return true;
1756}
1757
1758/// Return the opcode that does not set flags when possible - otherwise
1759/// return the original opcode. The caller is responsible to do the actual
1760/// substitution and legality checking.
1762 // Don't convert all compare instructions, because for some the zero register
1763 // encoding becomes the sp register.
1764 bool MIDefinesZeroReg = false;
1765 if (MI.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
1766 MI.definesRegister(AArch64::XZR, /*TRI=*/nullptr))
1767 MIDefinesZeroReg = true;
1768
1769 switch (MI.getOpcode()) {
1770 default:
1771 return MI.getOpcode();
1772 case AArch64::ADDSWrr:
1773 return AArch64::ADDWrr;
1774 case AArch64::ADDSWri:
1775 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1776 case AArch64::ADDSWrs:
1777 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1778 case AArch64::ADDSWrx:
1779 return AArch64::ADDWrx;
1780 case AArch64::ADDSXrr:
1781 return AArch64::ADDXrr;
1782 case AArch64::ADDSXri:
1783 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1784 case AArch64::ADDSXrs:
1785 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1786 case AArch64::ADDSXrx:
1787 return AArch64::ADDXrx;
1788 case AArch64::SUBSWrr:
1789 return AArch64::SUBWrr;
1790 case AArch64::SUBSWri:
1791 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1792 case AArch64::SUBSWrs:
1793 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1794 case AArch64::SUBSWrx:
1795 return AArch64::SUBWrx;
1796 case AArch64::SUBSXrr:
1797 return AArch64::SUBXrr;
1798 case AArch64::SUBSXri:
1799 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1800 case AArch64::SUBSXrs:
1801 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1802 case AArch64::SUBSXrx:
1803 return AArch64::SUBXrx;
1804 }
1805}
1806
1807enum AccessKind { AK_Write = 0x01, AK_Read = 0x10, AK_All = 0x11 };
1808
1809/// True when condition flags are accessed (either by writing or reading)
1810/// on the instruction trace starting at From and ending at To.
1811///
1812/// Note: If From and To are from different blocks it's assumed CC are accessed
1813/// on the path.
1816 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
1817 // Early exit if To is at the beginning of the BB.
1818 if (To == To->getParent()->begin())
1819 return true;
1820
1821 // Check whether the instructions are in the same basic block
1822 // If not, assume the condition flags might get modified somewhere.
1823 if (To->getParent() != From->getParent())
1824 return true;
1825
1826 // From must be above To.
1827 assert(std::any_of(
1828 ++To.getReverse(), To->getParent()->rend(),
1829 [From](MachineInstr &MI) { return MI.getIterator() == From; }));
1830
1831 // We iterate backward starting at \p To until we hit \p From.
1832 for (const MachineInstr &Instr :
1834 if (((AccessToCheck & AK_Write) &&
1835 Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
1836 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
1837 return true;
1838 }
1839 return false;
1840}
1841
1842std::optional<unsigned>
1843AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1844 MachineInstr *Pred,
1845 const MachineRegisterInfo *MRI) const {
1846 unsigned MaskOpcode = Mask->getOpcode();
1847 unsigned PredOpcode = Pred->getOpcode();
1848 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1849 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1850
1851 if (PredIsWhileLike) {
1852 // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1853 // instruction and the condition is "any" since WHILcc does an implicit
1854 // PTEST(ALL, PG) check and PG is always a subset of ALL.
1855 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1856 return PredOpcode;
1857
1858 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1859 // redundant since WHILE performs an implicit PTEST with an all active
1860 // mask.
1861 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1862 getElementSizeForOpcode(MaskOpcode) ==
1863 getElementSizeForOpcode(PredOpcode))
1864 return PredOpcode;
1865
1866 // For PTEST_FIRST(PTRUE_ALL, WHILE), the PTEST_FIRST is redundant since
1867 // WHILEcc performs an implicit PTEST with an all active mask, setting
1868 // the N flag as the PTEST_FIRST would.
1869 if (PTest->getOpcode() == AArch64::PTEST_PP_FIRST &&
1870 isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31)
1871 return PredOpcode;
1872
1873 return {};
1874 }
1875
1876 if (PredIsPTestLike) {
1877 // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1878 // instruction that sets the flags as PTEST would and the condition is
1879 // "any" since PG is always a subset of the governing predicate of the
1880 // ptest-like instruction.
1881 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1882 return PredOpcode;
1883
1884 auto PTestLikeMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1885
1886 // If the PTEST like instruction's general predicate is not `Mask`, attempt
1887 // to look through a copy and try again. This is because some instructions
1888 // take a predicate whose register class is a subset of its result class.
1889 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1890 PTestLikeMask->getOperand(1).getReg().isVirtual())
1891 PTestLikeMask =
1892 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1893
1894 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1895 // the element size matches and either the PTEST_LIKE instruction uses
1896 // the same all active mask or the condition is "any".
1897 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1898 getElementSizeForOpcode(MaskOpcode) ==
1899 getElementSizeForOpcode(PredOpcode)) {
1900 if (Mask == PTestLikeMask || PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1901 return PredOpcode;
1902 }
1903
1904 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
1905 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
1906 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
1907 // compare that also support 16/32/64-bit predicates, the implicit PTEST
1908 // performed by the compare could consider fewer lanes for these element
1909 // sizes.
1910 //
1911 // For example, consider
1912 //
1913 // ptrue p0.b ; P0=1111-1111-1111-1111
1914 // index z0.s, #0, #1 ; Z0=<0,1,2,3>
1915 // index z1.s, #1, #1 ; Z1=<1,2,3,4>
1916 // cmphi p1.s, p0/z, z1.s, z0.s ; P1=0001-0001-0001-0001
1917 // ; ^ last active
1918 // ptest p0, p1.b ; P1=0001-0001-0001-0001
1919 // ; ^ last active
1920 //
1921 // where the compare generates a canonical all active 32-bit predicate
1922 // (equivalent to 'ptrue p1.s, all'). The implicit PTEST sets the last
1923 // active flag, whereas the PTEST instruction with the same mask doesn't.
1924 // For PTEST_ANY this doesn't apply as the flags in this case would be
1925 // identical regardless of element size.
1926 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1927 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1928 PTest->getOpcode() == AArch64::PTEST_PP_ANY))
1929 return PredOpcode;
1930
1931 return {};
1932 }
1933
1934 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1935 // opcode so the PTEST becomes redundant.
1936 switch (PredOpcode) {
1937 case AArch64::AND_PPzPP:
1938 case AArch64::BIC_PPzPP:
1939 case AArch64::EOR_PPzPP:
1940 case AArch64::NAND_PPzPP:
1941 case AArch64::NOR_PPzPP:
1942 case AArch64::ORN_PPzPP:
1943 case AArch64::ORR_PPzPP:
1944 case AArch64::BRKA_PPzP:
1945 case AArch64::BRKPA_PPzPP:
1946 case AArch64::BRKB_PPzP:
1947 case AArch64::BRKPB_PPzPP:
1948 case AArch64::RDFFR_PPz: {
1949 // Check to see if our mask is the same. If not the resulting flag bits
1950 // may be different and we can't remove the ptest.
1951 auto *PredMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1952 if (Mask != PredMask)
1953 return {};
1954 break;
1955 }
1956 case AArch64::BRKN_PPzP: {
1957 // BRKN uses an all active implicit mask to set flags unlike the other
1958 // flag-setting instructions.
1959 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1960 if ((MaskOpcode != AArch64::PTRUE_B) ||
1961 (Mask->getOperand(1).getImm() != 31))
1962 return {};
1963 break;
1964 }
1965 case AArch64::PTRUE_B:
1966 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1967 break;
1968 default:
1969 // Bail out if we don't recognize the input
1970 return {};
1971 }
1972
1973 return convertToFlagSettingOpc(PredOpcode);
1974}
1975
1976/// optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
1977/// operation which could set the flags in an identical manner
1978bool AArch64InstrInfo::optimizePTestInstr(
1979 MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
1980 const MachineRegisterInfo *MRI) const {
1981 auto *Mask = MRI->getUniqueVRegDef(MaskReg);
1982 auto *Pred = MRI->getUniqueVRegDef(PredReg);
1983
1984 if (Pred->isCopy() && PTest->getOpcode() == AArch64::PTEST_PP_FIRST) {
1985 // Instructions which return a multi-vector (e.g. WHILECC_x2) require copies
1986 // before the branch to extract each subregister.
1987 auto Op = Pred->getOperand(1);
1988 if (Op.isReg() && Op.getReg().isVirtual() &&
1989 Op.getSubReg() == AArch64::psub0)
1990 Pred = MRI->getUniqueVRegDef(Op.getReg());
1991 }
1992
1993 unsigned PredOpcode = Pred->getOpcode();
1994 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
1995 if (!NewOp)
1996 return false;
1997
1998 const TargetRegisterInfo *TRI = &getRegisterInfo();
1999
2000 // If another instruction between Pred and PTest accesses flags, don't remove
2001 // the ptest or update the earlier instruction to modify them.
2002 if (areCFlagsAccessedBetweenInstrs(Pred, PTest, TRI))
2003 return false;
2004
2005 // If we pass all the checks, it's safe to remove the PTEST and use the flags
2006 // as they are prior to PTEST. Sometimes this requires the tested PTEST
2007 // operand to be replaced with an equivalent instruction that also sets the
2008 // flags.
2009 PTest->eraseFromParent();
2010 if (*NewOp != PredOpcode) {
2011 Pred->setDesc(get(*NewOp));
2012 bool succeeded = UpdateOperandRegClass(*Pred);
2013 (void)succeeded;
2014 assert(succeeded && "Operands have incompatible register classes!");
2015 Pred->addRegisterDefined(AArch64::NZCV, TRI);
2016 }
2017
2018 // Ensure that the flags def is live.
2019 if (Pred->registerDefIsDead(AArch64::NZCV, TRI)) {
2020 unsigned i = 0, e = Pred->getNumOperands();
2021 for (; i != e; ++i) {
2022 MachineOperand &MO = Pred->getOperand(i);
2023 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::NZCV) {
2024 MO.setIsDead(false);
2025 break;
2026 }
2027 }
2028 }
2029 return true;
2030}
2031
2032/// Try to optimize a compare instruction. A compare instruction is an
2033/// instruction which produces AArch64::NZCV. It can be truly compare
2034/// instruction
2035/// when there are no uses of its destination register.
2036///
2037/// The following steps are tried in order:
2038/// 1. Convert CmpInstr into an unconditional version.
2039/// 2. Remove CmpInstr if above there is an instruction producing a needed
2040/// condition code or an instruction which can be converted into such an
2041/// instruction.
2042/// Only comparison with zero is supported.
2044 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
2045 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
2046 assert(CmpInstr.getParent());
2047 assert(MRI);
2048
2049 // Replace SUBSWrr with SUBWrr if NZCV is not used.
2050 int DeadNZCVIdx =
2051 CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
2052 if (DeadNZCVIdx != -1) {
2053 if (CmpInstr.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
2054 CmpInstr.definesRegister(AArch64::XZR, /*TRI=*/nullptr)) {
2055 CmpInstr.eraseFromParent();
2056 return true;
2057 }
2058 unsigned Opc = CmpInstr.getOpcode();
2059 unsigned NewOpc = convertToNonFlagSettingOpc(CmpInstr);
2060 if (NewOpc == Opc)
2061 return false;
2062 const MCInstrDesc &MCID = get(NewOpc);
2063 CmpInstr.setDesc(MCID);
2064 CmpInstr.removeOperand(DeadNZCVIdx);
2065 bool succeeded = UpdateOperandRegClass(CmpInstr);
2066 (void)succeeded;
2067 assert(succeeded && "Some operands reg class are incompatible!");
2068 return true;
2069 }
2070
2071 if (CmpInstr.getOpcode() == AArch64::PTEST_PP ||
2072 CmpInstr.getOpcode() == AArch64::PTEST_PP_ANY ||
2073 CmpInstr.getOpcode() == AArch64::PTEST_PP_FIRST)
2074 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2075
2076 if (SrcReg2 != 0)
2077 return false;
2078
2079 // CmpInstr is a Compare instruction if destination register is not used.
2080 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
2081 return false;
2082
2083 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2084 return true;
2085 return (CmpValue == 0 || CmpValue == 1) &&
2086 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2087}
2088
2089/// Get opcode of S version of Instr.
2090/// If Instr is S version its opcode is returned.
2091/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
2092/// or we are not interested in it.
2093static unsigned sForm(MachineInstr &Instr) {
2094 switch (Instr.getOpcode()) {
2095 default:
2096 return AArch64::INSTRUCTION_LIST_END;
2097
2098 case AArch64::ADDSWrr:
2099 case AArch64::ADDSWri:
2100 case AArch64::ADDSXrr:
2101 case AArch64::ADDSXri:
2102 case AArch64::ADDSWrx:
2103 case AArch64::ADDSXrx:
2104 case AArch64::ADDSWrs:
2105 case AArch64::ADDSXrs:
2106 case AArch64::SUBSWrr:
2107 case AArch64::SUBSWri:
2108 case AArch64::SUBSWrx:
2109 case AArch64::SUBSWrs:
2110 case AArch64::SUBSXrr:
2111 case AArch64::SUBSXri:
2112 case AArch64::SUBSXrx:
2113 case AArch64::SUBSXrs:
2114 case AArch64::ANDSWri:
2115 case AArch64::ANDSWrr:
2116 case AArch64::ANDSWrs:
2117 case AArch64::ANDSXri:
2118 case AArch64::ANDSXrr:
2119 case AArch64::ANDSXrs:
2120 case AArch64::BICSWrr:
2121 case AArch64::BICSXrr:
2122 case AArch64::BICSWrs:
2123 case AArch64::BICSXrs:
2124 case AArch64::ADCSWr:
2125 case AArch64::ADCSXr:
2126 case AArch64::SBCSWr:
2127 case AArch64::SBCSXr:
2128 return Instr.getOpcode();
2129
2130 case AArch64::ADDWrr:
2131 return AArch64::ADDSWrr;
2132 case AArch64::ADDWri:
2133 return AArch64::ADDSWri;
2134 case AArch64::ADDXrr:
2135 return AArch64::ADDSXrr;
2136 case AArch64::ADDXri:
2137 return AArch64::ADDSXri;
2138 case AArch64::ADDWrx:
2139 return AArch64::ADDSWrx;
2140 case AArch64::ADDXrx:
2141 return AArch64::ADDSXrx;
2142 case AArch64::ADDWrs:
2143 return AArch64::ADDSWrs;
2144 case AArch64::ADDXrs:
2145 return AArch64::ADDSXrs;
2146 case AArch64::ADCWr:
2147 return AArch64::ADCSWr;
2148 case AArch64::ADCXr:
2149 return AArch64::ADCSXr;
2150 case AArch64::SUBWrr:
2151 return AArch64::SUBSWrr;
2152 case AArch64::SUBWri:
2153 return AArch64::SUBSWri;
2154 case AArch64::SUBXrr:
2155 return AArch64::SUBSXrr;
2156 case AArch64::SUBXri:
2157 return AArch64::SUBSXri;
2158 case AArch64::SUBWrx:
2159 return AArch64::SUBSWrx;
2160 case AArch64::SUBXrx:
2161 return AArch64::SUBSXrx;
2162 case AArch64::SUBWrs:
2163 return AArch64::SUBSWrs;
2164 case AArch64::SUBXrs:
2165 return AArch64::SUBSXrs;
2166 case AArch64::SBCWr:
2167 return AArch64::SBCSWr;
2168 case AArch64::SBCXr:
2169 return AArch64::SBCSXr;
2170 case AArch64::ANDWri:
2171 return AArch64::ANDSWri;
2172 case AArch64::ANDXri:
2173 return AArch64::ANDSXri;
2174 case AArch64::ANDWrr:
2175 return AArch64::ANDSWrr;
2176 case AArch64::ANDWrs:
2177 return AArch64::ANDSWrs;
2178 case AArch64::ANDXrr:
2179 return AArch64::ANDSXrr;
2180 case AArch64::ANDXrs:
2181 return AArch64::ANDSXrs;
2182 case AArch64::BICWrr:
2183 return AArch64::BICSWrr;
2184 case AArch64::BICXrr:
2185 return AArch64::BICSXrr;
2186 case AArch64::BICWrs:
2187 return AArch64::BICSWrs;
2188 case AArch64::BICXrs:
2189 return AArch64::BICSXrs;
2190 }
2191}
2192
2193/// Check if AArch64::NZCV should be alive in successors of MBB.
2195 for (auto *BB : MBB->successors())
2196 if (BB->isLiveIn(AArch64::NZCV))
2197 return true;
2198 return false;
2199}
2200
2201/// \returns The condition code operand index for \p Instr if it is a branch
2202/// or select and -1 otherwise.
2203int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2204 const MachineInstr &Instr) {
2205 switch (Instr.getOpcode()) {
2206 default:
2207 return -1;
2208
2209 case AArch64::Bcc: {
2210 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2211 assert(Idx >= 2);
2212 return Idx - 2;
2213 }
2214
2215 case AArch64::CSINVWr:
2216 case AArch64::CSINVXr:
2217 case AArch64::CSINCWr:
2218 case AArch64::CSINCXr:
2219 case AArch64::CSELWr:
2220 case AArch64::CSELXr:
2221 case AArch64::CSNEGWr:
2222 case AArch64::CSNEGXr:
2223 case AArch64::FCSELSrrr:
2224 case AArch64::FCSELDrrr: {
2225 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2226 assert(Idx >= 1);
2227 return Idx - 1;
2228 }
2229 }
2230}
2231
2232/// Find a condition code used by the instruction.
2233/// Returns AArch64CC::Invalid if either the instruction does not use condition
2234/// codes or we don't optimize CmpInstr in the presence of such instructions.
2236 int CCIdx =
2237 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2238 return CCIdx >= 0 ? static_cast<AArch64CC::CondCode>(
2239 Instr.getOperand(CCIdx).getImm())
2241}
2242
2245 UsedNZCV UsedFlags;
2246 switch (CC) {
2247 default:
2248 break;
2249
2250 case AArch64CC::EQ: // Z set
2251 case AArch64CC::NE: // Z clear
2252 UsedFlags.Z = true;
2253 break;
2254
2255 case AArch64CC::HI: // Z clear and C set
2256 case AArch64CC::LS: // Z set or C clear
2257 UsedFlags.Z = true;
2258 [[fallthrough]];
2259 case AArch64CC::HS: // C set
2260 case AArch64CC::LO: // C clear
2261 UsedFlags.C = true;
2262 break;
2263
2264 case AArch64CC::MI: // N set
2265 case AArch64CC::PL: // N clear
2266 UsedFlags.N = true;
2267 break;
2268
2269 case AArch64CC::VS: // V set
2270 case AArch64CC::VC: // V clear
2271 UsedFlags.V = true;
2272 break;
2273
2274 case AArch64CC::GT: // Z clear, N and V the same
2275 case AArch64CC::LE: // Z set, N and V differ
2276 UsedFlags.Z = true;
2277 [[fallthrough]];
2278 case AArch64CC::GE: // N and V the same
2279 case AArch64CC::LT: // N and V differ
2280 UsedFlags.N = true;
2281 UsedFlags.V = true;
2282 break;
2283 }
2284 return UsedFlags;
2285}
2286
2287/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
2288/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
2289/// \returns std::nullopt otherwise.
2290///
2291/// Collect instructions using that flags in \p CCUseInstrs if provided.
2292std::optional<UsedNZCV>
2294 const TargetRegisterInfo &TRI,
2295 SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
2296 MachineBasicBlock *CmpParent = CmpInstr.getParent();
2297 if (MI.getParent() != CmpParent)
2298 return std::nullopt;
2299
2300 if (areCFlagsAliveInSuccessors(CmpParent))
2301 return std::nullopt;
2302
2303 UsedNZCV NZCVUsedAfterCmp;
2305 std::next(CmpInstr.getIterator()), CmpParent->instr_end())) {
2306 if (Instr.readsRegister(AArch64::NZCV, &TRI)) {
2308 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
2309 return std::nullopt;
2310 NZCVUsedAfterCmp |= getUsedNZCV(CC);
2311 if (CCUseInstrs)
2312 CCUseInstrs->push_back(&Instr);
2313 }
2314 if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
2315 break;
2316 }
2317 return NZCVUsedAfterCmp;
2318}
2319
2320static bool isADDSRegImm(unsigned Opcode) {
2321 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2322}
2323
2324static bool isSUBSRegImm(unsigned Opcode) {
2325 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2326}
2327
2329 unsigned Opc = sForm(MI);
2330 switch (Opc) {
2331 case AArch64::ANDSWri:
2332 case AArch64::ANDSWrr:
2333 case AArch64::ANDSWrs:
2334 case AArch64::ANDSXri:
2335 case AArch64::ANDSXrr:
2336 case AArch64::ANDSXrs:
2337 case AArch64::BICSWrr:
2338 case AArch64::BICSXrr:
2339 case AArch64::BICSWrs:
2340 case AArch64::BICSXrs:
2341 return true;
2342 default:
2343 return false;
2344 }
2345}
2346
2347/// Check if CmpInstr can be substituted by MI.
2348///
2349/// CmpInstr can be substituted:
2350/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2351/// - and, MI and CmpInstr are from the same MachineBB
2352/// - and, condition flags are not alive in successors of the CmpInstr parent
2353/// - and, if MI opcode is the S form there must be no defs of flags between
2354/// MI and CmpInstr
2355/// or if MI opcode is not the S form there must be neither defs of flags
2356/// nor uses of flags between MI and CmpInstr.
2357/// - and, C is not used after CmpInstr; CmpInstr's C is from adds/subs #0 on
2358/// SrcReg and can differ from MI (e.g. carry out of ADCS/SBCS).
2359/// - and, V is not used after CmpInstr unless MI is AND/BIC (V cleared) or MI
2360/// has NoSWrap (overflow is poison and the fold is still safe).
2362 const TargetRegisterInfo &TRI) {
2363 // MI is an opcode sForm maps (add/sub/adc/sbc/and/bic and their S forms).
2364 assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END);
2365
2366 const unsigned CmpOpcode = CmpInstr.getOpcode();
2367 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
2368 return false;
2369
2370 assert((CmpInstr.getOperand(2).isImm() &&
2371 CmpInstr.getOperand(2).getImm() == 0) &&
2372 "Caller guarantees that CmpInstr compares with constant 0");
2373
2374 std::optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
2375 if (!NZVCUsed || NZVCUsed->C)
2376 return false;
2377
2378 // CmpInstr is ADDS/SUBS with immediate 0 on SrcReg (compare SrcReg to zero).
2379 // After the fold, users see NZCV from MI (or its S form), not from CmpInstr.
2380 // N/Z match CmpInstr for the value in SrcReg; C/V need not match in general
2381 // (e.g. ADCS vs adds #0), so we require C unused after CmpInstr and gate V
2382 // as below. NoSWrap makes signed overflow poison; AND/BIC clear V.
2383 if (NZVCUsed->V && !MI.getFlag(MachineInstr::NoSWrap) && !isANDOpcode(MI))
2384 return false;
2385
2386 AccessKind AccessToCheck = AK_Write;
2387 if (sForm(MI) != MI.getOpcode())
2388 AccessToCheck = AK_All;
2389 return !areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AccessToCheck);
2390}
2391
2392/// Substitute an instruction comparing to zero with another instruction
2393/// which produces needed condition flags.
2394///
2395/// Return true on success.
2396bool AArch64InstrInfo::substituteCmpToZero(
2397 MachineInstr &CmpInstr, unsigned SrcReg,
2398 const MachineRegisterInfo &MRI) const {
2399 // Get the unique definition of SrcReg.
2400 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2401 if (!MI)
2402 return false;
2403
2404 const TargetRegisterInfo &TRI = getRegisterInfo();
2405
2406 unsigned NewOpc = sForm(*MI);
2407 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2408 return false;
2409
2410 if (!canInstrSubstituteCmpInstr(*MI, CmpInstr, TRI))
2411 return false;
2412
2413 // Update the instruction to set NZCV.
2414 MI->setDesc(get(NewOpc));
2415 CmpInstr.eraseFromParent();
2417 (void)succeeded;
2418 assert(succeeded && "Some operands reg class are incompatible!");
2419 MI->addRegisterDefined(AArch64::NZCV, &TRI);
2420 return true;
2421}
2422
2423/// \returns True if \p CmpInstr can be removed.
2424///
2425/// \p IsInvertCC is true if, after removing \p CmpInstr, condition
2426/// codes used in \p CCUseInstrs must be inverted.
2428 int CmpValue, const TargetRegisterInfo &TRI,
2430 bool &IsInvertCC) {
2431 assert((CmpValue == 0 || CmpValue == 1) &&
2432 "Only comparisons to 0 or 1 considered for removal!");
2433
2434 // MI is 'CSINCWr %vreg, wzr, wzr, <cc>' or 'CSINCXr %vreg, xzr, xzr, <cc>'
2435 unsigned MIOpc = MI.getOpcode();
2436 if (MIOpc == AArch64::CSINCWr) {
2437 if (MI.getOperand(1).getReg() != AArch64::WZR ||
2438 MI.getOperand(2).getReg() != AArch64::WZR)
2439 return false;
2440 } else if (MIOpc == AArch64::CSINCXr) {
2441 if (MI.getOperand(1).getReg() != AArch64::XZR ||
2442 MI.getOperand(2).getReg() != AArch64::XZR)
2443 return false;
2444 } else {
2445 return false;
2446 }
2448 if (MICC == AArch64CC::Invalid)
2449 return false;
2450
2451 // NZCV needs to be defined
2452 if (MI.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) != -1)
2453 return false;
2454
2455 // CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0' or 'SUBS %vreg, 1'
2456 const unsigned CmpOpcode = CmpInstr.getOpcode();
2457 bool IsSubsRegImm = isSUBSRegImm(CmpOpcode);
2458 if (CmpValue && !IsSubsRegImm)
2459 return false;
2460 if (!CmpValue && !IsSubsRegImm && !isADDSRegImm(CmpOpcode))
2461 return false;
2462
2463 // MI conditions allowed: eq, ne, mi, pl
2464 UsedNZCV MIUsedNZCV = getUsedNZCV(MICC);
2465 if (MIUsedNZCV.C || MIUsedNZCV.V)
2466 return false;
2467
2468 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2469 examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
2470 // Condition flags are not used in CmpInstr basic block successors and only
2471 // Z or N flags allowed to be used after CmpInstr within its basic block
2472 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2473 return false;
2474 // Z or N flag used after CmpInstr must correspond to the flag used in MI
2475 if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||
2476 (MIUsedNZCV.N && NZCVUsedAfterCmp->Z))
2477 return false;
2478 // If CmpInstr is comparison to zero MI conditions are limited to eq, ne
2479 if (MIUsedNZCV.N && !CmpValue)
2480 return false;
2481
2482 // There must be no defs of flags between MI and CmpInstr
2483 if (areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AK_Write))
2484 return false;
2485
2486 // Condition code is inverted in the following cases:
2487 // 1. MI condition is ne; CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2488 // 2. MI condition is eq, pl; CmpInstr is 'SUBS %vreg, 1'
2489 IsInvertCC = (CmpValue && (MICC == AArch64CC::EQ || MICC == AArch64CC::PL)) ||
2490 (!CmpValue && MICC == AArch64CC::NE);
2491 return true;
2492}
2493
2494/// Remove comparison in csinc-cmp sequence
2495///
2496/// Examples:
2497/// 1. \code
2498/// csinc w9, wzr, wzr, ne
2499/// cmp w9, #0
2500/// b.eq
2501/// \endcode
2502/// to
2503/// \code
2504/// csinc w9, wzr, wzr, ne
2505/// b.ne
2506/// \endcode
2507///
2508/// 2. \code
2509/// csinc x2, xzr, xzr, mi
2510/// cmp x2, #1
2511/// b.pl
2512/// \endcode
2513/// to
2514/// \code
2515/// csinc x2, xzr, xzr, mi
2516/// b.pl
2517/// \endcode
2518///
2519/// \param CmpInstr comparison instruction
2520/// \return True when comparison removed
2521bool AArch64InstrInfo::removeCmpToZeroOrOne(
2522 MachineInstr &CmpInstr, unsigned SrcReg, int CmpValue,
2523 const MachineRegisterInfo &MRI) const {
2524 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2525 if (!MI)
2526 return false;
2527 const TargetRegisterInfo &TRI = getRegisterInfo();
2528 SmallVector<MachineInstr *, 4> CCUseInstrs;
2529 bool IsInvertCC = false;
2530 if (!canCmpInstrBeRemoved(*MI, CmpInstr, CmpValue, TRI, CCUseInstrs,
2531 IsInvertCC))
2532 return false;
2533 // Make transformation
2534 CmpInstr.eraseFromParent();
2535 if (IsInvertCC) {
2536 // Invert condition codes in CmpInstr CC users
2537 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2538 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2539 assert(Idx >= 0 && "Unexpected instruction using CC.");
2540 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2542 static_cast<AArch64CC::CondCode>(CCOperand.getImm()));
2543 CCOperand.setImm(CCUse);
2544 }
2545 }
2546 return true;
2547}
2548
2549bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
2550 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2551 MI.getOpcode() != AArch64::CATCHRET &&
2552 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2553 return false;
2554
2555 MachineBasicBlock &MBB = *MI.getParent();
2556 auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
2557 auto TRI = Subtarget.getRegisterInfo();
2558 DebugLoc DL = MI.getDebugLoc();
2559
2560 if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2561 // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
2562 // This computes FP - stored_mixed_value to unmix the cookie
2563 Register DstReg = MI.getOperand(0).getReg();
2564 Register SrcReg = MI.getOperand(1).getReg();
2565
2566 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
2567 .addReg(AArch64::FP)
2568 .addReg(SrcReg);
2569
2570 MBB.erase(MI);
2571 return true;
2572 }
2573
2574 if (MI.getOpcode() == AArch64::CATCHRET) {
2575 // Skip to the first instruction before the epilog.
2576 const TargetInstrInfo *TII =
2578 MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
2580 MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
2581 while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
2582 FirstEpilogSEH != MBB.begin())
2583 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2584 if (FirstEpilogSEH != MBB.begin())
2585 FirstEpilogSEH = std::next(FirstEpilogSEH);
2586 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
2587 .addReg(AArch64::X0, RegState::Define)
2588 .addMBB(TargetMBB);
2589 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
2590 .addReg(AArch64::X0, RegState::Define)
2591 .addReg(AArch64::X0)
2592 .addMBB(TargetMBB)
2593 .addImm(0);
2594 TargetMBB->setMachineBlockAddressTaken();
2595 return true;
2596 }
2597
2598 Register Reg = MI.getOperand(0).getReg();
2600 if (M.getStackProtectorGuard() == "sysreg") {
2601 const AArch64SysReg::SysReg *SrcReg =
2602 AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg());
2603 if (!SrcReg)
2604 report_fatal_error("Unknown SysReg for Stack Protector Guard Register");
2605
2606 // mrs xN, sysreg
2607 BuildMI(MBB, MI, DL, get(AArch64::MRS))
2609 .addImm(SrcReg->Encoding);
2610 int Offset = M.getStackProtectorGuardOffset();
2611 if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) {
2612 // ldr xN, [xN, #offset]
2613 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2614 .addDef(Reg)
2616 .addImm(Offset / 8);
2617 } else if (Offset >= -256 && Offset <= 255) {
2618 // ldur xN, [xN, #offset]
2619 BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
2620 .addDef(Reg)
2622 .addImm(Offset);
2623 } else if (Offset >= -4095 && Offset <= 4095) {
2624 if (Offset > 0) {
2625 // add xN, xN, #offset
2626 BuildMI(MBB, MI, DL, get(AArch64::ADDXri))
2627 .addDef(Reg)
2629 .addImm(Offset)
2630 .addImm(0);
2631 } else {
2632 // sub xN, xN, #offset
2633 BuildMI(MBB, MI, DL, get(AArch64::SUBXri))
2634 .addDef(Reg)
2636 .addImm(-Offset)
2637 .addImm(0);
2638 }
2639 // ldr xN, [xN]
2640 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2641 .addDef(Reg)
2643 .addImm(0);
2644 } else {
2645 // Cases that are larger than +/- 4095 and not a multiple of 8, or larger
2646 // than 23760.
2647 // It might be nice to use AArch64::MOVi32imm here, which would get
2648 // expanded in PreSched2 after PostRA, but our lone scratch Reg already
2649 // contains the MRS result. findScratchNonCalleeSaveRegister() in
2650 // AArch64FrameLowering might help us find such a scratch register
2651 // though. If we failed to find a scratch register, we could emit a
2652 // stream of add instructions to build up the immediate. Or, we could try
2653 // to insert a AArch64::MOVi32imm before register allocation so that we
2654 // didn't need to scavenge for a scratch register.
2655 report_fatal_error("Unable to encode Stack Protector Guard Offset");
2656 }
2657 MBB.erase(MI);
2658 return true;
2659 }
2660
2661 const GlobalValue *GV =
2662 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
2663 const TargetMachine &TM = MBB.getParent()->getTarget();
2664 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2665 const unsigned char MO_NC = AArch64II::MO_NC;
2666
2667 unsigned GuardWidth = M.getStackProtectorGuardValueWidth().value_or(
2668 Subtarget.isTargetILP32() ? 4 : 8);
2669 if (GuardWidth != 4 && GuardWidth != 8)
2670 report_fatal_error("Unsupported stack protector value width");
2671 if ((OpFlags & AArch64II::MO_GOT) != 0) {
2672 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
2673 .addGlobalAddress(GV, 0, OpFlags);
2674 if (GuardWidth == 4) {
2675 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2676 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2677 .addDef(Reg32, RegState::Dead)
2679 .addImm(0)
2680 .addMemOperand(*MI.memoperands_begin())
2682 } else {
2683 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2685 .addImm(0)
2686 .addMemOperand(*MI.memoperands_begin());
2687 }
2688 } else if (TM.getCodeModel() == CodeModel::Large) {
2689 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
2690 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
2691 .addImm(0);
2692 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2694 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC)
2695 .addImm(16);
2696 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2698 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC)
2699 .addImm(32);
2700 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2703 .addImm(48);
2704 if (GuardWidth == 4) {
2705 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2706 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2707 .addDef(Reg32, RegState::Dead)
2709 .addImm(0)
2710 .addMemOperand(*MI.memoperands_begin())
2712 } else {
2713 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2715 .addImm(0)
2716 .addMemOperand(*MI.memoperands_begin());
2717 }
2718 } else {
2719 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
2720 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
2721 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
2722 if (GuardWidth == 4) {
2723 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2724 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2725 .addDef(Reg32, RegState::Dead)
2727 .addGlobalAddress(GV, 0, LoFlags)
2728 .addMemOperand(*MI.memoperands_begin())
2730 } else {
2731 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2733 .addGlobalAddress(GV, 0, LoFlags)
2734 .addMemOperand(*MI.memoperands_begin());
2735 }
2736 }
2737 // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
2738 // we use sub instruction to mix the cookie on aarch64.
2739 // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
2740 // the final frame pointer value.
2741 if (Subtarget.getTargetTriple().isOSMSVCRT())
2742 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
2743 .addReg(AArch64::FP)
2745
2746 MBB.erase(MI);
2747
2748 return true;
2749}
2750
2751// Return true if this instruction simply sets its single destination register
2752// to zero. This is equivalent to a register rename of the zero-register.
2754 switch (MI.getOpcode()) {
2755 default:
2756 break;
2757 case AArch64::MOVZWi:
2758 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
2759 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
2760 assert(MI.getDesc().getNumOperands() == 3 &&
2761 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
2762 return true;
2763 }
2764 break;
2765 case AArch64::ANDWri: // and Rd, Rzr, #imm
2766 return MI.getOperand(1).getReg() == AArch64::WZR;
2767 case AArch64::ANDXri:
2768 return MI.getOperand(1).getReg() == AArch64::XZR;
2769 case TargetOpcode::COPY:
2770 return MI.getOperand(1).getReg() == AArch64::WZR;
2771 }
2772 return false;
2773}
2774
2775// Return true if this instruction simply renames a general register without
2776// modifying bits.
2778 switch (MI.getOpcode()) {
2779 default:
2780 break;
2781 case TargetOpcode::COPY: {
2782 // GPR32 copies will by lowered to ORRXrs
2783 Register DstReg = MI.getOperand(0).getReg();
2784 return (AArch64::GPR32RegClass.contains(DstReg) ||
2785 AArch64::GPR64RegClass.contains(DstReg));
2786 }
2787 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
2788 if (MI.getOperand(1).getReg() == AArch64::XZR) {
2789 assert(MI.getDesc().getNumOperands() == 4 &&
2790 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
2791 return true;
2792 }
2793 break;
2794 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
2795 if (MI.getOperand(2).getImm() == 0) {
2796 assert(MI.getDesc().getNumOperands() == 4 &&
2797 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
2798 return true;
2799 }
2800 break;
2801 }
2802 return false;
2803}
2804
2805// Return true if this instruction simply renames a general register without
2806// modifying bits.
2808 switch (MI.getOpcode()) {
2809 default:
2810 break;
2811 case TargetOpcode::COPY: {
2812 Register DstReg = MI.getOperand(0).getReg();
2813 return AArch64::FPR128RegClass.contains(DstReg);
2814 }
2815 case AArch64::ORRv16i8:
2816 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
2817 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
2818 "invalid ORRv16i8 operands");
2819 return true;
2820 }
2821 break;
2822 }
2823 return false;
2824}
2825
2826static bool isFrameLoadOpcode(int Opcode) {
2827 switch (Opcode) {
2828 default:
2829 return false;
2830 case AArch64::LDRWui:
2831 case AArch64::LDRXui:
2832 case AArch64::LDRBui:
2833 case AArch64::LDRHui:
2834 case AArch64::LDRSui:
2835 case AArch64::LDRDui:
2836 case AArch64::LDRQui:
2837 case AArch64::LDR_PXI:
2838 return true;
2839 }
2840}
2841
2843 int &FrameIndex) const {
2844 if (!isFrameLoadOpcode(MI.getOpcode()))
2845 return Register();
2846
2847 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2848 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2849 FrameIndex = MI.getOperand(1).getIndex();
2850 return MI.getOperand(0).getReg();
2851 }
2852 return Register();
2853}
2854
2855static bool isFrameStoreOpcode(int Opcode) {
2856 switch (Opcode) {
2857 default:
2858 return false;
2859 case AArch64::STRWui:
2860 case AArch64::STRXui:
2861 case AArch64::STRBui:
2862 case AArch64::STRHui:
2863 case AArch64::STRSui:
2864 case AArch64::STRDui:
2865 case AArch64::STRQui:
2866 case AArch64::STR_PXI:
2867 return true;
2868 }
2869}
2870
2872 int &FrameIndex) const {
2873 if (!isFrameStoreOpcode(MI.getOpcode()))
2874 return Register();
2875
2876 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2877 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2878 FrameIndex = MI.getOperand(1).getIndex();
2879 return MI.getOperand(0).getReg();
2880 }
2881 return Register();
2882}
2883
2885 int &FrameIndex) const {
2886 if (!isFrameStoreOpcode(MI.getOpcode()))
2887 return Register();
2888
2889 if (Register Reg = isStoreToStackSlot(MI, FrameIndex))
2890 return Reg;
2891
2893 if (hasStoreToStackSlot(MI, Accesses)) {
2894 if (Accesses.size() > 1)
2895 return Register();
2896
2897 FrameIndex =
2898 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2899 ->getFrameIndex();
2900 return MI.getOperand(0).getReg();
2901 }
2902 return Register();
2903}
2904
2906 int &FrameIndex) const {
2907 if (!isFrameLoadOpcode(MI.getOpcode()))
2908 return Register();
2909
2910 if (Register Reg = isLoadFromStackSlot(MI, FrameIndex))
2911 return Reg;
2912
2914 if (hasLoadFromStackSlot(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
2926/// Check all MachineMemOperands for a hint to suppress pairing.
2928 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2929 return MMO->getFlags() & MOSuppressPair;
2930 });
2931}
2932
2933/// Set a flag on the first MachineMemOperand to suppress pairing.
2935 if (MI.memoperands_empty())
2936 return;
2937 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
2938}
2939
2940/// Check all MachineMemOperands for a hint that the load/store is strided.
2942 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2943 return MMO->getFlags() & MOStridedAccess;
2944 });
2945}
2946
2948 switch (Opc) {
2949 default:
2950 return false;
2951 case AArch64::STURSi:
2952 case AArch64::STRSpre:
2953 case AArch64::STURDi:
2954 case AArch64::STRDpre:
2955 case AArch64::STURQi:
2956 case AArch64::STRQpre:
2957 case AArch64::STURBBi:
2958 case AArch64::STURHHi:
2959 case AArch64::STURWi:
2960 case AArch64::STRWpre:
2961 case AArch64::STURXi:
2962 case AArch64::STRXpre:
2963 case AArch64::LDURSi:
2964 case AArch64::LDRSpre:
2965 case AArch64::LDURDi:
2966 case AArch64::LDRDpre:
2967 case AArch64::LDURQi:
2968 case AArch64::LDRQpre:
2969 case AArch64::LDURWi:
2970 case AArch64::LDRWpre:
2971 case AArch64::LDURXi:
2972 case AArch64::LDRXpre:
2973 case AArch64::LDRSWpre:
2974 case AArch64::LDURSWi:
2975 case AArch64::LDURHHi:
2976 case AArch64::LDURBBi:
2977 case AArch64::LDURSBWi:
2978 case AArch64::LDURSHWi:
2979 return true;
2980 }
2981}
2982
2983std::optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) {
2984 switch (Opc) {
2985 default: return {};
2986 case AArch64::PRFMui: return AArch64::PRFUMi;
2987 case AArch64::LDRXui: return AArch64::LDURXi;
2988 case AArch64::LDRWui: return AArch64::LDURWi;
2989 case AArch64::LDRBui: return AArch64::LDURBi;
2990 case AArch64::LDRHui: return AArch64::LDURHi;
2991 case AArch64::LDRSui: return AArch64::LDURSi;
2992 case AArch64::LDRDui: return AArch64::LDURDi;
2993 case AArch64::LDRQui: return AArch64::LDURQi;
2994 case AArch64::LDRBBui: return AArch64::LDURBBi;
2995 case AArch64::LDRHHui: return AArch64::LDURHHi;
2996 case AArch64::LDRSBXui: return AArch64::LDURSBXi;
2997 case AArch64::LDRSBWui: return AArch64::LDURSBWi;
2998 case AArch64::LDRSHXui: return AArch64::LDURSHXi;
2999 case AArch64::LDRSHWui: return AArch64::LDURSHWi;
3000 case AArch64::LDRSWui: return AArch64::LDURSWi;
3001 case AArch64::STRXui: return AArch64::STURXi;
3002 case AArch64::STRWui: return AArch64::STURWi;
3003 case AArch64::STRBui: return AArch64::STURBi;
3004 case AArch64::STRHui: return AArch64::STURHi;
3005 case AArch64::STRSui: return AArch64::STURSi;
3006 case AArch64::STRDui: return AArch64::STURDi;
3007 case AArch64::STRQui: return AArch64::STURQi;
3008 case AArch64::STRBBui: return AArch64::STURBBi;
3009 case AArch64::STRHHui: return AArch64::STURHHi;
3010 }
3011}
3012
3014 switch (Opc) {
3015 default:
3016 llvm_unreachable("Unhandled Opcode in getLoadStoreImmIdx");
3017 case AArch64::ADDG:
3018 case AArch64::LDAPURBi:
3019 case AArch64::LDAPURHi:
3020 case AArch64::LDAPURi:
3021 case AArch64::LDAPURSBWi:
3022 case AArch64::LDAPURSBXi:
3023 case AArch64::LDAPURSHWi:
3024 case AArch64::LDAPURSHXi:
3025 case AArch64::LDAPURSWi:
3026 case AArch64::LDAPURXi:
3027 case AArch64::LDR_PPXI:
3028 case AArch64::LDR_PXI:
3029 case AArch64::LDR_ZXI:
3030 case AArch64::LDR_ZZXI:
3031 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3032 case AArch64::LDR_ZZZXI:
3033 case AArch64::LDR_ZZZZXI:
3034 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3035 case AArch64::LDRBBui:
3036 case AArch64::LDRBui:
3037 case AArch64::LDRDui:
3038 case AArch64::LDRHHui:
3039 case AArch64::LDRHui:
3040 case AArch64::LDRQui:
3041 case AArch64::LDRSBWui:
3042 case AArch64::LDRSBXui:
3043 case AArch64::LDRSHWui:
3044 case AArch64::LDRSHXui:
3045 case AArch64::LDRSui:
3046 case AArch64::LDRSWui:
3047 case AArch64::LDRWui:
3048 case AArch64::LDRXui:
3049 case AArch64::LDURBBi:
3050 case AArch64::LDURBi:
3051 case AArch64::LDURDi:
3052 case AArch64::LDURHHi:
3053 case AArch64::LDURHi:
3054 case AArch64::LDURQi:
3055 case AArch64::LDURSBWi:
3056 case AArch64::LDURSBXi:
3057 case AArch64::LDURSHWi:
3058 case AArch64::LDURSHXi:
3059 case AArch64::LDURSi:
3060 case AArch64::LDURSWi:
3061 case AArch64::LDURWi:
3062 case AArch64::LDURXi:
3063 case AArch64::PRFMui:
3064 case AArch64::PRFUMi:
3065 case AArch64::ST2Gi:
3066 case AArch64::STGi:
3067 case AArch64::STLURBi:
3068 case AArch64::STLURHi:
3069 case AArch64::STLURWi:
3070 case AArch64::STLURXi:
3071 case AArch64::StoreSwiftAsyncContext:
3072 case AArch64::STR_PPXI:
3073 case AArch64::STR_PXI:
3074 case AArch64::STR_ZXI:
3075 case AArch64::STR_ZZXI:
3076 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3077 case AArch64::STR_ZZZXI:
3078 case AArch64::STR_ZZZZXI:
3079 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3080 case AArch64::STRBBui:
3081 case AArch64::STRBui:
3082 case AArch64::STRDui:
3083 case AArch64::STRHHui:
3084 case AArch64::STRHui:
3085 case AArch64::STRQui:
3086 case AArch64::STRSui:
3087 case AArch64::STRWui:
3088 case AArch64::STRXui:
3089 case AArch64::STURBBi:
3090 case AArch64::STURBi:
3091 case AArch64::STURDi:
3092 case AArch64::STURHHi:
3093 case AArch64::STURHi:
3094 case AArch64::STURQi:
3095 case AArch64::STURSi:
3096 case AArch64::STURWi:
3097 case AArch64::STURXi:
3098 case AArch64::STZ2Gi:
3099 case AArch64::STZGi:
3100 case AArch64::TAGPstack:
3101 return 2;
3102 case AArch64::LD1B_D_IMM:
3103 case AArch64::LD1B_H_IMM:
3104 case AArch64::LD1B_IMM:
3105 case AArch64::LD1B_S_IMM:
3106 case AArch64::LD1D_IMM:
3107 case AArch64::LD1H_D_IMM:
3108 case AArch64::LD1H_IMM:
3109 case AArch64::LD1H_S_IMM:
3110 case AArch64::LD1RB_D_IMM:
3111 case AArch64::LD1RB_H_IMM:
3112 case AArch64::LD1RB_IMM:
3113 case AArch64::LD1RB_S_IMM:
3114 case AArch64::LD1RD_IMM:
3115 case AArch64::LD1RH_D_IMM:
3116 case AArch64::LD1RH_IMM:
3117 case AArch64::LD1RH_S_IMM:
3118 case AArch64::LD1RSB_D_IMM:
3119 case AArch64::LD1RSB_H_IMM:
3120 case AArch64::LD1RSB_S_IMM:
3121 case AArch64::LD1RSH_D_IMM:
3122 case AArch64::LD1RSH_S_IMM:
3123 case AArch64::LD1RSW_IMM:
3124 case AArch64::LD1RW_D_IMM:
3125 case AArch64::LD1RW_IMM:
3126 case AArch64::LD1SB_D_IMM:
3127 case AArch64::LD1SB_H_IMM:
3128 case AArch64::LD1SB_S_IMM:
3129 case AArch64::LD1SH_D_IMM:
3130 case AArch64::LD1SH_S_IMM:
3131 case AArch64::LD1SW_D_IMM:
3132 case AArch64::LD1W_D_IMM:
3133 case AArch64::LD1W_IMM:
3134 case AArch64::LD2B_IMM:
3135 case AArch64::LD2D_IMM:
3136 case AArch64::LD2H_IMM:
3137 case AArch64::LD2W_IMM:
3138 case AArch64::LD3B_IMM:
3139 case AArch64::LD3D_IMM:
3140 case AArch64::LD3H_IMM:
3141 case AArch64::LD3W_IMM:
3142 case AArch64::LD4B_IMM:
3143 case AArch64::LD4D_IMM:
3144 case AArch64::LD4H_IMM:
3145 case AArch64::LD4W_IMM:
3146 case AArch64::LDG:
3147 case AArch64::LDNF1B_D_IMM:
3148 case AArch64::LDNF1B_H_IMM:
3149 case AArch64::LDNF1B_IMM:
3150 case AArch64::LDNF1B_S_IMM:
3151 case AArch64::LDNF1D_IMM:
3152 case AArch64::LDNF1H_D_IMM:
3153 case AArch64::LDNF1H_IMM:
3154 case AArch64::LDNF1H_S_IMM:
3155 case AArch64::LDNF1SB_D_IMM:
3156 case AArch64::LDNF1SB_H_IMM:
3157 case AArch64::LDNF1SB_S_IMM:
3158 case AArch64::LDNF1SH_D_IMM:
3159 case AArch64::LDNF1SH_S_IMM:
3160 case AArch64::LDNF1SW_D_IMM:
3161 case AArch64::LDNF1W_D_IMM:
3162 case AArch64::LDNF1W_IMM:
3163 case AArch64::LDNPDi:
3164 case AArch64::LDNPQi:
3165 case AArch64::LDNPSi:
3166 case AArch64::LDNPWi:
3167 case AArch64::LDNPXi:
3168 case AArch64::LDNT1B_ZRI:
3169 case AArch64::LDNT1D_ZRI:
3170 case AArch64::LDNT1H_ZRI:
3171 case AArch64::LDNT1W_ZRI:
3172 case AArch64::LDPDi:
3173 case AArch64::LDPQi:
3174 case AArch64::LDPSi:
3175 case AArch64::LDPWi:
3176 case AArch64::LDPXi:
3177 case AArch64::LDRBBpost:
3178 case AArch64::LDRBBpre:
3179 case AArch64::LDRBpost:
3180 case AArch64::LDRBpre:
3181 case AArch64::LDRDpost:
3182 case AArch64::LDRDpre:
3183 case AArch64::LDRHHpost:
3184 case AArch64::LDRHHpre:
3185 case AArch64::LDRHpost:
3186 case AArch64::LDRHpre:
3187 case AArch64::LDRQpost:
3188 case AArch64::LDRQpre:
3189 case AArch64::LDRSpost:
3190 case AArch64::LDRSpre:
3191 case AArch64::LDRWpost:
3192 case AArch64::LDRWpre:
3193 case AArch64::LDRXpost:
3194 case AArch64::LDRXpre:
3195 case AArch64::ST1B_D_IMM:
3196 case AArch64::ST1B_H_IMM:
3197 case AArch64::ST1B_IMM:
3198 case AArch64::ST1B_S_IMM:
3199 case AArch64::ST1D_IMM:
3200 case AArch64::ST1H_D_IMM:
3201 case AArch64::ST1H_IMM:
3202 case AArch64::ST1H_S_IMM:
3203 case AArch64::ST1W_D_IMM:
3204 case AArch64::ST1W_IMM:
3205 case AArch64::ST2B_IMM:
3206 case AArch64::ST2D_IMM:
3207 case AArch64::ST2H_IMM:
3208 case AArch64::ST2W_IMM:
3209 case AArch64::ST3B_IMM:
3210 case AArch64::ST3D_IMM:
3211 case AArch64::ST3H_IMM:
3212 case AArch64::ST3W_IMM:
3213 case AArch64::ST4B_IMM:
3214 case AArch64::ST4D_IMM:
3215 case AArch64::ST4H_IMM:
3216 case AArch64::ST4W_IMM:
3217 case AArch64::STGPi:
3218 case AArch64::STGPreIndex:
3219 case AArch64::STZGPreIndex:
3220 case AArch64::ST2GPreIndex:
3221 case AArch64::STZ2GPreIndex:
3222 case AArch64::STGPostIndex:
3223 case AArch64::STZGPostIndex:
3224 case AArch64::ST2GPostIndex:
3225 case AArch64::STZ2GPostIndex:
3226 case AArch64::STNPDi:
3227 case AArch64::STNPQi:
3228 case AArch64::STNPSi:
3229 case AArch64::STNPWi:
3230 case AArch64::STNPXi:
3231 case AArch64::STNT1B_ZRI:
3232 case AArch64::STNT1D_ZRI:
3233 case AArch64::STNT1H_ZRI:
3234 case AArch64::STNT1W_ZRI:
3235 case AArch64::STPDi:
3236 case AArch64::STPQi:
3237 case AArch64::STPSi:
3238 case AArch64::STPWi:
3239 case AArch64::STPXi:
3240 case AArch64::STRBBpost:
3241 case AArch64::STRBBpre:
3242 case AArch64::STRBpost:
3243 case AArch64::STRBpre:
3244 case AArch64::STRDpost:
3245 case AArch64::STRDpre:
3246 case AArch64::STRHHpost:
3247 case AArch64::STRHHpre:
3248 case AArch64::STRHpost:
3249 case AArch64::STRHpre:
3250 case AArch64::STRQpost:
3251 case AArch64::STRQpre:
3252 case AArch64::STRSpost:
3253 case AArch64::STRSpre:
3254 case AArch64::STRWpost:
3255 case AArch64::STRWpre:
3256 case AArch64::STRXpost:
3257 case AArch64::STRXpre:
3258 case AArch64::LD1B_2Z_IMM:
3259 case AArch64::LD1B_2Z_STRIDED_IMM:
3260 case AArch64::LD1H_2Z_IMM:
3261 case AArch64::LD1H_2Z_STRIDED_IMM:
3262 case AArch64::LD1W_2Z_IMM:
3263 case AArch64::LD1W_2Z_STRIDED_IMM:
3264 case AArch64::LD1D_2Z_IMM:
3265 case AArch64::LD1D_2Z_STRIDED_IMM:
3266 case AArch64::LD1B_4Z_IMM:
3267 case AArch64::LD1B_4Z_STRIDED_IMM:
3268 case AArch64::LD1H_4Z_IMM:
3269 case AArch64::LD1H_4Z_STRIDED_IMM:
3270 case AArch64::LD1W_4Z_IMM:
3271 case AArch64::LD1W_4Z_STRIDED_IMM:
3272 case AArch64::LD1D_4Z_IMM:
3273 case AArch64::LD1D_4Z_STRIDED_IMM:
3274 case AArch64::LD1B_2Z_IMM_PSEUDO:
3275 case AArch64::LD1H_2Z_IMM_PSEUDO:
3276 case AArch64::LD1W_2Z_IMM_PSEUDO:
3277 case AArch64::LD1D_2Z_IMM_PSEUDO:
3278 case AArch64::LD1B_4Z_IMM_PSEUDO:
3279 case AArch64::LD1H_4Z_IMM_PSEUDO:
3280 case AArch64::LD1W_4Z_IMM_PSEUDO:
3281 case AArch64::LD1D_4Z_IMM_PSEUDO:
3282 case AArch64::ST1B_2Z_IMM:
3283 case AArch64::ST1B_2Z_STRIDED_IMM:
3284 case AArch64::ST1H_2Z_IMM:
3285 case AArch64::ST1H_2Z_STRIDED_IMM:
3286 case AArch64::ST1W_2Z_IMM:
3287 case AArch64::ST1W_2Z_STRIDED_IMM:
3288 case AArch64::ST1D_2Z_IMM:
3289 case AArch64::ST1D_2Z_STRIDED_IMM:
3290 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3291 case AArch64::LDNT1B_2Z_IMM:
3292 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3293 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3294 case AArch64::LDNT1H_2Z_IMM:
3295 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3296 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3297 case AArch64::LDNT1W_2Z_IMM:
3298 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3299 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3300 case AArch64::LDNT1D_2Z_IMM:
3301 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3302 case AArch64::STNT1B_2Z_IMM:
3303 case AArch64::STNT1B_2Z_STRIDED_IMM:
3304 case AArch64::STNT1H_2Z_IMM:
3305 case AArch64::STNT1H_2Z_STRIDED_IMM:
3306 case AArch64::STNT1W_2Z_IMM:
3307 case AArch64::STNT1W_2Z_STRIDED_IMM:
3308 case AArch64::STNT1D_2Z_IMM:
3309 case AArch64::STNT1D_2Z_STRIDED_IMM:
3310 case AArch64::ST1B_2Z_IMM_PSEUDO:
3311 case AArch64::ST1H_2Z_IMM_PSEUDO:
3312 case AArch64::ST1W_2Z_IMM_PSEUDO:
3313 case AArch64::ST1D_2Z_IMM_PSEUDO:
3314 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3315 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3316 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3317 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3318 case AArch64::ST1B_4Z_IMM:
3319 case AArch64::ST1B_4Z_STRIDED_IMM:
3320 case AArch64::ST1H_4Z_IMM:
3321 case AArch64::ST1H_4Z_STRIDED_IMM:
3322 case AArch64::ST1W_4Z_IMM:
3323 case AArch64::ST1W_4Z_STRIDED_IMM:
3324 case AArch64::ST1D_4Z_IMM:
3325 case AArch64::ST1D_4Z_STRIDED_IMM:
3326 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3327 case AArch64::LDNT1B_4Z_IMM:
3328 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3329 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3330 case AArch64::LDNT1H_4Z_IMM:
3331 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3332 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3333 case AArch64::LDNT1W_4Z_IMM:
3334 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3335 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3336 case AArch64::LDNT1D_4Z_IMM:
3337 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3338 case AArch64::STNT1B_4Z_IMM:
3339 case AArch64::STNT1B_4Z_STRIDED_IMM:
3340 case AArch64::STNT1H_4Z_IMM:
3341 case AArch64::STNT1H_4Z_STRIDED_IMM:
3342 case AArch64::STNT1W_4Z_IMM:
3343 case AArch64::STNT1W_4Z_STRIDED_IMM:
3344 case AArch64::STNT1D_4Z_IMM:
3345 case AArch64::STNT1D_4Z_STRIDED_IMM:
3346 case AArch64::ST1B_4Z_IMM_PSEUDO:
3347 case AArch64::ST1H_4Z_IMM_PSEUDO:
3348 case AArch64::ST1W_4Z_IMM_PSEUDO:
3349 case AArch64::ST1D_4Z_IMM_PSEUDO:
3350 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3351 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3352 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3353 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3354 return 3;
3355 case AArch64::LDPDpost:
3356 case AArch64::LDPDpre:
3357 case AArch64::LDPQpost:
3358 case AArch64::LDPQpre:
3359 case AArch64::LDPSpost:
3360 case AArch64::LDPSpre:
3361 case AArch64::LDPWpost:
3362 case AArch64::LDPWpre:
3363 case AArch64::LDPXpost:
3364 case AArch64::LDPXpre:
3365 case AArch64::STGPpre:
3366 case AArch64::STGPpost:
3367 case AArch64::STPDpost:
3368 case AArch64::STPDpre:
3369 case AArch64::STPQpost:
3370 case AArch64::STPQpre:
3371 case AArch64::STPSpost:
3372 case AArch64::STPSpre:
3373 case AArch64::STPWpost:
3374 case AArch64::STPWpre:
3375 case AArch64::STPXpost:
3376 case AArch64::STPXpre:
3377 return 4;
3378 }
3379}
3380
3382 switch (MI.getOpcode()) {
3383 default:
3384 return false;
3385 // Scaled instructions.
3386 case AArch64::STRSui:
3387 case AArch64::STRDui:
3388 case AArch64::STRQui:
3389 case AArch64::STRXui:
3390 case AArch64::STRWui:
3391 case AArch64::LDRSui:
3392 case AArch64::LDRDui:
3393 case AArch64::LDRQui:
3394 case AArch64::LDRXui:
3395 case AArch64::LDRWui:
3396 case AArch64::LDRSWui:
3397 // Unscaled instructions.
3398 case AArch64::STURSi:
3399 case AArch64::STRSpre:
3400 case AArch64::STURDi:
3401 case AArch64::STRDpre:
3402 case AArch64::STURQi:
3403 case AArch64::STRQpre:
3404 case AArch64::STURWi:
3405 case AArch64::STRWpre:
3406 case AArch64::STURXi:
3407 case AArch64::STRXpre:
3408 case AArch64::LDURSi:
3409 case AArch64::LDRSpre:
3410 case AArch64::LDURDi:
3411 case AArch64::LDRDpre:
3412 case AArch64::LDURQi:
3413 case AArch64::LDRQpre:
3414 case AArch64::LDURWi:
3415 case AArch64::LDRWpre:
3416 case AArch64::LDURXi:
3417 case AArch64::LDRXpre:
3418 case AArch64::LDURSWi:
3419 case AArch64::LDRSWpre:
3420 // SVE instructions.
3421 case AArch64::LDR_ZXI:
3422 case AArch64::STR_ZXI:
3423 return true;
3424 }
3425}
3426
3428 switch (MI.getOpcode()) {
3429 default:
3430 assert((!MI.isCall() || !MI.isReturn()) &&
3431 "Unexpected instruction - was a new tail call opcode introduced?");
3432 return false;
3433 case AArch64::TCRETURNdi:
3434 case AArch64::TCRETURNri:
3435 case AArch64::TCRETURNrix16x17:
3436 case AArch64::TCRETURNrix17:
3437 case AArch64::TCRETURNrinotx16:
3438 case AArch64::TCRETURNriALL:
3439 case AArch64::AUTH_TCRETURN:
3440 case AArch64::AUTH_TCRETURN_BTI:
3441 return true;
3442 }
3443}
3444
3446 switch (Opc) {
3447 default:
3448 llvm_unreachable("Opcode has no flag setting equivalent!");
3449 // 32-bit cases:
3450 case AArch64::ADDWri:
3451 return AArch64::ADDSWri;
3452 case AArch64::ADDWrr:
3453 return AArch64::ADDSWrr;
3454 case AArch64::ADDWrs:
3455 return AArch64::ADDSWrs;
3456 case AArch64::ADDWrx:
3457 return AArch64::ADDSWrx;
3458 case AArch64::ANDWri:
3459 return AArch64::ANDSWri;
3460 case AArch64::ANDWrr:
3461 return AArch64::ANDSWrr;
3462 case AArch64::ANDWrs:
3463 return AArch64::ANDSWrs;
3464 case AArch64::BICWrr:
3465 return AArch64::BICSWrr;
3466 case AArch64::BICWrs:
3467 return AArch64::BICSWrs;
3468 case AArch64::SUBWri:
3469 return AArch64::SUBSWri;
3470 case AArch64::SUBWrr:
3471 return AArch64::SUBSWrr;
3472 case AArch64::SUBWrs:
3473 return AArch64::SUBSWrs;
3474 case AArch64::SUBWrx:
3475 return AArch64::SUBSWrx;
3476 // 64-bit cases:
3477 case AArch64::ADDXri:
3478 return AArch64::ADDSXri;
3479 case AArch64::ADDXrr:
3480 return AArch64::ADDSXrr;
3481 case AArch64::ADDXrs:
3482 return AArch64::ADDSXrs;
3483 case AArch64::ADDXrx:
3484 return AArch64::ADDSXrx;
3485 case AArch64::ANDXri:
3486 return AArch64::ANDSXri;
3487 case AArch64::ANDXrr:
3488 return AArch64::ANDSXrr;
3489 case AArch64::ANDXrs:
3490 return AArch64::ANDSXrs;
3491 case AArch64::BICXrr:
3492 return AArch64::BICSXrr;
3493 case AArch64::BICXrs:
3494 return AArch64::BICSXrs;
3495 case AArch64::SUBXri:
3496 return AArch64::SUBSXri;
3497 case AArch64::SUBXrr:
3498 return AArch64::SUBSXrr;
3499 case AArch64::SUBXrs:
3500 return AArch64::SUBSXrs;
3501 case AArch64::SUBXrx:
3502 return AArch64::SUBSXrx;
3503 // SVE instructions:
3504 case AArch64::AND_PPzPP:
3505 return AArch64::ANDS_PPzPP;
3506 case AArch64::BIC_PPzPP:
3507 return AArch64::BICS_PPzPP;
3508 case AArch64::EOR_PPzPP:
3509 return AArch64::EORS_PPzPP;
3510 case AArch64::NAND_PPzPP:
3511 return AArch64::NANDS_PPzPP;
3512 case AArch64::NOR_PPzPP:
3513 return AArch64::NORS_PPzPP;
3514 case AArch64::ORN_PPzPP:
3515 return AArch64::ORNS_PPzPP;
3516 case AArch64::ORR_PPzPP:
3517 return AArch64::ORRS_PPzPP;
3518 case AArch64::BRKA_PPzP:
3519 return AArch64::BRKAS_PPzP;
3520 case AArch64::BRKPA_PPzPP:
3521 return AArch64::BRKPAS_PPzPP;
3522 case AArch64::BRKB_PPzP:
3523 return AArch64::BRKBS_PPzP;
3524 case AArch64::BRKPB_PPzPP:
3525 return AArch64::BRKPBS_PPzPP;
3526 case AArch64::BRKN_PPzP:
3527 return AArch64::BRKNS_PPzP;
3528 case AArch64::RDFFR_PPz:
3529 return AArch64::RDFFRS_PPz;
3530 case AArch64::PTRUE_B:
3531 return AArch64::PTRUES_B;
3532 }
3533}
3534
3535// Is this a candidate for ld/st merging or pairing? For example, we don't
3536// touch volatiles or load/stores that have a hint to avoid pair formation.
3538
3539 bool IsPreLdSt = isPreLdSt(MI);
3540
3541 // If this is a volatile load/store, don't mess with it.
3542 if (MI.hasOrderedMemoryRef())
3543 return false;
3544
3545 // Make sure this is a reg/fi+imm (as opposed to an address reloc).
3546 // For Pre-inc LD/ST, the operand is shifted by one.
3547 assert((MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3548 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3549 "Expected a reg or frame index operand.");
3550
3551 // For Pre-indexed addressing quadword instructions, the third operand is the
3552 // immediate value.
3553 bool IsImmPreLdSt = IsPreLdSt && MI.getOperand(3).isImm();
3554
3555 if (!MI.getOperand(2).isImm() && !IsImmPreLdSt)
3556 return false;
3557
3558 // Can't merge/pair if the instruction modifies the base register.
3559 // e.g., ldr x0, [x0]
3560 // This case will never occur with an FI base.
3561 // However, if the instruction is an LDR<S,D,Q,W,X,SW>pre or
3562 // STR<S,D,Q,W,X>pre, it can be merged.
3563 // For example:
3564 // ldr q0, [x11, #32]!
3565 // ldr q1, [x11, #16]
3566 // to
3567 // ldp q0, q1, [x11, #32]!
3568 if (MI.getOperand(1).isReg() && !IsPreLdSt) {
3569 Register BaseReg = MI.getOperand(1).getReg();
3571 if (MI.modifiesRegister(BaseReg, TRI))
3572 return false;
3573 }
3574
3575 // Pairing SVE fills/spills is only valid for little-endian targets that
3576 // implement VLS 128.
3577 switch (MI.getOpcode()) {
3578 default:
3579 break;
3580 case AArch64::LDR_ZXI:
3581 case AArch64::STR_ZXI:
3582 if (!Subtarget.isLittleEndian() ||
3583 Subtarget.getSVEVectorSizeInBits() != 128)
3584 return false;
3585 }
3586
3587 // Check if this load/store has a hint to avoid pair formation.
3588 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
3590 return false;
3591
3592 // Do not pair any callee-save store/reload instructions in the
3593 // prologue/epilogue if the CFI information encoded the operations as separate
3594 // instructions, as that will cause the size of the actual prologue to mismatch
3595 // with the prologue size recorded in the Windows CFI.
3596 const MCAsmInfo &MAI = MI.getMF()->getTarget().getMCAsmInfo();
3597 bool NeedsWinCFI =
3598 MAI.usesWindowsCFI() && MI.getMF()->getFunction().needsUnwindTableEntry();
3599 if (NeedsWinCFI && (MI.getFlag(MachineInstr::FrameSetup) ||
3601 return false;
3602
3603 // On some CPUs quad load/store pairs are slower than two single load/stores.
3604 if (Subtarget.isPaired128Slow()) {
3605 switch (MI.getOpcode()) {
3606 default:
3607 break;
3608 case AArch64::LDURQi:
3609 case AArch64::STURQi:
3610 case AArch64::LDRQui:
3611 case AArch64::STRQui:
3612 return false;
3613 }
3614 }
3615
3616 return true;
3617}
3618
3621 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
3622 const TargetRegisterInfo *TRI) const {
3623 if (!LdSt.mayLoadOrStore())
3624 return false;
3625
3626 const MachineOperand *BaseOp;
3627 TypeSize WidthN(0, false);
3628 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, OffsetIsScalable,
3629 WidthN, TRI))
3630 return false;
3631 // The maximum vscale is 16 under AArch64, return the maximal extent for the
3632 // vector.
3633 Width = LocationSize::precise(WidthN);
3634 BaseOps.push_back(BaseOp);
3635 return true;
3636}
3637
3638std::optional<ExtAddrMode>
3640 const TargetRegisterInfo *TRI) const {
3641 const MachineOperand *Base; // Filled with the base operand of MI.
3642 int64_t Offset; // Filled with the offset of MI.
3643 bool OffsetIsScalable;
3644 if (!getMemOperandWithOffset(MemI, Base, Offset, OffsetIsScalable, TRI))
3645 return std::nullopt;
3646
3647 if (!Base->isReg())
3648 return std::nullopt;
3649 ExtAddrMode AM;
3650 AM.BaseReg = Base->getReg();
3651 AM.Displacement = Offset;
3652 AM.ScaledReg = 0;
3653 AM.Scale = 0;
3654 return AM;
3655}
3656
3658 Register Reg,
3659 const MachineInstr &AddrI,
3660 ExtAddrMode &AM) const {
3661 // Filter out instructions into which we cannot fold.
3662 unsigned NumBytes;
3663 int64_t OffsetScale = 1;
3664 switch (MemI.getOpcode()) {
3665 default:
3666 return false;
3667
3668 case AArch64::LDURQi:
3669 case AArch64::STURQi:
3670 NumBytes = 16;
3671 break;
3672
3673 case AArch64::LDURDi:
3674 case AArch64::STURDi:
3675 case AArch64::LDURXi:
3676 case AArch64::STURXi:
3677 NumBytes = 8;
3678 break;
3679
3680 case AArch64::LDURWi:
3681 case AArch64::LDURSWi:
3682 case AArch64::STURWi:
3683 NumBytes = 4;
3684 break;
3685
3686 case AArch64::LDURHi:
3687 case AArch64::STURHi:
3688 case AArch64::LDURHHi:
3689 case AArch64::STURHHi:
3690 case AArch64::LDURSHXi:
3691 case AArch64::LDURSHWi:
3692 NumBytes = 2;
3693 break;
3694
3695 case AArch64::LDRBroX:
3696 case AArch64::LDRBBroX:
3697 case AArch64::LDRSBXroX:
3698 case AArch64::LDRSBWroX:
3699 case AArch64::STRBroX:
3700 case AArch64::STRBBroX:
3701 case AArch64::LDURBi:
3702 case AArch64::LDURBBi:
3703 case AArch64::LDURSBXi:
3704 case AArch64::LDURSBWi:
3705 case AArch64::STURBi:
3706 case AArch64::STURBBi:
3707 case AArch64::LDRBui:
3708 case AArch64::LDRBBui:
3709 case AArch64::LDRSBXui:
3710 case AArch64::LDRSBWui:
3711 case AArch64::STRBui:
3712 case AArch64::STRBBui:
3713 NumBytes = 1;
3714 break;
3715
3716 case AArch64::LDRQroX:
3717 case AArch64::STRQroX:
3718 case AArch64::LDRQui:
3719 case AArch64::STRQui:
3720 NumBytes = 16;
3721 OffsetScale = 16;
3722 break;
3723
3724 case AArch64::LDRDroX:
3725 case AArch64::STRDroX:
3726 case AArch64::LDRXroX:
3727 case AArch64::STRXroX:
3728 case AArch64::LDRDui:
3729 case AArch64::STRDui:
3730 case AArch64::LDRXui:
3731 case AArch64::STRXui:
3732 NumBytes = 8;
3733 OffsetScale = 8;
3734 break;
3735
3736 case AArch64::LDRWroX:
3737 case AArch64::LDRSWroX:
3738 case AArch64::STRWroX:
3739 case AArch64::LDRWui:
3740 case AArch64::LDRSWui:
3741 case AArch64::STRWui:
3742 NumBytes = 4;
3743 OffsetScale = 4;
3744 break;
3745
3746 case AArch64::LDRHroX:
3747 case AArch64::STRHroX:
3748 case AArch64::LDRHHroX:
3749 case AArch64::STRHHroX:
3750 case AArch64::LDRSHXroX:
3751 case AArch64::LDRSHWroX:
3752 case AArch64::LDRHui:
3753 case AArch64::STRHui:
3754 case AArch64::LDRHHui:
3755 case AArch64::STRHHui:
3756 case AArch64::LDRSHXui:
3757 case AArch64::LDRSHWui:
3758 NumBytes = 2;
3759 OffsetScale = 2;
3760 break;
3761 }
3762
3763 // Check the fold operand is not the loaded/stored value.
3764 const MachineOperand &BaseRegOp = MemI.getOperand(0);
3765 if (BaseRegOp.isReg() && BaseRegOp.getReg() == Reg)
3766 return false;
3767
3768 // Handle memory instructions with a [Reg, Reg] addressing mode.
3769 if (MemI.getOperand(2).isReg()) {
3770 // Bail if the addressing mode already includes extension of the offset
3771 // register.
3772 if (MemI.getOperand(3).getImm())
3773 return false;
3774
3775 // Check if we actually have a scaled offset.
3776 if (MemI.getOperand(4).getImm() == 0)
3777 OffsetScale = 1;
3778
3779 // If the address instructions is folded into the base register, then the
3780 // addressing mode must not have a scale. Then we can swap the base and the
3781 // scaled registers.
3782 if (MemI.getOperand(1).getReg() == Reg && OffsetScale != 1)
3783 return false;
3784
3785 switch (AddrI.getOpcode()) {
3786 default:
3787 return false;
3788
3789 case AArch64::SBFMXri:
3790 // sxtw Xa, Wm
3791 // ldr Xd, [Xn, Xa, lsl #N]
3792 // ->
3793 // ldr Xd, [Xn, Wm, sxtw #N]
3794 if (AddrI.getOperand(2).getImm() != 0 ||
3795 AddrI.getOperand(3).getImm() != 31)
3796 return false;
3797
3798 AM.BaseReg = MemI.getOperand(1).getReg();
3799 if (AM.BaseReg == Reg)
3800 AM.BaseReg = MemI.getOperand(2).getReg();
3801 AM.ScaledReg = AddrI.getOperand(1).getReg();
3802 AM.Scale = OffsetScale;
3803 AM.Displacement = 0;
3805 return true;
3806
3807 case TargetOpcode::SUBREG_TO_REG: {
3808 // mov Wa, Wm
3809 // ldr Xd, [Xn, Xa, lsl #N]
3810 // ->
3811 // ldr Xd, [Xn, Wm, uxtw #N]
3812
3813 // Zero-extension looks like an ORRWrs followed by a SUBREG_TO_REG.
3814 if (AddrI.getOperand(2).getImm() != AArch64::sub_32)
3815 return false;
3816
3817 const MachineRegisterInfo &MRI = AddrI.getMF()->getRegInfo();
3818 Register OffsetReg = AddrI.getOperand(1).getReg();
3819 if (!OffsetReg.isVirtual() || !MRI.hasOneNonDBGUse(OffsetReg))
3820 return false;
3821
3822 const MachineInstr &DefMI = *MRI.getVRegDef(OffsetReg);
3823 if (DefMI.getOpcode() != AArch64::ORRWrs ||
3824 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3825 DefMI.getOperand(3).getImm() != 0)
3826 return false;
3827
3828 AM.BaseReg = MemI.getOperand(1).getReg();
3829 if (AM.BaseReg == Reg)
3830 AM.BaseReg = MemI.getOperand(2).getReg();
3831 AM.ScaledReg = DefMI.getOperand(2).getReg();
3832 AM.Scale = OffsetScale;
3833 AM.Displacement = 0;
3835 return true;
3836 }
3837 }
3838 }
3839
3840 // Handle memory instructions with a [Reg, #Imm] addressing mode.
3841
3842 // Check we are not breaking a potential conversion to an LDP.
3843 auto validateOffsetForLDP = [](unsigned NumBytes, int64_t OldOffset,
3844 int64_t NewOffset) -> bool {
3845 int64_t MinOffset, MaxOffset;
3846 switch (NumBytes) {
3847 default:
3848 return true;
3849 case 4:
3850 MinOffset = -256;
3851 MaxOffset = 252;
3852 break;
3853 case 8:
3854 MinOffset = -512;
3855 MaxOffset = 504;
3856 break;
3857 case 16:
3858 MinOffset = -1024;
3859 MaxOffset = 1008;
3860 break;
3861 }
3862 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3863 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3864 };
3865 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) -> bool {
3866 int64_t OldOffset = MemI.getOperand(2).getImm() * OffsetScale;
3867 int64_t NewOffset = OldOffset + Disp;
3868 if (!isLegalAddressingMode(NumBytes, NewOffset, /* Scale */ 0))
3869 return false;
3870 // If the old offset would fit into an LDP, but the new offset wouldn't,
3871 // bail out.
3872 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3873 return false;
3874 AM.BaseReg = AddrI.getOperand(1).getReg();
3875 AM.ScaledReg = 0;
3876 AM.Scale = 0;
3877 AM.Displacement = NewOffset;
3879 return true;
3880 };
3881
3882 auto canFoldAddRegIntoAddrMode =
3883 [&](int64_t Scale,
3885 if (MemI.getOperand(2).getImm() != 0)
3886 return false;
3887 if ((unsigned)Scale != Scale)
3888 return false;
3889 if (!isLegalAddressingMode(NumBytes, /* Offset */ 0, Scale))
3890 return false;
3891 AM.BaseReg = AddrI.getOperand(1).getReg();
3892 AM.ScaledReg = AddrI.getOperand(2).getReg();
3893 AM.Scale = Scale;
3894 AM.Displacement = 0;
3895 AM.Form = Form;
3896 return true;
3897 };
3898
3899 auto avoidSlowSTRQ = [&](const MachineInstr &MemI) {
3900 unsigned Opcode = MemI.getOpcode();
3901 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3902 Subtarget.isSTRQroSlow();
3903 };
3904
3905 int64_t Disp = 0;
3906 const bool OptSize = MemI.getMF()->getFunction().hasOptSize();
3907 switch (AddrI.getOpcode()) {
3908 default:
3909 return false;
3910
3911 case AArch64::ADDXri:
3912 // add Xa, Xn, #N
3913 // ldr Xd, [Xa, #M]
3914 // ->
3915 // ldr Xd, [Xn, #N'+M]
3916 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3917 return canFoldAddSubImmIntoAddrMode(Disp);
3918
3919 case AArch64::SUBXri:
3920 // sub Xa, Xn, #N
3921 // ldr Xd, [Xa, #M]
3922 // ->
3923 // ldr Xd, [Xn, #N'+M]
3924 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3925 return canFoldAddSubImmIntoAddrMode(-Disp);
3926
3927 case AArch64::ADDXrs: {
3928 // add Xa, Xn, Xm, lsl #N
3929 // ldr Xd, [Xa]
3930 // ->
3931 // ldr Xd, [Xn, Xm, lsl #N]
3932
3933 // Don't fold the add if the result would be slower, unless optimising for
3934 // size.
3935 unsigned Shift = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3937 return false;
3938 Shift = AArch64_AM::getShiftValue(Shift);
3939 if (!OptSize) {
3940 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3941 return false;
3942 if (avoidSlowSTRQ(MemI))
3943 return false;
3944 }
3945 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3946 }
3947
3948 case AArch64::ADDXrr:
3949 // add Xa, Xn, Xm
3950 // ldr Xd, [Xa]
3951 // ->
3952 // ldr Xd, [Xn, Xm, lsl #0]
3953
3954 // Don't fold the add if the result would be slower, unless optimising for
3955 // size.
3956 if (!OptSize && avoidSlowSTRQ(MemI))
3957 return false;
3958 return canFoldAddRegIntoAddrMode(1);
3959
3960 case AArch64::ADDXrx:
3961 // add Xa, Xn, Wm, {s,u}xtw #N
3962 // ldr Xd, [Xa]
3963 // ->
3964 // ldr Xd, [Xn, Wm, {s,u}xtw #N]
3965
3966 // Don't fold the add if the result would be slower, unless optimising for
3967 // size.
3968 if (!OptSize && avoidSlowSTRQ(MemI))
3969 return false;
3970
3971 // Can fold only sign-/zero-extend of a word.
3972 unsigned Imm = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3974 if (Extend != AArch64_AM::UXTW && Extend != AArch64_AM::SXTW)
3975 return false;
3976
3977 return canFoldAddRegIntoAddrMode(
3978 1ULL << AArch64_AM::getArithShiftValue(Imm),
3981 }
3982}
3983
3984// Given an opcode for an instruction with a [Reg, #Imm] addressing mode,
3985// return the opcode of an instruction performing the same operation, but using
3986// the [Reg, Reg] addressing mode.
3987static unsigned regOffsetOpcode(unsigned Opcode) {
3988 switch (Opcode) {
3989 default:
3990 llvm_unreachable("Address folding not implemented for instruction");
3991
3992 case AArch64::LDURQi:
3993 case AArch64::LDRQui:
3994 return AArch64::LDRQroX;
3995 case AArch64::STURQi:
3996 case AArch64::STRQui:
3997 return AArch64::STRQroX;
3998 case AArch64::LDURDi:
3999 case AArch64::LDRDui:
4000 return AArch64::LDRDroX;
4001 case AArch64::STURDi:
4002 case AArch64::STRDui:
4003 return AArch64::STRDroX;
4004 case AArch64::LDURXi:
4005 case AArch64::LDRXui:
4006 return AArch64::LDRXroX;
4007 case AArch64::STURXi:
4008 case AArch64::STRXui:
4009 return AArch64::STRXroX;
4010 case AArch64::LDURWi:
4011 case AArch64::LDRWui:
4012 return AArch64::LDRWroX;
4013 case AArch64::LDURSWi:
4014 case AArch64::LDRSWui:
4015 return AArch64::LDRSWroX;
4016 case AArch64::STURWi:
4017 case AArch64::STRWui:
4018 return AArch64::STRWroX;
4019 case AArch64::LDURHi:
4020 case AArch64::LDRHui:
4021 return AArch64::LDRHroX;
4022 case AArch64::STURHi:
4023 case AArch64::STRHui:
4024 return AArch64::STRHroX;
4025 case AArch64::LDURHHi:
4026 case AArch64::LDRHHui:
4027 return AArch64::LDRHHroX;
4028 case AArch64::STURHHi:
4029 case AArch64::STRHHui:
4030 return AArch64::STRHHroX;
4031 case AArch64::LDURSHXi:
4032 case AArch64::LDRSHXui:
4033 return AArch64::LDRSHXroX;
4034 case AArch64::LDURSHWi:
4035 case AArch64::LDRSHWui:
4036 return AArch64::LDRSHWroX;
4037 case AArch64::LDURBi:
4038 case AArch64::LDRBui:
4039 return AArch64::LDRBroX;
4040 case AArch64::LDURBBi:
4041 case AArch64::LDRBBui:
4042 return AArch64::LDRBBroX;
4043 case AArch64::LDURSBXi:
4044 case AArch64::LDRSBXui:
4045 return AArch64::LDRSBXroX;
4046 case AArch64::LDURSBWi:
4047 case AArch64::LDRSBWui:
4048 return AArch64::LDRSBWroX;
4049 case AArch64::STURBi:
4050 case AArch64::STRBui:
4051 return AArch64::STRBroX;
4052 case AArch64::STURBBi:
4053 case AArch64::STRBBui:
4054 return AArch64::STRBBroX;
4055 }
4056}
4057
4058// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4059// the opcode of an instruction performing the same operation, but using the
4060// [Reg, #Imm] addressing mode with scaled offset.
4061unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale) {
4062 switch (Opcode) {
4063 default:
4064 llvm_unreachable("Address folding not implemented for instruction");
4065
4066 case AArch64::LDURQi:
4067 Scale = 16;
4068 return AArch64::LDRQui;
4069 case AArch64::STURQi:
4070 Scale = 16;
4071 return AArch64::STRQui;
4072 case AArch64::LDURDi:
4073 Scale = 8;
4074 return AArch64::LDRDui;
4075 case AArch64::STURDi:
4076 Scale = 8;
4077 return AArch64::STRDui;
4078 case AArch64::LDURXi:
4079 Scale = 8;
4080 return AArch64::LDRXui;
4081 case AArch64::STURXi:
4082 Scale = 8;
4083 return AArch64::STRXui;
4084 case AArch64::LDURWi:
4085 Scale = 4;
4086 return AArch64::LDRWui;
4087 case AArch64::LDURSWi:
4088 Scale = 4;
4089 return AArch64::LDRSWui;
4090 case AArch64::STURWi:
4091 Scale = 4;
4092 return AArch64::STRWui;
4093 case AArch64::LDURHi:
4094 Scale = 2;
4095 return AArch64::LDRHui;
4096 case AArch64::STURHi:
4097 Scale = 2;
4098 return AArch64::STRHui;
4099 case AArch64::LDURHHi:
4100 Scale = 2;
4101 return AArch64::LDRHHui;
4102 case AArch64::STURHHi:
4103 Scale = 2;
4104 return AArch64::STRHHui;
4105 case AArch64::LDURSHXi:
4106 Scale = 2;
4107 return AArch64::LDRSHXui;
4108 case AArch64::LDURSHWi:
4109 Scale = 2;
4110 return AArch64::LDRSHWui;
4111 case AArch64::LDURBi:
4112 Scale = 1;
4113 return AArch64::LDRBui;
4114 case AArch64::LDURBBi:
4115 Scale = 1;
4116 return AArch64::LDRBBui;
4117 case AArch64::LDURSBXi:
4118 Scale = 1;
4119 return AArch64::LDRSBXui;
4120 case AArch64::LDURSBWi:
4121 Scale = 1;
4122 return AArch64::LDRSBWui;
4123 case AArch64::STURBi:
4124 Scale = 1;
4125 return AArch64::STRBui;
4126 case AArch64::STURBBi:
4127 Scale = 1;
4128 return AArch64::STRBBui;
4129 case AArch64::LDRQui:
4130 case AArch64::STRQui:
4131 Scale = 16;
4132 return Opcode;
4133 case AArch64::LDRDui:
4134 case AArch64::STRDui:
4135 case AArch64::LDRXui:
4136 case AArch64::STRXui:
4137 Scale = 8;
4138 return Opcode;
4139 case AArch64::LDRWui:
4140 case AArch64::LDRSWui:
4141 case AArch64::STRWui:
4142 Scale = 4;
4143 return Opcode;
4144 case AArch64::LDRHui:
4145 case AArch64::STRHui:
4146 case AArch64::LDRHHui:
4147 case AArch64::STRHHui:
4148 case AArch64::LDRSHXui:
4149 case AArch64::LDRSHWui:
4150 Scale = 2;
4151 return Opcode;
4152 case AArch64::LDRBui:
4153 case AArch64::LDRBBui:
4154 case AArch64::LDRSBXui:
4155 case AArch64::LDRSBWui:
4156 case AArch64::STRBui:
4157 case AArch64::STRBBui:
4158 Scale = 1;
4159 return Opcode;
4160 }
4161}
4162
4163// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4164// the opcode of an instruction performing the same operation, but using the
4165// [Reg, #Imm] addressing mode with unscaled offset.
4166unsigned unscaledOffsetOpcode(unsigned Opcode) {
4167 switch (Opcode) {
4168 default:
4169 llvm_unreachable("Address folding not implemented for instruction");
4170
4171 case AArch64::LDURQi:
4172 case AArch64::STURQi:
4173 case AArch64::LDURDi:
4174 case AArch64::STURDi:
4175 case AArch64::LDURXi:
4176 case AArch64::STURXi:
4177 case AArch64::LDURWi:
4178 case AArch64::LDURSWi:
4179 case AArch64::STURWi:
4180 case AArch64::LDURHi:
4181 case AArch64::STURHi:
4182 case AArch64::LDURHHi:
4183 case AArch64::STURHHi:
4184 case AArch64::LDURSHXi:
4185 case AArch64::LDURSHWi:
4186 case AArch64::LDURBi:
4187 case AArch64::STURBi:
4188 case AArch64::LDURBBi:
4189 case AArch64::STURBBi:
4190 case AArch64::LDURSBWi:
4191 case AArch64::LDURSBXi:
4192 return Opcode;
4193 case AArch64::LDRQui:
4194 return AArch64::LDURQi;
4195 case AArch64::STRQui:
4196 return AArch64::STURQi;
4197 case AArch64::LDRDui:
4198 return AArch64::LDURDi;
4199 case AArch64::STRDui:
4200 return AArch64::STURDi;
4201 case AArch64::LDRXui:
4202 return AArch64::LDURXi;
4203 case AArch64::STRXui:
4204 return AArch64::STURXi;
4205 case AArch64::LDRWui:
4206 return AArch64::LDURWi;
4207 case AArch64::LDRSWui:
4208 return AArch64::LDURSWi;
4209 case AArch64::STRWui:
4210 return AArch64::STURWi;
4211 case AArch64::LDRHui:
4212 return AArch64::LDURHi;
4213 case AArch64::STRHui:
4214 return AArch64::STURHi;
4215 case AArch64::LDRHHui:
4216 return AArch64::LDURHHi;
4217 case AArch64::STRHHui:
4218 return AArch64::STURHHi;
4219 case AArch64::LDRSHXui:
4220 return AArch64::LDURSHXi;
4221 case AArch64::LDRSHWui:
4222 return AArch64::LDURSHWi;
4223 case AArch64::LDRBBui:
4224 return AArch64::LDURBBi;
4225 case AArch64::LDRBui:
4226 return AArch64::LDURBi;
4227 case AArch64::STRBBui:
4228 return AArch64::STURBBi;
4229 case AArch64::STRBui:
4230 return AArch64::STURBi;
4231 case AArch64::LDRSBWui:
4232 return AArch64::LDURSBWi;
4233 case AArch64::LDRSBXui:
4234 return AArch64::LDURSBXi;
4235 }
4236}
4237
4238// Given the opcode of a memory load/store instruction, return the opcode of an
4239// instruction performing the same operation, but using
4240// the [Reg, Reg, {s,u}xtw #N] addressing mode with sign-/zero-extend of the
4241// offset register.
4242static unsigned offsetExtendOpcode(unsigned Opcode) {
4243 switch (Opcode) {
4244 default:
4245 llvm_unreachable("Address folding not implemented for instruction");
4246
4247 case AArch64::LDRQroX:
4248 case AArch64::LDURQi:
4249 case AArch64::LDRQui:
4250 return AArch64::LDRQroW;
4251 case AArch64::STRQroX:
4252 case AArch64::STURQi:
4253 case AArch64::STRQui:
4254 return AArch64::STRQroW;
4255 case AArch64::LDRDroX:
4256 case AArch64::LDURDi:
4257 case AArch64::LDRDui:
4258 return AArch64::LDRDroW;
4259 case AArch64::STRDroX:
4260 case AArch64::STURDi:
4261 case AArch64::STRDui:
4262 return AArch64::STRDroW;
4263 case AArch64::LDRXroX:
4264 case AArch64::LDURXi:
4265 case AArch64::LDRXui:
4266 return AArch64::LDRXroW;
4267 case AArch64::STRXroX:
4268 case AArch64::STURXi:
4269 case AArch64::STRXui:
4270 return AArch64::STRXroW;
4271 case AArch64::LDRWroX:
4272 case AArch64::LDURWi:
4273 case AArch64::LDRWui:
4274 return AArch64::LDRWroW;
4275 case AArch64::LDRSWroX:
4276 case AArch64::LDURSWi:
4277 case AArch64::LDRSWui:
4278 return AArch64::LDRSWroW;
4279 case AArch64::STRWroX:
4280 case AArch64::STURWi:
4281 case AArch64::STRWui:
4282 return AArch64::STRWroW;
4283 case AArch64::LDRHroX:
4284 case AArch64::LDURHi:
4285 case AArch64::LDRHui:
4286 return AArch64::LDRHroW;
4287 case AArch64::STRHroX:
4288 case AArch64::STURHi:
4289 case AArch64::STRHui:
4290 return AArch64::STRHroW;
4291 case AArch64::LDRHHroX:
4292 case AArch64::LDURHHi:
4293 case AArch64::LDRHHui:
4294 return AArch64::LDRHHroW;
4295 case AArch64::STRHHroX:
4296 case AArch64::STURHHi:
4297 case AArch64::STRHHui:
4298 return AArch64::STRHHroW;
4299 case AArch64::LDRSHXroX:
4300 case AArch64::LDURSHXi:
4301 case AArch64::LDRSHXui:
4302 return AArch64::LDRSHXroW;
4303 case AArch64::LDRSHWroX:
4304 case AArch64::LDURSHWi:
4305 case AArch64::LDRSHWui:
4306 return AArch64::LDRSHWroW;
4307 case AArch64::LDRBroX:
4308 case AArch64::LDURBi:
4309 case AArch64::LDRBui:
4310 return AArch64::LDRBroW;
4311 case AArch64::LDRBBroX:
4312 case AArch64::LDURBBi:
4313 case AArch64::LDRBBui:
4314 return AArch64::LDRBBroW;
4315 case AArch64::LDRSBXroX:
4316 case AArch64::LDURSBXi:
4317 case AArch64::LDRSBXui:
4318 return AArch64::LDRSBXroW;
4319 case AArch64::LDRSBWroX:
4320 case AArch64::LDURSBWi:
4321 case AArch64::LDRSBWui:
4322 return AArch64::LDRSBWroW;
4323 case AArch64::STRBroX:
4324 case AArch64::STURBi:
4325 case AArch64::STRBui:
4326 return AArch64::STRBroW;
4327 case AArch64::STRBBroX:
4328 case AArch64::STURBBi:
4329 case AArch64::STRBBui:
4330 return AArch64::STRBBroW;
4331 }
4332}
4333
4335 const ExtAddrMode &AM) const {
4336
4337 const DebugLoc &DL = MemI.getDebugLoc();
4338 MachineBasicBlock &MBB = *MemI.getParent();
4339 MachineRegisterInfo &MRI = MemI.getMF()->getRegInfo();
4340
4342 if (AM.ScaledReg) {
4343 // The new instruction will be in the form `ldr Rt, [Xn, Xm, lsl #imm]`.
4344 unsigned Opcode = regOffsetOpcode(MemI.getOpcode());
4345 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4346 auto B = BuildMI(MBB, MemI, DL, get(Opcode))
4347 .addReg(MemI.getOperand(0).getReg(),
4348 getDefRegState(MemI.mayLoad()))
4349 .addReg(AM.BaseReg)
4350 .addReg(AM.ScaledReg)
4351 .addImm(0)
4352 .addImm(AM.Scale > 1)
4353 .setMemRefs(MemI.memoperands())
4354 .setMIFlags(MemI.getFlags());
4355 return B.getInstr();
4356 }
4357
4358 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
4359 "Addressing mode not supported for folding");
4360
4361 // The new instruction will be in the form `ld[u]r Rt, [Xn, #imm]`.
4362 unsigned Scale = 1;
4363 unsigned Opcode = MemI.getOpcode();
4364 if (isInt<9>(AM.Displacement))
4365 Opcode = unscaledOffsetOpcode(Opcode);
4366 else
4367 Opcode = scaledOffsetOpcode(Opcode, Scale);
4368
4369 auto B =
4370 BuildMI(MBB, MemI, DL, get(Opcode))
4371 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4372 .addReg(AM.BaseReg)
4373 .addImm(AM.Displacement / Scale)
4374 .setMemRefs(MemI.memoperands())
4375 .setMIFlags(MemI.getFlags());
4376 return B.getInstr();
4377 }
4378
4381 // The new instruction will be in the form `ldr Rt, [Xn, Wm, {s,u}xtw #N]`.
4382 assert(AM.ScaledReg && !AM.Displacement &&
4383 "Address offset can be a register or an immediate, but not both");
4384 unsigned Opcode = offsetExtendOpcode(MemI.getOpcode());
4385 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4386 // Make sure the offset register is in the correct register class.
4387 Register OffsetReg = AM.ScaledReg;
4388 const TargetRegisterClass *RC = MRI.getRegClass(OffsetReg);
4389 if (RC->hasSuperClassEq(&AArch64::GPR64RegClass)) {
4390 OffsetReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
4391 BuildMI(MBB, MemI, DL, get(TargetOpcode::COPY), OffsetReg)
4392 .addReg(AM.ScaledReg, {}, AArch64::sub_32);
4393 }
4394 auto B =
4395 BuildMI(MBB, MemI, DL, get(Opcode))
4396 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4397 .addReg(AM.BaseReg)
4398 .addReg(OffsetReg)
4400 .addImm(AM.Scale != 1)
4401 .setMemRefs(MemI.memoperands())
4402 .setMIFlags(MemI.getFlags());
4403
4404 return B.getInstr();
4405 }
4406
4408 "Function must not be called with an addressing mode it can't handle");
4409}
4410
4411/// Return true if the opcode is a post-index ld/st instruction, which really
4412/// loads from base+0.
4413static bool isPostIndexLdStOpcode(unsigned Opcode) {
4414 switch (Opcode) {
4415 default:
4416 return false;
4417 case AArch64::LD1Fourv16b_POST:
4418 case AArch64::LD1Fourv1d_POST:
4419 case AArch64::LD1Fourv2d_POST:
4420 case AArch64::LD1Fourv2s_POST:
4421 case AArch64::LD1Fourv4h_POST:
4422 case AArch64::LD1Fourv4s_POST:
4423 case AArch64::LD1Fourv8b_POST:
4424 case AArch64::LD1Fourv8h_POST:
4425 case AArch64::LD1Onev16b_POST:
4426 case AArch64::LD1Onev1d_POST:
4427 case AArch64::LD1Onev2d_POST:
4428 case AArch64::LD1Onev2s_POST:
4429 case AArch64::LD1Onev4h_POST:
4430 case AArch64::LD1Onev4s_POST:
4431 case AArch64::LD1Onev8b_POST:
4432 case AArch64::LD1Onev8h_POST:
4433 case AArch64::LD1Rv16b_POST:
4434 case AArch64::LD1Rv1d_POST:
4435 case AArch64::LD1Rv2d_POST:
4436 case AArch64::LD1Rv2s_POST:
4437 case AArch64::LD1Rv4h_POST:
4438 case AArch64::LD1Rv4s_POST:
4439 case AArch64::LD1Rv8b_POST:
4440 case AArch64::LD1Rv8h_POST:
4441 case AArch64::LD1Threev16b_POST:
4442 case AArch64::LD1Threev1d_POST:
4443 case AArch64::LD1Threev2d_POST:
4444 case AArch64::LD1Threev2s_POST:
4445 case AArch64::LD1Threev4h_POST:
4446 case AArch64::LD1Threev4s_POST:
4447 case AArch64::LD1Threev8b_POST:
4448 case AArch64::LD1Threev8h_POST:
4449 case AArch64::LD1Twov16b_POST:
4450 case AArch64::LD1Twov1d_POST:
4451 case AArch64::LD1Twov2d_POST:
4452 case AArch64::LD1Twov2s_POST:
4453 case AArch64::LD1Twov4h_POST:
4454 case AArch64::LD1Twov4s_POST:
4455 case AArch64::LD1Twov8b_POST:
4456 case AArch64::LD1Twov8h_POST:
4457 case AArch64::LD1i16_POST:
4458 case AArch64::LD1i32_POST:
4459 case AArch64::LD1i64_POST:
4460 case AArch64::LD1i8_POST:
4461 case AArch64::LD2Rv16b_POST:
4462 case AArch64::LD2Rv1d_POST:
4463 case AArch64::LD2Rv2d_POST:
4464 case AArch64::LD2Rv2s_POST:
4465 case AArch64::LD2Rv4h_POST:
4466 case AArch64::LD2Rv4s_POST:
4467 case AArch64::LD2Rv8b_POST:
4468 case AArch64::LD2Rv8h_POST:
4469 case AArch64::LD2Twov16b_POST:
4470 case AArch64::LD2Twov2d_POST:
4471 case AArch64::LD2Twov2s_POST:
4472 case AArch64::LD2Twov4h_POST:
4473 case AArch64::LD2Twov4s_POST:
4474 case AArch64::LD2Twov8b_POST:
4475 case AArch64::LD2Twov8h_POST:
4476 case AArch64::LD2i16_POST:
4477 case AArch64::LD2i32_POST:
4478 case AArch64::LD2i64_POST:
4479 case AArch64::LD2i8_POST:
4480 case AArch64::LD3Rv16b_POST:
4481 case AArch64::LD3Rv1d_POST:
4482 case AArch64::LD3Rv2d_POST:
4483 case AArch64::LD3Rv2s_POST:
4484 case AArch64::LD3Rv4h_POST:
4485 case AArch64::LD3Rv4s_POST:
4486 case AArch64::LD3Rv8b_POST:
4487 case AArch64::LD3Rv8h_POST:
4488 case AArch64::LD3Threev16b_POST:
4489 case AArch64::LD3Threev2d_POST:
4490 case AArch64::LD3Threev2s_POST:
4491 case AArch64::LD3Threev4h_POST:
4492 case AArch64::LD3Threev4s_POST:
4493 case AArch64::LD3Threev8b_POST:
4494 case AArch64::LD3Threev8h_POST:
4495 case AArch64::LD3i16_POST:
4496 case AArch64::LD3i32_POST:
4497 case AArch64::LD3i64_POST:
4498 case AArch64::LD3i8_POST:
4499 case AArch64::LD4Fourv16b_POST:
4500 case AArch64::LD4Fourv2d_POST:
4501 case AArch64::LD4Fourv2s_POST:
4502 case AArch64::LD4Fourv4h_POST:
4503 case AArch64::LD4Fourv4s_POST:
4504 case AArch64::LD4Fourv8b_POST:
4505 case AArch64::LD4Fourv8h_POST:
4506 case AArch64::LD4Rv16b_POST:
4507 case AArch64::LD4Rv1d_POST:
4508 case AArch64::LD4Rv2d_POST:
4509 case AArch64::LD4Rv2s_POST:
4510 case AArch64::LD4Rv4h_POST:
4511 case AArch64::LD4Rv4s_POST:
4512 case AArch64::LD4Rv8b_POST:
4513 case AArch64::LD4Rv8h_POST:
4514 case AArch64::LD4i16_POST:
4515 case AArch64::LD4i32_POST:
4516 case AArch64::LD4i64_POST:
4517 case AArch64::LD4i8_POST:
4518 case AArch64::LDAPRWpost:
4519 case AArch64::LDAPRXpost:
4520 case AArch64::LDIAPPWpost:
4521 case AArch64::LDIAPPXpost:
4522 case AArch64::LDPDpost:
4523 case AArch64::LDPQpost:
4524 case AArch64::LDPSWpost:
4525 case AArch64::LDPSpost:
4526 case AArch64::LDPWpost:
4527 case AArch64::LDPXpost:
4528 case AArch64::LDRBBpost:
4529 case AArch64::LDRBpost:
4530 case AArch64::LDRDpost:
4531 case AArch64::LDRHHpost:
4532 case AArch64::LDRHpost:
4533 case AArch64::LDRQpost:
4534 case AArch64::LDRSBWpost:
4535 case AArch64::LDRSBXpost:
4536 case AArch64::LDRSHWpost:
4537 case AArch64::LDRSHXpost:
4538 case AArch64::LDRSWpost:
4539 case AArch64::LDRSpost:
4540 case AArch64::LDRWpost:
4541 case AArch64::LDRXpost:
4542 case AArch64::ST1Fourv16b_POST:
4543 case AArch64::ST1Fourv1d_POST:
4544 case AArch64::ST1Fourv2d_POST:
4545 case AArch64::ST1Fourv2s_POST:
4546 case AArch64::ST1Fourv4h_POST:
4547 case AArch64::ST1Fourv4s_POST:
4548 case AArch64::ST1Fourv8b_POST:
4549 case AArch64::ST1Fourv8h_POST:
4550 case AArch64::ST1Onev16b_POST:
4551 case AArch64::ST1Onev1d_POST:
4552 case AArch64::ST1Onev2d_POST:
4553 case AArch64::ST1Onev2s_POST:
4554 case AArch64::ST1Onev4h_POST:
4555 case AArch64::ST1Onev4s_POST:
4556 case AArch64::ST1Onev8b_POST:
4557 case AArch64::ST1Onev8h_POST:
4558 case AArch64::ST1Threev16b_POST:
4559 case AArch64::ST1Threev1d_POST:
4560 case AArch64::ST1Threev2d_POST:
4561 case AArch64::ST1Threev2s_POST:
4562 case AArch64::ST1Threev4h_POST:
4563 case AArch64::ST1Threev4s_POST:
4564 case AArch64::ST1Threev8b_POST:
4565 case AArch64::ST1Threev8h_POST:
4566 case AArch64::ST1Twov16b_POST:
4567 case AArch64::ST1Twov1d_POST:
4568 case AArch64::ST1Twov2d_POST:
4569 case AArch64::ST1Twov2s_POST:
4570 case AArch64::ST1Twov4h_POST:
4571 case AArch64::ST1Twov4s_POST:
4572 case AArch64::ST1Twov8b_POST:
4573 case AArch64::ST1Twov8h_POST:
4574 case AArch64::ST1i16_POST:
4575 case AArch64::ST1i32_POST:
4576 case AArch64::ST1i64_POST:
4577 case AArch64::ST1i8_POST:
4578 case AArch64::ST2GPostIndex:
4579 case AArch64::ST2Twov16b_POST:
4580 case AArch64::ST2Twov2d_POST:
4581 case AArch64::ST2Twov2s_POST:
4582 case AArch64::ST2Twov4h_POST:
4583 case AArch64::ST2Twov4s_POST:
4584 case AArch64::ST2Twov8b_POST:
4585 case AArch64::ST2Twov8h_POST:
4586 case AArch64::ST2i16_POST:
4587 case AArch64::ST2i32_POST:
4588 case AArch64::ST2i64_POST:
4589 case AArch64::ST2i8_POST:
4590 case AArch64::ST3Threev16b_POST:
4591 case AArch64::ST3Threev2d_POST:
4592 case AArch64::ST3Threev2s_POST:
4593 case AArch64::ST3Threev4h_POST:
4594 case AArch64::ST3Threev4s_POST:
4595 case AArch64::ST3Threev8b_POST:
4596 case AArch64::ST3Threev8h_POST:
4597 case AArch64::ST3i16_POST:
4598 case AArch64::ST3i32_POST:
4599 case AArch64::ST3i64_POST:
4600 case AArch64::ST3i8_POST:
4601 case AArch64::ST4Fourv16b_POST:
4602 case AArch64::ST4Fourv2d_POST:
4603 case AArch64::ST4Fourv2s_POST:
4604 case AArch64::ST4Fourv4h_POST:
4605 case AArch64::ST4Fourv4s_POST:
4606 case AArch64::ST4Fourv8b_POST:
4607 case AArch64::ST4Fourv8h_POST:
4608 case AArch64::ST4i16_POST:
4609 case AArch64::ST4i32_POST:
4610 case AArch64::ST4i64_POST:
4611 case AArch64::ST4i8_POST:
4612 case AArch64::STGPostIndex:
4613 case AArch64::STGPpost:
4614 case AArch64::STPDpost:
4615 case AArch64::STPQpost:
4616 case AArch64::STPSpost:
4617 case AArch64::STPWpost:
4618 case AArch64::STPXpost:
4619 case AArch64::STRBBpost:
4620 case AArch64::STRBpost:
4621 case AArch64::STRDpost:
4622 case AArch64::STRHHpost:
4623 case AArch64::STRHpost:
4624 case AArch64::STRQpost:
4625 case AArch64::STRSpost:
4626 case AArch64::STRWpost:
4627 case AArch64::STRXpost:
4628 case AArch64::STZ2GPostIndex:
4629 case AArch64::STZGPostIndex:
4630 return true;
4631 }
4632}
4633
4635 const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset,
4636 bool &OffsetIsScalable, TypeSize &Width,
4637 const TargetRegisterInfo *TRI) const {
4638 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4639 // Handle only loads/stores with base register followed by immediate offset.
4640 if (LdSt.getNumExplicitOperands() == 3) {
4641 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
4642 if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
4643 !LdSt.getOperand(2).isImm())
4644 return false;
4645 } else if (LdSt.getNumExplicitOperands() == 4) {
4646 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
4647 if (!LdSt.getOperand(1).isReg() ||
4648 (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI()) ||
4649 !LdSt.getOperand(3).isImm())
4650 return false;
4651 } else
4652 return false;
4653
4654 // Get the scaling factor for the instruction and set the width for the
4655 // instruction.
4656 TypeSize Scale(0U, false);
4657 int64_t Dummy1, Dummy2;
4658
4659 // If this returns false, then it's an instruction we don't want to handle.
4660 if (!getMemOpInfo(LdSt.getOpcode(), Scale, Width, Dummy1, Dummy2))
4661 return false;
4662
4663 // Compute the offset. Offset is calculated as the immediate operand
4664 // multiplied by the scaling factor. Unscaled instructions have scaling factor
4665 // set to 1. Postindex are a special case which have an offset of 0.
4666 if (isPostIndexLdStOpcode(LdSt.getOpcode())) {
4667 BaseOp = &LdSt.getOperand(2);
4668 Offset = 0;
4669 } else if (LdSt.getNumExplicitOperands() == 3) {
4670 BaseOp = &LdSt.getOperand(1);
4671 Offset = LdSt.getOperand(2).getImm() * Scale.getKnownMinValue();
4672 } else {
4673 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
4674 BaseOp = &LdSt.getOperand(2);
4675 Offset = LdSt.getOperand(3).getImm() * Scale.getKnownMinValue();
4676 }
4677 OffsetIsScalable = Scale.isScalable();
4678
4679 return BaseOp->isReg() || BaseOp->isFI();
4680}
4681
4684 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4685 MachineOperand &OfsOp = LdSt.getOperand(LdSt.getNumExplicitOperands() - 1);
4686 assert(OfsOp.isImm() && "Offset operand wasn't immediate.");
4687 return OfsOp;
4688}
4689
4690bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale,
4691 TypeSize &Width, int64_t &MinOffset,
4692 int64_t &MaxOffset) {
4693 switch (Opcode) {
4694 // Not a memory operation or something we want to handle.
4695 default:
4696 Scale = Width = TypeSize::getFixed(0);
4697 MinOffset = MaxOffset = 0;
4698 return false;
4699 // LDR / STR
4700 case AArch64::LDRQui:
4701 case AArch64::STRQui:
4702 Scale = Width = TypeSize::getFixed(16);
4703 MinOffset = 0;
4704 MaxOffset = 4095;
4705 break;
4706 case AArch64::LDRXui:
4707 case AArch64::LDRDui:
4708 case AArch64::STRXui:
4709 case AArch64::STRDui:
4710 case AArch64::PRFMui:
4711 Scale = Width = TypeSize::getFixed(8);
4712 MinOffset = 0;
4713 MaxOffset = 4095;
4714 break;
4715 case AArch64::LDRWui:
4716 case AArch64::LDRSui:
4717 case AArch64::LDRSWui:
4718 case AArch64::STRWui:
4719 case AArch64::STRSui:
4720 Scale = Width = TypeSize::getFixed(4);
4721 MinOffset = 0;
4722 MaxOffset = 4095;
4723 break;
4724 case AArch64::LDRHui:
4725 case AArch64::LDRHHui:
4726 case AArch64::LDRSHWui:
4727 case AArch64::LDRSHXui:
4728 case AArch64::STRHui:
4729 case AArch64::STRHHui:
4730 Scale = Width = TypeSize::getFixed(2);
4731 MinOffset = 0;
4732 MaxOffset = 4095;
4733 break;
4734 case AArch64::LDRBui:
4735 case AArch64::LDRBBui:
4736 case AArch64::LDRSBWui:
4737 case AArch64::LDRSBXui:
4738 case AArch64::STRBui:
4739 case AArch64::STRBBui:
4740 Scale = Width = TypeSize::getFixed(1);
4741 MinOffset = 0;
4742 MaxOffset = 4095;
4743 break;
4744 // post/pre inc
4745 case AArch64::STRQpre:
4746 case AArch64::LDRQpost:
4747 Scale = TypeSize::getFixed(1);
4748 Width = TypeSize::getFixed(16);
4749 MinOffset = -256;
4750 MaxOffset = 255;
4751 break;
4752 case AArch64::LDRDpost:
4753 case AArch64::LDRDpre:
4754 case AArch64::LDRXpost:
4755 case AArch64::LDRXpre:
4756 case AArch64::STRDpost:
4757 case AArch64::STRDpre:
4758 case AArch64::STRXpost:
4759 case AArch64::STRXpre:
4760 Scale = TypeSize::getFixed(1);
4761 Width = TypeSize::getFixed(8);
4762 MinOffset = -256;
4763 MaxOffset = 255;
4764 break;
4765 case AArch64::STRWpost:
4766 case AArch64::STRWpre:
4767 case AArch64::LDRWpost:
4768 case AArch64::LDRWpre:
4769 case AArch64::STRSpost:
4770 case AArch64::STRSpre:
4771 case AArch64::LDRSpost:
4772 case AArch64::LDRSpre:
4773 Scale = TypeSize::getFixed(1);
4774 Width = TypeSize::getFixed(4);
4775 MinOffset = -256;
4776 MaxOffset = 255;
4777 break;
4778 case AArch64::LDRHpost:
4779 case AArch64::LDRHpre:
4780 case AArch64::STRHpost:
4781 case AArch64::STRHpre:
4782 case AArch64::LDRHHpost:
4783 case AArch64::LDRHHpre:
4784 case AArch64::STRHHpost:
4785 case AArch64::STRHHpre:
4786 Scale = TypeSize::getFixed(1);
4787 Width = TypeSize::getFixed(2);
4788 MinOffset = -256;
4789 MaxOffset = 255;
4790 break;
4791 case AArch64::LDRBpost:
4792 case AArch64::LDRBpre:
4793 case AArch64::STRBpost:
4794 case AArch64::STRBpre:
4795 case AArch64::LDRBBpost:
4796 case AArch64::LDRBBpre:
4797 case AArch64::STRBBpost:
4798 case AArch64::STRBBpre:
4799 Scale = Width = TypeSize::getFixed(1);
4800 MinOffset = -256;
4801 MaxOffset = 255;
4802 break;
4803 // Unscaled
4804 case AArch64::LDURQi:
4805 case AArch64::STURQi:
4806 Scale = TypeSize::getFixed(1);
4807 Width = TypeSize::getFixed(16);
4808 MinOffset = -256;
4809 MaxOffset = 255;
4810 break;
4811 case AArch64::LDURXi:
4812 case AArch64::LDURDi:
4813 case AArch64::LDAPURXi:
4814 case AArch64::STURXi:
4815 case AArch64::STURDi:
4816 case AArch64::STLURXi:
4817 case AArch64::PRFUMi:
4818 Scale = TypeSize::getFixed(1);
4819 Width = TypeSize::getFixed(8);
4820 MinOffset = -256;
4821 MaxOffset = 255;
4822 break;
4823 case AArch64::LDURWi:
4824 case AArch64::LDURSi:
4825 case AArch64::LDURSWi:
4826 case AArch64::LDAPURi:
4827 case AArch64::LDAPURSWi:
4828 case AArch64::STURWi:
4829 case AArch64::STURSi:
4830 case AArch64::STLURWi:
4831 Scale = TypeSize::getFixed(1);
4832 Width = TypeSize::getFixed(4);
4833 MinOffset = -256;
4834 MaxOffset = 255;
4835 break;
4836 case AArch64::LDURHi:
4837 case AArch64::LDURHHi:
4838 case AArch64::LDURSHXi:
4839 case AArch64::LDURSHWi:
4840 case AArch64::LDAPURHi:
4841 case AArch64::LDAPURSHWi:
4842 case AArch64::LDAPURSHXi:
4843 case AArch64::STURHi:
4844 case AArch64::STURHHi:
4845 case AArch64::STLURHi:
4846 Scale = TypeSize::getFixed(1);
4847 Width = TypeSize::getFixed(2);
4848 MinOffset = -256;
4849 MaxOffset = 255;
4850 break;
4851 case AArch64::LDURBi:
4852 case AArch64::LDURBBi:
4853 case AArch64::LDURSBXi:
4854 case AArch64::LDURSBWi:
4855 case AArch64::LDAPURBi:
4856 case AArch64::LDAPURSBWi:
4857 case AArch64::LDAPURSBXi:
4858 case AArch64::STURBi:
4859 case AArch64::STURBBi:
4860 case AArch64::STLURBi:
4861 Scale = Width = TypeSize::getFixed(1);
4862 MinOffset = -256;
4863 MaxOffset = 255;
4864 break;
4865 // LDP / STP (including pre/post inc)
4866 case AArch64::LDPQi:
4867 case AArch64::LDNPQi:
4868 case AArch64::STPQi:
4869 case AArch64::STNPQi:
4870 case AArch64::LDPQpost:
4871 case AArch64::LDPQpre:
4872 case AArch64::STPQpost:
4873 case AArch64::STPQpre:
4874 Scale = TypeSize::getFixed(16);
4875 Width = TypeSize::getFixed(16 * 2);
4876 MinOffset = -64;
4877 MaxOffset = 63;
4878 break;
4879 case AArch64::LDPXi:
4880 case AArch64::LDPDi:
4881 case AArch64::LDNPXi:
4882 case AArch64::LDNPDi:
4883 case AArch64::STPXi:
4884 case AArch64::STPDi:
4885 case AArch64::STNPXi:
4886 case AArch64::STNPDi:
4887 case AArch64::LDPDpost:
4888 case AArch64::LDPDpre:
4889 case AArch64::LDPXpost:
4890 case AArch64::LDPXpre:
4891 case AArch64::STPDpost:
4892 case AArch64::STPDpre:
4893 case AArch64::STPXpost:
4894 case AArch64::STPXpre:
4895 Scale = TypeSize::getFixed(8);
4896 Width = TypeSize::getFixed(8 * 2);
4897 MinOffset = -64;
4898 MaxOffset = 63;
4899 break;
4900 case AArch64::LDPWi:
4901 case AArch64::LDPSi:
4902 case AArch64::LDNPWi:
4903 case AArch64::LDNPSi:
4904 case AArch64::STPWi:
4905 case AArch64::STPSi:
4906 case AArch64::STNPWi:
4907 case AArch64::STNPSi:
4908 case AArch64::LDPSpost:
4909 case AArch64::LDPSpre:
4910 case AArch64::LDPWpost:
4911 case AArch64::LDPWpre:
4912 case AArch64::STPSpost:
4913 case AArch64::STPSpre:
4914 case AArch64::STPWpost:
4915 case AArch64::STPWpre:
4916 Scale = TypeSize::getFixed(4);
4917 Width = TypeSize::getFixed(4 * 2);
4918 MinOffset = -64;
4919 MaxOffset = 63;
4920 break;
4921 case AArch64::StoreSwiftAsyncContext:
4922 // Store is an STRXui, but there might be an ADDXri in the expansion too.
4923 Scale = TypeSize::getFixed(1);
4924 Width = TypeSize::getFixed(8);
4925 MinOffset = 0;
4926 MaxOffset = 4095;
4927 break;
4928 case AArch64::ADDG:
4929 Scale = TypeSize::getFixed(16);
4930 Width = TypeSize::getFixed(0);
4931 MinOffset = 0;
4932 MaxOffset = 63;
4933 break;
4934 case AArch64::TAGPstack:
4935 Scale = TypeSize::getFixed(16);
4936 Width = TypeSize::getFixed(0);
4937 // TAGP with a negative offset turns into SUBP, which has a maximum offset
4938 // of 63 (not 64!).
4939 MinOffset = -63;
4940 MaxOffset = 63;
4941 break;
4942 case AArch64::LDG:
4943 case AArch64::STGi:
4944 case AArch64::STGPreIndex:
4945 case AArch64::STGPostIndex:
4946 case AArch64::STZGi:
4947 case AArch64::STZGPreIndex:
4948 case AArch64::STZGPostIndex:
4949 Scale = Width = TypeSize::getFixed(16);
4950 MinOffset = -256;
4951 MaxOffset = 255;
4952 break;
4953 // SVE
4954 case AArch64::STR_ZZZZXI:
4955 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4956 case AArch64::LDR_ZZZZXI:
4957 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4958 Scale = TypeSize::getScalable(16);
4959 Width = TypeSize::getScalable(16 * 4);
4960 MinOffset = -256;
4961 MaxOffset = 252;
4962 break;
4963 case AArch64::STR_ZZZXI:
4964 case AArch64::LDR_ZZZXI:
4965 Scale = TypeSize::getScalable(16);
4966 Width = TypeSize::getScalable(16 * 3);
4967 MinOffset = -256;
4968 MaxOffset = 253;
4969 break;
4970 case AArch64::STR_ZZXI:
4971 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4972 case AArch64::LDR_ZZXI:
4973 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4974 Scale = TypeSize::getScalable(16);
4975 Width = TypeSize::getScalable(16 * 2);
4976 MinOffset = -256;
4977 MaxOffset = 254;
4978 break;
4979 case AArch64::LDR_PXI:
4980 case AArch64::STR_PXI:
4981 Scale = Width = TypeSize::getScalable(2);
4982 MinOffset = -256;
4983 MaxOffset = 255;
4984 break;
4985 case AArch64::LDR_PPXI:
4986 case AArch64::STR_PPXI:
4987 Scale = TypeSize::getScalable(2);
4988 Width = TypeSize::getScalable(2 * 2);
4989 MinOffset = -256;
4990 MaxOffset = 254;
4991 break;
4992 case AArch64::LDR_ZXI:
4993 case AArch64::STR_ZXI:
4994 Scale = Width = TypeSize::getScalable(16);
4995 MinOffset = -256;
4996 MaxOffset = 255;
4997 break;
4998 case AArch64::LD1B_IMM:
4999 case AArch64::LD1H_IMM:
5000 case AArch64::LD1W_IMM:
5001 case AArch64::LD1D_IMM:
5002 case AArch64::LDNT1B_ZRI:
5003 case AArch64::LDNT1H_ZRI:
5004 case AArch64::LDNT1W_ZRI:
5005 case AArch64::LDNT1D_ZRI:
5006 case AArch64::ST1B_IMM:
5007 case AArch64::ST1H_IMM:
5008 case AArch64::ST1W_IMM:
5009 case AArch64::ST1D_IMM:
5010 case AArch64::STNT1B_ZRI:
5011 case AArch64::STNT1H_ZRI:
5012 case AArch64::STNT1W_ZRI:
5013 case AArch64::STNT1D_ZRI:
5014 case AArch64::LDNF1B_IMM:
5015 case AArch64::LDNF1H_IMM:
5016 case AArch64::LDNF1W_IMM:
5017 case AArch64::LDNF1D_IMM:
5018 // A full vectors worth of data
5019 // Width = mbytes * elements
5020 Scale = Width = TypeSize::getScalable(16);
5021 MinOffset = -8;
5022 MaxOffset = 7;
5023 break;
5024 case AArch64::LD2B_IMM:
5025 case AArch64::LD2H_IMM:
5026 case AArch64::LD2W_IMM:
5027 case AArch64::LD2D_IMM:
5028 case AArch64::ST2B_IMM:
5029 case AArch64::ST2H_IMM:
5030 case AArch64::ST2W_IMM:
5031 case AArch64::ST2D_IMM:
5032 case AArch64::LD1B_2Z_IMM:
5033 case AArch64::LD1B_2Z_STRIDED_IMM:
5034 case AArch64::LD1H_2Z_IMM:
5035 case AArch64::LD1H_2Z_STRIDED_IMM:
5036 case AArch64::LD1W_2Z_IMM:
5037 case AArch64::LD1W_2Z_STRIDED_IMM:
5038 case AArch64::LD1D_2Z_IMM:
5039 case AArch64::LD1D_2Z_STRIDED_IMM:
5040 case AArch64::LD1B_2Z_IMM_PSEUDO:
5041 case AArch64::LD1H_2Z_IMM_PSEUDO:
5042 case AArch64::LD1W_2Z_IMM_PSEUDO:
5043 case AArch64::LD1D_2Z_IMM_PSEUDO:
5044 case AArch64::ST1B_2Z_IMM:
5045 case AArch64::ST1B_2Z_STRIDED_IMM:
5046 case AArch64::ST1H_2Z_IMM:
5047 case AArch64::ST1H_2Z_STRIDED_IMM:
5048 case AArch64::ST1W_2Z_IMM:
5049 case AArch64::ST1W_2Z_STRIDED_IMM:
5050 case AArch64::ST1D_2Z_IMM:
5051 case AArch64::ST1D_2Z_STRIDED_IMM:
5052 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5053 case AArch64::LDNT1B_2Z_IMM:
5054 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5055 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5056 case AArch64::LDNT1H_2Z_IMM:
5057 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5058 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5059 case AArch64::LDNT1W_2Z_IMM:
5060 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5061 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5062 case AArch64::LDNT1D_2Z_IMM:
5063 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5064 case AArch64::STNT1B_2Z_IMM:
5065 case AArch64::STNT1B_2Z_STRIDED_IMM:
5066 case AArch64::STNT1H_2Z_IMM:
5067 case AArch64::STNT1H_2Z_STRIDED_IMM:
5068 case AArch64::STNT1W_2Z_IMM:
5069 case AArch64::STNT1W_2Z_STRIDED_IMM:
5070 case AArch64::STNT1D_2Z_IMM:
5071 case AArch64::STNT1D_2Z_STRIDED_IMM:
5072 case AArch64::ST1B_2Z_IMM_PSEUDO:
5073 case AArch64::ST1H_2Z_IMM_PSEUDO:
5074 case AArch64::ST1W_2Z_IMM_PSEUDO:
5075 case AArch64::ST1D_2Z_IMM_PSEUDO:
5076 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5077 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5078 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5079 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5080 Scale = Width = TypeSize::getScalable(16 * 2);
5081 MinOffset = -8;
5082 MaxOffset = 7;
5083 break;
5084 case AArch64::LD3B_IMM:
5085 case AArch64::LD3H_IMM:
5086 case AArch64::LD3W_IMM:
5087 case AArch64::LD3D_IMM:
5088 case AArch64::ST3B_IMM:
5089 case AArch64::ST3H_IMM:
5090 case AArch64::ST3W_IMM:
5091 case AArch64::ST3D_IMM:
5092 Scale = Width = TypeSize::getScalable(16 * 3);
5093 MinOffset = -8;
5094 MaxOffset = 7;
5095 break;
5096 case AArch64::LD4B_IMM:
5097 case AArch64::LD4H_IMM:
5098 case AArch64::LD4W_IMM:
5099 case AArch64::LD4D_IMM:
5100 case AArch64::ST4B_IMM:
5101 case AArch64::ST4H_IMM:
5102 case AArch64::ST4W_IMM:
5103 case AArch64::ST4D_IMM:
5104 case AArch64::LD1B_4Z_IMM:
5105 case AArch64::LD1B_4Z_STRIDED_IMM:
5106 case AArch64::LD1H_4Z_IMM:
5107 case AArch64::LD1H_4Z_STRIDED_IMM:
5108 case AArch64::LD1W_4Z_IMM:
5109 case AArch64::LD1W_4Z_STRIDED_IMM:
5110 case AArch64::LD1D_4Z_IMM:
5111 case AArch64::LD1D_4Z_STRIDED_IMM:
5112 case AArch64::LD1B_4Z_IMM_PSEUDO:
5113 case AArch64::LD1H_4Z_IMM_PSEUDO:
5114 case AArch64::LD1W_4Z_IMM_PSEUDO:
5115 case AArch64::LD1D_4Z_IMM_PSEUDO:
5116 case AArch64::ST1B_4Z_IMM:
5117 case AArch64::ST1B_4Z_STRIDED_IMM:
5118 case AArch64::ST1H_4Z_IMM:
5119 case AArch64::ST1H_4Z_STRIDED_IMM:
5120 case AArch64::ST1W_4Z_IMM:
5121 case AArch64::ST1W_4Z_STRIDED_IMM:
5122 case AArch64::ST1D_4Z_IMM:
5123 case AArch64::ST1D_4Z_STRIDED_IMM:
5124 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5125 case AArch64::LDNT1B_4Z_IMM:
5126 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5127 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5128 case AArch64::LDNT1H_4Z_IMM:
5129 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5130 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5131 case AArch64::LDNT1W_4Z_IMM:
5132 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5133 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5134 case AArch64::LDNT1D_4Z_IMM:
5135 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5136 case AArch64::STNT1B_4Z_IMM:
5137 case AArch64::STNT1B_4Z_STRIDED_IMM:
5138 case AArch64::STNT1H_4Z_IMM:
5139 case AArch64::STNT1H_4Z_STRIDED_IMM:
5140 case AArch64::STNT1W_4Z_IMM:
5141 case AArch64::STNT1W_4Z_STRIDED_IMM:
5142 case AArch64::STNT1D_4Z_IMM:
5143 case AArch64::STNT1D_4Z_STRIDED_IMM:
5144 case AArch64::ST1B_4Z_IMM_PSEUDO:
5145 case AArch64::ST1H_4Z_IMM_PSEUDO:
5146 case AArch64::ST1W_4Z_IMM_PSEUDO:
5147 case AArch64::ST1D_4Z_IMM_PSEUDO:
5148 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5149 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5150 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5151 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5152 Scale = Width = TypeSize::getScalable(16 * 4);
5153 MinOffset = -8;
5154 MaxOffset = 7;
5155 break;
5156 case AArch64::LD1B_H_IMM:
5157 case AArch64::LD1SB_H_IMM:
5158 case AArch64::LD1H_S_IMM:
5159 case AArch64::LD1SH_S_IMM:
5160 case AArch64::LD1W_D_IMM:
5161 case AArch64::LD1SW_D_IMM:
5162 case AArch64::ST1B_H_IMM:
5163 case AArch64::ST1H_S_IMM:
5164 case AArch64::ST1W_D_IMM:
5165 case AArch64::LDNF1B_H_IMM:
5166 case AArch64::LDNF1SB_H_IMM:
5167 case AArch64::LDNF1H_S_IMM:
5168 case AArch64::LDNF1SH_S_IMM:
5169 case AArch64::LDNF1W_D_IMM:
5170 case AArch64::LDNF1SW_D_IMM:
5171 // A half vector worth of data
5172 // Width = mbytes * elements
5173 Scale = Width = TypeSize::getScalable(8);
5174 MinOffset = -8;
5175 MaxOffset = 7;
5176 break;
5177 case AArch64::LD1B_S_IMM:
5178 case AArch64::LD1SB_S_IMM:
5179 case AArch64::LD1H_D_IMM:
5180 case AArch64::LD1SH_D_IMM:
5181 case AArch64::ST1B_S_IMM:
5182 case AArch64::ST1H_D_IMM:
5183 case AArch64::LDNF1B_S_IMM:
5184 case AArch64::LDNF1SB_S_IMM:
5185 case AArch64::LDNF1H_D_IMM:
5186 case AArch64::LDNF1SH_D_IMM:
5187 // A quarter vector worth of data
5188 // Width = mbytes * elements
5189 Scale = Width = TypeSize::getScalable(4);
5190 MinOffset = -8;
5191 MaxOffset = 7;
5192 break;
5193 case AArch64::LD1B_D_IMM:
5194 case AArch64::LD1SB_D_IMM:
5195 case AArch64::ST1B_D_IMM:
5196 case AArch64::LDNF1B_D_IMM:
5197 case AArch64::LDNF1SB_D_IMM:
5198 // A eighth vector worth of data
5199 // Width = mbytes * elements
5200 Scale = Width = TypeSize::getScalable(2);
5201 MinOffset = -8;
5202 MaxOffset = 7;
5203 break;
5204 case AArch64::ST2Gi:
5205 case AArch64::ST2GPreIndex:
5206 case AArch64::ST2GPostIndex:
5207 case AArch64::STZ2Gi:
5208 case AArch64::STZ2GPreIndex:
5209 case AArch64::STZ2GPostIndex:
5210 Scale = TypeSize::getFixed(16);
5211 Width = TypeSize::getFixed(32);
5212 MinOffset = -256;
5213 MaxOffset = 255;
5214 break;
5215 case AArch64::STGPi:
5216 case AArch64::STGPpost:
5217 case AArch64::STGPpre:
5218 Scale = Width = TypeSize::getFixed(16);
5219 MinOffset = -64;
5220 MaxOffset = 63;
5221 break;
5222 case AArch64::LD1RB_IMM:
5223 case AArch64::LD1RB_H_IMM:
5224 case AArch64::LD1RB_S_IMM:
5225 case AArch64::LD1RB_D_IMM:
5226 case AArch64::LD1RSB_H_IMM:
5227 case AArch64::LD1RSB_S_IMM:
5228 case AArch64::LD1RSB_D_IMM:
5229 Scale = Width = TypeSize::getFixed(1);
5230 MinOffset = 0;
5231 MaxOffset = 63;
5232 break;
5233 case AArch64::LD1RH_IMM:
5234 case AArch64::LD1RH_S_IMM:
5235 case AArch64::LD1RH_D_IMM:
5236 case AArch64::LD1RSH_S_IMM:
5237 case AArch64::LD1RSH_D_IMM:
5238 Scale = Width = TypeSize::getFixed(2);
5239 MinOffset = 0;
5240 MaxOffset = 63;
5241 break;
5242 case AArch64::LD1RW_IMM:
5243 case AArch64::LD1RW_D_IMM:
5244 case AArch64::LD1RSW_IMM:
5245 Scale = Width = TypeSize::getFixed(4);
5246 MinOffset = 0;
5247 MaxOffset = 63;
5248 break;
5249 case AArch64::LD1RD_IMM:
5250 Scale = Width = TypeSize::getFixed(8);
5251 MinOffset = 0;
5252 MaxOffset = 63;
5253 break;
5254 }
5255
5256 return true;
5257}
5258
5259// Scaling factor for unscaled load or store.
5261 switch (Opc) {
5262 default:
5263 llvm_unreachable("Opcode has unknown scale!");
5264 case AArch64::LDRBui:
5265 case AArch64::LDRBBui:
5266 case AArch64::LDURBBi:
5267 case AArch64::LDRSBWui:
5268 case AArch64::LDURSBWi:
5269 case AArch64::STRBui:
5270 case AArch64::STRBBui:
5271 case AArch64::STURBBi:
5272 return 1;
5273 case AArch64::LDRHui:
5274 case AArch64::LDRHHui:
5275 case AArch64::LDURHHi:
5276 case AArch64::LDRSHWui:
5277 case AArch64::LDURSHWi:
5278 case AArch64::STRHui:
5279 case AArch64::STRHHui:
5280 case AArch64::STURHHi:
5281 return 2;
5282 case AArch64::LDRSui:
5283 case AArch64::LDURSi:
5284 case AArch64::LDRSpre:
5285 case AArch64::LDRSWui:
5286 case AArch64::LDURSWi:
5287 case AArch64::LDRSWpre:
5288 case AArch64::LDRWpre:
5289 case AArch64::LDRWui:
5290 case AArch64::LDURWi:
5291 case AArch64::STRSui:
5292 case AArch64::STURSi:
5293 case AArch64::STRSpre:
5294 case AArch64::STRWui:
5295 case AArch64::STURWi:
5296 case AArch64::STRWpre:
5297 case AArch64::LDPSi:
5298 case AArch64::LDPSWi:
5299 case AArch64::LDPWi:
5300 case AArch64::STPSi:
5301 case AArch64::STPWi:
5302 return 4;
5303 case AArch64::LDRDui:
5304 case AArch64::LDURDi:
5305 case AArch64::LDRDpre:
5306 case AArch64::LDRXui:
5307 case AArch64::LDURXi:
5308 case AArch64::LDRXpre:
5309 case AArch64::STRDui:
5310 case AArch64::STURDi:
5311 case AArch64::STRDpre:
5312 case AArch64::STRXui:
5313 case AArch64::STURXi:
5314 case AArch64::STRXpre:
5315 case AArch64::LDPDi:
5316 case AArch64::LDPXi:
5317 case AArch64::STPDi:
5318 case AArch64::STPXi:
5319 return 8;
5320 case AArch64::LDRQui:
5321 case AArch64::LDURQi:
5322 case AArch64::STRQui:
5323 case AArch64::STURQi:
5324 case AArch64::STRQpre:
5325 case AArch64::LDPQi:
5326 case AArch64::LDRQpre:
5327 case AArch64::STPQi:
5328 case AArch64::STGi:
5329 case AArch64::STZGi:
5330 case AArch64::ST2Gi:
5331 case AArch64::STZ2Gi:
5332 case AArch64::STGPi:
5333 return 16;
5334 }
5335}
5336
5338 switch (MI.getOpcode()) {
5339 default:
5340 return false;
5341 case AArch64::LDRWpre:
5342 case AArch64::LDRXpre:
5343 case AArch64::LDRSWpre:
5344 case AArch64::LDRSpre:
5345 case AArch64::LDRDpre:
5346 case AArch64::LDRQpre:
5347 return true;
5348 }
5349}
5350
5352 switch (MI.getOpcode()) {
5353 default:
5354 return false;
5355 case AArch64::STRWpre:
5356 case AArch64::STRXpre:
5357 case AArch64::STRSpre:
5358 case AArch64::STRDpre:
5359 case AArch64::STRQpre:
5360 return true;
5361 }
5362}
5363
5365 return isPreLd(MI) || isPreSt(MI);
5366}
5367
5369 switch (MI.getOpcode()) {
5370 default:
5371 return false;
5372 case AArch64::LDURBBi:
5373 case AArch64::LDURHHi:
5374 case AArch64::LDURWi:
5375 case AArch64::LDRBBui:
5376 case AArch64::LDRHHui:
5377 case AArch64::LDRWui:
5378 case AArch64::LDRBBroX:
5379 case AArch64::LDRHHroX:
5380 case AArch64::LDRWroX:
5381 case AArch64::LDRBBroW:
5382 case AArch64::LDRHHroW:
5383 case AArch64::LDRWroW:
5384 return true;
5385 }
5386}
5387
5389 switch (MI.getOpcode()) {
5390 default:
5391 return false;
5392 case AArch64::LDURSBWi:
5393 case AArch64::LDURSHWi:
5394 case AArch64::LDURSBXi:
5395 case AArch64::LDURSHXi:
5396 case AArch64::LDURSWi:
5397 case AArch64::LDRSBWui:
5398 case AArch64::LDRSHWui:
5399 case AArch64::LDRSBXui:
5400 case AArch64::LDRSHXui:
5401 case AArch64::LDRSWui:
5402 case AArch64::LDRSBWroX:
5403 case AArch64::LDRSHWroX:
5404 case AArch64::LDRSBXroX:
5405 case AArch64::LDRSHXroX:
5406 case AArch64::LDRSWroX:
5407 case AArch64::LDRSBWroW:
5408 case AArch64::LDRSHWroW:
5409 case AArch64::LDRSBXroW:
5410 case AArch64::LDRSHXroW:
5411 case AArch64::LDRSWroW:
5412 return true;
5413 }
5414}
5415
5417 switch (MI.getOpcode()) {
5418 default:
5419 return false;
5420 case AArch64::LDPSi:
5421 case AArch64::LDPSWi:
5422 case AArch64::LDPDi:
5423 case AArch64::LDPQi:
5424 case AArch64::LDPWi:
5425 case AArch64::LDPXi:
5426 case AArch64::STPSi:
5427 case AArch64::STPDi:
5428 case AArch64::STPQi:
5429 case AArch64::STPWi:
5430 case AArch64::STPXi:
5431 case AArch64::STGPi:
5432 return true;
5433 }
5434}
5435
5437 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5438 unsigned Idx =
5440 : 1;
5441 return MI.getOperand(Idx);
5442}
5443
5444const MachineOperand &
5446 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5447 unsigned Idx =
5449 : 2;
5450 return MI.getOperand(Idx);
5451}
5452
5453const MachineOperand &
5455 switch (MI.getOpcode()) {
5456 default:
5457 llvm_unreachable("Unexpected opcode");
5458 case AArch64::LDRBroX:
5459 case AArch64::LDRBBroX:
5460 case AArch64::LDRSBXroX:
5461 case AArch64::LDRSBWroX:
5462 case AArch64::LDRHroX:
5463 case AArch64::LDRHHroX:
5464 case AArch64::LDRSHXroX:
5465 case AArch64::LDRSHWroX:
5466 case AArch64::LDRWroX:
5467 case AArch64::LDRSroX:
5468 case AArch64::LDRSWroX:
5469 case AArch64::LDRDroX:
5470 case AArch64::LDRXroX:
5471 case AArch64::LDRQroX:
5472 return MI.getOperand(4);
5473 }
5474}
5475
5477 Register Reg) {
5478 if (MI.getParent() == nullptr)
5479 return nullptr;
5480 const MachineFunction *MF = MI.getParent()->getParent();
5481 return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr;
5482}
5483
5485 auto IsHFPR = [&](const MachineOperand &Op) {
5486 if (!Op.isReg())
5487 return false;
5488 auto Reg = Op.getReg();
5489 if (Reg.isPhysical())
5490 return AArch64::FPR16RegClass.contains(Reg);
5491 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5492 return TRC == &AArch64::FPR16RegClass ||
5493 TRC == &AArch64::FPR16_loRegClass;
5494 };
5495 return llvm::any_of(MI.operands(), IsHFPR);
5496}
5497
5499 auto IsQFPR = [&](const MachineOperand &Op) {
5500 if (!Op.isReg())
5501 return false;
5502 auto Reg = Op.getReg();
5503 if (Reg.isPhysical())
5504 return AArch64::FPR128RegClass.contains(Reg);
5505 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5506 return TRC == &AArch64::FPR128RegClass ||
5507 TRC == &AArch64::FPR128_loRegClass;
5508 };
5509 return llvm::any_of(MI.operands(), IsQFPR);
5510}
5511
5513 switch (MI.getOpcode()) {
5514 case AArch64::BRK:
5515 case AArch64::HLT:
5516 case AArch64::PACIASP:
5517 case AArch64::PACIBSP:
5518 // Implicit BTI behavior.
5519 return true;
5520 case AArch64::PAUTH_PROLOGUE:
5521 // PAUTH_PROLOGUE expands to PACI(A|B)SP.
5522 return true;
5523 case AArch64::HINT: {
5524 unsigned Imm = MI.getOperand(0).getImm();
5525 // Explicit BTI instruction.
5526 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5527 return true;
5528 // PACI(A|B)SP instructions.
5529 if (Imm == 25 || Imm == 27)
5530 return true;
5531 return false;
5532 }
5533 default:
5534 return false;
5535 }
5536}
5537
5539 if (Reg == 0)
5540 return false;
5541 assert(Reg.isPhysical() && "Expected physical register in isFpOrNEON");
5542 return AArch64::FPR128RegClass.contains(Reg) ||
5543 AArch64::FPR64RegClass.contains(Reg) ||
5544 AArch64::FPR32RegClass.contains(Reg) ||
5545 AArch64::FPR16RegClass.contains(Reg) ||
5546 AArch64::FPR8RegClass.contains(Reg);
5547}
5548
5550 auto IsFPR = [&](const MachineOperand &Op) {
5551 if (!Op.isReg())
5552 return false;
5553 auto Reg = Op.getReg();
5554 if (Reg.isPhysical())
5555 return isFpOrNEON(Reg);
5556
5557 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5558 return TRC == &AArch64::FPR128RegClass ||
5559 TRC == &AArch64::FPR128_loRegClass ||
5560 TRC == &AArch64::FPR64RegClass ||
5561 TRC == &AArch64::FPR64_loRegClass ||
5562 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5563 TRC == &AArch64::FPR8RegClass;
5564 };
5565 return llvm::any_of(MI.operands(), IsFPR);
5566}
5567
5568// Scale the unscaled offsets. Returns false if the unscaled offset can't be
5569// scaled.
5570static bool scaleOffset(unsigned Opc, int64_t &Offset) {
5572
5573 // If the byte-offset isn't a multiple of the stride, we can't scale this
5574 // offset.
5575 if (Offset % Scale != 0)
5576 return false;
5577
5578 // Convert the byte-offset used by unscaled into an "element" offset used
5579 // by the scaled pair load/store instructions.
5580 Offset /= Scale;
5581 return true;
5582}
5583
5584static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
5585 if (FirstOpc == SecondOpc)
5586 return true;
5587 // We can also pair sign-ext and zero-ext instructions.
5588 switch (FirstOpc) {
5589 default:
5590 return false;
5591 case AArch64::STRSui:
5592 case AArch64::STURSi:
5593 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5594 case AArch64::STRDui:
5595 case AArch64::STURDi:
5596 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5597 case AArch64::STRQui:
5598 case AArch64::STURQi:
5599 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5600 case AArch64::STRWui:
5601 case AArch64::STURWi:
5602 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5603 case AArch64::STRXui:
5604 case AArch64::STURXi:
5605 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5606 case AArch64::LDRSui:
5607 case AArch64::LDURSi:
5608 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5609 case AArch64::LDRDui:
5610 case AArch64::LDURDi:
5611 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5612 case AArch64::LDRQui:
5613 case AArch64::LDURQi:
5614 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5615 case AArch64::LDRWui:
5616 case AArch64::LDURWi:
5617 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5618 case AArch64::LDRSWui:
5619 case AArch64::LDURSWi:
5620 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5621 case AArch64::LDRXui:
5622 case AArch64::LDURXi:
5623 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5624 }
5625 // These instructions can't be paired based on their opcodes.
5626 return false;
5627}
5628
5629static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1,
5630 int64_t Offset1, unsigned Opcode1, int FI2,
5631 int64_t Offset2, unsigned Opcode2) {
5632 // Accesses through fixed stack object frame indices may access a different
5633 // fixed stack slot. Check that the object offsets + offsets match.
5634 if (MFI.isFixedObjectIndex(FI1) && MFI.isFixedObjectIndex(FI2)) {
5635 int64_t ObjectOffset1 = MFI.getObjectOffset(FI1);
5636 int64_t ObjectOffset2 = MFI.getObjectOffset(FI2);
5637 assert(ObjectOffset1 <= ObjectOffset2 && "Object offsets are not ordered.");
5638 // Convert to scaled object offsets.
5639 int Scale1 = AArch64InstrInfo::getMemScale(Opcode1);
5640 if (ObjectOffset1 % Scale1 != 0)
5641 return false;
5642 ObjectOffset1 /= Scale1;
5643 int Scale2 = AArch64InstrInfo::getMemScale(Opcode2);
5644 if (ObjectOffset2 % Scale2 != 0)
5645 return false;
5646 ObjectOffset2 /= Scale2;
5647 ObjectOffset1 += Offset1;
5648 ObjectOffset2 += Offset2;
5649 return ObjectOffset1 + 1 == ObjectOffset2;
5650 }
5651
5652 return FI1 == FI2;
5653}
5654
5655/// Detect opportunities for ldp/stp formation.
5656///
5657/// Only called for LdSt for which getMemOperandWithOffset returns true.
5659 ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
5660 bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
5661 int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
5662 unsigned NumBytes) const {
5663 assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
5664 const MachineOperand &BaseOp1 = *BaseOps1.front();
5665 const MachineOperand &BaseOp2 = *BaseOps2.front();
5666 const MachineInstr &FirstLdSt = *BaseOp1.getParent();
5667 const MachineInstr &SecondLdSt = *BaseOp2.getParent();
5668 if (BaseOp1.getType() != BaseOp2.getType())
5669 return false;
5670
5671 assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
5672 "Only base registers and frame indices are supported.");
5673
5674 // Check for both base regs and base FI.
5675 if (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg())
5676 return false;
5677
5678 // Only cluster up to a single pair.
5679 if (ClusterSize > 2)
5680 return false;
5681
5682 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
5683 return false;
5684
5685 // Can we pair these instructions based on their opcodes?
5686 unsigned FirstOpc = FirstLdSt.getOpcode();
5687 unsigned SecondOpc = SecondLdSt.getOpcode();
5688 if (!canPairLdStOpc(FirstOpc, SecondOpc))
5689 return false;
5690
5691 // Can't merge volatiles or load/stores that have a hint to avoid pair
5692 // formation, for example.
5693 if (!isCandidateToMergeOrPair(FirstLdSt) ||
5694 !isCandidateToMergeOrPair(SecondLdSt))
5695 return false;
5696
5697 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
5698 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
5699 if (hasUnscaledLdStOffset(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
5700 return false;
5701
5702 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
5703 if (hasUnscaledLdStOffset(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
5704 return false;
5705
5706 // Pairwise instructions have a 7-bit signed offset field.
5707 if (Offset1 > 63 || Offset1 < -64)
5708 return false;
5709
5710 // The caller should already have ordered First/SecondLdSt by offset.
5711 // Note: except for non-equal frame index bases
5712 if (BaseOp1.isFI()) {
5713 assert((!BaseOp1.isIdenticalTo(BaseOp2) || Offset1 <= Offset2) &&
5714 "Caller should have ordered offsets.");
5715
5716 const MachineFrameInfo &MFI =
5717 FirstLdSt.getParent()->getParent()->getFrameInfo();
5718 return shouldClusterFI(MFI, BaseOp1.getIndex(), Offset1, FirstOpc,
5719 BaseOp2.getIndex(), Offset2, SecondOpc);
5720 }
5721
5722 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
5723
5724 return Offset1 + 1 == Offset2;
5725}
5726
5728 MCRegister Reg, unsigned SubIdx,
5729 RegState State,
5730 const TargetRegisterInfo *TRI) {
5731 if (!SubIdx)
5732 return MIB.addReg(Reg, State);
5733
5734 if (Reg.isPhysical())
5735 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
5736 return MIB.addReg(Reg, State, SubIdx);
5737}
5738
5739static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg,
5740 unsigned NumRegs) {
5741 // We really want the positive remainder mod 32 here, that happens to be
5742 // easily obtainable with a mask.
5743 return ((DestReg - SrcReg) & 0x1f) < NumRegs;
5744}
5745
5748 const DebugLoc &DL, MCRegister DestReg,
5749 MCRegister SrcReg, bool KillSrc,
5750 unsigned Opcode,
5751 ArrayRef<unsigned> Indices) const {
5752 assert(Subtarget.hasNEON() && "Unexpected register copy without NEON");
5754 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5755 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5756 unsigned NumRegs = Indices.size();
5757
5758 int SubReg = 0, End = NumRegs, Incr = 1;
5759 if (forwardCopyWillClobberTuple(DestEncoding, SrcEncoding, NumRegs)) {
5760 SubReg = NumRegs - 1;
5761 End = -1;
5762 Incr = -1;
5763 }
5764
5765 for (; SubReg != End; SubReg += Incr) {
5766 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5767 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5768 AddSubReg(MIB, SrcReg, Indices[SubReg], {}, TRI);
5769 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5770 }
5771}
5772
5775 const DebugLoc &DL, MCRegister DestReg,
5776 MCRegister SrcReg, bool KillSrc,
5777 unsigned Opcode, unsigned ZeroReg,
5778 llvm::ArrayRef<unsigned> Indices) const {
5780 unsigned NumRegs = Indices.size();
5781
5782#ifndef NDEBUG
5783 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5784 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5785 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5786 "GPR reg sequences should not be able to overlap");
5787#endif
5788
5789 for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5790 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5791 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5792 MIB.addReg(ZeroReg);
5793 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5794 MIB.addImm(0);
5795 }
5796}
5797
5798/// Returns true if the instruction at I is in a streaming call site region,
5799/// within a single basic block.
5800/// A "call site streaming region" starts after smstart and ends at smstop
5801/// around a call to a streaming function. This walks backward from I.
5804 MachineFunction &MF = *MBB.getParent();
5806 if (!AFI->hasStreamingModeChanges())
5807 return false;
5808 // Walk backwards to find smstart/smstop
5809 for (MachineInstr &MI : reverse(make_range(MBB.begin(), I))) {
5810 unsigned Opc = MI.getOpcode();
5811 if (Opc == AArch64::MSRpstatesvcrImm1 || Opc == AArch64::MSRpstatePseudo) {
5812 // Check if this is SM change (not ZA)
5813 int64_t PState = MI.getOperand(0).getImm();
5814 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5815 // Operand 1 is 1 for start, 0 for stop
5816 return MI.getOperand(1).getImm() == 1;
5817 }
5818 }
5819 }
5820 return false;
5821}
5822
5823/// Returns true if in a streaming call site region without SME-FA64.
5824static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget,
5827 return !Subtarget.hasSMEFA64() && isInStreamingCallSiteRegion(MBB, I);
5828}
5829
5832 const DebugLoc &DL, Register DestReg,
5833 Register SrcReg, bool KillSrc,
5834 bool RenamableDest,
5835 bool RenamableSrc) const {
5836 ++NumCopyInstrs;
5837 if (AArch64::GPR32spRegClass.contains(DestReg) &&
5838 AArch64::GPR32spRegClass.contains(SrcReg)) {
5839 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5840 // If either operand is WSP, expand to ADD #0.
5841 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5842 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5843 // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
5844 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5845 &AArch64::GPR64spRegClass);
5846 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5847 &AArch64::GPR64spRegClass);
5848 // This instruction is reading and writing X registers. This may upset
5849 // the register scavenger and machine verifier, so we need to indicate
5850 // that we are reading an undefined value from SrcRegX, but a proper
5851 // value from SrcReg.
5852 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
5853 .addReg(SrcRegX, RegState::Undef)
5854 .addImm(0)
5856 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5857 ++NumZCRegMoveInstrsGPR;
5858 } else {
5859 BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
5860 .addReg(SrcReg, getKillRegState(KillSrc))
5861 .addImm(0)
5863 if (Subtarget.hasZeroCycleRegMoveGPR32())
5864 ++NumZCRegMoveInstrsGPR;
5865 }
5866 } else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5867 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5868 // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
5869 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5870 &AArch64::GPR64spRegClass);
5871 assert(DestRegX.isValid() && "Destination super-reg not valid");
5872 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5873 &AArch64::GPR64spRegClass);
5874 assert(SrcRegX.isValid() && "Source super-reg not valid");
5875 // This instruction is reading and writing X registers. This may upset
5876 // the register scavenger and machine verifier, so we need to indicate
5877 // that we are reading an undefined value from SrcRegX, but a proper
5878 // value from SrcReg.
5879 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
5880 .addReg(AArch64::XZR)
5881 .addReg(SrcRegX, RegState::Undef)
5882 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5883 ++NumZCRegMoveInstrsGPR;
5884 } else {
5885 // Otherwise, expand to ORR WZR.
5886 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5887 .addReg(AArch64::WZR)
5888 .addReg(SrcReg, getKillRegState(KillSrc));
5889 if (Subtarget.hasZeroCycleRegMoveGPR32())
5890 ++NumZCRegMoveInstrsGPR;
5891 }
5892 return;
5893 }
5894
5895 // GPR32 zeroing
5896 if (AArch64::GPR32spRegClass.contains(DestReg) && SrcReg == AArch64::WZR) {
5897 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5898 !Subtarget.hasZeroCycleZeroingGPR32()) {
5899 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5900 &AArch64::GPR64spRegClass);
5901 assert(DestRegX.isValid() && "Destination super-reg not valid");
5902 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestRegX)
5903 .addImm(0)
5905 ++NumZCZeroingInstrsGPR;
5906 } else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5907 BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg)
5908 .addImm(0)
5910 ++NumZCZeroingInstrsGPR;
5911 } else {
5912 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5913 .addReg(AArch64::WZR)
5914 .addReg(AArch64::WZR);
5915 }
5916 return;
5917 }
5918
5919 if (AArch64::GPR64spRegClass.contains(DestReg) &&
5920 AArch64::GPR64spRegClass.contains(SrcReg)) {
5921 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5922 // If either operand is SP, expand to ADD #0.
5923 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
5924 .addReg(SrcReg, getKillRegState(KillSrc))
5925 .addImm(0)
5927 if (Subtarget.hasZeroCycleRegMoveGPR64())
5928 ++NumZCRegMoveInstrsGPR;
5929 } else {
5930 // Otherwise, expand to ORR XZR.
5931 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5932 .addReg(AArch64::XZR)
5933 .addReg(SrcReg, getKillRegState(KillSrc));
5934 if (Subtarget.hasZeroCycleRegMoveGPR64())
5935 ++NumZCRegMoveInstrsGPR;
5936 }
5937 return;
5938 }
5939
5940 // GPR64 zeroing
5941 if (AArch64::GPR64spRegClass.contains(DestReg) && SrcReg == AArch64::XZR) {
5942 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5943 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg)
5944 .addImm(0)
5946 ++NumZCZeroingInstrsGPR;
5947 } else {
5948 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5949 .addReg(AArch64::XZR)
5950 .addReg(AArch64::XZR);
5951 }
5952 return;
5953 }
5954
5955 // Copy a Predicate register by ORRing with itself.
5956 if (AArch64::PPRRegClass.contains(DestReg) &&
5957 AArch64::PPRRegClass.contains(SrcReg)) {
5958 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5959 "Unexpected SVE register.");
5960 BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), DestReg)
5961 .addReg(SrcReg) // Pg
5962 .addReg(SrcReg)
5963 .addReg(SrcReg, getKillRegState(KillSrc));
5964 return;
5965 }
5966
5967 // Copy a predicate-as-counter register by ORRing with itself as if it
5968 // were a regular predicate (mask) register.
5969 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
5970 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
5971 if (DestIsPNR || SrcIsPNR) {
5972 auto ToPPR = [](MCRegister R) -> MCRegister {
5973 return (R - AArch64::PN0) + AArch64::P0;
5974 };
5975 MCRegister PPRSrcReg = SrcIsPNR ? ToPPR(SrcReg) : SrcReg.asMCReg();
5976 MCRegister PPRDestReg = DestIsPNR ? ToPPR(DestReg) : DestReg.asMCReg();
5977
5978 if (PPRSrcReg != PPRDestReg) {
5979 auto NewMI = BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), PPRDestReg)
5980 .addReg(PPRSrcReg) // Pg
5981 .addReg(PPRSrcReg)
5982 .addReg(PPRSrcReg, getKillRegState(KillSrc));
5983 if (DestIsPNR)
5984 NewMI.addDef(DestReg, RegState::Implicit);
5985 }
5986 return;
5987 }
5988
5989 // Copy a Z register by ORRing with itself.
5990 if (AArch64::ZPRRegClass.contains(DestReg) &&
5991 AArch64::ZPRRegClass.contains(SrcReg)) {
5992 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5993 "Unexpected SVE register.");
5994 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ), DestReg)
5995 .addReg(SrcReg)
5996 .addReg(SrcReg, getKillRegState(KillSrc));
5997 return;
5998 }
5999
6000 // Copy a Z register pair by copying the individual sub-registers.
6001 if ((AArch64::ZPR2RegClass.contains(DestReg) ||
6002 AArch64::ZPR2StridedOrContiguousRegClass.contains(DestReg)) &&
6003 (AArch64::ZPR2RegClass.contains(SrcReg) ||
6004 AArch64::ZPR2StridedOrContiguousRegClass.contains(SrcReg))) {
6005 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6006 "Unexpected SVE register.");
6007 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6008 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6009 Indices);
6010 return;
6011 }
6012
6013 // Copy a Z register triple by copying the individual sub-registers.
6014 if (AArch64::ZPR3RegClass.contains(DestReg) &&
6015 AArch64::ZPR3RegClass.contains(SrcReg)) {
6016 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6017 "Unexpected SVE register.");
6018 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6019 AArch64::zsub2};
6020 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6021 Indices);
6022 return;
6023 }
6024
6025 // Copy a Z register quad by copying the individual sub-registers.
6026 if ((AArch64::ZPR4RegClass.contains(DestReg) ||
6027 AArch64::ZPR4StridedOrContiguousRegClass.contains(DestReg)) &&
6028 (AArch64::ZPR4RegClass.contains(SrcReg) ||
6029 AArch64::ZPR4StridedOrContiguousRegClass.contains(SrcReg))) {
6030 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6031 "Unexpected SVE register.");
6032 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6033 AArch64::zsub2, AArch64::zsub3};
6034 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORR_ZZZ,
6035 Indices);
6036 return;
6037 }
6038
6039 // Copy a DDDD register quad by copying the individual sub-registers.
6040 if (AArch64::DDDDRegClass.contains(DestReg) &&
6041 AArch64::DDDDRegClass.contains(SrcReg)) {
6042 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6043 AArch64::dsub2, AArch64::dsub3};
6044 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6045 Indices);
6046 return;
6047 }
6048
6049 // Copy a DDD register triple by copying the individual sub-registers.
6050 if (AArch64::DDDRegClass.contains(DestReg) &&
6051 AArch64::DDDRegClass.contains(SrcReg)) {
6052 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6053 AArch64::dsub2};
6054 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6055 Indices);
6056 return;
6057 }
6058
6059 // Copy a DD register pair by copying the individual sub-registers.
6060 if (AArch64::DDRegClass.contains(DestReg) &&
6061 AArch64::DDRegClass.contains(SrcReg)) {
6062 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6063 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv8i8,
6064 Indices);
6065 return;
6066 }
6067
6068 // Copy a QQQQ register quad by copying the individual sub-registers.
6069 if (AArch64::QQQQRegClass.contains(DestReg) &&
6070 AArch64::QQQQRegClass.contains(SrcReg)) {
6071 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6072 AArch64::qsub2, AArch64::qsub3};
6073 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6074 Indices);
6075 return;
6076 }
6077
6078 // Copy a QQQ register triple by copying the individual sub-registers.
6079 if (AArch64::QQQRegClass.contains(DestReg) &&
6080 AArch64::QQQRegClass.contains(SrcReg)) {
6081 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6082 AArch64::qsub2};
6083 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6084 Indices);
6085 return;
6086 }
6087
6088 // Copy a QQ register pair by copying the individual sub-registers.
6089 if (AArch64::QQRegClass.contains(DestReg) &&
6090 AArch64::QQRegClass.contains(SrcReg)) {
6091 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6092 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRv16i8,
6093 Indices);
6094 return;
6095 }
6096
6097 if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
6098 AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
6099 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6100 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
6101 AArch64::XZR, Indices);
6102 return;
6103 }
6104
6105 if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
6106 AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
6107 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6108 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
6109 AArch64::WZR, Indices);
6110 return;
6111 }
6112
6113 if (AArch64::FPR128RegClass.contains(DestReg) &&
6114 AArch64::FPR128RegClass.contains(SrcReg)) {
6115 // In streaming regions, NEON is illegal but streaming-SVE is available.
6116 // Use SVE for copies if we're in a streaming region and SME is available.
6117 // With +sme-fa64, NEON is legal in streaming mode so we can use it.
6118 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6119 !Subtarget.isNeonAvailable()) ||
6120 mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6121 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ))
6122 .addReg(AArch64::Z0 + (DestReg - AArch64::Q0), RegState::Define)
6123 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6124 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6125 } else if (Subtarget.isNeonAvailable()) {
6126 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
6127 .addReg(SrcReg)
6128 .addReg(SrcReg, getKillRegState(KillSrc));
6129 if (Subtarget.hasZeroCycleRegMoveFPR128())
6130 ++NumZCRegMoveInstrsFPR;
6131 } else {
6132 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
6133 .addReg(AArch64::SP, RegState::Define)
6134 .addReg(SrcReg, getKillRegState(KillSrc))
6135 .addReg(AArch64::SP)
6136 .addImm(-16);
6137 BuildMI(MBB, I, DL, get(AArch64::LDRQpost))
6138 .addReg(AArch64::SP, RegState::Define)
6139 .addReg(DestReg, RegState::Define)
6140 .addReg(AArch64::SP)
6141 .addImm(16);
6142 }
6143 return;
6144 }
6145
6146 if (AArch64::FPR64RegClass.contains(DestReg) &&
6147 AArch64::FPR64RegClass.contains(SrcReg)) {
6148 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6149 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6150 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6151 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6152 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6153 &AArch64::FPR128RegClass);
6154 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6155 &AArch64::FPR128RegClass);
6156 // This instruction is reading and writing Q registers. This may upset
6157 // the register scavenger and machine verifier, so we need to indicate
6158 // that we are reading an undefined value from SrcRegQ, but a proper
6159 // value from SrcReg.
6160 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6161 .addReg(SrcRegQ, RegState::Undef)
6162 .addReg(SrcRegQ, RegState::Undef)
6163 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6164 ++NumZCRegMoveInstrsFPR;
6165 } else {
6166 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
6167 .addReg(SrcReg, getKillRegState(KillSrc));
6168 if (Subtarget.hasZeroCycleRegMoveFPR64())
6169 ++NumZCRegMoveInstrsFPR;
6170 }
6171 return;
6172 }
6173
6174 if (AArch64::FPR32RegClass.contains(DestReg) &&
6175 AArch64::FPR32RegClass.contains(SrcReg)) {
6176 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6177 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6178 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6179 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6180 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6181 &AArch64::FPR128RegClass);
6182 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6183 &AArch64::FPR128RegClass);
6184 // This instruction is reading and writing Q registers. This may upset
6185 // the register scavenger and machine verifier, so we need to indicate
6186 // that we are reading an undefined value from SrcRegQ, but a proper
6187 // value from SrcReg.
6188 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6189 .addReg(SrcRegQ, RegState::Undef)
6190 .addReg(SrcRegQ, RegState::Undef)
6191 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6192 ++NumZCRegMoveInstrsFPR;
6193 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6194 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6195 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6196 &AArch64::FPR64RegClass);
6197 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6198 &AArch64::FPR64RegClass);
6199 // This instruction is reading and writing D registers. This may upset
6200 // the register scavenger and machine verifier, so we need to indicate
6201 // that we are reading an undefined value from SrcRegD, but a proper
6202 // value from SrcReg.
6203 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6204 .addReg(SrcRegD, RegState::Undef)
6205 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6206 ++NumZCRegMoveInstrsFPR;
6207 } else {
6208 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6209 .addReg(SrcReg, getKillRegState(KillSrc));
6210 if (Subtarget.hasZeroCycleRegMoveFPR32())
6211 ++NumZCRegMoveInstrsFPR;
6212 }
6213 return;
6214 }
6215
6216 if (AArch64::FPR16RegClass.contains(DestReg) &&
6217 AArch64::FPR16RegClass.contains(SrcReg)) {
6218 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6219 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6220 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6221 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6222 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6223 &AArch64::FPR128RegClass);
6224 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6225 &AArch64::FPR128RegClass);
6226 // This instruction is reading and writing Q registers. This may upset
6227 // the register scavenger and machine verifier, so we need to indicate
6228 // that we are reading an undefined value from SrcRegQ, but a proper
6229 // value from SrcReg.
6230 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6231 .addReg(SrcRegQ, RegState::Undef)
6232 .addReg(SrcRegQ, RegState::Undef)
6233 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6234 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6235 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6236 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6237 &AArch64::FPR64RegClass);
6238 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6239 &AArch64::FPR64RegClass);
6240 // This instruction is reading and writing D registers. This may upset
6241 // the register scavenger and machine verifier, so we need to indicate
6242 // that we are reading an undefined value from SrcRegD, but a proper
6243 // value from SrcReg.
6244 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6245 .addReg(SrcRegD, RegState::Undef)
6246 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6247 } else {
6248 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6249 &AArch64::FPR32RegClass);
6250 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6251 &AArch64::FPR32RegClass);
6252 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6253 .addReg(SrcReg, getKillRegState(KillSrc));
6254 }
6255 return;
6256 }
6257
6258 if (AArch64::FPR8RegClass.contains(DestReg) &&
6259 AArch64::FPR8RegClass.contains(SrcReg)) {
6260 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6261 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6262 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6263 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6264 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6265 &AArch64::FPR128RegClass);
6266 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6267 &AArch64::FPR128RegClass);
6268 // This instruction is reading and writing Q registers. This may upset
6269 // the register scavenger and machine verifier, so we need to indicate
6270 // that we are reading an undefined value from SrcRegQ, but a proper
6271 // value from SrcReg.
6272 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6273 .addReg(SrcRegQ, RegState::Undef)
6274 .addReg(SrcRegQ, RegState::Undef)
6275 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6276 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6277 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6278 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6279 &AArch64::FPR64RegClass);
6280 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6281 &AArch64::FPR64RegClass);
6282 // This instruction is reading and writing D registers. This may upset
6283 // the register scavenger and machine verifier, so we need to indicate
6284 // that we are reading an undefined value from SrcRegD, but a proper
6285 // value from SrcReg.
6286 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6287 .addReg(SrcRegD, RegState::Undef)
6288 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6289 } else {
6290 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6291 &AArch64::FPR32RegClass);
6292 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6293 &AArch64::FPR32RegClass);
6294 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6295 .addReg(SrcReg, getKillRegState(KillSrc));
6296 }
6297 return;
6298 }
6299
6300 // Copies between GPR64 and FPR64.
6301 if (AArch64::FPR64RegClass.contains(DestReg) &&
6302 AArch64::GPR64RegClass.contains(SrcReg)) {
6303 if (AArch64::XZR == SrcReg) {
6304 BuildMI(MBB, I, DL, get(AArch64::FMOVD0), DestReg);
6305 } else {
6306 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
6307 .addReg(SrcReg, getKillRegState(KillSrc));
6308 }
6309 return;
6310 }
6311 if (AArch64::GPR64RegClass.contains(DestReg) &&
6312 AArch64::FPR64RegClass.contains(SrcReg)) {
6313 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
6314 .addReg(SrcReg, getKillRegState(KillSrc));
6315 return;
6316 }
6317 // Copies between GPR32 and FPR32.
6318 if (AArch64::FPR32RegClass.contains(DestReg) &&
6319 AArch64::GPR32RegClass.contains(SrcReg)) {
6320 if (AArch64::WZR == SrcReg) {
6321 BuildMI(MBB, I, DL, get(AArch64::FMOVS0), DestReg);
6322 } else {
6323 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
6324 .addReg(SrcReg, getKillRegState(KillSrc));
6325 }
6326 return;
6327 }
6328 if (AArch64::GPR32RegClass.contains(DestReg) &&
6329 AArch64::FPR32RegClass.contains(SrcReg)) {
6330 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
6331 .addReg(SrcReg, getKillRegState(KillSrc));
6332 return;
6333 }
6334
6335 if (DestReg == AArch64::NZCV) {
6336 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
6337 BuildMI(MBB, I, DL, get(AArch64::MSR))
6338 .addImm(AArch64SysReg::NZCV)
6339 .addReg(SrcReg, getKillRegState(KillSrc))
6340 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
6341 return;
6342 }
6343
6344 if (SrcReg == AArch64::NZCV) {
6345 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
6346 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
6347 .addImm(AArch64SysReg::NZCV)
6348 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
6349 return;
6350 }
6351
6352#ifndef NDEBUG
6353 errs() << RI.getRegAsmName(DestReg) << " = COPY " << RI.getRegAsmName(SrcReg)
6354 << "\n";
6355#endif
6356 llvm_unreachable("unimplemented reg-to-reg copy");
6357}
6358
6361 MachineBasicBlock::iterator InsertBefore,
6362 const MCInstrDesc &MCID,
6363 Register SrcReg, bool IsKill,
6364 unsigned SubIdx0, unsigned SubIdx1, int FI,
6365 MachineMemOperand *MMO) {
6366 Register SrcReg0 = SrcReg;
6367 Register SrcReg1 = SrcReg;
6368 if (SrcReg.isPhysical()) {
6369 SrcReg0 = TRI.getSubReg(SrcReg, SubIdx0);
6370 SubIdx0 = 0;
6371 SrcReg1 = TRI.getSubReg(SrcReg, SubIdx1);
6372 SubIdx1 = 0;
6373 }
6374 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6375 .addReg(SrcReg0, getKillRegState(IsKill), SubIdx0)
6376 .addReg(SrcReg1, getKillRegState(IsKill), SubIdx1)
6377 .addFrameIndex(FI)
6378 .addImm(0)
6379 .addMemOperand(MMO);
6380}
6381
6384 Register SrcReg, bool isKill, int FI,
6385 const TargetRegisterClass *RC,
6386 Register VReg,
6387 MachineInstr::MIFlag Flags) const {
6388 MachineFunction &MF = *MBB.getParent();
6389 MachineFrameInfo &MFI = MF.getFrameInfo();
6390
6392 MachineMemOperand *MMO =
6394 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6395 unsigned Opc = 0;
6396 bool Offset = true;
6398 unsigned StackID = TargetStackID::Default;
6399 switch (RI.getSpillSize(*RC)) {
6400 case 1:
6401 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6402 Opc = AArch64::STRBui;
6403 break;
6404 case 2: {
6405 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6406 Opc = AArch64::STRHui;
6407 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6408 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6409 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6410 "Unexpected register store without SVE store instructions");
6411 Opc = AArch64::STR_PXI;
6413 }
6414 break;
6415 }
6416 case 4:
6417 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6418 Opc = AArch64::STRWui;
6419 if (SrcReg.isVirtual())
6420 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
6421 else
6422 assert(SrcReg != AArch64::WSP);
6423 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6424 Opc = AArch64::STRSui;
6425 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6426 Opc = AArch64::STR_PPXI;
6428 }
6429 break;
6430 case 8:
6431 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6432 Opc = AArch64::STRXui;
6433 if (SrcReg.isVirtual())
6434 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
6435 else
6436 assert(SrcReg != AArch64::SP);
6437 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6438 Opc = AArch64::STRDui;
6439 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6441 get(AArch64::STPWi), SrcReg, isKill,
6442 AArch64::sube32, AArch64::subo32, FI, MMO);
6443 return;
6444 }
6445 break;
6446 case 16:
6447 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6448 Opc = AArch64::STRQui;
6449 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6450 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6451 Opc = AArch64::ST1Twov1d;
6452 Offset = false;
6453 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6455 get(AArch64::STPXi), SrcReg, isKill,
6456 AArch64::sube64, AArch64::subo64, FI, MMO);
6457 return;
6458 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6459 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6460 "Unexpected register store without SVE store instructions");
6461 Opc = AArch64::STR_ZXI;
6463 }
6464 break;
6465 case 24:
6466 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6467 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6468 Opc = AArch64::ST1Threev1d;
6469 Offset = false;
6470 }
6471 break;
6472 case 32:
6473 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6474 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6475 Opc = AArch64::ST1Fourv1d;
6476 Offset = false;
6477 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6478 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6479 Opc = AArch64::ST1Twov2d;
6480 Offset = false;
6481 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6482 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6483 "Unexpected register store without SVE store instructions");
6484 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6486 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6487 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6488 "Unexpected register store without SVE store instructions");
6489 Opc = AArch64::STR_ZZXI;
6491 }
6492 break;
6493 case 48:
6494 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6495 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6496 Opc = AArch64::ST1Threev2d;
6497 Offset = false;
6498 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6499 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6500 "Unexpected register store without SVE store instructions");
6501 Opc = AArch64::STR_ZZZXI;
6503 }
6504 break;
6505 case 64:
6506 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6507 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6508 Opc = AArch64::ST1Fourv2d;
6509 Offset = false;
6510 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6511 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6512 "Unexpected register store without SVE store instructions");
6513 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6515 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6516 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6517 "Unexpected register store without SVE store instructions");
6518 Opc = AArch64::STR_ZZZZXI;
6520 }
6521 break;
6522 }
6523 assert(Opc && "Unknown register class");
6524 MFI.setStackID(FI, StackID);
6525
6527 .addReg(SrcReg, getKillRegState(isKill))
6528 .addFrameIndex(FI);
6529
6530 if (Offset)
6531 MI.addImm(0);
6532 if (PNRReg.isValid())
6533 MI.addDef(PNRReg, RegState::Implicit);
6534 MI.addMemOperand(MMO);
6535}
6536
6539 MachineBasicBlock::iterator InsertBefore,
6540 const MCInstrDesc &MCID,
6541 Register DestReg, unsigned SubIdx0,
6542 unsigned SubIdx1, int FI,
6543 MachineMemOperand *MMO) {
6544 Register DestReg0 = DestReg;
6545 Register DestReg1 = DestReg;
6546 bool IsUndef = true;
6547 if (DestReg.isPhysical()) {
6548 DestReg0 = TRI.getSubReg(DestReg, SubIdx0);
6549 SubIdx0 = 0;
6550 DestReg1 = TRI.getSubReg(DestReg, SubIdx1);
6551 SubIdx1 = 0;
6552 IsUndef = false;
6553 }
6554 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6555 .addReg(DestReg0, RegState::Define | getUndefRegState(IsUndef), SubIdx0)
6556 .addReg(DestReg1, RegState::Define | getUndefRegState(IsUndef), SubIdx1)
6557 .addFrameIndex(FI)
6558 .addImm(0)
6559 .addMemOperand(MMO);
6560}
6561
6564 Register DestReg, int FI,
6565 const TargetRegisterClass *RC,
6566 Register VReg, unsigned SubReg,
6567 MachineInstr::MIFlag Flags) const {
6568 MachineFunction &MF = *MBB.getParent();
6569 MachineFrameInfo &MFI = MF.getFrameInfo();
6571 MachineMemOperand *MMO =
6573 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6574
6575 unsigned Opc = 0;
6576 bool Offset = true;
6577 unsigned StackID = TargetStackID::Default;
6579 switch (TRI.getSpillSize(*RC)) {
6580 case 1:
6581 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6582 Opc = AArch64::LDRBui;
6583 break;
6584 case 2: {
6585 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6586 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6587 Opc = AArch64::LDRHui;
6588 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6589 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6590 "Unexpected register load without SVE load instructions");
6591 if (IsPNR)
6592 PNRReg = DestReg;
6593 Opc = AArch64::LDR_PXI;
6595 }
6596 break;
6597 }
6598 case 4:
6599 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6600 Opc = AArch64::LDRWui;
6601 if (DestReg.isVirtual())
6602 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
6603 else
6604 assert(DestReg != AArch64::WSP);
6605 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6606 Opc = AArch64::LDRSui;
6607 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6608 Opc = AArch64::LDR_PPXI;
6610 }
6611 break;
6612 case 8:
6613 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6614 Opc = AArch64::LDRXui;
6615 if (DestReg.isVirtual())
6616 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
6617 else
6618 assert(DestReg != AArch64::SP);
6619 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6620 Opc = AArch64::LDRDui;
6621 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6623 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6624 AArch64::subo32, FI, MMO);
6625 return;
6626 }
6627 break;
6628 case 16:
6629 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6630 Opc = AArch64::LDRQui;
6631 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6632 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6633 Opc = AArch64::LD1Twov1d;
6634 Offset = false;
6635 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6637 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6638 AArch64::subo64, FI, MMO);
6639 return;
6640 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6641 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6642 "Unexpected register load without SVE load instructions");
6643 Opc = AArch64::LDR_ZXI;
6645 }
6646 break;
6647 case 24:
6648 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6649 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6650 Opc = AArch64::LD1Threev1d;
6651 Offset = false;
6652 }
6653 break;
6654 case 32:
6655 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6656 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6657 Opc = AArch64::LD1Fourv1d;
6658 Offset = false;
6659 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6660 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6661 Opc = AArch64::LD1Twov2d;
6662 Offset = false;
6663 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6664 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6665 "Unexpected register load without SVE load instructions");
6666 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6668 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6669 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6670 "Unexpected register load without SVE load instructions");
6671 Opc = AArch64::LDR_ZZXI;
6673 }
6674 break;
6675 case 48:
6676 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6677 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6678 Opc = AArch64::LD1Threev2d;
6679 Offset = false;
6680 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6681 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6682 "Unexpected register load without SVE load instructions");
6683 Opc = AArch64::LDR_ZZZXI;
6685 }
6686 break;
6687 case 64:
6688 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6689 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6690 Opc = AArch64::LD1Fourv2d;
6691 Offset = false;
6692 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6693 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6694 "Unexpected register load without SVE load instructions");
6695 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6697 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6698 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6699 "Unexpected register load without SVE load instructions");
6700 Opc = AArch64::LDR_ZZZZXI;
6702 }
6703 break;
6704 }
6705
6706 assert(Opc && "Unknown register class");
6707 MFI.setStackID(FI, StackID);
6708
6710 .addReg(DestReg, getDefRegState(true))
6711 .addFrameIndex(FI);
6712 if (Offset)
6713 MI.addImm(0);
6714 if (PNRReg.isValid() && !PNRReg.isVirtual())
6715 MI.addDef(PNRReg, RegState::Implicit);
6716 MI.addMemOperand(MMO);
6717}
6718
6720 const MachineInstr &UseMI,
6721 const TargetRegisterInfo *TRI) {
6722 return any_of(instructionsWithoutDebug(std::next(DefMI.getIterator()),
6723 UseMI.getIterator()),
6724 [TRI](const MachineInstr &I) {
6725 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6726 I.readsRegister(AArch64::NZCV, TRI);
6727 });
6728}
6729
6730void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6731 const StackOffset &Offset, int64_t &ByteSized, int64_t &VGSized) {
6732 // The smallest scalable element supported by scaled SVE addressing
6733 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6734 // byte offset must always be a multiple of 2.
6735 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6736
6737 // VGSized offsets are divided by '2', because the VG register is the
6738 // the number of 64bit granules as opposed to 128bit vector chunks,
6739 // which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
6740 // So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
6741 // VG = n * 2 and the dwarf offset must be VG * 8 bytes.
6742 ByteSized = Offset.getFixed();
6743 VGSized = Offset.getScalable() / 2;
6744}
6745
6746/// Returns the offset in parts to which this frame offset can be
6747/// decomposed for the purpose of describing a frame offset.
6748/// For non-scalable offsets this is simply its byte size.
6749void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6750 const StackOffset &Offset, int64_t &NumBytes, int64_t &NumPredicateVectors,
6751 int64_t &NumDataVectors) {
6752 // The smallest scalable element supported by scaled SVE addressing
6753 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6754 // byte offset must always be a multiple of 2.
6755 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6756
6757 NumBytes = Offset.getFixed();
6758 NumDataVectors = 0;
6759 NumPredicateVectors = Offset.getScalable() / 2;
6760 // This method is used to get the offsets to adjust the frame offset.
6761 // If the function requires ADDPL to be used and needs more than two ADDPL
6762 // instructions, part of the offset is folded into NumDataVectors so that it
6763 // uses ADDVL for part of it, reducing the number of ADDPL instructions.
6764 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6765 NumPredicateVectors > 62) {
6766 NumDataVectors = NumPredicateVectors / 8;
6767 NumPredicateVectors -= NumDataVectors * 8;
6768 }
6769}
6770
6771// Convenience function to create a DWARF expression for: Constant `Operation`.
6772// This helper emits compact sequences for common cases. For example, for`-15
6773// DW_OP_plus`, this helper would create DW_OP_lit15 DW_OP_minus.
6776 if (Operation == dwarf::DW_OP_plus && Constant < 0 && -Constant <= 31) {
6777 // -Constant (1 to 31)
6778 Expr.push_back(dwarf::DW_OP_lit0 - Constant);
6779 Operation = dwarf::DW_OP_minus;
6780 } else if (Constant >= 0 && Constant <= 31) {
6781 // Literal value 0 to 31
6782 Expr.push_back(dwarf::DW_OP_lit0 + Constant);
6783 } else {
6784 // Signed constant
6785 Expr.push_back(dwarf::DW_OP_consts);
6787 }
6788 return Expr.push_back(Operation);
6789}
6790
6791// Convenience function to create a DWARF expression for a register.
6792static void appendReadRegExpr(SmallVectorImpl<char> &Expr, unsigned RegNum) {
6793 Expr.push_back((char)dwarf::DW_OP_bregx);
6795 Expr.push_back(0);
6796}
6797
6798// Convenience function to create a DWARF expression for loading a register from
6799// a CFA offset.
6801 int64_t OffsetFromDefCFA) {
6802 // This assumes the top of the DWARF stack contains the CFA.
6803 Expr.push_back(dwarf::DW_OP_dup);
6804 // Add the offset to the register.
6805 appendConstantExpr(Expr, OffsetFromDefCFA, dwarf::DW_OP_plus);
6806 // Dereference the address (loads a 64 bit value)..
6807 Expr.push_back(dwarf::DW_OP_deref);
6808}
6809
6810// Convenience function to create a comment for
6811// (+/-) NumBytes (* RegScale)?
6812static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment,
6813 StringRef RegScale = {}) {
6814 if (NumBytes) {
6815 Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
6816 if (!RegScale.empty())
6817 Comment << ' ' << RegScale;
6818 }
6819}
6820
6821// Creates an MCCFIInstruction:
6822// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
6824 unsigned Reg,
6825 const StackOffset &Offset) {
6826 int64_t NumBytes, NumVGScaledBytes;
6827 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(Offset, NumBytes,
6828 NumVGScaledBytes);
6829 std::string CommentBuffer;
6830 llvm::raw_string_ostream Comment(CommentBuffer);
6831
6832 if (Reg == AArch64::SP)
6833 Comment << "sp";
6834 else if (Reg == AArch64::FP)
6835 Comment << "fp";
6836 else
6837 Comment << printReg(Reg, &TRI);
6838
6839 // Build up the expression (Reg + NumBytes + VG * NumVGScaledBytes)
6840 SmallString<64> Expr;
6841 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6842 assert(DwarfReg <= 31 && "DwarfReg out of bounds (0..31)");
6843 // Reg + NumBytes
6844 Expr.push_back(dwarf::DW_OP_breg0 + DwarfReg);
6845 appendLEB128<LEB128Sign::Signed>(Expr, NumBytes);
6846 appendOffsetComment(NumBytes, Comment);
6847 if (NumVGScaledBytes) {
6848 // + VG * NumVGScaledBytes
6849 appendOffsetComment(NumVGScaledBytes, Comment, "* VG");
6850 appendReadRegExpr(Expr, TRI.getDwarfRegNum(AArch64::VG, true));
6851 appendConstantExpr(Expr, NumVGScaledBytes, dwarf::DW_OP_mul);
6852 Expr.push_back(dwarf::DW_OP_plus);
6853 }
6854
6855 // Wrap this into DW_CFA_def_cfa.
6856 SmallString<64> DefCfaExpr;
6857 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
6858 appendLEB128<LEB128Sign::Unsigned>(DefCfaExpr, Expr.size());
6859 DefCfaExpr.append(Expr.str());
6860 return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
6861 Comment.str());
6862}
6863
6865 unsigned FrameReg, unsigned Reg,
6866 const StackOffset &Offset,
6867 bool LastAdjustmentWasScalable) {
6868 if (Offset.getScalable())
6869 return createDefCFAExpression(TRI, Reg, Offset);
6870
6871 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6872 return MCCFIInstruction::cfiDefCfaOffset(nullptr, int(Offset.getFixed()));
6873
6874 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6875 return MCCFIInstruction::cfiDefCfa(nullptr, DwarfReg, (int)Offset.getFixed());
6876}
6877
6880 const StackOffset &OffsetFromDefCFA,
6881 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6882 int64_t NumBytes, NumVGScaledBytes;
6883 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6884 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6885
6886 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6887
6888 // Non-scalable offsets can use DW_CFA_offset directly.
6889 if (!NumVGScaledBytes)
6890 return MCCFIInstruction::createOffset(nullptr, DwarfReg, NumBytes);
6891
6892 std::string CommentBuffer;
6893 llvm::raw_string_ostream Comment(CommentBuffer);
6894 Comment << printReg(Reg, &TRI) << " @ cfa";
6895
6896 // Build up expression (CFA + VG * NumVGScaledBytes + NumBytes)
6897 assert(NumVGScaledBytes && "Expected scalable offset");
6898 SmallString<64> OffsetExpr;
6899 // + VG * NumVGScaledBytes
6900 StringRef VGRegScale;
6901 if (IncomingVGOffsetFromDefCFA) {
6902 appendLoadRegExpr(OffsetExpr, *IncomingVGOffsetFromDefCFA);
6903 VGRegScale = "* IncomingVG";
6904 } else {
6905 appendReadRegExpr(OffsetExpr, TRI.getDwarfRegNum(AArch64::VG, true));
6906 VGRegScale = "* VG";
6907 }
6908 appendConstantExpr(OffsetExpr, NumVGScaledBytes, dwarf::DW_OP_mul);
6909 appendOffsetComment(NumVGScaledBytes, Comment, VGRegScale);
6910 OffsetExpr.push_back(dwarf::DW_OP_plus);
6911 if (NumBytes) {
6912 // + NumBytes
6913 appendOffsetComment(NumBytes, Comment);
6914 appendConstantExpr(OffsetExpr, NumBytes, dwarf::DW_OP_plus);
6915 }
6916
6917 // Wrap this into DW_CFA_expression
6918 SmallString<64> CfaExpr;
6919 CfaExpr.push_back(dwarf::DW_CFA_expression);
6920 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, DwarfReg);
6921 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, OffsetExpr.size());
6922 CfaExpr.append(OffsetExpr.str());
6923
6924 return MCCFIInstruction::createEscape(nullptr, CfaExpr.str(), SMLoc(),
6925 Comment.str());
6926}
6927
6928// Helper function to emit a frame offset adjustment from a given
6929// pointer (SrcReg), stored into DestReg. This function is explicit
6930// in that it requires the opcode.
6933 const DebugLoc &DL, unsigned DestReg,
6934 unsigned SrcReg, int64_t Offset, unsigned Opc,
6935 const TargetInstrInfo *TII,
6936 MachineInstr::MIFlag Flag, bool NeedsWinCFI,
6937 bool *HasWinCFI, bool EmitCFAOffset,
6938 StackOffset CFAOffset, unsigned FrameReg) {
6939 int Sign = 1;
6940 unsigned MaxEncoding, ShiftSize;
6941 switch (Opc) {
6942 case AArch64::ADDXri:
6943 case AArch64::ADDSXri:
6944 case AArch64::SUBXri:
6945 case AArch64::SUBSXri:
6946 MaxEncoding = 0xfff;
6947 ShiftSize = 12;
6948 break;
6949 case AArch64::ADDVL_XXI:
6950 case AArch64::ADDPL_XXI:
6951 case AArch64::ADDSVL_XXI:
6952 case AArch64::ADDSPL_XXI:
6953 MaxEncoding = 31;
6954 ShiftSize = 0;
6955 if (Offset < 0) {
6956 MaxEncoding = 32;
6957 Sign = -1;
6958 Offset = -Offset;
6959 }
6960 break;
6961 default:
6962 llvm_unreachable("Unsupported opcode");
6963 }
6964
6965 // `Offset` can be in bytes or in "scalable bytes".
6966 int VScale = 1;
6967 if (Opc == AArch64::ADDVL_XXI || Opc == AArch64::ADDSVL_XXI)
6968 VScale = 16;
6969 else if (Opc == AArch64::ADDPL_XXI || Opc == AArch64::ADDSPL_XXI)
6970 VScale = 2;
6971
6972 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
6973 // scratch register. If DestReg is a virtual register, use it as the
6974 // scratch register; otherwise, create a new virtual register (to be
6975 // replaced by the scavenger at the end of PEI). That case can be optimized
6976 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
6977 // register can be loaded with offset%8 and the add/sub can use an extending
6978 // instruction with LSL#3.
6979 // Currently the function handles any offsets but generates a poor sequence
6980 // of code.
6981 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
6982
6983 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
6984 Register TmpReg = DestReg;
6985 if (TmpReg == AArch64::XZR)
6986 TmpReg = MBB.getParent()->getRegInfo().createVirtualRegister(
6987 &AArch64::GPR64RegClass);
6988 do {
6989 uint64_t ThisVal = std::min<uint64_t>(Offset, MaxEncodableValue);
6990 unsigned LocalShiftSize = 0;
6991 if (ThisVal > MaxEncoding) {
6992 ThisVal = ThisVal >> ShiftSize;
6993 LocalShiftSize = ShiftSize;
6994 }
6995 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
6996 "Encoding cannot handle value that big");
6997
6998 Offset -= ThisVal << LocalShiftSize;
6999 if (Offset == 0)
7000 TmpReg = DestReg;
7001 auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), TmpReg)
7002 .addReg(SrcReg)
7003 .addImm(Sign * (int)ThisVal);
7004 if (ShiftSize)
7005 MBI = MBI.addImm(
7007 MBI = MBI.setMIFlag(Flag);
7008
7009 auto Change =
7010 VScale == 1
7011 ? StackOffset::getFixed(ThisVal << LocalShiftSize)
7012 : StackOffset::getScalable(VScale * (ThisVal << LocalShiftSize));
7013 if (Sign == -1 || Opc == AArch64::SUBXri || Opc == AArch64::SUBSXri)
7014 CFAOffset += Change;
7015 else
7016 CFAOffset -= Change;
7017 if (EmitCFAOffset && DestReg == TmpReg) {
7018 MachineFunction &MF = *MBB.getParent();
7019 const TargetSubtargetInfo &STI = MF.getSubtarget();
7020 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
7021
7022 unsigned CFIIndex = MF.addFrameInst(
7023 createDefCFA(TRI, FrameReg, DestReg, CFAOffset, VScale != 1));
7024 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
7025 .addCFIIndex(CFIIndex)
7026 .setMIFlags(Flag);
7027 }
7028
7029 if (NeedsWinCFI) {
7030 int Imm = (int)(ThisVal << LocalShiftSize);
7031 if (VScale != 1 && DestReg == AArch64::SP) {
7032 if (HasWinCFI)
7033 *HasWinCFI = true;
7034 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ))
7035 .addImm(ThisVal)
7036 .setMIFlag(Flag);
7037 } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7038 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7039 assert(VScale == 1 && "Expected non-scalable operation");
7040 if (HasWinCFI)
7041 *HasWinCFI = true;
7042 if (Imm == 0)
7043 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
7044 else
7045 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
7046 .addImm(Imm)
7047 .setMIFlag(Flag);
7048 assert(Offset == 0 && "Expected remaining offset to be zero to "
7049 "emit a single SEH directive");
7050 } else if (DestReg == AArch64::SP) {
7051 assert(VScale == 1 && "Expected non-scalable operation");
7052 if (HasWinCFI)
7053 *HasWinCFI = true;
7054 assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
7055 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
7056 .addImm(Imm)
7057 .setMIFlag(Flag);
7058 }
7059 }
7060
7061 SrcReg = TmpReg;
7062 } while (Offset);
7063}
7064
7067 unsigned DestReg, unsigned SrcReg,
7069 MachineInstr::MIFlag Flag, bool SetNZCV,
7070 bool NeedsWinCFI, bool *HasWinCFI,
7071 bool EmitCFAOffset, StackOffset CFAOffset,
7072 unsigned FrameReg) {
7073 // If a function is marked as arm_locally_streaming, then the runtime value of
7074 // vscale in the prologue/epilogue is different the runtime value of vscale
7075 // in the function's body. To avoid having to consider multiple vscales,
7076 // we can use `addsvl` to allocate any scalable stack-slots, which under
7077 // most circumstances will be only locals, not callee-save slots.
7078 const Function &F = MBB.getParent()->getFunction();
7079 bool UseSVL = F.hasFnAttribute("aarch64_pstate_sm_body");
7080
7081 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7082 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7083 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7084
7085 // Insert ADDSXri for scalable offset at the end.
7086 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7087 if (NeedsFinalDefNZCV)
7088 SetNZCV = false;
7089
7090 // First emit non-scalable frame offsets, or a simple 'mov'.
7091 if (Bytes || (!Offset && SrcReg != DestReg)) {
7092 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7093 "SP increment/decrement not 8-byte aligned");
7094 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7095 if (Bytes < 0) {
7096 Bytes = -Bytes;
7097 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7098 }
7099 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
7100 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7101 FrameReg);
7102 CFAOffset += (Opc == AArch64::ADDXri || Opc == AArch64::ADDSXri)
7103 ? StackOffset::getFixed(-Bytes)
7104 : StackOffset::getFixed(Bytes);
7105 SrcReg = DestReg;
7106 FrameReg = DestReg;
7107 }
7108
7109 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7110 "WinCFI can't allocate fractions of an SVE data vector");
7111
7112 if (NumDataVectors) {
7113 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors,
7114 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII,
7115 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7116 FrameReg);
7117 CFAOffset += StackOffset::getScalable(-NumDataVectors * 16);
7118 SrcReg = DestReg;
7119 }
7120
7121 if (NumPredicateVectors) {
7122 assert(DestReg != AArch64::SP && "Unaligned access to SP");
7123 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors,
7124 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII,
7125 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7126 FrameReg);
7127 }
7128
7129 if (NeedsFinalDefNZCV)
7130 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDSXri), DestReg)
7131 .addReg(DestReg)
7132 .addImm(0)
7133 .addImm(0);
7134}
7135
7138 int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS,
7139 VirtRegMap *VRM) const {
7141 // This is a bit of a hack. Consider this instruction:
7142 //
7143 // %0 = COPY %sp; GPR64all:%0
7144 //
7145 // We explicitly chose GPR64all for the virtual register so such a copy might
7146 // be eliminated by RegisterCoalescer. However, that may not be possible, and
7147 // %0 may even spill. We can't spill %sp, and since it is in the GPR64all
7148 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
7149 //
7150 // To prevent that, we are going to constrain the %0 register class here.
7151 if (MI.isFullCopy()) {
7152 Register DstReg = MI.getOperand(0).getReg();
7153 Register SrcReg = MI.getOperand(1).getReg();
7154 if (SrcReg == AArch64::SP && DstReg.isVirtual()) {
7155 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
7156 return nullptr;
7157 }
7158 if (DstReg == AArch64::SP && SrcReg.isVirtual()) {
7159 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
7160 return nullptr;
7161 }
7162 // Nothing can folded with copy from/to NZCV.
7163 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7164 return nullptr;
7165 }
7166
7167 // Handle the case where a copy is being spilled or filled but the source
7168 // and destination register class don't match. For example:
7169 //
7170 // %0 = COPY %xzr; GPR64common:%0
7171 //
7172 // In this case we can still safely fold away the COPY and generate the
7173 // following spill code:
7174 //
7175 // STRXui %xzr, %stack.0
7176 //
7177 // This also eliminates spilled cross register class COPYs (e.g. between x and
7178 // d regs) of the same size. For example:
7179 //
7180 // %0 = COPY %1; GPR64:%0, FPR64:%1
7181 //
7182 // will be filled as
7183 //
7184 // LDRDui %0, fi<#0>
7185 //
7186 // instead of
7187 //
7188 // LDRXui %Temp, fi<#0>
7189 // %0 = FMOV %Temp
7190 //
7191 if (MI.isCopy() && Ops.size() == 1 &&
7192 // Make sure we're only folding the explicit COPY defs/uses.
7193 (Ops[0] == 0 || Ops[0] == 1)) {
7194 bool IsSpill = Ops[0] == 0;
7195 bool IsFill = !IsSpill;
7197 const MachineRegisterInfo &MRI = MF.getRegInfo();
7198 MachineBasicBlock &MBB = *MI.getParent();
7199 const MachineOperand &DstMO = MI.getOperand(0);
7200 const MachineOperand &SrcMO = MI.getOperand(1);
7201 Register DstReg = DstMO.getReg();
7202 Register SrcReg = SrcMO.getReg();
7203 // This is slightly expensive to compute for physical regs since
7204 // getMinimalPhysRegClass is slow.
7205 auto getRegClass = [&](unsigned Reg) {
7206 return Register::isVirtualRegister(Reg) ? MRI.getRegClass(Reg)
7207 : TRI.getMinimalPhysRegClass(Reg);
7208 };
7209
7210 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
7211 assert(TRI.getRegSizeInBits(*getRegClass(DstReg)) ==
7212 TRI.getRegSizeInBits(*getRegClass(SrcReg)) &&
7213 "Mismatched register size in non subreg COPY");
7214 if (IsSpill)
7215 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
7216 getRegClass(SrcReg), Register());
7217 else
7218 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
7219 getRegClass(DstReg), Register());
7220 return &*--InsertPt;
7221 }
7222
7223 // Handle cases like spilling def of:
7224 //
7225 // %0:sub_32<def,read-undef> = COPY %wzr; GPR64common:%0
7226 //
7227 // where the physical register source can be widened and stored to the full
7228 // virtual reg destination stack slot, in this case producing:
7229 //
7230 // STRXui %xzr, %stack.0
7231 //
7232 if (IsSpill && DstMO.isUndef() && SrcReg == AArch64::WZR &&
7233 TRI.getRegSizeInBits(*getRegClass(DstReg)) == 64) {
7234 assert(SrcMO.getSubReg() == 0 &&
7235 "Unexpected subreg on physical register");
7236 storeRegToStackSlot(MBB, InsertPt, AArch64::XZR, SrcMO.isKill(),
7237 FrameIndex, &AArch64::GPR64RegClass, Register());
7238 return &*--InsertPt;
7239 }
7240
7241 // Handle cases like filling use of:
7242 //
7243 // %0:sub_32<def,read-undef> = COPY %1; GPR64:%0, GPR32:%1
7244 //
7245 // where we can load the full virtual reg source stack slot, into the subreg
7246 // destination, in this case producing:
7247 //
7248 // LDRWui %0:sub_32<def,read-undef>, %stack.0
7249 //
7250 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
7251 const TargetRegisterClass *FillRC = nullptr;
7252 switch (DstMO.getSubReg()) {
7253 default:
7254 break;
7255 case AArch64::sub_32:
7256 if (AArch64::GPR64RegClass.hasSubClassEq(getRegClass(DstReg)))
7257 FillRC = &AArch64::GPR32RegClass;
7258 break;
7259 case AArch64::ssub:
7260 FillRC = &AArch64::FPR32RegClass;
7261 break;
7262 case AArch64::dsub:
7263 FillRC = &AArch64::FPR64RegClass;
7264 break;
7265 }
7266
7267 if (FillRC) {
7268 assert(TRI.getRegSizeInBits(*getRegClass(SrcReg)) ==
7269 TRI.getRegSizeInBits(*FillRC) &&
7270 "Mismatched regclass size on folded subreg COPY");
7271 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC,
7272 Register());
7273 MachineInstr &LoadMI = *--InsertPt;
7274 MachineOperand &LoadDst = LoadMI.getOperand(0);
7275 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
7276 LoadDst.setSubReg(DstMO.getSubReg());
7277 LoadDst.setIsUndef();
7278 return &LoadMI;
7279 }
7280 }
7281 }
7282
7283 // Cannot fold.
7284 return nullptr;
7285}
7286
7288 StackOffset &SOffset,
7289 bool *OutUseUnscaledOp,
7290 unsigned *OutUnscaledOp,
7291 int64_t *EmittableOffset) {
7292 // Set output values in case of early exit.
7293 if (EmittableOffset)
7294 *EmittableOffset = 0;
7295 if (OutUseUnscaledOp)
7296 *OutUseUnscaledOp = false;
7297 if (OutUnscaledOp)
7298 *OutUnscaledOp = 0;
7299
7300 // Exit early for structured vector spills/fills as they can't take an
7301 // immediate offset.
7302 switch (MI.getOpcode()) {
7303 default:
7304 break;
7305 case AArch64::LD1Rv1d:
7306 case AArch64::LD1Rv2s:
7307 case AArch64::LD1Rv2d:
7308 case AArch64::LD1Rv4h:
7309 case AArch64::LD1Rv4s:
7310 case AArch64::LD1Rv8b:
7311 case AArch64::LD1Rv8h:
7312 case AArch64::LD1Rv16b:
7313 case AArch64::LD1Twov2d:
7314 case AArch64::LD1Threev2d:
7315 case AArch64::LD1Fourv2d:
7316 case AArch64::LD1Twov1d:
7317 case AArch64::LD1Threev1d:
7318 case AArch64::LD1Fourv1d:
7319 case AArch64::ST1Twov2d:
7320 case AArch64::ST1Threev2d:
7321 case AArch64::ST1Fourv2d:
7322 case AArch64::ST1Twov1d:
7323 case AArch64::ST1Threev1d:
7324 case AArch64::ST1Fourv1d:
7325 case AArch64::ST1i8:
7326 case AArch64::ST1i16:
7327 case AArch64::ST1i32:
7328 case AArch64::ST1i64:
7329 case AArch64::IRG:
7330 case AArch64::IRGstack:
7331 case AArch64::STGloop:
7332 case AArch64::STZGloop:
7334 }
7335
7336 // Get the min/max offset and the scale.
7337 TypeSize ScaleValue(0U, false), Width(0U, false);
7338 int64_t MinOff, MaxOff;
7339 if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), ScaleValue, Width, MinOff,
7340 MaxOff))
7341 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7342
7343 // Construct the complete offset.
7344 bool IsMulVL = ScaleValue.isScalable();
7345 unsigned Scale = ScaleValue.getKnownMinValue();
7346 int64_t Offset = IsMulVL ? SOffset.getScalable() : SOffset.getFixed();
7347
7348 const MachineOperand &ImmOpnd =
7349 MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode()));
7350 Offset += ImmOpnd.getImm() * Scale;
7351
7352 // If the offset doesn't match the scale, we rewrite the instruction to
7353 // use the unscaled instruction instead. Likewise, if we have a negative
7354 // offset and there is an unscaled op to use.
7355 std::optional<unsigned> UnscaledOp =
7357 bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0);
7358 if (useUnscaledOp &&
7359 !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, ScaleValue, Width, MinOff,
7360 MaxOff))
7361 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7362
7363 Scale = ScaleValue.getKnownMinValue();
7364 assert(IsMulVL == ScaleValue.isScalable() &&
7365 "Unscaled opcode has different value for scalable");
7366
7367 int64_t Remainder = Offset % Scale;
7368 assert(!(Remainder && useUnscaledOp) &&
7369 "Cannot have remainder when using unscaled op");
7370
7371 assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
7372 int64_t NewOffset = Offset / Scale;
7373 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7374 Offset = Remainder;
7375 else {
7376 // Try to minimise the number of instructions required to materialise the
7377 // offset calculation. Specifically, for fixed offsets, if masking out the
7378 // low 12 bits leaves a legal add immediate, we can realise the offset
7379 // calculation with a single add instruction. Whenever this is possible,
7380 // prefer this split.
7381 int64_t HighPart = Offset & ~0xFFF;
7382 int64_t LowPart = Offset & 0xFFF;
7383 int64_t LowScaled = LowPart / Scale;
7384 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7385 MinOff <= LowScaled && LowScaled <= MaxOff &&
7387 NewOffset = LowScaled;
7388 Offset = HighPart;
7389 } else {
7390 // Default to a greedy split: take the memop immediate to be maximum /
7391 // minimum expressible offset and materialise the remainder.
7392 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7393 Offset = Offset - (NewOffset * Scale);
7394 }
7395 }
7396
7397 if (EmittableOffset)
7398 *EmittableOffset = NewOffset;
7399 if (OutUseUnscaledOp)
7400 *OutUseUnscaledOp = useUnscaledOp;
7401 if (OutUnscaledOp && UnscaledOp)
7402 *OutUnscaledOp = *UnscaledOp;
7403
7404 if (IsMulVL)
7405 SOffset = StackOffset::get(SOffset.getFixed(), Offset);
7406 else
7407 SOffset = StackOffset::get(Offset, SOffset.getScalable());
7409 (SOffset ? 0 : AArch64FrameOffsetIsLegal);
7410}
7411
7413 unsigned FrameReg, StackOffset &Offset,
7414 const AArch64InstrInfo *TII) {
7415 unsigned Opcode = MI.getOpcode();
7416 unsigned ImmIdx = FrameRegIdx + 1;
7417
7418 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7419 Offset += StackOffset::getFixed(MI.getOperand(ImmIdx).getImm());
7420 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
7421 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
7422 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
7423 MI.eraseFromParent();
7424 Offset = StackOffset();
7425 return true;
7426 }
7427
7428 int64_t NewOffset;
7429 unsigned UnscaledOp;
7430 bool UseUnscaledOp;
7431 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
7432 &UnscaledOp, &NewOffset);
7435 // Replace the FrameIndex with FrameReg.
7436 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
7437 if (UseUnscaledOp)
7438 MI.setDesc(TII->get(UnscaledOp));
7439
7440 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7441 return !Offset;
7442 }
7443
7444 return false;
7445}
7446
7452
7453MCInst AArch64InstrInfo::getNop() const { return MCInstBuilder(AArch64::NOP); }
7454
7455// AArch64 supports MachineCombiner.
7456bool AArch64InstrInfo::useMachineCombiner() const { return true; }
7457
7458// True when Opc sets flag
7459static bool isCombineInstrSettingFlag(unsigned Opc) {
7460 switch (Opc) {
7461 case AArch64::ADDSWrr:
7462 case AArch64::ADDSWri:
7463 case AArch64::ADDSXrr:
7464 case AArch64::ADDSXri:
7465 case AArch64::SUBSWrr:
7466 case AArch64::SUBSXrr:
7467 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7468 case AArch64::SUBSWri:
7469 case AArch64::SUBSXri:
7470 return true;
7471 default:
7472 break;
7473 }
7474 return false;
7475}
7476
7477// 32b Opcodes that can be combined with a MUL
7478static bool isCombineInstrCandidate32(unsigned Opc) {
7479 switch (Opc) {
7480 case AArch64::ADDWrr:
7481 case AArch64::ADDWri:
7482 case AArch64::SUBWrr:
7483 case AArch64::ADDSWrr:
7484 case AArch64::ADDSWri:
7485 case AArch64::SUBSWrr:
7486 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7487 case AArch64::SUBWri:
7488 case AArch64::SUBSWri:
7489 return true;
7490 default:
7491 break;
7492 }
7493 return false;
7494}
7495
7496// 64b Opcodes that can be combined with a MUL
7497static bool isCombineInstrCandidate64(unsigned Opc) {
7498 switch (Opc) {
7499 case AArch64::ADDXrr:
7500 case AArch64::ADDXri:
7501 case AArch64::SUBXrr:
7502 case AArch64::ADDSXrr:
7503 case AArch64::ADDSXri:
7504 case AArch64::SUBSXrr:
7505 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7506 case AArch64::SUBXri:
7507 case AArch64::SUBSXri:
7508 case AArch64::ADDv8i8:
7509 case AArch64::ADDv16i8:
7510 case AArch64::ADDv4i16:
7511 case AArch64::ADDv8i16:
7512 case AArch64::ADDv2i32:
7513 case AArch64::ADDv4i32:
7514 case AArch64::SUBv8i8:
7515 case AArch64::SUBv16i8:
7516 case AArch64::SUBv4i16:
7517 case AArch64::SUBv8i16:
7518 case AArch64::SUBv2i32:
7519 case AArch64::SUBv4i32:
7520 return true;
7521 default:
7522 break;
7523 }
7524 return false;
7525}
7526
7527// FP Opcodes that can be combined with a FMUL.
7528static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
7529 switch (Inst.getOpcode()) {
7530 default:
7531 break;
7532 case AArch64::FADDHrr:
7533 case AArch64::FADDSrr:
7534 case AArch64::FADDDrr:
7535 case AArch64::FADDv4f16:
7536 case AArch64::FADDv8f16:
7537 case AArch64::FADDv2f32:
7538 case AArch64::FADDv2f64:
7539 case AArch64::FADDv4f32:
7540 case AArch64::FSUBHrr:
7541 case AArch64::FSUBSrr:
7542 case AArch64::FSUBDrr:
7543 case AArch64::FSUBv4f16:
7544 case AArch64::FSUBv8f16:
7545 case AArch64::FSUBv2f32:
7546 case AArch64::FSUBv2f64:
7547 case AArch64::FSUBv4f32:
7549 // We can fuse FADD/FSUB with FMUL, if fusion is either allowed globally by
7550 // the target options or if FADD/FSUB has the contract fast-math flag.
7551 return Options.AllowFPOpFusion == FPOpFusion::Fast ||
7553 }
7554 return false;
7555}
7556
7557// Opcodes that can be combined with a MUL
7561
7562//
7563// Utility routine that checks if \param MO is defined by an
7564// \param CombineOpc instruction in the basic block \param MBB
7566 unsigned CombineOpc, unsigned ZeroReg = 0,
7567 bool CheckZeroReg = false) {
7568 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
7569 MachineInstr *MI = nullptr;
7570
7571 if (MO.isReg() && MO.getReg().isVirtual())
7572 MI = MRI.getUniqueVRegDef(MO.getReg());
7573 // And it needs to be in the trace (otherwise, it won't have a depth).
7574 if (!MI || MI->getParent() != &MBB || MI->getOpcode() != CombineOpc)
7575 return false;
7576 // Must only used by the user we combine with.
7577 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
7578 return false;
7579
7580 if (CheckZeroReg) {
7581 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
7582 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
7583 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
7584 // The third input reg must be zero.
7585 if (MI->getOperand(3).getReg() != ZeroReg)
7586 return false;
7587 }
7588
7589 if (isCombineInstrSettingFlag(CombineOpc) &&
7590 MI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) == -1)
7591 return false;
7592
7593 return true;
7594}
7595
7596//
7597// Is \param MO defined by an integer multiply and can be combined?
7599 unsigned MulOpc, unsigned ZeroReg) {
7600 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
7601}
7602
7603//
7604// Is \param MO defined by a floating-point multiply and can be combined?
7606 unsigned MulOpc) {
7607 return canCombine(MBB, MO, MulOpc);
7608}
7609
7610// TODO: There are many more machine instruction opcodes to match:
7611// 1. Other data types (integer, vectors)
7612// 2. Other math / logic operations (xor, or)
7613// 3. Other forms of the same operation (intrinsics and other variants)
7614bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
7615 bool Invert) const {
7616 if (Invert)
7617 return false;
7618 switch (Inst.getOpcode()) {
7619 // == Floating-point types ==
7620 // -- Floating-point instructions --
7621 case AArch64::FADDHrr:
7622 case AArch64::FADDSrr:
7623 case AArch64::FADDDrr:
7624 case AArch64::FMULHrr:
7625 case AArch64::FMULSrr:
7626 case AArch64::FMULDrr:
7627 case AArch64::FMULX16:
7628 case AArch64::FMULX32:
7629 case AArch64::FMULX64:
7630 // -- Advanced SIMD instructions --
7631 case AArch64::FADDv4f16:
7632 case AArch64::FADDv8f16:
7633 case AArch64::FADDv2f32:
7634 case AArch64::FADDv4f32:
7635 case AArch64::FADDv2f64:
7636 case AArch64::FMULv4f16:
7637 case AArch64::FMULv8f16:
7638 case AArch64::FMULv2f32:
7639 case AArch64::FMULv4f32:
7640 case AArch64::FMULv2f64:
7641 case AArch64::FMULXv4f16:
7642 case AArch64::FMULXv8f16:
7643 case AArch64::FMULXv2f32:
7644 case AArch64::FMULXv4f32:
7645 case AArch64::FMULXv2f64:
7646 // -- SVE instructions --
7647 // Opcodes FMULX_ZZZ_? don't exist because there is no unpredicated FMULX
7648 // in the SVE instruction set (though there are predicated ones).
7649 case AArch64::FADD_ZZZ_H:
7650 case AArch64::FADD_ZZZ_S:
7651 case AArch64::FADD_ZZZ_D:
7652 case AArch64::FMUL_ZZZ_H:
7653 case AArch64::FMUL_ZZZ_S:
7654 case AArch64::FMUL_ZZZ_D:
7657
7658 // == Integer types ==
7659 // -- Base instructions --
7660 // Opcodes MULWrr and MULXrr don't exist because
7661 // `MUL <Wd>, <Wn>, <Wm>` and `MUL <Xd>, <Xn>, <Xm>` are aliases of
7662 // `MADD <Wd>, <Wn>, <Wm>, WZR` and `MADD <Xd>, <Xn>, <Xm>, XZR` respectively.
7663 // The machine-combiner does not support three-source-operands machine
7664 // instruction. So we cannot reassociate MULs.
7665 case AArch64::ADDWrr:
7666 case AArch64::ADDXrr:
7667 case AArch64::ANDWrr:
7668 case AArch64::ANDXrr:
7669 case AArch64::ORRWrr:
7670 case AArch64::ORRXrr:
7671 case AArch64::EORWrr:
7672 case AArch64::EORXrr:
7673 case AArch64::EONWrr:
7674 case AArch64::EONXrr:
7675 // -- Advanced SIMD instructions --
7676 // Opcodes MULv1i64 and MULv2i64 don't exist because there is no 64-bit MUL
7677 // in the Advanced SIMD instruction set.
7678 case AArch64::ADDv8i8:
7679 case AArch64::ADDv16i8:
7680 case AArch64::ADDv4i16:
7681 case AArch64::ADDv8i16:
7682 case AArch64::ADDv2i32:
7683 case AArch64::ADDv4i32:
7684 case AArch64::ADDv1i64:
7685 case AArch64::ADDv2i64:
7686 case AArch64::MULv8i8:
7687 case AArch64::MULv16i8:
7688 case AArch64::MULv4i16:
7689 case AArch64::MULv8i16:
7690 case AArch64::MULv2i32:
7691 case AArch64::MULv4i32:
7692 case AArch64::ANDv8i8:
7693 case AArch64::ANDv16i8:
7694 case AArch64::ORRv8i8:
7695 case AArch64::ORRv16i8:
7696 case AArch64::EORv8i8:
7697 case AArch64::EORv16i8:
7698 // -- SVE instructions --
7699 case AArch64::ADD_ZZZ_B:
7700 case AArch64::ADD_ZZZ_H:
7701 case AArch64::ADD_ZZZ_S:
7702 case AArch64::ADD_ZZZ_D:
7703 case AArch64::MUL_ZZZ_B:
7704 case AArch64::MUL_ZZZ_H:
7705 case AArch64::MUL_ZZZ_S:
7706 case AArch64::MUL_ZZZ_D:
7707 case AArch64::AND_ZZZ:
7708 case AArch64::ORR_ZZZ:
7709 case AArch64::EOR_ZZZ:
7710 return true;
7711
7712 default:
7713 return false;
7714 }
7715}
7716
7717/// Find instructions that can be turned into madd.
7719 SmallVectorImpl<unsigned> &Patterns) {
7720 unsigned Opc = Root.getOpcode();
7721 MachineBasicBlock &MBB = *Root.getParent();
7722 bool Found = false;
7723
7725 return false;
7727 int Cmp_NZCV =
7728 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
7729 // When NZCV is live bail out.
7730 if (Cmp_NZCV == -1)
7731 return false;
7732 unsigned NewOpc = convertToNonFlagSettingOpc(Root);
7733 // When opcode can't change bail out.
7734 // CHECKME: do we miss any cases for opcode conversion?
7735 if (NewOpc == Opc)
7736 return false;
7737 Opc = NewOpc;
7738 }
7739
7740 auto setFound = [&](int Opcode, int Operand, unsigned ZeroReg,
7741 unsigned Pattern) {
7742 if (canCombineWithMUL(MBB, Root.getOperand(Operand), Opcode, ZeroReg)) {
7743 Patterns.push_back(Pattern);
7744 Found = true;
7745 }
7746 };
7747
7748 auto setVFound = [&](int Opcode, int Operand, unsigned Pattern) {
7749 if (canCombine(MBB, Root.getOperand(Operand), Opcode)) {
7750 Patterns.push_back(Pattern);
7751 Found = true;
7752 }
7753 };
7754
7756
7757 switch (Opc) {
7758 default:
7759 break;
7760 case AArch64::ADDWrr:
7761 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
7762 "ADDWrr does not have register operands");
7763 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7764 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7765 break;
7766 case AArch64::ADDXrr:
7767 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7768 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7769 break;
7770 case AArch64::SUBWrr:
7771 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7772 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7773 break;
7774 case AArch64::SUBXrr:
7775 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7776 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7777 break;
7778 case AArch64::ADDWri:
7779 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7780 break;
7781 case AArch64::ADDXri:
7782 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7783 break;
7784 case AArch64::SUBWri:
7785 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7786 break;
7787 case AArch64::SUBXri:
7788 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7789 break;
7790 case AArch64::ADDv8i8:
7791 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7792 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7793 break;
7794 case AArch64::ADDv16i8:
7795 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7796 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7797 break;
7798 case AArch64::ADDv4i16:
7799 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7800 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7801 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7802 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7803 break;
7804 case AArch64::ADDv8i16:
7805 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7806 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7807 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7808 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7809 break;
7810 case AArch64::ADDv2i32:
7811 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7812 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7813 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7814 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7815 break;
7816 case AArch64::ADDv4i32:
7817 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7818 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7819 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7820 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7821 break;
7822 case AArch64::SUBv8i8:
7823 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7824 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7825 break;
7826 case AArch64::SUBv16i8:
7827 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7828 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7829 break;
7830 case AArch64::SUBv4i16:
7831 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7832 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7833 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7834 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7835 break;
7836 case AArch64::SUBv8i16:
7837 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7838 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7839 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7840 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7841 break;
7842 case AArch64::SUBv2i32:
7843 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7844 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7845 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7846 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7847 break;
7848 case AArch64::SUBv4i32:
7849 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7850 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7851 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7852 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7853 break;
7854 }
7855 return Found;
7856}
7857
7858bool AArch64InstrInfo::isAccumulationOpcode(unsigned Opcode) const {
7859 switch (Opcode) {
7860 default:
7861 break;
7862 case AArch64::UABALB_ZZZ_D:
7863 case AArch64::UABALB_ZZZ_H:
7864 case AArch64::UABALB_ZZZ_S:
7865 case AArch64::UABALT_ZZZ_D:
7866 case AArch64::UABALT_ZZZ_H:
7867 case AArch64::UABALT_ZZZ_S:
7868 case AArch64::SABALB_ZZZ_D:
7869 case AArch64::SABALB_ZZZ_S:
7870 case AArch64::SABALB_ZZZ_H:
7871 case AArch64::SABALT_ZZZ_D:
7872 case AArch64::SABALT_ZZZ_S:
7873 case AArch64::SABALT_ZZZ_H:
7874 case AArch64::UABALv16i8_v8i16:
7875 case AArch64::UABALv2i32_v2i64:
7876 case AArch64::UABALv4i16_v4i32:
7877 case AArch64::UABALv4i32_v2i64:
7878 case AArch64::UABALv8i16_v4i32:
7879 case AArch64::UABALv8i8_v8i16:
7880 case AArch64::UABAv16i8:
7881 case AArch64::UABAv2i32:
7882 case AArch64::UABAv4i16:
7883 case AArch64::UABAv4i32:
7884 case AArch64::UABAv8i16:
7885 case AArch64::UABAv8i8:
7886 case AArch64::SABALv16i8_v8i16:
7887 case AArch64::SABALv2i32_v2i64:
7888 case AArch64::SABALv4i16_v4i32:
7889 case AArch64::SABALv4i32_v2i64:
7890 case AArch64::SABALv8i16_v4i32:
7891 case AArch64::SABALv8i8_v8i16:
7892 case AArch64::SABAv16i8:
7893 case AArch64::SABAv2i32:
7894 case AArch64::SABAv4i16:
7895 case AArch64::SABAv4i32:
7896 case AArch64::SABAv8i16:
7897 case AArch64::SABAv8i8:
7898 return true;
7899 }
7900
7901 return false;
7902}
7903
7904unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7905 unsigned AccumulationOpcode) const {
7906 switch (AccumulationOpcode) {
7907 default:
7908 llvm_unreachable("Unsupported accumulation Opcode!");
7909 case AArch64::UABALB_ZZZ_D:
7910 return AArch64::UABDLB_ZZZ_D;
7911 case AArch64::UABALB_ZZZ_H:
7912 return AArch64::UABDLB_ZZZ_H;
7913 case AArch64::UABALB_ZZZ_S:
7914 return AArch64::UABDLB_ZZZ_S;
7915 case AArch64::UABALT_ZZZ_D:
7916 return AArch64::UABDLT_ZZZ_D;
7917 case AArch64::UABALT_ZZZ_H:
7918 return AArch64::UABDLT_ZZZ_H;
7919 case AArch64::UABALT_ZZZ_S:
7920 return AArch64::UABDLT_ZZZ_S;
7921 case AArch64::UABALv16i8_v8i16:
7922 return AArch64::UABDLv16i8_v8i16;
7923 case AArch64::UABALv2i32_v2i64:
7924 return AArch64::UABDLv2i32_v2i64;
7925 case AArch64::UABALv4i16_v4i32:
7926 return AArch64::UABDLv4i16_v4i32;
7927 case AArch64::UABALv4i32_v2i64:
7928 return AArch64::UABDLv4i32_v2i64;
7929 case AArch64::UABALv8i16_v4i32:
7930 return AArch64::UABDLv8i16_v4i32;
7931 case AArch64::UABALv8i8_v8i16:
7932 return AArch64::UABDLv8i8_v8i16;
7933 case AArch64::UABAv16i8:
7934 return AArch64::UABDv16i8;
7935 case AArch64::UABAv2i32:
7936 return AArch64::UABDv2i32;
7937 case AArch64::UABAv4i16:
7938 return AArch64::UABDv4i16;
7939 case AArch64::UABAv4i32:
7940 return AArch64::UABDv4i32;
7941 case AArch64::UABAv8i16:
7942 return AArch64::UABDv8i16;
7943 case AArch64::UABAv8i8:
7944 return AArch64::UABDv8i8;
7945 case AArch64::SABALB_ZZZ_D:
7946 return AArch64::SABDLB_ZZZ_D;
7947 case AArch64::SABALB_ZZZ_S:
7948 return AArch64::SABDLB_ZZZ_S;
7949 case AArch64::SABALB_ZZZ_H:
7950 return AArch64::SABDLB_ZZZ_H;
7951 case AArch64::SABALT_ZZZ_D:
7952 return AArch64::SABDLT_ZZZ_D;
7953 case AArch64::SABALT_ZZZ_S:
7954 return AArch64::SABDLT_ZZZ_S;
7955 case AArch64::SABALT_ZZZ_H:
7956 return AArch64::SABDLT_ZZZ_H;
7957 case AArch64::SABALv16i8_v8i16:
7958 return AArch64::SABDLv16i8_v8i16;
7959 case AArch64::SABALv2i32_v2i64:
7960 return AArch64::SABDLv2i32_v2i64;
7961 case AArch64::SABALv4i16_v4i32:
7962 return AArch64::SABDLv4i16_v4i32;
7963 case AArch64::SABALv4i32_v2i64:
7964 return AArch64::SABDLv4i32_v2i64;
7965 case AArch64::SABALv8i16_v4i32:
7966 return AArch64::SABDLv8i16_v4i32;
7967 case AArch64::SABALv8i8_v8i16:
7968 return AArch64::SABDLv8i8_v8i16;
7969 case AArch64::SABAv16i8:
7970 return AArch64::SABDv16i8;
7971 case AArch64::SABAv2i32:
7972 return AArch64::SABAv2i32;
7973 case AArch64::SABAv4i16:
7974 return AArch64::SABDv4i16;
7975 case AArch64::SABAv4i32:
7976 return AArch64::SABDv4i32;
7977 case AArch64::SABAv8i16:
7978 return AArch64::SABDv8i16;
7979 case AArch64::SABAv8i8:
7980 return AArch64::SABDv8i8;
7981 }
7982}
7983
7984/// Floating-Point Support
7985
7986/// Find instructions that can be turned into madd.
7988 SmallVectorImpl<unsigned> &Patterns) {
7989
7990 if (!isCombineInstrCandidateFP(Root))
7991 return false;
7992
7993 MachineBasicBlock &MBB = *Root.getParent();
7994 bool Found = false;
7995
7996 auto Match = [&](int Opcode, int Operand, unsigned Pattern) -> bool {
7997 if (canCombineWithFMUL(MBB, Root.getOperand(Operand), Opcode)) {
7998 Patterns.push_back(Pattern);
7999 return true;
8000 }
8001 return false;
8002 };
8003
8005
8006 switch (Root.getOpcode()) {
8007 default:
8008 assert(false && "Unsupported FP instruction in combiner\n");
8009 break;
8010 case AArch64::FADDHrr:
8011 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8012 "FADDHrr does not have register operands");
8013
8014 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8015 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8016 break;
8017 case AArch64::FADDSrr:
8018 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8019 "FADDSrr does not have register operands");
8020
8021 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8022 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8023
8024 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8025 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8026 break;
8027 case AArch64::FADDDrr:
8028 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8029 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8030
8031 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8032 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8033 break;
8034 case AArch64::FADDv4f16:
8035 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8036 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8037
8038 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8039 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8040 break;
8041 case AArch64::FADDv8f16:
8042 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8043 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8044
8045 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8046 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8047 break;
8048 case AArch64::FADDv2f32:
8049 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8050 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8051
8052 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8053 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8054 break;
8055 case AArch64::FADDv2f64:
8056 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8057 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8058
8059 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8060 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8061 break;
8062 case AArch64::FADDv4f32:
8063 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8064 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8065
8066 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8067 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8068 break;
8069 case AArch64::FSUBHrr:
8070 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8071 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8072 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8073 break;
8074 case AArch64::FSUBSrr:
8075 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8076
8077 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8078 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8079
8080 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8081 break;
8082 case AArch64::FSUBDrr:
8083 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8084
8085 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8086 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8087
8088 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8089 break;
8090 case AArch64::FSUBv4f16:
8091 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8092 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8093
8094 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8095 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8096 break;
8097 case AArch64::FSUBv8f16:
8098 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8099 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8100
8101 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8102 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8103 break;
8104 case AArch64::FSUBv2f32:
8105 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8106 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8107
8108 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8109 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8110 break;
8111 case AArch64::FSUBv2f64:
8112 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8113 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8114
8115 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8116 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8117 break;
8118 case AArch64::FSUBv4f32:
8119 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8120 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8121
8122 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8123 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8124 break;
8125 }
8126 return Found;
8127}
8128
8130 SmallVectorImpl<unsigned> &Patterns) {
8131 MachineBasicBlock &MBB = *Root.getParent();
8132 bool Found = false;
8133
8134 auto Match = [&](unsigned Opcode, int Operand, unsigned Pattern) -> bool {
8135 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8136 MachineOperand &MO = Root.getOperand(Operand);
8137 MachineInstr *MI = nullptr;
8138 if (MO.isReg() && MO.getReg().isVirtual())
8139 MI = MRI.getUniqueVRegDef(MO.getReg());
8140 // Ignore No-op COPYs in FMUL(COPY(DUP(..)))
8141 if (MI && MI->getOpcode() == TargetOpcode::COPY &&
8142 MI->getOperand(1).getReg().isVirtual())
8143 MI = MRI.getUniqueVRegDef(MI->getOperand(1).getReg());
8144 if (MI && MI->getOpcode() == Opcode) {
8145 Patterns.push_back(Pattern);
8146 return true;
8147 }
8148 return false;
8149 };
8150
8152
8153 switch (Root.getOpcode()) {
8154 default:
8155 return false;
8156 case AArch64::FMULv2f32:
8157 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8158 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8159 break;
8160 case AArch64::FMULv2f64:
8161 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8162 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8163 break;
8164 case AArch64::FMULv4f16:
8165 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8166 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8167 break;
8168 case AArch64::FMULv4f32:
8169 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8170 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8171 break;
8172 case AArch64::FMULv8f16:
8173 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8174 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8175 break;
8176 }
8177
8178 return Found;
8179}
8180
8182 SmallVectorImpl<unsigned> &Patterns) {
8183 unsigned Opc = Root.getOpcode();
8184 MachineBasicBlock &MBB = *Root.getParent();
8185 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8186
8187 auto Match = [&](unsigned Opcode, unsigned Pattern) -> bool {
8188 MachineOperand &MO = Root.getOperand(1);
8190 if (MI != nullptr && (MI->getOpcode() == Opcode) &&
8191 MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()) &&
8195 MI->getFlag(MachineInstr::MIFlag::FmNsz)) {
8196 Patterns.push_back(Pattern);
8197 return true;
8198 }
8199 return false;
8200 };
8201
8202 switch (Opc) {
8203 default:
8204 break;
8205 case AArch64::FNEGDr:
8206 return Match(AArch64::FMADDDrrr, AArch64MachineCombinerPattern::FNMADD);
8207 case AArch64::FNEGSr:
8208 return Match(AArch64::FMADDSrrr, AArch64MachineCombinerPattern::FNMADD);
8209 }
8210
8211 return false;
8212}
8213
8214/// Return true when a code sequence can improve throughput. It
8215/// should be called only for instructions in loops.
8216/// \param Pattern - combiner pattern
8218 switch (Pattern) {
8219 default:
8220 break;
8326 return true;
8327 } // end switch (Pattern)
8328 return false;
8329}
8330
8331/// Find other MI combine patterns.
8333 SmallVectorImpl<unsigned> &Patterns) {
8334 // A - (B + C) ==> (A - B) - C or (A - C) - B
8335 unsigned Opc = Root.getOpcode();
8336 MachineBasicBlock &MBB = *Root.getParent();
8337
8338 switch (Opc) {
8339 case AArch64::SUBWrr:
8340 case AArch64::SUBSWrr:
8341 case AArch64::SUBXrr:
8342 case AArch64::SUBSXrr:
8343 // Found candidate root.
8344 break;
8345 default:
8346 return false;
8347 }
8348
8350 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) ==
8351 -1)
8352 return false;
8353
8354 if (canCombine(MBB, Root.getOperand(2), AArch64::ADDWrr) ||
8355 canCombine(MBB, Root.getOperand(2), AArch64::ADDSWrr) ||
8356 canCombine(MBB, Root.getOperand(2), AArch64::ADDXrr) ||
8357 canCombine(MBB, Root.getOperand(2), AArch64::ADDSXrr)) {
8360 return true;
8361 }
8362
8363 return false;
8364}
8365
8366/// Check if the given instruction forms a gather load pattern that can be
8367/// optimized for better Memory-Level Parallelism (MLP). This function
8368/// identifies chains of NEON lane load instructions that load data from
8369/// different memory addresses into individual lanes of a 128-bit vector
8370/// register, then attempts to split the pattern into parallel loads to break
8371/// the serial dependency between instructions.
8372///
8373/// Pattern Matched:
8374/// Initial scalar load -> SUBREG_TO_REG (lane 0) -> LD1i* (lane 1) ->
8375/// LD1i* (lane 2) -> ... -> LD1i* (lane N-1, Root)
8376///
8377/// Transformed Into:
8378/// Two parallel vector loads using fewer lanes each, followed by ZIP1v2i64
8379/// to combine the results, enabling better memory-level parallelism.
8380///
8381/// Supported Element Types:
8382/// - 32-bit elements (LD1i32, 4 lanes total)
8383/// - 16-bit elements (LD1i16, 8 lanes total)
8384/// - 8-bit elements (LD1i8, 16 lanes total)
8386 SmallVectorImpl<unsigned> &Patterns,
8387 unsigned LoadLaneOpCode, unsigned NumLanes) {
8388 const MachineFunction *MF = Root.getMF();
8389
8390 // Early exit if optimizing for size.
8391 if (MF->getFunction().hasMinSize())
8392 return false;
8393
8394 const MachineRegisterInfo &MRI = MF->getRegInfo();
8396
8397 // The root of the pattern must load into the last lane of the vector.
8398 if (Root.getOperand(2).getImm() != NumLanes - 1)
8399 return false;
8400
8401 // Check that we have load into all lanes except lane 0.
8402 // For each load we also want to check that:
8403 // 1. It has a single non-debug use (since we will be replacing the virtual
8404 // register)
8405 // 2. That the addressing mode only uses a single pointer operand
8406 auto *CurrInstr = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8407 auto Range = llvm::seq<unsigned>(1, NumLanes - 1);
8408 SmallSet<unsigned, 16> RemainingLanes(Range.begin(), Range.end());
8410 while (!RemainingLanes.empty() && CurrInstr &&
8411 CurrInstr->getOpcode() == LoadLaneOpCode &&
8412 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
8413 CurrInstr->getNumOperands() == 4) {
8414 RemainingLanes.erase(CurrInstr->getOperand(2).getImm());
8415 LoadInstrs.push_back(CurrInstr);
8416 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8417 }
8418
8419 // Check that we have found a match for lanes N-1.. 1.
8420 if (!RemainingLanes.empty())
8421 return false;
8422
8423 // Match the SUBREG_TO_REG sequence.
8424 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8425 return false;
8426
8427 // Verify that the subreg to reg loads an integer into the first lane.
8428 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8429 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8430 if (TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8431 return false;
8432
8433 // Verify that it also has a single non debug use.
8434 if (!MRI.hasOneNonDBGUse(Lane0LoadReg))
8435 return false;
8436
8437 LoadInstrs.push_back(MRI.getUniqueVRegDef(Lane0LoadReg));
8438
8439 // If there is any chance of aliasing, do not apply the pattern.
8440 // Walk backward through the MBB starting from Root.
8441 // Exit early if we've encountered all load instructions or hit the search
8442 // limit.
8443 auto MBBItr = Root.getIterator();
8444 unsigned RemainingSteps = GatherOptSearchLimit;
8445 SmallPtrSet<const MachineInstr *, 16> RemainingLoadInstrs;
8446 RemainingLoadInstrs.insert(LoadInstrs.begin(), LoadInstrs.end());
8447 const MachineBasicBlock *MBB = Root.getParent();
8448
8449 for (; MBBItr != MBB->begin() && RemainingSteps > 0 &&
8450 !RemainingLoadInstrs.empty();
8451 --MBBItr, --RemainingSteps) {
8452 const MachineInstr &CurrInstr = *MBBItr;
8453
8454 // Remove this instruction from remaining loads if it's one we're tracking.
8455 RemainingLoadInstrs.erase(&CurrInstr);
8456
8457 // Check for potential aliasing with any of the load instructions to
8458 // optimize.
8459 if (CurrInstr.isLoadFoldBarrier())
8460 return false;
8461 }
8462
8463 // If we hit the search limit without finding all load instructions,
8464 // don't match the pattern.
8465 if (RemainingSteps == 0 && !RemainingLoadInstrs.empty())
8466 return false;
8467
8468 switch (NumLanes) {
8469 case 4:
8471 break;
8472 case 8:
8474 break;
8475 case 16:
8477 break;
8478 default:
8479 llvm_unreachable("Got bad number of lanes for gather pattern.");
8480 }
8481
8482 return true;
8483}
8484
8485/// Search for patterns of LD instructions we can optimize.
8487 SmallVectorImpl<unsigned> &Patterns) {
8488
8489 // The pattern searches for loads into single lanes.
8490 switch (Root.getOpcode()) {
8491 case AArch64::LD1i32:
8492 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 4);
8493 case AArch64::LD1i16:
8494 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 8);
8495 case AArch64::LD1i8:
8496 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 16);
8497 default:
8498 return false;
8499 }
8500}
8501
8502/// Generate optimized instruction sequence for gather load patterns to improve
8503/// Memory-Level Parallelism (MLP). This function transforms a chain of
8504/// sequential NEON lane loads into parallel vector loads that can execute
8505/// concurrently.
8506static void
8510 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8511 unsigned Pattern, unsigned NumLanes) {
8512 MachineFunction &MF = *Root.getParent()->getParent();
8513 MachineRegisterInfo &MRI = MF.getRegInfo();
8515
8516 // Gather the initial load instructions to build the pattern.
8517 SmallVector<MachineInstr *, 16> LoadToLaneInstrs;
8518 MachineInstr *CurrInstr = &Root;
8519 for (unsigned i = 0; i < NumLanes - 1; ++i) {
8520 LoadToLaneInstrs.push_back(CurrInstr);
8521 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8522 }
8523
8524 // Sort the load instructions according to the lane.
8525 llvm::sort(LoadToLaneInstrs,
8526 [](const MachineInstr *A, const MachineInstr *B) {
8527 return A->getOperand(2).getImm() > B->getOperand(2).getImm();
8528 });
8529
8530 MachineInstr *SubregToReg = CurrInstr;
8531 LoadToLaneInstrs.push_back(
8532 MRI.getUniqueVRegDef(SubregToReg->getOperand(1).getReg()));
8533 auto LoadToLaneInstrsAscending = llvm::reverse(LoadToLaneInstrs);
8534
8535 const TargetRegisterClass *FPR128RegClass =
8536 MRI.getRegClass(Root.getOperand(0).getReg());
8537
8538 // Helper lambda to create a LD1 instruction.
8539 auto CreateLD1Instruction = [&](MachineInstr *OriginalInstr,
8540 Register SrcRegister, unsigned Lane,
8541 Register OffsetRegister,
8542 bool OffsetRegisterKillState) {
8543 auto NewRegister = MRI.createVirtualRegister(FPR128RegClass);
8544 MachineInstrBuilder LoadIndexIntoRegister =
8545 BuildMI(MF, MIMetadata(*OriginalInstr), TII->get(Root.getOpcode()),
8546 NewRegister)
8547 .addReg(SrcRegister)
8548 .addImm(Lane)
8549 .addReg(OffsetRegister, getKillRegState(OffsetRegisterKillState))
8550 .setMemRefs(OriginalInstr->memoperands());
8551 InstrIdxForVirtReg.insert(std::make_pair(NewRegister, InsInstrs.size()));
8552 InsInstrs.push_back(LoadIndexIntoRegister);
8553 return NewRegister;
8554 };
8555
8556 // Helper to create load instruction based on the NumLanes in the NEON
8557 // register we are rewriting.
8558 auto CreateLDRInstruction =
8559 [&](unsigned NumLanes, Register DestReg, Register OffsetReg,
8561 unsigned Opcode;
8562 switch (NumLanes) {
8563 case 4:
8564 Opcode = AArch64::LDRSui;
8565 break;
8566 case 8:
8567 Opcode = AArch64::LDRHui;
8568 break;
8569 case 16:
8570 Opcode = AArch64::LDRBui;
8571 break;
8572 default:
8574 "Got unsupported number of lanes in machine-combiner gather pattern");
8575 }
8576 // Immediate offset load
8577 return BuildMI(MF, MIMetadata(Root), TII->get(Opcode), DestReg)
8578 .addReg(OffsetReg)
8579 .addImm(0)
8580 .setMemRefs(MMOs);
8581 };
8582
8583 // Load the remaining lanes into register 0.
8584 auto LanesToLoadToReg0 =
8585 llvm::make_range(LoadToLaneInstrsAscending.begin() + 1,
8586 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8587 Register PrevReg = SubregToReg->getOperand(0).getReg();
8588 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg0)) {
8589 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8590 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8591 OffsetRegOperand.getReg(),
8592 OffsetRegOperand.isKill());
8593 DelInstrs.push_back(LoadInstr);
8594 }
8595 Register LastLoadReg0 = PrevReg;
8596
8597 // First load into register 1. Perform an integer load to zero out the upper
8598 // lanes in a single instruction.
8599 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8600 MachineInstr *OriginalSplitLoad =
8601 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8602 Register DestRegForMiddleIndex = MRI.createVirtualRegister(
8603 MRI.getRegClass(Lane0Load->getOperand(0).getReg()));
8604
8605 const MachineOperand &OriginalSplitToLoadOffsetOperand =
8606 OriginalSplitLoad->getOperand(3);
8607 MachineInstrBuilder MiddleIndexLoadInstr =
8608 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8609 OriginalSplitToLoadOffsetOperand.getReg(),
8610 OriginalSplitLoad->memoperands());
8611
8612 InstrIdxForVirtReg.insert(
8613 std::make_pair(DestRegForMiddleIndex, InsInstrs.size()));
8614 InsInstrs.push_back(MiddleIndexLoadInstr);
8615 DelInstrs.push_back(OriginalSplitLoad);
8616
8617 // Subreg To Reg instruction for register 1.
8618 Register DestRegForSubregToReg = MRI.createVirtualRegister(FPR128RegClass);
8619 unsigned SubregType;
8620 switch (NumLanes) {
8621 case 4:
8622 SubregType = AArch64::ssub;
8623 break;
8624 case 8:
8625 SubregType = AArch64::hsub;
8626 break;
8627 case 16:
8628 SubregType = AArch64::bsub;
8629 break;
8630 default:
8632 "Got invalid NumLanes for machine-combiner gather pattern");
8633 }
8634
8635 auto SubRegToRegInstr =
8636 BuildMI(MF, MIMetadata(Root), TII->get(SubregToReg->getOpcode()),
8637 DestRegForSubregToReg)
8638 .addReg(DestRegForMiddleIndex, getKillRegState(true))
8639 .addImm(SubregType);
8640 InstrIdxForVirtReg.insert(
8641 std::make_pair(DestRegForSubregToReg, InsInstrs.size()));
8642 InsInstrs.push_back(SubRegToRegInstr);
8643
8644 // Load remaining lanes into register 1.
8645 auto LanesToLoadToReg1 =
8646 llvm::make_range(LoadToLaneInstrsAscending.begin() + NumLanes / 2 + 1,
8647 LoadToLaneInstrsAscending.end());
8648 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8649 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg1)) {
8650 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8651 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8652 OffsetRegOperand.getReg(),
8653 OffsetRegOperand.isKill());
8654
8655 // Do not add the last reg to DelInstrs - it will be removed later.
8656 if (Index == NumLanes / 2 - 2) {
8657 break;
8658 }
8659 DelInstrs.push_back(LoadInstr);
8660 }
8661 Register LastLoadReg1 = PrevReg;
8662
8663 // Create the final zip instruction to combine the results.
8664 MachineInstrBuilder ZipInstr =
8665 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::ZIP1v2i64),
8666 Root.getOperand(0).getReg())
8667 .addReg(LastLoadReg0)
8668 .addReg(LastLoadReg1);
8669 InsInstrs.push_back(ZipInstr);
8670}
8671
8685
8686/// Return true when there is potentially a faster code sequence for an
8687/// instruction chain ending in \p Root. All potential patterns are listed in
8688/// the \p Pattern vector. Pattern should be sorted in priority order since the
8689/// pattern evaluator stops checking as soon as it finds a faster sequence.
8690
8691bool AArch64InstrInfo::getMachineCombinerPatterns(
8692 MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
8693 bool DoRegPressureReduce) const {
8694 // Integer patterns
8695 if (getMaddPatterns(Root, Patterns))
8696 return true;
8697 // Floating point patterns
8698 if (getFMULPatterns(Root, Patterns))
8699 return true;
8700 if (getFMAPatterns(Root, Patterns))
8701 return true;
8702 if (getFNEGPatterns(Root, Patterns))
8703 return true;
8704
8705 // Other patterns
8706 if (getMiscPatterns(Root, Patterns))
8707 return true;
8708
8709 // Load patterns
8710 if (getLoadPatterns(Root, Patterns))
8711 return true;
8712
8713 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
8714 DoRegPressureReduce);
8715}
8716
8718/// genFusedMultiply - Generate fused multiply instructions.
8719/// This function supports both integer and floating point instructions.
8720/// A typical example:
8721/// F|MUL I=A,B,0
8722/// F|ADD R,I,C
8723/// ==> F|MADD R,A,B,C
8724/// \param MF Containing MachineFunction
8725/// \param MRI Register information
8726/// \param TII Target information
8727/// \param Root is the F|ADD instruction
8728/// \param [out] InsInstrs is a vector of machine instructions and will
8729/// contain the generated madd instruction
8730/// \param IdxMulOpd is index of operand in Root that is the result of
8731/// the F|MUL. In the example above IdxMulOpd is 1.
8732/// \param MaddOpc the opcode fo the f|madd instruction
8733/// \param RC Register class of operands
8734/// \param kind of fma instruction (addressing mode) to be generated
8735/// \param ReplacedAddend is the result register from the instruction
8736/// replacing the non-combined operand, if any.
8737static MachineInstr *
8739 const TargetInstrInfo *TII, MachineInstr &Root,
8740 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
8741 unsigned MaddOpc, const TargetRegisterClass *RC,
8743 const Register *ReplacedAddend = nullptr) {
8744 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8745
8746 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8747 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8748 Register ResultReg = Root.getOperand(0).getReg();
8749 Register SrcReg0 = MUL->getOperand(1).getReg();
8750 bool Src0IsKill = MUL->getOperand(1).isKill();
8751 Register SrcReg1 = MUL->getOperand(2).getReg();
8752 bool Src1IsKill = MUL->getOperand(2).isKill();
8753
8754 Register SrcReg2;
8755 bool Src2IsKill;
8756 if (ReplacedAddend) {
8757 // If we just generated a new addend, we must be it's only use.
8758 SrcReg2 = *ReplacedAddend;
8759 Src2IsKill = true;
8760 } else {
8761 SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
8762 Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
8763 }
8764
8765 if (ResultReg.isVirtual())
8766 MRI.constrainRegClass(ResultReg, RC);
8767 if (SrcReg0.isVirtual())
8768 MRI.constrainRegClass(SrcReg0, RC);
8769 if (SrcReg1.isVirtual())
8770 MRI.constrainRegClass(SrcReg1, RC);
8771 if (SrcReg2.isVirtual())
8772 MRI.constrainRegClass(SrcReg2, RC);
8773
8775 if (kind == FMAInstKind::Default)
8776 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8777 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8778 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8779 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8780 else if (kind == FMAInstKind::Indexed)
8781 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8782 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8783 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8784 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8785 .addImm(MUL->getOperand(3).getImm());
8786 else if (kind == FMAInstKind::Accumulator)
8787 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8788 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8789 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8790 .addReg(SrcReg1, getKillRegState(Src1IsKill));
8791 else
8792 assert(false && "Invalid FMA instruction kind \n");
8793 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
8794 InsInstrs.push_back(MIB);
8795 return MUL;
8796}
8797
8798static MachineInstr *
8800 const TargetInstrInfo *TII, MachineInstr &Root,
8802 MachineInstr *MAD = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8803
8804 unsigned Opc = 0;
8805 const TargetRegisterClass *RC = MRI.getRegClass(MAD->getOperand(0).getReg());
8806 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8807 Opc = AArch64::FNMADDSrrr;
8808 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8809 Opc = AArch64::FNMADDDrrr;
8810 else
8811 return nullptr;
8812
8813 Register ResultReg = Root.getOperand(0).getReg();
8814 Register SrcReg0 = MAD->getOperand(1).getReg();
8815 Register SrcReg1 = MAD->getOperand(2).getReg();
8816 Register SrcReg2 = MAD->getOperand(3).getReg();
8817 bool Src0IsKill = MAD->getOperand(1).isKill();
8818 bool Src1IsKill = MAD->getOperand(2).isKill();
8819 bool Src2IsKill = MAD->getOperand(3).isKill();
8820 if (ResultReg.isVirtual())
8821 MRI.constrainRegClass(ResultReg, RC);
8822 if (SrcReg0.isVirtual())
8823 MRI.constrainRegClass(SrcReg0, RC);
8824 if (SrcReg1.isVirtual())
8825 MRI.constrainRegClass(SrcReg1, RC);
8826 if (SrcReg2.isVirtual())
8827 MRI.constrainRegClass(SrcReg2, RC);
8828
8830 BuildMI(MF, MIMetadata(Root), TII->get(Opc), ResultReg)
8831 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8832 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8833 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8834 InsInstrs.push_back(MIB);
8835
8836 return MAD;
8837}
8838
8839/// Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
8840static MachineInstr *
8843 unsigned IdxDupOp, unsigned MulOpc,
8844 const TargetRegisterClass *RC, MachineRegisterInfo &MRI) {
8845 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8846 "Invalid index of FMUL operand");
8847
8848 MachineFunction &MF = *Root.getMF();
8850
8851 MachineInstr *Dup =
8852 MF.getRegInfo().getUniqueVRegDef(Root.getOperand(IdxDupOp).getReg());
8853
8854 if (Dup->getOpcode() == TargetOpcode::COPY)
8855 Dup = MRI.getUniqueVRegDef(Dup->getOperand(1).getReg());
8856
8857 Register DupSrcReg = Dup->getOperand(1).getReg();
8858 MRI.clearKillFlags(DupSrcReg);
8859 MRI.constrainRegClass(DupSrcReg, RC);
8860
8861 unsigned DupSrcLane = Dup->getOperand(2).getImm();
8862
8863 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8864 MachineOperand &MulOp = Root.getOperand(IdxMulOp);
8865
8866 Register ResultReg = Root.getOperand(0).getReg();
8867
8869 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MulOpc), ResultReg)
8870 .add(MulOp)
8871 .addReg(DupSrcReg)
8872 .addImm(DupSrcLane);
8873
8874 InsInstrs.push_back(MIB);
8875 return &Root;
8876}
8877
8878/// genFusedMultiplyAcc - Helper to generate fused multiply accumulate
8879/// instructions.
8880///
8881/// \see genFusedMultiply
8885 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8886 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8888}
8889
8890/// genNeg - Helper to generate an intermediate negation of the second operand
8891/// of Root
8893 const TargetInstrInfo *TII, MachineInstr &Root,
8895 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8896 unsigned MnegOpc, const TargetRegisterClass *RC) {
8897 Register NewVR = MRI.createVirtualRegister(RC);
8899 BuildMI(MF, MIMetadata(Root), TII->get(MnegOpc), NewVR)
8900 .add(Root.getOperand(2));
8901 InsInstrs.push_back(MIB);
8902
8903 assert(InstrIdxForVirtReg.empty());
8904 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
8905
8906 return NewVR;
8907}
8908
8909/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8910/// instructions with an additional negation of the accumulator
8914 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8915 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8916 assert(IdxMulOpd == 1);
8917
8918 Register NewVR =
8919 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8920 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8921 FMAInstKind::Accumulator, &NewVR);
8922}
8923
8924/// genFusedMultiplyIdx - Helper to generate fused multiply accumulate
8925/// instructions.
8926///
8927/// \see genFusedMultiply
8931 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8932 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
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
8948 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8949 FMAInstKind::Indexed, &NewVR);
8950}
8951
8952/// genMaddR - Generate madd instruction and combine mul and add using
8953/// an extra virtual register
8954/// Example - an ADD intermediate needs to be stored in a register:
8955/// MUL I=A,B,0
8956/// ADD R,I,Imm
8957/// ==> ORR V, ZR, Imm
8958/// ==> MADD R,A,B,V
8959/// \param MF Containing MachineFunction
8960/// \param MRI Register information
8961/// \param TII Target information
8962/// \param Root is the ADD instruction
8963/// \param [out] InsInstrs is a vector of machine instructions and will
8964/// contain the generated madd instruction
8965/// \param IdxMulOpd is index of operand in Root that is the result of
8966/// the MUL. In the example above IdxMulOpd is 1.
8967/// \param MaddOpc the opcode fo the madd instruction
8968/// \param VR is a virtual register that holds the value of an ADD operand
8969/// (V in the example above).
8970/// \param RC Register class of operands
8972 const TargetInstrInfo *TII, MachineInstr &Root,
8974 unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR,
8975 const TargetRegisterClass *RC) {
8976 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8977
8978 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8979 Register ResultReg = Root.getOperand(0).getReg();
8980 Register SrcReg0 = MUL->getOperand(1).getReg();
8981 bool Src0IsKill = MUL->getOperand(1).isKill();
8982 Register SrcReg1 = MUL->getOperand(2).getReg();
8983 bool Src1IsKill = MUL->getOperand(2).isKill();
8984
8985 if (ResultReg.isVirtual())
8986 MRI.constrainRegClass(ResultReg, RC);
8987 if (SrcReg0.isVirtual())
8988 MRI.constrainRegClass(SrcReg0, RC);
8989 if (SrcReg1.isVirtual())
8990 MRI.constrainRegClass(SrcReg1, RC);
8992 MRI.constrainRegClass(VR, RC);
8993
8995 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8996 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8997 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8998 .addReg(VR);
8999 // Insert the MADD
9000 InsInstrs.push_back(MIB);
9001 return MUL;
9002}
9003
9004/// Do the following transformation
9005/// A - (B + C) ==> (A - B) - C
9006/// A - (B + C) ==> (A - C) - B
9008 const TargetInstrInfo *TII, MachineInstr &Root,
9011 unsigned IdxOpd1,
9012 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
9013 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9014 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9015 MachineInstr *AddMI = MRI.getUniqueVRegDef(Root.getOperand(2).getReg());
9016
9017 Register ResultReg = Root.getOperand(0).getReg();
9018 Register RegA = Root.getOperand(1).getReg();
9019 bool RegAIsKill = Root.getOperand(1).isKill();
9020 Register RegB = AddMI->getOperand(IdxOpd1).getReg();
9021 bool RegBIsKill = AddMI->getOperand(IdxOpd1).isKill();
9022 Register RegC = AddMI->getOperand(IdxOtherOpd).getReg();
9023 bool RegCIsKill = AddMI->getOperand(IdxOtherOpd).isKill();
9024 Register NewVR =
9026
9027 unsigned Opcode = Root.getOpcode();
9028 if (Opcode == AArch64::SUBSWrr)
9029 Opcode = AArch64::SUBWrr;
9030 else if (Opcode == AArch64::SUBSXrr)
9031 Opcode = AArch64::SUBXrr;
9032 else
9033 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9034 "Unexpected instruction opcode.");
9035
9036 uint32_t Flags = Root.mergeFlagsWith(*AddMI);
9037 Flags &= ~MachineInstr::NoSWrap;
9038 Flags &= ~MachineInstr::NoUWrap;
9039
9040 MachineInstrBuilder MIB1 =
9041 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), NewVR)
9042 .addReg(RegA, getKillRegState(RegAIsKill))
9043 .addReg(RegB, getKillRegState(RegBIsKill))
9044 .setMIFlags(Flags);
9045 MachineInstrBuilder MIB2 =
9046 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), ResultReg)
9047 .addReg(NewVR, getKillRegState(true))
9048 .addReg(RegC, getKillRegState(RegCIsKill))
9049 .setMIFlags(Flags);
9050
9051 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9052 InsInstrs.push_back(MIB1);
9053 InsInstrs.push_back(MIB2);
9054 DelInstrs.push_back(AddMI);
9055 DelInstrs.push_back(&Root);
9056}
9057
9058unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9059 unsigned int AccumulatorOpCode) const {
9060 switch (AccumulatorOpCode) {
9061 case AArch64::UABALB_ZZZ_D:
9062 case AArch64::SABALB_ZZZ_D:
9063 case AArch64::UABALT_ZZZ_D:
9064 case AArch64::SABALT_ZZZ_D:
9065 return AArch64::ADD_ZZZ_D;
9066 case AArch64::UABALB_ZZZ_H:
9067 case AArch64::SABALB_ZZZ_H:
9068 case AArch64::UABALT_ZZZ_H:
9069 case AArch64::SABALT_ZZZ_H:
9070 return AArch64::ADD_ZZZ_H;
9071 case AArch64::UABALB_ZZZ_S:
9072 case AArch64::SABALB_ZZZ_S:
9073 case AArch64::UABALT_ZZZ_S:
9074 case AArch64::SABALT_ZZZ_S:
9075 return AArch64::ADD_ZZZ_S;
9076 case AArch64::UABALv16i8_v8i16:
9077 case AArch64::SABALv8i8_v8i16:
9078 case AArch64::SABAv8i16:
9079 case AArch64::UABAv8i16:
9080 return AArch64::ADDv8i16;
9081 case AArch64::SABALv2i32_v2i64:
9082 case AArch64::UABALv2i32_v2i64:
9083 case AArch64::SABALv4i32_v2i64:
9084 return AArch64::ADDv2i64;
9085 case AArch64::UABALv4i16_v4i32:
9086 case AArch64::SABALv4i16_v4i32:
9087 case AArch64::SABALv8i16_v4i32:
9088 case AArch64::SABAv4i32:
9089 case AArch64::UABAv4i32:
9090 return AArch64::ADDv4i32;
9091 case AArch64::UABALv4i32_v2i64:
9092 return AArch64::ADDv2i64;
9093 case AArch64::UABALv8i16_v4i32:
9094 return AArch64::ADDv4i32;
9095 case AArch64::UABALv8i8_v8i16:
9096 case AArch64::SABALv16i8_v8i16:
9097 return AArch64::ADDv8i16;
9098 case AArch64::UABAv16i8:
9099 case AArch64::SABAv16i8:
9100 return AArch64::ADDv16i8;
9101 case AArch64::UABAv4i16:
9102 case AArch64::SABAv4i16:
9103 return AArch64::ADDv4i16;
9104 case AArch64::UABAv2i32:
9105 case AArch64::SABAv2i32:
9106 return AArch64::ADDv2i32;
9107 case AArch64::UABAv8i8:
9108 case AArch64::SABAv8i8:
9109 return AArch64::ADDv8i8;
9110 default:
9111 llvm_unreachable("Unknown accumulator opcode");
9112 }
9113}
9114
9115/// When getMachineCombinerPatterns() finds potential patterns,
9116/// this function generates the instructions that could replace the
9117/// original code sequence
9118void AArch64InstrInfo::genAlternativeCodeSequence(
9119 MachineInstr &Root, unsigned Pattern,
9122 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const {
9123 MachineBasicBlock &MBB = *Root.getParent();
9124 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9125 MachineFunction &MF = *MBB.getParent();
9126 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
9127
9128 MachineInstr *MUL = nullptr;
9129 const TargetRegisterClass *RC;
9130 unsigned Opc;
9131 switch (Pattern) {
9132 default:
9133 // Reassociate instructions.
9134 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
9135 DelInstrs, InstrIdxForVirtReg);
9136 return;
9138 // A - (B + C)
9139 // ==> (A - B) - C
9140 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 1,
9141 InstrIdxForVirtReg);
9142 return;
9144 // A - (B + C)
9145 // ==> (A - C) - B
9146 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 2,
9147 InstrIdxForVirtReg);
9148 return;
9151 // MUL I=A,B,0
9152 // ADD R,I,C
9153 // ==> MADD R,A,B,C
9154 // --- Create(MADD);
9156 Opc = AArch64::MADDWrrr;
9157 RC = &AArch64::GPR32RegClass;
9158 } else {
9159 Opc = AArch64::MADDXrrr;
9160 RC = &AArch64::GPR64RegClass;
9161 }
9162 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9163 break;
9166 // MUL I=A,B,0
9167 // ADD R,C,I
9168 // ==> MADD R,A,B,C
9169 // --- Create(MADD);
9171 Opc = AArch64::MADDWrrr;
9172 RC = &AArch64::GPR32RegClass;
9173 } else {
9174 Opc = AArch64::MADDXrrr;
9175 RC = &AArch64::GPR64RegClass;
9176 }
9177 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9178 break;
9183 // MUL I=A,B,0
9184 // ADD/SUB R,I,Imm
9185 // ==> MOV V, Imm/-Imm
9186 // ==> MADD R,A,B,V
9187 // --- Create(MADD);
9188 const TargetRegisterClass *RC;
9189 unsigned BitSize, MovImm;
9192 MovImm = AArch64::MOVi32imm;
9193 RC = &AArch64::GPR32spRegClass;
9194 BitSize = 32;
9195 Opc = AArch64::MADDWrrr;
9196 RC = &AArch64::GPR32RegClass;
9197 } else {
9198 MovImm = AArch64::MOVi64imm;
9199 RC = &AArch64::GPR64spRegClass;
9200 BitSize = 64;
9201 Opc = AArch64::MADDXrrr;
9202 RC = &AArch64::GPR64RegClass;
9203 }
9204 Register NewVR = MRI.createVirtualRegister(RC);
9205 uint64_t Imm = Root.getOperand(2).getImm();
9206
9207 if (Root.getOperand(3).isImm()) {
9208 unsigned Val = Root.getOperand(3).getImm();
9209 Imm = Imm << Val;
9210 }
9211 bool IsSub = Pattern == AArch64MachineCombinerPattern::MULSUBWI_OP1 ||
9213 uint64_t UImm = SignExtend64(IsSub ? -Imm : Imm, BitSize);
9214 // Check that the immediate can be composed via a single instruction.
9216 AArch64_IMM::expandMOVImm(UImm, BitSize, Insn);
9217 if (Insn.size() != 1)
9218 return;
9219 MachineInstrBuilder MIB1 =
9220 BuildMI(MF, MIMetadata(Root), TII->get(MovImm), NewVR)
9221 .addImm(IsSub ? -Imm : Imm);
9222 InsInstrs.push_back(MIB1);
9223 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9224 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9225 break;
9226 }
9229 // MUL I=A,B,0
9230 // SUB R,I, C
9231 // ==> SUB V, 0, C
9232 // ==> MADD R,A,B,V // = -C + A*B
9233 // --- Create(MADD);
9234 const TargetRegisterClass *SubRC;
9235 unsigned SubOpc, ZeroReg;
9237 SubOpc = AArch64::SUBWrr;
9238 SubRC = &AArch64::GPR32spRegClass;
9239 ZeroReg = AArch64::WZR;
9240 Opc = AArch64::MADDWrrr;
9241 RC = &AArch64::GPR32RegClass;
9242 } else {
9243 SubOpc = AArch64::SUBXrr;
9244 SubRC = &AArch64::GPR64spRegClass;
9245 ZeroReg = AArch64::XZR;
9246 Opc = AArch64::MADDXrrr;
9247 RC = &AArch64::GPR64RegClass;
9248 }
9249 Register NewVR = MRI.createVirtualRegister(SubRC);
9250 // SUB NewVR, 0, C
9251 MachineInstrBuilder MIB1 =
9252 BuildMI(MF, MIMetadata(Root), TII->get(SubOpc), NewVR)
9253 .addReg(ZeroReg)
9254 .add(Root.getOperand(2));
9255 InsInstrs.push_back(MIB1);
9256 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9257 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9258 break;
9259 }
9262 // MUL I=A,B,0
9263 // SUB R,C,I
9264 // ==> MSUB R,A,B,C (computes C - A*B)
9265 // --- Create(MSUB);
9267 Opc = AArch64::MSUBWrrr;
9268 RC = &AArch64::GPR32RegClass;
9269 } else {
9270 Opc = AArch64::MSUBXrrr;
9271 RC = &AArch64::GPR64RegClass;
9272 }
9273 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9274 break;
9276 Opc = AArch64::MLAv8i8;
9277 RC = &AArch64::FPR64RegClass;
9278 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9279 break;
9281 Opc = AArch64::MLAv8i8;
9282 RC = &AArch64::FPR64RegClass;
9283 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9284 break;
9286 Opc = AArch64::MLAv16i8;
9287 RC = &AArch64::FPR128RegClass;
9288 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9289 break;
9291 Opc = AArch64::MLAv16i8;
9292 RC = &AArch64::FPR128RegClass;
9293 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9294 break;
9296 Opc = AArch64::MLAv4i16;
9297 RC = &AArch64::FPR64RegClass;
9298 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9299 break;
9301 Opc = AArch64::MLAv4i16;
9302 RC = &AArch64::FPR64RegClass;
9303 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9304 break;
9306 Opc = AArch64::MLAv8i16;
9307 RC = &AArch64::FPR128RegClass;
9308 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9309 break;
9311 Opc = AArch64::MLAv8i16;
9312 RC = &AArch64::FPR128RegClass;
9313 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9314 break;
9316 Opc = AArch64::MLAv2i32;
9317 RC = &AArch64::FPR64RegClass;
9318 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9319 break;
9321 Opc = AArch64::MLAv2i32;
9322 RC = &AArch64::FPR64RegClass;
9323 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9324 break;
9326 Opc = AArch64::MLAv4i32;
9327 RC = &AArch64::FPR128RegClass;
9328 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9329 break;
9331 Opc = AArch64::MLAv4i32;
9332 RC = &AArch64::FPR128RegClass;
9333 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9334 break;
9335
9337 Opc = AArch64::MLAv8i8;
9338 RC = &AArch64::FPR64RegClass;
9339 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9340 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i8,
9341 RC);
9342 break;
9344 Opc = AArch64::MLSv8i8;
9345 RC = &AArch64::FPR64RegClass;
9346 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9347 break;
9349 Opc = AArch64::MLAv16i8;
9350 RC = &AArch64::FPR128RegClass;
9351 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9352 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv16i8,
9353 RC);
9354 break;
9356 Opc = AArch64::MLSv16i8;
9357 RC = &AArch64::FPR128RegClass;
9358 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9359 break;
9361 Opc = AArch64::MLAv4i16;
9362 RC = &AArch64::FPR64RegClass;
9363 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9364 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9365 RC);
9366 break;
9368 Opc = AArch64::MLSv4i16;
9369 RC = &AArch64::FPR64RegClass;
9370 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9371 break;
9373 Opc = AArch64::MLAv8i16;
9374 RC = &AArch64::FPR128RegClass;
9375 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9376 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9377 RC);
9378 break;
9380 Opc = AArch64::MLSv8i16;
9381 RC = &AArch64::FPR128RegClass;
9382 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9383 break;
9385 Opc = AArch64::MLAv2i32;
9386 RC = &AArch64::FPR64RegClass;
9387 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9388 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9389 RC);
9390 break;
9392 Opc = AArch64::MLSv2i32;
9393 RC = &AArch64::FPR64RegClass;
9394 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9395 break;
9397 Opc = AArch64::MLAv4i32;
9398 RC = &AArch64::FPR128RegClass;
9399 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9400 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9401 RC);
9402 break;
9404 Opc = AArch64::MLSv4i32;
9405 RC = &AArch64::FPR128RegClass;
9406 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9407 break;
9408
9410 Opc = AArch64::MLAv4i16_indexed;
9411 RC = &AArch64::FPR64RegClass;
9412 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9413 break;
9415 Opc = AArch64::MLAv4i16_indexed;
9416 RC = &AArch64::FPR64RegClass;
9417 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9418 break;
9420 Opc = AArch64::MLAv8i16_indexed;
9421 RC = &AArch64::FPR128RegClass;
9422 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9423 break;
9425 Opc = AArch64::MLAv8i16_indexed;
9426 RC = &AArch64::FPR128RegClass;
9427 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9428 break;
9430 Opc = AArch64::MLAv2i32_indexed;
9431 RC = &AArch64::FPR64RegClass;
9432 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9433 break;
9435 Opc = AArch64::MLAv2i32_indexed;
9436 RC = &AArch64::FPR64RegClass;
9437 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9438 break;
9440 Opc = AArch64::MLAv4i32_indexed;
9441 RC = &AArch64::FPR128RegClass;
9442 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9443 break;
9445 Opc = AArch64::MLAv4i32_indexed;
9446 RC = &AArch64::FPR128RegClass;
9447 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9448 break;
9449
9451 Opc = AArch64::MLAv4i16_indexed;
9452 RC = &AArch64::FPR64RegClass;
9453 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9454 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9455 RC);
9456 break;
9458 Opc = AArch64::MLSv4i16_indexed;
9459 RC = &AArch64::FPR64RegClass;
9460 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9461 break;
9463 Opc = AArch64::MLAv8i16_indexed;
9464 RC = &AArch64::FPR128RegClass;
9465 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9466 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9467 RC);
9468 break;
9470 Opc = AArch64::MLSv8i16_indexed;
9471 RC = &AArch64::FPR128RegClass;
9472 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9473 break;
9475 Opc = AArch64::MLAv2i32_indexed;
9476 RC = &AArch64::FPR64RegClass;
9477 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9478 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9479 RC);
9480 break;
9482 Opc = AArch64::MLSv2i32_indexed;
9483 RC = &AArch64::FPR64RegClass;
9484 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9485 break;
9487 Opc = AArch64::MLAv4i32_indexed;
9488 RC = &AArch64::FPR128RegClass;
9489 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9490 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9491 RC);
9492 break;
9494 Opc = AArch64::MLSv4i32_indexed;
9495 RC = &AArch64::FPR128RegClass;
9496 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9497 break;
9498
9499 // Floating Point Support
9501 Opc = AArch64::FMADDHrrr;
9502 RC = &AArch64::FPR16RegClass;
9503 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9504 break;
9506 Opc = AArch64::FMADDSrrr;
9507 RC = &AArch64::FPR32RegClass;
9508 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9509 break;
9511 Opc = AArch64::FMADDDrrr;
9512 RC = &AArch64::FPR64RegClass;
9513 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9514 break;
9515
9517 Opc = AArch64::FMADDHrrr;
9518 RC = &AArch64::FPR16RegClass;
9519 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9520 break;
9522 Opc = AArch64::FMADDSrrr;
9523 RC = &AArch64::FPR32RegClass;
9524 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9525 break;
9527 Opc = AArch64::FMADDDrrr;
9528 RC = &AArch64::FPR64RegClass;
9529 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9530 break;
9531
9533 Opc = AArch64::FMLAv1i32_indexed;
9534 RC = &AArch64::FPR32RegClass;
9535 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9537 break;
9539 Opc = AArch64::FMLAv1i32_indexed;
9540 RC = &AArch64::FPR32RegClass;
9541 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9543 break;
9544
9546 Opc = AArch64::FMLAv1i64_indexed;
9547 RC = &AArch64::FPR64RegClass;
9548 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9550 break;
9552 Opc = AArch64::FMLAv1i64_indexed;
9553 RC = &AArch64::FPR64RegClass;
9554 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9556 break;
9557
9559 RC = &AArch64::FPR64RegClass;
9560 Opc = AArch64::FMLAv4i16_indexed;
9561 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9563 break;
9565 RC = &AArch64::FPR64RegClass;
9566 Opc = AArch64::FMLAv4f16;
9567 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9569 break;
9571 RC = &AArch64::FPR64RegClass;
9572 Opc = AArch64::FMLAv4i16_indexed;
9573 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9575 break;
9577 RC = &AArch64::FPR64RegClass;
9578 Opc = AArch64::FMLAv4f16;
9579 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9581 break;
9582
9585 RC = &AArch64::FPR64RegClass;
9587 Opc = AArch64::FMLAv2i32_indexed;
9588 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9590 } else {
9591 Opc = AArch64::FMLAv2f32;
9592 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9594 }
9595 break;
9598 RC = &AArch64::FPR64RegClass;
9600 Opc = AArch64::FMLAv2i32_indexed;
9601 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9603 } else {
9604 Opc = AArch64::FMLAv2f32;
9605 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9607 }
9608 break;
9609
9611 RC = &AArch64::FPR128RegClass;
9612 Opc = AArch64::FMLAv8i16_indexed;
9613 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9615 break;
9617 RC = &AArch64::FPR128RegClass;
9618 Opc = AArch64::FMLAv8f16;
9619 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9621 break;
9623 RC = &AArch64::FPR128RegClass;
9624 Opc = AArch64::FMLAv8i16_indexed;
9625 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9627 break;
9629 RC = &AArch64::FPR128RegClass;
9630 Opc = AArch64::FMLAv8f16;
9631 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9633 break;
9634
9637 RC = &AArch64::FPR128RegClass;
9639 Opc = AArch64::FMLAv2i64_indexed;
9640 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9642 } else {
9643 Opc = AArch64::FMLAv2f64;
9644 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9646 }
9647 break;
9650 RC = &AArch64::FPR128RegClass;
9652 Opc = AArch64::FMLAv2i64_indexed;
9653 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9655 } else {
9656 Opc = AArch64::FMLAv2f64;
9657 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9659 }
9660 break;
9661
9664 RC = &AArch64::FPR128RegClass;
9666 Opc = AArch64::FMLAv4i32_indexed;
9667 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9669 } else {
9670 Opc = AArch64::FMLAv4f32;
9671 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9673 }
9674 break;
9675
9678 RC = &AArch64::FPR128RegClass;
9680 Opc = AArch64::FMLAv4i32_indexed;
9681 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9683 } else {
9684 Opc = AArch64::FMLAv4f32;
9685 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9687 }
9688 break;
9689
9691 Opc = AArch64::FNMSUBHrrr;
9692 RC = &AArch64::FPR16RegClass;
9693 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9694 break;
9696 Opc = AArch64::FNMSUBSrrr;
9697 RC = &AArch64::FPR32RegClass;
9698 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9699 break;
9701 Opc = AArch64::FNMSUBDrrr;
9702 RC = &AArch64::FPR64RegClass;
9703 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9704 break;
9705
9707 Opc = AArch64::FNMADDHrrr;
9708 RC = &AArch64::FPR16RegClass;
9709 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9710 break;
9712 Opc = AArch64::FNMADDSrrr;
9713 RC = &AArch64::FPR32RegClass;
9714 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9715 break;
9717 Opc = AArch64::FNMADDDrrr;
9718 RC = &AArch64::FPR64RegClass;
9719 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9720 break;
9721
9723 Opc = AArch64::FMSUBHrrr;
9724 RC = &AArch64::FPR16RegClass;
9725 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9726 break;
9728 Opc = AArch64::FMSUBSrrr;
9729 RC = &AArch64::FPR32RegClass;
9730 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9731 break;
9733 Opc = AArch64::FMSUBDrrr;
9734 RC = &AArch64::FPR64RegClass;
9735 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9736 break;
9737
9739 Opc = AArch64::FMLSv1i32_indexed;
9740 RC = &AArch64::FPR32RegClass;
9741 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9743 break;
9744
9746 Opc = AArch64::FMLSv1i64_indexed;
9747 RC = &AArch64::FPR64RegClass;
9748 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9750 break;
9751
9754 RC = &AArch64::FPR64RegClass;
9755 Register NewVR = MRI.createVirtualRegister(RC);
9756 MachineInstrBuilder MIB1 =
9757 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f16), NewVR)
9758 .add(Root.getOperand(2));
9759 InsInstrs.push_back(MIB1);
9760 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9762 Opc = AArch64::FMLAv4f16;
9763 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9764 FMAInstKind::Accumulator, &NewVR);
9765 } else {
9766 Opc = AArch64::FMLAv4i16_indexed;
9767 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9768 FMAInstKind::Indexed, &NewVR);
9769 }
9770 break;
9771 }
9773 RC = &AArch64::FPR64RegClass;
9774 Opc = AArch64::FMLSv4f16;
9775 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9777 break;
9779 RC = &AArch64::FPR64RegClass;
9780 Opc = AArch64::FMLSv4i16_indexed;
9781 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9783 break;
9784
9787 RC = &AArch64::FPR64RegClass;
9789 Opc = AArch64::FMLSv2i32_indexed;
9790 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9792 } else {
9793 Opc = AArch64::FMLSv2f32;
9794 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9796 }
9797 break;
9798
9801 RC = &AArch64::FPR128RegClass;
9802 Register NewVR = MRI.createVirtualRegister(RC);
9803 MachineInstrBuilder MIB1 =
9804 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv8f16), NewVR)
9805 .add(Root.getOperand(2));
9806 InsInstrs.push_back(MIB1);
9807 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9809 Opc = AArch64::FMLAv8f16;
9810 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9811 FMAInstKind::Accumulator, &NewVR);
9812 } else {
9813 Opc = AArch64::FMLAv8i16_indexed;
9814 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9815 FMAInstKind::Indexed, &NewVR);
9816 }
9817 break;
9818 }
9820 RC = &AArch64::FPR128RegClass;
9821 Opc = AArch64::FMLSv8f16;
9822 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9824 break;
9826 RC = &AArch64::FPR128RegClass;
9827 Opc = AArch64::FMLSv8i16_indexed;
9828 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9830 break;
9831
9834 RC = &AArch64::FPR128RegClass;
9836 Opc = AArch64::FMLSv2i64_indexed;
9837 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9839 } else {
9840 Opc = AArch64::FMLSv2f64;
9841 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9843 }
9844 break;
9845
9848 RC = &AArch64::FPR128RegClass;
9850 Opc = AArch64::FMLSv4i32_indexed;
9851 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9853 } else {
9854 Opc = AArch64::FMLSv4f32;
9855 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9857 }
9858 break;
9861 RC = &AArch64::FPR64RegClass;
9862 Register NewVR = MRI.createVirtualRegister(RC);
9863 MachineInstrBuilder MIB1 =
9864 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f32), NewVR)
9865 .add(Root.getOperand(2));
9866 InsInstrs.push_back(MIB1);
9867 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9869 Opc = AArch64::FMLAv2i32_indexed;
9870 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9871 FMAInstKind::Indexed, &NewVR);
9872 } else {
9873 Opc = AArch64::FMLAv2f32;
9874 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9875 FMAInstKind::Accumulator, &NewVR);
9876 }
9877 break;
9878 }
9881 RC = &AArch64::FPR128RegClass;
9882 Register NewVR = MRI.createVirtualRegister(RC);
9883 MachineInstrBuilder MIB1 =
9884 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f32), NewVR)
9885 .add(Root.getOperand(2));
9886 InsInstrs.push_back(MIB1);
9887 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9889 Opc = AArch64::FMLAv4i32_indexed;
9890 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9891 FMAInstKind::Indexed, &NewVR);
9892 } else {
9893 Opc = AArch64::FMLAv4f32;
9894 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9895 FMAInstKind::Accumulator, &NewVR);
9896 }
9897 break;
9898 }
9901 RC = &AArch64::FPR128RegClass;
9902 Register NewVR = MRI.createVirtualRegister(RC);
9903 MachineInstrBuilder MIB1 =
9904 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f64), NewVR)
9905 .add(Root.getOperand(2));
9906 InsInstrs.push_back(MIB1);
9907 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9909 Opc = AArch64::FMLAv2i64_indexed;
9910 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9911 FMAInstKind::Indexed, &NewVR);
9912 } else {
9913 Opc = AArch64::FMLAv2f64;
9914 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9915 FMAInstKind::Accumulator, &NewVR);
9916 }
9917 break;
9918 }
9921 unsigned IdxDupOp =
9923 : 2;
9924 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i32_indexed,
9925 &AArch64::FPR128RegClass, MRI);
9926 break;
9927 }
9930 unsigned IdxDupOp =
9932 : 2;
9933 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i64_indexed,
9934 &AArch64::FPR128RegClass, MRI);
9935 break;
9936 }
9939 unsigned IdxDupOp =
9941 : 2;
9942 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i16_indexed,
9943 &AArch64::FPR128_loRegClass, MRI);
9944 break;
9945 }
9948 unsigned IdxDupOp =
9950 : 2;
9951 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i32_indexed,
9952 &AArch64::FPR128RegClass, MRI);
9953 break;
9954 }
9957 unsigned IdxDupOp =
9959 : 2;
9960 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv8i16_indexed,
9961 &AArch64::FPR128_loRegClass, MRI);
9962 break;
9963 }
9965 MUL = genFNegatedMAD(MF, MRI, TII, Root, InsInstrs);
9966 break;
9967 }
9969 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9970 Pattern, 4);
9971 break;
9972 }
9974 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9975 Pattern, 8);
9976 break;
9977 }
9979 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
9980 Pattern, 16);
9981 break;
9982 }
9983
9984 } // end switch (Pattern)
9985 // Record MUL and ADD/SUB for deletion
9986 if (MUL)
9987 DelInstrs.push_back(MUL);
9988 DelInstrs.push_back(&Root);
9989
9990 // Set the flags on the inserted instructions to be the merged flags of the
9991 // instructions that we have combined.
9992 uint32_t Flags = Root.getFlags();
9993 if (MUL)
9994 Flags = Root.mergeFlagsWith(*MUL);
9995 for (auto *MI : InsInstrs)
9996 MI->setFlags(Flags);
9997}
9998
9999/// Replace csincr-branch sequence by simple conditional branch
10000///
10001/// Examples:
10002/// 1. \code
10003/// csinc w9, wzr, wzr, <condition code>
10004/// tbnz w9, #0, 0x44
10005/// \endcode
10006/// to
10007/// \code
10008/// b.<inverted condition code>
10009/// \endcode
10010///
10011/// 2. \code
10012/// csinc w9, wzr, wzr, <condition code>
10013/// tbz w9, #0, 0x44
10014/// \endcode
10015/// to
10016/// \code
10017/// b.<condition code>
10018/// \endcode
10019///
10020/// Replace compare and branch sequence by TBZ/TBNZ instruction when the
10021/// compare's constant operand is power of 2.
10022///
10023/// Examples:
10024/// \code
10025/// and w8, w8, #0x400
10026/// cbnz w8, L1
10027/// \endcode
10028/// to
10029/// \code
10030/// tbnz w8, #10, L1
10031/// \endcode
10032///
10033/// \param MI Conditional Branch
10034/// \return True when the simple conditional branch is generated
10035///
10037 bool IsNegativeBranch = false;
10038 bool IsTestAndBranch = false;
10039 unsigned TargetBBInMI = 0;
10040 switch (MI.getOpcode()) {
10041 default:
10042 llvm_unreachable("Unknown branch instruction?");
10043 case AArch64::Bcc:
10044 case AArch64::CBWPri:
10045 case AArch64::CBXPri:
10046 case AArch64::CBBAssertExt:
10047 case AArch64::CBHAssertExt:
10048 case AArch64::CBWPrr:
10049 case AArch64::CBXPrr:
10050 return false;
10051 case AArch64::CBZW:
10052 case AArch64::CBZX:
10053 TargetBBInMI = 1;
10054 break;
10055 case AArch64::CBNZW:
10056 case AArch64::CBNZX:
10057 TargetBBInMI = 1;
10058 IsNegativeBranch = true;
10059 break;
10060 case AArch64::TBZW:
10061 case AArch64::TBZX:
10062 TargetBBInMI = 2;
10063 IsTestAndBranch = true;
10064 break;
10065 case AArch64::TBNZW:
10066 case AArch64::TBNZX:
10067 TargetBBInMI = 2;
10068 IsNegativeBranch = true;
10069 IsTestAndBranch = true;
10070 break;
10071 }
10072 // So we increment a zero register and test for bits other
10073 // than bit 0? Conservatively bail out in case the verifier
10074 // missed this case.
10075 if (IsTestAndBranch && MI.getOperand(1).getImm())
10076 return false;
10077
10078 // Find Definition.
10079 assert(MI.getParent() && "Incomplete machine instruction\n");
10080 MachineBasicBlock *MBB = MI.getParent();
10081 MachineFunction *MF = MBB->getParent();
10082 MachineRegisterInfo *MRI = &MF->getRegInfo();
10083 Register VReg = MI.getOperand(0).getReg();
10084 if (!VReg.isVirtual())
10085 return false;
10086
10087 MachineInstr *DefMI = MRI->getVRegDef(VReg);
10088
10089 // Look through COPY instructions to find definition.
10090 while (DefMI->isCopy()) {
10091 Register CopyVReg = DefMI->getOperand(1).getReg();
10092 if (!MRI->hasOneNonDBGUse(CopyVReg))
10093 return false;
10094 if (!MRI->hasOneDef(CopyVReg))
10095 return false;
10096 DefMI = MRI->getVRegDef(CopyVReg);
10097 }
10098
10099 switch (DefMI->getOpcode()) {
10100 default:
10101 return false;
10102 // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
10103 case AArch64::ANDWri:
10104 case AArch64::ANDXri: {
10105 if (IsTestAndBranch)
10106 return false;
10107 if (DefMI->getParent() != MBB)
10108 return false;
10109 if (!MRI->hasOneNonDBGUse(VReg))
10110 return false;
10111
10112 bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
10114 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
10115 if (!isPowerOf2_64(Mask))
10116 return false;
10117
10118 MachineOperand &MO = DefMI->getOperand(1);
10119 Register NewReg = MO.getReg();
10120 if (!NewReg.isVirtual())
10121 return false;
10122
10123 assert(!MRI->def_empty(NewReg) && "Register must be defined.");
10124
10125 MachineBasicBlock &RefToMBB = *MBB;
10126 MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
10127 DebugLoc DL = MI.getDebugLoc();
10128 unsigned Imm = Log2_64(Mask);
10129 unsigned Opc = (Imm < 32)
10130 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
10131 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
10132 MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
10133 .addReg(NewReg)
10134 .addImm(Imm)
10135 .addMBB(TBB);
10136 // Register lives on to the CBZ now.
10137 MO.setIsKill(false);
10138
10139 // For immediate smaller than 32, we need to use the 32-bit
10140 // variant (W) in all cases. Indeed the 64-bit variant does not
10141 // allow to encode them.
10142 // Therefore, if the input register is 64-bit, we need to take the
10143 // 32-bit sub-part.
10144 if (!Is32Bit && Imm < 32)
10145 NewMI->getOperand(0).setSubReg(AArch64::sub_32);
10146 MI.eraseFromParent();
10147 return true;
10148 }
10149 // Look for CSINC
10150 case AArch64::CSINCWr:
10151 case AArch64::CSINCXr: {
10152 if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
10153 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
10154 !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
10155 DefMI->getOperand(2).getReg() == AArch64::XZR))
10156 return false;
10157
10158 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
10159 true) != -1)
10160 return false;
10161
10162 AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
10163 // Convert only when the condition code is not modified between
10164 // the CSINC and the branch. The CC may be used by other
10165 // instructions in between.
10167 return false;
10168 MachineBasicBlock &RefToMBB = *MBB;
10169 MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
10170 DebugLoc DL = MI.getDebugLoc();
10171 if (IsNegativeBranch)
10173 BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
10174 MI.eraseFromParent();
10175 return true;
10176 }
10177 }
10178}
10179
10180std::pair<unsigned, unsigned>
10181AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
10182 const unsigned Mask = AArch64II::MO_FRAGMENT;
10183 return std::make_pair(TF & Mask, TF & ~Mask);
10184}
10185
10187AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
10188 using namespace AArch64II;
10189
10190 static const std::pair<unsigned, const char *> TargetFlags[] = {
10191 {MO_PAGE, "aarch64-page"}, {MO_PAGEOFF, "aarch64-pageoff"},
10192 {MO_G3, "aarch64-g3"}, {MO_G2, "aarch64-g2"},
10193 {MO_G1, "aarch64-g1"}, {MO_G0, "aarch64-g0"},
10194 {MO_HI12, "aarch64-hi12"}};
10195 return ArrayRef(TargetFlags);
10196}
10197
10199AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
10200 using namespace AArch64II;
10201
10202 static const std::pair<unsigned, const char *> TargetFlags[] = {
10203 {MO_COFFSTUB, "aarch64-coffstub"},
10204 {MO_GOT, "aarch64-got"},
10205 {MO_NC, "aarch64-nc"},
10206 {MO_S, "aarch64-s"},
10207 {MO_TLS, "aarch64-tls"},
10208 {MO_DLLIMPORT, "aarch64-dllimport"},
10209 {MO_PREL, "aarch64-prel"},
10210 {MO_TAGGED, "aarch64-tagged"},
10211 {MO_ARM64EC_CALLMANGLE, "aarch64-arm64ec-callmangle"},
10212 };
10213 return ArrayRef(TargetFlags);
10214}
10215
10217AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const {
10218 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10219 {{MOSuppressPair, "aarch64-suppress-pair"},
10220 {MOStridedAccess, "aarch64-strided-access"}};
10221 return ArrayRef(TargetFlags);
10222}
10223
10224/// Constants defining how certain sequences should be outlined.
10225/// This encompasses how an outlined function should be called, and what kind of
10226/// frame should be emitted for that outlined function.
10227///
10228/// \p MachineOutlinerDefault implies that the function should be called with
10229/// a save and restore of LR to the stack.
10230///
10231/// That is,
10232///
10233/// I1 Save LR OUTLINED_FUNCTION:
10234/// I2 --> BL OUTLINED_FUNCTION I1
10235/// I3 Restore LR I2
10236/// I3
10237/// RET
10238///
10239/// * Call construction overhead: 3 (save + BL + restore)
10240/// * Frame construction overhead: 1 (ret)
10241/// * Requires stack fixups? Yes
10242///
10243/// \p MachineOutlinerTailCall implies that the function is being created from
10244/// a sequence of instructions ending in a return.
10245///
10246/// That is,
10247///
10248/// I1 OUTLINED_FUNCTION:
10249/// I2 --> B OUTLINED_FUNCTION I1
10250/// RET I2
10251/// RET
10252///
10253/// * Call construction overhead: 1 (B)
10254/// * Frame construction overhead: 0 (Return included in sequence)
10255/// * Requires stack fixups? No
10256///
10257/// \p MachineOutlinerNoLRSave implies that the function should be called using
10258/// a BL instruction, but doesn't require LR to be saved and restored. This
10259/// happens when LR is known to be dead.
10260///
10261/// That is,
10262///
10263/// I1 OUTLINED_FUNCTION:
10264/// I2 --> BL OUTLINED_FUNCTION I1
10265/// I3 I2
10266/// I3
10267/// RET
10268///
10269/// * Call construction overhead: 1 (BL)
10270/// * Frame construction overhead: 1 (RET)
10271/// * Requires stack fixups? No
10272///
10273/// \p MachineOutlinerThunk implies that the function is being created from
10274/// a sequence of instructions ending in a call. The outlined function is
10275/// called with a BL instruction, and the outlined function tail-calls the
10276/// original call destination.
10277///
10278/// That is,
10279///
10280/// I1 OUTLINED_FUNCTION:
10281/// I2 --> BL OUTLINED_FUNCTION I1
10282/// BL f I2
10283/// B f
10284/// * Call construction overhead: 1 (BL)
10285/// * Frame construction overhead: 0
10286/// * Requires stack fixups? No
10287///
10288/// \p MachineOutlinerRegSave implies that the function should be called with a
10289/// save and restore of LR to an available register. This allows us to avoid
10290/// stack fixups. Note that this outlining variant is compatible with the
10291/// NoLRSave case.
10292///
10293/// That is,
10294///
10295/// I1 Save LR OUTLINED_FUNCTION:
10296/// I2 --> BL OUTLINED_FUNCTION I1
10297/// I3 Restore LR I2
10298/// I3
10299/// RET
10300///
10301/// * Call construction overhead: 3 (save + BL + restore)
10302/// * Frame construction overhead: 1 (ret)
10303/// * Requires stack fixups? No
10305 MachineOutlinerDefault, /// Emit a save, restore, call, and return.
10306 MachineOutlinerTailCall, /// Only emit a branch.
10307 MachineOutlinerNoLRSave, /// Emit a call and return.
10308 MachineOutlinerThunk, /// Emit a call and tail-call.
10309 MachineOutlinerRegSave /// Same as default, but save to a register.
10310};
10311
10317
10319AArch64InstrInfo::findRegisterToSaveLRTo(outliner::Candidate &C) const {
10320 MachineFunction *MF = C.getMF();
10321 const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
10322 const AArch64RegisterInfo *ARI =
10323 static_cast<const AArch64RegisterInfo *>(&TRI);
10324 // Check if there is an available register across the sequence that we can
10325 // use.
10326 for (unsigned Reg : AArch64::GPR64RegClass) {
10327 if (!ARI->isReservedReg(*MF, Reg) &&
10328 Reg != AArch64::LR && // LR is not reserved, but don't use it.
10329 Reg != AArch64::X16 && // X16 is not guaranteed to be preserved.
10330 Reg != AArch64::X17 && // Ditto for X17.
10331 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&
10332 C.isAvailableInsideSeq(Reg, TRI))
10333 return Reg;
10334 }
10335 return Register();
10336}
10337
10338static bool
10340 const outliner::Candidate &b) {
10341 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10342 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10343
10344 return MFIa->getSignReturnAddressCondition() ==
10346}
10347
10348static bool
10350 const outliner::Candidate &b) {
10351 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10352 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10353
10354 return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey();
10355}
10356
10358 const outliner::Candidate &b) {
10359 const AArch64Subtarget &SubtargetA =
10361 const AArch64Subtarget &SubtargetB =
10362 b.getMF()->getSubtarget<AArch64Subtarget>();
10363 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10364}
10365
10366std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10367AArch64InstrInfo::getOutliningCandidateInfo(
10368 const MachineModuleInfo &MMI,
10369 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10370 unsigned MinRepeats) const {
10371 unsigned SequenceSize = 0;
10372 for (auto &MI : RepeatedSequenceLocs[0])
10373 SequenceSize += getInstSizeInBytes(MI);
10374
10375 unsigned NumBytesToCreateFrame = 0;
10376
10377 // Avoid splitting ADRP ADD/LDR pair into outlined functions.
10378 // These instructions are fused together by the scheduler.
10379 // Any candidate where ADRP is the last instruction should be rejected
10380 // as that will lead to splitting ADRP pair.
10381 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10382 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10383 if (LastMI.getOpcode() == AArch64::ADRP &&
10384 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0 &&
10385 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10386 return std::nullopt;
10387 }
10388
10389 // Similarly any candidate where the first instruction is ADD/LDR with a
10390 // page offset should be rejected to avoid ADRP splitting.
10391 if ((FirstMI.getOpcode() == AArch64::ADDXri ||
10392 FirstMI.getOpcode() == AArch64::LDRXui) &&
10393 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_PAGEOFF) != 0 &&
10394 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10395 return std::nullopt;
10396 }
10397
10398 // We only allow outlining for functions having exactly matching return
10399 // address signing attributes, i.e., all share the same value for the
10400 // attribute "sign-return-address" and all share the same type of key they
10401 // are signed with.
10402 // Additionally we require all functions to simultaneously either support
10403 // v8.3a features or not. Otherwise an outlined function could get signed
10404 // using dedicated v8.3 instructions and a call from a function that doesn't
10405 // support v8.3 instructions would therefore be invalid.
10406 if (std::adjacent_find(
10407 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10408 [](const outliner::Candidate &a, const outliner::Candidate &b) {
10409 // Return true if a and b are non-equal w.r.t. return address
10410 // signing or support of v8.3a features
10411 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10412 outliningCandidatesSigningKeyConsensus(a, b) &&
10413 outliningCandidatesV8_3OpsConsensus(a, b)) {
10414 return false;
10415 }
10416 return true;
10417 }) != RepeatedSequenceLocs.end()) {
10418 return std::nullopt;
10419 }
10420
10421 // Since at this point all candidates agree on their return address signing
10422 // picking just one is fine. If the candidate functions potentially sign their
10423 // return addresses, the outlined function should do the same. Note that in
10424 // the case of "sign-return-address"="non-leaf" this is an assumption: It is
10425 // not certainly true that the outlined function will have to sign its return
10426 // address but this decision is made later, when the decision to outline
10427 // has already been made.
10428 // The same holds for the number of additional instructions we need: On
10429 // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
10430 // necessary. However, at this point we don't know if the outlined function
10431 // will have a RET instruction so we assume the worst.
10432 const TargetRegisterInfo &TRI = getRegisterInfo();
10433 // Performing a tail call may require extra checks when PAuth is enabled.
10434 // If PAuth is disabled, set it to zero for uniformity.
10435 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10436 const auto RASignCondition = RepeatedSequenceLocs[0]
10437 .getMF()
10438 ->getInfo<AArch64FunctionInfo>()
10439 ->getSignReturnAddressCondition();
10440 if (RASignCondition != SignReturnAddress::None) {
10441 // One PAC and one AUT instructions
10442 NumBytesToCreateFrame += 8;
10443
10444 // PAuth is enabled - set extra tail call cost, if any.
10445 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10446 *RepeatedSequenceLocs[0].getMF());
10447 NumBytesToCheckLRInTCEpilogue =
10449 // Checking the authenticated LR value may significantly impact
10450 // SequenceSize, so account for it for more precise results.
10451 if (isTailCallReturnInst(RepeatedSequenceLocs[0].back()))
10452 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10453
10454 // We have to check if sp modifying instructions would get outlined.
10455 // If so we only allow outlining if sp is unchanged overall, so matching
10456 // sub and add instructions are okay to outline, all other sp modifications
10457 // are not
10458 auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) {
10459 int SPValue = 0;
10460 for (auto &MI : C) {
10461 if (MI.modifiesRegister(AArch64::SP, &TRI)) {
10462 switch (MI.getOpcode()) {
10463 case AArch64::ADDXri:
10464 case AArch64::ADDWri:
10465 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10466 assert(MI.getOperand(2).isImm() &&
10467 "Expected operand to be immediate");
10468 assert(MI.getOperand(1).isReg() &&
10469 "Expected operand to be a register");
10470 // Check if the add just increments sp. If so, we search for
10471 // matching sub instructions that decrement sp. If not, the
10472 // modification is illegal
10473 if (MI.getOperand(1).getReg() == AArch64::SP)
10474 SPValue += MI.getOperand(2).getImm();
10475 else
10476 return true;
10477 break;
10478 case AArch64::SUBXri:
10479 case AArch64::SUBWri:
10480 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10481 assert(MI.getOperand(2).isImm() &&
10482 "Expected operand to be immediate");
10483 assert(MI.getOperand(1).isReg() &&
10484 "Expected operand to be a register");
10485 // Check if the sub just decrements sp. If so, we search for
10486 // matching add instructions that increment sp. If not, the
10487 // modification is illegal
10488 if (MI.getOperand(1).getReg() == AArch64::SP)
10489 SPValue -= MI.getOperand(2).getImm();
10490 else
10491 return true;
10492 break;
10493 default:
10494 return true;
10495 }
10496 }
10497 }
10498 if (SPValue)
10499 return true;
10500 return false;
10501 };
10502 // Remove candidates with illegal stack modifying instructions
10503 llvm::erase_if(RepeatedSequenceLocs, hasIllegalSPModification);
10504
10505 // If the sequence doesn't have enough candidates left, then we're done.
10506 if (RepeatedSequenceLocs.size() < MinRepeats)
10507 return std::nullopt;
10508 }
10509
10510 // Properties about candidate MBBs that hold for all of them.
10511 unsigned FlagsSetInAll = 0xF;
10512
10513 // Compute liveness information for each candidate, and set FlagsSetInAll.
10514 for (outliner::Candidate &C : RepeatedSequenceLocs)
10515 FlagsSetInAll &= C.Flags;
10516
10517 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10518
10519 // Helper lambda which sets call information for every candidate.
10520 auto SetCandidateCallInfo =
10521 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {
10522 for (outliner::Candidate &C : RepeatedSequenceLocs)
10523 C.setCallInfo(CallID, NumBytesForCall);
10524 };
10525
10526 unsigned FrameID = MachineOutlinerDefault;
10527 NumBytesToCreateFrame += 4;
10528
10529 bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10530 return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement();
10531 });
10532
10533 // We check to see if CFI Instructions are present, and if they are
10534 // we find the number of CFI Instructions in the candidates.
10535 unsigned CFICount = 0;
10536 for (auto &I : RepeatedSequenceLocs[0]) {
10537 if (I.isCFIInstruction())
10538 CFICount++;
10539 }
10540
10541 // We compare the number of found CFI Instructions to the number of CFI
10542 // instructions in the parent function for each candidate. We must check this
10543 // since if we outline one of the CFI instructions in a function, we have to
10544 // outline them all for correctness. If we do not, the address offsets will be
10545 // incorrect between the two sections of the program.
10546 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10547 std::vector<MCCFIInstruction> CFIInstructions =
10548 C.getMF()->getFrameInstructions();
10549
10550 if (CFICount > 0 && CFICount != CFIInstructions.size())
10551 return std::nullopt;
10552 }
10553
10554 // Returns true if an instructions is safe to fix up, false otherwise.
10555 auto IsSafeToFixup = [this, &TRI](MachineInstr &MI) {
10556 if (MI.isCall())
10557 return true;
10558
10559 if (!MI.modifiesRegister(AArch64::SP, &TRI) &&
10560 !MI.readsRegister(AArch64::SP, &TRI))
10561 return true;
10562
10563 // Any modification of SP will break our code to save/restore LR.
10564 // FIXME: We could handle some instructions which add a constant
10565 // offset to SP, with a bit more work.
10566 if (MI.modifiesRegister(AArch64::SP, &TRI))
10567 return false;
10568
10569 // At this point, we have a stack instruction that we might need to
10570 // fix up. We'll handle it if it's a load or store.
10571 if (MI.mayLoadOrStore()) {
10572 const MachineOperand *Base; // Filled with the base operand of MI.
10573 int64_t Offset; // Filled with the offset of MI.
10574 bool OffsetIsScalable;
10575
10576 // Does it allow us to offset the base operand and is the base the
10577 // register SP?
10578 if (!getMemOperandWithOffset(MI, Base, Offset, OffsetIsScalable, &TRI) ||
10579 !Base->isReg() || Base->getReg() != AArch64::SP)
10580 return false;
10581
10582 // Fixe-up code below assumes bytes.
10583 if (OffsetIsScalable)
10584 return false;
10585
10586 // Find the minimum/maximum offset for this instruction and check
10587 // if fixing it up would be in range.
10588 int64_t MinOffset,
10589 MaxOffset; // Unscaled offsets for the instruction.
10590 // The scale to multiply the offsets by.
10591 TypeSize Scale(0U, false), DummyWidth(0U, false);
10592 getMemOpInfo(MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10593
10594 Offset += 16; // Update the offset to what it would be if we outlined.
10595 if (Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10596 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10597 return false;
10598
10599 // It's in range, so we can outline it.
10600 return true;
10601 }
10602
10603 // FIXME: Add handling for instructions like "add x0, sp, #8".
10604
10605 // We can't fix it up, so don't outline it.
10606 return false;
10607 };
10608
10609 // True if it's possible to fix up each stack instruction in this sequence.
10610 // Important for frames/call variants that modify the stack.
10611 bool AllStackInstrsSafe =
10612 llvm::all_of(RepeatedSequenceLocs[0], IsSafeToFixup);
10613
10614 // If the last instruction in any candidate is a terminator, then we should
10615 // tail call all of the candidates.
10616 if (RepeatedSequenceLocs[0].back().isTerminator()) {
10617 FrameID = MachineOutlinerTailCall;
10618 NumBytesToCreateFrame = 0;
10619 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10620 SetCandidateCallInfo(MachineOutlinerTailCall, NumBytesForCall);
10621 }
10622
10623 else if (LastInstrOpcode == AArch64::BL ||
10624 ((LastInstrOpcode == AArch64::BLR ||
10625 LastInstrOpcode == AArch64::BLRNoIP) &&
10626 !HasBTI)) {
10627 // FIXME: Do we need to check if the code after this uses the value of LR?
10628 FrameID = MachineOutlinerThunk;
10629 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10630 SetCandidateCallInfo(MachineOutlinerThunk, 4);
10631 }
10632
10633 else {
10634 // We need to decide how to emit calls + frames. We can always emit the same
10635 // frame if we don't need to save to the stack. If we have to save to the
10636 // stack, then we need a different frame.
10637 unsigned NumBytesNoStackCalls = 0;
10638 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10639
10640 // Check if we have to save LR.
10641 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10642 bool LRAvailable =
10644 ? C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI)
10645 : true;
10646 // If we have a noreturn caller, then we're going to be conservative and
10647 // say that we have to save LR. If we don't have a ret at the end of the
10648 // block, then we can't reason about liveness accurately.
10649 //
10650 // FIXME: We can probably do better than always disabling this in
10651 // noreturn functions by fixing up the liveness info.
10652 bool IsNoReturn =
10653 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10654
10655 // Is LR available? If so, we don't need a save.
10656 if (LRAvailable && !IsNoReturn) {
10657 NumBytesNoStackCalls += 4;
10658 C.setCallInfo(MachineOutlinerNoLRSave, 4);
10659 CandidatesWithoutStackFixups.push_back(C);
10660 }
10661
10662 // Is an unused register available? If so, we won't modify the stack, so
10663 // we can outline with the same frame type as those that don't save LR.
10664 else if (findRegisterToSaveLRTo(C)) {
10665 NumBytesNoStackCalls += 12;
10666 C.setCallInfo(MachineOutlinerRegSave, 12);
10667 CandidatesWithoutStackFixups.push_back(C);
10668 }
10669
10670 // Is SP used in the sequence at all? If not, we don't have to modify
10671 // the stack, so we are guaranteed to get the same frame.
10672 else if (C.isAvailableInsideSeq(AArch64::SP, TRI)) {
10673 NumBytesNoStackCalls += 12;
10674 C.setCallInfo(MachineOutlinerDefault, 12);
10675 CandidatesWithoutStackFixups.push_back(C);
10676 }
10677
10678 // If we outline this, we need to modify the stack. Pretend we don't
10679 // outline this by saving all of its bytes.
10680 else {
10681 NumBytesNoStackCalls += SequenceSize;
10682 }
10683 }
10684
10685 // If there are no places where we have to save LR, then note that we
10686 // don't have to update the stack. Otherwise, give every candidate the
10687 // default call type, as long as it's safe to do so.
10688 if (!AllStackInstrsSafe ||
10689 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10690 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10691 FrameID = MachineOutlinerNoLRSave;
10692 if (RepeatedSequenceLocs.size() < MinRepeats)
10693 return std::nullopt;
10694 } else {
10695 SetCandidateCallInfo(MachineOutlinerDefault, 12);
10696
10697 // Bugzilla ID: 46767
10698 // TODO: Check if fixing up the stack more than once is safe so we can
10699 // outline these.
10700 //
10701 // An outline resulting in a caller that requires stack fixups at the
10702 // callsite to a callee that also requires stack fixups can happen when
10703 // there are no available registers at the candidate callsite for a
10704 // candidate that itself also has calls.
10705 //
10706 // In other words if function_containing_sequence in the following pseudo
10707 // assembly requires that we save LR at the point of the call, but there
10708 // are no available registers: in this case we save using SP and as a
10709 // result the SP offsets requires stack fixups by multiples of 16.
10710 //
10711 // function_containing_sequence:
10712 // ...
10713 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10714 // call OUTLINED_FUNCTION_N
10715 // restore LR from SP
10716 // ...
10717 //
10718 // OUTLINED_FUNCTION_N:
10719 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10720 // ...
10721 // bl foo
10722 // restore LR from SP
10723 // ret
10724 //
10725 // Because the code to handle more than one stack fixup does not
10726 // currently have the proper checks for legality, these cases will assert
10727 // in the AArch64 MachineOutliner. This is because the code to do this
10728 // needs more hardening, testing, better checks that generated code is
10729 // legal, etc and because it is only verified to handle a single pass of
10730 // stack fixup.
10731 //
10732 // The assert happens in AArch64InstrInfo::buildOutlinedFrame to catch
10733 // these cases until they are known to be handled. Bugzilla 46767 is
10734 // referenced in comments at the assert site.
10735 //
10736 // To avoid asserting (or generating non-legal code on noassert builds)
10737 // we remove all candidates which would need more than one stack fixup by
10738 // pruning the cases where the candidate has calls while also having no
10739 // available LR and having no available general purpose registers to copy
10740 // LR to (ie one extra stack save/restore).
10741 //
10742 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10743 erase_if(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
10744 auto IsCall = [](const MachineInstr &MI) { return MI.isCall(); };
10745 return (llvm::any_of(C, IsCall)) &&
10746 (!C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI) ||
10747 !findRegisterToSaveLRTo(C));
10748 });
10749 }
10750 }
10751
10752 // If we dropped all of the candidates, bail out here.
10753 if (RepeatedSequenceLocs.size() < MinRepeats)
10754 return std::nullopt;
10755 }
10756
10757 // Does every candidate's MBB contain a call? If so, then we might have a call
10758 // in the range.
10759 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10760 // Check if the range contains a call. These require a save + restore of the
10761 // link register.
10762 outliner::Candidate &FirstCand = RepeatedSequenceLocs[0];
10763 bool ModStackToSaveLR = false;
10764 if (any_of(drop_end(FirstCand),
10765 [](const MachineInstr &MI) { return MI.isCall(); }))
10766 ModStackToSaveLR = true;
10767
10768 // Handle the last instruction separately. If this is a tail call, then the
10769 // last instruction is a call. We don't want to save + restore in this case.
10770 // However, it could be possible that the last instruction is a call without
10771 // it being valid to tail call this sequence. We should consider this as
10772 // well.
10773 else if (FrameID != MachineOutlinerThunk &&
10774 FrameID != MachineOutlinerTailCall && FirstCand.back().isCall())
10775 ModStackToSaveLR = true;
10776
10777 if (ModStackToSaveLR) {
10778 // We can't fix up the stack. Bail out.
10779 if (!AllStackInstrsSafe)
10780 return std::nullopt;
10781
10782 // Save + restore LR.
10783 NumBytesToCreateFrame += 8;
10784 }
10785 }
10786
10787 // If we have CFI instructions, we can only outline if the outlined section
10788 // can be a tail call
10789 if (FrameID != MachineOutlinerTailCall && CFICount > 0)
10790 return std::nullopt;
10791
10792 return std::make_unique<outliner::OutlinedFunction>(
10793 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10794}
10795
10796void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10797 Function &F, std::vector<outliner::Candidate> &Candidates) const {
10798 // If a bunch of candidates reach this point they must agree on their return
10799 // address signing. It is therefore enough to just consider the signing
10800 // behaviour of one of them
10801 const auto &CFn = Candidates.front().getMF()->getFunction();
10802
10803 if (CFn.hasFnAttribute("ptrauth-returns"))
10804 F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
10805 if (CFn.hasFnAttribute("ptrauth-auth-traps"))
10806 F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
10807 // Since all candidates belong to the same module, just copy the
10808 // function-level attributes of an arbitrary function.
10809 if (CFn.hasFnAttribute("sign-return-address"))
10810 F.addFnAttr(CFn.getFnAttribute("sign-return-address"));
10811 if (CFn.hasFnAttribute("sign-return-address-key"))
10812 F.addFnAttr(CFn.getFnAttribute("sign-return-address-key"));
10813
10814 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);
10815}
10816
10817bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10818 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
10819 const Function &F = MF.getFunction();
10820
10821 // Can F be deduplicated by the linker? If it can, don't outline from it.
10822 if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
10823 return false;
10824
10825 // Don't outline from functions with section markings; the program could
10826 // expect that all the code is in the named section.
10827 // FIXME: Allow outlining from multiple functions with the same section
10828 // marking.
10829 if (F.hasSection())
10830 return false;
10831
10832 // Outlining from functions with redzones is unsafe since the outliner may
10833 // modify the stack. Check if hasRedZone is true or unknown; if yes, don't
10834 // outline from it.
10835 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
10836 if (!AFI || AFI->hasRedZone().value_or(true))
10837 return false;
10838
10839 // FIXME: Determine whether it is safe to outline from functions which contain
10840 // streaming-mode changes. We may need to ensure any smstart/smstop pairs are
10841 // outlined together and ensure it is safe to outline with async unwind info,
10842 // required for saving & restoring VG around calls.
10843 if (AFI->hasStreamingModeChanges())
10844 return false;
10845
10846 // FIXME: Teach the outliner to generate/handle Windows unwind info.
10848 return false;
10849
10850 // It's safe to outline from MF.
10851 return true;
10852}
10853
10855AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
10856 unsigned &Flags) const {
10858 "Must track liveness!");
10860 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10861 Ranges;
10862 // According to the AArch64 Procedure Call Standard, the following are
10863 // undefined on entry/exit from a function call:
10864 //
10865 // * Registers x16, x17, (and thus w16, w17)
10866 // * Condition codes (and thus the NZCV register)
10867 //
10868 // If any of these registers are used inside or live across an outlined
10869 // function, then they may be modified later, either by the compiler or
10870 // some other tool (like the linker).
10871 //
10872 // To avoid outlining in these situations, partition each block into ranges
10873 // where these registers are dead. We will only outline from those ranges.
10874 LiveRegUnits LRU(getRegisterInfo());
10875 auto AreAllUnsafeRegsDead = [&LRU]() {
10876 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10877 LRU.available(AArch64::NZCV);
10878 };
10879
10880 // We need to know if LR is live across an outlining boundary later on in
10881 // order to decide how we'll create the outlined call, frame, etc.
10882 //
10883 // It's pretty expensive to check this for *every candidate* within a block.
10884 // That's some potentially n^2 behaviour, since in the worst case, we'd need
10885 // to compute liveness from the end of the block for O(n) candidates within
10886 // the block.
10887 //
10888 // So, to improve the average case, let's keep track of liveness from the end
10889 // of the block to the beginning of *every outlinable range*. If we know that
10890 // LR is available in every range we could outline from, then we know that
10891 // we don't need to check liveness for any candidate within that range.
10892 bool LRAvailableEverywhere = true;
10893 // Compute liveness bottom-up.
10894 LRU.addLiveOuts(MBB);
10895 // Update flags that require info about the entire MBB.
10896 auto UpdateWholeMBBFlags = [&Flags](const MachineInstr &MI) {
10897 if (MI.isCall() && !MI.isTerminator())
10899 };
10900 // Range: [RangeBegin, RangeEnd)
10901 MachineBasicBlock::instr_iterator RangeBegin, RangeEnd;
10902 unsigned RangeLen;
10903 auto CreateNewRangeStartingAt =
10904 [&RangeBegin, &RangeEnd,
10905 &RangeLen](MachineBasicBlock::instr_iterator NewBegin) {
10906 RangeBegin = NewBegin;
10907 RangeEnd = std::next(RangeBegin);
10908 RangeLen = 0;
10909 };
10910 auto SaveRangeIfNonEmpty = [&RangeLen, &Ranges, &RangeBegin, &RangeEnd]() {
10911 // At least one unsafe register is not dead. We do not want to outline at
10912 // this point. If it is long enough to outline from and does not cross a
10913 // bundle boundary, save the range [RangeBegin, RangeEnd).
10914 if (RangeLen <= 1)
10915 return;
10916 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
10917 return;
10918 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
10919 return;
10920 Ranges.emplace_back(RangeBegin, RangeEnd);
10921 };
10922 // Find the first point where all unsafe registers are dead.
10923 // FIND: <safe instr> <-- end of first potential range
10924 // SKIP: <unsafe def>
10925 // SKIP: ... everything between ...
10926 // SKIP: <unsafe use>
10927 auto FirstPossibleEndPt = MBB.instr_rbegin();
10928 for (; FirstPossibleEndPt != MBB.instr_rend(); ++FirstPossibleEndPt) {
10929 if (!FirstPossibleEndPt->isDebugInstr())
10930 LRU.stepBackward(*FirstPossibleEndPt);
10931 // Update flags that impact how we outline across the entire block,
10932 // regardless of safety.
10933 UpdateWholeMBBFlags(*FirstPossibleEndPt);
10934 if (AreAllUnsafeRegsDead())
10935 break;
10936 }
10937 // If we exhausted the entire block, we have no safe ranges to outline.
10938 if (FirstPossibleEndPt == MBB.instr_rend())
10939 return Ranges;
10940 // Current range.
10941 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
10942 // StartPt points to the first place where all unsafe registers
10943 // are dead (if there is any such point). Begin partitioning the MBB into
10944 // ranges.
10945 for (auto &MI : make_range(FirstPossibleEndPt, MBB.instr_rend())) {
10946 if (!MI.isDebugInstr())
10947 LRU.stepBackward(MI);
10948 UpdateWholeMBBFlags(MI);
10949 if (!AreAllUnsafeRegsDead()) {
10950 SaveRangeIfNonEmpty();
10951 CreateNewRangeStartingAt(MI.getIterator());
10952 continue;
10953 }
10954 LRAvailableEverywhere &= LRU.available(AArch64::LR);
10955 RangeBegin = MI.getIterator();
10956 ++RangeLen;
10957 }
10958 // Above loop misses the last (or only) range. If we are still safe, then
10959 // let's save the range.
10960 if (AreAllUnsafeRegsDead())
10961 SaveRangeIfNonEmpty();
10962 if (Ranges.empty())
10963 return Ranges;
10964 // We found the ranges bottom-up. Mapping expects the top-down. Reverse
10965 // the order.
10966 std::reverse(Ranges.begin(), Ranges.end());
10967 // If there is at least one outlinable range where LR is unavailable
10968 // somewhere, remember that.
10969 if (!LRAvailableEverywhere)
10971 return Ranges;
10972}
10973
10975AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
10977 unsigned Flags) const {
10978 MachineInstr &MI = *MIT;
10979
10980 // Don't outline anything used for return address signing. The outlined
10981 // function will get signed later if needed
10982 switch (MI.getOpcode()) {
10983 case AArch64::PACM:
10984 case AArch64::PACIASP:
10985 case AArch64::PACIBSP:
10986 case AArch64::PACIASPPC:
10987 case AArch64::PACIBSPPC:
10988 case AArch64::AUTIASP:
10989 case AArch64::AUTIBSP:
10990 case AArch64::AUTIASPPCi:
10991 case AArch64::AUTIASPPCr:
10992 case AArch64::AUTIBSPPCi:
10993 case AArch64::AUTIBSPPCr:
10994 case AArch64::RETAA:
10995 case AArch64::RETAB:
10996 case AArch64::RETAASPPCi:
10997 case AArch64::RETAASPPCr:
10998 case AArch64::RETABSPPCi:
10999 case AArch64::RETABSPPCr:
11000 case AArch64::EMITBKEY:
11001 case AArch64::PAUTH_PROLOGUE:
11002 case AArch64::PAUTH_EPILOGUE:
11004 }
11005
11006 // We can only outline these if we will tail call the outlined function, or
11007 // fix up the CFI offsets. Currently, CFI instructions are outlined only if
11008 // in a tail call.
11009 //
11010 // FIXME: If the proper fixups for the offset are implemented, this should be
11011 // possible.
11012 if (MI.isCFIInstruction())
11014
11015 // Is this a terminator for a basic block?
11016 if (MI.isTerminator())
11017 // TargetInstrInfo::getOutliningType has already filtered out anything
11018 // that would break this, so we can allow it here.
11020
11021 // Make sure none of the operands are un-outlinable.
11022 for (const MachineOperand &MOP : MI.operands()) {
11023 // A check preventing CFI indices was here before, but only CFI
11024 // instructions should have those.
11025 assert(!MOP.isCFIIndex());
11026
11027 // If it uses LR or W30 explicitly, then don't touch it.
11028 if (MOP.isReg() && !MOP.isImplicit() &&
11029 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
11031 }
11032
11033 // Special cases for instructions that can always be outlined, but will fail
11034 // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
11035 // be outlined because they don't require a *specific* value to be in LR.
11036 if (MI.getOpcode() == AArch64::ADRP)
11038
11039 // If MI is a call we might be able to outline it. We don't want to outline
11040 // any calls that rely on the position of items on the stack. When we outline
11041 // something containing a call, we have to emit a save and restore of LR in
11042 // the outlined function. Currently, this always happens by saving LR to the
11043 // stack. Thus, if we outline, say, half the parameters for a function call
11044 // plus the call, then we'll break the callee's expectations for the layout
11045 // of the stack.
11046 //
11047 // FIXME: Allow calls to functions which construct a stack frame, as long
11048 // as they don't access arguments on the stack.
11049 // FIXME: Figure out some way to analyze functions defined in other modules.
11050 // We should be able to compute the memory usage based on the IR calling
11051 // convention, even if we can't see the definition.
11052 if (MI.isCall()) {
11053 // Get the function associated with the call. Look at each operand and find
11054 // the one that represents the callee and get its name.
11055 const Function *Callee = nullptr;
11056 for (const MachineOperand &MOP : MI.operands()) {
11057 if (MOP.isGlobal()) {
11058 Callee = dyn_cast<Function>(MOP.getGlobal());
11059 break;
11060 }
11061 }
11062
11063 // Never outline calls to mcount. There isn't any rule that would require
11064 // this, but the Linux kernel's "ftrace" feature depends on it.
11065 if (Callee && Callee->getName() == "\01_mcount")
11067
11068 // If we don't know anything about the callee, assume it depends on the
11069 // stack layout of the caller. In that case, it's only legal to outline
11070 // as a tail-call. Explicitly list the call instructions we know about so we
11071 // don't get unexpected results with call pseudo-instructions.
11072 auto UnknownCallOutlineType = outliner::InstrType::Illegal;
11073 if (MI.getOpcode() == AArch64::BLR ||
11074 MI.getOpcode() == AArch64::BLRNoIP || MI.getOpcode() == AArch64::BL)
11075 UnknownCallOutlineType = outliner::InstrType::LegalTerminator;
11076
11077 if (!Callee)
11078 return UnknownCallOutlineType;
11079
11080 // We have a function we have information about. Check it if it's something
11081 // can safely outline.
11082 MachineFunction *CalleeMF = MMI.getMachineFunction(*Callee);
11083
11084 // We don't know what's going on with the callee at all. Don't touch it.
11085 if (!CalleeMF)
11086 return UnknownCallOutlineType;
11087
11088 // Check if we know anything about the callee saves on the function. If we
11089 // don't, then don't touch it, since that implies that we haven't
11090 // computed anything about its stack frame yet.
11091 MachineFrameInfo &MFI = CalleeMF->getFrameInfo();
11092 if (!MFI.isCalleeSavedInfoValid() || MFI.getStackSize() > 0 ||
11093 MFI.getNumObjects() > 0)
11094 return UnknownCallOutlineType;
11095
11096 // At this point, we can say that CalleeMF ought to not pass anything on the
11097 // stack. Therefore, we can outline it.
11099 }
11100
11101 // Don't touch the link register or W30.
11102 if (MI.readsRegister(AArch64::W30, &getRegisterInfo()) ||
11103 MI.modifiesRegister(AArch64::W30, &getRegisterInfo()))
11105
11106 // Don't outline BTI instructions, because that will prevent the outlining
11107 // site from being indirectly callable.
11108 if (hasBTISemantics(MI))
11110
11112}
11113
11114void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
11115 for (MachineInstr &MI : MBB) {
11116 const MachineOperand *Base;
11117 TypeSize Width(0, false);
11118 int64_t Offset;
11119 bool OffsetIsScalable;
11120
11121 // Is this a load or store with an immediate offset with SP as the base?
11122 if (!MI.mayLoadOrStore() ||
11123 !getMemOperandWithOffsetWidth(MI, Base, Offset, OffsetIsScalable, Width,
11124 &RI) ||
11125 (Base->isReg() && Base->getReg() != AArch64::SP))
11126 continue;
11127
11128 // It is, so we have to fix it up.
11129 TypeSize Scale(0U, false);
11130 int64_t Dummy1, Dummy2;
11131
11132 MachineOperand &StackOffsetOperand = getMemOpBaseRegImmOfsOffsetOperand(MI);
11133 assert(StackOffsetOperand.isImm() && "Stack offset wasn't immediate!");
11134 getMemOpInfo(MI.getOpcode(), Scale, Width, Dummy1, Dummy2);
11135 assert(Scale != 0 && "Unexpected opcode!");
11136 assert(!OffsetIsScalable && "Expected offset to be a byte offset");
11137
11138 // We've pushed the return address to the stack, so add 16 to the offset.
11139 // This is safe, since we already checked if it would overflow when we
11140 // checked if this instruction was legal to outline.
11141 int64_t NewImm = (Offset + 16) / (int64_t)Scale.getFixedValue();
11142 StackOffsetOperand.setImm(NewImm);
11143 }
11144}
11145
11147 const AArch64InstrInfo *TII,
11148 bool ShouldSignReturnAddr) {
11149 if (!ShouldSignReturnAddr)
11150 return;
11151
11152 BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(AArch64::PAUTH_PROLOGUE))
11154 TII->createPauthEpilogueInstr(MBB, DebugLoc());
11155}
11156
11157void AArch64InstrInfo::buildOutlinedFrame(
11159 const outliner::OutlinedFunction &OF) const {
11160
11161 AArch64FunctionInfo *FI = MF.getInfo<AArch64FunctionInfo>();
11162
11163 if (OF.FrameConstructionID == MachineOutlinerTailCall)
11164 FI->setOutliningStyle("Tail Call");
11165 else if (OF.FrameConstructionID == MachineOutlinerThunk) {
11166 // For thunk outlining, rewrite the last instruction from a call to a
11167 // tail-call.
11168 MachineInstr *Call = &*--MBB.instr_end();
11169 unsigned TailOpcode;
11170 if (Call->getOpcode() == AArch64::BL) {
11171 TailOpcode = AArch64::TCRETURNdi;
11172 } else {
11173 assert(Call->getOpcode() == AArch64::BLR ||
11174 Call->getOpcode() == AArch64::BLRNoIP);
11175 TailOpcode = AArch64::TCRETURNriALL;
11176 }
11177 MachineInstr *TC = BuildMI(MF, DebugLoc(), get(TailOpcode))
11178 .add(Call->getOperand(0))
11179 .addImm(0);
11180 MBB.insert(MBB.end(), TC);
11182
11183 FI->setOutliningStyle("Thunk");
11184 }
11185
11186 bool IsLeafFunction = true;
11187
11188 // Is there a call in the outlined range?
11189 auto IsNonTailCall = [](const MachineInstr &MI) {
11190 return MI.isCall() && !MI.isReturn();
11191 };
11192
11193 if (llvm::any_of(MBB.instrs(), IsNonTailCall)) {
11194 // Fix up the instructions in the range, since we're going to modify the
11195 // stack.
11196
11197 // Bugzilla ID: 46767
11198 // TODO: Check if fixing up twice is safe so we can outline these.
11199 assert(OF.FrameConstructionID != MachineOutlinerDefault &&
11200 "Can only fix up stack references once");
11201 fixupPostOutline(MBB);
11202
11203 IsLeafFunction = false;
11204
11205 // LR has to be a live in so that we can save it.
11206 if (!MBB.isLiveIn(AArch64::LR))
11207 MBB.addLiveIn(AArch64::LR);
11208
11211
11212 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11213 OF.FrameConstructionID == MachineOutlinerThunk)
11214 Et = std::prev(MBB.end());
11215
11216 // Insert a save before the outlined region
11217 MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11218 .addReg(AArch64::SP, RegState::Define)
11219 .addReg(AArch64::LR)
11220 .addReg(AArch64::SP)
11221 .addImm(-16);
11222 It = MBB.insert(It, STRXpre);
11223
11224 if (MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11225 CFIInstBuilder CFIBuilder(MBB, It, MachineInstr::FrameSetup);
11226
11227 // Add a CFI saying the stack was moved 16 B down.
11228 CFIBuilder.buildDefCFAOffset(16);
11229
11230 // Add a CFI saying that the LR that we want to find is now 16 B higher
11231 // than before.
11232 CFIBuilder.buildOffset(AArch64::LR, -16);
11233 }
11234
11235 // Insert a restore before the terminator for the function.
11236 MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11237 .addReg(AArch64::SP, RegState::Define)
11238 .addReg(AArch64::LR, RegState::Define)
11239 .addReg(AArch64::SP)
11240 .addImm(16);
11241 Et = MBB.insert(Et, LDRXpost);
11242 }
11243
11244 auto RASignCondition = FI->getSignReturnAddressCondition();
11245 bool ShouldSignReturnAddr = AArch64FunctionInfo::shouldSignReturnAddress(
11246 RASignCondition, !IsLeafFunction);
11247
11248 // If this is a tail call outlined function, then there's already a return.
11249 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11250 OF.FrameConstructionID == MachineOutlinerThunk) {
11251 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11252 return;
11253 }
11254
11255 // It's not a tail call, so we have to insert the return ourselves.
11256
11257 // LR has to be a live in so that we can return to it.
11258 if (!MBB.isLiveIn(AArch64::LR))
11259 MBB.addLiveIn(AArch64::LR);
11260
11261 MachineInstr *ret = BuildMI(MF, DebugLoc(), get(AArch64::RET))
11262 .addReg(AArch64::LR);
11263 MBB.insert(MBB.end(), ret);
11264
11265 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11266
11267 FI->setOutliningStyle("Function");
11268
11269 // Did we have to modify the stack by saving the link register?
11270 if (OF.FrameConstructionID != MachineOutlinerDefault)
11271 return;
11272
11273 // We modified the stack.
11274 // Walk over the basic block and fix up all the stack accesses.
11275 fixupPostOutline(MBB);
11276}
11277
11278MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall(
11281
11282 // Are we tail calling?
11283 if (C.CallConstructionID == MachineOutlinerTailCall) {
11284 // If yes, then we can just branch to the label.
11285 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::TCRETURNdi))
11286 .addGlobalAddress(M.getNamedValue(MF.getName()))
11287 .addImm(0));
11288 return It;
11289 }
11290
11291 // Are we saving the link register?
11292 if (C.CallConstructionID == MachineOutlinerNoLRSave ||
11293 C.CallConstructionID == MachineOutlinerThunk) {
11294 // No, so just insert the call.
11295 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11296 .addGlobalAddress(M.getNamedValue(MF.getName())));
11297 return It;
11298 }
11299
11300 // We want to return the spot where we inserted the call.
11302
11303 // Instructions for saving and restoring LR around the call instruction we're
11304 // going to insert.
11305 MachineInstr *Save;
11306 MachineInstr *Restore;
11307 // Can we save to a register?
11308 if (C.CallConstructionID == MachineOutlinerRegSave) {
11309 // FIXME: This logic should be sunk into a target-specific interface so that
11310 // we don't have to recompute the register.
11311 Register Reg = findRegisterToSaveLRTo(C);
11312 assert(Reg && "No callee-saved register available?");
11313
11314 // LR has to be a live in so that we can save it.
11315 if (!MBB.isLiveIn(AArch64::LR))
11316 MBB.addLiveIn(AArch64::LR);
11317
11318 // Save and restore LR from Reg.
11319 Save = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), Reg)
11320 .addReg(AArch64::XZR)
11321 .addReg(AArch64::LR)
11322 .addImm(0);
11323 Restore = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), AArch64::LR)
11324 .addReg(AArch64::XZR)
11325 .addReg(Reg)
11326 .addImm(0);
11327 } else {
11328 // We have the default case. Save and restore from SP.
11329 Save = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11330 .addReg(AArch64::SP, RegState::Define)
11331 .addReg(AArch64::LR)
11332 .addReg(AArch64::SP)
11333 .addImm(-16);
11334 Restore = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11335 .addReg(AArch64::SP, RegState::Define)
11336 .addReg(AArch64::LR, RegState::Define)
11337 .addReg(AArch64::SP)
11338 .addImm(16);
11339 }
11340
11341 It = MBB.insert(It, Save);
11342 It++;
11343
11344 // Insert the call.
11345 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11346 .addGlobalAddress(M.getNamedValue(MF.getName())));
11347 CallPt = It;
11348 It++;
11349
11350 It = MBB.insert(It, Restore);
11351 return CallPt;
11352}
11353
11354bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11355 MachineFunction &MF) const {
11356 return MF.getFunction().hasMinSize();
11357}
11358
11359void AArch64InstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
11361 DebugLoc &DL,
11362 bool AllowSideEffects) const {
11363 const MachineFunction &MF = *MBB.getParent();
11364 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
11365 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
11366
11367 if (TRI.isGeneralPurposeRegister(MF, Reg)) {
11368 BuildMI(MBB, Iter, DL, get(AArch64::MOVZXi), Reg).addImm(0).addImm(0);
11369 } else if (STI.isSVEorStreamingSVEAvailable()) {
11370 BuildMI(MBB, Iter, DL, get(AArch64::DUP_ZI_D), Reg)
11371 .addImm(0)
11372 .addImm(0);
11373 } else if (STI.isNeonAvailable()) {
11374 BuildMI(MBB, Iter, DL, get(AArch64::MOVIv2d_ns), Reg)
11375 .addImm(0);
11376 } else {
11377 // No Advanced SIMD (streaming-compatible without SVE, or +nosimd), so use
11378 // `fmov d...` instead of `movi v...`; writing `d` also clears the upper
11379 // 64 bits.
11380 assert(STI.hasFPARMv8() && "Expected FP to be available.");
11381 Register Reg64 = TRI.getSubReg(Reg, AArch64::dsub);
11382 BuildMI(MBB, Iter, DL, get(AArch64::FMOVD0), Reg64);
11383 }
11384}
11385
11386std::optional<DestSourcePair>
11388
11389 // AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg
11390 // and zero immediate operands used as an alias for mov instruction.
11391 if ((MI.getOpcode() == AArch64::ORRWrs &&
11392 MI.getOperand(1).getReg() == AArch64::WZR &&
11393 MI.getOperand(3).getImm() == 0x0) ||
11394 (MI.getOpcode() == AArch64::ORRWrr &&
11395 MI.getOperand(1).getReg() == AArch64::WZR)) {
11396 // Check that the w->w move is not a zero-extending w->x mov.
11397 if ((MI.getOperand(0).getReg().isPhysical() &&
11398 MI.findRegisterDefOperandIdx(
11399 getXRegFromWReg(MI.getOperand(0).getReg()),
11400 /*TRI=*/nullptr) == -1) ||
11401 (MI.getOperand(0).getReg().isVirtual() &&
11402 !MI.getOperand(0).getSubReg()))
11403 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11404 }
11405
11406 if (MI.getOpcode() == AArch64::ORRXrs &&
11407 MI.getOperand(1).getReg() == AArch64::XZR &&
11408 MI.getOperand(3).getImm() == 0x0)
11409 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11410
11411 return std::nullopt;
11412}
11413
11414std::optional<DestSourcePair>
11416 if ((MI.getOpcode() == AArch64::ORRWrs &&
11417 MI.getOperand(1).getReg() == AArch64::WZR &&
11418 MI.getOperand(3).getImm() == 0x0) ||
11419 (MI.getOpcode() == AArch64::ORRWrr &&
11420 MI.getOperand(1).getReg() == AArch64::WZR))
11421 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11422 return std::nullopt;
11423}
11424
11425std::optional<RegImmPair>
11426AArch64InstrInfo::isAddImmediate(const MachineInstr &MI, Register Reg) const {
11427 int Sign = 1;
11428 int64_t Offset = 0;
11429
11430 // TODO: Handle cases where Reg is a super- or sub-register of the
11431 // destination register.
11432 const MachineOperand &Op0 = MI.getOperand(0);
11433 if (!Op0.isReg() || Reg != Op0.getReg())
11434 return std::nullopt;
11435
11436 switch (MI.getOpcode()) {
11437 default:
11438 return std::nullopt;
11439 case AArch64::SUBWri:
11440 case AArch64::SUBXri:
11441 case AArch64::SUBSWri:
11442 case AArch64::SUBSXri:
11443 Sign *= -1;
11444 [[fallthrough]];
11445 case AArch64::ADDSWri:
11446 case AArch64::ADDSXri:
11447 case AArch64::ADDWri:
11448 case AArch64::ADDXri: {
11449 // TODO: Third operand can be global address (usually some string).
11450 if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
11451 !MI.getOperand(2).isImm())
11452 return std::nullopt;
11453 int Shift = MI.getOperand(3).getImm();
11454 assert((Shift == 0 || Shift == 12) && "Shift can be either 0 or 12");
11455 Offset = Sign * (MI.getOperand(2).getImm() << Shift);
11456 }
11457 }
11458 return RegImmPair{MI.getOperand(1).getReg(), Offset};
11459}
11460
11461/// If the given ORR instruction is a copy, and \p DescribedReg overlaps with
11462/// the destination register then, if possible, describe the value in terms of
11463/// the source register.
11464static std::optional<ParamLoadedValue>
11466 const TargetInstrInfo *TII,
11467 const TargetRegisterInfo *TRI) {
11468 auto DestSrc = TII->isCopyLikeInstr(MI);
11469 if (!DestSrc)
11470 return std::nullopt;
11471
11472 Register DestReg = DestSrc->Destination->getReg();
11473 Register SrcReg = DestSrc->Source->getReg();
11474
11475 if (!DestReg.isValid() || !SrcReg.isValid())
11476 return std::nullopt;
11477
11478 auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
11479
11480 // If the described register is the destination, just return the source.
11481 if (DestReg == DescribedReg)
11482 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11483
11484 // ORRWrs zero-extends to 64-bits, so we need to consider such cases.
11485 if (MI.getOpcode() == AArch64::ORRWrs &&
11486 TRI->isSuperRegister(DestReg, DescribedReg))
11487 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11488
11489 // We may need to describe the lower part of a ORRXrs move.
11490 if (MI.getOpcode() == AArch64::ORRXrs &&
11491 TRI->isSubRegister(DestReg, DescribedReg)) {
11492 Register SrcSubReg = TRI->getSubReg(SrcReg, AArch64::sub_32);
11493 return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
11494 }
11495
11496 assert(!TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11497 "Unhandled ORR[XW]rs copy case");
11498
11499 return std::nullopt;
11500}
11501
11502bool AArch64InstrInfo::isFunctionSafeToSplit(const MachineFunction &MF) const {
11503 // Functions cannot be split to different sections on AArch64 if they have
11504 // a red zone. This is because relaxing a cross-section branch may require
11505 // incrementing the stack pointer to spill a register, which would overwrite
11506 // the red zone.
11507 if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(true))
11508 return false;
11509
11511}
11512
11513bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11514 const MachineBasicBlock &MBB) const {
11515 // Asm Goto blocks can contain conditional branches to goto labels, which can
11516 // get moved out of range of the branch instruction.
11517 auto isAsmGoto = [](const MachineInstr &MI) {
11518 return MI.getOpcode() == AArch64::INLINEASM_BR;
11519 };
11520 if (llvm::any_of(MBB, isAsmGoto) || MBB.isInlineAsmBrIndirectTarget())
11521 return false;
11522
11523 // Because jump tables are label-relative instead of table-relative, they all
11524 // must be in the same section or relocation fixup handling will fail.
11525
11526 // Check if MBB is a jump table target
11527 const MachineJumpTableInfo *MJTI = MBB.getParent()->getJumpTableInfo();
11528 auto containsMBB = [&MBB](const MachineJumpTableEntry &JTE) {
11529 return llvm::is_contained(JTE.MBBs, &MBB);
11530 };
11531 if (MJTI != nullptr && llvm::any_of(MJTI->getJumpTables(), containsMBB))
11532 return false;
11533
11534 // Check if MBB contains a jump table lookup
11535 for (const MachineInstr &MI : MBB) {
11536 switch (MI.getOpcode()) {
11537 case TargetOpcode::G_BRJT:
11538 case AArch64::JumpTableDest32:
11539 case AArch64::JumpTableDest16:
11540 case AArch64::JumpTableDest8:
11541 return false;
11542 default:
11543 continue;
11544 }
11545 }
11546
11547 // MBB isn't a special case, so it's safe to be split to the cold section.
11548 return true;
11549}
11550
11551std::optional<ParamLoadedValue>
11552AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
11553 Register Reg) const {
11554 const MachineFunction *MF = MI.getMF();
11555 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
11556 switch (MI.getOpcode()) {
11557 case AArch64::MOVZWi:
11558 case AArch64::MOVZXi: {
11559 // MOVZWi may be used for producing zero-extended 32-bit immediates in
11560 // 64-bit parameters, so we need to consider super-registers.
11561 if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
11562 return std::nullopt;
11563
11564 if (!MI.getOperand(1).isImm())
11565 return std::nullopt;
11566 int64_t Immediate = MI.getOperand(1).getImm();
11567 int Shift = MI.getOperand(2).getImm();
11568 return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
11569 nullptr);
11570 }
11571 case AArch64::ORRWrs:
11572 case AArch64::ORRXrs:
11573 return describeORRLoadedValue(MI, Reg, this, TRI);
11574 }
11575
11577}
11578
11579bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11580 MachineInstr &ExtMI, MachineRegisterInfo &MRI) const {
11581 assert(ExtMI.getOpcode() == TargetOpcode::G_SEXT ||
11582 ExtMI.getOpcode() == TargetOpcode::G_ZEXT ||
11583 ExtMI.getOpcode() == TargetOpcode::G_ANYEXT);
11584
11585 // Anyexts are nops.
11586 if (ExtMI.getOpcode() == TargetOpcode::G_ANYEXT)
11587 return true;
11588
11589 Register DefReg = ExtMI.getOperand(0).getReg();
11590 if (!MRI.hasOneNonDBGUse(DefReg))
11591 return false;
11592
11593 // It's likely that a sext/zext as a G_PTR_ADD offset will be folded into an
11594 // addressing mode.
11595 auto *UserMI = &*MRI.use_instr_nodbg_begin(DefReg);
11596 return UserMI->getOpcode() == TargetOpcode::G_PTR_ADD;
11597}
11598
11599uint64_t AArch64InstrInfo::getElementSizeForOpcode(unsigned Opc) const {
11600 return get(Opc).TSFlags & AArch64::ElementSizeMask;
11601}
11602
11603bool AArch64InstrInfo::isPTestLikeOpcode(unsigned Opc) const {
11604 return get(Opc).TSFlags & AArch64::InstrFlagIsPTestLike;
11605}
11606
11607bool AArch64InstrInfo::isWhileOpcode(unsigned Opc) const {
11608 return get(Opc).TSFlags & AArch64::InstrFlagIsWhile;
11609}
11610
11611unsigned int
11612AArch64InstrInfo::getTailDuplicateSize(CodeGenOptLevel OptLevel) const {
11613 return OptLevel >= CodeGenOptLevel::Aggressive ? 6 : 2;
11614}
11615
11616bool AArch64InstrInfo::isLegalAddressingMode(unsigned NumBytes, int64_t Offset,
11617 unsigned Scale) const {
11618 if (Offset && Scale)
11619 return false;
11620
11621 // Check Reg + Imm
11622 if (!Scale) {
11623 // 9-bit signed offset
11624 if (isInt<9>(Offset))
11625 return true;
11626
11627 // 12-bit unsigned offset
11628 unsigned Shift = Log2_64(NumBytes);
11629 if (NumBytes && Offset > 0 && (Offset / NumBytes) <= (1LL << 12) - 1 &&
11630 // Must be a multiple of NumBytes (NumBytes is a power of 2)
11631 (Offset >> Shift) << Shift == Offset)
11632 return true;
11633 return false;
11634 }
11635
11636 // Check reg1 + SIZE_IN_BYTES * reg2 and reg1 + reg2
11637 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11638}
11639
11641 if (MF.getSubtarget<AArch64Subtarget>().hardenSlsBlr())
11642 return AArch64::BLRNoIP;
11643 else
11644 return AArch64::BLR;
11645}
11646
11648 DebugLoc DL) const {
11649 MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
11650 auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
11652
11653 MachineFunction &MF = *MBB.getParent();
11654 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
11655 auto &AFL = *static_cast<const AArch64FrameLowering *>(
11656 MF.getSubtarget().getFrameLowering());
11657 if (AFL.getArgumentStackToRestore(MF, MBB)) {
11658 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
11659 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11660 if (Subtarget.hasPAuthLR())
11661 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
11662 return;
11663 }
11664
11665 if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
11666 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11667}
11668
11670AArch64InstrInfo::probedStackAlloc(MachineBasicBlock::iterator MBBI,
11671 Register TargetReg, bool FrameSetup) const {
11672 assert(TargetReg != AArch64::SP && "New top of stack cannot already be in SP");
11673
11674 MachineBasicBlock &MBB = *MBBI->getParent();
11675 MachineFunction &MF = *MBB.getParent();
11676 const AArch64InstrInfo *TII =
11677 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
11678 int64_t ProbeSize = MF.getInfo<AArch64FunctionInfo>()->getStackProbeSize();
11679 DebugLoc DL = MBB.findDebugLoc(MBBI);
11680
11681 MachineFunction::iterator MBBInsertPoint = std::next(MBB.getIterator());
11682 MachineBasicBlock *LoopTestMBB =
11683 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11684 MF.insert(MBBInsertPoint, LoopTestMBB);
11685 MachineBasicBlock *LoopBodyMBB =
11686 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11687 MF.insert(MBBInsertPoint, LoopBodyMBB);
11688 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11689 MF.insert(MBBInsertPoint, ExitMBB);
11690 MachineInstr::MIFlag Flags =
11692
11693 // LoopTest:
11694 // SUB SP, SP, #ProbeSize
11695 emitFrameOffset(*LoopTestMBB, LoopTestMBB->end(), DL, AArch64::SP,
11696 AArch64::SP, StackOffset::getFixed(-ProbeSize), TII, Flags);
11697
11698 // CMP SP, TargetReg
11699 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::SUBSXrx64),
11700 AArch64::XZR)
11701 .addReg(AArch64::SP)
11702 .addReg(TargetReg)
11704 .setMIFlags(Flags);
11705
11706 // B.<Cond> LoopExit
11707 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::Bcc))
11709 .addMBB(ExitMBB)
11710 .setMIFlags(Flags);
11711
11712 // LDR XZR, [SP]
11713 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::LDRXui))
11714 .addDef(AArch64::XZR)
11715 .addReg(AArch64::SP)
11716 .addImm(0)
11720 Align(8)))
11721 .setMIFlags(Flags);
11722
11723 // B loop
11724 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::B))
11725 .addMBB(LoopTestMBB)
11726 .setMIFlags(Flags);
11727
11728 // LoopExit:
11729 // MOV SP, TargetReg
11730 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::ADDXri), AArch64::SP)
11731 .addReg(TargetReg)
11732 .addImm(0)
11734 .setMIFlags(Flags);
11735
11736 // LDR XZR, [SP]
11737 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::LDRXui))
11738 .addReg(AArch64::XZR, RegState::Define)
11739 .addReg(AArch64::SP)
11740 .addImm(0)
11741 .setMIFlags(Flags);
11742
11743 ExitMBB->splice(ExitMBB->end(), &MBB, std::next(MBBI), MBB.end());
11745
11746 LoopTestMBB->addSuccessor(ExitMBB);
11747 LoopTestMBB->addSuccessor(LoopBodyMBB);
11748 LoopBodyMBB->addSuccessor(LoopTestMBB);
11749 MBB.addSuccessor(LoopTestMBB);
11750
11751 // Update liveins.
11752 if (MF.getRegInfo().reservedRegsFrozen())
11753 fullyRecomputeLiveIns({ExitMBB, LoopBodyMBB, LoopTestMBB});
11754
11755 return ExitMBB->begin();
11756}
11757
11758namespace {
11759class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
11760 MachineFunction *MF;
11761 const TargetInstrInfo *TII;
11762 const TargetRegisterInfo *TRI;
11763 MachineRegisterInfo &MRI;
11764
11765 /// The block of the loop
11766 MachineBasicBlock *LoopBB;
11767 /// The conditional branch of the loop
11768 MachineInstr *CondBranch;
11769 /// The compare instruction for loop control
11770 MachineInstr *Comp;
11771 /// The number of the operand of the loop counter value in Comp
11772 unsigned CompCounterOprNum;
11773 /// The instruction that updates the loop counter value
11774 MachineInstr *Update;
11775 /// The number of the operand of the loop counter value in Update
11776 unsigned UpdateCounterOprNum;
11777 /// The initial value of the loop counter
11778 Register Init;
11779 /// True iff Update is a predecessor of Comp
11780 bool IsUpdatePriorComp;
11781
11782 /// The normalized condition used by createTripCountGreaterCondition()
11784
11785public:
11786 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11787 MachineInstr *Comp, unsigned CompCounterOprNum,
11788 MachineInstr *Update, unsigned UpdateCounterOprNum,
11789 Register Init, bool IsUpdatePriorComp,
11790 const SmallVectorImpl<MachineOperand> &Cond)
11791 : MF(Comp->getParent()->getParent()),
11792 TII(MF->getSubtarget().getInstrInfo()),
11793 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11794 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11795 CompCounterOprNum(CompCounterOprNum), Update(Update),
11796 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11797 IsUpdatePriorComp(IsUpdatePriorComp), Cond(Cond.begin(), Cond.end()) {}
11798
11799 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
11800 // Make the instructions for loop control be placed in stage 0.
11801 // The predecessors of Comp are considered by the caller.
11802 return MI == Comp;
11803 }
11804
11805 std::optional<bool> createTripCountGreaterCondition(
11806 int TC, MachineBasicBlock &MBB,
11807 SmallVectorImpl<MachineOperand> &CondParam) override {
11808 // A branch instruction will be inserted as "if (Cond) goto epilogue".
11809 // Cond is normalized for such use.
11810 // The predecessors of the branch are assumed to have already been inserted.
11811 CondParam = Cond;
11812 return {};
11813 }
11814
11815 void createRemainingIterationsGreaterCondition(
11816 int TC, MachineBasicBlock &MBB, SmallVectorImpl<MachineOperand> &Cond,
11817 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts) override;
11818
11819 void setPreheader(MachineBasicBlock *NewPreheader) override {}
11820
11821 void adjustTripCount(int TripCountAdjust) override {}
11822
11823 bool isMVEExpanderSupported() override { return true; }
11824};
11825} // namespace
11826
11827/// Clone an instruction from MI. The register of ReplaceOprNum-th operand
11828/// is replaced by ReplaceReg. The output register is newly created.
11829/// The other operands are unchanged from MI.
11830static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum,
11831 Register ReplaceReg, MachineBasicBlock &MBB,
11832 MachineBasicBlock::iterator InsertTo) {
11833 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
11834 const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
11835 MachineInstr *NewMI = MBB.getParent()->CloneMachineInstr(MI);
11836 Register Result = 0;
11837 for (unsigned I = 0; I < NewMI->getNumOperands(); ++I) {
11838 if (I == 0 && NewMI->getOperand(0).getReg().isVirtual()) {
11839 Result = MRI.createVirtualRegister(
11840 MRI.getRegClass(NewMI->getOperand(0).getReg()));
11841 NewMI->getOperand(I).setReg(Result);
11842 } else if (I == ReplaceOprNum) {
11843 MRI.constrainRegClass(ReplaceReg, TII->getRegClass(NewMI->getDesc(), I));
11844 NewMI->getOperand(I).setReg(ReplaceReg);
11845 }
11846 }
11847 MBB.insert(InsertTo, NewMI);
11848 return Result;
11849}
11850
11851void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
11854 // Create and accumulate conditions for next TC iterations.
11855 // Example:
11856 // SUBSXrr N, counter, implicit-def $nzcv # compare instruction for the last
11857 // # iteration of the kernel
11858 //
11859 // # insert the following instructions
11860 // cond = CSINCXr 0, 0, C, implicit $nzcv
11861 // counter = ADDXri counter, 1 # clone from this->Update
11862 // SUBSXrr n, counter, implicit-def $nzcv # clone from this->Comp
11863 // cond = CSINCXr cond, cond, C, implicit $nzcv
11864 // ... (repeat TC times)
11865 // SUBSXri cond, 0, implicit-def $nzcv
11866
11867 assert(CondBranch->getOpcode() == AArch64::Bcc);
11868 // CondCode to exit the loop
11870 (AArch64CC::CondCode)CondBranch->getOperand(0).getImm();
11871 if (CondBranch->getOperand(1).getMBB() == LoopBB)
11873
11874 // Accumulate conditions to exit the loop
11875 Register AccCond = AArch64::XZR;
11876
11877 // If CC holds, CurCond+1 is returned; otherwise CurCond is returned.
11878 auto AccumulateCond = [&](Register CurCond,
11880 Register NewCond = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
11881 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::CSINCXr))
11882 .addReg(NewCond, RegState::Define)
11883 .addReg(CurCond)
11884 .addReg(CurCond)
11886 return NewCond;
11887 };
11888
11889 if (!LastStage0Insts.empty() && LastStage0Insts[Comp]->getParent() == &MBB) {
11890 // Update and Comp for I==0 are already exists in MBB
11891 // (MBB is an unrolled kernel)
11892 Register Counter;
11893 for (int I = 0; I <= TC; ++I) {
11894 Register NextCounter;
11895 if (I != 0)
11896 NextCounter =
11897 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
11898
11899 AccCond = AccumulateCond(AccCond, CC);
11900
11901 if (I != TC) {
11902 if (I == 0) {
11903 if (Update != Comp && IsUpdatePriorComp) {
11904 Counter =
11905 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11906 NextCounter = cloneInstr(Update, UpdateCounterOprNum, Counter, MBB,
11907 MBB.end());
11908 } else {
11909 // can use already calculated value
11910 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
11911 }
11912 } else if (Update != Comp) {
11913 NextCounter =
11914 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
11915 }
11916 }
11917 Counter = NextCounter;
11918 }
11919 } else {
11920 Register Counter;
11921 if (LastStage0Insts.empty()) {
11922 // use initial counter value (testing if the trip count is sufficient to
11923 // be executed by pipelined code)
11924 Counter = Init;
11925 if (IsUpdatePriorComp)
11926 Counter =
11927 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
11928 } else {
11929 // MBB is an epilogue block. LastStage0Insts[Comp] is in the kernel block.
11930 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11931 }
11932
11933 for (int I = 0; I <= TC; ++I) {
11934 Register NextCounter;
11935 NextCounter =
11936 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
11937 AccCond = AccumulateCond(AccCond, CC);
11938 if (I != TC && Update != Comp)
11939 NextCounter =
11940 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
11941 Counter = NextCounter;
11942 }
11943 }
11944
11945 // If AccCond == 0, the remainder is greater than TC.
11946 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::SUBSXri))
11947 .addReg(AArch64::XZR, RegState::Define | RegState::Dead)
11948 .addReg(AccCond)
11949 .addImm(0)
11950 .addImm(0);
11951 Cond.clear();
11953}
11954
11955static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB,
11956 Register &RegMBB, Register &RegOther) {
11957 assert(Phi.getNumOperands() == 5);
11958 if (Phi.getOperand(2).getMBB() == MBB) {
11959 RegMBB = Phi.getOperand(1).getReg();
11960 RegOther = Phi.getOperand(3).getReg();
11961 } else {
11962 assert(Phi.getOperand(4).getMBB() == MBB);
11963 RegMBB = Phi.getOperand(3).getReg();
11964 RegOther = Phi.getOperand(1).getReg();
11965 }
11966}
11967
11969 if (!Reg.isVirtual())
11970 return false;
11971 const MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
11972 return MRI.getVRegDef(Reg)->getParent() != BB;
11973}
11974
11975/// If Reg is an induction variable, return true and set some parameters
11976static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB,
11977 MachineInstr *&UpdateInst,
11978 unsigned &UpdateCounterOprNum, Register &InitReg,
11979 bool &IsUpdatePriorComp) {
11980 // Example:
11981 //
11982 // Preheader:
11983 // InitReg = ...
11984 // LoopBB:
11985 // Reg0 = PHI (InitReg, Preheader), (Reg1, LoopBB)
11986 // Reg = COPY Reg0 ; COPY is ignored.
11987 // Reg1 = ADD Reg, #1; UpdateInst. Incremented by a loop invariant value.
11988 // ; Reg is the value calculated in the previous
11989 // ; iteration, so IsUpdatePriorComp == false.
11990
11991 if (LoopBB->pred_size() != 2)
11992 return false;
11993 if (!Reg.isVirtual())
11994 return false;
11995 const MachineRegisterInfo &MRI = LoopBB->getParent()->getRegInfo();
11996 UpdateInst = nullptr;
11997 UpdateCounterOprNum = 0;
11998 InitReg = 0;
11999 IsUpdatePriorComp = true;
12000 Register CurReg = Reg;
12001 while (true) {
12002 MachineInstr *Def = MRI.getVRegDef(CurReg);
12003 if (Def->getParent() != LoopBB)
12004 return false;
12005 if (Def->isCopy()) {
12006 // Ignore copy instructions unless they contain subregisters
12007 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
12008 return false;
12009 CurReg = Def->getOperand(1).getReg();
12010 } else if (Def->isPHI()) {
12011 if (InitReg != 0)
12012 return false;
12013 if (!UpdateInst)
12014 IsUpdatePriorComp = false;
12015 extractPhiReg(*Def, LoopBB, CurReg, InitReg);
12016 } else {
12017 if (UpdateInst)
12018 return false;
12019 switch (Def->getOpcode()) {
12020 case AArch64::ADDSXri:
12021 case AArch64::ADDSWri:
12022 case AArch64::SUBSXri:
12023 case AArch64::SUBSWri:
12024 case AArch64::ADDXri:
12025 case AArch64::ADDWri:
12026 case AArch64::SUBXri:
12027 case AArch64::SUBWri:
12028 UpdateInst = Def;
12029 UpdateCounterOprNum = 1;
12030 break;
12031 case AArch64::ADDSXrr:
12032 case AArch64::ADDSWrr:
12033 case AArch64::SUBSXrr:
12034 case AArch64::SUBSWrr:
12035 case AArch64::ADDXrr:
12036 case AArch64::ADDWrr:
12037 case AArch64::SUBXrr:
12038 case AArch64::SUBWrr:
12039 UpdateInst = Def;
12040 if (isDefinedOutside(Def->getOperand(2).getReg(), LoopBB))
12041 UpdateCounterOprNum = 1;
12042 else if (isDefinedOutside(Def->getOperand(1).getReg(), LoopBB))
12043 UpdateCounterOprNum = 2;
12044 else
12045 return false;
12046 break;
12047 default:
12048 return false;
12049 }
12050 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
12051 }
12052
12053 if (!CurReg.isVirtual())
12054 return false;
12055 if (Reg == CurReg)
12056 break;
12057 }
12058
12059 if (!UpdateInst)
12060 return false;
12061
12062 return true;
12063}
12064
12065std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
12067 // Accept loops that meet the following conditions
12068 // * The conditional branch is BCC
12069 // * The compare instruction is ADDS/SUBS/WHILEXX
12070 // * One operand of the compare is an induction variable and the other is a
12071 // loop invariant value
12072 // * The induction variable is incremented/decremented by a single instruction
12073 // * Does not contain CALL or instructions which have unmodeled side effects
12074
12075 for (MachineInstr &MI : *LoopBB)
12076 if (MI.isCall() || MI.hasUnmodeledSideEffects())
12077 // This instruction may use NZCV, which interferes with the instruction to
12078 // be inserted for loop control.
12079 return nullptr;
12080
12081 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
12083 if (analyzeBranch(*LoopBB, TBB, FBB, Cond))
12084 return nullptr;
12085
12086 // Infinite loops are not supported
12087 if (TBB == LoopBB && FBB == LoopBB)
12088 return nullptr;
12089
12090 // Must be conditional branch
12091 if (TBB != LoopBB && FBB == nullptr)
12092 return nullptr;
12093
12094 assert((TBB == LoopBB || FBB == LoopBB) &&
12095 "The Loop must be a single-basic-block loop");
12096
12097 MachineInstr *CondBranch = &*LoopBB->getFirstTerminator();
12099
12100 if (CondBranch->getOpcode() != AArch64::Bcc)
12101 return nullptr;
12102
12103 // Normalization for createTripCountGreaterCondition()
12104 if (TBB == LoopBB)
12106
12107 MachineInstr *Comp = nullptr;
12108 unsigned CompCounterOprNum = 0;
12109 for (MachineInstr &MI : reverse(*LoopBB)) {
12110 if (MI.modifiesRegister(AArch64::NZCV, &TRI)) {
12111 // Guarantee that the compare is SUBS/ADDS/WHILEXX and that one of the
12112 // operands is a loop invariant value
12113
12114 switch (MI.getOpcode()) {
12115 case AArch64::SUBSXri:
12116 case AArch64::SUBSWri:
12117 case AArch64::ADDSXri:
12118 case AArch64::ADDSWri:
12119 Comp = &MI;
12120 CompCounterOprNum = 1;
12121 break;
12122 case AArch64::ADDSWrr:
12123 case AArch64::ADDSXrr:
12124 case AArch64::SUBSWrr:
12125 case AArch64::SUBSXrr:
12126 Comp = &MI;
12127 break;
12128 default:
12129 if (isWhileOpcode(MI.getOpcode())) {
12130 Comp = &MI;
12131 break;
12132 }
12133 return nullptr;
12134 }
12135
12136 if (CompCounterOprNum == 0) {
12137 if (isDefinedOutside(Comp->getOperand(1).getReg(), LoopBB))
12138 CompCounterOprNum = 2;
12139 else if (isDefinedOutside(Comp->getOperand(2).getReg(), LoopBB))
12140 CompCounterOprNum = 1;
12141 else
12142 return nullptr;
12143 }
12144 break;
12145 }
12146 }
12147 if (!Comp)
12148 return nullptr;
12149
12150 MachineInstr *Update = nullptr;
12151 Register Init;
12152 bool IsUpdatePriorComp;
12153 unsigned UpdateCounterOprNum;
12154 if (!getIndVarInfo(Comp->getOperand(CompCounterOprNum).getReg(), LoopBB,
12155 Update, UpdateCounterOprNum, Init, IsUpdatePriorComp))
12156 return nullptr;
12157
12158 return std::make_unique<AArch64PipelinerLoopInfo>(
12159 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
12160 Init, IsUpdatePriorComp, Cond);
12161}
12162
12163/// verifyInstruction - Perform target specific instruction verification.
12164bool AArch64InstrInfo::verifyInstruction(const MachineInstr &MI,
12165 StringRef &ErrInfo) const {
12166 // Verify that immediate offsets on load/store instructions are within range.
12167 // Stack objects with an FI operand are excluded as they can be fixed up
12168 // during PEI.
12169 TypeSize Scale(0U, false), Width(0U, false);
12170 int64_t MinOffset, MaxOffset;
12171 if (getMemOpInfo(MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
12172 unsigned ImmIdx = getLoadStoreImmIdx(MI.getOpcode());
12173 if (MI.getOperand(ImmIdx).isImm() && !MI.getOperand(ImmIdx - 1).isFI()) {
12174 int64_t Imm = MI.getOperand(ImmIdx).getImm();
12175 if (Imm < MinOffset || Imm > MaxOffset) {
12176 ErrInfo = "Unexpected immediate on load/store instruction";
12177 return false;
12178 }
12179 }
12180 }
12181
12182 const MCInstrDesc &MCID = MI.getDesc();
12183 for (unsigned Op = 0; Op < MCID.getNumOperands(); Op++) {
12184 const MachineOperand &MO = MI.getOperand(Op);
12185 switch (MCID.operands()[Op].OperandType) {
12187 if (!MO.isImm() || MO.getImm() != 0) {
12188 ErrInfo = "OPERAND_IMPLICIT_IMM_0 should be 0";
12189 return false;
12190 }
12191 break;
12193 if (!MO.isImm() ||
12195 (AArch64_AM::getShiftValue(MO.getImm()) != 8 &&
12196 AArch64_AM::getShiftValue(MO.getImm()) != 16)) {
12197 ErrInfo = "OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
12198 return false;
12199 }
12200 break;
12202 if (!MO.isImm() || (MO.getImm() != 0 && MO.getImm() != 1)) {
12203 ErrInfo = "OPERAND_IMM_UINT1 should be 0 or 1";
12204 return false;
12205 }
12206 break;
12208 if (!MO.isImm() || MO.getImm() <= 0 || MO.getImm() > 16) {
12209 ErrInfo = "OPERAND_IMM_UINT4plus1 should be in the range 1 to 16";
12210 return false;
12211 }
12212 break;
12214 if (!MO.isImm() || !isUInt<5>(MO.getImm())) {
12215 ErrInfo = "OPERAND_IMM_UINT5 should be in the range 0 to 31";
12216 return false;
12217 }
12218 break;
12220 if (!MO.isImm() || !isUInt<8>(MO.getImm())) {
12221 ErrInfo = "OPERAND_IMM_UINT8 should be in the range 0 to 255";
12222 return false;
12223 }
12224 break;
12225 default:
12226 break;
12227 }
12228 }
12229 return true;
12230}
12231
12232#define GET_INSTRINFO_HELPERS
12233#define GET_INSTRMAP_INFO
12234#include "AArch64GenInstrInfo.inc"
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
static cl::opt< unsigned > BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of Bcc instructions (DEBUG)"))
static Register genNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned MnegOpc, const TargetRegisterClass *RC)
genNeg - Helper to generate an intermediate negation of the second operand of Root
static bool isFrameStoreOpcode(int Opcode)
static cl::opt< unsigned > GatherOptSearchLimit("aarch64-search-limit", cl::Hidden, cl::init(2048), cl::desc("Restrict range of instructions to search for the " "machine-combiner gather pattern optimization"))
static bool getMaddPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find instructions that can be turned into madd.
static AArch64CC::CondCode findCondCodeUsedByInstr(const MachineInstr &Instr)
Find a condition code used by the instruction.
static MachineInstr * genFusedMultiplyAcc(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyAcc - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genFusedMultiplyAccNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate64(unsigned Opc)
static bool isFrameLoadOpcode(int Opcode)
static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg)
static bool areCFlagsAccessedBetweenInstrs(MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI, const AccessKind AccessToCheck=AK_All)
True when condition flags are accessed (either by writing or reading) on the instruction trace starti...
static bool getFMAPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Floating-Point Support.
static bool isADDSRegImm(unsigned Opcode)
static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI)
static bool isANDOpcode(MachineInstr &MI)
static 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 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 void appendLoadRegExpr(SmallVectorImpl< char > &Expr, int64_t OffsetFromDefCFA)
static void appendConstantExpr(SmallVectorImpl< char > &Expr, int64_t Constant, dwarf::LocationAtom Operation)
static unsigned convertToNonFlagSettingOpc(const MachineInstr &MI)
Return the opcode that does not set flags when possible - otherwise return the original opcode.
static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool isCombineInstrCandidate32(unsigned Opc)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
static unsigned offsetExtendOpcode(unsigned Opcode)
MachineOutlinerMBBFlags
@ LRUnavailableSomewhere
@ UnsafeRegsDead
static void loadRegPairFromStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register DestReg, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
static void generateGatherLanePattern(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned Pattern, unsigned NumLanes)
Generate optimized instruction sequence for gather load patterns to improve Memory-Level Parallelism ...
static bool getMiscPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find other MI combine patterns.
static bool outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, RegState State, const TargetRegisterInfo *TRI)
static bool outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1, int64_t Offset1, unsigned Opcode1, int FI2, int64_t Offset2, unsigned Opcode2)
static cl::opt< unsigned > TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14), cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"))
static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB, Register &RegMBB, Register &RegOther)
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
static bool isDefinedOutside(Register Reg, const MachineBasicBlock *BB)
static MachineInstr * genFusedMultiply(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC, FMAInstKind kind=FMAInstKind::Default, const Register *ReplacedAddend=nullptr)
genFusedMultiply - Generate fused multiply instructions.
static bool getGatherLanePattern(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, unsigned LoadLaneOpCode, unsigned NumLanes)
Check if the given instruction forms a gather load pattern that can be optimized for better Memory-Le...
static MachineInstr * genFusedMultiplyIdxNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate(unsigned Opc)
static unsigned regOffsetOpcode(unsigned Opcode)
MachineOutlinerClass
Constants defining how certain sequences should be outlined.
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
@ MachineOutlinerNoLRSave
Only emit a branch.
@ MachineOutlinerThunk
Emit a call and return.
@ MachineOutlinerDefault
static cl::opt< unsigned > BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26), cl::desc("Restrict range of B instructions (DEBUG)"))
static bool areCFlagsAliveInSuccessors(const MachineBasicBlock *MBB)
Check if AArch64::NZCV should be alive in successors of MBB.
static void emitFrameOffsetAdj(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, int64_t Offset, unsigned Opc, const TargetInstrInfo *TII, MachineInstr::MIFlag Flag, bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFAOffset, StackOffset CFAOffset, unsigned FrameReg)
static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize)
static cl::opt< unsigned > CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"))
static void genSubAdd2SubSub(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, unsigned IdxOpd1, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
Do the following transformation A - (B + C) ==> (A - B) - C A - (B + C) ==> (A - C) - B.
static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg, unsigned *NewReg=nullptr)
static void signOutlinedFunction(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64InstrInfo *TII, bool ShouldSignReturnAddr)
static MachineInstr * genFNegatedMAD(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs)
static bool canCombineWithMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc, unsigned ZeroReg)
static void storeRegPairToStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register SrcReg, bool IsKill, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
@ Default
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static LVOptions Options
Definition LVOptions.cpp:25
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
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)
std::optional< bool > hasRedZone() const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
static bool isHForm(const MachineInstr &MI)
Returns whether the instruction is in H form (16 bit operands)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
static bool hasBTISemantics(const MachineInstr &MI)
Returns whether the instruction can be compatible with non-zero BTYPE.
static bool isQForm(const MachineInstr &MI)
Returns whether the instruction is in Q form (128 bit operands)
static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width, int64_t &MinOffset, int64_t &MaxOffset)
Returns true if opcode Opc is a memory operation.
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
static bool isFPRCopy(const MachineInstr &MI)
Does this instruction rename an FPR without modifying bits?
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is an instruction that moves/copies value from one register to an...
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
static bool isZExtLoad(const MachineInstr &MI)
Returns whether the instruction is a zero-extending load.
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
static bool isGPRCopy(const MachineInstr &MI)
Does this instruction rename a GPR without modifying bits?
static unsigned convertToFlagSettingOpc(unsigned Opc)
Return the opcode that set flags when possible.
void createPauthEpilogueInstr(MachineBasicBlock &MBB, DebugLoc DL) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
bool canInsertSelect(const MachineBasicBlock &, ArrayRef< MachineOperand > Cond, Register, Register, Register, int &, int &, int &) const override
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
static const MachineOperand & getLdStOffsetOp(const MachineInstr &MI)
Returns the immediate offset operator of a load/store.
bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg, Register &DstReg, unsigned &SubIdx) const override
static std::optional< unsigned > getUnscaledLdSt(unsigned Opc)
Returns the unscaled load/store for the scaled load/store opcode, if there is a corresponding unscale...
static bool hasUnscaledLdStOffset(unsigned Opc)
Return true if it has an unscaled load/store offset.
static const MachineOperand & getLdStAmountOp(const MachineInstr &MI)
Returns the shift amount operator of a load/store.
static bool isPreLdSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load/store.
std::optional< ExtAddrMode > getAddrModeFromMemoryOp(const MachineInstr &MemI, const TargetRegisterInfo *TRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
bool analyzeBranchPredicate(MachineBasicBlock &MBB, MachineBranchPredicate &MBP, bool AllowModify) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isPairableLdStInst(const MachineInstr &MI)
Return true if pairing the given load or store may be paired with another.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSExtLoad(const MachineInstr &MI)
Returns whether the instruction is a sign-extending load.
const AArch64RegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
static bool isPreSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed store.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
AArch64InstrInfo(const AArch64Subtarget &STI)
static bool isPairedLdSt(const MachineInstr &MI)
Returns whether the instruction is a paired load/store.
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &MI, const MachineOperand *&BaseOp, int64_t &Offset, bool &OffsetIsScalable, TypeSize &Width, const TargetRegisterInfo *TRI) const
If OffsetIsScalable is set to 'true', the offset is scaled by vscale.
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isStridedAccess(const MachineInstr &MI)
Return true if the given load or store is a strided memory access.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
Detect opportunities for ldp/stp formation.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool isThroughputPattern(unsigned Pattern) const override
Return true when a code sequence can improve throughput.
MachineOperand & getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const
Return the immediate offset of the base register in a load/store LdSt.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
static bool isLdStPairSuppressed(const MachineInstr &MI)
Return true if pairing the given load or store is hinted to be unprofitable.
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction supplying the argument to the comparison into one that...
static unsigned getLoadStoreImmIdx(unsigned Opc)
Returns the index for the immediate for a given instruction.
static bool isGPRZero(const MachineInstr &MI)
Does this instruction set its full destination register to zero?
void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, unsigned ZeroReg, llvm::ArrayRef< unsigned > Indices) const
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2,...
CombinerObjective getCombinerObjective(unsigned Pattern) const override
static bool isFpOrNEON(Register Reg)
Returns whether the physical register is FP or NEON.
bool isAsCheapAsAMove(const MachineInstr &MI) const override
std::optional< DestSourcePair > isCopyLikeInstrImpl(const MachineInstr &MI) const override
static void suppressLdStPair(MachineInstr &MI)
Hint that pairing the given load or store is unprofitable.
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isPreLd(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load.
void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, llvm::ArrayRef< unsigned > Indices) const
bool optimizeCondBranch(MachineInstr &MI) const override
Replace csincr-branch sequence by simple conditional branch.
static int getMemScale(unsigned Opc)
Scaling factor for (scaled or unscaled) load or store.
bool isCandidateToMergeOrPair(const MachineInstr &MI) const
Return true if this is a load/store that can be potentially paired/merged.
MCInst getNop() const override
static const MachineOperand & getLdStBaseOp(const MachineInstr &MI)
Returns the base register operator of a load/store.
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const
const AArch64RegisterInfo * getRegisterInfo() const override
bool isNeonAvailable() const
Returns true if the target has NEON and the function at runtime is known to have NEON enabled (e....
bool isSVEorStreamingSVEAvailable() const
Returns true if the target has access to either the full range of SVE instructions,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
This is an important base class in LLVM.
Definition Constant.h:43
A debug info location.
Definition DebugLoc.h:126
bool empty() const
Definition DenseMap.h:171
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Definition Function.h:691
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Definition Function.h:688
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.
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.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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...
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 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.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
MI-level patchpoint operands.
Definition StackMaps.h:77
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
Definition StackMaps.h:105
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:66
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents a location in source code.
Definition SMLoc.h:22
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
bool empty() const
Definition SmallSet.h:169
bool erase(const T &V)
Definition SmallSet.h:200
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:68
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
Definition StackMaps.h:36
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
Definition StackMaps.h:51
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
int64_t getFixed() const
Returns the fixed component of the stack.
Definition TypeSize.h:46
int64_t getScalable() const
Returns the scalable component of the stack.
Definition TypeSize.h:49
static StackOffset get(int64_t Fixed, int64_t Scalable)
Definition TypeSize.h:41
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:40
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:39
MI-level Statepoint operands.
Definition StackMaps.h:159
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Definition StackMaps.h:208
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const
Produce the expression describing the MI loading a value into the physical register Reg.
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual bool isFunctionSafeToSplit(const MachineFunction &MF) const
Return true if the function is a viable candidate for machine function splitting.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetOptions Options
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:346
Value * getOperand(unsigned i) const
Definition User.h:207
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
self_iterator getIterator()
Definition ilist_node.h:123
A raw_ostream that writes to an std::string.
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCode getInvertedCondCode(CondCode Code)
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_ARM64EC_CALLMANGLE
MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version of a symbol,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_HI12
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address,...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
@ MO_G2
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address,...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
unsigned getCheckerSizeInBytes(AuthCheckMethod Method)
Returns the number of bytes added by checkAuthenticatedRegister.
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
constexpr bool isLegalArithImmed(const uint64_t C)
isLegalArithImmed -
static unsigned getArithShiftValue(unsigned Imm)
getArithShiftValue - get the arithmetic shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static AArch64_AM::ShiftExtendType getExtendType(unsigned Imm)
getExtendType - Extract the extend type for operands of arithmetic ops.
static AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void expandMOVAddr(unsigned Opcode, unsigned TargetFlags, bool IsTargetMachO, SmallVectorImpl< AddrInsnModel > &Insn)
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static const uint64_t InstrFlagIsWhile
static const uint64_t InstrFlagIsPTestLike
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
initializer< Ty > init(const Ty &Val)
constexpr double e
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< InstrNode * > Instr
Definition RDFGraph.h:389
iterator end() const
Definition BasicBlock.h:89
LLVM_ABI Instruction & back() const
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:578
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
static bool isCondBranchOpcode(int Opc)
MCCFIInstruction createDefCFA(const TargetRegisterInfo &TRI, unsigned FrameReg, unsigned Reg, const StackOffset &Offset, bool LastAdjustmentWasScalable=true)
static bool isPTrueOpcode(unsigned Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool succeeded(LogicalResult Result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset, bool *OutUseUnscaledOp=nullptr, unsigned *OutUnscaledOp=nullptr, int64_t *EmittableOffset=nullptr)
Check if the Offset is a valid frame offset for MI.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
@ Renamable
Register that may be renamed.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
static bool isIndirectBranchOpcode(int Opc)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
@ AArch64FrameOffsetIsLegal
Offset is legal.
@ AArch64FrameOffsetCanUpdate
Offset can apply, at least partly.
@ AArch64FrameOffsetCannotUpdate
Offset cannot apply.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:338
static bool isSEHInstruction(const MachineInstr &MI)
bool isLFIPrePostMemAccess(unsigned Opcode)
Returns true if Opcode is a pre- or post-indexed memory access that the LFI rewriter expands with a b...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
AArch64MachineCombinerPattern
@ MULSUBv8i16_OP2
@ FMULv4i16_indexed_OP1
@ FMLSv1i32_indexed_OP2
@ MULSUBv2i32_indexed_OP1
@ FMLAv2i32_indexed_OP2
@ MULADDv4i16_indexed_OP2
@ FMLAv1i64_indexed_OP1
@ MULSUBv16i8_OP1
@ FMLAv8i16_indexed_OP2
@ FMULv2i32_indexed_OP1
@ MULSUBv8i16_indexed_OP2
@ FMLAv1i64_indexed_OP2
@ MULSUBv4i16_indexed_OP2
@ FMLAv1i32_indexed_OP1
@ FMLAv2i64_indexed_OP2
@ FMLSv8i16_indexed_OP1
@ MULSUBv2i32_OP1
@ FMULv4i16_indexed_OP2
@ MULSUBv4i32_indexed_OP2
@ FMULv2i64_indexed_OP2
@ FMLAv4i32_indexed_OP1
@ MULADDv4i16_OP2
@ FMULv8i16_indexed_OP2
@ MULSUBv4i16_OP1
@ MULADDv4i32_OP2
@ MULADDv2i32_OP2
@ MULADDv16i8_OP2
@ FMLSv4i16_indexed_OP1
@ MULADDv16i8_OP1
@ FMLAv2i64_indexed_OP1
@ FMLAv1i32_indexed_OP2
@ FMLSv2i64_indexed_OP2
@ MULADDv2i32_OP1
@ MULADDv4i32_OP1
@ MULADDv2i32_indexed_OP1
@ MULSUBv16i8_OP2
@ MULADDv4i32_indexed_OP1
@ MULADDv2i32_indexed_OP2
@ FMLAv4i16_indexed_OP2
@ MULSUBv8i16_OP1
@ FMULv2i32_indexed_OP2
@ FMLSv2i32_indexed_OP2
@ FMLSv4i32_indexed_OP1
@ FMULv2i64_indexed_OP1
@ MULSUBv4i16_OP2
@ FMLSv4i16_indexed_OP2
@ FMLAv2i32_indexed_OP1
@ FMLSv2i32_indexed_OP1
@ FMLAv8i16_indexed_OP1
@ MULSUBv4i16_indexed_OP1
@ FMLSv4i32_indexed_OP2
@ MULADDv4i32_indexed_OP2
@ MULSUBv4i32_OP2
@ MULSUBv8i16_indexed_OP1
@ MULADDv8i16_OP2
@ MULSUBv2i32_indexed_OP2
@ FMULv4i32_indexed_OP2
@ FMLSv2i64_indexed_OP1
@ MULADDv4i16_OP1
@ FMLAv4i32_indexed_OP2
@ MULADDv8i16_indexed_OP1
@ FMULv4i32_indexed_OP1
@ FMLAv4i16_indexed_OP1
@ FMULv8i16_indexed_OP1
@ MULADDv8i16_OP1
@ MULSUBv4i32_indexed_OP1
@ MULSUBv4i32_OP1
@ FMLSv8i16_indexed_OP2
@ MULADDv8i16_indexed_OP2
@ MULSUBv2i32_OP2
@ FMLSv1i64_indexed_OP2
@ MULADDv4i16_indexed_OP1
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr RegState getDefRegState(bool B)
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
std::optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:149
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition STLExtras.h:322
static MCRegister getXRegFromWReg(MCRegister Reg)
MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg, const StackOffset &OffsetFromDefCFA, std::optional< int64_t > IncomingVGOffsetFromDefCFA)
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static bool isUncondBranchOpcode(int Opc)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2192
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, StackOffset &Offset, const AArch64InstrInfo *TII)
rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
static const MachineMemOperand::Flags MOSuppressPair
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
void appendLEB128(SmallVectorImpl< U > &Buffer, T Value)
Definition LEB128.h:246
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
bool optimizeTerminators(MachineBasicBlock *MBB, const TargetInstrInfo &TII)
std::pair< MachineOperand, DIExpression * > ParamLoadedValue
bool isNZCVTouchedInInstructionRange(const MachineInstr &DefMI, const MachineInstr &UseMI, const TargetRegisterInfo *TRI)
Return true if there is an instruction /after/ DefMI and before UseMI which either reads or clobbers ...
static const MachineMemOperand::Flags MOStridedAccess
constexpr RegState getUndefRegState(bool B)
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare.
LLVM_ABI static const MBBSectionID ColdSectionID
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
An individual sequence of instructions to be replaced with a call to an outlined function.
MachineFunction * getMF() const
The information necessary to create an outlined function for some class of candidate.